Addpath does not work for soft-reconfiguration

This commit is contained in:
Donald Sharp 2015-05-19 18:04:01 -07:00
parent 801a9bcc7f
commit 43143c8f2c
3 changed files with 66 additions and 31 deletions

View File

@ -189,13 +189,14 @@ bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
void void
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr) bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
u_int32_t addpath_id)
{ {
struct bgp_adj_in *adj; struct bgp_adj_in *adj;
for (adj = rn->adj_in; adj; adj = adj->next) for (adj = rn->adj_in; adj; adj = adj->next)
{ {
if (adj->peer == peer) if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
{ {
if (adj->attr != attr) if (adj->attr != attr)
{ {
@ -208,6 +209,7 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in)); adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
adj->peer = peer_lock (peer); /* adj_in peer reference */ adj->peer = peer_lock (peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern (attr); adj->attr = bgp_attr_intern (attr);
adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD (rn, adj); BGP_ADJ_IN_ADD (rn, adj);
bgp_lock_node (rn); bgp_lock_node (rn);
} }
@ -222,19 +224,25 @@ bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
} }
void void
bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer) bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
u_int32_t addpath_id)
{ {
struct bgp_adj_in *adj; struct bgp_adj_in *adj;
struct bgp_adj_in *adj_next;
for (adj = rn->adj_in; adj; adj = adj->next) adj = rn->adj_in;
if (adj->peer == peer) while (adj)
break; {
adj_next = adj->next;
if (! adj)
return;
if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
{
bgp_adj_in_remove (rn, adj); bgp_adj_in_remove (rn, adj);
bgp_unlock_node (rn); bgp_unlock_node (rn);
}
adj = adj_next;
}
} }
void void

View File

@ -101,6 +101,9 @@ struct bgp_adj_in
/* Received attribute. */ /* Received attribute. */
struct attr *attr; struct attr *attr;
/* Addpath identifier */
u_int32_t addpath_rx_id;
}; };
/* BGP advertisement list. */ /* BGP advertisement list. */
@ -168,8 +171,8 @@ struct bgp_synchronize
extern int bgp_adj_out_lookup (struct peer *, struct prefix *, afi_t, safi_t, extern int bgp_adj_out_lookup (struct peer *, struct prefix *, afi_t, safi_t,
struct bgp_node *); struct bgp_node *);
extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *); extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *, u_int32_t);
extern void bgp_adj_in_unset (struct bgp_node *, struct peer *); extern void bgp_adj_in_unset (struct bgp_node *, struct peer *, u_int32_t);
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *); extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *);
extern void bgp_sync_init (struct peer *); extern void bgp_sync_init (struct peer *);

View File

@ -2882,7 +2882,7 @@ bgp_update_main (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
Adj-RIBs-In. */ Adj-RIBs-In. */
if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self) && peer != bgp->peer_self)
bgp_adj_in_set (rn, peer, attr); bgp_adj_in_set (rn, peer, attr, addpath_id);
/* Check previously received route. */ /* Check previously received route. */
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
@ -3281,7 +3281,7 @@ bgp_withdraw (struct peer *peer, struct prefix *p, u_int32_t addpath_id,
further calculation. */ further calculation. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG) if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self) && peer != bgp->peer_self)
bgp_adj_in_unset (rn, peer); bgp_adj_in_unset (rn, peer, addpath_id);
/* Lookup withdrawn route. */ /* Lookup withdrawn route. */
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
@ -3485,7 +3485,7 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
struct bgp_info *ri = rn->info; struct bgp_info *ri = rn->info;
u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL; u_char *tag = (ri && ri->extra) ? ri->extra->tag : NULL;
ret = bgp_update (peer, &rn->p, ri->addpath_rx_id, ain->attr, ret = bgp_update (peer, &rn->p, ain->addpath_rx_id, ain->attr,
afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL,
prd, tag, 1); prd, tag, 1);
@ -3494,7 +3494,6 @@ bgp_soft_reconfig_table (struct peer *peer, afi_t afi, safi_t safi,
bgp_unlock_node (rn); bgp_unlock_node (rn);
return; return;
} }
continue;
} }
} }
} }
@ -3543,6 +3542,9 @@ bgp_clear_route_node (struct work_queue *wq, void *data)
assert (rn && peer); assert (rn && peer);
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/
for (ri = rn->info; ri; ri = ri->next) for (ri = rn->info; ri; ri = ri->next)
if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
{ {
@ -3554,7 +3556,6 @@ bgp_clear_route_node (struct work_queue *wq, void *data)
bgp_info_set_flag (rn, ri, BGP_INFO_STALE); bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
else else
bgp_rib_remove (rn, ri, peer, afi, safi); bgp_rib_remove (rn, ri, peer, afi, safi);
break;
} }
return WQ_SUCCESS; return WQ_SUCCESS;
} }
@ -3624,6 +3625,7 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
{ {
struct bgp_info *ri; struct bgp_info *ri;
struct bgp_adj_in *ain; struct bgp_adj_in *ain;
struct bgp_adj_in *ain_next;
struct bgp_adj_out *aout; struct bgp_adj_out *aout;
/* XXX:TODO: This is suboptimal, every non-empty route_node is /* XXX:TODO: This is suboptimal, every non-empty route_node is
@ -3656,13 +3658,22 @@ bgp_clear_route_table (struct peer *peer, afi_t afi, safi_t safi,
* Given that our per-peer prefix-counts now should be reliable, * Given that our per-peer prefix-counts now should be reliable,
* this may actually be achievable. It doesn't seem to be a huge * this may actually be achievable. It doesn't seem to be a huge
* problem at this time, * problem at this time,
*
* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/ */
for (ain = rn->adj_in; ain; ain = ain->next) ain = rn->adj_in;
while (ain)
{
ain_next = ain->next;
if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT) if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
{ {
bgp_adj_in_remove (rn, ain); bgp_adj_in_remove (rn, ain);
bgp_unlock_node (rn); bgp_unlock_node (rn);
break; }
ain = ain_next;
} }
/* /*
@ -3788,16 +3799,29 @@ bgp_clear_adj_in (struct peer *peer, afi_t afi, safi_t safi)
struct bgp_table *table; struct bgp_table *table;
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_adj_in *ain; struct bgp_adj_in *ain;
struct bgp_adj_in *ain_next;
table = peer->bgp->rib[afi][safi]; table = peer->bgp->rib[afi][safi];
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/
for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn)) for (rn = bgp_table_top (table); rn; rn = bgp_route_next (rn))
for (ain = rn->adj_in; ain ; ain = ain->next) {
ain = rn->adj_in;
while (ain)
{
ain_next = ain->next;
if (ain->peer == peer) if (ain->peer == peer)
{ {
bgp_adj_in_remove (rn, ain); bgp_adj_in_remove (rn, ain);
bgp_unlock_node (rn); bgp_unlock_node (rn);
break; }
ain = ain_next;
}
} }
} }