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

Reply via email to