]>
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. */ | |
4d28080c | 46 | struct bgp_advertise_attr *bgp_advertise_attr_new(void) |
718e3744 | 47 | { |
9f5dc319 QY |
48 | return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR, |
49 | sizeof(struct bgp_advertise_attr)); | |
718e3744 | 50 | } |
51 | ||
4d28080c | 52 | void bgp_advertise_attr_free(struct bgp_advertise_attr *baa) |
718e3744 | 53 | { |
d62a17ae | 54 | XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa); |
718e3744 | 55 | } |
56 | ||
4d28080c | 57 | static void *bgp_advertise_attr_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 | |
4d28080c | 62 | baa = bgp_advertise_attr_new(); |
d62a17ae | 63 | baa->attr = ref->attr; |
64 | return baa; | |
718e3744 | 65 | } |
66 | ||
4d28080c | 67 | unsigned int bgp_advertise_attr_hash_key(const void *p) |
718e3744 | 68 | { |
d8b87afe | 69 | const struct bgp_advertise_attr *baa = p; |
923de654 | 70 | |
d62a17ae | 71 | return attrhash_key_make(baa->attr); |
718e3744 | 72 | } |
73 | ||
4d28080c | 74 | bool bgp_advertise_attr_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 | { |
9f5dc319 | 87 | return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise)); |
718e3744 | 88 | } |
89 | ||
d62a17ae | 90 | void bgp_advertise_free(struct bgp_advertise *adv) |
718e3744 | 91 | { |
9b6d8fcf DS |
92 | if (adv->pathi) |
93 | /* bgp_advertise bgp_path_info reference */ | |
94 | bgp_path_info_unlock(adv->pathi); | |
d62a17ae | 95 | XFREE(MTYPE_BGP_ADVERTISE, adv); |
718e3744 | 96 | } |
97 | ||
d62a17ae | 98 | void bgp_advertise_add(struct bgp_advertise_attr *baa, |
99 | struct bgp_advertise *adv) | |
718e3744 | 100 | { |
d62a17ae | 101 | adv->next = baa->adv; |
102 | if (baa->adv) | |
103 | baa->adv->prev = adv; | |
104 | baa->adv = adv; | |
718e3744 | 105 | } |
106 | ||
d62a17ae | 107 | void bgp_advertise_delete(struct bgp_advertise_attr *baa, |
108 | struct bgp_advertise *adv) | |
718e3744 | 109 | { |
d62a17ae | 110 | if (adv->next) |
111 | adv->next->prev = adv->prev; | |
112 | if (adv->prev) | |
113 | adv->prev->next = adv->next; | |
114 | else | |
115 | baa->adv = adv->next; | |
718e3744 | 116 | } |
117 | ||
4d28080c DA |
118 | struct bgp_advertise_attr *bgp_advertise_attr_intern(struct hash *hash, |
119 | struct attr *attr) | |
718e3744 | 120 | { |
d62a17ae | 121 | struct bgp_advertise_attr ref; |
122 | struct bgp_advertise_attr *baa; | |
718e3744 | 123 | |
d62a17ae | 124 | ref.attr = bgp_attr_intern(attr); |
4d28080c DA |
125 | baa = (struct bgp_advertise_attr *)hash_get( |
126 | hash, &ref, bgp_advertise_attr_hash_alloc); | |
d62a17ae | 127 | baa->refcnt++; |
718e3744 | 128 | |
d62a17ae | 129 | return baa; |
718e3744 | 130 | } |
131 | ||
4d28080c DA |
132 | void bgp_advertise_attr_unintern(struct hash *hash, |
133 | struct bgp_advertise_attr *baa) | |
718e3744 | 134 | { |
d62a17ae | 135 | if (baa->refcnt) |
136 | baa->refcnt--; | |
137 | ||
138 | if (baa->refcnt && baa->attr) | |
139 | bgp_attr_unintern(&baa->attr); | |
140 | else { | |
141 | if (baa->attr) { | |
142 | hash_release(hash, baa); | |
143 | bgp_attr_unintern(&baa->attr); | |
144 | } | |
4d28080c | 145 | bgp_advertise_attr_free(baa); |
718e3744 | 146 | } |
718e3744 | 147 | } |
6b0655a2 | 148 | |
9bcb3eef | 149 | bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, |
3dc339cd | 150 | uint32_t addpath_tx_id) |
718e3744 | 151 | { |
d62a17ae | 152 | struct bgp_adj_out *adj; |
153 | struct peer_af *paf; | |
154 | afi_t afi; | |
155 | safi_t safi; | |
be92fc9f | 156 | bool addpath_capable; |
d62a17ae | 157 | |
9bcb3eef | 158 | RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) |
a2addae8 RW |
159 | SUBGRP_FOREACH_PEER (adj->subgroup, paf) |
160 | if (paf->peer == peer) { | |
161 | afi = SUBGRP_AFI(adj->subgroup); | |
162 | safi = SUBGRP_SAFI(adj->subgroup); | |
163 | addpath_capable = | |
164 | bgp_addpath_encode_tx(peer, afi, safi); | |
165 | ||
166 | /* Match on a specific addpath_tx_id if we are | |
167 | * using addpath for | |
168 | * this | |
169 | * peer and if an addpath_tx_id was specified */ | |
170 | if (addpath_capable && addpath_tx_id | |
171 | && adj->addpath_tx_id != addpath_tx_id) | |
172 | continue; | |
173 | ||
3dc339cd DA |
174 | return (adj->adv |
175 | ? (adj->adv->baa ? true : false) | |
176 | : (adj->attr ? true : false)); | |
a2addae8 | 177 | } |
718e3744 | 178 | |
3dc339cd | 179 | return false; |
718e3744 | 180 | } |
181 | ||
6b0655a2 | 182 | |
9bcb3eef | 183 | void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr, |
d7c0a89a | 184 | uint32_t addpath_id) |
718e3744 | 185 | { |
d62a17ae | 186 | struct bgp_adj_in *adj; |
187 | ||
9bcb3eef | 188 | for (adj = dest->adj_in; adj; adj = adj->next) { |
d62a17ae | 189 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { |
190 | if (adj->attr != attr) { | |
191 | bgp_attr_unintern(&adj->attr); | |
192 | adj->attr = bgp_attr_intern(attr); | |
193 | } | |
194 | return; | |
195 | } | |
718e3744 | 196 | } |
d62a17ae | 197 | adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); |
198 | adj->peer = peer_lock(peer); /* adj_in peer reference */ | |
199 | adj->attr = bgp_attr_intern(attr); | |
083ec940 | 200 | adj->uptime = monotime(NULL); |
d62a17ae | 201 | adj->addpath_rx_id = addpath_id; |
9bcb3eef DS |
202 | BGP_ADJ_IN_ADD(dest, adj); |
203 | bgp_dest_lock_node(dest); | |
718e3744 | 204 | } |
205 | ||
9bcb3eef | 206 | void bgp_adj_in_remove(struct bgp_dest *dest, struct bgp_adj_in *bai) |
718e3744 | 207 | { |
d62a17ae | 208 | bgp_attr_unintern(&bai->attr); |
9bcb3eef | 209 | BGP_ADJ_IN_DEL(dest, bai); |
6a840fd9 | 210 | bgp_dest_unlock_node(dest); |
d62a17ae | 211 | peer_unlock(bai->peer); /* adj_in peer reference */ |
212 | XFREE(MTYPE_BGP_ADJ_IN, bai); | |
718e3744 | 213 | } |
214 | ||
9bcb3eef | 215 | bool bgp_adj_in_unset(struct bgp_dest *dest, struct peer *peer, |
3dc339cd | 216 | uint32_t addpath_id) |
718e3744 | 217 | { |
d62a17ae | 218 | struct bgp_adj_in *adj; |
219 | struct bgp_adj_in *adj_next; | |
718e3744 | 220 | |
9bcb3eef | 221 | adj = dest->adj_in; |
6b87f736 | 222 | |
d62a17ae | 223 | if (!adj) |
3dc339cd | 224 | return false; |
6b87f736 | 225 | |
d62a17ae | 226 | while (adj) { |
227 | adj_next = adj->next; | |
718e3744 | 228 | |
6a840fd9 | 229 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) |
9bcb3eef | 230 | bgp_adj_in_remove(dest, adj); |
718e3744 | 231 | |
d62a17ae | 232 | adj = adj_next; |
233 | } | |
6b87f736 | 234 | |
3dc339cd | 235 | return true; |
718e3744 | 236 | } |
6b0655a2 | 237 | |
d62a17ae | 238 | void bgp_sync_init(struct peer *peer) |
718e3744 | 239 | { |
d62a17ae | 240 | afi_t afi; |
241 | safi_t safi; | |
242 | struct bgp_synchronize *sync; | |
243 | ||
05c7a1cc QY |
244 | FOREACH_AFI_SAFI (afi, safi) { |
245 | sync = XCALLOC(MTYPE_BGP_SYNCHRONISE, | |
246 | sizeof(struct bgp_synchronize)); | |
a274fef8 DL |
247 | bgp_adv_fifo_init(&sync->update); |
248 | bgp_adv_fifo_init(&sync->withdraw); | |
249 | bgp_adv_fifo_init(&sync->withdraw_low); | |
05c7a1cc | 250 | peer->sync[afi][safi] = sync; |
05c7a1cc | 251 | } |
718e3744 | 252 | } |
253 | ||
d62a17ae | 254 | void bgp_sync_delete(struct peer *peer) |
718e3744 | 255 | { |
d62a17ae | 256 | afi_t afi; |
257 | safi_t safi; | |
258 | ||
05c7a1cc | 259 | FOREACH_AFI_SAFI (afi, safi) { |
0a22ddfb | 260 | XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); |
05c7a1cc | 261 | } |
718e3744 | 262 | } |