b.a.t.m.a.n.lists.open-mesh.org archive mirror
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on
@ 2016-09-30 13:20 Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 1/7] batman-adv: Return non-const ptr in batadv_getlink_net Sven Eckelmann
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:20 UTC (permalink / raw)
  To: b.a.t.m.a.n

[-- Attachment #1: Type: text/plain, Size: 1975 bytes --]

Hi,

Marek created some patches a while ago to automatically detect the wifi
interface under virtual interfaces like VLANs. These patches had some problems
because they failed to correctly set the num_bcasts in these situations and
also had some locking problems.

The following patches try to address these by introducing a cache for the
detected wifi configuration (wifi_flags which make taking the rtnl lock in
critical section unnecessary) and by updating the num_bcast and wifi_flags
when the interface behind iflink changes.

 * added patch "batman-adv: Return non-const ptr in batadv_getlink_net"
 * added patch "batman-adv: Close two alignment holes in batadv_hard_iface"
 * added patch "batman-adv: Cache the type of wifi device for each hardif"
 * added patch "batman-adv: Update wifi flags on upper link change"
 * introduced batadv_get_real_netdevice which can be used inside rtnl
   locked contexts
 * replaced wifi check functions with ones that use the wifi_flags cache
 * use batadv_getlink_net to get the iflink net_namespace
 * force rtnl_lock in batadv_get_real_netdev

Kind regards,
	Sven


Marek Lindner (3):
      batman-adv: refactor wifi interface detection
      batman-adv: additional checks for virtual interfaces on top of WiFi
      batman-adv: retrieve B.A.T.M.A.N. V WiFi neighbor stats from real interface

Sven Eckelmann (4):
      batman-adv: Return non-const ptr in batadv_getlink_net
      batman-adv: Close two alignment holes in batadv_hard_iface
      batman-adv: Cache the type of wifi device for each hardif
      batman-adv: Update wifi flags on upper link change

 net/batman-adv/bat_iv_ogm.c        |   2 +-
 net/batman-adv/bat_v_elp.c         |  41 +++++----
 net/batman-adv/hard-interface.c    | 173 ++++++++++++++++++++++++++++++++++---
 net/batman-adv/hard-interface.h    |   5 +-
 net/batman-adv/translation-table.c |  10 ++-
 net/batman-adv/types.h             |  21 ++++-
 6 files changed, 217 insertions(+), 35 deletions(-)

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* [B.A.T.M.A.N.] [PATCH v2 1/7] batman-adv: Return non-const ptr in batadv_getlink_net
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 2/7] batman-adv: Close two alignment holes in batadv_hard_iface Sven Eckelmann
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

The returned net_namespace of batadv_getlink_net may be used with functions
that potentially modify the struct. Thus it must return the pointer as
non-const like rtnl_link_ops::get_link_net does.

Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - new patch
---
 net/batman-adv/hard-interface.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 08ce361..a0b01cb 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -92,8 +92,8 @@ out:
  *
  * Return: result of rtnl_link_ops->get_link_net or @fallback_net
  */
