[RFC 1/2] add multicast to unicast support

Michael Braun michael-dev at fami-braun.de
Mon Oct 31 06:58:08 PDT 2016


This adds support for nl80211 NL80211_CMD_SET_MULTICAST_TO_UNICAST
command.

By setting the new hostapd configuration option, hostapd configures
if this AP should perform multicast to unicast conversion.

When enabled, all multicast packets with ethertype ARP, IPv4 or IPv6
(possibly within an 802.1Q header) will be sent out to each station
once with the destination (multicast) MAC address replaced by the
station's MAC address.
Note that this may break certain expectations of the receiver, e.g.
the ability to drop unicast IP packets encapsulated in multicast L2
frames, or the ability to not send destination unreachable messages
in such cases.

This also does not implement Directed Multicast Service (DMS).

Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
 hostapd/config_file.c        |  2 ++
 hostapd/hostapd.conf         | 16 +++++++++++++++
 src/ap/ap_config.h           |  2 ++
 src/ap/beacon.c              |  1 +
 src/drivers/driver.h         | 21 ++++++++++++++++++++
 src/drivers/driver_nl80211.c | 47 ++++++++++++++++++++++++++++++++++++++++++++
 src/drivers/nl80211_copy.h   | 21 ++++++++++++++++++++
 7 files changed, 110 insertions(+)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 3dc0d06..b809670 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3558,6 +3558,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		}
 		bss->fils_cache_id_set = 1;
 #endif /* CONFIG_FILS */
