Skip to content

Commit 05cf9d0

Browse files
committed
bgpd: Handle Addpath capability using dynamic capabilities
Changing Addpath type, and or disabling RX (receiving) flag, we can do this without tearing down the session, and using dynamic capabilities. Signed-off-by: Donatas Abraitis <[email protected]>
1 parent 51255e1 commit 05cf9d0

File tree

5 files changed

+246
-14
lines changed

5 files changed

+246
-14
lines changed

bgpd/bgp_addpath.c

+32-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#include "bgp_addpath.h"
1212
#include "bgp_route.h"
13+
#include "bgp_open.h"
14+
#include "bgp_packet.h"
1315

1416
static const struct bgp_addpath_strategy_names strat_names[BGP_ADDPATH_MAX] = {
1517
{
@@ -359,6 +361,31 @@ void bgp_addpath_type_changed(struct bgp *bgp)
359361
}
360362
}
361363

364+
int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
365+
uint8_t paths)
366+
{
367+
int action = CAPABILITY_ACTION_UNSET;
368+
369+
switch (addpath_type) {
370+
case BGP_ADDPATH_ALL:
371+
case BGP_ADDPATH_BEST_PER_AS:
372+
action = CAPABILITY_ACTION_SET;
373+
break;
374+
case BGP_ADDPATH_BEST_SELECTED:
375+
if (paths)
376+
action = CAPABILITY_ACTION_SET;
377+
else
378+
action = CAPABILITY_ACTION_UNSET;
379+
break;
380+
case BGP_ADDPATH_NONE:
381+
case BGP_ADDPATH_MAX:
382+
action = CAPABILITY_ACTION_UNSET;
383+
break;
384+
}
385+
386+
return action;
387+
}
388+
362389
/*
363390
* Change the addpath type assigned to a peer, or peer group. In addition to
364391
* adjusting the counts, peer sessions will be reset as needed to make the
@@ -373,6 +400,7 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
373400
struct listnode *node, *nnode;
374401
struct peer *tmp_peer;
375402
struct peer_group *group;
403+
int action = bgp_addpath_capability_action(addpath_type, paths);
376404

377405
if (safi == SAFI_LABELED_UNICAST)
378406
safi = SAFI_UNICAST;
@@ -430,9 +458,12 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi,
430458
}
431459
}
432460
} else {
433-
peer_change_action(peer, afi, safi, peer_change_reset);
461+
if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
462+
!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
463+
peer_change_action(peer, afi, safi, peer_change_reset);
434464
}
435465

466+
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
436467
}
437468

438469
/*

bgpd/bgp_addpath.h

+8
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
#include "bgpd/bgp_table.h"
1616
#include "lib/json.h"
1717

18+
struct bgp_addpath_capability {
19+
uint16_t afi;
20+
uint8_t safi;
21+
uint8_t flags;
22+
};
23+
1824
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
1925

2026
void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
@@ -57,4 +63,6 @@ void bgp_addpath_update_ids(struct bgp *bgp, struct bgp_dest *dest, afi_t afi,
5763
safi_t safi);
5864

5965
void bgp_addpath_type_changed(struct bgp *bgp);
66+
extern int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type,
67+
uint8_t paths);
6068
#endif

bgpd/bgp_packet.c

+177-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "lib_errors.h"
2525

2626
#include "bgpd/bgpd.h"
27+
#include "bgpd/bgp_addpath.h"
2728
#include "bgpd/bgp_table.h"
2829
#include "bgpd/bgp_dump.h"
2930
#include "bgpd/bgp_bmp.h"
@@ -1216,6 +1217,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
12161217
unsigned long cap_len;
12171218
uint16_t len;
12181219
uint32_t gr_restart_time;
1220+
uint8_t addpath_afi_safi_count = 0;
1221+
bool adv_addpath_tx = false;
12191222
const char *capability = lookup_msg(capcode_str, capability_code,
12201223
"Unknown");
12211224

@@ -1379,11 +1382,91 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
13791382
capability, iana_afi2str(pkt_afi),
13801383
iana_safi2str(pkt_safi));
13811384
break;
1385+
case CAPABILITY_CODE_ADDPATH:
1386+
SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV);
1387+
1388+
FOREACH_AFI_SAFI (afi, safi) {
1389+
if (peer->afc[afi][safi]) {
1390+
addpath_afi_safi_count++;
1391+
1392+
/* Only advertise addpath TX if a feature that
1393+
* will use it is
1394+
* configured */
1395+
if (peer->addpath_type[afi][safi] !=
1396+
BGP_ADDPATH_NONE)
1397+
adv_addpath_tx = true;
1398+
1399+
/* If we have enabled labeled unicast, we MUST check
1400+
* against unicast SAFI because addpath IDs are
1401+
* allocated under unicast SAFI, the same as the RIB
1402+
* is managed in unicast SAFI.
1403+
*/
1404+
if (safi == SAFI_LABELED_UNICAST)
1405+
if (peer->addpath_type[afi][SAFI_UNICAST] !=
1406+
BGP_ADDPATH_NONE)
1407+
adv_addpath_tx = true;
1408+
}
1409+
}
1410+
1411+
stream_putc(s, action);
1412+
stream_putc(s, CAPABILITY_CODE_ADDPATH);
1413+
stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN *
1414+
addpath_afi_safi_count);
1415+
1416+
FOREACH_AFI_SAFI (afi, safi) {
1417+
if (peer->afc[afi][safi]) {
1418+
bool adv_addpath_rx =
1419+
!CHECK_FLAG(peer->af_flags[afi][safi],
1420+
PEER_FLAG_DISABLE_ADDPATH_RX);
1421+
uint8_t flags = 0;
1422+
1423+
/* Convert AFI, SAFI to values for packet. */
1424+
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
1425+
&pkt_safi);
1426+
1427+
stream_putw(s, pkt_afi);
1428+
stream_putc(s, pkt_safi);
1429+
1430+
if (adv_addpath_rx) {
1431+
SET_FLAG(flags, BGP_ADDPATH_RX);
1432+
SET_FLAG(peer->af_cap[afi][safi],
1433+
PEER_CAP_ADDPATH_AF_RX_ADV);
1434+
} else {
1435+
UNSET_FLAG(peer->af_cap[afi][safi],
1436+
PEER_CAP_ADDPATH_AF_RX_ADV);
1437+
}
1438+
1439+
if (adv_addpath_tx) {
1440+
SET_FLAG(flags, BGP_ADDPATH_TX);
1441+
SET_FLAG(peer->af_cap[afi][safi],
1442+
PEER_CAP_ADDPATH_AF_TX_ADV);
1443+
if (safi == SAFI_LABELED_UNICAST)
1444+
SET_FLAG(peer->af_cap[afi]
1445+
[SAFI_UNICAST],
1446+
PEER_CAP_ADDPATH_AF_TX_ADV);
1447+
} else {
1448+
UNSET_FLAG(peer->af_cap[afi][safi],
1449+
PEER_CAP_ADDPATH_AF_TX_ADV);
1450+
}
1451+
1452+
stream_putc(s, flags);
1453+
}
1454+
}
1455+
1456+
if (bgp_debug_neighbor_events(peer))
1457+
zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s",
1458+
peer,
1459+
action == CAPABILITY_ACTION_SET
1460+
? "Advertising"
1461+
: "Removing",
1462+
capability, iana_afi2str(pkt_afi),
1463+
iana_safi2str(pkt_safi));
1464+
1465+
break;
13821466
case CAPABILITY_CODE_REFRESH:
13831467
case CAPABILITY_CODE_ORF:
13841468
case CAPABILITY_CODE_AS4:
13851469
case CAPABILITY_CODE_DYNAMIC:
1386-
case CAPABILITY_CODE_ADDPATH:
13871470
case CAPABILITY_CODE_ENHANCED_RR:
13881471
case CAPABILITY_CODE_FQDN:
13891472
case CAPABILITY_CODE_ENHE:
@@ -2878,6 +2961,96 @@ static int bgp_route_refresh_receive(struct peer_connection *connection,
28782961
return BGP_PACKET_NOOP;
28792962
}
28802963

