[RFC/RFT] driver_nl80211: automatically use concurrent P2P if possible

Johannes Berg johannes
Wed Sep 7 12:50:43 PDT 2011


From: Johannes Berg <johannes.berg at intel.com>

Since the kernel can now advertise P2P concurrent
support by advertising interface combinations, we
can take advantage of that and automatically use
P2P_CONCURRENT / P2P_MGMT_AND_NON_P2P for drivers
that advertise support.

Keep driver_param=use_p2p_group_interface=1 for
anyone not advertising interface combinations in
their drivers yet.

Signed-off-by: Johannes Berg <johannes.berg at intel.com>
---
 src/drivers/driver_nl80211.c |   75 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 75 insertions(+)

--- a/src/drivers/driver_nl80211.c	2011-09-06 08:10:45.000000000 +0200
+++ b/src/drivers/driver_nl80211.c	2011-09-07 21:48:13.000000000 +0200
@@ -1636,6 +1636,7 @@ struct wiphy_info_data {
 	int max_scan_ssids;
 	int ap_supported;
 	int p2p_supported;
+	int p2p_concurrent;
 	int auth_supported;
 	int connect_supported;
 	int offchan_tx_supported;
@@ -1649,6 +1650,17 @@ static int wiphy_info_handler(struct nl_
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 	struct wiphy_info_data *info = arg;
 	int p2p_go_supported = 0, p2p_client_supported = 0;
+	static struct nla_policy
+	iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+		[NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+		[NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+		[NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
+		[NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+	},
+	iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+		[NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
+		[NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
+	};
 
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
@@ -1676,6 +1688,63 @@ static int wiphy_info_handler(struct nl_
 		}
 	}
 
+	if (tb[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
+		struct nlattr *nl_combi;
+		int rem_combi;
+
+		nla_for_each_nested(nl_combi,
+				    tb[NL80211_ATTR_INTERFACE_COMBINATIONS],
+				    rem_combi) {
+			struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+			struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+			struct nlattr *nl_limit, *nl_mode;
+			int err, rem_limit, rem_mode;
+			int combination_has_p2p = 0, combination_has_mgd = 0;
+
+			err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+					       nl_combi,
+					       iface_combination_policy);
+			if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+			    !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+			    !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS])
+				goto broken_combination;
+
+			nla_for_each_nested(nl_limit,
+					    tb_comb[NL80211_IFACE_COMB_LIMITS],
+					    rem_limit) {
+				err = nla_parse_nested(tb_limit,
+						       MAX_NL80211_IFACE_LIMIT,
+						       nl_limit,
+						       iface_limit_policy);
+				if (err ||
+				    !tb_limit[NL80211_IFACE_LIMIT_TYPES])
+					goto broken_combination;
+
+				nla_for_each_nested(nl_mode,
+						    tb_limit[NL80211_IFACE_LIMIT_TYPES],
+						    rem_mode) {
+					int ift = nla_type(nl_mode);
+					if (ift == NL80211_IFTYPE_P2P_GO ||
+					    ift == NL80211_IFTYPE_P2P_CLIENT)
+						combination_has_p2p = 1;
+					if (ift == NL80211_IFTYPE_STATION)
+						combination_has_mgd = 1;
+				}
+				if (combination_has_p2p && combination_has_mgd)
+					break;
+			}
+
+			if (combination_has_p2p && combination_has_mgd) {
+				info->p2p_concurrent = 1;
+				break;
+			}
+
+broken_combination:
+			;
+		}
+	}
+
+
 	info->p2p_supported = p2p_go_supported && p2p_client_supported;
 
 	if (tb[NL80211_ATTR_SUPPORTED_COMMANDS]) {
@@ -1772,6 +1841,12 @@ static int wpa_driver_nl80211_capa(struc
 	drv->capa.flags |= WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE;
 	if (info.p2p_supported)
 		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CAPABLE;
+	if (info.p2p_concurrent) {
+		wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
+			   "interface (driver advertised support)");
+		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
+		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P;
+	}
 	drv->capa.flags |= WPA_DRIVER_FLAGS_EAPOL_TX_STATUS;
 	drv->capa.flags |= WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS;
 	drv->capa.max_remain_on_chan = info.max_remain_on_chan;





More information about the Hostap mailing list