Commit 60476372 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

[NET]: Treat CHECKSUM_PARTIAL as CHECKSUM_UNNECESSARY

When a transmitted packet is looped back directly, CHECKSUM_PARTIAL
maps to the semantics of CHECKSUM_UNNECESSARY.  Therefore we should
treat it as such in the stack.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 628592cc
...@@ -32,10 +32,11 @@ ...@@ -32,10 +32,11 @@
#define HAVE_ALLOC_SKB /* For the drivers to know */ #define HAVE_ALLOC_SKB /* For the drivers to know */
#define HAVE_ALIGNABLE_SKB /* Ditto 8) */ #define HAVE_ALIGNABLE_SKB /* Ditto 8) */
/* Don't change this without changing skb_csum_unnecessary! */
#define CHECKSUM_NONE 0 #define CHECKSUM_NONE 0
#define CHECKSUM_PARTIAL 1 #define CHECKSUM_UNNECESSARY 1
#define CHECKSUM_UNNECESSARY 2 #define CHECKSUM_COMPLETE 2
#define CHECKSUM_COMPLETE 3 #define CHECKSUM_PARTIAL 3
#define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \ #define SKB_DATA_ALIGN(X) (((X) + (SMP_CACHE_BYTES - 1)) & \
~(SMP_CACHE_BYTES - 1)) ~(SMP_CACHE_BYTES - 1))
...@@ -1572,6 +1573,11 @@ static inline void __net_timestamp(struct sk_buff *skb) ...@@ -1572,6 +1573,11 @@ static inline void __net_timestamp(struct sk_buff *skb)
extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
extern __sum16 __skb_checksum_complete(struct sk_buff *skb); extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
static inline int skb_csum_unnecessary(const struct sk_buff *skb)
{
return skb->ip_summed & CHECKSUM_UNNECESSARY;
}
/** /**
* skb_checksum_complete - Calculate checksum of an entire packet * skb_checksum_complete - Calculate checksum of an entire packet
* @skb: packet to process * @skb: packet to process
...@@ -1590,8 +1596,8 @@ extern __sum16 __skb_checksum_complete(struct sk_buff *skb); ...@@ -1590,8 +1596,8 @@ extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
*/ */
static inline unsigned int skb_checksum_complete(struct sk_buff *skb) static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
{ {
return skb->ip_summed != CHECKSUM_UNNECESSARY && return skb_csum_unnecessary(skb) ?
__skb_checksum_complete(skb); 0 : __skb_checksum_complete(skb);
} }
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
......
...@@ -818,7 +818,7 @@ static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb) ...@@ -818,7 +818,7 @@ static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb)
static inline int tcp_checksum_complete(struct sk_buff *skb) static inline int tcp_checksum_complete(struct sk_buff *skb)
{ {
return skb->ip_summed != CHECKSUM_UNNECESSARY && return !skb_csum_unnecessary(skb) &&
__tcp_checksum_complete(skb); __tcp_checksum_complete(skb);
} }
......
...@@ -77,7 +77,7 @@ static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb) ...@@ -77,7 +77,7 @@ static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
static inline int udp_lib_checksum_complete(struct sk_buff *skb) static inline int udp_lib_checksum_complete(struct sk_buff *skb)
{ {
return skb->ip_summed != CHECKSUM_UNNECESSARY && return !skb_csum_unnecessary(skb) &&
__udp_lib_checksum_complete(skb); __udp_lib_checksum_complete(skb);
} }
......
...@@ -86,7 +86,7 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, ...@@ -86,7 +86,7 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
{ {
__wsum psum; __wsum psum;
if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY) if (uh->check == 0 || skb_csum_unnecessary(skb))
return 0; return 0;
psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
......
...@@ -681,8 +681,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related) ...@@ -681,8 +681,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
} }
/* Ensure the checksum is correct */ /* Ensure the checksum is correct */
if (skb->ip_summed != CHECKSUM_UNNECESSARY && if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
ip_vs_checksum_complete(skb, ihl)) {
/* Failed checksum! */ /* Failed checksum! */
IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n", IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n",
NIPQUAD(iph->saddr)); NIPQUAD(iph->saddr));
...@@ -921,8 +920,7 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum) ...@@ -921,8 +920,7 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
verdict = NF_DROP; verdict = NF_DROP;
/* Ensure the checksum is correct */ /* Ensure the checksum is correct */
if (skb->ip_summed != CHECKSUM_UNNECESSARY && if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
ip_vs_checksum_complete(skb, ihl)) {
/* Failed checksum! */ /* Failed checksum! */
IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n", IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n",
NIPQUAD(iph->saddr)); NIPQUAD(iph->saddr));
......
...@@ -4009,7 +4009,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) ...@@ -4009,7 +4009,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
int err; int err;
local_bh_enable(); local_bh_enable();
if (skb->ip_summed==CHECKSUM_UNNECESSARY) if (skb_csum_unnecessary(skb))
err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk); err = skb_copy_datagram_iovec(skb, hlen, tp->ucopy.iov, chunk);
else else
err = skb_copy_and_csum_datagram_iovec(skb, hlen, err = skb_copy_and_csum_datagram_iovec(skb, hlen,
...@@ -4041,7 +4041,7 @@ static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb ...@@ -4041,7 +4041,7 @@ static __sum16 __tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb
static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb) static inline int tcp_checksum_complete_user(struct sock *sk, struct sk_buff *skb)
{ {
return skb->ip_summed != CHECKSUM_UNNECESSARY && return !skb_csum_unnecessary(skb) &&
__tcp_checksum_complete_user(sk, skb); __tcp_checksum_complete_user(sk, skb);
} }
...@@ -4059,7 +4059,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, int hlen ...@@ -4059,7 +4059,7 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, int hlen
if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list) if (!tp->ucopy.dma_chan && tp->ucopy.pinned_list)
tp->ucopy.dma_chan = get_softnet_dma(); tp->ucopy.dma_chan = get_softnet_dma();
if (tp->ucopy.dma_chan && skb->ip_summed == CHECKSUM_UNNECESSARY) { if (tp->ucopy.dma_chan && skb_csum_unnecessary(skb)) {
dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan, dma_cookie = dma_skb_copy_datagram_iovec(tp->ucopy.dma_chan,
skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list); skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
......
...@@ -1638,8 +1638,7 @@ int tcp_v4_rcv(struct sk_buff *skb) ...@@ -1638,8 +1638,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
* Packet length and doff are validated by header prediction, * Packet length and doff are validated by header prediction,
* provided case of th->doff==0 is eliminated. * provided case of th->doff==0 is eliminated.
* So, we defer the checks. */ * So, we defer the checks. */
if ((skb->ip_summed != CHECKSUM_UNNECESSARY && if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
tcp_v4_checksum_init(skb)))
goto bad_packet; goto bad_packet;
th = tcp_hdr(skb); th = tcp_hdr(skb);
......
...@@ -848,7 +848,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, ...@@ -848,7 +848,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
goto csum_copy_err; goto csum_copy_err;
} }
if (skb->ip_summed == CHECKSUM_UNNECESSARY) if (skb_csum_unnecessary(skb))
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
msg->msg_iov, copied ); msg->msg_iov, copied );
else { else {
...@@ -1190,7 +1190,7 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh, ...@@ -1190,7 +1190,7 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
proto, skb->csum)) proto, skb->csum))
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
if (skb->ip_summed != CHECKSUM_UNNECESSARY) if (!skb_csum_unnecessary(skb))
skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
skb->len, proto, 0); skb->len, proto, 0);
/* Probably, we should checksum udp header (it should be in cache /* Probably, we should checksum udp header (it should be in cache
......
...@@ -368,7 +368,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -368,7 +368,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
skb->len, inet->num, skb->csum)) skb->len, inet->num, skb->csum))
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
} }
if (skb->ip_summed != CHECKSUM_UNNECESSARY) if (!skb_csum_unnecessary(skb))
skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr, &ipv6_hdr(skb)->daddr,
skb->len, skb->len,
...@@ -421,7 +421,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -421,7 +421,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
msg->msg_flags |= MSG_TRUNC; msg->msg_flags |= MSG_TRUNC;
} }
if (skb->ip_summed==CHECKSUM_UNNECESSARY) { if (skb_csum_unnecessary(skb)) {
err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
} else if (msg->msg_flags&MSG_TRUNC) { } else if (msg->msg_flags&MSG_TRUNC) {
if (__skb_checksum_complete(skb)) if (__skb_checksum_complete(skb))
......
...@@ -1707,8 +1707,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb) ...@@ -1707,8 +1707,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb)
if (!pskb_may_pull(skb, th->doff*4)) if (!pskb_may_pull(skb, th->doff*4))
goto discard_it; goto discard_it;
if ((skb->ip_summed != CHECKSUM_UNNECESSARY && if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
tcp_v6_checksum_init(skb)))
goto bad_packet; goto bad_packet;
th = tcp_hdr(skb); th = tcp_hdr(skb);
......
...@@ -153,7 +153,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -153,7 +153,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
goto csum_copy_err; goto csum_copy_err;
} }
if (skb->ip_summed == CHECKSUM_UNNECESSARY) if (skb_csum_unnecessary(skb))
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
msg->msg_iov, copied ); msg->msg_iov, copied );
else { else {
...@@ -397,7 +397,7 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, ...@@ -397,7 +397,7 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
skb->len, proto, skb->csum)) skb->len, proto, skb->csum))
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
if (skb->ip_summed != CHECKSUM_UNNECESSARY) if (!skb_csum_unnecessary(skb))
skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr, skb->csum = ~csum_unfold(csum_ipv6_magic(&ipv6_hdr(skb)->saddr,
&ipv6_hdr(skb)->daddr, &ipv6_hdr(skb)->daddr,
skb->len, proto, 0)); skb->len, proto, 0));
......
...@@ -140,8 +140,7 @@ int sctp_rcv(struct sk_buff *skb) ...@@ -140,8 +140,7 @@ int sctp_rcv(struct sk_buff *skb)
__skb_pull(skb, skb_transport_offset(skb)); __skb_pull(skb, skb_transport_offset(skb));
if (skb->len < sizeof(struct sctphdr)) if (skb->len < sizeof(struct sctphdr))
goto discard_it; goto discard_it;
if ((skb->ip_summed != CHECKSUM_UNNECESSARY) && if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0)
(sctp_rcv_checksum(skb) < 0))
goto discard_it; goto discard_it;
skb_pull(skb, sizeof(struct sctphdr)); skb_pull(skb, sizeof(struct sctphdr));
......
...@@ -154,7 +154,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) ...@@ -154,7 +154,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
desc.offset = sizeof(struct udphdr); desc.offset = sizeof(struct udphdr);
desc.count = skb->len - desc.offset; desc.count = skb->len - desc.offset;
if (skb->ip_summed == CHECKSUM_UNNECESSARY) if (skb_csum_unnecessary(skb))
goto no_checksum; goto no_checksum;
desc.csum = csum_partial(skb->data, desc.offset, skb->csum); desc.csum = csum_partial(skb->data, desc.offset, skb->csum);
......
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