summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_advertise.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_advertise.c')
-rw-r--r--bgpd/bgp_advertise.c164
1 files changed, 119 insertions, 45 deletions
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index 04f1f847..552b2291 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -153,12 +153,6 @@ bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
}
/* BGP adjacency keeps minimal advertisement information. */
-static void
-bgp_adj_out_free (struct bgp_adj_out *adj)
-{
- peer_unlock (adj->peer); /* adj_out peer reference */
- XFREE (MTYPE_BGP_ADJ_OUT, adj);
-}
int
bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
@@ -166,7 +160,7 @@ bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
{
struct bgp_adj_out *adj;
- for (adj = rn->adj_out; adj; adj = adj->next)
+ for (adj = rn->adj_out; adj; adj = adj->adj_next)
if (adj->peer == peer)
break;
@@ -217,31 +211,45 @@ bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
struct bgp_info *binfo)
{
- struct bgp_adj_out *adj = NULL;
+ struct bgp_adj_out* adj = NULL;
+ struct bgp_adj_out** adj_out_head ;
struct bgp_advertise *adv;
if (DISABLE_BGP_ANNOUNCE)
return;
+ assert(rn != NULL) ;
+ assert((afi == rn->table->afi) && (safi == rn->table->safi)) ;
+
/* Look for adjacency information. */
- if (rn)
- {
- for (adj = rn->adj_out; adj; adj = adj->next)
- if (adj->peer == peer)
+ for (adj = rn->adj_out; adj; adj = adj->adj_next)
+ if (adj->peer == peer)
break;
- }
- if (! adj)
+ if (adj == NULL)
{
adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
- adj->peer = peer_lock (peer); /* adj_out peer reference */
- if (rn)
- {
- BGP_ADJ_OUT_ADD (rn, adj);
- bgp_lock_node (rn);
- }
- }
+ /* Add to list of adj_out stuff for the peer */
+ adj->peer = peer_lock (peer);
+
+ adj_out_head = &(peer->adj_out_head[afi][safi]) ;
+
+ adj->route_next = *adj_out_head ;
+ adj->route_prev = NULL ;
+ if (*adj_out_head != NULL)
+ (*adj_out_head)->route_prev = adj ;
+ *adj_out_head = adj ;
+
+ /* Add to list of adj out stuff for the bgp_node */
+ adj->rn = bgp_lock_node (rn);
+
+ adj->adj_next = rn->adj_out ;
+ adj->adj_prev = NULL ;
+ if (rn->adj_out != NULL)
+ rn->adj_out->adj_prev = adj ;
+ rn->adj_out = adj ;
+ } ;
if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);
@@ -277,63 +285,80 @@ bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p,
return;
/* Lookup existing adjacency, if it is not there return immediately. */
- for (adj = rn->adj_out; adj; adj = adj->next)
+ for (adj = rn->adj_out; adj; adj = adj->adj_next)
if (adj->peer == peer)
break;
- if (! adj)
+ if (adj == NULL)
return;
- /* Clearn up previous advertisement. */
+ assert(rn == adj->rn) ;
+
+ /* Clear up previous advertisement. */
if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);
if (adj->attr)
{
- /* We need advertisement structure. */
+ /* We need advertisement structure. */
adj->adv = bgp_advertise_new ();
adv = adj->adv;
adv->rn = rn;
adv->adj = adj;
- /* Add to synchronization entry for withdraw announcement. */
+ /* Add to synchronization entry for withdraw announcement */
bgp_advertise_fifo_add(&peer->sync[afi][safi]->withdraw, adv);
/* Schedule packet write. */
bgp_write(peer, NULL) ;
}
else
- {
- /* Remove myself from adjacency. */
- BGP_ADJ_OUT_DEL (rn, adj);
-
- /* Free allocated information. */
- bgp_adj_out_free (adj);
-
- bgp_unlock_node (rn);
- }
+ bgp_adj_out_remove(rn, adj, peer, afi, safi) ;
}
void
bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj,
struct peer *peer, afi_t afi, safi_t safi)
{
+ assert((rn == adj->rn) && (peer == adj->peer)) ;
+
if (adj->attr)
bgp_attr_unintern (adj->attr);
if (adj->adv)
bgp_advertise_clean (peer, adj, afi, safi);
- BGP_ADJ_OUT_DEL (rn, adj);
- bgp_adj_out_free (adj);
+ /* Unhook from peer */
+ if (adj->route_next != NULL)
+ adj->route_next->route_prev = adj->route_prev ;
+ if (adj->route_prev != NULL)
+ adj->route_prev->route_next = adj->route_next ;
+ else
+ peer->adj_out_head[afi][safi] = adj->route_next ;
+
+ peer_unlock (peer);
+
+ /* Unhook from bgp_node */
+ if (adj->adj_next)
+ adj->adj_next->adj_prev = adj->adj_prev;
+ if (adj->adj_prev)
+ adj->adj_prev->adj_next = adj->adj_next;
+ else
+ rn->adj_out = adj->adj_next;
+
+ bgp_unlock_node (rn);
+
+ /* now can release memory. */
+ XFREE (MTYPE_BGP_ADJ_OUT, adj);
}
void
bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
{
struct bgp_adj_in *adj;
+ struct bgp_adj_in** adj_in_head ;
- for (adj = rn->adj_in; adj; adj = adj->next)
+ for (adj = rn->adj_in; adj; adj = adj->adj_next)
{
if (adj->peer == peer)
{
@@ -345,19 +370,69 @@ bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
return;
}
}
+
+ /* Need to create a brand new bgp_adj_in */
+
adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
- adj->peer = peer_lock (peer); /* adj_in peer reference */
+
+ /* Set the interned attributes */
adj->attr = bgp_attr_intern (attr);
- BGP_ADJ_IN_ADD (rn, adj);
- bgp_lock_node (rn);
+
+ /* Add to list of adj in stuff for the peer */
+ adj->peer = peer_lock (peer);
+
+ adj_in_head = &(peer->adj_in_head[rn->table->afi][rn->table->safi]) ;
+
+ adj->route_next = *adj_in_head ;
+ adj->route_prev = NULL ;
+ if (*adj_in_head != NULL)
+ (*adj_in_head)->route_prev = adj ;
+ *adj_in_head = adj ;
+
+ /* Add to list of adj in stuff for the bgp_node */
+ adj->rn = bgp_lock_node (rn);
+
+ adj->adj_next = rn->adj_in ;
+ adj->adj_prev = NULL ;
+ if (rn->adj_in != NULL)
+ rn->adj_in->adj_prev = adj ;
+ rn->adj_in = adj ;
}
void
bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
{
+ bgp_peer peer = bai->peer ;
+ struct bgp_adj_in** adj_in_head ;
+
+ adj_in_head = &(peer->adj_in_head[rn->table->afi][rn->table->safi]) ;
+
+ assert(rn == bai->rn) ;
+
+ /* Done with this copy of attributes */
bgp_attr_unintern (bai->attr);
- BGP_ADJ_IN_DEL (rn, bai);
- peer_unlock (bai->peer); /* adj_in peer reference */
+
+ /* Unhook from peer */
+ if (bai->route_next != NULL)
+ bai->route_next->route_prev = bai->route_prev ;
+ if (bai->route_prev != NULL)
+ bai->route_prev->route_next = bai->route_next ;
+ else
+ *adj_in_head = bai->route_next ;
+
+ peer_unlock (peer);
+
+ /* Unhook from bgp_node */
+ if (bai->adj_next)
+ bai->adj_next->adj_prev = bai->adj_prev;
+ if (bai->adj_prev)
+ bai->adj_prev->adj_next = bai->adj_next;
+ else
+ rn->adj_in = bai->adj_next;
+
+ bgp_unlock_node (rn);
+
+ /* now can release memory. */
XFREE (MTYPE_BGP_ADJ_IN, bai);
}
@@ -366,7 +441,7 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
{
struct bgp_adj_in *adj;
- for (adj = rn->adj_in; adj; adj = adj->next)
+ for (adj = rn->adj_in; adj; adj = adj->adj_next)
if (adj->peer == peer)
break;
@@ -374,7 +449,6 @@ bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
return;
bgp_adj_in_remove (rn, adj);
- bgp_unlock_node (rn);
}
void