diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2006-02-21 19:36:44 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-03 20:58:00 -0500 |
commit | 8f903c708fcc2b579ebf16542bf6109bad593a1d (patch) | |
tree | 8fb890c05d962c2dd63f8dbc960efbd0b09802d2 | |
parent | ebe19a4ed78d4a11a7e01cdeda25f91b7f2fcb5a (diff) |
[PATCH] bonding: suppress duplicate packets
Originally submitted by Kenzo Iwami; his original description is:
The current bonding driver receives duplicate packets when broadcast/
multicast packets are sent by other devices or packets are flooded by the
switch. In this patch, new flags are added in priv_flags of net_device
structure to let the bonding driver discard duplicate packets in
dev.c:skb_bond().
Modified by Jay Vosburgh to change a define name, update some
comments, rearrange the new skb_bond() for clarity, clear all bonding
priv_flags on slave release, and update the driver version.
Signed-off-by: Kenzo Iwami <k-iwami@cj.jp.nec.com>
Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/bonding/bond_main.c | 43 | ||||
-rw-r--r-- | drivers/net/bonding/bond_sysfs.c | 6 | ||||
-rw-r--r-- | drivers/net/bonding/bonding.h | 33 | ||||
-rw-r--r-- | include/linux/if.h | 3 | ||||
-rw-r--r-- | include/linux/if_ether.h | 1 | ||||
-rw-r--r-- | net/core/dev.c | 26 |
6 files changed, 85 insertions, 27 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bcf9f17daf0d..623c87a83615 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1040,6 +1040,10 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active) | |||
1040 | if ((bond->params.mode == BOND_MODE_TLB) || | 1040 | if ((bond->params.mode == BOND_MODE_TLB) || |
1041 | (bond->params.mode == BOND_MODE_ALB)) { | 1041 | (bond->params.mode == BOND_MODE_ALB)) { |
1042 | bond_alb_handle_active_change(bond, new_active); | 1042 | bond_alb_handle_active_change(bond, new_active); |
1043 | if (old_active) | ||
1044 | bond_set_slave_inactive_flags(old_active); | ||
1045 | if (new_active) | ||
1046 | bond_set_slave_active_flags(new_active); | ||
1043 | } else { | 1047 | } else { |
1044 | bond->curr_active_slave = new_active; | 1048 | bond->curr_active_slave = new_active; |
1045 | } | 1049 | } |
@@ -1443,15 +1447,16 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1443 | 1447 | ||
1444 | switch (bond->params.mode) { | 1448 | switch (bond->params.mode) { |
1445 | case BOND_MODE_ACTIVEBACKUP: | 1449 | case BOND_MODE_ACTIVEBACKUP: |
1446 | /* if we're in active-backup mode, we need one and only one active | 1450 | /* if we're in active-backup mode, we need one and |
1447 | * interface. The backup interfaces will have their NOARP flag set | 1451 | * only one active interface. The backup interfaces |
1448 | * because we need them to be completely deaf and not to respond to | 1452 | * will have their SLAVE_INACTIVE flag set because we |
1449 | * any ARP request on the network to avoid fooling a switch. Thus, | 1453 | * need them to be drop all packets. Thus, since we |
1450 | * since we guarantee that curr_active_slave always point to the last | 1454 | * guarantee that curr_active_slave always point to |
1451 | * usable interface, we just have to verify this interface's flag. | 1455 | * the last usable interface, we just have to verify |
1456 | * this interface's flag. | ||
1452 | */ | 1457 | */ |
1453 | if (((!bond->curr_active_slave) || | 1458 | if (((!bond->curr_active_slave) || |
1454 | (bond->curr_active_slave->dev->flags & IFF_NOARP)) && | 1459 | (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && |
1455 | (new_slave->link != BOND_LINK_DOWN)) { | 1460 | (new_slave->link != BOND_LINK_DOWN)) { |
1456 | dprintk("This is the first active slave\n"); | 1461 | dprintk("This is the first active slave\n"); |
1457 | /* first slave or no active slave yet, and this link | 1462 | /* first slave or no active slave yet, and this link |
@@ -1492,6 +1497,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1492 | * is OK, so make this interface the active one | 1497 | * is OK, so make this interface the active one |
1493 | */ | 1498 | */ |
1494 | bond_change_active_slave(bond, new_slave); | 1499 | bond_change_active_slave(bond, new_slave); |
1500 | } else { | ||
1501 | bond_set_slave_inactive_flags(new_slave); | ||
1495 | } | 1502 | } |
1496 | break; | 1503 | break; |
1497 | default: | 1504 | default: |
@@ -1724,13 +1731,8 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1724 | addr.sa_family = slave_dev->type; | 1731 | addr.sa_family = slave_dev->type; |
1725 | dev_set_mac_address(slave_dev, &addr); | 1732 | dev_set_mac_address(slave_dev, &addr); |
1726 | 1733 | ||
1727 | /* restore the original state of the | 1734 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | |
1728 | * IFF_NOARP flag that might have been | 1735 | IFF_SLAVE_INACTIVE); |
1729 | * set by bond_set_slave_inactive_flags() | ||
1730 | */ | ||
1731 | if ((slave->original_flags & IFF_NOARP) == 0) { | ||
1732 | slave_dev->flags &= ~IFF_NOARP; | ||
1733 | } | ||
1734 | 1736 | ||
1735 | kfree(slave); | 1737 | kfree(slave); |
1736 | 1738 | ||
@@ -1816,12 +1818,8 @@ static int bond_release_all(struct net_device *bond_dev) | |||
1816 | addr.sa_family = slave_dev->type; | 1818 | addr.sa_family = slave_dev->type; |
1817 | dev_set_mac_address(slave_dev, &addr); | 1819 | dev_set_mac_address(slave_dev, &addr); |
1818 | 1820 | ||
1819 | /* restore the original state of the IFF_NOARP flag that might have | 1821 | slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB | |
1820 | * been set by bond_set_slave_inactive_flags() | 1822 | IFF_SLAVE_INACTIVE); |
1821 | */ | ||
1822 | if ((slave->original_flags & IFF_NOARP) == 0) { | ||
1823 | slave_dev->flags &= ~IFF_NOARP; | ||
1824 | } | ||
1825 | 1823 | ||
1826 | kfree(slave); | 1824 | kfree(slave); |
1827 | 1825 | ||
@@ -4061,14 +4059,17 @@ void bond_set_mode_ops(struct bonding *bond, int mode) | |||
4061 | bond_dev->hard_start_xmit = bond_xmit_broadcast; | 4059 | bond_dev->hard_start_xmit = bond_xmit_broadcast; |
4062 | break; | 4060 | break; |
4063 | case BOND_MODE_8023AD: | 4061 | case BOND_MODE_8023AD: |
4062 | bond_set_master_3ad_flags(bond); | ||
4064 | bond_dev->hard_start_xmit = bond_3ad_xmit_xor; | 4063 | bond_dev->hard_start_xmit = bond_3ad_xmit_xor; |
4065 | if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) | 4064 | if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) |
4066 | bond->xmit_hash_policy = bond_xmit_hash_policy_l34; | 4065 | bond->xmit_hash_policy = bond_xmit_hash_policy_l34; |
4067 | else | 4066 | else |
4068 | bond->xmit_hash_policy = bond_xmit_hash_policy_l2; | 4067 | bond->xmit_hash_policy = bond_xmit_hash_policy_l2; |
4069 | break; | 4068 | break; |
4070 | case BOND_MODE_TLB: | ||
4071 | case BOND_MODE_ALB: | 4069 | case BOND_MODE_ALB: |
4070 | bond_set_master_alb_flags(bond); | ||
4071 | /* FALLTHRU */ | ||
4072 | case BOND_MODE_TLB: | ||
4072 | bond_dev->hard_start_xmit = bond_alb_xmit; | 4073 | bond_dev->hard_start_xmit = bond_alb_xmit; |
4073 | bond_dev->set_mac_address = bond_alb_set_mac_address; | 4074 | bond_dev->set_mac_address = bond_alb_set_mac_address; |
4074 | break; | 4075 | break; |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 041bcc583557..5a9bd95884be 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -424,6 +424,12 @@ static ssize_t bonding_store_mode(struct class_device *cd, const char *buf, size | |||
424 | ret = -EINVAL; | 424 | ret = -EINVAL; |
425 | goto out; | 425 | goto out; |
426 | } else { | 426 | } else { |
427 | if (bond->params.mode == BOND_MODE_8023AD) | ||
428 | bond_unset_master_3ad_flags(bond); | ||
429 | |||
430 | if (bond->params.mode == BOND_MODE_ALB) | ||
431 | bond_unset_master_alb_flags(bond); | ||
432 | |||
427 | bond->params.mode = new_value; | 433 | bond->params.mode = new_value; |
428 | bond_set_mode_ops(bond, bond->params.mode); | 434 | bond_set_mode_ops(bond, bond->params.mode); |
429 | printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", | 435 | printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 3dd78d048c3e..ce9dc9b4e2dc 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -22,8 +22,8 @@ | |||
22 | #include "bond_3ad.h" | 22 | #include "bond_3ad.h" |
23 | #include "bond_alb.h" | 23 | #include "bond_alb.h" |
24 | 24 | ||
25 | #define DRV_VERSION "3.0.1" | 25 | #define DRV_VERSION "3.0.2" |
26 | #define DRV_RELDATE "January 9, 2006" | 26 | #define DRV_RELDATE "February 21, 2006" |
27 | #define DRV_NAME "bonding" | 27 | #define DRV_NAME "bonding" |
28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" | 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" |
29 | 29 | ||
@@ -230,14 +230,37 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave) | |||
230 | 230 | ||
231 | static inline void bond_set_slave_inactive_flags(struct slave *slave) | 231 | static inline void bond_set_slave_inactive_flags(struct slave *slave) |
232 | { | 232 | { |
233 | slave->state = BOND_STATE_BACKUP; | 233 | struct bonding *bond = slave->dev->master->priv; |
234 | slave->dev->flags |= IFF_NOARP; | 234 | if (bond->params.mode != BOND_MODE_TLB && |
235 | bond->params.mode != BOND_MODE_ALB) | ||
236 | slave->state = BOND_STATE_BACKUP; | ||
237 | slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; | ||
235 | } | 238 | } |
236 | 239 | ||
237 | static inline void bond_set_slave_active_flags(struct slave *slave) | 240 | static inline void bond_set_slave_active_flags(struct slave *slave) |
238 | { | 241 | { |
239 | slave->state = BOND_STATE_ACTIVE; | 242 | slave->state = BOND_STATE_ACTIVE; |
240 | slave->dev->flags &= ~IFF_NOARP; | 243 | slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; |
244 | } | ||
245 | |||
246 | static inline void bond_set_master_3ad_flags(struct bonding *bond) | ||
247 | { | ||
248 | bond->dev->priv_flags |= IFF_MASTER_8023AD; | ||
249 | } | ||
250 | |||
251 | static inline void bond_unset_master_3ad_flags(struct bonding *bond) | ||
252 | { | ||
253 | bond->dev->priv_flags &= ~IFF_MASTER_8023AD; | ||
254 | } | ||
255 | |||
256 | static inline void bond_set_master_alb_flags(struct bonding *bond) | ||
257 | { | ||
258 | bond->dev->priv_flags |= IFF_MASTER_ALB; | ||
259 | } | ||
260 | |||
261 | static inline void bond_unset_master_alb_flags(struct bonding *bond) | ||
262 | { | ||
263 | bond->dev->priv_flags &= ~IFF_MASTER_ALB; | ||
241 | } | 264 | } |
242 | 265 | ||
243 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); | 266 | struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); |
diff --git a/include/linux/if.h b/include/linux/if.h index ce627d9092ef..12c6f6d157c3 100644 --- a/include/linux/if.h +++ b/include/linux/if.h | |||
@@ -52,6 +52,9 @@ | |||
52 | /* Private (from user) interface flags (netdevice->priv_flags). */ | 52 | /* Private (from user) interface flags (netdevice->priv_flags). */ |
53 | #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ | 53 | #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ |
54 | #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ | 54 | #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ |
55 | #define IFF_SLAVE_INACTIVE 0x4 /* bonding slave not the curr. active */ | ||
56 | #define IFF_MASTER_8023AD 0x8 /* bonding master, 802.3ad. */ | ||
57 | #define IFF_MASTER_ALB 0x10 /* bonding master, balance-alb. */ | ||
55 | 58 | ||
56 | #define IF_GET_IFACE 0x0001 /* for querying only */ | 59 | #define IF_GET_IFACE 0x0001 /* for querying only */ |
57 | #define IF_GET_PROTO 0x0002 | 60 | #define IF_GET_PROTO 0x0002 |
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index 7a92c1ce1457..ab08f35cbc35 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h | |||
@@ -61,6 +61,7 @@ | |||
61 | #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ | 61 | #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ |
62 | #define ETH_P_IPX 0x8137 /* IPX over DIX */ | 62 | #define ETH_P_IPX 0x8137 /* IPX over DIX */ |
63 | #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ | 63 | #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ |
64 | #define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ | ||
64 | #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol | 65 | #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol |
65 | * defined in draft-wilson-wrec-wccp-v2-00.txt */ | 66 | * defined in draft-wilson-wrec-wccp-v2-00.txt */ |
66 | #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ | 67 | #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ |
diff --git a/net/core/dev.c b/net/core/dev.c index 225e38ff57c4..ef56c035d44e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1446,8 +1446,29 @@ static inline struct net_device *skb_bond(struct sk_buff *skb) | |||
1446 | { | 1446 | { |
1447 | struct net_device *dev = skb->dev; | 1447 | struct net_device *dev = skb->dev; |
1448 | 1448 | ||
1449 | if (dev->master) | 1449 | if (dev->master) { |
1450 | /* | ||
1451 | * On bonding slaves other than the currently active | ||
1452 | * slave, suppress duplicates except for 802.3ad | ||
1453 | * ETH_P_SLOW and alb non-mcast/bcast. | ||
1454 | */ | ||
1455 | if (dev->priv_flags & IFF_SLAVE_INACTIVE) { | ||
1456 | if (dev->master->priv_flags & IFF_MASTER_ALB) { | ||
1457 | if (skb->pkt_type != PACKET_BROADCAST && | ||
1458 | skb->pkt_type != PACKET_MULTICAST) | ||
1459 | goto keep; | ||
1460 | } | ||
1461 | |||
1462 | if (dev->master->priv_flags & IFF_MASTER_8023AD && | ||
1463 | skb->protocol == __constant_htons(ETH_P_SLOW)) | ||
1464 | goto keep; | ||
1465 | |||
1466 | kfree_skb(skb); | ||
1467 | return NULL; | ||
1468 | } | ||
1469 | keep: | ||
1450 | skb->dev = dev->master; | 1470 | skb->dev = dev->master; |
1471 | } | ||
1451 | 1472 | ||
1452 | return dev; | 1473 | return dev; |
1453 | } | 1474 | } |
@@ -1591,6 +1612,9 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1591 | 1612 | ||
1592 | orig_dev = skb_bond(skb); | 1613 | orig_dev = skb_bond(skb); |
1593 | 1614 | ||
1615 | if (!orig_dev) | ||
1616 | return NET_RX_DROP; | ||
1617 | |||
1594 | __get_cpu_var(netdev_rx_stat).total++; | 1618 | __get_cpu_var(netdev_rx_stat).total++; |
1595 | 1619 | ||
1596 | skb->h.raw = skb->nh.raw = skb->data; | 1620 | skb->h.raw = skb->nh.raw = skb->data; |