summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/interface.c7
-rw-r--r--zebra/rt.h5
-rw-r--r--zebra/rt_netlink.c29
-rw-r--r--zebra/rt_socket.c4
-rw-r--r--zebra/zapi_msg.c80
5 files changed, 108 insertions, 17 deletions
diff --git a/zebra/interface.c b/zebra/interface.c
index 3eeed9ac9..4b708496a 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -898,7 +898,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
* Remove and re-add any existing neighbor entry for this address,
* since Netlink doesn't currently offer update message types.
*/
- kernel_neigh_update(0, ifp->ifindex, ipv4_ll.s_addr, mac, 6, ns_id);
+ kernel_neigh_update(0, ifp->ifindex, (void *)&ipv4_ll.s_addr, mac, 6,
+ ns_id, AF_INET, true);
/* Add new neighbor entry.
*
@@ -910,8 +911,8 @@ void if_nbr_mac_to_ipv4ll_neigh_update(struct interface *ifp,
* they'll be useless to us.
*/
if (add)
- kernel_neigh_update(add, ifp->ifindex, ipv4_ll.s_addr, mac, 6,
- ns_id);
+ kernel_neigh_update(add, ifp->ifindex, (void *)&ipv4_ll.s_addr,
+ mac, 6, ns_id, AF_INET, true);
memcpy(&zif->neigh_mac[0], &mac[0], 6);
diff --git a/zebra/rt.h b/zebra/rt.h
index 00ff37875..f79ddbe95 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -68,8 +68,9 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx);
#endif /* !HAVE_NETLINK */
-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_update(int cmd, int ifindex, void *addr, char *lla,
+ int llalen, ns_id_t ns_id, uint8_t family,
+ bool permanent);
extern int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client,
bool reg);
extern int kernel_interface_set_master(struct interface *master,
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 82ef78d29..be9c91367 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1537,10 +1537,10 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
routedesc, nl_msg_type_to_str(cmd), label);
}
-static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
- int llalen, ns_id_t ns_id)
+static int netlink_neigh_update(int cmd, int ifindex, void *addr, char *lla,
+ int llalen, ns_id_t ns_id, uint8_t family,
+ bool permanent, uint8_t protocol)
{
- uint8_t protocol = RTPROT_ZEBRA;
struct {
struct nlmsghdr n;
struct ndmsg ndm;
@@ -1556,15 +1556,23 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla,
req.n.nlmsg_type = cmd; // RTM_NEWNEIGH or RTM_DELNEIGH
req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid;
- req.ndm.ndm_family = AF_INET;
- req.ndm.ndm_state = NUD_PERMANENT;
+ req.ndm.ndm_family = family;
req.ndm.ndm_ifindex = ifindex;
req.ndm.ndm_type = RTN_UNICAST;
+ if (cmd == RTM_NEWNEIGH) {
+ if (!permanent)
+ req.ndm.ndm_state = NUD_REACHABLE;
+ else
+ req.ndm.ndm_state = NUD_PERMANENT;
+ } else
+ req.ndm.ndm_state = NUD_FAILED;
nl_attr_put(&req.n, sizeof(req), NDA_PROTOCOL, &protocol,
sizeof(protocol));
- nl_attr_put32(&req.n, sizeof(req), NDA_DST, addr);
- nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
+ req.ndm.ndm_type = RTN_UNICAST;
+ nl_attr_put32(&req.n, family2addrsize(family), NDA_DST, addr);
+ if (lla)
+ nl_attr_put(&req.n, sizeof(req), NDA_LLADDR, lla, llalen);
return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns,
0);
@@ -2679,11 +2687,12 @@ int netlink_nexthop_read(struct zebra_ns *zns)
}
-int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
- int llalen, ns_id_t ns_id)
+int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
+ ns_id_t ns_id, uint8_t family, bool permanent)
{
return netlink_neigh_update(add ? RTM_NEWNEIGH : RTM_DELNEIGH, ifindex,
- addr, lla, llalen, ns_id);
+ addr, lla, llalen, ns_id, family, permanent,
+ RTPROT_ZEBRA);
}
/**
diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c
index 5fdf58962..006513ac9 100644
--- a/zebra/rt_socket.c
+++ b/zebra/rt_socket.c
@@ -368,8 +368,8 @@ int kernel_neigh_register(vrf_id_t vrf_id, struct zserv *client, bool reg)
return 0;
}
-int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
- int llalen, ns_id_t ns_id)
+int kernel_neigh_update(int add, int ifindex, void *addr, char *lla, int llalen,
+ ns_id_t ns_id, uint8_t family, bool permanent)
{
/* TODO */
return 0;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 304a6a03f..909b3b8ac 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -3214,6 +3214,39 @@ stream_failure:
return;
}
+static int zebra_neigh_read_ip(struct stream *s, struct prefix *add)
+{
+ STREAM_GETC(s, add->family);
+ if (add->family != AF_INET && add->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;
+ return 0;
+stream_failure:
+ return -1;
+}
+
+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);
+ if (ret < 0)
+ return -1;
+ if (add) {
+ ret = zebra_neigh_read_ip(s, &api->pfx_out);
+ if (ret < 0)
+ return -1;
+ }
+ STREAM_GETL(s, api->index);
+ return 0;
+stream_failure:
+ return -1;
+}
+
static inline void zebra_neigh_register(ZAPI_HANDLER_ARGS)
{
afi_t afi;
@@ -3246,6 +3279,51 @@ stream_failure:
return;
}
+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;
+
+ 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);
+}
+
+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;
+
+ 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);
+}
+
+
static inline void zread_iptable(ZAPI_HANDLER_ARGS)
{
struct zebra_pbr_iptable *zpi =
@@ -3431,6 +3509,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_NEIGH_ADD] = zebra_neigh_add,
+ [ZEBRA_NEIGH_DEL] = zebra_neigh_del,
[ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
[ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
};