aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@gmail.com>2014-07-17 11:02:23 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-20 23:35:00 -0400
commit3e403a77779faf046862d91c36ef79fb4b12be9a (patch)
tree25f1b3b47eff4aa4e437d991b33f3438eed85eec /drivers/net/bonding
parent224e923cd9b001c612b7b68933264156271722f9 (diff)
bonding: make it possible to have unlimited nested upper vlans
Currently we're limited by a constant level of vlan nestings, and fail to find anything beyound that level (currently 2). To fix this - remove the limit of nestings when going through device tree, and when the end device is found - allocate the needed amount of vlan tags and return them, instead of found/not found. CC: Jay Vosburgh <j.vosburgh@gmail.com> CC: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Veaceslav Falico <vfalico@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_alb.c8
-rw-r--r--drivers/net/bonding/bond_main.c82
-rw-r--r--drivers/net/bonding/bonding.h7
3 files changed, 58 insertions, 39 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index d3c6801f101e..95dd1f58c260 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -1042,7 +1042,7 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
1042 struct bonding *bond = bond_get_bond_by_slave(slave); 1042 struct bonding *bond = bond_get_bond_by_slave(slave);
1043 struct net_device *upper; 1043 struct net_device *upper;
1044 struct list_head *iter; 1044 struct list_head *iter;
1045 struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; 1045 struct bond_vlan_tag *tags;
1046 1046
1047 /* send untagged */ 1047 /* send untagged */
1048 alb_send_lp_vid(slave, mac_addr, 0, 0); 1048 alb_send_lp_vid(slave, mac_addr, 0, 0);
@@ -1070,10 +1070,12 @@ static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[],
1070 * when strict_match is turned off. 1070 * when strict_match is turned off.
1071 */ 1071 */
1072 if (netif_is_macvlan(upper) && !strict_match) { 1072 if (netif_is_macvlan(upper) && !strict_match) {
1073 memset(tags, 0, sizeof(tags)); 1073 tags = bond_verify_device_path(bond->dev, upper, 0);
1074 bond_verify_device_path(bond->dev, upper, tags); 1074 if (IS_ERR_OR_NULL(tags))
1075 BUG();
1075 alb_send_lp_vid(slave, upper->dev_addr, 1076 alb_send_lp_vid(slave, upper->dev_addr,
1076 tags[0].vlan_proto, tags[0].vlan_id); 1077 tags[0].vlan_proto, tags[0].vlan_id);
1078 kfree(tags);
1077 } 1079 }
1078 } 1080 }
1079 rcu_read_unlock(); 1081 rcu_read_unlock();
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 14f789551616..023ec365209c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2145,7 +2145,7 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
2145 struct bond_vlan_tag *tags) 2145 struct bond_vlan_tag *tags)
2146{ 2146{
2147 struct sk_buff *skb; 2147 struct sk_buff *skb;
2148 int i; 2148 struct bond_vlan_tag *outer_tag = tags;
2149 2149
2150 netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n", 2150 netdev_dbg(slave_dev, "arp %d on slave %s: dst %pI4 src %pI4\n",
2151 arp_op, slave_dev->name, &dest_ip, &src_ip); 2151 arp_op, slave_dev->name, &dest_ip, &src_ip);
@@ -2158,30 +2158,42 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
2158 return; 2158 return;
2159 } 2159 }
2160 2160
2161 if (!tags || tags->vlan_proto == VLAN_N_VID)
2162 goto xmit;
2163
2164 tags++;
2165
2161 /* Go through all the tags backwards and add them to the packet */ 2166 /* Go through all the tags backwards and add them to the packet */
2162 for (i = BOND_MAX_VLAN_ENCAP - 1; i > 0; i--) { 2167 while (tags->vlan_proto != VLAN_N_VID) {
2163 if (!tags[i].vlan_id) 2168 if (!tags->vlan_id) {
2169 tags++;
2164 continue; 2170 continue;
2171 }
2165 2172
2166 netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n", 2173 netdev_dbg(slave_dev, "inner tag: proto %X vid %X\n",
2167 ntohs(tags[i].vlan_proto), tags[i].vlan_id); 2174 ntohs(outer_tag->vlan_proto), tags->vlan_id);
2168 skb = __vlan_put_tag(skb, tags[i].vlan_proto, 2175 skb = __vlan_put_tag(skb, tags->vlan_proto,
2169 tags[i].vlan_id); 2176 tags->vlan_id);
2170 if (!skb) { 2177 if (!skb) {
2171 net_err_ratelimited("failed to insert inner VLAN tag\n"); 2178 net_err_ratelimited("failed to insert inner VLAN tag\n");
2172 return; 2179 return;
2173 } 2180 }
2181
2182 tags++;
2174 } 2183 }
2175 /* Set the outer tag */ 2184 /* Set the outer tag */
2176 if (tags[0].vlan_id) { 2185 if (outer_tag->vlan_id) {
2177 netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n", 2186 netdev_dbg(slave_dev, "outer tag: proto %X vid %X\n",
2178 ntohs(tags[0].vlan_proto), tags[0].vlan_id); 2187 ntohs(outer_tag->vlan_proto), outer_tag->vlan_id);
2179 skb = vlan_put_tag(skb, tags[0].vlan_proto, tags[0].vlan_id); 2188 skb = vlan_put_tag(skb, outer_tag->vlan_proto,
2189 outer_tag->vlan_id);
2180 if (!skb) { 2190 if (!skb) {
2181 net_err_ratelimited("failed to insert outer VLAN tag\n"); 2191 net_err_ratelimited("failed to insert outer VLAN tag\n");
2182 return; 2192 return;
2183 } 2193 }
2184 } 2194 }
2195
2196xmit:
2185 arp_xmit(skb); 2197 arp_xmit(skb);
2186} 2198}
2187 2199
@@ -2191,46 +2203,50 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op,
2191 * When the path is validated, collect any vlan information in the 2203 * When the path is validated, collect any vlan information in the
2192 * path. 2204 * path.
2193 */ 2205 */
2194bool bond_verify_device_path(struct net_device *start_dev, 2206struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
2195 struct net_device *end_dev, 2207 struct net_device *end_dev,
2196 struct bond_vlan_tag *tags) 2208 int level)
2197{ 2209{
2210 struct bond_vlan_tag *tags;
2198 struct net_device *upper; 2211 struct net_device *upper;
2199 struct list_head *iter; 2212 struct list_head *iter;
2200 int idx;
2201 2213
2202 if (start_dev == end_dev) 2214 if (start_dev == end_dev) {
2203 return true; 2215 tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC);
2216 if (!tags)
2217 return ERR_PTR(-ENOMEM);
2218 tags[level].vlan_proto = VLAN_N_VID;
2219 return tags;
2220 }
2204 2221
2205 netdev_for_each_upper_dev_rcu(start_dev, upper, iter) { 2222 netdev_for_each_upper_dev_rcu(start_dev, upper, iter) {
2206 if (bond_verify_device_path(upper, end_dev, tags)) { 2223 tags = bond_verify_device_path(upper, end_dev, level + 1);
2207 if (is_vlan_dev(upper)) { 2224 if (IS_ERR_OR_NULL(tags)) {
2208 idx = vlan_get_encap_level(upper); 2225 if (IS_ERR(tags))
2209 if (idx >= BOND_MAX_VLAN_ENCAP) 2226 return tags;
2210 return false; 2227 continue;
2211
2212 tags[idx].vlan_proto =
2213 vlan_dev_vlan_proto(upper);
2214 tags[idx].vlan_id = vlan_dev_vlan_id(upper);
2215 }
2216 return true;
2217 } 2228 }
2229 if (is_vlan_dev(upper)) {
2230 tags[level].vlan_proto = vlan_dev_vlan_proto(upper);
2231 tags[level].vlan_id = vlan_dev_vlan_id(upper);
2232 }
2233
2234 return tags;
2218 } 2235 }
2219 2236
2220 return false; 2237 return NULL;
2221} 2238}
2222 2239
2223static void bond_arp_send_all(struct bonding *bond, struct slave *slave) 2240static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2224{ 2241{
2225 struct rtable *rt; 2242 struct rtable *rt;
2226 struct bond_vlan_tag tags[BOND_MAX_VLAN_ENCAP]; 2243 struct bond_vlan_tag *tags;
2227 __be32 *targets = bond->params.arp_targets, addr; 2244 __be32 *targets = bond->params.arp_targets, addr;
2228 int i; 2245 int i;
2229 bool ret;
2230 2246
2231 for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) { 2247 for (i = 0; i < BOND_MAX_ARP_TARGETS && targets[i]; i++) {
2232 netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]); 2248 netdev_dbg(bond->dev, "basa: target %pI4\n", &targets[i]);
2233 memset(tags, 0, sizeof(tags)); 2249 tags = NULL;
2234 2250
2235 /* Find out through which dev should the packet go */ 2251 /* Find out through which dev should the packet go */
2236 rt = ip_route_output(dev_net(bond->dev), targets[i], 0, 2252 rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
@@ -2253,10 +2269,10 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
2253 goto found; 2269 goto found;
2254 2270
2255 rcu_read_lock(); 2271 rcu_read_lock();
2256 ret = bond_verify_device_path(bond->dev, rt->dst.dev, tags); 2272 tags = bond_verify_device_path(bond->dev, rt->dst.dev, 0);
2257 rcu_read_unlock(); 2273 rcu_read_unlock();
2258 2274
2259 if (ret) 2275 if (!IS_ERR_OR_NULL(tags))
2260 goto found; 2276 goto found;
2261 2277
2262 /* Not our device - skip */ 2278 /* Not our device - skip */
@@ -2271,6 +2287,8 @@ found:
2271 ip_rt_put(rt); 2287 ip_rt_put(rt);
2272 bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i], 2288 bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
2273 addr, tags); 2289 addr, tags);
2290 if (!tags)
2291 kfree(tags);
2274 } 2292 }
2275} 2293}
2276 2294
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a85ca51eabf5..aace510d08d1 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -36,7 +36,6 @@
36 36
37#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n" 37#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
38 38
39#define BOND_MAX_VLAN_ENCAP 2
40#define BOND_MAX_ARP_TARGETS 16 39#define BOND_MAX_ARP_TARGETS 16
41 40
42#define BOND_DEFAULT_MIIMON 100 41#define BOND_DEFAULT_MIIMON 100
@@ -525,9 +524,9 @@ int bond_netlink_init(void);
525void bond_netlink_fini(void); 524void bond_netlink_fini(void);
526struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond); 525struct net_device *bond_option_active_slave_get_rcu(struct bonding *bond);
527const char *bond_slave_link_status(s8 link); 526const char *bond_slave_link_status(s8 link);
528bool bond_verify_device_path(struct net_device *start_dev, 527struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
529 struct net_device *end_dev, 528 struct net_device *end_dev,
530 struct bond_vlan_tag *tags); 529 int level);
531 530
532#ifdef CONFIG_PROC_FS 531#ifdef CONFIG_PROC_FS
533void bond_create_proc_entry(struct bonding *bond); 532void bond_create_proc_entry(struct bonding *bond);