|
@@ -424,6 +424,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
|
|
{
|
|
{
|
|
unsigned short uninitialized_var(vlan_id);
|
|
unsigned short uninitialized_var(vlan_id);
|
|
|
|
|
|
|
|
+ /* Test vlan_list not vlgrp to catch and handle 802.1p tags */
|
|
if (!list_empty(&bond->vlan_list) &&
|
|
if (!list_empty(&bond->vlan_list) &&
|
|
!(slave_dev->features & NETIF_F_HW_VLAN_TX) &&
|
|
!(slave_dev->features & NETIF_F_HW_VLAN_TX) &&
|
|
vlan_get_tag(skb, &vlan_id) == 0) {
|
|
vlan_get_tag(skb, &vlan_id) == 0) {
|
|
@@ -487,7 +488,9 @@ static void bond_vlan_rx_register(struct net_device *bond_dev,
|
|
struct slave *slave;
|
|
struct slave *slave;
|
|
int i;
|
|
int i;
|
|
|
|
|
|
|
|
+ write_lock(&bond->lock);
|
|
bond->vlgrp = grp;
|
|
bond->vlgrp = grp;
|
|
|
|
+ write_unlock(&bond->lock);
|
|
|
|
|
|
bond_for_each_slave(bond, slave, i) {
|
|
bond_for_each_slave(bond, slave, i) {
|
|
struct net_device *slave_dev = slave->dev;
|
|
struct net_device *slave_dev = slave->dev;
|
|
@@ -569,7 +572,7 @@ static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *sla
|
|
|
|
|
|
write_lock_bh(&bond->lock);
|
|
write_lock_bh(&bond->lock);
|
|
|
|
|
|
- if (list_empty(&bond->vlan_list))
|
|
|
|
|
|
+ if (!bond->vlgrp)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
|
|
if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
|
|
@@ -596,7 +599,7 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
|
|
|
|
|
|
write_lock_bh(&bond->lock);
|
|
write_lock_bh(&bond->lock);
|
|
|
|
|
|
- if (list_empty(&bond->vlan_list))
|
|
|
|
|
|
+ if (!bond->vlgrp)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
|
|
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
|
|
@@ -604,6 +607,8 @@ static void bond_del_vlans_from_slave(struct bonding *bond,
|
|
goto unreg;
|
|
goto unreg;
|
|
|
|
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
|
|
+ if (!vlan->vlan_id)
|
|
|
|
+ continue;
|
|
/* Save and then restore vlan_dev in the grp array,
|
|
/* Save and then restore vlan_dev in the grp array,
|
|
* since the slave's driver might clear it.
|
|
* since the slave's driver might clear it.
|
|
*/
|
|
*/
|
|
@@ -1443,7 +1448,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
/* no need to lock since we're protected by rtnl_lock */
|
|
/* no need to lock since we're protected by rtnl_lock */
|
|
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
|
|
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
|
|
pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
|
|
pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
|
|
- if (!list_empty(&bond->vlan_list)) {
|
|
|
|
|
|
+ if (bond->vlgrp) {
|
|
pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
|
|
pr_err("%s: Error: cannot enslave VLAN challenged slave %s on VLAN enabled bond %s\n",
|
|
bond_dev->name, slave_dev->name, bond_dev->name);
|
|
bond_dev->name, slave_dev->name, bond_dev->name);
|
|
return -EPERM;
|
|
return -EPERM;
|
|
@@ -1942,7 +1947,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
|
*/
|
|
*/
|
|
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
|
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
|
|
|
|
|
- if (list_empty(&bond->vlan_list)) {
|
|
|
|
|
|
+ if (!bond->vlgrp) {
|
|
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
|
|
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
|
|
} else {
|
|
} else {
|
|
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
|
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
|
@@ -2134,9 +2139,9 @@ static int bond_release_all(struct net_device *bond_dev)
|
|
*/
|
|
*/
|
|
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
|
memset(bond_dev->dev_addr, 0, bond_dev->addr_len);
|
|
|
|
|
|
- if (list_empty(&bond->vlan_list))
|
|
|
|
|
|
+ if (!bond->vlgrp) {
|
|
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
|
|
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
|
|
- else {
|
|
|
|
|
|
+ } else {
|
|
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
|
pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
|
|
bond_dev->name, bond_dev->name);
|
|
bond_dev->name, bond_dev->name);
|
|
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
|
|
pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
|
|
@@ -2569,7 +2574,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
|
|
if (!targets[i])
|
|
if (!targets[i])
|
|
break;
|
|
break;
|
|
pr_debug("basa: target %x\n", targets[i]);
|
|
pr_debug("basa: target %x\n", targets[i]);
|
|
- if (list_empty(&bond->vlan_list)) {
|
|
|
|
|
|
+ if (!bond->vlgrp) {
|
|
pr_debug("basa: empty vlan: arp_send\n");
|
|
pr_debug("basa: empty vlan: arp_send\n");
|
|
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
|
|
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
|
|
bond->master_ip, 0);
|
|
bond->master_ip, 0);
|
|
@@ -2658,6 +2663,9 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
|
|
bond->master_ip, 0);
|
|
bond->master_ip, 0);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!bond->vlgrp)
|
|
|
|
+ return;
|
|
|
|
+
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
|
|
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
|
|
if (vlan->vlan_ip) {
|
|
if (vlan->vlan_ip) {
|
|
@@ -3590,6 +3598,8 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
|
|
}
|
|
}
|
|
|
|
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
|
|
|
|
+ if (!bond->vlgrp)
|
|
|
|
+ continue;
|
|
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
|
|
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
|
|
if (vlan_dev == event_dev) {
|
|
if (vlan_dev == event_dev) {
|
|
switch (event) {
|
|
switch (event) {
|
|
@@ -4686,6 +4696,7 @@ static void bond_work_cancel_all(struct bonding *bond)
|
|
static void bond_uninit(struct net_device *bond_dev)
|
|
static void bond_uninit(struct net_device *bond_dev)
|
|
{
|
|
{
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
|
|
+ struct vlan_entry *vlan, *tmp;
|
|
|
|
|
|
bond_netpoll_cleanup(bond_dev);
|
|
bond_netpoll_cleanup(bond_dev);
|
|
|
|
|
|
@@ -4699,6 +4710,11 @@ static void bond_uninit(struct net_device *bond_dev)
|
|
bond_remove_proc_entry(bond);
|
|
bond_remove_proc_entry(bond);
|
|
|
|
|
|
__hw_addr_flush(&bond->mc_list);
|
|
__hw_addr_flush(&bond->mc_list);
|
|
|
|
+
|
|
|
|
+ list_for_each_entry_safe(vlan, tmp, &bond->vlan_list, vlan_list) {
|
|
|
|
+ list_del(&vlan->vlan_list);
|
|
|
|
+ kfree(vlan);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
/*------------------------- Module initialization ---------------------------*/
|
|
/*------------------------- Module initialization ---------------------------*/
|