All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] cfg80211/mac80211: Add support for Proxy ARP
@ 2014-05-15 19:06 Kyeyoon Park
  2014-05-15 19:32 ` Ben Greear
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Kyeyoon Park @ 2014-05-15 19:06 UTC (permalink / raw)
  To: johannes; +Cc: jouni, linux-wireless

Proxy ARP allows the AP devices to keep track of the hardware address
to IP address mapping of the STA devices within the BSS. When a request
for such information is made (i.e. ARP request, Neighbor Solicitation),
the AP will respond on behalf of the STA device within the BSS. Such
requests could originate from a device within the BSS or also from the
bridge. In the process of the AP replying to the request (i.e. ARP
reply, Neighbor Advertisement), the AP will drop the original request
frame. The relevant STA will not even know that such information was
ever requested.

This feature is a requirement for Hotspot 2.0. This feature is defined
in IEEE Std 802.11-2012, 10.23.13. This particular commit will
eventually be split into two separate commits (cfg80211 and mac80211
separately). This commit implements one part of the feature, dynamic
IPv4 addresses and ARP. Additional commits will be made to support
static IPv4 addresses and IPv6.

Signed-off-by: Kyeyoon Park <kyeyoonp@qca.qualcomm.com>
---
 include/net/cfg80211.h       |   2 +
 include/net/mac80211.h       |   2 +
 include/uapi/linux/nl80211.h |   8 ++
 net/mac80211/cfg.c           |   1 +
 net/mac80211/debug.h         |  10 ++
 net/mac80211/ieee80211_i.h   |   1 +
 net/mac80211/main.c          |   3 +-
 net/mac80211/sta_info.c      | 100 +++++++++++++++++++
 net/mac80211/sta_info.h      |  14 +++
 net/mac80211/tx.c            | 229 +++++++++++++++++++++++++++++++++++++++++++
 net/wireless/nl80211.c       |   6 ++
 11 files changed, 375 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f2c3186..07cba1d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -668,6 +668,7 @@ struct cfg80211_acl_data {
  * @p2p_opp_ps: P2P opportunistic PS
  * @acl: ACL configuration used by the drivers which has support for
  *	MAC address based access control
+ * @proxy_arp: the proxy ARP enable flag for the AP
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -685,6 +686,7 @@ struct cfg80211_ap_settings {
 	u8 p2p_ctwindow;
 	bool p2p_opp_ps;
 	const struct cfg80211_acl_data *acl;
+	bool proxy_arp;
 };
 
 /**
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 451c1bf..c329ee9 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -337,6 +337,7 @@ enum ieee80211_rssi_event {
  * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
  * @txpower: TX power in dBm
  * @p2p_noa_attr: P2P NoA attribute for P2P powersave
+ * @proxy_arp: This is a Proxy ARP enabled BSS.
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -372,6 +373,7 @@ struct ieee80211_bss_conf {
 	bool hidden_ssid;
 	int txpower;
 	struct ieee80211_p2p_noa_attr p2p_noa_attr;
+	bool proxy_arp;
 };
 
 /**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9922b9b..f2d212c 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -1583,6 +1583,9 @@ enum nl80211_commands {
  *	creation then the new interface will be owned by the netlink socket
  *	that created it and will be destroyed when the socket is closed
  *
+ * @NL80211_ATTR_PROXY_ARP: A flag indicating that the AP device has proxy ARP
+ *	enabled. This should not be enabled for a non-AP device.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1920,6 +1923,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_IFACE_SOCKET_OWNER,
 
+	NL80211_ATTR_PROXY_ARP,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3934,6 +3939,8 @@ enum nl80211_ap_sme_features {
  * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic
  *	channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the
  *	lifetime of a BSS.
+ * @NL80211_FEATURE_AP_PROXY_ARP: This driver supports proxy ARP. This feature
+ *	is for AP mode only.
  */
 enum nl80211_feature_flags {
 	NL80211_FEATURE_SK_TX_STATUS			= 1 << 0,
@@ -3955,6 +3962,7 @@ enum nl80211_feature_flags {
 	NL80211_FEATURE_USERSPACE_MPM			= 1 << 16,
 	NL80211_FEATURE_ACTIVE_MONITOR			= 1 << 17,
 	NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE	= 1 << 18,
+	NL80211_FEATURE_AP_PROXY_ARP			= 1 << 19,
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b8d3cf..d69906d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1013,6 +1013,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 	sdata->vif.bss_conf.dtim_period = params->dtim_period;
 	sdata->vif.bss_conf.enable_beacon = true;
+	sdata->vif.bss_conf.proxy_arp = params->proxy_arp;
 
 	sdata->vif.bss_conf.ssid_len = params->ssid_len;
 	if (params->ssid_len)
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index 493d680..2f985d9 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -74,6 +74,12 @@
 #define MAC80211_MLME_DEBUG 0
 #endif
 
+#ifdef CONFIG_MAC80211_PROXYARP_DEBUG
+#define MAC80211_PROXYARP_DEBUG 1
+#else
+#define MAC80211_PROXYARP_DEBUG 0
+#endif
+
 #ifdef CONFIG_MAC80211_MESSAGE_TRACING
 void __sdata_info(const char *fmt, ...) __printf(1, 2);
 void __sdata_dbg(bool print, const char *fmt, ...) __printf(2, 3);
@@ -187,4 +193,8 @@ do {									\
 	_sdata_dbg(MAC80211_MLME_DEBUG && net_ratelimit(),		\
 		   sdata, fmt, ##__VA_ARGS__)
 
+#define proxyarp_dbg(sdata, fmt, ...)					\
+	_sdata_dbg(MAC80211_PROXYARP_DEBUG && net_ratelimit(),		\
+		   sdata, fmt, ##__VA_ARGS__)
+
 #endif /* __MAC80211_DEBUG_H */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 487c2ef..9241b03 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1093,6 +1093,7 @@ struct ieee80211_local {
 	unsigned long num_sta;
 	struct list_head sta_list;
 	struct sta_info __rcu *sta_hash[STA_HASH_SIZE];
+	struct sta_info __rcu *sta_ipv4hash[STA_IPV4_HASH_SIZE];
 	struct timer_list sta_cleanup;
 	int sta_generation;
 
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 27b9364..bfd586b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -548,7 +548,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
 			   NL80211_FEATURE_SAE |
 			   NL80211_FEATURE_HT_IBSS |
 			   NL80211_FEATURE_VIF_TXPOWER |
-			   NL80211_FEATURE_USERSPACE_MPM;
+			   NL80211_FEATURE_USERSPACE_MPM |
+			   NL80211_FEATURE_AP_PROXY_ARP;
 
 	if (!ops->hw_scan)
 		wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 632d372..be9ba33 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -194,6 +194,29 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
 	return sta;
 }
 
+struct sta_info *sta_info_get_ipv4(struct ieee80211_sub_if_data *sdata,
+				   __be32 ipv4_addr)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct sta_info *sta;
+
+	mutex_lock(&local->sta_mtx);
+
+	sta = rcu_dereference_check(local->
+				    sta_ipv4hash[STA_IPV4_HASH(ipv4_addr)],
+				    lockdep_is_held(&local->sta_mtx));
+	while (sta) {
+		if (sta->sdata == sdata && sta->ipv4_addr == ipv4_addr)
+			break;
+		sta = rcu_dereference_check(sta->ipv4hnext,
+					    lockdep_is_held(&local->sta_mtx));
+	}
+
+	mutex_unlock(&local->sta_mtx);
+
+	return sta;
+}
+
 struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata,
 				     int idx)
 {
@@ -583,6 +606,81 @@ int sta_info_insert(struct sta_info *sta)
 	return err;
 }
 
+static int __sta_info_ipv4hash_del(struct ieee80211_local *local,
+				   struct sta_info *sta)
+{
+	struct sta_info *s;
+	int idx = STA_IPV4_HASH(sta->ipv4_addr);
+
+	if (!sta->ipv4_addr)
+		return -ENOENT;
+
+	s = rcu_dereference_protected(local->sta_ipv4hash[idx],
+		lockdep_is_held(&local->sta_mtx));
+	if (!s)
+		return -ENOENT;
+
+	if (s == sta) {
+		rcu_assign_pointer(local->sta_ipv4hash[idx],
+				   s->ipv4hnext);
+		sta->ipv4_addr = 0;
+		return 0;
+	}
+
+	while (rcu_access_pointer(s->ipv4hnext) &&
+	       rcu_access_pointer(s->ipv4hnext) != sta)
+		s = rcu_dereference_protected(s->ipv4hnext,
+					lockdep_is_held(&local->sta_mtx));
+
+	if (rcu_access_pointer(s->ipv4hnext)) {
+		rcu_assign_pointer(s->ipv4hnext, sta->ipv4hnext);
+		sta->ipv4_addr = 0;
+		return 0;
+	}
+
+	return -ENOENT;
+}
+
+void sta_info_ipv4hash_add_sta(struct sta_info *sta,
+			       __be32 ipv4_addr) __acquires(RCU)
+{
+	struct ieee80211_local *local = sta->local;
+	int idx = STA_IPV4_HASH(sta->ipv4_addr);
+
+	if (sta->ipv4_addr == ipv4_addr)
+		return;
+
+	might_sleep();
+
+	mutex_lock(&local->sta_mtx);
+
+	if (sta->ipv4_addr)
+		__sta_info_ipv4hash_del(local, sta);
+
+	lockdep_assert_held(&local->sta_mtx);
+	sta->ipv4hnext = local->sta_ipv4hash[idx];
+	sta->ipv4_addr = ipv4_addr;
+	rcu_assign_pointer(local->sta_ipv4hash[idx], sta);
+
+	mutex_unlock(&local->sta_mtx);
+}
+
+int sta_info_ipv4hash_remove_sta(struct sta_info *sta) __acquires(RCU)
+{
+	struct ieee80211_local *local = sta->local;
+	int err;
+
+	might_sleep();
+
+	mutex_lock(&local->sta_mtx);
+
+	err = __sta_info_ipv4hash_del(local, sta);
+
+	mutex_unlock(&local->sta_mtx);
+
+	return err;
+}
+
 static inline void __bss_tim_set(u8 *tim, u16 id)
 {
 	/*
@@ -849,6 +947,8 @@ static int __must_check __sta_info_destroy_part1(struct sta_info *sta)
 	set_sta_flag(sta, WLAN_STA_BLOCK_BA);
 	ieee80211_sta_tear_down_BA_sessions(sta, AGG_STOP_DESTROY_STA);
 
+	__sta_info_ipv4hash_del(local, sta);
+
 	ret = sta_info_hash_del(local, sta);
 	if (WARN_ON(ret))
 		return ret;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4acc5fc..a6699b4 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -335,6 +335,7 @@ struct sta_info {
 	struct list_head list, free_list;
 	struct rcu_head rcu_head;
 	struct sta_info __rcu *hnext;
+	struct sta_info __rcu *ipv4hnext;
 	struct ieee80211_local *local;
 	struct ieee80211_sub_if_data *sdata;
 	struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
@@ -445,6 +446,10 @@ struct sta_info {
 	enum ieee80211_smps_mode known_smps_mode;
 	const struct ieee80211_cipher_scheme *cipher_scheme;
 
+	/* Proxy ARP IP address */
+	__be32 ipv4_addr;
+	unsigned long ipv4_lease_timeout;
+
 	/* keep last! */
 	struct ieee80211_sta sta;
 };
@@ -528,6 +533,8 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
 #define STA_HASH_SIZE 256
 #define STA_HASH(sta) (sta[5])
 
+#define STA_IPV4_HASH_SIZE 32
+#define STA_IPV4_HASH(ipv4) (((u8 *)&ipv4)[3] & 0x1F)
 
 /* Maximum number of frames to buffer per power saving station per AC */
 #define STA_MAX_TX_BUFFER	64
@@ -549,6 +556,9 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
 struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
 				  const u8 *addr);
 
+struct sta_info *sta_info_get_ipv4(struct ieee80211_sub_if_data *sdata,
+				   __be32 ipv4_addr);
+
 static inline
 void for_each_sta_info_type_check(struct ieee80211_local *local,
 				  const u8 *addr,
@@ -596,6 +606,10 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
  */
 int sta_info_insert(struct sta_info *sta);
 int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
+void sta_info_ipv4hash_add_sta(struct sta_info *sta,
+			       __be32 ipv4_addr) __acquires(RCU);
+int sta_info_ipv4hash_remove_sta(struct sta_info *sta) __acquires(RCU);
+
 
 int __must_check __sta_info_destroy(struct sta_info *sta);
 int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 19d36d4..9a20547 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -24,6 +24,8 @@
 #include <net/ieee80211_radiotap.h>
 #include <net/cfg80211.h>
 #include <net/mac80211.h>
+#include <net/arp.h>
+#include <net/ip.h>
 #include <asm/unaligned.h>
 
 #include "ieee80211_i.h"
@@ -194,6 +196,219 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
 }
 
 /* tx handlers */
+
+struct bootp_pkt {		/* BOOTP packet format */
+	struct iphdr iph;	/* IP header */
+	struct udphdr udph;	/* UDP header */
+	u8 op;			/* 1=request, 2=reply */
+	u8 htype;		/* HW address type */
+	u8 hlen;		/* HW address length */
+	u8 hops;		/* Used only by gateways */
+	__be32 xid;		/* Transaction ID */
+	__be16 secs;		/* Seconds since we started */
+	__be16 flags;		/* Just what it says */
+	__be32 client_ip;	/* Client's IP address if known */
+	__be32 your_ip;		/* Assigned IP address */
+	__be32 server_ip;	/* (Next, e.g. NFS) Server's IP address */
+	__be32 relay_ip;	/* IP address of BOOTP relay */
+	u8 hw_addr[16];		/* Client's HW address */
+	u8 serv_name[64];	/* Server host name */
+	u8 boot_file[128];	/* Name of boot file */
+	u8 exten[312];		/* DHCP options / BOOTP vendor extensions */
+};
+
+#define DHCPACK	5
+static const u8 ic_bootp_cookie[4] = { 99, 130, 83, 99 };
+
+static inline int ieee80211_proxyarp_arp(struct ieee80211_sub_if_data *sdata,
+					 struct sk_buff *skb)
+{
+	struct net_device *dev = sdata->dev;
+	struct ethhdr *eh = (struct ethhdr *)skb->data;
+	struct arphdr *arp = (struct arphdr *)(eh + 1);
+	int linear_len;
+	u8 *sha, *tha, *pos;
+	__be32 sip, tip;
+
+	linear_len = sizeof(struct ethhdr) + sizeof(struct arphdr);
+	if (!pskb_may_pull(skb, linear_len))
+		return 1;
+
+	pos = (unsigned char *)(arp + 1);
+	sha = pos;
+	pos += ETH_ALEN;
+	memcpy(&sip, pos, sizeof(__be32));
+	pos += sizeof(__be32);
+	tha = pos;
+	pos += ETH_ALEN;
+	memcpy(&tip, pos , sizeof(__be32));
+
+	if (arp->ar_op == htons(ARPOP_REQUEST)) {
+		struct sta_info *ssta, *tsta;
+
+		/* Proxy ARP request for the STAs within the BSS */
+		tsta = sta_info_get_ipv4(sdata, tip);
+		if (tsta && !tsta->ipv4_lease_timeout &&
+		    time_after(jiffies, tsta->ipv4_lease_timeout)) {
+			proxyarp_dbg(sdata,
+				     "Remove ARP entry: mac %pM-> ip %pI4 due to timeout. expired %lu, current %lu\n",
+				     tsta->sta.addr, &tip,
+				     tsta->ipv4_lease_timeout,
+				     jiffies);
+
+			sta_info_ipv4hash_remove_sta(tsta);
+
+		} else if (tsta && !ether_addr_equal(tsta->sta.addr, sha)) {
+			bool frombridge;
+
+			/* Drop G.ARP from both BSS and bridge */
+			if (tip == sip)
+				return 1;
+
+			/* Regular ARP Request, form ARP Reply */
+			ssta = sta_info_get(sdata, sha);
+			frombridge = ssta ? false : true;
+			tha = sha;
+			if (frombridge) {
+				struct sk_buff *skb;
+
+				skb = arp_create(ARPOP_REPLY, ETH_P_ARP, sip,
+						 dev, tip, sha, tsta->sta.addr,
+						 tha);
+				if (skb)
+					netif_rx(skb);
+			} else {
+				arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip,
+					 sha, tsta->sta.addr, tha);
+			}
+			return 1;
+		}
+
+		/**
+		 * The ARP Request Target IP Address is not in our hash.
+		 *
+		 * Try to learn from the G.ARP requests
+		 */
+		if (tip == sip || sip == 0) {
+			/**
+			 * Learn ARP mapping from G.ARP request. Allow
+			 * the IPv4 address update from a later G.ARP
+			 * to overwrite a previous one.
+			 */
+			ssta = sta_info_get(sdata, sha);
+			if (ssta) {
+				sta_info_ipv4hash_add_sta(ssta, tip);
+				/**
+				 * If we receive a G.ARP for a previously
+				 * expired DHCP lease, change the lease type
+				 * to unlimited.
+				 */
+				if (ssta->ipv4_lease_timeout &&
+				    time_after(jiffies,
+					       ssta->ipv4_lease_timeout))
+					ssta->ipv4_lease_timeout = 0;
+			}
+		}
+
+		/* Suppress ARP Request within the BSS */
+		return 1;
+
+	} else if (arp->ar_op == htons(ARPOP_REPLY)) {
+		if (is_multicast_ether_addr(eh->h_dest))
+			return 1;
+	}
+
+	return 0;
+}
+
+static inline int ieee80211_proxyarp_ipv4(struct ieee80211_sub_if_data *sdata,
+					  struct sk_buff *skb)
+{
+	struct ethhdr *eh = (struct ethhdr *)skb->data;
+	struct bootp_pkt *b = (struct bootp_pkt *)(eh + 1);
+	struct sta_info *sta;
+	int len, linear_len, exten_len;
+
+	linear_len = sizeof(struct ethhdr) + sizeof(struct iphdr) +
+		     sizeof(struct udphdr) + 1;
+	if (!pskb_may_pull(skb, linear_len))
+		return 0;
+
+	/* Only downstream DHCP packets are relevant */
+	if (b->iph.protocol != IPPROTO_UDP ||
+	    b->udph.source != htons(67) ||
+	    b->udph.dest != htons(68) ||
+	    b->op != 2)
+		return 0;
+
+	if (skb->len < ntohs(b->iph.tot_len))
+		return 0;
+
+	if (ntohs(b->iph.tot_len) < ntohs(b->udph.len) + sizeof(struct iphdr))
+		return 0;
+
+	len = ntohs(b->udph.len) - sizeof(struct udphdr);
+	exten_len = len - (sizeof(*b) - sizeof(struct iphdr) -
+			 sizeof(struct udphdr) - sizeof(b->exten));
+	if (exten_len < 0)
+		return 0;
+
+	if (skb_linearize(skb))
+		return 0;
+
+	/* Parse DHCP options */
+	b = (struct bootp_pkt *)skb_network_header(skb);
+	if (exten_len >= 4 && !memcmp(b->exten, ic_bootp_cookie, 4)) {
+		u8 *end = (u8 *)b + ntohs(b->iph.tot_len);
+		u8 *pos = &b->exten[4];
+		int mt = 0;
+		u32 lease_time = 0;
+
+		while (pos < end && *pos != 0xff) {
+			u8 *opt = pos++;
+
+			if (*opt == 0) /* padding */
+				continue;
+
+			pos += *pos + 1;
+			if (pos >= end)
+				break;
+
+			switch (*opt) {
+			case 53: /* message type */
+				if (opt[1])
+					mt = opt[2];
+				break;
+
+			case 51: /* lease time */
+				if (opt[1] == 4)
+					lease_time =
+						get_unaligned_be32(&opt[2]);
+				break;
+			}
+		}
+
+		if (mt == DHCPACK) {
+			sta = sta_info_get(sdata, b->hw_addr);
+
+			/* DHCPACK for DHCPINFORM */
+			if (b->your_ip == 0)
+				return 0;
+
+			/* DHCPACK for DHCPREQUEST */
+			sta_info_ipv4hash_add_sta(sta, b->your_ip);
+
+			if (lease_time) {
+				sta->ipv4_lease_timeout =
+					msecs_to_jiffies(lease_time * 1000) +
+					jiffies;
+			} else
+				sta->ipv4_lease_timeout = 0;
+		}
+	}
+	return 0;
+}
+
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
 {
@@ -1859,6 +2074,20 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 			chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 		if (!chanctx_conf)
 			goto fail_rcu;
+
+		if (unlikely(sdata->vif.bss_conf.proxy_arp)) {
+			switch (ethertype) {
+			case ETH_P_ARP:
+				if (ieee80211_proxyarp_arp(sdata, skb))
+					goto fail;
+				break;
+			case ETH_P_IP:
+				if (ieee80211_proxyarp_ipv4(sdata, skb))
+					goto fail;
+				break;
+			}
+		}
+
 		fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
 		/* DA BSSID SA */
 		memcpy(hdr.addr1, skb->data, ETH_ALEN);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0f1b18f2..9624f3a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -382,6 +382,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 	[NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY },
 	[NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY,
 				   .len = IEEE80211_QOS_MAP_LEN_MAX },
+	[NL80211_ATTR_PROXY_ARP] = { .type = NLA_U8 },
 	[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
 	[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
 	[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
@@ -3309,6 +3310,11 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			return PTR_ERR(params.acl);
 	}
 
+	if (info->attrs[NL80211_ATTR_PROXY_ARP]) {
+		params.proxy_arp =
+			nla_get_u8(info->attrs[NL80211_ATTR_PROXY_ARP]);
+	}
+
 	wdev_lock(wdev);
 	err = rdev_start_ap(rdev, dev, &params);
 	if (!err) {
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-15 19:06 [RFC] cfg80211/mac80211: Add support for Proxy ARP Kyeyoon Park
@ 2014-05-15 19:32 ` Ben Greear
  2014-05-16 23:04   ` Park, Kyeyoon
  2014-05-16  9:16 ` Johannes Berg
  2018-02-16 12:53 ` Ujjal Roy
  2 siblings, 1 reply; 11+ messages in thread
From: Ben Greear @ 2014-05-15 19:32 UTC (permalink / raw)
  To: Kyeyoon Park; +Cc: johannes, jouni, linux-wireless

On 05/15/2014 12:06 PM, Kyeyoon Park wrote:
> Proxy ARP allows the AP devices to keep track of the hardware address
> to IP address mapping of the STA devices within the BSS. When a request
> for such information is made (i.e. ARP request, Neighbor Solicitation),
> the AP will respond on behalf of the STA device within the BSS. Such
> requests could originate from a device within the BSS or also from the
> bridge. In the process of the AP replying to the request (i.e. ARP
> reply, Neighbor Advertisement), the AP will drop the original request
> frame. The relevant STA will not even know that such information was
> ever requested.
> 
> This feature is a requirement for Hotspot 2.0. This feature is defined
> in IEEE Std 802.11-2012, 10.23.13. This particular commit will
> eventually be split into two separate commits (cfg80211 and mac80211
> separately). This commit implements one part of the feature, dynamic
> IPv4 addresses and ARP. Additional commits will be made to support
> static IPv4 addresses and IPv6.
> 
> Signed-off-by: Kyeyoon Park <kyeyoonp@qca.qualcomm.com>

> +#define STA_IPV4_HASH_SIZE 32
> +#define STA_IPV4_HASH(ipv4) (((u8 *)&ipv4)[3] & 0x1F)

This should be a better hash I think.  Use an existing hash
method or at least mix in the higher bits manually?

Thanks,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-15 19:06 [RFC] cfg80211/mac80211: Add support for Proxy ARP Kyeyoon Park
  2014-05-15 19:32 ` Ben Greear
