diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/compiler.h | 8 | ||||
| -rw-r--r-- | lib/cspf.c | 2 | ||||
| -rw-r--r-- | lib/cspf.h | 2 | ||||
| -rw-r--r-- | lib/if_rmap.c | 291 | ||||
| -rw-r--r-- | lib/if_rmap.h | 12 | ||||
| -rw-r--r-- | lib/iso.c | 144 | ||||
| -rw-r--r-- | lib/iso.h | 49 | ||||
| -rw-r--r-- | lib/link_state.c | 24 | ||||
| -rw-r--r-- | lib/link_state.h | 4 | ||||
| -rw-r--r-- | lib/mgmt_be_client.c | 15 | ||||
| -rw-r--r-- | lib/mgmt_fe_client.c | 29 | ||||
| -rw-r--r-- | lib/routemap.c | 74 | ||||
| -rw-r--r-- | lib/subdir.am | 3 | ||||
| -rw-r--r-- | lib/vty.c | 2 | ||||
| -rw-r--r-- | lib/vty.h | 1 | ||||
| -rw-r--r-- | lib/zclient.c | 2 |
16 files changed, 437 insertions, 225 deletions
diff --git a/lib/compiler.h b/lib/compiler.h index d12e282832..29fcfbefbf 100644 --- a/lib/compiler.h +++ b/lib/compiler.h @@ -439,6 +439,14 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8, #pragma diag_suppress 167 #endif /* __INTELISENSE__ */ +#if defined(__GNUC__) && (__GNUC__ >= 3) +#define likely(_x) __builtin_expect(!!(_x), 1) +#define unlikely(_x) __builtin_expect(!!(_x), 0) +#else +#define likely(_x) !!(_x) +#define unlikely(_x) !!(_x) +#endif + #ifdef __cplusplus } #endif diff --git a/lib/cspf.c b/lib/cspf.c index b92c9cb395..6a0fb7f63c 100644 --- a/lib/cspf.c +++ b/lib/cspf.c @@ -88,7 +88,7 @@ static struct c_path *cpath_copy(struct c_path *dest, const struct c_path *src) * * @param path Constrained Path structure to be deleted */ -static void cpath_del(struct c_path *path) +void cpath_del(struct c_path *path) { if (!path) return; diff --git a/lib/cspf.h b/lib/cspf.h index 3eceaa04af..bba685a617 100644 --- a/lib/cspf.h +++ b/lib/cspf.h @@ -191,6 +191,8 @@ extern void cspf_del(struct cspf *algo); */ extern struct c_path *compute_p2p_path(struct cspf *algo, struct ls_ted *ted); +extern void cpath_del(struct c_path *path); + #ifdef __cplusplus } #endif diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 27c41aaa27..5895924a5e 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* route-map for interface. * Copyright (C) 1999 Kunihiro Ishiguro + * Copyright (C) 2023 LabN Consulting, L.L.C. */ #include <zebra.h> @@ -10,6 +11,9 @@ #include "memory.h" #include "if.h" #include "if_rmap.h" +#include "northbound_cli.h" + +#include "lib/if_rmap_clippy.c" DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX, "Interface route map container"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, @@ -17,8 +21,6 @@ DEFINE_MTYPE_STATIC(LIB, IF_RMAP_CTX_NAME, DEFINE_MTYPE_STATIC(LIB, IF_RMAP, "Interface route map"); DEFINE_MTYPE_STATIC(LIB, IF_RMAP_NAME, "I.f. route map name"); -static struct list *if_rmap_ctx_list; - static struct if_rmap *if_rmap_new(void) { struct if_rmap *new; @@ -30,7 +32,9 @@ static struct if_rmap *if_rmap_new(void) static void if_rmap_free(struct if_rmap *if_rmap) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->ifname); + char *no_const_ifname = (char *)if_rmap->ifname; + + XFREE(MTYPE_IF_RMAP_NAME, no_const_ifname); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); @@ -40,22 +44,16 @@ static void if_rmap_free(struct if_rmap *if_rmap) struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *if_rmap; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - if_rmap = hash_lookup(ctx->ifrmaphash, &key); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return if_rmap; } void if_rmap_hook_add(struct if_rmap_ctx *ctx, - void (*func)(struct if_rmap_ctx *ctx, - struct if_rmap *)) + void (*func)(struct if_rmap_ctx *ctx, struct if_rmap *)) { ctx->if_rmap_add_hook = func; } @@ -80,16 +78,11 @@ static void *if_rmap_hash_alloc(void *arg) static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname) { - struct if_rmap key; + struct if_rmap key = {.ifname = ifname}; struct if_rmap *ret; - /* temporary copy */ - key.ifname = (ifname) ? XSTRDUP(MTYPE_IF_RMAP_NAME, ifname) : NULL; - ret = hash_get(ctx->ifrmaphash, &key, if_rmap_hash_alloc); - XFREE(MTYPE_IF_RMAP_NAME, key.ifname); - return ret; } @@ -108,142 +101,171 @@ static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) return strcmp(if_rmap1->ifname, if_rmap2->ifname) == 0; } -static struct if_rmap *if_rmap_set(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_set(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type, const char *routemap_name) { - struct if_rmap *if_rmap; - - if_rmap = if_rmap_get(ctx, ifname); + struct if_rmap *if_rmap = if_rmap_get(ctx, ifname); - if (type == IF_RMAP_IN) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - if_rmap->routemap[IF_RMAP_IN] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } - if (type == IF_RMAP_OUT) { - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - if_rmap->routemap[IF_RMAP_OUT] = - XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); - } + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); + if_rmap->routemap[type] = XSTRDUP(MTYPE_IF_RMAP_NAME, routemap_name); if (ctx->if_rmap_add_hook) (ctx->if_rmap_add_hook)(ctx, if_rmap); - - return if_rmap; } -static int if_rmap_unset(struct if_rmap_ctx *ctx, - const char *ifname, enum if_rmap_type type, - const char *routemap_name) +static void if_rmap_unset(struct if_rmap_ctx *ctx, const char *ifname, + enum if_rmap_type type) { - struct if_rmap *if_rmap; + struct if_rmap *if_rmap = if_rmap_lookup(ctx, ifname); - if_rmap = if_rmap_lookup(ctx, ifname); if (!if_rmap) - return 0; - - if (type == IF_RMAP_IN) { - if (!if_rmap->routemap[IF_RMAP_IN]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_IN], routemap_name) != 0) - return 0; - - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_IN]); - } + return; - if (type == IF_RMAP_OUT) { - if (!if_rmap->routemap[IF_RMAP_OUT]) - return 0; - if (strcmp(if_rmap->routemap[IF_RMAP_OUT], routemap_name) != 0) - return 0; + assert(type == IF_RMAP_IN || type == IF_RMAP_OUT); + if (!if_rmap->routemap[type]) + return; - XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[IF_RMAP_OUT]); - } + XFREE(MTYPE_IF_RMAP_NAME, if_rmap->routemap[type]); if (ctx->if_rmap_delete_hook) ctx->if_rmap_delete_hook(ctx, if_rmap); - if (if_rmap->routemap[IF_RMAP_IN] == NULL - && if_rmap->routemap[IF_RMAP_OUT] == NULL) { + if (if_rmap->routemap[IF_RMAP_IN] == NULL && + if_rmap->routemap[IF_RMAP_OUT] == NULL) { hash_release(ctx->ifrmaphash, if_rmap); if_rmap_free(if_rmap); } - - return 1; } -DEFUN (if_rmap, - if_rmap_cmd, - "route-map RMAP_NAME <in|out> IFNAME", - "Route map set\n" - "Route map name\n" - "Route map set for input filtering\n" - "Route map set for output filtering\n" - "Route map interface name\n") +static int if_route_map_handler(struct vty *vty, bool no, const char *dir, + const char *other_dir, const char *ifname, + const char *route_map) { - int idx_rmap_name = 1; - int idx_in_out = 2; - int idx_ifname = 3; - enum if_rmap_type type; - struct if_rmap_ctx *ctx = - (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); - - if (strncmp(argv[idx_in_out]->text, "in", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->text, "out", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; + enum nb_operation op = no ? NB_OP_DESTROY : NB_OP_MODIFY; + const struct lyd_node *dnode; + char xpath[XPATH_MAXLEN]; + + if (!no) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* + * If we are deleting the last policy for this interface, + * (i.e., no `in` or `out` policy). delete the interface list + * node instead. + */ + dnode = yang_dnode_get(vty->candidate_config->dnode, + VTY_CURR_XPATH); + if (yang_dnode_existsf( + dnode, + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, other_dir)) { + snprintf( + xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']/%s-route-map", + ifname, dir); + } else { + /* both dir will be empty so delete the list node */ + snprintf(xpath, sizeof(xpath), + "./if-route-maps/if-route-map[interface='%s']", + ifname); + } } + nb_cli_enqueue_change(vty, xpath, op, route_map); + + return nb_cli_apply_changes(vty, NULL); +} - if_rmap_set(ctx, argv[idx_ifname]->arg, - type, argv[idx_rmap_name]->arg); +DEFPY_YANG(if_ipv4_route_map, if_ipv4_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; - return CMD_SUCCESS; + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); } -DEFUN (no_if_rmap, - no_if_rmap_cmd, - "no route-map ROUTEMAP_NAME <in|out> IFNAME", - NO_STR - "Route map unset\n" - "Route map name\n" - "Route map for input filtering\n" - "Route map for output filtering\n" - "Route map interface name\n") +DEFPY_YANG(no_if_ipv4_route_map, no_if_ipv4_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) { - int idx_routemap_name = 2; - int idx_in_out = 3; - int idx_ifname = 4; - int ret; - enum if_rmap_type type; - struct if_rmap_ctx *ctx = - (struct if_rmap_ctx *)listnode_head(if_rmap_ctx_list); - - if (strncmp(argv[idx_in_out]->arg, "i", 1) == 0) - type = IF_RMAP_IN; - else if (strncmp(argv[idx_in_out]->arg, "o", 1) == 0) - type = IF_RMAP_OUT; - else { - vty_out(vty, "route-map direction must be [in|out]\n"); - return CMD_WARNING_CONFIG_FAILED; - } + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; - ret = if_rmap_unset(ctx, argv[idx_ifname]->arg, type, - argv[idx_routemap_name]->arg); - if (!ret) { - vty_out(vty, "route-map doesn't exist\n"); - return CMD_WARNING_CONFIG_FAILED; - } - return CMD_SUCCESS; + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + +/* + * CLI infra requires new handlers for ripngd + */ +DEFPY_YANG(if_ipv6_route_map, if_ipv6_route_map_cmd, + "route-map ROUTE-MAP <in$in|out> IFNAME", + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, false, dir, other_dir, ifname, + route_map); +} + +DEFPY_YANG(no_if_ipv6_route_map, no_if_ipv6_route_map_cmd, + "no route-map [ROUTE-MAP] <in$in|out> IFNAME", + NO_STR + "Route map set\n" + "Route map name\n" + "Route map set for input filtering\n" + "Route map set for output filtering\n" INTERFACE_STR) +{ + const char *dir = in ? "in" : "out"; + const char *other_dir = in ? "out" : "in"; + + return if_route_map_handler(vty, true, dir, other_dir, ifname, + route_map); +} + + +void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del) +{ + + const char *mapname = yang_dnode_get_string(dnode, NULL); + const char *ifname = yang_dnode_get_string(dnode, "../interface"); + + if (del) + if_rmap_unset(ctx, ifname, type); + else + if_rmap_set(ctx, ifname, type, mapname); +} + +void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode) +{ + const char *ifname = yang_dnode_get_string(dnode, "interface"); + if_rmap_unset(ctx, ifname, IF_RMAP_IN); + if_rmap_unset(ctx, ifname, IF_RMAP_OUT); } /* Configuration write function. */ -int config_write_if_rmap(struct vty *vty, - struct if_rmap_ctx *ctx) +int config_write_if_rmap(struct vty *vty, struct if_rmap_ctx *ctx) { unsigned int i; struct hash_bucket *mp; @@ -275,10 +297,8 @@ int config_write_if_rmap(struct vty *vty, void if_rmap_ctx_delete(struct if_rmap_ctx *ctx) { - listnode_delete(if_rmap_ctx_list, ctx); hash_clean_and_free(&ctx->ifrmaphash, (void (*)(void *))if_rmap_free); - if (ctx->name) - XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx); + XFREE(MTYPE_IF_RMAP_CTX_NAME, ctx->name); XFREE(MTYPE_IF_RMAP_CTX, ctx); } @@ -289,29 +309,24 @@ struct if_rmap_ctx *if_rmap_ctx_create(const char *name) ctx = XCALLOC(MTYPE_IF_RMAP_CTX, sizeof(struct if_rmap_ctx)); - if (ctx->name) - ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); - ctx->ifrmaphash = hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, - "Interface Route-Map Hash"); - if (!if_rmap_ctx_list) - if_rmap_ctx_list = list_new(); - listnode_add(if_rmap_ctx_list, ctx); + ctx->name = XSTRDUP(MTYPE_IF_RMAP_CTX_NAME, name); + ctx->ifrmaphash = + hash_create_size(4, if_rmap_hash_make, if_rmap_hash_cmp, + "Interface Route-Map Hash"); return ctx; } void if_rmap_init(int node) { - if (node == RIPNG_NODE) { - } else if (node == RIP_NODE) { - install_element(RIP_NODE, &if_rmap_cmd); - install_element(RIP_NODE, &no_if_rmap_cmd); + if (node == RIP_NODE) { + install_element(RIP_NODE, &if_ipv4_route_map_cmd); + install_element(RIP_NODE, &no_if_ipv4_route_map_cmd); + } else if (node == RIPNG_NODE) { + install_element(RIPNG_NODE, &if_ipv6_route_map_cmd); + install_element(RIPNG_NODE, &no_if_ipv6_route_map_cmd); } - if_rmap_ctx_list = list_new(); } void if_rmap_terminate(void) { - if (!if_rmap_ctx_list) - return; - list_delete(&if_rmap_ctx_list); } diff --git a/lib/if_rmap.h b/lib/if_rmap.h index 3bdbc2a3b2..6f5fb578f0 100644 --- a/lib/if_rmap.h +++ b/lib/if_rmap.h @@ -6,15 +6,20 @@ #ifndef _ZEBRA_IF_RMAP_H #define _ZEBRA_IF_RMAP_H +#include "typesafe.h" + #ifdef __cplusplus extern "C" { #endif +struct lyd_node; +struct vty; + enum if_rmap_type { IF_RMAP_IN, IF_RMAP_OUT, IF_RMAP_MAX }; struct if_rmap { /* Name of the interface. */ - char *ifname; + const char *ifname; char *routemap[IF_RMAP_MAX]; }; @@ -45,6 +50,11 @@ void if_rmap_hook_delete(struct if_rmap_ctx *ctx, struct if_rmap *)); extern struct if_rmap *if_rmap_lookup(struct if_rmap_ctx *ctx, const char *ifname); +extern void if_rmap_yang_modify_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode, + enum if_rmap_type type, bool del); +extern void if_rmap_yang_destroy_cb(struct if_rmap_ctx *ctx, + const struct lyd_node *dnode); extern int config_write_if_rmap(struct vty *, struct if_rmap_ctx *ctx); #ifdef __cplusplus diff --git a/lib/iso.c b/lib/iso.c new file mode 100644 index 0000000000..fe97776ade --- /dev/null +++ b/lib/iso.c @@ -0,0 +1,144 @@ +/* + * ISO Network functions - iso_net.c + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2023 Orange http://www.orange.com + * + * This file is part of Free Range Routing (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 this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "compiler.h" + +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "printfrr.h" +#include "iso.h" + +/** + * Print ISO System ID as 0000.0000.0000 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("SY", printfrr_iso_sysid); +static ssize_t printfrr_iso_sysid(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x", + id[0], id[1], id[2], id[3], id[4], id[5]); +} + +/** + * Print ISO Pseudo Node system ID as 0000.0000.0000.00 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("PN", printfrr_iso_pseudo); +static ssize_t printfrr_iso_pseudo(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x", + id[0], id[1], id[2], id[3], id[4], id[5], id[6]); +} + +/** + * Print ISO LSP Fragment System ID as 0000.0000.0000.00-00 + * + * @param Print buffer + * @param Print argument + * @param Pointer to the System ID to be printed + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("LS", printfrr_iso_frag_id); +static ssize_t printfrr_iso_frag_id(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const uint8_t *id = vptr; + + if (!id) + return bputs(buf, "(null)"); + + return bprintfrr(buf, "%02x%02x.%02x%02x.%02x%02x.%02x-%02x", + id[0], id[1], id[2], id[3], id[4], id[5], id[6], + id[7]); +} + +/** + * Print ISO Network address as 00.0000.0000.0000 ... with the System ID + * as 0000.0000.0000.00 when long 'l' option is added to '%pIS' + * + * @param Print buffer + * @param Print argument + * @param Pointer to the ISO Network address + * + * @return Number of printed characters + */ +printfrr_ext_autoreg_p("IS", printfrr_iso_addr); +static ssize_t printfrr_iso_addr(struct fbuf *buf, struct printfrr_eargs *ea, + const void *vptr) +{ + const struct iso_address *ia = vptr; + uint8_t len = 0; + int i = 0; + ssize_t ret = 0; + + if (ea->fmt[0] == 'l') { + len = 7; /* ISO SYSTEM ID + 1 */ + ea->fmt++; + } + + if (!ia) + return bputs(buf, "(null)"); + + len += ia->addr_len; + while (i < len) { + /* No dot for odd index and at the end of address */ + if ((i & 1) || (i == (len - 1))) + ret += bprintfrr(buf, "%02x", ia->area_addr[i]); + else + ret += bprintfrr(buf, "%02x.", ia->area_addr[i]); + i++; + } + + return ret; +} + diff --git a/lib/iso.h b/lib/iso.h new file mode 100644 index 0000000000..975d3c154b --- /dev/null +++ b/lib/iso.h @@ -0,0 +1,49 @@ +/* + * ISO Network definition - iso_net.h + * + * Author: Olivier Dugeon <olivier.dugeon@orange.com> + * + * Copyright (C) 2023 Orange http://www.orange.com + * + * This file is part of Free Range Routing (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 this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LIB_ISO_H_ +#define LIB_ISO_H_ + +#include "compiler.h" + +/* len of "xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx.xx" + '\0' */ +#define ISO_ADDR_STRLEN 51 +#define ISO_ADDR_MIN 8 +#define ISO_ADDR_SIZE 20 +struct iso_address { + uint8_t addr_len; + uint8_t area_addr[ISO_ADDR_SIZE]; +}; + +/* len of "xxxx.xxxx.xxxx.xx-xx" + '\0' */ +#define ISO_SYSID_STRLEN 21 + +#ifdef _FRR_ATTRIBUTE_PRINTFRR +#pragma FRR printfrr_ext "%pSY" (uint8_t *) +#pragma FRR printfrr_ext "%pPN" (uint8_t *) +#pragma FRR printfrr_ext "%pLS" (uint8_t *) +#pragma FRR printfrr_ext "%pIS" (struct iso_address *) +#endif + +#endif /* LIB_ISO_H_ */ diff --git a/lib/link_state.c b/lib/link_state.c index b501018be7..7f20cdcf5e 100644 --- a/lib/link_state.c +++ b/lib/link_state.c @@ -26,6 +26,7 @@ #include "printfrr.h" #include <lib/json.h> #include "link_state.h" +#include "iso.h" /* Link State Memory allocation */ DEFINE_MTYPE_STATIC(LIB, LS_DB, "Link State Database"); @@ -333,7 +334,7 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2) /** * Link State prefix management functions */ -struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p) +struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p) { struct ls_prefix *new; @@ -342,7 +343,7 @@ struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p) new = XCALLOC(MTYPE_LS_DB, sizeof(struct ls_prefix)); new->adv = adv; - new->pref = p; + new->pref = *p; return new; } @@ -889,7 +890,7 @@ struct ls_subnet *ls_subnet_update(struct ls_ted *ted, struct ls_prefix *pref) if (pref == NULL) return NULL; - old = ls_find_subnet(ted, pref->pref); + old = ls_find_subnet(ted, &pref->pref); if (old) { if (!ls_prefix_same(old->ls_pref, pref)) { ls_prefix_del(old->ls_pref); @@ -942,11 +943,12 @@ void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet) ls_subnet_del(ted, subnet); } -struct ls_subnet *ls_find_subnet(struct ls_ted *ted, const struct prefix prefix) +struct ls_subnet *ls_find_subnet(struct ls_ted *ted, + const struct prefix *prefix) { struct ls_subnet subnet = {}; - subnet.key = prefix; + subnet.key = *prefix; return subnets_find(&ted->subnets, &subnet); } @@ -1846,7 +1848,7 @@ struct ls_subnet *ls_msg2subnet(struct ls_ted *ted, struct ls_message *msg, subnet->status = UPDATE; break; case LS_MSG_EVENT_DELETE: - subnet = ls_find_subnet(ted, pref->pref); + subnet = ls_find_subnet(ted, &pref->pref); if (subnet) { if (delete) ls_subnet_del_all(ted, subnet); @@ -1979,13 +1981,9 @@ static const char *const status2txt[] = { static const char *ls_node_id_to_text(struct ls_node_id lnid, char *str, size_t size) { - if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) { - uint8_t *id; - - id = lnid.id.iso.sys_id; - snprintfrr(str, size, "%02x%02x.%02x%02x.%02x%02x", id[0], - id[1], id[2], id[3], id[4], id[5]); - } else + if (lnid.origin == ISIS_L1 || lnid.origin == ISIS_L2) + snprintfrr(str, size, "%pSY", lnid.id.iso.sys_id); + else snprintfrr(str, size, "%pI4", &lnid.id.ip.addr); return str; diff --git a/lib/link_state.h b/lib/link_state.h index e6a6388ba4..b75f035431 100644 --- a/lib/link_state.h +++ b/lib/link_state.h @@ -314,7 +314,7 @@ extern int ls_attributes_same(struct ls_attributes *a1, * * @return New Link State Prefix */ -extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix p); +extern struct ls_prefix *ls_prefix_new(struct ls_node_id adv, struct prefix *p); /** * Remove Link State Prefix. Data Structure is freed. @@ -709,7 +709,7 @@ extern void ls_subnet_del_all(struct ls_ted *ted, struct ls_subnet *subnet); * @return Subnet if found, NULL otherwise */ extern struct ls_subnet *ls_find_subnet(struct ls_ted *ted, - const struct prefix prefix); + const struct prefix *prefix); /** * Create a new Link State Data Base. diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c index 36c78052bc..7437eedfc7 100644 --- a/lib/mgmt_be_client.c +++ b/lib/mgmt_be_client.c @@ -16,17 +16,17 @@ #include "sockopt.h" #ifdef REDIRECT_DEBUG_TO_STDERR -#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ +#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__) -#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ +#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ fprintf(stderr, "%s: ERROR, " fmt "\n", __func__, ##__VA_ARGS__) #else /* REDIRECT_DEBUG_TO_STDERR */ -#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ +#define MGMTD_BE_CLIENT_DBG(fmt, ...) \ do { \ - if (mgmt_debug_be_client) \ - zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ + if (mgmt_debug_be_client) \ + zlog_debug("%s: " fmt, __func__, ##__VA_ARGS__); \ } while (0) -#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ +#define MGMTD_BE_CLIENT_ERR(fmt, ...) \ zlog_err("%s: ERROR: " fmt, __func__, ##__VA_ARGS__) #endif /* REDIRECT_DEBUG_TO_STDERR */ @@ -597,7 +597,8 @@ static int mgmt_be_txn_cfg_prepare(struct mgmt_be_txn_ctx *txn) MGMTD_BE_CLIENT_DBG( "Avg-nb-edit-duration %lu uSec, nb-prep-duration %lu (avg: %lu) uSec, batch size %u", client_ctx->avg_edit_nb_cfg_tm, prep_nb_cfg_tm, - client_ctx->avg_prep_nb_cfg_tm, (uint32_t)num_processed); + client_ctx->avg_prep_nb_cfg_tm, + (uint32_t)num_processed); if (error) mgmt_be_txn_cfg_abort(txn); diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c index a2c4fd6572..7cb9aa3def 100644 --- a/lib/mgmt_fe_client.c +++ b/lib/mgmt_fe_client.c @@ -109,8 +109,8 @@ mgmt_fe_find_session_by_session_id(struct mgmt_fe_client_ctx *client_ctx, FOREACH_SESSION_IN_LIST (client_ctx, session) { if (session->session_id == session_id) { MGMTD_FE_CLIENT_DBG( - "Found session %p for session-id %llu.", session, - (unsigned long long)session_id); + "Found session %p for session-id %llu.", + session, (unsigned long long)session_id); return session; } } @@ -274,7 +274,8 @@ mgmt_fe_send_lockds_req(struct mgmt_fe_client_ctx *client_ctx, MGMTD_FE_CLIENT_DBG( "Sending %sLOCK_REQ message for Ds:%d session %llu to MGMTD Frontend server", - lock ? "" : "UN", ds_id, (unsigned long long)session->client_id); + lock ? "" : "UN", ds_id, + (unsigned long long)session->client_id); return mgmt_fe_client_send_msg(client_ctx, &fe_msg); } @@ -310,12 +311,12 @@ mgmt_fe_send_setcfg_req(struct mgmt_fe_client_ctx *client_ctx, return mgmt_fe_client_send_msg(client_ctx, &fe_msg); } -static int -mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx, - struct mgmt_fe_client_session *session, - uint64_t req_id, Mgmtd__DatastoreId src_ds_id, - Mgmtd__DatastoreId dest_ds_id, bool validate_only, - bool abort) +static int mgmt_fe_send_commitcfg_req(struct mgmt_fe_client_ctx *client_ctx, + struct mgmt_fe_client_session *session, + uint64_t req_id, + Mgmtd__DatastoreId src_ds_id, + Mgmtd__DatastoreId dest_ds_id, + bool validate_only, bool abort) { (void)req_id; Mgmtd__FeMessage fe_msg; @@ -450,15 +451,17 @@ mgmt_fe_client_handle_msg(struct mgmt_fe_client_ctx *client_ctx, if (session && fe_msg->session_reply->success) { MGMTD_FE_CLIENT_DBG( "Session Create for client-id %llu successful.", - (unsigned long long)fe_msg - ->session_reply->client_conn_id); + (unsigned long long) + fe_msg->session_reply + ->client_conn_id); session->session_id = fe_msg->session_reply->session_id; } else { MGMTD_FE_CLIENT_ERR( "Session Create for client-id %llu failed.", - (unsigned long long)fe_msg - ->session_reply->client_conn_id); + (unsigned long long) + fe_msg->session_reply + ->client_conn_id); } } else if (!fe_msg->session_reply->create) { MGMTD_FE_CLIENT_DBG( diff --git a/lib/routemap.c b/lib/routemap.c index 16da81fa74..20dcd2a53d 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -669,7 +669,7 @@ static struct route_map *route_map_add(const char *name) if (!map->ipv6_prefix_table) map->ipv6_prefix_table = route_table_init(); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Add route-map %s", name); return map; } @@ -689,7 +689,7 @@ static void route_map_free_map(struct route_map *map) while ((index = map->head) != NULL) route_map_index_delete(index, 0); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting route-map %s", map->name); list = &route_map_master; @@ -706,6 +706,9 @@ static void route_map_free_map(struct route_map *map) else list->head = map->next; + route_table_finish(map->ipv4_prefix_table); + route_table_finish(map->ipv6_prefix_table); + hash_release(route_map_master_hash, map); XFREE(MTYPE_ROUTE_MAP_NAME, map->name); XFREE(MTYPE_ROUTE_MAP, map); @@ -1120,7 +1123,7 @@ void route_map_index_delete(struct route_map_index *index, int notify) QOBJ_UNREG(index); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting route-map %s sequence %d", index->map->name, index->pref); @@ -1231,7 +1234,7 @@ route_map_index_add(struct route_map *map, enum route_map_type type, int pref) route_map_notify_dependencies(map->name, RMAP_EVENT_CALL_ADDED); } - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Route-map %s add sequence %d, type: %s", map->name, pref, route_map_type_str(type)); @@ -1811,10 +1814,8 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, * must be AF_INET or AF_INET6 in order for the lookup to succeed. So if * the AF doesn't line up with the LPM trees, skip the optimization. */ - if (map->optimization_disabled || - (prefix->family == AF_INET && !map->ipv4_prefix_table) || - (prefix->family == AF_INET6 && !map->ipv6_prefix_table)) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (map->optimization_disabled) { + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Skipping route-map optimization for route-map: %s, pfx: %pFX, family: %d", map->name, prefix, prefix->family); @@ -1826,9 +1827,6 @@ route_map_get_index(struct route_map *map, const struct prefix *prefix, else table = map->ipv6_prefix_table; - if (!table) - return NULL; - do { candidate_rmap_list = route_map_get_index_list(&rn, prefix, table); @@ -1914,19 +1912,10 @@ static void route_map_pfx_table_add_default(afi_t afi, p.family = afi2family(afi); p.prefixlen = 0; - if (p.family == AF_INET) { - table = index->map->ipv4_prefix_table; - if (!table) - index->map->ipv4_prefix_table = route_table_init(); - + if (p.family == AF_INET) table = index->map->ipv4_prefix_table; - } else { - table = index->map->ipv6_prefix_table; - if (!table) - index->map->ipv6_prefix_table = route_table_init(); - + else table = index->map->ipv6_prefix_table; - } /* Add default route to table */ rn = route_node_get(table, &p); @@ -2317,8 +2306,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event, struct route_map_index *index, afi_t afi, const char *plist_name) { - struct route_map *rmap = NULL; - if (!index) return; @@ -2332,19 +2319,6 @@ static void route_map_pfx_tbl_update(route_map_event_t event, route_map_pfx_table_del_default(AFI_IP, index); route_map_pfx_table_del_default(AFI_IP6, index); - if ((index->map->head == NULL) && (index->map->tail == NULL)) { - rmap = index->map; - - if (rmap->ipv4_prefix_table) { - route_table_finish(rmap->ipv4_prefix_table); - rmap->ipv4_prefix_table = NULL; - } - - if (rmap->ipv6_prefix_table) { - route_table_finish(rmap->ipv6_prefix_table); - rmap->ipv6_prefix_table = NULL; - } - } return; } @@ -2569,12 +2543,14 @@ route_map_result_t route_map_apply_ext(struct route_map *map, */ if (prefix->family == AF_EVPN) { if (evpn_prefix2prefix(prefix, &conv) != 0) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Unable to convert EVPN prefix %pFX into IPv4/IPv6 prefix. Falling back to non-optimized route-map lookup", prefix); } else { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL)) + if (unlikely(CHECK_FLAG(rmap_debug, + DEBUG_ROUTEMAP_DETAIL))) zlog_debug( "Converted EVPN prefix %pFX into %pFX for optimized route-map lookup", prefix, &conv); @@ -2586,13 +2562,13 @@ route_map_result_t route_map_apply_ext(struct route_map *map, index = route_map_get_index(map, prefix, match_object, &match_ret); if (index) { index->applied++; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug( "Best match route-map: %s, sequence: %d for pfx: %pFX, result: %s", map->name, index->pref, prefix, route_map_cmd_result_str(match_ret)); } else { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug( "No best match sequence for pfx: %pFX in route-map: %s, result: %s", prefix, map->name, @@ -2615,7 +2591,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map, /* Apply this index. */ match_ret = route_map_apply_match(&index->match_list, prefix, match_object); - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) { + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) { zlog_debug( "Route-map: %s, sequence: %d, prefix: %pFX, result: %s", map->name, index->pref, prefix, @@ -2728,7 +2704,7 @@ route_map_result_t route_map_apply_ext(struct route_map *map, } route_map_apply_end: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Route-map: %s, prefix: %pFX, result: %s", (map ? map->name : "null"), prefix, route_map_result_str(ret)); @@ -2783,7 +2759,7 @@ static void route_map_clear_reference(struct hash_bucket *bucket, void *arg) tmp_dep_data.rname = arg; dep_data = hash_release(dep->dep_rmap_hash, &tmp_dep_data); if (dep_data) { - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Clearing reference for %s to %s count: %d", dep->dep_name, tmp_dep_data.rname, dep_data->refcnt); @@ -2803,7 +2779,7 @@ static void route_map_clear_all_references(char *rmap_name) { int i; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Clearing references for %s", rmap_name); for (i = 1; i < ROUTE_MAP_DEP_MAX; i++) { @@ -2879,7 +2855,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_LLIST_ADDED: case RMAP_EVENT_CALL_ADDED: case RMAP_EVENT_FILTER_ADDED: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Adding dependency for filter %s in route-map %s", dep_name, rmap_name); dep = (struct route_map_dep *)hash_get( @@ -2908,7 +2884,7 @@ static int route_map_dep_update(struct hash *dephash, const char *dep_name, case RMAP_EVENT_LLIST_DELETED: case RMAP_EVENT_CALL_DELETED: case RMAP_EVENT_FILTER_DELETED: - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Deleting dependency for filter %s in route-map %s", dep_name, rmap_name); dep = (struct route_map_dep *)hash_get(dephash, dname, NULL); @@ -3034,7 +3010,7 @@ static void route_map_process_dependency(struct hash_bucket *bucket, void *data) dep_data = bucket->data; rmap_name = dep_data->rname; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Notifying %s of dependency", rmap_name); if (route_map_master.event_hook) (*route_map_master.event_hook)(rmap_name); @@ -3082,7 +3058,7 @@ void route_map_notify_dependencies(const char *affected_name, if (!dep->this_hash) dep->this_hash = upd8_hash; - if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP)) + if (unlikely(CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP))) zlog_debug("Filter %s updated", dep->dep_name); hash_iterate(dep->dep_rmap_hash, route_map_process_dependency, (void *)event); diff --git a/lib/subdir.am b/lib/subdir.am index 0f5bbef0b2..dcc58b31ae 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -47,6 +47,7 @@ lib_libfrr_la_SOURCES = \ lib/if_rmap.c \ lib/imsg-buffer.c \ lib/imsg.c \ + lib/iso.c \ lib/jhash.c \ lib/json.c \ lib/keychain.c \ @@ -173,6 +174,7 @@ clippy_scan += \ lib/affinitymap_cli.c \ lib/if.c \ lib/filter_cli.c \ + lib/if_rmap.c \ lib/log_vty.c \ lib/nexthop_group.c \ lib/northbound_cli.c \ @@ -224,6 +226,7 @@ pkginclude_HEADERS += \ lib/if_rmap.h \ lib/imsg.h \ lib/ipaddr.h \ + lib/iso.h \ lib/jhash.h \ lib/json.h \ lib/keychain.h \ @@ -2400,7 +2400,7 @@ static void vty_timeout(struct event *thread) } /* Read up configuration file from file_name. */ -static void vty_read_file(struct nb_config *config, FILE *confp) +void vty_read_file(struct nb_config *config, FILE *confp) { int ret; struct vty *vty; @@ -369,6 +369,7 @@ extern void vty_pass_fd(struct vty *vty, int fd); extern bool vty_read_config(struct nb_config *config, const char *config_file, char *config_default_dir); +extern void vty_read_file(struct nb_config *config, FILE *confp); extern void vty_time_print(struct vty *, int); extern void vty_serv_sock(const char *, unsigned short, const char *); extern void vty_close(struct vty *); diff --git a/lib/zclient.c b/lib/zclient.c index 95093a56f5..d42cb20191 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -4294,6 +4294,8 @@ int32_t zapi_capabilities_decode(struct stream *s, struct zapi_cap *api) memset(api, 0, sizeof(*api)); + api->safi = SAFI_UNICAST; + STREAM_GETL(s, api->cap); switch (api->cap) { case ZEBRA_CLIENT_GR_CAPABILITIES: |
