aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxlan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/vxlan.c')
-rw-r--r--drivers/net/vxlan.c133
1 files changed, 116 insertions, 17 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 026a313c2d2d..1236812c7be6 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -469,7 +469,6 @@ static inline struct hlist_head *vxlan_fdb_head(struct vxlan_dev *vxlan,
469/* Look up Ethernet address in forwarding table */ 469/* Look up Ethernet address in forwarding table */
470static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan, 470static struct vxlan_fdb *__vxlan_find_mac(struct vxlan_dev *vxlan,
471 const u8 *mac) 471 const u8 *mac)
472
473{ 472{
474 struct hlist_head *head = vxlan_fdb_head(vxlan, mac); 473 struct hlist_head *head = vxlan_fdb_head(vxlan, mac);
475 struct vxlan_fdb *f; 474 struct vxlan_fdb *f;
@@ -596,10 +595,8 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, struct sk_buff
596 NAPI_GRO_CB(p)->same_flow = 0; 595 NAPI_GRO_CB(p)->same_flow = 0;
597 continue; 596 continue;
598 } 597 }
599 goto found;
600 } 598 }
601 599
602found:
603 type = eh->h_proto; 600 type = eh->h_proto;
604 601
605 rcu_read_lock(); 602 rcu_read_lock();
@@ -1321,6 +1318,9 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
1321 1318
1322 neigh_release(n); 1319 neigh_release(n);
1323 1320
1321 if (reply == NULL)
1322 goto out;
1323
1324 skb_reset_mac_header(reply); 1324 skb_reset_mac_header(reply);
1325 __skb_pull(reply, skb_network_offset(reply)); 1325 __skb_pull(reply, skb_network_offset(reply));
1326 reply->ip_summed = CHECKSUM_UNNECESSARY; 1326 reply->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1342,15 +1342,103 @@ out:
1342} 1342}
1343 1343
1344#if IS_ENABLED(CONFIG_IPV6) 1344#if IS_ENABLED(CONFIG_IPV6)
1345
1346static struct sk_buff *vxlan_na_create(struct sk_buff *request,
1347 struct neighbour *n, bool isrouter)
1348{
1349 struct net_device *dev = request->dev;
1350 struct sk_buff *reply;
1351 struct nd_msg *ns, *na;
1352 struct ipv6hdr *pip6;
1353 u8 *daddr;
1354 int na_olen = 8; /* opt hdr + ETH_ALEN for target */
1355 int ns_olen;
1356 int i, len;
1357
1358 if (dev == NULL)
1359 return NULL;
1360
1361 len = LL_RESERVED_SPACE(dev) + sizeof(struct ipv6hdr) +
1362 sizeof(*na) + na_olen + dev->needed_tailroom;
1363 reply = alloc_skb(len, GFP_ATOMIC);
1364 if (reply == NULL)
1365 return NULL;
1366
1367 reply->protocol = htons(ETH_P_IPV6);
1368 reply->dev = dev;
1369 skb_reserve(reply, LL_RESERVED_SPACE(request->dev));
1370 skb_push(reply, sizeof(struct ethhdr));
1371 skb_set_mac_header(reply, 0);
1372
1373 ns = (struct nd_msg *)skb_transport_header(request);
1374
1375 daddr = eth_hdr(request)->h_source;
1376 ns_olen = request->len - skb_transport_offset(request) - sizeof(*ns);
1377 for (i = 0; i < ns_olen-1; i += (ns->opt[i+1]<<3)) {
1378 if (ns->opt[i] == ND_OPT_SOURCE_LL_ADDR) {
1379 daddr = ns->opt + i + sizeof(struct nd_opt_hdr);
1380 break;
1381 }
1382 }
1383
1384 /* Ethernet header */
1385 ether_addr_copy(eth_hdr(reply)->h_dest, daddr);
1386 ether_addr_copy(eth_hdr(reply)->h_source, n->ha);
1387 eth_hdr(reply)->h_proto = htons(ETH_P_IPV6);
1388 reply->protocol = htons(ETH_P_IPV6);
1389
1390 skb_pull(reply, sizeof(struct ethhdr));
1391 skb_set_network_header(reply, 0);
1392 skb_put(reply, sizeof(struct ipv6hdr));
1393
1394 /* IPv6 header */
1395
1396 pip6 = ipv6_hdr(reply);
1397 memset(pip6, 0, sizeof(struct ipv6hdr));
1398 pip6->version = 6;
1399 pip6->priority = ipv6_hdr(request)->priority;
1400 pip6->nexthdr = IPPROTO_ICMPV6;
1401 pip6->hop_limit = 255;
1402 pip6->daddr = ipv6_hdr(request)->saddr;
1403 pip6->saddr = *(struct in6_addr *)n->primary_key;
1404
1405 skb_pull(reply, sizeof(struct ipv6hdr));
1406 skb_set_transport_header(reply, 0);
1407
1408 na = (struct nd_msg *)skb_put(reply, sizeof(*na) + na_olen);
1409
1410 /* Neighbor Advertisement */
1411 memset(na, 0, sizeof(*na)+na_olen);
1412 na->icmph.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
1413 na->icmph.icmp6_router = isrouter;
1414 na->icmph.icmp6_override = 1;
1415 na->icmph.icmp6_solicited = 1;
1416 na->target = ns->target;
1417 ether_addr_copy(&na->opt[2], n->ha);
1418 na->opt[0] = ND_OPT_TARGET_LL_ADDR;
1419 na->opt[1] = na_olen >> 3;
1420
1421 na->icmph.icmp6_cksum = csum_ipv6_magic(&pip6->saddr,
1422 &pip6->daddr, sizeof(*na)+na_olen, IPPROTO_ICMPV6,
1423 csum_partial(na, sizeof(*na)+na_olen, 0));
1424
1425 pip6->payload_len = htons(sizeof(*na)+na_olen);
1426
1427 skb_push(reply, sizeof(struct ipv6hdr));
1428
1429 reply->ip_summed = CHECKSUM_UNNECESSARY;
1430
1431 return reply;
1432}
1433
1345static int neigh_reduce(struct net_device *dev, struct sk_buff *skb) 1434static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
1346{ 1435{
1347 struct vxlan_dev *vxlan = netdev_priv(dev); 1436 struct vxlan_dev *vxlan = netdev_priv(dev);
1348 struct neighbour *n; 1437 struct nd_msg *msg;
1349 union vxlan_addr ipa;
1350 const struct ipv6hdr *iphdr; 1438 const struct ipv6hdr *iphdr;
1351 const struct in6_addr *saddr, *daddr; 1439 const struct in6_addr *saddr, *daddr;
1352 struct nd_msg *msg; 1440 struct neighbour *n;
1353 struct inet6_dev *in6_dev = NULL; 1441 struct inet6_dev *in6_dev;
1354 1442
1355 in6_dev = __in6_dev_get(dev); 1443 in6_dev = __in6_dev_get(dev);
1356 if (!in6_dev) 1444 if (!in6_dev)
@@ -1363,19 +1451,20 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
1363 saddr = &iphdr->saddr; 1451 saddr = &iphdr->saddr;
1364 daddr = &iphdr->daddr; 1452 daddr = &iphdr->daddr;
1365 1453
1366 if (ipv6_addr_loopback(daddr) ||
1367 ipv6_addr_is_multicast(daddr))
1368 goto out;
1369
1370 msg = (struct nd_msg *)skb_transport_header(skb); 1454 msg = (struct nd_msg *)skb_transport_header(skb);
1371 if (msg->icmph.icmp6_code != 0 || 1455 if (msg->icmph.icmp6_code != 0 ||
1372 msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) 1456 msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION)
1373 goto out; 1457 goto out;
1374 1458
1375 n = neigh_lookup(ipv6_stub->nd_tbl, daddr, dev); 1459 if (ipv6_addr_loopback(daddr) ||
1460 ipv6_addr_is_multicast(&msg->target))
1461 goto out;
1462
1463 n = neigh_lookup(ipv6_stub->nd_tbl, &msg->target, dev);
1376 1464
1377 if (n) { 1465 if (n) {
1378 struct vxlan_fdb *f; 1466 struct vxlan_fdb *f;
1467 struct sk_buff *reply;
1379 1468
1380 if (!(n->nud_state & NUD_CONNECTED)) { 1469 if (!(n->nud_state & NUD_CONNECTED)) {
1381 neigh_release(n); 1470 neigh_release(n);
@@ -1389,13 +1478,23 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb)
1389 goto out; 1478 goto out;
1390 } 1479 }
1391 1480
1392 ipv6_stub->ndisc_send_na(dev, n, saddr, &msg->target, 1481 reply = vxlan_na_create(skb, n,
1393 !!in6_dev->cnf.forwarding, 1482 !!(f ? f->flags & NTF_ROUTER : 0));
1394 true, false, false); 1483
1395 neigh_release(n); 1484 neigh_release(n);
1485
1486 if (reply == NULL)
1487 goto out;
1488
1489 if (netif_rx_ni(reply) == NET_RX_DROP)
1490 dev->stats.rx_dropped++;
1491
1396 } else if (vxlan->flags & VXLAN_F_L3MISS) { 1492 } else if (vxlan->flags & VXLAN_F_L3MISS) {
1397 ipa.sin6.sin6_addr = *daddr; 1493 union vxlan_addr ipa = {
1398 ipa.sa.sa_family = AF_INET6; 1494 .sin6.sin6_addr = msg->target,
1495 .sa.sa_family = AF_INET6,
1496 };
1497
1399 vxlan_ip_miss(dev, &ipa); 1498 vxlan_ip_miss(dev, &ipa);
1400 } 1499 }
1401 1500