]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
ad28e79a SW |
2 | /* Zebra Nexthop Group header. |
3 | * Copyright (C) 2019 Cumulus Networks, Inc. | |
4 | * Donald Sharp | |
5 | * Stephen Worley | |
ad28e79a SW |
6 | */ |
7 | #ifndef __ZEBRA_NHG_H__ | |
8 | #define __ZEBRA_NHG_H__ | |
9 | ||
5463ce26 | 10 | #include "lib/nexthop.h" |
69171da2 | 11 | #include "lib/nexthop_group.h" |
ad28e79a | 12 | |
17e38209 RW |
13 | #ifdef __cplusplus |
14 | extern "C" { | |
15 | #endif | |
16 | ||
0c8215cb SW |
17 | /* This struct is used exclusively for dataplane |
18 | * interaction via a dataplane context. | |
19 | * | |
20 | * It is designed to mimic the netlink nexthop_grp | |
21 | * struct in include/linux/nexthop.h | |
22 | */ | |
e22e8001 | 23 | struct nh_grp { |
0c8215cb SW |
24 | uint32_t id; |
25 | uint8_t weight; | |
26 | }; | |
27 | ||
37c6708b | 28 | PREDECL_RBTREE_UNIQ(nhg_connected_tree); |
0c8215cb | 29 | |
53ac1fbb | 30 | /* |
c415d895 | 31 | * Hashtables containing nhg entries is in `zebra_router`. |
53ac1fbb | 32 | */ |
69171da2 | 33 | struct nhg_hash_entry { |
a95b8020 | 34 | uint32_t id; |
77b76fc9 | 35 | afi_t afi; |
69171da2 | 36 | vrf_id_t vrf_id; |
ee94437e | 37 | |
45691de9 SW |
38 | /* Time since last update */ |
39 | time_t uptime; | |
40 | ||
ee94437e | 41 | /* Source protocol - zebra or another daemon */ |
38e40db1 | 42 | int type; |
69171da2 | 43 | |
ee94437e MS |
44 | /* zapi instance and session id, for groups from other daemons */ |
45 | uint16_t zapi_instance; | |
46 | uint32_t zapi_session; | |
47 | ||
c415d895 | 48 | struct nexthop_group nhg; |
69171da2 | 49 | |
1d48702e MS |
50 | /* If supported, a mapping of backup nexthops. */ |
51 | struct nhg_backup_info *backup_info; | |
52 | ||
2614bf87 SW |
53 | /* If this is not a group, it |
54 | * will be a single nexthop | |
55 | * and must have an interface | |
56 | * associated with it. | |
57 | * Otherwise, this will be null. | |
58 | */ | |
59 | struct interface *ifp; | |
60 | ||
69171da2 DS |
61 | uint32_t refcnt; |
62 | uint32_t dplane_ref; | |
c8ee3cdb DS |
63 | |
64 | uint32_t flags; | |
3119f6a1 | 65 | |
5772319e | 66 | /* Dependency trees for other entries. |
3119f6a1 SW |
67 | * For instance a group with two |
68 | * nexthops will have two dependencies | |
69 | * pointing to those nhg_hash_entries. | |
0c8215cb SW |
70 | * |
71 | * Using a rb tree here to make lookups | |
72 | * faster with ID's. | |
5772319e DS |
73 | * |
74 | * nhg_depends the RB tree of entries that this | |
75 | * group contains. | |
76 | * | |
77 | * nhg_dependents the RB tree of entries that | |
78 | * this group is being used by | |
79 | * | |
80 | * NHG id 3 with nexthops id 1/2 | |
81 | * nhg(3)->nhg_depends has 1 and 2 in the tree | |
82 | * nhg(3)->nhg_dependents is empty | |
83 | * | |
84 | * nhg(1)->nhg_depends is empty | |
85 | * nhg(1)->nhg_dependents is 3 in the tree | |
86 | * | |
87 | * nhg(2)->nhg_depends is empty | |
88 | * nhg(3)->nhg_dependents is 3 in the tree | |
3119f6a1 | 89 | */ |
37c6708b | 90 | struct nhg_connected_tree_head nhg_depends, nhg_dependents; |
1d48702e | 91 | |
e6685141 | 92 | struct event *timer; |
35729f38 | 93 | |
c8ee3cdb DS |
94 | /* |
95 | * Is this nexthop group valid, ie all nexthops are fully resolved. | |
96 | * What is fully resolved? It's a nexthop that is either self contained | |
97 | * and correct( ie no recursive pointer ) or a nexthop that is recursively | |
98 | * resolved and correct. | |
99 | */ | |
38e40db1 | 100 | #define NEXTHOP_GROUP_VALID (1 << 0) |
c8ee3cdb DS |
101 | /* |
102 | * Has this nexthop group been installed? At this point in time, this | |
103 | * means that the data-plane has been told about this nexthop group | |
104 | * and it's possible usage by a route entry. | |
105 | */ | |
38e40db1 | 106 | #define NEXTHOP_GROUP_INSTALLED (1 << 1) |
7f6077d0 SW |
107 | /* |
108 | * Has the nexthop group been queued to be send to the FIB? | |
109 | * The NEXTHOP_GROUP_VALID flag should also be set by this point. | |
110 | */ | |
38e40db1 | 111 | #define NEXTHOP_GROUP_QUEUED (1 << 2) |
98cda54a SW |
112 | /* |
113 | * Is this a nexthop that is recursively resolved? | |
114 | */ | |
38e40db1 | 115 | #define NEXTHOP_GROUP_RECURSIVE (1 << 3) |
1d48702e MS |
116 | |
117 | /* | |
118 | * Backup nexthop support - identify groups that are backups for | |
119 | * another group. | |
120 | */ | |
0885b1e3 | 121 | #define NEXTHOP_GROUP_BACKUP (1 << 4) |
1d48702e | 122 | |
8155e8c5 SW |
123 | /* |
124 | * The NHG has been release by an upper level protocol via the | |
125 | * `zebra_nhg_proto_del()` API. | |
126 | * | |
127 | * We use this flag to track this state in case the NHG is still being used | |
128 | * by routes therefore holding their refcnts as well. Otherwise, the NHG will | |
129 | * be removed and uninstalled. | |
130 | * | |
131 | */ | |
132 | #define NEXTHOP_GROUP_PROTO_RELEASED (1 << 5) | |
133 | ||
35729f38 DS |
134 | /* |
135 | * When deleting a NHG notice that it is still installed | |
136 | * and if it is, slightly delay the actual removal to | |
137 | * the future. So that upper level protocols might | |
138 | * be able to take advantage of some NHG's that | |
139 | * are there | |
140 | */ | |
141 | #define NEXTHOP_GROUP_KEEP_AROUND (1 << 6) | |
142 | ||
981ca597 RZ |
143 | /* |
144 | * Track FPM installation status.. | |
145 | */ | |
8155e8c5 | 146 | #define NEXTHOP_GROUP_FPM (1 << 6) |
69171da2 DS |
147 | }; |
148 | ||
4f9bb78e AK |
149 | /* Upper 4 bits of the NHG are reserved for indicating the NHG type */ |
150 | #define NHG_ID_TYPE_POS 28 | |
151 | enum nhg_type { | |
152 | NHG_TYPE_L3 = 0, | |
153 | NHG_TYPE_L2_NH, /* NHs in a L2 NHG used as a MAC/FDB dest */ | |
154 | NHG_TYPE_L2, /* L2 NHG used as a MAC/FDB dest */ | |
155 | }; | |
156 | ||
38e40db1 | 157 | /* Was this one we created, either this session or previously? */ |
0885b1e3 SW |
158 | #define ZEBRA_NHG_CREATED(NHE) \ |
159 | (((NHE->type) <= ZEBRA_ROUTE_MAX) && (NHE->type != ZEBRA_ROUTE_KERNEL)) | |
160 | ||
161 | /* Is this an NHE owned by zebra and not an upper level protocol? */ | |
162 | #define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG) | |
38e40db1 | 163 | |
65f137fe SW |
164 | #define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER) |
165 | ||
1d48702e MS |
166 | /* |
167 | * Backup nexthops: this is a group object itself, so | |
168 | * that the backup nexthops can use the same code as a normal object. | |
169 | */ | |
170 | struct nhg_backup_info { | |
171 | struct nhg_hash_entry *nhe; | |
172 | }; | |
e22e8001 SW |
173 | |
174 | enum nhg_ctx_op_e { | |
175 | NHG_CTX_OP_NONE = 0, | |
176 | NHG_CTX_OP_NEW, | |
177 | NHG_CTX_OP_DEL, | |
178 | }; | |
179 | ||
1b366e63 | 180 | enum nhg_ctx_status { |
e22e8001 SW |
181 | NHG_CTX_NONE = 0, |
182 | NHG_CTX_QUEUED, | |
1b366e63 | 183 | NHG_CTX_REQUEUED, |
e22e8001 SW |
184 | NHG_CTX_SUCCESS, |
185 | NHG_CTX_FAILURE, | |
186 | }; | |
187 | ||
188 | /* | |
189 | * Context needed to queue nhg updates on the | |
190 | * work queue. | |
191 | */ | |
192 | struct nhg_ctx { | |
193 | ||
194 | /* Unique ID */ | |
195 | uint32_t id; | |
196 | ||
197 | vrf_id_t vrf_id; | |
198 | afi_t afi; | |
9b4ab909 | 199 | |
38e40db1 | 200 | /* |
9b4ab909 | 201 | * This should only ever be ZEBRA_ROUTE_NHG unless we get a a kernel |
38e40db1 SW |
202 | * created nexthop not made by us. |
203 | */ | |
204 | int type; | |
e22e8001 SW |
205 | |
206 | /* If its a group array, how many? */ | |
207 | uint8_t count; | |
208 | ||
209 | /* Its either a single nexthop or an array of ID's */ | |
210 | union { | |
211 | struct nexthop nh; | |
212 | struct nh_grp grp[MULTIPATH_NUM]; | |
213 | } u; | |
214 | ||
569e1411 | 215 | struct nhg_resilience resilience; |
e22e8001 | 216 | enum nhg_ctx_op_e op; |
1b366e63 | 217 | enum nhg_ctx_status status; |
e22e8001 SW |
218 | }; |
219 | ||
7c99d51b MS |
220 | /* Global control to disable use of kernel nexthops, if available. We can't |
221 | * force the kernel to support nexthop ids, of course, but we can disable | |
222 | * zebra's use of them, for testing e.g. By default, if the kernel supports | |
223 | * nexthop ids, zebra uses them. | |
224 | */ | |
225 | void zebra_nhg_enable_kernel_nexthops(bool set); | |
226 | bool zebra_nhg_kernel_nexthops_enabled(void); | |
e22e8001 | 227 | |
6c67f41f SW |
228 | /* Global control for zebra to only use proto-owned nexthops */ |
229 | void zebra_nhg_set_proto_nexthops_only(bool set); | |
230 | bool zebra_nhg_proto_nexthops_only(void); | |
231 | ||
aa458838 MS |
232 | /* Global control for use of activated backups for recursive resolution. */ |
233 | void zebra_nhg_set_recursive_use_backups(bool set); | |
234 | bool zebra_nhg_recursive_use_backups(void); | |
235 | ||
fe593b78 SW |
236 | /** |
237 | * NHE abstracted tree functions. | |
1d48702e | 238 | * Use these where possible instead of direct access. |
fe593b78 | 239 | */ |
0eb97b86 MS |
240 | struct nhg_hash_entry *zebra_nhg_alloc(void); |
241 | void zebra_nhg_free(struct nhg_hash_entry *nhe); | |
242 | /* In order to clear a generic hash, we need a generic api, sigh. */ | |
243 | void zebra_nhg_hash_free(void *p); | |
d5795103 | 244 | void zebra_nhg_hash_free_zero_id(struct hash_bucket *b, void *arg); |
0eb97b86 | 245 | |
377e29f7 MS |
246 | /* Init an nhe, for use in a hash lookup for example. There's some fuzziness |
247 | * if the nhe represents only a single nexthop, so we try to capture that | |
248 | * variant also. | |
249 | */ | |
250 | void zebra_nhe_init(struct nhg_hash_entry *nhe, afi_t afi, | |
251 | const struct nexthop *nh); | |
252 | ||
f727646a MS |
253 | /* |
254 | * Shallow copy of 'orig', into new/allocated nhe. | |
255 | */ | |
256 | struct nhg_hash_entry *zebra_nhe_copy(const struct nhg_hash_entry *orig, | |
257 | uint32_t id); | |
258 | ||
1d48702e MS |
259 | /* Allocate, free backup nexthop info objects */ |
260 | struct nhg_backup_info *zebra_nhg_backup_alloc(void); | |
261 | void zebra_nhg_backup_free(struct nhg_backup_info **p); | |
262 | ||
1d48702e MS |
263 | struct nexthop_group *zebra_nhg_get_backup_nhg(struct nhg_hash_entry *nhe); |
264 | ||
98cda54a | 265 | extern struct nhg_hash_entry *zebra_nhg_resolve(struct nhg_hash_entry *nhe); |
98cda54a | 266 | |
fe593b78 | 267 | extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry *nhe); |
0c8215cb | 268 | extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry *nhe); |
5948f013 | 269 | |
fe593b78 SW |
270 | extern unsigned int |
271 | zebra_nhg_dependents_count(const struct nhg_hash_entry *nhe); | |
272 | extern bool zebra_nhg_dependents_is_empty(const struct nhg_hash_entry *nhe); | |
3119f6a1 | 273 | |
5948f013 | 274 | /* Lookup ID, doesn't create */ |
d9f5b2f5 | 275 | extern struct nhg_hash_entry *zebra_nhg_lookup_id(uint32_t id); |
d9f5b2f5 | 276 | |
5948f013 | 277 | /* Hash functions */ |
69171da2 | 278 | extern uint32_t zebra_nhg_hash_key(const void *arg); |
a95b8020 | 279 | extern uint32_t zebra_nhg_id_key(const void *arg); |
69171da2 DS |
280 | |
281 | extern bool zebra_nhg_hash_equal(const void *arg1, const void *arg2); | |
d9f5b2f5 | 282 | extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2); |
69171da2 | 283 | |
e22e8001 SW |
284 | /* |
285 | * Process a context off of a queue. | |
286 | * Specifically this should be from | |
287 | * the rib meta queue. | |
288 | */ | |
289 | extern int nhg_ctx_process(struct nhg_ctx *ctx); | |
04bec7b2 | 290 | void nhg_ctx_free(struct nhg_ctx **ctx); |
85f5e761 | 291 | |
e22e8001 SW |
292 | /* Find via kernel nh creation */ |
293 | extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, | |
294 | struct nh_grp *grp, uint8_t count, | |
38e40db1 | 295 | vrf_id_t vrf_id, afi_t afi, int type, |
569e1411 DS |
296 | int startup, |
297 | struct nhg_resilience *resilience); | |
9a1588c4 | 298 | /* Del via kernel */ |
88cafda7 | 299 | extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id); |
e22e8001 | 300 | |
377e29f7 | 301 | /* Find an nhe based on a nexthop_group */ |
0885b1e3 SW |
302 | extern struct nhg_hash_entry *zebra_nhg_rib_find(uint32_t id, |
303 | struct nexthop_group *nhg, | |
304 | afi_t rt_afi, int type); | |
3057df51 | 305 | |
377e29f7 MS |
306 | /* Find an nhe based on a route's nhe, used during route creation */ |
307 | struct nhg_hash_entry * | |
308 | zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi); | |
309 | ||
0885b1e3 SW |
310 | |
311 | /** | |
312 | * Functions for Add/Del/Replace via protocol NHG creation. | |
313 | * | |
314 | * The NHEs will not be hashed. They will only be present in the | |
315 | * ID table and therefore not sharable. | |
316 | * | |
317 | * It is the owning protocols job to manage these. | |
318 | */ | |
319 | ||
320 | /* | |
2d8a9c54 | 321 | * Add NHE. If already exists, Replace. |
0885b1e3 SW |
322 | * |
323 | * Returns allocated NHE on success, otherwise NULL. | |
324 | */ | |
325 | struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, | |
ee94437e | 326 | uint16_t instance, uint32_t session, |
0885b1e3 SW |
327 | struct nexthop_group *nhg, |
328 | afi_t afi); | |
329 | ||
0885b1e3 SW |
330 | /* |
331 | * Del NHE. | |
332 | * | |
333 | * Returns deleted NHE on success, otherwise NULL. | |
334 | * | |
1f655680 | 335 | * Caller must decrement ref with zebra_nhg_decrement_ref() when done. |
0885b1e3 | 336 | */ |
aaa42e05 | 337 | struct nhg_hash_entry *zebra_nhg_proto_del(uint32_t id, int type); |
0885b1e3 | 338 | |
24db1a7b SW |
339 | /* |
340 | * Remove specific by proto NHGs. | |
341 | * | |
342 | * Called after client disconnect. | |
343 | * | |
344 | */ | |
345 | unsigned long zebra_nhg_score_proto(int type); | |
346 | ||
5948f013 SW |
347 | /* Reference counter functions */ |
348 | extern void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe); | |
349 | extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe); | |
144a1b34 | 350 | |
5948f013 SW |
351 | /* Check validity of nhe, if invalid will update dependents as well */ |
352 | extern void zebra_nhg_check_valid(struct nhg_hash_entry *nhe); | |
353 | ||
354 | /* Convert nhe depends to a grp context that can be passed around safely */ | |
8dbc800f SW |
355 | extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, |
356 | int size); | |
98cda54a | 357 | |
5948f013 SW |
358 | /* Dataplane install/uninstall */ |
359 | extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe); | |
360 | extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe); | |
147bad16 | 361 | |
0c8215cb SW |
362 | /* Forward ref of dplane update context type */ |
363 | struct zebra_dplane_ctx; | |
5948f013 SW |
364 | extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx); |
365 | ||
38e40db1 | 366 | |
b1b07ef5 | 367 | /* Sweep the nhg hash tables for old entries on restart */ |
5948f013 SW |
368 | extern void zebra_nhg_sweep_table(struct hash *hash); |
369 | ||
b1b07ef5 DS |
370 | /* |
371 | * We are shutting down but the nexthops should be kept | |
372 | * as that -r has been specified and we don't want to delete | |
373 | * the routes unintentionally | |
374 | */ | |
375 | extern void zebra_nhg_mark_keep(void); | |
376 | ||
5948f013 | 377 | /* Nexthop resolution processing */ |
5463ce26 | 378 | struct route_entry; /* Forward ref to avoid circular includes */ |
5948f013 | 379 | extern int nexthop_active_update(struct route_node *rn, struct route_entry *re); |
7c99d51b | 380 | |
cc75cbea DS |
381 | #ifdef _FRR_ATTRIBUTE_PRINTFRR |
382 | #pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *) | |
383 | #endif | |
384 | ||
17e38209 RW |
385 | #ifdef __cplusplus |
386 | } | |
387 | #endif | |
388 | ||
7c99d51b | 389 | #endif /* __ZEBRA_NHG_H__ */ |