@ 2014-05-16  9:16 ` Johannes Berg
  2014-05-16 22:49   ` Park, Kyeyoon
  2018-02-16 12:53 ` Ujjal Roy
  2 siblings, 1 reply; 11+ messages in thread
From: Johannes Berg @ 2014-05-16  9:16 UTC (permalink / raw)
  To: Kyeyoon Park; +Cc: jouni, linux-wireless

Hi,

Thanks for the code. It's always good to have a proof-of-concept to
discuss the system. Before I go into the general discussion, let me ask
a few specific questions.

> +void sta_info_ipv4hash_add_sta(struct sta_info *sta,
> +			       __be32 ipv4_addr) __acquires(RCU)

> +int sta_info_ipv4hash_remove_sta(struct sta_info *sta) __acquires(RCU)

Those sparse locking annotations clearly seem wrong - does that point to
the annotations being superfluous or the implementation doing something
else than you wanted?

> +static inline int ieee80211_proxyarp_arp(struct ieee80211_sub_if_data *sdata,
> +					 struct sk_buff *skb)
> +{
...
> +	if (arp->ar_op == htons(ARPOP_REQUEST)) {
> +		struct sta_info *ssta, *tsta;
> +
> +		/* Proxy ARP request for the STAs within the BSS */
> +		tsta = sta_info_get_ipv4(sdata, tip);
> +		if (tsta && !tsta->ipv4_lease_timeout &&
> +		    time_after(jiffies, tsta->ipv4_lease_timeout)) {
...
> +		} else if (tsta && !ether_addr_equal(tsta->sta.addr, sha)) {
...
> +			return 1;
> +		}
...
> +		/* Suppress ARP Request within the BSS */
> +		return 1;
> +

All code paths within the REQUEST return 1 - is that intentional? It
seems to me that there might be a requirement to actually pass the frame
if you don't know a response? OTOH, maybe you don't actually need this
since you don't necessarily want the stations communicating anyway (at
least in a HS2 scenario)

I think this code path:

> +       } else if (arp->ar_op == htons(ARPOP_REPLY)) {
> +               if (is_multicast_ether_addr(eh->h_dest))
> +                       return 1;

is also implementing something else - not this particular feature, no?


Overall though, I can't say I like this. I can understand how it's very
tempting to just stick all the code into the wireless stack and be done
with it, but it's quite a bit of code that needs to parse all the frames
etc. and I'm sure it will only get more complicated with the addition of
IPv6. It's also not clear to me that parsing DHCP is actually the best
course of action - if, for example, the DHCP server is colocated with
the AP then it should be simple to actually listen to events coming from
the DHCP server instead of piggy-backing on the actual frames.
Additionally, even listening to those frames in userspace shouldn't be
more complicated than a simple packet socket (with appropriate BPF.)
Similar for ARP (which you seem to be using for some hash table updates)
of course.

If we assume then that this is done, the second part we have is actually
replying to these frames. This is obviously complicated by the fact that

 a) we need to look at frames that are re-transmitted within the AP
context (e.g.
    broadcast from a STA to the DS, and potentially STA-to-STA frames)
 b) we need to drop ARP requests (all in your patch, but maybe only
handled
    ones?) - this also applies to the ones in (a)

Actually (a) might also affect the first part where we build the
database? The whole "use ARP frames to build database" part isn't very
clear to me.

Since we're moving to have more things like this, and more high-level
protocol integration, I think we should instead extend ip/eb/nftables.
It seems that much of this can be implemented in userspace already, with
the exception of the two complications above (at least (b) - (a) might
not be an issue depending on what we need.)

johannes


^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-16  9:16 ` Johannes Berg
@ 2014-05-16 22:49   ` Park, Kyeyoon
  2014-06-04 11:47     ` Johannes Berg
  0 siblings, 1 reply; 11+ messages in thread
