]> git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_nhg.h
Merge pull request #5451 from opensourcerouting/rcu-log
[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 /* This struct is used exclusively for dataplane
30 * interaction via a dataplane context.
31 *
32 * It is designed to mimic the netlink nexthop_grp
33 * struct in include/linux/nexthop.h
34 */
35 struct nh_grp {
36 uint32_t id;
37 uint8_t weight;
38 };
39
40 PREDECL_RBTREE_UNIQ(nhg_connected_tree);
41
42 /*
43 * Hashtables containing nhg entries is in `zebra_router`.
44 */
45 struct nhg_hash_entry {
46 uint32_t id;
47 afi_t afi;
48 vrf_id_t vrf_id;
49 int type;
50
51 struct nexthop_group nhg;
52
53 /* If supported, a mapping of backup nexthops. */
54 struct nhg_backup_info *backup_info;
55
56 /* If this is not a group, it
57 * will be a single nexthop
58 * and must have an interface
59 * associated with it.
60 * Otherwise, this will be null.
61 */
62 struct interface *ifp;
63
64 uint32_t refcnt;
65 uint32_t dplane_ref;
66
67 uint32_t flags;
68
69 /* Dependency tree for other entries.
70 * For instance a group with two
71 * nexthops will have two dependencies
72 * pointing to those nhg_hash_entries.
73 *
74 * Using a rb tree here to make lookups
75 * faster with ID's.
76 */
77 struct nhg_connected_tree_head nhg_depends, nhg_dependents;
78
79 /*
80 * Is this nexthop group valid, ie all nexthops are fully resolved.
81 * What is fully resolved? It's a nexthop that is either self contained
82 * and correct( ie no recursive pointer ) or a nexthop that is recursively
83 * resolved and correct.
84 */
85 #define NEXTHOP_GROUP_VALID (1 << 0)
86 /*
87 * Has this nexthop group been installed? At this point in time, this
88 * means that the data-plane has been told about this nexthop group
89 * and it's possible usage by a route entry.
90 */
91 #define NEXTHOP_GROUP_INSTALLED (1 << 1)
92 /*
93 * Has the nexthop group been queued to be send to the FIB?
94 * The NEXTHOP_GROUP_VALID flag should also be set by this point.
95 */
96 #define NEXTHOP_GROUP_QUEUED (1 << 2)
97 /*
98 * Is this a nexthop that is recursively resolved?
99 */
100 #define NEXTHOP_GROUP_RECURSIVE (1 << 3)
101 /*
102 * This is a nexthop group we got from the kernel, it is identical to
103 * one we already have. (The kernel allows duplicate nexthops, we don't
104 * since we hash on them). We are only tracking it in our ID table,
105 * it is unusable by our created routes but may be used by routes we get
106 * from the kernel. Therefore, it is unhashable.
107 */
108 #define NEXTHOP_GROUP_UNHASHABLE (1 << 4)
109
110 /*
111 * Backup nexthop support - identify groups that are backups for
112 * another group.
113 */
114 #define NEXTHOP_GROUP_BACKUP (1 << 5)
115
116 };
117
118 /* Was this one we created, either this session or previously? */
119 #define ZEBRA_NHG_CREATED(NHE) ((NHE->type) == ZEBRA_ROUTE_NHG)
120
121 /*
122 * Backup nexthops: this is a group object itself, so
123 * that the backup nexthops can use the same code as a normal object.
124 */
125 struct nhg_backup_info {
126 struct nhg_hash_entry *nhe;
127 };
128
129 enum nhg_ctx_op_e {
130 NHG_CTX_OP_NONE = 0,
131 NHG_CTX_OP_NEW,
132 NHG_CTX_OP_DEL,
133 };
134
135 enum nhg_ctx_status {
136 NHG_CTX_NONE = 0,
137 NHG_CTX_QUEUED,
138 NHG_CTX_REQUEUED,
139 NHG_CTX_SUCCESS,
140 NHG_CTX_FAILURE,
141 };
142
143 /*
144 * Context needed to queue nhg updates on the
145 * work queue.
146 */
147 struct nhg_ctx {
148
149 /* Unique ID */
150 uint32_t id;
151
152 vrf_id_t vrf_id;
153 afi_t afi;
154 /*
155 * This should only every be ZEBRA_ROUTE_NHG unless we get a a kernel
156 * created nexthop not made by us.
157 */
158 int type;
159
160 /* If its a group array, how many? */
161 uint8_t count;
162
163 /* Its either a single nexthop or an array of ID's */
164 union {
165 struct nexthop nh;
166 struct nh_grp grp[MULTIPATH_NUM];
167 } u;
168
169 enum nhg_ctx_op_e op;
170 enum nhg_ctx_status status;
171 };
172
173 /* Global control to disable use of kernel nexthops, if available. We can't
174 * force the kernel to support nexthop ids, of course, but we can disable
175 * zebra's use of them, for testing e.g. By default, if the kernel supports
176 * nexthop ids, zebra uses them.
177 */
178 void zebra_nhg_enable_kernel_nexthops(bool set);
179 bool zebra_nhg_kernel_nexthops_enabled(void);
180
181 /**
182 * NHE abstracted tree functions.
183 * Use these where possible instead of direct access.
184 */
185 struct nhg_hash_entry *zebra_nhg_alloc(void);
186 void zebra_nhg_free(struct nhg_hash_entry *nhe);
187 /* In order to clear a generic hash, we need a generic api, sigh. */
188 void zebra_nhg_hash_free(void *p);
189
190 /* Init an nhe, for use in a hash lookup for example. There's some fuzziness
191 * if the nhe represents only a single nexthop, so we try to capture that
192 * variant also.
193 */
194 void zebra_nhe_init(struct nhg_hash_entry *nhe, afi_t afi,
195 const struct nexthop *nh);
196
197 /* Allocate, free backup nexthop info objects */
198 struct nhg_backup_info *zebra_nhg_backup_alloc(void);
199 void zebra_nhg_backup_free(struct nhg_backup_info **p);
200
201 struct nexthop_group *zebra_nhg_get_backup_nhg(struct nhg_hash_entry *nhe);
202
203 extern struct nhg_hash_entry *zebra_nhg_resolve(struct nhg_hash_entry *nhe);
204
205 extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry *nhe);
206 extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry *nhe);
207
208 extern unsigned int
209 zebra_nhg_dependents_count(const struct nhg_hash_entry *nhe);
210 extern bool zebra_nhg_dependents_is_empty(const struct nhg_hash_entry *nhe);
211
212 /* Lookup ID, doesn't create */
213 extern struct nhg_hash_entry *zebra_nhg_lookup_id(uint32_t id);
214
215 /* Hash functions */
216 extern uint32_t zebra_nhg_hash_key(const void *arg);
217 extern uint32_t zebra_nhg_id_key(const void *arg);
218
219 extern bool zebra_nhg_hash_equal(const void *arg1, const void *arg2);
220 extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2);
221
222 /*
223 * Process a context off of a queue.
224 * Specifically this should be from
225 * the rib meta queue.
226 */
227 extern int nhg_ctx_process(struct nhg_ctx *ctx);
228
229 /* Find via kernel nh creation */
230 extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh,
231 struct nh_grp *grp, uint8_t count,
232 vrf_id_t vrf_id, afi_t afi, int type,
233 int startup);
234 /* Del via kernel */
235 extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id);
236
237 /* Find an nhe based on a nexthop_group */
238 extern struct nhg_hash_entry *
239 zebra_nhg_rib_find(uint32_t id, struct nexthop_group *nhg, afi_t rt_afi);
240
241 /* Find an nhe based on a route's nhe, used during route creation */
242 struct nhg_hash_entry *
243 zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi);
244
245 /* Reference counter functions */
246 extern void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe);
247 extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe);
248
249 /* Check validity of nhe, if invalid will update dependents as well */
250 extern void zebra_nhg_check_valid(struct nhg_hash_entry *nhe);
251
252 /* Convert nhe depends to a grp context that can be passed around safely */
253 extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe,
254 int size);
255
256 /* Dataplane install/uninstall */
257 extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe);
258 extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe);
259
260 /* Forward ref of dplane update context type */
261 struct zebra_dplane_ctx;
262 extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx);
263
264
265 /* Sweet the nhg hash tables for old entries on restart */
266 extern void zebra_nhg_sweep_table(struct hash *hash);
267
268 /* Nexthop resolution processing */
269 struct route_entry; /* Forward ref to avoid circular includes */
270 extern int nexthop_active_update(struct route_node *rn, struct route_entry *re);
271
272 #endif /* __ZEBRA_NHG_H__ */