-static const struct net *batadv_getlink_net(const struct net_device *netdev,
-					    const struct net *fallback_net)
+static struct net *batadv_getlink_net(const struct net_device *netdev,
+				      struct net *fallback_net)
 {
 	if (!netdev->rtnl_link_ops)
 		return fallback_net;
@@ -116,9 +116,9 @@ static const struct net *batadv_getlink_net(const struct net_device *netdev,
  * Return: true if the devices are each others parent, otherwise false
  */
 static bool batadv_mutual_parents(const struct net_device *dev1,
-				  const struct net *net1,
+				  struct net *net1,
 				  const struct net_device *dev2,
-				  const struct net *net2)
+				  struct net *net2)
 {
 	int dev1_parent_iflink = dev_get_iflink(dev1);
 	int dev2_parent_iflink = dev_get_iflink(dev2);
@@ -154,7 +154,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
 {
 	struct net *net = dev_net(net_dev);
 	struct net_device *parent_dev;
-	const struct net *parent_net;
+	struct net *parent_net;
 	bool ret;
 
 	/* check if this is a batman-adv mesh interface */
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 2/7] batman-adv: Close two alignment holes in batadv_hard_iface
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 1/7] batman-adv: Return non-const ptr in batadv_getlink_net Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 3/7] batman-adv: refactor wifi interface detection Sven Eckelmann
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - new patch
---
 net/batman-adv/types.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index b3dd1a3..8eef6a3 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -123,8 +123,8 @@ struct batadv_hard_iface_bat_v {
  * @list: list node for batadv_hardif_list
  * @if_num: identificator of the interface
  * @if_status: status of the interface for batman-adv
- * @net_dev: pointer to the net_device
  * @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
+ * @net_dev: pointer to the net_device
  * @hardif_obj: kobject of the per interface sysfs "mesh" directory
  * @refcount: number of contexts the object is used
  * @batman_adv_ptype: packet type describing packets that should be processed by
@@ -141,8 +141,8 @@ struct batadv_hard_iface {
 	struct list_head list;
 	s16 if_num;
 	char if_status;
-	struct net_device *net_dev;
 	u8 num_bcasts;
+	struct net_device *net_dev;
 	struct kobject *hardif_obj;
 	struct kref refcount;
 	struct packet_type batman_adv_ptype;
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 3/7] batman-adv: refactor wifi interface detection
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 1/7] batman-adv: Return non-const ptr in batadv_getlink_net Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 2/7] batman-adv: Close two alignment holes in batadv_hard_iface Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 4/7] batman-adv: Cache the type of wifi device for each hardif Sven Eckelmann
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann, Marek Lindner

From: Marek Lindner <mareklindner@neomailbox.ch>

