Skip to content

Commit fbd929f

Browse files
dingtianhongdavem330
authored andcommitted
bonding: support QinQ for bond arp interval
The bond send arp request to indicate that the slave is active, and if the bond dev is a vlan dev, it will set the vlan tag in skb to notice the vlan group, but the bond could only send a skb with 802.1q proto, not support for QinQ. So add outer tag for lower vlan tag and inner tag for upper vlan tag to support QinQ, The new skb will be consist of two vlan tag just like this: dst mac | src mac | outer vlan tag | inner vlan tag | data | ..... If We don't need QinQ, the inner vlan tag could be set to 0 and use outer vlan tag as a normal vlan group. Using "ip link" to configure the bond for QinQ and add test log: ip link add link bond0 bond0.20 type vlan proto 802.1ad id 20 ip link add link bond0.20 bond0.20.200 type vlan proto 802.1q id 200 ifconfig bond0.20 11.11.20.36/24 ifconfig bond0.20.200 11.11.200.36/24 echo +11.11.200.37 > /sys/class/net/bond0/bonding/arp_ip_target 90:e2:ba:07:4a:5c (oui Unknown) > Broadcast, ethertype 802.1Q-QinQ (0x88a8),length 50: vlan 20, p 0,ethertype 802.1Q, vlan 200, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 11.11.200.37 tell 11.11.200.36, length 28 90:e2:ba:06:f9:86 (oui Unknown) > 90:e2:ba:07:4a:5c (oui Unknown), ethertype 802.1Q-QinQ (0x88a8), length 50: vlan 20, p 0, ethertype 802.1Q, vlan 200, p 0, ethertype ARP, Ethernet (len 6), IPv4 (len 4), Reply 11.11.200.37 is-at 90:e2:ba:06:f9:86 (oui Unknown), length 28 v1->v2: remove the comment "TODO: QinQ?". Cc: Jay Vosburgh <fubar@us.ibm.com> Cc: Veaceslav Falico <vfalico@redhat.com> Cc: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 71e415e commit fbd929f

File tree

2 files changed

+50
-18
lines changed

2 files changed

+50
-18
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,12 +2124,15 @@ static bool bond_has_this_ip(struct bonding *bond, __be32 ip)
21242124
* switches in VLAN mode (especially if ports are configured as
21252125
* "native" to a VLAN) might not pass non-tagged frames.
21262126
*/
2127-
static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_ip, __be32 src_ip, unsigned short vlan_id)
2127+
static void bond_arp_send(struct net_device *slave_dev, int arp_op,
2128+
__be32 dest_ip, __be32 src_ip,
2129+
struct bond_vlan_tag *inner,
2130+
struct bond_vlan_tag *outer)
21282131
{
21292132
struct sk_buff *skb;
21302133

2131-
pr_debug("arp %d on slave %s: dst %pI4 src %pI4 vid %d\n",
2132-
arp_op, slave_dev->name, &dest_ip, &src_ip, vlan_id);
2134+
pr_debug("arp %d on slave %s: dst %pI4 src %pI4\n",
2135+
arp_op, slave_dev->name, &dest_ip, &src_ip);
21332136

21342137
skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
21352138
NULL, slave_dev->dev_addr, NULL);
@@ -2138,10 +2141,22 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
21382141
pr_err("ARP packet allocation failed\n");
21392142
return;
21402143
}
2141-
if (vlan_id) {
2142-
skb = vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_id);
2144+
if (outer->vlan_id) {
2145+
if (inner->vlan_id) {
2146+
pr_debug("inner tag: proto %X vid %X\n",
2147+
ntohs(inner->vlan_proto), inner->vlan_id);
2148+
skb = __vlan_put_tag(skb, inner->vlan_proto, inner->vlan_id);
2149+
if (!skb) {
2150+
pr_err("failed to insert inner VLAN tag\n");
2151+
return;
2152+
}
2153+
}
2154+
2155+
pr_debug("outer reg: proto %X vid %X\n",
2156+
ntohs(outer->vlan_proto), outer->vlan_id);
2157+
skb = vlan_put_tag(skb, outer->vlan_proto, outer->vlan_id);
21432158
if (!skb) {
2144-
pr_err("failed to insert VLAN tag\n");
2159+
pr_err("failed to insert outer VLAN tag\n");
21452160
return;
21462161
}
21472162
}
@@ -2154,11 +2169,16 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
21542169
struct net_device *upper, *vlan_upper;
21552170
struct list_head *iter, *vlan_iter;
21562171
struct rtable *rt;
2172+
struct bond_vlan_tag inner, outer;
21572173
__be32 *targets = bond->params.arp_targets, addr;
2158-
int i, vlan_id;
2174+
int i;
21592175

