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]