The ELP protocol requires cfg80211 to auto-detect the WiFi througput
to a given neighbor. Use batadv_is_cfg80211_netdev() to determine
whether or not an interface is eligible.

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - rebased on top of current master
---
 net/batman-adv/bat_v_elp.c      | 29 ++++++++++++++---------------
 net/batman-adv/hard-interface.c | 26 +++++++++++++++++++++-----
 net/batman-adv/hard-interface.h |  1 +
 3 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index ee08540..b61ec79 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -90,22 +90,21 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 	 * cfg80211 API
 	 */
 	if (batadv_is_wifi_netdev(hard_iface->net_dev)) {
-		if (hard_iface->net_dev->ieee80211_ptr) {
-			ret = cfg80211_get_station(hard_iface->net_dev,
-						   neigh->addr, &sinfo);
-			if (ret == -ENOENT) {
-				/* Node is not associated anymore! It would be
-				 * possible to delete this neighbor. For now set
-				 * the throughput metric to 0.
-				 */
-				return 0;
-			}
-			if (!ret)
-				return sinfo.expected_throughput / 100;
+		if (!batadv_is_cfg80211_netdev(hard_iface->net_dev))
+			/* unsupported WiFi driver version */
+			goto default_throughput;
+
+		ret = cfg80211_get_station(hard_iface->net_dev,
+					   neigh->addr, &sinfo);
+		if (ret == -ENOENT) {
+			/* Node is not associated anymore! It would be
+			 * possible to delete this neighbor. For now set
+			 * the throughput metric to 0.
+			 */
+			return 0;
 		}
-
-		/* unsupported WiFi driver version */
-		goto default_throughput;
+		if (!ret)
+			return sinfo.expected_throughput / 100;
 	}
 
 	/* if not a wifi interface, check if this device provides data via
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index a0b01cb..b09fec2 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -202,6 +202,26 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
 }
 
 /**
+ * batadv_is_cfg80211_netdev - check if the given net_device struct is a
+ *  cfg80211 wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ *  otherwise.
+ */
+bool batadv_is_cfg80211_netdev(struct net_device *net_device)
+{
+	if (!net_device)
+		return false;
+
+	/* cfg80211 drivers have to set ieee80211_ptr */
+	if (net_device->ieee80211_ptr)
+		return true;
+
+	return false;
+}
+
+/**
  * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
  *  interface
  * @net_device: the device to check
@@ -221,11 +241,7 @@ bool batadv_is_wifi_netdev(struct net_device *net_device)
 		return true;
 #endif
 
-	/* cfg80211 drivers have to set ieee80211_ptr */
-	if (net_device->ieee80211_ptr)
-		return true;
-
-	return false;
+	return batadv_is_cfg80211_netdev(net_device);
 }
 
 static struct batadv_hard_iface *
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index a76724d..e0893de 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -51,6 +51,7 @@ enum batadv_hard_if_cleanup {
 
 extern struct notifier_block batadv_hard_if_notifier;
 
+bool batadv_is_cfg80211_netdev(struct net_device *net_device);
 bool batadv_is_wifi_netdev(struct net_device *net_device);
 bool batadv_is_wifi_iface(int ifindex);
 struct batadv_hard_iface*
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 4/7] batman-adv: Cache the type of wifi device for each hardif
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
                   ` (2 preceding siblings ...)
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 3/7] batman-adv: refactor wifi interface detection Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 5/7] batman-adv: additional checks for virtual interfaces on top of WiFi Sven Eckelmann
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

batman-adv is requiring the type of wifi device in different contexts. Some
of them can take the rtnl semaphore and some of them already have the
semaphore taken. But even others don't allow that the semaphore will be
taken.

The data has to be retrieved when the hardif is added to batman-adv because
some of the wifi information for an hardif will only be available with rtnl
lock. It can then be cached in the batadv_hard_iface and the functions
is_wifi_netdev and is_cfg80211_netdev can just compare the correct bits
without imposing extra locking requirements.

Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - new patch
---
 net/batman-adv/bat_iv_ogm.c        |  2 +-
 net/batman-adv/bat_v_elp.c         |  8 ++--
 net/batman-adv/hard-interface.c    | 82 +++++++++++++++++++++++++++++++-------
 net/batman-adv/hard-interface.h    |  5 +--
 net/batman-adv/translation-table.c | 10 ++++-
 net/batman-adv/types.h             | 13 ++++++
 6 files changed, 95 insertions(+), 25 deletions(-)

diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
index e2d18d0..7079d55 100644
--- a/net/batman-adv/bat_iv_ogm.c
+++ b/net/batman-adv/bat_iv_ogm.c
@@ -1272,7 +1272,7 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node,
 	 */
 	tq_iface_penalty = BATADV_TQ_MAX_VALUE;
 	if (if_outgoing && (if_incoming == if_outgoing) &&
-	    batadv_is_wifi_netdev(if_outgoing->net_dev))
+	    batadv_is_wifi_hardif(if_outgoing))
 		tq_iface_penalty = batadv_hop_penalty(BATADV_TQ_MAX_VALUE,
 						      bat_priv);
 
diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index b61ec79..cdcaf6b 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -89,8 +89,8 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 	/* if this is a wireless device, then ask its throughput through
 	 * cfg80211 API
 	 */
-	if (batadv_is_wifi_netdev(hard_iface->net_dev)) {
-		if (!batadv_is_cfg80211_netdev(hard_iface->net_dev))
+	if (batadv_is_wifi_hardif(hard_iface)) {
+		if (!batadv_is_cfg80211_hardif(hard_iface))
 			/* unsupported WiFi driver version */
 			goto default_throughput;
 
@@ -186,7 +186,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
 	int elp_skb_len;
 
 	/* this probing routine is for Wifi neighbours only */
-	if (!batadv_is_wifi_netdev(hard_iface->net_dev))
+	if (!batadv_is_wifi_hardif(hard_iface))
 		return true;
 
 	/* probe the neighbor only if no unicast packets have been sent
@@ -351,7 +351,7 @@ int batadv_v_elp_iface_enable(struct batadv_hard_iface *hard_iface)
 	/* warn the user (again) if there is no throughput data is available */
 	hard_iface->bat_v.flags &= ~BATADV_WARNING_DEFAULT;
 
-	if (batadv_is_wifi_netdev(hard_iface->net_dev))
+	if (batadv_is_wifi_hardif(hard_iface))
 		hard_iface->bat_v.flags &= ~BATADV_FULL_DUPLEX;
 
 	INIT_DELAYED_WORK(&hard_iface->bat_v.elp_wq,
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index b09fec2..341fbb5 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -202,6 +202,30 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
 }
 
 /**
+ * batadv_is_wext_netdev - check if the given net_device struct is a
+ *  wext wifi interface
+ * @net_device: the device to check
+ *
+ * Return: true if the net device is a wext wireless device, false
+ *  otherwise.
+ */
+static bool batadv_is_wext_netdev(struct net_device *net_device)
+{
+	if (!net_device)
+		return false;
+
+#ifdef CONFIG_WIRELESS_EXT
+	/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
+	 * check for wireless_handlers != NULL
+	 */
+	if (net_device->wireless_handlers)
+		return true;
+#endif
+
+	return false;
+}
+
+/**
  * batadv_is_cfg80211_netdev - check if the given net_device struct is a
  *  cfg80211 wifi interface
  * @net_device: the device to check
@@ -209,7 +233,7 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
  * Return: true if the net device is a cfg80211 wireless device, false
  *  otherwise.
  */
-bool batadv_is_cfg80211_netdev(struct net_device *net_device)
+static bool batadv_is_cfg80211_netdev(struct net_device *net_device)
 {
 	if (!net_device)
 		return false;
@@ -222,26 +246,53 @@ bool batadv_is_cfg80211_netdev(struct net_device *net_device)
 }
 
 /**
- * batadv_is_wifi_netdev - check if the given net_device struct is a wifi
- *  interface
+ * batadv_wifi_flags_evaluate - calculate wifi flags for net_device
  * @net_device: the device to check
  *
+ * Return: batadv_hard_iface_wifi_flags flags of the device
+ */
+static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
+{
+	u32 wifi_flags = 0;
+
+	if (batadv_is_wext_netdev(net_device))
+		wifi_flags |= BATADV_HARDIF_WIFI_WEXT_DIRECT;
+
+	if (batadv_is_cfg80211_netdev(net_device))
+		wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+
+	return wifi_flags;
+}
+
+/**
+ * batadv_is_cfg80211_hardif - check if the given hardif is a cfg80211 wifi
+ *  interface
+ * @hard_iface: the device to check
+ *
+ * Return: true if the net device is a cfg80211 wireless device, false
+ *  otherwise.
+ */
+bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
+{
+	u32 allowed_flags = 0;
+
+	allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+
+	return !!(hard_iface->wifi_flags & allowed_flags);
+}
+
+/**
+ * batadv_is_wifi_hardif - check if the given hardif is a wifi interface
+ * @hard_iface: the device to check
+ *
  * Return: true if the net device is a 802.11 wireless device, false otherwise.
  */
-bool batadv_is_wifi_netdev(struct net_device *net_device)
+bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface)
 {
-	if (!net_device)
+	if (!hard_iface)
 		return false;
 
-#ifdef CONFIG_WIRELESS_EXT
-	/* pre-cfg80211 drivers have to implement WEXT, so it is possible to
-	 * check for wireless_handlers != NULL
-	 */
-	if (net_device->wireless_handlers)
-		return true;
-#endif
-
-	return batadv_is_cfg80211_netdev(net_device);
+	return hard_iface->wifi_flags != 0;
 }
 
 static struct batadv_hard_iface *
@@ -713,7 +764,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
 	kref_init(&hard_iface->refcount);
 
 	hard_iface->num_bcasts = BATADV_NUM_BCASTS_DEFAULT;
-	if (batadv_is_wifi_netdev(net_dev))
+	hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+	if (batadv_is_wifi_hardif(hard_iface))
 		hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
 
 	batadv_v_hardif_init(hard_iface);
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index e0893de..957fd8f 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -51,9 +51,8 @@ enum batadv_hard_if_cleanup {
 
 extern struct notifier_block batadv_hard_if_notifier;
 
-bool batadv_is_cfg80211_netdev(struct net_device *net_device);
-bool batadv_is_wifi_netdev(struct net_device *net_device);
-bool batadv_is_wifi_iface(int ifindex);
+bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface);
+bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
 struct batadv_hard_iface*
 batadv_hardif_get_by_netdev(const struct net_device *net_dev);
 int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 7f66309..7c76f83 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -647,6 +647,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
 	struct net *net = dev_net(soft_iface);
 	struct batadv_softif_vlan *vlan;
 	struct net_device *in_dev = NULL;
+	struct batadv_hard_iface *in_hardif = NULL;
 	struct hlist_head *head;
 	struct batadv_tt_orig_list_entry *orig_entry;
 	int hash_added, table_size, packet_size_max;
@@ -658,6 +659,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
 	if (ifindex != BATADV_NULL_IFINDEX)
 		in_dev = dev_get_by_index(net, ifindex);
 
+	if (in_dev)
+		in_hardif = batadv_hardif_get_by_netdev(in_dev);
+
 	tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);
 
 	if (!is_multicast_ether_addr(addr))
@@ -731,7 +735,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
 	 */
 	tt_local->common.flags = BATADV_TT_CLIENT_NEW;
 	tt_local->common.vid = vid;
-	if (batadv_is_wifi_netdev(in_dev))
+	if (batadv_is_wifi_hardif(in_hardif))
 		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
 	kref_init(&tt_local->common.refcount);
 	tt_local->last_seen = jiffies;
@@ -791,7 +795,7 @@ check_roaming:
 	 */
 	remote_flags = tt_local->common.flags & BATADV_TT_REMOTE_MASK;
 
-	if (batadv_is_wifi_netdev(in_dev))
+	if (batadv_is_wifi_hardif(in_hardif))
 		tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
 	else
 		tt_local->common.flags &= ~BATADV_TT_CLIENT_WIFI;
@@ -815,6 +819,8 @@ check_roaming:
 
 	ret = true;
 out:
+	if (in_hardif)
+		batadv_hardif_put(in_hardif);
 	if (in_dev)
 		dev_put(in_dev);
 	if (tt_local)
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index 8eef6a3..fe64669 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -119,11 +119,23 @@ struct batadv_hard_iface_bat_v {
 };
 
 /**
+ * enum batadv_hard_iface_wifi_flags - Flags describing the wifi configuration
+ *  of a batadv_hard_iface
+ * @BATADV_HARDIF_WIFI_WEXT_DIRECT: it is a wext wifi device
+ * @BATADV_HARDIF_WIFI_CFG80211_DIRECT: it is a cfg80211 wifi device
+ */
+enum batadv_hard_iface_wifi_flags {
+	BATADV_HARDIF_WIFI_WEXT_DIRECT = BIT(0),
+	BATADV_HARDIF_WIFI_CFG80211_DIRECT = BIT(1),
+};
+
+/**
  * struct batadv_hard_iface - network device known to batman-adv
  * @list: list node for batadv_hardif_list
  * @if_num: identificator of the interface
  * @if_status: status of the interface for batman-adv
  * @num_bcasts: number of payload re-broadcasts on this interface (ARQ)
+ * @wifi_flags: flags whether this is (directly or indirectly) a wifi interface
  * @net_dev: pointer to the net_device
  * @hardif_obj: kobject of the per interface sysfs "mesh" directory
  * @refcount: number of contexts the object is used
@@ -142,6 +154,7 @@ struct batadv_hard_iface {
 	s16 if_num;
 	char if_status;
 	u8 num_bcasts;
+	u32 wifi_flags;
 	struct net_device *net_dev;
 	struct kobject *hardif_obj;
 	struct kref refcount;
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 5/7] batman-adv: additional checks for virtual interfaces on top of WiFi
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
                   ` (3 preceding siblings ...)
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 4/7] batman-adv: Cache the type of wifi device for each hardif Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 6/7] batman-adv: retrieve B.A.T.M.A.N. V WiFi neighbor stats from real interface Sven Eckelmann
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann, Marek Lindner