From: Park, Kyeyoon @ 2014-05-16 22:49 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Malinen, Jouni, linux-wireless

SGkgSm9oYW5uZXMsDQoNCj4gPiArdm9pZCBzdGFfaW5mb19pcHY0aGFzaF9hZGRfc3RhKHN0cnVj
dCBzdGFfaW5mbyAqc3RhLA0KPiA+ICsJCQkgICAgICAgX19iZTMyIGlwdjRfYWRkcikgX19hY3F1
aXJlcyhSQ1UpDQo+IA0KPiA+ICtpbnQgc3RhX2luZm9faXB2NGhhc2hfcmVtb3ZlX3N0YShzdHJ1
Y3Qgc3RhX2luZm8gKnN0YSkNCj4gPiArX19hY3F1aXJlcyhSQ1UpDQo+IA0KPiBUaG9zZSBzcGFy
c2UgbG9ja2luZyBhbm5vdGF0aW9ucyBjbGVhcmx5IHNlZW0gd3JvbmcgLSBkb2VzIHRoYXQgcG9p
bnQgdG8NCj4gdGhlIGFubm90YXRpb25zIGJlaW5nIHN1cGVyZmx1b3VzIG9yIHRoZSBpbXBsZW1l
bnRhdGlvbiBkb2luZw0KPiBzb21ldGhpbmcgZWxzZSB0aGFuIHlvdSB3YW50ZWQ/DQoNClRoZXkg
YXJlIHdyb25nLi4uIHRoZXNlIGFyZSBsZWZ0b3ZlcnMgZnJvbSBhbiBhZHZhbmNlZCBjb2Rpbmcg
dGVjaG5pcXVlLA0KY29weS1hbmQtcGFzdGUuIDspIENsZWFybHksIHRoZSBsb2NrIGlzIHJlbGVh
c2VkIGJlZm9yZSB0aGUgZXhpdCwgaGVuY2UNCnRob3NlIGFubm90YXRpb25zIHNob3VsZCBub3Qg
YmUgdGhlcmUuDQoNCg0KPiA+ICtzdGF0aWMgaW5saW5lIGludCBpZWVlODAyMTFfcHJveHlhcnBf
YXJwKHN0cnVjdA0KPiBpZWVlODAyMTFfc3ViX2lmX2RhdGEgKnNkYXRhLA0KPiA+ICsJCQkJCSBz
dHJ1Y3Qgc2tfYnVmZiAqc2tiKQ0KPiA+ICt7DQo+IC4uLg0KPiA+ICsJaWYgKGFycC0+YXJfb3Ag
PT0gaHRvbnMoQVJQT1BfUkVRVUVTVCkpIHsNCj4gPiArCQlzdHJ1Y3Qgc3RhX2luZm8gKnNzdGEs
ICp0c3RhOw0KPiA+ICsNCj4gPiArCQkvKiBQcm94eSBBUlAgcmVxdWVzdCBmb3IgdGhlIFNUQXMg
d2l0aGluIHRoZSBCU1MgKi8NCj4gPiArCQl0c3RhID0gc3RhX2luZm9fZ2V0X2lwdjQoc2RhdGEs
IHRpcCk7DQo+ID4gKwkJaWYgKHRzdGEgJiYgIXRzdGEtPmlwdjRfbGVhc2VfdGltZW91dCAmJg0K
PiA+ICsJCSAgICB0aW1lX2FmdGVyKGppZmZpZXMsIHRzdGEtPmlwdjRfbGVhc2VfdGltZW91dCkp
IHsNCj4gLi4uDQo+ID4gKwkJfSBlbHNlIGlmICh0c3RhICYmICFldGhlcl9hZGRyX2VxdWFsKHRz
dGEtPnN0YS5hZGRyLCBzaGEpKQ0KPiB7DQo+IC4uLg0KPiA+ICsJCQlyZXR1cm4gMTsNCj4gPiAr
CQl9DQo+IC4uLg0KPiA+ICsJCS8qIFN1cHByZXNzIEFSUCBSZXF1ZXN0IHdpdGhpbiB0aGUgQlNT
ICovDQo+ID4gKwkJcmV0dXJuIDE7DQo+ID4gKw0KPiANCj4gQWxsIGNvZGUgcGF0aHMgd2l0aGlu
IHRoZSBSRVFVRVNUIHJldHVybiAxIC0gaXMgdGhhdCBpbnRlbnRpb25hbD8gSXQgc2VlbXMNCj4g
dG8gbWUgdGhhdCB0aGVyZSBtaWdodCBiZSBhIHJlcXVpcmVtZW50IHRvIGFjdHVhbGx5IHBhc3Mg
dGhlIGZyYW1lIGlmIHlvdQ0KPiBkb24ndCBrbm93IGEgcmVzcG9uc2U/IE9UT0gsIG1heWJlIHlv
dSBkb24ndCBhY3R1YWxseSBuZWVkIHRoaXMgc2luY2UNCj4geW91IGRvbid0IG5lY2Vzc2FyaWx5
IHdhbnQgdGhlIHN0YXRpb25zIGNvbW11bmljYXRpbmcgYW55d2F5IChhdCBsZWFzdA0KPiBpbiBh
IEhTMiBzY2VuYXJpbykNCg0KSXQgaXMgaW50ZW50aW9uYWwgZm9yIHRoaXMgcGFydGljdWxhciBj
YXNlLiBUaGVyZSB3b3VsZCBiZSBhIGNhc2UgZm9yDQpzdGF0aWMgSVAsIElQdjQgREFEIChSRkMg
NTIyNyksIHdoZXJlIGEgZGVmZW5zZSBBUlAgQW5ub3VuY2VtZW50IHBhY2tldA0KZnJvbSB0aGUg
YnJpZGdlIHdvdWxkIG5vdCBvbmx5IGludmFsaWRhdGUgdGhlIHRhYmxlIHdlIGJ1aWx0IGluIHRo
ZSBBUCwNCmJ1dCBhbHNvIHdvdWxkIGluZm9ybSB0aGUgU1RBIHRoYXQgdGhlcmUgaXMgYW4gZW50
aXR5IG91dCB0aGVyZSB3aXRoDQp0aGUgc2FtZSBJUCBhZGRyZXNzLiBJbiB0aGlzIGNhc2UsIHRo
ZSAiQVJQIFJFUVVFU1QiIGZyYW1lIHdvdWxkIGJlDQphbGxvd2VkIHRocm91Z2guIE5vdGU6IE5P
VCBpbXBsZW1lbnRlZCB5ZXQuIFRoaXMgd291bGQgYmUgcGFydCAyLg0KDQpUaGUgU1RBcyBub3Qg
YmVpbmcgYWJsZSB0byBjb21tdW5pY2F0ZSB3aXRoIGVhY2ggb3RoZXIsIGF0IGxlYXN0IG5vdA0K
ZGlyZWN0bHkgd2l0aG91dCB0aGUgY29uc2VudCBvZiBhbiBvdmVyc2VlaW5nIGVudGl0eSBjb25u
ZWN0ZWQgdG8gdGhlDQpicmlkZ2UsIGlzIGZvciB0aGUgb3RoZXIgZmVhdHVyZSBpbiBIUzIsIEwy
VElGIChMMiBUcmFmZmljIEluc3BlY3Rpb24NCmFuZCBGaWx0ZXJpbmcpLiBDb21pbmcgdG8gYW4g
ZS1tYWlsIGluYm94IG5lYXIgeW91LCBob3BlZnVsbHkgaW4gdGhlDQpuZWFyIGZ1dHVyZS4NCg0K
DQo+ID4gKyAgICAgICB9IGVsc2UgaWYgKGFycC0+YXJfb3AgPT0gaHRvbnMoQVJQT1BfUkVQTFkp
KSB7DQo+ID4gKyAgICAgICAgICAgICAgIGlmIChpc19tdWx0aWNhc3RfZXRoZXJfYWRkcihlaC0+
aF9kZXN0KSkNCj4gPiArICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTsNCj4gDQo+IGlz
IGFsc28gaW1wbGVtZW50aW5nIHNvbWV0aGluZyBlbHNlIC0gbm90IHRoaXMgcGFydGljdWxhciBm
ZWF0dXJlLCBubz8NCg0KUmlnaHQuIFRoaXMgaXMgc3VwcHJlc3NpbmcgdGhlIEcuQVJQIFJlcGx5
IHdpdGhpbiB0aGUgQlNTLg0KDQoNCj4gT3ZlcmFsbCB0aG91Z2gsIEkgY2FuJ3Qgc2F5IEkgbGlr
ZSB0aGlzLiBJIGNhbiB1bmRlcnN0YW5kIGhvdyBpdCdzIHZlcnkNCj4gdGVtcHRpbmcgdG8ganVz
dCBzdGljayBhbGwgdGhlIGNvZGUgaW50byB0aGUgd2lyZWxlc3Mgc3RhY2sgYW5kIGJlIGRvbmUN
Cj4gd2l0aCBpdCwgYnV0IGl0J3MgcXVpdGUgYSBiaXQgb2YgY29kZSB0aGF0IG5lZWRzIHRvIHBh
cnNlIGFsbCB0aGUgZnJhbWVzIGV0Yy4NCj4gYW5kIEknbSBzdXJlIGl0IHdpbGwgb25seSBnZXQg
bW9yZSBjb21wbGljYXRlZCB3aXRoIHRoZSBhZGRpdGlvbiBvZiBJUHY2Lg0KPiBJdCdzIGFsc28g
bm90IGNsZWFyIHRvIG1lIHRoYXQgcGFyc2luZyBESENQIGlzIGFjdHVhbGx5IHRoZSBiZXN0IGNv
dXJzZSBvZg0KPiBhY3Rpb24gLSBpZiwgZm9yIGV4YW1wbGUsIHRoZSBESENQIHNlcnZlciBpcyBj
b2xvY2F0ZWQgd2l0aCB0aGUgQVAgdGhlbiBpdA0KPiBzaG91bGQgYmUgc2ltcGxlIHRvIGFjdHVh
bGx5IGxpc3RlbiB0byBldmVudHMgY29taW5nIGZyb20gdGhlIERIQ1ANCj4gc2VydmVyIGluc3Rl
YWQgb2YgcGlnZ3ktYmFja2luZyBvbiB0aGUgYWN0dWFsIGZyYW1lcy4NCj4gQWRkaXRpb25hbGx5
LCBldmVuIGxpc3RlbmluZyB0byB0aG9zZSBmcmFtZXMgaW4gdXNlcnNwYWNlIHNob3VsZG4ndCBi
ZQ0KPiBtb3JlIGNvbXBsaWNhdGVkIHRoYW4gYSBzaW1wbGUgcGFja2V0IHNvY2tldCAod2l0aCBh
cHByb3ByaWF0ZSBCUEYuKQ0KPiBTaW1pbGFyIGZvciBBUlAgKHdoaWNoIHlvdSBzZWVtIHRvIGJl
IHVzaW5nIGZvciBzb21lIGhhc2ggdGFibGUgdXBkYXRlcykNCj4gb2YgY291cnNlLg0KPiANCj4g
SWYgd2UgYXNzdW1lIHRoZW4gdGhhdCB0aGlzIGlzIGRvbmUsIHRoZSBzZWNvbmQgcGFydCB3ZSBo
YXZlIGlzIGFjdHVhbGx5DQo+IHJlcGx5aW5nIHRvIHRoZXNlIGZyYW1lcy4gVGhpcyBpcyBvYnZp
b3VzbHkgY29tcGxpY2F0ZWQgYnkgdGhlIGZhY3QgdGhhdA0KPiANCj4gIGEpIHdlIG5lZWQgdG8g
bG9vayBhdCBmcmFtZXMgdGhhdCBhcmUgcmUtdHJhbnNtaXR0ZWQgd2l0aGluIHRoZSBBUA0KPiBj
b250ZXh0IChlLmcuDQo+ICAgICBicm9hZGNhc3QgZnJvbSBhIFNUQSB0byB0aGUgRFMsIGFuZCBw
b3RlbnRpYWxseSBTVEEtdG8tU1RBIGZyYW1lcykNCj4gIGIpIHdlIG5lZWQgdG8gZHJvcCBBUlAg
cmVxdWVzdHMgKGFsbCBpbiB5b3VyIHBhdGNoLCBidXQgbWF5YmUgb25seQ0KPiBoYW5kbGVkDQo+
ICAgICBvbmVzPykgLSB0aGlzIGFsc28gYXBwbGllcyB0byB0aGUgb25lcyBpbiAoYSkNCj4gDQo+
IEFjdHVhbGx5IChhKSBtaWdodCBhbHNvIGFmZmVjdCB0aGUgZmlyc3QgcGFydCB3aGVyZSB3ZSBi
dWlsZCB0aGUgZGF0YWJhc2U/DQo+IFRoZSB3aG9sZSAidXNlIEFSUCBmcmFtZXMgdG8gYnVpbGQg
ZGF0YWJhc2UiIHBhcnQgaXNuJ3QgdmVyeSBjbGVhciB0byBtZS4NCj4gDQo+IFNpbmNlIHdlJ3Jl
IG1vdmluZyB0byBoYXZlIG1vcmUgdGhpbmdzIGxpa2UgdGhpcywgYW5kIG1vcmUgaGlnaC1sZXZl
bA0KPiBwcm90b2NvbCBpbnRlZ3JhdGlvbiwgSSB0aGluayB3ZSBzaG91bGQgaW5zdGVhZCBleHRl
bmQgaXAvZWIvbmZ0YWJsZXMuDQo+IEl0IHNlZW1zIHRoYXQgbXVjaCBvZiB0aGlzIGNhbiBiZSBp
bXBsZW1lbnRlZCBpbiB1c2Vyc3BhY2UgYWxyZWFkeSwNCj4gd2l0aCB0aGUgZXhjZXB0aW9uIG9m
IHRoZSB0d28gY29tcGxpY2F0aW9ucyBhYm92ZSAoYXQgbGVhc3QgKGIpIC0gKGEpDQo+IG1pZ2h0
IG5vdCBiZSBhbiBpc3N1ZSBkZXBlbmRpbmcgb24gd2hhdCB3ZSBuZWVkLikNCg0KVGhpcyBpcyBl
eGFjdGx5IHRoZSBkaWxlbW1hIHRoYXQgSSByYW4gaW50byB3aGlsZSB0cnlpbmcgdG8gZG8gdGhp
cw0KZWxzZXdoZXJlLiBJZiB3ZSBhcmUgdGFsa2luZyBhYm91dCBldmVyeSBJUCBlbnRpdHkgdGhh
dCBwYXNzZXMNCnRocm91Z2ggKGluL291dCBvZikgdGhpcyBBUCdzIGJyaWRnZSBhbmQgbWFpbnRh
aW5pbmcgYSBkYXRhYmFzZSBmb3IgYWxsDQpvZiB0aGVtLCBpdCBjb3VsZCBiZSBpbXBsZW1lbnRl
ZCBtb3JlIGVhc2lseSAodGhvdWdoLCBub3Qgc3VyZSB3aGF0IHRoZQ0KcGVyZm9ybWFuY2Ugd291
bGQgbG9vayBsaWtlKS4gSG93ZXZlciwgdGhlIHdob2xlICJBUCBjb250ZXh0Ig0KY29tcGxpY2F0
ZXMgdGhpbmdzIHF1aXRlIGEgYml0LiBBcyB5b3UgY2FuIHByb2JhYmx5IHNlZSBmcm9tIHRoZSBj
b2RlLA0KY3VycmVudGx5LCB0aGUgZnJhbWUgaGFuZGxpbmcgaXMgZG9uZSB0aHJvdWdoIHRoZSBU
eCBwYXRoIG9mIHRoZSBBUCwNCm1lYW5pbmcgdGhlIGJyaWRnZSBoYXMgYWxyZWFkeSBkb25lIGl0
cyBqb2I7IGVpdGhlciBhIFNUQS10by1TVEENCnRyYWZmaWMgY29taW5nIGJhY2sgdG8gdGhlIHNh
bWUgInBvcnQiIG9yIGEgU1RBJ3MgYnJvYWRjYXN0IGZyYW1lIGdvaW5nDQpiYWNrIG91dCB0byB0
aGUgQVAgInBvcnQiIGFzIHdlbGwgYXMgdG8gYWxsIG9mIHRoZSBpbnRlcmZhY2VzIHRoYXQgYXJl
DQphdHRhY2hlZCB0byB0aGUgYnJpZGdlLiBUaGlzIGFsbG93cyB0aGUgaW1wbGVtZW50ZWQgY29k
ZSB0byBiZSBpc29sYXRlZA0KZnJvbSB0aGUgcmVzdCBvZiB0aGUgZWNvc3lzdGVtLiBGb3IgYSBz
aW1wbGljaXR5IHNha2UsIHRoaXMgaXMgZ29vZC4gQXMNCmZvciB0aGUgZWxlZ2FuY2Ugb2YgdGhl
IGRlc2lnbiwgcGVyaGFwcyBub3QuDQoNCkhvbmVzdGx5LCBJIGhhdmUgbm8gcHJvYmxlbSBkb2lu
ZyB0aGlzIGVsc2V3aGVyZSBhcyBsb25nIGFzOg0KMSkgV2UgY2FuIGFkZCBhbiBBUCBjb250ZXh0
IHRvIGlwL2ViL25mdGFibGVzIGluIGEgY2xlYW4gd2F5LiBNYXliZSBnZXQNCnRoZSBob3N0YXBk
IGludm9sdmVkIHNvbWVob3c/IEdldCBpdCB0byBpbmZvcm0gdGhlIE1BQyBhZGRyZXNzZXMgb2YN
CnRoZSBTVEFzIHRvIGlwL2ViL25mdGFibGVzPyBBIHNwZWNpZmljIGRldGFpbCB3b3VsZCBiZSBo
ZWxwZnVsIGZvcg0KbWUgaW4gZG9pbmcgdGhlIGltcGxlbWVudGF0aW9uLiBHcmVhdGx5IGFwcHJl
Y2lhdGVkIGluIGFkdmFuY2UuDQoNCjIpIFRoZSBwZXJmb3JtYW5jZSBoaXQgZnJvbSBzdWNoIG1l
dGhvZCB3b3VsZCBiZSBjb21wYXJhYmxlIHRvIHRoYXQNCm9mIHRoZSBwcm9wb3NlZCBtZXRob2Qu
IEkgZmVlbCB0aGF0IHRoZSBjdXJyZW50IGltcGxlbWVudGF0aW9uJ3MNCnBlcmZvcm1hbmNlIGhp
dCBzaG91bGQgYmUgbWluaW1hbCB0byB0aGUgd2lyZWxlc3Mgc3RhY2suDQoNClRoYW5rcyENCg0K
S3lleW9vbg0KDQo=

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-15 19:32 ` Ben Greear
@ 2014-05-16 23:04   ` Park, Kyeyoon
  2014-05-19 15:58     ` Ben Greear
  0 siblings, 1 reply; 11+ messages in thread
From: Park, Kyeyoon @ 2014-05-16 23:04 UTC (permalink / raw)
  To: Ben Greear; +Cc: johannes, Malinen, Jouni, linux-wireless

Hi Ben,

> > +#define STA_IPV4_HASH_SIZE 32
> > +#define STA_IPV4_HASH(ipv4) (((u8 *)&ipv4)[3] & 0x1F)
> 
> This should be a better hash I think.  Use an existing hash
> method or at least mix in the higher bits manually?

I assume that there is an existing IP address hash function
somewhere in the TCP/IP stack. I have a hard time finding
an externally available API that does this for me. Could you
point me to it?

Thanks!

Kyeyoon

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-16 23:04   ` Park, Kyeyoon
@ 2014-05-19 15:58     ` Ben Greear
  0 siblings, 0 replies; 11+ messages in thread
From: Ben Greear @ 2014-05-19 15:58 UTC (permalink / raw)
  To: Park, Kyeyoon; +Cc: johannes, Malinen, Jouni, linux-wireless

On 05/16/2014 04:04 PM, Park, Kyeyoon wrote:
> Hi Ben,
> 
>>> +#define STA_IPV4_HASH_SIZE 32
>>> +#define STA_IPV4_HASH(ipv4) (((u8 *)&ipv4)[3] & 0x1F)
>>
>> This should be a better hash I think.  Use an existing hash
>> method or at least mix in the higher bits manually?
> 
> I assume that there is an existing IP address hash function
> somewhere in the TCP/IP stack. I have a hard time finding
> an externally available API that does this for me. Could you
> point me to it?

Maybe jhash_1word?

Thanks,
Ben



-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-16 22:49   ` Park, Kyeyoon
@ 2014-06-04 11:47     ` Johannes Berg
  2014-06-04 13:42       ` Jouni Malinen
  0 siblings, 1 reply; 11+ messages in thread