2964+
static void bgp_dynamic_capability_addpath(uint8_t *pnt, int action,
2965+
struct capability_header *hdr,
2966+
struct peer *peer)
2967+
{
2968+
uint8_t *data = pnt + 3;
2969+
uint8_t *end = data + hdr->length;
2970+
size_t len = end - data;
2971+
afi_t afi;
2972+
safi_t safi;
2973+
2974+
if (action == CAPABILITY_ACTION_SET) {
2975+
if (len % CAPABILITY_CODE_ADDPATH_LEN) {
2976+
flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
2977+
"Add Path: Received invalid length %zu, non-multiple of 4",
2978+
len);
2979+
return;
2980+
}
2981+
2982+
SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
2983+
2984+
while (data + CAPABILITY_CODE_ADDPATH_LEN <= end) {
2985+
afi_t afi;
2986+
safi_t safi;
2987+
iana_afi_t pkt_afi;
2988+
iana_safi_t pkt_safi;
2989+
struct bgp_addpath_capability bac;
2990+
2991+
memcpy(&bac, data, sizeof(bac));
2992+
pkt_afi = ntohs(bac.afi);
2993+
pkt_safi = safi_int2iana(bac.safi);
2994+
2995+
if (bgp_debug_neighbor_events(peer))
2996+
zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s%s%s",
2997+
peer->host,
2998+
lookup_msg(capcode_str, hdr->code,
2999+
NULL),
3000+
iana_afi2str(pkt_afi),
3001+
iana_safi2str(pkt_safi),
3002+
(bac.flags & BGP_ADDPATH_RX)
3003+
? ", receive"
3004+
: "",
3005+
(bac.flags & BGP_ADDPATH_TX)
3006+
? ", transmit"
3007+
: "");
3008+
3009+
if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
3010+
&safi)) {
3011+
if (bgp_debug_neighbor_events(peer))
3012+
zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI",
3013+
peer->host,
3014+
iana_afi2str(pkt_afi),
3015+
iana_safi2str(pkt_safi));
3016+
continue;
3017+
} else if (!peer->afc[afi][safi]) {
3018+
if (bgp_debug_neighbor_events(peer))
3019+
zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the AddPath capability for this AFI/SAFI",
3020+
peer->host,
3021+
iana_afi2str(pkt_afi),
3022+
iana_safi2str(pkt_safi));
3023+
continue;
3024+
}
3025+
3026+
if (CHECK_FLAG(bac.flags, BGP_ADDPATH_RX))
3027+
SET_FLAG(peer->af_cap[afi][safi],
3028+
PEER_CAP_ADDPATH_AF_RX_RCV);
3029+
else
3030+
UNSET_FLAG(peer->af_cap[afi][safi],
3031+
PEER_CAP_ADDPATH_AF_RX_RCV);
3032+
3033+
if (CHECK_FLAG(bac.flags, BGP_ADDPATH_TX))
3034+
SET_FLAG(peer->af_cap[afi][safi],
3035+
PEER_CAP_ADDPATH_AF_TX_RCV);
3036+
else
3037+
UNSET_FLAG(peer->af_cap[afi][safi],
3038+
PEER_CAP_ADDPATH_AF_TX_RCV);
3039+
3040+
data += CAPABILITY_CODE_ADDPATH_LEN;
3041+
}
3042+
} else {
3043+
FOREACH_AFI_SAFI (afi, safi) {
3044+
UNSET_FLAG(peer->af_cap[afi][safi],
3045+
PEER_CAP_ADDPATH_AF_RX_RCV);
3046+
UNSET_FLAG(peer->af_cap[afi][safi],
3047+
PEER_CAP_ADDPATH_AF_TX_RCV);
3048+
}
3049+
3050+
UNSET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
3051+
}
3052+
}
3053+
28813054
static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
28823055
struct capability_header *hdr,
28833056
struct peer *peer)
@@ -3232,11 +3405,13 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
32323405
case CAPABILITY_CODE_LLGR:
32333406
bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
32343407
break;
3408+
case CAPABILITY_CODE_ADDPATH:
3409+
bgp_dynamic_capability_addpath(pnt, action, hdr, peer);
3410+
break;
32353411
case CAPABILITY_CODE_REFRESH:
32363412
case CAPABILITY_CODE_ORF:
32373413
case CAPABILITY_CODE_AS4:
32383414
case CAPABILITY_CODE_DYNAMIC:
3239-
case CAPABILITY_CODE_ADDPATH:
32403415
case CAPABILITY_CODE_ENHANCED_RR:
32413416
case CAPABILITY_CODE_FQDN:
32423417
case CAPABILITY_CODE_ENHE:

bgpd/bgp_vty.c

+28-10
Original file line numberDiff line numberDiff line change
@@ -8925,13 +8925,21 @@ DEFUN(neighbor_disable_addpath_rx,
89258925
struct peer *peer;
89268926
afi_t afi = bgp_node_afi(vty);
89278927
safi_t safi = bgp_node_safi(vty);
8928+
int ret;
8929+
int action;
89288930

89298931
peer = peer_and_group_lookup_vty(vty, peer_str);
89308932
if (!peer)
89318933
return CMD_WARNING_CONFIG_FAILED;
89328934

8933-
return peer_af_flag_set_vty(vty, peer_str, afi, safi,
8934-
PEER_FLAG_DISABLE_ADDPATH_RX);
8935+
action = bgp_addpath_capability_action(peer->addpath_type[afi][safi], 0);
8936+
8937+
ret = peer_af_flag_set_vty(vty, peer_str, afi, safi,
8938+
PEER_FLAG_DISABLE_ADDPATH_RX);
8939+
8940+
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
8941+
8942+
return ret;
89358943
}
89368944

89378945
DEFUN(no_neighbor_disable_addpath_rx,
@@ -8946,13 +8954,21 @@ DEFUN(no_neighbor_disable_addpath_rx,
89468954
struct peer *peer;
89478955
afi_t afi = bgp_node_afi(vty);
89488956
safi_t safi = bgp_node_safi(vty);
8957+
int ret;
8958+
int action;
89498959

89508960
peer = peer_and_group_lookup_vty(vty, peer_str);
89518961
if (!peer)
89528962
return CMD_WARNING_CONFIG_FAILED;
89538963

8954-
return peer_af_flag_unset_vty(vty, peer_str, afi, safi,
8955-
PEER_FLAG_DISABLE_ADDPATH_RX);
8964+
action = bgp_addpath_capability_action(peer->addpath_type[afi][safi], 0);
8965+
8966+
ret = peer_af_flag_unset_vty(vty, peer_str, afi, safi,
8967+
PEER_FLAG_DISABLE_ADDPATH_RX);
8968+
8969+
bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action);
8970+
8971+
return ret;
89568972
}
89578973

