]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra, lib: handle NEIGH_ADD/DELETE to zebra dataplane framework
authorPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 25 Feb 2021 10:12:34 +0000 (11:12 +0100)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Fri, 9 Apr 2021 16:29:58 +0000 (18:29 +0200)
EVPN neighbor operations were already done in the zebra dataplane
framework. Now that NHRP is able to use zebra to perform neighbor IP
operations (by programming link IP operations), handle this operation
under dataplane framework:
- assign two new operations NEIGH_IP_INSTALL and NEIGH_IP_DELETE; this
is reserved for GRE like interfaces:
example: ip neigh add A.B.C.D lladdr E.F.G.H
- use 'struct ipaddr' to store and encode the link ip address
- reuse dplane_neigh_info, and create an union with mac address
- reuse the protocol type and use it for neighbor operations; this
permits to store the daemon originating this neighbor operation.
a new route type is created: ZEBRA_ROUTE_NEIGH.
- the netlink level functions will handle a pointer, and a type; the
type indicates the family of the pointer: AF_INET or AF_INET6 if the
link type is an ip address, mac address otherwise.
- to keep backward compatibility with old queries, as no extension was
done, an option NEIGH_NO_EXTENSION has been put in place
- also, 2 new state flags are used: NUD_PERMANENT and NUD_FAILED.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
lib/route_types.txt
lib/zclient.h
zebra/kernel_netlink.c
zebra/rt_netlink.c
zebra/zapi_msg.c
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_nhg.c
zebra/zebra_rib.c

index c48391545d0f4a36098ae9929f8d7b0191fd2e47..32c7a89d3d01f6e40f2f46e0a969eefea7146f50 100644 (file)
@@ -85,6 +85,7 @@ ZEBRA_ROUTE_BFD,        bfd,       bfdd,   '-', 0, 0, 0,     "BFD",           bf
 ZEBRA_ROUTE_OPENFABRIC, openfabric, fabricd,  'f', 1, 1, 1,  "OpenFabric",    fabricd
 ZEBRA_ROUTE_VRRP,       vrrp,      vrrpd,  '-', 0, 0, 0,     "VRRP",          vrrpd
 ZEBRA_ROUTE_NHG,        zebra,     none,   '-', 0, 0, 0,     "Nexthop Group", none
+ZEBRA_ROUTE_NEIGH,      neigh,     none,   '-', 0, 0, 0,     "Neigh Entry",   none
 ZEBRA_ROUTE_SRTE,       srte,      none,   '-', 0, 0, 0,     "SR-TE",         none
 ZEBRA_ROUTE_ALL,        wildcard,  none,   '-', 0, 0, 0,     "-",             none
 
@@ -116,3 +117,4 @@ ZEBRA_ROUTE_BFD, "Bidirectional Fowarding Detection (BFD)"
 ZEBRA_ROUTE_VRRP, "Virtual Router Redundancy Protocol (VRRP)"
 ZEBRA_ROUTE_OPENFABRIC, "OpenFabric Routing Protocol"
 ZEBRA_ROUTE_NHG, "Zebra Nexthop Groups (NHG)"
+ZEBRA_ROUTE_NEIGH, "Zebra Neighbor Entry"
index 119194ac2978018277464ee9b599b5b450be4716..25b710311608af7d2ed084a0e8d28e9b17fc90b6 100644 (file)
@@ -23,6 +23,7 @@
 
 /* For struct zapi_route. */
 #include "prefix.h"
+#include "ipaddr.h"
 
 /* For struct interface and struct connected. */
 #include "if.h"
@@ -806,13 +807,13 @@ struct zclient_options {
 extern struct zclient_options zclient_options_default;
 
 /* link layer representation for GRE like interfaces
- * pfx_in is the underlay IP, pfx_out is the tunnel dest
+ * ip_in is the underlay IP, ip_out is the tunnel dest
  * index stands for the index of the interface
  */
 struct zapi_nbr {
        int cmd;
-       struct prefix pfx_in;
-       struct prefix pfx_out;
+       struct ipaddr ip_in;
+       struct ipaddr ip_out;
        ifindex_t index;
 };
 
index e71e6624589d42acff66b861f3c0205f3ef287a5..808602162148a734262d10504ce6f30ec5f93fc1 100644 (file)
@@ -1335,6 +1335,8 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                return netlink_put_neigh_update_msg(bth, ctx);
 
        case DPLANE_OP_RULE_ADD:
index a7fbbf133bf8d1c14d5489e3e2182637ed45ff49..97122668dc7be1cbb211700edc750e5b2ccbbc37 100644 (file)
@@ -185,6 +185,10 @@ static uint16_t neigh_state_to_netlink(uint16_t dplane_state)
                state |= NUD_PROBE;
        if (dplane_state & DPLANE_NUD_INCOMPLETE)
                state |= NUD_INCOMPLETE;
+       if (dplane_state & DPLANE_NUD_PERMANENT)
+               state |= NUD_PERMANENT;
+       if (dplane_state & DPLANE_NUD_FAILED)
+               state |= NUD_FAILED;
 
        return state;
 }