From: Johannes Berg @ 2014-06-04 11:47 UTC (permalink / raw)
  To: Park, Kyeyoon; +Cc: Malinen, Jouni, linux-wireless

On Fri, 2014-05-16 at 22:49 +0000, Park, Kyeyoon wrote:

> > All code paths within the REQUEST return 1 - is that intentional? It seems
> > to me that there might be a requirement to actually pass the frame if you
> > don't know a response? OTOH, maybe you don't actually need this since
> > you don't necessarily want the stations communicating anyway (at least
> > in a HS2 scenario)
> 
> It is intentional for this particular case. There would be a case for
> static IP, IPv4 DAD (RFC 5227), where a defense ARP Announcement packet
> from the bridge would not only invalidate the table we built in the AP,
> but also would inform the STA that there is an entity out there with
> the same IP address. In this case, the "ARP REQUEST" frame would be
> allowed through. Note: NOT implemented yet. This would be part 2.
> 
> The STAs not being able to communicate with each other, at least not
> directly without the consent of an overseeing entity connected to the
> bridge, is for the other feature in HS2, L2TIF (L2 Traffic Inspection
> and Filtering). Coming to an e-mail inbox near you, hopefully in the
> near future.

Right, but it seems to me that these two features aren't necessarily
dependent on each other - iow it seems that there might be a use case
for doing proxy ARP while not doing filtering?