89588974
DEFUN (neighbor_addpath_tx_all_paths,
@@ -8964,13 +8980,15 @@ DEFUN (neighbor_addpath_tx_all_paths,
89648980
{
89658981
int idx_peer = 1;
89668982
struct peer *peer;
8983+
afi_t afi = bgp_node_afi(vty);
8984+
safi_t safi = bgp_node_safi(vty);
89678985

89688986
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
89698987
if (!peer)
89708988
return CMD_WARNING_CONFIG_FAILED;
89718989

8972-
bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
8973-
BGP_ADDPATH_ALL, 0);
8990+
bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_ALL, 0);
8991+
89748992
return CMD_SUCCESS;
89758993
}
89768994

@@ -8990,20 +9008,20 @@ DEFUN (no_neighbor_addpath_tx_all_paths,
89909008
{
89919009
int idx_peer = 2;
89929010
struct peer *peer;
9011+
afi_t afi = bgp_node_afi(vty);
9012+
safi_t safi = bgp_node_safi(vty);
89939013

89949014
peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg);
89959015
if (!peer)
89969016
return CMD_WARNING_CONFIG_FAILED;
89979017

8998-
if (peer->addpath_type[bgp_node_afi(vty)][bgp_node_safi(vty)]
8999-
!= BGP_ADDPATH_ALL) {
9018+
if (peer->addpath_type[afi][safi] != BGP_ADDPATH_ALL) {
90009019
vty_out(vty,
90019020
"%% Peer not currently configured to transmit all paths.");
90029021
return CMD_WARNING_CONFIG_FAILED;
90039022
}
90049023

9005-
bgp_addpath_set_peer_type(peer, bgp_node_afi(vty), bgp_node_safi(vty),
9006-
BGP_ADDPATH_NONE, 0);
9024+
bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE, 0);
90079025

90089026
return CMD_SUCCESS;
90099027
}

0 commit comments

Comments
 (0)