@@ -254,6 +258,7 @@ static inline int zebra2proto(int proto)
                break;
        case ZEBRA_ROUTE_TABLE:
        case ZEBRA_ROUTE_NHG:
+       case ZEBRA_ROUTE_NEIGH:
                proto = RTPROT_ZEBRA;
                break;
        case ZEBRA_ROUTE_CONNECT:
@@ -2750,7 +2755,9 @@ int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
  * entry.
  * @ctx:               Dataplane context
  * @cmd:               Netlink command (RTM_NEWNEIGH or RTM_DELNEIGH)
- * @mac:               A neighbor cache link layer address
+ * @lla:               A pointer to neighbor cache link layer address
+ * @llalen:            Length of the pointer to neighbor cache link layer
+ * address
  * @ip:                A neighbor cache n/w layer destination address
  *                     In the case of bridge FDB, this represnts the remote
  *                     VTEP IP.
@@ -2762,18 +2769,18 @@ int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
  * @state:             NUD_* states
  * @data:              data buffer pointer
  * @datalen:           total amount of data buffer space
+ * @protocol:          protocol information
  *
  * Return:             0 when the msg doesn't fit entirely in the buffer
  *                             otherwise the number of bytes written to buf.
  */
 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,
+       const struct zebra_dplane_ctx *ctx, int cmd, const void *lla,
+       int llalen, 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, bool ext, uint32_t ext_flags, void *data,
-       size_t datalen)
+       size_t datalen, uint8_t protocol)
 {
-       uint8_t protocol = RTPROT_ZEBRA;
        struct {
                struct nlmsghdr n;
                struct ndmsg ndm;
@@ -2805,8 +2812,8 @@ static ssize_t netlink_neigh_update_msg_encode(
                         sizeof(protocol)))
                return 0;
 
-       if (mac) {
-               if (!nl_attr_put(&req->n, datalen, NDA_LLADDR, mac, 6))
+       if (lla) {
+               if (!nl_attr_put(&req->n, datalen, NDA_LLADDR, lla, llalen))
                        return 0;
        }
 
@@ -2872,10 +2879,11 @@ netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd,
        struct ethaddr dst_mac = {.octet = {0}};
 
        return 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*/,
-               false /*nfy*/, 0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/,
-               buf, buflen);
+               ctx, cmd, (const void *)&dst_mac, ETH_ALEN,
+               dplane_ctx_neigh_get_ipaddr(ctx), false, PF_BRIDGE, 0, NTF_SELF,
+               (NUD_NOARP | NUD_PERMANENT), 0 /*nhg*/, false /*nfy*/,
+               0 /*nfy_flags*/, false /*ext*/, 0 /*ext_flags*/, buf, buflen,
+               zebra2proto(dplane_ctx_get_type(ctx)));
 }
 
 #ifndef NDA_RTA
@@ -3307,9 +3315,10 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
        }
 
        total = netlink_neigh_update_msg_encode(
-               ctx, cmd, dplane_ctx_mac_get_addr(ctx), &vtep_ip, true,
-               AF_BRIDGE, 0, flags, state, nhg_id, nfy, nfy_flags,
-               false /*ext*/, 0 /*ext_flags*/, data, datalen);
+               ctx, cmd, (const void *)dplane_ctx_mac_get_addr(ctx), ETH_ALEN,
+               &vtep_ip, true, AF_BRIDGE, 0, flags, state, nhg_id, nfy,
+               nfy_flags, false /*ext*/, 0 /*ext_flags*/, data, datalen,
+               zebra2proto(dplane_ctx_get_type(ctx)));
 
        return total;
 }