OTOH, if the filtering is required for HS2, then maybe we don't have to
worry about this part, and then we can implement it elsewhere fairly
easily?

> > > +       } else if (arp->ar_op == htons(ARPOP_REPLY)) {
> > > +               if (is_multicast_ether_addr(eh->h_dest))
> > > +                       return 1;
> > 
> > is also implementing something else - not this particular feature, no?
> 
> Right. This is suppressing the G.ARP Reply within the BSS.

Yeah, again more related to the filtering though, not plain proxy ARP.

> Honestly, I have no problem doing this elsewhere as long as:
> 1) We can add an AP context to ip/eb/nftables in a clean way. Maybe get
> the hostapd involved somehow? Get it to inform the MAC addresses of
> the STAs to ip/eb/nftables? A specific detail would be helpful for
> me in doing the implementation. Greatly appreciated in advance.

It seems to me that ebtables should be able to filter on the ports
already, so I'm not really sure what you mean by this.

The real issue is the internal forwarding. Is that even necessary? Maybe
instead the bridge could forward back to the same port in some cases,
and you could just disable the internal forwarding in mac80211 entirely?

Beyond that, even the "only reply when you have a response" part could
be done using the nftables framework, it has quick hash/tree data
structures that say the DHCP server could manage (somehow.)

I feel that this is more of a system integration issue. We may not have
the full capabilities to allow such integration, but I also think
implementing it all in the stack is the wrong approach.


