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