aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-06-05 01:52:31 -0400
committerDavid S. Miller <davem@davemloft.net>2014-06-05 01:52:31 -0400
commit00d115fc758c6ef331553a9c6aa34b7bd79116a5 (patch)
treeca8567d5204c6b891dcf5d3e012ceb4a4f027c09
parent6579867c8b02606e101a6c511c2511b027ed3f4a (diff)
parent359a0ea9875ef4f32c8425bbe1ae348e1fd2ed2a (diff)
Merge branch 'inet_csums'
Tom Herbert says: ==================== net: Support checksum in UDP This patch series adds support for using checksums in UDP tunnels. With this it is possible that two or more checksums may be set within the same packet and we would like to do that efficiently. This series also creates some new helper functions to be used by various tunnel protocol implementations. v2: Fixed indentation in tcp_v6_send_check arguments. v3: Move udp_set_csum and udp6_set_csum to be not inlined Also have this functions call with a nocheck boolean argument instead of passing a sock structure. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/vxlan.c120
-rw-r--r--include/linux/netdev_features.h3
-rw-r--r--include/linux/skbuff.h30
-rw-r--r--include/net/gre.h5
-rw-r--r--include/net/ip6_checksum.h12
-rw-r--r--include/net/udp.h9
-rw-r--r--include/net/vxlan.h12
-rw-r--r--include/uapi/linux/if_link.h3
-rw-r--r--net/core/skbuff.c8
-rw-r--r--net/ipv4/af_inet.c2
-rw-r--r--net/ipv4/gre_demux.c3
-rw-r--r--net/ipv4/gre_offload.c10
-rw-r--r--net/ipv4/ip_tunnel_core.c8
-rw-r--r--net/ipv4/tcp_offload.c9
-rw-r--r--net/ipv4/udp.c77
-rw-r--r--net/ipv4/udp_offload.c7
-rw-r--r--net/ipv6/ip6_checksum.c38
-rw-r--r--net/ipv6/ip6_offload.c2
-rw-r--r--net/ipv6/udp_offload.c5
-rw-r--r--net/l2tp/l2tp_core.c54
-rw-r--r--net/mpls/mpls_gso.c1
-rw-r--r--net/openvswitch/vport-vxlan.c2
22 files changed, 272 insertions, 148 deletions
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index e68c8eb4ea8e..4e2caaf8b5da 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -135,7 +135,7 @@ struct vxlan_dev {
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 {
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 */
161static u32 vxlan_salt __read_mostly; 154static u32 vxlan_salt __read_mostly;
162static struct workqueue_struct *vxlan_wq; 155static struct workqueue_struct *vxlan_wq;
@@ -1601,18 +1594,11 @@ __be16 vxlan_src_port(__u16 port_min, __u16 port_max, struct sk_buff *skb)
1601} 1594}
1602EXPORT_SYMBOL_GPL(vxlan_src_port); 1595EXPORT_SYMBOL_GPL(vxlan_src_port);
1603 1596
1604static int handle_offloads(struct sk_buff *skb) 1597static 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,
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,
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,
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,
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,
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)
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 */
2408static struct socket *create_v6_sock(struct net *net, __be16 port) 2373static 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)
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
2450static struct socket *create_v6_sock(struct net *net, __be16 port) 2422static 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
2456static struct socket *create_v4_sock(struct net *net, __be16 port) 2428static 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)
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 */
2493static struct vxlan_sock *vxlan_socket_create(struct net *net, __be16 port, 2469static 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,
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,
2549 2527
2550struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, 2528struct 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)
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,
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)
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)
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))
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index c26d0ec2ef3a..e5a589435e2b 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -42,9 +42,11 @@ enum {
42 NETIF_F_TSO6_BIT, /* ... TCPv6 segmentation */ 42 NETIF_F_TSO6_BIT, /* ... TCPv6 segmentation */
43 NETIF_F_FSO_BIT, /* ... FCoE segmentation */ 43 NETIF_F_FSO_BIT, /* ... FCoE segmentation */
44 NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */ 44 NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */
45 NETIF_F_GSO_GRE_CSUM_BIT, /* ... GRE with csum with TSO */
45 NETIF_F_GSO_IPIP_BIT, /* ... IPIP tunnel with TSO */ 46 NETIF_F_GSO_IPIP_BIT, /* ... IPIP tunnel with TSO */
46 NETIF_F_GSO_SIT_BIT, /* ... SIT tunnel with TSO */ 47 NETIF_F_GSO_SIT_BIT, /* ... SIT tunnel with TSO */
47 NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ 48 NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
49 NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
48 NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */ 50 NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
49 /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ 51 /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
50 NETIF_F_GSO_MPLS_BIT, 52 NETIF_F_GSO_MPLS_BIT,
@@ -111,6 +113,7 @@ enum {
111#define NETIF_F_RXFCS __NETIF_F(RXFCS) 113#define NETIF_F_RXFCS __NETIF_F(RXFCS)
112#define NETIF_F_RXALL __NETIF_F(RXALL) 114#define NETIF_F_RXALL __NETIF_F(RXALL)
113#define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) 115#define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE)
116#define NETIF_F_GSO_GRE_CSUM __NETIF_F(GSO_GRE_CSUM)
114#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP) 117#define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP)
115#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT) 118#define NETIF_F_GSO_SIT __NETIF_F(GSO_SIT)
116#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) 119#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 7a9beeb1c458..c705808bef9c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -345,6 +345,10 @@ enum {
345 SKB_GSO_UDP_TUNNEL = 1 << 9, 345 SKB_GSO_UDP_TUNNEL = 1 << 9,
346 346
347 SKB_GSO_MPLS = 1 << 10, 347 SKB_GSO_MPLS = 1 << 10,
348
349 SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
350
351 SKB_GSO_GRE_CSUM = 1 << 12,
348}; 352};
349 353
350#if BITS_PER_LONG > 32 354#if BITS_PER_LONG > 32
@@ -567,7 +571,8 @@ struct sk_buff {
567 * headers if needed 571 * headers if needed
568 */ 572 */
569 __u8 encapsulation:1; 573 __u8 encapsulation:1;
570 /* 6/8 bit hole (depending on ndisc_nodetype presence) */ 574 __u8 encap_hdr_csum:1;
575 /* 5/7 bit hole (depending on ndisc_nodetype presence) */
571 kmemcheck_bitfield_end(flags2); 576 kmemcheck_bitfield_end(flags2);
572 577
573#if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL 578#if defined CONFIG_NET_DMA || defined CONFIG_NET_RX_BUSY_POLL
@@ -2988,6 +2993,7 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb)
2988struct skb_gso_cb { 2993struct skb_gso_cb {
2989 int mac_offset; 2994 int mac_offset;
2990 int encap_level; 2995 int encap_level;
2996 __u16 csum_start;
2991}; 2997};
2992#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb) 2998#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb)
2993 2999
@@ -3012,6 +3018,28 @@ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
3012 return 0; 3018 return 0;
3013} 3019}
3014 3020
3021/* Compute the checksum for a gso segment. First compute the checksum value
3022 * from the start of transport header to SKB_GSO_CB(skb)->csum_start, and
3023 * then add in skb->csum (checksum from csum_start to end of packet).
3024 * skb->csum and csum_start are then updated to reflect the checksum of the
3025 * resultant packet starting from the transport header-- the resultant checksum
3026 * is in the res argument (i.e. normally zero or ~ of checksum of a pseudo
3027 * header.
3028 */
3029static inline __sum16 gso_make_checksum(struct sk_buff *skb, __wsum res)
3030{
3031 int plen = SKB_GSO_CB(skb)->csum_start - skb_headroom(skb) -
3032 skb_transport_offset(skb);
3033 __u16 csum;
3034
3035 csum = csum_fold(csum_partial(skb_transport_header(skb),
3036 plen, skb->csum));
3037 skb->csum = res;
3038 SKB_GSO_CB(skb)->csum_start -= plen;
3039
3040 return csum;
3041}
3042
3015static inline bool skb_is_gso(const struct sk_buff *skb) 3043static inline bool skb_is_gso(const struct sk_buff *skb)
3016{ 3044{
3017 return skb_shinfo(skb)->gso_size; 3045 return skb_shinfo(skb)->gso_size;
diff --git a/include/net/gre.h b/include/net/gre.h
index 70046a0b0b89..b53182018743 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -37,9 +37,10 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
37 int hdr_len); 37 int hdr_len);
38 38
39static inline struct sk_buff *gre_handle_offloads(struct sk_buff *skb, 39static inline struct sk_buff *gre_handle_offloads(struct sk_buff *skb,
40 bool gre_csum) 40 bool csum)
41{ 41{
42 return iptunnel_handle_offloads(skb, gre_csum, SKB_GSO_GRE); 42 return iptunnel_handle_offloads(skb, csum,
43 csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
43} 44}
44 45
45 46
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index 8ac5c21f8456..55236cb71174 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -82,5 +82,17 @@ static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
82} 82}
83#endif 83#endif
84 84
85static inline __sum16 udp_v6_check(int len,
86 const struct in6_addr *saddr,
87 const struct in6_addr *daddr,
88 __wsum base)
89{
90 return csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, base);
91}
92
93void udp6_set_csum(bool nocheck, struct sk_buff *skb,
94 const struct in6_addr *saddr,
95 const struct in6_addr *daddr, int len);
96
85int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto); 97int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto);
86#endif 98#endif
diff --git a/include/net/udp.h b/include/net/udp.h
index 5eb86874bcd6..2ecfc6e15609 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -147,6 +147,15 @@ static inline __wsum udp_csum(struct sk_buff *skb)
147 return csum; 147 return csum;
148} 148}
149 149
150static inline __sum16 udp_v4_check(int len, __be32 saddr,
151 __be32 daddr, __wsum base)
152{
153 return csum_tcpudp_magic(saddr, daddr, len, IPPROTO_UDP, base);
154}
155
156void udp_set_csum(bool nocheck, struct sk_buff *skb,
157 __be32 saddr, __be32 daddr, int len);
158
150/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */ 159/* hash routines shared between UDPv4/6 and UDP-Litev4/6 */
151static inline void udp_lib_hash(struct sock *sk) 160static inline void udp_lib_hash(struct sock *sk)
152{ 161{
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 7bb4084b1bd0..12196ce661d9 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -24,9 +24,19 @@ struct vxlan_sock {
24 struct udp_offload udp_offloads; 24 struct udp_offload udp_offloads;
25}; 25};
26 26
27#define VXLAN_F_LEARN 0x01
28#define VXLAN_F_PROXY 0x02
29#define VXLAN_F_RSC 0x04
30#define VXLAN_F_L2MISS 0x08
31#define VXLAN_F_L3MISS 0x10
32#define VXLAN_F_IPV6 0x20
33#define VXLAN_F_UDP_CSUM 0x40
34#define VXLAN_F_UDP_ZERO_CSUM6_TX 0x80
35#define VXLAN_F_UDP_ZERO_CSUM6_RX 0x100
36
27struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port, 37struct vxlan_sock *vxlan_sock_add(struct net *net, __be16 port,
28 vxlan_rcv_t *rcv, void *data, 38 vxlan_rcv_t *rcv, void *data,
29 bool no_share, bool ipv6); 39 bool no_share, u32 flags);
30 40
31void vxlan_sock_release(struct vxlan_sock *vs); 41void vxlan_sock_release(struct vxlan_sock *vs);
32 42
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 622e7910b8cc..b38534895db5 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -319,6 +319,9 @@ enum {
319 IFLA_VXLAN_PORT, /* destination port */ 319 IFLA_VXLAN_PORT, /* destination port */
320 IFLA_VXLAN_GROUP6, 320 IFLA_VXLAN_GROUP6,
321 IFLA_VXLAN_LOCAL6, 321 IFLA_VXLAN_LOCAL6,
322 IFLA_VXLAN_UDP_CSUM,
323 IFLA_VXLAN_UDP_ZERO_CSUM6_TX,
324 IFLA_VXLAN_UDP_ZERO_CSUM6_RX,
322 __IFLA_VXLAN_MAX 325 __IFLA_VXLAN_MAX
323}; 326};
324#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) 327#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3f6c7e8be8a4..05f4bef2ce12 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2885,7 +2885,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
2885 if (unlikely(!proto)) 2885 if (unlikely(!proto))
2886 return ERR_PTR(-EINVAL); 2886 return ERR_PTR(-EINVAL);
2887 2887
2888 csum = !!can_checksum_protocol(features, proto); 2888 csum = !head_skb->encap_hdr_csum &&
2889 !!can_checksum_protocol(features, proto);
2890
2889 __skb_push(head_skb, doffset); 2891 __skb_push(head_skb, doffset);
2890 headroom = skb_headroom(head_skb); 2892 headroom = skb_headroom(head_skb);
2891 pos = skb_headlen(head_skb); 2893 pos = skb_headlen(head_skb);
@@ -2983,6 +2985,8 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
2983 nskb->csum = skb_copy_and_csum_bits(head_skb, offset, 2985 nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
2984 skb_put(nskb, len), 2986 skb_put(nskb, len),
2985 len, 0); 2987 len, 0);
2988 SKB_GSO_CB(nskb)->csum_start =
2989 skb_headroom(nskb) + offset;
2986 continue; 2990 continue;
2987 } 2991 }
2988 2992
@@ -3052,6 +3056,8 @@ perform_csum_check:
3052 nskb->csum = skb_checksum(nskb, doffset, 3056 nskb->csum = skb_checksum(nskb, doffset,
3053 nskb->len - doffset, 0); 3057 nskb->len - doffset, 0);
3054 nskb->ip_summed = CHECKSUM_NONE; 3058 nskb->ip_summed = CHECKSUM_NONE;
3059 SKB_GSO_CB(nskb)->csum_start =
3060 skb_headroom(nskb) + doffset;
3055 } 3061 }
3056 } while ((offset += len) < head_skb->len); 3062 } while ((offset += len) < head_skb->len);
3057 3063
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0e9bb08a91e4..d5e6836cf772 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1254,10 +1254,12 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1254 SKB_GSO_DODGY | 1254 SKB_GSO_DODGY |
1255 SKB_GSO_TCP_ECN | 1255 SKB_GSO_TCP_ECN |
1256 SKB_GSO_GRE | 1256 SKB_GSO_GRE |
1257 SKB_GSO_GRE_CSUM |
1257 SKB_GSO_IPIP | 1258 SKB_GSO_IPIP |
1258 SKB_GSO_SIT | 1259 SKB_GSO_SIT |
1259 SKB_GSO_TCPV6 | 1260 SKB_GSO_TCPV6 |
1260 SKB_GSO_UDP_TUNNEL | 1261 SKB_GSO_UDP_TUNNEL |
1262 SKB_GSO_UDP_TUNNEL_CSUM |
1261 SKB_GSO_MPLS | 1263 SKB_GSO_MPLS |
1262 0))) 1264 0)))
1263 goto out; 1265 goto out;
diff --git a/net/ipv4/gre_demux.c b/net/ipv4/gre_demux.c
index fbfd829f4049..4e9619bca732 100644
--- a/net/ipv4/gre_demux.c
+++ b/net/ipv4/gre_demux.c
@@ -84,7 +84,8 @@ void gre_build_header(struct sk_buff *skb, const struct tnl_ptk_info *tpi,
84 ptr--; 84 ptr--;
85 } 85 }
86 if (tpi->flags&TUNNEL_CSUM && 86 if (tpi->flags&TUNNEL_CSUM &&
87 !(skb_shinfo(skb)->gso_type & SKB_GSO_GRE)) { 87 !(skb_shinfo(skb)->gso_type &
88 (SKB_GSO_GRE|SKB_GSO_GRE_CSUM))) {
88 *ptr = 0; 89 *ptr = 0;
89 *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0, 90 *(__sum16 *)ptr = csum_fold(skb_checksum(skb, 0,
90 skb->len, 0)); 91 skb->len, 0));
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index f1d32280cb54..24deb3928b9e 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -42,6 +42,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
42 SKB_GSO_DODGY | 42 SKB_GSO_DODGY |
43 SKB_GSO_TCP_ECN | 43 SKB_GSO_TCP_ECN |
44 SKB_GSO_GRE | 44 SKB_GSO_GRE |
45 SKB_GSO_GRE_CSUM |
45 SKB_GSO_IPIP))) 46 SKB_GSO_IPIP)))
46 goto out; 47 goto out;
47 48
@@ -55,6 +56,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
55 goto out; 56 goto out;
56 57
57 csum = !!(greh->flags & GRE_CSUM); 58 csum = !!(greh->flags & GRE_CSUM);
59 if (csum)
60 skb->encap_hdr_csum = 1;
58 61
59 if (unlikely(!pskb_may_pull(skb, ghl))) 62 if (unlikely(!pskb_may_pull(skb, ghl)))
60 goto out; 63 goto out;
@@ -94,10 +97,13 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
94 } 97 }
95 } 98 }
96 99
97 greh = (struct gre_base_hdr *)(skb->data); 100 skb_reset_transport_header(skb);
101
102 greh = (struct gre_base_hdr *)
103 skb_transport_header(skb);
98 pcsum = (__be32 *)(greh + 1); 104 pcsum = (__be32 *)(greh + 1);
99 *pcsum = 0; 105 *pcsum = 0;
100 *(__sum16 *)pcsum = csum_fold(skb_checksum(skb, 0, skb->len, 0)); 106 *(__sum16 *)pcsum = gso_make_checksum(skb, 0);
101 } 107 }
102 __skb_push(skb, tnl_hlen - ghl); 108 __skb_push(skb, tnl_hlen - ghl);
103 109
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c
index 847e69cbff7e..f4c987bb7e94 100644
--- a/net/ipv4/ip_tunnel_core.c
+++ b/net/ipv4/ip_tunnel_core.c
@@ -135,6 +135,14 @@ struct sk_buff *iptunnel_handle_offloads(struct sk_buff *skb,
135 return skb; 135 return skb;
136 } 136 }
137 137
138 /* If packet is not gso and we are resolving any partial checksum,
139 * clear encapsulation flag. This allows setting CHECKSUM_PARTIAL
140 * on the outer header without confusing devices that implement
141 * NETIF_F_IP_CSUM with encapsulation.
142 */
143 if (csum_help)
144 skb->encapsulation = 0;
145
138 if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) { 146 if (skb->ip_summed == CHECKSUM_PARTIAL && csum_help) {
139 err = skb_checksum_help(skb); 147 err = skb_checksum_help(skb);
140 if (unlikely(err)) 148 if (unlikely(err))
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index b92b81718ca4..4e86c59ec7f7 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -57,10 +57,12 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
57 SKB_GSO_TCP_ECN | 57 SKB_GSO_TCP_ECN |
58 SKB_GSO_TCPV6 | 58 SKB_GSO_TCPV6 |
59 SKB_GSO_GRE | 59 SKB_GSO_GRE |
60 SKB_GSO_GRE_CSUM |
60 SKB_GSO_IPIP | 61 SKB_GSO_IPIP |
61 SKB_GSO_SIT | 62 SKB_GSO_SIT |
62 SKB_GSO_MPLS | 63 SKB_GSO_MPLS |
63 SKB_GSO_UDP_TUNNEL | 64 SKB_GSO_UDP_TUNNEL |
65 SKB_GSO_UDP_TUNNEL_CSUM |
64 0) || 66 0) ||
65 !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) 67 !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
66 goto out; 68 goto out;
@@ -97,9 +99,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
97 th->check = newcheck; 99 th->check = newcheck;
98 100
99 if (skb->ip_summed != CHECKSUM_PARTIAL) 101 if (skb->ip_summed != CHECKSUM_PARTIAL)
100 th->check = 102 th->check = gso_make_checksum(skb, ~th->check);
101 csum_fold(csum_partial(skb_transport_header(skb),
102 thlen, skb->csum));
103 103
104 seq += mss; 104 seq += mss;
105 if (copy_destructor) { 105 if (copy_destructor) {
@@ -133,8 +133,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
133 th->check = ~csum_fold((__force __wsum)((__force u32)th->check + 133 th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
134 (__force u32)delta)); 134 (__force u32)delta));
135 if (skb->ip_summed != CHECKSUM_PARTIAL) 135 if (skb->ip_summed != CHECKSUM_PARTIAL)
136 th->check = csum_fold(csum_partial(skb_transport_header(skb), 136 th->check = gso_make_checksum(skb, ~th->check);
137 thlen, skb->csum));
138out: 137out:
139 return segs; 138 return segs;
140} 139}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index e07d52b8617a..8d8c33d84c9a 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -762,6 +762,43 @@ void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst)
762} 762}
763EXPORT_SYMBOL_GPL(udp4_hwcsum); 763EXPORT_SYMBOL_GPL(udp4_hwcsum);
764 764
765/* Function to set UDP checksum for an IPv4 UDP packet. This is intended
766 * for the simple case like when setting the checksum for a UDP tunnel.
767 */
768void udp_set_csum(bool nocheck, struct sk_buff *skb,
769 __be32 saddr, __be32 daddr, int len)
770{
771 struct udphdr *uh = udp_hdr(skb);
772
773 if (nocheck)
774 uh->check = 0;
775 else if (skb_is_gso(skb))
776 uh->check = ~udp_v4_check(len, saddr, daddr, 0);
777 else if (skb_dst(skb) && skb_dst(skb)->dev &&
778 (skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
779
780 BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
781
782 skb->ip_summed = CHECKSUM_PARTIAL;
783 skb->csum_start = skb_transport_header(skb) - skb->head;
784 skb->csum_offset = offsetof(struct udphdr, check);
785 uh->check = ~udp_v4_check(len, saddr, daddr, 0);
786 } else {
787 __wsum csum;
788
789 BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
790
791 uh->check = 0;
792 csum = skb_checksum(skb, 0, len, 0);
793 uh->check = udp_v4_check(len, saddr, daddr, csum);
794 if (uh->check == 0)
795 uh->check = CSUM_MANGLED_0;
796
797 skb->ip_summed = CHECKSUM_UNNECESSARY;
798 }
799}
800EXPORT_SYMBOL(udp_set_csum);
801
765static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) 802static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4)
766{ 803{
767 struct sock *sk = skb->sk; 804 struct sock *sk = skb->sk;
@@ -2491,7 +2528,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
2491 int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); 2528 int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb);
2492 __be16 protocol = skb->protocol; 2529 __be16 protocol = skb->protocol;
2493 netdev_features_t enc_features; 2530 netdev_features_t enc_features;
2494 int outer_hlen; 2531 int udp_offset, outer_hlen;
2532 unsigned int oldlen;
2533 bool need_csum;
2534
2535 oldlen = (u16)~skb->len;
2495 2536
2496 if (unlikely(!pskb_may_pull(skb, tnl_hlen))) 2537 if (unlikely(!pskb_may_pull(skb, tnl_hlen)))
2497 goto out; 2538 goto out;
@@ -2503,6 +2544,10 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
2503 skb->mac_len = skb_inner_network_offset(skb); 2544 skb->mac_len = skb_inner_network_offset(skb);
2504 skb->protocol = htons(ETH_P_TEB); 2545 skb->protocol = htons(ETH_P_TEB);
2505 2546
2547 need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM);
2548 if (need_csum)
2549 skb->encap_hdr_csum = 1;
2550
2506 /* segment inner packet. */ 2551 /* segment inner packet. */
2507 enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); 2552 enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
2508 segs = skb_mac_gso_segment(skb, enc_features); 2553 segs = skb_mac_gso_segment(skb, enc_features);
@@ -2513,10 +2558,11 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
2513 } 2558 }
2514 2559
2515 outer_hlen = skb_tnl_header_len(skb); 2560 outer_hlen = skb_tnl_header_len(skb);
2561 udp_offset = outer_hlen - tnl_hlen;
2516 skb = segs; 2562 skb = segs;
2517 do { 2563 do {
2518 struct udphdr *uh; 2564 struct udphdr *uh;
2519 int udp_offset = outer_hlen - tnl_hlen; 2565 int len;
2520 2566
2521 skb_reset_inner_headers(skb); 2567 skb_reset_inner_headers(skb);
2522 skb->encapsulation = 1; 2568 skb->encapsulation = 1;
@@ -2527,31 +2573,20 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
2527 skb_reset_mac_header(skb); 2573 skb_reset_mac_header(skb);
2528 skb_set_network_header(skb, mac_len); 2574 skb_set_network_header(skb, mac_len);
2529 skb_set_transport_header(skb, udp_offset); 2575 skb_set_transport_header(skb, udp_offset);
2576 len = skb->len - udp_offset;
2530 uh = udp_hdr(skb); 2577 uh = udp_hdr(skb);
2531 uh->len = htons(skb->len - udp_offset); 2578 uh->len = htons(len);
2532
2533 /* csum segment if tunnel sets skb with csum. */
2534 if (protocol == htons(ETH_P_IP) && unlikely(uh->check)) {
2535 struct iphdr *iph = ip_hdr(skb);
2536 2579
2537 uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, 2580 if (need_csum) {
2538 skb->len - udp_offset, 2581 __be32 delta = htonl(oldlen + len);
2539 IPPROTO_UDP, 0);
2540 uh->check = csum_fold(skb_checksum(skb, udp_offset,
2541 skb->len - udp_offset, 0));
2542 if (uh->check == 0)
2543 uh->check = CSUM_MANGLED_0;
2544 2582
2545 } else if (protocol == htons(ETH_P_IPV6)) { 2583 uh->check = ~csum_fold((__force __wsum)
2546 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 2584 ((__force u32)uh->check +
2547 u32 len = skb->len - udp_offset; 2585 (__force u32)delta));
2586 uh->check = gso_make_checksum(skb, ~uh->check);
2548 2587
2549 uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
2550 len, IPPROTO_UDP, 0);
2551 uh->check = csum_fold(skb_checksum(skb, udp_offset, len, 0));
2552 if (uh->check == 0) 2588 if (uh->check == 0)
2553 uh->check = CSUM_MANGLED_0; 2589 uh->check = CSUM_MANGLED_0;
2554 skb->ip_summed = CHECKSUM_NONE;
2555 } 2590 }
2556 2591
2557 skb->protocol = protocol; 2592 skb->protocol = protocol;
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 88b4023ecfcf..7b1840110173 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -56,7 +56,8 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
56 __wsum csum; 56 __wsum csum;
57 57
58 if (skb->encapsulation && 58 if (skb->encapsulation &&
59 skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) { 59 (skb_shinfo(skb)->gso_type &
60 (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))) {
60 segs = skb_udp_tunnel_segment(skb, features); 61 segs = skb_udp_tunnel_segment(skb, features);
61 goto out; 62 goto out;
62 } 63 }
@@ -71,8 +72,10 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
71 72
72 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | 73 if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
73 SKB_GSO_UDP_TUNNEL | 74 SKB_GSO_UDP_TUNNEL |
75 SKB_GSO_UDP_TUNNEL_CSUM |
74 SKB_GSO_IPIP | 76 SKB_GSO_IPIP |
75 SKB_GSO_GRE | SKB_GSO_MPLS) || 77 SKB_GSO_GRE | SKB_GSO_GRE_CSUM |
78 SKB_GSO_MPLS) ||
76 !(type & (SKB_GSO_UDP)))) 79 !(type & (SKB_GSO_UDP))))
77 goto out; 80 goto out;
78 81
diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c
index da26224a5993..9a4d7322fb22 100644
--- a/net/ipv6/ip6_checksum.c
+++ b/net/ipv6/ip6_checksum.c
@@ -84,3 +84,41 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto)
84 ip6_compute_pseudo); 84 ip6_compute_pseudo);
85} 85}
86EXPORT_SYMBOL(udp6_csum_init); 86EXPORT_SYMBOL(udp6_csum_init);
87
88/* Function to set UDP checksum for an IPv6 UDP packet. This is intended
89 * for the simple case like when setting the checksum for a UDP tunnel.
90 */
91void udp6_set_csum(bool nocheck, struct sk_buff *skb,
92 const struct in6_addr *saddr,
93 const struct in6_addr *daddr, int len)
94{
95 struct udphdr *uh = udp_hdr(skb);
96
97 if (nocheck)
98 uh->check = 0;
99 else if (skb_is_gso(skb))
100 uh->check = ~udp_v6_check(len, saddr, daddr, 0);
101 else if (skb_dst(skb) && skb_dst(skb)->dev &&
102 (skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) {
103
104 BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
105
106 skb->ip_summed = CHECKSUM_PARTIAL;
107 skb->csum_start = skb_transport_header(skb) - skb->head;
108 skb->csum_offset = offsetof(struct udphdr, check);
109 uh->check = ~udp_v6_check(len, saddr, daddr, 0);
110 } else {
111 __wsum csum;
112
113 BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
114
115 uh->check = 0;
116 csum = skb_checksum(skb, 0, len, 0);
117 uh->check = udp_v6_check(len, saddr, daddr, csum);
118 if (uh->check == 0)
119 uh->check = CSUM_MANGLED_0;
120
121 skb->ip_summed = CHECKSUM_UNNECESSARY;
122 }
123}
124EXPORT_SYMBOL(udp6_set_csum);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index b2f091566f88..65eda2a8af48 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -97,9 +97,11 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
97 SKB_GSO_DODGY | 97 SKB_GSO_DODGY |
98 SKB_GSO_TCP_ECN | 98 SKB_GSO_TCP_ECN |
99 SKB_GSO_GRE | 99 SKB_GSO_GRE |
100 SKB_GSO_GRE_CSUM |
100 SKB_GSO_IPIP | 101 SKB_GSO_IPIP |
101 SKB_GSO_SIT | 102 SKB_GSO_SIT |
102 SKB_GSO_UDP_TUNNEL | 103 SKB_GSO_UDP_TUNNEL |
104 SKB_GSO_UDP_TUNNEL_CSUM |
103 SKB_GSO_MPLS | 105 SKB_GSO_MPLS |
104 SKB_GSO_TCPV6 | 106 SKB_GSO_TCPV6 |
105 0))) 107 0)))
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index b261ee8b83fc..0ae3d98f83e0 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -63,7 +63,9 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
63 if (unlikely(type & ~(SKB_GSO_UDP | 63 if (unlikely(type & ~(SKB_GSO_UDP |
64 SKB_GSO_DODGY | 64 SKB_GSO_DODGY |
65 SKB_GSO_UDP_TUNNEL | 65 SKB_GSO_UDP_TUNNEL |
66 SKB_GSO_UDP_TUNNEL_CSUM |
66 SKB_GSO_GRE | 67 SKB_GSO_GRE |
68 SKB_GSO_GRE_CSUM |
67 SKB_GSO_IPIP | 69 SKB_GSO_IPIP |
68 SKB_GSO_SIT | 70 SKB_GSO_SIT |
69 SKB_GSO_MPLS) || 71 SKB_GSO_MPLS) ||
@@ -76,7 +78,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
76 goto out; 78 goto out;
77 } 79 }
78 80
79 if (skb->encapsulation && skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL) 81 if (skb->encapsulation && skb_shinfo(skb)->gso_type &
82 (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM))
80 segs = skb_udp_tunnel_segment(skb, features); 83 segs = skb_udp_tunnel_segment(skb, features);
81 else { 84 else {
82 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot 85 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index 379558014b60..bea259043205 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1095,33 +1095,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
1095 return 0; 1095 return 0;
1096} 1096}
1097 1097
1098#if IS_ENABLED(CONFIG_IPV6)
1099static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb,
1100 int udp_len)
1101{
1102 struct ipv6_pinfo *np = inet6_sk(sk);
1103 struct udphdr *uh = udp_hdr(skb);
1104
1105 if (udp_get_no_check6_tx(sk))
1106 skb->ip_summed = CHECKSUM_NONE;
1107 else if (!skb_dst(skb) || !skb_dst(skb)->dev ||
1108 !(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) {
1109 __wsum csum = skb_checksum(skb, 0, udp_len, 0);
1110 skb->ip_summed = CHECKSUM_UNNECESSARY;
1111 uh->check = csum_ipv6_magic(&np->saddr, &sk->sk_v6_daddr, udp_len,
1112 IPPROTO_UDP, csum);
1113 if (uh->check == 0)
1114 uh->check = CSUM_MANGLED_0;
1115 } else {
1116 skb->ip_summed = CHECKSUM_PARTIAL;
1117 skb->csum_start = skb_transport_header(skb) - skb->head;
1118 skb->csum_offset = offsetof(struct udphdr, check);
1119 uh->check = ~csum_ipv6_magic(&np->saddr, &sk->sk_v6_daddr,
1120 udp_len, IPPROTO_UDP, 0);
1121 }
1122}
1123#endif
1124
1125/* If caller requires the skb to have a ppp header, the header must be 1098/* If caller requires the skb to have a ppp header, the header must be
1126 * inserted in the skb data before calling this function. 1099 * inserted in the skb data before calling this function.
1127 */ 1100 */
@@ -1133,7 +1106,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
1133 struct flowi *fl; 1106 struct flowi *fl;
1134 struct udphdr *uh; 1107 struct udphdr *uh;
1135 struct inet_sock *inet; 1108 struct inet_sock *inet;
1136 __wsum csum;
1137 int headroom; 1109 int headroom;
1138 int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0; 1110 int uhlen = (tunnel->encap == L2TP_ENCAPTYPE_UDP) ? sizeof(struct udphdr) : 0;
1139 int udp_len; 1111 int udp_len;
@@ -1182,33 +1154,17 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
1182 uh->dest = inet->inet_dport; 1154 uh->dest = inet->inet_dport;
1183 udp_len = uhlen + hdr_len + data_len; 1155 udp_len = uhlen + hdr_len + data_len;
1184 uh->len = htons(udp_len); 1156 uh->len = htons(udp_len);
1185 uh->check = 0;
1186 1157
1187 /* Calculate UDP checksum if configured to do so */ 1158 /* Calculate UDP checksum if configured to do so */
1188#if IS_ENABLED(CONFIG_IPV6) 1159#if IS_ENABLED(CONFIG_IPV6)
1189 if (sk->sk_family == PF_INET6 && !tunnel->v4mapped) 1160 if (sk->sk_family == PF_INET6 && !tunnel->v4mapped)
1190 l2tp_xmit_ipv6_csum(sk, skb, udp_len); 1161 udp6_set_csum(udp_get_no_check6_tx(sk),
1162 skb, &inet6_sk(sk)->saddr,
1163 &sk->sk_v6_daddr, udp_len);
1191 else 1164 else
1192#endif 1165#endif
1193 if (sk->sk_no_check_tx) 1166 udp_set_csum(sk->sk_no_check_tx, skb, inet->inet_saddr,
1194 skb->ip_summed = CHECKSUM_NONE; 1167 inet->inet_daddr, udp_len);
1195 else if ((skb_dst(skb) && skb_dst(skb)->dev) &&
1196 (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) {
1197 skb->ip_summed = CHECKSUM_COMPLETE;
1198 csum = skb_checksum(skb, 0, udp_len, 0);
1199 uh->check = csum_tcpudp_magic(inet->inet_saddr,
1200 inet->inet_daddr,
1201 udp_len, IPPROTO_UDP, csum);
1202 if (uh->check == 0)
1203 uh->check = CSUM_MANGLED_0;
1204 } else {
1205 skb->ip_summed = CHECKSUM_PARTIAL;
1206 skb->csum_start = skb_transport_header(skb) - skb->head;
1207 skb->csum_offset = offsetof(struct udphdr, check);
1208 uh->check = ~csum_tcpudp_magic(inet->inet_saddr,
1209 inet->inet_daddr,
1210 udp_len, IPPROTO_UDP, 0);
1211 }
1212 break; 1168 break;
1213 1169
1214 case L2TP_ENCAPTYPE_IP: 1170 case L2TP_ENCAPTYPE_IP:
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
index 851cd880b0c0..6b38d083e1c9 100644
--- a/net/mpls/mpls_gso.c
+++ b/net/mpls/mpls_gso.c
@@ -33,6 +33,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
33 SKB_GSO_DODGY | 33 SKB_GSO_DODGY |
34 SKB_GSO_TCP_ECN | 34 SKB_GSO_TCP_ECN |
35 SKB_GSO_GRE | 35 SKB_GSO_GRE |
36 SKB_GSO_GRE_CSUM |
36 SKB_GSO_IPIP | 37 SKB_GSO_IPIP |
37 SKB_GSO_MPLS))) 38 SKB_GSO_MPLS)))
38 goto out; 39 goto out;
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index a93efa3f64c3..0edbd95c60e7 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -122,7 +122,7 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
122 vxlan_port = vxlan_vport(vport); 122 vxlan_port = vxlan_vport(vport);
123 strncpy(vxlan_port->name, parms->name, IFNAMSIZ); 123 strncpy(vxlan_port->name, parms->name, IFNAMSIZ);
124 124
125 vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true, false); 125 vs = vxlan_sock_add(net, htons(dst_port), vxlan_rcv, vport, true, 0);
126 if (IS_ERR(vs)) { 126 if (IS_ERR(vs)) {
127 ovs_vport_free(vport); 127 ovs_vport_free(vport);
128 return (void *)vs; 128 return (void *)vs;