Commit 4fd671de authored by Tom Herbert's avatar Tom Herbert Committed by David S. Miller

gue: Call remcsum_adjust

Change remote checksum offload to call remcsum_adjust. This also
eliminates the optimization to skip an IP header as part of the
adjustment (really does not seem to be much of a win).
Signed-off-by: default avatarTom Herbert <therbert@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7c967b22
...@@ -64,15 +64,13 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb) ...@@ -64,15 +64,13 @@ static int fou_udp_recv(struct sock *sk, struct sk_buff *skb)
} }
static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
void *data, int hdrlen, u8 ipproto) void *data, size_t hdrlen, u8 ipproto)
{ {
__be16 *pd = data; __be16 *pd = data;
u16 start = ntohs(pd[0]); size_t start = ntohs(pd[0]);
u16 offset = ntohs(pd[1]); size_t offset = ntohs(pd[1]);
u16 poffset = 0; size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
u16 plen; __wsum delta;
__wsum csum, delta;
__sum16 *psum;
if (skb->remcsum_offload) { if (skb->remcsum_offload) {
/* Already processed in GRO path */ /* Already processed in GRO path */
...@@ -80,35 +78,15 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr, ...@@ -80,35 +78,15 @@ static struct guehdr *gue_remcsum(struct sk_buff *skb, struct guehdr *guehdr,
return guehdr; return guehdr;
} }
if (start > skb->len - hdrlen ||
offset > skb->len - hdrlen - sizeof(u16))
return NULL;
if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE))
__skb_checksum_complete(skb);
plen = hdrlen + offset + sizeof(u16);
if (!pskb_may_pull(skb, plen)) if (!pskb_may_pull(skb, plen))
return NULL; return NULL;
guehdr = (struct guehdr *)&udp_hdr(skb)[1]; guehdr = (struct guehdr *)&udp_hdr(skb)[1];
if (ipproto == IPPROTO_IP && sizeof(struct iphdr) < plen) { if (unlikely(skb->ip_summed != CHECKSUM_COMPLETE))
struct iphdr *ip = (struct iphdr *)(skb->data + hdrlen); __skb_checksum_complete(skb);
/* If next header happens to be IP we can skip that for the
* checksum calculation since the IP header checksum is zero
* if correct.
*/
poffset = ip->ihl * 4;
}
csum = csum_sub(skb->csum, skb_checksum(skb, poffset + hdrlen,
start - poffset - hdrlen, 0));
/* Set derived checksum in packet */ delta = remcsum_adjust((void *)guehdr + hdrlen,
psum = (__sum16 *)(skb->data + hdrlen + offset); skb->csum, start, offset);
delta = csum_sub(csum_fold(csum), *psum);
*psum = csum_fold(csum);
/* Adjust skb->csum since we changed the packet */ /* Adjust skb->csum since we changed the packet */
skb->csum = csum_add(skb->csum, delta); skb->csum = csum_add(skb->csum, delta);
...@@ -158,9 +136,6 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) ...@@ -158,9 +136,6 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len); ip_hdr(skb)->tot_len = htons(ntohs(ip_hdr(skb)->tot_len) - len);
/* Pull UDP header now, skb->data points to guehdr */
__skb_pull(skb, sizeof(struct udphdr));
/* Pull csum through the guehdr now . This can be used if /* Pull csum through the guehdr now . This can be used if
* there is a remote checksum offload. * there is a remote checksum offload.
*/ */
...@@ -188,7 +163,7 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) ...@@ -188,7 +163,7 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb)
if (unlikely(guehdr->control)) if (unlikely(guehdr->control))
return gue_control_message(skb, guehdr); return gue_control_message(skb, guehdr);
__skb_pull(skb, hdrlen); __skb_pull(skb, sizeof(struct udphdr) + hdrlen);
skb_reset_transport_header(skb); skb_reset_transport_header(skb);
return -guehdr->proto_ctype; return -guehdr->proto_ctype;
...@@ -248,24 +223,17 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, ...@@ -248,24 +223,17 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
size_t hdrlen, u8 ipproto) size_t hdrlen, u8 ipproto)
{ {
__be16 *pd = data; __be16 *pd = data;
u16 start = ntohs(pd[0]); size_t start = ntohs(pd[0]);
u16 offset = ntohs(pd[1]); size_t offset = ntohs(pd[1]);
u16 poffset = 0; size_t plen = hdrlen + max_t(size_t, offset + sizeof(u16), start);
u16 plen; __wsum delta;
void *ptr;
__wsum csum, delta;
__sum16 *psum;
if (skb->remcsum_offload) if (skb->remcsum_offload)
return guehdr; return guehdr;
if (start > skb_gro_len(skb) - hdrlen || if (!NAPI_GRO_CB(skb)->csum_valid)
offset > skb_gro_len(skb) - hdrlen - sizeof(u16) ||
!NAPI_GRO_CB(skb)->csum_valid || skb->remcsum_offload)
return NULL; return NULL;
plen = hdrlen + offset + sizeof(u16);
/* Pull checksum that will be written */ /* Pull checksum that will be written */
if (skb_gro_header_hard(skb, off + plen)) { if (skb_gro_header_hard(skb, off + plen)) {
guehdr = skb_gro_header_slow(skb, off + plen, off); guehdr = skb_gro_header_slow(skb, off + plen, off);
...@@ -273,26 +241,8 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off, ...@@ -273,26 +241,8 @@ static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
return NULL; return NULL;
} }
ptr = (void *)guehdr + hdrlen; delta = remcsum_adjust((void *)guehdr + hdrlen,
NAPI_GRO_CB(skb)->csum, start, offset);
if (ipproto == IPPROTO_IP &&
(hdrlen + sizeof(struct iphdr) < plen)) {
struct iphdr *ip = (struct iphdr *)(ptr + hdrlen);
/* If next header happens to be IP we can skip
* that for the checksum calculation since the
* IP header checksum is zero if correct.
*/
poffset = ip->ihl * 4;
}
csum = csum_sub(NAPI_GRO_CB(skb)->csum,
csum_partial(ptr + poffset, start - poffset, 0));
/* Set derived checksum in packet */
psum = (__sum16 *)(ptr + offset);
delta = csum_sub(csum_fold(csum), *psum);
*psum = csum_fold(csum);
/* Adjust skb->csum since we changed the packet */ /* Adjust skb->csum since we changed the packet */
skb->csum = csum_add(skb->csum, delta); skb->csum = csum_add(skb->csum, delta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment