summaryrefslogtreecommitdiffstats
path: root/nhrpd
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2019-12-12 16:08:26 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2021-04-09 18:29:58 +0200
commitb3b7510464952d0f2f024a31c5d4aede0fcabd75 (patch)
tree4b81fc781f1d197df4fd5183b559a183b02ea32d /nhrpd
parentzebra: link layer config and notification, implementation in zebra (diff)
downloadfrr-b3b7510464952d0f2f024a31c5d4aede0fcabd75.tar.xz
frr-b3b7510464952d0f2f024a31c5d4aede0fcabd75.zip
nhrpd: link layer registration to notifications
neighbor notifications are done in zebra. so, instead of relying on nhrp, rely on zebra by using zebra api interface. Consequently, the code originally used in nhrp for netlink neighor notification is no more used. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
Diffstat (limited to 'nhrpd')
-rw-r--r--nhrpd/netlink_arp.c167
-rw-r--r--nhrpd/nhrp_route.c26
-rw-r--r--nhrpd/nhrpd.h1
3 files changed, 91 insertions, 103 deletions
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index dc4697cda..bb8e73ab1 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -19,6 +19,8 @@
#include <linux/netfilter/nfnetlink_log.h>
#include "thread.h"
+#include "stream.h"
+#include "prefix.h"
#include "nhrpd.h"
#include "netlink.h"
#include "znl.h"
@@ -27,8 +29,6 @@ int netlink_req_fd = -1;
int netlink_nflog_group;
static int netlink_log_fd = -1;
static struct thread *netlink_log_thread;
-static int netlink_listen_fd = -1;
-
typedef void (*netlink_dispatch_f)(struct nlmsghdr *msg, struct zbuf *zb);
void netlink_update_binding(struct interface *ifp, union sockunion *proto,
@@ -58,100 +58,6 @@ void netlink_update_binding(struct interface *ifp, union sockunion *proto,
zbuf_free(zb);
}
-static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
-{
- struct ndmsg *ndm;
- struct rtattr *rta;
- struct nhrp_cache *c;
- struct interface *ifp;
- struct zbuf payload;
- union sockunion addr, lladdr;
- size_t len;
- int state;
-
- memset(&lladdr, 0, sizeof(lladdr));
- ndm = znl_pull(zb, sizeof(*ndm));
- if (!ndm)
- return;
-
- sockunion_family(&addr) = AF_UNSPEC;
- while ((rta = znl_rta_pull(zb, &payload)) != NULL) {
- len = zbuf_used(&payload);
- switch (rta->rta_type) {
- case NDA_DST:
- sockunion_set(&addr, ndm->ndm_family,
- zbuf_pulln(&payload, len), len);
- break;
- case NDA_LLADDR:
- sockunion_set(&lladdr, ndm->ndm_family,
- zbuf_pulln(&payload, len), len);
- break;
- }
- }
-
- ifp = if_lookup_by_index(ndm->ndm_ifindex, VRF_DEFAULT);
- if (!ifp || sockunion_family(&addr) == AF_UNSPEC)
- return;
-
- c = nhrp_cache_get(ifp, &addr, 0);
- if (!c)
- return;
-
- debugf(NHRP_DEBUG_KERNEL,
- "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
- (msg->nlmsg_type == RTM_GETNEIGH)
- ? "who-has"
- : (msg->nlmsg_type == RTM_NEWNEIGH) ? "new-neigh"
- : "del-neigh",
- &addr, ifp->name, &lladdr, ndm->ndm_state, c->used, c->cur.type);
-
- if (msg->nlmsg_type == RTM_GETNEIGH) {
- if (c->cur.type >= NHRP_CACHE_CACHED) {
- nhrp_cache_set_used(c, 1);
- debugf(NHRP_DEBUG_KERNEL,
- "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
- &addr, ifp->name, &c->cur.remote_nbma_natoa,
- &c->cur.peer->vc->remote.nbma, &lladdr);
- /* In case of shortcuts, nbma is given by lladdr, not
- * vc->remote.nbma.
- */
- netlink_update_binding(ifp, &addr, &lladdr);
- }
- } else {
- state = (msg->nlmsg_type == RTM_NEWNEIGH) ? ndm->ndm_state
- : NUD_FAILED;
- nhrp_cache_set_used(c, state == NUD_REACHABLE);
- }
-}
-
-static int netlink_route_recv(struct thread *t)
-{
- uint8_t buf[ZNL_BUFFER_SIZE];
- int fd = THREAD_FD(t);
- struct zbuf payload, zb;
- struct nlmsghdr *n;
-
- zbuf_init(&zb, buf, sizeof(buf), 0);
- while (zbuf_recv(&zb, fd) > 0) {
- while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
- debugf(NHRP_DEBUG_KERNEL,
- "Netlink: Received msg_type %u, msg_flags %u",
- n->nlmsg_type, n->nlmsg_flags);
- switch (n->nlmsg_type) {
- case RTM_GETNEIGH:
- case RTM_NEWNEIGH:
- case RTM_DELNEIGH:
- netlink_neigh_msg(n, &payload);
- break;
- }
- }
- }
-
- thread_add_read(master, netlink_route_recv, 0, fd, NULL);
-
- return 0;
-}
-
static void netlink_log_register(int fd, int group)
{
struct nlmsghdr *n;
@@ -265,17 +171,74 @@ void netlink_set_nflog_group(int nlgroup)
}
}
+void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
+{
+ union sockunion addr = {}, lladdr = {};
+ struct interface *ifp;
+ ifindex_t idx;
+ struct ethaddr mac;
+ int state, ndm_state;
+ struct nhrp_cache *c;
+ unsigned short l2_len;
+
+ STREAM_GETL(zclient->ibuf, idx);
+ ifp = if_lookup_by_index(idx, vrf_id);
+ STREAM_GETW(zclient->ibuf, addr.sa.sa_family);
+ if (addr.sa.sa_family == AF_INET) {
+ STREAM_GET(&addr.sin.sin_addr.s_addr,
+ zclient->ibuf, IPV4_MAX_BYTELEN);
+ } else {
+ STREAM_GET(&addr.sin6.sin6_addr.s6_addr,
+ zclient->ibuf, IPV6_MAX_BYTELEN);
+ }
+ STREAM_GETL(zclient->ibuf, ndm_state);
+
+ STREAM_GETL(zclient->ibuf, l2_len);
+ if (l2_len) {
+ STREAM_GET(&mac, zclient->ibuf, l2_len);
+ if (l2_len == IPV4_MAX_BYTELEN)
+ sockunion_set(&lladdr, AF_INET, (const uint8_t *)&mac,
+ l2_len);
+ }
+ if (!ifp)
+ return;
+ c = nhrp_cache_get(ifp, &addr, 0);
+ if (!c)
+ return;
+ debugf(NHRP_DEBUG_KERNEL,
+ "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
+ (cmd == ZEBRA_NHRP_NEIGH_GET)
+ ? "who-has"
+ : (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? "new-neigh"
+ : "del-neigh",
+ &addr, ifp->name, &lladdr, ndm_state, c->used, c->cur.type);
+ if (cmd == ZEBRA_NHRP_NEIGH_GET) {
+ if (c->cur.type >= NHRP_CACHE_CACHED) {
+ nhrp_cache_set_used(c, 1);
+ debugf(NHRP_DEBUG_KERNEL,
+ "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
+ &addr, ifp->name, &c->cur.remote_nbma_natoa,
+ &c->cur.peer->vc->remote.nbma, &lladdr);
+ /* In case of shortcuts, nbma is given by lladdr, not
+ * vc->remote.nbma.
+ */
+ netlink_update_binding(ifp, &addr, &lladdr);
+ }
+ } else {
+ state = (cmd == ZEBRA_NHRP_NEIGH_ADDED) ? ndm_state
+ : NUD_FAILED;
+ nhrp_cache_set_used(c, state == NUD_REACHABLE);
+ }
+ return;
+ stream_failure:
+ return;
+}
+
void netlink_init(void)
{
netlink_req_fd = znl_open(NETLINK_ROUTE, 0);
if (netlink_req_fd < 0)
return;
-
- netlink_listen_fd = znl_open(NETLINK_ROUTE, RTMGRP_NEIGH);
- if (netlink_listen_fd < 0)
- return;
-
- thread_add_read(master, netlink_route_recv, 0, netlink_listen_fd, NULL);
}
int netlink_configure_arp(unsigned int ifindex, int pf)
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 7a4c57b5d..746b585ed 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -79,6 +79,24 @@ static void nhrp_route_update_zebra(const struct prefix *p,
}
}
+static void nhrp_zebra_register_neigh(vrf_id_t vrf_id, afi_t afi, bool reg)
+{
+ struct stream *s;
+
+ if (!zclient || zclient->sock < 0)
+ return;
+
+ s = zclient->obuf;
+ stream_reset(s);
+
+ zclient_create_header(s, reg ? ZEBRA_NHRP_NEIGH_REGISTER :
+ ZEBRA_NHRP_NEIGH_UNREGISTER,
+ vrf_id);
+ stream_putw(s, afi);
+ stream_putw_at(s, 0, stream_get_endp(s));
+ zclient_send_message(zclient);
+}
+
void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp)
{
struct route_node *rn;
@@ -344,6 +362,8 @@ static void nhrp_zebra_connected(struct zclient *zclient)
ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+ nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, true);
+ nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, true);
}
void nhrp_zebra_init(void)
@@ -357,7 +377,9 @@ void nhrp_zebra_init(void)
zclient->interface_address_delete = nhrp_interface_address_delete;
zclient->redistribute_route_add = nhrp_route_read;
zclient->redistribute_route_del = nhrp_route_read;
-
+ zclient->neighbor_added = nhrp_neighbor_operation;
+ zclient->neighbor_removed = nhrp_neighbor_operation;
+ zclient->neighbor_get = nhrp_neighbor_operation;
zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
}
@@ -372,6 +394,8 @@ static void nhrp_table_node_cleanup(struct route_table *table,
void nhrp_zebra_terminate(void)
{
+ nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false);
+ nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP6, false);
zclient_stop(zclient);
zclient_free(zclient);
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index e4afb22f8..6e7ddda18 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -326,6 +326,7 @@ int nhrp_interface_up(ZAPI_CALLBACK_ARGS);
int nhrp_interface_down(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);
int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
+void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
notifier_fn_t fn);