> 2) The performance hit from such method would be comparable to that
> of the proposed method. I feel that the current implementation's
> performance hit should be minimal to the wireless stack.

Until proven otherwise, I don't see any performance issues :-)
Or let me put it this way - until we can actually see that there's no
way to make the other solution perform well enough (which I highly
doubt, with BPF JIT being available etc.!) I don't think it makes sense
to think about performance much.

johannes


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-06-04 11:47     ` Johannes Berg
@ 2014-06-04 13:42       ` Jouni Malinen
  2014-06-04 13:46         ` Johannes Berg
  0 siblings, 1 reply; 11+ messages in thread
From: Jouni Malinen @ 2014-06-04 13:42 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Park, Kyeyoon, linux-wireless

On Wed, Jun 04, 2014 at 01:47:06PM +0200, Johannes Berg wrote:
> It seems to me that ebtables should be able to filter on the ports
> already, so I'm not really sure what you mean by this.
> 
> The real issue is the internal forwarding. Is that even necessary? Maybe
> instead the bridge could forward back to the same port in some cases,
> and you could just disable the internal forwarding in mac80211 entirely?

I'd assume that for most Hotspot 2.0 use cases, internal forwarding
would be disabled completely, but there may very well be cases where one
would like to use ProxyARP with forwarding between associated stations.
Doing that through the bridge code above mac80211 should be fine,
though, i.e., there is no particular reason why the internal forwarding
really needs to be internal within mac80211 as long as the
implementation outside is doable (forward back to same port).

> Beyond that, even the "only reply when you have a response" part could
> be done using the nftables framework, it has quick hash/tree data
> structures that say the DHCP server could manage (somehow.)

Getting DHCP server involved in Proxy ARP management sounds complex and
quite impractical for many cases. I'd expect Hotspot 2.0 APs to work
with any deployed DHCP setup and there is not really going to be any
coordination between the two apart from the AP obviously seeing the DHCP
messages flowing through it.

Sure, there could be an interface that allows external control, but I
think there needs to be capability to learn automatically from ARP (and
IPv6 neighbor messages) and DHCP frames flowing through the AP.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-06-04 13:42       ` Jouni Malinen
@ 2014-06-04 13:46         ` Johannes Berg
  2014-06-04 15:21           ` Luis R. Rodriguez
  0 siblings, 1 reply; 11+ messages in thread
