bgp_advertise.c 9.6 KB

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