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);

Reply via email to