]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Implement rfc9072
authorDonatas Abraitis <donatas.abraitis@gmail.com>
Sat, 20 Nov 2021 20:00:23 +0000 (22:00 +0200)
committerDonatas Abraitis <donatas.abraitis@gmail.com>
Mon, 22 Nov 2021 13:34:46 +0000 (15:34 +0200)
Related: https://datatracker.ietf.org/doc/html/rfc9072

Signed-off-by: Donatas Abraitis <donatas.abraitis@gmail.com>
bgpd/bgp_open.c
bgpd/bgp_open.h
bgpd/bgp_packet.c
bgpd/bgp_vty.c
bgpd/bgpd.c
bgpd/bgpd.h

index e15690835aafed5c956262359ff0db5cf939ab17..2e01ff6f8952772aa0a70e3280ac07dc58422506 100644 (file)
@@ -1088,7 +1088,7 @@ static bool strict_capability_same(struct peer *peer)
 /* peek into option, stores ASN to *as4 if the AS4 capability was found.
  * Returns  0 if no as4 found, as4cap value otherwise.
  */
-as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
+as_t peek_for_as4_capability(struct peer *peer, uint16_t length)
 {
        struct stream *s = BGP_INPUT(peer);
        size_t orig_getp = stream_get_getp(s);
@@ -1104,7 +1104,7 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
         */
        while (stream_get_getp(s) < end) {
                uint8_t opt_type;
-               uint8_t opt_length;
+               uint16_t opt_length;
 
                /* Check the length. */
                if (stream_get_getp(s) + 2 > end)
@@ -1112,7 +1112,9 @@ as_t peek_for_as4_capability(struct peer *peer, uint8_t length)
 
                /* Fetch option type and length. */
                opt_type = stream_getc(s);
-               opt_length = stream_getc(s);
+               opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+                                    ? stream_getw(s)
+                                    : stream_getc(s);
 
                /* Option length check. */
                if (stream_get_getp(s) + opt_length > end)
@@ -1160,7 +1162,8 @@ end:
  *
  * @param[out] mp_capability @see bgp_capability_parse() for semantics.
  */
-int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
+int bgp_open_option_parse(struct peer *peer, uint16_t length,
+                         int *mp_capability)
 {
        int ret = 0;
        uint8_t *error;
@@ -1179,7 +1182,7 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
 
        while (stream_get_getp(s) < end) {
                uint8_t opt_type;
-               uint8_t opt_length;
+               uint16_t opt_length;
 
                /* Must have at least an OPEN option header */
                if (STREAM_READABLE(s) < 2) {
@@ -1191,11 +1194,14 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
 
                /* Fetch option type and length. */
                opt_type = stream_getc(s);
-               opt_length = stream_getc(s);
+               opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+                                    ? stream_getw(s)
+                                    : stream_getc(s);
 
                /* Option length check. */
                if (STREAM_READABLE(s) < opt_length) {
-                       zlog_info("%s Option length error", peer->host);
+                       zlog_info("%s Option length error (%d)", peer->host,
+                                 opt_length);
                        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
                                        BGP_NOTIFY_OPEN_MALFORMED_ATTR);
                        return -1;
@@ -1299,9 +1305,10 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
 }
 
 static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
-                                   afi_t afi, safi_t safi, uint8_t code)
+                                   afi_t afi, safi_t safi, uint8_t code,
+                                   bool ext_opt_params)
 {
-       uint8_t cap_len;
+       uint16_t cap_len;
        uint8_t orf_len;
        unsigned long capp;
        unsigned long orfp;
@@ -1315,7 +1322,8 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
 
        stream_putc(s, BGP_OPEN_OPT_CAP);
        capp = stream_get_endp(s); /* Set Capability Len Pointer */
-       stream_putc(s, 0);       /* Capability Length */
+       ext_opt_params ? stream_putw(s, 0)
+                      : stream_putc(s, 0); /* Capability Length */
        stream_putc(s, code);      /* Capability Code */
        orfp = stream_get_endp(s); /* Set ORF Len Pointer */
        stream_putc(s, 0);       /* ORF Length */
@@ -1363,11 +1371,12 @@ static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
 
        /* Total Capability Len. */
        cap_len = stream_get_endp(s) - capp - 1;
-       stream_putc_at(s, capp, cap_len);
+       ext_opt_params ? stream_putw_at(s, capp, cap_len)
+                      : stream_putc_at(s, capp, cap_len);
 }
 
 static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
-                                       unsigned long cp)
+                                       bool ext_opt_params)
 {
        int len;
        iana_afi_t pkt_afi;
@@ -1389,7 +1398,8 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
        SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
        capp = stream_get_endp(s); /* Set Capability Len Pointer */
-       stream_putc(s, 0);       /* Capability Length */
+       ext_opt_params ? stream_putw(s, 0)
+                      : stream_putc(s, 0); /* Capability Length */
        stream_putc(s, CAPABILITY_CODE_RESTART);
        /* Set Restart Capability Len Pointer */
        rcapp = stream_get_endp(s);
@@ -1444,11 +1454,12 @@ static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
 
        /* Total Capability Len. */
        len = stream_get_endp(s) - capp - 1;
-       stream_putc_at(s, capp, len);
+       ext_opt_params ? stream_putw_at(s, capp, len - 1)
+                      : stream_putc_at(s, capp, len);
 }
 
 static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
