1 /* BGP advertisement and adjacency
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
4 This file is part of GNU Zebra.
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
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.
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
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"
39 /* BGP advertise attribute is used for pack same attribute update into
40 one packet. To do that we maintain attribute hash in struct
42 static struct bgp_advertise_attr
*
45 return (struct bgp_advertise_attr
*)
46 XCALLOC (MTYPE_BGP_ADVERTISE_ATTR
, sizeof (struct bgp_advertise_attr
));
50 baa_free (struct bgp_advertise_attr
*baa
)
52 XFREE (MTYPE_BGP_ADVERTISE_ATTR
, baa
);
56 baa_hash_alloc (struct bgp_advertise_attr
*ref
)
58 struct bgp_advertise_attr
*baa
;
61 baa
->attr
= ref
->attr
;
66 baa_hash_key (struct bgp_advertise_attr
*baa
)
68 return attrhash_key_make (baa
->attr
);
72 baa_hash_cmp (struct bgp_advertise_attr
*baa1
, struct bgp_advertise_attr
*baa2
)
74 return attrhash_cmp (baa1
->attr
, baa2
->attr
);
77 /* BGP update and withdraw information is stored in BGP advertise
78 structure. This structure is referred from BGP adjacency
80 static struct bgp_advertise
*
83 return (struct bgp_advertise
*)
84 XCALLOC (MTYPE_BGP_ADVERTISE
, sizeof (struct bgp_advertise
));
88 bgp_advertise_free (struct bgp_advertise
*adv
)
91 bgp_info_unlock (adv
->binfo
); /* bgp_advertise bgp_info reference */
92 XFREE (MTYPE_BGP_ADVERTISE
, adv
);
96 bgp_advertise_add (struct bgp_advertise_attr
*baa
,
97 struct bgp_advertise
*adv
)
101 baa
->adv
->prev
= adv
;
106 bgp_advertise_delete (struct bgp_advertise_attr
*baa
,
107 struct bgp_advertise
*adv
)
110 adv
->next
->prev
= adv
->prev
;
112 adv
->prev
->next
= adv
->next
;
114 baa
->adv
= adv
->next
;
117 static struct bgp_advertise_attr
*
118 bgp_advertise_intern (struct hash
*hash
, struct attr
*attr
)
120 struct bgp_advertise_attr ref
;
121 struct bgp_advertise_attr
*baa
;
123 ref
.attr
= bgp_attr_intern (attr
);
124 baa
= (struct bgp_advertise_attr
*) hash_get (hash
, &ref
, baa_hash_alloc
);
131 bgp_advertise_unintern (struct hash
*hash
, struct bgp_advertise_attr
*baa
)
136 if (baa
->refcnt
&& baa
->attr
)
137 bgp_attr_unintern (baa
->attr
);
142 hash_release (hash
, baa
);
143 bgp_attr_unintern (baa
->attr
);
149 /* BGP adjacency keeps minimal advertisement information. */
151 bgp_adj_out_free (struct bgp_adj_out
*adj
)
153 peer_unlock (adj
->peer
); /* adj_out peer reference */
154 XFREE (MTYPE_BGP_ADJ_OUT
, adj
);
158 bgp_adj_out_lookup (struct peer
*peer
, struct prefix
*p
,
159 afi_t afi
, safi_t safi
, struct bgp_node
*rn
)
161 struct bgp_adj_out
*adj
;
163 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
164 if (adj
->peer
== peer
)
171 ? (adj
->adv
->baa
? 1 : 0)
172 : (adj
->attr
? 1 : 0));
175 struct bgp_advertise
*
176 bgp_advertise_clean (struct peer
*peer
, struct bgp_adj_out
*adj
,
177 afi_t afi
, safi_t safi
)
179 struct bgp_advertise
*adv
;
180 struct bgp_advertise_attr
*baa
;
181 struct bgp_advertise
*next
;
189 /* Unlink myself from advertise attribute FIFO. */
190 bgp_advertise_delete (baa
, adv
);
192 /* Fetch next advertise candidate. */
195 /* Unintern BGP advertise attribute. */
196 bgp_advertise_unintern (peer
->hash
[afi
][safi
], baa
);
199 /* Unlink myself from advertisement FIFO. */
203 bgp_advertise_free (adj
->adv
);
210 bgp_adj_out_set (struct bgp_node
*rn
, struct peer
*peer
, struct prefix
*p
,
211 struct attr
*attr
, afi_t afi
, safi_t safi
,
212 struct bgp_info
*binfo
)
214 struct bgp_adj_out
*adj
= NULL
;
215 struct bgp_advertise
*adv
;
217 #ifdef DISABLE_BGP_ANNOUNCE
219 #endif /* DISABLE_BGP_ANNOUNCE */
221 /* Look for adjacency information. */
224 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
225 if (adj
->peer
== peer
)
231 adj
= XCALLOC (MTYPE_BGP_ADJ_OUT
, sizeof (struct bgp_adj_out
));
232 adj
->peer
= peer_lock (peer
); /* adj_out peer reference */
236 BGP_ADJ_OUT_ADD (rn
, adj
);
242 bgp_advertise_clean (peer
, adj
, afi
, safi
);
244 adj
->adv
= bgp_advertise_new ();
249 assert (adv
->binfo
== NULL
);
250 adv
->binfo
= bgp_info_lock (binfo
); /* bgp_info adj_out reference */
253 adv
->baa
= bgp_advertise_intern (peer
->hash
[afi
][safi
], attr
);
255 adv
->baa
= baa_new ();
258 /* Add new advertisement to advertisement attribute list. */
259 bgp_advertise_add (adv
->baa
, adv
);
261 FIFO_ADD (&peer
->sync
[afi
][safi
]->update
, &adv
->fifo
);
265 bgp_adj_out_unset (struct bgp_node
*rn
, struct peer
*peer
, struct prefix
*p
,
266 afi_t afi
, safi_t safi
)
268 struct bgp_adj_out
*adj
;
269 struct bgp_advertise
*adv
;
271 #ifdef DISABLE_BGP_ANNOUNCE
273 #endif /* DISABLE_BGP_ANNOUNCE */
275 /* Lookup existing adjacency, if it is not there return immediately. */
276 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
277 if (adj
->peer
== peer
)
283 /* Clearn up previous advertisement. */
285 bgp_advertise_clean (peer
, adj
, afi
, safi
);
289 /* We need advertisement structure. */
290 adj
->adv
= bgp_advertise_new ();
295 /* Add to synchronization entry for withdraw announcement. */
296 FIFO_ADD (&peer
->sync
[afi
][safi
]->withdraw
, &adv
->fifo
);
298 /* Schedule packet write. */
299 BGP_WRITE_ON (peer
->t_write
, bgp_write
, peer
->fd
);
303 /* Remove myself from adjacency. */
304 BGP_ADJ_OUT_DEL (rn
, adj
);
306 /* Free allocated information. */
307 bgp_adj_out_free (adj
);
309 bgp_unlock_node (rn
);
314 bgp_adj_out_remove (struct bgp_node
*rn
, struct bgp_adj_out
*adj
,
315 struct peer
*peer
, afi_t afi
, safi_t safi
)
318 bgp_attr_unintern (adj
->attr
);
321 bgp_advertise_clean (peer
, adj
, afi
, safi
);
323 BGP_ADJ_OUT_DEL (rn
, adj
);
324 bgp_adj_out_free (adj
);
328 bgp_adj_in_set (struct bgp_node
*rn
, struct peer
*peer
, struct attr
*attr
)
330 struct bgp_adj_in
*adj
;
332 for (adj
= rn
->adj_in
; adj
; adj
= adj
->next
)
334 if (adj
->peer
== peer
)
336 if (adj
->attr
!= attr
)
338 bgp_attr_unintern (adj
->attr
);
339 adj
->attr
= bgp_attr_intern (attr
);
344 adj
= XCALLOC (MTYPE_BGP_ADJ_IN
, sizeof (struct bgp_adj_in
));
345 adj
->peer
= peer_lock (peer
); /* adj_in peer reference */
346 adj
->attr
= bgp_attr_intern (attr
);
347 BGP_ADJ_IN_ADD (rn
, adj
);
352 bgp_adj_in_remove (struct bgp_node
*rn
, struct bgp_adj_in
*bai
)
354 bgp_attr_unintern (bai
->attr
);
355 BGP_ADJ_IN_DEL (rn
, bai
);
356 peer_unlock (bai
->peer
); /* adj_in peer reference */
357 XFREE (MTYPE_BGP_ADJ_IN
, bai
);
361 bgp_adj_in_unset (struct bgp_node
*rn
, struct peer
*peer
)
363 struct bgp_adj_in
*adj
;
365 for (adj
= rn
->adj_in
; adj
; adj
= adj
->next
)
366 if (adj
->peer
== peer
)
372 bgp_adj_in_remove (rn
, adj
);
373 bgp_unlock_node (rn
);
377 bgp_sync_init (struct peer
*peer
)
381 struct bgp_synchronize
*sync
;
383 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
384 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
386 sync
= XCALLOC (MTYPE_TMP
, sizeof (struct bgp_synchronize
));
387 FIFO_INIT (&sync
->update
);
388 FIFO_INIT (&sync
->withdraw
);
389 FIFO_INIT (&sync
->withdraw_low
);
390 peer
->sync
[afi
][safi
] = sync
;
391 peer
->hash
[afi
][safi
] = hash_create (baa_hash_key
, baa_hash_cmp
);
396 bgp_sync_delete (struct peer
*peer
)
401 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
402 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
404 if (peer
->sync
[afi
][safi
])
405 XFREE (MTYPE_TMP
, peer
->sync
[afi
][safi
]);
406 peer
->sync
[afi
][safi
] = NULL
;
408 if (peer
->hash
[afi
][safi
])
409 hash_free (peer
->hash
[afi
][safi
]);