@@ -3743,7 +3752,12 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
                                        int cmd, void *buf, size_t buflen)
 {
        const struct ipaddr *ip;
-       const struct ethaddr *mac;
+       const struct ethaddr *mac = NULL;
+       const struct ipaddr *link_ip = NULL;
+       const void *link_ptr = NULL;
+       char buf2[ETHER_ADDR_STRLEN];
+
+       int llalen;
        uint8_t flags;
        uint16_t state;
        uint8_t family;
@@ -3752,10 +3766,24 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
        bool ext = false;
 
        ip = dplane_ctx_neigh_get_ipaddr(ctx);
-       mac = dplane_ctx_neigh_get_mac(ctx);
-       if (is_zero_mac(mac))
-               mac = NULL;
 
+       if (dplane_ctx_get_op(ctx) == DPLANE_OP_NEIGH_IP_INSTALL
+           || dplane_ctx_get_op(ctx) == DPLANE_OP_NEIGH_IP_DELETE) {
+               link_ip = dplane_ctx_neigh_get_link_ip(ctx);
+               llalen = IPADDRSZ(link_ip);
+               link_ptr = (const void *)&(link_ip->ip.addr);
+               ipaddr2str(link_ip, buf2, sizeof(buf2));
+       } else {
+               mac = dplane_ctx_neigh_get_mac(ctx);
+               llalen = ETH_ALEN;
+               link_ptr = (const void *)mac;
+               if (is_zero_mac(mac))
+                       mac = NULL;
+               if (mac)
+                       prefix_mac2str(mac, buf2, sizeof(buf2));
+               else
+                       snprintf(buf2, sizeof(buf2), "null");
+       }
        update_flags = dplane_ctx_neigh_get_update_flags(ctx);
        flags = neigh_flags_to_netlink(dplane_ctx_neigh_get_flags(ctx));
        state = neigh_state_to_netlink(dplane_ctx_neigh_get_state(ctx));
@@ -3769,7 +3797,7 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
                 */
                if (update_flags & DPLANE_NEIGH_WAS_STATIC)
                        ext = true;
-       } else {
+       } else if (!(update_flags & DPLANE_NEIGH_NO_EXTENSION)) {
                ext = true;
                /* local neigh */
                if (update_flags & DPLANE_NEIGH_SET_STATIC)
@@ -3777,15 +3805,16 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
        }
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_debug(
-                       "Tx %s family %s IF %s(%u) Neigh %pIA MAC %pEA flags 0x%x state 0x%x %sext_flags 0x%x",
+                       "Tx %s family %s IF %s(%u) Neigh %pIA %s %s flags 0x%x state 0x%x %sext_flags 0x%x",
                        nl_msg_type_to_str(cmd), nl_family_to_str(family),
                        dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
-                       ip, mac, flags, state, ext ? "ext " : "", ext_flags);
+                       ip, link_ip ? "Link " : "MAC ", buf2, flags, state,
+                       ext ? "ext " : "", ext_flags);
 
        return netlink_neigh_update_msg_encode(
-               ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state,
-               0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext, ext_flags, buf,
-               buflen);
+               ctx, cmd, link_ptr, llalen, ip, true, family, RTN_UNICAST,
+               flags, state, 0 /*nhg*/, false /*nfy*/, 0 /*nfy_flags*/, ext,
+               ext_flags, buf, buflen, zebra2proto(dplane_ctx_get_type(ctx)));
 }
 
 static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
@@ -3797,9 +3826,11 @@ static ssize_t netlink_neigh_msg_encoder(struct zebra_dplane_ctx *ctx,
        case DPLANE_OP_NEIGH_INSTALL:
        case DPLANE_OP_NEIGH_UPDATE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
                ret = netlink_neigh_update_ctx(ctx, RTM_NEWNEIGH, buf, buflen);
                break;
        case DPLANE_OP_NEIGH_DELETE:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                ret = netlink_neigh_update_ctx(ctx, RTM_DELNEIGH, buf, buflen);
                break;
        case DPLANE_OP_VTEP_ADD:
index e880a6d7b8ef52a4c29d7a00ba164bceefc419d8..8898235a33f3b2979ede6029613496ff682de1c5 100644 (file)
@@ -3214,16 +3214,16 @@ stream_failure:
        return;
 }
 
