Commit 373500db authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller

bonding: network device names are case sensative

The bonding device acts unlike all other Linux network device functions
in that it ignores case of device names. The developer must have come
from windows!

Cleanup the management of names and use standard routines where possible.
Flag places where bonding device still doesn't work right with network
namespaces.
Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6d7ab43c
...@@ -5064,20 +5064,17 @@ static void bond_set_lockdep_class(struct net_device *dev) ...@@ -5064,20 +5064,17 @@ static void bond_set_lockdep_class(struct net_device *dev)
int bond_create(const char *name) int bond_create(const char *name)
{ {
struct net_device *bond_dev; struct net_device *bond_dev;
struct bonding *bond;
int res; int res;
rtnl_lock(); rtnl_lock();
/* Check to see if the bond already exists. */ /* Check to see if the bond already exists. */
if (name) { /* FIXME: pass netns from caller */
list_for_each_entry(bond, &bond_dev_list, bond_list) if (name && __dev_get_by_name(&init_net, name)) {
if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) { pr_err(DRV_NAME ": cannot add bond %s; already exists\n",
pr_err(DRV_NAME ": cannot add bond %s;" name);
" it already exists\n", name); res = -EEXIST;
res = -EPERM;
goto out_rtnl; goto out_rtnl;
} }
}
bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "", bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
ether_setup); ether_setup);
......
...@@ -68,6 +68,17 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf) ...@@ -68,6 +68,17 @@ static ssize_t bonding_show_bonds(struct class *cls, char *buf)
return res; return res;
} }
static struct net_device *bond_get_by_name(const char *ifname)
{
struct bonding *bond;
list_for_each_entry(bond, &bond_dev_list, bond_list) {
if (strncmp(bond->dev->name, ifname, IFNAMSIZ) == 0)
return bond->dev;
}
return NULL;
}
/* /*
* "store" function for the bond_masters attribute. This is what * "store" function for the bond_masters attribute. This is what
* creates and deletes entire bonds. * creates and deletes entire bonds.
...@@ -82,7 +93,6 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -82,7 +93,6 @@ static ssize_t bonding_store_bonds(struct class *cls,
char command[IFNAMSIZ + 1] = {0, }; char command[IFNAMSIZ + 1] = {0, };
char *ifname; char *ifname;
int rv, res = count; int rv, res = count;
struct bonding *bond;
sscanf(buffer, "%16s", command); /* IFNAMSIZ*/ sscanf(buffer, "%16s", command); /* IFNAMSIZ*/
ifname = command + 1; ifname = command + 1;
...@@ -98,41 +108,35 @@ static ssize_t bonding_store_bonds(struct class *cls, ...@@ -98,41 +108,35 @@ static ssize_t bonding_store_bonds(struct class *cls,
pr_info(DRV_NAME ": Bond creation failed.\n"); pr_info(DRV_NAME ": Bond creation failed.\n");
res = rv; res = rv;
} }
goto out; } else if (command[0] == '-') {
} struct net_device *bond_dev;
if (command[0] == '-') {
rtnl_lock(); rtnl_lock();
bond_dev = bond_get_by_name(ifname);
list_for_each_entry(bond, &bond_dev_list, bond_list) if (bond_dev) {
if (strnicmp(bond->dev->name, ifname, IFNAMSIZ) == 0) { pr_info(DRV_NAME ": %s is being deleted...\n",
pr_info(DRV_NAME ifname);
": %s is being deleted...\n", unregister_netdevice(bond_dev);
bond->dev->name); } else {
unregister_netdevice(bond->dev); pr_err(DRV_NAME ": unable to delete non-existent %s\n",
goto out_unlock; ifname);
}
pr_err(DRV_NAME
": unable to delete non-existent bond %s\n", ifname);
res = -ENODEV; res = -ENODEV;
goto out_unlock;
} }
err_no_cmd:
pr_err(DRV_NAME ": no command found in bonding_masters."
" Use +ifname or -ifname.\n");
return -EPERM;
out_unlock:
rtnl_unlock(); rtnl_unlock();
} else
goto err_no_cmd;
/* Always return either count or an error. If you return 0, you'll /* Always return either count or an error. If you return 0, you'll
* get called forever, which is bad. * get called forever, which is bad.
*/ */
out:
return res; return res;
err_no_cmd:
pr_err(DRV_NAME ": no command found in bonding_masters."
" Use +ifname or -ifname.\n");
return -EPERM;
} }
/* class attribute for bond_masters file. This ends up in /sys/class/net */ /* class attribute for bond_masters file. This ends up in /sys/class/net */
static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO, static CLASS_ATTR(bonding_masters, S_IWUSR | S_IRUGO,
bonding_show_bonds, bonding_store_bonds); bonding_show_bonds, bonding_store_bonds);
...@@ -233,29 +237,16 @@ static ssize_t bonding_store_slaves(struct device *d, ...@@ -233,29 +237,16 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Got a slave name in ifname. Is it already in the list? */ /* Got a slave name in ifname. Is it already in the list? */
found = 0; found = 0;
read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0) {
pr_err(DRV_NAME
": %s: Interface %s is already enslaved!\n",
bond->dev->name, ifname);
ret = -EPERM;
read_unlock(&bond->lock);
goto out;
}
read_unlock(&bond->lock); /* FIXME: get netns from sysfs object */
pr_info(DRV_NAME ": %s: Adding slave %s.\n", dev = __dev_get_by_name(&init_net, ifname);
bond->dev->name, ifname);
dev = dev_get_by_name(&init_net, ifname);
if (!dev) { if (!dev) {
pr_info(DRV_NAME pr_info(DRV_NAME
": %s: Interface %s does not exist!\n", ": %s: Interface %s does not exist!\n",
bond->dev->name, ifname); bond->dev->name, ifname);
ret = -EPERM; ret = -ENODEV;
goto out; goto out;
} else }
dev_put(dev);
if (dev->flags & IFF_UP) { if (dev->flags & IFF_UP) {
pr_err(DRV_NAME pr_err(DRV_NAME
...@@ -265,6 +256,22 @@ static ssize_t bonding_store_slaves(struct device *d, ...@@ -265,6 +256,22 @@ static ssize_t bonding_store_slaves(struct device *d,
ret = -EPERM; ret = -EPERM;
goto out; goto out;
} }
read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i)
if (slave->dev == dev) {
pr_err(DRV_NAME
": %s: Interface %s is already enslaved!\n",
bond->dev->name, ifname);
ret = -EPERM;
read_unlock(&bond->lock);
goto out;
}
read_unlock(&bond->lock);
pr_info(DRV_NAME ": %s: Adding slave %s.\n",
bond->dev->name, ifname);
/* If this is the first slave, then we need to set /* If this is the first slave, then we need to set
the master's hardware address to be the same as the the master's hardware address to be the same as the
slave's. */ slave's. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment