Dear team, This patch adds support for the "graceful shutdown" well-known community as described in draft-ietf-grow-bgp-gshut.
An example implementation would be to add the following to your bgpd.conf: match from any community GRACEFUL_SHUTDOWN set { localpref 0 } Kind regards, Job --- etc/examples/bgpd.conf | 4 ++++ usr.sbin/bgpctl/bgpctl.c | 3 +++ usr.sbin/bgpctl/parser.c | 7 ++++++- usr.sbin/bgpd/bgpd.conf.5 | 2 ++ usr.sbin/bgpd/bgpd.h | 1 + usr.sbin/bgpd/parse.y | 6 +++++- 6 files changed, 21 insertions(+), 2 deletions(-) diff --git a/etc/examples/bgpd.conf b/etc/examples/bgpd.conf index 2ec37b2c752..1caf200ceab 100644 --- a/etc/examples/bgpd.conf +++ b/etc/examples/bgpd.conf @@ -87,6 +87,10 @@ allow from any inet6 prefixlen 16 - 48 #allow from any prefix 0.0.0.0/0 #allow from any prefix ::/0 +# Honor requests to gracefully shutdown BGP sessions +# https://tools.ietf.org/html/draft-ietf-grow-bgp-gshut +match from any community GRACEFUL_SHUTDOWN set { localpref 0 } + # https://www.arin.net/announcements/2014/20140130.html # This block will be subject to a minimum size allocation of /28 and a # maximum size allocation of /24. ARIN should use sparse allocation when diff --git a/usr.sbin/bgpctl/bgpctl.c b/usr.sbin/bgpctl/bgpctl.c index 4d9701da35b..8baa8be0ff2 100644 --- a/usr.sbin/bgpctl/bgpctl.c +++ b/usr.sbin/bgpctl/bgpctl.c @@ -1532,6 +1532,9 @@ show_community(u_char *data, u_int16_t len) v = ntohs(v); if (a == COMMUNITY_WELLKNOWN) switch (v) { + case COMMUNITY_GRACEFUL_SHUTDOWN: + printf("GRACEFUL_SHUTDOWN"); + break; case COMMUNITY_NO_EXPORT: printf("NO_EXPORT"); break; diff --git a/usr.sbin/bgpctl/parser.c b/usr.sbin/bgpctl/parser.c index 0d1e5d9fb3a..4ea16533b71 100644 --- a/usr.sbin/bgpctl/parser.c +++ b/usr.sbin/bgpctl/parser.c @@ -953,7 +953,11 @@ parse_community(const char *word, struct parse_result *r) int as, type; /* Well-known communities */ - if (strcasecmp(word, "NO_EXPORT") == 0) { + if (strcasecmp(word, "GRACEFUL_SHUTDOWN") == 0) { + as = COMMUNITY_WELLKNOWN; + type = COMMUNITY_GRACEFUL_SHUTDOWN; + goto done; + } else if (strcasecmp(word, "NO_EXPORT") == 0) { as = COMMUNITY_WELLKNOWN; type = COMMUNITY_NO_EXPORT; goto done; @@ -991,6 +995,7 @@ done: } if (as == COMMUNITY_WELLKNOWN) switch (type) { + case COMMUNITY_GRACEFUL_SHUTDOWN: case COMMUNITY_NO_EXPORT: case COMMUNITY_NO_ADVERTISE: case COMMUNITY_NO_EXPSUBCONFED: diff --git a/usr.sbin/bgpd/bgpd.conf.5 b/usr.sbin/bgpd/bgpd.conf.5 index 6cecd7a5a80..3afc54ef385 100644 --- a/usr.sbin/bgpd/bgpd.conf.5 +++ b/usr.sbin/bgpd/bgpd.conf.5 @@ -1173,6 +1173,7 @@ to do wildcard matching. Alternatively, well-known communities may be given by name instead and include .Ic BLACKHOLE , +.Ic GRACEFUL_SHUTDOWN , .Ic NO_EXPORT , .Ic NO_ADVERTISE , .Ic NO_EXPORT_SUBCONFED , @@ -1444,6 +1445,7 @@ is an AS number and is a locally-significant number between zero and .Li 65535 . Alternately, well-known communities may be specified by name: +.Ic GRACEFUL_SHUTDOWN , .Ic NO_EXPORT , .Ic NO_ADVERTISE , .Ic NO_EXPORT_SUBCONFED , diff --git a/usr.sbin/bgpd/bgpd.h b/usr.sbin/bgpd/bgpd.h index db52f858241..ef4e30ffd94 100644 --- a/usr.sbin/bgpd/bgpd.h +++ b/usr.sbin/bgpd/bgpd.h @@ -750,6 +750,7 @@ struct filter_peers { #define COMMUNITY_LOCAL_AS -4 #define COMMUNITY_UNSET -5 #define COMMUNITY_WELLKNOWN 0xffff +#define COMMUNITY_GRACEFUL_SHUTDOWN 0x0000 /* draft-ietf-grow-bgp-gshut */ #define COMMUNITY_BLACKHOLE 0x029A /* RFC 7999 */ #define COMMUNITY_NO_EXPORT 0xff01 #define COMMUNITY_NO_ADVERTISE 0xff02 diff --git a/usr.sbin/bgpd/parse.y b/usr.sbin/bgpd/parse.y index 73bdb3a0cb9..0b09f83bc0a 100644 --- a/usr.sbin/bgpd/parse.y +++ b/usr.sbin/bgpd/parse.y @@ -2991,7 +2991,11 @@ parsecommunity(struct filter_community *c, char *s) int i, as; /* Well-known communities */ - if (strcasecmp(s, "NO_EXPORT") == 0) { + if (strcasecmp(s, "GRACEFUL_SHUTDOWN") == 0) { + c->as = COMMUNITY_WELLKNOWN; + c->type = COMMUNITY_GRACEFUL_SHUTDOWN; + return (0); + } else if (strcasecmp(s, "NO_EXPORT") == 0) { c->as = COMMUNITY_WELLKNOWN; c->type = COMMUNITY_NO_EXPORT; return (0);