Annotation of embedaddon/quagga/bgpd/bgp_advertise.c, revision 1.1

1.1     ! misho       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>