File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_advertise.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:26:11 2012 UTC (12 years, 4 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, v0_99_20_1, v0_99_20, HEAD
quagga

    1: /* BGP advertisement and adjacency
    2:    Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
    3: 
    4: This file is part of GNU Zebra.
    5: 
    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
    9: later version.
   10: 
   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.
   15: 
   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
   19: 02111-1307, USA.  */
   20: 
   21: #include <zebra.h>
   22: 
   23: #include "command.h"
   24: #include "memory.h"
   25: #include "prefix.h"
   26: #include "hash.h"
   27: #include "thread.h"
   28: 
   29: #include "bgpd/bgpd.h"
   30: #include "bgpd/bgp_table.h"
   31: #include "bgpd/bgp_route.h"
   32: #include "bgpd/bgp_advertise.h"
   33: #include "bgpd/bgp_attr.h"
   34: #include "bgpd/bgp_aspath.h"
   35: #include "bgpd/bgp_packet.h"
   36: #include "bgpd/bgp_fsm.h"
   37: #include "bgpd/bgp_mplsvpn.h"
   38: 
   39: /* BGP advertise attribute is used for pack same attribute update into
   40:    one packet.  To do that we maintain attribute hash in struct
   41:    peer.  */
   42: static struct bgp_advertise_attr *
   43: baa_new (void)
   44: {
   45:   return (struct bgp_advertise_attr *)
   46:     XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
   47: }
   48: 
   49: static void
   50: baa_free (struct bgp_advertise_attr *baa)
   51: {
   52:   XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
   53: }
   54: 
   55: static void *
   56: baa_hash_alloc (void *p)
   57: {
   58:   struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
   59:   struct bgp_advertise_attr *baa;
   60: 
   61:   baa = baa_new ();
   62:   baa->attr = ref->attr;
   63:   return baa;
   64: }
   65: 
   66: static unsigned int
   67: baa_hash_key (void *p)
   68: {
   69:   struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
   70: 
   71:   return attrhash_key_make (baa->attr);
   72: }
   73: 
   74: static int
   75: baa_hash_cmp (const void *p1, const void *p2)
   76: {
   77:   const struct bgp_advertise_attr * baa1 = p1;
   78:   const struct bgp_advertise_attr * baa2 = p2;
   79: 
   80:   return attrhash_cmp (baa1->attr, baa2->attr);
   81: }
   82: 
   83: /* BGP update and withdraw information is stored in BGP advertise
   84:    structure.  This structure is referred from BGP adjacency
   85:    information.  */
   86: static struct bgp_advertise *
   87: bgp_advertise_new (void)
   88: {
   89:   return (struct bgp_advertise *) 
   90:     XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
   91: }
   92: 
   93: static void
   94: bgp_advertise_free (struct bgp_advertise *adv)
   95: {
   96:   if (adv->binfo)
   97:     bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
   98:   XFREE (MTYPE_BGP_ADVERTISE, adv);
   99: }
  100: 
  101: static void
  102: bgp_advertise_add (struct bgp_advertise_attr *baa,
  103: 		   struct bgp_advertise *adv)
  104: {
  105:   adv->next = baa->adv;
  106:   if (baa->adv)
  107:     baa->adv->prev = adv;
  108:   baa->adv = adv;
  109: }
  110: 
  111: static void
  112: bgp_advertise_delete (struct bgp_advertise_attr *baa,
  113: 		      struct bgp_advertise *adv)
  114: {
  115:   if (adv->next)
  116:     adv->next->prev = adv->prev;
  117:   if (adv->prev)
  118:     adv->prev->next = adv->next;
  119:   else
  120:     baa->adv = adv->next;
  121: }
  122: 
  123: static struct bgp_advertise_attr *
  124: bgp_advertise_intern (struct hash *hash, struct attr *attr)
  125: {
  126:   struct bgp_advertise_attr ref;
  127:   struct bgp_advertise_attr *baa;
  128: 
  129:   ref.attr = bgp_attr_intern (attr);
  130:   baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
  131:   baa->refcnt++;
  132: 
  133:   return baa;
  134: }
  135: 
  136: static void
  137: bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
  138: {
  139:   if (baa->refcnt)
  140:     baa->refcnt--;
  141: 
  142:   if (baa->refcnt && baa->attr)
  143:     bgp_attr_unintern (&baa->attr);
  144:   else
  145:     {
  146:       if (baa->attr)
  147: 	{
  148: 	  hash_release (hash, baa);
  149: 	  bgp_attr_unintern (&baa->attr);
  150: 	}
  151:       baa_free (baa);
  152:     }
  153: }
  154: 
  155: /* BGP adjacency keeps minimal advertisement information.  */
  156: static void
  157: bgp_adj_out_free (struct bgp_adj_out *adj)
  158: {
  159:   peer_unlock (adj->peer); /* adj_out peer reference */
  160:   XFREE (MTYPE_BGP_ADJ_OUT, adj);
  161: }
  162: 
  163: int
  164: bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
  165: 		    afi_t afi, safi_t safi, struct bgp_node *rn)
  166: {
  167:   struct bgp_adj_out *adj;
  168: 
  169:   for (adj = rn->adj_out; adj; adj = adj->next)
  170:     if (adj->peer == peer)
  171:       break;
  172: 
  173:   if (! adj)
  174:     return 0;
  175: 
  176:   return (adj->adv 
  177: 	  ? (adj->adv->baa ? 1 : 0)
  178: 	  : (adj->attr ? 1 : 0));
  179: }
  180: 
  181: struct bgp_advertise *
  182: bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
  183: 		     afi_t afi, safi_t safi)
  184: {
  185:   struct bgp_advertise *adv;
  186:   struct bgp_advertise_attr *baa;
  187:   struct bgp_advertise *next;
  188: 
  189:   adv = adj->adv;
  190:   baa = adv->baa;
  191:   next = NULL;
  192: 
  193:   if (baa)
  194:     {
  195:       /* Unlink myself from advertise attribute FIFO.  */
  196:       bgp_advertise_delete (baa, adv);
  197: 
  198:       /* Fetch next advertise candidate. */
  199:       next = baa->adv;
  200: 
  201:       /* Unintern BGP advertise attribute.  */
  202:       bgp_advertise_unintern (peer->hash[afi][safi], baa);
  203:     }
  204: 
  205:   /* Unlink myself from advertisement FIFO.  */
  206:   FIFO_DEL (adv);
  207: 
  208:   /* Free memory.  */
  209:   bgp_advertise_free (adj->adv);
  210:   adj->adv = NULL;
  211: 
  212:   return next;
  213: }
  214: 
  215: void
  216: bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
  217: 		 struct attr *attr, afi_t afi, safi_t safi,
  218: 		 struct bgp_info *binfo)
  219: {
  220:   struct bgp_adj_out *adj = NULL;
  221:   struct bgp_advertise *adv;
  222: 
  223:   if (DISABLE_BGP_ANNOUNCE)
  224:     return;
  225: 
  226:   /* Look for adjacency information. */
  227:   if (rn)
  228:     {
  229:       for (adj = rn->adj_out; adj; adj = adj->next)
  230: 	if (adj->peer == peer)
  231: 	  break;
  232:     }
  233: 
  234:   if (! adj)
  235:     {
  236:       adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
  237:       adj->peer = peer_lock (peer); /* adj_out peer reference */
  238:       
  239:       if (rn)
  240:         {
  241:           BGP_ADJ_OUT_ADD (rn, adj);
  242:           bgp_lock_node (rn);
  243:         }
  244:     }
  245: 
  246:   if (adj->adv)
  247:     bgp_advertise_clean (peer, adj, afi, safi);
  248:   
  249:   adj->adv = bgp_advertise_new ();
  250: 
  251:   adv = adj->adv;
  252:   adv->rn = rn;
  253:   
  254:   assert (adv->binfo == NULL);
  255:   adv->binfo = bgp_info_lock (binfo); /* bgp_info adj_out reference */
  256:   
  257:   if (attr)
  258:     adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
  259:   else
  260:     adv->baa = baa_new ();
  261:   adv->adj = adj;
  262: 
  263:   /* Add new advertisement to advertisement attribute list. */
  264:   bgp_advertise_add (adv->baa, adv);
  265: 
  266:   FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
  267: }
  268: 
  269: void
  270: bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p, 
  271: 		   afi_t afi, safi_t safi)
  272: {
  273:   struct bgp_adj_out *adj;
  274:   struct bgp_advertise *adv;
  275: 
  276:   if (DISABLE_BGP_ANNOUNCE)
  277:     return;
  278: 
  279:   /* Lookup existing adjacency, if it is not there return immediately.  */
  280:   for (adj = rn->adj_out; adj; adj = adj->next)
  281:     if (adj->peer == peer)
  282:       break;
  283: 
  284:   if (! adj)
  285:     return;
  286: 
  287:   /* Clearn up previous advertisement.  */
  288:   if (adj->adv)
  289:     bgp_advertise_clean (peer, adj, afi, safi);
  290: 
  291:   if (adj->attr)
  292:     {
  293:       /* We need advertisement structure.  */
  294:       adj->adv = bgp_advertise_new ();
  295:       adv = adj->adv;
  296:       adv->rn = rn;
  297:       adv->adj = adj;
  298: 
  299:       /* Add to synchronization entry for withdraw announcement.  */
  300:       FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
  301: 
  302:       /* Schedule packet write. */
  303:       BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
  304:     }
  305:   else
  306:     {
  307:       /* Remove myself from adjacency. */
  308:       BGP_ADJ_OUT_DEL (rn, adj);
  309:       
  310:       /* Free allocated information.  */
  311:       bgp_adj_out_free (adj);
  312: 
  313:       bgp_unlock_node (rn);
  314:     }
  315: }
  316: 
  317: void
  318: bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj, 
  319: 		    struct peer *peer, afi_t afi, safi_t safi)
  320: {
  321:   if (adj->attr)
  322:     bgp_attr_unintern (&adj->attr);
  323: 
  324:   if (adj->adv)
  325:     bgp_advertise_clean (peer, adj, afi, safi);
  326: 
  327:   BGP_ADJ_OUT_DEL (rn, adj);
  328:   bgp_adj_out_free (adj);
  329: }
  330: 
  331: void
  332: bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
  333: {
  334:   struct bgp_adj_in *adj;
  335: 
  336:   for (adj = rn->adj_in; adj; adj = adj->next)
  337:     {
  338:       if (adj->peer == peer)
  339: 	{
  340: 	  if (adj->attr != attr)
  341: 	    {
  342: 	      bgp_attr_unintern (&adj->attr);
  343: 	      adj->attr = bgp_attr_intern (attr);
  344: 	    }
  345: 	  return;
  346: 	}
  347:     }
  348:   adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
  349:   adj->peer = peer_lock (peer); /* adj_in peer reference */
  350:   adj->attr = bgp_attr_intern (attr);
  351:   BGP_ADJ_IN_ADD (rn, adj);
  352:   bgp_lock_node (rn);
  353: }
  354: 
  355: void
  356: bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
  357: {
  358:   bgp_attr_unintern (&bai->attr);
  359:   BGP_ADJ_IN_DEL (rn, bai);
  360:   peer_unlock (bai->peer); /* adj_in peer reference */
  361:   XFREE (MTYPE_BGP_ADJ_IN, bai);
  362: }
  363: 
  364: void
  365: bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
  366: {
  367:   struct bgp_adj_in *adj;
  368: 
  369:   for (adj = rn->adj_in; adj; adj = adj->next)
  370:     if (adj->peer == peer)
  371:       break;
  372: 
  373:   if (! adj)
  374:     return;
  375: 
  376:   bgp_adj_in_remove (rn, adj);
  377:   bgp_unlock_node (rn);
  378: }
  379: 
  380: void
  381: bgp_sync_init (struct peer *peer)
  382: {
  383:   afi_t afi;
  384:   safi_t safi;
  385:   struct bgp_synchronize *sync;
  386: 
  387:   for (afi = AFI_IP; afi < AFI_MAX; afi++)
  388:     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
  389:       {
  390: 	sync = XCALLOC (MTYPE_BGP_SYNCHRONISE, 
  391: 	                sizeof (struct bgp_synchronize));
  392: 	FIFO_INIT (&sync->update);
  393: 	FIFO_INIT (&sync->withdraw);
  394: 	FIFO_INIT (&sync->withdraw_low);
  395: 	peer->sync[afi][safi] = sync;
  396: 	peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
  397:       }
  398: }
  399: 
  400: void
  401: bgp_sync_delete (struct peer *peer)
  402: {
  403:   afi_t afi;
  404:   safi_t safi;
  405: 
  406:   for (afi = AFI_IP; afi < AFI_MAX; afi++)
  407:     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
  408:       {
  409: 	if (peer->sync[afi][safi])
  410: 	  XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
  411: 	peer->sync[afi][safi] = NULL;
  412: 	
  413: 	if (peer->hash[afi][safi])
  414: 	  hash_free (peer->hash[afi][safi]);
  415: 	peer->hash[afi][safi] = NULL;
  416:       }
  417: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>