]>
Commit | Line | Data |
---|---|---|
718e3744 | 1 | /* BGP advertisement and adjacency |
896014f4 DL |
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 | */ | |
718e3744 | 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. */ | |
d62a17ae | 46 | struct bgp_advertise_attr *baa_new(void) |
718e3744 | 47 | { |
d62a17ae | 48 | return (struct bgp_advertise_attr *)XCALLOC( |
49 | MTYPE_BGP_ADVERTISE_ATTR, sizeof(struct bgp_advertise_attr)); | |
718e3744 | 50 | } |
51 | ||
d62a17ae | 52 | static void baa_free(struct bgp_advertise_attr *baa) |
718e3744 | 53 | { |
d62a17ae | 54 | XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa); |
718e3744 | 55 | } |
56 | ||
d62a17ae | 57 | static void *baa_hash_alloc(void *p) |
718e3744 | 58 | { |
d62a17ae | 59 | struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p; |
60 | struct bgp_advertise_attr *baa; | |
718e3744 | 61 | |
d62a17ae | 62 | baa = baa_new(); |
63 | baa->attr = ref->attr; | |
64 | return baa; | |
718e3744 | 65 | } |
66 | ||
d62a17ae | 67 | unsigned int baa_hash_key(void *p) |
718e3744 | 68 | { |
d62a17ae | 69 | struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p; |
923de654 | 70 | |
d62a17ae | 71 | return attrhash_key_make(baa->attr); |
718e3744 | 72 | } |
73 | ||
d62a17ae | 74 | int baa_hash_cmp(const void *p1, const void *p2) |
718e3744 | 75 | { |
d62a17ae | 76 | const struct bgp_advertise_attr *baa1 = p1; |
77 | const struct bgp_advertise_attr *baa2 = p2; | |
923de654 | 78 | |
d62a17ae | 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. */ | |
d62a17ae | 85 | struct bgp_advertise *bgp_advertise_new(void) |
718e3744 | 86 | { |
d62a17ae | 87 | return (struct bgp_advertise *)XCALLOC(MTYPE_BGP_ADVERTISE, |
88 | sizeof(struct bgp_advertise)); | |
718e3744 | 89 | } |
90 | ||
d62a17ae | 91 | void bgp_advertise_free(struct bgp_advertise *adv) |
718e3744 | 92 | { |
d62a17ae | 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 | ||
d62a17ae | 99 | void bgp_advertise_add(struct bgp_advertise_attr *baa, |
100 | struct bgp_advertise *adv) | |
718e3744 | 101 | { |
d62a17ae | 102 | adv->next = baa->adv; |
103 | if (baa->adv) | |
104 | baa->adv->prev = adv; | |
105 | baa->adv = adv; | |
718e3744 | 106 | } |
107 | ||
d62a17ae | 108 | void bgp_advertise_delete(struct bgp_advertise_attr *baa, |
109 | struct bgp_advertise *adv) | |
718e3744 | 110 | { |
d62a17ae | 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 | ||
d62a17ae | 119 | struct bgp_advertise_attr *bgp_advertise_intern(struct hash *hash, |
120 | struct attr *attr) | |
718e3744 | 121 | { |
d62a17ae | 122 | struct bgp_advertise_attr ref; |
123 | struct bgp_advertise_attr *baa; | |
718e3744 | 124 | |
d62a17ae | 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 | |
d62a17ae | 129 | return baa; |
718e3744 | 130 | } |
131 | ||
d62a17ae | 132 | void bgp_advertise_unintern(struct hash *hash, struct bgp_advertise_attr *baa) |
718e3744 | 133 | { |
d62a17ae | 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 | |
d62a17ae | 148 | int bgp_adj_out_lookup(struct peer *peer, struct bgp_node *rn, |
d7c0a89a | 149 | uint32_t addpath_tx_id) |
718e3744 | 150 | { |
d62a17ae | 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) | |
a2addae8 RW |
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 = | |
163 | bgp_addpath_encode_tx(peer, afi, safi); | |
164 | ||
165 | /* Match on a specific addpath_tx_id if we are | |
166 | * using addpath for | |
167 | * this | |
168 | * peer and if an addpath_tx_id was specified */ | |
169 | if (addpath_capable && addpath_tx_id | |
170 | && adj->addpath_tx_id != addpath_tx_id) | |
171 | continue; | |
172 | ||
173 | return (adj->adv ? (adj->adv->baa ? 1 : 0) | |
174 | : (adj->attr ? 1 : 0)); | |
175 | } | |
718e3744 | 176 | |
d62a17ae | 177 | return 0; |
718e3744 | 178 | } |
179 | ||
6b0655a2 | 180 | |
d62a17ae | 181 | void bgp_adj_in_set(struct bgp_node *rn, struct peer *peer, struct attr *attr, |
d7c0a89a | 182 | uint32_t addpath_id) |
718e3744 | 183 | { |
d62a17ae | 184 | struct bgp_adj_in *adj; |
185 | ||
186 | for (adj = rn->adj_in; adj; adj = adj->next) { | |
187 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { | |
188 | if (adj->attr != attr) { | |
189 | bgp_attr_unintern(&adj->attr); | |
190 | adj->attr = bgp_attr_intern(attr); | |
191 | } | |
192 | return; | |
193 | } | |
718e3744 | 194 | } |
d62a17ae | 195 | adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); |
196 | adj->peer = peer_lock(peer); /* adj_in peer reference */ | |
197 | adj->attr = bgp_attr_intern(attr); | |
198 | adj->addpath_rx_id = addpath_id; | |
199 | BGP_ADJ_IN_ADD(rn, adj); | |
200 | bgp_lock_node(rn); | |
718e3744 | 201 | } |
202 | ||
d62a17ae | 203 | void bgp_adj_in_remove(struct bgp_node *rn, struct bgp_adj_in *bai) |
718e3744 | 204 | { |
d62a17ae | 205 | bgp_attr_unintern(&bai->attr); |
206 | BGP_ADJ_IN_DEL(rn, bai); | |
207 | peer_unlock(bai->peer); /* adj_in peer reference */ | |
208 | XFREE(MTYPE_BGP_ADJ_IN, bai); | |
718e3744 | 209 | } |
210 | ||
d62a17ae | 211 | int bgp_adj_in_unset(struct bgp_node *rn, struct peer *peer, |
d7c0a89a | 212 | uint32_t addpath_id) |
718e3744 | 213 | { |
d62a17ae | 214 | struct bgp_adj_in *adj; |
215 | struct bgp_adj_in *adj_next; | |
718e3744 | 216 | |
d62a17ae | 217 | adj = rn->adj_in; |
6b87f736 | 218 | |
d62a17ae | 219 | if (!adj) |
220 | return 0; | |
6b87f736 | 221 | |
d62a17ae | 222 | while (adj) { |
223 | adj_next = adj->next; | |
718e3744 | 224 | |
d62a17ae | 225 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { |
226 | bgp_adj_in_remove(rn, adj); | |
227 | bgp_unlock_node(rn); | |
228 | } | |
718e3744 | 229 | |
d62a17ae | 230 | adj = adj_next; |
231 | } | |
6b87f736 | 232 | |
d62a17ae | 233 | return 1; |
718e3744 | 234 | } |
6b0655a2 | 235 | |
d62a17ae | 236 | void bgp_sync_init(struct peer *peer) |
718e3744 | 237 | { |
d62a17ae | 238 | afi_t afi; |
239 | safi_t safi; | |
240 | struct bgp_synchronize *sync; | |
241 | ||
05c7a1cc QY |
242 | FOREACH_AFI_SAFI (afi, safi) { |
243 | sync = XCALLOC(MTYPE_BGP_SYNCHRONISE, | |
244 | sizeof(struct bgp_synchronize)); | |
245 | BGP_ADV_FIFO_INIT(&sync->update); | |
246 | BGP_ADV_FIFO_INIT(&sync->withdraw); | |
247 | BGP_ADV_FIFO_INIT(&sync->withdraw_low); | |
248 | peer->sync[afi][safi] = sync; | |
05c7a1cc | 249 | } |
718e3744 | 250 | } |
251 | ||
d62a17ae | 252 | void bgp_sync_delete(struct peer *peer) |
718e3744 | 253 | { |
d62a17ae | 254 | afi_t afi; |
255 | safi_t safi; | |
256 | ||
05c7a1cc QY |
257 | FOREACH_AFI_SAFI (afi, safi) { |
258 | if (peer->sync[afi][safi]) | |
259 | XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); | |
260 | peer->sync[afi][safi] = NULL; | |
05c7a1cc | 261 | } |
718e3744 | 262 | } |