diff options
Diffstat (limited to '')
49 files changed, 2026 insertions, 1340 deletions
diff --git a/zebra/.gitignore b/zebra/.gitignore index 41a86e7..f10240d 100644 --- a/zebra/.gitignore +++ b/zebra/.gitignore @@ -1,3 +1,4 @@ zebra zebra.conf client +fpm_listener diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c index a7cccdb..037d0b6 100644 --- a/zebra/debug_nl.c +++ b/zebra/debug_nl.c @@ -534,6 +534,12 @@ const char *rtm_rta2str(int type) return "NH_ID"; case RTA_EXPIRES: return "EXPIRES"; + case RTA_VIA: + return "VIA"; + case RTA_ENCAP_TYPE: + return "RTA_ENCAP_TYPE"; + case RTA_ENCAP: + return "RTA_ENCAP"; default: return "UNKNOWN"; } diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c index 4c32044..4111551 100644 --- a/zebra/dpdk/zebra_dplane_dpdk.c +++ b/zebra/dpdk/zebra_dplane_dpdk.c @@ -52,7 +52,7 @@ void zd_dpdk_stat_show(struct vty *vty) static void zd_dpdk_flow_stat_show(struct vty *vty, int in_ifindex, intptr_t dp_flow_ptr) { - struct rte_flow_action_count count = {.shared = 0, .id = 0}; + struct rte_flow_action_count count = { .id = 0 }; const struct rte_flow_action actions[] = { { .type = RTE_FLOW_ACTION_TYPE_COUNT, @@ -105,8 +105,7 @@ static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket *bucket, void *arg) ifp = if_lookup_by_name_vrf(rule->ifname, vrf); if (ifp) - zd_dpdk_flow_stat_show(vty, ifp->ifindex, - zaction->dp_flow_ptr); + zd_dpdk_flow_stat_show(vty, ifp->ifindex, zaction->dp_flow_ptr); } return HASHWALK_CONTINUE; } @@ -153,8 +152,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL) zlog_debug( "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n", - dplane_ctx_rule_get_ifname(ctx), seq, pri, - unique, in_ifindex); + dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, in_ifindex); return; } @@ -163,8 +161,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL) zlog_debug( "PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n", - dplane_ctx_rule_get_ifname(ctx), seq, pri, - unique, out_ifindex); + dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, out_ifindex); return; } @@ -180,7 +177,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) memset(&ip, 0, sizeof(ip)); memset(&ip_mask, 0, sizeof(ip_mask)); - if (filter_bm & PBR_FILTER_SRC_IP) { + if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_IP)) { const struct prefix *src_ip; src_ip = dplane_ctx_rule_get_src_ip(ctx); @@ -188,7 +185,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) masklen2ip(src_ip->prefixlen, &tmp_mask); ip_mask.hdr.src_addr = tmp_mask.s_addr; } - if (filter_bm & PBR_FILTER_DST_IP) { + if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_IP)) { const struct prefix *dst_ip; dst_ip = dplane_ctx_rule_get_dst_ip(ctx); @@ -196,7 +193,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) masklen2ip(dst_ip->prefixlen, &tmp_mask); ip_mask.hdr.dst_addr = tmp_mask.s_addr; } - if (filter_bm & PBR_FILTER_IP_PROTOCOL) { + if (CHECK_FLAG(filter_bm, PBR_FILTER_IP_PROTOCOL)) { ip.hdr.next_proto_id = dplane_ctx_rule_get_ipproto(ctx); ip_mask.hdr.next_proto_id = UINT8_MAX; } @@ -206,17 +203,15 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) items[item_cnt].last = NULL; ++item_cnt; - if ((filter_bm & (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) { + if (CHECK_FLAG(filter_bm, (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) { memset(&udp, 0, sizeof(udp)); memset(&udp_mask, 0, sizeof(udp_mask)); - if (filter_bm & PBR_FILTER_SRC_PORT) { - udp.hdr.src_port = - RTE_BE16(dplane_ctx_rule_get_src_port(ctx)); + if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_PORT)) { + udp.hdr.src_port = RTE_BE16(dplane_ctx_rule_get_src_port(ctx)); udp_mask.hdr.src_port = UINT16_MAX; } - if (filter_bm & PBR_FILTER_DST_PORT) { - udp.hdr.dst_port = - RTE_BE16(dplane_ctx_rule_get_dst_port(ctx)); + if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_PORT)) { + udp.hdr.dst_port = RTE_BE16(dplane_ctx_rule_get_dst_port(ctx)); udp_mask.hdr.dst_port = UINT16_MAX; } items[item_cnt].type = RTE_FLOW_ITEM_TYPE_UDP; @@ -273,8 +268,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx) } else { zlog_warn( "PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n", - dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, - error.type); + dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, error.type); } } @@ -504,9 +498,11 @@ static void zd_dpdk_port_show_entry(struct zd_dpdk_port *dport, struct vty *vty, if (detail) { vty_out(vty, "DPDK port: %u\n", dport->port_id); vty_out(vty, " Device: %s\n", - dev_info->device ? dev_info->device->name : "-"); + dev_info->device ? rte_dev_name(dev_info->device) : "-"); vty_out(vty, " Driver: %s\n", - dev_info->driver_name ? dev_info->driver_name : "-"); + dev_info->driver_name ? rte_driver_name(rte_dev_driver( + dev_info->device)) + : "-"); vty_out(vty, " Interface: %s (%d)\n", ifindex2ifname(dev_info->if_index, VRF_DEFAULT), dev_info->if_index); @@ -516,9 +512,8 @@ static void zd_dpdk_port_show_entry(struct zd_dpdk_port *dport, struct vty *vty, dev_info->switch_info.port_id); vty_out(vty, "\n"); } else { - vty_out(vty, "%-4u %-16s %-16s %-16d %s,%u,%u\n", - dport->port_id, - dev_info->device ? dev_info->device->name : "-", + vty_out(vty, "%-4u %-16s %-16s %-16d %s,%u,%u\n", dport->port_id, + dev_info->device ? rte_dev_name(dev_info->device) : "-", ifindex2ifname(dev_info->if_index, VRF_DEFAULT), dev_info->if_index, dev_info->switch_info.name, dev_info->switch_info.domain_id, @@ -562,7 +557,7 @@ void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj, int detail) for (count = 0; count < RTE_MAX_ETHPORTS; ++count) { dport = &dpdk_ctx->dpdk_ports[count]; - if (dport->flags & ZD_DPDK_PORT_FLAG_INITED) + if (CHECK_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED)) zd_dpdk_port_show_entry(dport, vty, detail); } } @@ -592,31 +587,31 @@ static void zd_dpdk_port_init(void) dport = &dpdk_ctx->dpdk_ports[count]; count++; dport->port_id = port_id; - dport->flags |= ZD_DPDK_PORT_FLAG_PROBED; + SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_PROBED); dev_info = &dport->dev_info; if (rte_eth_dev_info_get(port_id, dev_info) < 0) { zlog_warn("failed to get dev info for %u, %s", port_id, rte_strerror(rte_errno)); continue; } - dport->flags |= ZD_DPDK_PORT_FLAG_INITED; + SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED); if (IS_ZEBRA_DEBUG_DPLANE_DPDK) - zlog_debug( - "port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u", - port_id, - dev_info->device ? dev_info->device->name : "-", - dev_info->if_index, dev_info->switch_info.name, - dev_info->switch_info.domain_id, - dev_info->switch_info.port_id); + zlog_debug("port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u", + port_id, + dev_info->device + ? rte_dev_name(dev_info->device) + : "-", + dev_info->if_index, + dev_info->switch_info.name, + dev_info->switch_info.domain_id, + dev_info->switch_info.port_id); if (rte_flow_isolate(port_id, 1, &error)) { if (IS_ZEBRA_DEBUG_DPLANE_DPDK) zlog_debug( - "Flow isolate on port %u failed %d", - port_id, error.type); + "Flow isolate on port %u failed %d", port_id, error.type); } else { if (IS_ZEBRA_DEBUG_DPLANE_DPDK) - zlog_debug("Flow isolate on port %u", - port_id); + zlog_debug("Flow isolate on port %u", port_id); } rc = rte_eth_dev_start(port_id); if (rc) { @@ -625,8 +620,7 @@ static void zd_dpdk_port_init(void) continue; } if (IS_ZEBRA_DEBUG_DPLANE_DPDK) - zlog_debug("DPDK port %d started in promiscuous mode ", - port_id); + zlog_debug("DPDK port %d started in promiscuous mode ", port_id); } if (!count) { @@ -639,13 +633,12 @@ static void zd_dpdk_port_init(void) static int zd_dpdk_init(void) { int rc; - static const char *argv[] = {(char *)"/usr/lib/frr/zebra", - (char *)"--"}; + static const char *argv[] = {(char *)"/usr/lib/frr/zebra", (char *)"--"}; zd_dpdk_vty_init(); frr_with_privs (&zserv_privs) { - rc = rte_eal_init(array_size(argv), argv); + rc = rte_eal_init(array_size(argv), (char **)argv); } if (rc < 0) { zlog_warn("EAL init failed %s", rte_strerror(rte_errno)); @@ -674,8 +667,7 @@ static int zd_dpdk_finish(struct zebra_dplane_provider *prov, bool early) if (early) { if (IS_ZEBRA_DEBUG_DPLANE_DPDK) - zlog_debug("%s early finish", - dplane_provider_get_name(prov)); + zlog_debug("%s early finish", dplane_provider_get_name(prov)); return 0; } diff --git a/zebra/dpdk/zebra_dplane_dpdk.h b/zebra/dpdk/zebra_dplane_dpdk.h index e5a3dbe..ece72d9 100644 --- a/zebra/dpdk/zebra_dplane_dpdk.h +++ b/zebra/dpdk/zebra_dplane_dpdk.h @@ -20,4 +20,6 @@ extern void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj, extern void zd_dpdk_stat_show(struct vty *vty); extern void zd_dpdk_vty_init(void); +extern struct zebra_privs_t zserv_privs; + #endif diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index 7ae1b2a..9ad92d6 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -30,6 +30,7 @@ #include "lib/network.h" #include "lib/ns.h" #include "lib/frr_pthread.h" +#include "lib/termtable.h" #include "zebra/debug.h" #include "zebra/interface.h" #include "zebra/zebra_dplane.h" @@ -44,6 +45,8 @@ #include "zebra/debug.h" #include "fpm/fpm.h" +#include "zebra/dplane_fpm_nl_clippy.c" + #define SOUTHBOUND_DEFAULT_ADDR INADDR_LOOPBACK /* @@ -322,6 +325,74 @@ DEFUN(fpm_reset_counters, fpm_reset_counters_cmd, return CMD_SUCCESS; } +DEFPY(fpm_show_status, + fpm_show_status_cmd, + "show fpm status [json]$json", + SHOW_STR FPM_STR "FPM status\n" JSON_STR) +{ + struct json_object *j; + bool connected; + uint16_t port; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + char buf[BUFSIZ]; + + connected = gfnc->socket > 0 ? true : false; + + switch (gfnc->addr.ss_family) { + case AF_INET: + sin = (struct sockaddr_in *)&gfnc->addr; + snprintfrr(buf, sizeof(buf), "%pI4", &sin->sin_addr); + port = ntohs(sin->sin_port); + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *)&gfnc->addr; + snprintfrr(buf, sizeof(buf), "%pI6", &sin6->sin6_addr); + port = ntohs(sin6->sin6_port); + break; + default: + strlcpy(buf, "Unknown", sizeof(buf)); + port = FPM_DEFAULT_PORT; + break; + } + + if (json) { + j = json_object_new_object(); + + json_object_boolean_add(j, "connected", connected); + json_object_boolean_add(j, "useNHG", gfnc->use_nhg); + json_object_boolean_add(j, "useRouteReplace", + gfnc->use_route_replace); + json_object_boolean_add(j, "disabled", gfnc->disabled); + json_object_string_add(j, "address", buf); + json_object_int_add(j, "port", port); + + vty_json(vty, j); + } else { + struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]); + char *out; + + ttable_rowseps(table, 0, BOTTOM, true, '-'); + ttable_add_row(table, "Address to connect to|%s", buf); + ttable_add_row(table, "Port|%u", port); + ttable_add_row(table, "Connected|%s", connected ? "Yes" : "No"); + ttable_add_row(table, "Use Nexthop Groups|%s", + gfnc->use_nhg ? "Yes" : "No"); + ttable_add_row(table, "Use Route Replace Semantics|%s", + gfnc->use_route_replace ? "Yes" : "No"); + ttable_add_row(table, "Disabled|%s", + gfnc->disabled ? "Yes" : "No"); + + out = ttable_dump(table, "\n"); + vty_out(vty, "%s\n", out); + XFREE(MTYPE_TMP, out); + + ttable_del(table); + } + + return CMD_SUCCESS; +} + DEFUN(fpm_show_counters, fpm_show_counters_cmd, "show fpm counters", SHOW_STR @@ -583,14 +654,6 @@ static void fpm_read(struct event *t) hdr_available_bytes = fpm.msg_len - FPM_MSG_HDR_LEN; available_bytes -= hdr_available_bytes; - /* Sanity check: must be at least header size. */ - if (hdr->nlmsg_len < sizeof(*hdr)) { - zlog_warn( - "%s: [seq=%u] invalid message length %u (< %zu)", - __func__, hdr->nlmsg_seq, hdr->nlmsg_len, - sizeof(*hdr)); - continue; - } if (hdr->nlmsg_len > fpm.msg_len) { zlog_warn( "%s: Received a inner header length of %u that is greater than the fpm total length of %u", @@ -620,6 +683,14 @@ static void fpm_read(struct event *t) switch (hdr->nlmsg_type) { case RTM_NEWROUTE: + /* Sanity check: need at least route msg header size. */ + if (hdr->nlmsg_len < sizeof(struct rtmsg)) { + zlog_warn("%s: [seq=%u] invalid message length %u (< %zu)", + __func__, hdr->nlmsg_seq, + hdr->nlmsg_len, sizeof(struct rtmsg)); + break; + } + ctx = dplane_ctx_alloc(); dplane_ctx_route_init(ctx, DPLANE_OP_ROUTE_NOTIFY, NULL, NULL); @@ -1394,8 +1465,14 @@ static void fpm_process_queue(struct event *t) uint64_t processed_contexts = 0; while (true) { + size_t writeable_amount; + + frr_with_mutex (&fnc->obuf_mutex) { + writeable_amount = STREAM_WRITEABLE(fnc->obuf); + } + /* No space available yet. */ - if (STREAM_WRITEABLE(fnc->obuf) < NL_PKT_BUF_SIZE) { + if (writeable_amount < NL_PKT_BUF_SIZE) { no_bufs = true; break; } @@ -1665,6 +1742,7 @@ static int fpm_nl_new(struct event_loop *tm) zlog_debug("%s register status: %d", prov_name, rv); install_node(&fpm_node); + install_element(ENABLE_NODE, &fpm_show_status_cmd); install_element(ENABLE_NODE, &fpm_show_counters_cmd); install_element(ENABLE_NODE, &fpm_show_counters_json_cmd); install_element(ENABLE_NODE, &fpm_reset_counters_cmd); diff --git a/zebra/fpm_listener.c b/zebra/fpm_listener.c new file mode 100644 index 0000000..7d84c70 --- /dev/null +++ b/zebra/fpm_listener.c @@ -0,0 +1,814 @@ +// SPDX-License-Identifier: ISC +/* + * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC") + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +#include "config.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#ifdef GNU_LINUX +#include <stdint.h> +#include <memory.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <errno.h> +#include <assert.h> +#include <err.h> +#include <sys/types.h> + +#include <linux/netlink.h> +#include <linux/rtnetlink.h> +#include <linux/if_link.h> + +#include "rt_netlink.h" +#include "fpm/fpm.h" +#include "lib/libfrr.h" + +XREF_SETUP(); + +struct glob { + int server_sock; + int sock; + bool reflect; + bool dump_hex; +}; + +struct glob glob_space; +struct glob *glob = &glob_space; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +/* + * get_print_buf + */ +static char * +get_print_buf(size_t *buf_len) +{ + static char print_bufs[16][128]; + static int counter; + + counter++; + if (counter >= 16) + counter = 0; + + *buf_len = 128; + return &print_bufs[counter][0]; +} + +/* + * create_listen_sock + */ +static int create_listen_sock(int port, int *sock_p) +{ + int sock; + struct sockaddr_in addr; + int reuse; + + sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock < 0) { + fprintf(stderr, "Failed to create socket: %s\n", strerror(errno)); + return 0; + } + + reuse = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < + 0) { + fprintf(stderr, "Failed to set reuse addr option: %s\n", + strerror(errno)); + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(port); + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + fprintf(stderr, "Failed to bind to port %d: %s\n", port, strerror(errno)); + close(sock); + return 0; + } + + if (listen(sock, 5)) { + fprintf(stderr, "Failed to listen on socket: %s\n", strerror(errno)); + close(sock); + return 0; + } + + *sock_p = sock; + return 1; +} + +/* + * accept_conn + */ +static int accept_conn(int listen_sock) +{ + int sock; + struct sockaddr_in client_addr = { 0 }; + unsigned int client_len; + + while (1) { + char buf[120]; + + fprintf(stdout, "Waiting for client connection...\n"); + client_len = sizeof(client_addr); + sock = accept(listen_sock, (struct sockaddr *)&client_addr, + &client_len); + + if (sock >= 0) { + fprintf(stdout, "Accepted client %s\n", + inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf))); + return sock; + } + fprintf(stderr, "Failed to accept socket: %s\n", strerror(errno)); + } +} + +/* + * read_fpm_msg + */ +static fpm_msg_hdr_t * +read_fpm_msg(char *buf, size_t buf_len) +{ + char *cur, *end; + long need_len, bytes_read, have_len; + fpm_msg_hdr_t *hdr; + int reading_full_msg; + + end = buf + buf_len; + cur = buf; + hdr = (fpm_msg_hdr_t *)buf; + + while (1) { + reading_full_msg = 0; + + have_len = cur - buf; + + if (have_len < (long)FPM_MSG_HDR_LEN) { + need_len = FPM_MSG_HDR_LEN - have_len; + } else { + need_len = fpm_msg_len(hdr) - have_len; + assert(need_len >= 0 && need_len <= (end - cur)); + + if (!need_len) + return hdr; + + reading_full_msg = 1; + } + + bytes_read = read(glob->sock, cur, need_len); + + if (bytes_read == 0) { + fprintf(stdout, + "Socket closed as that read returned 0\n"); + return NULL; + } + + if (bytes_read < 0) { + fprintf(stderr, "Error reading from socket: %s\n", + strerror(errno)); + return NULL; + } + + cur += bytes_read; + + if (bytes_read < need_len) { + fprintf(stderr, + "Read %lu bytes but expected to read %lu bytes instead\n", + bytes_read, need_len); + return NULL; + } + + if (reading_full_msg) + return hdr; + + if (!fpm_msg_ok(hdr, buf_len)) { + assert(0); + fprintf(stderr, "Malformed fpm message\n"); + return NULL; + } + } +} + +/* + * netlink_msg_type_to_s + */ +static const char * +netlink_msg_type_to_s(uint16_t type) +{ + switch (type) { + + case RTM_NEWROUTE: + return "New route"; + + case RTM_DELROUTE: + return "Del route"; + + case RTM_NEWNEXTHOP: + return "New Nexthop Group"; + + case RTM_DELNEXTHOP: + return "Del Nexthop Group"; + + default: + return "Unknown"; + } +} + +/* + * netlink_prot_to_s + */ +static const char * +netlink_prot_to_s(unsigned char prot) +{ + switch (prot) { + + case RTPROT_KERNEL: + return "Kernel"; + + case RTPROT_BOOT: + return "Boot"; + + case RTPROT_STATIC: + return "Static"; + + case RTPROT_ZEBRA: + return "Zebra"; + + case RTPROT_DHCP: + return "Dhcp"; + + case RTPROT_BGP: + return "BGP"; + + case RTPROT_ISIS: + return "ISIS"; + + case RTPROT_OSPF: + return "OSPF"; + + case RTPROT_RIP: + return "RIP"; + + case RTPROT_RIPNG: + return "RIPNG"; + + case RTPROT_BABEL: + return "BABEL"; + + case RTPROT_NHRP: + return "NHRP"; + + case RTPROT_EIGRP: + return "EIGRP"; + + case RTPROT_SHARP: + return "SHARP"; + + case RTPROT_PBR: + return "PBR"; + + case RTPROT_ZSTATIC: + return "Static"; + + default: + return "Unknown"; + } +} + +#define MAX_NHS 16 + +struct netlink_nh { + struct rtattr *gateway; + int if_index; + uint16_t encap_type; + uint32_t vxlan_vni; +}; + +struct netlink_msg_ctx { + struct nlmsghdr *hdr; + + /* + * Stuff pertaining to route messages. + */ + struct rtmsg *rtmsg; + struct rtattr *rtattrs[RTA_MAX + 1]; + + /* + * Nexthops. + */ + struct netlink_nh nhs[MAX_NHS]; + unsigned long num_nhs; + + struct rtattr *dest; + struct rtattr *src; + int *metric; + unsigned int *nhgid; + + const char *err_msg; +}; + +/* + * netlink_msg_ctx_init + */ +static inline void netlink_msg_ctx_init(struct netlink_msg_ctx *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +/* + * netlink_msg_ctx_set_err + */ +static inline void netlink_msg_ctx_set_err(struct netlink_msg_ctx *ctx, + const char *err_msg) +{ + if (ctx->err_msg) + return; + + ctx->err_msg = err_msg; +} + +/* + * parse_rtattrs_ + */ +static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas, + uint16_t num_rtas, const char **err_msg) +{ + memset(rtas, 0, num_rtas * sizeof(rtas[0])); + + for (; len > 0; rta = RTA_NEXT(rta, len)) { + uint16_t type = rta->rta_type & NLA_TYPE_MASK; + + if (!RTA_OK(rta, len)) { + *err_msg = "Malformed rta"; + return 0; + } + + if (type >= num_rtas) { + warn("Unknown rtattr type %d", rta->rta_type); + continue; + } + + rtas[type] = rta; + } + + return 1; +} + +/* + * parse_rtattrs + */ +static int parse_rtattrs(struct netlink_msg_ctx *ctx, struct rtattr *rta, + size_t len) +{ + const char *err_msg; + + err_msg = NULL; + + if (!parse_rtattrs_(rta, len, ctx->rtattrs, ARRAY_SIZE(ctx->rtattrs), + &err_msg)) { + netlink_msg_ctx_set_err(ctx, err_msg); + return 0; + } + + return 1; +} + +/* + * netlink_msg_ctx_add_nh + */ +static int netlink_msg_ctx_add_nh(struct netlink_msg_ctx *ctx, int if_index, + struct rtattr *gateway, uint16_t encap_type, + uint32_t vxlan_vni) +{ + struct netlink_nh *nh; + + if (ctx->num_nhs + 1 >= ARRAY_SIZE(ctx->nhs)) { + warn("Too many next hops"); + return 0; + } + nh = &ctx->nhs[ctx->num_nhs]; + ctx->num_nhs++; + + nh->gateway = gateway; + nh->if_index = if_index; + + nh->encap_type = encap_type; + nh->vxlan_vni = vxlan_vni; + return 1; +} + +/* + * parse_multipath_attr + */ +static int parse_multipath_attr(struct netlink_msg_ctx *ctx, + struct rtattr *mpath_rtattr) +{ + int len; + struct rtnexthop *rtnh; + struct rtattr *rtattrs[RTA_MAX + 1]; + struct rtattr *tb[RTA_MAX + 1]; + struct rtattr *gateway; + const char *err_msg; + + rtnh = RTA_DATA(mpath_rtattr); + len = RTA_PAYLOAD(mpath_rtattr); + + for (; len > 0; + len -= NLMSG_ALIGN(rtnh->rtnh_len), rtnh = RTNH_NEXT(rtnh)) { + uint32_t vxlan_vni; + uint16_t encap_type; + + if (!RTNH_OK(rtnh, len)) { + netlink_msg_ctx_set_err(ctx, "Malformed nh"); + return 0; + } + + if (rtnh->rtnh_len <= sizeof(*rtnh)) { + netlink_msg_ctx_set_err(ctx, "NH len too small"); + return 0; + } + + /* + * Parse attributes included in the nexthop. + */ + err_msg = NULL; + if (!parse_rtattrs_(RTNH_DATA(rtnh), + rtnh->rtnh_len - sizeof(*rtnh), rtattrs, + ARRAY_SIZE(rtattrs), &err_msg)) { + netlink_msg_ctx_set_err(ctx, err_msg); + return 0; + } + + gateway = rtattrs[RTA_GATEWAY]; + memset(tb, 0, sizeof(tb)); + if (rtattrs[RTA_ENCAP]) { + parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]), + rtattrs[RTA_ENCAP]->rta_len - + sizeof(struct rtattr), + tb, ARRAY_SIZE(tb), &err_msg); + } + + if (rtattrs[RTA_ENCAP_TYPE]) + encap_type = + *(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]); + else + encap_type = 0; + + if (tb[0]) + vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]); + else + vxlan_vni = 0; + + netlink_msg_ctx_add_nh(ctx, rtnh->rtnh_ifindex, gateway, + encap_type, vxlan_vni); + } + + return 1; +} + +/* + * parse_route_msg + */ +static int parse_route_msg(struct netlink_msg_ctx *ctx) +{ + int len; + struct rtattr **rtattrs, *rtattr, *gateway, *oif; + int if_index; + + ctx->rtmsg = NLMSG_DATA(ctx->hdr); + + len = ctx->hdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)); + if (len < 0) { + netlink_msg_ctx_set_err(ctx, "Bad message length"); + return 0; + } + + if (!parse_rtattrs(ctx, RTM_RTA(ctx->rtmsg), len)) + return 0; + + rtattrs = ctx->rtattrs; + + ctx->dest = rtattrs[RTA_DST]; + ctx->src = rtattrs[RTA_PREFSRC]; + + rtattr = rtattrs[RTA_PRIORITY]; + if (rtattr) + ctx->metric = (int *)RTA_DATA(rtattr); + + rtattr = rtattrs[RTA_NH_ID]; + if (rtattr) + ctx->nhgid = (unsigned int *)RTA_DATA(rtattr); + + gateway = rtattrs[RTA_GATEWAY]; + oif = rtattrs[RTA_OIF]; + if (gateway || oif) { + struct rtattr *tb[RTA_MAX + 1] = { 0 }; + uint16_t encap_type = 0; + uint32_t vxlan_vni = 0; + + if_index = 0; + if (oif) + if_index = *((int *)RTA_DATA(oif)); + + + if (rtattrs[RTA_ENCAP]) { + const char *err_msg; + + parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]), + rtattrs[RTA_ENCAP]->rta_len - + sizeof(struct rtattr), + tb, ARRAY_SIZE(tb), &err_msg); + } + + if (rtattrs[RTA_ENCAP_TYPE]) + encap_type = + *(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]); + + if (tb[0]) + vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]); + + netlink_msg_ctx_add_nh(ctx, if_index, gateway, encap_type, + vxlan_vni); + } + + rtattr = rtattrs[RTA_MULTIPATH]; + if (rtattr) + parse_multipath_attr(ctx, rtattr); + + return 1; +} + +/* + * addr_to_s + */ +static const char * +addr_to_s(unsigned char family, void *addr) +{ + size_t buf_len; + char *buf; + + buf = get_print_buf(&buf_len); + + return inet_ntop(family, addr, buf, buf_len); +} + +/* + * netlink_msg_ctx_print + */ +static int netlink_msg_ctx_snprint(struct netlink_msg_ctx *ctx, char *buf, + size_t buf_len) +{ + struct nlmsghdr *hdr; + struct rtmsg *rtmsg; + struct netlink_nh *nh; + char *cur, *end; + unsigned long i; + + hdr = ctx->hdr; + rtmsg = ctx->rtmsg; + + cur = buf; + end = buf + buf_len; + + cur += snprintf(cur, end - cur, "%s %s/%d, Prot: %s(%u)", + netlink_msg_type_to_s(hdr->nlmsg_type), + addr_to_s(rtmsg->rtm_family, RTA_DATA(ctx->dest)), + rtmsg->rtm_dst_len, + netlink_prot_to_s(rtmsg->rtm_protocol), + rtmsg->rtm_protocol); + + if (ctx->metric) + cur += snprintf(cur, end - cur, ", Metric: %d", *ctx->metric); + + if (ctx->nhgid) + cur += snprintf(cur, end - cur, ", nhgid: %u", *ctx->nhgid); + for (i = 0; i < ctx->num_nhs; i++) { + cur += snprintf(cur, end - cur, "\n "); + nh = &ctx->nhs[i]; + + if (nh->gateway) { + cur += snprintf(cur, end - cur, " %s", + addr_to_s(rtmsg->rtm_family, + RTA_DATA(nh->gateway))); + } + + if (nh->if_index) { + cur += snprintf(cur, end - cur, " via interface %d", + nh->if_index); + } + + if (nh->encap_type) + cur += snprintf(cur, end - cur, + ", Encap Type: %u Vxlan vni %u", + nh->encap_type, nh->vxlan_vni); + } + + return cur - buf; +} + +/* + * print_netlink_msg_ctx + */ +static void print_netlink_msg_ctx(struct netlink_msg_ctx *ctx) +{ + char buf[1024]; + + netlink_msg_ctx_snprint(ctx, buf, sizeof(buf)); + printf("%s\n", buf); +} + +static void fpm_listener_hexdump(const void *mem, size_t len) +{ + char line[64]; + const uint8_t *src = mem; + const uint8_t *end = src + len; + + if (!glob->dump_hex) + return; + + if (len == 0) { + printf("%016lx: (zero length / no data)\n", (long)src); + return; + } + + while (src < end) { + struct fbuf fb = { + .buf = line, + .pos = line, + .len = sizeof(line), + }; + const uint8_t *lineend = src + 8; + uint32_t line_bytes = 0; + + printf("%016lx: ", (long)src); + + while (src < lineend && src < end) { + printf("%02x ", *src++); + line_bytes++; + } + if (line_bytes < 8) + printf("%*s", (8 - line_bytes) * 3, ""); + + src -= line_bytes; + while (src < lineend && src < end && fb.pos < fb.buf + fb.len) { + uint8_t byte = *src++; + + if (isprint(byte)) + *fb.pos++ = byte; + else + *fb.pos++ = '.'; + } + printf("\n"); + } +} + +/* + * parse_netlink_msg + */ +static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm) +{ + struct netlink_msg_ctx ctx_space, *ctx; + struct nlmsghdr *hdr; + unsigned int len; + + fpm_listener_hexdump(buf, buf_len); + ctx = &ctx_space; + + hdr = (struct nlmsghdr *)buf; + len = buf_len; + for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) { + + netlink_msg_ctx_init(ctx); + ctx->hdr = hdr; + + switch (hdr->nlmsg_type) { + + case RTM_DELROUTE: + case RTM_NEWROUTE: + + parse_route_msg(ctx); + if (ctx->err_msg) { + fprintf(stderr, + "Error parsing route message: %s\n", + ctx->err_msg); + } + + print_netlink_msg_ctx(ctx); + + if (glob->reflect && hdr->nlmsg_type == RTM_NEWROUTE && + ctx->rtmsg->rtm_protocol > RTPROT_STATIC) { + printf(" Route %s(%u) reflecting back\n", + netlink_prot_to_s( + ctx->rtmsg->rtm_protocol), + ctx->rtmsg->rtm_protocol); + ctx->rtmsg->rtm_flags |= RTM_F_OFFLOAD; + write(glob->sock, fpm, fpm_msg_len(fpm)); + } + break; + + default: + fprintf(stdout, + "Ignoring netlink message - Type: %s(%d)\n", + netlink_msg_type_to_s(hdr->nlmsg_type), + hdr->nlmsg_type); + } + } +} + +/* + * process_fpm_msg + */ +static void process_fpm_msg(fpm_msg_hdr_t *hdr) +{ + fprintf(stdout, "FPM message - Type: %d, Length %d\n", hdr->msg_type, + ntohs(hdr->msg_len)); + + if (hdr->msg_type != FPM_MSG_TYPE_NETLINK) { + fprintf(stderr, "Unknown fpm message type %u\n", hdr->msg_type); + return; + } + + parse_netlink_msg(fpm_msg_data(hdr), fpm_msg_data_len(hdr), hdr); +} + +/* + * fpm_serve + */ +static void fpm_serve(void) +{ + char buf[FPM_MAX_MSG_LEN * 4]; + fpm_msg_hdr_t *hdr; + + while (1) { + + hdr = read_fpm_msg(buf, sizeof(buf)); + if (!hdr) + return; + + process_fpm_msg(hdr); + } +} + +int main(int argc, char **argv) +{ + pid_t daemon; + int r; + bool fork_daemon = false; + + memset(glob, 0, sizeof(*glob)); + + while ((r = getopt(argc, argv, "rdv")) != -1) { + switch (r) { + case 'r': + glob->reflect = true; + break; + case 'd': + fork_daemon = true; + break; + case 'v': + glob->dump_hex = true; + break; + } + } + + if (fork_daemon) { + daemon = fork(); + + if (daemon) + exit(0); + } + + if (!create_listen_sock(FPM_DEFAULT_PORT, &glob->server_sock)) + exit(1); + + /* + * Server forever. + */ + while (1) { + glob->sock = accept_conn(glob->server_sock); + fpm_serve(); + fprintf(stdout, "Done serving client"); + } +} +#else + +int main(int argc, char **argv) +{ + fprintf(stderr, "This program only works on linux"); + exit(-1); +} +#endif diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 5f096e3..3233519 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -1473,7 +1473,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifi = NLMSG_DATA(h); - /* assume if not default zns, then new VRF */ if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) { /* If this is not link add/delete message so print warning. */ zlog_debug("%s: wrong kernel message %s", __func__, diff --git a/zebra/interface.c b/zebra/interface.c index 5ce222c..b3adc44 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -108,17 +108,6 @@ static void zebra_if_node_destroy(route_table_delegate_t *delegate, route_node_destroy(delegate, table, node); } -static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if) -{ - nhg_connected_tree_free(&zebra_if->nhg_dependents); -} - -static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if) -{ - nhg_connected_tree_init(&zebra_if->nhg_dependents); -} - - route_table_delegate_t zebra_if_table_delegate = { .create_node = route_node_create, .destroy_node = zebra_if_node_destroy}; @@ -137,7 +126,7 @@ static int if_zebra_new_hook(struct interface *ifp) zebra_if->link_nsid = NS_UNKNOWN; - zebra_if_nhg_dependents_init(zebra_if); + nhg_connected_tree_init(&zebra_if->nhg_dependents); zebra_ptm_if_init(zebra_if); @@ -187,6 +176,10 @@ static void if_nhg_dependents_release(const struct interface *ifp) frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) { rb_node_dep->nhe->ifp = NULL; /* Null it out */ zebra_nhg_check_valid(rb_node_dep->nhe); + if (CHECK_FLAG(rb_node_dep->nhe->flags, + NEXTHOP_GROUP_KEEP_AROUND) && + rb_node_dep->nhe->refcnt == 1) + zebra_nhg_decrement_ref(rb_node_dep->nhe); } } @@ -221,7 +214,7 @@ static int if_zebra_delete_hook(struct interface *ifp) zebra_evpn_mac_ifp_del(ifp); if_nhg_dependents_release(ifp); - zebra_if_nhg_dependents_free(zebra_if); + nhg_connected_tree_free(&zebra_if->nhg_dependents); XFREE(MTYPE_ZIF_DESC, zebra_if->desc); @@ -954,47 +947,6 @@ static void if_down_del_nbr_connected(struct interface *ifp) } } -void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe); - } -} - -void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe); - } -} - -unsigned int if_nhg_dependents_count(const struct interface *ifp) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - return nhg_connected_tree_count(&zif->nhg_dependents); - } - - return 0; -} - - -bool if_nhg_dependents_is_empty(const struct interface *ifp) -{ - if (ifp->info) { - struct zebra_if *zif = (struct zebra_if *)ifp->info; - - return nhg_connected_tree_is_empty(&zif->nhg_dependents); - } - - return false; -} - /* Interface is up. */ void if_up(struct interface *ifp, bool install_connected) { @@ -1022,6 +974,14 @@ void if_up(struct interface *ifp, bool install_connected) if (install_connected) if_install_connected(ifp); + /* + * Interface associated NHG's have been deleted on + * interface down events, now that this interface + * is coming back up, let's resync the zebra -> dplane + * nhg's so that they can be continued to be used. + */ + zebra_interface_nhg_reinstall(ifp); + /* Handle interface up for specific types for EVPN. Non-VxLAN interfaces * are checked to see if (remote) neighbor entries need to be installed * on them for ARP suppression. @@ -1523,23 +1483,27 @@ static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex, "DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u", name, ifindex, tableid); - if (!vrf_lookup_by_id((vrf_id_t)ifindex)) { - vrf_id_t exist_id; + /* + * For a given tableid, if there already exists a vrf and it + * is different from the current vrf to be operated, then there + * is a misconfiguration and zebra will exit. + */ + vrf_id_t exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); - exist_id = zebra_vrf_lookup_by_table(tableid, ns_id); - if (exist_id != VRF_DEFAULT) { - vrf = vrf_lookup_by_id(exist_id); + if (exist_id != VRF_DEFAULT) { + vrf = vrf_lookup_by_id(exist_id); - if (vrf) - flog_err(EC_ZEBRA_VRF_MISCONFIGURED, - "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", - name, ifindex, vrf->name, - vrf->vrf_id); - else - flog_err(EC_ZEBRA_VRF_NOT_FOUND, - "VRF %s id %u does not exist", - name, ifindex); + if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) { + flog_err(EC_ZEBRA_VRF_NOT_FOUND, + "VRF %s id %u does not exist", name, + ifindex); + exit(-1); + } + if (vrf && strcmp(name, vrf->name)) { + flog_err(EC_ZEBRA_VRF_MISCONFIGURED, + "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting", + name, ifindex, vrf->name, vrf->vrf_id); exit(-1); } } @@ -1696,8 +1660,10 @@ static void interface_if_protodown(struct interface *ifp, bool protodown, uint32_t rc_bitfield) { struct zebra_if *zif = ifp->info; - bool old_protodown; + bool old_protodown, reason_extern; + reason_extern = !!CHECK_FLAG(zif->protodown_rc, + ZEBRA_PROTODOWN_EXTERNAL); /* * Set our reason code to note it wasn't us. * If the reason we got from the kernel is ONLY frr though, don't @@ -1713,8 +1679,8 @@ static void interface_if_protodown(struct interface *ifp, bool protodown, return; if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE) - zlog_debug("interface %s dplane change, protodown %s", - ifp->name, protodown ? "on" : "off"); + zlog_debug("interface %s dplane change, protodown %s curr reason_extern %u", + ifp->name, protodown ? "on" : "off", reason_extern); /* Set protodown, respectively */ COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown); @@ -1739,6 +1705,13 @@ static void interface_if_protodown(struct interface *ifp, bool protodown, return; } + if (!protodown && reason_extern) { + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("bond member %s has protodown reason external and clear the reason, skip reinstall.", + ifp->name); + return; + } + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "bond mbr %s reinstate protodown %s in the dplane", diff --git a/zebra/interface.h b/zebra/interface.h index 7d633f3..8d19c18 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -331,11 +331,6 @@ void link_param_cmd_set_float(struct interface *ifp, float *field, void link_param_cmd_unset(struct interface *ifp, uint32_t type); /* Nexthop group connected functions */ -extern void if_nhg_dependents_add(struct interface *ifp, - struct nhg_hash_entry *nhe); -extern void if_nhg_dependents_del(struct interface *ifp, - struct nhg_hash_entry *nhe); -extern unsigned int if_nhg_dependents_count(const struct interface *ifp); extern bool if_nhg_dependents_is_empty(const struct interface *ifp); extern void vrf_add_update(struct vrf *vrfp); diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index 8a64a1e..d2f1db6 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -619,6 +619,11 @@ static void netlink_install_filter(int sock, uint32_t pid, uint32_t dplane_pid) safe_strerror(errno)); } +/* + * Please note, the assumption with this function is that the + * flags passed in that are bit masked with type, we are implicitly + * assuming that this is handling the NLA_F_NESTED ilk. + */ void netlink_parse_rtattr_flags(struct rtattr **tb, int max, struct rtattr *rta, int len, unsigned short flags) { @@ -638,8 +643,19 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta, { memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); while (RTA_OK(rta, len)) { - if (rta->rta_type <= max) - tb[rta->rta_type] = rta; + /* + * The type may be &'ed with NLA_F_NESTED + * which puts data in the upper 8 bits of the + * rta_type. Mask it off and save the actual + * underlying value to be placed into the array. + * This way we don't accidently crash in the future + * when the kernel sends us new data and we try + * to write well beyond the end of the array. + */ + uint16_t type = rta->rta_type & NLA_TYPE_MASK; + + if (type <= max) + tb[type] = rta; rta = RTA_NEXT(rta, len); } } diff --git a/zebra/main.c b/zebra/main.c index 27e05e7..ea1e1cb 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -26,6 +26,7 @@ #include "routemap.h" #include "routing_nb.h" #include "mgmt_be_client.h" +#include "libagentx.h" #include "zebra/zebra_router.h" #include "zebra/zebra_errors.h" @@ -203,6 +204,7 @@ static void sigint(void) rib_update_finish(); list_delete(&zrouter.client_list); + list_delete(&zrouter.stale_client_list); /* * Besides other clean-ups zebra's vrf_disable() also enqueues installed @@ -434,6 +436,7 @@ int main(int argc, char **argv) zrouter.master = frr_init(); /* Zebra related initialize. */ + libagentx_init(); zebra_router_init(asic_offload, notify_on_ack, v6_with_v4_nexthop); zserv_init(); zebra_rib_init(); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 70ace35..11c1330 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -605,10 +605,6 @@ void zebra_interface_address_add_update(struct interface *ifp, client, ifp, ifc); } } - /* interface associated NHGs may have been deleted, - * re-sync zebra -> dplane NHGs - */ - zebra_interface_nhg_reinstall(ifp); } /* Interface address deletion. */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f092fc5..01b527e 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1550,7 +1550,7 @@ static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen, srh->first_segment = segs->num_segs - 1; for (i = 0; i < segs->num_segs; i++) { - memcpy(&srh->segments[i], &segs->seg[i], + memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i], sizeof(struct in6_addr)); } @@ -1683,6 +1683,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p, sizeof(struct in_addr))) return false; break; + case ZEBRA_SEG6_LOCAL_ACTION_END_DX6: + if (!nl_attr_put32(nlmsg, req_size, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DX6)) + return false; + if (!nl_attr_put(nlmsg, req_size, + SEG6_LOCAL_NH6, &ctx->nh6, + sizeof(struct in_addr))) + return false; + break; case ZEBRA_SEG6_LOCAL_ACTION_END_DT6: if (!nl_attr_put32(nlmsg, req_size, SEG6_LOCAL_ACTION, @@ -1714,7 +1724,6 @@ static bool _netlink_route_build_singlepath(const struct prefix *p, return false; break; case ZEBRA_SEG6_LOCAL_ACTION_END_DX2: - case ZEBRA_SEG6_LOCAL_ACTION_END_DX6: case ZEBRA_SEG6_LOCAL_ACTION_END_B6: case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP: case ZEBRA_SEG6_LOCAL_ACTION_END_BM: @@ -1882,6 +1891,36 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen, return true; } +/* + * The function returns true if the attribute could be added + * to the message, otherwise false is returned. + */ +static int netlink_route_nexthop_encap(bool fpm, struct nlmsghdr *n, + size_t nlen, const struct nexthop *nh) +{ + struct rtattr *nest; + + if (!fpm) + return true; + + switch (nh->nh_encap_type) { + case NET_VXLAN: + if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type)) + return false; + + nest = nl_attr_nest(n, nlen, RTA_ENCAP); + if (!nest) + return false; + + if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni)) + return false; + nl_attr_nest_end(n, nest); + break; + } + + return true; +} + /* This function takes a nexthop as argument and * appends to the given netlink msg. If the nexthop * defines a preferred source, the src parameter @@ -1900,10 +1939,13 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen, * The function returns true if the nexthop could be added * to the message, otherwise false is returned. */ -static bool _netlink_route_build_multipath( - const struct prefix *p, const char *routedesc, int bytelen, - const struct nexthop *nexthop, struct nlmsghdr *nlmsg, size_t req_size, - struct rtmsg *rtmsg, const union g_addr **src, route_tag_t tag) +static bool _netlink_route_build_multipath(const struct prefix *p, + const char *routedesc, int bytelen, + const struct nexthop *nexthop, + struct nlmsghdr *nlmsg, + size_t req_size, struct rtmsg *rtmsg, + const union g_addr **src, + route_tag_t tag, bool fpm) { char label_buf[256]; struct vrf *vrf; @@ -2011,6 +2053,13 @@ static bool _netlink_route_build_multipath( if (!_netlink_set_tag(nlmsg, req_size, tag)) return false; + /* + * Add encapsulation information when installing via + * FPM. + */ + if (!netlink_route_nexthop_encap(fpm, nlmsg, req_size, nexthop)) + return false; + nl_attr_rtnh_end(nlmsg, rtnh); return true; } @@ -2045,7 +2094,7 @@ _netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc, bytelen = (family == AF_INET ? 4 : 16); return _netlink_route_build_multipath(p, routedesc, bytelen, nhlfe->nexthop, nlmsg, req_size, - rtmsg, src, 0); + rtmsg, src, 0, false); } static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc) @@ -2141,34 +2190,6 @@ static bool nexthop_set_src(const struct nexthop *nexthop, int family, } /* - * The function returns true if the attribute could be added - * to the message, otherwise false is returned. - */ -static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen, - struct nexthop *nh) -{ - struct rtattr *nest; - - switch (nh->nh_encap_type) { - case NET_VXLAN: - if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type)) - return false; - - nest = nl_attr_nest(n, nlen, RTA_ENCAP); - if (!nest) - return false; - - if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, - nh->nh_encap.vni)) - return false; - nl_attr_nest_end(n, nest); - break; - } - - return true; -} - -/* * Routing table change via netlink interface, using a dataplane context object * * Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer @@ -2360,6 +2381,14 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx break; setsrc = nexthop_set_src(nexthop, p->family, &src); + if (setsrc && IS_ZEBRA_DEBUG_KERNEL) { + if (p->family == AF_INET) + zlog_debug("%s: %pFX set src %pI4", + __func__, p, &src.ipv4); + else if (p->family == AF_INET6) + zlog_debug("%s: %pFX set src %pI6", + __func__, p, &src.ipv6); + } } if (setsrc) { @@ -2402,6 +2431,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx setsrc = nexthop_set_src(nexthop, p->family, &src); + if (setsrc && IS_ZEBRA_DEBUG_KERNEL) { + if (p->family == AF_INET) + zlog_debug("%s: %pFX set src %pI4", + __func__, p, + &src.ipv4); + else if (p->family == AF_INET6) + zlog_debug("%s: %pFX set src %pI6", + __func__, p, + &src.ipv6); + } continue; } @@ -2422,12 +2461,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx * Add encapsulation information when * installing via FPM. */ - if (fpm) { - if (!netlink_route_nexthop_encap(&req->n, - datalen, - nexthop)) - return 0; - } + if (!netlink_route_nexthop_encap(fpm, &req->n, + datalen, + nexthop)) + return 0; nexthop_num++; break; @@ -2463,6 +2500,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx setsrc = nexthop_set_src(nexthop, p->family, &src); + if (setsrc && IS_ZEBRA_DEBUG_KERNEL) { + if (p->family == AF_INET) + zlog_debug("%s: %pFX set src %pI4", + __func__, p, + &src.ipv4); + else if (p->family == AF_INET6) + zlog_debug("%s: %pFX set src %pI6", + __func__, p, + &src.ipv6); + } continue; } @@ -2472,22 +2519,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx : "multipath"; nexthop_num++; - if (!_netlink_route_build_multipath( - p, routedesc, bytelen, nexthop, - &req->n, datalen, &req->r, &src1, - tag)) + if (!_netlink_route_build_multipath(p, routedesc, + bytelen, + nexthop, + &req->n, + datalen, + &req->r, + &src1, tag, + fpm)) return 0; - /* - * Add encapsulation information when installing via - * FPM. - */ - if (fpm) { - if (!netlink_route_nexthop_encap( - &req->n, datalen, nexthop)) - return 0; - } - if (!setsrc && src1) { if (p->family == AF_INET) src.ipv4 = src1->ipv4; @@ -2931,6 +2972,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, sizeof(struct in_addr))) return 0; break; + case SEG6_LOCAL_ACTION_END_DX6: + if (!nl_attr_put32(&req->n, + buflen, + SEG6_LOCAL_ACTION, + SEG6_LOCAL_ACTION_END_DX6)) + return 0; + if (!nl_attr_put(&req->n, buflen, + SEG6_LOCAL_NH6, + &ctx->nh6, + sizeof(struct in_addr))) + return 0; + break; case SEG6_LOCAL_ACTION_END_DT6: if (!nl_attr_put32( &req->n, buflen, diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 6aca643..470391d 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -184,13 +184,13 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf, static void rtadv_send_packet(int sock, struct interface *ifp, enum ipv6_nd_suppress_ra_status stop) { - struct msghdr msg; - struct iovec iov; + struct msghdr msg = { 0 }; + struct iovec iov = { 0 }; struct cmsghdr *cmsgptr; struct in6_pktinfo *pkt; - struct sockaddr_in6 addr; - unsigned char buf[RTADV_MSG_SIZE]; - char adata[RTADV_ADATA_SIZE]; + struct sockaddr_in6 addr = { 0 }; + unsigned char buf[RTADV_MSG_SIZE] = { 0 }; + char adata[RTADV_ADATA_SIZE] = { 0 }; struct nd_router_advert *rtadv; int ret; diff --git a/zebra/subdir.am b/zebra/subdir.am index d9c8d90..f767447 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -19,6 +19,12 @@ if LINUX module_LTLIBRARIES += zebra/zebra_cumulus_mlag.la endif +#if FPM_LISTENER +sbin_PROGRAMS += zebra/fpm_listener +zebra_fpm_listener_SOURCES = zebra/fpm_listener.c +zebra_fpm_listener_LDADD = lib/libfrr.la +#endf + # Dataplane sample plugin if DEV_BUILD module_LTLIBRARIES += zebra/dplane_sample_plugin.la @@ -116,6 +122,7 @@ zebra_zebra_SOURCES = \ clippy_scan += \ zebra/debug.c \ + zebra/dplane_fpm_nl.c \ zebra/interface.c \ zebra/rtadv.c \ zebra/zebra_mlag_vty.c \ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 76cabd1..d585ef9 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1724,7 +1724,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, * Let's convert the weights to a scaled value * between 1 and zrouter.nexthop_weight_scale_value * This is a simple application of a ratio: - * scaled_weight/zrouter.nexthop_weight_scale_value = + * scaled_weight/zrouter.nexthop_weight_scale_value = * weight/max_weight * This translates to: * scaled_weight = weight * zrouter.nexthop_weight_scale_value @@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p, for (i = 0; i < nexthop_num; i++) { znh = &nhops[i]; - tmp = (uint64_t)znh->weight * - zrouter.nexthop_weight_scale_value; - znh->weight = MAX(1, ((uint32_t)(tmp / max_weight))); + tmp = znh->weight * zrouter.nexthop_weight_scale_value; + znh->weight = MAX(1, (tmp / max_weight)); } } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 99693a5..3944876 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -39,6 +39,13 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes"); # define AOK 0 #endif +/* + * Dataplane API version. This must be updated when any incompatible changes + * are made. The minor version (at least) should be updated when new APIs + * are introduced. + */ +static uint32_t zdplane_version = MAKE_FRRVERSION(2, 0, 0); + /* Control for collection of extra interface info with route updates; a plugin * can enable the extra info via a dplane api. */ @@ -664,6 +671,12 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp, * Public APIs */ +/* Access the dplane API version */ +uint32_t zebra_dplane_get_version(void) +{ + return zdplane_version; +} + /* Obtain thread_master for dataplane thread */ struct event_loop *dplane_get_thread_master(void) { @@ -6351,7 +6364,7 @@ dplane_provider_dequeue_out_ctx(struct zebra_dplane_provider *prov) */ bool dplane_provider_is_threaded(const struct zebra_dplane_provider *prov) { - return (prov->dp_flags & DPLANE_PROV_FLAG_THREADED); + return CHECK_FLAG(prov->dp_flags, DPLANE_PROV_FLAG_THREADED); } #ifdef HAVE_NETLINK @@ -7428,6 +7441,11 @@ static void dplane_thread_loop(struct event *event) zlog_debug("dplane dequeues %d completed work from provider %s", counter, dplane_provider_get_name(prov)); + if (event_should_yield(event)) { + reschedule = true; + break; + } + /* Locate next provider */ prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov); } diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 2f7d218..060b1c8 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -24,6 +24,13 @@ extern "C" { #endif +/* Retrieve the dataplane API version number; see libfrr.h to decode major, + * minor, sub version values. + * Plugins should pay attention to the major version number, at least, to + * be able to detect API changes that may not be backward-compatible. + */ +uint32_t zebra_dplane_get_version(void); + /* Key netlink info from zebra ns */ struct zebra_dplane_info { ns_id_t ns_id; diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c index 147f5b9..ebb5a42 100644 --- a/zebra/zebra_evpn.c +++ b/zebra/zebra_evpn.c @@ -109,21 +109,14 @@ void zebra_evpn_print(struct zebra_evpn *zevpn, void **ctxt) } else { json_object_int_add(json, "vni", zevpn->vni); json_object_string_add(json, "type", "L2"); -#if CONFDATE > 20240210 -CPP_NOTICE("Drop `vrf` from JSON output") -#endif - json_object_string_add(json, "vrf", - vrf_id_to_name(zevpn->vrf_id)); - json_object_string_add(json, "tenantVrf", - vrf_id_to_name(zevpn->vrf_id)); + json_object_string_add(json, "tenantVrf", vrf_id_to_name(zevpn->vrf_id)); } if (!zevpn->vxlan_if) { // unexpected if (json == NULL) vty_out(vty, " VxLAN interface: unknown\n"); else - json_object_string_add(json, "vxlanInterface", - "unknown"); + json_object_string_add(json, "vxlanInterface", "unknown"); return; } num_macs = num_valid_macs(zevpn); @@ -135,35 +128,21 @@ CPP_NOTICE("Drop `vrf` from JSON output") (zevpn->svi_if ? zevpn->svi_if->name : "")); vty_out(vty, " SVI ifIndex: %u\n", (zevpn->svi_if ? zevpn->svi_if->ifindex : 0)); - vty_out(vty, " Local VTEP IP: %pI4\n", - &zevpn->local_vtep_ip); - vty_out(vty, " Mcast group: %pI4\n", - &zevpn->mcast_grp); + vty_out(vty, " Local VTEP IP: %pI4\n", &zevpn->local_vtep_ip); + vty_out(vty, " Mcast group: %pI4\n", &zevpn->mcast_grp); } else { - json_object_string_add(json, "vxlanInterface", - zevpn->vxlan_if->name); -#if CONFDATE > 20240210 -CPP_NOTICE("Drop `ifindex` from JSON output") -#endif - json_object_int_add(json, "ifindex", zevpn->vxlan_if->ifindex); - json_object_int_add(json, "vxlanIfindex", - zevpn->vxlan_if->ifindex); + json_object_string_add(json, "vxlanInterface", zevpn->vxlan_if->name); + json_object_int_add(json, "vxlanIfindex", zevpn->vxlan_if->ifindex); if (zevpn->svi_if) { - json_object_string_add(json, "sviInterface", - zevpn->svi_if->name); - json_object_int_add(json, "sviIfindex", - zevpn->svi_if->ifindex); + json_object_string_add(json, "sviInterface", zevpn->svi_if->name); + json_object_int_add(json, "sviIfindex", zevpn->svi_if->ifindex); } - json_object_string_addf(json, "vtepIp", "%pI4", - &zevpn->local_vtep_ip); - json_object_string_addf(json, "mcastGroup", "%pI4", - &zevpn->mcast_grp); + json_object_string_addf(json, "vtepIp", "%pI4", &zevpn->local_vtep_ip); + json_object_string_addf(json, "mcastGroup", "%pI4", &zevpn->mcast_grp); json_object_string_add(json, "advertiseGatewayMacip", - zevpn->advertise_gw_macip ? "Yes" - : "No"); + zevpn->advertise_gw_macip ? "Yes" : "No"); json_object_string_add(json, "advertiseSviMacip", - zevpn->advertise_svi_macip ? "Yes" - : "No"); + zevpn->advertise_svi_macip ? "Yes" : "No"); json_object_int_add(json, "numMacs", num_macs); json_object_int_add(json, "numArpNd", num_neigh); } @@ -179,28 +158,21 @@ CPP_NOTICE("Drop `ifindex` from JSON output") json_vtep_list = json_object_new_array(); for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { const char *flood_str = lookup_msg( - zvtep_flood_str, zvtep->flood_control, - VXLAN_FLOOD_STR_DEFAULT); + zvtep_flood_str, zvtep->flood_control, VXLAN_FLOOD_STR_DEFAULT); if (json == NULL) { - vty_out(vty, " %pI4 flood: %s\n", - &zvtep->vtep_ip, - flood_str); + vty_out(vty, " %pI4 flood: %s\n", &zvtep->vtep_ip, flood_str); } else { json_vtep = json_object_new_object(); - json_object_string_addf(json_vtep, "ip", "%pI4", - &zvtep->vtep_ip); - json_object_string_add(json_vtep, "flood", - flood_str); - json_object_array_add(json_vtep_list, - json_vtep); + json_object_string_addf(json_vtep, "ip", "%pI4", &zvtep->vtep_ip); + json_object_string_add(json_vtep, "flood", flood_str); + json_object_array_add(json_vtep_list, json_vtep); } num_vteps++; } if (json) { json_object_int_add(json, "numRemoteVteps", num_vteps); - json_object_object_add(json, "remoteVteps", - json_vtep_list); + json_object_object_add(json, "remoteVteps", json_vtep_list); } } if (json == NULL) { @@ -261,8 +233,7 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[]) json_object_int_add(json_evpn, "vni", zevpn->vni); json_object_string_add(json_evpn, "type", "L2"); json_object_string_add(json_evpn, "vxlanIf", - zevpn->vxlan_if ? zevpn->vxlan_if->name - : "unknown"); + zevpn->vxlan_if ? zevpn->vxlan_if->name : "unknown"); json_object_int_add(json_evpn, "numMacs", num_macs); json_object_int_add(json_evpn, "numArpNd", num_neigh); json_object_int_add(json_evpn, "numRemoteVteps", num_vteps); @@ -272,13 +243,10 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[]) json_vtep_list = json_object_new_array(); for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) { json_ip_str = json_object_new_string( - inet_ntop(AF_INET, &zvtep->vtep_ip, buf, - sizeof(buf))); - json_object_array_add(json_vtep_list, - json_ip_str); + inet_ntop(AF_INET, &zvtep->vtep_ip, buf, sizeof(buf))); + json_object_array_add(json_vtep_list, json_ip_str); } - json_object_object_add(json_evpn, "remoteVteps", - json_vtep_list); + json_object_object_add(json_evpn, "remoteVteps", json_vtep_list); } json_object_object_add(json, vni_str, json_evpn); } @@ -383,7 +351,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p, if (!client) return 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); zclient_create_header(s, cmd, vrf_id); stream_put(s, p, sizeof(struct prefix)); @@ -490,8 +458,7 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, struct zebra_evpn *zevpn, /* Remove neighbor from BGP. */ zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac, - n->flags, ZEBRA_NEIGH_ACTIVE, - false /*force*/); + n->flags, ZEBRA_NEIGH_ACTIVE, false /*force*/); /* Delete this neighbor entry. */ zebra_evpn_neigh_del(zevpn, n); @@ -521,8 +488,7 @@ void zebra_evpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket, */ if (zevpn->advertise_gw_macip) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", - zevpn->vni); + zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", zevpn->vni); return; } @@ -694,8 +660,7 @@ static int zebra_evpn_map_vlan_ns(struct ns *ns, if (zif->brslave_info.br_if != br_if) continue; - vni_id = - zebra_vxlan_if_access_vlan_vni_find(zif, br_if); + vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, br_if); if (vni_id) { found = 1; break; @@ -732,9 +697,7 @@ struct zebra_evpn *zebra_evpn_map_vlan(struct interface *ifp, in_param.zif = zif; p_zevpn = &zevpn; - ns_walk_func(zebra_evpn_map_vlan_ns, - (void *)&in_param, - (void **)p_zevpn); + ns_walk_func(zebra_evpn_map_vlan_ns, (void *)&in_param, (void **)p_zevpn); return zevpn; } @@ -854,9 +817,7 @@ struct zebra_evpn *zebra_evpn_from_svi(struct interface *ifp, return zevpn; } -static int zvni_map_to_macvlan_ns(struct ns *ns, - void *_in_param, - void **_p_ifp) +static int zvni_map_to_macvlan_ns(struct ns *ns, void *_in_param, void **_p_ifp) { struct zebra_ns *zns = ns->info; struct zebra_from_svi_param *in_param = @@ -918,9 +879,7 @@ struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if, p_ifp = &tmp_if; /* Identify corresponding VLAN interface. */ - ns_walk_func(zvni_map_to_macvlan_ns, - (void *)&in_param, - (void **)p_ifp); + ns_walk_func(zvni_map_to_macvlan_ns, (void *)&in_param, (void **)p_ifp); return tmp_if; } @@ -1125,8 +1084,7 @@ struct zebra_evpn *zebra_evpn_add(vni_t vni) /* Create hash table for MAC */ zevpn->mac_table = zebra_mac_db_create(buffer); - snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u", - vni); + snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u", vni); /* Create hash table for neighbors */ zevpn->neigh_table = zebra_neigh_db_create(buffer); @@ -1182,7 +1140,7 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn) svi_index = zevpn->svi_if ? zevpn->svi_if->ifindex : 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id()); stream_putl(s, zevpn->vni); @@ -1205,8 +1163,8 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn) client->vniadd_cnt++; rc = zserv_send_message(client, s); - if (!(zevpn->flags & ZEVPN_READY_FOR_BGP)) { - zevpn->flags |= ZEVPN_READY_FOR_BGP; + if (!CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) { + SET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP); /* once the EVPN is sent the ES-EVIs can also be replayed * to BGP */ @@ -1228,13 +1186,13 @@ int zebra_evpn_send_del_to_client(struct zebra_evpn *zevpn) if (!client) return 0; - if (zevpn->flags & ZEVPN_READY_FOR_BGP) { - zevpn->flags &= ~ZEVPN_READY_FOR_BGP; + if (CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) { + UNSET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP); /* the ES-EVIs must be removed from BGP before the EVPN is */ zebra_evpn_update_all_es(zevpn); } - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); stream_reset(s); zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id()); @@ -1350,8 +1308,7 @@ int zebra_evpn_vtep_install(struct zebra_evpn *zevpn, struct zebra_vtep *zvtep) if (is_vxlan_flooding_head_end() && (zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) { if (ZEBRA_DPLANE_REQUEST_FAILURE == - dplane_vtep_add(zevpn->vxlan_if, - &zvtep->vtep_ip, zevpn->vni)) + dplane_vtep_add(zevpn->vxlan_if, &zvtep->vtep_ip, zevpn->vni)) return -1; } @@ -1442,9 +1399,7 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn, zevpn->vni, macaddr, ipa_len ? " IP " : "", - ipa_len ? ipaddr2str(ipaddr, ipbuf, - sizeof(ipbuf)) - : "", + ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", sticky ? " sticky" : "", remote_gw ? " remote_gw" : ""); return; @@ -1459,16 +1414,13 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn, mac = zebra_evpn_mac_lookup(zevpn, macaddr); if (!mac) { mac = zebra_evpn_proc_sync_mac_update(zevpn, macaddr, - ipa_len, ipaddr, - flags, seq, esi); + ipa_len, ipaddr, flags, seq, esi); } if (!mac) return; n = zebra_evpn_neigh_lookup(zevpn, ipaddr); - if (n - && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq, - true)) + if (n && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq, true)) return; zebra_evpn_proc_sync_neigh_update(zevpn, n, ipa_len, ipaddr, @@ -1514,22 +1466,19 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr, * SYNC - if ES is local * REMOTE - if ES is not local */ - if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) { + if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH)) { struct zebra_evpn_es *es; es = zebra_evpn_es_find(esi); - if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) { + if (es && CHECK_FLAG(es->flags, ZEBRA_EVPNES_READY_FOR_BGP)) { zebra_evpn_process_sync_macip_add(zevpn, macaddr, - ipa_len, ipaddr, - flags, seq, esi); + ipa_len, ipaddr, flags, seq, esi); } else { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) { char esi_str[ESI_STR_LEN]; esi_to_str(esi, esi_str, sizeof(esi_str)); - zlog_debug( - "Ignore sync-macip add; ES %s is not ready", - esi_str); + zlog_debug("Ignore sync-macip add; ES %s is not ready", esi_str); } } @@ -1543,8 +1492,7 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr, if (vtep_ip.s_addr) { zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip); if (!zvtep) { - zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, - VXLAN_FLOOD_DISABLED); + zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, VXLAN_FLOOD_DISABLED); if (!zvtep) { flog_err( EC_ZEBRA_VTEP_ADD_FAILED, @@ -1621,9 +1569,7 @@ void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr, vnip = zebra_vxlan_if_vni_find(zif, vni); if (!vnip) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "VNI %u not in interface upon remote MACIP DEL", - vni); + zlog_debug("VNI %u not in interface upon remote MACIP DEL", vni); return; } diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c index 6d5cd66..bfc060d 100644 --- a/zebra/zebra_evpn_mac.c +++ b/zebra/zebra_evpn_mac.c @@ -103,9 +103,7 @@ static void zebra_evpn_mac_ifp_unlink(struct zebra_mac *zmac) if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) zlog_debug("VNI %d MAC %pEA unlinked from ifp %s (%u)", - zmac->zevpn->vni, - &zmac->macaddr, - ifp->name, ifp->ifindex); + zmac->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex); zif = ifp->info; list_delete_node(zif->mac_list, &zmac->ifp_listnode); @@ -122,7 +120,7 @@ void zebra_evpn_mac_ifp_del(struct interface *ifp) if (zif->mac_list) { if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) zlog_debug("MAC list deleted for ifp %s (%u)", - zif->ifp->name, zif->ifp->ifindex); + zif->ifp->name, zif->ifp->ifindex); for (ALL_LIST_ELEMENTS_RO(zif->mac_list, node, zmac)) { zebra_evpn_mac_ifp_unlink(zmac); @@ -161,9 +159,7 @@ static void zebra_evpn_mac_ifp_link(struct zebra_mac *zmac, if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) zlog_debug("VNI %d MAC %pEA linked to ifp %s (%u)", - zmac->zevpn->vni, - &zmac->macaddr, - ifp->name, ifp->ifindex); + zmac->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex); zmac->ifp = ifp; listnode_init(&zmac->ifp_listnode, zmac); @@ -205,7 +201,7 @@ int zebra_evpn_rem_mac_install(struct zebra_evpn *zevpn, struct zebra_mac *mac, return -1; sticky = !!CHECK_FLAG(mac->flags, - (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)); + (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)); /* If nexthop group for the FDB entry is inactive (not programmed in * the dataplane) the MAC entry cannot be installed @@ -249,7 +245,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn, enum zebra_dplane_result res; /* If the MAC was not installed there is no need to uninstall it */ - if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE)) + if (!force && mac->es && !CHECK_FLAG(mac->es->flags, ZEBRA_EVPNES_NHG_ACTIVE)) return -1; if (!zevpn->vxlan_if) { @@ -282,8 +278,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn, ifp = zevpn->vxlan_if; vtep_ip = mac->fwd_info.r_vtep_ip; - res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni, - vtep_ip); + res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni, vtep_ip); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; else @@ -341,8 +336,7 @@ static void zebra_evpn_mac_get_access_info(struct zebra_mac *mac, *vid = mac->fwd_info.local.vid; zns = zebra_ns_lookup(mac->fwd_info.local.ns_id); - *p_ifp = if_lookup_by_index_per_ns(zns, - mac->fwd_info.local.ifindex); + *p_ifp = if_lookup_by_index_per_ns(zns, mac->fwd_info.local.ifindex); } } @@ -355,26 +349,19 @@ static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac *mac, char *buf, return buf; } - snprintfrr( - buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s", + snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s", CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "", - CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router " - : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "", - CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW " - : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "", - CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) - ? "PEER Active " - : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "PEER Active " : "", CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "", - CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) - ? "LOC Inactive " - : ""); + CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "LOC Inactive " : ""); return buf; } @@ -407,8 +394,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t) zlog_debug( "%s: duplicate addr mac %pEA flags %slearn count %u host count %u auto recovery expired", __func__, &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), mac->dad_count, listcount(mac->neigh_list)); } @@ -418,8 +404,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t) if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL)) ZEBRA_NEIGH_SET_INACTIVE(nbr); else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE)) - zebra_evpn_rem_neigh_install( - zevpn, nbr, false /*was_static*/); + zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/); } UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE); @@ -438,13 +423,11 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t) if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { /* Inform to BGP */ if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr, - mac->flags, mac->loc_seq, - mac->es)) + mac->flags, mac->loc_seq, mac->es)) return; /* Process all neighbors associated with this MAC. */ - zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, - 0 /*es_change*/); + zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, 0 /*es_change*/); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); @@ -479,8 +462,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, zlog_debug( "%s: duplicate addr MAC %pEA flags %sskip update to client, learn count %u recover time %u", __func__, &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), mac->dad_count, zvrf->dad_freeze_time); } /* For duplicate MAC do not update @@ -516,8 +498,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, zlog_debug( "%s: duplicate addr MAC %pEA flags %sdetection time passed, reset learn count %u", __func__, &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), mac->dad_count); } @@ -545,10 +526,10 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, if (mac->dad_count >= zvrf->dad_max_moves) { flog_warn(EC_ZEBRA_DUP_MAC_DETECTED, - "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4", - mac->zevpn->vni, &mac->macaddr, - is_local ? "local update, last" : - "remote update, from", &vtep_ip); + "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4", + mac->zevpn->vni, &mac->macaddr, + is_local ? "local update, last" : "remote update, from", + &vtep_ip); SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE); @@ -583,15 +564,13 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, zlog_debug( "%s: duplicate addr MAC %pEA flags %sauto recovery time %u start", __func__, &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), zvrf->dad_freeze_time); } event_add_timer(zrouter.master, - zebra_evpn_dad_mac_auto_recovery_exp, - mac, zvrf->dad_freeze_time, - &mac->dad_mac_auto_recovery_timer); + zebra_evpn_dad_mac_auto_recovery_exp, mac, + zvrf->dad_freeze_time, &mac->dad_mac_auto_recovery_timer); } /* In case of local update, do not inform to client (BGPd), @@ -638,22 +617,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) zebra_evpn_mac_get_access_info(mac, &ifp, &vid); json_object_string_add(json_mac, "type", "local"); if (ifp) { - json_object_string_add(json_mac, "intf", - ifp->name); - json_object_int_add(json_mac, "ifindex", - ifp->ifindex); + json_object_string_add(json_mac, "intf", ifp->name); + json_object_int_add(json_mac, "ifindex", ifp->ifindex); } if (vid) json_object_int_add(json_mac, "vlan", vid); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { json_object_string_add(json_mac, "type", "remote"); if (mac->es) - json_object_string_add(json_mac, "remoteEs", - mac->es->esi_str); + json_object_string_add(json_mac, "remoteEs", mac->es->esi_str); else json_object_string_addf( - json_mac, "remoteVtep", "%pI4", - &mac->fwd_info.r_vtep_ip); + json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) json_object_string_add(json_mac, "type", "auto"); @@ -664,12 +639,10 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) json_object_boolean_true_add(json_mac, "sviMac"); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) - json_object_boolean_true_add(json_mac, - "defaultGateway"); + json_object_boolean_true_add(json_mac, "defaultGateway"); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)) - json_object_boolean_true_add(json_mac, - "remoteGatewayMac"); + json_object_boolean_true_add(json_mac, "remoteGatewayMac"); json_object_string_add(json_mac, "uptime", up_str); json_object_int_add(json_mac, "localSequence", mac->loc_seq); @@ -690,46 +663,31 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)) json_object_boolean_true_add(json_mac, "peerActive"); if (mac->hold_timer) - json_object_string_add( - json_mac, "peerActiveHold", - event_timer_to_hhmmss(thread_buf, - sizeof(thread_buf), - mac->hold_timer)); + json_object_string_add(json_mac, "peerActiveHold", + event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer)); if (mac->es) - json_object_string_add(json_mac, "esi", - mac->es->esi_str); + json_object_string_add(json_mac, "esi", mac->es->esi_str); /* print all the associated neigh */ if (!listcount(mac->neigh_list)) json_object_string_add(json_mac, "neighbors", "none"); else { json_object *json_active_nbrs = json_object_new_array(); - json_object *json_inactive_nbrs = - json_object_new_array(); + json_object *json_inactive_nbrs = json_object_new_array(); json_object *json_nbrs = json_object_new_object(); for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { if (IS_ZEBRA_NEIGH_ACTIVE(n)) - json_object_array_add( - json_active_nbrs, - json_object_new_string( - ipaddr2str( - &n->ip, buf2, - sizeof(buf2)))); + json_object_array_add(json_active_nbrs, + json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2)))); else json_object_array_add( json_inactive_nbrs, - json_object_new_string( - ipaddr2str( - &n->ip, buf2, - sizeof(buf2)))); + json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2)))); } - json_object_object_add(json_nbrs, "active", - json_active_nbrs); - json_object_object_add(json_nbrs, "inactive", - json_inactive_nbrs); - json_object_object_add(json_mac, "neighbors", - json_nbrs); + json_object_object_add(json_nbrs, "active", json_active_nbrs); + json_object_object_add(json_nbrs, "inactive", json_inactive_nbrs); + json_object_object_add(json_mac, "neighbors", json_nbrs); } json_object_object_add(json, buf1, json_mac); @@ -746,18 +704,15 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) vty_out(vty, " ESI: %s\n", mac->es->esi_str); if (ifp) - vty_out(vty, " Intf: %s(%u)", ifp->name, - ifp->ifindex); + vty_out(vty, " Intf: %s(%u)", ifp->name, ifp->ifindex); else vty_out(vty, " Intf: -"); vty_out(vty, " VLAN: %u", vid); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { if (mac->es) - vty_out(vty, " Remote ES: %s", - mac->es->esi_str); + vty_out(vty, " Remote ES: %s", mac->es->esi_str); else - vty_out(vty, " Remote VTEP: %pI4", - &mac->fwd_info.r_vtep_ip); + vty_out(vty, " Remote VTEP: %pI4", &mac->fwd_info.r_vtep_ip); } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) { vty_out(vty, " Auto Mac "); } @@ -784,24 +739,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) vty_out(vty, " peer-active"); if (mac->hold_timer) vty_out(vty, " (ht: %s)", - event_timer_to_hhmmss(thread_buf, - sizeof(thread_buf), - mac->hold_timer)); + event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer)); vty_out(vty, "\n"); - vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq, - mac->rem_seq); + vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq, mac->rem_seq); vty_out(vty, " Uptime: %s\n", up_str); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) { vty_out(vty, " Duplicate, detected at %s", - time_to_string(mac->dad_dup_detect_time, - timebuf)); + time_to_string(mac->dad_dup_detect_time, timebuf)); } else if (mac->dad_count) { - monotime_since(&mac->detect_start_time, - &detect_start_time); + monotime_since(&mac->detect_start_time, &detect_start_time); if (detect_start_time.tv_sec <= zvrf->dad_time) { - time_to_string(mac->detect_start_time.tv_sec, - timebuf); + time_to_string(mac->detect_start_time.tv_sec, timebuf); vty_out(vty, " Duplicate detection started at %s, detection count %u\n", timebuf, mac->dad_count); @@ -816,9 +765,7 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json) for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) { vty_out(vty, " %s %s\n", ipaddr2str(&n->ip, buf2, sizeof(buf2)), - (IS_ZEBRA_NEIGH_ACTIVE(n) - ? "Active" - : "Inactive")); + (IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active" : "Inactive")); } } @@ -831,9 +778,9 @@ static char *zebra_evpn_print_mac_flags(struct zebra_mac *mac, char *flags_buf, { snprintf(flags_buf, flags_buf_sz, "%s%s%s%s", mac->sync_neigh_cnt ? "N" : "", - (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "", - (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "", - (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : ""); + CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "", + CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : ""); return flags_buf; } @@ -870,14 +817,12 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt) zebra_evpn_mac_get_access_info(mac, &ifp, &vid); if (json_mac_hdr == NULL) { vty_out(vty, "%-17s %-6s %-5s %-30s", buf1, "local", - zebra_evpn_print_mac_flags(mac, flags_buf, - sizeof(flags_buf)), + zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)), ifp ? ifp->name : "-"); } else { json_object_string_add(json_mac, "type", "local"); if (ifp) - json_object_string_add(json_mac, "intf", - ifp->name); + json_object_string_add(json_mac, "intf", ifp->name); } if (vid) { if (json_mac_hdr == NULL) @@ -891,18 +836,13 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt) vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq); vty_out(vty, "\n"); } else { - json_object_int_add(json_mac, "localSequence", - mac->loc_seq); - json_object_int_add(json_mac, "remoteSequence", - mac->rem_seq); - json_object_int_add(json_mac, "detectionCount", - mac->dad_count); + json_object_int_add(json_mac, "localSequence", mac->loc_seq); + json_object_int_add(json_mac, "remoteSequence", mac->rem_seq); + json_object_int_add(json_mac, "detectionCount", mac->dad_count); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - json_object_boolean_true_add(json_mac, - "isDuplicate"); + json_object_boolean_true_add(json_mac, "isDuplicate"); else - json_object_boolean_false_add(json_mac, - "isDuplicate"); + json_object_boolean_false_add(json_mac, "isDuplicate"); json_object_object_add(json_mac_hdr, buf1, json_mac); } @@ -910,19 +850,16 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt) } else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) - && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, - &wctx->r_vtep_ip)) + if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP) + && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip)) return; if (json_mac_hdr == NULL) { - if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP) + if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP) && (wctx->count == 0)) { vty_out(vty, "\nVNI %u\n\n", wctx->zevpn->vni); vty_out(vty, "%-17s %-6s %-5s%-30s %-5s %s\n", - "MAC", "Type", "Flags", - "Intf/Remote ES/VTEP", "VLAN", - "Seq #'s"); + "MAC", "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s"); } if (mac->es == NULL) inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip, @@ -930,32 +867,24 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt) vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1, "remote", - zebra_evpn_print_mac_flags(mac, flags_buf, - sizeof(flags_buf)), + zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)), mac->es ? mac->es->esi_str : addr_buf, "", mac->loc_seq, mac->rem_seq); } else { json_object_string_add(json_mac, "type", "remote"); if (mac->es) - json_object_string_add(json_mac, "remoteEs", - mac->es->esi_str); + json_object_string_add(json_mac, "remoteEs", mac->es->esi_str); else json_object_string_addf( - json_mac, "remoteVtep", "%pI4", - &mac->fwd_info.r_vtep_ip); + json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip); json_object_object_add(json_mac_hdr, buf1, json_mac); - json_object_int_add(json_mac, "localSequence", - mac->loc_seq); - json_object_int_add(json_mac, "remoteSequence", - mac->rem_seq); - json_object_int_add(json_mac, "detectionCount", - mac->dad_count); + json_object_int_add(json_mac, "localSequence", mac->loc_seq); + json_object_int_add(json_mac, "remoteSequence", mac->rem_seq); + json_object_int_add(json_mac, "detectionCount", mac->dad_count); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) - json_object_boolean_true_add(json_mac, - "isDuplicate"); + json_object_boolean_true_add(json_mac, "isDuplicate"); else - json_object_boolean_false_add(json_mac, - "isDuplicate"); + json_object_boolean_false_add(json_mac, "isDuplicate"); } wctx->count++; @@ -1004,7 +933,7 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, if (!client) return 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); zclient_create_header(s, cmd, zebra_vrf_get_evpn_id()); stream_putl(s, vni); @@ -1040,9 +969,9 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, zlog_debug( "Send MACIP %s f %s state %u MAC %pEA IP %pIA seq %u L2-VNI %u ESI %s to %s", (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", - zclient_evpn_dump_macip_flags(flags, flag_buf, - sizeof(flag_buf)), - state, macaddr, ip, seq, vni, es ? es->esi_str : "-", + zclient_evpn_dump_macip_flags(flags, flag_buf, sizeof(flag_buf)), + state, macaddr, ip, seq, vni, + es ? es->esi_str : "-", zebra_route_string(client->proto)); } @@ -1076,8 +1005,7 @@ static bool mac_cmp(const void *p1, const void *p2) if (pmac1 == NULL || pmac2 == NULL) return false; - return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) - == 0); + return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) == 0); } /* @@ -1117,10 +1045,8 @@ struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevpn, if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) { char mac_buf[MAC_BUF_SIZE]; - zlog_debug("%s: MAC %pEA flags %s", __func__, - &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } return mac; } @@ -1135,10 +1061,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac) if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) { char mac_buf[MAC_BUF_SIZE]; - zlog_debug("%s: MAC %pEA flags %s", __func__, - &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } /* force de-ref any ES entry linked to the MAC */ @@ -1165,9 +1089,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac) if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( "MAC %pEA (flags 0x%x vni %u) has non-empty neigh list " - "count %u, mark MAC as AUTO", - &mac->macaddr, mac->flags, zevpn->vni, - listcount(mac->neigh_list)); + "count %u, mark MAC as AUTO", &mac->macaddr, mac->flags, + zevpn->vni, listcount(mac->neigh_list)); SET_FLAG(mac->flags, ZEBRA_MAC_AUTO); return 0; @@ -1204,25 +1127,25 @@ struct zebra_mac *zebra_evpn_mac_add_auto(struct zebra_evpn *zevpn, static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx, struct zebra_mac *mac) { - if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL)) + if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC) + && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) return true; - else if ((wctx->flags & DEL_REMOTE_MAC) - && (mac->flags & ZEBRA_MAC_REMOTE)) + else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC) + && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) return true; - else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP) - && (mac->flags & ZEBRA_MAC_REMOTE) + else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC_FROM_VTEP) + && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip)) return true; - else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO) + else if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC) + && CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) && !listcount(mac->neigh_list)) { if (IS_ZEBRA_DEBUG_VXLAN) { char mac_buf[MAC_BUF_SIZE]; zlog_debug( - "%s: Del MAC %pEA flags %s", __func__, - &mac->macaddr, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + "%s: Del MAC %pEA flags %s", __func__, &mac->macaddr, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } wctx->uninstall = 0; @@ -1241,21 +1164,17 @@ static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg) struct zebra_mac *mac = bucket->data; if (zebra_evpn_check_mac_del_from_db(wctx, mac)) { - if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) { + if (wctx->upd_client && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni, - &mac->macaddr, - mac->flags, false); + &mac->macaddr, mac->flags, false); } if (wctx->uninstall) { if (zebra_evpn_mac_is_static(mac)) - zebra_evpn_sync_mac_dp_install( - mac, false /* set_inactive */, - true /* force_clear_static */, - __func__); + zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */, + true /* force_clear_static */, __func__); if (mac->flags & ZEBRA_MAC_REMOTE) - zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac, - false /*force*/); + zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac, false /*force*/); } zebra_evpn_mac_del(wctx->zevpn, mac); @@ -1330,8 +1249,7 @@ int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr, SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW); return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags, - seq, ZEBRA_NEIGH_ACTIVE, es, - ZEBRA_MACIP_ADD); + seq, ZEBRA_NEIGH_ACTIVE, es, ZEBRA_MACIP_ADD); } /* @@ -1357,9 +1275,8 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr, state = ZEBRA_NEIGH_INACTIVE; } - return zebra_evpn_macip_send_msg_to_client( - vni, macaddr, NULL, 0 /* flags */, 0 /* seq */, state, NULL, - ZEBRA_MACIP_DEL); + return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, + 0 /* flags */, 0 /* seq */, state, NULL, ZEBRA_MACIP_DEL); } /* @@ -1412,8 +1329,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port", caller, zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), set_inactive ? "inactive " : ""); } return -1; @@ -1429,8 +1345,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, "%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br", caller, zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), set_inactive ? "inactive " : ""); } return -1; @@ -1455,19 +1370,16 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, set_static ? "install" : "uninstall", zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), set_inactive ? "inactive " : ""); } if (set_static) /* XXX - old_static needs to be computed more * accurately */ - zebra_evpn_rem_mac_install(zevpn, mac, - true /* old_static */); + zebra_evpn_rem_mac_install(zevpn, mac, true /* old_static */); else - zebra_evpn_rem_mac_uninstall(zevpn, mac, - false /* force */); + zebra_evpn_rem_mac_uninstall(zevpn, mac, false /* force */); return 0; } @@ -1478,14 +1390,13 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive, zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s", zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), set_static ? "static " : "", set_inactive ? "inactive " : ""); } dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky, - set_static, set_inactive); + set_static, set_inactive); return 0; } @@ -1495,12 +1406,11 @@ void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac, { if (new_bgp_ready) zebra_evpn_mac_send_add_to_client(mac->zevpn->vni, - &mac->macaddr, mac->flags, - mac->loc_seq, mac->es); + &mac->macaddr, mac->flags, + mac->loc_seq, mac->es); else if (old_bgp_ready) zebra_evpn_mac_send_del_to_client(mac->zevpn->vni, - &mac->macaddr, mac->flags, - true /* force */); + &mac->macaddr, mac->flags, true /* force */); } /* MAC hold timer is used to age out peer-active flag. @@ -1537,8 +1447,7 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t) "sync-mac vni %u mac %pEA es %s %shold expired", mac->zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } /* re-program the local mac in the dataplane if the mac is no @@ -1546,13 +1455,11 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t) */ if (old_static != new_static) zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */, - false /* force_clear_static */, - __func__); + false /* force_clear_static */, __func__); /* inform bgp if needed */ if (old_bgp_ready != new_bgp_ready) - zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, - new_bgp_ready); + zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready); } static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac) @@ -1567,8 +1474,7 @@ static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac) "sync-mac vni %u mac %pEA es %s %shold started", mac->zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } event_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac, zmh_info->mac_hold_time, &mac->hold_timer); @@ -1586,8 +1492,7 @@ void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac) "sync-mac vni %u mac %pEA es %s %shold stopped", mac->zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } EVENT_OFF(mac->hold_timer); @@ -1605,8 +1510,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac) "sync-mac del vni %u mac %pEA es %s seq %d f %s", mac->zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", mac->loc_seq, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } old_static = zebra_evpn_mac_is_static(mac); @@ -1618,8 +1522,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac) if (old_static != new_static) /* program the local mac in the kernel */ zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */, - false /* force_clear_static */, - __func__); + false /* force_clear_static */, __func__); } static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn, @@ -1647,8 +1550,7 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn, zlog_debug( "%s-macip not ready vni %u %s-mac %pEA lower seq %u f 0x%x", sync ? "sync" : "rem", zevpn->vni, - n_type, &mac->macaddr, tmp_seq, - mac->flags); + n_type, &mac->macaddr, tmp_seq, mac->flags); return true; } @@ -1660,10 +1562,9 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn, IS_ZEBRA_DEBUG_VXLAN) { zlog_debug( "%s-macip accept vni %u %s-mac %pEA lower seq %u f %s", - sync ? "sync" : "rem", zevpn->vni, - n_type, &mac->macaddr, tmp_seq, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + (sync ? "sync" : "rem"), + zevpn->vni, n_type, &mac->macaddr, tmp_seq, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } return true; @@ -1672,10 +1573,8 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn, if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) { zlog_debug( "%s-macip ignore vni %u %s-mac %pEA as existing has higher seq %u f %s", - sync ? "sync" : "rem", zevpn->vni, n_type, - &mac->macaddr, tmp_seq, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + (sync ? "sync" : "rem"), zevpn->vni, n_type, &mac->macaddr, tmp_seq, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } return false; @@ -1749,9 +1648,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, "Ignore sync-macip vni %u mac %pEA%s%s%s%s", zevpn->vni, macaddr, ipa_len ? " IP " : "", - ipa_len ? ipaddr2str(ipaddr, ipbuf, - sizeof(ipbuf)) - : "", + ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "", sticky ? " sticky" : "", remote_gw ? " remote_gw" : ""); return NULL; @@ -1766,16 +1663,16 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, new_flags = 0; SET_FLAG(new_flags, ZEBRA_MAC_LOCAL); /* retain old local activity flag */ - if (old_flags & ZEBRA_MAC_LOCAL) - new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE); + if (CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL)) + SET_FLAG (new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL_INACTIVE)); else - new_flags |= ZEBRA_MAC_LOCAL_INACTIVE; + SET_FLAG(new_flags, ZEBRA_MAC_LOCAL_INACTIVE); if (ipa_len) { /* if mac-ip route do NOT update the peer flags * i.e. retain only flags as is */ - new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS); + SET_FLAG(new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_ALL_PEER_FLAGS)); } else { /* if mac-only route update peer flags */ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) { @@ -1785,10 +1682,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, * holdtimer on it. the peer-active flag is * cleared on holdtimer expiry. */ - if (CHECK_FLAG(old_flags, - ZEBRA_MAC_ES_PEER_ACTIVE)) { - SET_FLAG(new_flags, - ZEBRA_MAC_ES_PEER_ACTIVE); + if (CHECK_FLAG(old_flags, ZEBRA_MAC_ES_PEER_ACTIVE)) { + SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE); zebra_evpn_mac_start_hold_timer(mac); } } else { @@ -1811,10 +1706,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, zlog_debug( "sync-mac vni %u mac %pEA old_f %snew_f %s", zevpn->vni, macaddr, - zebra_evpn_zebra_mac_flag_dump( - &omac, omac_buf, sizeof(omac_buf)), - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(&omac, omac_buf, sizeof(omac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } /* update es */ @@ -1854,24 +1747,24 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, char mac_buf[MAC_BUF_SIZE]; zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s", - created ? "created" : "updated", zevpn->vni, macaddr, - mac->es ? mac->es->esi_str : "-", mac->loc_seq, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), - inform_bgp ? "inform_bgp" : "", - inform_dataplane ? " inform_dp" : ""); + created ? "created" : "updated", + zevpn->vni, macaddr, + mac->es ? mac->es->esi_str : "-", + mac->loc_seq, + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), + inform_bgp ? "inform_bgp" : "", + inform_dataplane ? " inform_dp" : ""); } if (inform_bgp) - zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, - new_bgp_ready); + zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready); /* neighs using the mac may need to be re-sent to * bgp with updated info */ if (seq_change || es_change || !old_local) zebra_evpn_process_neigh_on_local_mac_change( - zevpn, mac, seq_change, es_change); + zevpn, mac, seq_change, es_change); if (inform_dataplane && !ipa_len) { /* program the local mac in the kernel. when the ES @@ -1879,9 +1772,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, * the activity as we are yet to establish activity * locally */ - zebra_evpn_sync_mac_dp_install( - mac, mac_inactive /* set_inactive */, - false /* force_clear_static */, __func__); + zebra_evpn_sync_mac_dp_install(mac, mac_inactive /* set_inactive */, + false /* force_clear_static */, __func__); } return mac; @@ -1891,8 +1783,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn, * is detected */ static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac, - struct interface *ifp, - vlanid_t vid) + struct interface *ifp, vlanid_t vid) { struct zebra_if *zif = ifp->info; bool es_change; @@ -1934,8 +1825,8 @@ static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket, if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL)) zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni, - &zmac->macaddr, zmac->flags, - zmac->loc_seq, zmac->es); + &zmac->macaddr, zmac->flags, + zmac->loc_seq, zmac->es); } /* Iterator to Notify Local MACs of a EVPN */ @@ -1949,8 +1840,7 @@ void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn) memset(&wctx, 0, sizeof(wctx)); wctx.zevpn = zevpn; - hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client, - &wctx); + hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client, &wctx); } void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac) @@ -1992,8 +1882,7 @@ void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt) } /* Print Duplicate MAC in detail */ -void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket, - void *ctxt) +void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket, void *ctxt) { struct zebra_mac *mac; @@ -2043,11 +1932,13 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn, * If so, that needs to be updated first. Note that client could * install MAC and MACIP separately or just install the latter. */ - if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) - || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) - || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip) - || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq) + if (!mac + || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) + || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) + || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) + || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip) + || memcmp(old_esi, esi, sizeof(esi_t)) + || seq != mac->rem_seq) update_mac = 1; if (update_mac) { @@ -2063,8 +1954,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn, * the sequence number and ignore this update * if appropriate. */ - if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, - false)) + if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, false)) return -1; old_es_present = !!mac->es; @@ -2091,8 +1981,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn, * MAC is already marked duplicate set dad, then * is_dup_detect will be set to not install the entry. */ - if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) - && mac->dad_count) + if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && mac->dad_count) || CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) do_dad = true; @@ -2108,14 +1997,12 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn, zevpn->vni, macaddr, mac->es ? mac->es->esi_str : "-", mac->loc_seq, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } zebra_evpn_mac_clear_sync_info(mac); - zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, - mac->flags, - false /* force */); + zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags, + false /* force */); } /* Set "auto" and "remote" forwarding info. */ @@ -2135,8 +2022,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn, UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW); zebra_evpn_dup_addr_detect_for_mac( - zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad, - &is_dup_detect, false); + zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad, &is_dup_detect, false); if (!is_dup_detect) { zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac); @@ -2180,8 +2066,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) zlog_debug( "ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s", - sticky ? "sticky " : "", macaddr, - ifp->name, ifp->ifindex, vid, zevpn->vni, + sticky ? "sticky " : "", + macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni, local_inactive ? " local-inactive" : ""); mac = zebra_evpn_mac_add(zevpn, macaddr); @@ -2196,11 +2082,10 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zlog_debug( "UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s", - sticky ? "sticky " : "", macaddr, - ifp->name, ifp->ifindex, vid, zevpn->vni, + sticky ? "sticky " : "", + macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni, local_inactive ? "local-inactive " : "", - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) { @@ -2209,42 +2094,34 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, bool old_static; zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid); - old_bgp_ready = - zebra_evpn_mac_is_ready_for_bgp(mac->flags); - old_local_inactive = - !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE); + old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); + old_local_inactive = !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE); old_static = zebra_evpn_mac_is_static(mac); if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) mac_sticky = true; - es_change = zebra_evpn_local_mac_update_fwd_info( - mac, ifp, vid); + es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid); /* * Update any changes and if changes are relevant to * BGP, note it. */ - if (mac_sticky == sticky && old_ifp == ifp - && old_vid == vid - && old_local_inactive == local_inactive - && dp_static == old_static && !es_change) { + if (mac_sticky == sticky && old_ifp == ifp && old_vid == vid + && old_local_inactive == local_inactive + && dp_static == old_static && !es_change) { if (IS_ZEBRA_DEBUG_VXLAN) zlog_debug( " Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, " "entry exists and has not changed ", sticky ? "sticky " : "", - macaddr, ifp->name, - ifp->ifindex, vid, zevpn->vni, - local_inactive - ? " local_inactive" - : ""); + macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni, + local_inactive ? " local_inactive" : ""); return 0; } if (mac_sticky != sticky) { if (sticky) SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); else - UNSET_FLAG(mac->flags, - ZEBRA_MAC_STICKY); + UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY); inform_client = true; } @@ -2262,11 +2139,9 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, /* force drop the peer/sync info as it is * simply no longer relevant */ - if (CHECK_FLAG(mac->flags, - ZEBRA_MAC_ALL_PEER_FLAGS)) { + if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ALL_PEER_FLAGS)) { zebra_evpn_mac_clear_sync_info(mac); - new_static = - zebra_evpn_mac_is_static(mac); + new_static = zebra_evpn_mac_is_static(mac); /* if we clear peer-flags we * also need to notify the dataplane * to drop the static flag @@ -2289,16 +2164,13 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, flog_warn( EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT, "MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u", - macaddr, - &mac->fwd_info.r_vtep_ip, - zevpn->vni); + macaddr, &mac->fwd_info.r_vtep_ip, zevpn->vni); return 0; } /* If an actual move, compute MAC's seq number */ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) { - mac->loc_seq = - MAX(mac->rem_seq + 1, mac->loc_seq); + mac->loc_seq = MAX(mac->rem_seq + 1, mac->loc_seq); vtep_ip = mac->fwd_info.r_vtep_ip; /* Trigger DAD for remote MAC */ do_dad = true; @@ -2307,8 +2179,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE); UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO); SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL); - es_change = zebra_evpn_local_mac_update_fwd_info( - mac, ifp, vid); + es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid); if (sticky) SET_FLAG(mac->flags, ZEBRA_MAC_STICKY); else @@ -2321,8 +2192,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, upd_neigh = true; zebra_evpn_dup_addr_detect_for_mac( - zvrf, mac, vtep_ip, do_dad, &is_dup_detect, - true); + zvrf, mac, vtep_ip, do_dad, &is_dup_detect, true); if (is_dup_detect) { inform_client = false; upd_neigh = false; @@ -2357,8 +2227,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, "local mac vni %u mac %pEA es %s seq %d f %s%s", zevpn->vni, macaddr, mac->es ? mac->es->esi_str : "", mac->loc_seq, - zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, - sizeof(mac_buf)), + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)), local_inactive ? "local-inactive" : ""); } @@ -2374,18 +2243,15 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, /* Inform dataplane if required. */ if (inform_dataplane) zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */, - false /* force_clear_static */, - __func__); + false /* force_clear_static */, __func__); /* Inform BGP if required. */ if (inform_client) - zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, - new_bgp_ready); + zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready); /* Process all neighbors associated with this MAC, if required. */ if (upd_neigh) - zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, - es_change); + zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, es_change); return 0; } @@ -2415,23 +2281,20 @@ int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac, "re-add sync-mac vni %u mac %pEA es %s seq %d f %s", zevpn->vni, &mac->macaddr, mac->es ? mac->es->esi_str : "-", mac->loc_seq, - zebra_evpn_zebra_mac_flag_dump( - mac, mac_buf, sizeof(mac_buf))); + zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf))); } /* inform-bgp about change in local-activity if any */ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) { SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE); - new_bgp_ready = - zebra_evpn_mac_is_ready_for_bgp(mac->flags); + new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); zebra_evpn_mac_send_add_del_to_client( - mac, old_bgp_ready, new_bgp_ready); + mac, old_bgp_ready, new_bgp_ready); } /* re-install the inactive entry in the kernel */ zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */, - false /* force_clear_static */, - __func__); + false /* force_clear_static */, __func__); return 0; } @@ -2519,8 +2382,7 @@ void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn) old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI); - zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, - false); + zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, false); zebra_evpn_deref_ip2mac(mac->zevpn, mac); } } @@ -2548,13 +2410,11 @@ void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn) if (IS_ZEBRA_DEBUG_EVPN_MH_ES) zlog_debug("SVI %s mac add", zif->ifp->name); - old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags)) - ? true - : false; + old_bgp_ready = + (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags)) ? true : false; zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false); new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags); - zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, - new_bgp_ready); + zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready); } diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c index 35d5027..75e7e20 100644 --- a/zebra/zebra_evpn_mh.c +++ b/zebra/zebra_evpn_mh.c @@ -563,8 +563,9 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if) struct zebra_evpn_access_bd *acc_bd; struct interface *vlan_if; - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("access vlan %d bridge %s add", vid, br_if->name); + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s access vlan %d bridge %s add", __func__, vid, + br_if->name); acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd)); @@ -582,8 +583,8 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if) vlan_if = zvni_map_to_svi(vid, br_if); if (vlan_if) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("vlan %d bridge %s SVI %s set", vid, - br_if->name, vlan_if->name); + zlog_debug("%s vlan %d bridge %s SVI %s set", __func__, + vid, br_if->name, vlan_if->name); acc_bd->vlan_zif = vlan_if->info; } return acc_bd; @@ -731,6 +732,29 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd, } } +/* Lookup API for VxLAN_IF's Bridge, VLAN in EVPN cache */ +int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, struct zebra_if *vxlan_zif) +{ + struct interface *br_if; + struct zebra_evpn_access_bd *acc_bd; + + if (!vid) + return -1; + + br_if = vxlan_zif->brslave_info.br_if; + + if (!br_if) + return -1; + + acc_bd = zebra_evpn_acc_vl_find(vid, br_if); + + if (!acc_bd) + return 0; + + return 1; +} + + /* handle VLAN->VxLAN_IF association */ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id, struct zebra_if *vxlan_zif) @@ -768,8 +792,9 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id, if (acc_bd->zevpn == old_zevpn) return; - if (IS_ZEBRA_DEBUG_EVPN_MH_ES) - zlog_debug("access vlan %d vni %u ref", acc_bd->vid, vni_id); + if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s bridge %s access vlan %d vni %u ref", __func__, + br_if->name, acc_bd->vid, vni_id); if (old_zevpn) zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn); @@ -1935,7 +1960,7 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es) if (!client) return 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id()); stream_put(s, &es->esi, sizeof(esi_t)); @@ -1971,7 +1996,7 @@ static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es) if (!client) return 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); stream_reset(s); zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id()); @@ -2639,7 +2664,7 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es, if (!client) return 0; - s = stream_new(ZEBRA_MAX_PACKET_SIZ); + s = stream_new(ZEBRA_SMALL_PACKET_SIZE); zclient_create_header(s, add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL, @@ -3001,7 +3026,7 @@ void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up) } static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es, - uint8_t vtep_str_size) + size_t vtep_str_size) { struct zebra_evpn_es_vtep *zvtep; struct listnode *node; diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h index 34ef79f..f68e2ea 100644 --- a/zebra/zebra_evpn_mh.h +++ b/zebra/zebra_evpn_mh.h @@ -378,7 +378,8 @@ extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es, extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS); extern struct zebra_evpn_es_evi * zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn); - +extern int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, + struct zebra_if *vxlan_zif); void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi); void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac); diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 1dd9634..95207ce 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -592,19 +592,19 @@ int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf, RTM_DELNEIGH : RTM_NEWNEIGH; req->hdr.nlmsg_flags = NLM_F_REQUEST; if (req->hdr.nlmsg_type == RTM_NEWNEIGH) - req->hdr.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE); + SET_FLAG(req->hdr.nlmsg_flags, (NLM_F_CREATE | NLM_F_REPLACE)); /* Construct ndmsg */ req->ndm.ndm_family = AF_BRIDGE; req->ndm.ndm_ifindex = mac->vxlan_if; req->ndm.ndm_state = NUD_REACHABLE; - req->ndm.ndm_flags |= NTF_SELF | NTF_MASTER; + SET_FLAG(req->ndm.ndm_flags, (NTF_SELF | NTF_MASTER)); if (CHECK_FLAG(mac->zebra_flags, (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW))) - req->ndm.ndm_state |= NUD_NOARP; + SET_FLAG(req->ndm.ndm_state, NUD_NOARP); else - req->ndm.ndm_flags |= NTF_EXT_LEARNED; + SET_FLAG(req->ndm.ndm_flags, NTF_EXT_LEARNED); /* Add attributes */ nl_attr_put(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6); diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c index f4241f1..cee66cc 100644 --- a/zebra/zebra_gr.c +++ b/zebra/zebra_gr.c @@ -298,6 +298,16 @@ struct zebra_gr_afi_clean { * Functions to deal with capabilities */ +void zebra_gr_client_final_shutdown(struct zserv *client) +{ + struct client_gr_info *info; + + while (!TAILQ_EMPTY(&client->gr_info_queue)) { + info = TAILQ_FIRST(&client->gr_info_queue); + zebra_gr_client_info_delete(client, info); + } +} + /* * Function to decode and call appropriate functions * to handle client capabilities. diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c index 4f7a1cd..240f674 100644 --- a/zebra/zebra_l2.c +++ b/zebra/zebra_l2.c @@ -111,13 +111,13 @@ static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif) { struct listnode *node; struct zebra_if *bond_mbr; - bool old_bypass = !!(bond_zif->flags & ZIF_FLAG_LACP_BYPASS); + bool old_bypass = !!CHECK_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS); bool new_bypass = false; if (bond_zif->bond_info.mbr_zifs) { for (ALL_LIST_ELEMENTS_RO(bond_zif->bond_info.mbr_zifs, node, bond_mbr)) { - if (bond_mbr->flags & ZIF_FLAG_LACP_BYPASS) { + if (CHECK_FLAG(bond_mbr->flags, ZIF_FLAG_LACP_BYPASS)) { new_bypass = true; break; } @@ -132,9 +132,9 @@ static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif) bond_zif->ifp->name, new_bypass ? "on" : "off"); if (new_bypass) - bond_zif->flags |= ZIF_FLAG_LACP_BYPASS; + SET_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS); else - bond_zif->flags &= ~ZIF_FLAG_LACP_BYPASS; + UNSET_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS); if (bond_zif->es_info.es) zebra_evpn_es_bypass_update(bond_zif->es_info.es, bond_zif->ifp, @@ -174,8 +174,7 @@ void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id) } } else { if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bond mbr %s link to bond skipped", - zif->ifp->name); + zlog_debug("bond mbr %s link to bond skipped", zif->ifp->name); } } @@ -186,8 +185,7 @@ void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif) if (!bond_slave->bond_if) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bond mbr %s unlink from bond skipped", - zif->ifp->name); + zlog_debug("bond mbr %s unlink from bond skipped", zif->ifp->name); return; } @@ -218,8 +216,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add) if (add) { if (!bond->mbr_zifs) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) - zlog_debug("bond %s mbr list create", - ifp->name); + zlog_debug("bond %s mbr list create", ifp->name); bond->mbr_zifs = list_new(); } } else { @@ -347,7 +344,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp, ctx.old_vtep_ip = zif->l2info.vxl.vtep_ip; if (!IPV4_ADDR_SAME(&ctx.old_vtep_ip, &vxlan_info->vtep_ip)) { - chgflags |= ZEBRA_VXLIF_LOCAL_IP_CHANGE; + SET_FLAG(chgflags, ZEBRA_VXLIF_LOCAL_IP_CHANGE); zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip; } @@ -355,7 +352,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp, ctx.old_vni = vxlan_info->vni_info.vni; if (!IPV4_ADDR_SAME(&zif->l2info.vxl.vni_info.vni.mcast_grp, &vxlan_info->vni_info.vni.mcast_grp)) { - chgflags |= ZEBRA_VXLIF_MCAST_GRP_CHANGE; + SET_FLAG(chgflags, ZEBRA_VXLIF_MCAST_GRP_CHANGE); zif->l2info.vxl.vni_info.vni.mcast_grp = vxlan_info->vni_info.vni.mcast_grp; } @@ -387,7 +384,7 @@ void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp, return; old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan; - ; + if (old_access_vlan == access_vlan) return; @@ -441,11 +438,11 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp, if (zif->zif_type == ZEBRA_IF_VXLAN && chgflags != ZEBRA_BRIDGE_NO_ACTION) { - if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) { + if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_MAC_CHANGE)) { ctx.chgflags = ZEBRA_VXLIF_MASTER_MAC_CHANGE; zebra_vxlan_if_update(ifp, &ctx); } - if (chgflags & ZEBRA_BRIDGE_MASTER_UP) { + if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_UP)) { ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE; zebra_vxlan_if_update(ifp, &ctx); } @@ -494,16 +491,16 @@ void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex, zif = ifp->info; assert(zif); - old_bypass = !!(zif->flags & ZIF_FLAG_LACP_BYPASS); + old_bypass = !!CHECK_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS); if (old_bypass != new_bypass) { if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT) zlog_debug("bond-mbr %s lacp bypass changed to %s", zif->ifp->name, new_bypass ? "on" : "off"); if (new_bypass) - zif->flags |= ZIF_FLAG_LACP_BYPASS; + SET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS); else - zif->flags &= ~ZIF_FLAG_LACP_BYPASS; + UNSET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS); bond_mbr = &zif->bondslave_info; if (bond_mbr->bond_if) { diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 39fc678..d1c9cd5 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -329,7 +329,7 @@ static void fec_evaluate(struct zebra_vrf *zvrf) /* Skip configured FECs and those without a label index. */ - if (fec->flags & FEC_FLAG_CONFIGURED + if (CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) || fec->label_index == MPLS_INVALID_LABEL_INDEX) continue; @@ -2291,7 +2291,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p, new_client = true; } else { /* Check if the FEC has been statically defined in the config */ - is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED; + is_configured_fec = CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED); /* Client may register same FEC with different label index. */ new_client = (listnode_lookup(fec->client_list, client) == NULL); @@ -2382,8 +2382,8 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, /* If not a configured entry, delete the FEC if no other clients. Before * deleting, see if any LSP needs to be uninstalled. */ - if (!(fec->flags & FEC_FLAG_CONFIGURED) - && list_isempty(fec->client_list)) { + if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) && + list_isempty(fec->client_list)) { mpls_label_t old_label = fec->label; fec->label = MPLS_INVALID_LABEL; /* reset */ fec_change_update_lsp(zvrf, fec, old_label); @@ -2420,7 +2420,7 @@ static int zebra_mpls_cleanup_fecs_for_client(struct zserv *client) if (fec_client == client) { listnode_delete(fec->client_list, fec_client); - if (!(fec->flags & FEC_FLAG_CONFIGURED) + if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) && list_isempty(fec->client_list)) fec_del(fec); break; @@ -2476,7 +2476,7 @@ static int zebra_mpls_cleanup_zclient_labels(struct zserv *client) * hash.. */ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, - mpls_label_t label) + struct prefix *p, mpls_label_t label) { struct route_node *rn; struct zebra_fec *fec; @@ -2491,8 +2491,11 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, if (!rn->info) continue; fec = rn->info; - if (fec->label == label) + if (fec->label == label) { + if (p && prefix_same(p, &rn->p)) + return NULL; return fec; + } } } @@ -2502,9 +2505,10 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, /* * Inform if specified label is currently bound to a FEC or not. */ -int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label) +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t label) { - return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0); + return (zebra_mpls_fec_for_label(zvrf, p, label) ? 1 : 0); } /* @@ -2538,7 +2542,7 @@ int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p, if (IS_ZEBRA_DEBUG_MPLS) zlog_debug("Add fec %pFX label %u", p, in_label); } else { - fec->flags |= FEC_FLAG_CONFIGURED; + SET_FLAG(fec->flags, FEC_FLAG_CONFIGURED); if (fec->label == in_label) /* Duplicate config */ return 0; @@ -2587,7 +2591,7 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p) } old_label = fec->label; - fec->flags &= ~FEC_FLAG_CONFIGURED; + UNSET_FLAG(fec->flags, FEC_FLAG_CONFIGURED); fec->label = MPLS_INVALID_LABEL; /* If no client exists, just delete the FEC. */ @@ -2630,7 +2634,7 @@ int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf) char lstr[BUFSIZ]; fec = rn->info; - if (!(fec->flags & FEC_FLAG_CONFIGURED)) + if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED)) continue; write = 1; diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h index 1ed2f9b..dd6f960 100644 --- a/zebra/zebra_mpls.h +++ b/zebra/zebra_mpls.h @@ -203,12 +203,13 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p, * hash.. */ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf, - mpls_label_t label); + struct prefix *p, mpls_label_t label); /* * Inform if specified label is currently bound to a FEC or not. */ -int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label); +int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p, + mpls_label_t label); /* * Add static FEC to label binding. If there are clients registered for this diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 9cbe6a2..85a53dd 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -64,8 +64,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, sa_label_in.smpls_family = AF_MPLS; sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; + SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH)); + SET_FLAG(hdr.rtm_addrs, RTA_DST); hdr.rtm_msglen += sizeof(sa_label_in); /* adjust iovec */ iov[iovcnt].iov_base = &sa_label_in; @@ -77,8 +77,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, nexthop.sin_family = AF_INET; nexthop.sin_addr = nhlfe->nexthop->gate.ipv4; /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; + SET_FLAG(hdr.rtm_flags, RTF_GATEWAY); + SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY); hdr.rtm_msglen += sizeof(nexthop); /* adjust iovec */ iov[iovcnt].iov_base = &nexthop; @@ -93,8 +93,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label, htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; + SET_FLAG(hdr.rtm_addrs, RTA_SRC); + SET_FLAG(hdr.rtm_flags, RTF_MPLS); hdr.rtm_msglen += sizeof(sa_label_out); /* adjust iovec */ iov[iovcnt].iov_base = &sa_label_out; @@ -159,8 +159,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, sa_label_in.smpls_family = AF_MPLS; sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET); /* adjust header */ - hdr.rtm_flags |= RTF_MPLS | RTF_MPATH; - hdr.rtm_addrs |= RTA_DST; + SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH)); + SET_FLAG(hdr.rtm_addrs, RTA_DST); hdr.rtm_msglen += sizeof(sa_label_in); /* adjust iovec */ iov[iovcnt].iov_base = &sa_label_in; @@ -184,8 +184,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, } /* adjust header */ - hdr.rtm_flags |= RTF_GATEWAY; - hdr.rtm_addrs |= RTA_GATEWAY; + SET_FLAG(hdr.rtm_flags, RTF_GATEWAY); + SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY); hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6)); /* adjust iovec */ iov[iovcnt].iov_base = &nexthop; @@ -200,8 +200,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label, htonl(nhlfe->nexthop->nh_label->label[0] << MPLS_LABEL_OFFSET); /* adjust header */ - hdr.rtm_addrs |= RTA_SRC; - hdr.rtm_flags |= RTF_MPLS; + SET_FLAG(hdr.rtm_addrs, RTA_SRC); + SET_FLAG(hdr.rtm_flags, RTF_MPLS); hdr.rtm_msglen += sizeof(sa_label_out); /* adjust iovec */ iov[iovcnt].iov_base = &sa_label_out; @@ -324,8 +324,8 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_FAILURE; } - if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD) - imr.imr_flags |= IMR_FLAG_CONTROLWORD; + if (CHECK_FLAG(dplane_ctx_get_pw_flags(ctx), F_PSEUDOWIRE_CWORD)) + SET_FLAG(imr.imr_flags, IMR_FLAG_CONTROLWORD); /* pseudowire nexthop */ memset(&ss, 0, sizeof(ss)); diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c index 83a1aad..b31bf44 100644 --- a/zebra/zebra_mpls_vty.c +++ b/zebra/zebra_mpls_vty.c @@ -210,7 +210,7 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix, vty_out(vty, "%% Invalid label\n"); return CMD_WARNING_CONFIG_FAILED; } - if (zebra_mpls_label_already_bound(zvrf, label)) { + if (zebra_mpls_label_already_bound(zvrf, &p, label)) { vty_out(vty, "%% Label already bound to a FEC\n"); return CMD_WARNING_CONFIG_FAILED; diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c index e1ca5ec..eee9323 100644 --- a/zebra/zebra_nb.c +++ b/zebra/zebra_nb.c @@ -803,6 +803,12 @@ const struct frr_yang_module_info frr_zebra_info = { } }, { + .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/bond", + .cbs = { + .get_elem = lib_interface_zebra_state_bond_get_elem, + } + }, + { .xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/router-id", .cbs = { .modify = lib_vrf_zebra_router_id_modify, diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h index d7cf5f4..b40ed68 100644 --- a/zebra/zebra_nb.h +++ b/zebra/zebra_nb.h @@ -285,6 +285,7 @@ struct yang_data *lib_interface_zebra_state_remote_vtep_get_elem( struct nb_cb_get_elem_args *args); struct yang_data *lib_interface_zebra_state_mcast_group_get_elem( struct nb_cb_get_elem_args *args); +struct yang_data *lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args); int lib_vrf_zebra_router_id_modify(struct nb_cb_modify_args *args); int lib_vrf_zebra_router_id_destroy(struct nb_cb_destroy_args *args); int lib_vrf_zebra_ipv6_router_id_modify(struct nb_cb_modify_args *args); diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index ff2529f..ae6232a 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -3102,7 +3102,7 @@ int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create( struct nb_cb_create_args *args) { struct interface *ifp; - struct rtadv_rdnss rdnss = {0}, *p; + struct rtadv_rdnss rdnss = {{{{0}}}}, *p; if (args->event != NB_EV_APPLY) return NB_OK; @@ -3181,7 +3181,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create( struct nb_cb_create_args *args) { struct interface *ifp; - struct rtadv_dnssl dnssl = {0}, *p; + struct rtadv_dnssl dnssl = {{0}}, *p; int ret; strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"), diff --git a/zebra/zebra_nb_rpcs.c b/zebra/zebra_nb_rpcs.c index 083ab3f..744ba62 100644 --- a/zebra/zebra_nb_rpcs.c +++ b/zebra/zebra_nb_rpcs.c @@ -12,6 +12,8 @@ #include "zebra/zebra_router.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_vxlan.h" +#include "zebra/zebra_vxlan_if.h" +#include "zebra/zebra_evpn.h" /* * XPath: /frr-zebra:clear-evpn-dup-addr @@ -20,48 +22,41 @@ int clear_evpn_dup_addr_rpc(struct nb_cb_rpc_args *args) { struct zebra_vrf *zvrf; int ret = NB_OK; - struct yang_data *yang_dup_choice = NULL, *yang_dup_vni = NULL, - *yang_dup_ip = NULL, *yang_dup_mac = NULL; - - yang_dup_choice = yang_data_list_find(args->input, "%s/%s", args->xpath, - "input/clear-dup-choice"); + if (!is_evpn_enabled()) { + snprintf(args->errmsg, args->errmsg_len, + "%% EVPN not enabled\n"); + return NB_ERR_VALIDATION; + } zvrf = zebra_vrf_get_evpn(); - if (yang_dup_choice - && strcmp(yang_dup_choice->value, "all-case") == 0) { + if (yang_dnode_exists(args->input, "all-vnis")) { zebra_vxlan_clear_dup_detect_vni_all(zvrf); } else { - vni_t vni; + vni_t vni = yang_dnode_get_uint32(args->input, "vni-id"); struct ipaddr host_ip = {.ipa_type = IPADDR_NONE}; struct ethaddr mac; - yang_dup_vni = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id"); - if (yang_dup_vni) { - vni = yang_str2uint32(yang_dup_vni->value); - - yang_dup_mac = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id/mac-addr"); - yang_dup_ip = yang_data_list_find( - args->input, "%s/%s", args->xpath, - "input/clear-dup-choice/single-case/vni-id/vni-ipaddr"); - - if (yang_dup_mac) { - yang_str2mac(yang_dup_mac->value, &mac); - ret = zebra_vxlan_clear_dup_detect_vni_mac( - zvrf, vni, &mac, args->errmsg, - args->errmsg_len); - } else if (yang_dup_ip) { - yang_str2ip(yang_dup_ip->value, &host_ip); - ret = zebra_vxlan_clear_dup_detect_vni_ip( - zvrf, vni, &host_ip, args->errmsg, - args->errmsg_len); - } else - ret = zebra_vxlan_clear_dup_detect_vni(zvrf, - vni); + if (!zebra_evpn_lookup(vni)) { + snprintf(args->errmsg, args->errmsg_len, + "%% VNI %u does not exist\n", vni); + return NB_ERR_VALIDATION; + } + + if (yang_dnode_exists(args->input, "mac-addr")) { + yang_dnode_get_mac(&mac, args->input, "mac-addr"); + ret = zebra_vxlan_clear_dup_detect_vni_mac(zvrf, vni, + &mac, + args->errmsg, + args->errmsg_len); + } else if (yang_dnode_exists(args->input, "vni-ipaddr")) { + yang_dnode_get_ip(&host_ip, args->input, "vni-ipaddr"); + ret = zebra_vxlan_clear_dup_detect_vni_ip(zvrf, vni, + &host_ip, + args->errmsg, + args->errmsg_len); + } else { + ret = zebra_vxlan_clear_dup_detect_vni(zvrf, vni); } } if (ret < 0) diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c index 00df9bf..63ac787 100644 --- a/zebra/zebra_nb_state.c +++ b/zebra/zebra_nb_state.c @@ -49,8 +49,50 @@ lib_interface_zebra_state_down_count_get_elem(struct nb_cb_get_elem_args *args) struct yang_data * lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args *args) { - /* TODO: implement me. */ - return NULL; + const struct interface *ifp = args->list_entry; + struct zebra_if *zebra_if; + const char *type = NULL; + + zebra_if = ifp->info; + + /* + * NOTE: when adding a new type to the switch, make sure it is defined + * in it's YANG model. + */ + switch (zebra_if->zif_type) { + case ZEBRA_IF_OTHER: + type = "frr-zebra:zif-other"; + break; + case ZEBRA_IF_VXLAN: + type = "frr-zebra:zif-vxlan"; + break; + case ZEBRA_IF_VRF: + type = "frr-zebra:zif-vrf"; + break; + case ZEBRA_IF_BRIDGE: + type = "frr-zebra:zif-bridge"; + break; + case ZEBRA_IF_VLAN: + type = "frr-zebra:zif-vlan"; + break; + case ZEBRA_IF_MACVLAN: + type = "frr-zebra:zif-macvlan"; + break; + case ZEBRA_IF_VETH: + type = "frr-zebra:zif-veth"; + break; + case ZEBRA_IF_BOND: + type = "frr-zebra:zif-bond"; + break; + case ZEBRA_IF_GRE: + type = "frr-zebra:zif-gre"; + break; + } + + if (!type) + return NULL; + + return yang_data_new_string(args->xpath, type); } /* @@ -145,6 +187,28 @@ lib_interface_zebra_state_mcast_group_get_elem(struct nb_cb_get_elem_args *args) return yang_data_new_ipv4(args->xpath, &vni->mcast_grp); } +/* + * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/bond + */ +struct yang_data * +lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args) +{ + const struct interface *ifp = args->list_entry; + struct zebra_if *zebra_if; + struct interface *bond; + + if (!IS_ZEBRA_IF_BOND_SLAVE(ifp)) + return NULL; + + zebra_if = ifp->info; + bond = zebra_if->bondslave_info.bond_if; + + if (!bond) + return NULL; + + return yang_data_new_string(args->xpath, bond->name); +} + const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args) { struct vrf *vrf = (struct vrf *)args->parent_list_entry; @@ -548,7 +612,7 @@ struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem( { struct route_entry *re = (struct route_entry *)args->list_entry; - return yang_data_new_date_and_time(args->xpath, re->uptime); + return yang_data_new_date_and_time(args->xpath, re->uptime, true); } /* diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c index 941088a..a222e7f 100644 --- a/zebra/zebra_neigh.c +++ b/zebra/zebra_neigh.c @@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac) n->ifindex = ifindex; if (mac) { memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); } /* Add to rb_tree */ @@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n) /* if rules are still using the neigh mark it as inactive and * update the dataplane */ - if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) { - n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE; - memset(&n->mac, 0, sizeof(n->mac)); - } + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); + memset(&n->mac, 0, sizeof(n->mac)); zebra_neigh_pbr_rules_update(n); return; } @@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip, return; memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); /* update rules linked to the neigh */ zebra_neigh_pbr_rules_update(n); @@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule) rule->action.neigh = NULL; /* remove rule from the list and free if it is inactive */ list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode); - if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE)) + if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE)) zebra_neigh_free(n); } diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index 1af3a3e..4cee3b8 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -42,7 +42,7 @@ #define NETLINK_SOCKET_BUFFER_SIZE 512 #define NETLINK_ALIGNTO 4 #define NETLINK_ALIGN(len) \ - (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1)) + CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1)) #define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b) #endif /* defined(HAVE_NETLINK) */ @@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type) nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST; if (type == RTM_NEWNSID) - nlh->nlmsg_flags |= NLM_F_ACK; + SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK); nlh->nlmsg_seq = *seq = frr_sequence32_next(); return nlh; } diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 1bb1292..fb326b0 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -15,6 +15,7 @@ #include <sched.h> #endif #include <dirent.h> +#include <libgen.h> #include <sys/inotify.h> #include <sys/stat.h> @@ -234,6 +235,7 @@ static void zebra_ns_ready_read(struct event *t) { struct zebra_netns_info *zns_info = EVENT_ARG(t); const char *netnspath; + const char *netnspath_basename; int err, stop_retry = 0; if (!zns_info) @@ -261,23 +263,24 @@ static void zebra_ns_ready_read(struct event *t) zebra_ns_continue_read(zns_info, stop_retry); return; } + netnspath_basename = basename(strdupa(netnspath)); /* check default name is not already set */ - if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) { - zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath)); + if (strmatch(VRF_DEFAULT_NAME, netnspath_basename)) { + zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", netnspath_basename); zebra_ns_continue_read(zns_info, 1); return; } - if (zebra_ns_notify_is_default_netns(basename(netnspath))) { + if (zebra_ns_notify_is_default_netns(netnspath_basename)) { zlog_warn( "NS notify : NS %s is default VRF. Ignore VRF creation", - basename(netnspath)); + netnspath_basename); zebra_ns_continue_read(zns_info, 1); return; } /* success : close fd and create zns context */ - zebra_ns_notify_create_context_from_entry_name(basename(netnspath)); + zebra_ns_notify_create_context_from_entry_name(netnspath_basename); zebra_ns_continue_read(zns_info, 1); } @@ -304,7 +307,7 @@ static void zebra_ns_notify_read(struct event *t) char *netnspath; struct zebra_netns_info *netnsinfo; - if (!(event->mask & (IN_CREATE | IN_DELETE))) + if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE))) continue; if (offsetof(struct inotify_event, name) + event->len @@ -350,7 +353,7 @@ static void zebra_ns_notify_read(struct event *t) memcpy(event_name, event->name, event->len); event_name[event->len - 1] = 0; - if (event->mask & IN_DELETE) { + if (CHECK_FLAG(event->mask, IN_DELETE)) { zebra_ns_delete(event_name); continue; } @@ -396,7 +399,7 @@ void zebra_ns_notify_parse(void) continue; } /* check default name is not already set */ - if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) { + if (strmatch(VRF_DEFAULT_NAME, basename(strdupa(dent->d_name)))) { zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name); continue; } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index ed949da..9971b19 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -309,8 +309,10 @@ static int zebra_nhg_insert_id(struct nhg_hash_entry *nhe) static void zebra_nhg_set_if(struct nhg_hash_entry *nhe, struct interface *ifp) { + struct zebra_if *zif = (struct zebra_if *)ifp->info; + nhe->ifp = ifp; - if_nhg_dependents_add(ifp, nhe); + nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe); } static void @@ -1031,31 +1033,44 @@ static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh, return ctx; } -static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe) +static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid) { struct nhg_connected *rb_node_dep; - SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); + if (valid) + SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); + else { + UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); - frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) - zebra_nhg_set_valid(rb_node_dep->nhe); -} + /* If we're in shutdown, this interface event needs to clean + * up installed NHGs, so don't clear that flag directly. + */ + if (!zebra_router_in_shutdown()) + UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); + } -static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe) -{ - struct nhg_connected *rb_node_dep; + /* Update validity of nexthops depending on it */ + frr_each (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) { + if (!valid) { + /* + * Grab the first nexthop from the depending nexthop group + * then let's find the nexthop in that group that matches + * my individual nexthop and mark it as no longer ACTIVE + */ + struct nexthop *nexthop = rb_node_dep->nhe->nhg.nexthop; - UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); + while (nexthop) { + if (nexthop_same(nexthop, nhe->nhg.nexthop)) + break; - /* If we're in shutdown, this interface event needs to clean - * up installed NHGs, so don't clear that flag directly. - */ - if (!zebra_router_in_shutdown()) - UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); + nexthop = nexthop->next; + } - /* Update validity of nexthops depending on it */ - frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) - zebra_nhg_check_valid(rb_node_dep->nhe); + if (nexthop) + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + zebra_nhg_set_valid(rb_node_dep->nhe, valid); + } } void zebra_nhg_check_valid(struct nhg_hash_entry *nhe) @@ -1063,6 +1078,13 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe) struct nhg_connected *rb_node_dep = NULL; bool valid = false; + /* + * If I have other nhe's depending on me, then this is a + * singleton nhe so set this nexthops flag as appropriate. + */ + if (nhg_connected_tree_count(&nhe->nhg_depends)) + UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_ACTIVE); + /* If anthing else in the group is valid, the group is valid */ frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) { if (CHECK_FLAG(rb_node_dep->nhe->flags, NEXTHOP_GROUP_VALID)) { @@ -1071,10 +1093,7 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe) } } - if (valid) - zebra_nhg_set_valid(nhe); - else - zebra_nhg_set_invalid(nhe); + zebra_nhg_set_valid(nhe, valid); } static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe) @@ -1082,8 +1101,11 @@ static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe) /* Remove it from any lists it may be on */ zebra_nhg_depends_release(nhe); zebra_nhg_dependents_release(nhe); - if (nhe->ifp) - if_nhg_dependents_del(nhe->ifp, nhe); + if (nhe->ifp) { + struct zebra_if *zif = nhe->ifp->info; + + nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe); + } } static void zebra_nhg_release(struct nhg_hash_entry *nhe) @@ -1115,7 +1137,7 @@ static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe, bool install) struct nhg_connected *rb_node_dep; frr_each_safe (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) { - zebra_nhg_set_valid(rb_node_dep->nhe); + zebra_nhg_set_valid(rb_node_dep->nhe, true); /* install dependent NHG into kernel */ if (install) { if (IS_ZEBRA_DEBUG_NHG_DETAIL) @@ -1799,8 +1821,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi, break; } - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK)) + SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK); /* Copy labels of the resolved route and the parent resolving to it */ if (policy) { @@ -3094,14 +3116,15 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe) zebra_nhg_install_kernel(rb_node_dep->nhe); } - if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID) - && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) - && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) { + if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID) && + (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) || + CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) && + !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) { /* Change its type to us since we are installing it */ if (!ZEBRA_NHG_CREATED(nhe)) nhe->type = ZEBRA_ROUTE_NHG; - int ret = dplane_nexthop_add(nhe); + enum zebra_dplane_result ret = dplane_nexthop_add(nhe); switch (ret) { case ZEBRA_DPLANE_REQUEST_QUEUED: @@ -3114,8 +3137,9 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe) nhe); break; case ZEBRA_DPLANE_REQUEST_SUCCESS: - SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); - zebra_nhg_handle_install(nhe, false); + flog_err(EC_ZEBRA_DP_INVALID_RC, + "DPlane returned an invalid result code for attempt of installation of %pNG into the kernel", + nhe); break; } } @@ -3182,8 +3206,9 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) } UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED); - if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { - SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID); + UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL); + switch (status) { + case ZEBRA_DPLANE_REQUEST_SUCCESS: SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); zebra_nhg_handle_install(nhe, true); @@ -3192,7 +3217,9 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) zsend_nhg_notify(nhe->type, nhe->zapi_instance, nhe->zapi_session, nhe->id, ZAPI_NHG_INSTALLED); - } else { + break; + case ZEBRA_DPLANE_REQUEST_FAILURE: + UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED); /* If daemon nhg, send it an update */ if (PROTO_OWNED(nhe)) zsend_nhg_notify(nhe->type, nhe->zapi_instance, @@ -3205,6 +3232,12 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx) EC_ZEBRA_DP_INSTALL_FAIL, "Failed to install Nexthop (%pNG) into the kernel", nhe); + break; + case ZEBRA_DPLANE_REQUEST_QUEUED: + flog_err(EC_ZEBRA_DP_INVALID_RC, + "Dplane returned an invalid result code for a result from the dplane for %pNG into the kernel", + nhe); + break; } } } @@ -3682,12 +3715,11 @@ void zebra_interface_nhg_reinstall(struct interface *ifp) &rb_node_dep->nhe->nhg_dependents, rb_node_dependent) { if (IS_ZEBRA_DEBUG_NHG) - zlog_debug( - "%s dependent nhe %pNG unset installed flag", - __func__, - rb_node_dependent->nhe); - UNSET_FLAG(rb_node_dependent->nhe->flags, - NEXTHOP_GROUP_INSTALLED); + zlog_debug("%s dependent nhe %pNG Setting Reinstall flag", + __func__, + rb_node_dependent->nhe); + SET_FLAG(rb_node_dependent->nhe->flags, + NEXTHOP_GROUP_REINSTALL); } } } diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h index 4eddecb..3bb697a 100644 --- a/zebra/zebra_nhg.h +++ b/zebra/zebra_nhg.h @@ -85,7 +85,7 @@ struct nhg_hash_entry { * nhg(1)->nhg_dependents is 3 in the tree * * nhg(2)->nhg_depends is empty - * nhg(3)->nhg_dependents is 3 in the tree + * nhg(2)->nhg_dependents is 3 in the tree */ struct nhg_connected_tree_head nhg_depends, nhg_dependents; @@ -144,6 +144,14 @@ struct nhg_hash_entry { * Track FPM installation status.. */ #define NEXTHOP_GROUP_FPM (1 << 7) + +/* + * When an interface comes up install the + * singleton's and schedule the NHG's that + * are using this nhg to be reinstalled + * when installation is successful. + */ +#define NEXTHOP_GROUP_REINSTALL (1 << 8) }; /* Upper 4 bits of the NHG are reserved for indicating the NHG type */ diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index b387e99..bff8258 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -1266,327 +1266,42 @@ failure: */ void show_nexthop_json_helper(json_object *json_nexthop, const struct nexthop *nexthop, + const struct route_node *rn, const struct route_entry *re) { - json_object *json_labels = NULL; - json_object *json_backups = NULL; - json_object *json_seg6local = NULL; - json_object *json_seg6 = NULL; - json_object *json_segs = NULL; - int i; - - json_object_int_add(json_nexthop, "flags", nexthop->flags); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) - json_object_boolean_true_add(json_nexthop, "duplicate"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - json_object_boolean_true_add(json_nexthop, "fib"); - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - json_object_string_addf(json_nexthop, "ip", "%pI4", - &nexthop->gate.ipv4); - json_object_string_add(json_nexthop, "afi", "ipv4"); - - if (nexthop->ifindex) { - json_object_int_add(json_nexthop, "interfaceIndex", - nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - json_object_string_addf(json_nexthop, "ip", "%pI6", - &nexthop->gate.ipv6); - json_object_string_add(json_nexthop, "afi", "ipv6"); - - if (nexthop->ifindex) { - json_object_int_add(json_nexthop, "interfaceIndex", - nexthop->ifindex); - json_object_string_add(json_nexthop, "interfaceName", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - } - break; - - case NEXTHOP_TYPE_IFINDEX: - json_object_boolean_true_add(json_nexthop, "directlyConnected"); - json_object_int_add(json_nexthop, "interfaceIndex", - nexthop->ifindex); - json_object_string_add( - json_nexthop, "interfaceName", - ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - json_object_boolean_true_add(json_nexthop, "unreachable"); - switch (nexthop->bh_type) { - case BLACKHOLE_REJECT: - json_object_boolean_true_add(json_nexthop, "reject"); - break; - case BLACKHOLE_ADMINPROHIB: - json_object_boolean_true_add(json_nexthop, - "adminProhibited"); - break; - case BLACKHOLE_NULL: - json_object_boolean_true_add(json_nexthop, "blackhole"); - break; - case BLACKHOLE_UNSPEC: - break; - } - break; - } - - /* This nexthop is a resolver for the parent nexthop. - * Set resolver flag for better clarity and delimiter - * in flat list of nexthops in json. - */ - if (nexthop->rparent) - json_object_boolean_true_add(json_nexthop, "resolver"); - - if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) - json_object_string_add(json_nexthop, "vrf", - vrf_id_to_name(nexthop->vrf_id)); + bool display_vrfid = false; + uint8_t rn_family; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) - json_object_boolean_true_add(json_nexthop, "duplicate"); + if (re == NULL || nexthop->vrf_id != re->vrf_id) + display_vrfid = true; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - json_object_boolean_true_add(json_nexthop, "active"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - json_object_boolean_true_add(json_nexthop, "onLink"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) - json_object_boolean_true_add(json_nexthop, "linkDown"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - json_object_boolean_true_add(json_nexthop, "recursive"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - json_backups = json_object_new_array(); - for (i = 0; i < nexthop->backup_num; i++) { - json_object_array_add( - json_backups, - json_object_new_int(nexthop->backup_idx[i])); - } - - json_object_object_add(json_nexthop, "backupIndex", - json_backups); - } - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) - json_object_string_addf(json_nexthop, "source", "%pI4", - &nexthop->src.ipv4); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - json_object_string_addf(json_nexthop, "source", "%pI6", - &nexthop->src.ipv6); - break; - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_BLACKHOLE: - break; - } - - if (nexthop->nh_label && nexthop->nh_label->num_labels) { - json_labels = json_object_new_array(); - - for (int label_index = 0; - label_index < nexthop->nh_label->num_labels; label_index++) - json_object_array_add( - json_labels, - json_object_new_int(( - (nexthop->nh_label_type == - ZEBRA_LSP_EVPN) - ? label2vni( - &nexthop->nh_label->label - [label_index]) - : nexthop->nh_label->label - [label_index]))); - - json_object_object_add(json_nexthop, "labels", json_labels); - } + if (rn) + rn_family = rn->p.family; + else + rn_family = AF_UNSPEC; - if (nexthop->weight) - json_object_int_add(json_nexthop, "weight", nexthop->weight); - - if (nexthop->srte_color) - json_object_int_add(json_nexthop, "srteColor", - nexthop->srte_color); - - if (nexthop->nh_srv6) { - json_seg6local = json_object_new_object(); - json_object_string_add( - json_seg6local, "action", - seg6local_action2str( - nexthop->nh_srv6->seg6local_action)); - json_object_object_add(json_nexthop, "seg6local", - json_seg6local); - if (nexthop->nh_srv6->seg6_segs && - nexthop->nh_srv6->seg6_segs->num_segs == 1) { - json_seg6 = json_object_new_object(); - json_object_string_addf(json_seg6, "segs", "%pI6", - &nexthop->nh_srv6->seg6_segs - ->seg[0]); - json_object_object_add(json_nexthop, "seg6", json_seg6); - } else { - if (nexthop->nh_srv6->seg6_segs) { - json_segs = json_object_new_array(); - for (int seg_idx = 0; - seg_idx < - nexthop->nh_srv6->seg6_segs->num_segs; - seg_idx++) - json_object_array_add( - json_segs, - json_object_new_stringf( - "%pI6", - &nexthop->nh_srv6 - ->seg6_segs - ->seg[seg_idx])); - json_object_object_add(json_nexthop, "seg6", - json_segs); - } - } - } + nexthop_json_helper(json_nexthop, nexthop, display_vrfid, rn_family); } /* * Helper for nexthop output, used in the 'show ip route' path */ -void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, +void show_route_nexthop_helper(struct vty *vty, const struct route_node *rn, + const struct route_entry *re, const struct nexthop *nexthop) { - char buf[MPLS_LABEL_STRLEN]; - char seg_buf[SRV6_SEG_STRLEN]; - struct seg6_segs segs; - uint8_t i; - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - vty_out(vty, " via %pI4", &nexthop->gate.ipv4); - if (nexthop->ifindex) - vty_out(vty, ", %s", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - vty_out(vty, " via %s", - inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf, - sizeof(buf))); - if (nexthop->ifindex) - vty_out(vty, ", %s", - ifindex2ifname(nexthop->ifindex, - nexthop->vrf_id)); - break; - - case NEXTHOP_TYPE_IFINDEX: - vty_out(vty, " is directly connected, %s", - ifindex2ifname(nexthop->ifindex, nexthop->vrf_id)); - break; - case NEXTHOP_TYPE_BLACKHOLE: - vty_out(vty, " unreachable"); - switch (nexthop->bh_type) { - case BLACKHOLE_REJECT: - vty_out(vty, " (ICMP unreachable)"); - break; - case BLACKHOLE_ADMINPROHIB: - vty_out(vty, " (ICMP admin-prohibited)"); - break; - case BLACKHOLE_NULL: - vty_out(vty, " (blackhole)"); - break; - case BLACKHOLE_UNSPEC: - break; - } - break; - } - - if ((re == NULL || (nexthop->vrf_id != re->vrf_id))) - vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id)); - - if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - vty_out(vty, " inactive"); + bool display_vrfid = false; + uint8_t rn_family; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) - vty_out(vty, " onlink"); + if (re == NULL || nexthop->vrf_id != re->vrf_id) + display_vrfid = true; - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN)) - vty_out(vty, " linkdown"); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - vty_out(vty, " (recursive)"); - - switch (nexthop->type) { - case NEXTHOP_TYPE_IPV4: - case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) { - vty_out(vty, ", src %pI4", &nexthop->src.ipv4); - /* SR-TE information */ - if (nexthop->srte_color) - vty_out(vty, ", SR-TE color %u", - nexthop->srte_color); - } - break; - case NEXTHOP_TYPE_IPV6: - case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) - vty_out(vty, ", src %pI6", &nexthop->src.ipv6); - break; - case NEXTHOP_TYPE_IFINDEX: - case NEXTHOP_TYPE_BLACKHOLE: - break; - } - - /* Label information */ - if (nexthop->nh_label && nexthop->nh_label->num_labels) { - vty_out(vty, ", label %s", - mpls_label2str(nexthop->nh_label->num_labels, - nexthop->nh_label->label, buf, - sizeof(buf), nexthop->nh_label_type, 1)); - } - - if (nexthop->nh_srv6) { - seg6local_context2str(buf, sizeof(buf), - &nexthop->nh_srv6->seg6local_ctx, - nexthop->nh_srv6->seg6local_action); - if (nexthop->nh_srv6->seg6local_action != - ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) - vty_out(vty, ", seg6local %s %s", - seg6local_action2str( - nexthop->nh_srv6->seg6local_action), - buf); - if (nexthop->nh_srv6->seg6_segs && - IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs->seg[0], - &in6addr_any)) { - segs.num_segs = nexthop->nh_srv6->seg6_segs->num_segs; - for (i = 0; i < segs.num_segs; i++) - memcpy(&segs.segs[i], - &nexthop->nh_srv6->seg6_segs->seg[i], - sizeof(struct in6_addr)); - snprintf_seg6_segs(seg_buf, SRV6_SEG_STRLEN, &segs); - vty_out(vty, ", seg6 %s", seg_buf); - } - } - - if (nexthop->weight) - vty_out(vty, ", weight %u", nexthop->weight); - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) { - vty_out(vty, ", backup %d", nexthop->backup_idx[0]); + if (rn) + rn_family = rn->p.family; + else + rn_family = AF_UNSPEC; - for (i = 1; i < nexthop->backup_num; i++) - vty_out(vty, ",%d", nexthop->backup_idx[i]); - } + nexthop_vty_helper(vty, nexthop, display_vrfid, rn_family); } static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json) @@ -1644,9 +1359,10 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json) json_object_array_add(json_nexthop_array, json_nexthop); show_nexthop_json_helper(json_nexthop, nexthop, - NULL); + rn, NULL); } else { - show_route_nexthop_helper(vty, NULL, nexthop); + show_route_nexthop_helper(vty, rn, NULL, + nexthop); vty_out(vty, "\n"); } } diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index 07db7bb..f0b10d8 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -45,8 +45,10 @@ bool rnh_get_hide_backups(void); void show_nexthop_json_helper(json_object *json_nexthop, const struct nexthop *nexthop, + const struct route_node *rn, const struct route_entry *re); -void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re, +void show_route_nexthop_helper(struct vty *vty, const struct route_node *rn, + const struct route_entry *re, const struct nexthop *nexthop); #ifdef __cplusplus diff --git a/zebra/zebra_routemap_nb_config.c b/zebra/zebra_routemap_nb_config.c index 5bcfb72..ad012da 100644 --- a/zebra/zebra_routemap_nb_config.c +++ b/zebra/zebra_routemap_nb_config.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + #include <zebra.h> #include "lib/command.h" diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c index c5b8505..d5cd30e 100644 --- a/zebra/zebra_srv6_vty.c +++ b/zebra/zebra_srv6_vty.c @@ -475,16 +475,24 @@ static int zebra_sr_config(struct vty *vty) struct listnode *node; struct srv6_locator *locator; char str[256]; + bool display_source_srv6 = false; + + if (srv6 && !IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any)) + display_source_srv6 = true; vty_out(vty, "!\n"); - if (zebra_srv6_is_enable()) { + if (display_source_srv6 || zebra_srv6_is_enable()) { vty_out(vty, "segment-routing\n"); vty_out(vty, " srv6\n"); + } + if (display_source_srv6) { if (!IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any)) { vty_out(vty, " encapsulation\n"); vty_out(vty, " source-address %pI6\n", &srv6->encap_src_addr); } + } + if (zebra_srv6_is_enable()) { vty_out(vty, " locators\n"); for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) { inet_ntop(AF_INET6, &locator->prefix.prefix, @@ -514,6 +522,8 @@ static int zebra_sr_config(struct vty *vty) vty_out(vty, " !\n"); vty_out(vty, " exit\n"); vty_out(vty, " !\n"); + } + if (display_source_srv6 || zebra_srv6_is_enable()) { vty_out(vty, "exit\n"); vty_out(vty, "!\n"); } diff --git a/zebra/zebra_trace.c b/zebra/zebra_trace.c index fef5ad2..7b0fb32 100644 --- a/zebra/zebra_trace.c +++ b/zebra/zebra_trace.c @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + #define TRACEPOINT_CREATE_PROBES #define TRACEPOINT_DEFINE diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 9a68d5a..ae82d20 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -60,28 +60,33 @@ struct route_show_ctx { }; static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, - safi_t safi, bool use_fib, json_object *vrf_json, - bool use_json, route_tag_t tag, + safi_t safi, bool use_fib, bool use_json, + route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, unsigned short ospf_instance_id, uint32_t tableid, bool show_ng, struct route_show_ctx *ctx); static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, int mcast, bool use_fib, bool show_ng); -static void vty_show_ip_route_summary(struct vty *vty, - struct route_table *table, bool use_json); +static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table, + json_object *vrf_json, bool use_json); static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table, + json_object *vrf_json, bool use_json); /* Helper api to format a nexthop in the 'detailed' output path. */ static void show_nexthop_detail_helper(struct vty *vty, + const struct route_node *rn, const struct route_entry *re, const struct nexthop *nexthop, bool is_backup); static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table); -static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop, - struct route_entry *re, unsigned int num); +static void show_ip_route_nht_dump(struct vty *vty, + const struct nexthop *nexthop, + const struct route_node *rn, + const struct route_entry *re, + unsigned int num); DEFUN (ip_multicast_mode, ip_multicast_mode_cmd, @@ -148,8 +153,8 @@ DEFPY (show_ip_rpf, }; return do_show_ip_route(vty, VRF_DEFAULT_NAME, ip ? AFI_IP : AFI_IP6, - SAFI_MULTICAST, false, NULL, uj, 0, NULL, false, - 0, 0, 0, false, &ctx); + SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0, + 0, false, &ctx); } DEFPY (show_ip_rpf_addr, @@ -210,7 +215,7 @@ static char re_status_output_char(const struct route_entry *re, if (is_fib) { star_p = !!CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_FIB); - } else + } else if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_ACTIVE)) star_p = true; } @@ -251,7 +256,7 @@ static char re_status_output_char(const struct route_entry *re, /* * Show backup nexthop info, in the 'detailed' output path */ -static void show_nh_backup_helper(struct vty *vty, +static void show_nh_backup_helper(struct vty *vty, const struct route_node *rn, const struct route_entry *re, const struct nexthop *nexthop) { @@ -281,7 +286,7 @@ static void show_nh_backup_helper(struct vty *vty, temp = backup; while (backup) { vty_out(vty, " "); - show_nexthop_detail_helper(vty, re, backup, + show_nexthop_detail_helper(vty, rn, re, backup, true /*backup*/); vty_out(vty, "\n"); @@ -302,11 +307,11 @@ static void show_nh_backup_helper(struct vty *vty, * output path. */ static void show_nexthop_detail_helper(struct vty *vty, + const struct route_node *rn, const struct route_entry *re, const struct nexthop *nexthop, bool is_backup) { - char addrstr[32]; char buf[MPLS_LABEL_STRLEN]; int i; @@ -390,23 +395,21 @@ static void show_nexthop_detail_helper(struct vty *vty, switch (nexthop->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - if (nexthop->src.ipv4.s_addr) { - if (inet_ntop(AF_INET, &nexthop->src.ipv4, - addrstr, sizeof(addrstr))) - vty_out(vty, ", src %s", - addrstr); - } + if (nexthop->rmap_src.ipv4.s_addr) + vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4); + else if (nexthop->src.ipv4.s_addr) + vty_out(vty, ", src %pI4", &nexthop->src.ipv4); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, - &in6addr_any)) { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, - addrstr, sizeof(addrstr))) - vty_out(vty, ", src %s", - addrstr); - } + /* Allow for 5549 ipv4 prefix with ipv6 nexthop */ + if (rn->p.family == AF_INET && nexthop->rmap_src.ipv4.s_addr) + vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4); + else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any)) + vty_out(vty, ", rmapsrc %pI6", &nexthop->rmap_src.ipv6); + else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + vty_out(vty, ", src %pI6", &nexthop->src.ipv6); break; case NEXTHOP_TYPE_IFINDEX: @@ -590,13 +593,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) { /* Use helper to format each nexthop */ - show_nexthop_detail_helper(vty, re, nexthop, + show_nexthop_detail_helper(vty, rn, re, nexthop, false /*not backup*/); vty_out(vty, "\n"); /* Include backup(s), if present */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) - show_nh_backup_helper(vty, re, nexthop); + show_nh_backup_helper(vty, rn, re, nexthop); } zebra_show_ip_route_opaque(vty, re, NULL); @@ -703,8 +706,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { json_nexthop = json_object_new_object(); - show_nexthop_json_helper(json_nexthop, - nexthop, re); + show_nexthop_json_helper(json_nexthop, nexthop, rn, re); json_object_array_add(json_nexthops, json_nexthop); @@ -724,8 +726,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, for (ALL_NEXTHOPS_PTR(nhg, nexthop)) { json_nexthop = json_object_new_object(); - show_nexthop_json_helper(json_nexthop, - nexthop, re); + show_nexthop_json_helper(json_nexthop, nexthop, + rn, re); json_object_array_add(json_nexthops, json_nexthop); } @@ -790,7 +792,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, len - 3 + (2 * nexthop_level(nexthop)), ' '); } - show_route_nexthop_helper(vty, re, nexthop); + show_route_nexthop_helper(vty, rn, re, nexthop); vty_out(vty, ", %s\n", up_str); } @@ -821,7 +823,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, vty_out(vty, " b%c %*c", (star_p ? '*' : ' '), len - 3 + (2 * nexthop_level(nexthop)), ' '); - show_route_nexthop_helper(vty, re, nexthop); + show_route_nexthop_helper(vty, rn, re, nexthop); vty_out(vty, "\n"); } @@ -856,19 +858,20 @@ static void vty_show_ip_route_detail_json(struct vty *vty, vty_json(vty, json); } -static void -do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, - struct route_table *table, afi_t afi, bool use_fib, - json_object *vrf_json, route_tag_t tag, - const struct prefix *longer_prefix_p, bool supernets_only, - int type, unsigned short ospf_instance_id, bool use_json, - uint32_t tableid, bool show_ng, struct route_show_ctx *ctx) +static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, + struct route_table *table, afi_t afi, + bool use_fib, route_tag_t tag, + const struct prefix *longer_prefix_p, + bool supernets_only, int type, + unsigned short ospf_instance_id, bool use_json, + uint32_t tableid, bool show_ng, + struct route_show_ctx *ctx) { struct route_node *rn; struct route_entry *re; + bool first_json = true; int first = 1; rib_dest_t *dest; - json_object *json = NULL; json_object *json_prefix = NULL; uint32_t addr; char buf[BUFSIZ]; @@ -884,9 +887,6 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, * => display the VRF and table if specific */ - if (use_json && !vrf_json) - json = json_object_new_object(); - /* Show all routes. */ for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) { dest = rib_dest_from_rnode(rn); @@ -959,28 +959,20 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf, if (json_prefix) { prefix2str(&rn->p, buf, sizeof(buf)); - if (!vrf_json) - json_object_object_add(json, buf, json_prefix); - else - json_object_object_add(vrf_json, buf, - json_prefix); + vty_json_key(vty, buf, &first_json); + vty_json_no_pretty(vty, json_prefix); + json_prefix = NULL; } } - /* - * This is an extremely expensive operation at scale - * and non-pretty reduces memory footprint significantly. - */ - if (use_json && !vrf_json) { - vty_json_no_pretty(vty, json); - json = NULL; - } + if (use_json) + vty_json_close(vty, first_json); } static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf, - afi_t afi, bool use_fib, json_object *vrf_json, - bool use_json, route_tag_t tag, + afi_t afi, bool use_fib, bool use_json, + route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, unsigned short ospf_instance_id, bool show_ng, @@ -1000,15 +992,15 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf, continue; do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST, - use_fib, vrf_json, use_json, tag, - longer_prefix_p, supernets_only, type, - ospf_instance_id, zrt->tableid, show_ng, ctx); + use_fib, use_json, tag, longer_prefix_p, + supernets_only, type, ospf_instance_id, + zrt->tableid, show_ng, ctx); } } static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, - safi_t safi, bool use_fib, json_object *vrf_json, - bool use_json, route_tag_t tag, + safi_t safi, bool use_fib, bool use_json, + route_tag_t tag, const struct prefix *longer_prefix_p, bool supernets_only, int type, unsigned short ospf_instance_id, uint32_t tableid, @@ -1043,7 +1035,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi, return CMD_SUCCESS; } - do_show_route_helper(vty, zvrf, table, afi, use_fib, vrf_json, tag, + do_show_route_helper(vty, zvrf, table, afi, use_fib, tag, longer_prefix_p, supernets_only, type, ospf_instance_id, use_json, tableid, show_ng, ctx); @@ -1225,7 +1217,12 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe, json_object_boolean_true_add(json, "valid"); else vty_out(vty, " Valid"); - + if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) { + if (json) + json_object_boolean_true_add(json, "reInstall"); + else + vty_out(vty, ", Reinstall"); + } if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) { if (json) json_object_boolean_true_add(json, "installed"); @@ -1272,14 +1269,15 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe, for (ALL_NEXTHOPS(nhe->nhg, nexthop)) { if (json_nexthop_array) { json_nexthops = json_object_new_object(); - show_nexthop_json_helper(json_nexthops, nexthop, NULL); + show_nexthop_json_helper(json_nexthops, nexthop, NULL, + NULL); } else { if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) vty_out(vty, " "); else /* Make recursive nexthops a bit more clear */ vty_out(vty, " "); - show_route_nexthop_helper(vty, NULL, nexthop); + show_route_nexthop_helper(vty, NULL, NULL, nexthop); } if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) { @@ -1337,7 +1335,7 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe, if (json_backup_nexthop_array) { json_backup_nexthops = json_object_new_object(); show_nexthop_json_helper(json_backup_nexthops, - nexthop, NULL); + nexthop, NULL, NULL); json_object_array_add(json_backup_nexthop_array, json_backup_nexthops); } else { @@ -1350,7 +1348,8 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe, * clear */ vty_out(vty, " "); - show_route_nexthop_helper(vty, NULL, nexthop); + show_route_nexthop_helper(vty, NULL, NULL, + nexthop); vty_out(vty, "\n"); } } @@ -1481,17 +1480,18 @@ static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp) { struct zebra_if *zebra_if = NULL; struct nhg_connected *rb_node_dep = NULL; + bool first = true; zebra_if = ifp->info; - if (!if_nhg_dependents_is_empty(ifp)) { - vty_out(vty, "Interface %s:\n", ifp->name); - - frr_each(nhg_connected_tree, &zebra_if->nhg_dependents, - rb_node_dep) { - vty_out(vty, " "); - show_nexthop_group_out(vty, rb_node_dep->nhe, NULL); + frr_each (nhg_connected_tree, &zebra_if->nhg_dependents, rb_node_dep) { + if (first) { + vty_out(vty, "Interface %s:\n", ifp->name); + first = false; } + + vty_out(vty, " "); + show_nexthop_group_out(vty, rb_node_dep->nhe, NULL); } } @@ -1734,13 +1734,13 @@ DEFPY (show_route, "Nexthop Group Information\n") { afi_t afi = ipv4 ? AFI_IP : AFI_IP6; + bool first_vrf_json = true; struct vrf *vrf; int type = 0; struct zebra_vrf *zvrf; struct route_show_ctx ctx = { .multi = vrf_all || table_all, }; - json_object *root_json = NULL; if (!vrf_is_backend_netns()) { if ((vrf_all || vrf_name) && (table || table_all)) { @@ -1762,43 +1762,30 @@ DEFPY (show_route, } if (vrf_all) { - if (!!json) - root_json = json_object_new_object(); RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { - json_object *vrf_json = NULL; - if ((zvrf = vrf->info) == NULL || (zvrf->table[afi][SAFI_UNICAST] == NULL)) continue; - - if (!!json) - vrf_json = json_object_new_object(); - + if (json) + vty_json_key(vty, zvrf_name(zvrf), + &first_vrf_json); if (table_all) do_show_ip_route_all(vty, zvrf, afi, !!fib, - vrf_json, !!json, tag, + !!json, tag, prefix_str ? prefix : NULL, !!supernets_only, type, ospf_instance_id, !!ng, &ctx); else do_show_ip_route(vty, zvrf_name(zvrf), afi, - SAFI_UNICAST, !!fib, vrf_json, - !!json, tag, - prefix_str ? prefix : NULL, + SAFI_UNICAST, !!fib, !!json, + tag, prefix_str ? prefix : NULL, !!supernets_only, type, ospf_instance_id, table, !!ng, &ctx); - - if (!!json) - json_object_object_add(root_json, - zvrf_name(zvrf), - vrf_json); - } - if (!!json) { - vty_json_no_pretty(vty, root_json); - root_json = NULL; } + if (json) + vty_json_close(vty, first_vrf_json); } else { vrf_id_t vrf_id = VRF_DEFAULT; @@ -1813,13 +1800,13 @@ DEFPY (show_route, return CMD_SUCCESS; if (table_all) - do_show_ip_route_all(vty, zvrf, afi, !!fib, NULL, !!json, - tag, prefix_str ? prefix : NULL, + do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag, + prefix_str ? prefix : NULL, !!supernets_only, type, ospf_instance_id, !!ng, &ctx); else do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST, - !!fib, NULL, !!json, tag, + !!fib, !!json, tag, prefix_str ? prefix : NULL, !!supernets_only, type, ospf_instance_id, table, !!ng, &ctx); @@ -1991,11 +1978,15 @@ DEFPY (show_route_summary, afi_t afi = ipv4 ? AFI_IP : AFI_IP6; struct route_table *table; bool uj = use_json(argc, argv); + json_object *vrf_json = NULL; if (vrf_all) { struct vrf *vrf; struct zebra_vrf *zvrf; + if (uj && !vrf_json) + vrf_json = json_object_new_object(); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { if ((zvrf = vrf->info) == NULL) continue; @@ -2013,10 +2004,14 @@ DEFPY (show_route_summary, if (prefix) vty_show_ip_route_summary_prefix(vty, table, - uj); + vrf_json, uj); else - vty_show_ip_route_summary(vty, table, uj); + vty_show_ip_route_summary(vty, table, vrf_json, + uj); } + + if (uj) + vty_json(vty, vrf_json); } else { vrf_id_t vrf_id = VRF_DEFAULT; @@ -2032,9 +2027,9 @@ DEFPY (show_route_summary, return CMD_SUCCESS; if (prefix) - vty_show_ip_route_summary_prefix(vty, table, uj); + vty_show_ip_route_summary_prefix(vty, table, NULL, uj); else - vty_show_ip_route_summary(vty, table, uj); + vty_show_ip_route_summary(vty, table, NULL, uj); } return CMD_SUCCESS; @@ -2089,8 +2084,11 @@ DEFUN_HIDDEN (show_route_zebra_dump, return CMD_SUCCESS; } -static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop, - struct route_entry *re, unsigned int num) +static void show_ip_route_nht_dump(struct vty *vty, + const struct nexthop *nexthop, + const struct route_node *rn, + const struct route_entry *re, + unsigned int num) { char buf[SRCDEST2STR_BUFFER]; @@ -2114,10 +2112,12 @@ static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop, nexthop->vrf_id)); } - if (nexthop->src.ipv4.s_addr - && (inet_ntop(AF_INET, &nexthop->src.ipv4, buf, - sizeof(buf)))) - vty_out(vty, " source: %s\n", buf); + if (nexthop->rmap_src.ipv4.s_addr) + vty_out(vty, " rmapsrc: %pI4\n", + &nexthop->rmap_src.ipv4); + else if (nexthop->src.ipv4.s_addr) + vty_out(vty, " source: %pI4\n", + &nexthop->src.ipv4.s_addr); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: @@ -2134,11 +2134,15 @@ static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop, nexthop->vrf_id)); } - if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) { - if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf, - sizeof(buf))) - vty_out(vty, " source: %s\n", buf); - } + /* Allow for 5549 ipv4 prefix with ipv6 nexthop */ + if (rn->p.family == AF_INET && nexthop->rmap_src.ipv4.s_addr) + vty_out(vty, " rmapsrc: %pI4\n", + &nexthop->rmap_src.ipv4); + else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any)) + vty_out(vty, " rmapsrc: %pI6\n", + &nexthop->rmap_src.ipv6); + else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) + vty_out(vty, " source: %pI6\n", &nexthop->src.ipv6); break; case NEXTHOP_TYPE_IFINDEX: vty_out(vty, @@ -2230,7 +2234,7 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table) for (ALL_NEXTHOPS_PTR(&(re->nhe->nhg), nexthop)) { nexthop_num++; - show_ip_route_nht_dump(vty, nexthop, re, + show_ip_route_nht_dump(vty, nexthop, rn, re, nexthop_num); } @@ -2240,8 +2244,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table) } } -static void vty_show_ip_route_summary(struct vty *vty, - struct route_table *table, bool use_json) +static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table, + json_object *vrf_json, bool use_json) { struct route_node *rn; struct route_entry *re; @@ -2255,6 +2259,8 @@ static void vty_show_ip_route_summary(struct vty *vty, uint32_t is_ibgp; json_object *json_route_summary = NULL; json_object *json_route_routes = NULL; + const char *vrf_name = zvrf_name( + ((struct rib_table_info *)route_table_get_info(table))->zvrf); memset(&rib_cnt, 0, sizeof(rib_cnt)); memset(&fib_cnt, 0, sizeof(fib_cnt)); @@ -2305,10 +2311,7 @@ static void vty_show_ip_route_summary(struct vty *vty, if (!use_json) vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", - "Routes", "FIB", - zvrf_name(((struct rib_table_info *) - route_table_get_info(table)) - ->zvrf)); + "Routes", "FIB", vrf_name); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP @@ -2400,7 +2403,11 @@ static void vty_show_ip_route_summary(struct vty *vty, json_object_int_add(json_route_summary, "routesTotalFib", fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_json(vty, json_route_summary); + if (!vrf_json) + vty_json(vty, json_route_summary); + else + json_object_object_add(vrf_json, vrf_name, + json_route_summary); } else { vty_out(vty, "------\n"); vty_out(vty, "%-20s %-20d %-20d \n", "Totals", @@ -2418,6 +2425,7 @@ static void vty_show_ip_route_summary(struct vty *vty, */ static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table, + json_object *vrf_json, bool use_json) { struct route_node *rn; @@ -2431,6 +2439,8 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty, int cnt; json_object *json_route_summary = NULL; json_object *json_route_routes = NULL; + const char *vrf_name = zvrf_name( + ((struct rib_table_info *)route_table_get_info(table))->zvrf); memset(&rib_cnt, 0, sizeof(rib_cnt)); memset(&fib_cnt, 0, sizeof(fib_cnt)); @@ -2470,10 +2480,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty, if (!use_json) vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source", - "Prefix Routes", "FIB", - zvrf_name(((struct rib_table_info *) - route_table_get_info(table)) - ->zvrf)); + "Prefix Routes", "FIB", vrf_name); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { if (rib_cnt[i] > 0) { @@ -2548,7 +2555,11 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty, json_object_int_add(json_route_summary, "prefixRoutesTotalFib", fib_cnt[ZEBRA_ROUTE_TOTAL]); - vty_json(vty, json_route_summary); + if (!vrf_json) + vty_json(vty, json_route_summary); + else + json_object_object_add(vrf_json, vrf_name, + json_route_summary); } else { vty_out(vty, "------\n"); vty_out(vty, "%-20s %-20d %-20d \n", "Totals", @@ -3531,56 +3542,17 @@ DEFPY (clear_evpn_dup_addr, "IPv4 address\n" "IPv6 address\n") { - struct ipaddr host_ip = {.ipa_type = IPADDR_NONE }; - int ret = CMD_SUCCESS; - struct list *input; - struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL, - *yang_dup_mac = NULL; - - input = list_new(); - if (!vni_str) { - yang_dup = yang_data_new( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice", - "all-case"); + nb_cli_rpc_enqueue(vty, "all-vnis", NULL); } else { - yang_dup = yang_data_new_uint32( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id", - vni); - if (!is_zero_mac(&mac->eth_addr)) { - yang_dup_mac = yang_data_new_mac( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr", - &mac->eth_addr); - if (yang_dup_mac) - listnode_add(input, yang_dup_mac); - } else if (ip) { - if (sockunion_family(ip) == AF_INET) { - host_ip.ipa_type = IPADDR_V4; - host_ip.ipaddr_v4.s_addr = sockunion2ip(ip); - } else { - host_ip.ipa_type = IPADDR_V6; - memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr, - sizeof(struct in6_addr)); - } - - yang_dup_ip = yang_data_new_ip( - "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr", - &host_ip); - - if (yang_dup_ip) - listnode_add(input, yang_dup_ip); - } - } - - if (yang_dup) { - listnode_add(input, yang_dup); - ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input, - NULL); + nb_cli_rpc_enqueue(vty, "vni-id", vni_str); + if (mac_str) + nb_cli_rpc_enqueue(vty, "mac-addr", mac_str); + else if (ip_str) + nb_cli_rpc_enqueue(vty, "vni-ipaddr", ip_str); } - list_delete(&input); - - return ret; + return nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", NULL); } DEFPY_HIDDEN (evpn_accept_bgp_seq, diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 0b75ec2..b8c11e1 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -108,10 +108,11 @@ static void zevpn_build_hash_table(void); static unsigned int zebra_vxlan_sg_hash_key_make(const void *p); static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2); static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, - struct in_addr sip, struct in_addr mcast_grp); -static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, - struct in_addr sip, - struct in_addr mcast_grp); + const struct ipaddr *sip, + const struct in_addr mcast_grp); +static struct zebra_vxlan_sg * +zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, const struct ipaddr *sip, + const struct in_addr mcast_grp); static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf); bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf) @@ -769,10 +770,6 @@ static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx) json_evpn_list = json_object_new_array(); json_object_int_add(json, "vni", zl3vni->vni); json_object_string_add(json, "type", "L3"); -#if CONFDATE > 20240210 -CPP_NOTICE("Drop `vrf` from JSON outputs") -#endif - json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni)); json_object_string_add(json, "tenantVrf", zl3vni_vrf_name(zl3vni)); json_object_string_addf(json, "localVtepIp", "%pI4", @@ -5895,7 +5892,10 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf, zclient_create_header(s, cmd, VRF_DEFAULT); stream_putl(s, IPV4_MAX_BYTELEN); - stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN); + /* + * There is currently no support for IPv6 VTEPs with PIM. + */ + stream_put(s, &sg->src.ipaddr_v4, IPV4_MAX_BYTELEN); stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN); /* Write packet size. */ @@ -5918,9 +5918,17 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf, static unsigned int zebra_vxlan_sg_hash_key_make(const void *p) { const struct zebra_vxlan_sg *vxlan_sg = p; + uint32_t hash1; - return (jhash_2words(vxlan_sg->sg.src.s_addr, - vxlan_sg->sg.grp.s_addr, 0)); + if (IS_IPADDR_V4(&vxlan_sg->sg.src)) { + return (jhash_2words(vxlan_sg->sg.src.ipaddr_v4.s_addr, + vxlan_sg->sg.grp.s_addr, 0)); + } else { + hash1 = jhash_1word(vxlan_sg->sg.grp.s_addr, 0); + return jhash2(vxlan_sg->sg.src.ipaddr_v6.s6_addr32, + array_size(vxlan_sg->sg.src.ipaddr_v6.s6_addr32), + hash1); + } } static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2) @@ -5928,8 +5936,8 @@ static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2) const struct zebra_vxlan_sg *sg1 = p1; const struct zebra_vxlan_sg *sg2 = p2; - return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr) - && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr)); + return (ipaddr_is_same(&sg1->sg.src, &sg2->sg.src) && + (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr)); } static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf, @@ -5965,7 +5973,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf, { struct zebra_vxlan_sg *vxlan_sg; struct zebra_vxlan_sg *parent = NULL; - struct in_addr sip; + struct ipaddr sip; vxlan_sg = zebra_vxlan_sg_find(zvrf, sg); if (vxlan_sg) @@ -5976,9 +5984,9 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf, * 2. the XG entry is used by pimd to setup the * vxlan-termination-mroute */ - if (sg->src.s_addr != INADDR_ANY) { + if (!ipaddr_is_zero(&sg->src)) { memset(&sip, 0, sizeof(sip)); - parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp); + parent = zebra_vxlan_sg_do_ref(zvrf, &sip, sg->grp); if (!parent) return NULL; } @@ -5993,7 +6001,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf, static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg) { - struct in_addr sip; + struct ipaddr sip; struct zebra_vrf *zvrf; zvrf = vrf_info_lookup(VRF_DEFAULT); @@ -6001,13 +6009,13 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg) /* On SG entry deletion remove the reference to its parent XG * entry */ - if (vxlan_sg->sg.src.s_addr != INADDR_ANY) { + if (!ipaddr_is_zero(&vxlan_sg->sg.src)) { memset(&sip, 0, sizeof(sip)); - zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp); + zebra_vxlan_sg_do_deref(zvrf, &sip, vxlan_sg->sg.grp); } - zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, - vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL); + zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, vxlan_sg->sg_str, + ZEBRA_VXLAN_SG_DEL); hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg); @@ -6018,14 +6026,15 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg) } static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, - struct in_addr sip, struct in_addr mcast_grp) + const struct ipaddr *sip, + const struct in_addr mcast_grp) { struct zebra_vxlan_sg *vxlan_sg; struct prefix_sg sg; sg.family = AF_INET; sg.prefixlen = IPV4_MAX_BYTELEN; - sg.src = sip; + sg.src = *sip; sg.grp = mcast_grp; vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg); if (!vxlan_sg) @@ -6038,16 +6047,16 @@ static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, zebra_vxlan_sg_del(vxlan_sg); } -static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, - struct in_addr sip, - struct in_addr mcast_grp) +static struct zebra_vxlan_sg * +zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, const struct ipaddr *sip, + const struct in_addr mcast_grp) { struct zebra_vxlan_sg *vxlan_sg; struct prefix_sg sg; sg.family = AF_INET; sg.prefixlen = IPV4_MAX_BYTELEN; - sg.src = sip; + sg.src = *sip; sg.grp = mcast_grp; vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg); if (vxlan_sg) @@ -6056,10 +6065,10 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, return vxlan_sg; } -void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, - struct in_addr mcast_grp) +void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, struct in_addr mcast_grp) { struct zebra_vrf *zvrf; + struct ipaddr local_vtep_ipaddr; if (local_vtep_ip.s_addr == INADDR_ANY || mcast_grp.s_addr == INADDR_ANY) @@ -6067,20 +6076,26 @@ void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp); + SET_IPADDR_V4(&local_vtep_ipaddr); + local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip; + + zebra_vxlan_sg_do_deref(zvrf, &local_vtep_ipaddr, mcast_grp); } void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp) { struct zebra_vrf *zvrf; + struct ipaddr local_vtep_ipaddr; - if (local_vtep_ip.s_addr == INADDR_ANY - || mcast_grp.s_addr == INADDR_ANY) + if (local_vtep_ip.s_addr == INADDR_ANY || mcast_grp.s_addr == INADDR_ANY) return; zvrf = vrf_info_lookup(VRF_DEFAULT); - zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp); + SET_IPADDR_V4(&local_vtep_ipaddr); + local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip; + + zebra_vxlan_sg_do_ref(zvrf, &local_vtep_ipaddr, mcast_grp); } static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg) @@ -6090,7 +6105,7 @@ static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg) /* increment the ref count against (*,G) to prevent them from being * deleted */ - if (vxlan_sg->sg.src.s_addr == INADDR_ANY) + if (ipaddr_is_zero(&vxlan_sg->sg.src)) ++vxlan_sg->ref_cnt; } @@ -6099,7 +6114,7 @@ static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg) struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data; /* decrement the dummy ref count against (*,G) to delete them */ - if (vxlan_sg->sg.src.s_addr == INADDR_ANY) { + if (ipaddr_is_zero(&vxlan_sg->sg.src)) { if (vxlan_sg->ref_cnt) --vxlan_sg->ref_cnt; if (!vxlan_sg->ref_cnt) diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c index 3cc7e49..f4b859b 100644 --- a/zebra/zebra_vxlan_if.c +++ b/zebra/zebra_vxlan_if.c @@ -506,7 +506,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif, if ((hashcount(ctx->old_vni_table) == 0) || !(old_vni = hash_release(ctx->old_vni_table, &vni_tmp))) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("vxlan %s adding vni(%d, %d)", + zlog_debug("%s vxlan %s adding vni(%d, %d)", __func__, zif->ifp->name, vni->vni, vni->access_vlan); zebra_vxlan_if_vni_entry_add(zif, &vni_tmp); @@ -521,17 +521,39 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif, if (old_vni->access_vlan != vni->access_vlan) { if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug( - "vxlan %s updating vni(%d, %d) -> vni(%d, %d)", - zif->ifp->name, old_vni->vni, - old_vni->access_vlan, vni->vni, - vni->access_vlan); + zlog_debug("%s vxlan %s updating vni(%d, %d) -> vni(%d, %d)", + __func__, zif->ifp->name, old_vni->vni, + old_vni->access_vlan, vni->vni, + vni->access_vlan); zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni, zif); zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif); zebra_vxlan_if_update_vni(zif->ifp, vni, ctx); zebra_vxlan_vni_free(old_vni); + } else { + int ret; + + ret = zebra_evpn_vl_vxl_bridge_lookup(vni->access_vlan, zif); + /* Here ret value 0 implied bridge vlan mapping is not present + * repopulated. Ignore ret value 1 as it means vlan mapping is + * present in bridge table. + */ + if (ret < 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s vxlan %s vni %u has error accessing bridge table.", + __func__, zif->ifp->name, vni->vni); + } else if (ret == 0) { + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("%s vxlan %s vni (%u, %u) not present in bridge table", + __func__, zif->ifp->name, vni->vni, + vni->access_vlan); + zebra_evpn_vl_vxl_deref(old_vni->access_vlan, + old_vni->vni, zif); + zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif); + zebra_vxlan_if_update_vni(zif->ifp, vni, ctx); + zebra_vxlan_vni_free(old_vni); + } } return 0; @@ -768,6 +790,7 @@ vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif, return vni->vni; } +/* SVD VLAN-VNI mapping update */ int zebra_vxlan_if_vni_table_add_update(struct interface *ifp, struct hash *vni_table) { diff --git a/zebra/zserv.c b/zebra/zserv.c index 6a64176..2766853 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -306,6 +306,14 @@ zwrite_fail: * this task reschedules itself. * * Any failure in any of these actions is handled by terminating the client. + * + * The client's input buffer ibuf_fifo can have a maximum items as configured + * in the packets_to_process. This way we are not filling up the FIFO more + * than the maximum when the zebra main is busy. If the fifo has space, we + * reschedule ourselves to read more. + * + * The main thread processes the items in ibuf_fifo and always signals the + * client IO thread. */ static void zserv_read(struct event *thread) { @@ -313,15 +321,25 @@ static void zserv_read(struct event *thread) int sock; size_t already; struct stream_fifo *cache; - uint32_t p2p_orig; - - uint32_t p2p; + uint32_t p2p; /* Temp p2p used to process */ + uint32_t p2p_orig; /* Configured p2p (Default-1000) */ + int p2p_avail; /* How much space is available for p2p */ struct zmsghdr hdr; + size_t client_ibuf_fifo_cnt = stream_fifo_count_safe(client->ibuf_fifo); p2p_orig = atomic_load_explicit(&zrouter.packets_to_process, memory_order_relaxed); + p2p_avail = p2p_orig - client_ibuf_fifo_cnt; + + /* + * Do nothing if ibuf_fifo count has reached its max limit. Otherwise + * proceed and reschedule ourselves if there is space in the ibuf_fifo. + */ + if (p2p_avail <= 0) + return; + + p2p = p2p_avail; cache = stream_fifo_new(); - p2p = p2p_orig; sock = EVENT_FD(thread); while (p2p) { @@ -421,7 +439,7 @@ static void zserv_read(struct event *thread) p2p--; } - if (p2p < p2p_orig) { + if (p2p < (uint32_t)p2p_avail) { uint64_t time_now = monotime(NULL); /* update session statistics */ @@ -435,19 +453,23 @@ static void zserv_read(struct event *thread) while (cache->head) stream_fifo_push(client->ibuf_fifo, stream_fifo_pop(cache)); + /* Need to update count as main thread could have processed few */ + client_ibuf_fifo_cnt = + stream_fifo_count_safe(client->ibuf_fifo); } /* Schedule job to process those packets */ zserv_event(client, ZSERV_PROCESS_MESSAGES); - } if (IS_ZEBRA_DEBUG_PACKET) - zlog_debug("Read %d packets from client: %s", p2p_orig - p2p, - zebra_route_string(client->proto)); + zlog_debug("Read %d packets from client: %s. Current ibuf fifo count: %zu. Conf P2p %d", + p2p_avail - p2p, zebra_route_string(client->proto), + client_ibuf_fifo_cnt, p2p_orig); - /* Reschedule ourselves */ - zserv_client_event(client, ZSERV_CLIENT_READ); + /* Reschedule ourselves since we have space in ibuf_fifo */ + if (client_ibuf_fifo_cnt < p2p_orig) + zserv_client_event(client, ZSERV_CLIENT_READ); stream_fifo_free(cache); @@ -483,14 +505,20 @@ static void zserv_client_event(struct zserv *client, * as the task argument. * * Each message is popped off the client's input queue and the action associated - * with the message is executed. This proceeds until there are no more messages, - * an error occurs, or the processing limit is reached. + * with the message is executed. This proceeds until an error occurs, or the + * processing limit is reached. * * The client's I/O thread can push at most zrouter.packets_to_process messages * onto the input buffer before notifying us there are packets to read. As long * as we always process zrouter.packets_to_process messages here, then we can * rely on the read thread to handle queuing this task enough times to process * everything on the input queue. + * + * If the client ibuf always schedules a wakeup to the client IO to read more + * items from the socked buffer. This way we ensure + * - Client IO thread always tries to read the socket buffer and add more + * items to the ibuf_fifo (until max limit) + * - the hidden config change (zebra zapi-packets <>) is taken into account. */ static void zserv_process_messages(struct event *thread) { @@ -524,6 +552,9 @@ static void zserv_process_messages(struct event *thread) /* Reschedule ourselves if necessary */ if (need_resched) zserv_event(client, ZSERV_PROCESS_MESSAGES); + + /* Ensure to include the read socket in the select/poll/etc.. */ + zserv_client_event(client, ZSERV_CLIENT_READ); } int zserv_send_message(struct zserv *client, struct stream *msg) @@ -644,10 +675,14 @@ static void zserv_client_free(struct zserv *client) * If any instance are graceful restart enabled, * client is not deleted */ - if (DYNAMIC_CLIENT_GR_DISABLED(client)) { + if (DYNAMIC_CLIENT_GR_DISABLED(client) || zebra_router_in_shutdown()) { if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: Deleting client %s", __func__, zebra_route_string(client->proto)); + + if (zebra_router_in_shutdown()) + zebra_gr_client_final_shutdown(client); + zserv_client_delete(client); } else { /* Handle cases where client has GR instance. */ @@ -1090,12 +1125,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) vty_out(vty, "ES-EVI %-12u%-12u%-12u\n", client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt); vty_out(vty, "Errors: %u\n", client->error_cnt); - -#if defined DEV_BUILD vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n", client->ibuf_fifo->count, client->ibuf_fifo->max_count, client->obuf_fifo->count, client->obuf_fifo->max_count); -#endif + vty_out(vty, "\n"); } diff --git a/zebra/zserv.h b/zebra/zserv.h index e1c990f..57d6730 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -378,6 +378,7 @@ __attribute__((__noreturn__)) void zebra_finalize(struct event *event); /* * Graceful restart functions. */ +extern void zebra_gr_client_final_shutdown(struct zserv *client); extern int zebra_gr_client_disconnect(struct zserv *client); extern void zebra_gr_client_reconnect(struct zserv *client); extern void zebra_gr_stale_client_cleanup(struct list *client_list); |