-                                         unsigned long cp)
+                                         bool ext_opt_params)
 {
        int len;
        iana_afi_t pkt_afi;
@@ -1465,7 +1476,8 @@ static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
 
        stream_putc(s, BGP_OPEN_OPT_CAP);
        capp = stream_get_endp(s); /* Set Capability Len Pointer */
-       stream_putc(s, 0);       /* Capability Length */
+       ext_opt_params ? stream_putw(s, 0)
+                      : stream_putc(s, 0); /* Capability Length */
        stream_putc(s, CAPABILITY_CODE_LLGR);
 
        rcapp = stream_get_endp(s);
@@ -1491,14 +1503,16 @@ static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
 
        /* Total Capability Len. */
        len = stream_get_endp(s) - capp - 1;
-       stream_putc_at(s, capp, len);
+       ext_opt_params ? stream_putw_at(s, capp, len - 1)
+                      : stream_putc_at(s, capp, len);
 }
 
 /* Fill in capability open option to the packet. */
-void bgp_open_capability(struct stream *s, struct peer *peer)
+uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
+                            bool ext_opt_params)
 {
-       uint8_t len;
-       unsigned long cp, capp, rcapp;
+       uint16_t len;
+       unsigned long cp, capp, rcapp, eopl = 0;
        iana_afi_t pkt_afi;
        afi_t afi;
        safi_t safi;
@@ -1507,16 +1521,26 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        uint8_t afi_safi_count = 0;
        int adv_addpath_tx = 0;
 
-       /* Remember current pointer for Opt Parm Len. */
+       /* Non-Ext OP Len. */
        cp = stream_get_endp(s);
-
-       /* Opt Parm Len. */
        stream_putc(s, 0);
 
+       if (ext_opt_params) {
+               /* Non-Ext OP Len. */
+               stream_putc_at(s, cp, BGP_OPEN_NON_EXT_OPT_LEN);
+
+               /* Non-Ext OP Type */
+               stream_putc(s, BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH);
+
+               /* Extended Opt. Parm. Length */
+               eopl = stream_get_endp(s);
+               stream_putw(s, 0);
+       }
+
        /* Do not send capability. */
        if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
            || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY))
-               return;
+               return 0;
 
        /* MP capability for configured AFI, SAFI */
        FOREACH_AFI_SAFI (afi, safi) {
@@ -1527,7 +1551,9 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
 
                        peer->afc_adv[afi][safi] = 1;
                        stream_putc(s, BGP_OPEN_OPT_CAP);
-                       stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
+                       ext_opt_params
+                               ? stream_putw(s, CAPABILITY_CODE_MP_LEN + 2)
+                               : stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
                        stream_putc(s, CAPABILITY_CODE_MP);
                        stream_putc(s, CAPABILITY_CODE_MP_LEN);
                        stream_putw(s, pkt_afi);
@@ -1547,7 +1573,13 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                                 */
                                SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV);
                                stream_putc(s, BGP_OPEN_OPT_CAP);
-                               stream_putc(s, CAPABILITY_CODE_ENHE_LEN + 2);
+                               ext_opt_params
+                                       ? stream_putw(s,
+                                                     CAPABILITY_CODE_ENHE_LEN
+                                                             + 2)
+                                       : stream_putc(s,
+                                                     CAPABILITY_CODE_ENHE_LEN
+                                                             + 2);
                                stream_putc(s, CAPABILITY_CODE_ENHE);
                                stream_putc(s, CAPABILITY_CODE_ENHE_LEN);
 
@@ -1568,25 +1600,29 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        /* Route refresh. */
        SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
