LCOV - code coverage report
Current view: top level - bgpd - bgp_advertise.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 10 174 5.7 %
Date: 2015-11-19 Functions: 1 22 4.5 %

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

Generated by: LCOV version 1.10