]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
718e3744 | 2 | /* BGP advertisement and adjacency |
896014f4 | 3 | * Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro |
896014f4 | 4 | */ |
718e3744 | 5 | |
6 | #include <zebra.h> | |
7 | ||
8 | #include "command.h" | |
9 | #include "memory.h" | |
10 | #include "prefix.h" | |
11 | #include "hash.h" | |
cb37cb33 | 12 | #include "event.h" |
3f9c7369 | 13 | #include "queue.h" |
039f3a34 | 14 | #include "filter.h" |
718e3744 | 15 | |
16 | #include "bgpd/bgpd.h" | |
17 | #include "bgpd/bgp_table.h" | |
18 | #include "bgpd/bgp_route.h" | |
19 | #include "bgpd/bgp_advertise.h" | |
20 | #include "bgpd/bgp_attr.h" | |
d889623f | 21 | #include "bgpd/bgp_debug.h" |
718e3744 | 22 | #include "bgpd/bgp_aspath.h" |
23 | #include "bgpd/bgp_packet.h" | |
24 | #include "bgpd/bgp_fsm.h" | |
25 | #include "bgpd/bgp_mplsvpn.h" | |
3f9c7369 | 26 | #include "bgpd/bgp_updgrp.h" |
6b0655a2 | 27 | |
718e3744 | 28 | /* BGP advertise attribute is used for pack same attribute update into |
29 | one packet. To do that we maintain attribute hash in struct | |
30 | peer. */ | |
4d28080c | 31 | struct bgp_advertise_attr *bgp_advertise_attr_new(void) |
718e3744 | 32 | { |
9f5dc319 QY |
33 | return XCALLOC(MTYPE_BGP_ADVERTISE_ATTR, |
34 | sizeof(struct bgp_advertise_attr)); | |
718e3744 | 35 | } |
36 | ||
4d28080c | 37 | void bgp_advertise_attr_free(struct bgp_advertise_attr *baa) |
718e3744 | 38 | { |
d62a17ae | 39 | XFREE(MTYPE_BGP_ADVERTISE_ATTR, baa); |
718e3744 | 40 | } |
41 | ||
4d28080c | 42 | static void *bgp_advertise_attr_hash_alloc(void *p) |
718e3744 | 43 | { |
d62a17ae | 44 | struct bgp_advertise_attr *ref = (struct bgp_advertise_attr *)p; |
45 | struct bgp_advertise_attr *baa; | |
718e3744 | 46 | |
4d28080c | 47 | baa = bgp_advertise_attr_new(); |
d62a17ae | 48 | baa->attr = ref->attr; |
49 | return baa; | |
718e3744 | 50 | } |
51 | ||
4d28080c | 52 | unsigned int bgp_advertise_attr_hash_key(const void *p) |
718e3744 | 53 | { |
d8b87afe | 54 | const struct bgp_advertise_attr *baa = p; |
923de654 | 55 | |
d62a17ae | 56 | return attrhash_key_make(baa->attr); |
718e3744 | 57 | } |
58 | ||
4d28080c | 59 | bool bgp_advertise_attr_hash_cmp(const void *p1, const void *p2) |
718e3744 | 60 | { |
d62a17ae | 61 | const struct bgp_advertise_attr *baa1 = p1; |
62 | const struct bgp_advertise_attr *baa2 = p2; | |
923de654 | 63 | |
d62a17ae | 64 | return attrhash_cmp(baa1->attr, baa2->attr); |
718e3744 | 65 | } |
6b0655a2 | 66 | |
718e3744 | 67 | /* BGP update and withdraw information is stored in BGP advertise |
68 | structure. This structure is referred from BGP adjacency | |
69 | information. */ | |
d62a17ae | 70 | struct bgp_advertise *bgp_advertise_new(void) |
718e3744 | 71 | { |
9f5dc319 | 72 | return XCALLOC(MTYPE_BGP_ADVERTISE, sizeof(struct bgp_advertise)); |
718e3744 | 73 | } |
74 | ||
d62a17ae | 75 | void bgp_advertise_free(struct bgp_advertise *adv) |
718e3744 | 76 | { |
9b6d8fcf DS |
77 | if (adv->pathi) |
78 | /* bgp_advertise bgp_path_info reference */ | |
79 | bgp_path_info_unlock(adv->pathi); | |
d62a17ae | 80 | XFREE(MTYPE_BGP_ADVERTISE, adv); |
718e3744 | 81 | } |
82 | ||
d62a17ae | 83 | void bgp_advertise_add(struct bgp_advertise_attr *baa, |
84 | struct bgp_advertise *adv) | |
718e3744 | 85 | { |
d62a17ae | 86 | adv->next = baa->adv; |
87 | if (baa->adv) | |
88 | baa->adv->prev = adv; | |
89 | baa->adv = adv; | |
718e3744 | 90 | } |
91 | ||
d62a17ae | 92 | void bgp_advertise_delete(struct bgp_advertise_attr *baa, |
93 | struct bgp_advertise *adv) | |
718e3744 | 94 | { |
d62a17ae | 95 | if (adv->next) |
96 | adv->next->prev = adv->prev; | |
97 | if (adv->prev) | |
98 | adv->prev->next = adv->next; | |
99 | else | |
100 | baa->adv = adv->next; | |
718e3744 | 101 | } |
102 | ||
4d28080c DA |
103 | struct bgp_advertise_attr *bgp_advertise_attr_intern(struct hash *hash, |
104 | struct attr *attr) | |
718e3744 | 105 | { |
d62a17ae | 106 | struct bgp_advertise_attr ref; |
107 | struct bgp_advertise_attr *baa; | |
718e3744 | 108 | |
d62a17ae | 109 | ref.attr = bgp_attr_intern(attr); |
4d28080c DA |
110 | baa = (struct bgp_advertise_attr *)hash_get( |
111 | hash, &ref, bgp_advertise_attr_hash_alloc); | |
d62a17ae | 112 | baa->refcnt++; |
718e3744 | 113 | |
d62a17ae | 114 | return baa; |
718e3744 | 115 | } |
116 | ||
4d28080c DA |
117 | void bgp_advertise_attr_unintern(struct hash *hash, |
118 | struct bgp_advertise_attr *baa) | |
718e3744 | 119 | { |
d62a17ae | 120 | if (baa->refcnt) |
121 | baa->refcnt--; | |
122 | ||
123 | if (baa->refcnt && baa->attr) | |
124 | bgp_attr_unintern(&baa->attr); | |
125 | else { | |
126 | if (baa->attr) { | |
127 | hash_release(hash, baa); | |
128 | bgp_attr_unintern(&baa->attr); | |
129 | } | |
4d28080c | 130 | bgp_advertise_attr_free(baa); |
718e3744 | 131 | } |
718e3744 | 132 | } |
6b0655a2 | 133 | |
9bcb3eef | 134 | bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest, |
3dc339cd | 135 | uint32_t addpath_tx_id) |
718e3744 | 136 | { |
d62a17ae | 137 | struct bgp_adj_out *adj; |
138 | struct peer_af *paf; | |
139 | afi_t afi; | |
140 | safi_t safi; | |
be92fc9f | 141 | bool addpath_capable; |
d62a17ae | 142 | |
9bcb3eef | 143 | RB_FOREACH (adj, bgp_adj_out_rb, &dest->adj_out) |
a2addae8 RW |
144 | SUBGRP_FOREACH_PEER (adj->subgroup, paf) |
145 | if (paf->peer == peer) { | |
146 | afi = SUBGRP_AFI(adj->subgroup); | |
147 | safi = SUBGRP_SAFI(adj->subgroup); | |
148 | addpath_capable = | |
149 | bgp_addpath_encode_tx(peer, afi, safi); | |
150 | ||
151 | /* Match on a specific addpath_tx_id if we are | |
152 | * using addpath for | |
153 | * this | |
154 | * peer and if an addpath_tx_id was specified */ | |
155 | if (addpath_capable && addpath_tx_id | |
156 | && adj->addpath_tx_id != addpath_tx_id) | |
157 | continue; | |
158 | ||
3dc339cd DA |
159 | return (adj->adv |
160 | ? (adj->adv->baa ? true : false) | |
161 | : (adj->attr ? true : false)); | |
a2addae8 | 162 | } |
718e3744 | 163 | |
3dc339cd | 164 | return false; |
718e3744 | 165 | } |
166 | ||
6b0655a2 | 167 | |
9bcb3eef | 168 | void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr, |
d7c0a89a | 169 | uint32_t addpath_id) |
718e3744 | 170 | { |
d62a17ae | 171 | struct bgp_adj_in *adj; |
172 | ||
9bcb3eef | 173 | for (adj = dest->adj_in; adj; adj = adj->next) { |
d62a17ae | 174 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) { |
175 | if (adj->attr != attr) { | |
176 | bgp_attr_unintern(&adj->attr); | |
177 | adj->attr = bgp_attr_intern(attr); | |
178 | } | |
179 | return; | |
180 | } | |
718e3744 | 181 | } |
d62a17ae | 182 | adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in)); |
183 | adj->peer = peer_lock(peer); /* adj_in peer reference */ | |
184 | adj->attr = bgp_attr_intern(attr); | |
083ec940 | 185 | adj->uptime = monotime(NULL); |
d62a17ae | 186 | adj->addpath_rx_id = addpath_id; |
9bcb3eef DS |
187 | BGP_ADJ_IN_ADD(dest, adj); |
188 | bgp_dest_lock_node(dest); | |
718e3744 | 189 | } |
190 | ||
9bcb3eef | 191 | void bgp_adj_in_remove(struct bgp_dest *dest, struct bgp_adj_in *bai) |
718e3744 | 192 | { |
d62a17ae | 193 | bgp_attr_unintern(&bai->attr); |
9bcb3eef | 194 | BGP_ADJ_IN_DEL(dest, bai); |
6a840fd9 | 195 | bgp_dest_unlock_node(dest); |
d62a17ae | 196 | peer_unlock(bai->peer); /* adj_in peer reference */ |
197 | XFREE(MTYPE_BGP_ADJ_IN, bai); | |
718e3744 | 198 | } |
199 | ||
9bcb3eef | 200 | bool bgp_adj_in_unset(struct bgp_dest *dest, struct peer *peer, |
3dc339cd | 201 | uint32_t addpath_id) |
718e3744 | 202 | { |
d62a17ae | 203 | struct bgp_adj_in *adj; |
204 | struct bgp_adj_in *adj_next; | |
718e3744 | 205 | |
9bcb3eef | 206 | adj = dest->adj_in; |
6b87f736 | 207 | |
d62a17ae | 208 | if (!adj) |
3dc339cd | 209 | return false; |
6b87f736 | 210 | |
d62a17ae | 211 | while (adj) { |
212 | adj_next = adj->next; | |
718e3744 | 213 | |
6a840fd9 | 214 | if (adj->peer == peer && adj->addpath_rx_id == addpath_id) |
9bcb3eef | 215 | bgp_adj_in_remove(dest, adj); |
718e3744 | 216 | |
d62a17ae | 217 | adj = adj_next; |
218 | } | |
6b87f736 | 219 | |
3dc339cd | 220 | return true; |
718e3744 | 221 | } |
6b0655a2 | 222 | |
d62a17ae | 223 | void bgp_sync_init(struct peer *peer) |
718e3744 | 224 | { |
d62a17ae | 225 | afi_t afi; |
226 | safi_t safi; | |
227 | struct bgp_synchronize *sync; | |
228 | ||
05c7a1cc QY |
229 | FOREACH_AFI_SAFI (afi, safi) { |
230 | sync = XCALLOC(MTYPE_BGP_SYNCHRONISE, | |
231 | sizeof(struct bgp_synchronize)); | |
a274fef8 DL |
232 | bgp_adv_fifo_init(&sync->update); |
233 | bgp_adv_fifo_init(&sync->withdraw); | |
234 | bgp_adv_fifo_init(&sync->withdraw_low); | |
05c7a1cc | 235 | peer->sync[afi][safi] = sync; |
05c7a1cc | 236 | } |
718e3744 | 237 | } |
238 | ||
d62a17ae | 239 | void bgp_sync_delete(struct peer *peer) |
718e3744 | 240 | { |
d62a17ae | 241 | afi_t afi; |
242 | safi_t safi; | |
243 | ||
05c7a1cc | 244 | FOREACH_AFI_SAFI (afi, safi) { |
0a22ddfb | 245 | XFREE(MTYPE_BGP_SYNCHRONISE, peer->sync[afi][safi]); |
05c7a1cc | 246 | } |
718e3744 | 247 | } |