diff options
author | David S. Miller <davem@davemloft.net> | 2014-03-25 20:29:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-25 20:29:20 -0400 |
commit | 04f58c88542b6b351efb4eea01134eb672e22e6e (patch) | |
tree | 47bb617212f8c8951f35730e324bdc43487a01ca /drivers/net/vxlan.c | |
parent | 0fc31966035d7a540c011b6c967ce8eae1db121b (diff) | |
parent | 632b06aa2842b12c6d6a510ec080fb6ebdb38ea5 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
Documentation/devicetree/bindings/net/micrel-ks8851.txt
net/core/netpoll.c
The net/core/netpoll.c conflict is a bug fix in 'net' happening
to code which is completely removed in 'net-next'.
In micrel-ks8851.txt we simply have overlapping changes.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r-- | drivers/net/vxlan.c | 130 |
1 files changed, 116 insertions, 14 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index eb59b14d5ee0..0d862a5077ab 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -1315,6 +1315,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb) | |||
1315 | 1315 | ||
1316 | neigh_release(n); | 1316 | neigh_release(n); |
1317 | 1317 | ||
1318 | if (reply == NULL) | ||
1319 | goto out; | ||
1320 | |||
1318 | skb_reset_mac_header(reply); | 1321 | skb_reset_mac_header(reply); |
1319 | __skb_pull(reply, skb_network_offset(reply)); | 1322 | __skb_pull(reply, skb_network_offset(reply)); |
1320 | reply->ip_summed = CHECKSUM_UNNECESSARY; | 1323 | reply->ip_summed = CHECKSUM_UNNECESSARY; |
@@ -1336,15 +1339,103 @@ out: | |||
1336 | } | 1339 | } |
1337 | 1340 | ||
1338 | #if IS_ENABLED(CONFIG_IPV6) | 1341 | #if IS_ENABLED(CONFIG_IPV6) |
1342 | |||
1343 | static struct sk_buff *vxlan_na_create(struct sk_buff *request, | ||
1344 | struct neighbour *n, bool isrouter) | ||
1345 | { | ||
1346 | struct net_device *dev = request->dev; | ||
1347 | struct sk_buff *reply; | ||
1348 | struct nd_msg *ns, *na; | ||
1349 | struct ipv6hdr *pip6; | ||
1350 | u8 *daddr; | ||
1351 | int na_olen = 8; /* opt hdr + ETH_ALEN for target */ | ||
1352 | int ns_olen; | ||
1353 | int i, len; | ||
1354 | |||
1355 | if (dev == NULL) | ||
1356 | return NULL; | ||
1357 | |||
1358 | len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) + | ||
1359 | sizeof(*na) + na_olen + dev->needed_tailroom; | ||
1360 | reply = alloc_skb(len, GFP_ATOMIC); | ||
1361 | if (reply == NULL) | ||
1362 | return NULL; | ||
1363 | |||
1364 | reply->protocol = htons(ETH_P_IPV6); | ||
1365 | reply->dev = dev; | ||
1366 | skb_reserve(reply, LL_RESERVED_SPACE(request->dev)); | ||
1367 | skb_push(reply, sizeof(struct ethhdr)); | ||
1368 | skb_set_mac_header(reply, 0); | ||
1369 | |||
1370 | ns = (struct nd_msg *)skb_transport_header(request); | ||
1371 | |||
1372 | daddr = eth_hdr(request)->h_source; | ||
1373 | ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns); | ||
1374 | for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) { | ||
1375 | if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) { | ||
1376 | daddr = ns->opt + i + sizeof(struct nd_opt_hdr); | ||
1377 | break; | ||
1378 | } | ||
1379 | } | ||
1380 | |||
1381 | /* Ethernet header */ | ||
1382 | ether_addr_copy(eth_hdr(reply)->h_dest, daddr); | ||
1383 | ether_addr_copy(eth_hdr(reply)->h_source, n->ha); | ||
1384 | eth_hdr(reply)->h_proto = htons(ETH_P_IPV6); | ||
1385 | reply->protocol = htons(ETH_P_IPV6); | ||
1386 | |||
1387 | skb_pull(reply, sizeof(struct ethhdr)); | ||
1388 | skb_set_network_header(reply, 0); | ||
1389 | skb_put(reply, sizeof(struct ipv6hdr)); | ||
1390 | |||
1391 | /* IPv6 header */ | ||
1392 | |||
1393 | pip6 = ipv6_hdr(reply); | ||
1394 | memset(pip6, 0, sizeof(struct ipv6hdr)); | ||
1395 | pip6->version = 6; | ||
1396 | pip6->priority = ipv6_hdr(request)->priority; | ||
1397 | pip6->nexthdr = IPPROTO_ICMPV6; | ||
1398 | pip6->hop_limit = 255; | ||
1399 | pip6->daddr = ipv6_hdr(request)->saddr; | ||
1400 | pip6->saddr = *(struct in6_addr *)n->primary_key; | ||
1401 | |||
1402 | skb_pull(reply, sizeof(struct ipv6hdr)); | ||
1403 | skb_set_transport_header(reply, 0); | ||
1404 | |||
1405 | na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen); | ||
1406 | |||
1407 | /* Neighbor Advertisement */ | ||
1408 | memset(na, 0, sizeof(*na)+na_olen); | ||
1409 | na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; | ||
1410 | na->icmph.icmp6_router = isrouter; | ||
1411 | na->icmph.icmp6_override = 1; | ||
1412 | na->icmph.icmp6_solicited = 1; | ||
1413 | na->target = ns->target; | ||
1414 | ether_addr_copy(&na->opt[2], n->ha); | ||
1415 | na->opt[0] = ND_OPT_TARGET_LL_ADDR; | ||
1416 | na->opt[1] = na_olen >> 3; | ||
1417 | |||
1418 | na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr, | ||
1419 | &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6, | ||
1420 | csum_partial(na, sizeof(*na)+na_olen, 0)); | ||
1421 | |||
1422 | pip6->payload_len = htons(sizeof(*na)+na_olen); | ||
1423 | |||
1424 | skb_push(reply, sizeof(struct ipv6hdr)); | ||
1425 | |||
1426 | reply->ip_summed = CHECKSUM_UNNECESSARY; | ||
1427 | |||
1428 | return reply; | ||
1429 | } | ||
1430 | |||
1339 | static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) | 1431 | static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) |
1340 | { | 1432 | { |
1341 | struct vxlan_dev *vxlan = netdev_priv(dev); | 1433 | struct vxlan_dev *vxlan = netdev_priv(dev); |
1342 | struct neighbour *n; | 1434 | struct nd_msg *msg; |
1343 | union vxlan_addr ipa; | ||
1344 | const struct ipv6hdr *iphdr; | 1435 | const struct ipv6hdr *iphdr; |
1345 | const struct in6_addr *saddr, *daddr; | 1436 | const struct in6_addr *saddr, *daddr; |
1346 | struct nd_msg *msg; | 1437 | struct neighbour *n; |
1347 | struct inet6_dev *in6_dev = NULL; | 1438 | struct inet6_dev *in6_dev; |
1348 | 1439 | ||
1349 | in6_dev = __in6_dev_get(dev); | 1440 | in6_dev = __in6_dev_get(dev); |
1350 | if (!in6_dev) | 1441 | if (!in6_dev) |
@@ -1357,19 +1448,20 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) | |||
1357 | saddr = &iphdr->saddr; | 1448 | saddr = &iphdr->saddr; |
1358 | daddr = &iphdr->daddr; | 1449 | daddr = &iphdr->daddr; |
1359 | 1450 | ||
1360 | if (ipv6_addr_loopback(daddr) || | ||
1361 | ipv6_addr_is_multicast(daddr)) | ||
1362 | goto out; | ||
1363 | |||
1364 | msg = (struct nd_msg *)skb_transport_header(skb); | 1451 | msg = (struct nd_msg *)skb_transport_header(skb); |
1365 | if (msg->icmph.icmp6_code != 0 || | 1452 | if (msg->icmph.icmp6_code != 0 || |
1366 | msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) | 1453 | msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) |
1367 | goto out; | 1454 | goto out; |
1368 | 1455 | ||
1369 | n = neigh_lookup(ipv6_stub->nd_tbl, daddr, dev); | 1456 | if (ipv6_addr_loopback(daddr) || |
1457 | ipv6_addr_is_multicast(&msg->target)) | ||
1458 | goto out; | ||
1459 | |||
1460 | n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev); | ||
1370 | 1461 | ||
1371 | if (n) { | 1462 | if (n) { |
1372 | struct vxlan_fdb *f; | 1463 | struct vxlan_fdb *f; |
1464 | struct sk_buff *reply; | ||
1373 | 1465 | ||
1374 | if (!(n->nud_state & NUD_CONNECTED)) { | 1466 | if (!(n->nud_state & NUD_CONNECTED)) { |
1375 | neigh_release(n); | 1467 | neigh_release(n); |
@@ -1383,13 +1475,23 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) | |||
1383 | goto out; | 1475 | goto out; |
1384 | } | 1476 | } |
1385 | 1477 | ||
1386 | ipv6_stub->ndisc_send_na(dev, n, saddr, &msg->target, | 1478 | reply = vxlan_na_create(skb, n, |
1387 | !!in6_dev->cnf.forwarding, | 1479 | !!(f ? f->flags & NTF_ROUTER : 0)); |
1388 | true, false, false); | 1480 | |
1389 | neigh_release(n); | 1481 | neigh_release(n); |
1482 | |||
1483 | if (reply == NULL) | ||
1484 | goto out; | ||
1485 | |||
1486 | if (netif_rx_ni(reply) == NET_RX_DROP) | ||
1487 | dev->stats.rx_dropped++; | ||
1488 | |||
1390 | } else if (vxlan->flags & VXLAN_F_L3MISS) { | 1489 | } else if (vxlan->flags & VXLAN_F_L3MISS) { |
1391 | ipa.sin6.sin6_addr = *daddr; | 1490 | union vxlan_addr ipa = { |
1392 | ipa.sa.sa_family = AF_INET6; | 1491 | .sin6.sin6_addr = msg->target, |
1492 | .sa.sa_family = AF_INET6, | ||
1493 | }; | ||
1494 | |||
1393 | vxlan_ip_miss(dev, &ipa); | 1495 | vxlan_ip_miss(dev, &ipa); |
1394 | } | 1496 | } |
1395 | 1497 | ||