From 506efd379b4ed72454650a32049028a7f5b4c5c8 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Fri, 27 Mar 2020 16:36:24 -0700 Subject: zebra: support for adding L2NHG and mac-ecmp in the linux kernel Multihoming support requires a new dataplane feature, MAC-ECMP, to bridge traffic to remote ESs that are attached to more than one active VTEP. As a part of this support indirection has also been added via L2-NHGs. Using a nexthop group allows for fast failover of MAC entries when an access port attached to a remote-ES goes down i.e. instead of updating many MAC entries this becomes a single NHG update to the dataplane. Note: Some of the code here needs to be reworked to the new dataplane model. Signed-off-by: Anuradha Karuppiah --- zebra/zebra_dplane.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'zebra/zebra_dplane.c') diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 53956e3ae..dc4bd4a8c 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -180,6 +180,7 @@ struct dplane_mac_info { struct ethaddr mac; struct in_addr vtep_ip; bool is_sticky; + uint32_t nhg_id; }; /* @@ -441,7 +442,7 @@ static enum zebra_dplane_result mac_update_common( enum dplane_op_e op, const struct interface *ifp, const struct interface *br_ifp, vlanid_t vid, const struct ethaddr *mac, - struct in_addr vtep_ip, bool sticky); + struct in_addr vtep_ip, bool sticky, uint32_t nhg_id); static enum zebra_dplane_result neigh_update_internal( enum dplane_op_e op, const struct interface *ifp, @@ -1552,6 +1553,12 @@ bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx) return ctx->u.macinfo.is_sticky; } +uint32_t dplane_ctx_mac_get_nhg_id(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.macinfo.nhg_id; +} + const struct ethaddr *dplane_ctx_mac_get_addr( const struct zebra_dplane_ctx *ctx) { @@ -2900,13 +2907,14 @@ enum zebra_dplane_result dplane_mac_add(const struct interface *ifp, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, - bool sticky) + bool sticky, + uint32_t nhg_id) { enum zebra_dplane_result result; /* Use common helper api */ result = mac_update_common(DPLANE_OP_MAC_INSTALL, ifp, bridge_ifp, - vid, mac, vtep_ip, sticky); + vid, mac, vtep_ip, sticky, nhg_id); return result; } @@ -2923,7 +2931,7 @@ enum zebra_dplane_result dplane_mac_del(const struct interface *ifp, /* Use common helper api */ result = mac_update_common(DPLANE_OP_MAC_DELETE, ifp, bridge_ifp, - vid, mac, vtep_ip, false); + vid, mac, vtep_ip, false, 0); return result; } @@ -2937,7 +2945,8 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, - bool sticky) + bool sticky, + uint32_t nhg_id) { struct zebra_ns *zns; @@ -2958,6 +2967,7 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx, ctx->u.macinfo.mac = *mac; ctx->u.macinfo.vid = vid; ctx->u.macinfo.is_sticky = sticky; + ctx->u.macinfo.nhg_id = nhg_id; } /* @@ -2970,7 +2980,8 @@ mac_update_common(enum dplane_op_e op, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, - bool sticky) + bool sticky, + uint32_t nhg_id) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; int ret; @@ -2990,7 +3001,7 @@ mac_update_common(enum dplane_op_e op, ctx->zd_op = op; /* Common init for the ctx */ - dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky); + dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky, nhg_id); /* Enqueue for processing on the dplane pthread */ ret = dplane_update_enqueue(ctx); -- cgit v1.2.3 From f188e68e5cac90175f6cf0cd821ad3e3e6d25cbb Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Sat, 28 Mar 2020 10:16:30 -0700 Subject: zebra: debug flags for MAC-IP sync Filters for zebra debug logs. Signed-off-by: Anuradha Karuppiah --- zebra/debug.c | 35 +++++++++++- zebra/debug.h | 12 +++- zebra/dplane_fpm_nl.c | 3 +- zebra/rt_netlink.c | 109 +++++++++++++++++++++++++++++++------ zebra/zebra_dplane.c | 148 +++++++++++++++++++++++++++++++++++++++++++------- zebra/zebra_dplane.h | 52 +++++++++++++----- zebra/zebra_vxlan.c | 25 +++++---- 7 files changed, 318 insertions(+), 66 deletions(-) (limited to 'zebra/zebra_dplane.c') diff --git a/zebra/debug.c b/zebra/debug.c index 630614f5e..8c53ab73e 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -116,6 +116,12 @@ DEFUN_NOSH (show_debugging_zebra, if (IS_ZEBRA_DEBUG_EVPN_MH_NH) vty_out(vty, " Zebra EVPN-MH nexthop debugging is on\n"); + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) + vty_out(vty, " Zebra EVPN-MH MAC debugging is on\n"); + + if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) + vty_out(vty, " Zebra EVPN-MH Neigh debugging is on\n"); + hook_call(zebra_debug_show_debugging, vty); return CMD_SUCCESS; } @@ -329,13 +335,15 @@ DEFPY (debug_zebra_mlag, DEFPY (debug_zebra_evpn_mh, debug_zebra_evpn_mh_cmd, - "[no$no] debug zebra evpn mh ", + "[no$no] debug zebra evpn mh ", NO_STR DEBUG_STR "Zebra configuration\n" "EVPN\n" "Multihoming\n" "Ethernet Segment Debugging\n" + "MAC Debugging\n" + "Neigh Debugging\n" "Nexthop Debugging\n") { if (es) { @@ -345,6 +353,23 @@ DEFPY (debug_zebra_evpn_mh, SET_FLAG(zebra_debug_evpn_mh, ZEBRA_DEBUG_EVPN_MH_ES); } + if (mac) { + if (no) + UNSET_FLAG(zebra_debug_evpn_mh, + ZEBRA_DEBUG_EVPN_MH_MAC); + else + SET_FLAG(zebra_debug_evpn_mh, ZEBRA_DEBUG_EVPN_MH_MAC); + } + + if (neigh) { + if (no) + UNSET_FLAG(zebra_debug_evpn_mh, + ZEBRA_DEBUG_EVPN_MH_NEIGH); + else + SET_FLAG(zebra_debug_evpn_mh, + ZEBRA_DEBUG_EVPN_MH_NEIGH); + } + if (nh) { if (no) UNSET_FLAG(zebra_debug_evpn_mh, ZEBRA_DEBUG_EVPN_MH_NH); @@ -596,6 +621,14 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug zebra evpn mh nh\n"); write++; } + if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) { + vty_out(vty, "debug zebra evpn mh mac\n"); + write++; + } + if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH) { + vty_out(vty, "debug zebra evpn mh neigh\n"); + write++; + } if (IS_ZEBRA_DEBUG_PW) { vty_out(vty, "debug zebra pseudowires\n"); write++; diff --git a/zebra/debug.h b/zebra/debug.h index ffd88d1d4..8402224f1 100644 --- a/zebra/debug.h +++ b/zebra/debug.h @@ -64,6 +64,8 @@ extern "C" { #define ZEBRA_DEBUG_EVPN_MH_ES 0x01 #define ZEBRA_DEBUG_EVPN_MH_NH 0x02 +#define ZEBRA_DEBUG_EVPN_MH_MAC 0x04 +#define ZEBRA_DEBUG_EVPN_MH_NEIGH 0x08 /* Debug related macro. */ #define IS_ZEBRA_DEBUG_EVENT (zebra_debug_event & ZEBRA_DEBUG_EVENT) @@ -103,8 +105,14 @@ extern "C" { #define IS_ZEBRA_DEBUG_NHG_DETAIL \ (zebra_debug_nexthop & ZEBRA_DEBUG_NHG_DETAILED) -#define IS_ZEBRA_DEBUG_EVPN_MH_ES (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_ES) -#define IS_ZEBRA_DEBUG_EVPN_MH_NH (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_NH) +#define IS_ZEBRA_DEBUG_EVPN_MH_ES \ + (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_ES) +#define IS_ZEBRA_DEBUG_EVPN_MH_NH \ + (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_NH) +#define IS_ZEBRA_DEBUG_EVPN_MH_MAC \ + (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_MAC) +#define IS_ZEBRA_DEBUG_EVPN_MH_NEIGH \ + (zebra_debug_evpn_mh & ZEBRA_DEBUG_EVPN_MH_NEIGH) extern unsigned long zebra_debug_event; extern unsigned long zebra_debug_packet; diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index c81d45169..4165fa1b3 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -1015,7 +1015,8 @@ static void fpm_enqueue_rmac_table(struct hash_bucket *backet, void *arg) dplane_ctx_set_op(fra->ctx, DPLANE_OP_MAC_INSTALL); dplane_mac_init(fra->ctx, fra->zl3vni->vxlan_if, zif->brslave_info.br_if, vid, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, sticky); + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, sticky, + 0 /*nhg*/, 0 /*update_flags*/); if (fpm_nl_enqueue(fra->fnc, fra->ctx) == -1) { thread_add_timer(zrouter.master, fpm_rmac_send, fra->fnc, 1, &fra->fnc->t_rmacwalk); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 8977074d9..edab6d464 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -23,6 +23,7 @@ #ifdef HAVE_NETLINK #include +#include #include #include #include @@ -2687,6 +2688,7 @@ static ssize_t netlink_neigh_update_msg_encode( const struct zebra_dplane_ctx *ctx, int cmd, const struct ethaddr *mac, const struct ipaddr *ip, bool replace_obj, uint8_t family, uint8_t type, uint8_t flags, uint16_t state, uint32_t nhg_id, + bool nfy, uint8_t nfy_flags, void *data, size_t datalen) { uint8_t protocol = RTPROT_ZEBRA; @@ -2730,6 +2732,11 @@ static ssize_t netlink_neigh_update_msg_encode( if (!nl_attr_put32(&req->n, datalen, NDA_NH_ID, nhg_id)) return 0; } + if (nfy) { + if (!nl_attr_put32(&req->n, datalen, NDA_NOTIFY, + &nfy_flags, sizeof(nfy_flags))) + return 0; + } ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; if (!nl_attr_put(&req->n, datalen, NDA_DST, &ip->ip.addr, ipa_len)) @@ -2764,7 +2771,8 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, if (netlink_neigh_update_msg_encode( ctx, cmd, &dst_mac, dplane_ctx_neigh_get_ipaddr(ctx), false, PF_BRIDGE, 0, NTF_SELF, (NUD_NOARP | NUD_PERMANENT), - 0 /*nhg*/, nl_pkt, sizeof(nl_pkt)) + 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, + nl_pkt, sizeof(nl_pkt)) <= 0) return -1; @@ -2793,6 +2801,9 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) char vid_buf[20]; char dst_buf[30]; bool sticky; + bool local_inactive = false; + bool dp_static = false; + uint32_t nhg_id = 0; ndm = NLMSG_DATA(h); @@ -2840,13 +2851,29 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) inet_ntoa(vtep_ip)); } + if (tb[NDA_NH_ID]) + nhg_id = *(uint32_t *)RTA_DATA(tb[NDA_NH_ID]); + + if (ndm->ndm_state & NUD_STALE) + local_inactive = true; + + if (tb[NDA_NOTIFY]) { + uint8_t nfy_flags; + + dp_static = true; + nfy_flags = *(uint8_t *)RTA_DATA(tb[NDA_NOTIFY]); + /* local activity has not been detected on the entry */ + if (nfy_flags & (1 << BR_FDB_NFY_INACTIVE)) + local_inactive = true; + } + if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %s%s", + zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %s%s nhg %d", nl_msg_type_to_str(h->nlmsg_type), ndm->ndm_ifindex, vid_present ? vid_buf : "", ndm->ndm_state, ndm->ndm_flags, prefix_mac2str(&mac, buf, sizeof(buf)), - dst_present ? dst_buf : ""); + dst_present ? dst_buf : "", nhg_id); /* The interface should exist. */ ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(ns_id), @@ -2869,7 +2896,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) return 0; } - sticky = !!(ndm->ndm_state & NUD_NOARP); + sticky = !!(ndm->ndm_flags & NTF_STICKY); if (filter_vlan && vid != filter_vlan) { if (IS_ZEBRA_DEBUG_KERNEL) @@ -2897,7 +2924,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) vid); return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid, - sticky); + sticky, local_inactive, dp_static); } /* This is a delete notification. @@ -2910,6 +2937,9 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) * Note: We will get notifications from both bridge driver and VxLAN * driver. */ + if (nhg_id) + return 0; + if (dst_present) { u_char zero_mac[6] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; @@ -3108,17 +3138,40 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, uint8_t *data, uint8_t flags; uint16_t state; uint32_t nhg_id; + uint32_t update_flags; + bool nfy = false; + uint8_t nfy_flags = 0; cmd = dplane_ctx_get_op(ctx) == DPLANE_OP_MAC_INSTALL ? RTM_NEWNEIGH : RTM_DELNEIGH; - flags = (NTF_SELF | NTF_MASTER); + flags = NTF_MASTER; state = NUD_REACHABLE; - if (dplane_ctx_mac_is_sticky(ctx)) - state |= NUD_NOARP; - else - flags |= NTF_EXT_LEARNED; + update_flags = dplane_ctx_mac_get_update_flags(ctx); + if (update_flags & DPLANE_MAC_REMOTE) { + flags |= NTF_SELF; + if (dplane_ctx_mac_is_sticky(ctx)) + flags |= NTF_STICKY; + else + flags |= NTF_EXT_LEARNED; + /* if it was static-local previously we need to clear the + * notify flags on replace with remote + */ + if (update_flags & DPLANE_MAC_WAS_STATIC) + nfy = true; + } else { + /* local mac */ + if (update_flags & DPLANE_MAC_SET_STATIC) { + nfy_flags |= (1 << BR_FDB_NFY_STATIC); + state |= NUD_NOARP; + } + + if (update_flags & DPLANE_MAC_SET_INACTIVE) + nfy_flags |= (1 << BR_FDB_NFY_INACTIVE); + + nfy = true; + } nhg_id = dplane_ctx_mac_get_nhg_id(ctx); vtep_ip.ipaddr_v4 = *(dplane_ctx_mac_get_vtep_ip(ctx)); @@ -3136,19 +3189,30 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, uint8_t *data, else vid_buf[0] = '\0'; - zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u", + zlog_debug("Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s", nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE), dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx), vid_buf, dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "", prefix_mac2str(mac, buf, sizeof(buf)), ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), - nhg_id); + nhg_id, + (update_flags & + DPLANE_MAC_REMOTE) ? " rem" : "", + (update_flags & + DPLANE_MAC_WAS_STATIC) ? " clr_sync" : "", + (update_flags & + DPLANE_MAC_SET_STATIC) ? " static" : "", + (update_flags & + DPLANE_MAC_SET_INACTIVE) ? " inactive" : "", + (nfy & + DPLANE_MAC_SET_INACTIVE) ? " nfy" : ""); } total = netlink_neigh_update_msg_encode( ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true, - AF_BRIDGE, 0, flags, state, nhg_id, data, datalen); + AF_BRIDGE, 0, flags, state, nhg_id, nfy, nfy_flags, + data, datalen); return total; } @@ -3182,6 +3246,8 @@ static void netlink_handle_5549(struct ndmsg *ndm, struct zebra_if *zif, #define NUD_VALID \ (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE | NUD_PROBE | NUD_STALE \ | NUD_DELAY) +#define NUD_LOCAL_ACTIVE \ + (NUD_PERMANENT | NUD_NOARP | NUD_REACHABLE) static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) { @@ -3198,6 +3264,7 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) int mac_present = 0; bool is_ext; bool is_router; + bool local_inactive; ndm = NLMSG_DATA(h); @@ -3307,10 +3374,17 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id) * result * in re-adding the neighbor if it is a valid "remote" neighbor. */ - if (ndm->ndm_state & NUD_VALID) + if (ndm->ndm_state & NUD_VALID) { + local_inactive = !(ndm->ndm_state & NUD_LOCAL_ACTIVE); + + /* XXX - populate dp-static based on the sync flags + * in the kernel + */ return zebra_vxlan_handle_kernel_neigh_update( ifp, link_if, &ip, &mac, ndm->ndm_state, - is_ext, is_router); + is_ext, is_router, local_inactive, + false /* dp_static */); + } return zebra_vxlan_handle_kernel_neigh_del(ifp, link_if, &ip); } @@ -3565,8 +3639,9 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, } if (netlink_neigh_update_msg_encode(ctx, cmd, mac, ip, true, family, - RTN_UNICAST, flags, state, nl_pkt, - sizeof(nl_pkt)) + RTN_UNICAST, flags, state, + 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, + nl_pkt, sizeof(nl_pkt)) <= 0) return -1; diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index dc4bd4a8c..3f7812a74 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -181,6 +181,7 @@ struct dplane_mac_info { struct in_addr vtep_ip; bool is_sticky; uint32_t nhg_id; + uint32_t update_flags; }; /* @@ -191,6 +192,7 @@ struct dplane_neigh_info { struct ethaddr mac; uint32_t flags; uint16_t state; + uint32_t update_flags; }; /* @@ -442,13 +444,14 @@ static enum zebra_dplane_result mac_update_common( enum dplane_op_e op, const struct interface *ifp, const struct interface *br_ifp, vlanid_t vid, const struct ethaddr *mac, - struct in_addr vtep_ip, bool sticky, uint32_t nhg_id); + struct in_addr vtep_ip, bool sticky, uint32_t nhg_id, + uint32_t update_flags); static enum zebra_dplane_result neigh_update_internal( enum dplane_op_e op, const struct interface *ifp, const struct ethaddr *mac, const struct ipaddr *ip, - uint32_t flags, uint16_t state); + uint32_t flags, uint16_t state, uint32_t update_flags); /* * Public APIs @@ -1559,6 +1562,12 @@ uint32_t dplane_ctx_mac_get_nhg_id(const struct zebra_dplane_ctx *ctx) return ctx->u.macinfo.nhg_id; } +uint32_t dplane_ctx_mac_get_update_flags(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.macinfo.update_flags; +} + const struct ethaddr *dplane_ctx_mac_get_addr( const struct zebra_dplane_ctx *ctx) { @@ -1606,6 +1615,12 @@ uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx) return ctx->u.neigh.state; } +uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + return ctx->u.neigh.update_flags; +} + /* Accessors for PBR rule information */ int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx) { @@ -2902,36 +2917,75 @@ static enum zebra_dplane_result intf_addr_update_internal( /* * Enqueue vxlan/evpn mac add (or update). */ -enum zebra_dplane_result dplane_mac_add(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_mac_add(const struct interface *ifp, const struct interface *bridge_ifp, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, bool sticky, - uint32_t nhg_id) + uint32_t nhg_id, + bool was_static) { enum zebra_dplane_result result; + uint32_t update_flags = 0; + + update_flags |= DPLANE_MAC_REMOTE; + if (was_static) + update_flags |= DPLANE_MAC_WAS_STATIC; /* Use common helper api */ result = mac_update_common(DPLANE_OP_MAC_INSTALL, ifp, bridge_ifp, - vid, mac, vtep_ip, sticky, nhg_id); + vid, mac, vtep_ip, sticky, nhg_id, update_flags); return result; } /* * Enqueue vxlan/evpn mac delete. */ -enum zebra_dplane_result dplane_mac_del(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp, const struct interface *bridge_ifp, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip) { enum zebra_dplane_result result; + uint32_t update_flags = 0; + + update_flags |= DPLANE_MAC_REMOTE; /* Use common helper api */ result = mac_update_common(DPLANE_OP_MAC_DELETE, ifp, bridge_ifp, - vid, mac, vtep_ip, false, 0); + vid, mac, vtep_ip, false, 0, update_flags); + return result; +} + +/* + * Enqueue local mac add (or update). + */ +enum zebra_dplane_result dplane_local_mac_add(const struct interface *ifp, + const struct interface *bridge_ifp, + vlanid_t vid, + const struct ethaddr *mac, + bool sticky, + uint32_t set_static, + uint32_t set_inactive) +{ + enum zebra_dplane_result result; + uint32_t update_flags = 0; + struct in_addr vtep_ip; + + if (set_static) + update_flags |= DPLANE_MAC_SET_STATIC; + + if (set_inactive) + update_flags |= DPLANE_MAC_SET_INACTIVE; + + vtep_ip.s_addr = 0; + + /* Use common helper api */ + result = mac_update_common(DPLANE_OP_MAC_INSTALL, ifp, bridge_ifp, + vid, mac, vtep_ip, sticky, 0, + update_flags); return result; } @@ -2946,7 +3000,8 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx, const struct ethaddr *mac, struct in_addr vtep_ip, bool sticky, - uint32_t nhg_id) + uint32_t nhg_id, + uint32_t update_flags) { struct zebra_ns *zns; @@ -2968,6 +3023,7 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx, ctx->u.macinfo.vid = vid; ctx->u.macinfo.is_sticky = sticky; ctx->u.macinfo.nhg_id = nhg_id; + ctx->u.macinfo.update_flags = update_flags; } /* @@ -2981,7 +3037,8 @@ mac_update_common(enum dplane_op_e op, const struct ethaddr *mac, struct in_addr vtep_ip, bool sticky, - uint32_t nhg_id) + uint32_t nhg_id, + uint32_t update_flags) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; int ret; @@ -3001,7 +3058,8 @@ mac_update_common(enum dplane_op_e op, ctx->zd_op = op; /* Common init for the ctx */ - dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky, nhg_id); + dplane_mac_init(ctx, ifp, br_ifp, vid, mac, vtep_ip, sticky, + nhg_id, update_flags); /* Enqueue for processing on the dplane pthread */ ret = dplane_update_enqueue(ctx); @@ -3025,15 +3083,56 @@ mac_update_common(enum dplane_op_e op, /* * Enqueue evpn neighbor add for the dataplane. */ -enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_neigh_add(const struct interface *ifp, const struct ipaddr *ip, const struct ethaddr *mac, - uint32_t flags) + uint32_t flags, bool was_static) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + uint32_t update_flags = 0; + + update_flags |= DPLANE_NEIGH_REMOTE; + + if (was_static) + update_flags |= DPLANE_NEIGH_WAS_STATIC; result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL, - ifp, mac, ip, flags, DPLANE_NUD_NOARP); + ifp, mac, ip, flags, DPLANE_NUD_NOARP, + update_flags); + + return result; +} + +/* + * Enqueue local neighbor add for the dataplane. + */ +enum zebra_dplane_result dplane_local_neigh_add(const struct interface *ifp, + const struct ipaddr *ip, + const struct ethaddr *mac, + bool set_router, bool set_static, + bool set_inactive) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + uint32_t update_flags = 0; + uint32_t ntf = 0; + uint16_t state; + + if (set_static) + update_flags |= DPLANE_NEIGH_SET_STATIC; + + if (set_inactive) { + update_flags |= DPLANE_NEIGH_SET_INACTIVE; + state = DPLANE_NUD_STALE; + } else { + state = DPLANE_NUD_REACHABLE; + } + + if (set_router) + ntf |= DPLANE_NTF_ROUTER; + + result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL, + ifp, mac, ip, ntf, + state, update_flags); return result; } @@ -3041,14 +3140,18 @@ enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp, /* * Enqueue evpn neighbor update for the dataplane. */ -enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_neigh_update(const struct interface *ifp, const struct ipaddr *ip, const struct ethaddr *mac) { enum zebra_dplane_result result; + uint32_t update_flags = 0; + + update_flags |= DPLANE_NEIGH_REMOTE; result = neigh_update_internal(DPLANE_OP_NEIGH_UPDATE, - ifp, mac, ip, 0, DPLANE_NUD_PROBE); + ifp, mac, ip, 0, DPLANE_NUD_PROBE, + update_flags); return result; } @@ -3056,13 +3159,16 @@ enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp, /* * Enqueue evpn neighbor delete for the dataplane. */ -enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_neigh_delete(const struct interface *ifp, const struct ipaddr *ip) { enum zebra_dplane_result result; + uint32_t update_flags = 0; + + update_flags |= DPLANE_NEIGH_REMOTE; result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE, - ifp, NULL, ip, 0, 0); + ifp, NULL, ip, 0, 0, update_flags); return result; } @@ -3086,7 +3192,7 @@ enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp, addr.ipaddr_v4 = *ip; result = neigh_update_internal(DPLANE_OP_VTEP_ADD, - ifp, &mac, &addr, 0, 0); + ifp, &mac, &addr, 0, 0, 0); return result; } @@ -3111,7 +3217,7 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp, addr.ipaddr_v4 = *ip; result = neigh_update_internal(DPLANE_OP_VTEP_DELETE, - ifp, &mac, &addr, 0, 0); + ifp, &mac, &addr, 0, 0, 0); return result; } @@ -3124,7 +3230,8 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp, const struct ethaddr *mac, const struct ipaddr *ip, - uint32_t flags, uint16_t state) + uint32_t flags, uint16_t state, + uint32_t update_flags) { enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; int ret; @@ -3161,6 +3268,7 @@ neigh_update_internal(enum dplane_op_e op, ctx->u.neigh.mac = *mac; ctx->u.neigh.flags = flags; ctx->u.neigh.state = state; + ctx->u.neigh.update_flags = update_flags; /* Enqueue for processing on the dplane pthread */ ret = dplane_update_enqueue(ctx); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index e62b5c304..71818f2cf 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -168,6 +168,18 @@ enum dplane_op_e { #define DPLANE_NUD_NOARP 0x04 #define DPLANE_NUD_PROBE 0x08 +/* MAC update flags - dplane_mac_info.update_flags */ +#define DPLANE_MAC_REMOTE (1 << 0) +#define DPLANE_MAC_WAS_STATIC (1 << 1) +#define DPLANE_MAC_SET_STATIC (1 << 2) +#define DPLANE_MAC_SET_INACTIVE (1 << 3) + +/* Neigh update flags - dplane_neigh_info.update_flags */ +#define DPLANE_NEIGH_REMOTE (1 << 0) +#define DPLANE_NEIGH_WAS_STATIC (1 << 1) +#define DPLANE_NEIGH_SET_STATIC (1 << 2) +#define DPLANE_NEIGH_SET_INACTIVE (1 << 3) + /* Enable system route notifications */ void dplane_enable_sys_route_notifs(void); @@ -386,6 +398,7 @@ const char *dplane_ctx_get_intf_label(const struct zebra_dplane_ctx *ctx); /* Accessors for MAC information */ vlanid_t dplane_ctx_mac_get_vlan(const struct zebra_dplane_ctx *ctx); bool dplane_ctx_mac_is_sticky(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_mac_get_update_flags(const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_mac_get_nhg_id(const struct zebra_dplane_ctx *ctx); const struct ethaddr *dplane_ctx_mac_get_addr( const struct zebra_dplane_ctx *ctx); @@ -400,6 +413,7 @@ const struct ethaddr *dplane_ctx_neigh_get_mac( const struct zebra_dplane_ctx *ctx); uint32_t dplane_ctx_neigh_get_flags(const struct zebra_dplane_ctx *ctx); uint16_t dplane_ctx_neigh_get_state(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx); /* Accessors for policy based routing rule information */ int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx); @@ -498,21 +512,24 @@ enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp, /* * Enqueue evpn mac operations for the dataplane. */ -extern struct zebra_dplane_ctx *mac_update_internal( - enum dplane_op_e op, const struct interface *ifp, - const struct interface *br_ifp, - vlanid_t vid, const struct ethaddr *mac, - struct in_addr vtep_ip, bool sticky); - -enum zebra_dplane_result dplane_mac_add(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_mac_add(const struct interface *ifp, const struct interface *bridge_ifp, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, bool sticky, - uint32_t nhg_id); + uint32_t nhg_id, + bool was_static); -enum zebra_dplane_result dplane_mac_del(const struct interface *ifp, +enum zebra_dplane_result dplane_local_mac_add(const struct interface *ifp, + const struct interface *bridge_ifp, + vlanid_t vid, + const struct ethaddr *mac, + bool sticky, + uint32_t set_static, + uint32_t set_inactive); + +enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp, const struct interface *bridge_ifp, vlanid_t vid, const struct ethaddr *mac, @@ -525,19 +542,26 @@ void dplane_mac_init(struct zebra_dplane_ctx *ctx, vlanid_t vid, const struct ethaddr *mac, struct in_addr vtep_ip, - bool sticky); + bool sticky, + uint32_t nhg_id, + uint32_t update_flags); /* * Enqueue evpn neighbor updates for the dataplane. */ -enum zebra_dplane_result dplane_neigh_add(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_neigh_add(const struct interface *ifp, + const struct ipaddr *ip, + const struct ethaddr *mac, + uint32_t flags, bool was_static); +enum zebra_dplane_result dplane_local_neigh_add(const struct interface *ifp, const struct ipaddr *ip, const struct ethaddr *mac, - uint32_t flags); -enum zebra_dplane_result dplane_neigh_update(const struct interface *ifp, + bool set_router, bool set_static, + bool set_inactive); +enum zebra_dplane_result dplane_rem_neigh_update(const struct interface *ifp, const struct ipaddr *ip, const struct ethaddr *mac); -enum zebra_dplane_result dplane_neigh_delete(const struct interface *ifp, +enum zebra_dplane_result dplane_rem_neigh_delete(const struct interface *ifp, const struct ipaddr *ip); /* diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index dbfa49a6e..d2916cfce 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -2549,7 +2549,8 @@ static int zvni_neigh_install(zebra_vni_t *zvni, zebra_neigh_t *n) flags |= DPLANE_NTF_ROUTER; ZEBRA_NEIGH_SET_ACTIVE(n); - dplane_neigh_add(vlan_if, &n->ip, &n->emac, flags); + dplane_rem_neigh_add(vlan_if, &n->ip, &n->emac, flags, + false /*was_static*/); return ret; } @@ -2584,7 +2585,7 @@ static int zvni_neigh_uninstall(zebra_vni_t *zvni, zebra_neigh_t *n) ZEBRA_NEIGH_SET_INACTIVE(n); n->loc_seq = 0; - dplane_neigh_delete(vlan_if, &n->ip); + dplane_rem_neigh_delete(vlan_if, &n->ip); return 0; } @@ -2607,7 +2608,7 @@ static int zvni_neigh_probe(zebra_vni_t *zvni, zebra_neigh_t *n) if (!vlan_if) return -1; - dplane_neigh_update(vlan_if, &n->ip, &n->emac); + dplane_rem_neigh_update(vlan_if, &n->ip, &n->emac); return 0; } @@ -3833,9 +3834,9 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac) else vid = 0; - res = dplane_mac_add(zvni->vxlan_if, br_ifp, vid, + res = dplane_rem_mac_add(zvni->vxlan_if, br_ifp, vid, &mac->macaddr, mac->fwd_info.r_vtep_ip, sticky, - nhg_id); + nhg_id, false /*was_static*/); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; else @@ -3884,7 +3885,7 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac) ifp = zvni->vxlan_if; vtep_ip = mac->fwd_info.r_vtep_ip; - res = dplane_mac_del(ifp, br_ifp, vid, &mac->macaddr, vtep_ip); + res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vtep_ip); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; else @@ -4674,8 +4675,9 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) else vid = 0; - res = dplane_mac_add(zl3vni->vxlan_if, br_ifp, vid, - &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0); + res = dplane_rem_mac_add(zl3vni->vxlan_if, br_ifp, vid, + &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip, 0, 0, + false /*was_static*/); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; else @@ -4724,7 +4726,7 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac) else vid = 0; - res = dplane_mac_del(zl3vni->vxlan_if, br_ifp, vid, + res = dplane_rem_mac_del(zl3vni->vxlan_if, br_ifp, vid, &zrmac->macaddr, zrmac->fwd_info.r_vtep_ip); if (res != ZEBRA_DPLANE_REQUEST_FAILURE) return 0; @@ -4903,7 +4905,8 @@ static int zl3vni_nh_install(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) if (n->flags & ZEBRA_NEIGH_ROUTER_FLAG) flags |= DPLANE_NTF_ROUTER; - dplane_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags); + dplane_rem_neigh_add(zl3vni->svi_if, &n->ip, &n->emac, flags, + false /*was_static*/); return ret; } @@ -4920,7 +4923,7 @@ static int zl3vni_nh_uninstall(zebra_l3vni_t *zl3vni, zebra_neigh_t *n) if (!zl3vni->svi_if || !if_is_operative(zl3vni->svi_if)) return 0; - dplane_neigh_delete(zl3vni->svi_if, &n->ip); + dplane_rem_neigh_delete(zl3vni->svi_if, &n->ip); return 0; } -- cgit v1.2.3