[v2,2/4] batman-adv: Create batman soft interfaces within correct netns.
Commit Message
When creating a soft interface, create it in the same netns as the
hard interface. Replace all references to init_net with the correct
name space for the interface being manipulated.
Suggested-by: Daniel Ehlers <danielehlers@mindeye.net>
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Antonio Quartulli <a@unstable.cc>
---
v2:
struct net forward declarations
Removed unneeded net/net_namespace.h
Rebased on https://git.open-mesh.org/batman-adv.git master
---
net/batman-adv/hard-interface.c | 9 +++++----
net/batman-adv/hard-interface.h | 3 ++-
net/batman-adv/soft-interface.c | 7 +++++--
net/batman-adv/soft-interface.h | 3 ++-
net/batman-adv/sysfs.c | 3 ++-
net/batman-adv/translation-table.c | 4 ++--
6 files changed, 18 insertions(+), 11 deletions(-)
Comments
On Tuesday 01 March 2016 22:19:06 Andrew Lunn wrote:
> When creating a soft interface, create it in the same netns as the
> hard interface. Replace all references to init_net with the correct
> name space for the interface being manipulated.
>
> Suggested-by: Daniel Ehlers <danielehlers@mindeye.net>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> Acked-by: Antonio Quartulli <a@unstable.cc>
> ---
>
> v2:
> struct net forward declarations
> Removed unneeded net/net_namespace.h
> Rebased on https://git.open-mesh.org/batman-adv.git master
> ---
> net/batman-adv/hard-interface.c | 9 +++++----
> net/batman-adv/hard-interface.h | 3 ++-
> net/batman-adv/soft-interface.c | 7 +++++--
> net/batman-adv/soft-interface.h | 3 ++-
> net/batman-adv/sysfs.c | 3 ++-
> net/batman-adv/translation-table.c | 4 ++--
> 6 files changed, 18 insertions(+), 11 deletions(-)
Just so that I have mentioned it: In theory '#include <net/net_namespace.h>'
should be removed by this patch (hard-interface.c) and added again in the next
patch. But this would be rather useless when applying the two patches
together. It may be different when this patch is applied first without the
next patch.
Just to be sure (and so that I don't have to test it here :) ): When this
patch is applied, batadv_softif_create would already fail when the two
namespaces have a batadv interface with the same name because the debugfs
function would fail. But it would work when the batman-adv interfaces + the
slave interfaces (for per-slave interface information) have different names.
Right?
Just some of my notes (just in case someone else asks himself the same
questions):
It looks to me that the only reason a device from a different namespace isn't
added is because batadv_softif_slave_add + batadv_store_mesh_iface is getting
the namespace of the new slave device and batadv_hardif_enable_interface then
only searches the soft-interface (batX) in this namespace.
It is currently not prevented that a slave device changes the namespace after
it was added. But this should not be a problem because the device will be
first removed from the original namespace (so it will be removed from batX)
and later added to the target namespace (see dev_change_net_namespace).
Reviewed-by: Sven Eckelmann <sven@narfation.org>
Kind regards,
Sven
> Just to be sure (and so that I don't have to test it here :) ): When this
> patch is applied, batadv_softif_create would already fail when the two
> namespaces have a batadv interface with the same name because the debugfs
> function would fail. But it would work when the batman-adv interfaces + the
> slave interfaces (for per-slave interface information) have different names.
> Right?
That is correct. As far as i remember, it failed in a good way,
i.e. not an opps. Which is why i put this patch first. We could swap
the order, have the debugfs patch first, but i though the 'why' of the
debugfs patch is probably clearer to somebody who has just reviewed
this patch first.
> It is currently not prevented that a slave device changes the namespace after
> it was added. But this should not be a problem because the device will be
> first removed from the original namespace (so it will be removed from batX)
> and later added to the target namespace (see dev_change_net_namespace).
Yes, and this is the same mechanism used for other master devices,
like bridges, teams/bonding. The slave is hot-unplugged from one name
space and hot-plugged into another name space.
> Reviewed-by: Sven Eckelmann <sven@narfation.org>
Thanks
Andrew
@@ -121,6 +121,7 @@ static bool batadv_mutual_parents(const struct net_device *dev1,
static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
{
struct net_device *parent_dev;
+ struct net *net = dev_net(net_dev);
bool ret;
/* check if this is a batman-adv mesh interface */
@@ -133,7 +134,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
return false;
/* recurse over the parent device */
- parent_dev = __dev_get_by_index(&init_net, dev_get_iflink(net_dev));
+ parent_dev = __dev_get_by_index(net, dev_get_iflink(net_dev));
/* if we got a NULL parent_dev there is something broken.. */
if (WARN(!parent_dev, "Cannot find parent device"))
return false;
@@ -453,7 +454,7 @@ static int batadv_master_del_slave(struct batadv_hard_iface *slave,
}
int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
- const char *iface_name)
+ struct net *net, const char *iface_name)
{
struct batadv_priv *bat_priv;
struct net_device *soft_iface, *master;
@@ -467,10 +468,10 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
if (!kref_get_unless_zero(&hard_iface->refcount))
goto out;
- soft_iface = dev_get_by_name(&init_net, iface_name);
+ soft_iface = dev_get_by_name(net, iface_name);
if (!soft_iface) {
- soft_iface = batadv_softif_create(iface_name);
+ soft_iface = batadv_softif_create(net, iface_name);
if (!soft_iface) {
ret = -ENOMEM;
@@ -28,6 +28,7 @@
#include <linux/types.h>
struct net_device;
+struct net;
enum batadv_hard_if_state {
BATADV_IF_NOT_IN_USE,
@@ -55,7 +56,7 @@ bool batadv_is_wifi_iface(int ifindex);
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,
- const char *iface_name);
+ struct net *net, const char *iface_name);
void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface,
enum batadv_hard_if_cleanup autodel);
void batadv_hardif_remove_interfaces(void);
@@ -868,13 +868,14 @@ static int batadv_softif_slave_add(struct net_device *dev,
struct net_device *slave_dev)
{
struct batadv_hard_iface *hard_iface;
+ struct net *net = dev_net(dev);
int ret = -EINVAL;
hard_iface = batadv_hardif_get_by_netdev(slave_dev);
if (!hard_iface || hard_iface->soft_iface)
goto out;
- ret = batadv_hardif_enable_interface(hard_iface, dev->name);
+ ret = batadv_hardif_enable_interface(hard_iface, net, dev->name);
out:
if (hard_iface)
@@ -971,7 +972,7 @@ static void batadv_softif_init_early(struct net_device *dev)
memset(priv, 0, sizeof(*priv));
}
-struct net_device *batadv_softif_create(const char *name)
+struct net_device *batadv_softif_create(struct net *net, const char *name)
{
struct net_device *soft_iface;
int ret;
@@ -981,6 +982,8 @@ struct net_device *batadv_softif_create(const char *name)
if (!soft_iface)
return NULL;
+ dev_net_set(soft_iface, net);
+
soft_iface->rtnl_link_ops = &batadv_link_ops;
ret = register_netdevice(soft_iface);
@@ -23,13 +23,14 @@
#include <net/rtnetlink.h>
struct net_device;
+struct net;
struct sk_buff;
int batadv_skb_head_push(struct sk_buff *skb, unsigned int len);
void batadv_interface_rx(struct net_device *soft_iface,
struct sk_buff *skb, struct batadv_hard_iface *recv_if,
int hdr_size, struct batadv_orig_node *orig_node);
-struct net_device *batadv_softif_create(const char *name);
+struct net_device *batadv_softif_create(struct net *net, const char *name);
void batadv_softif_destroy_sysfs(struct net_device *soft_iface);
bool batadv_softif_is_valid(const struct net_device *net_dev);
extern struct rtnl_link_ops batadv_link_ops;
@@ -830,6 +830,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
size_t count)
{
struct net_device *net_dev = batadv_kobj_to_netdev(kobj);
+ struct net *net = dev_net(net_dev);
struct batadv_hard_iface *hard_iface;
int status_tmp = -1;
int ret = count;
@@ -873,7 +874,7 @@ static ssize_t batadv_store_mesh_iface(struct kobject *kobj,
batadv_hardif_disable_interface(hard_iface,
BATADV_IF_CLEANUP_AUTO);
- ret = batadv_hardif_enable_interface(hard_iface, buff);
+ ret = batadv_hardif_enable_interface(hard_iface, net, buff);
unlock:
rtnl_unlock();
@@ -43,7 +43,6 @@
#include <linux/stddef.h>
#include <linux/string.h>
#include <linux/workqueue.h>
-#include <net/net_namespace.h>
#include "bridge_loop_avoidance.h"
#include "hard-interface.h"
@@ -583,6 +582,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
struct batadv_priv *bat_priv = netdev_priv(soft_iface);
struct batadv_tt_local_entry *tt_local;
struct batadv_tt_global_entry *tt_global = NULL;
+ struct net *net = dev_net(soft_iface);
struct batadv_softif_vlan *vlan;
struct net_device *in_dev = NULL;
struct hlist_head *head;
@@ -594,7 +594,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
u32 match_mark;
if (ifindex != BATADV_NULL_IFINDEX)
- in_dev = dev_get_by_index(&init_net, ifindex);
+ in_dev = dev_get_by_index(net, ifindex);
tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid);