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 (void *p
)
58 struct bgp_advertise_attr
* ref
= (struct bgp_advertise_attr
*) p
;
59 struct bgp_advertise_attr
*baa
;
62 baa
->attr
= ref
->attr
;
67 baa_hash_key (void *p
)
69 struct bgp_advertise_attr
* baa
= (struct bgp_advertise_attr
*) p
;
71 return attrhash_key_make (baa
->attr
);
75 baa_hash_cmp (const void *p1
, const void *p2
)
77 const struct bgp_advertise_attr
* baa1
= p1
;
78 const struct bgp_advertise_attr
* baa2
= p2
;
80 return attrhash_cmp (baa1
->attr
, baa2
->attr
);
83 /* BGP update and withdraw information is stored in BGP advertise
84 structure. This structure is referred from BGP adjacency
86 static struct bgp_advertise
*
87 bgp_advertise_new (void)
89 return (struct bgp_advertise
*)
90 XCALLOC (MTYPE_BGP_ADVERTISE
, sizeof (struct bgp_advertise
));
94 bgp_advertise_free (struct bgp_advertise
*adv
)
97 bgp_info_unlock (adv
->binfo
); /* bgp_advertise bgp_info reference */
98 XFREE (MTYPE_BGP_ADVERTISE
, adv
);
102 bgp_advertise_add (struct bgp_advertise_attr
*baa
,
103 struct bgp_advertise
*adv
)
105 adv
->next
= baa
->adv
;
107 baa
->adv
->prev
= adv
;
112 bgp_advertise_delete (struct bgp_advertise_attr
*baa
,
113 struct bgp_advertise
*adv
)
116 adv
->next
->prev
= adv
->prev
;
118 adv
->prev
->next
= adv
->next
;
120 baa
->adv
= adv
->next
;
123 static struct bgp_advertise_attr
*
124 bgp_advertise_intern (struct hash
*hash
, struct attr
*attr
)
126 struct bgp_advertise_attr ref
;
127 struct bgp_advertise_attr
*baa
;
129 ref
.attr
= bgp_attr_intern (attr
);
130 baa
= (struct bgp_advertise_attr
*) hash_get (hash
, &ref
, baa_hash_alloc
);
137 bgp_advertise_unintern (struct hash
*hash
, struct bgp_advertise_attr
*baa
)
142 if (baa
->refcnt
&& baa
->attr
)
143 bgp_attr_unintern (baa
->attr
);
148 hash_release (hash
, baa
);
149 bgp_attr_unintern (baa
->attr
);
155 /* BGP adjacency keeps minimal advertisement information. */
157 bgp_adj_out_free (struct bgp_adj_out
*adj
)
159 peer_unlock (adj
->peer
); /* adj_out peer reference */
160 XFREE (MTYPE_BGP_ADJ_OUT
, adj
);
164 bgp_adj_out_lookup (struct peer
*peer
, struct prefix
*p
,
165 afi_t afi
, safi_t safi
, struct bgp_node
*rn
)
167 struct bgp_adj_out
*adj
;
169 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
170 if (adj
->peer
== peer
)
177 ? (adj
->adv
->baa
? 1 : 0)
178 : (adj
->attr
? 1 : 0));
181 struct bgp_advertise
*
182 bgp_advertise_clean (struct peer
*peer
, struct bgp_adj_out
*adj
,
183 afi_t afi
, safi_t safi
)
185 struct bgp_advertise
*adv
;
186 struct bgp_advertise_attr
*baa
;
187 struct bgp_advertise
*next
;
195 /* Unlink myself from advertise attribute FIFO. */
196 bgp_advertise_delete (baa
, adv
);
198 /* Fetch next advertise candidate. */
201 /* Unintern BGP advertise attribute. */
202 bgp_advertise_unintern (peer
->hash
[afi
][safi
], baa
);
205 /* Unlink myself from advertisement FIFO. */
209 bgp_advertise_free (adj
->adv
);
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
)
220 struct bgp_adj_out
*adj
= NULL
;
221 struct bgp_advertise
*adv
;
223 if (DISABLE_BGP_ANNOUNCE
)
226 /* Look for adjacency information. */
229 for (adj
= rn
->adj_out
; adj
; adj
= adj
->next
)
230 if (adj
->peer
== peer
)
236 adj
= XCALLOC (MTYPE_BGP_ADJ_OUT
, sizeof (struct bgp_adj_out
));
237 adj
->peer
= peer_lock (peer
); /* adj_out peer reference */
241 BGP_ADJ_OUT_ADD (rn
, adj
);
247 bgp_advertise_clean (peer
, adj
, afi
, safi
);
249 adj
->adv
= bgp_advertise_new ();
254 assert (adv
->binfo
== NULL
);
255 adv
->binfo
= bgp_info_lock (binfo
); /* bgp_info adj_out reference */
258 adv
->baa
= bgp_advertise_intern (peer
->hash
[afi
][safi
], attr
);
260 adv
->baa
= baa_new ();
263 /* Add new advertisement to advertisement attribute list. */
264 bgp_advertise_add (adv
->baa
, adv
);
266 FIFO_ADD (&peer
->sync
[afi
][safi
]->update
, &adv
->fifo
);
270 bgp_adj_out_unset (struct bgp_node
*rn
, struct peer
*peer
, struct prefix
*p
,
271 afi_t afi
, safi_t safi
)
273 struct bgp_adj_out
*adj
;
274 struct bgp_advertise
*adv
;
276 if (DISABLE_BGP_ANNOUNCE
)
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
)
287 /* Clearn up previous advertisement. */
289 bgp_advertise_clean (peer
, adj
, afi
, safi
);
293 /* We need advertisement structure. */
294 adj
->adv
= bgp_advertise_new ();
299 /* Add to synchronization entry for withdraw announcement. */
300 FIFO_ADD (&peer
->sync
[afi
][safi
]->withdraw
, &adv
->fifo
);
302 /* Schedule packet write. */
303 BGP_WRITE_ON (peer
->t_write
, bgp_write
, peer
->fd
);
307 /* Remove myself from adjacency. */
308 BGP_ADJ_OUT_DEL (rn
, adj
);
310 /* Free allocated information. */
311 bgp_adj_out_free (adj
);
313 bgp_unlock_node (rn
);
318 bgp_adj_out_remove (struct bgp_node
*rn
, struct bgp_adj_out
*adj
,
319 struct peer
*peer
, afi_t afi
, safi_t safi
)
322 bgp_attr_unintern (adj
->attr
);
325 bgp_advertise_clean (peer
, adj
, afi
, safi
);
327 BGP_ADJ_OUT_DEL (rn
, adj
);
328 bgp_adj_out_free (adj
);
332 bgp_adj_in_set (struct bgp_node
*rn
, struct peer
*peer
, struct attr
*attr
)
334 struct bgp_adj_in
*adj
;
336 for (adj
= rn
->adj_in
; adj
; adj
= adj
->next
)
338 if (adj
->peer
== peer
)
340 if (adj
->attr
!= attr
)
342 bgp_attr_unintern (adj
->attr
);
343 adj
->attr
= bgp_attr_intern (attr
);
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
);
356 bgp_adj_in_remove (struct bgp_node
*rn
, struct bgp_adj_in
*bai
)
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
);
365 bgp_adj_in_unset (struct bgp_node
*rn
, struct peer
*peer
)
367 struct bgp_adj_in
*adj
;
369 for (adj
= rn
->adj_in
; adj
; adj
= adj
->next
)
370 if (adj
->peer
== peer
)
376 bgp_adj_in_remove (rn
, adj
);
377 bgp_unlock_node (rn
);
381 bgp_sync_init (struct peer
*peer
)
385 struct bgp_synchronize
*sync
;
387 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
388 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
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
);
401 bgp_sync_delete (struct peer
*peer
)
406 for (afi
= AFI_IP
; afi
< AFI_MAX
; afi
++)
407 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++)
409 if (peer
->sync
[afi
][safi
])
410 XFREE (MTYPE_BGP_SYNCHRONISE
, peer
->sync
[afi
][safi
]);
411 peer
->sync
[afi
][safi
] = NULL
;
413 if (peer
->hash
[afi
][safi
])
414 hash_free (peer
->hash
[afi
][safi
]);
415 peer
->hash
[afi
][safi
] = NULL
;