Skip to content

Commit e585f23

Browse files
Tom Herbertdavem330
authored andcommitted
udp: Changes to udp_offload to support remote checksum offload
Add a new GSO type, SKB_GSO_TUNNEL_REMCSUM, which indicates remote checksum offload being done (in this case inner checksum must not be offloaded to the NIC). Added logic in __skb_udp_tunnel_segment to handle remote checksum offload case. Signed-off-by: Tom Herbert <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5024c33 commit e585f23

File tree

9 files changed

+29
-6
lines changed

9 files changed

+29
-6
lines changed

include/linux/netdev_features.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ enum {
4848
NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */
4949
NETIF_F_GSO_UDP_TUNNEL_CSUM_BIT,/* ... UDP TUNNEL with TSO & CSUM */
5050
NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */
51+
NETIF_F_GSO_TUNNEL_REMCSUM_BIT, /* ... TUNNEL with TSO & REMCSUM */
5152
/**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */
52-
NETIF_F_GSO_MPLS_BIT,
53+
NETIF_F_GSO_TUNNEL_REMCSUM_BIT,
5354

5455
NETIF_F_FCOE_CRC_BIT, /* FCoE CRC32 */
5556
NETIF_F_SCTP_CSUM_BIT, /* SCTP checksum offload */
@@ -119,6 +120,7 @@ enum {
119120
#define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
120121
#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
121122
#define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS)
123+
#define NETIF_F_GSO_TUNNEL_REMCSUM __NETIF_F(GSO_TUNNEL_REMCSUM)
122124
#define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
123125
#define NETIF_F_HW_VLAN_STAG_RX __NETIF_F(HW_VLAN_STAG_RX)
124126
#define NETIF_F_HW_VLAN_STAG_TX __NETIF_F(HW_VLAN_STAG_TX)

include/linux/netdevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3584,6 +3584,7 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
35843584
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
35853585
BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
35863586
BUILD_BUG_ON(SKB_GSO_MPLS != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
3587+
BUILD_BUG_ON(SKB_GSO_TUNNEL_REMCSUM != (NETIF_F_GSO_TUNNEL_REMCSUM >> NETIF_F_GSO_SHIFT));
35873588

35883589
return (features & feature) == feature;
35893590
}

include/linux/skbuff.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ enum {
373373

374374
SKB_GSO_MPLS = 1 << 12,
375375

376+
SKB_GSO_TUNNEL_REMCSUM = 1 << 13,
376377
};
377378

378379
#if BITS_PER_LONG > 32
@@ -603,7 +604,8 @@ struct sk_buff {
603604
#endif
604605
__u8 ipvs_property:1;
605606
__u8 inner_protocol_type:1;
606-
/* 4 or 6 bit hole */
607+
__u8 remcsum_offload:1;
608+
/* 3 or 5 bit hole */
607609

608610
#ifdef CONFIG_NET_SCHED
609611
__u16 tc_index; /* traffic control index */

net/core/skbuff.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,7 +3013,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
30133013
if (nskb->len == len + doffset)
30143014
goto perform_csum_check;
30153015

3016-
if (!sg) {
3016+
if (!sg && !nskb->remcsum_offload) {
30173017
nskb->ip_summed = CHECKSUM_NONE;
30183018
nskb->csum = skb_copy_and_csum_bits(head_skb, offset,
30193019
skb_put(nskb, len),
@@ -3085,7 +3085,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
30853085
nskb->truesize += nskb->data_len;
30863086

30873087
perform_csum_check:
3088-
if (!csum) {
3088+
if (!csum && !nskb->remcsum_offload) {
30893089
nskb->csum = skb_checksum(nskb, doffset,
30903090
nskb->len - doffset, 0);
30913091
nskb->ip_summed = CHECKSUM_NONE;

net/ipv4/af_inet.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,6 +1222,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
12221222
SKB_GSO_TCPV6 |
12231223
SKB_GSO_UDP_TUNNEL |
12241224
SKB_GSO_UDP_TUNNEL_CSUM |
1225+
SKB_GSO_TUNNEL_REMCSUM |
12251226
SKB_GSO_MPLS |
12261227
0)))
12271228
goto out;

net/ipv4/tcp_offload.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
9797
SKB_GSO_MPLS |
9898
SKB_GSO_UDP_TUNNEL |
9999
SKB_GSO_UDP_TUNNEL_CSUM |
100+
SKB_GSO_TUNNEL_REMCSUM |
100101
0) ||
101102
!(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
102103
goto out;

net/ipv4/udp_offload.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
4141
unsigned int oldlen;
4242
bool need_csum = !!(skb_shinfo(skb)->gso_type &
4343
SKB_GSO_UDP_TUNNEL_CSUM);
44-
bool offload_csum = false, dont_encap = need_csum;
44+
bool remcsum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TUNNEL_REMCSUM);
45+
bool offload_csum = false, dont_encap = (need_csum || remcsum);
4546

4647
oldlen = (u16)~skb->len;
4748

@@ -55,6 +56,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
5556
skb->mac_len = skb_inner_network_offset(skb);
5657
skb->protocol = new_protocol;
5758
skb->encap_hdr_csum = need_csum;
59+
skb->remcsum_offload = remcsum;
5860

5961
/* Try to offload checksum if possible */
6062
offload_csum = !!(need_csum &&
@@ -108,11 +110,22 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
108110
uh->check = ~csum_fold((__force __wsum)
109111
((__force u32)uh->check +
110112
(__force u32)delta));
111-
112113
if (offload_csum) {
113114
skb->ip_summed = CHECKSUM_PARTIAL;
114115
skb->csum_start = skb_transport_header(skb) - skb->head;
115116
skb->csum_offset = offsetof(struct udphdr, check);
117+
} else if (remcsum) {
118+
/* Need to calculate checksum from scratch,
119+
* inner checksums are never when doing
120+
* remote_checksum_offload.
121+
*/
122+
123+
skb->csum = skb_checksum(skb, udp_offset,
124+
skb->len - udp_offset,
125+
0);
126+
uh->check = csum_fold(skb->csum);
127+
if (uh->check == 0)
128+
uh->check = CSUM_MANGLED_0;
116129
} else {
117130
uh->check = gso_make_checksum(skb, ~uh->check);
118131

@@ -192,6 +205,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
192205
if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY |
193206
SKB_GSO_UDP_TUNNEL |
194207
SKB_GSO_UDP_TUNNEL_CSUM |
208+
SKB_GSO_TUNNEL_REMCSUM |
195209
SKB_GSO_IPIP |
196210
SKB_GSO_GRE | SKB_GSO_GRE_CSUM |
197211
SKB_GSO_MPLS) ||

net/ipv6/ip6_offload.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
7878
SKB_GSO_SIT |
7979
SKB_GSO_UDP_TUNNEL |
8080
SKB_GSO_UDP_TUNNEL_CSUM |
81+
SKB_GSO_TUNNEL_REMCSUM |
8182
SKB_GSO_MPLS |
8283
SKB_GSO_TCPV6 |
8384
0)))

net/ipv6/udp_offload.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
4242
SKB_GSO_DODGY |
4343
SKB_GSO_UDP_TUNNEL |
4444
SKB_GSO_UDP_TUNNEL_CSUM |
45+
SKB_GSO_TUNNEL_REMCSUM |
4546
SKB_GSO_GRE |
4647
SKB_GSO_GRE_CSUM |
4748
SKB_GSO_IPIP |

0 commit comments

Comments
 (0)