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"
29 /* This struct is used exclusively for dataplane
30 * interaction via a dataplane context.
32 * It is designed to mimic the netlink nexthop_grp
33 * struct in include/linux/nexthop.h
40 PREDECL_RBTREE_UNIQ(nhg_connected_tree
);
43 * Hashtables contiaining entries found in `zebra_router`.
46 struct nhg_hash_entry
{
52 struct nexthop_group
*nhg
;
54 /* If this is not a group, it
55 * will be a single nexthop
56 * and must have an interface
58 * Otherwise, this will be null.
60 struct interface
*ifp
;
67 /* Dependency tree for other entries.
68 * For instance a group with two
69 * nexthops will have two dependencies
70 * pointing to those nhg_hash_entries.
72 * Using a rb tree here to make lookups
75 struct nhg_connected_tree_head nhg_depends
, nhg_dependents
;
77 * Is this nexthop group valid, ie all nexthops are fully resolved.
78 * What is fully resolved? It's a nexthop that is either self contained
79 * and correct( ie no recursive pointer ) or a nexthop that is recursively
80 * resolved and correct.
82 #define NEXTHOP_GROUP_VALID (1 << 0)
84 * Has this nexthop group been installed? At this point in time, this
85 * means that the data-plane has been told about this nexthop group
86 * and it's possible usage by a route entry.
88 #define NEXTHOP_GROUP_INSTALLED (1 << 1)
90 * Has the nexthop group been queued to be send to the FIB?
91 * The NEXTHOP_GROUP_VALID flag should also be set by this point.
93 #define NEXTHOP_GROUP_QUEUED (1 << 2)
95 * Is this a nexthop that is recursively resolved?
97 #define NEXTHOP_GROUP_RECURSIVE (1 << 3)
99 * This is a nexthop group we got from the kernel, it is identical to
100 * one we already have. (The kernel allows duplicate nexthops, we don't
101 * since we hash on them). We are only tracking it in our ID table,
102 * it is unusable by our created routes but may be used by routes we get
103 * from the kernel. Therefore, it is unhashable.
105 #define NEXTHOP_GROUP_UNHASHABLE (1 << 4)
108 /* Was this one we created, either this session or previously? */
109 #define ZEBRA_NHG_CREATED(NHE) ((NHE->type) == ZEBRA_ROUTE_NHG)
118 enum nhg_ctx_status
{
127 * Context needed to queue nhg updates on the
138 * This should only every be ZEBRA_ROUTE_NHG unless we get a a kernel
139 * created nexthop not made by us.
143 /* If its a group array, how many? */
146 /* Its either a single nexthop or an array of ID's */
149 struct nh_grp grp
[MULTIPATH_NUM
];
152 enum nhg_ctx_op_e op
;
153 enum nhg_ctx_status status
;
158 * NHE abstracted tree functions.
159 * Use these where possible instead of the direct ones access ones.
161 struct nhg_hash_entry
*zebra_nhg_alloc(void);
162 void zebra_nhg_free(struct nhg_hash_entry
*nhe
);
163 /* In order to clear a generic hash, we need a generic api, sigh. */
164 void zebra_nhg_hash_free(void *p
);
166 extern struct nhg_hash_entry
*zebra_nhg_resolve(struct nhg_hash_entry
*nhe
);
168 extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry
*nhe
);
169 extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry
*nhe
);
172 zebra_nhg_dependents_count(const struct nhg_hash_entry
*nhe
);
173 extern bool zebra_nhg_dependents_is_empty(const struct nhg_hash_entry
*nhe
);
175 /* Lookup ID, doesn't create */
176 extern struct nhg_hash_entry
*zebra_nhg_lookup_id(uint32_t id
);
179 extern uint32_t zebra_nhg_hash_key(const void *arg
);
180 extern uint32_t zebra_nhg_id_key(const void *arg
);
182 extern bool zebra_nhg_hash_equal(const void *arg1
, const void *arg2
);
183 extern bool zebra_nhg_hash_id_equal(const void *arg1
, const void *arg2
);
186 * Process a context off of a queue.
187 * Specifically this should be from
188 * the rib meta queue.
190 extern int nhg_ctx_process(struct nhg_ctx
*ctx
);
192 /* Find via kernel nh creation */
193 extern int zebra_nhg_kernel_find(uint32_t id
, struct nexthop
*nh
,
194 struct nh_grp
*grp
, uint8_t count
,
195 vrf_id_t vrf_id
, afi_t afi
, int type
,
198 extern int zebra_nhg_kernel_del(uint32_t id
);
200 /* Find via route creation */
201 extern struct nhg_hash_entry
*
202 zebra_nhg_rib_find(uint32_t id
, struct nexthop_group
*nhg
, afi_t rt_afi
);
204 /* Reference counter functions */
205 extern void zebra_nhg_decrement_ref(struct nhg_hash_entry
*nhe
);
206 extern void zebra_nhg_increment_ref(struct nhg_hash_entry
*nhe
);
208 /* Check validity of nhe, if invalid will update dependents as well */
209 extern void zebra_nhg_check_valid(struct nhg_hash_entry
*nhe
);
211 /* Convert nhe depends to a grp context that can be passed around safely */
212 extern uint8_t zebra_nhg_nhe2grp(struct nh_grp
*grp
, struct nhg_hash_entry
*nhe
,
215 /* Dataplane install/uninstall */
216 extern void zebra_nhg_install_kernel(struct nhg_hash_entry
*nhe
);
217 extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry
*nhe
);
219 /* Forward ref of dplane update context type */
220 struct zebra_dplane_ctx
;
221 extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx
*ctx
);
224 /* Sweet the nhg hash tables for old entries on restart */
225 extern void zebra_nhg_sweep_table(struct hash
*hash
);
227 /* Nexthop resolution processing */
228 struct route_entry
; /* Forward ref to avoid circular includes */
229 extern int nexthop_active_update(struct route_node
*rn
, struct route_entry
*re
);