From fcfdc53703ed48f775ec550eb52473537a504cc5 Mon Sep 17 00:00:00 2001 From: Alexandre Derumier Date: Mon, 20 Aug 2012 21:10:38 +0200 Subject: [PATCH] rhel6.3 bonding vlan fixes Signed-off-by: Alexandre Derumier --- Makefile | 2 + rhel63-vlan-bonding-failover-fix.patch | 144 +++++++++++++++++++++++++ rhel63-vlan-bonding-fix.patch | 89 +++++++++++++++ 3 files changed, 235 insertions(+) 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 +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 +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 +--- + 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 + -- 2.39.5