+       ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
+                      : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
        stream_putc(s, CAPABILITY_CODE_REFRESH_OLD);
        stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
+       ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
+                      : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
        stream_putc(s, CAPABILITY_CODE_REFRESH);
        stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
 
        /* Enhanced Route Refresh. */
        SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
+       ext_opt_params ? stream_putw(s, CAPABILITY_CODE_ENHANCED_LEN + 2)
+                      : stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
        stream_putc(s, CAPABILITY_CODE_ENHANCED_RR);
        stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN);
 
        /* AS4 */
        SET_FLAG(peer->cap, PEER_CAP_AS4_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
+       ext_opt_params ? stream_putw(s, CAPABILITY_CODE_AS4_LEN + 2)
+                      : stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
        stream_putc(s, CAPABILITY_CODE_AS4);
        stream_putc(s, CAPABILITY_CODE_AS4_LEN);
        if (peer->change_local_as)
@@ -1598,7 +1634,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        /* Extended Message Support */
        SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
+       ext_opt_params ? stream_putw(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2)
+                      : stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
        stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE);
        stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN);
 
@@ -1617,7 +1654,11 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
 
        SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV);
        stream_putc(s, BGP_OPEN_OPT_CAP);
-       stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count) + 2);
+       ext_opt_params
+               ? stream_putw(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
+                                        + 2)
+               : stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
+                                        + 2);
        stream_putc(s, CAPABILITY_CODE_ADDPATH);
        stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count);
 
@@ -1664,9 +1705,11 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                    || CHECK_FLAG(peer->af_flags[afi][safi],
                                  PEER_FLAG_ORF_PREFIX_RM)) {
                        bgp_open_capability_orf(s, peer, afi, safi,
-                                               CAPABILITY_CODE_ORF_OLD);
+                                               CAPABILITY_CODE_ORF_OLD,
+                                               ext_opt_params);
                        bgp_open_capability_orf(s, peer, afi, safi,
-                                               CAPABILITY_CODE_ORF);
+                                               CAPABILITY_CODE_ORF,
+                                               ext_opt_params);
                }
        }
 
@@ -1674,11 +1717,15 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
        if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
                SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
                stream_putc(s, BGP_OPEN_OPT_CAP);
-               stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
+               ext_opt_params
+                       ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
+                       : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
                stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD);
                stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
                stream_putc(s, BGP_OPEN_OPT_CAP);
-               stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
+               ext_opt_params
+                       ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
+                       : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
                stream_putc(s, CAPABILITY_CODE_DYNAMIC);
                stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
        }
@@ -1688,7 +1735,8 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
                stream_putc(s, BGP_OPEN_OPT_CAP);
                rcapp = stream_get_endp(s); /* Ptr to length placeholder */
-               stream_putc(s, 0);        /* dummy len for now */
+               ext_opt_params ? stream_putw(s, 0)
+                              : stream_putc(s, 0); /* Capability Length */
                stream_putc(s, CAPABILITY_CODE_FQDN);
                capp = stream_get_endp(s);
                stream_putc(s, 0); /* dummy len for now */
@@ -1710,7 +1758,9 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
 
                /* Set the lengths straight */
                len = stream_get_endp(s) - rcapp - 1;
-               stream_putc_at(s, rcapp, len);
+               ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
+                              : stream_putc_at(s, rcapp, len);
+
                len = stream_get_endp(s) - capp - 1;
                stream_putc_at(s, capp, len);
 
@@ -1721,10 +1771,18 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
                                cmd_domainname_get());
        }
 
-       bgp_peer_send_gr_capability(s, peer, cp);
-       bgp_peer_send_llgr_capability(s, peer, cp);
+       bgp_peer_send_gr_capability(s, peer, ext_opt_params);
+       bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
 
        /* Total Opt Parm Len. */
        len = stream_get_endp(s) - cp - 1;
-       stream_putc_at(s, cp, len);
+
+       if (ext_opt_params) {
+               len = stream_get_endp(s) - eopl - 2;
+               stream_putw_at(s, eopl, len);
+       } else {
+               stream_putc_at(s, cp, len);
+       }
+
+       return len;
 }
