mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-07 15:24:43 +00:00
BGP: Implement "neighbor x.x.x.x addpath-tx-bestpath-per-AS"
Signed-off-by: Daniel Walton <dwalton@cumulusnetworks.com> Reviewed-by: Donald Sharp <sharpd@cumulusnetworks.com> Ticket: CM-8114
This commit is contained in:
parent
06830cb85f
commit
06370dacc0
@ -1147,6 +1147,15 @@ aspath_firstas_check (struct aspath *aspath, as_t asno)
|
|||||||
return 0;
|
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. */
|
/* AS path loop check. If aspath contains asno then return >= 1. */
|
||||||
int
|
int
|
||||||
aspath_loop_check (struct aspath *aspath, as_t asno)
|
aspath_loop_check (struct aspath *aspath, as_t asno)
|
||||||
|
@ -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_vty (struct vty *, const char *, struct aspath *, const char *);
|
||||||
extern void aspath_print_all_vty (struct vty *);
|
extern void aspath_print_all_vty (struct vty *);
|
||||||
extern unsigned int aspath_key_make (void *);
|
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_loop_check (struct aspath *, as_t);
|
||||||
extern int aspath_private_as_check (struct aspath *);
|
extern int aspath_private_as_check (struct aspath *);
|
||||||
extern int aspath_single_asn_check (struct aspath *, as_t asn);
|
extern int aspath_single_asn_check (struct aspath *, as_t asn);
|
||||||
|
@ -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
|
/* Only advertise addpath TX if a feature that will use it is
|
||||||
* configured */
|
* 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;
|
adv_addpath_tx = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,6 +1235,16 @@ subgroup_announce_check (struct bgp_info *ri, struct update_subgroup *subgrp,
|
|||||||
return 0;
|
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. */
|
/* Aggregate-address suppress check. */
|
||||||
if (ri->extra && ri->extra->suppress)
|
if (ri->extra && ri->extra->suppress)
|
||||||
if (! UNSUPPRESS_MAP_NAME (filter))
|
if (! UNSUPPRESS_MAP_NAME (filter))
|
||||||
@ -1782,6 +1792,12 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
|
|||||||
/* bgp deterministic-med */
|
/* bgp deterministic-med */
|
||||||
new_select = NULL;
|
new_select = NULL;
|
||||||
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
|
if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
|
||||||
|
{
|
||||||
|
|
||||||
|
/* 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)
|
for (ri1 = rn->info; ri1; ri1 = ri1->next)
|
||||||
{
|
{
|
||||||
if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK))
|
if (CHECK_FLAG (ri1->flags, BGP_INFO_DMED_CHECK))
|
||||||
@ -1795,6 +1811,7 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
|
|||||||
new_select = ri1;
|
new_select = ri1;
|
||||||
old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
|
old_select = CHECK_FLAG (ri1->flags, BGP_INFO_SELECTED) ? ri1 : NULL;
|
||||||
if (ri1->next)
|
if (ri1->next)
|
||||||
|
{
|
||||||
for (ri2 = ri1->next; ri2; ri2 = ri2->next)
|
for (ri2 = ri1->next; ri2; ri2 = ri2->next)
|
||||||
{
|
{
|
||||||
if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK))
|
if (CHECK_FLAG (ri2->flags, BGP_INFO_DMED_CHECK))
|
||||||
@ -1823,8 +1840,15 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
|
|||||||
bgp_info_set_flag (rn, ri2, BGP_INFO_DMED_CHECK);
|
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_CHECK);
|
||||||
bgp_info_set_flag (rn, new_select, BGP_INFO_DMED_SELECTED);
|
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. */
|
/* Check old selected route and new selected route. */
|
||||||
@ -1859,8 +1883,8 @@ bgp_best_selection (struct bgp *bgp, struct bgp_node *rn,
|
|||||||
bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
|
bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bgp_info_unset_flag (rn, ri, BGP_INFO_DMED_CHECK);
|
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))
|
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;
|
struct peer *peer;
|
||||||
int addpath_capable;
|
int addpath_capable;
|
||||||
int has_adj;
|
int has_adj;
|
||||||
|
int first_as;
|
||||||
|
|
||||||
if (json_paths)
|
if (json_paths)
|
||||||
{
|
{
|
||||||
@ -7733,18 +7758,41 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p,
|
|||||||
vty_out (vty, ", multipath");
|
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 (CHECK_FLAG (binfo->flags, BGP_INFO_SELECTED))
|
||||||
{
|
{
|
||||||
if (json_paths)
|
if (json_paths)
|
||||||
{
|
{
|
||||||
|
if (!json_bestpath)
|
||||||
json_bestpath = json_object_new_object();
|
json_bestpath = json_object_new_object();
|
||||||
json_object_boolean_true_add(json_bestpath, "overall");
|
json_object_boolean_true_add(json_bestpath, "overall");
|
||||||
json_object_object_add(json_path, "bestpath", json_bestpath);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
vty_out (vty, ", best");
|
vty_out (vty, ", best");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json_bestpath)
|
||||||
|
json_object_object_add(json_path, "bestpath", json_bestpath);
|
||||||
|
|
||||||
if (!json_paths)
|
if (!json_paths)
|
||||||
vty_out (vty, "%s", VTY_NEWLINE);
|
vty_out (vty, "%s", VTY_NEWLINE);
|
||||||
|
|
||||||
|
@ -1955,9 +1955,28 @@ update_group_clear_update_dbg (struct update_group *updgrp, void *arg)
|
|||||||
return UPDWALK_CONTINUE;
|
return UPDWALK_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if we should addpath encode NLRI to this peer */
|
||||||
int
|
int
|
||||||
bgp_addpath_encode_tx (struct peer *peer, afi_t afi, safi_t safi)
|
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) &&
|
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));
|
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;
|
||||||
|
}
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
|
PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE | \
|
||||||
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
|
PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE | \
|
||||||
PEER_FLAG_ADDPATH_TX_ALL_PATHS | \
|
PEER_FLAG_ADDPATH_TX_ALL_PATHS | \
|
||||||
|
PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS | \
|
||||||
PEER_FLAG_AS_OVERRIDE)
|
PEER_FLAG_AS_OVERRIDE)
|
||||||
|
|
||||||
#define PEER_UPDGRP_CAP_FLAGS (PEER_CAP_AS4_RCV)
|
#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 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_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
|
* Inline functions
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
/* Skip the bestpath for now */
|
||||||
if (ri == ctx->ri)
|
if (ri == ctx->ri)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
subgroup_process_announce_selected (subgrp, ri, ctx->rn, ri->addpath_tx_id);
|
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)
|
if (ctx->ri)
|
||||||
subgroup_process_announce_selected (subgrp, ctx->ri, ctx->rn, ctx->ri->addpath_tx_id);
|
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)
|
for (ri = rn->info; ri; ri = ri->next)
|
||||||
|
|
||||||
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) ||
|
if (CHECK_FLAG (ri->flags, BGP_INFO_SELECTED) ||
|
||||||
(addpath_capable &&
|
(addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri)))
|
||||||
CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)))
|
|
||||||
{
|
{
|
||||||
if (!rsclient
|
if (!rsclient
|
||||||
&& subgroup_announce_check (ri, subgrp, &rn->p, &attr))
|
&& subgroup_announce_check (ri, subgrp, &rn->p, &attr))
|
||||||
|
104
bgpd/bgp_vty.c
104
bgpd/bgp_vty.c
@ -289,28 +289,6 @@ enum clear_sort
|
|||||||
clear_as
|
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
|
static void
|
||||||
bgp_clear_vty_error (struct vty *vty, struct peer *peer, afi_t afi,
|
bgp_clear_vty_error (struct vty *vty, struct peer *peer, afi_t afi,
|
||||||
safi_t safi, int error)
|
safi_t safi, int error)
|
||||||
@ -1655,14 +1633,44 @@ DEFUN (no_bgp_deterministic_med,
|
|||||||
"Pick the best-MED path among paths advertised from the neighboring AS\n")
|
"Pick the best-MED path among paths advertised from the neighboring AS\n")
|
||||||
{
|
{
|
||||||
struct bgp *bgp;
|
struct bgp *bgp;
|
||||||
|
int bestpath_per_as_used;
|
||||||
|
afi_t afi;
|
||||||
|
safi_t safi;
|
||||||
|
struct peer *peer;
|
||||||
|
struct listnode *node, *nnode;
|
||||||
|
|
||||||
bgp = vty->index;
|
bgp = vty->index;
|
||||||
|
|
||||||
if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED))
|
if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED))
|
||||||
|
{
|
||||||
|
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_flag_unset (bgp, BGP_FLAG_DETERMINISTIC_MED);
|
||||||
bgp_recalculate_all_bestpaths (bgp);
|
bgp_recalculate_all_bestpaths (bgp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return CMD_SUCCESS;
|
return CMD_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -5803,6 +5811,38 @@ DEFUN (no_neighbor_addpath_tx_all_paths,
|
|||||||
PEER_FLAG_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. */
|
/* Address family configuration. */
|
||||||
DEFUN (address_family_ipv4,
|
DEFUN (address_family_ipv4,
|
||||||
address_family_ipv4_cmd,
|
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))
|
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS))
|
||||||
json_object_boolean_true_add(json_addr, "addpathTxAllPaths");
|
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))
|
if (CHECK_FLAG (p->af_flags[afi][safi], PEER_FLAG_AS_OVERRIDE))
|
||||||
json_object_string_add(json_addr, "overrideASNsInOutboundUpdates", "ifAspathEqualRemoteAs");
|
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))
|
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);
|
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))
|
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);
|
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, &neighbor_addpath_tx_all_paths_cmd);
|
||||||
install_element (BGP_VPNV4_NODE, &no_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. */
|
/* "neighbor passive" commands. */
|
||||||
install_element (BGP_NODE, &neighbor_passive_cmd);
|
install_element (BGP_NODE, &neighbor_passive_cmd);
|
||||||
install_element (BGP_NODE, &no_neighbor_passive_cmd);
|
install_element (BGP_NODE, &no_neighbor_passive_cmd);
|
||||||
|
46
bgpd/bgpd.c
46
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);
|
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. */
|
/* Create new BGP peer. */
|
||||||
struct peer *
|
struct peer *
|
||||||
peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
|
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_AS_OVERRIDE, 1, peer_change_reset_out },
|
||||||
{ PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,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_ALL_PATHS, 1, peer_change_reset },
|
||||||
|
{ PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset },
|
||||||
{ 0, 0, 0 }
|
{ 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 */
|
/* 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;
|
bgp = peer->bgp;
|
||||||
addpath_tx_used = 0;
|
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)
|
if (set)
|
||||||
{
|
{
|
||||||
addpath_tx_used = 1;
|
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
|
else
|
||||||
{
|
{
|
||||||
for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer))
|
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;
|
addpath_tx_used = 1;
|
||||||
break;
|
break;
|
||||||
@ -6551,8 +6587,10 @@ bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
|
|||||||
|
|
||||||
/* addpath TX knobs */
|
/* addpath TX knobs */
|
||||||
if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS))
|
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_out (vty, " neighbor %s addpath-tx-all-paths%s", addr, VTY_NEWLINE);
|
||||||
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. */
|
/* ORF capability. */
|
||||||
if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
|
if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
|
||||||
|
@ -654,6 +654,7 @@ struct peer
|
|||||||
#define PEER_FLAG_AS_OVERRIDE (1 << 20) /* as-override */
|
#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_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_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 */
|
/* MD5 password */
|
||||||
char *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 bgp_peer_sort_t peer_sort (struct peer *peer);
|
||||||
extern int peer_active (struct peer *);
|
extern int peer_active (struct peer *);
|
||||||
extern int peer_active_nego (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 *,
|
extern struct peer *peer_create(union sockunion *, const char *, struct bgp *,
|
||||||
as_t, as_t, int, afi_t, safi_t);
|
as_t, as_t, int, afi_t, safi_t);
|
||||||
extern struct peer *peer_create_accept (struct bgp *);
|
extern struct peer *peer_create_accept (struct bgp *);
|
||||||
|
Loading…
Reference in New Issue
Block a user