From: Johannes Berg @ 2014-06-04 13:46 UTC (permalink / raw)
  To: Jouni Malinen; +Cc: Park, Kyeyoon, linux-wireless

On Wed, 2014-06-04 at 16:42 +0300, Jouni Malinen wrote:
> On Wed, Jun 04, 2014 at 01:47:06PM +0200, Johannes Berg wrote:
> > It seems to me that ebtables should be able to filter on the ports
> > already, so I'm not really sure what you mean by this.
> > 
> > The real issue is the internal forwarding. Is that even necessary? Maybe
> > instead the bridge could forward back to the same port in some cases,
> > and you could just disable the internal forwarding in mac80211 entirely?
> 
> I'd assume that for most Hotspot 2.0 use cases, internal forwarding
> would be disabled completely, but there may very well be cases where one
> would like to use ProxyARP with forwarding between associated stations.
> Doing that through the bridge code above mac80211 should be fine,
> though, i.e., there is no particular reason why the internal forwarding
> really needs to be internal within mac80211 as long as the
> implementation outside is doable (forward back to same port).

Right - I think currently the forward back to the same port part would
be missing. We should probably have a wider discussion with
bridging/nftables/etc. folks.

> > Beyond that, even the "only reply when you have a response" part could
> > be done using the nftables framework, it has quick hash/tree data
> > structures that say the DHCP server could manage (somehow.)
> 
> Getting DHCP server involved in Proxy ARP management sounds complex and
> quite impractical for many cases. I'd expect Hotspot 2.0 APs to work
> with any deployed DHCP setup and there is not really going to be any
> coordination between the two apart from the AP obviously seeing the DHCP
> messages flowing through it.
> 
> Sure, there could be an interface that allows external control, but I
> think there needs to be capability to learn automatically from ARP (and
> IPv6 neighbor messages) and DHCP frames flowing through the AP.

