summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/log.c4
-rw-r--r--lib/zclient.h13
-rw-r--r--nhrpd/netlink_arp.c23
-rw-r--r--nhrpd/nhrp_route.c26
-rw-r--r--nhrpd/nhrpd.h3
-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
10 files changed, 154 insertions, 40 deletions
diff --git a/lib/log.c b/lib/log.c
index 6e8df9951..97cf9b6cd 100644
--- a/lib/log.c
+++ b/lib/log.c
@@ -469,7 +469,9 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY(ZEBRA_NHRP_NEIGH_REMOVED),
DESC_ENTRY(ZEBRA_NHRP_NEIGH_GET),
DESC_ENTRY(ZEBRA_NHRP_NEIGH_REGISTER),
- DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER)};
+ DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER),
+ DESC_ENTRY(ZEBRA_NEIGH_ADD),
+ DESC_ENTRY(ZEBRA_NEIGH_DEL)};
#undef DESC_ENTRY
diff --git a/lib/zclient.h b/lib/zclient.h
index d0d77f93c..8d531c53f 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -228,6 +228,8 @@ typedef enum {
ZEBRA_NHRP_NEIGH_GET,
ZEBRA_NHRP_NEIGH_REGISTER,
ZEBRA_NHRP_NEIGH_UNREGISTER,
+ ZEBRA_NEIGH_ADD,
+ ZEBRA_NEIGH_DEL,
} zebra_message_types_t;
enum zebra_error_types {
@@ -802,6 +804,17 @@ 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
+ * index stands for the index of the interface
+ */
+struct zapi_nbr {
+ int cmd;
+ struct prefix pfx_in;
+ struct prefix pfx_out;
+ ifindex_t index;
+};
+
/*
* We reserve the top 4 bits for l2-NHG, everything else
* is for zebra/proto l3-NHG.
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index bb8e73ab1..bf5d74c25 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -34,28 +34,7 @@ typedef void (*netlink_dispatch_f)(struct nlmsghdr *msg, struct zbuf *zb);
void netlink_update_binding(struct interface *ifp, union sockunion *proto,
union sockunion *nbma)
{
- struct nlmsghdr *n;
- struct ndmsg *ndm;
- struct zbuf *zb = zbuf_alloc(512);
-
- n = znl_nlmsg_push(zb, nbma ? RTM_NEWNEIGH : RTM_DELNEIGH,
- NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE);
- ndm = znl_push(zb, sizeof(*ndm));
- *ndm = (struct ndmsg){
- .ndm_family = sockunion_family(proto),
- .ndm_ifindex = ifp->ifindex,
- .ndm_type = RTN_UNICAST,
- .ndm_state = nbma ? NUD_REACHABLE : NUD_FAILED,
- };
- znl_rta_push(zb, NDA_DST, sockunion_get_addr(proto),
- family2addrsize(sockunion_family(proto)));
- if (nbma)
- znl_rta_push(zb, NDA_LLADDR, sockunion_get_addr(nbma),
- family2addrsize(sockunion_family(nbma)));
- znl_nlmsg_complete(zb, n);
- zbuf_send(zb, netlink_req_fd);
- zbuf_recv(zb, netlink_req_fd);
- zbuf_free(zb);
+ nhrp_send_zebra_nbr(proto, nbma, ifp);
}
static void netlink_log_register(int fd, int group)
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 746b585ed..06a9564e8 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -392,6 +392,32 @@ static void nhrp_table_node_cleanup(struct route_table *table,
XFREE(MTYPE_NHRP_ROUTE, node->info);
}
+void nhrp_send_zebra_nbr(union sockunion *in,
+ union sockunion *out,
+ struct interface *ifp)
+{
+ struct stream *s;
+
+ if (!zclient || zclient->sock < 0)
+ return;
+ s = zclient->obuf;
+ stream_reset(s);
+ zclient_create_header(s,
+ out ? ZEBRA_NEIGH_ADD : ZEBRA_NEIGH_DEL,
+ ifp->vrf_id);
+ stream_putc(s, sockunion_family(in));
+ stream_write(s, sockunion_get_addr(in), sockunion_get_addrlen(in));
+ if (out) {
+ stream_putc(s, sockunion_family(out));
+ stream_write(s, sockunion_get_addr(out),
+ sockunion_get_addrlen(out));
+ }
+ stream_putl(s, ifp->ifindex);
+
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(zclient);
+}
+
void nhrp_zebra_terminate(void)
{
nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false);
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index 6e7ddda18..0f4635d3d 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -88,6 +88,9 @@ static inline int notifier_active(struct notifier_list *l)
void nhrp_zebra_init(void);
void nhrp_zebra_terminate(void);
+void nhrp_send_zebra_nbr(union sockunion *in,
+ union sockunion *out,
+ struct interface *ifp);
struct zbuf;
struct nhrp_vc;
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,
};