-static int zebra_neigh_read_ip(struct stream *s, struct prefix *add)
+static int zebra_neigh_read_ip(struct stream *s, struct ipaddr *add)
 {
-       STREAM_GETC(s, add->family);
-       if (add->family != AF_INET && add->family != AF_INET6)
+       uint8_t family;
+
+       STREAM_GETC(s, family);
+       if (family != AF_INET && family != AF_INET6)
                return -1;
-       STREAM_GET(&add->u.prefix, s, family2addrsize(add->family));
-       if (add->family == AF_INET)
-               add->prefixlen = IPV4_MAX_BITLEN;
-       else
-               add->prefixlen = IPV6_MAX_BITLEN;
+
+       STREAM_GET(&add->ip.addr, s, family2addrsize(family));
+       add->ipa_type = family;
        return 0;
 stream_failure:
        return -1;
@@ -3233,11 +3233,11 @@ static int zebra_neigh_get(struct stream *s, struct zapi_nbr *api, bool add)
 {
        int ret;
 
-       ret = zebra_neigh_read_ip(s, &api->pfx_in);
+       ret = zebra_neigh_read_ip(s, &api->ip_in);
        if (ret < 0)
                return -1;
        if (add) {
-               ret = zebra_neigh_read_ip(s, &api->pfx_out);
+               ret = zebra_neigh_read_ip(s, &api->ip_out);
                if (ret < 0)
                        return -1;
        }
@@ -3306,43 +3306,38 @@ static inline void zebra_neigh_add(ZAPI_HANDLER_ARGS)
        struct stream *s;
        struct zapi_nbr api;
        int ret;
-       struct zebra_ns *zns = zvrf->zns;
-       ns_id_t ns_id;
-
-       if (!zns)
-               return;
-       ns_id = zns->ns_id;
+       const struct interface *ifp;
 
        s = msg;
        memset(&api, 0, sizeof(api));
        ret = zebra_neigh_get(s, &api, true);
        if (ret < 0)
                return;
-       kernel_neigh_update(1, api.index, &api.pfx_in.u.prefix,
-                           (char *)&api.pfx_out.u.prefix,
-                           family2addrsize(api.pfx_out.family),
-                           ns_id, api.pfx_in.family, false, client->proto);
+       ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
+       if (!ifp)
+               return;
+       dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_INSTALL, ifp, &api.ip_out,
+                              &api.ip_in, false, client->proto);
 }
 
+
 static inline void zebra_neigh_del(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
        struct zapi_nbr api;
        int ret;
-       struct zebra_ns *zns = zvrf->zns;
-       ns_id_t ns_id;
+       struct interface *ifp;
 
-       if (!zns)
-               return;
-       ns_id = zns->ns_id;
        s = msg;
        memset(&api, 0, sizeof(api));
        ret = zebra_neigh_get(s, &api, false);
        if (ret < 0)
                return;
-       kernel_neigh_update(0, api.index, &api.pfx_in.u.prefix,
-                           NULL, 0, ns_id, api.pfx_in.family,
-                           true, client->proto);
+       ifp = if_lookup_by_index(api.index, zvrf_id(zvrf));
+       if (!ifp)
+               return;
+       dplane_neigh_ip_update(DPLANE_OP_NEIGH_IP_DELETE, ifp, &api.ip_out,
+                              &api.ip_in, true, client->proto);
 }
 
 
