]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_advertise.c
*: make consistent & update GPLv2 file headers
[mirror_frr.git] / 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 along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
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 #include "queue.h"
29 #include "filter.h"
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"
36 #include "bgpd/bgp_debug.h"
37 #include "bgpd/bgp_aspath.h"
38 #include "bgpd/bgp_packet.h"
39 #include "bgpd/bgp_fsm.h"
40 #include "bgpd/bgp_mplsvpn.h"
41 #include "bgpd/bgp_updgrp.h"
42
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. */
46 struct bgp_advertise_attr *
47 baa_new (void)
48 {
49 return (struct bgp_advertise_attr *)
50 XCALLOC (MTYPE_BGP_ADVERTISE_ATTR, sizeof (struct bgp_advertise_attr));
51 }
52
53 static void
54 baa_free (struct bgp_advertise_attr *baa)
55 {
56 XFREE (MTYPE_BGP_ADVERTISE_ATTR, baa);
57 }
58
59 static void *
60 baa_hash_alloc (void *p)
61 {
62 struct bgp_advertise_attr * ref = (struct bgp_advertise_attr *) p;
63 struct bgp_advertise_attr *baa;
64
65 baa = baa_new ();
66 baa->attr = ref->attr;
67 return baa;
68 }
69
70 unsigned int
71 baa_hash_key (void *p)
72 {
73 struct bgp_advertise_attr * baa = (struct bgp_advertise_attr *) p;
74
75 return attrhash_key_make (baa->attr);
76 }
77
78 int
79 baa_hash_cmp (const void *p1, const void *p2)
80 {
81 const struct bgp_advertise_attr * baa1 = p1;
82 const struct bgp_advertise_attr * baa2 = p2;
83
84 return attrhash_cmp (baa1->attr, baa2->attr);
85 }
86
87 /* BGP update and withdraw information is stored in BGP advertise
88 structure. This structure is referred from BGP adjacency
89 information. */
90 struct bgp_advertise *
91 bgp_advertise_new (void)
92 {
93 return (struct bgp_advertise *)
94 XCALLOC (MTYPE_BGP_ADVERTISE, sizeof (struct bgp_advertise));
95 }
96
97 void
98 bgp_advertise_free (struct bgp_advertise *adv)
99 {
100 if (adv->binfo)
101 bgp_info_unlock (adv->binfo); /* bgp_advertise bgp_info reference */
102 XFREE (MTYPE_BGP_ADVERTISE, adv);
103 }
104
105 void
106 bgp_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
115 void
116 bgp_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
127 struct bgp_advertise_attr *
128 bgp_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
140 void
141 bgp_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)
147 bgp_attr_unintern (&baa->attr);
148 else
149 {
150 if (baa->attr)
151 {
152 hash_release (hash, baa);
153 bgp_attr_unintern (&baa->attr);
154 }
155 baa_free (baa);
156 }
157 }
158
159 int
160 bgp_adj_out_lookup (struct peer *peer, struct bgp_node *rn,
161 u_int32_t addpath_tx_id)
162 {
163 struct bgp_adj_out *adj;
164 struct peer_af *paf;
165 afi_t afi;
166 safi_t safi;
167 int addpath_capable;
168
169 for (adj = rn->adj_out; adj; adj = adj->next)
170 SUBGRP_FOREACH_PEER(adj->subgroup, paf)
171 if (paf->peer == peer)
172 {
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
182 return (adj->adv
183 ? (adj->adv->baa ? 1 : 0)
184 : (adj->attr ? 1 : 0));
185 }
186
187 return 0;
188 }
189
190
191 void
192 bgp_adj_in_set (struct bgp_node *rn, struct peer *peer, struct attr *attr,
193 u_int32_t addpath_id)
194 {
195 struct bgp_adj_in *adj;
196
197 for (adj = rn->adj_in; adj; adj = adj->next)
198 {
199 if (adj->peer == peer && adj->addpath_rx_id == addpath_id)
200 {
201 if (adj->attr != attr)
202 {
203 bgp_attr_unintern (&adj->attr);
204 adj->attr = bgp_attr_intern (attr);
205 }
206 return;
207 }
208 }
209 adj = XCALLOC (MTYPE_BGP_ADJ_IN, sizeof (struct bgp_adj_in));
210 adj->peer = peer_lock (peer); /* adj_in peer reference */
211 adj->attr = bgp_attr_intern (attr);
212 adj->addpath_rx_id = addpath_id;
213 BGP_ADJ_IN_ADD (rn, adj);
214 bgp_lock_node (rn);
215 }
216
217 void
218 bgp_adj_in_remove (struct bgp_node *rn, struct bgp_adj_in *bai)
219 {
220 bgp_attr_unintern (&bai->attr);
221 BGP_ADJ_IN_DEL (rn, bai);
222 peer_unlock (bai->peer); /* adj_in peer reference */
223 XFREE (MTYPE_BGP_ADJ_IN, bai);
224 }
225
226 int
227 bgp_adj_in_unset (struct bgp_node *rn, struct peer *peer,
228 u_int32_t addpath_id)
229 {
230 struct bgp_adj_in *adj;
231 struct bgp_adj_in *adj_next;
232
233 adj = rn->adj_in;
234
235 if (!adj)
236 return 0;
237
238 while (adj)
239 {
240 adj_next = adj->next;
241
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 }
247
248 adj = adj_next;
249 }
250
251 return 1;
252 }
253
254 void
255 bgp_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 {
264 sync = XCALLOC (MTYPE_BGP_SYNCHRONISE,
265 sizeof (struct bgp_synchronize));
266 BGP_ADV_FIFO_INIT (&sync->update);
267 BGP_ADV_FIFO_INIT (&sync->withdraw);
268 BGP_ADV_FIFO_INIT (&sync->withdraw_low);
269 peer->sync[afi][safi] = sync;
270 peer->hash[afi][safi] = hash_create (baa_hash_key, baa_hash_cmp);
271 }
272 }
273
274 void
275 bgp_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])
284 XFREE (MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]);
285 peer->sync[afi][safi] = NULL;
286
287 if (peer->hash[afi][safi])
288 hash_free (peer->hash[afi][safi]);
289 peer->hash[afi][safi] = NULL;
290 }
291 }