From: Marek Lindner <mareklindner@neomailbox.ch>

In a few situations batman-adv tries to determine whether a given interface
is a WiFi interface to enable specific WiFi optimizations. If the interface
batman-adv has been configured with is a virtual interface (e.g. VLAN) it
would not be properly detected as WiFi interface and thus not benefit from
the special WiFi treatment.
This patch changes that by peeking under the hood whenever a virtual
interface is in play.

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
[sven.eckelmann@open-mesh.com: integrate in wifi_flags caching, retrieve
 namespace of link interface]
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - introduced batadv_get_real_netdevice which can be used inside rtnl
   locked contexts
 - replace check functions with ones that use the wifi_flags cache
 - use batadv_getlink_net to get the iflink net_namespace
---
 net/batman-adv/hard-interface.c | 58 +++++++++++++++++++++++++++++++++++++++++
 net/batman-adv/types.h          |  4 +++
 2 files changed, 62 insertions(+)

diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 341fbb5..ba587fb 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -202,6 +202,47 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
 }
 
 /**
+ * batadv_get_real_netdevice - check if the given netdev struct is a virtual
+ *  interface on top of another 'real' interface
+ * @netdev: the device to check
+ *
+ * Return: the 'real' net device or the original net device and NULL in case
+ *  of an error.
+ */
+static struct net_device *batadv_get_real_netdevice(struct net_device *netdev)
+{
+	struct batadv_hard_iface *hard_iface = NULL;
+	struct net_device *real_netdev = NULL;
+	struct net *real_net;
+	struct net *net;
+	int ifindex;
+
+	ASSERT_RTNL();
+
+	if (!netdev)
+		return NULL;
+
+	if (netdev->ifindex == dev_get_iflink(netdev)) {
+		dev_hold(netdev);
+		return netdev;
+	}
+
+	hard_iface = batadv_hardif_get_by_netdev(netdev);
+	if (!hard_iface || !hard_iface->soft_iface)
+		goto out;
+
+	net = dev_net(hard_iface->soft_iface);
+	ifindex = dev_get_iflink(netdev);
+	real_net = batadv_getlink_net(netdev, net);
+	real_netdev = dev_get_by_index(real_net, ifindex);
+
+out:
+	if (hard_iface)
+		batadv_hardif_put(hard_iface);
+	return real_netdev;
+}
+
+/**
  * batadv_is_wext_netdev - check if the given net_device struct is a
  *  wext wifi interface
  * @net_device: the device to check
@@ -254,6 +295,7 @@ static bool batadv_is_cfg80211_netdev(struct net_device *net_device)
 static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
 {
 	u32 wifi_flags = 0;
+	struct net_device *real_netdev;
 
 	if (batadv_is_wext_netdev(net_device))
 		wifi_flags |= BATADV_HARDIF_WIFI_WEXT_DIRECT;
@@ -261,6 +303,21 @@ static u32 batadv_wifi_flags_evaluate(struct net_device *net_device)
 	if (batadv_is_cfg80211_netdev(net_device))
 		wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
 
+	real_netdev = batadv_get_real_netdevice(net_device);
+	if (!real_netdev)
+		return wifi_flags;
+
+	if (real_netdev == net_device)
+		goto out;
+
+	if (batadv_is_wext_netdev(real_netdev))
+		wifi_flags |= BATADV_HARDIF_WIFI_WEXT_INDIRECT;
+
+	if (batadv_is_cfg80211_netdev(real_netdev))
+		wifi_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
+
+out:
+	dev_put(real_netdev);
 	return wifi_flags;
 }
 
@@ -277,6 +334,7 @@ bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface)
 	u32 allowed_flags = 0;
 
 	allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_DIRECT;
+	allowed_flags |= BATADV_HARDIF_WIFI_CFG80211_INDIRECT;
 
 	return !!(hard_iface->wifi_flags & allowed_flags);
 }
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h
index fe64669..a6d8c98 100644
--- a/net/batman-adv/types.h
+++ b/net/batman-adv/types.h
@@ -123,10 +123,14 @@ struct batadv_hard_iface_bat_v {
  *  of a batadv_hard_iface
  * @BATADV_HARDIF_WIFI_WEXT_DIRECT: it is a wext wifi device
  * @BATADV_HARDIF_WIFI_CFG80211_DIRECT: it is a cfg80211 wifi device
+ * @BATADV_HARDIF_WIFI_WEXT_INDIRECT: link device is a wext wifi device
+ * @BATADV_HARDIF_WIFI_CFG80211_INDIRECT: link device is a cfg80211 wifi device
  */
 enum batadv_hard_iface_wifi_flags {
 	BATADV_HARDIF_WIFI_WEXT_DIRECT = BIT(0),
 	BATADV_HARDIF_WIFI_CFG80211_DIRECT = BIT(1),
+	BATADV_HARDIF_WIFI_WEXT_INDIRECT = BIT(2),
+	BATADV_HARDIF_WIFI_CFG80211_INDIRECT = BIT(3),
 };
 
 /**
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 6/7] batman-adv: retrieve B.A.T.M.A.N. V WiFi neighbor stats from real interface
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
                   ` (4 preceding siblings ...)
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 5/7] batman-adv: additional checks for virtual interfaces on top of WiFi Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 7/7] batman-adv: Update wifi flags on upper link change Sven Eckelmann
  2016-10-24 10:20 ` [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Simon Wunderlich
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann, Marek Lindner

From: Marek Lindner <mareklindner@neomailbox.ch>

Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
[sven.eckelmann@open-mesh.com: re-add batadv_get_real_netdev to take rtnl
 semaphore for batadv_get_real_netdevice]
Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - reintroduce batadv_get_real_netdev for situations were the rtnl_lock
   has to be taken
---
 net/batman-adv/bat_v_elp.c      | 10 ++++++++--
 net/batman-adv/hard-interface.c | 22 ++++++++++++++++++++++
 net/batman-adv/hard-interface.h |  1 +
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
index cdcaf6b..89488dc 100644
--- a/net/batman-adv/bat_v_elp.c
+++ b/net/batman-adv/bat_v_elp.c
@@ -75,6 +75,7 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 {
 	struct batadv_hard_iface *hard_iface = neigh->if_incoming;
 	struct ethtool_link_ksettings link_settings;
+	struct net_device *real_netdev;
 	struct station_info sinfo;
 	u32 throughput;
 	int ret;
@@ -94,8 +95,13 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 			/* unsupported WiFi driver version */
 			goto default_throughput;
 
