From: Andy Gospodarek <gospo@redhat.com> Date: Mon, 30 Nov 2009 20:22:51 -0500 Subject: [net] bonding: allow arp_ip_targets on separate vlan from bond device Message-id: <20091130202250.GV3259@gospo.rdu.redhat.com> Patchwork-id: 21552 O-Subject: [RHEL5.4 PATCH] bonding: allow arp_ip_targets to be on a separate vlan from bond device Bugzilla: 526976 This allows a bond device to specify an arp_ip_target as a host that is not on the same vlan as the base bond device. A configuration like this, now works: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth1: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 qlen 1000 link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff 3: eth0: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 qlen 1000 link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff 8: bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff inet6 fe80::213:21ff:febe:33e9/64 scope link valid_lft forever preferred_lft forever 9: bond0.100@bond0: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc noqueue link/ether 00:13:21:be:33:e9 brd ff:ff:ff:ff:ff:ff inet 10.0.100.2/24 brd 10.0.100.255 scope global bond0.100 inet6 fe80::213:21ff:febe:33e9/64 scope link valid_lft forever preferred_lft forever Ethernet Channel Bonding Driver: v3.5.0 (November 4, 2008) Bonding Mode: fault-tolerance (active-backup) Primary Slave: None Currently Active Slave: eth1 MII Status: up MII Polling Interval (ms): 0 Up Delay (ms): 0 Down Delay (ms): 0 ARP Polling Interval (ms): 1000 ARP IP target/s (n.n.n.n form): 10.0.100.1 Slave Interface: eth1 MII Status: up Link Failure Count: 1 Permanent HW addr: 00:40:05:30:ff:30 Slave Interface: eth0 MII Status: up Link Failure Count: 0 Permanent HW addr: 00:13:21:be:33:e9 Just posted upstream: http://marc.info/?l=linux-netdev&m=125961211011723&w=2 I have tested this backport with both VLAN accelerated devices and non-accelerated devices and it works well. The reporting customer has also verified the fix. This will resolve RHBZ 526976. diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 16485ba..f708fd7 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2778,6 +2778,9 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack unsigned char *arp_ptr; __be32 sip, tip; + while (dev->priv_flags & IFF_802_1Q_VLAN) + dev = VLAN_DEV_INFO(dev)->real_dev; + if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER)) goto out; diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 2d18f2c..65f954a 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -161,6 +161,7 @@ static inline int __vlan_hwaccel_rx(struct sk_buff *skb, return NET_RX_DROP; } + skb->input_dev = skb->dev; skb->dev = grp->vlan_devices[vlan_tag & VLAN_VID_MASK]; if (skb->dev == NULL) { dev_kfree_skb_any(skb); diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 2c7a5f1..158a2ae 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -904,6 +904,7 @@ static int vlan_gro_common(struct napi_struct *napi, struct vlan_group *grp, if (skb_bond_should_drop(skb)) goto drop; + skb->input_dev = skb->dev; skb->dev = grp->vlan_devices[vlan_tci & VLAN_VID_MASK]; if (!skb->dev) diff --git a/net/core/dev.c b/net/core/dev.c index adf5434..9f5f1fa 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1886,8 +1886,8 @@ int netif_receive_skb(struct sk_buff *skb) skb->input_dev = skb->dev; null_or_orig = NULL; - orig_dev = skb->dev; - if (orig_dev->master) { + orig_dev = skb->input_dev; + if (orig_dev->master && !(skb->dev->priv_flags & IFF_802_1Q_VLAN)) { if (skb_bond_should_drop(skb)) null_or_orig = orig_dev; /* deliver only exact match */ else @@ -1962,7 +1962,7 @@ ncls: list_for_each_entry_rcu(ptype, &ptype_base[ntohs(type)&15], list) { if (ptype->type == type && (ptype->dev == null_or_orig || ptype->dev == skb->dev || - ptype->dev == orig_dev)) { + ptype->dev == orig_dev || ptype->dev == orig_dev->master)) { if (pt_prev) ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = ptype;