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
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"
/* For struct zapi_route. */
#include "prefix.h"
+#include "ipaddr.h"
/* For struct interface and struct connected. */
#include "if.h"
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;
};
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:
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;
}
break;
case ZEBRA_ROUTE_TABLE:
case ZEBRA_ROUTE_NHG:
+ case ZEBRA_ROUTE_NEIGH:
proto = RTPROT_ZEBRA;
break;
case ZEBRA_ROUTE_CONNECT:
* 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.
* @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;
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;
}
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
}
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;
}
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;
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));
*/
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)
}
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,
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:
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;
{
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;
}
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);
}
*/
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;
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
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:
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;
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)
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).
*/
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;
}
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;
}
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;
}
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;
}
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;
}
{
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;
}
* 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);
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;
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));
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);
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,
};
/*
#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)
#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)
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);
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.
*/
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:
[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 */
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: