]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_bmp.h
*: auto-convert to SPDX License IDs
[mirror_frr.git] / bgpd / bgp_bmp.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BMP support.
3 * Copyright (C) 2018 Yasuhiro Ohara
4 * Copyright (C) 2019 David Lamparter for NetDEF, Inc.
5 */
6
7 #ifndef _BGP_BMP_H_
8 #define _BGP_BMP_H_
9
10 #include "zebra.h"
11 #include "typesafe.h"
12 #include "pullwr.h"
13 #include "qobj.h"
14 #include "resolver.h"
15
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
33 #define BMP_PeerUp 2
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
56 PREDECL_DLIST(bmp_qlist);
57 PREDECL_HASH(bmp_qhash);
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;
69
70 /* initialized only for L2VPN/EVPN (S)AFIs */
71 struct prefix_rd rd;
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
82 PREDECL_LIST(bmp_mirrorq);
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
102 PREDECL_LIST(bmp_session);
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;
112
113 int socket;
114 char remote[SU_ADDRSTRLEN + 6];
115 struct thread *t_read;
116
117 struct pullwr *pullwr;
118
119 int state;
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;
146 struct bgp_dest *syncrdpos;
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
156 PREDECL_SORTLIST_UNIQ(bmp_actives);
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;
169 char *ifsrc;
170 union sockunion addrsrc;
171
172 struct resolver_query resq;
173
174 unsigned curretry;
175 unsigned addrpos, addrtotal;
176 union sockunion addrs[8];
177 int socket;
178 const char *last_err;
179 struct thread *t_timer, *t_read, *t_write;
180 };
181
182 /* config & state for passive / listening sockets */
183 PREDECL_SORTLIST_UNIQ(bmp_listeners);
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 */
201 PREDECL_SORTLIST_UNIQ(bmp_targets);
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
217 /* only supporting:
218 * - IPv4 / unicast & multicast
219 * - IPv6 / unicast & multicast
220 * - L2VPN / EVPN
221 */
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
237 QOBJ_FIELDS;
238 };
239 DECLARE_QOBJ_TYPE(bmp_targets);
240
241 /* per struct peer * data. Lookup by peer->qobj_node.nid, created on demand,
242 * deleted in peer_backward hook. */
243 PREDECL_HASH(bmp_peerh);
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 */
259 PREDECL_HASH(bmp_bgph);
260
261 #define BMP_PEER_DOWN_NO_RELEVANT_EVENT_CODE 0x00
262
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,
299 };
300
301 DECLARE_MGROUP(BMP);
302
303 #endif /*_BGP_BMP_H_*/