]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_nhg.h
Merge pull request #13395 from LabNConsulting/chopps/mgmtd-debug-flags
[mirror_frr.git] / zebra / zebra_nhg.h
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Zebra Nexthop Group header.
3 * Copyright (C) 2019 Cumulus Networks, Inc.
4 * Donald Sharp
5 * Stephen Worley
6 */
7 #ifndef __ZEBRA_NHG_H__
8 #define __ZEBRA_NHG_H__
9
10 #include "lib/nexthop.h"
11 #include "lib/nexthop_group.h"
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16
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 */
23 struct nh_grp {
24 uint32_t id;
25 uint8_t weight;
26 };
27
28 PREDECL_RBTREE_UNIQ(nhg_connected_tree);
29
30 /*
31 * Hashtables containing nhg entries is in `zebra_router`.
32 */
33 struct nhg_hash_entry {
34 uint32_t id;
35 afi_t afi;
36 vrf_id_t vrf_id;
37
38 /* Time since last update */
39 time_t uptime;
40
41 /* Source protocol - zebra or another daemon */
42 int type;
43
44 /* zapi instance and session id, for groups from other daemons */
45 uint16_t zapi_instance;
46 uint32_t zapi_session;
47
48 struct nexthop_group nhg;
49
50 /* If supported, a mapping of backup nexthops. */
51 struct nhg_backup_info *backup_info;
52
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
61 uint32_t refcnt;
62 uint32_t dplane_ref;
63
64 uint32_t flags;
65
66 /* Dependency trees for other entries.
67 * For instance a group with two
68 * nexthops will have two dependencies
69 * pointing to those nhg_hash_entries.
70 *
71 * Using a rb tree here to make lookups
72 * faster with ID's.
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
89 */
90 struct nhg_connected_tree_head nhg_depends, nhg_dependents;
91
92 struct event *timer;
93
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 */
100 #define NEXTHOP_GROUP_VALID (1 << 0)
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 */
106 #define NEXTHOP_GROUP_INSTALLED (1 << 1)
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 */
111 #define NEXTHOP_GROUP_QUEUED (1 << 2)
112 /*
113 * Is this a nexthop that is recursively resolved?
114 */
115 #define NEXTHOP_GROUP_RECURSIVE (1 << 3)
116
117 /*
118 * Backup nexthop support - identify groups that are backups for
119 * another group.
120 */
121 #define NEXTHOP_GROUP_BACKUP (1 << 4)
122
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
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
143 /*
144 * Track FPM installation status..
145 */
146 #define NEXTHOP_GROUP_FPM (1 << 6)
147 };
148
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
157 /* Was this one we created, either this session or previously? */
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)
163
164 #define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER)
165
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 };
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
180 enum nhg_ctx_status {
181 NHG_CTX_NONE = 0,
182 NHG_CTX_QUEUED,
183 NHG_CTX_REQUEUED,
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;
199
200 /*
201 * This should only ever be ZEBRA_ROUTE_NHG unless we get a a kernel
202 * created nexthop not made by us.
203 */
204 int type;
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
215 struct nhg_resilience resilience;
216 enum nhg_ctx_op_e op;
217 enum nhg_ctx_status status;
218 };
219
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);
227
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
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
236 /**
237 * NHE abstracted tree functions.
238 * Use these where possible instead of direct access.
239 */
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);
244 void zebra_nhg_hash_free_zero_id(struct hash_bucket *b, void *arg);
245
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
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
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
263 struct nexthop_group *zebra_nhg_get_backup_nhg(struct nhg_hash_entry *nhe);
264
265 extern struct nhg_hash_entry *zebra_nhg_resolve(struct nhg_hash_entry *nhe);
266
267 extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry *nhe);
268 extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry *nhe);
269
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);
273
274 /* Lookup ID, doesn't create */
275 extern struct nhg_hash_entry *zebra_nhg_lookup_id(uint32_t id);
276
277 /* Hash functions */
278 extern uint32_t zebra_nhg_hash_key(const void *arg);
279 extern uint32_t zebra_nhg_id_key(const void *arg);
280
281 extern bool zebra_nhg_hash_equal(const void *arg1, const void *arg2);
282 extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2);
283
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);
290 void nhg_ctx_free(struct nhg_ctx **ctx);
291
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,
295 vrf_id_t vrf_id, afi_t afi, int type,
296 int startup,
297 struct nhg_resilience *resilience);
298 /* Del via kernel */
299 extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id);
300
301 /* Find an nhe based on a nexthop_group */
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);
305
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
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 /*
321 * Add NHE. If already exists, Replace.
322 *
323 * Returns allocated NHE on success, otherwise NULL.
324 */
325 struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type,
326 uint16_t instance, uint32_t session,
327 struct nexthop_group *nhg,
328 afi_t afi);
329
330 /*
331 * Del NHE.
332 *
333 * Returns deleted NHE on success, otherwise NULL.
334 *
335 * Caller must decrement ref with zebra_nhg_decrement_ref() when done.
336 */
337 struct nhg_hash_entry *zebra_nhg_proto_del(uint32_t id, int type);
338
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
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);
350
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 */
355 extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
356 int size);
357
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);
361
362 /* Forward ref of dplane update context type */
363 struct zebra_dplane_ctx;
364 extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx);
365
366
367 /* Sweep the nhg hash tables for old entries on restart */
368 extern void zebra_nhg_sweep_table(struct hash *hash);
369
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
377 /* Nexthop resolution processing */
378 struct route_entry; /* Forward ref to avoid circular includes */
379 extern int nexthop_active_update(struct route_node *rn, struct route_entry *re);
380
381 #ifdef _FRR_ATTRIBUTE_PRINTFRR
382 #pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *)
383 #endif
384
385 #ifdef __cplusplus
386 }
387 #endif
388
389 #endif /* __ZEBRA_NHG_H__ */