Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

udp: move logic out of udp[46]_ufo_send_check

In udp[46]_ufo_send_check the UDP checksum initialized to the pseudo
header checksum. We can move this logic into udp[46]_ufo_fragment.
After this change udp[64]_ufo_send_check is a no-op.

Signed-off-by: Tom Herbert <therbert@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tom Herbert and committed by
David S. Miller
f71470b3 d020f8f7

+33 -44
+15 -22
net/ipv4/udp_offload.c
··· 27 27 28 28 static int udp4_ufo_send_check(struct sk_buff *skb) 29 29 { 30 - if (!pskb_may_pull(skb, sizeof(struct udphdr))) 31 - return -EINVAL; 32 - 33 - if (likely(!skb->encapsulation)) { 34 - const struct iphdr *iph; 35 - struct udphdr *uh; 36 - 37 - iph = ip_hdr(skb); 38 - uh = udp_hdr(skb); 39 - 40 - uh->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, skb->len, 41 - IPPROTO_UDP, 0); 42 - skb->csum_start = skb_transport_header(skb) - skb->head; 43 - skb->csum_offset = offsetof(struct udphdr, check); 44 - skb->ip_summed = CHECKSUM_PARTIAL; 45 - } 46 - 47 30 return 0; 48 31 } 49 32 ··· 111 128 { 112 129 struct sk_buff *segs = ERR_PTR(-EINVAL); 113 130 unsigned int mss; 114 - int offset; 115 131 __wsum csum; 132 + struct udphdr *uh; 133 + struct iphdr *iph; 116 134 117 135 if (skb->encapsulation && 118 136 (skb_shinfo(skb)->gso_type & ··· 121 137 segs = skb_udp_tunnel_segment(skb, features); 122 138 goto out; 123 139 } 140 + 141 + if (!pskb_may_pull(skb, sizeof(struct udphdr))) 142 + goto out; 124 143 125 144 mss = skb_shinfo(skb)->gso_size; 126 145 if (unlikely(skb->len <= mss)) ··· 152 165 * HW cannot do checksum of UDP packets sent as multiple 153 166 * IP fragments. 154 167 */ 155 - offset = skb_checksum_start_offset(skb); 156 - csum = skb_checksum(skb, offset, skb->len - offset, 0); 157 - offset += skb->csum_offset; 158 - *(__sum16 *)(skb->data + offset) = csum_fold(csum); 168 + 169 + uh = udp_hdr(skb); 170 + iph = ip_hdr(skb); 171 + 172 + uh->check = 0; 173 + csum = skb_checksum(skb, 0, skb->len, 0); 174 + uh->check = udp_v4_check(skb->len, iph->saddr, iph->daddr, csum); 175 + if (uh->check == 0) 176 + uh->check = CSUM_MANGLED_0; 177 + 159 178 skb->ip_summed = CHECKSUM_NONE; 160 179 161 180 /* Fragment the skb. IP headers of the fragments are updated in
+18 -22
net/ipv6/udp_offload.c
··· 19 19 20 20 static int udp6_ufo_send_check(struct sk_buff *skb) 21 21 { 22 - const struct ipv6hdr *ipv6h; 23 - struct udphdr *uh; 24 - 25 - if (!pskb_may_pull(skb, sizeof(*uh))) 26 - return -EINVAL; 27 - 28 - if (likely(!skb->encapsulation)) { 29 - ipv6h = ipv6_hdr(skb); 30 - uh = udp_hdr(skb); 31 - 32 - uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len, 33 - IPPROTO_UDP, 0); 34 - skb->csum_start = skb_transport_header(skb) - skb->head; 35 - skb->csum_offset = offsetof(struct udphdr, check); 36 - skb->ip_summed = CHECKSUM_PARTIAL; 37 - } 38 - 39 22 return 0; 40 23 } 41 24 ··· 32 49 u8 *packet_start, *prevhdr; 33 50 u8 nexthdr; 34 51 u8 frag_hdr_sz = sizeof(struct frag_hdr); 35 - int offset; 36 52 __wsum csum; 37 53 int tnl_hlen; 38 54 ··· 65 83 (SKB_GSO_UDP_TUNNEL|SKB_GSO_UDP_TUNNEL_CSUM)) 66 84 segs = skb_udp_tunnel_segment(skb, features); 67 85 else { 86 + const struct ipv6hdr *ipv6h; 87 + struct udphdr *uh; 88 + 89 + if (!pskb_may_pull(skb, sizeof(struct udphdr))) 90 + goto out; 91 + 68 92 /* Do software UFO. Complete and fill in the UDP checksum as HW cannot 69 93 * do checksum of UDP packets sent as multiple IP fragments. 70 94 */ 71 - offset = skb_checksum_start_offset(skb); 72 - csum = skb_checksum(skb, offset, skb->len - offset, 0); 73 - offset += skb->csum_offset; 74 - *(__sum16 *)(skb->data + offset) = csum_fold(csum); 95 + 96 + uh = udp_hdr(skb); 97 + ipv6h = ipv6_hdr(skb); 98 + 99 + uh->check = 0; 100 + csum = skb_checksum(skb, 0, skb->len, 0); 101 + uh->check = udp_v6_check(skb->len, &ipv6h->saddr, 102 + &ipv6h->daddr, csum); 103 + 104 + if (uh->check == 0) 105 + uh->check = CSUM_MANGLED_0; 106 + 75 107 skb->ip_summed = CHECKSUM_NONE; 76 108 77 109 /* Check if there is enough headroom to insert fragment header. */