From d08c0c8077fbb3e100ed2e87927edec1a09d224b Mon Sep 17 00:00:00 2001 From: Donatas Abraitis Date: Sat, 20 Nov 2021 22:00:23 +0200 Subject: [PATCH] bgpd: Implement rfc9072 Related: https://datatracker.ietf.org/doc/html/rfc9072 Signed-off-by: Donatas Abraitis --- bgpd/bgp_open.c | 140 ++++++++++++++++++++++++++++++++-------------- bgpd/bgp_open.h | 15 ++++- bgpd/bgp_packet.c | 53 +++++++++++++++--- bgpd/bgp_vty.c | 47 ++++++++++++++++ bgpd/bgpd.c | 1 + bgpd/bgpd.h | 4 ++ 6 files changed, 207 insertions(+), 53 deletions(-) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index e15690835a..2e01ff6f89 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -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; } diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h index 0d616926a2..c04816c006 100644 --- a/bgpd/bgp_open.h +++ b/bgpd/bgp_open.h @@ -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 */ diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index de9a89523b..319213ef76 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -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; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 88d84a3c50..d692bf82a6 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -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 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 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); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9316d71baf..762a338c1c 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -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[] = { diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 29775bccce..7c91065601 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -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]; -- 2.39.5