mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-05 04:40:21 +00:00
Merge pull request #10105 from ton31337/feature/rfc9072
bgpd: Implement rfc9072
This commit is contained in:
commit
5c24a442d9
140
bgpd/bgp_open.c
140
bgpd/bgp_open.c
@ -1091,7 +1091,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);
|
||||
@ -1107,7 +1107,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)
|
||||
@ -1115,7 +1115,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)
|
||||
@ -1163,7 +1165,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;
|
||||
@ -1182,7 +1185,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) {
|
||||
@ -1194,11 +1197,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;
|
||||
@ -1302,9 +1308,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;
|
||||
@ -1318,7 +1325,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 */
|
||||
@ -1366,11 +1374,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;
|
||||
@ -1392,7 +1401,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);
|
||||
@ -1447,11 +1457,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;
|
||||
@ -1468,7 +1479,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);
|
||||
@ -1494,14 +1506,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;
|
||||
@ -1510,16 +1524,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) {
|
||||
@ -1530,7 +1554,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);
|
||||
@ -1550,7 +1576,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);
|
||||
|
||||
@ -1571,25 +1603,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)
|
||||
@ -1601,7 +1637,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);
|
||||
|
||||
@ -1620,7 +1657,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);
|
||||
|
||||
@ -1667,9 +1708,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1677,11 +1720,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);
|
||||
}
|
||||
@ -1691,7 +1738,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 */
|
||||
@ -1713,7 +1761,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);
|
||||
|
||||
@ -1724,10 +1774,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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -6302,6 +6302,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,
|
||||
@ -12497,6 +12521,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)
|
||||
@ -12569,6 +12601,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)) {
|
||||
@ -16636,6 +16673,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);
|
||||
@ -18593,6 +18635,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);
|
||||
|
@ -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[] = {
|
||||
|
@ -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];
|
||||
|
@ -1423,6 +1423,15 @@ Configuring Peers
|
||||
value is carried encoded as uint32. To enable backward compatibility we
|
||||
need to disable IEEE floating-point encoding option per-peer.
|
||||
|
||||
.. clicmd:: neighbor PEER extended-optional-parameters
|
||||
|
||||
Force Extended Optional Parameters Length format to be used for OPEN messages.
|
||||
|
||||
By default, it's disabled. If the standard optional parameters length is
|
||||
higher than one-octet (255), then extended format is enabled automatically.
|
||||
|
||||
For testing purposes, extended format can be enabled with this command.
|
||||
|
||||
.. clicmd:: neighbor PEER ebgp-multihop
|
||||
|
||||
Specifying ``ebgp-multihop`` allows sessions with eBGP neighbors to
|
||||
|
@ -371,7 +371,8 @@ BGP
|
||||
:t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017`
|
||||
- :rfc:`8654`
|
||||
:t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019`
|
||||
|
||||
- :rfc:`9072`
|
||||
:t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021`
|
||||
|
||||
OSPF
|
||||
----
|
||||
|
@ -0,0 +1,6 @@
|
||||
!
|
||||
router bgp 65001
|
||||
no bgp ebgp-requires-policy
|
||||
neighbor 192.168.1.2 remote-as external
|
||||
neighbor 192.168.1.2 extended-optional-parameters
|
||||
!
|
@ -0,0 +1,4 @@
|
||||
!
|
||||
int r1-eth0
|
||||
ip address 192.168.1.1/24
|
||||
!
|
@ -0,0 +1,8 @@
|
||||
router bgp 65002
|
||||
no bgp ebgp-requires-policy
|
||||
neighbor 192.168.1.1 remote-as external
|
||||
neighbor 192.168.1.1 extended-optional-parameters
|
||||
address-family ipv4 unicast
|
||||
redistribute connected
|
||||
exit-address-family
|
||||
!
|
@ -0,0 +1,7 @@
|
||||
!
|
||||
int lo
|
||||
ip address 172.16.16.1/32
|
||||
!
|
||||
int r2-eth0
|
||||
ip address 192.168.1.2/24
|
||||
!
|
@ -0,0 +1,106 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (c) 2021 by
|
||||
# Donatas Abraitis <donatas.abraitis@gmail.com>
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software
|
||||
# for any purpose with or without fee is hereby granted, provided
|
||||
# that the above copyright notice and this permission notice appear
|
||||
# in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
|
||||
# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||||
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
# OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
"""
|
||||
Test if Extended Optional Parameters Length encoding format works
|
||||
if forced with a knob.
|
||||
https://datatracker.ietf.org/doc/html/rfc9072
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import pytest
|
||||
import functools
|
||||
|
||||
pytestmark = pytest.mark.bgpd
|
||||
|
||||
CWD = os.path.dirname(os.path.realpath(__file__))
|
||||
sys.path.append(os.path.join(CWD, "../"))
|
||||
|
||||
# pylint: disable=C0413
|
||||
from lib import topotest
|
||||
from lib.topogen import Topogen, TopoRouter, get_topogen
|
||||
|
||||
pytestmark = [pytest.mark.bgpd]
|
||||
|
||||
|
||||
def setup_module(mod):
|
||||
topodef = {"s1": ("r1", "r2")}
|
||||
tgen = Topogen(topodef, mod.__name__)
|
||||
tgen.start_topology()
|
||||
|
||||
router_list = tgen.routers()
|
||||
|
||||
for i, (rname, router) in enumerate(router_list.items(), 1):
|
||||
router.load_config(
|
||||
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
|
||||
)
|
||||
router.load_config(
|
||||
TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
|
||||
)
|
||||
|
||||
tgen.start_router()
|
||||
|
||||
|
||||
def teardown_module(mod):
|
||||
tgen = get_topogen()
|
||||
tgen.stop_topology()
|
||||
|
||||
|
||||
def test_bgp_extended_optional_parameters_length():
|
||||
tgen = get_topogen()
|
||||
|
||||
if tgen.routers_have_failure():
|
||||
pytest.skip(tgen.errors)
|
||||
|
||||
router = tgen.gears["r1"]
|
||||
|
||||
def _bgp_converge(router):
|
||||
output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast summary json"))
|
||||
expected = {
|
||||
"peers": {
|
||||
"192.168.1.2": {
|
||||
"pfxRcd": 2,
|
||||
"pfxSnt": 2,
|
||||
"state": "Established",
|
||||
"peerState": "OK",
|
||||
}
|
||||
}
|
||||
}
|
||||
return topotest.json_cmp(output, expected)
|
||||
|
||||
test_func = functools.partial(_bgp_converge, router)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||
assert result is None, "Can't converge with extended-optional-parameters"
|
||||
|
||||
def _bgp_extended_optional_parameters_length(router):
|
||||
output = json.loads(router.vtysh_cmd("show bgp neighbor 192.168.1.2 json"))
|
||||
expected = {"192.168.1.2": {"extendedOptionalParametersLength": True}}
|
||||
return topotest.json_cmp(output, expected)
|
||||
|
||||
test_func = functools.partial(_bgp_extended_optional_parameters_length, router)
|
||||
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
|
||||
assert result is None, "Can't see Extended Optional Parameters Length to be used"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = ["-s"] + sys.argv[1:]
|
||||
sys.exit(pytest.main(args))
|
Loading…
Reference in New Issue
Block a user