bgp_advertise.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:9k
源码类别:

网络

开发平台:

Unix_Linux

  1. /* BGP advertisement and adjacency
  2.    Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
  3.    This file is part of GNU Zebra.
  4.    GNU Zebra is free software; you can redistribute it and/or modify it
  5.    under the terms of the GNU General Public License as published by the
  6.    Free Software Foundation; either version 2, or (at your option) any
  7.    later version.
  8.    GNU Zebra is distributed in the hope that it will be useful, but
  9.    WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    General Public License for more details.
  12.    You should have received a copy of the GNU General Public License
  13.    along with GNU Zebra; see the file COPYING.  If not, write to the Free
  14.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15.    02111-1307, USA.  */
  16. #include <zebra.h>
  17. #include "command.h"
  18. #include "memory.h"
  19. #include "prefix.h"
  20. #include "hash.h"
  21. #include "thread.h"
  22. #include "bgpd/bgpd.h"
  23. #include "bgpd/bgp_table.h"
  24. #include "bgpd/bgp_route.h"
  25. #include "bgpd/bgp_advertise.h"
  26. #include "bgpd/bgp_attr.h"
  27. #include "bgpd/bgp_aspath.h"
  28. #include "bgpd/bgp_packet.h"
  29. #include "bgpd/bgp_fsm.h"
  30. #include "bgpd/bgp_mplsvpn.h"
  31. /* BGP advertise attribute is used for pack same attribute update into
  32.    one packet.  To do that we maintain attribute hash in struct
  33.    peer.  */
  34. static struct bgp_advertise_attr *
  35. baa_new ()
  36. {
  37.   return (struct bgp_advertise_attr *)
  38.     XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
  39. }
  40. static void
  41. baa_free (struct bgp_advertise_attr *baa)
  42. {
  43.   XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
  44. }
  45. static void *
  46. baa_hash_alloc (struct bgp_advertise_attr *ref)
  47. {
  48.   struct bgp_advertise_attr *baa;
  49.   baa = baa_new ();
  50.   baa->attr = ref->attr;
  51.   return baa;
  52. }
  53. static unsigned int
  54. baa_hash_key (struct bgp_advertise_attr *baa)
  55. {
  56.   return attrhash_key_make (baa->attr);
  57. }
  58. static int
  59. baa_hash_cmp (struct bgp_advertise_attr *baa1, struct bgp_advertise_attr *baa2)
  60. {
  61.   return attrhash_cmp (baa1->attr, baa2->attr);
  62. }
  63. /* BGP update and withdraw information is stored in BGP advertise
  64.    structure.  This structure is referred from BGP adjacency
  65.    information.  */
  66. static struct bgp_advertise *
  67. bgp_advertise_new ()
  68. {
  69.   return (struct bgp_advertise *) 
  70.     XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
  71. }
  72. void
  73. bgp_advertise_free (struct bgp_advertise *adv)
  74. {
  75.   XFREE (MTYPE_BGP_ADVERTISE, adv);
  76. }
  77. void
  78. bgp_advertise_add (struct bgp_advertise_attr *baa,
  79.    struct bgp_advertise *adv)
  80. {
  81.   adv->next = baa->adv;
  82.   if (baa->adv)
  83.     baa->adv->prev = adv;
  84.   baa->adv = adv;
  85. }
  86. void
  87. bgp_advertise_delete (struct bgp_advertise_attr *baa,
  88.       struct bgp_advertise *adv)
  89. {
  90.   if (adv->next)
  91.     adv->next->prev = adv->prev;
  92.   if (adv->prev)
  93.     adv->prev->next = adv->next;
  94.   else
  95.     baa->adv = adv->next;
  96. }
  97. static struct bgp_advertise_attr *
  98. bgp_advertise_intern (struct hash *hash, struct attr *attr)
  99. {
  100.   struct bgp_advertise_attr ref;
  101.   struct bgp_advertise_attr *baa;
  102.   ref.attr = bgp_attr_intern (attr);
  103.   baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
  104.   baa->refcnt++;
  105.   return baa;
  106. }
  107. void
  108. bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
  109. {
  110.   if (baa->refcnt)
  111.     baa->refcnt--;
  112.   if (baa->refcnt && baa->attr)
  113.     bgp_attr_unintern (baa->attr);
  114.   else
  115.     {
  116.       if (baa->attr)
  117. {
  118.   hash_release (hash, baa);
  119.   bgp_attr_unintern (baa->attr);
  120. }
  121.       baa_free (baa);
  122.     }
  123. }
  124. /* BGP adjacency keeps minimal advertisement information.  */
  125. void
  126. bgp_adj_out_free (struct bgp_adj_out *adj)
  127. {
  128.   XFREE (MTYPE_BGP_ADJ_OUT, adj);
  129. }
  130. int
  131. bgp_adj_out_lookup (struct peer *peer, struct prefix *p,
  132.     afi_t afi, safi_t safi, struct bgp_node *rn)
  133. {
  134.   struct bgp_adj_out *adj;
  135.   for (adj = rn->adj_out; adj; adj = adj->next)
  136.     if (adj->peer == peer)
  137.       break;
  138.   if (! adj)
  139.     return 0;
  140.   return (adj->adv 
  141.   ? (adj->adv->baa ? 1 : 0)
  142.   : (adj->attr ? 1 : 0));
  143. }
  144. struct bgp_advertise *
  145. bgp_advertise_clean (struct peer *peer, struct bgp_adj_out *adj,
  146.      afi_t afi, safi_t safi)
  147. {
  148.   struct bgp_advertise *adv;
  149.   struct bgp_advertise_attr *baa;
  150.   struct bgp_advertise *next;
  151.   adv = adj->adv;
  152.   baa = adv->baa;
  153.   next = NULL;
  154.   if (baa)
  155.     {
  156.       /* Unlink myself from advertise attribute FIFO.  */
  157.       bgp_advertise_delete (baa, adv);
  158.       /* Fetch next advertise candidate. */
  159.       next = baa->adv;
  160.       /* Unintern BGP advertise attribute.  */
  161.       bgp_advertise_unintern (peer->hash[afi][safi], baa);
  162.       adv->baa = NULL;
  163.       adv->rn = NULL;
  164.     }
  165.   /* Unlink myself from advertisement FIFO.  */
  166.   FIFO_DEL (adv);
  167.   /* Free memory.  */
  168.   bgp_advertise_free (adj->adv);
  169.   adj->adv = NULL;
  170.   return next;
  171. }
  172. void
  173. bgp_adj_out_set (struct bgp_node *rn, struct peer *peer, struct prefix *p,
  174.  struct attr *attr, afi_t afi, safi_t safi,
  175.  struct bgp_info *binfo)
  176. {
  177.   struct bgp_adj_out *adj = NULL;
  178.   struct bgp_advertise *adv;
  179. #ifdef DISABLE_BGP_ANNOUNCE
  180.   return;
  181. #endif /* DISABLE_BGP_ANNOUNCE */
  182.   /* Look for adjacency information. */
  183.   if (rn)
  184.     {
  185.       for (adj = rn->adj_out; adj; adj = adj->next)
  186. if (adj->peer == peer)
  187.   break;
  188.     }
  189.   if (! adj)
  190.     {
  191.       adj = XCALLOC (MTYPE_BGP_ADJ_OUT, sizeof (struct bgp_adj_out));
  192.       if (rn)
  193.         {
  194.           BGP_ADJ_OUT_ADD (rn, adj);
  195.           bgp_lock_node (rn);
  196.         }
  197.     }
  198.   if (adj->adv)
  199.     bgp_advertise_clean (peer, adj, afi, safi);
  200.   adj->peer = peer;
  201.   adj->adv = bgp_advertise_new ();
  202.   adv = adj->adv;
  203.   adv->rn = rn;
  204.   adv->binfo = binfo;
  205.   if (attr)
  206.     adv->baa = bgp_advertise_intern (peer->hash[afi][safi], attr);
  207.   else
  208.     adv->baa = baa_new ();
  209.   adv->adj = adj;
  210.   /* Add new advertisement to advertisement attribute list. */
  211.   bgp_advertise_add (adv->baa, adv);
  212.   FIFO_ADD (&peer->sync[afi][safi]->update, &adv->fifo);
  213. }
  214. void
  215. bgp_adj_out_unset (struct bgp_node *rn, struct peer *peer, struct prefix *p, 
  216.    afi_t afi, safi_t safi)
  217. {
  218.   struct bgp_adj_out *adj;
  219.   struct bgp_advertise *adv;
  220. #ifdef DISABLE_BGP_ANNOUNCE
  221.   return;
  222. #endif /* DISABLE_BGP_ANNOUNCE */
  223.   /* Lookup existing adjacency, if it is not there return immediately.  */
  224.   for (adj = rn->adj_out; adj; adj = adj->next)
  225.     if (adj->peer == peer)
  226.       break;
  227.   if (! adj)
  228.     return;
  229.   /* Clearn up previous advertisement.  */
  230.   if (adj->adv)
  231.     bgp_advertise_clean (peer, adj, afi, safi);
  232.   if (adj->attr)
  233.     {
  234.       /* We need advertisement structure.  */
  235.       adj->adv = bgp_advertise_new ();
  236.       adv = adj->adv;
  237.       adv->rn = rn;
  238.       adv->adj = adj;
  239.       /* Add to synchronization entry for withdraw announcement.  */
  240.       FIFO_ADD (&peer->sync[afi][safi]->withdraw, &adv->fifo);
  241.       /* Schedule packet write. */
  242.       BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
  243.     }
  244.   else
  245.     {
  246.       /* Remove myself from adjacency. */
  247.       BGP_ADJ_OUT_DEL (rn, adj);
  248.       
  249.       /* Free allocated information.  */
  250.       bgp_adj_out_free (adj);
  251.       bgp_unlock_node (rn);
  252.     }
  253. }
  254. void
  255. bgp_adj_out_remove (struct bgp_node *rn, struct bgp_adj_out *adj, 
  256.     struct peer *peer, afi_t afi, safi_t safi)
  257. {
  258.   if (adj->attr)
  259.     bgp_attr_unintern (adj->attr);
  260.   if (adj->adv)
  261.     bgp_advertise_clean (peer, adj, afi, safi);
  262.   BGP_ADJ_OUT_DEL (rn, adj);
  263.   bgp_adj_out_free (adj);
  264. }
  265. void
  266. bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr)
  267. {
  268.   struct bgp_adj_in *adj;
  269.   for (adj = rn->adj_in; adj; adj = adj->next)
  270.     {
  271.       if (adj->peer == peer)
  272. {
  273.   if (adj->attr != attr)
  274.     {
  275.       bgp_attr_unintern (adj->attr);
  276.       adj->attr = bgp_attr_intern (attr);
  277.     }
  278.   return;
  279. }
  280.     }
  281.   adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
  282.   adj->peer = peer;
  283.   adj->attr = bgp_attr_intern (attr);
  284.   BGP_ADJ_IN_ADD (rn, adj);
  285.   bgp_lock_node (rn);
  286. }
  287. void
  288. bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
  289. {
  290.   bgp_attr_unintern (bai->attr);
  291.   BGP_ADJ_IN_DEL (rn, bai);
  292.   XFREE (MTYPE_BGP_ADJ_IN, bai);
  293. }
  294. void
  295. bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer)
  296. {
  297.   struct bgp_adj_in *adj;
  298.   for (adj = rn->adj_in; adj; adj = adj->next)
  299.     if (adj->peer == peer)
  300.       break;
  301.   if (! adj)
  302.     return;
  303.   bgp_adj_in_remove (rn, adj);
  304.   bgp_unlock_node (rn);
  305. }
  306. void
  307. bgp_sync_init (struct peer *peer)
  308. {
  309.   afi_t afi;
  310.   safi_t safi;
  311.   struct bgp_synchronize *sync;
  312.   for (afi = AFI_IP; afi < AFI_MAX; afi++)
  313.     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
  314.       {
  315. sync = XCALLOC (MTYPE_TMP, sizeof (struct bgp_synchronize));
  316. FIFO_INIT (&sync->update);
  317. FIFO_INIT (&sync->withdraw);
  318. FIFO_INIT (&sync->withdraw_low);
  319. peer->sync[afi][safi] = sync;
  320. peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
  321.       }
  322. }
  323. void
  324. bgp_sync_delete (struct peer *peer)
  325. {
  326.   afi_t afi;
  327.   safi_t safi;
  328.   for (afi = AFI_IP; afi < AFI_MAX; afi++)
  329.     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
  330.       {
  331. if (peer->sync[afi][safi])
  332.   XFREE (MTYPE_TMP, peer->sync[afi][safi]);
  333. peer->sync[afi][safi] = NULL;
  334. hash_free (peer->hash[afi][safi]);
  335.       }
  336. }