Skip to content

Commit

Permalink
bgpd: add [no]neighbor dont-capability-negotiate hostname command
Browse files Browse the repository at this point in the history
cisco routers are not dealing fairly whith unsupported capabilities.
When a cisco router receive an unsupported capabilities it reset the
negociation without notifying the unmatching capability as described in
RFC2842.
Cisco suggest the use of
neighbor x.x.x.x dont-capability-negociate capability-type
to avoid the use of "capability-type" in open message.
Our case is about the hostname capability.

this new command is to remove the use of hostname capability in the
open message with the peer "x.x.x.x".

Link: https://www.cisco.com/c/en/us/support/docs/ip/border-gateway-protocol-bgp/116189-problemsolution-technology-00.pdf

Signed-off-by: Francois Dumontet <[email protected]>
  • Loading branch information
fdumontet6WIND committed Jan 23, 2024
1 parent 94178ed commit ea84a53
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 33 deletions.
67 changes: 34 additions & 33 deletions bgpd/bgp_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -1897,46 +1897,47 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
}

/* Hostname capability */
if (cmd_hostname_get()) {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
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 */
len = strlen(cmd_hostname_get());
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;

stream_putc(s, len);
stream_put(s, cmd_hostname_get(), len);
if (cmd_domainname_get()) {
len = strlen(cmd_domainname_get());
/* FQDN capability */
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN))
if (cmd_hostname_get()) {
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
rcapp = stream_get_endp(s); /* Ptr to length placeholder */
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 */
len = strlen(cmd_hostname_get());
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;

stream_putc(s, len);
stream_put(s, cmd_domainname_get(), len);
} else
stream_putc(s, 0); /* 0 length */
stream_put(s, cmd_hostname_get(), len);
if (cmd_domainname_get()) {
len = strlen(cmd_domainname_get());
if (len > BGP_MAX_HOSTNAME)
len = BGP_MAX_HOSTNAME;

/* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1;
ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
: stream_putc_at(s, rcapp, len);
stream_putc(s, len);
stream_put(s, cmd_domainname_get(), len);
} else
stream_putc(s, 0); /* 0 length */

len = stream_get_endp(s) - capp - 1;
stream_putc_at(s, capp, len);
/* Set the lengths straight */
len = stream_get_endp(s) - rcapp - 1;
ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
: stream_putc_at(s, rcapp, len);

if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%s Sending hostname cap with hn = %s, dn = %s",
peer->host, cmd_hostname_get(),
cmd_domainname_get());
}
len = stream_get_endp(s) - capp - 1;
stream_putc_at(s, capp, len);

if (bgp_debug_neighbor_events(peer))
zlog_debug(
"%s Sending hostname cap with hn = %s, dn = %s",
peer->host, cmd_hostname_get(),
cmd_domainname_get());
}

bgp_peer_send_gr_capability(s, peer, ext_opt_params);
bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
Expand Down
27 changes: 27 additions & 0 deletions bgpd/bgp_vty.c
Original file line number Diff line number Diff line change
Expand Up @@ -5735,6 +5735,24 @@ DEFUN (no_neighbor_dont_capability_negotiate,
PEER_FLAG_DONT_CAPABILITY);
}

/* neighbor capability fqdn */
DEFPY (neighbor_capability_fqdn,
neighbor_capability_fqdn_cmd,
"[no$no]neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor capability fqdn",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Advertise capability to the peer\n"
"Advertise fqdn capability to the peer\n")
{
if (no)
return peer_flag_unset_vty(vty, neighbor,
PEER_FLAG_CAPABILITY_FQDN);
else
return peer_flag_set_vty(vty, neighbor,
PEER_FLAG_CAPABILITY_FQDN);
}

/* neighbor capability extended next hop encoding */
DEFUN (neighbor_capability_enhe,
neighbor_capability_enhe_cmd,
Expand Down Expand Up @@ -18189,6 +18207,12 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
if (peergroup_flag_check(peer, PEER_FLAG_DONT_CAPABILITY))
vty_out(vty, " neighbor %s dont-capability-negotiate\n", addr);

/* capability fqdn*/
if (!peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_FQDN))
vty_out(vty,
" no neighbor %s capability fqdn\n",
addr);

/* override-capability */
if (peergroup_flag_check(peer, PEER_FLAG_OVERRIDE_CAPABILITY))
vty_out(vty, " neighbor %s override-capability\n", addr);
Expand Down Expand Up @@ -20525,6 +20549,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE, &neighbor_dont_capability_negotiate_cmd);
install_element(BGP_NODE, &no_neighbor_dont_capability_negotiate_cmd);

/* "neighbor capability fqdn" command.*/
install_element(BGP_NODE, &neighbor_capability_fqdn_cmd);

/* "neighbor ebgp-multihop" commands. */
install_element(BGP_NODE, &neighbor_ebgp_multihop_cmd);
install_element(BGP_NODE, &neighbor_ebgp_multihop_ttl_cmd);
Expand Down
3 changes: 3 additions & 0 deletions bgpd/bgpd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1535,6 +1535,8 @@ struct peer *peer_new(struct bgp *bgp)
if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS))
SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS);

SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN);

/* Initialize per peer bgp GR FSM */
bgp_peer_gr_init(peer);

Expand Down Expand Up @@ -4571,6 +4573,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_AIGP, 0, peer_change_none},
{PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{0, 0, 0}};

static const struct peer_flag_action peer_af_flag_action_list[] = {
Expand Down
1 change: 1 addition & 0 deletions bgpd/bgpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,7 @@ struct peer {
#define PEER_FLAG_AIGP (1ULL << 34)
#define PEER_FLAG_GRACEFUL_SHUTDOWN (1ULL << 35)
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability*/

/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
Expand Down

0 comments on commit ea84a53

Please sign in to comment.