index 0d616926a2e0702e530e4ad5f0ef4f962827cd56..c04816c00600503dfad60bf386bb0587d67a0f5b 100644 (file)
@@ -93,10 +93,19 @@ struct graceful_restart_af {
 /* Long-lived Graceful Restart */
 #define LLGR_F_BIT 0x80
 
-extern int bgp_open_option_parse(struct peer *, uint8_t, int *);
-extern void bgp_open_capability(struct stream *, struct peer *);
+/* Optional Parameters */
+#define BGP_OPEN_NON_EXT_OPT_LEN 255                 /* Non-Ext OP Len. */
+#define BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH 255 /* Non-Ext OP Type */
+#define BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)                                  \
+       (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)                \
+        || CHECK_FLAG(peer->sflags, PEER_STATUS_EXT_OPT_PARAMS_LENGTH))
+
+extern int bgp_open_option_parse(struct peer *peer, uint16_t length,
+                                int *mp_capability);
+extern uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
+                                   bool ext_opt_params);
 extern void bgp_capability_vty_out(struct vty *vty, struct peer *peer,
                                   bool use_json, json_object *json_neigh);
-extern as_t peek_for_as4_capability(struct peer *, uint8_t);
+extern as_t peek_for_as4_capability(struct peer *peer, uint16_t length);
 
 #endif /* _QUAGGA_BGP_OPEN_H */
index de9a89523b4eeff36ed1dd9e1ab7cf6e9a1e1d2a..319213ef76db3468e43ff0a39a447173edb86fa0 100644 (file)
@@ -608,8 +608,22 @@ void bgp_open_send(struct peer *peer)
        stream_putw(s, send_holdtime);          /* Hold Time */
        stream_put_in_addr(s, &peer->local_id); /* BGP Identifier */
 
-       /* Set capability code. */
-       bgp_open_capability(s, peer);
+       /* Set capabilities */
+       if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
+               (void)bgp_open_capability(s, peer, true);
+       } else {
+               struct stream *tmp = stream_new(STREAM_SIZE(s));
+
+               stream_copy(tmp, s);
+               if (bgp_open_capability(tmp, peer, false)
+                   > BGP_OPEN_NON_EXT_OPT_LEN) {
+                       stream_free(tmp);
+                       (void)bgp_open_capability(s, peer, true);
+               } else {
+                       stream_copy(s, tmp);
+                       stream_free(tmp);
+               }
+       }
 
        /* Set BGP packet length. */
        (void)bgp_packet_set_size(s);
@@ -1136,7 +1150,7 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
 {
        int ret;
        uint8_t version;
-       uint8_t optlen;
+       uint16_t optlen;
        uint16_t holdtime;
        uint16_t send_holdtime;
        as_t remote_as;
@@ -1157,19 +1171,40 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
        memcpy(notify_data_remote_id, stream_pnt(peer->curr), 4);
        remote_id.s_addr = stream_get_ipv4(peer->curr);
 
-       /* Receive OPEN message log  */
-       if (bgp_debug_neighbor_events(peer))
-               zlog_debug(
-                       "%s rcv OPEN, version %d, remote-as (in open) %u, holdtime %d, id %pI4",
-                       peer->host, version, remote_as, holdtime, &remote_id);
-
        /* BEGIN to read the capability here, but dont do it yet */
        mp_capability = 0;
        optlen = stream_getc(peer->curr);
 
+       /* Extended Optional Parameters Length for BGP OPEN Message */
+       if (optlen == BGP_OPEN_NON_EXT_OPT_LEN
+           || CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_OPT_PARAMS)) {
+               uint8_t opttype;
+
+               opttype = stream_getc(peer->curr);
+               if (opttype == BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH) {
+                       optlen = stream_getw(peer->curr);
+                       SET_FLAG(peer->sflags,
+                                PEER_STATUS_EXT_OPT_PARAMS_LENGTH);
+               }
+       }
+
+       /* Receive OPEN message log  */
+       if (bgp_debug_neighbor_events(peer))
+               zlog_debug(
+                       "%s rcv OPEN%s, version %d, remote-as (in open) %u, holdtime %d, id %pI4",
+                       peer->host,
+                       CHECK_FLAG(peer->sflags,
+                                  PEER_STATUS_EXT_OPT_PARAMS_LENGTH)
+                               ? " (Extended)"
+                               : "",
+                       version, remote_as, holdtime, &remote_id);
+
        if (optlen != 0) {
                /* If not enough bytes, it is an error. */
                if (STREAM_READABLE(peer->curr) < optlen) {
+                       flog_err(EC_BGP_PKT_OPEN,
+                                "%s: stream has not enough bytes (%u)",
+                                peer->host, optlen);
                        bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
                                        BGP_NOTIFY_OPEN_MALFORMED_ATTR);
                        return BGP_Stop;
index 88d84a3c50af99e7034f2b27de69310e34da0243..d692bf82a610b88f78921e6259f7a31edf07fa5c 100644 (file)
@@ -6308,6 +6308,30 @@ DEFUN(no_neighbor_disable_link_bw_encoding_ieee,
                                   PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE);
 }
 
