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