lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <77EF4405DD4BB54AACCE7DB593DF6A9A9FD653@SJEXCHMB14.corp.ad.broadcom.com>
Date:	Thu, 12 Nov 2015 16:02:18 +0000
From:	Premkumar Jonnala <pjonnala@...adcom.com>
To:	"netdev@...r.kernel.org" <netdev@...r.kernel.org>
Subject: [PATCH] bonding: Offloading bonds to hardware

Packet forwarding to/from bond interfaces is done in software.

This patch enables certain platforms to bridge traffic to/from
bond interfaces in hardware.  Notifications are sent out when 
the "active" slave set for a bond interface is updated in 
software.  Platforms use the notifications to program the 
hardware accordingly.  The changes have been verified to work 
with configured and 802.3ad bond interfaces.

Signed-off-by: Premkumar Jonnala <pjonnala@...adcom.com>

---

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index b4351ca..4b53733 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3759,6 +3759,101 @@ err:
 	bond_slave_arr_work_rearm(bond, 1);
 }
 
+static int slave_present(struct slave *slave, struct bond_up_slave *arr)
+{
+	int i;
+
+	if (!arr)
+		return 0;
+
+	for (i = 0; i < arr->count; i++) {
+		if (arr->arr[i] == slave)
+			return 1;
+	}
+	return 0;
+}
+
+/* Send notification to clear/remove slaves for 'bond' in 'arr' except for
+ * slaves in 'ignore_arr'.
+ */
+static int bond_slave_arr_clear_notify(struct bonding *bond,
+				struct bond_up_slave *arr,
+				struct bond_up_slave *ignore_arr)
+{
+	struct slave *slave;
+	struct net_device *slave_dev;
+	int i, rv;
+	const struct net_device_ops *ops;
+
+	if (!bond->dev || !arr)
+		return -EINVAL;
+
+	rv = 0;
+	for (i = 0; i < arr->count; i++) {
+		slave = arr->arr[i];
+		if (!slave || !slave->dev)
+			continue;
+
+		slave_dev = slave->dev;
+		if (slave_present(slave, ignore_arr)) {
+			netdev_dbg(bond->dev, "ignoring clear of slave %s\n",
+				slave_dev->name);
+			continue;
+		}
+		ops = slave_dev->netdev_ops;
+		if (!ops || !ops->ndo_bond_slave_discard) {
+			netdev_dbg(bond->dev, "No slave discard ops for %s\n",
+				slave_dev->name);
+			continue;
+		}
+		rv = ops->ndo_bond_slave_discard(slave_dev, bond->dev);
+		if (rv < 0)
+			return rv;
+	}
+	return rv;
+}
+
+/* Send notification about updated slaves for 'bond' except for slaves in
+ * 'ignore_arr'.
+ */
+static int bond_slave_arr_set_notify(struct bonding *bond,
+				struct bond_up_slave *ignore_arr)
+{
+	struct slave *slave;
+	struct net_device *slave_dev;
+	struct bond_up_slave *arr;
+	int i, rv;
+	const struct net_device_ops *ops;
+
+	if (!bond || !bond->dev)
+		return -EINVAL;
+	rv = 0;
+
+	arr = rtnl_dereference(bond->slave_arr);
+	if (!arr)
+		return -EINVAL;
+
+	for (i = 0; i < arr->count; i++) {
+		slave = arr->arr[i];
+		slave_dev = slave->dev;
+		if (slave_present(slave, ignore_arr)) {
+			netdev_dbg(bond->dev, "ignoring add of slave %s\n",
+				slave->dev->name);
+			continue;
+		}
+		ops = slave_dev->netdev_ops;
+		if (!ops || !ops->ndo_bond_slave_add) {
+			netdev_dbg(bond->dev, "No slave add ops for %s\n",
+				slave_dev->name);
+			continue;
+		}
+		rv = ops->ndo_bond_slave_add(slave_dev, bond->dev);
+		if (rv < 0)
+			return rv;
+	}
+	return rv;
+}
+
 /* Build the usable slaves array in control path for modes that use xmit-hash
  * to determine the slave interface -
  * (a) BOND_MODE_8023AD
@@ -3771,7 +3866,7 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 {
 	struct slave *slave;
 	struct list_head *iter;
-	struct bond_up_slave *new_arr, *old_arr;
+	struct bond_up_slave *new_arr, *old_arr, *discard_arr = 0;
 	int agg_id = 0;
 	int ret = 0;
 
@@ -3786,6 +3881,12 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 		pr_err("Failed to build slave-array.\n");
 		goto out;
 	}
+	discard_arr = kzalloc(offsetof(struct bond_up_slave, arr[bond->slave_cnt]),
+			GFP_KERNEL);
+	if (!discard_arr) {
+		ret = -ENOMEM;
+		goto out;
+	}
 	if (BOND_MODE(bond) == BOND_MODE_8023AD) {
 		struct ad_info ad_info;
 
@@ -3797,6 +3898,7 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 			 */
 			old_arr = rtnl_dereference(bond->slave_arr);
 			if (old_arr) {
+				bond_slave_arr_clear_notify(bond, old_arr, 0);
 				RCU_INIT_POINTER(bond->slave_arr, NULL);
 				kfree_rcu(old_arr, rcu);
 			}
@@ -3809,8 +3911,10 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 			struct aggregator *agg;
 
 			agg = SLAVE_AD_INFO(slave)->port.aggregator;
-			if (!agg || agg->aggregator_identifier != agg_id)
+			if (!agg || agg->aggregator_identifier != agg_id) {
+				discard_arr->arr[discard_arr->count++] = slave;
 				continue;
+			}
 		}
 		if (!bond_slave_can_tx(slave))
 			continue;
@@ -3820,10 +3924,15 @@ int bond_update_slave_arr(struct bonding *bond, struct slave *skipslave)
 	}
 
 	old_arr = rtnl_dereference(bond->slave_arr);
+	bond_slave_arr_clear_notify(bond, old_arr, new_arr);
+	bond_slave_arr_clear_notify(bond, discard_arr, 0);
 	rcu_assign_pointer(bond->slave_arr, new_arr);
+	bond_slave_arr_set_notify(bond, old_arr);
 	if (old_arr)
 		kfree_rcu(old_arr, rcu);
 out:
+	if (discard_arr)
+		kfree(discard_arr);
 	if (ret != 0 && skipslave) {
 		int idx;
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 4ac653b..facc35f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1236,6 +1236,10 @@ struct net_device_ops {
 							 bool proto_down);
 	int			(*ndo_fill_metadata_dst)(struct net_device *dev,
 						       struct sk_buff *skb);
+	int		(*ndo_bond_slave_add)(struct net_device *slave_dev,
+				struct net_device *bond);
+	int		(*ndo_bond_slave_discard)(struct net_device *slave_dev,
+				struct net_device *bond);
 };
 
 /**
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