index 18fe0a7e853a597ae56964607f39df2cd019eedb..44330b785c346eb185944ffe9fe8ebd0083c56d8 100644 (file)
@@ -220,7 +220,10 @@ struct dplane_mac_info {
  */
 struct dplane_neigh_info {
        struct ipaddr ip_addr;
-       struct ethaddr mac;
+       union {
+               struct ethaddr mac;
+               struct ipaddr ip_addr;
+       } link;
        uint32_t flags;
        uint16_t state;
        uint32_t update_flags;
@@ -496,12 +499,11 @@ static enum zebra_dplane_result mac_update_common(
        vlanid_t vid, const struct ethaddr *mac,
        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 update_flags);
+static enum zebra_dplane_result
+neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
+                     const void *link, int link_family,
+                     const struct ipaddr *ip, uint32_t flags, uint16_t state,
+                     uint32_t update_flags, int protocol);
 
 /*
  * Public APIs
@@ -669,6 +671,8 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_RULE_UPDATE:
        case DPLANE_OP_NEIGH_DISCOVER:
        case DPLANE_OP_BR_PORT_UPDATE:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
        case DPLANE_OP_NONE:
        case DPLANE_OP_IPSET_ADD:
        case DPLANE_OP_IPSET_DELETE:
@@ -950,6 +954,12 @@ const char *dplane_op2str(enum dplane_op_e op)
        case DPLANE_OP_IPSET_ENTRY_DELETE:
                ret = "IPSET_ENTRY_DELETE";
                break;
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+               ret = "NEIGH_IP_INSTALL";
+               break;
+       case DPLANE_OP_NEIGH_IP_DELETE:
+               ret = "NEIGH_IP_DELETE";
+               break;
        }
 
        return ret;
@@ -1711,11 +1721,18 @@ const struct ipaddr *dplane_ctx_neigh_get_ipaddr(
        return &(ctx->u.neigh.ip_addr);
 }
 
+const struct ipaddr *
+dplane_ctx_neigh_get_link_ip(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+       return &(ctx->u.neigh.link.ip_addr);
+}
+
 const struct ethaddr *dplane_ctx_neigh_get_mac(
        const struct zebra_dplane_ctx *ctx)
 {
        DPLANE_CTX_VALID(ctx);
-       return &(ctx->u.neigh.mac);
+       return &(ctx->u.neigh.link.mac);
 }
 
 uint32_t dplane_ctx_neigh_get_flags(const struct zebra_dplane_ctx *ctx)
@@ -3435,6 +3452,44 @@ enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp,
        return result;
 }
 
+/*
+ * API to configure link local with either MAC address or IP information
+ */
+enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
+                                               const struct interface *ifp,
+                                               struct ipaddr *link_ip,
+                                               struct ipaddr *ip,
+                                               bool permanent, int protocol)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       uint16_t state = 0;
+       uint32_t update_flags;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[PREFIX_STRLEN], buf2[PREFIX_STRLEN];
+
+               ipaddr2str(link_ip, buf1, sizeof(buf1));
+               ipaddr2str(ip, buf2, sizeof(buf2));
+               zlog_debug("init link ctx %s: ifp %s, ip %s link %s",
+                          dplane_op2str(op), ifp->name, buf1, buf2);
+       }
+       if (op == DPLANE_OP_NEIGH_IP_INSTALL) {
+               if (!permanent)
+                       state = DPLANE_NUD_REACHABLE;
+               else
+                       state = DPLANE_NUD_PERMANENT;
+       } else
+               state = DPLANE_NUD_FAILED;
+
+       update_flags = DPLANE_NEIGH_NO_EXTENSION;
+
+       result = neigh_update_internal(op, ifp, (const void *)link_ip,
+                                      ipaddr_family(link_ip), ip, 0, state,
+                                      update_flags, protocol);
+
+       return result;
+}
+
 /*
  * Enqueue local mac add (or update).
  */
