net: local checksum offload for encapsulation
The arithmetic properties of the ones-complement checksum mean that a correctly checksummed inner packet, including its checksum, has a ones complement sum depending only on whatever value was used to initialise the checksum field before checksumming (in the case of TCP and UDP, this is the ones complement sum of the pseudo header, complemented). Consequently, if we are going to offload the inner checksum with CHECKSUM_PARTIAL, we can compute the outer checksum based only on the packed data not covered by the inner checksum, and the initial value of the inner checksum field. Signed-off-by: Edward Cree <ecree@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Šī revīzija ir iekļauta:

revīziju iesūtīja
David S. Miller

vecāks
e51271d4ce
revīzija
179bc67f69
@@ -98,11 +98,13 @@ void udp6_set_csum(bool nocheck, struct sk_buff *skb,
|
||||
uh->check = 0;
|
||||
else if (skb_is_gso(skb))
|
||||
uh->check = ~udp_v6_check(len, saddr, daddr, 0);
|
||||
else if (skb_dst(skb) && skb_dst(skb)->dev &&
|
||||
(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) {
|
||||
|
||||
BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
|
||||
|
||||
else if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
uh->check = 0;
|
||||
uh->check = udp_v6_check(len, saddr, daddr, lco_csum(skb));
|
||||
if (uh->check == 0)
|
||||
uh->check = CSUM_MANGLED_0;
|
||||
} else if (skb_dst(skb) && skb_dst(skb)->dev &&
|
||||
(skb_dst(skb)->dev->features & NETIF_F_IPV6_CSUM)) {
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->csum_start = skb_transport_header(skb) - skb->head;
|
||||
skb->csum_offset = offsetof(struct udphdr, check);
|
||||
@@ -110,8 +112,6 @@ void udp6_set_csum(bool nocheck, struct sk_buff *skb,
|
||||
} else {
|
||||
__wsum csum;
|
||||
|
||||
BUG_ON(skb->ip_summed == CHECKSUM_PARTIAL);
|
||||
|
||||
uh->check = 0;
|
||||
csum = skb_checksum(skb, 0, len, 0);
|
||||
uh->check = udp_v6_check(len, saddr, daddr, csum);
|
||||
|
Atsaukties uz šo jaunā problēmā
Block a user