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