1 /* Zebra Nexthop Group header.
2 * Copyright (C) 2019 Cumulus Networks, Inc.
6 * This file is part of FRR.
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
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.
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
23 #ifndef __ZEBRA_NHG_H__
24 #define __ZEBRA_NHG_H__
26 #include "lib/nexthop.h"
27 #include "lib/nexthop_group.h"
33 /* This struct is used exclusively for dataplane
34 * interaction via a dataplane context.
36 * It is designed to mimic the netlink nexthop_grp
37 * struct in include/linux/nexthop.h
44 PREDECL_RBTREE_UNIQ(nhg_connected_tree
);
47 * Hashtables containing nhg entries is in `zebra_router`.
49 struct nhg_hash_entry
{
54 /* Time since last update */
57 /* Source protocol - zebra or another daemon */
60 /* zapi instance and session id, for groups from other daemons */
61 uint16_t zapi_instance
;
62 uint32_t zapi_session
;
64 struct nexthop_group nhg
;
66 /* If supported, a mapping of backup nexthops. */
67 struct nhg_backup_info
*backup_info
;
69 /* If this is not a group, it
70 * will be a single nexthop
71 * and must have an interface
73 * Otherwise, this will be null.
75 struct interface
*ifp
;
82 /* Dependency tree for other entries.
83 * For instance a group with two
84 * nexthops will have two dependencies
85 * pointing to those nhg_hash_entries.
87 * Using a rb tree here to make lookups
90 struct nhg_connected_tree_head nhg_depends
, nhg_dependents
;
93 * Is this nexthop group valid, ie all nexthops are fully resolved.
94 * What is fully resolved? It's a nexthop that is either self contained
95 * and correct( ie no recursive pointer ) or a nexthop that is recursively
96 * resolved and correct.
98 #define NEXTHOP_GROUP_VALID (1 << 0)
100 * Has this nexthop group been installed? At this point in time, this
101 * means that the data-plane has been told about this nexthop group
102 * and it's possible usage by a route entry.
104 #define NEXTHOP_GROUP_INSTALLED (1 << 1)
106 * Has the nexthop group been queued to be send to the FIB?
107 * The NEXTHOP_GROUP_VALID flag should also be set by this point.
109 #define NEXTHOP_GROUP_QUEUED (1 << 2)
111 * Is this a nexthop that is recursively resolved?
113 #define NEXTHOP_GROUP_RECURSIVE (1 << 3)
116 * Backup nexthop support - identify groups that are backups for
119 #define NEXTHOP_GROUP_BACKUP (1 << 4)
122 * The NHG has been release by an upper level protocol via the
123 * `zebra_nhg_proto_del()` API.
125 * We use this flag to track this state in case the NHG is still being used
126 * by routes therefore holding their refcnts as well. Otherwise, the NHG will
127 * be removed and uninstalled.
130 #define NEXTHOP_GROUP_PROTO_RELEASED (1 << 5)
133 * Track FPM installation status..
135 #define NEXTHOP_GROUP_FPM (1 << 6)
138 /* Upper 4 bits of the NHG are reserved for indicating the NHG type */
139 #define NHG_ID_TYPE_POS 28
142 NHG_TYPE_L2_NH
, /* NHs in a L2 NHG used as a MAC/FDB dest */
143 NHG_TYPE_L2
, /* L2 NHG used as a MAC/FDB dest */
146 /* Was this one we created, either this session or previously? */
147 #define ZEBRA_NHG_CREATED(NHE) \
148 (((NHE->type) <= ZEBRA_ROUTE_MAX) && (NHE->type != ZEBRA_ROUTE_KERNEL))
150 /* Is this an NHE owned by zebra and not an upper level protocol? */
151 #define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG)
153 #define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER)
156 * Backup nexthops: this is a group object itself, so
157 * that the backup nexthops can use the same code as a normal object.
159 struct nhg_backup_info
{
160 struct nhg_hash_entry
*nhe
;
169 enum nhg_ctx_status
{
178 * Context needed to queue nhg updates on the
190 * This should only ever be ZEBRA_ROUTE_NHG unless we get a a kernel
191 * created nexthop not made by us.
195 /* If its a group array, how many? */
198 /* Its either a single nexthop or an array of ID's */
201 struct nh_grp grp
[MULTIPATH_NUM
];
204 enum nhg_ctx_op_e op
;
205 enum nhg_ctx_status status
;
208 /* Global control to disable use of kernel nexthops, if available. We can't
209 * force the kernel to support nexthop ids, of course, but we can disable
210 * zebra's use of them, for testing e.g. By default, if the kernel supports
211 * nexthop ids, zebra uses them.
213 void zebra_nhg_enable_kernel_nexthops(bool set
);
214 bool zebra_nhg_kernel_nexthops_enabled(void);
216 /* Global control for zebra to only use proto-owned nexthops */
217 void zebra_nhg_set_proto_nexthops_only(bool set
);
218 bool zebra_nhg_proto_nexthops_only(void);
220 /* Global control for use of activated backups for recursive resolution. */
221 void zebra_nhg_set_recursive_use_backups(bool set
);
222 bool zebra_nhg_recursive_use_backups(void);
225 * NHE abstracted tree functions.
226 * Use these where possible instead of direct access.
228 struct nhg_hash_entry
*zebra_nhg_alloc(void);
229 void zebra_nhg_free(struct nhg_hash_entry
*nhe
);
230 /* In order to clear a generic hash, we need a generic api, sigh. */
231 void zebra_nhg_hash_free(void *p
);
233 /* Init an nhe, for use in a hash lookup for example. There's some fuzziness
234 * if the nhe represents only a single nexthop, so we try to capture that
237 void zebra_nhe_init(struct nhg_hash_entry
*nhe
, afi_t afi
,
238 const struct nexthop
*nh
);
241 * Shallow copy of 'orig', into new/allocated nhe.
243 struct nhg_hash_entry
*zebra_nhe_copy(const struct nhg_hash_entry
*orig
,
246 /* Allocate, free backup nexthop info objects */
247 struct nhg_backup_info
*zebra_nhg_backup_alloc(void);
248 void zebra_nhg_backup_free(struct nhg_backup_info
**p
);
250 struct nexthop_group
*zebra_nhg_get_backup_nhg(struct nhg_hash_entry
*nhe
);
252 extern struct nhg_hash_entry
*zebra_nhg_resolve(struct nhg_hash_entry
*nhe
);
254 extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry
*nhe
);
255 extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry
*nhe
);
258 zebra_nhg_dependents_count(const struct nhg_hash_entry
*nhe
);
259 extern bool zebra_nhg_dependents_is_empty(const struct nhg_hash_entry
*nhe
);
261 /* Lookup ID, doesn't create */
262 extern struct nhg_hash_entry
*zebra_nhg_lookup_id(uint32_t id
);
265 extern uint32_t zebra_nhg_hash_key(const void *arg
);
266 extern uint32_t zebra_nhg_id_key(const void *arg
);
268 extern bool zebra_nhg_hash_equal(const void *arg1
, const void *arg2
);
269 extern bool zebra_nhg_hash_id_equal(const void *arg1
, const void *arg2
);
272 * Process a context off of a queue.
273 * Specifically this should be from
274 * the rib meta queue.
276 extern int nhg_ctx_process(struct nhg_ctx
*ctx
);
277 void nhg_ctx_free(struct nhg_ctx
**ctx
);
279 /* Find via kernel nh creation */
280 extern int zebra_nhg_kernel_find(uint32_t id
, struct nexthop
*nh
,
281 struct nh_grp
*grp
, uint8_t count
,
282 vrf_id_t vrf_id
, afi_t afi
, int type
,
285 extern int zebra_nhg_kernel_del(uint32_t id
, vrf_id_t vrf_id
);
287 /* Find an nhe based on a nexthop_group */
288 extern struct nhg_hash_entry
*zebra_nhg_rib_find(uint32_t id
,
289 struct nexthop_group
*nhg
,
290 afi_t rt_afi
, int type
);
292 /* Find an nhe based on a route's nhe, used during route creation */
293 struct nhg_hash_entry
*
294 zebra_nhg_rib_find_nhe(struct nhg_hash_entry
*rt_nhe
, afi_t rt_afi
);
298 * Functions for Add/Del/Replace via protocol NHG creation.
300 * The NHEs will not be hashed. They will only be present in the
301 * ID table and therefore not sharable.
303 * It is the owning protocols job to manage these.
307 * Add NHE. If already exists, Replace.
309 * Returns allocated NHE on success, otherwise NULL.
311 struct nhg_hash_entry
*zebra_nhg_proto_add(uint32_t id
, int type
,
312 uint16_t instance
, uint32_t session
,
313 struct nexthop_group
*nhg
,
319 * Returns deleted NHE on success, otherwise NULL.
321 * Caller must decrement ref with zebra_nhg_decrement_ref() when done.
323 struct nhg_hash_entry
*zebra_nhg_proto_del(uint32_t id
, int type
);
326 * Remove specific by proto NHGs.
328 * Called after client disconnect.
331 unsigned long zebra_nhg_score_proto(int type
);
333 /* Reference counter functions */
334 extern void zebra_nhg_decrement_ref(struct nhg_hash_entry
*nhe
);
335 extern void zebra_nhg_increment_ref(struct nhg_hash_entry
*nhe
);
337 /* Check validity of nhe, if invalid will update dependents as well */
338 extern void zebra_nhg_check_valid(struct nhg_hash_entry
*nhe
);
340 /* Convert nhe depends to a grp context that can be passed around safely */
341 extern uint8_t zebra_nhg_nhe2grp(struct nh_grp
*grp
, struct nhg_hash_entry
*nhe
,
344 /* Dataplane install/uninstall */
345 extern void zebra_nhg_install_kernel(struct nhg_hash_entry
*nhe
);
346 extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry
*nhe
);
348 /* Forward ref of dplane update context type */
349 struct zebra_dplane_ctx
;
350 extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx
*ctx
);
353 /* Sweep the nhg hash tables for old entries on restart */
354 extern void zebra_nhg_sweep_table(struct hash
*hash
);
357 * We are shutting down but the nexthops should be kept
358 * as that -r has been specified and we don't want to delete
359 * the routes unintentionally
361 extern void zebra_nhg_mark_keep(void);
363 /* Nexthop resolution processing */
364 struct route_entry
; /* Forward ref to avoid circular includes */
365 extern int nexthop_active_update(struct route_node
*rn
, struct route_entry
*re
);
367 #ifdef _FRR_ATTRIBUTE_PRINTFRR
368 #pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *)
375 #endif /* __ZEBRA_NHG_H__ */