1 /* BGP advertisement and adjacency
 
   2    Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
 
   4 This file is part of GNU Zebra.
 
   6 GNU Zebra is free software; you can redistribute it and/or modify it
 
   7 under the terms of the GNU General Public License as published by the
 
   8 Free Software Foundation; either version 2, or (at your option) any
 
  11 GNU Zebra is distributed in the hope that it will be useful, but
 
  12 WITHOUT ANY WARRANTY; without even the implied warranty of
 
  13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
  14 General Public License for more details.
 
  16 You should have received a copy of the GNU General Public License
 
  17 along with GNU Zebra; see the file COPYING.  If not, write to the Free
 
  18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 
  30 #include "bgpd/bgpd.h"
 
  31 #include "bgpd/bgp_table.h"
 
  32 #include "bgpd/bgp_route.h"
 
  33 #include "bgpd/bgp_advertise.h"
 
  34 #include "bgpd/bgp_attr.h"
 
  35 #include "bgpd/bgp_aspath.h"
 
  36 #include "bgpd/bgp_packet.h"
 
  37 #include "bgpd/bgp_fsm.h"
 
  38 #include "bgpd/bgp_mplsvpn.h"
 
  40 /* BGP advertise attribute is used for pack same attribute update into
 
  41    one packet.  To do that we maintain attribute hash in struct
 
  43 static struct bgp_advertise_attr *
 
  46   return (struct bgp_advertise_attr *)
 
  47     XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
 
  51 baa_free (struct bgp_advertise_attr *baa)
 
  53   XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
 
  57 baa_hash_alloc (void *p)
 
  59   struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
 
  60   struct bgp_advertise_attr *baa;
 
  63   baa->attr = ref->attr;
 
  68 baa_hash_key (void *p)
 
  70   struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
 
  72   return attrhash_key_make (baa->attr);
 
  76 baa_hash_cmp (const void *p1, const void *p2)
 
  78   const struct bgp_advertise_attr * baa1 = p1;
 
  79   const struct bgp_advertise_attr * baa2 = p2;
 
  81   return attrhash_cmp (baa1->attr, baa2->attr);
 
  84 /* BGP update and withdraw information is stored in BGP advertise
 
  85    structure.  This structure is referred from BGP adjacency
 
  87 static struct bgp_advertise *
 
  88 bgp_advertise_new (void)
 
  90   return (struct bgp_advertise *) 
 
  91     XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
 
  95 bgp_advertise_free (struct bgp_advertise *adv)
 
  98     bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
 
  99   XFREE (MTYPE_BGP_ADVERTISE, adv);
 
 103 bgp_advertise_add (struct bgp_advertise_attr *baa,
 
 104                    struct bgp_advertise *adv)
 
 106   adv->next = baa->adv;
 
 108     baa->adv->prev = adv;
 
 113 bgp_advertise_delete (struct bgp_advertise_attr *baa,
 
 114                       struct bgp_advertise *adv)
 
 117     adv->next->prev = adv->prev;
 
 119     adv->prev->next = adv->next;
 
 121     baa->adv = adv->next;
 
 124 static struct bgp_advertise_attr *
 
 125 bgp_advertise_intern (struct hash *hash, struct attr *attr)
 
 127   struct bgp_advertise_attr ref;
 
 128   struct bgp_advertise_attr *baa;
 
 130   ref.attr = bgp_attr_intern (attr);
 
 131   baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
 
 138 bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
 
 143   if (baa->refcnt && baa->attr)
 
 144     bgp_attr_unintern (&baa->attr);
 
 149           hash_release (hash, baa);
 
 150           bgp_attr_unintern (&baa->attr);
 
 156 /* BGP adjacency keeps minimal advertisement information.  */
 
 158 bgp_adj_out_free (struct bgp_adj_out *adj)
 
 160   peer_unlock (adj->peer); /* adj_out peer reference */
 
 161   XFREE (MTYPE_BGP_ADJ_OUT, adj);
 
 165 bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
 
 166                     afi_t afi, safi_t safi, struct bgp_node *rn)
 
 168   struct bgp_adj_out *adj;
 
 170   for (adj = rn->adj_out; adj; adj = adj->next)
 
 171     if (adj->peer == peer)
 
 178           ? (adj->adv->baa ? 1 : 0)
 
 179           : (adj->attr ? 1 : 0));
 
 182 struct bgp_advertise *
 
 183 bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
 
 184                      afi_t afi, safi_t safi)
 
 186   struct bgp_advertise *adv;
 
 187   struct bgp_advertise_attr *baa;
 
 188   struct bgp_advertise *next;
 
 189   struct bgp_advertise_fifo *fhead;
 
 194   fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->withdraw;
 
 198       /* Unlink myself from advertise attribute FIFO.  */
 
 199       bgp_advertise_delete (baa, adv);
 
 201       /* Fetch next advertise candidate. */
 
 204       /* Unintern BGP advertise attribute.  */
 
 205       bgp_advertise_unintern (peer->hash[afi][safi], baa);
 
 207       fhead = (struct bgp_advertise_fifo *)&peer->sync[afi][safi]->update;
 
 210   /* Unlink myself from advertisement FIFO.  */
 
 211   BGP_ADV_FIFO_DEL (fhead, adv);
 
 214   bgp_advertise_free (adj->adv);
 
 221 bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
 
 222                  struct attr *attr, afi_t afi, safi_t safi,
 
 223                  struct bgp_info *binfo)
 
 225   struct bgp_adj_out *adj = NULL;
 
 226   struct bgp_advertise *adv;
 
 228   if (DISABLE_BGP_ANNOUNCE)
 
 231   /* Look for adjacency information. */
 
 234       for (adj = rn->adj_out; adj; adj = adj->next)
 
 235         if (adj->peer == peer)
 
 241       adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
 
 242       adj->peer = peer_lock (peer); /* adj_out peer reference */
 
 246           BGP_ADJ_OUT_ADD (rn, adj);
 
 252     bgp_advertise_clean (peer, adj, afi, safi);
 
 254   adj->adv = bgp_advertise_new ();
 
 259   assert (adv->binfo == NULL);
 
 260   adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */
 
 263     adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
 
 265     adv->baa = baa_new ();
 
 268   /* Add new advertisement to advertisement attribute list. */
 
 269   bgp_advertise_add (adv->baa, adv);
 
 271   BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
 
 275 bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p, 
 
 276                    afi_t afi, safi_t safi)
 
 278   struct bgp_adj_out *adj;
 
 279   struct bgp_advertise *adv;
 
 281   if (DISABLE_BGP_ANNOUNCE)
 
 284   /* Lookup existing adjacency, if it is not there return immediately.  */
 
 285   for (adj = rn->adj_out; adj; adj = adj->next)
 
 286     if (adj->peer == peer)
 
 292   /* Clearn up previous advertisement.  */
 
 294     bgp_advertise_clean (peer, adj, afi, safi);
 
 298       /* We need advertisement structure.  */
 
 299       adj->adv = bgp_advertise_new ();
 
 304       /* Add to synchronization entry for withdraw announcement.  */
 
 305       BGP_ADV_FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
 
 307       /* Schedule packet write. */
 
 308       BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
 
 312       /* Remove myself from adjacency. */
 
 313       BGP_ADJ_OUT_DEL (rn, adj);
 
 315       /* Free allocated information.  */
 
 316       bgp_adj_out_free (adj);
 
 318       bgp_unlock_node (rn);
 
 323 bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj, 
 
 324                     struct peer *peer, afi_t afi, safi_t safi)
 
 327     bgp_attr_unintern (&adj->attr);
 
 330     bgp_advertise_clean (peer, adj, afi, safi);
 
 332   BGP_ADJ_OUT_DEL (rn, adj);
 
 333   bgp_adj_out_free (adj);
 
 337 bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
 
 339   struct bgp_adj_in *adj;
 
 341   for (adj = rn->adj_in; adj; adj = adj->next)
 
 343       if (adj->peer == peer)
 
 345           if (adj->attr != attr)
 
 347               bgp_attr_unintern (&adj->attr);
 
 348               adj->attr = bgp_attr_intern (attr);
 
 353   adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
 
 354   adj->peer = peer_lock (peer); /* adj_in peer reference */
 
 355   adj->attr = bgp_attr_intern (attr);
 
 356   BGP_ADJ_IN_ADD (rn, adj);
 
 361 bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
 
 363   bgp_attr_unintern (&bai->attr);
 
 364   BGP_ADJ_IN_DEL (rn, bai);
 
 365   peer_unlock (bai->peer); /* adj_in peer reference */
 
 366   XFREE (MTYPE_BGP_ADJ_IN, bai);
 
 370 bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
 
 372   struct bgp_adj_in *adj;
 
 374   for (adj = rn->adj_in; adj; adj = adj->next)
 
 375     if (adj->peer == peer)
 
 381   bgp_adj_in_remove (rn, adj);
 
 382   bgp_unlock_node (rn);
 
 387 bgp_sync_init (struct peer *peer)
 
 391   struct bgp_synchronize *sync;
 
 393   for (afi = AFI_IP; afi < AFI_MAX; afi++)
 
 394     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 
 396         sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, 
 
 397                         sizeof (struct bgp_synchronize));
 
 398         BGP_ADV_FIFO_INIT (&sync->update);
 
 399         BGP_ADV_FIFO_INIT (&sync->withdraw);
 
 400         BGP_ADV_FIFO_INIT (&sync->withdraw_low);
 
 401         peer->sync[afi][safi] = sync;
 
 402         peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
 
 407 bgp_sync_delete (struct peer *peer)
 
 412   for (afi = AFI_IP; afi < AFI_MAX; afi++)
 
 413     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
 
 415         if (peer->sync[afi][safi])
 
 416           XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
 
 417         peer->sync[afi][safi] = NULL;
 
 419         if (peer->hash[afi][safi])
 
 420           hash_free (peer->hash[afi][safi]);
 
 421         peer->hash[afi][safi] = NULL;