]>
Commit | Line | Data |
---|---|---|
718e3744 | 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" | |
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. */ | |
ac4d0be5 | 46 | struct bgp_advertise_attr *baa_new(void) |
718e3744 | 47 | { |
ac4d0be5 | 48 | return (struct bgp_advertise_attr *)XCALLOC( |
49 | MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr)); | |
718e3744 | 50 | } |
51 | ||
ac4d0be5 | 52 | static void baa_free(struct bgp_advertise_attr *baa) |
718e3744 | 53 | { |
ac4d0be5 | 54 | XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa); |
718e3744 | 55 | } |
56 | ||
ac4d0be5 | 57 | static void *baa_hash_alloc(void *p) |
718e3744 | 58 | { |
ac4d0be5 | 59 | struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p; |
60 | struct bgp_advertise_attr *baa; | |
718e3744 | 61 | |
ac4d0be5 | 62 | baa = baa_new(); |
63 | baa->attr = ref->attr; | |
64 | return baa; | |
718e3744 | 65 | } |
66 | ||
ac4d0be5 | 67 | unsigned int baa_hash_key(void *p) |
718e3744 | 68 | { |
ac4d0be5 | 69 | struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p; |
923de654 | 70 | |
ac4d0be5 | 71 | return attrhash_key_make(baa->attr); |
718e3744 | 72 | } |
73 | ||
ac4d0be5 | 74 | int baa_hash_cmp(const void *p1, const void *p2) |
718e3744 | 75 | { |
ac4d0be5 | 76 | const struct bgp_advertise_attr *baa1 = p1; |
77 | const struct bgp_advertise_attr *baa2 = p2; | |
923de654 | 78 | |
ac4d0be5 | 79 | return attrhash_cmp(baa1->attr, baa2->attr); |
718e3744 | 80 | } |
6b0655a2 | 81 | |
718e3744 | 82 | /* BGP update and withdraw information is stored in BGP advertise |
83 | structure. This structure is referred from BGP adjacency | |
84 | information. */ | |
ac4d0be5 | 85 | struct bgp_advertise *bgp_advertise_new(void) |
718e3744 | 86 | { |
ac4d0be5 | 87 | return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE, |
88 | sizeof(struct bgp_advertise)); | |
718e3744 | 89 | } |
90 | ||
ac4d0be5 | 91 | void bgp_advertise_free(struct bgp_advertise *adv) |
718e3744 | 92 | { |
ac4d0be5 | 93 | if (adv->binfo) |
94 | bgp_info_unlock( | |
95 | adv->binfo); /* bgp_advertise bgp_info reference */ | |
96 | XFREE(MTYPE_BGP_ADVERTISE, adv); | |
718e3744 | 97 | } |
98 | ||
ac4d0be5 | 99 | void bgp_advertise_add(struct bgp_advertise_attr *baa, |
100 | struct bgp_advertise *adv) | |
718e3744 | 101 | { |
ac4d0be5 | 102 | adv->next = baa->adv; |
103 | if (baa->adv) | |
104 | baa->adv->prev = adv; | |
105 | baa->adv = adv; | |
718e3744 | 106 | } |
107 | ||
ac4d0be5 | 108 | void bgp_advertise_delete(struct bgp_advertise_attr *baa, |
109 | struct bgp_advertise *adv) | |
718e3744 | 110 | { |
ac4d0be5 | 111 | if (adv->next) |
112 | adv->next->prev = adv->prev; | |
113 | if (adv->prev) | |
114 | adv->prev->next = adv->next; | |
115 | else | |
116 | baa->adv = adv->next; | |
718e3744 | 117 | } |
118 | ||
ac4d0be5 | 119 | struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash, |
120 | struct attr *attr) | |
718e3744 | 121 | { |
ac4d0be5 | 122 | struct bgp_advertise_attr ref; |
123 | struct bgp_advertise_attr *baa; | |
718e3744 | 124 | |
ac4d0be5 | 125 | ref.attr = bgp_attr_intern(attr); |
126 | baa = (struct bgp_advertise_attr *)hash_get(hash, &ref, baa_hash_alloc); | |
127 | baa->refcnt++; | |
718e3744 | 128 | |
ac4d0be5 | 129 | return baa; |
718e3744 | 130 | } |
131 | ||
ac4d0be5 | 132 | void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa) |
718e3744 | 133 | { |
ac4d0be5 | 134 | if (baa->refcnt) |
135 | baa->refcnt--; | |
136 | ||
137 | if (baa->refcnt && baa->attr) | |
138 | bgp_attr_unintern(&baa->attr); | |
139 | else { | |
140 | if (baa->attr) { | |
141 | hash_release(hash, baa); | |
142 | bgp_attr_unintern(&baa->attr); | |
143 | } | |
144 | baa_free(baa); | |
718e3744 | 145 | } |
718e3744 | 146 | } |
6b0655a2 | 147 | |
ac4d0be5 | 148 | int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, |
149 | u_int32_t addpath_tx_id) | |
718e3744 | 150 | { |
ac4d0be5 | 151 | struct bgp_adj_out *adj; |
152 | struct peer_af *paf; | |
153 | afi_t afi; | |
154 | safi_t safi; | |
155 | int addpath_capable; | |
156 | ||
157 | for (adj = rn->adj_out; adj; adj = adj->next) | |
158 | SUBGRP_FOREACH_PEER(adj->subgroup, paf) | |
159 | if (paf->peer == peer) { | |
160 | afi = SUBGRP_AFI(adj->subgroup); | |
161 | safi = SUBGRP_SAFI(adj->subgroup); | |
162 | addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); | |
163 | ||
164 | /* Match on a specific addpath_tx_id if we are using addpath for | |
165 | * this | |
166 | * peer and if an addpath_tx_id was specified */ | |
167 | if (addpath_capable && addpath_tx_id | |
168 | && adj->addpath_tx_id != addpath_tx_id) | |
169 | continue; | |
170 | ||
171 | return (adj->adv ? (adj->adv->baa ? 1 : 0) | |
172 | : (adj->attr ? 1 : 0)); | |
3f9c7369 | 173 | } |
718e3744 | 174 | |
ac4d0be5 | 175 | return 0; |
718e3744 | 176 | } |
177 | ||
6b0655a2 | 178 | |
ac4d0be5 | 179 | void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr, |
180 | u_int32_t addpath_id) | |
718e3744 | 181 | { |
ac4d0be5 | 182 | struct bgp_adj_in *adj; |
183 | ||
184 | for (adj = rn->adj_in; adj; adj = adj->next) { | |
185 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { | |
186 | if (adj->attr != attr) { | |
187 | bgp_attr_unintern(&adj->attr); | |
188 | adj->attr = bgp_attr_intern(attr); | |
189 | } | |
190 | return; | |
191 | } | |
718e3744 | 192 | } |
ac4d0be5 | 193 | adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); |
194 | adj->peer = peer_lock(peer); /* adj_in peer reference */ | |
195 | adj->attr = bgp_attr_intern(attr); | |
196 | adj->addpath_rx_id = addpath_id; | |
197 | BGP_ADJ_IN_ADD(rn, adj); | |
198 | bgp_lock_node(rn); | |
718e3744 | 199 | } |
200 | ||
ac4d0be5 | 201 | void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai) |
718e3744 | 202 | { |
ac4d0be5 | 203 | bgp_attr_unintern(&bai->attr); |
204 | BGP_ADJ_IN_DEL(rn, bai); | |
205 | peer_unlock(bai->peer); /* adj_in peer reference */ | |
206 | XFREE(MTYPE_BGP_ADJ_IN, bai); | |
718e3744 | 207 | } |
208 | ||
ac4d0be5 | 209 | int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, |
210 | u_int32_t addpath_id) | |
718e3744 | 211 | { |
ac4d0be5 | 212 | struct bgp_adj_in *adj; |
213 | struct bgp_adj_in *adj_next; | |
718e3744 | 214 | |
ac4d0be5 | 215 | adj = rn->adj_in; |
6b87f736 | 216 | |
ac4d0be5 | 217 | if (!adj) |
218 | return 0; | |
6b87f736 | 219 | |
ac4d0be5 | 220 | while (adj) { |
221 | adj_next = adj->next; | |
718e3744 | 222 | |
ac4d0be5 | 223 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { |
224 | bgp_adj_in_remove(rn, adj); | |
225 | bgp_unlock_node(rn); | |
226 | } | |
718e3744 | 227 | |
ac4d0be5 | 228 | adj = adj_next; |
229 | } | |
6b87f736 | 230 | |
ac4d0be5 | 231 | return 1; |
718e3744 | 232 | } |
6b0655a2 | 233 | |
ac4d0be5 | 234 | void bgp_sync_init(struct peer *peer) |
718e3744 | 235 | { |
ac4d0be5 | 236 | afi_t afi; |
237 | safi_t safi; | |
238 | struct bgp_synchronize *sync; | |
239 | ||
240 | for (afi = AFI_IP; afi < AFI_MAX; afi++) | |
241 | for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { | |
242 | sync = XCALLOC(MTYPE_BGP_SYNCHRONISE, | |
243 | sizeof(struct bgp_synchronize)); | |
244 | BGP_ADV_FIFO_INIT(&sync->update); | |
245 | BGP_ADV_FIFO_INIT(&sync->withdraw); | |
246 | BGP_ADV_FIFO_INIT(&sync->withdraw_low); | |
247 | peer->sync[afi][safi] = sync; | |
248 | peer->hash[afi][safi] = | |
249 | hash_create(baa_hash_key, baa_hash_cmp); | |
250 | } | |
718e3744 | 251 | } |
252 | ||
ac4d0be5 | 253 | void bgp_sync_delete(struct peer *peer) |
718e3744 | 254 | { |
ac4d0be5 | 255 | afi_t afi; |
256 | safi_t safi; | |
257 | ||
258 | for (afi = AFI_IP; afi < AFI_MAX; afi++) | |
259 | for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) { | |
260 | if (peer->sync[afi][safi]) | |
261 | XFREE(MTYPE_BGP_SYNCHRONISE, | |
262 | peer->sync[afi][safi]); | |
263 | peer->sync[afi][safi] = NULL; | |
264 | ||
265 | if (peer->hash[afi][safi]) | |
266 | hash_free(peer->hash[afi][safi]); | |
267 | peer->hash[afi][safi] = NULL; | |
268 | } | |
718e3744 | 269 | } |