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;
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)
{
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
adj->peer = peer_lock (peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern (attr);
+ adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD (rn, adj);
bgp_lock_node (rn);
}
}
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_next;
- for (adj = rn->adj_in; adj; adj = adj->next)
- if (adj->peer == peer)
- break;
+ adj = rn->adj_in;
+ while (adj)
+ {
+ adj_next = adj->next;
- if (! adj)
- return;
+ if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
+ {
+ bgp_adj_in_remove (rn, adj);
+ bgp_unlock_node (rn);
+ }
- bgp_adj_in_remove (rn, adj);
- bgp_unlock_node (rn);
+ adj = adj_next;
+ }
}
void
/* Received attribute. */
struct attr *attr;
+
+ /* Addpath identifier */
+ u_int32_t addpath_rx_id;
};
/* BGP advertisement list. */
extern int bgp_adj_out_lookup (struct peer *, struct prefix *, afi_t, safi_t,
struct bgp_node *);
-extern void bgp_adj_in_set (struct bgp_node *, struct peer *, struct attr *);
-extern void bgp_adj_in_unset (struct bgp_node *, struct peer *);
+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 *, u_int32_t);
extern void bgp_adj_in_remove (struct bgp_node *, struct bgp_adj_in *);
extern void bgp_sync_init (struct peer *);
Adj-RIBs-In. */
if (! soft_reconfig && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self)
- bgp_adj_in_set (rn, peer, attr);
+ bgp_adj_in_set (rn, peer, attr, addpath_id);
/* Check previously received route. */
for (ri = rn->info; ri; ri = ri->next)
further calculation. */
if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG)
&& peer != bgp->peer_self)
- bgp_adj_in_unset (rn, peer);
+ bgp_adj_in_unset (rn, peer, addpath_id);
/* Lookup withdrawn route. */
for (ri = rn->info; ri; ri = ri->next)
struct bgp_info *ri = rn->info;
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,
prd, tag, 1);
bgp_unlock_node (rn);
return;
}
- continue;
}
}
}
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)
if (ri->peer == peer || cnq->purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
{
bgp_info_set_flag (rn, ri, BGP_INFO_STALE);
else
bgp_rib_remove (rn, ri, peer, afi, safi);
- break;
}
return WQ_SUCCESS;
}
{
struct bgp_info *ri;
struct bgp_adj_in *ain;
+ struct bgp_adj_in *ain_next;
struct bgp_adj_out *aout;
/* XXX:TODO: This is suboptimal, every non-empty route_node is
* Given that our per-peer prefix-counts now should be reliable,
* this may actually be achievable. It doesn't seem to be a huge
* 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)
- if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
- {
- bgp_adj_in_remove (rn, ain);
- bgp_unlock_node (rn);
- break;
- }
+ ain = rn->adj_in;
+ while (ain)
+ {
+ ain_next = ain->next;
+
+ if (ain->peer == peer || purpose == BGP_CLEAR_ROUTE_MY_RSCLIENT)
+ {
+ bgp_adj_in_remove (rn, ain);
+ bgp_unlock_node (rn);
+ }
+
+ ain = ain_next;
+ }
/*
* Can't do this anymore. adj-outs are not maintained per peer.
struct bgp_table *table;
struct bgp_node *rn;
struct bgp_adj_in *ain;
+ struct bgp_adj_in *ain_next;
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 (ain = rn->adj_in; ain ; ain = ain->next)
- if (ain->peer == peer)
- {
- bgp_adj_in_remove (rn, ain);
- bgp_unlock_node (rn);
- break;
- }
+ {
+ ain = rn->adj_in;
+
+ while (ain)
+ {
+ ain_next = ain->next;
+
+ if (ain->peer == peer)
+ {
+ bgp_adj_in_remove (rn, ain);
+ bgp_unlock_node (rn);
+ }
+
+ ain = ain_next;
+ }
+ }
}
void