|
24 | 24 | #include "lib_errors.h"
|
25 | 25 |
|
26 | 26 | #include "bgpd/bgpd.h"
|
| 27 | +#include "bgpd/bgp_addpath.h" |
27 | 28 | #include "bgpd/bgp_table.h"
|
28 | 29 | #include "bgpd/bgp_dump.h"
|
29 | 30 | #include "bgpd/bgp_bmp.h"
|
@@ -1216,6 +1217,8 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
1216 | 1217 | unsigned long cap_len;
|
1217 | 1218 | uint16_t len;
|
1218 | 1219 | uint32_t gr_restart_time;
|
| 1220 | + uint8_t addpath_afi_safi_count = 0; |
| 1221 | + bool adv_addpath_tx = false; |
1219 | 1222 | const char *capability = lookup_msg(capcode_str, capability_code,
|
1220 | 1223 | "Unknown");
|
1221 | 1224 |
|
@@ -1379,11 +1382,91 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
|
1379 | 1382 | capability, iana_afi2str(pkt_afi),
|
1380 | 1383 | iana_safi2str(pkt_safi));
|
1381 | 1384 | 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; |
1382 | 1466 | case CAPABILITY_CODE_REFRESH:
|
1383 | 1467 | case CAPABILITY_CODE_ORF:
|
1384 | 1468 | case CAPABILITY_CODE_AS4:
|
1385 | 1469 | case CAPABILITY_CODE_DYNAMIC:
|
1386 |
| - case CAPABILITY_CODE_ADDPATH: |
1387 | 1470 | case CAPABILITY_CODE_ENHANCED_RR:
|
1388 | 1471 | case CAPABILITY_CODE_FQDN:
|
1389 | 1472 | case CAPABILITY_CODE_ENHE:
|
@@ -2878,6 +2961,96 @@ static int bgp_route_refresh_receive(struct peer_connection *connection,
|
2878 | 2961 | return BGP_PACKET_NOOP;
|
2879 | 2962 | }
|
2880 | 2963 |
|
| 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 | + |
2881 | 3054 | static void bgp_dynamic_capability_llgr(uint8_t *pnt, int action,
|
2882 | 3055 | struct capability_header *hdr,
|
2883 | 3056 | struct peer *peer)
|
@@ -3232,11 +3405,13 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
|
3232 | 3405 | case CAPABILITY_CODE_LLGR:
|
3233 | 3406 | bgp_dynamic_capability_llgr(pnt, action, hdr, peer);
|
3234 | 3407 | break;
|
| 3408 | + case CAPABILITY_CODE_ADDPATH: |
| 3409 | + bgp_dynamic_capability_addpath(pnt, action, hdr, peer); |
| 3410 | + break; |
3235 | 3411 | case CAPABILITY_CODE_REFRESH:
|
3236 | 3412 | case CAPABILITY_CODE_ORF:
|
3237 | 3413 | case CAPABILITY_CODE_AS4:
|
3238 | 3414 | case CAPABILITY_CODE_DYNAMIC:
|
3239 |
| - case CAPABILITY_CODE_ADDPATH: |
3240 | 3415 | case CAPABILITY_CODE_ENHANCED_RR:
|
3241 | 3416 | case CAPABILITY_CODE_FQDN:
|
3242 | 3417 | case CAPABILITY_CODE_ENHE:
|
|
0 commit comments