diff options
Diffstat (limited to 'bgpd/bgp_addpath.c')
| -rw-r--r-- | bgpd/bgp_addpath.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/bgpd/bgp_addpath.c b/bgpd/bgp_addpath.c index 7f746541ff..f391c13847 100644 --- a/bgpd/bgp_addpath.c +++ b/bgpd/bgp_addpath.c @@ -10,6 +10,8 @@ #include "bgp_addpath.h" #include "bgp_route.h" +#include "bgp_open.h" +#include "bgp_packet.h" static const struct bgp_addpath_strategy_names strat_names[BGP_ADDPATH_MAX] = { { @@ -25,7 +27,14 @@ static const struct bgp_addpath_strategy_names strat_names[BGP_ADDPATH_MAX] = { .human_description = "Advertise bestpath per AS via addpath", .type_json_name = "addpathTxBestpathPerAS", .id_json_name = "addpathTxIdBestPerAS" - } + }, + { + .config_name = "addpath-tx-best-selected", + .human_name = "Best-Selected", + .human_description = "Advertise best N selected paths via addpath", + .type_json_name = "addpathTxBestSelectedPaths", + .id_json_name = "addpathTxIdBestSelected" + }, }; static const struct bgp_addpath_strategy_names unknown_names = { @@ -161,6 +170,8 @@ bool bgp_addpath_tx_path(enum bgp_addpath_strat strat, struct bgp_path_info *pi) return true; else return false; + case BGP_ADDPATH_BEST_SELECTED: + return true; case BGP_ADDPATH_MAX: return false; } @@ -350,23 +361,52 @@ void bgp_addpath_type_changed(struct bgp *bgp) } } +int bgp_addpath_capability_action(enum bgp_addpath_strat addpath_type, + uint8_t paths) +{ + int action = CAPABILITY_ACTION_UNSET; + + switch (addpath_type) { + case BGP_ADDPATH_ALL: + case BGP_ADDPATH_BEST_PER_AS: + action = CAPABILITY_ACTION_SET; + break; + case BGP_ADDPATH_BEST_SELECTED: + if (paths) + action = CAPABILITY_ACTION_SET; + else + action = CAPABILITY_ACTION_UNSET; + break; + case BGP_ADDPATH_NONE: + case BGP_ADDPATH_MAX: + action = CAPABILITY_ACTION_UNSET; + break; + } + + return action; +} + /* * Change the addpath type assigned to a peer, or peer group. In addition to * adjusting the counts, peer sessions will be reset as needed to make the * change take effect. */ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi, - enum bgp_addpath_strat addpath_type) + enum bgp_addpath_strat addpath_type, + uint8_t paths) { struct bgp *bgp = peer->bgp; enum bgp_addpath_strat old_type; struct listnode *node, *nnode; struct peer *tmp_peer; struct peer_group *group; + int action = bgp_addpath_capability_action(addpath_type, paths); if (safi == SAFI_LABELED_UNICAST) safi = SAFI_UNICAST; + peer->addpath_best_selected[afi][safi] = paths; + old_type = peer->addpath_type[afi][safi]; if (addpath_type == old_type) return; @@ -411,17 +451,19 @@ void bgp_addpath_set_peer_type(struct peer *peer, afi_t afi, safi_t safi, tmp_peer)) { if (tmp_peer->addpath_type[afi][safi] == old_type) { - bgp_addpath_set_peer_type(tmp_peer, - afi, - safi, - addpath_type); + bgp_addpath_set_peer_type( + tmp_peer, afi, safi, + addpath_type, paths); } } } } else { - peer_change_action(peer, afi, safi, peer_change_reset); + if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) && + !CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) + peer_change_action(peer, afi, safi, peer_change_reset); } + bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_ADDPATH, action); } /* |