+	} else if (os_strcmp(buf, "multicast_to_unicast") == 0) {
+		bss->multicast_to_unicast = atoi(pos);
 	} else {
 		wpa_printf(MSG_ERROR,
 			   "Line %d: unknown configuration item '%s'",
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index c216782..16fb9ec 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -482,6 +482,22 @@ wmm_ac_vo_acm=0
 # <station count>:<channel utilization>:<available admission capacity>
 #bss_load_test=12:80:20000
 
+# Multicast to unicast conversion
+# Request that the AP will do multicast-to-unicast conversion for ARP, IPv4 and
+# IPv6 frames (possibly within 802.1Q). If enabled, such frames are to be sent
+# to each station separately, with the DA replaced by their own MAC address
+# rather than the group address.
+#
+# Note that this may break certain expectations of the receiver, such as the
+# ability to drop unicast IP packets received within multicast L2 frames, or the
+# ability to not send ICMP destination unreachable messages for packets received
+# in L2 multicast (which is required, but the receiver can't tell the difference
+# if this new option is enabled.)
+#
+# This also doesn't implement the 802.11 DMS (directed multicast service).
+#
+#multicast_to_unicast=0
+
 ##### IEEE 802.11n related configuration ######################################
 
 # ieee80211n: Whether IEEE 802.11n (HT) is enabled
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 066c554..476e56c 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -619,6 +619,8 @@ struct hostapd_bss_config {
 	u8 fils_cache_id[FILS_CACHE_ID_LEN];
 	int fils_cache_id_set;
 #endif /* CONFIG_FILS */
+
+	int multicast_to_unicast:1;
 };
 
 
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 474ff59..a8b58c6 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -1284,6 +1284,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
 		params->osen = 1;
 	}
 #endif /* CONFIG_HS20 */
+	params->multicast_to_unicast = hapd->conf->multicast_to_unicast;
 	params->pbss = hapd->conf->pbss;
 	return 0;
 }
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 9035450..62d24c0 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1118,6 +1118,27 @@ struct wpa_driver_ap_params {
 	 * infrastructure BSS. Valid only for DMG network.
 	 */
 	int pbss;
+
+	/**
+	 * multicast_to_unicast - Whether to use multicast_to_unicast
+	 *
+	 * If this is non-zero, the AP is requested to perform multicast to
+	 * unicast conversion for ARP, IPv4 and IPv6 frames (possibly within
+	 * 802.1Q). If enabled, such frames are to be sent to each station
+	 * separately, with the DA replaced by their own MAC address rather
+	 * than the group address.
+	 *
+	 * Note that this may break certain expectations of the receiver, such
+	 * as the ability to drop unicast IP packets received within multicast
+	 * L2 frames, or the ability to not send ICMP destination unreachable
+	 * messages for packets received in L2 multicast (which is required,
+	 * but the receiver can't tell the difference if this new option is
+	 * enabled.)
+	 *
+	 * This also doesn't implement the 802.11 DMS (directed multicast
+	 * service).
+	 */
+	int multicast_to_unicast:1;
 };
 
 struct wpa_driver_mesh_bss_params {
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 8af840b..600d9c8 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3525,6 +3525,51 @@ static int nl80211_set_mesh_config(void *priv,
 #endif /* CONFIG_MESH */
 
 
+static int nl80211_set_multicast_to_unicast(struct i802_bss *bss,
+					    int multicast_to_unicast)
+{
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	int ret;
+
+	msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_MULTICAST_TO_UNICAST);
+	if (!msg)
+		goto err;
+	if (multicast_to_unicast &&
+	    nla_put_flag(msg, NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED))
+		goto err;
+
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+
+	switch (ret) {
+	case 0:
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: multicast to unicast %s on interface %s",
+			   multicast_to_unicast ? "enabled" : "disabled",
+			   bss->ifname);
+		break;
+	case -EOPNOTSUPP:
+		if (!multicast_to_unicast)
+			break;
+		wpa_printf(MSG_ERROR, "nl80211: multicast to unicast not "
+			   "supported on interface %s", bss->ifname);
+		break;
+	default:
+		wpa_printf(MSG_ERROR, "nl80211: %s multicast to unicast "
+			   "failed with %d (%s) on interface %s",
+			   multicast_to_unicast ? "enabling" : "disabling",
+			   ret, strerror(-ret), bss->ifname);
+	}
+
+	return ret;
+err:
+	wpa_printf(MSG_ERROR, "nl80211: Failed to build %s msg for %s",
+		   "NL80211_CMD_SET_MULTICAST_TO_UNICAST", bss->ifname);
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
 				     struct wpa_driver_ap_params *params)
 {
@@ -3741,6 +3786,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 		nl80211_set_bss(bss, params->cts_protect, params->preamble,
 				params->short_slot_time, params->ht_opmode,
 				params->isolate, params->basic_rates);
+		nl80211_set_multicast_to_unicast(bss,
+						 params->multicast_to_unicast);
 		if (beacon_set && params->freq &&
 		    params->freq->bandwidth != bss->bandwidth) {
 			wpa_printf(MSG_DEBUG,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 2206941..7dc5e2e 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -599,6 +599,20 @@
  *
  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
  *
+ * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform
+ *	multicast to unicast conversion. When enabled, all multicast packets
+ *	with ethertype ARP, IPv4 or IPv6 (possibly within an 802.1Q header)
+ *	will be sent out to each station once with the destination (multicast)
+ *	MAC address replaced by the station's MAC address. Note that this may
+ *	break certain expectations of the receiver, e.g. the ability to drop
+ *	unicast IP packets encapsulated in multicast L2 frames, or the ability
+ *	to not send destination unreachable messages in such cases.
+ *	This can only be toggled per BSS. Configure this on an interface of
+ *	type %NL80211_IFTYPE_AP. It applies to all its VLAN interfaces
+ *	(%NL80211_IFTYPE_AP_VLAN), except for those in 4addr (WDS) mode.
+ *	If %NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED is not present with this
+ *	command, the feature is disabled.
+ *
  * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
  *	mesh config parameters may be given.
  * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
@@ -1026,6 +1040,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_ABORT_SCAN,
 
+	NL80211_CMD_SET_MULTICAST_TO_UNICAST,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1867,6 +1883,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
  *	used to pull the stored data for mesh peer in power save state.
  *
+ * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Indicates whether or not multicast
+ *	packets should be send out as unicast to all stations (flag attribute).
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2261,6 +2280,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_MESH_PEER_AID,
 
+	NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
-- 
2.1.4




More information about the Hostap mailing list