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