| @@ -135,7 +135,7 @@ struct vxlan_dev { · 134 unmodified lines |
| 135 | __u16 port_max; | 135 | __u16 port_max; |
| 136 | __u8 tos; /* TOS override */ | 136 | __u8 tos; /* TOS override */ |
| 137 | __u8 ttl; | 137 | __u8 ttl; |
| 138 | u32 flags; /* VXLAN_F_* below */ | 138 | u32 flags; /* VXLAN_F_* in vxlan.h */ |
| 139 | | 139 | |
| 140 | struct work_struct sock_work; | 140 | struct work_struct sock_work; |
| 141 | struct work_struct igmp_join; | 141 | struct work_struct igmp_join; |
| @@ -150,13 +150,6 @@ struct vxlan_dev { · 8 unmodified lines |
| 150 | struct hlist_head fdb_head[FDB_HASH_SIZE]; | 150 | struct hlist_head fdb_head[FDB_HASH_SIZE]; |
| 151 | }; | 151 | }; |
| 152 | | 152 | |
| 153 | #define VXLAN_F_LEARN 0x01 | | |
| 154 | #define VXLAN_F_PROXY 0x02 | | |
| 155 | #define VXLAN_F_RSC 0x04 | | |
| 156 | #define VXLAN_F_L2MISS 0x08 | | |
| 157 | #define VXLAN_F_L3MISS 0x10 | | |
| 158 | #define VXLAN_F_IPV6 0x20 /* internal flag */ | | |
| 159 | | | |
| 160 | /* salt for hash table */ | 153 | /* salt for hash table */ |
| 161 | static u32 vxlan_salt __read_mostly; | 154 | static u32 vxlan_salt __read_mostly; |
| 162 | static struct workqueue_struct *vxlan_wq; | 155 | static struct workqueue_struct *vxlan_wq; |
| @@ -1601,18 +1594,11 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb) · 1438 unmodified lines |
| 1601 | } | 1594 | } |
| 1602 | EXPORT_SYMBOL_GPL(vxlan_src_port); | 1595 | EXPORT_SYMBOL_GPL(vxlan_src_port); |
| 1603 | | 1596 | |
| 1604 | static int handle_offloads(struct sk_buff *skb) | 1597 | static inline struct sk_buff *vxlan_handle_offloads(struct sk_buff *skb, |
| | 1598 | bool udp_csum) |
| 1605 | { | 1599 | { |
| 1606 | if (skb_is_gso(skb)) { | 1600 | int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL; |
| 1607 | int err = skb_unclone(skb, GFP_ATOMIC); | 1601 | return iptunnel_handle_offloads(skb, udp_csum, type); |
| 1608 | if (unlikely(err)) | | |
| 1609 | return err; | | |
| 1610 | | | |
| 1611 | skb_shinfo(skb)->gso_type |= SKB_GSO_UDP_TUNNEL; | | |
| 1612 | } else if (skb->ip_summed != CHECKSUM_PARTIAL) | | |
| 1613 | skb->ip_summed = CHECKSUM_NONE; | | |
| 1614 | | | |
| 1615 | return 0; | | |
| 1616 | } | 1602 | } |
| 1617 | | 1603 | |
| 1618 | #if IS_ENABLED(CONFIG_IPV6) | 1604 | #if IS_ENABLED(CONFIG_IPV6) |
| @@ -1629,10 +1615,9 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, · 10 unmodified lines |
| 1629 | int min_headroom; | 1615 | int min_headroom; |
| 1630 | int err; | 1616 | int err; |
| 1631 | | 1617 | |
| 1632 | if (!skb->encapsulation) { | 1618 | skb = vxlan_handle_offloads(skb, !udp_get_no_check6_tx(vs->sock->sk)); |
| 1633 | skb_reset_inner_headers(skb); | 1619 | if (IS_ERR(skb)) |
| 1634 | skb->encapsulation = 1; | 1620 | return -EINVAL; |
| 1635 | } | | |
| 1636 | | 1621 | |
| 1637 | skb_scrub_packet(skb, xnet); | 1622 | skb_scrub_packet(skb, xnet); |
| 1638 | | 1623 | |
| @@ -1666,27 +1651,14 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, · 27 unmodified lines |
| 1666 | uh->source = src_port; | 1651 | uh->source = src_port; |
| 1667 | | 1652 | |
| 1668 | uh->len = htons(skb->len); | 1653 | uh->len = htons(skb->len); |
| 1669 | uh->check = 0; | | |
| 1670 | | 1654 | |
| 1671 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 1655 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
| 1672 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | | 1656 | IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | |
| 1673 | IPSKB_REROUTED); | 1657 | IPSKB_REROUTED); |
| 1674 | skb_dst_set(skb, dst); | 1658 | skb_dst_set(skb, dst); |
| 1675 | | 1659 | |
| 1676 | if (!skb_is_gso(skb) && !(dst->dev->features & NETIF_F_IPV6_CSUM)) { | 1660 | udp6_set_csum(udp_get_no_check6_tx(vs->sock->sk), skb, |
| 1677 | __wsum csum = skb_checksum(skb, 0, skb->len, 0); | 1661 | saddr, daddr, skb->len); |
| 1678 | skb->ip_summed = CHECKSUM_UNNECESSARY; | | |
| 1679 | uh->check = csum_ipv6_magic(saddr, daddr, skb->len, | | |
| 1680 | IPPROTO_UDP, csum); | | |
| 1681 | if (uh->check == 0) | | |
| 1682 | uh->check = CSUM_MANGLED_0; | | |
| 1683 | } else { | | |
| 1684 | skb->ip_summed = CHECKSUM_PARTIAL; | | |
| 1685 | skb->csum_start = skb_transport_header(skb) - skb->head; | | |
| 1686 | skb->csum_offset = offsetof(struct udphdr, check); | | |
| 1687 | uh->check = ~csum_ipv6_magic(saddr, daddr, | | |
| 1688 | skb->len, IPPROTO_UDP, 0); | | |
| 1689 | } | | |
| 1690 | | 1662 | |
| 1691 | __skb_push(skb, sizeof(*ip6h)); | 1663 | __skb_push(skb, sizeof(*ip6h)); |
| 1692 | skb_reset_network_header(skb); | 1664 | skb_reset_network_header(skb); |
| @@ -1702,10 +1674,6 @@ static int vxlan6_xmit_skb(struct vxlan_sock *vs, · 9 unmodified lines |
| 1702 | ip6h->daddr = *daddr; | 1674 | ip6h->daddr = *daddr; |
| 1703 | ip6h->saddr = *saddr; | 1675 | ip6h->saddr = *saddr; |
| 1704 | | 1676 | |
| 1705 | err = handle_offloads(skb); | | |
| 1706 | if (err) | | |
| 1707 | return err; | | |
| 1708 | | | |
| 1709 | ip6tunnel_xmit(skb, dev); | 1677 | ip6tunnel_xmit(skb, dev); |
| 1710 | return 0; | 1678 | return 0; |
| 1711 | } | 1679 | } |
| @@ -1721,10 +1689,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, · 9 unmodified lines |
| 1721 | int min_headroom; | 1689 | int min_headroom; |
| 1722 | int err; | 1690 | int err; |
| 1723 | | 1691 | |
| 1724 | if (!skb->encapsulation) { | 1692 | skb = vxlan_handle_offloads(skb, !vs->sock->sk->sk_no_check_tx); |
| 1725 | skb_reset_inner_headers(skb); | 1693 | if (IS_ERR(skb)) |
| 1726 | skb->encapsulation = 1; | 1694 | return -EINVAL; |
| 1727 | } | | |
| 1728 | | 1695 | |
| 1729 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len | 1696 | min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len |
| 1730 | + VXLAN_HLEN + sizeof(struct iphdr) | 1697 | + VXLAN_HLEN + sizeof(struct iphdr) |
| @@ -1756,11 +1723,9 @@ int vxlan_xmit_skb(struct vxlan_sock *vs, · 25 unmodified lines |
| 1756 | uh->source = src_port; | 1723 | uh->source = src_port; |
| 1757 | | 1724 | |
| 1758 | uh->len = htons(skb->len); | 1725 | uh->len = htons(skb->len); |
| 1759 | uh->check = 0; | | |
| 1760 | | 1726 | |
| 1761 | err = handle_offloads(skb); | 1727 | udp_set_csum(vs->sock->sk->sk_no_check_tx, skb, |
| 1762 | if (err) | 1728 | src, dst, skb->len); |
| 1763 | return err; | | |
| 1764 | | 1729 | |
| 1765 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, | 1730 | return iptunnel_xmit(vs->sock->sk, rt, skb, src, dst, IPPROTO_UDP, |
| 1766 | tos, ttl, df, xnet); | 1731 | tos, ttl, df, xnet); |
| @@ -2405,7 +2370,7 @@ static void vxlan_del_work(struct work_struct *work) · 638 unmodified lines |
| 2405 | * could be used for both IPv4 and IPv6 communications, but | 2370 | * could be used for both IPv4 and IPv6 communications, but |
| 2406 | * users may set bindv6only=1. | 2371 | * users may set bindv6only=1. |
| 2407 | */ | 2372 | */ |
| 2408 | static struct socket *create_v6_sock(struct net *net, __be16 port) | 2373 | static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) |
| 2409 | { | 2374 | { |
| 2410 | struct sock *sk; | 2375 | struct sock *sk; |
| 2411 | struct socket *sock; | 2376 | struct socket *sock; |
| @@ -2442,18 +2407,25 @@ static struct socket *create_v6_sock(struct net *net, __be16 port) · 30 unmodified lines |
| 2442 | | 2407 | |
| 2443 | /* Disable multicast loopback */ | 2408 | /* Disable multicast loopback */ |
| 2444 | inet_sk(sk)->mc_loop = 0; | 2409 | inet_sk(sk)->mc_loop = 0; |
| | 2410 | |
| | 2411 | if (flags & VXLAN_F_UDP_ZERO_CSUM6_TX) |
| | 2412 | udp_set_no_check6_tx(sk, true); |
| | 2413 | |
| | 2414 | if (flags & VXLAN_F_UDP_ZERO_CSUM6_RX) |
| | 2415 | udp_set_no_check6_rx(sk, true); |
| | 2416 | |
| 2445 | return sock; | 2417 | return sock; |
| 2446 | } | 2418 | } |
| 2447 | | 2419 | |
| 2448 | #else | 2420 | #else |
| 2449 | | 2421 | |
| 2450 | static struct socket *create_v6_sock(struct net *net, __be16 port) | 2422 | static struct socket *create_v6_sock(struct net *net, __be16 port, u32 flags) |
| 2451 | { | 2423 | { |
| 2452 | return ERR_PTR(-EPFNOSUPPORT); | 2424 | return ERR_PTR(-EPFNOSUPPORT); |
| 2453 | } | 2425 | } |
| 2454 | #endif | 2426 | #endif |
| 2455 | | 2427 | |
| 2456 | static struct socket *create_v4_sock(struct net *net, __be16 port) | 2428 | static struct socket *create_v4_sock(struct net *net, __be16 port, u32 flags) |
| 2457 | { | 2429 | { |
| 2458 | struct sock *sk; | 2430 | struct sock *sk; |
| 2459 | struct socket *sock; | 2431 | struct socket *sock; |
| @@ -2486,18 +2458,24 @@ static struct socket *create_v4_sock(struct net *net, __be16 port) · 26 unmodified lines |
| 2486 | | 2458 | |
| 2487 | /* Disable multicast loopback */ | 2459 | /* Disable multicast loopback */ |
| 2488 | inet_sk(sk)->mc_loop = 0; | 2460 | inet_sk(sk)->mc_loop = 0; |
| | 2461 | |
| | 2462 | if (!(flags & VXLAN_F_UDP_CSUM)) |
| | 2463 | sock->sk->sk_no_check_tx = 1; |
| | 2464 | |
| 2489 | return sock; | 2465 | return sock; |
| 2490 | } | 2466 | } |
| 2491 | | 2467 | |
| 2492 | /* Create new listen socket if needed */ | 2468 | /* Create new listen socket if needed */ |
| 2493 | static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, | 2469 | static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, |
| 2494 | vxlan_rcv_t *rcv, void *data, bool ipv6) | 2470 | vxlan_rcv_t *rcv, void *data, |
| | 2471 | u32 flags) |
| 2495 | { | 2472 | { |
| 2496 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 2473 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 2497 | struct vxlan_sock *vs; | 2474 | struct vxlan_sock *vs; |
| 2498 | struct socket *sock; | 2475 | struct socket *sock; |
| 2499 | struct sock *sk; | 2476 | struct sock *sk; |
| 2500 | unsigned int h; | 2477 | unsigned int h; |
| | 2478 | bool ipv6 = !!(flags & VXLAN_F_IPV6); |
| 2501 | | 2479 | |
| 2502 | vs = kzalloc(sizeof(*vs), GFP_KERNEL); | 2480 | vs = kzalloc(sizeof(*vs), GFP_KERNEL); |
| 2503 | if (!vs) | 2481 | if (!vs) |
| @@ -2509,9 +2487,9 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, · 5 unmodified lines |
| 2509 | INIT_WORK(&vs->del_work, vxlan_del_work); | 2487 | INIT_WORK(&vs->del_work, vxlan_del_work); |
| 2510 | | 2488 | |
| 2511 | if (ipv6) | 2489 | if (ipv6) |
| 2512 | sock = create_v6_sock(net, port); | 2490 | sock = create_v6_sock(net, port, flags); |
| 2513 | else | 2491 | else |
| 2514 | sock = create_v4_sock(net, port); | 2492 | sock = create_v4_sock(net, port, flags); |
| 2515 | if (IS_ERR(sock)) { | 2493 | if (IS_ERR(sock)) { |
| 2516 | kfree(vs); | 2494 | kfree(vs); |
| 2517 | return ERR_CAST(sock); | 2495 | return ERR_CAST(sock); |
| @@ -2549,12 +2527,12 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, · 31 unmodified lines |
| 2549 | | 2527 | |
| 2550 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, | 2528 | struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, |
| 2551 | vxlan_rcv_t *rcv, void *data, | 2529 | vxlan_rcv_t *rcv, void *data, |
| 2552 | bool no_share, bool ipv6) | 2530 | bool no_share, u32 flags) |
| 2553 | { | 2531 | { |
| 2554 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 2532 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
| 2555 | struct vxlan_sock *vs; | 2533 | struct vxlan_sock *vs; |
| 2556 | | 2534 | |
| 2557 | vs = vxlan_socket_create(net, port, rcv, data, ipv6); | 2535 | vs = vxlan_socket_create(net, port, rcv, data, flags); |
| 2558 | if (!IS_ERR(vs)) | 2536 | if (!IS_ERR(vs)) |
| 2559 | return vs; | 2537 | return vs; |
| 2560 | | 2538 | |
| @@ -2587,7 +2565,7 @@ static void vxlan_sock_work(struct work_struct *work) · 26 unmodified lines |
| 2587 | __be16 port = vxlan->dst_port; | 2565 | __be16 port = vxlan->dst_port; |
| 2588 | struct vxlan_sock *nvs; | 2566 | struct vxlan_sock *nvs; |
| 2589 | | 2567 | |
| 2590 | nvs = vxlan_sock_add(net, port, vxlan_rcv, NULL, false, vxlan->flags & VXLAN_F_IPV6); | 2568 | nvs = vxlan_sock_add(net, port, vxlan_rcv, NULL, false, vxlan->flags); |
| 2591 | spin_lock(&vn->sock_lock); | 2569 | spin_lock(&vn->sock_lock); |
| 2592 | if (!IS_ERR(nvs)) | 2570 | if (!IS_ERR(nvs)) |
| 2593 | vxlan_vs_add_dev(nvs, vxlan); | 2571 | vxlan_vs_add_dev(nvs, vxlan); |
| @@ -2711,6 +2689,17 @@ static int vxlan_newlink(struct net *net, struct net_device *dev, · 117 unmodified lines |
| 2711 | if (data[IFLA_VXLAN_PORT]) | 2689 | if (data[IFLA_VXLAN_PORT]) |
| 2712 | vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); | 2690 | vxlan->dst_port = nla_get_be16(data[IFLA_VXLAN_PORT]); |
| 2713 | | 2691 | |
| | 2692 | if (data[IFLA_VXLAN_UDP_CSUM] && nla_get_u8(data[IFLA_VXLAN_UDP_CSUM])) |
| | 2693 | vxlan->flags |= VXLAN_F_UDP_CSUM; |
| | 2694 | |
| | 2695 | if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX] && |
| | 2696 | nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_TX])) |
| | 2697 | vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_TX; |
| | 2698 | |
| | 2699 | if (data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX] && |
| | 2700 | nla_get_u8(data[IFLA_VXLAN_UDP_ZERO_CSUM6_RX])) |
| | 2701 | vxlan->flags |= VXLAN_F_UDP_ZERO_CSUM6_RX; |
| | 2702 | |
| 2714 | if (vxlan_find_vni(net, vni, vxlan->dst_port)) { | 2703 | if (vxlan_find_vni(net, vni, vxlan->dst_port)) { |
| 2715 | pr_info("duplicate VNI %u\n", vni); | 2704 | pr_info("duplicate VNI %u\n", vni); |
| 2716 | return -EEXIST; | 2705 | return -EEXIST; |
| @@ -2774,7 +2763,10 @@ static size_t vxlan_get_size(const struct net_device *dev) · 57 unmodified lines |
| 2774 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ | 2763 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */ |
| 2775 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ | 2764 | nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */ |
| 2776 | nla_total_size(sizeof(struct ifla_vxlan_port_range)) + | 2765 | nla_total_size(sizeof(struct ifla_vxlan_port_range)) + |
| 2777 | nla_total_size(sizeof(__be16))+ /* IFLA_VXLAN_PORT */ | 2766 | nla_total_size(sizeof(__be16)) + /* IFLA_VXLAN_PORT */ |
| | 2767 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_CSUM */ |
| | 2768 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_TX */ |
| | 2769 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_UDP_ZERO_CSUM6_RX */ |
| 2778 | 0; | 2770 | 0; |
| 2779 | } | 2771 | } |
| 2780 | | 2772 | |
| @@ -2834,7 +2826,13 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) · 53 unmodified lines |
| 2834 | !!(vxlan->flags & VXLAN_F_L3MISS)) || | 2826 | !!(vxlan->flags & VXLAN_F_L3MISS)) || |
| 2835 | nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || | 2827 | nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) || |
| 2836 | nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax) || | 2828 | nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax) || |
| 2837 | nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->dst_port)) | 2829 | nla_put_be16(skb, IFLA_VXLAN_PORT, vxlan->dst_port) || |
| | 2830 | nla_put_u8(skb, IFLA_VXLAN_UDP_CSUM, |
| | 2831 | !!(vxlan->flags & VXLAN_F_UDP_CSUM)) || |
| | 2832 | nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, |
| | 2833 | !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) || |
| | 2834 | nla_put_u8(skb, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, |
| | 2835 | !!(vxlan->flags & VXLAN_F_UDP_ZERO_CSUM6_RX))) |
| 2838 | goto nla_put_failure; | 2836 | goto nla_put_failure; |
| 2839 | | 2837 | |
| 2840 | if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) | 2838 | if (nla_put(skb, IFLA_VXLAN_PORT_RANGE, sizeof(ports), &ports)) |