[PATCH 3/4] bonding: L2DA command IOCTL

From: Anton Nayshtut
Date: Thu Nov 21 2013 - 10:11:58 EST


L2DA command IOCTL introduction. The SIOCBONDL2DACMD is used to control L2DA
bonding logic: change default slave, add and delete map entries.

Signed-off-by: Anton Nayshtut <Anton.Nayshtut@xxxxxxxxxxxx>
Signed-off-by: Erez Kirshenbaum <Erez.Kirshenbaum@xxxxxxxxxxxx>
Signed-off-by: Boris Lapshin <Boris.Lapshin@xxxxxxxxxxxx>
---
drivers/net/bonding/bond_main.c | 52 +++++++++++++++++++++++++++++++++++++++++
include/uapi/linux/if_bonding.h | 16 +++++++++++++
include/uapi/linux/sockios.h | 1 +
net/core/dev_ioctl.c | 2 ++
net/socket.c | 2 ++
5 files changed, 73 insertions(+)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 33733be..ddaee7b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1886,6 +1886,55 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
return ret;
}

+static int bond_ioctl_l2da_cmd(struct net_device *bond_dev,
+ void __user *usr_data)
+{
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct l2da_cmd *u_l2dacmd = (struct l2da_cmd __user *)usr_data;
+ struct l2da_cmd k_l2dacmd;
+ struct net_device *slave_dev;
+ struct slave *slave;
+ int res = -EFAULT;
+
+ if (copy_from_user(&k_l2dacmd, u_l2dacmd, sizeof(struct l2da_cmd)))
+ return res;
+
+ read_lock(&bond->lock);
+
+ if (!bond_is_l2da(bond))
+ goto out;
+
+ switch (k_l2dacmd.cmd) {
+ case BOND_L2DA_CMD_SET_DEFAULT:
+ slave_dev = dev_get_by_name(dev_net(bond_dev),
+ k_l2dacmd.slave_name);
+ if (slave_dev) {
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ bond_l2da_set_default_slave(bond, slave);
+ dev_put(slave_dev);
+ res = 0;
+ }
+ break;
+ case BOND_L2DA_CMD_MAP_ADD:
+ slave_dev = dev_get_by_name(dev_net(bond_dev),
+ k_l2dacmd.slave_name);
+ if (slave_dev) {
+ slave = bond_get_slave_by_dev(bond, slave_dev);
+ res = bond_l2da_set_da_slave(bond, k_l2dacmd.da, slave);
+ dev_put(slave_dev);
+ }
+ break;
+ case BOND_L2DA_CMD_MAP_DEL:
+ res = bond_l2da_del_da(bond, k_l2dacmd.da);
+ break;
+ default:
+ break;
+ }
+out:
+ read_unlock(&bond->lock);
+ return res;
+}
+
static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
{
struct bonding *bond = netdev_priv(bond_dev);
@@ -3262,6 +3311,9 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
return -EPERM;

+ if (cmd == SIOCBONDL2DACMD)
+ return bond_ioctl_l2da_cmd(bond_dev, ifr->ifr_data);
+
slave_dev = dev_get_by_name(net, ifr->ifr_slave);

pr_debug("slave_dev=%p:\n", slave_dev);
diff --git a/include/uapi/linux/if_bonding.h b/include/uapi/linux/if_bonding.h
index b70ff3e..a4d3baf 100644
--- a/include/uapi/linux/if_bonding.h
+++ b/include/uapi/linux/if_bonding.h
@@ -95,6 +95,11 @@
#define BOND_XMIT_POLICY_ENCAP23 3 /* encapsulated layer 2+3 */
#define BOND_XMIT_POLICY_ENCAP34 4 /* encapsulated layer 3+4 */

+/* l2da commands */
+#define BOND_L2DA_CMD_SET_DEFAULT 0 /* set default slave */
+#define BOND_L2DA_CMD_MAP_ADD 1 /* add DA:iface mapping */
+#define BOND_L2DA_CMD_MAP_DEL 2 /* add DA mapping */
+
typedef struct ifbond {
__s32 bond_mode;
__s32 num_slaves;
@@ -117,6 +122,17 @@ struct ad_info {
__u8 partner_system[ETH_ALEN];
};

+struct l2da_cmd {
+ __u16 cmd; /* one of the BOND_L2DA_CMD_... commands */
+ __u8 da[ETH_ALEN]; /* Used as IN parameter in:
+ * BOND_L2DA_CMD_MAP_ADD
+ * BOND_L2DA_CMD_MAP_DEL*/
+ char slave_name[IFNAMSIZ]; /* Used as IN parameter in:
+ * BOND_L2DA_CMD_SET_DEFAULT
+ * BOND_L2DA_CMD_MAP_ADD
+ * */
+};
+
#endif /* _LINUX_IF_BONDING_H */

/*
diff --git a/include/uapi/linux/sockios.h b/include/uapi/linux/sockios.h
index 7997a50..2af055d 100644
--- a/include/uapi/linux/sockios.h
+++ b/include/uapi/linux/sockios.h
@@ -117,6 +117,7 @@
#define SIOCBONDSLAVEINFOQUERY 0x8993 /* rtn info about slave state */
#define SIOCBONDINFOQUERY 0x8994 /* rtn info about bond state */
#define SIOCBONDCHANGEACTIVE 0x8995 /* update to a new active slave */
+#define SIOCBONDL2DACMD 0x8996 /* l2da related command */

/* bridge calls */
#define SIOCBRADDBR 0x89a0 /* create new bridge device */
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 5b7d0e1..3a4716a 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -321,6 +321,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
cmd == SIOCBONDSLAVEINFOQUERY ||
cmd == SIOCBONDINFOQUERY ||
cmd == SIOCBONDCHANGEACTIVE ||
+ cmd == SIOCBONDL2DACMD ||
cmd == SIOCGMIIPHY ||
cmd == SIOCGMIIREG ||
cmd == SIOCSMIIREG ||
@@ -518,6 +519,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCBONDRELEASE:
case SIOCBONDSETHWADDR:
case SIOCBONDCHANGEACTIVE:
+ case SIOCBONDL2DACMD:
case SIOCBRADDIF:
case SIOCBRDELIF:
case SIOCSHWTSTAMP:
diff --git a/net/socket.c b/net/socket.c
index c226ace..2ed653b 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2975,6 +2975,7 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
case SIOCBONDRELEASE:
case SIOCBONDSETHWADDR:
case SIOCBONDCHANGEACTIVE:
+ case SIOCBONDL2DACMD:
if (copy_from_user(&kifr, ifr32, sizeof(struct compat_ifreq)))
return -EFAULT;

@@ -3262,6 +3263,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCBONDSLAVEINFOQUERY:
case SIOCBONDINFOQUERY:
case SIOCBONDCHANGEACTIVE:
+ case SIOCBONDL2DACMD:
return bond_ioctl(net, cmd, argp);
case SIOCADDRT:
case SIOCDELRT:
--
1.8.3.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/