diff --git a/lib/route_types.txt b/lib/route_types.txt index c48391545d..32c7a89d3d 100644 --- a/lib/route_types.txt +++ b/lib/route_types.txt @@ -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" diff --git a/lib/zclient.h b/lib/zclient.h index 119194ac29..25b7103116 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -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; }; diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index e71e662458..8086021621 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -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: diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a7fbbf133b..97122668dc 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -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: diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index e880a6d7b8..8898235a33 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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); } diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index 18fe0a7e85..44330b785c 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -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); diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 4913ca251f..fb5d4225e8 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -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. */ diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 12ed024a66..4ed4bc9ba7 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -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: diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index ffe4be8557..807c9f0e81 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -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: