diff options
-rw-r--r-- | bgpd/bgp_aspath.c | 9 | ||||
-rw-r--r-- | bgpd/bgp_aspath.h | 1 | ||||
-rw-r--r-- | bgpd/bgp_open.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_route.c | 134 | ||||
-rw-r--r-- | bgpd/bgp_updgrp.c | 19 | ||||
-rw-r--r-- | bgpd/bgp_updgrp.h | 3 | ||||
-rw-r--r-- | bgpd/bgp_updgrp_adv.c | 18 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 108 | ||||
-rw-r--r-- | bgpd/bgpd.c | 46 | ||||
-rw-r--r-- | bgpd/bgpd.h | 2 |
10 files changed, 262 insertions, 81 deletions
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index c9a6f3fd9..f4d7c4aad 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1147,6 +1147,15 @@ aspath_firstas_check (struct aspath *aspath, as_t asno) return 0; } +int +aspath_get_firstas (struct aspath *aspath) +{ + if (aspath == NULL || aspath->segments == NULL) + return 0; + + return aspath->segments->as[0]; +} + /* AS path loop check. If aspath contains asno then return >= 1. */ int aspath_loop_check (struct aspath *aspath, as_t asno) diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index faf3bc8ea..e4c781385 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -100,6 +100,7 @@ extern const char *aspath_print (struct aspath *); extern void aspath_print_vty (struct vty *, const char *, struct aspath *, const char *); extern void aspath_print_all_vty (struct vty *); extern unsigned int aspath_key_make (void *); +extern int aspath_get_firstas (struct aspath *); extern int aspath_loop_check (struct aspath *, as_t); extern int aspath_private_as_check (struct aspath *); extern int aspath_single_asn_check (struct aspath *, as_t asn); diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 2a168899f..d7a828b02 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -1316,7 +1316,8 @@ bgp_open_capability (struct stream *s, struct peer *peer) /* Only advertise addpath TX if a feature that will use it is * configured */ - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || + CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) adv_addpath_tx = 1; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 6c7a24239..bb40b4ed4 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1235,6 +1235,16 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp, return 0; } + /* If this is not the bestpath then check to see if there is an enabled addpath + * feature that requires us to advertise it */ + if (! CHECK_FLAG (ri->flags, BGP_INFO_SELECTED)) + { + if (! bgp_addpath_tx_path(peer, afi, safi, ri)) + { + return 0; + } + } + /* Aggregate-address suppress check. */ if (ri->extra && ri->extra->suppress) if (! UNSUPPRESS_MAP_NAME (filter)) @@ -1782,50 +1792,64 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, /* bgp deterministic-med */ new_select = NULL; if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) - for (ri1 = rn->info; ri1; ri1 = ri1->next) - { - if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) - continue; - if (BGP_INFO_HOLDDOWN (ri1)) - continue; - if (ri1->peer && ri1->peer != bgp->peer_self) - if (ri1->peer->status != Established) + { + + /* Clear BGP_INFO_DMED_SELECTED for all paths */ + for (ri1 = rn->info; ri1; ri1 = ri1->next) + bgp_info_unset_flag (rn, ri1, BGP_INFO_DMED_SELECTED); + + for (ri1 = rn->info; ri1; ri1 = ri1->next) + { + if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK)) continue; + if (BGP_INFO_HOLDDOWN (ri1)) + continue; + if (ri1->peer && ri1->peer != bgp->peer_self) + if (ri1->peer->status != Established) + continue; - new_select = ri1; - old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL; - if (ri1->next) - for (ri2 = ri1->next; ri2; ri2 = ri2->next) - { - if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) - continue; - if (BGP_INFO_HOLDDOWN (ri2)) - continue; - if (ri2->peer && - ri2->peer != bgp->peer_self && - !CHECK_FLAG (ri2->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri2->peer->status != Established) - continue; + new_select = ri1; + old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL; + if (ri1->next) + { + for (ri2 = ri1->next; ri2; ri2 = ri2->next) + { + if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK)) + continue; + if (BGP_INFO_HOLDDOWN (ri2)) + continue; + if (ri2->peer && + ri2->peer != bgp->peer_self && + !CHECK_FLAG (ri2->peer->sflags, PEER_STATUS_NSF_WAIT)) + if (ri2->peer->status != Established) + continue; - if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) - || aspath_cmp_left_confed (ri1->attr->aspath, - ri2->attr->aspath)) - { - if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED)) - old_select = ri2; - if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq, - mpath_cfg, debug, pfx_buf)) - { - bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED); - new_select = ri2; - } + if (aspath_cmp_left (ri1->attr->aspath, ri2->attr->aspath) + || aspath_cmp_left_confed (ri1->attr->aspath, + ri2->attr->aspath)) + { + if (CHECK_FLAG (ri2->flags, BGP_INFO_SELECTED)) + old_select = ri2; + if (bgp_info_cmp (bgp, ri2, new_select, &paths_eq, + mpath_cfg, debug, pfx_buf)) + { + bgp_info_unset_flag (rn, new_select, BGP_INFO_DMED_SELECTED); + new_select = ri2; + } - bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK); - } - } - bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK); - bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED); - } + bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK); + } + } + } + bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_CHECK); + bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED); + + if (debug) + zlog_debug("%s: path %s is the bestpath from AS %d", + pfx_buf, new_select->peer->host, + aspath_get_firstas(new_select->attr->aspath)); + } + } /* Check old selected route and new selected route. */ old_select = NULL; @@ -1859,8 +1883,8 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn, bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); continue; } + bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK); - bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_SELECTED); if (bgp_info_cmp (bgp, ri, new_select, &paths_eq, mpath_cfg, debug, pfx_buf)) { @@ -7311,6 +7335,7 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, struct peer *peer; int addpath_capable; int has_adj; + int first_as; if (json_paths) { @@ -7733,18 +7758,41 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out (vty, ", multipath"); } + // Mark the bestpath(s) + if (CHECK_FLAG (binfo->flags, BGP_INFO_DMED_SELECTED)) + { + first_as = aspath_get_firstas(attr->aspath); + + if (json_paths) + { + if (!json_bestpath) + json_bestpath = json_object_new_object(); + json_object_int_add(json_bestpath, "bestpathFromAs", first_as); + } + else + { + if (first_as) + vty_out (vty, ", bestpath-from-AS %d", first_as); + else + vty_out (vty, ", bestpath-from-AS Local"); + } + } + if (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED)) { if (json_paths) { - json_bestpath = json_object_new_object(); + if (!json_bestpath) + json_bestpath = json_object_new_object(); json_object_boolean_true_add(json_bestpath, "overall"); - json_object_object_add(json_path, "bestpath", json_bestpath); } else vty_out (vty, ", best"); } + if (json_bestpath) + json_object_object_add(json_path, "bestpath", json_bestpath); + if (!json_paths) vty_out (vty, "%s", VTY_NEWLINE); diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index c0f0c20b7..cfb3c7976 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -1955,9 +1955,28 @@ update_group_clear_update_dbg (struct update_group *updgrp, void *arg) return UPDWALK_CONTINUE; } +/* Return true if we should addpath encode NLRI to this peer */ int bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi) { return (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_TX_ADV) && CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ADDPATH_AF_RX_RCV)); } + +/* + * Return true if this is a path we should advertise due to a + * configured addpath-tx knob + */ +int +bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, + struct bgp_info *ri) +{ + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + return 1; + + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) && + CHECK_FLAG (ri->flags, BGP_INFO_DMED_SELECTED)) + return 1; + + return 0; +} diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index 1ca62a0a8..427168db5 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -50,6 +50,7 @@ PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \ PEER_FLAG_ADDPATH_TX_ALL_PATHS | \ + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \ PEER_FLAG_AS_OVERRIDE) #define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV) @@ -480,6 +481,8 @@ update_group_clear_update_dbg (struct update_group *updgrp, void *arg); extern void update_bgp_group_free(struct bgp *bgp); extern int bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi); +extern int bgp_addpath_tx_path (struct peer *peer, afi_t afi, safi_t safi, + struct bgp_info *ri); /* * Inline functions diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 493948e79..cc2fb8afd 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -155,16 +155,17 @@ group_announce_route_walkcb (struct update_group *updgrp, void *arg) } } - if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + for (ri = ctx->rn->info; ri; ri = ri->next) { - for (ri = ctx->rn->info; ri; ri = ri->next) - { - if (ri == ctx->ri) - continue; - subgroup_process_announce_selected (subgrp, ri, ctx->rn, ri->addpath_tx_id); - } + /* Skip the bestpath for now */ + if (ri == ctx->ri) + continue; + + subgroup_process_announce_selected (subgrp, ri, ctx->rn, ri->addpath_tx_id); } + /* Process the bestpath last so the "show ip bgp neighbor x.x.x.x advertised" + * output shows the attributes from the bestpath */ if (ctx->ri) subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id); } @@ -613,8 +614,7 @@ subgroup_announce_table (struct update_subgroup *subgrp, for (ri = rn->info; ri; ri = ri->next) if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) || - (addpath_capable && - CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS))) + (addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri))) { if (!rsclient && subgroup_announce_check (ri, subgrp, &rn->p, &attr)) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c021e8297..753f529aa 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -289,28 +289,6 @@ enum clear_sort clear_as }; -/* Force a bestpath recalculation for all prefixes. This is used - * when 'bgp bestpath' commands are entered. - */ -static void -bgp_recalculate_all_bestpaths (struct bgp *bgp) -{ - afi_t afi; - safi_t safi; - struct bgp_node *rn; - - for (afi = AFI_IP; afi < AFI_MAX; afi++) - { - for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) - { - for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) - { - bgp_process (bgp, rn, afi, safi); - } - } - } -} - static void bgp_clear_vty_error (struct vty *vty, struct peer *peer, afi_t afi, safi_t safi, int error) @@ -1655,13 +1633,43 @@ DEFUN (no_bgp_deterministic_med, "Pick the best-MED path among paths advertised from the neighboring AS\n") { struct bgp *bgp; + int bestpath_per_as_used; + afi_t afi; + safi_t safi; + struct peer *peer; + struct listnode *node, *nnode; bgp = vty->index; if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { - bgp_flag_unset (bgp, BGP_FLAG_DETERMINISTIC_MED); - bgp_recalculate_all_bestpaths (bgp); + bestpath_per_as_used = 0; + + for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) + { + for (afi = AFI_IP; afi < AFI_MAX; afi++) + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + { + bestpath_per_as_used = 1; + break; + } + + if (bestpath_per_as_used) + break; + } + + if (bestpath_per_as_used) + { + vty_out (vty, "bgp deterministic-med cannot be disabled while addpath-tx-bestpath-per-AS is in use%s", + VTY_NEWLINE); + return CMD_WARNING; + } + else + { + bgp_flag_unset (bgp, BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths (bgp); + } } return CMD_SUCCESS; @@ -5803,6 +5811,38 @@ DEFUN (no_neighbor_addpath_tx_all_paths, PEER_FLAG_ADDPATH_TX_ALL_PATHS); } +DEFUN (neighbor_addpath_tx_bestpath_per_as, + neighbor_addpath_tx_bestpath_per_as_cmd, + NEIGHBOR_CMD2 "addpath-tx-bestpath-per-AS", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Use addpath to advertise the bestpath per each neighboring AS\n") +{ + struct peer *peer; + + peer = peer_and_group_lookup_vty (vty, argv[0]); + if (! peer) + return CMD_WARNING; + + return peer_af_flag_set_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); +} + +DEFUN (no_neighbor_addpath_tx_bestpath_per_as, + no_neighbor_addpath_tx_bestpath_per_as_cmd, + NO_NEIGHBOR_CMD2 "addpath-tx-bestpath-per-AS", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Use addpath to advertise the bestpath per each neighboring AS\n") +{ + return peer_af_flag_unset_vty (vty, argv[0], bgp_node_afi (vty), + bgp_node_safi (vty), + PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS); +} + + /* Address family configuration. */ DEFUN (address_family_ipv4, address_family_ipv4_cmd, @@ -9282,6 +9322,9 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) json_object_boolean_true_add(json_addr, "addpathTxAllPaths"); + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + json_object_boolean_true_add(json_addr, "addpathTxBestpathPerAS"); + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) json_object_string_add(json_addr, "overrideASNsInOutboundUpdates", "ifAspathEqualRemoteAs"); @@ -9472,6 +9515,9 @@ bgp_show_peer_afi (struct vty *vty, struct peer *p, afi_t afi, safi_t safi, if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) vty_out (vty, " Advertise all paths via addpath%s", VTY_NEWLINE); + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + vty_out (vty, " Advertise bestpath per AS via addpath%s", VTY_NEWLINE); + if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE)) vty_out (vty, " Override ASNs in outbound updates if aspath equals remote-as%s", VTY_NEWLINE); @@ -13223,6 +13269,20 @@ bgp_vty_init (void) install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_all_paths_cmd); install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_all_paths_cmd); + /* "neighbor addpath-tx-bestpath-per-AS" commands.*/ + install_element (BGP_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV4M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV4M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV6_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV6_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV6M_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_IPV6M_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_VPNV4_NODE, &neighbor_addpath_tx_bestpath_per_as_cmd); + install_element (BGP_VPNV4_NODE, &no_neighbor_addpath_tx_bestpath_per_as_cmd); + /* "neighbor passive" commands. */ install_element (BGP_NODE, &neighbor_passive_cmd); install_element (BGP_NODE, &no_neighbor_passive_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 7b7634514..4e026d8d4 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1362,6 +1362,28 @@ bgp_peer_conf_if_to_su_update (struct peer *peer) hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); } +/* Force a bestpath recalculation for all prefixes. This is used + * when 'bgp bestpath' commands are entered. + */ +void +bgp_recalculate_all_bestpaths (struct bgp *bgp) +{ + afi_t afi; + safi_t safi; + struct bgp_node *rn; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) + { + for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) + { + for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn)) + { + bgp_process (bgp, rn, afi, safi); + } + } + } +} + /* Create new BGP peer. */ struct peer * peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, @@ -3484,6 +3506,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out }, { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out }, { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset }, + { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset }, { 0, 0, 0 } }; @@ -3792,7 +3815,7 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, } /* Track if addpath TX is in use */ - if (flag & PEER_FLAG_ADDPATH_TX_ALL_PATHS) + if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS|PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { bgp = peer->bgp; addpath_tx_used = 0; @@ -3800,12 +3823,25 @@ peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag, if (set) { addpath_tx_used = 1; + + if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) + { + if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED)) + { + zlog_warn("%s: enabling bgp deterministic-med, this is required"\ + " for addpath-tx-bestpath-per-AS", + peer->host); + bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED); + bgp_recalculate_all_bestpaths (bgp); + } + } } else { for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer)) { - if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) + if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) || + CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) { addpath_tx_used = 1; break; @@ -6551,8 +6587,10 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp, /* addpath TX knobs */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS)) - vty_out (vty, " neighbor %s addpath-tx-all-paths%s", addr, - VTY_NEWLINE); + vty_out (vty, " neighbor %s addpath-tx-all-paths%s", addr, VTY_NEWLINE); + + if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) + vty_out (vty, " neighbor %s addpath-tx-bestpath-per-AS%s", addr, VTY_NEWLINE); /* ORF capability. */ if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) || diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 7ed8176b1..851527b3b 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -654,6 +654,7 @@ struct peer #define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */ #define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1 << 21) /* remove-private-as all replace-as */ #define PEER_FLAG_ADDPATH_TX_ALL_PATHS (1 << 22) /* addpath-tx-all-paths */ +#define PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS (1 << 23) /* addpath-tx-bestpath-per-AS */ /* MD5 password */ char *password; @@ -1152,6 +1153,7 @@ extern struct peer *peer_unlock_with_caller(const char *, struct peer *); extern bgp_peer_sort_t peer_sort (struct peer *peer); extern int peer_active (struct peer *); extern int peer_active_nego (struct peer *); +extern void bgp_recalculate_all_bestpaths (struct bgp *bgp); extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, as_t, as_t, int, afi_t, safi_t); extern struct peer *peer_create_accept (struct bgp *); |