summaryrefslogtreecommitdiff
path: root/net/batman-adv/hard-interface.c
diff options
context:
space:
mode:
authorMarek Lindner <mareklindner@neomailbox.ch>2016-09-30 16:21:04 +0300
committerSimon Wunderlich <sw@simonwunderlich.de>2016-11-08 21:02:38 +0300
commit5ed4a460a1d359e1e9e7f54f6c78dfa9d1586b4b (patch)
tree9b98f285285ac6a1292fc7296658cc4785a84bd1 /net/batman-adv/hard-interface.c
parent10b1bbb46c6c8e571458a9a8913514dbebbaf20c (diff)
downloadlinux-5ed4a460a1d359e1e9e7f54f6c78dfa9d1586b4b.tar.xz
batman-adv: additional checks for virtual interfaces on top of WiFi
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> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
Diffstat (limited to 'net/batman-adv/hard-interface.c')
-rw-r--r--net/batman-adv/hard-interface.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 57e89125ab3e..df31f2fef636 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);
}