From: Donatas Abraitis Date: Sat, 5 Aug 2023 19:32:57 +0000 (+0300) Subject: bgpd: Handle role capability using dynamic capability X-Git-Tag: base_9.1~171^2~2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=454d37aec249673c7a2fff1e99f11e90c659973f;p=matthieu%2Ffrr.git bgpd: Handle role capability using dynamic capability When setting local-role for the neighbor, force sending ROLE capability via dynamic capability if it's enabled. Signed-off-by: Donatas Abraitis --- diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 7c2c6f616b..fcd644a210 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1272,7 +1272,15 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi, case CAPABILITY_CODE_FQDN: case CAPABILITY_CODE_ENHE: case CAPABILITY_CODE_EXT_MESSAGE: + break; case CAPABILITY_CODE_ROLE: + if (peer->local_role != ROLE_UNDEFINED) { + SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV); + stream_putc(s, action); + stream_putc(s, CAPABILITY_CODE_ROLE); + stream_putc(s, CAPABILITY_CODE_ROLE_LEN); + stream_putc(s, peer->local_role); + } break; default: break; @@ -2876,7 +2884,22 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt, case CAPABILITY_CODE_FQDN: case CAPABILITY_CODE_ENHE: case CAPABILITY_CODE_EXT_MESSAGE: + break; case CAPABILITY_CODE_ROLE: + SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV); + if (hdr->length != CAPABILITY_CODE_ROLE_LEN) { + flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH, + "Role: Received invalid length %d", + hdr->length); + bgp_notify_send(peer, BGP_NOTIFY_CEASE, + BGP_NOTIFY_SUBCODE_UNSPECIFIC); + return BGP_Stop; + } + uint8_t role; + + memcpy(&role, pnt + 3, sizeof(role)); + + peer->remote_role = role; break; default: flog_warn( diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 591e0c3969..52c9b95992 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6786,14 +6786,9 @@ static uint8_t get_role_by_name(const char *role_str) return ROLE_UNDEFINED; } -static int peer_role_set_vty(struct vty *vty, const char *ip_str, +static int peer_role_set_vty(struct vty *vty, struct peer *peer, const char *role_str, bool strict_mode) { - struct peer *peer; - - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; uint8_t role = get_role_by_name(role_str); if (role == ROLE_UNDEFINED) @@ -6801,50 +6796,66 @@ static int peer_role_set_vty(struct vty *vty, const char *ip_str, return bgp_vty_return(vty, peer_role_set(peer, role, strict_mode)); } -static int peer_role_unset_vty(struct vty *vty, const char *ip_str) -{ - struct peer *peer; - - peer = peer_and_group_lookup_vty(vty, ip_str); - if (!peer) - return CMD_WARNING_CONFIG_FAILED; - return bgp_vty_return(vty, peer_role_unset(peer)); -} - DEFPY(neighbor_role, neighbor_role_cmd, - "neighbor local-role ", + "neighbor $neighbor local-role $role", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Set session role\n" ROLE_STR) { - int idx_peer = 1; - int idx_role = 3; + int ret; + struct peer *peer; + + peer = peer_and_group_lookup_vty(vty, neighbor); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + ret = peer_role_set_vty(vty, peer, role, false); + + if (peer_established(peer)) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) && + CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_ROLE, + CAPABILITY_ACTION_SET); + } - return peer_role_set_vty(vty, argv[idx_peer]->arg, argv[idx_role]->arg, - false); + return ret; } DEFPY(neighbor_role_strict, neighbor_role_strict_cmd, - "neighbor local-role strict-mode", + "neighbor $neighbor local-role $role strict-mode", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Set session role\n" ROLE_STR "Use additional restriction on peer\n") { - int idx_peer = 1; - int idx_role = 3; + int ret; + struct peer *peer; + + peer = peer_and_group_lookup_vty(vty, neighbor); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; - return peer_role_set_vty(vty, argv[idx_peer]->arg, argv[idx_role]->arg, - true); + ret = peer_role_set_vty(vty, peer, role, true); + + if (peer_established(peer)) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) && + CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_ROLE, + CAPABILITY_ACTION_SET); + } + + return ret; } DEFPY(no_neighbor_role, no_neighbor_role_cmd, - "no neighbor local-role [strict-mode]", + "no neighbor $neighbor local-role [strict-mode]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 @@ -6852,9 +6863,24 @@ DEFPY(no_neighbor_role, ROLE_STR "Use additional restriction on peer\n") { - int idx_peer = 2; + int ret; + struct peer *peer; + + peer = peer_and_group_lookup_vty(vty, neighbor); + if (!peer) + return CMD_WARNING_CONFIG_FAILED; + + ret = bgp_vty_return(vty, peer_role_unset(peer)); - return peer_role_unset_vty(vty, argv[idx_peer]->arg); + if (peer_established(peer)) { + if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) && + CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_ROLE, + CAPABILITY_ACTION_UNSET); + } + + return ret; } /* disable-connected-check */ diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index b72e75d12e..aaf1f41c4b 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -4444,8 +4444,8 @@ static const struct peer_flag_action peer_flag_action_list[] = { {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}, - {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset}, - {PEER_FLAG_ROLE, 0, peer_change_reset}, + {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_none}, + {PEER_FLAG_ROLE, 0, peer_change_none}, {PEER_FLAG_PORT, 0, peer_change_reset}, {PEER_FLAG_AIGP, 0, peer_change_none}, {PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none}, @@ -5167,7 +5167,6 @@ int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode) else UNSET_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE); - bgp_session_reset(peer); } return CMD_SUCCESS; @@ -5212,7 +5211,6 @@ int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode) UNSET_FLAG(member->flags, PEER_FLAG_ROLE_STRICT_MODE); } - bgp_session_reset(member); } }