Hi, Previously, I posted a patch that prevented the bonding driver from receiving duplicate packets. (https://sourceforge.net/mailarchive/forum.php?thread_id=9398718&forum_id=2094)
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(). When I posted this patch to the bonding-devel, I got response that this patch's methodology is ok. However, I change dev.c:skb_bond() besides the code in the bonding driver. So, I want to fix this patch if there are some problems in this modification method, before the 2.6.16 kernel is released. Do you find anything inconvenient in this patch? I welcome any comments. -- Kenzo Iwami ([EMAIL PROTECTED]) Signed-off-by: Kenzo Iwami <[EMAIL PROTECTED]> diff -urpN linux-2.6.16-rc4/drivers/net/bonding/bond_main.c linux-2.6.16-rc4_fix/drivers/net/bonding/bond_main.c --- linux-2.6.16-rc4/drivers/net/bonding/bond_main.c 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/drivers/net/bonding/bond_main.c 2006-02-20 16:34:41.041938803 +0900 @@ -1040,6 +1040,11 @@ void bond_change_active_slave(struct bon if ((bond->params.mode == BOND_MODE_TLB) || (bond->params.mode == BOND_MODE_ALB)) { bond_alb_handle_active_change(bond, new_active); + if (old_active) + bond_set_slave_inactive_flags(old_active); + + if (new_active) + bond_set_slave_active_flags(new_active); } else { bond->curr_active_slave = new_active; } @@ -1444,14 +1449,13 @@ int bond_enslave(struct net_device *bond switch (bond->params.mode) { case BOND_MODE_ACTIVEBACKUP: /* if we're in active-backup mode, we need one and only one active - * interface. The backup interfaces will have their NOARP flag set - * because we need them to be completely deaf and not to respond to - * any ARP request on the network to avoid fooling a switch. Thus, + * interface. The backup interfaces will have their SLAVE_INACTIVE + * flag set because we need them to be drop all packets. Thus, * since we guarantee that curr_active_slave always point to the last * usable interface, we just have to verify this interface's flag. */ if (((!bond->curr_active_slave) || - (bond->curr_active_slave->dev->flags & IFF_NOARP)) && + (bond->curr_active_slave->dev->priv_flags & IFF_SLAVE_INACTIVE)) && (new_slave->link != BOND_LINK_DOWN)) { dprintk("This is the first active slave\n"); /* first slave or no active slave yet, and this link @@ -1492,6 +1496,8 @@ int bond_enslave(struct net_device *bond * is OK, so make this interface the active one */ bond_change_active_slave(bond, new_slave); + } else { + bond_set_slave_inactive_flags(new_slave); } break; default: @@ -1724,13 +1730,7 @@ int bond_release(struct net_device *bond addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the - * IFF_NOARP flag that might have been - * set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~IFF_SLAVE_INACTIVE; kfree(slave); @@ -1816,12 +1816,7 @@ static int bond_release_all(struct net_d addr.sa_family = slave_dev->type; dev_set_mac_address(slave_dev, &addr); - /* restore the original state of the IFF_NOARP flag that might have - * been set by bond_set_slave_inactive_flags() - */ - if ((slave->original_flags & IFF_NOARP) == 0) { - slave_dev->flags &= ~IFF_NOARP; - } + slave_dev->priv_flags &= ~IFF_SLAVE_INACTIVE; kfree(slave); @@ -4061,14 +4056,17 @@ void bond_set_mode_ops(struct bonding *b bond_dev->hard_start_xmit = bond_xmit_broadcast; break; case BOND_MODE_8023AD: + bond_set_master_3ad_flags(bond); bond_dev->hard_start_xmit = bond_3ad_xmit_xor; if (bond->params.xmit_policy == BOND_XMIT_POLICY_LAYER34) bond->xmit_hash_policy = bond_xmit_hash_policy_l34; else bond->xmit_hash_policy = bond_xmit_hash_policy_l2; break; - case BOND_MODE_TLB: case BOND_MODE_ALB: + bond_set_master_rlb_flags(bond); + /* FALLTHRU */ + case BOND_MODE_TLB: bond_dev->hard_start_xmit = bond_alb_xmit; bond_dev->set_mac_address = bond_alb_set_mac_address; break; diff -urpN linux-2.6.16-rc4/drivers/net/bonding/bond_sysfs.c linux-2.6.16-rc4_fix/drivers/net/bonding/bond_sysfs.c --- linux-2.6.16-rc4/drivers/net/bonding/bond_sysfs.c 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/drivers/net/bonding/bond_sysfs.c 2006-02-20 16:35:49.596042808 +0900 @@ -424,6 +424,12 @@ static ssize_t bonding_store_mode(struct ret = -EINVAL; goto out; } else { + if (bond->params.mode == BOND_MODE_8023AD) + bond_unset_master_3ad_flags(bond); + + if (bond->params.mode == BOND_MODE_ALB) + bond_unset_master_rlb_flags(bond); + bond->params.mode = new_value; bond_set_mode_ops(bond, bond->params.mode); printk(KERN_INFO DRV_NAME ": %s: setting mode to %s (%d).\n", diff -urpN linux-2.6.16-rc4/drivers/net/bonding/bonding.h linux-2.6.16-rc4_fix/drivers/net/bonding/bonding.h --- linux-2.6.16-rc4/drivers/net/bonding/bonding.h 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/drivers/net/bonding/bonding.h 2006-02-20 16:39:57.732992078 +0900 @@ -230,14 +230,37 @@ static inline struct bonding *bond_get_b static inline void bond_set_slave_inactive_flags(struct slave *slave) { - slave->state = BOND_STATE_BACKUP; - slave->dev->flags |= IFF_NOARP; + struct bonding *bond = slave->dev->master->priv; + if (bond->params.mode != BOND_MODE_TLB && + bond->params.mode != BOND_MODE_ALB) + slave->state = BOND_STATE_BACKUP; + slave->dev->priv_flags |= IFF_SLAVE_INACTIVE; } static inline void bond_set_slave_active_flags(struct slave *slave) { slave->state = BOND_STATE_ACTIVE; - slave->dev->flags &= ~IFF_NOARP; + slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE; +} + +static inline void bond_set_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_8023AD; +} + +static inline void bond_unset_master_3ad_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_8023AD; +} + +static inline void bond_set_master_rlb_flags(struct bonding *bond) +{ + bond->dev->priv_flags |= IFF_MASTER_RLB; +} + +static inline void bond_unset_master_rlb_flags(struct bonding *bond) +{ + bond->dev->priv_flags &= ~IFF_MASTER_RLB; } struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr); diff -urpN linux-2.6.16-rc4/include/linux/if.h linux-2.6.16-rc4_fix/include/linux/if.h --- linux-2.6.16-rc4/include/linux/if.h 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/include/linux/if.h 2006-02-20 16:41:28.000000000 +0900 @@ -52,6 +52,9 @@ /* Private (from user) interface flags (netdevice->priv_flags). */ #define IFF_802_1Q_VLAN 0x1 /* 802.1Q VLAN device. */ #define IFF_EBRIDGE 0x2 /* Ethernet bridging device. */ +#define IFF_SLAVE_INACTIVE 0x4 /* Inactive slave of Bonding. */ +#define IFF_MASTER_8023AD 0x8 /* Master of Bonding in 802.3ad mode */ +#define IFF_MASTER_RLB 0x10 /* Master of Bonding in balance-alb mode */ #define IF_GET_IFACE 0x0001 /* for querying only */ #define IF_GET_PROTO 0x0002 diff -urpN linux-2.6.16-rc4/include/linux/if_ether.h linux-2.6.16-rc4_fix/include/linux/if_ether.h --- linux-2.6.16-rc4/include/linux/if_ether.h 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/include/linux/if_ether.h 2006-02-20 16:42:09.000000000 +0900 @@ -61,6 +61,7 @@ #define ETH_P_8021Q 0x8100 /* 802.1Q VLAN Extended Header */ #define ETH_P_IPX 0x8137 /* IPX over DIX */ #define ETH_P_IPV6 0x86DD /* IPv6 over bluebook */ +#define ETH_P_SLOW 0x8809 /* Slow Protocol. See 802.3ad 43B */ #define ETH_P_WCCP 0x883E /* Web-cache coordination protocol * defined in draft-wilson-wrec-wccp-v2-00.txt */ #define ETH_P_PPP_DISC 0x8863 /* PPPoE discovery messages */ diff -urpN linux-2.6.16-rc4/net/core/dev.c linux-2.6.16-rc4_fix/net/core/dev.c --- linux-2.6.16-rc4/net/core/dev.c 2006-02-18 07:23:45.000000000 +0900 +++ linux-2.6.16-rc4_fix/net/core/dev.c 2006-02-20 16:46:39.000000000 +0900 @@ -1448,8 +1448,26 @@ static inline struct net_device *skb_bon { struct net_device *dev = skb->dev; - if (dev->master) - skb->dev = dev->master; + if (dev->master) { + if (dev->master->priv_flags & IFF_MASTER_RLB) + if (skb->pkt_type != PACKET_BROADCAST && + skb->pkt_type != PACKET_MULTICAST) + goto keep; + + if (dev->priv_flags & IFF_SLAVE_INACTIVE) { + /* Slow Protocol frame must no be dropped. */ + if (dev->master->priv_flags & IFF_MASTER_8023AD && + skb->protocol == __constant_htons(ETH_P_SLOW)) + goto keep; + + dev = NULL; + kfree_skb(skb); + } + +keep: + if (dev && dev->master) + skb->dev = dev->master; + } return dev; } @@ -1593,6 +1611,9 @@ int netif_receive_skb(struct sk_buff *sk orig_dev = skb_bond(skb); + if (!orig_dev) + return NET_RX_DROP; + __get_cpu_var(netdev_rx_stat).total++; skb->h.raw = skb->nh.raw = skb->data; - To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html