Oh, sure, I agree - and it doesn't really matter where the learning
comes from. I was just trying to say that the filtering part of "drop
frame only when going to reply" should be entirely doable with something
like nftables' set datastructure (or whatever it's called)

johannes


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-06-04 13:46         ` Johannes Berg
@ 2014-06-04 15:21           ` Luis R. Rodriguez
  0 siblings, 0 replies; 11+ messages in thread
From: Luis R. Rodriguez @ 2014-06-04 15:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Jouni Malinen, Park, Kyeyoon, linux-wireless

On Wed, Jun 4, 2014 at 6:46 AM, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Wed, 2014-06-04 at 16:42 +0300, Jouni Malinen wrote:
>> On Wed, Jun 04, 2014 at 01:47:06PM +0200, Johannes Berg wrote:
>> > It seems to me that ebtables should be able to filter on the ports
>> > already, so I'm not really sure what you mean by this.
>> >
>> > The real issue is the internal forwarding. Is that even necessary? Maybe
>> > instead the bridge could forward back to the same port in some cases,
>> > and you could just disable the internal forwarding in mac80211 entirely?
>>
>> I'd assume that for most Hotspot 2.0 use cases, internal forwarding
>> would be disabled completely, but there may very well be cases where one
>> would like to use ProxyARP with forwarding between associated stations.
>> Doing that through the bridge code above mac80211 should be fine,
>> though, i.e., there is no particular reason why the internal forwarding
>> really needs to be internal within mac80211 as long as the
>> implementation outside is doable (forward back to same port).
>
> Right - I think currently the forward back to the same port part would
> be missing. We should probably have a wider discussion with
> bridging/nftables/etc. folks.

I have some virtualization interests on this topic as well. The same
problem and need is present if one wants to implement a clean solution
to use 802.11 on the backend dom0 to share given we can't bridge
802.11, additionally there is a bit of overhead I see with existing
virtualization strategies on relying on full backend device drivers in
*addition* to the TAP interfaces created by qemu, what I hope for is
doing away with the backend device drivers completely. There are
issues with this architecturally though and although I'm not yet a fan
of the existing code the DPDK [0] code is one example strategy. The
way I was thinking about this was having APIs for userspace to deal
with the a proxy arp requirements which are currently not handled in
the kernel.

[0] http://dpdk.org/

  Luis

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [RFC] cfg80211/mac80211: Add support for Proxy ARP
  2014-05-15 19:06 [RFC] cfg80211/mac80211: Add support for Proxy ARP Kyeyoon Park
  2014-05-15 19:32 ` Ben Greear
  2014-05-16  9:16 ` Johannes Berg
@ 2018-02-16 12:53 ` Ujjal Roy
  2 siblings, 0 replies; 11+ messages in thread
From: Ujjal Roy @ 2018-02-16 12:53 UTC (permalink / raw)
  To: Kyeyoon Park; +Cc: Johannes Berg, jouni, Kernel

He All,

On Fri, May 16, 2014 at 12:36 AM, Kyeyoon Park
<kyeyoonp@qca.qualcomm.com> wrote:
> in IEEE Std 802.11-2012, 10.23.13. This particular commit will
> eventually be split into two separate commits (cfg80211 and mac80211
> separately).

I wanted to know the status now? Is it fully implemented in mac80211
and or cfg80211? Is it still partially implemented?

Thanks,
UjjaL Roy

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2018-02-16 12:53 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-15 19:06 [RFC] cfg80211/mac80211: Add support for Proxy ARP Kyeyoon Park
2014-05-15 19:32 ` Ben Greear
2014-05-16 23:04   ` Park, Kyeyoon
2014-05-19 15:58     ` Ben Greear
2014-05-16  9:16 ` Johannes Berg
2014-05-16 22:49   ` Park, Kyeyoon
2014-06-04 11:47     ` Johannes Berg
2014-06-04 13:42       ` Jouni Malinen
2014-06-04 13:46         ` Johannes Berg
2014-06-04 15:21           ` Luis R. Rodriguez
2018-02-16 12:53 ` Ujjal Roy

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.