@@ -3584,9 +3639,9 @@ enum zebra_dplane_result dplane_rem_neigh_add(const struct interface *ifp,
        if (was_static)
                update_flags |= DPLANE_NEIGH_WAS_STATIC;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
-                                      ifp, mac, ip, flags, DPLANE_NUD_NOARP,
-                                      update_flags);
+       result = neigh_update_internal(
+               DPLANE_OP_NEIGH_INSTALL, ifp, (const void *)mac, AF_ETHERNET,
+               ip, flags, DPLANE_NUD_NOARP, update_flags, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3618,9 +3673,9 @@ enum zebra_dplane_result dplane_local_neigh_add(const struct interface *ifp,
        if (set_router)
                ntf |= DPLANE_NTF_ROUTER;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL,
-                                      ifp, mac, ip, ntf,
-                                      state, update_flags);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_INSTALL, ifp,
+                                      (const void *)mac, AF_ETHERNET, ip, ntf,
+                                      state, update_flags, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3636,8 +3691,8 @@ enum zebra_dplane_result dplane_rem_neigh_delete(const struct interface *ifp,
 
        update_flags |= DPLANE_NEIGH_REMOTE;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE,
-                                      ifp, NULL, ip, 0, 0, update_flags);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_DELETE, ifp, NULL,
+                                      AF_ETHERNET, ip, 0, 0, update_flags, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3660,8 +3715,8 @@ enum zebra_dplane_result dplane_vtep_add(const struct interface *ifp,
        SET_IPADDR_V4(&addr);
        addr.ipaddr_v4 = *ip;
 
-       result = neigh_update_internal(DPLANE_OP_VTEP_ADD,
-                                      ifp, &mac, &addr, 0, 0, 0);
+       result = neigh_update_internal(DPLANE_OP_VTEP_ADD, ifp, &mac,
+                                      AF_ETHERNET, &addr, 0, 0, 0, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3685,8 +3740,9 @@ enum zebra_dplane_result dplane_vtep_delete(const struct interface *ifp,
        SET_IPADDR_V4(&addr);
        addr.ipaddr_v4 = *ip;
 
-       result = neigh_update_internal(DPLANE_OP_VTEP_DELETE,
-                                      ifp, &mac, &addr, 0, 0, 0);
+       result = neigh_update_internal(DPLANE_OP_VTEP_DELETE, ifp,
+                                      (const void *)&mac, AF_ETHERNET, &addr,
+                                      0, 0, 0, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3696,8 +3752,9 @@ enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
 {
        enum zebra_dplane_result result;
 
-       result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL, ip,
-                                      DPLANE_NTF_USE, DPLANE_NUD_INCOMPLETE, 0);
+       result = neigh_update_internal(DPLANE_OP_NEIGH_DISCOVER, ifp, NULL,
+                                      AF_ETHERNET, ip, DPLANE_NTF_USE,
+                                      DPLANE_NUD_INCOMPLETE, 0, ZEBRA_ROUTE_NEIGH);
 
        return result;
 }
@@ -3706,27 +3763,43 @@ enum zebra_dplane_result dplane_neigh_discover(const struct interface *ifp,
  * Common helper api for neighbor updates
  */
 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 update_flags)
+neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
+                     const void *link, const int link_family,
+                     const struct ipaddr *ip, uint32_t flags, uint16_t state,
+                     uint32_t update_flags, int protocol)
 {
        enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
        int ret;
        struct zebra_dplane_ctx *ctx = NULL;
        struct zebra_ns *zns;
+       const struct ethaddr *mac = NULL;
+       const struct ipaddr *link_ip = NULL;
 
-       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
-               zlog_debug("init neigh ctx %s: ifp %s, mac %pEA, ip %pIA",
-                          dplane_op2str(op), ifp->name, mac, ip);
+       if (link_family == AF_ETHERNET)
+               mac = (const struct ethaddr *)link;
+       else
+               link_ip = (const struct ipaddr *)link;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               char buf1[PREFIX_STRLEN];
+
+               buf1[0] = '\0';
+               if (link_family == AF_ETHERNET)
+                       prefix_mac2str(mac, buf1, sizeof(buf1));
+               else
+                       ipaddr2str(link_ip, buf1, sizeof(buf1));
+               zlog_debug("init neigh ctx %s: ifp %s, %s %s, ip %pIA",
+                          dplane_op2str(op), ifp->name,
+                          link_family == AF_ETHERNET ? "mac " : "link ",
+                          buf1, ip);
+       }
 
        ctx = dplane_ctx_alloc();
 
        ctx->zd_op = op;
        ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
        ctx->zd_vrf_id = ifp->vrf_id;
+       dplane_ctx_set_type(ctx, protocol);
 
        zns = zebra_ns_lookup(ifp->vrf_id);
        dplane_ctx_ns_init(ctx, zns, false);
@@ -3739,7 +3812,10 @@ neigh_update_internal(enum dplane_op_e op,
 
        ctx->u.neigh.ip_addr = *ip;
        if (mac)
-               ctx->u.neigh.mac = *mac;
+               ctx->u.neigh.link.mac = *mac;
+       else if (link_ip)
+               ctx->u.neigh.link.ip_addr = *link_ip;
+
        ctx->u.neigh.flags = flags;
        ctx->u.neigh.state = state;
        ctx->u.neigh.update_flags = update_flags;
@@ -4433,6 +4509,8 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                ipaddr2str(dplane_ctx_neigh_get_ipaddr(ctx), buf,
                           sizeof(buf));
 
@@ -4568,6 +4646,8 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_NEIGH_DISCOVER:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
                if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
                        atomic_fetch_add_explicit(&zdplane_info.dg_neigh_errors,
                                                  1, memory_order_relaxed);
index 4913ca251f83b548d3c4bdb5592b35fe03fad8af..fb5d4225e8e154ddcf4fbed5c36c47db15e5d408 100644 (file)
@@ -165,6 +165,10 @@ enum dplane_op_e {
        DPLANE_OP_IPSET_DELETE,
        DPLANE_OP_IPSET_ENTRY_ADD,
        DPLANE_OP_IPSET_ENTRY_DELETE,
+
+       /* LINK LAYER IP address update */
+       DPLANE_OP_NEIGH_IP_INSTALL,
+       DPLANE_OP_NEIGH_IP_DELETE,
 };
 
 /*
@@ -184,6 +188,8 @@ enum dplane_op_e {
 #define DPLANE_NUD_NOARP          0x04
 #define DPLANE_NUD_PROBE          0x08
 #define DPLANE_NUD_INCOMPLETE     0x10
+#define DPLANE_NUD_PERMANENT      0x20
+#define DPLANE_NUD_FAILED         0x40
 
 /* MAC update flags - dplane_mac_info.update_flags */
 #define DPLANE_MAC_REMOTE       (1 << 0)
@@ -196,6 +202,7 @@ enum dplane_op_e {
 #define DPLANE_NEIGH_WAS_STATIC   (1 << 1)
 #define DPLANE_NEIGH_SET_STATIC   (1 << 2)
 #define DPLANE_NEIGH_SET_INACTIVE (1 << 3)
+#define DPLANE_NEIGH_NO_EXTENSION (1 << 4)
 
 #define DPLANE_BR_PORT_NON_DF (1 << 0)
 
@@ -458,6 +465,8 @@ const struct ipaddr *dplane_ctx_neigh_get_ipaddr(
        const struct zebra_dplane_ctx *ctx);
 const struct ethaddr *dplane_ctx_neigh_get_mac(
        const struct zebra_dplane_ctx *ctx);
+const struct ipaddr *
+dplane_ctx_neigh_get_link_ip(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);
@@ -584,6 +593,15 @@ enum zebra_dplane_result dplane_intf_addr_set(const struct interface *ifp,
 enum zebra_dplane_result dplane_intf_addr_unset(const struct interface *ifp,
                                                const struct connected *ifc);
 
+/*
+ * Link layer operations for the dataplane.
+ */
+enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
+                                               const struct interface *ifp,
+                                               struct ipaddr *link_ip,
+                                               struct ipaddr *ip,
+                                               bool permanent, int protocol);
+
 /*
  * Enqueue evpn mac operations for the dataplane.
  */
index 12ed024a661ea3986dc027b700b907157bcbe8dc..4ed4bc9ba7c4f96003e55a65ffa0eb96794a5565 100644 (file)
@@ -2898,6 +2898,8 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_NEIGH_INSTALL:
        case DPLANE_OP_NEIGH_UPDATE:
        case DPLANE_OP_NEIGH_DELETE:
+       case DPLANE_OP_NEIGH_IP_INSTALL:
+       case DPLANE_OP_NEIGH_IP_DELETE:
        case DPLANE_OP_VTEP_ADD:
        case DPLANE_OP_VTEP_DELETE:
        case DPLANE_OP_RULE_ADD:
index ffe4be8557fd9d37bffeffeb8abb2ac730533d76..807c9f0e81a493bb6c9be9485dcd3a6d4b1a74a1 100644 (file)
@@ -112,6 +112,7 @@ static const struct {
        [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 4},
        [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 6},
        [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 6},
+       [ZEBRA_ROUTE_NEIGH] = {ZEBRA_ROUTE_NEIGH, 255, 6},
        /* Any new route type added to zebra, should be mirrored here */
 
        /* no entry/default: 150 */
@@ -3924,6 +3925,8 @@ static int rib_process_dplane_results(struct thread *thread)
                        case DPLANE_OP_NEIGH_INSTALL:
                        case DPLANE_OP_NEIGH_UPDATE:
                        case DPLANE_OP_NEIGH_DELETE:
+                       case DPLANE_OP_NEIGH_IP_INSTALL:
+                       case DPLANE_OP_NEIGH_IP_DELETE:
                        case DPLANE_OP_VTEP_ADD:
                        case DPLANE_OP_VTEP_DELETE:
                        case DPLANE_OP_NEIGH_DISCOVER: