]>
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; | |
82 | }; | |
83 | ||
84 | /* This is for BMP Route Mirroring, which feeds fully raw BGP PDUs out to BMP | |
85 | * receivers. So, this goes directly off packet RX/TX handling instead of | |
86 | * grabbing bits from tables. | |
87 | * | |
88 | * There is *one* queue for each "struct bgp *" where we throw everything on, | |
89 | * with a size limit. Refcount works the same as for monitoring above. | |
90 | */ | |
91 | ||
92 | PREDECL_LIST(bmp_mirrorq) | |
93 | ||
94 | struct bmp_mirrorq { | |
95 | struct bmp_mirrorq_item bmi; | |
96 | ||
97 | size_t refcount; | |
98 | uint64_t peerid; | |
99 | struct timeval tv; | |
100 | ||
101 | size_t len; | |
102 | uint8_t data[0]; | |
103 | }; | |
104 | ||
105 | enum { | |
106 | BMP_AFI_INACTIVE = 0, | |
107 | BMP_AFI_NEEDSYNC, | |
108 | BMP_AFI_SYNC, | |
109 | BMP_AFI_LIVE, | |
110 | }; | |
111 | ||
112 | PREDECL_LIST(bmp_session) | |
113 | ||
114 | struct bmp_active; | |
115 | struct bmp_targets; | |
116 | ||
117 | /* an established BMP session to a peer */ | |
118 | struct bmp { | |
119 | struct bmp_session_item bsi; | |
120 | struct bmp_targets *targets; | |
121 | struct bmp_active *active; | |
6c29258c | 122 | |
6c29258c | 123 | int socket; |
ed18356f | 124 | char remote[SU_ADDRSTRLEN + 6]; |
6c29258c | 125 | struct thread *t_read; |
ed18356f DL |
126 | |
127 | struct pullwr *pullwr; | |
6c29258c YO |
128 | |
129 | int state; | |
ed18356f DL |
130 | |
131 | /* queue positions must remain synced with refcounts in the items. | |
132 | * Whenever appending a queue item, we need to know the correct number | |
133 | * of "struct bmp *" that want it, and when moving these positions | |
134 | * ahead we need to make sure that refcount is decremented. Also, on | |
135 | * disconnects we need to walk the queue and drop our reference. | |
136 | */ | |
137 | struct bmp_queue_entry *queuepos; | |
138 | struct bmp_mirrorq *mirrorpos; | |
139 | bool mirror_lost; | |
140 | ||
141 | /* enum BMP_AFI_* */ | |
142 | uint8_t afistate[AFI_MAX][SAFI_MAX]; | |
143 | ||
144 | /* counters for the various BMP packet types */ | |
145 | uint64_t cnt_update, cnt_mirror; | |
146 | /* number of times this peer wasn't fast enough in consuming the | |
147 | * mirror queue | |
148 | */ | |
149 | uint64_t cnt_mirror_overruns; | |
150 | struct timeval t_up; | |
151 | ||
152 | /* synchronization / startup works by repeatedly finding the next | |
153 | * table entry, the sync* fields note down what we sent last | |
154 | */ | |
155 | struct prefix syncpos; | |
156 | uint64_t syncpeerid; | |
157 | afi_t syncafi; | |
158 | safi_t syncsafi; | |
159 | }; | |
160 | ||
161 | /* config & state for an active outbound connection. When the connection | |
162 | * succeeds, "bmp" is set up. | |
163 | */ | |
164 | ||
165 | PREDECL_SORTLIST_UNIQ(bmp_actives) | |
166 | ||
167 | #define BMP_DFLT_MINRETRY 30000 | |
168 | #define BMP_DFLT_MAXRETRY 720000 | |
169 | ||
170 | struct bmp_active { | |
171 | struct bmp_actives_item bai; | |
172 | struct bmp_targets *targets; | |
173 | struct bmp *bmp; | |
174 | ||
175 | char *hostname; | |
176 | int port; | |
177 | unsigned minretry, maxretry; | |
178 | ||
179 | struct resolver_query resq; | |
180 | ||
181 | unsigned curretry; | |
182 | unsigned addrpos, addrtotal; | |
183 | union sockunion addrs[8]; | |
184 | int socket; | |
3286ca07 | 185 | const char *last_err; |
ed18356f DL |
186 | struct thread *t_timer, *t_read, *t_write; |
187 | }; | |
188 | ||
189 | /* config & state for passive / listening sockets */ | |
190 | PREDECL_SORTLIST_UNIQ(bmp_listeners) | |
191 | ||
192 | struct bmp_listener { | |
193 | struct bmp_listeners_item bli; | |
194 | ||
195 | struct bmp_targets *targets; | |
196 | ||
197 | union sockunion addr; | |
198 | int port; | |
199 | ||
200 | struct thread *t_accept; | |
201 | int sock; | |
202 | }; | |
203 | ||
204 | /* bmp_targets - plural since it may contain multiple bmp_listener & | |
205 | * bmp_active items. If they have the same config, BMP session should be | |
206 | * put in the same targets since that's a bit more effective. | |
207 | */ | |
208 | PREDECL_SORTLIST_UNIQ(bmp_targets) | |
209 | ||
210 | struct bmp_targets { | |
211 | struct bmp_targets_item bti; | |
212 | ||
213 | struct bmp_bgp *bmpbgp; | |
214 | struct bgp *bgp; | |
215 | char *name; | |
216 | ||
217 | struct bmp_listeners_head listeners; | |
218 | ||
219 | char *acl_name; | |
220 | char *acl6_name; | |
221 | #define BMP_STAT_DEFAULT_TIMER 60000 | |
222 | int stat_msec; | |
223 | ||
224 | /* only IPv4 & IPv6 / unicast & multicast supported for now */ | |
225 | #define BMP_MON_PREPOLICY (1 << 0) | |
226 | #define BMP_MON_POSTPOLICY (1 << 1) | |
227 | uint8_t afimon[AFI_MAX][SAFI_MAX]; | |
228 | bool mirror; | |
229 | ||
230 | struct bmp_actives_head actives; | |
231 | ||
232 | struct thread *t_stats; | |
233 | struct bmp_session_head sessions; | |
234 | ||
235 | struct bmp_qhash_head updhash; | |
236 | struct bmp_qlist_head updlist; | |
237 | ||
238 | uint64_t cnt_accept, cnt_aclrefused; | |
239 | ||
240 | QOBJ_FIELDS | |
241 | }; | |
242 | DECLARE_QOBJ_TYPE(bmp_targets) | |
243 | ||
244 | /* per struct peer * data. Lookup by peer->qobj_node.nid, created on demand, | |
245 | * deleted in peer_backward hook. */ | |
246 | PREDECL_HASH(bmp_peerh) | |
247 | ||
248 | struct bmp_bgp_peer { | |
249 | struct bmp_peerh_item bpi; | |
250 | ||
251 | uint64_t peerid; | |
252 | /* struct peer *peer; */ | |
253 | ||
254 | uint8_t *open_rx; | |
255 | size_t open_rx_len; | |
256 | ||
257 | uint8_t *open_tx; | |
258 | size_t open_tx_len; | |
259 | }; | |
260 | ||
261 | /* per struct bgp * data */ | |
262 | PREDECL_HASH(bmp_bgph) | |
263 | ||
264 | struct bmp_bgp { | |
265 | struct bmp_bgph_item bbi; | |
266 | ||
267 | struct bgp *bgp; | |
268 | struct bmp_targets_head targets; | |
269 | ||
270 | struct bmp_mirrorq_head mirrorq; | |
271 | size_t mirror_qsize, mirror_qsizemax; | |
272 | ||
273 | size_t mirror_qsizelimit; | |
274 | }; | |
275 | ||
276 | enum { | |
277 | BMP_PEERDOWN_LOCAL_NOTIFY = 1, | |
278 | BMP_PEERDOWN_LOCAL_FSM = 2, | |
279 | BMP_PEERDOWN_REMOTE_NOTIFY = 3, | |
280 | BMP_PEERDOWN_REMOTE_CLOSE = 4, | |
281 | BMP_PEERDOWN_ENDMONITOR = 5, | |
282 | }; | |
283 | ||
284 | enum { | |
285 | BMP_STATS_PFX_REJECTED = 0, | |
286 | BMP_STATS_PFX_DUP_ADV = 1, | |
287 | BMP_STATS_PFX_DUP_WITHDRAW = 2, | |
288 | BMP_STATS_UPD_LOOP_CLUSTER = 3, | |
289 | BMP_STATS_UPD_LOOP_ASPATH = 4, | |
290 | BMP_STATS_UPD_LOOP_ORIGINATOR = 5, | |
291 | BMP_STATS_UPD_LOOP_CONFED = 6, | |
292 | BMP_STATS_SIZE_ADJ_RIB_IN = 7, | |
293 | BMP_STATS_SIZE_LOC_RIB = 8, | |
294 | BMP_STATS_SIZE_ADJ_RIB_IN_SAFI = 9, | |
295 | BMP_STATS_SIZE_LOC_RIB_IN_SAFI = 10, | |
296 | BMP_STATS_UPD_7606_WITHDRAW = 11, | |
297 | BMP_STATS_PFX_7606_WITHDRAW = 12, | |
298 | BMP_STATS_UPD_DUP = 13, | |
299 | BMP_STATS_FRR_NH_INVALID = 65531, | |
6c29258c YO |
300 | }; |
301 | ||
ed18356f | 302 | DECLARE_MGROUP(BMP) |
6c29258c | 303 | |
6c29258c | 304 | #endif /*_BGP_BMP_H_*/ |