From 2c7cac91ed6e7db0f6937923d2b57f97dbdbc337 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 28 Apr 2024 11:53:30 +0200 Subject: Adding upstream version 8.4.4. Signed-off-by: Daniel Baumann --- zebra/zebra_nhg.h | 403 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 zebra/zebra_nhg.h (limited to 'zebra/zebra_nhg.h') diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h new file mode 100644 index 0000000..62f71f9 --- /dev/null +++ b/zebra/zebra_nhg.h @@ -0,0 +1,403 @@ +/* Zebra Nexthop Group header. + * Copyright (C) 2019 Cumulus Networks, Inc. + * Donald Sharp + * Stephen Worley + * + * This file is part of FRR. + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef __ZEBRA_NHG_H__ +#define __ZEBRA_NHG_H__ + +#include "lib/nexthop.h" +#include "lib/nexthop_group.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* This struct is used exclusively for dataplane + * interaction via a dataplane context. + * + * It is designed to mimic the netlink nexthop_grp + * struct in include/linux/nexthop.h + */ +struct nh_grp { + uint32_t id; + uint8_t weight; +}; + +PREDECL_RBTREE_UNIQ(nhg_connected_tree); + +/* + * Hashtables containing nhg entries is in `zebra_router`. + */ +struct nhg_hash_entry { + uint32_t id; + afi_t afi; + vrf_id_t vrf_id; + + /* Time since last update */ + time_t uptime; + + /* Source protocol - zebra or another daemon */ + int type; + + /* zapi instance and session id, for groups from other daemons */ + uint16_t zapi_instance; + uint32_t zapi_session; + + struct nexthop_group nhg; + + /* If supported, a mapping of backup nexthops. */ + struct nhg_backup_info *backup_info; + + /* If this is not a group, it + * will be a single nexthop + * and must have an interface + * associated with it. + * Otherwise, this will be null. + */ + struct interface *ifp; + + uint32_t refcnt; + uint32_t dplane_ref; + + uint32_t flags; + + /* Dependency trees for other entries. + * For instance a group with two + * nexthops will have two dependencies + * pointing to those nhg_hash_entries. + * + * Using a rb tree here to make lookups + * faster with ID's. + * + * nhg_depends the RB tree of entries that this + * group contains. + * + * nhg_dependents the RB tree of entries that + * this group is being used by + * + * NHG id 3 with nexthops id 1/2 + * nhg(3)->nhg_depends has 1 and 2 in the tree + * nhg(3)->nhg_dependents is empty + * + * nhg(1)->nhg_depends is empty + * nhg(1)->nhg_dependents is 3 in the tree + * + * nhg(2)->nhg_depends is empty + * nhg(3)->nhg_dependents is 3 in the tree + */ + struct nhg_connected_tree_head nhg_depends, nhg_dependents; + + struct thread *timer; + +/* + * Is this nexthop group valid, ie all nexthops are fully resolved. + * What is fully resolved? It's a nexthop that is either self contained + * and correct( ie no recursive pointer ) or a nexthop that is recursively + * resolved and correct. + */ +#define NEXTHOP_GROUP_VALID (1 << 0) +/* + * Has this nexthop group been installed? At this point in time, this + * means that the data-plane has been told about this nexthop group + * and it's possible usage by a route entry. + */ +#define NEXTHOP_GROUP_INSTALLED (1 << 1) +/* + * Has the nexthop group been queued to be send to the FIB? + * The NEXTHOP_GROUP_VALID flag should also be set by this point. + */ +#define NEXTHOP_GROUP_QUEUED (1 << 2) +/* + * Is this a nexthop that is recursively resolved? + */ +#define NEXTHOP_GROUP_RECURSIVE (1 << 3) + +/* + * Backup nexthop support - identify groups that are backups for + * another group. + */ +#define NEXTHOP_GROUP_BACKUP (1 << 4) + +/* + * The NHG has been release by an upper level protocol via the + * `zebra_nhg_proto_del()` API. + * + * We use this flag to track this state in case the NHG is still being used + * by routes therefore holding their refcnts as well. Otherwise, the NHG will + * be removed and uninstalled. + * + */ +#define NEXTHOP_GROUP_PROTO_RELEASED (1 << 5) + +/* + * When deleting a NHG notice that it is still installed + * and if it is, slightly delay the actual removal to + * the future. So that upper level protocols might + * be able to take advantage of some NHG's that + * are there + */ +#define NEXTHOP_GROUP_KEEP_AROUND (1 << 6) + +/* + * Track FPM installation status.. + */ +#define NEXTHOP_GROUP_FPM (1 << 6) +}; + +/* Upper 4 bits of the NHG are reserved for indicating the NHG type */ +#define NHG_ID_TYPE_POS 28 +enum nhg_type { + NHG_TYPE_L3 = 0, + NHG_TYPE_L2_NH, /* NHs in a L2 NHG used as a MAC/FDB dest */ + NHG_TYPE_L2, /* L2 NHG used as a MAC/FDB dest */ +}; + +/* Was this one we created, either this session or previously? */ +#define ZEBRA_NHG_CREATED(NHE) \ + (((NHE->type) <= ZEBRA_ROUTE_MAX) && (NHE->type != ZEBRA_ROUTE_KERNEL)) + +/* Is this an NHE owned by zebra and not an upper level protocol? */ +#define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG) + +#define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER) + +/* + * Backup nexthops: this is a group object itself, so + * that the backup nexthops can use the same code as a normal object. + */ +struct nhg_backup_info { + struct nhg_hash_entry *nhe; +}; + +enum nhg_ctx_op_e { + NHG_CTX_OP_NONE = 0, + NHG_CTX_OP_NEW, + NHG_CTX_OP_DEL, +}; + +enum nhg_ctx_status { + NHG_CTX_NONE = 0, + NHG_CTX_QUEUED, + NHG_CTX_REQUEUED, + NHG_CTX_SUCCESS, + NHG_CTX_FAILURE, +}; + +/* + * Context needed to queue nhg updates on the + * work queue. + */ +struct nhg_ctx { + + /* Unique ID */ + uint32_t id; + + vrf_id_t vrf_id; + afi_t afi; + + /* + * This should only ever be ZEBRA_ROUTE_NHG unless we get a a kernel + * created nexthop not made by us. + */ + int type; + + /* If its a group array, how many? */ + uint8_t count; + + /* Its either a single nexthop or an array of ID's */ + union { + struct nexthop nh; + struct nh_grp grp[MULTIPATH_NUM]; + } u; + + enum nhg_ctx_op_e op; + enum nhg_ctx_status status; +}; + +/* Global control to disable use of kernel nexthops, if available. We can't + * force the kernel to support nexthop ids, of course, but we can disable + * zebra's use of them, for testing e.g. By default, if the kernel supports + * nexthop ids, zebra uses them. + */ +void zebra_nhg_enable_kernel_nexthops(bool set); +bool zebra_nhg_kernel_nexthops_enabled(void); + +/* Global control for zebra to only use proto-owned nexthops */ +void zebra_nhg_set_proto_nexthops_only(bool set); +bool zebra_nhg_proto_nexthops_only(void); + +/* Global control for use of activated backups for recursive resolution. */ +void zebra_nhg_set_recursive_use_backups(bool set); +bool zebra_nhg_recursive_use_backups(void); + +/** + * NHE abstracted tree functions. + * Use these where possible instead of direct access. + */ +struct nhg_hash_entry *zebra_nhg_alloc(void); +void zebra_nhg_free(struct nhg_hash_entry *nhe); +/* In order to clear a generic hash, we need a generic api, sigh. */ +void zebra_nhg_hash_free(void *p); +void zebra_nhg_hash_free_zero_id(struct hash_bucket *b, void *arg); + +/* Init an nhe, for use in a hash lookup for example. There's some fuzziness + * if the nhe represents only a single nexthop, so we try to capture that + * variant also. + */ +void zebra_nhe_init(struct nhg_hash_entry *nhe, afi_t afi, + const struct nexthop *nh); + +/* + * Shallow copy of 'orig', into new/allocated nhe. + */ +struct nhg_hash_entry *zebra_nhe_copy(const struct nhg_hash_entry *orig, + uint32_t id); + +/* Allocate, free backup nexthop info objects */ +struct nhg_backup_info *zebra_nhg_backup_alloc(void); +void zebra_nhg_backup_free(struct nhg_backup_info **p); + +struct nexthop_group *zebra_nhg_get_backup_nhg(struct nhg_hash_entry *nhe); + +extern struct nhg_hash_entry *zebra_nhg_resolve(struct nhg_hash_entry *nhe); + +extern unsigned int zebra_nhg_depends_count(const struct nhg_hash_entry *nhe); +extern bool zebra_nhg_depends_is_empty(const struct nhg_hash_entry *nhe); + +extern unsigned int +zebra_nhg_dependents_count(const struct nhg_hash_entry *nhe); +extern bool zebra_nhg_dependents_is_empty(const struct nhg_hash_entry *nhe); + +/* Lookup ID, doesn't create */ +extern struct nhg_hash_entry *zebra_nhg_lookup_id(uint32_t id); + +/* Hash functions */ +extern uint32_t zebra_nhg_hash_key(const void *arg); +extern uint32_t zebra_nhg_id_key(const void *arg); + +extern bool zebra_nhg_hash_equal(const void *arg1, const void *arg2); +extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2); + +/* + * Process a context off of a queue. + * Specifically this should be from + * the rib meta queue. + */ +extern int nhg_ctx_process(struct nhg_ctx *ctx); +void nhg_ctx_free(struct nhg_ctx **ctx); + +/* Find via kernel nh creation */ +extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh, + struct nh_grp *grp, uint8_t count, + vrf_id_t vrf_id, afi_t afi, int type, + int startup); +/* Del via kernel */ +extern int zebra_nhg_kernel_del(uint32_t id, vrf_id_t vrf_id); + +/* Find an nhe based on a nexthop_group */ +extern struct nhg_hash_entry *zebra_nhg_rib_find(uint32_t id, + struct nexthop_group *nhg, + afi_t rt_afi, int type); + +/* Find an nhe based on a route's nhe, used during route creation */ +struct nhg_hash_entry * +zebra_nhg_rib_find_nhe(struct nhg_hash_entry *rt_nhe, afi_t rt_afi); + + +/** + * Functions for Add/Del/Replace via protocol NHG creation. + * + * The NHEs will not be hashed. They will only be present in the + * ID table and therefore not sharable. + * + * It is the owning protocols job to manage these. + */ + +/* + * Add NHE. If already exists, Replace. + * + * Returns allocated NHE on success, otherwise NULL. + */ +struct nhg_hash_entry *zebra_nhg_proto_add(uint32_t id, int type, + uint16_t instance, uint32_t session, + struct nexthop_group *nhg, + afi_t afi); + +/* + * Del NHE. + * + * Returns deleted NHE on success, otherwise NULL. + * + * Caller must decrement ref with zebra_nhg_decrement_ref() when done. + */ +struct nhg_hash_entry *zebra_nhg_proto_del(uint32_t id, int type); + +/* + * Remove specific by proto NHGs. + * + * Called after client disconnect. + * + */ +unsigned long zebra_nhg_score_proto(int type); + +/* Reference counter functions */ +extern void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe); +extern void zebra_nhg_increment_ref(struct nhg_hash_entry *nhe); + +/* Check validity of nhe, if invalid will update dependents as well */ +extern void zebra_nhg_check_valid(struct nhg_hash_entry *nhe); + +/* Convert nhe depends to a grp context that can be passed around safely */ +extern uint8_t zebra_nhg_nhe2grp(struct nh_grp *grp, struct nhg_hash_entry *nhe, + int size); + +/* Dataplane install/uninstall */ +extern void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe); +extern void zebra_nhg_uninstall_kernel(struct nhg_hash_entry *nhe); + +/* Forward ref of dplane update context type */ +struct zebra_dplane_ctx; +extern void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx); + + +/* Sweep the nhg hash tables for old entries on restart */ +extern void zebra_nhg_sweep_table(struct hash *hash); + +/* + * We are shutting down but the nexthops should be kept + * as that -r has been specified and we don't want to delete + * the routes unintentionally + */ +extern void zebra_nhg_mark_keep(void); + +/* Nexthop resolution processing */ +struct route_entry; /* Forward ref to avoid circular includes */ +extern int nexthop_active_update(struct route_node *rn, struct route_entry *re); + +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#pragma FRR printfrr_ext "%pNG" (const struct nhg_hash_entry *) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* __ZEBRA_NHG_H__ */ -- cgit v1.2.3