Commit f9708b43 authored by Jan Beulich's avatar Jan Beulich Committed by David S. Miller

consolidate duplicate code is skb_checksum_setup() helpers

consolidate duplicate code is skb_checksum_setup() helpers

Realizing that the skb_maybe_pull_tail() calls in the IP-protocol
specific portions of both helpers are terminal ones (i.e. no further
pulls are expected), their maximum size to be pulled can be made match
their minimal size needed, thus making the code identical and hence
possible to be moved into another helper.
Signed-off-by: default avatarJan Beulich <jbeulich@suse.com>
Cc: Paul Durrant <paul.durrant@citrix.com>
Cc: David Miller <davem@davemloft.net>
Cc: Eric Dumazet <edumazet@google.com>
Reviewed-by: default avatarPaul Durrant <paul.durrant@citrix.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 50240dc3
...@@ -3566,15 +3566,47 @@ static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len, ...@@ -3566,15 +3566,47 @@ static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len,
return 0; return 0;
} }
#define MAX_TCP_HDR_LEN (15 * 4)
static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb,
typeof(IPPROTO_IP) proto,
unsigned int off)
{
switch (proto) {
int err;
case IPPROTO_TCP:
err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr),
off + MAX_TCP_HDR_LEN);
if (!err && !skb_partial_csum_set(skb, off,
offsetof(struct tcphdr,
check)))
err = -EPROTO;
return err ? ERR_PTR(err) : &tcp_hdr(skb)->check;
case IPPROTO_UDP:
err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr),
off + sizeof(struct udphdr));
if (!err && !skb_partial_csum_set(skb, off,
offsetof(struct udphdr,
check)))
err = -EPROTO;
return err ? ERR_PTR(err) : &udp_hdr(skb)->check;
}
return ERR_PTR(-EPROTO);
}
/* This value should be large enough to cover a tagged ethernet header plus /* This value should be large enough to cover a tagged ethernet header plus
* maximally sized IP and TCP or UDP headers. * maximally sized IP and TCP or UDP headers.
*/ */
#define MAX_IP_HDR_LEN 128 #define MAX_IP_HDR_LEN 128
static int skb_checksum_setup_ip(struct sk_buff *skb, bool recalculate) static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate)
{ {
unsigned int off; unsigned int off;
bool fragment; bool fragment;
__sum16 *csum;
int err; int err;
fragment = false; fragment = false;
...@@ -3595,51 +3627,15 @@ static int skb_checksum_setup_ip(struct sk_buff *skb, bool recalculate) ...@@ -3595,51 +3627,15 @@ static int skb_checksum_setup_ip(struct sk_buff *skb, bool recalculate)
if (fragment) if (fragment)
goto out; goto out;
switch (ip_hdr(skb)->protocol) { csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off);
case IPPROTO_TCP: if (IS_ERR(csum))
err = skb_maybe_pull_tail(skb, return PTR_ERR(csum);
off + sizeof(struct tcphdr),
MAX_IP_HDR_LEN);
if (err < 0)
goto out;
if (!skb_partial_csum_set(skb, off,
offsetof(struct tcphdr, check))) {
err = -EPROTO;
goto out;
}
if (recalculate)
tcp_hdr(skb)->check =
~csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
skb->len - off,
IPPROTO_TCP, 0);
break;
case IPPROTO_UDP:
err = skb_maybe_pull_tail(skb,
off + sizeof(struct udphdr),
MAX_IP_HDR_LEN);
if (err < 0)
goto out;
if (!skb_partial_csum_set(skb, off,
offsetof(struct udphdr, check))) {
err = -EPROTO;
goto out;
}
if (recalculate)
udp_hdr(skb)->check =
~csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
skb->len - off,
IPPROTO_UDP, 0);
break;
default:
goto out;
}
if (recalculate)
*csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr,
ip_hdr(skb)->daddr,
skb->len - off,
ip_hdr(skb)->protocol, 0);
err = 0; err = 0;
out: out:
...@@ -3662,6 +3658,7 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) ...@@ -3662,6 +3658,7 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate)
unsigned int len; unsigned int len;
bool fragment; bool fragment;
bool done; bool done;
__sum16 *csum;
fragment = false; fragment = false;
done = false; done = false;
...@@ -3739,51 +3736,14 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) ...@@ -3739,51 +3736,14 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate)
if (!done || fragment) if (!done || fragment)
goto out; goto out;
switch (nexthdr) { csum = skb_checksum_setup_ip(skb, nexthdr, off);
case IPPROTO_TCP: if (IS_ERR(csum))
err = skb_maybe_pull_tail(skb, return PTR_ERR(csum);
off + sizeof(struct tcphdr),
MAX_IPV6_HDR_LEN);
if (err < 0)
goto out;
if (!skb_partial_csum_set(skb, off,
offsetof(struct tcphdr, check))) {
err = -EPROTO;
goto out;
}
if (recalculate)
tcp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
skb->len - off,
IPPROTO_TCP, 0);
break;
case IPPROTO_UDP:
err = skb_maybe_pull_tail(skb,
off + sizeof(struct udphdr),
MAX_IPV6_HDR_LEN);
if (err < 0)
goto out;
if (!skb_partial_csum_set(skb, off,
offsetof(struct udphdr, check))) {
err = -EPROTO;
goto out;
}
if (recalculate)
udp_hdr(skb)->check =
~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
skb->len - off,
IPPROTO_UDP, 0);
break;
default:
goto out;
}
if (recalculate)
*csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr,
skb->len - off, nexthdr, 0);
err = 0; err = 0;
out: out:
...@@ -3801,7 +3761,7 @@ int skb_checksum_setup(struct sk_buff *skb, bool recalculate) ...@@ -3801,7 +3761,7 @@ int skb_checksum_setup(struct sk_buff *skb, bool recalculate)
switch (skb->protocol) { switch (skb->protocol) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
err = skb_checksum_setup_ip(skb, recalculate); err = skb_checksum_setup_ipv4(skb, recalculate);
break; break;
case htons(ETH_P_IPV6): case htons(ETH_P_IPV6):
......
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