[PATCH] 2.6.12 Ethernet bridge over bonding interfaces

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ethernet bridge configured over bonding interfaces dead loops and
multiplies ethernet broadcast packets (ARP requests)
The following patch solves this problem.

Signed-off-by: Garik E. <[email protected]>


diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -605,6 +605,7 @@ static struct bond_parm_tbl bond_mode_tb
 { "802.3ad",  BOND_MODE_8023AD},
 { "balance-tlb",  BOND_MODE_TLB},
 { "balance-alb",  BOND_MODE_ALB},
+{ "bridge-active-backup", BOND_MODE_BRACBP},
 { NULL,   -1},
 };

@@ -631,6 +632,8 @@ static const char *bond_mode_name(int mo
   return "transmit load balancing";
  case BOND_MODE_ALB:
   return "adaptive load balancing";
+ case BOND_MODE_BRACBP:
+  return "bridge fault-tolerance (active-backup)";
  default:
   return "unknown";
  }
@@ -4203,6 +4206,36 @@ out:
  return 0;
 }

+static int bond_xmit_bridge(struct sk_buff *skb, struct net_device *bond_dev)
+{
+ struct bonding *bond = bond_dev->priv;
+ int res = 1;
+
+ read_lock(&bond->lock);
+
+ if (!BOND_IS_OK(bond)) {
+  goto out;
+ }
+
+ if (bond->params.mode == BOND_MODE_BRACBP) {
+  read_lock(&bond->curr_slave_lock);
+  if (bond->curr_active_slave) { /* one usable interface */
+   res = bond_dev_queue_xmit(bond, skb,
+     bond->curr_active_slave->dev);
+  }
+  read_unlock(&bond->curr_slave_lock);
+ }
+
+out:
+ if (res) {
+  /* no suitable interface, frame not sent */
+  dev_kfree_skb(skb);
+ }
+
+ read_unlock(&bond->lock);
+ return 0;
+}
+
 /*------------------------- Device initialization ---------------------------*/

 /*
@@ -4231,6 +4264,9 @@ static inline void bond_set_mode_ops(str
   bond_dev->hard_start_xmit = bond_alb_xmit;
   bond_dev->set_mac_address = bond_alb_set_mac_address;
   break;
+ case BOND_MODE_BRACBP:
+  bond_dev->hard_start_xmit = bond_xmit_bridge;
+  break;
  default:
   /* Should never happen, mode already checked */
   printk(KERN_ERR DRV_NAME
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -79,7 +79,8 @@
 #define USES_PRIMARY(mode)    \
   (((mode) == BOND_MODE_ACTIVEBACKUP) || \
    ((mode) == BOND_MODE_TLB)          || \
-   ((mode) == BOND_MODE_ALB))
+   ((mode) == BOND_MODE_ALB)          || \
+   ((mode) == BOND_MODE_BRACBP))

 /*
  * Less bad way to call ioctl from within the kernel; this needs to be
diff --git a/include/linux/if_bonding.h b/include/linux/if_bonding.h
--- a/include/linux/if_bonding.h
+++ b/include/linux/if_bonding.h
@@ -67,6 +67,7 @@
 #define BOND_MODE_8023AD        4
 #define BOND_MODE_TLB           5
 #define BOND_MODE_ALB  6 /* TLB + RLB (receive load balancing) */
+#define BOND_MODE_BRACBP 7 /* Active Backup for bridge */

 /* each slave's link has 4 states */
 #define BOND_LINK_UP    0           /* link is up and running */
diff --git a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1597,6 +1597,11 @@ static __inline__ int handle_bridge(stru
      (port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
   return 0;

+ if ((*pskb)->real_dev && !((*pskb)->real_dev->flags & IFF_PROMISC)) {
+  kfree_skb(*pskb);
+  return 1;
+ }
+
  if (*pt_prev) {
   *ret = deliver_skb(*pskb, *pt_prev);
   *pt_prev = NULL;


-------------------------------------------------------
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux