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