-		ret = cfg80211_get_station(hard_iface->net_dev,
-					   neigh->addr, &sinfo);
+		real_netdev = batadv_get_real_netdev(hard_iface->net_dev);
+		if (!real_netdev)
+			goto default_throughput;
+
+		ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
+
+		dev_put(real_netdev);
 		if (ret == -ENOENT) {
 			/* Node is not associated anymore! It would be
 			 * possible to delete this neighbor. For now set
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index ba587fb..7d336e1 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -206,6 +206,9 @@ static bool batadv_is_valid_iface(const struct net_device *net_dev)
  *  interface on top of another 'real' interface
  * @netdev: the device to check
  *
+ * Callers must hold the rtnl semaphore. You may want batadv_get_real_netdev()
+ * instead of this.
+ *
  * Return: the 'real' net device or the original net device and NULL in case
  *  of an error.
  */
@@ -243,6 +246,25 @@ out:
 }
 
 /**
+ * batadv_get_real_netdev - check if the given net_device struct is a virtual
+ *  interface on top of another 'real' interface
+ * @net_device: the device to check
+ *
+ * Return: the 'real' net device or the original net device and NULL in case
+ *  of an error.
+ */
+struct net_device *batadv_get_real_netdev(struct net_device *net_device)
+{
+	struct net_device *real_netdev = NULL;
+
+	rtnl_lock();
+	real_netdev = batadv_get_real_netdevice(net_device);
+	rtnl_unlock();
+
+	return real_netdev;
+}
+
+/**
  * batadv_is_wext_netdev - check if the given net_device struct is a
  *  wext wifi interface
  * @net_device: the device to check
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h
index 957fd8f..0c7ff14 100644
--- a/net/batman-adv/hard-interface.h
+++ b/net/batman-adv/hard-interface.h
@@ -51,6 +51,7 @@ enum batadv_hard_if_cleanup {
 
 extern struct notifier_block batadv_hard_if_notifier;
 
+struct net_device *batadv_get_real_netdev(struct net_device *net_device);
 bool batadv_is_cfg80211_hardif(struct batadv_hard_iface *hard_iface);
 bool batadv_is_wifi_hardif(struct batadv_hard_iface *hard_iface);
 struct batadv_hard_iface*
-- 
2.9.3


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

* [B.A.T.M.A.N.] [PATCH v2 7/7] batman-adv: Update wifi flags on upper link change
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
                   ` (5 preceding siblings ...)
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 6/7] batman-adv: retrieve B.A.T.M.A.N. V WiFi neighbor stats from real interface Sven Eckelmann
@ 2016-09-30 13:21 ` Sven Eckelmann
  2016-10-24 10:20 ` [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Simon Wunderlich
  7 siblings, 0 replies; 9+ messages in thread
From: Sven Eckelmann @ 2016-09-30 13:21 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

Things like VLANs don't have their link set when they are created. Thus
the wifi flags have to be evaluated later to fix their contents for the
link interface.

Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
---
v2:
 - new patch
---
 compat-include/linux/netdevice.h | 2 ++
 net/batman-adv/hard-interface.c  | 5 +++++
 2 files changed, 7 insertions(+)

diff --git a/compat-include/linux/netdevice.h b/compat-include/linux/netdevice.h
index fb5b519..e71e614 100644
--- a/compat-include/linux/netdevice.h
+++ b/compat-include/linux/netdevice.h
@@ -43,6 +43,8 @@
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0)
 
+#define NETDEV_CHANGEUPPER	0x0015
+
 #define netdev_notifier_info_to_dev(ptr) ptr
 
 #endif /* < KERNEL_VERSION(3, 11, 0) */
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 7d336e1..400935f 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -954,6 +954,11 @@ static int batadv_hard_if_event(struct notifier_block *this,
 		if (hard_iface == primary_if)
 			batadv_primary_if_update_addr(bat_priv, NULL);
 		break;
+	case NETDEV_CHANGEUPPER:
+		hard_iface->wifi_flags = batadv_wifi_flags_evaluate(net_dev);
+		if (batadv_is_wifi_hardif(hard_iface))
+			hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+		break;
 	default:
 		break;
 	}
