Messages in this thread Patch in this message | | | Date | Thu, 23 Jun 2005 14:34:59 +0300 | From | Garik E <> | Subject | [PATCH] 2.6.12 Ethernet bridge over bonding interfaces |
| |
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. <kiragon@gmail.com>
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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |