File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / bgpd / bgp_advertise.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 2 10:09:10 2016 UTC (7 years, 8 months ago) by misho
Branches: quagga, MAIN
CVS tags: v1_0_20160315, HEAD
quagga 1.0.20160315

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

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