]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_advertise.c
Merge pull request #531 from qlyoung/fix-stack-ref
[mirror_frr.git] / bgpd / bgp_advertise.c
CommitLineData
718e3744 1/* BGP advertisement and adjacency
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-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"
3f9c7369 28#include "queue.h"
039f3a34 29#include "filter.h"
718e3744 30
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_table.h"
33#include "bgpd/bgp_route.h"
34#include "bgpd/bgp_advertise.h"
35#include "bgpd/bgp_attr.h"
d889623f 36#include "bgpd/bgp_debug.h"
718e3744 37#include "bgpd/bgp_aspath.h"
38#include "bgpd/bgp_packet.h"
39#include "bgpd/bgp_fsm.h"
40#include "bgpd/bgp_mplsvpn.h"
3f9c7369 41#include "bgpd/bgp_updgrp.h"
6b0655a2 42
718e3744 43/* BGP advertise attribute is used for pack same attribute update into
44 one packet. To do that we maintain attribute hash in struct
45 peer. */
3f9c7369 46struct bgp_advertise_attr *
66e5cd87 47baa_new (void)
718e3744 48{
49 return (struct bgp_advertise_attr *)
50 XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
51}
52
53static void
54baa_free (struct bgp_advertise_attr *baa)
55{
56 XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
57}
58
59static void *
923de654 60baa_hash_alloc (void *p)
718e3744 61{
923de654 62 struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
718e3744 63 struct bgp_advertise_attr *baa;
64
65 baa = baa_new ();
66 baa->attr = ref->attr;
67 return baa;
68}
69
3f9c7369 70unsigned int
923de654 71baa_hash_key (void *p)
718e3744 72{
923de654
PJ
73 struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
74
718e3744 75 return attrhash_key_make (baa->attr);
76}
77
3f9c7369 78int
ffe11cfb 79baa_hash_cmp (const void *p1, const void *p2)
718e3744 80{
ffe11cfb
SH
81 const struct bgp_advertise_attr * baa1 = p1;
82 const struct bgp_advertise_attr * baa2 = p2;
923de654 83
718e3744 84 return attrhash_cmp (baa1->attr, baa2->attr);
85}
6b0655a2 86
718e3744 87/* BGP update and withdraw information is stored in BGP advertise
88 structure. This structure is referred from BGP adjacency
89 information. */
3f9c7369 90struct bgp_advertise *
66e5cd87 91bgp_advertise_new (void)
718e3744 92{
3f9c7369 93 return (struct bgp_advertise *)
718e3744 94 XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
95}
96
3f9c7369 97void
718e3744 98bgp_advertise_free (struct bgp_advertise *adv)
99{
200df115 100 if (adv->binfo)
101 bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
718e3744 102 XFREE (MTYPE_BGP_ADVERTISE, adv);
103}
104
3f9c7369 105void
718e3744 106bgp_advertise_add (struct bgp_advertise_attr *baa,
107 struct bgp_advertise *adv)
108{
109 adv->next = baa->adv;
110 if (baa->adv)
111 baa->adv->prev = adv;
112 baa->adv = adv;
113}
114
3f9c7369 115void
718e3744 116bgp_advertise_delete (struct bgp_advertise_attr *baa,
117 struct bgp_advertise *adv)
118{
119 if (adv->next)
120 adv->next->prev = adv->prev;
121 if (adv->prev)
122 adv->prev->next = adv->next;
123 else
124 baa->adv = adv->next;
125}
126
3f9c7369 127struct bgp_advertise_attr *
718e3744 128bgp_advertise_intern (struct hash *hash, struct attr *attr)
129{
130 struct bgp_advertise_attr ref;
131 struct bgp_advertise_attr *baa;
132
133 ref.attr = bgp_attr_intern (attr);
134 baa = (struct bgp_advertise_attr *) hash_get (hash, &ref, baa_hash_alloc);
135 baa->refcnt++;
136
137 return baa;
138}
139
3f9c7369 140void
718e3744 141bgp_advertise_unintern (struct hash *hash, struct bgp_advertise_attr *baa)
142{
143 if (baa->refcnt)
144 baa->refcnt--;
145
146 if (baa->refcnt && baa->attr)
f6f434b2 147 bgp_attr_unintern (&baa->attr);
718e3744 148 else
149 {
150 if (baa->attr)
151 {
152 hash_release (hash, baa);
f6f434b2 153 bgp_attr_unintern (&baa->attr);
718e3744 154 }
155 baa_free (baa);
156 }
157}
6b0655a2 158
3f9c7369 159int
adbac85e
DW
160bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
161 u_int32_t addpath_tx_id)
718e3744 162{
163 struct bgp_adj_out *adj;
3f9c7369 164 struct peer_af *paf;
adbac85e
DW
165 afi_t afi;
166 safi_t safi;
167 int addpath_capable;
718e3744 168
718e3744 169 for (adj = rn->adj_out; adj; adj = adj->next)
3f9c7369
DS
170 SUBGRP_FOREACH_PEER(adj->subgroup, paf)
171 if (paf->peer == peer)
172 {
adbac85e
DW
173 afi = SUBGRP_AFI (adj->subgroup);
174 safi = SUBGRP_SAFI (adj->subgroup);
175 addpath_capable = bgp_addpath_encode_tx (peer, afi, safi);
176
177 /* Match on a specific addpath_tx_id if we are using addpath for this
178 * peer and if an addpath_tx_id was specified */
179 if (addpath_capable && addpath_tx_id && adj->addpath_tx_id != addpath_tx_id)
180 continue;
181
3f9c7369
DS
182 return (adj->adv
183 ? (adj->adv->baa ? 1 : 0)
184 : (adj->attr ? 1 : 0));
185 }
718e3744 186
3f9c7369 187 return 0;
718e3744 188}
189
6b0655a2 190
718e3744 191void
43143c8f
DS
192bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
193 u_int32_t addpath_id)
718e3744 194{
195 struct bgp_adj_in *adj;
196
197 for (adj = rn->adj_in; adj; adj = adj->next)
198 {
43143c8f 199 if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
718e3744 200 {
201 if (adj->attr != attr)
202 {
f6f434b2 203 bgp_attr_unintern (&adj->attr);
718e3744 204 adj->attr = bgp_attr_intern (attr);
205 }
206 return;
207 }
208 }
209 adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
200df115 210 adj->peer = peer_lock (peer); /* adj_in peer reference */
718e3744 211 adj->attr = bgp_attr_intern (attr);
43143c8f 212 adj->addpath_rx_id = addpath_id;
718e3744 213 BGP_ADJ_IN_ADD (rn, adj);
214 bgp_lock_node (rn);
215}
216
217void
218bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
219{
f6f434b2 220 bgp_attr_unintern (&bai->attr);
718e3744 221 BGP_ADJ_IN_DEL (rn, bai);
200df115 222 peer_unlock (bai->peer); /* adj_in peer reference */
718e3744 223 XFREE (MTYPE_BGP_ADJ_IN, bai);
224}
225
6b87f736 226int
43143c8f
DS
227bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
228 u_int32_t addpath_id)
718e3744 229{
230 struct bgp_adj_in *adj;
43143c8f 231 struct bgp_adj_in *adj_next;
718e3744 232
43143c8f 233 adj = rn->adj_in;
6b87f736
DL
234
235 if (!adj)
236 return 0;
237
43143c8f
DS
238 while (adj)
239 {
240 adj_next = adj->next;
718e3744 241
43143c8f
DS
242 if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
243 {
244 bgp_adj_in_remove (rn, adj);
245 bgp_unlock_node (rn);
246 }
718e3744 247
43143c8f
DS
248 adj = adj_next;
249 }
6b87f736
DL
250
251 return 1;
718e3744 252}
6b0655a2 253
718e3744 254void
255bgp_sync_init (struct peer *peer)
256{
257 afi_t afi;
258 safi_t safi;
259 struct bgp_synchronize *sync;
260
261 for (afi = AFI_IP; afi < AFI_MAX; afi++)
262 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
263 {
b51f126e
PJ
264 sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
265 sizeof (struct bgp_synchronize));
cdabb8b6
DS
266 BGP_ADV_FIFO_INIT (&sync->update);
267 BGP_ADV_FIFO_INIT (&sync->withdraw);
268 BGP_ADV_FIFO_INIT (&sync->withdraw_low);
718e3744 269 peer->sync[afi][safi] = sync;
270 peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
271 }
272}
273
274void
275bgp_sync_delete (struct peer *peer)
276{
277 afi_t afi;
278 safi_t safi;
279
280 for (afi = AFI_IP; afi < AFI_MAX; afi++)
281 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
282 {
283 if (peer->sync[afi][safi])
9f906c7c 284 XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
718e3744 285 peer->sync[afi][safi] = NULL;
200df115 286
287 if (peer->hash[afi][safi])
288 hash_free (peer->hash[afi][safi]);
9f906c7c 289 peer->hash[afi][safi] = NULL;
718e3744 290 }
291}