]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
6c29258c YO |
2 | /* BMP support. |
3 | * Copyright (C) 2018 Yasuhiro Ohara | |
ed18356f | 4 | * Copyright (C) 2019 David Lamparter for NetDEF, Inc. |
6c29258c YO |
5 | */ |
6 | ||
7 | #ifndef _BGP_BMP_H_ | |
8 | #define _BGP_BMP_H_ | |
9 | ||
ed18356f DL |
10 | #include "zebra.h" |
11 | #include "typesafe.h" | |
12 | #include "pullwr.h" | |
13 | #include "qobj.h" | |
14 | #include "resolver.h" | |
15 | ||
6c29258c YO |
16 | #define BMP_VERSION_3 3 |
17 | ||
18 | #define BMP_LENGTH_POS 1 | |
19 | ||
20 | /* BMP message types */ | |
21 | #define BMP_TYPE_ROUTE_MONITORING 0 | |
22 | #define BMP_TYPE_STATISTICS_REPORT 1 | |
23 | #define BMP_TYPE_PEER_DOWN_NOTIFICATION 2 | |
24 | #define BMP_TYPE_PEER_UP_NOTIFICATION 3 | |
25 | #define BMP_TYPE_INITIATION 4 | |
26 | #define BMP_TYPE_TERMINATION 5 | |
27 | #define BMP_TYPE_ROUTE_MIRRORING 6 | |
28 | ||
29 | #define BMP_READ_BUFSIZ 1024 | |
30 | ||
31 | /* bmp->state */ | |
32 | #define BMP_None 0 | |
6c29258c | 33 | #define BMP_PeerUp 2 |
ed18356f DL |
34 | #define BMP_Run 3 |
35 | ||
36 | /* This one is for BMP Route Monitoring messages, i.e. delivering updates | |
37 | * in somewhat processed (as opposed to fully raw, see mirroring below) form. | |
38 | * RFC explicitly says that we can skip old updates if we haven't sent them out | |
39 | * yet and another newer update for the same prefix arrives. | |
40 | * | |
41 | * So, at most one of these can exist for each (bgp, afi, safi, prefix, peerid) | |
42 | * tuple; if some prefix is "re-added" to the queue, the existing entry is | |
43 | * instead moved to the end of the queue. This ensures that the queue size is | |
44 | * bounded by the BGP table size. | |
45 | * | |
46 | * bmp_qlist is the queue itself while bmp_qhash is used to efficiently check | |
47 | * whether a tuple is already on the list. The queue is maintained per | |
48 | * bmp_target. | |
49 | * | |
50 | * refcount = number of "struct bmp *" whose queue position is before this | |
51 | * entry, i.e. number of BMP sessions where we still want to send this out. | |
52 | * Decremented on send so we know when we're done with an entry (i.e. this | |
53 | * always happens from the front of the queue.) | |
54 | */ | |
55 | ||
960b9a53 DL |
56 | PREDECL_DLIST(bmp_qlist); |
57 | PREDECL_HASH(bmp_qhash); | |
ed18356f DL |
58 | |
59 | struct bmp_queue_entry { | |
60 | struct bmp_qlist_item bli; | |
61 | struct bmp_qhash_item bhi; | |
62 | ||
63 | struct prefix p; | |
64 | uint64_t peerid; | |
65 | afi_t afi; | |
66 | safi_t safi; | |
67 | ||
68 | size_t refcount; | |
87102aa0 | 69 | |
70 | /* initialized only for L2VPN/EVPN (S)AFIs */ | |
71 | struct prefix_rd rd; | |
ed18356f DL |
72 | }; |
73 | ||
74 | /* This is for BMP Route Mirroring, which feeds fully raw BGP PDUs out to BMP | |
75 | * receivers. So, this goes directly off packet RX/TX handling instead of | |
76 | * grabbing bits from tables. | |
77 | * | |
78 | * There is *one* queue for each "struct bgp *" where we throw everything on, | |
79 | * with a size limit. Refcount works the same as for monitoring above. | |
80 | */ | |
81 | ||
960b9a53 | 82 | PREDECL_LIST(bmp_mirrorq); |
ed18356f DL |
83 | |
84 | struct bmp_mirrorq { | |
85 | struct bmp_mirrorq_item bmi; | |
86 | ||
87 | size_t refcount; | |
88 | uint64_t peerid; | |
89 | struct timeval tv; | |
90 | ||
91 | size_t len; | |
92 | uint8_t data[0]; | |
93 | }; | |
94 | ||
95 | enum { | |
96 | BMP_AFI_INACTIVE = 0, | |
97 | BMP_AFI_NEEDSYNC, | |
98 | BMP_AFI_SYNC, | |
99 | BMP_AFI_LIVE, | |
100 | }; | |
101 | ||
960b9a53 | 102 | PREDECL_LIST(bmp_session); |
ed18356f DL |
103 | |
104 | struct bmp_active; | |
105 | struct bmp_targets; | |
106 | ||
107 | /* an established BMP session to a peer */ | |
108 | struct bmp { | |
109 | struct bmp_session_item bsi; | |
110 | struct bmp_targets *targets; | |
111 | struct bmp_active *active; | |
6c29258c | 112 | |
6c29258c | 113 | int socket; |
ed18356f | 114 | char remote[SU_ADDRSTRLEN + 6]; |
6c29258c | 115 | struct thread *t_read; |
ed18356f DL |
116 | |
117 | struct pullwr *pullwr; | |
6c29258c YO |
118 | |
119 | int state; | |
ed18356f DL |
120 | |
121 | /* queue positions must remain synced with refcounts in the items. | |
122 | * Whenever appending a queue item, we need to know the correct number | |
123 | * of "struct bmp *" that want it, and when moving these positions | |
124 | * ahead we need to make sure that refcount is decremented. Also, on | |
125 | * disconnects we need to walk the queue and drop our reference. | |
126 | */ | |
127 | struct bmp_queue_entry *queuepos; | |
128 | struct bmp_mirrorq *mirrorpos; | |
129 | bool mirror_lost; | |
130 | ||
131 | /* enum BMP_AFI_* */ | |
132 | uint8_t afistate[AFI_MAX][SAFI_MAX]; | |
133 | ||
134 | /* counters for the various BMP packet types */ | |
135 | uint64_t cnt_update, cnt_mirror; | |
136 | /* number of times this peer wasn't fast enough in consuming the | |
137 | * mirror queue | |
138 | */ | |
139 | uint64_t cnt_mirror_overruns; | |
140 | struct timeval t_up; | |
141 | ||
142 | /* synchronization / startup works by repeatedly finding the next | |
143 | * table entry, the sync* fields note down what we sent last | |
144 | */ | |
145 | struct prefix syncpos; | |
09319b4e | 146 | struct bgp_dest *syncrdpos; |
ed18356f DL |
147 | uint64_t syncpeerid; |
148 | afi_t syncafi; | |
149 | safi_t syncsafi; | |
150 | }; | |
151 | ||
152 | /* config & state for an active outbound connection. When the connection | |
153 | * succeeds, "bmp" is set up. | |
154 | */ | |
155 | ||
960b9a53 | 156 | PREDECL_SORTLIST_UNIQ(bmp_actives); |
ed18356f DL |
157 | |
158 | #define BMP_DFLT_MINRETRY 30000 | |
159 | #define BMP_DFLT_MAXRETRY 720000 | |
160 | ||
161 | struct bmp_active { | |
162 | struct bmp_actives_item bai; | |
163 | struct bmp_targets *targets; | |
164 | struct bmp *bmp; | |
165 | ||
166 | char *hostname; | |
167 | int port; | |
168 | unsigned minretry, maxretry; | |
09f267ec FD |
169 | char *ifsrc; |
170 | union sockunion addrsrc; | |
ed18356f DL |
171 | |
172 | struct resolver_query resq; | |
173 | ||
174 | unsigned curretry; | |
175 | unsigned addrpos, addrtotal; | |
176 | union sockunion addrs[8]; | |
177 | int socket; | |
3286ca07 | 178 | const char *last_err; |
ed18356f DL |
179 | struct thread *t_timer, *t_read, *t_write; |
180 | }; | |
181 | ||
182 | /* config & state for passive / listening sockets */ | |
960b9a53 | 183 | PREDECL_SORTLIST_UNIQ(bmp_listeners); |
ed18356f DL |
184 | |
185 | struct bmp_listener { | |
186 | struct bmp_listeners_item bli; | |
187 | ||
188 | struct bmp_targets *targets; | |
189 | ||
190 | union sockunion addr; | |
191 | int port; | |
192 | ||
193 | struct thread *t_accept; | |
194 | int sock; | |
195 | }; | |
196 | ||
197 | /* bmp_targets - plural since it may contain multiple bmp_listener & | |
198 | * bmp_active items. If they have the same config, BMP session should be | |
199 | * put in the same targets since that's a bit more effective. | |
200 | */ | |
960b9a53 | 201 | PREDECL_SORTLIST_UNIQ(bmp_targets); |
ed18356f DL |
202 | |
203 | struct bmp_targets { | |
204 | struct bmp_targets_item bti; | |
205 | ||
206 | struct bmp_bgp *bmpbgp; | |
207 | struct bgp *bgp; | |
208 | char *name; | |
209 | ||
210 | struct bmp_listeners_head listeners; | |
211 | ||
212 | char *acl_name; | |
213 | char *acl6_name; | |
214 | #define BMP_STAT_DEFAULT_TIMER 60000 | |
215 | int stat_msec; | |
216 | ||
87102aa0 | 217 | /* only supporting: |
218 | * - IPv4 / unicast & multicast | |
219 | * - IPv6 / unicast & multicast | |
220 | * - L2VPN / EVPN | |
221 | */ | |
ed18356f DL |
222 | #define BMP_MON_PREPOLICY (1 << 0) |
223 | #define BMP_MON_POSTPOLICY (1 << 1) | |
224 | uint8_t afimon[AFI_MAX][SAFI_MAX]; | |
225 | bool mirror; | |
226 | ||
227 | struct bmp_actives_head actives; | |
228 | ||
229 | struct thread *t_stats; | |
230 | struct bmp_session_head sessions; | |
231 | ||
232 | struct bmp_qhash_head updhash; | |
233 | struct bmp_qlist_head updlist; | |
234 | ||
235 | uint64_t cnt_accept, cnt_aclrefused; | |
236 | ||
96244aca | 237 | QOBJ_FIELDS; |
ed18356f | 238 | }; |
96244aca | 239 | DECLARE_QOBJ_TYPE(bmp_targets); |
ed18356f DL |
240 | |
241 | /* per struct peer * data. Lookup by peer->qobj_node.nid, created on demand, | |
242 | * deleted in peer_backward hook. */ | |
960b9a53 | 243 | PREDECL_HASH(bmp_peerh); |
ed18356f DL |
244 | |
245 | struct bmp_bgp_peer { | |
246 | struct bmp_peerh_item bpi; | |
247 | ||
248 | uint64_t peerid; | |
249 | /* struct peer *peer; */ | |
250 | ||
251 | uint8_t *open_rx; | |
252 | size_t open_rx_len; | |
253 | ||
254 | uint8_t *open_tx; | |
255 | size_t open_tx_len; | |
256 | }; | |
257 | ||
258 | /* per struct bgp * data */ | |
960b9a53 | 259 | PREDECL_HASH(bmp_bgph); |
ed18356f | 260 | |
21e8caa2 QY |
261 | #define BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE 0x00 |
262 | ||
ed18356f DL |
263 | struct bmp_bgp { |
264 | struct bmp_bgph_item bbi; | |
265 | ||
266 | struct bgp *bgp; | |
267 | struct bmp_targets_head targets; | |
268 | ||
269 | struct bmp_mirrorq_head mirrorq; | |
270 | size_t mirror_qsize, mirror_qsizemax; | |
271 | ||
272 | size_t mirror_qsizelimit; | |
273 | }; | |
274 | ||
275 | enum { | |
276 | BMP_PEERDOWN_LOCAL_NOTIFY = 1, | |
277 | BMP_PEERDOWN_LOCAL_FSM = 2, | |
278 | BMP_PEERDOWN_REMOTE_NOTIFY = 3, | |
279 | BMP_PEERDOWN_REMOTE_CLOSE = 4, | |
280 | BMP_PEERDOWN_ENDMONITOR = 5, | |
281 | }; | |
282 | ||
283 | enum { | |
284 | BMP_STATS_PFX_REJECTED = 0, | |
285 | BMP_STATS_PFX_DUP_ADV = 1, | |
286 | BMP_STATS_PFX_DUP_WITHDRAW = 2, | |
287 | BMP_STATS_UPD_LOOP_CLUSTER = 3, | |
288 | BMP_STATS_UPD_LOOP_ASPATH = 4, | |
289 | BMP_STATS_UPD_LOOP_ORIGINATOR = 5, | |
290 | BMP_STATS_UPD_LOOP_CONFED = 6, | |
291 | BMP_STATS_SIZE_ADJ_RIB_IN = 7, | |
292 | BMP_STATS_SIZE_LOC_RIB = 8, | |
293 | BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, | |
294 | BMP_STATS_SIZE_LOC_RIB_IN_SAFI = 10, | |
295 | BMP_STATS_UPD_7606_WITHDRAW = 11, | |
296 | BMP_STATS_PFX_7606_WITHDRAW = 12, | |
297 | BMP_STATS_UPD_DUP = 13, | |
298 | BMP_STATS_FRR_NH_INVALID = 65531, | |
6c29258c YO |
299 | }; |
300 | ||
bf8d3d6a | 301 | DECLARE_MGROUP(BMP); |
6c29258c | 302 | |
6c29258c | 303 | #endif /*_BGP_BMP_H_*/ |