-- 
2.9.3


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

* Re: [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on
  2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
                   ` (6 preceding siblings ...)
  2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 7/7] batman-adv: Update wifi flags on upper link change Sven Eckelmann
@ 2016-10-24 10:20 ` Simon Wunderlich
  7 siblings, 0 replies; 9+ messages in thread
From: Simon Wunderlich @ 2016-10-24 10:20 UTC (permalink / raw)
  To: b.a.t.m.a.n; +Cc: Sven Eckelmann

[-- Attachment #1: Type: text/plain, Size: 1286 bytes --]

On Friday, September 30, 2016 3:20:23 PM CEST Sven Eckelmann wrote:
> Hi,
> 
> Marek created some patches a while ago to automatically detect the wifi
> interface under virtual interfaces like VLANs. These patches had some
> problems because they failed to correctly set the num_bcasts in these
> situations and also had some locking problems.
> 
> The following patches try to address these by introducing a cache for the
> detected wifi configuration (wifi_flags which make taking the rtnl lock in
> critical section unnecessary) and by updating the num_bcast and wifi_flags
> when the interface behind iflink changes.
> 
>  * added patch "batman-adv: Return non-const ptr in batadv_getlink_net"
>  * added patch "batman-adv: Close two alignment holes in batadv_hard_iface"
>  * added patch "batman-adv: Cache the type of wifi device for each hardif"
>  * added patch "batman-adv: Update wifi flags on upper link change"
>  * introduced batadv_get_real_netdevice which can be used inside rtnl
>    locked contexts
>  * replaced wifi check functions with ones that use the wifi_flags cache
>  * use batadv_getlink_net to get the iflink net_namespace
>  * force rtnl_lock in batadv_get_real_netdev
> 
> Kind regards,
> 	Sven

Applied this series on 451eab1..846df98.

Thanks,
     Simon

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 801 bytes --]

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

end of thread, other threads:[~2016-10-24 10:20 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-30 13:20 [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 1/7] batman-adv: Return non-const ptr in batadv_getlink_net Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 2/7] batman-adv: Close two alignment holes in batadv_hard_iface Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 3/7] batman-adv: refactor wifi interface detection Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 4/7] batman-adv: Cache the type of wifi device for each hardif Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 5/7] batman-adv: additional checks for virtual interfaces on top of WiFi Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 6/7] batman-adv: retrieve B.A.T.M.A.N. V WiFi neighbor stats from real interface Sven Eckelmann
2016-09-30 13:21 ` [B.A.T.M.A.N.] [PATCH v2 7/7] batman-adv: Update wifi flags on upper link change Sven Eckelmann
2016-10-24 10:20 ` [B.A.T.M.A.N.] [PATCH v2 0/7] batman-adv: wifi interface detection on Simon Wunderlich

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).