]>
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; | |
185 | struct thread *t_timer, *t_read, *t_write; | |
186 | }; | |
187 | ||
188 | /* config & state for passive / listening sockets */ | |
189 | PREDECL_SORTLIST_UNIQ(bmp_listeners) | |
190 | ||
191 | struct bmp_listener { | |
192 | struct bmp_listeners_item bli; | |
193 | ||
194 | struct bmp_targets *targets; | |
195 | ||
196 | union sockunion addr; | |
197 | int port; | |
198 | ||
199 | struct thread *t_accept; | |
200 | int sock; | |
201 | }; | |
202 | ||
203 | /* bmp_targets - plural since it may contain multiple bmp_listener & | |
204 | * bmp_active items. If they have the same config, BMP session should be | |
205 | * put in the same targets since that's a bit more effective. | |
206 | */ | |
207 | PREDECL_SORTLIST_UNIQ(bmp_targets) | |
208 | ||
209 | struct bmp_targets { | |
210 | struct bmp_targets_item bti; | |
211 | ||
212 | struct bmp_bgp *bmpbgp; | |
213 | struct bgp *bgp; | |
214 | char *name; | |
215 | ||
216 | struct bmp_listeners_head listeners; | |
217 | ||
218 | char *acl_name; | |
219 | char *acl6_name; | |
220 | #define BMP_STAT_DEFAULT_TIMER 60000 | |
221 | int stat_msec; | |
222 | ||
223 | /* only IPv4 & IPv6 / unicast & multicast supported for now */ | |
224 | #define BMP_MON_PREPOLICY (1 << 0) | |
225 | #define BMP_MON_POSTPOLICY (1 << 1) | |
226 | uint8_t afimon[AFI_MAX][SAFI_MAX]; | |
227 | bool mirror; | |
228 | ||
229 | struct bmp_actives_head actives; | |
230 | ||
231 | struct thread *t_stats; | |
232 | struct bmp_session_head sessions; | |
233 | ||
234 | struct bmp_qhash_head updhash; | |
235 | struct bmp_qlist_head updlist; | |
236 | ||
237 | uint64_t cnt_accept, cnt_aclrefused; | |
238 | ||
239 | QOBJ_FIELDS | |
240 | }; | |
241 | DECLARE_QOBJ_TYPE(bmp_targets) | |
242 | ||
243 | /* per struct peer * data. Lookup by peer->qobj_node.nid, created on demand, | |
244 | * deleted in peer_backward hook. */ | |
245 | PREDECL_HASH(bmp_peerh) | |
246 | ||
247 | struct bmp_bgp_peer { | |
248 | struct bmp_peerh_item bpi; | |
249 | ||
250 | uint64_t peerid; | |
251 | /* struct peer *peer; */ | |
252 | ||
253 | uint8_t *open_rx; | |
254 | size_t open_rx_len; | |
255 | ||
256 | uint8_t *open_tx; | |
257 | size_t open_tx_len; | |
258 | }; | |
259 | ||
260 | /* per struct bgp * data */ | |
261 | PREDECL_HASH(bmp_bgph) | |
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, | |
6c29258c YO |
299 | }; |
300 | ||
ed18356f | 301 | DECLARE_MGROUP(BMP) |
6c29258c | 302 | |
6c29258c | 303 | #endif /*_BGP_BMP_H_*/ |