bgp_advertise.c 9.4 KB

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