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