[pve-devel] [PATCH] rhel6.3 bonding vlan fixes

Alexandre Derumier aderumier at odiso.com
Mon Aug 20 21:10:38 CEST 2012


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 Makefile                               |    2 +
 rhel63-vlan-bonding-failover-fix.patch |  144 ++++++++++++++++++++++++++++++++
 rhel63-vlan-bonding-fix.patch          |   89 ++++++++++++++++++++
 3 files changed, 235 insertions(+), 0 deletions(-)
 create mode 100644 rhel63-vlan-bonding-failover-fix.patch
 create mode 100644 rhel63-vlan-bonding-fix.patch

diff --git a/Makefile b/Makefile
index a037b64..3bff1a6 100644
--- a/Makefile
+++ b/Makefile
@@ -134,6 +134,8 @@ ${KERNEL_SRC}/README: ${KERNEL_SRC}.org/README
 	cd ${KERNEL_SRC}; patch -p1 <../bridge-patch.diff
 	cd ${KERNEL_SRC}; patch -p1 <../fix-aspm-policy.patch
 	cd ${KERNEL_SRC}; patch -p1 <../optimize-cfq-parameters.patch
+	cd ${KERNEL_SRC}; patch -p1 <../rhel63-vlan-bonding-fix.patch
+	cd ${KERNEL_SRC}; patch -p1 <../rhel63-vlan-bonding-failover-fix.patch
 	sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/'
 	touch $@
 
diff --git a/rhel63-vlan-bonding-failover-fix.patch b/rhel63-vlan-bonding-failover-fix.patch
new file mode 100644
index 0000000..ec48078
--- /dev/null
+++ b/rhel63-vlan-bonding-failover-fix.patch
@@ -0,0 +1,144 @@
+From b0c17fb0e76a50f6845083964f42842ad5cebb41 Mon Sep 17 00:00:00 2001
+From: Neil Horman <nhorman at redhat.com>
+Date: Fri, 20 Jul 2012 15:55:45 -0400
+Subject: [RHEL 6.3.Z PATCH] vlan: filter device events on bonds
+
+Since bond masters and slaves only have separate vlan groups now, the
+vlan_device_event handler has to be taught to ignore network events from slave
+devices when they're truly attached to the bond master.  We do this by looking
+up the network device of a given vide on both the slave and its master.  if they
+match, then we're processing an event for a physical device that we don't really
+care about (since the masters events are realy what we're interested in.
+
+This patch adds that comparison, and allows us to filter those slave events that
+the vlan code should ignore.
+---
+ net/8021q/vlan.c |   64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 64 insertions(+), 0 deletions(-)
+
+diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
+index ad5e2ae..cc046a1 100644
+--- a/net/8021q/vlan.c
++++ b/net/8021q/vlan.c
+@@ -439,6 +439,56 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
+ 	}
+ }
+ 
++/*
++ * Since bonding slaves have their own vlan groups now, we need
++ * to make sure that, when we process an event for a device, that its
++ * actually relevant to a particular vid.  If the bond actually owns the vid
++ * and the slave just holds a copy of it, then we need to ignore the event,
++ * because the vlan treats the bond, not the slave as its lower layer device
++ */
++static int ignore_slave_event(struct net_device *dev, int i)
++{
++	struct vlan_group *sgrp, *mgrp;
++	struct net_device *svdev, *mvdev;
++
++	/* process if this isn't a slave */
++	if (!dev->master)
++		return 0;
++
++	/* This is just a check for bonding */
++	if (!(dev->master->priv_flags & IFF_BONDING))
++		return 0;
++
++	sgrp = __vlan_find_group(dev);
++	mgrp = __vlan_find_group(dev->master);
++
++	/* process if either the slave or master doesn't have a vlan group */
++	if (!sgrp || !mgrp)
++		return 0;
++
++	svdev = vlan_group_get_device(sgrp, i);
++	mvdev = vlan_group_get_device(mgrp, i);
++
++	/* process If a vlan isn't found on either the slave or master */
++	if (!svdev || !mvdev)
++		return 0;	
++
++	/*
++ 	 * If, and only if, we have the same vlan device attached to both 
++ 	 * the slave and the master device, then we know for certain that
++ 	 * this event is comming from a slave, and that the vlan is actually
++ 	 * attached to the master.  In this case, vlan_device_event should
++ 	 * ignore the event process and not transfer the operstae, because
++ 	 * the bonds operstate won't actually change, it will just fail over
++ 	 * to another slave
++ 	 */
++	if (svdev == mvdev)
++		return 1;
++
++	return 0;
++		
++}
++
+ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 			     void *ptr)
+ {
+@@ -470,6 +520,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_CHANGE:
+ 		/* Propagate real device state to vlan devices */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -481,6 +533,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_CHANGEADDR:
+ 		/* Adjust unicast filters on underlying device */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -495,6 +549,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 
+ 	case NETDEV_CHANGEMTU:
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -509,6 +565,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_FEAT_CHANGE:
+ 		/* Propagate device features to underlying device */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -521,6 +579,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_DOWN:
+ 		/* Put all VLANs for this dev in the down state too.  */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -537,6 +597,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_UP:
+ 		/* Put all VLANs for this dev in the up state too.  */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+@@ -553,6 +615,8 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
+ 	case NETDEV_UNREGISTER:
+ 		/* Delete all VLANs for this dev. */
+ 		for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) {
++			if (ignore_slave_event(dev, i))
++				continue;
+ 			vlandev = vlan_group_get_device(grp, i);
+ 			if (!vlandev)
+ 				continue;
+-- 
+1.7.7.6
diff --git a/rhel63-vlan-bonding-fix.patch b/rhel63-vlan-bonding-fix.patch
new file mode 100644
index 0000000..92b4d03
--- /dev/null
+++ b/rhel63-vlan-bonding-fix.patch
@@ -0,0 +1,89 @@
+From bf46c88fabc0787975c7ea202c9d82be4175a1fa Mon Sep 17 00:00:00 2001
+From: Neil Horman <nhorman at redhat.com>
+Date: Mon, 25 Jun 2012 09:41:26 -0400
+Subject: [RHEL 6 PATCH] bonding: Always add vid to new slave group
+
+If a bonded device has a vid added to it, we need to unilaterally add that vid
+to the slaves now, otherwise we can't receive frames on that vid.  This happened
+to work before because the slave shared a vlan group with the bond master, but
+that is no longer the case.
+
+Signed-off-by: Neil Horman <nhorman at redhat.com>
+---
+ drivers/net/bonding/bond_main.c |   55 +++++++++++++++++++--------------------
+ 1 files changed, 27 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 23c21b5..53fb138 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -566,39 +566,38 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
+ 		struct net_device *slave_dev = slave->dev;
+ 		const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
+ 
+-		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
+-		    slave_ops->ndo_vlan_rx_add_vid) {
+ 
+-			/* We only inform the hardware of vlan 0, don't store it in the group */
+-			if (vid) {
+-				sgrp = vlan_find_group(slave->dev);
+-				if (!sgrp) {
+-					pr_err(DRV_NAME ": %s: Could not find vlan group\n",
+-						slave->dev->name);
+-					continue;
+-				}
+-
+-				/* Cant add the vid if we can't alloc storage for it */
+-				if (vlan_group_prealloc_vid(sgrp, vid)) {
+-					pr_err(DRV_NAME ": %s: Could not prealloc vid array\n",
+-						slave->dev->name);
+-					continue;
+-				}
++		/* We only inform the hardware of vlan 0, don't store it in the group */
++		if (vid) {
++			sgrp = vlan_find_group(slave->dev);
++			if (!sgrp) {
++				pr_err(DRV_NAME ": %s: Could not find vlan group\n",
++					slave->dev->name);
++				continue;
++			}
+ 
+-				/*
+-				 * If the slave already has a vlan on that vid, don't overwrite it
+-				 */
+-				if (vlan_group_get_device(sgrp, vid)) {
+-					pr_err(DRV_NAME ": %s: vid %d already exists on %s\n",
+-						bond_dev->name, vid, slave_dev->name);
+-					continue;
+-				}
++			/* Cant add the vid if we can't alloc storage for it */
++			if (vlan_group_prealloc_vid(sgrp, vid)) {
++				pr_err(DRV_NAME ": %s: Could not prealloc vid array\n",
++					slave->dev->name);
++				continue;
++			}
+ 
+-				vlan_group_set_device(sgrp, vid, vdev);
+-				sgrp->nr_vlans++;
++			/*
++			 * If the slave already has a vlan on that vid, don't overwrite it
++			 */
++			if (vlan_group_get_device(sgrp, vid)) {
++				pr_err(DRV_NAME ": %s: vid %d already exists on %s\n",
++					bond_dev->name, vid, slave_dev->name);
++				continue;
+ 			}
+-			slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid);
++
++			vlan_group_set_device(sgrp, vid, vdev);
++			sgrp->nr_vlans++;
+ 		}
++		if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
++		     slave_ops->ndo_vlan_rx_add_vid)
++			slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid);
+ 	}
+ 
+ 	res = bond_add_vlan(bond, vid);
+-- 
+1.7.7.6
+
-- 
1.7.2.5



More information about the pve-devel mailing list