mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-15 05:18:47 +00:00
Merge pull request #14540 from opensourcerouting/feature/bgpd_handle_fqdn_capability_via_dynamic_capability
bgpd: Handle FQDN capability using dynamic capabilities
This commit is contained in:
commit
b6b0001a4c
@ -1218,6 +1218,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
uint8_t number_of_orfs = 0;
|
uint8_t number_of_orfs = 0;
|
||||||
const char *capability = lookup_msg(capcode_str, capability_code,
|
const char *capability = lookup_msg(capcode_str, capability_code,
|
||||||
"Unknown");
|
"Unknown");
|
||||||
|
const char *hostname = cmd_hostname_get();
|
||||||
|
const char *domainname = cmd_domainname_get();
|
||||||
|
|
||||||
if (!peer_established(peer->connection))
|
if (!peer_established(peer->connection))
|
||||||
return;
|
return;
|
||||||
@ -1531,11 +1533,48 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
capability, iana_afi2str(pkt_afi),
|
capability, iana_afi2str(pkt_afi),
|
||||||
iana_safi2str(pkt_safi));
|
iana_safi2str(pkt_safi));
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_FQDN:
|
||||||
|
if (hostname) {
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
|
||||||
|
stream_putc(s, action);
|
||||||
|
stream_putc(s, CAPABILITY_CODE_FQDN);
|
||||||
|
cap_len = stream_get_endp(s);
|
||||||
|
stream_putc(s, 0); /* Capability Length */
|
||||||
|
|
||||||
|
len = strlen(hostname);
|
||||||
|
if (len > BGP_MAX_HOSTNAME)
|
||||||
|
len = BGP_MAX_HOSTNAME;
|
||||||
|
|
||||||
|
stream_putc(s, len);
|
||||||
|
stream_put(s, hostname, len);
|
||||||
|
|
||||||
|
if (domainname) {
|
||||||
|
len = strlen(domainname);
|
||||||
|
if (len > BGP_MAX_HOSTNAME)
|
||||||
|
len = BGP_MAX_HOSTNAME;
|
||||||
|
|
||||||
|
stream_putc(s, len);
|
||||||
|
stream_put(s, domainname, len);
|
||||||
|
} else
|
||||||
|
stream_putc(s, 0);
|
||||||
|
|
||||||
|
len = stream_get_endp(s) - cap_len - 1;
|
||||||
|
stream_putc_at(s, cap_len, len);
|
||||||
|
|
||||||
|
if (bgp_debug_neighbor_events(peer))
|
||||||
|
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
|
||||||
|
peer,
|
||||||
|
action == CAPABILITY_ACTION_SET
|
||||||
|
? "Advertising"
|
||||||
|
: "Removing",
|
||||||
|
capability, iana_afi2str(pkt_afi),
|
||||||
|
iana_safi2str(pkt_safi));
|
||||||
|
}
|
||||||
|
break;
|
||||||
case CAPABILITY_CODE_REFRESH:
|
case CAPABILITY_CODE_REFRESH:
|
||||||
case CAPABILITY_CODE_AS4:
|
case CAPABILITY_CODE_AS4:
|
||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
case CAPABILITY_CODE_ENHANCED_RR:
|
case CAPABILITY_CODE_ENHANCED_RR:
|
||||||
case CAPABILITY_CODE_FQDN:
|
|
||||||
case CAPABILITY_CODE_ENHE:
|
case CAPABILITY_CODE_ENHE:
|
||||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||||
break;
|
break;
|
||||||
@ -3233,6 +3272,89 @@ static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
|
||||||
|
struct capability_header *hdr,
|
||||||
|
struct peer *peer)
|
||||||
|
{
|
||||||
|
uint8_t *data = pnt + 3;
|
||||||
|
uint8_t *end = data + hdr->length;
|
||||||
|
char str[BGP_MAX_HOSTNAME + 1] = {};
|
||||||
|
uint8_t len;
|
||||||
|
|
||||||
|
if (action == CAPABILITY_ACTION_SET) {
|
||||||
|
/* hostname */
|
||||||
|
if (data + 1 > end) {
|
||||||
|
zlog_err("%pBP: Received invalid FQDN capability (host name length)",
|
||||||
|
peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = *data;
|
||||||
|
if (data + len > end) {
|
||||||
|
zlog_err("%pBP: Received invalid FQDN capability length (host name) %d",
|
||||||
|
peer, hdr->length);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data++;
|
||||||
|
|
||||||
|
if (len > BGP_MAX_HOSTNAME) {
|
||||||
|
memcpy(&str, data, BGP_MAX_HOSTNAME);
|
||||||
|
str[BGP_MAX_HOSTNAME] = '\0';
|
||||||
|
} else if (len) {
|
||||||
|
memcpy(&str, data, len);
|
||||||
|
str[len] = '\0';
|
||||||
|
}
|
||||||
|
data += len;
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
str[len] = '\0';
|
||||||
|
|
||||||
|
XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
|
||||||
|
XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
|
||||||
|
|
||||||
|
peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data + 1 > end) {
|
||||||
|
zlog_err("%pBP: Received invalid FQDN capability (domain name length)",
|
||||||
|
peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* domainname */
|
||||||
|
len = *data;
|
||||||
|
if (data + len > end) {
|
||||||
|
zlog_err("%pBP: Received invalid FQDN capability length (domain name) %d",
|
||||||
|
peer, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
data++;
|
||||||
|
|
||||||
|
if (len > BGP_MAX_HOSTNAME) {
|
||||||
|
memcpy(&str, data, BGP_MAX_HOSTNAME);
|
||||||
|
str[BGP_MAX_HOSTNAME] = '\0';
|
||||||
|
} else if (len) {
|
||||||
|
memcpy(&str, data, len);
|
||||||
|
str[len] = '\0';
|
||||||
|
}
|
||||||
|
data += len;
|
||||||
|
|
||||||
|
if (len) {
|
||||||
|
str[len] = '\0';
|
||||||
|
|
||||||
|
XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
|
||||||
|
|
||||||
|
peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
|
||||||
|
} else {
|
||||||
|
UNSET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
|
||||||
|
XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
|
||||||
|
XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
|
static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
|
||||||
struct capability_header *hdr,
|
struct capability_header *hdr,
|
||||||
struct peer *peer)
|
struct peer *peer)
|
||||||
@ -3593,11 +3715,13 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
|
|||||||
case CAPABILITY_CODE_ORF:
|
case CAPABILITY_CODE_ORF:
|
||||||
bgp_dynamic_capability_orf(pnt, action, hdr, peer);
|
bgp_dynamic_capability_orf(pnt, action, hdr, peer);
|
||||||
break;
|
break;
|
||||||
|
case CAPABILITY_CODE_FQDN:
|
||||||
|
bgp_dynamic_capability_fqdn(pnt, action, hdr, peer);
|
||||||
|
break;
|
||||||
case CAPABILITY_CODE_REFRESH:
|
case CAPABILITY_CODE_REFRESH:
|
||||||
case CAPABILITY_CODE_AS4:
|
case CAPABILITY_CODE_AS4:
|
||||||
case CAPABILITY_CODE_DYNAMIC:
|
case CAPABILITY_CODE_DYNAMIC:
|
||||||
case CAPABILITY_CODE_ENHANCED_RR:
|
case CAPABILITY_CODE_ENHANCED_RR:
|
||||||
case CAPABILITY_CODE_FQDN:
|
|
||||||
case CAPABILITY_CODE_ENHE:
|
case CAPABILITY_CODE_ENHE:
|
||||||
case CAPABILITY_CODE_EXT_MESSAGE:
|
case CAPABILITY_CODE_EXT_MESSAGE:
|
||||||
break;
|
break;
|
||||||
|
@ -10572,7 +10572,7 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
|
|||||||
/* one clear bgp command to rule them all */
|
/* one clear bgp command to rule them all */
|
||||||
DEFUN (clear_ip_bgp_all,
|
DEFUN (clear_ip_bgp_all,
|
||||||
clear_ip_bgp_all_cmd,
|
clear_ip_bgp_all_cmd,
|
||||||
"clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats>]",
|
"clear [ip] bgp [<view|vrf> VIEWVRFNAME] [<ipv4|ipv6|l2vpn> [<unicast|multicast|vpn|labeled-unicast|flowspec|evpn>]] <*|A.B.C.D$neighbor|X:X::X:X$neighbor|WORD$neighbor|ASNUM|external|peer-group PGNAME> [<soft [<in|out>]|in [prefix-filter]|out|message-stats|capabilities>]",
|
||||||
CLEAR_STR
|
CLEAR_STR
|
||||||
IP_STR
|
IP_STR
|
||||||
BGP_STR
|
BGP_STR
|
||||||
@ -10595,7 +10595,8 @@ DEFUN (clear_ip_bgp_all,
|
|||||||
BGP_SOFT_IN_STR
|
BGP_SOFT_IN_STR
|
||||||
"Push out prefix-list ORF and do inbound soft reconfig\n"
|
"Push out prefix-list ORF and do inbound soft reconfig\n"
|
||||||
BGP_SOFT_OUT_STR
|
BGP_SOFT_OUT_STR
|
||||||
"Reset message statistics\n")
|
"Reset message statistics\n"
|
||||||
|
"Resend capabilities\n")
|
||||||
{
|
{
|
||||||
char *vrf = NULL;
|
char *vrf = NULL;
|
||||||
|
|
||||||
@ -10652,7 +10653,7 @@ DEFUN (clear_ip_bgp_all,
|
|||||||
clr_sort = clear_external;
|
clr_sort = clear_external;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* [<soft [<in|out>]|in [prefix-filter]|out|message-stats>] */
|
/* [<soft [<in|out>]|in [prefix-filter]|out|message-stats|capabilities>] */
|
||||||
if (argv_find(argv, argc, "soft", &idx)) {
|
if (argv_find(argv, argc, "soft", &idx)) {
|
||||||
if (argv_find(argv, argc, "in", &idx)
|
if (argv_find(argv, argc, "in", &idx)
|
||||||
|| argv_find(argv, argc, "out", &idx))
|
|| argv_find(argv, argc, "out", &idx))
|
||||||
@ -10669,6 +10670,8 @@ DEFUN (clear_ip_bgp_all,
|
|||||||
clr_type = BGP_CLEAR_SOFT_OUT;
|
clr_type = BGP_CLEAR_SOFT_OUT;
|
||||||
} else if (argv_find(argv, argc, "message-stats", &idx)) {
|
} else if (argv_find(argv, argc, "message-stats", &idx)) {
|
||||||
clr_type = BGP_CLEAR_MESSAGE_STATS;
|
clr_type = BGP_CLEAR_MESSAGE_STATS;
|
||||||
|
} else if (argv_find(argv, argc, "capabilities", &idx)) {
|
||||||
|
clr_type = BGP_CLEAR_CAPABILITIES;
|
||||||
} else
|
} else
|
||||||
clr_type = BGP_CLEAR_SOFT_NONE;
|
clr_type = BGP_CLEAR_SOFT_NONE;
|
||||||
|
|
||||||
|
13
bgpd/bgpd.c
13
bgpd/bgpd.c
@ -8046,6 +8046,16 @@ static void peer_reset_message_stats(struct peer *peer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function to resend some BGP capabilities that are uncontrolled.
|
||||||
|
* For instance, FQDN capability, that can't be turned off, but let's say
|
||||||
|
* we changed the hostname, we need to resend it.
|
||||||
|
*/
|
||||||
|
static void peer_clear_capabilities(struct peer *peer, afi_t afi, safi_t safi)
|
||||||
|
{
|
||||||
|
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_FQDN,
|
||||||
|
CAPABILITY_ACTION_SET);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If peer clear is invoked in a loop for all peers on the BGP instance,
|
* If peer clear is invoked in a loop for all peers on the BGP instance,
|
||||||
* it may end up freeing the doppelganger, and if this was the next node
|
* it may end up freeing the doppelganger, and if this was the next node
|
||||||
@ -8154,6 +8164,9 @@ int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
|
|||||||
if (stype == BGP_CLEAR_MESSAGE_STATS)
|
if (stype == BGP_CLEAR_MESSAGE_STATS)
|
||||||
peer_reset_message_stats(peer);
|
peer_reset_message_stats(peer);
|
||||||
|
|
||||||
|
if (stype == BGP_CLEAR_CAPABILITIES)
|
||||||
|
peer_clear_capabilities(peer, afi, safi);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2073,7 +2073,8 @@ enum bgp_clear_type {
|
|||||||
BGP_CLEAR_SOFT_IN,
|
BGP_CLEAR_SOFT_IN,
|
||||||
BGP_CLEAR_SOFT_BOTH,
|
BGP_CLEAR_SOFT_BOTH,
|
||||||
BGP_CLEAR_SOFT_IN_ORF_PREFIX,
|
BGP_CLEAR_SOFT_IN_ORF_PREFIX,
|
||||||
BGP_CLEAR_MESSAGE_STATS
|
BGP_CLEAR_MESSAGE_STATS,
|
||||||
|
BGP_CLEAR_CAPABILITIES,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Macros. */
|
/* Macros. */
|
||||||
|
@ -3938,6 +3938,26 @@ The following are available in the top level *enable* mode:
|
|||||||
Clear BGP message statistics for a specified peer or for all peers,
|
Clear BGP message statistics for a specified peer or for all peers,
|
||||||
optionally filtered by activated address-family and sub-address-family.
|
optionally filtered by activated address-family and sub-address-family.
|
||||||
|
|
||||||
|
.. clicmd:: clear bgp [ipv4|ipv6] [unicast] PEER|\* capabilities
|
||||||
|
|
||||||
|
Clear specific BGP capabilities for a specified peer or for all peers. This
|
||||||
|
includes such capabilities like FQDN capability, that can't be controlled by
|
||||||
|
any other configuration knob.
|
||||||
|
|
||||||
|
For example, if you want to change the FQDN, you MUST reset the BGP session
|
||||||
|
in order to send a new FQDN capability to the peer. This command allows you
|
||||||
|
to resend FQDN capability without resetting the session.
|
||||||
|
|
||||||
|
.. code-block:: frr
|
||||||
|
|
||||||
|
hostname bgp-new.example.com
|
||||||
|
clear bgp 10.10.10.1 capabilities
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Changing the hostname is possible only when connected to the specific daemon.
|
||||||
|
If you change the hostname via ``vtysh``, it won't be changed.
|
||||||
|
|
||||||
The following are available in the ``router bgp`` mode:
|
The following are available in the ``router bgp`` mode:
|
||||||
|
|
||||||
.. clicmd:: write-quanta (1-64)
|
.. clicmd:: write-quanta (1-64)
|
||||||
|
Loading…
Reference in New Issue
Block a user