[LEDE-DEV] [PATCH odhcpd] Support muliple RAs on single interface

ppfister at cisco.com ppfister at cisco.com
Fri Dec 8 01:33:45 PST 2017


From: Pierre Pfister <ppfister at cisco.com>

IETF is moving toward implementing IPv6 multihoming by sending
multiple RAs on a single interface:
- draft-ietf-intarea-provisioning-domains-00
- draft-ietf-rtgwg-enterprise-pa-multihoming-02

odhcpd supports configuration of multiple software interfaces
on the same physical interface, which already advertises
multiple RAs, but had two issues:
- Each RA includes all the prefixes available on the interface.
- Replies to sollicits with a single RA.

This patch introduces the prefix_filter configuration parameter
which allows filtering prefixes that are sent in a given RA,
and fixes the sollicit code in order to reply with all the RAs
that are configured on a given interface.

Signed-off-by: Pierre Pfister <ppfister at cisco.com>
---
 src/config.c | 19 +++++++++++++++++++
 src/odhcpd.c | 28 +++++++++++++++++++---------
 src/odhcpd.h |  2 ++
 src/router.c |  5 +++++
 4 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/src/config.c b/src/config.c
index bb885d0..409b3b8 100644
--- a/src/config.c
+++ b/src/config.c
@@ -62,6 +62,7 @@ enum {
 	IFACE_ATTR_PD_CER,
 	IFACE_ATTR_NDPROXY_ROUTING,
 	IFACE_ATTR_NDPROXY_SLAVE,
+	IFACE_ATTR_PREFIX_FILTER,
 	IFACE_ATTR_MAX
 };
 
@@ -104,6 +105,7 @@ static const struct blobmsg_policy iface_attrs[IFACE_ATTR_MAX] = {
 	[IFACE_ATTR_RA_MTU] = { .name = "ra_mtu", .type = BLOBMSG_TYPE_INT32 },
 	[IFACE_ATTR_NDPROXY_ROUTING] = { .name = "ndproxy_routing", .type = BLOBMSG_TYPE_BOOL },
 	[IFACE_ATTR_NDPROXY_SLAVE] = { .name = "ndproxy_slave", .type = BLOBMSG_TYPE_BOOL },
+	[IFACE_ATTR_PREFIX_FILTER] = { .name = "prefix_filter", .type = BLOBMSG_TYPE_STRING },
 };
 
 static const struct uci_blob_param_info iface_attr_info[IFACE_ATTR_MAX] = {
@@ -720,6 +722,23 @@ int config_parse_interface(void *data, size_t len, const char *name, bool overwr
 	if ((c = tb[IFACE_ATTR_NDPROXY_SLAVE]))
 		iface->external = blobmsg_get_bool(c);
 
+	if ((c = tb[IFACE_ATTR_PREFIX_FILTER])) {
+		const char *str = blobmsg_get_string(c);
+		char *astr = malloc(strlen(str) + 1);
+		char *delim;
+		int l;
+		if (!astr || !strcpy(astr, str) ||
+				(delim = strchr(astr, '/')) == NULL || (*(delim++) = 0) ||
+				sscanf(delim, "%i", &l) == 0 || l > 128 ||
+				inet_pton(AF_INET6, astr, &iface->pio_filter_addr) == 0) {
+			iface->pio_filter_length = 0;
+		} else {
+			iface->pio_filter_length = l;
+		}
+		if (astr)
+			free(astr);
+	}
+
 	return 0;
 
 err:
diff --git a/src/odhcpd.c b/src/odhcpd.c
index 97a6de9..58c4338 100644
--- a/src/odhcpd.c
+++ b/src/odhcpd.c
@@ -371,12 +371,6 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even
 		if (addr.ll.sll_family == AF_PACKET)
 			destiface = addr.ll.sll_ifindex;
 
-		struct interface *iface =
-				odhcpd_get_interface_by_index(destiface);
-
-		if (!iface && addr.nl.nl_family != AF_NETLINK)
-			continue;
-
 		char ipbuf[INET6_ADDRSTRLEN] = "kernel";
 		if (addr.ll.sll_family == AF_PACKET &&
 				len >= (ssize_t)sizeof(struct ip6_hdr))
@@ -386,10 +380,26 @@ static void odhcpd_receive_packets(struct uloop_fd *u, _unused unsigned int even
 		else if (addr.in.sin_family == AF_INET)
 			inet_ntop(AF_INET, &addr.in.sin_addr, ipbuf, sizeof(ipbuf));
 
-		syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
-				ipbuf, (iface) ? iface->ifname : "netlink");
+		// From netlink
+		if (addr.nl.nl_family == AF_NETLINK) {
+			syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
+					ipbuf, "netlink");
+			e->handle_dgram(&addr, data_buf, len, NULL, dest);
+			return;
+		} else if (destiface != 0) {
+			struct interface *iface;
+			list_for_each_entry(iface, &interfaces, head) {
+				if (iface->ifindex != destiface)
+					continue;
+
+				syslog(LOG_DEBUG, "Received %li Bytes from %s%%%s", (long)len,
+						ipbuf, iface->ifname);
+
+				e->handle_dgram(&addr, data_buf, len, iface, dest);
+			}
+		}
+
 
-		e->handle_dgram(&addr, data_buf, len, iface, dest);
 	}
 }
 
diff --git a/src/odhcpd.h b/src/odhcpd.h
index fbfeb67..48ee51e 100644
--- a/src/odhcpd.h
+++ b/src/odhcpd.h
@@ -208,6 +208,8 @@ struct interface {
 	bool ra_advrouter;
 	bool ra_useleasetime;
 	bool no_dynamic_dhcp;
+	uint8_t pio_filter_length;
+	struct in6_addr pio_filter_addr;
 
 	// RA
 	int learn_routes;
diff --git a/src/router.c b/src/router.c
index c35cd12..7bc94ed 100644
--- a/src/router.c
+++ b/src/router.c
@@ -380,6 +380,11 @@ static uint64_t send_router_advert(struct interface *iface, const struct in6_add
 			continue;
 		}
 
+		if (odhcpd_bmemcmp(&addr->addr, &iface->pio_filter_addr,
+				iface->pio_filter_length) != 0 ||
+				addr->prefix < iface->pio_filter_length)
+			continue; // PIO filtered out of this RA
+
 		struct nd_opt_prefix_info *p = NULL;
 		for (size_t i = 0; i < pfxs_cnt; ++i) {
 			if (addr->prefix == pfxs[i].nd_opt_pi_prefix_len &&
-- 
2.13.6 (Apple Git-96)




More information about the Lede-dev mailing list