summaryrefslogtreecommitdiff
path: root/bgpd/bgp_addpath.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_addpath.c')
-rw-r--r--bgpd/bgp_addpath.c56
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);
}
/*