+/* extended-optional-parameters */
+DEFUN(neighbor_extended_optional_parameters,
+      neighbor_extended_optional_parameters_cmd,
+      "neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+      NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+      "Force the extended optional parameters format for OPEN messages\n")
+{
+       int idx_peer = 1;
+
+       return peer_flag_set_vty(vty, argv[idx_peer]->arg,
+                                PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
+
+DEFUN(no_neighbor_extended_optional_parameters,
+      no_neighbor_extended_optional_parameters_cmd,
+      "no neighbor <A.B.C.D|X:X::X:X|WORD> extended-optional-parameters",
+      NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+      "Force the extended optional parameters format for OPEN messages\n")
+{
+       int idx_peer = 2;
+
+       return peer_flag_unset_vty(vty, argv[idx_peer]->arg,
+                                  PEER_FLAG_EXTENDED_OPT_PARAMS);
+}
 
 /* enforce-first-as */
 DEFUN (neighbor_enforce_first_as,
@@ -12509,6 +12533,14 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
                                "bgpTimerConfiguredKeepAliveIntervalMsecs",
                                bgp->default_keepalive);
                }
+
+               /* Extended Optional Parameters Length for BGP OPEN Message */
+               if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+                       json_object_boolean_true_add(
+                               json_neigh, "extendedOptionalParametersLength");
+               else
+                       json_object_boolean_false_add(
+                               json_neigh, "extendedOptionalParametersLength");
        } else {
                /* Administrative shutdown. */
                if (CHECK_FLAG(p->flags, PEER_FLAG_SHUTDOWN)
@@ -12581,6 +12613,11 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
                        vty_out(vty, "  Configured tcp-mss is %d", p->tcp_mss);
                        vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss);
                }
+
+               /* Extended Optional Parameters Length for BGP OPEN Message */
+               if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(p))
+                       vty_out(vty,
+                               "  Extended Optional Parameters Length is enabled\n");
        }
        /* Capability. */
        if (peer_established(p)) {
@@ -16674,6 +16711,11 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
                vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
                        addr);
 
+       /* extended-optional-parameters */
+       if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
+               vty_out(vty, " neighbor %s extended-optional-parameters\n",
+                       addr);
+
        /* enforce-first-as */
        if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
                vty_out(vty, " neighbor %s enforce-first-as\n", addr);
@@ -18631,6 +18673,11 @@ void bgp_vty_init(void)
        install_element(BGP_NODE,
                        &no_neighbor_disable_link_bw_encoding_ieee_cmd);
 
+       /* "neighbor extended-optional-parameters" commands.  */
+       install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
+       install_element(BGP_NODE,
+                       &no_neighbor_extended_optional_parameters_cmd);
+
        /* "neighbor enforce-first-as" commands. */
        install_element(BGP_NODE, &neighbor_enforce_first_as_cmd);
        install_element(BGP_NODE, &no_neighbor_enforce_first_as_cmd);
index 9316d71baffd55e18c0e07a13e6a5dec0b787f63..762a338c1c6a3679fc6691f5f8121bd38111ad48 100644 (file)
@@ -4181,6 +4181,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
        {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
        {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
        {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
+       {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
        {0, 0, 0}};
 
 static const struct peer_flag_action peer_af_flag_action_list[] = {
index 29775bccceffccfe19a57f595e79b68f190a0bfe..7c9106560118cc63e8bad609e56513c195930141 100644 (file)
@@ -1298,6 +1298,8 @@ struct peer {
  * extended communities.
  */
 #define PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE (1U << 29)
+/* force the extended format for Optional Parameters in OPEN message */
+#define PEER_FLAG_EXTENDED_OPT_PARAMS (1U << 30)
 
        /*
         *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1384,6 +1386,8 @@ struct peer {
 #define PEER_STATUS_GROUP             (1U << 4) /* peer-group conf */
 #define PEER_STATUS_NSF_MODE          (1U << 5) /* NSF aware peer */
 #define PEER_STATUS_NSF_WAIT          (1U << 6) /* wait comeback peer */
+/* received extended format encoding for OPEN message */
+#define PEER_STATUS_EXT_OPT_PARAMS_LENGTH (1U << 7)
 
        /* Peer status af flags (reset in bgp_stop) */
        uint16_t af_sflags[AFI_MAX][SAFI_MAX];