21602176
for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
21612177
pr_debug("basa: target %pI4\n", &targets[i]);
2178+
inner.vlan_proto = 0;
2179+
inner.vlan_id = 0;
2180+
outer.vlan_proto = 0;
2181+
outer.vlan_id = 0;
21622182

21632183
/* Find out through which dev should the packet go */
21642184
rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
@@ -2170,12 +2190,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
21702190
if (bond->params.arp_validate && net_ratelimit())
21712191
pr_warn("%s: no route to arp_ip_target %pI4 and arp_validate is set\n",
21722192
bond->dev->name, &targets[i]);
2173-
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 0, 0);
2193+
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 0, &inner, &outer);
21742194
continue;
21752195
}
21762196

2177-
vlan_id = 0;
2178-
21792197
/* bond device itself */
21802198
if (rt->dst.dev == bond->dev)
21812199
goto found;
@@ -2185,17 +2203,30 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
21852203
* found we verify its upper dev list, searching for the
21862204
* rt->dst.dev. If found we save the tag of the vlan and
21872205
* proceed to send the packet.
2188-
*
2189-
* TODO: QinQ?
21902206
*/
21912207
netdev_for_each_all_upper_dev_rcu(bond->dev, vlan_upper,
21922208
vlan_iter) {
21932209
if (!is_vlan_dev(vlan_upper))
21942210
continue;
2211+
2212+
if (vlan_upper == rt->dst.dev) {
2213+
outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper);
2214+
outer.vlan_id = vlan_dev_vlan_id(vlan_upper);
2215+
rcu_read_unlock();
2216+
goto found;
2217+
}
21952218
netdev_for_each_all_upper_dev_rcu(vlan_upper, upper,
21962219
iter) {
21972220
if (upper == rt->dst.dev) {
2198-
vlan_id = vlan_dev_vlan_id(vlan_upper);
2221+
/* If the upper dev is a vlan dev too,
2222+
* set the vlan tag to inner tag.
2223+
*/
2224+
if (is_vlan_dev(upper)) {
2225+
inner.vlan_proto = vlan_dev_vlan_proto(upper);
2226+
inner.vlan_id = vlan_dev_vlan_id(upper);
2227+
}
2228+
outer.vlan_proto = vlan_dev_vlan_proto(vlan_upper);
2229+
outer.vlan_id = vlan_dev_vlan_id(vlan_upper);
21992230
rcu_read_unlock();
22002231
goto found;
22012232
}
@@ -2208,10 +2239,6 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
22082239
*/
22092240
netdev_for_each_all_upper_dev_rcu(bond->dev, upper, iter) {
22102241
if (upper == rt->dst.dev) {
2211-
/* if it's a vlan - get its VID */
2212-
if (is_vlan_dev(upper))
2213-
vlan_id = vlan_dev_vlan_id(upper);
2214-
22152242
rcu_read_unlock();
22162243
goto found;
22172244
}
@@ -2230,7 +2257,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
22302257
addr = bond_confirm_addr(rt->dst.dev, targets[i], 0);
22312258
ip_rt_put(rt);
22322259
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
2233-
addr, vlan_id);
2260+
addr, &inner, &outer);
22342261
}
22352262
}
22362263

drivers/net/bonding/bonding.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,11 @@ struct bonding {
266266
#define bond_slave_get_rtnl(dev) \
267267
((struct slave *) rtnl_dereference(dev->rx_handler_data))
268268

269+
struct bond_vlan_tag {
270+
__be16 vlan_proto;
271+
unsigned short vlan_id;
272+
};
273+
269274
/**
270275
* Returns NULL if the net_device does not belong to any of the bond's slaves
271276
*

0 commit comments

Comments
 (0)