summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/log.c4
-rw-r--r--lib/zclient.h2
-rw-r--r--zebra/rt.h2
-rw-r--r--zebra/rt_netlink.c33
-rw-r--r--zebra/rt_socket.c6
-rw-r--r--zebra/zapi_msg.c81
-rw-r--r--zebra/zapi_msg.h3
-rw-r--r--zebra/zserv.c2
-rw-r--r--zebra/zserv.h3
9 files changed, 134 insertions, 2 deletions
diff --git a/lib/log.c b/lib/log.c
index 9a8a91b004..6e8df99512 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -467,7 +467,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL),
DESC_ENTRY(ZEBRA_NHRP_NEIGH_ADDED),
DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED),
- DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET)};
+ DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET),
+ DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER),
+ DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER)};
#undef DESC_ENTRY
diff --git a/lib/zclient.h b/lib/zclient.h
index a99f2eba16..d0d77f93c2 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -226,6 +226,8 @@ typedef enum {
ZEBRA_NHRP_NEIGH_ADDED,
ZEBRA_NHRP_NEIGH_REMOVED,
ZEBRA_NHRP_NEIGH_GET,
+ ZEBRA_NHRP_NEIGH_REGISTER,
+ ZEBRA_NHRP_NEIGH_UNREGISTER,
} zebra_message_types_t;
enum zebra_error_types {
diff --git a/zebra/rt.h b/zebra/rt.h
index 48f1df2868..00ff378753 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -70,6 +70,8 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx);
extern int kernel_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
int llalen, ns_id_t ns_id);
+extern int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client,
+ bool reg);
extern int kernel_interface_set_master(struct interface *master,
struct interface *slave);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 55e0775a8c..82ef78d299 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -3307,6 +3307,8 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
bool local_inactive;
uint32_t ext_flags = 0;
bool dp_static = false;
+ int l2_len = 0;
+ int cmd;
ndm = NLMSG_DATA(h);
@@ -3348,6 +3350,34 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (h->nlmsg_type == RTM_NEWNEIGH && !(ndm->ndm_state & NUD_VALID))
netlink_handle_5549(ndm, zif, ifp, &ip, true);
+ /* we send link layer information to client:
+ * - nlmsg_type = RTM_DELNEIGH|NEWNEIGH|GETNEIGH
+ * - struct ipaddr ( for DEL and GET)
+ * - struct ethaddr mac; (for NEW)
+ */
+ if (h->nlmsg_type == RTM_NEWNEIGH)
+ cmd = ZEBRA_NHRP_NEIGH_ADDED;
+ else if (h->nlmsg_type == RTM_GETNEIGH)
+ cmd = ZEBRA_NHRP_NEIGH_GET;
+ else if (h->nlmsg_type == RTM_DELNEIGH)
+ cmd = ZEBRA_NHRP_NEIGH_REMOVED;
+ else {
+ zlog_debug("%s(): unknown nlmsg type %u", __func__,
+ h->nlmsg_type);
+ return 0;
+ }
+ if (tb[NDA_LLADDR]) {
+ /* copy LLADDR information */
+ l2_len = RTA_PAYLOAD(tb[NDA_LLADDR]);
+ memcpy(&mac, RTA_DATA(tb[NDA_LLADDR]), l2_len);
+ }
+ if (l2_len == IPV4_MAX_BYTELEN || l2_len == 0)
+ zsend_nhrp_neighbor_notify(cmd, ifp, &ip, ndm->ndm_state,
+ &mac, l2_len);
+
+ if (h->nlmsg_type == RTM_GETNEIGH)
+ return 0;
+
/* The neighbor is present on an SVI. From this, we locate the
* underlying
* bridge because we're only interested in neighbors on a VxLAN bridge.
@@ -3615,7 +3645,8 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id)
int len;
struct ndmsg *ndm;
- if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH))
+ if (!(h->nlmsg_type == RTM_NEWNEIGH || h->nlmsg_type == RTM_DELNEIGH
+ || h->nlmsg_type == RTM_GETNEIGH))
return 0;
/* Length validity. */
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index a0f401c334..5fdf589624 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -362,6 +362,12 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx)
return ZEBRA_DPLANE_REQUEST_SUCCESS;
}
+int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg)
+{
+ /* TODO */
+ return 0;
+}
+
int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
int llalen, ns_id_t ns_id)
{
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index b482914418..304a6a03f1 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -974,6 +974,52 @@ void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
zserv_send_message(client, s);
}
+void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
+ struct ipaddr *ipaddr, int ndm_state,
+ void *mac, int macsize)
+{
+ struct stream *s;
+ struct listnode *node, *nnode;
+ struct zserv *client;
+ afi_t afi;
+
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("%s: Notifying Neighbor entry (%u)",
+ __PRETTY_FUNCTION__, cmd);
+
+ if (ipaddr->ipa_type == IPADDR_V4)
+ afi = AFI_IP;
+ else if (ipaddr->ipa_type == IPADDR_V6)
+ afi = AFI_IP6;
+ else
+ return;
+ for (ALL_LIST_ELEMENTS(zrouter.client_list, node, nnode, client)) {
+ if (!vrf_bitmap_check(client->nhrp_neighinfo[afi], ifp->vrf_id))
+ continue;
+
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, cmd, ifp->vrf_id);
+ stream_putl(s, ifp->ifindex);
+ if (ipaddr->ipa_type == IPADDR_V4) {
+ stream_putw(s, AF_INET);
+ stream_put(s, &ipaddr->ip._v4_addr, IPV4_MAX_BYTELEN);
+ } else if (ipaddr->ipa_type == IPADDR_V6) {
+ stream_putw(s, AF_INET6);
+ stream_put(s, &ipaddr->ip._v6_addr, IPV6_MAX_BYTELEN);
+ } else
+ return;
+ stream_putl(s, ndm_state);
+ stream_putl(s, macsize);
+ if (mac)
+ stream_put(s, mac, macsize);
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ zserv_send_message(client, s);
+ }
+}
+
+
/* Router-id is updated. Send ZEBRA_ROUTER_ID_UPDATE to client. */
int zsend_router_id_update(struct zserv *client, afi_t afi, struct prefix *p,
vrf_id_t vrf_id)
@@ -2277,6 +2323,7 @@ static void zread_vrf_unregister(ZAPI_HANDLER_ARGS)
vrf_bitmap_unset(client->redist[afi][i], zvrf_id(zvrf));
vrf_bitmap_unset(client->redist_default[afi], zvrf_id(zvrf));
vrf_bitmap_unset(client->ridinfo[afi], zvrf_id(zvrf));
+ vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
}
}
@@ -3167,6 +3214,38 @@ stream_failure:
return;
}
+static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS)
+{
+ afi_t afi;
+
+ STREAM_GETW(msg, afi);
+ if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+ zlog_warn(
+ "Invalid AFI %u while registering for neighbors notifications",
+ afi);
+ goto stream_failure;
+ }
+ vrf_bitmap_set(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+stream_failure:
+ return;
+}
+
+static inline void zebra_neigh_unregister(ZAPI_HANDLER_ARGS)
+{
+ afi_t afi;
+
+ STREAM_GETW(msg, afi);
+ if (afi <= AFI_UNSPEC || afi >= AFI_MAX) {
+ zlog_warn(
+ "Invalid AFI %u while unregistering from neighbor notifications",
+ afi);
+ goto stream_failure;
+ }
+ vrf_bitmap_unset(client->nhrp_neighinfo[afi], zvrf_id(zvrf));
+stream_failure:
+ return;
+}
+
static inline void zread_iptable(ZAPI_HANDLER_ARGS)
{
struct zebra_pbr_iptable *zpi =
@@ -3352,6 +3431,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
[ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh,
[ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
+ [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
+ [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
};
/*
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index ca471f8d98..2822619da9 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -104,6 +104,9 @@ extern int zsend_label_manager_connect_response(struct zserv *client,
extern int zsend_sr_policy_notify_status(uint32_t color,
struct ipaddr *endpoint, char *name,
int status);
+extern void zsend_nhrp_neighbor_notify(int cmd, struct interface *ifp,
+ struct ipaddr *ipaddr, int ndm_state,
+ void *mac, int macsize);
extern int zsend_client_close_notify(struct zserv *client,
struct zserv *closed_client);
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 6c5eebe6fe..f89b6fe478 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -638,6 +638,7 @@ static void zserv_client_free(struct zserv *client)
vrf_bitmap_free(client->redist_default[afi]);
vrf_bitmap_free(client->ridinfo[afi]);
+ vrf_bitmap_free(client->nhrp_neighinfo[afi]);
}
/*
@@ -760,6 +761,7 @@ static struct zserv *zserv_client_create(int sock)
client->redist[afi][i] = vrf_bitmap_init();
client->redist_default[afi] = vrf_bitmap_init();
client->ridinfo[afi] = vrf_bitmap_init();
+ client->nhrp_neighinfo[afi] = vrf_bitmap_init();
}
/* Add this client to linked list. */
diff --git a/zebra/zserv.h b/zebra/zserv.h
index c60799b8ba..203670ac1d 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -137,6 +137,9 @@ struct zserv {
/* Router-id information. */
vrf_bitmap_t ridinfo[AFI_MAX];
+ /* Router-id information. */
+ vrf_bitmap_t nhrp_neighinfo[AFI_MAX];
+
bool notify_owner;
/* Indicates if client is synchronous. */