]> git.proxmox.com Git - pve-kernel-2.6.32.git/commitdiff
rhel6.3 bonding vlan fixes
authorAlexandre Derumier <aderumier@odiso.com>
Mon, 20 Aug 2012 19:10:38 +0000 (21:10 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Tue, 21 Aug 2012 06:08:03 +0000 (08:08 +0200)
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
Makefile
rhel63-vlan-bonding-failover-fix.patch [new file with mode: 0644]
rhel63-vlan-bonding-fix.patch [new file with mode: 0644]

index a037b6429e0023d5cd80a81119556d38b0da482d..3bff1a6a8b56a8c6f6531d4f21db90165cc251e0 100644 (file)
--- 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 (file)
index 0000000..ec48078
--- /dev/null
@@ -0,0 +1,144 @@
+From b0c17fb0e76a50f6845083964f42842ad5cebb41 Mon Sep 17 00:00:00 2001
+From: Neil Horman <nhorman@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 (file)
index 0000000..92b4d03
--- /dev/null
@@ -0,0 +1,89 @@
+From bf46c88fabc0787975c7ea202c9d82be4175a1fa Mon Sep 17 00:00:00 2001
+From: Neil Horman <nhorman@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@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
+