[NET]: Treat CHECKSUM_PARTIAL as CHECKSUM_UNNECESSARY
authorHerbert Xu <herbert@gondor.apana.org.au>
Mon, 9 Apr 2007 18:59:39 +0000 (11:59 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 26 Apr 2007 05:28:43 +0000 (22:28 -0700)
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: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
13 files changed:
include/linux/skbuff.h
include/net/tcp.h
include/net/udp.h
net/core/netpoll.c
net/ipv4/ipvs/ip_vs_core.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv6/raw.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/sctp/input.c
net/sunrpc/socklib.c

index 910560e855619917a5f7103bfbae9642f7ee139b..c413afbe0b9c8948e827d62dc8e6aa9feeccea93 100644 (file)
 #define HAVE_ALLOC_SKB         /* For the drivers to know */
 #define HAVE_ALIGNABLE_SKB     /* Ditto 8)                */
 
+/* Don't change this without changing skb_csum_unnecessary! */
 #define CHECKSUM_NONE 0
-#define CHECKSUM_PARTIAL 1
-#define CHECKSUM_UNNECESSARY 2
-#define CHECKSUM_COMPLETE 3
+#define CHECKSUM_UNNECESSARY 1
+#define CHECKSUM_COMPLETE 2
+#define CHECKSUM_PARTIAL 3
 
 #define SKB_DATA_ALIGN(X)      (((X) + (SMP_CACHE_BYTES - 1)) & \
                                 ~(SMP_CACHE_BYTES - 1))
@@ -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(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: packet to process
@@ -1590,8 +1596,8 @@ extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
  */
 static inline unsigned int skb_checksum_complete(struct sk_buff *skb)
 {
-       return skb->ip_summed != CHECKSUM_UNNECESSARY &&
-               __skb_checksum_complete(skb);
+       return skb_csum_unnecessary(skb) ?
+              0 : __skb_checksum_complete(skb);
 }
 
 #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
index af9273204cfd446857d5282b52a8ce733f03da79..07f724e02f8482fea675816f0ef91f33a17a56a8 100644 (file)
@@ -818,7 +818,7 @@ static inline __sum16 __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);
 }
 
index 4906ed7113e7e887df984560b0a0d23d1789167d..98755ebaf163cfe788b4117167cfeaf1a861f269 100644 (file)
@@ -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)
 {
-       return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+       return !skb_csum_unnecessary(skb) &&
                __udp_lib_checksum_complete(skb);
 }
 
index 1fb30c3528bc016237f83ae81292c0b121dad138..b316435b0e2a5632446c70a23228e75c6294a6a5 100644 (file)
@@ -86,7 +86,7 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh,
 {
        __wsum psum;
 
-       if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY)
+       if (uh->check == 0 || skb_csum_unnecessary(skb))
                return 0;
 
        psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
index 62cfbed317bf07176d6bbcd67545381f141c3711..f005a2f929f4121825c2aa94d15d79b2ea558608 100644 (file)
@@ -681,8 +681,7 @@ static int ip_vs_out_icmp(struct sk_buff **pskb, int *related)
        }
 
        /* Ensure the checksum is correct */
-       if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
-           ip_vs_checksum_complete(skb, ihl)) {
+       if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
                /* Failed checksum! */
                IP_VS_DBG(1, "Forward ICMP: failed checksum from %d.%d.%d.%d!\n",
                          NIPQUAD(iph->saddr));
@@ -921,8 +920,7 @@ ip_vs_in_icmp(struct sk_buff **pskb, int *related, unsigned int hooknum)
        verdict = NF_DROP;
 
        /* Ensure the checksum is correct */
-       if (skb->ip_summed != CHECKSUM_UNNECESSARY &&
-           ip_vs_checksum_complete(skb, ihl)) {
+       if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
                /* Failed checksum! */
                IP_VS_DBG(1, "Incoming ICMP: failed checksum from %d.%d.%d.%d!\n",
                          NIPQUAD(iph->saddr));
index 9c3b4c7a50ad1a1dd82e914a4c219d837a1fa816..d1604f59d77e36fdc0d14a839807b0e3fe442f8c 100644 (file)
@@ -4009,7 +4009,7 @@ static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
        int err;
 
        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);
        else
                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
 
 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);
 }
 
@@ -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)
                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,
                        skb, hlen, tp->ucopy.iov, chunk, tp->ucopy.pinned_list);
index a091a99ad263d7eaa3519dfccfd25d5891c60272..5a3e7f839fc52f838122a88a40209566ce2e3ab7 100644 (file)
@@ -1638,8 +1638,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
         * Packet length and doff are validated by header prediction,
         * provided case of th->doff==0 is eliminated.
         * So, we defer the checks. */
-       if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-            tcp_v4_checksum_init(skb)))
+       if (!skb_csum_unnecessary(skb) && tcp_v4_checksum_init(skb))
                goto bad_packet;
 
        th = tcp_hdr(skb);
index 5ad7a26e30917fea6b356268dd9dcf38a98cdfd9..cec0f2cc49b7357975e8b254df25709cfc261d90 100644 (file)
@@ -848,7 +848,7 @@ try_again:
                        goto csum_copy_err;
        }
 
-       if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+       if (skb_csum_unnecessary(skb))
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
                                              msg->msg_iov, copied       );
        else {
@@ -1190,7 +1190,7 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,
                                      proto, skb->csum))
                        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->len, proto, 0);
        /* Probably, we should checksum udp header (it should be in cache
index 2b3be68b70a7ee6d8f2ae912de4dbd1600f5ab89..f65fcd7704cadeb911ff078650914f74ed59425b 100644 (file)
@@ -368,7 +368,7 @@ int rawv6_rcv(struct sock *sk, struct sk_buff *skb)
                                     skb->len, inet->num, skb->csum))
                        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,
                                                         &ipv6_hdr(skb)->daddr,
                                                         skb->len,
@@ -421,7 +421,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk,
                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);
        } else if (msg->msg_flags&MSG_TRUNC) {
                if (__skb_checksum_complete(skb))
index 7e824b97126d78d8a7e26baeaa28f18817152c20..2b668a6ae6984874484011beda0ac8c2b463b735 100644 (file)
@@ -1707,8 +1707,7 @@ static int tcp_v6_rcv(struct sk_buff **pskb)
        if (!pskb_may_pull(skb, th->doff*4))
                goto discard_it;
 
-       if ((skb->ip_summed != CHECKSUM_UNNECESSARY &&
-            tcp_v6_checksum_init(skb)))
+       if (!skb_csum_unnecessary(skb) && tcp_v6_checksum_init(skb))
                goto bad_packet;
 
        th = tcp_hdr(skb);
index 1e3dfb20b1cf95d6760f72bae148fbc436a22e16..b083c09e3d2d1b4757042e08684a10d7dc48d649 100644 (file)
@@ -153,7 +153,7 @@ try_again:
                        goto csum_copy_err;
        }
 
-       if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+       if (skb_csum_unnecessary(skb))
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
                                              msg->msg_iov, copied       );
        else {
@@ -397,7 +397,7 @@ static inline int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh,
                             skb->len, proto, skb->csum))
                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,
                                                         &ipv6_hdr(skb)->daddr,
                                                         skb->len, proto, 0));
index 18b97eedc1fad86b1279d38245c3a92378fb3302..885109fb3dda129a551ccac0ca4e88d29236c712 100644 (file)
@@ -140,8 +140,7 @@ int sctp_rcv(struct sk_buff *skb)
        __skb_pull(skb, skb_transport_offset(skb));
        if (skb->len < sizeof(struct sctphdr))
                goto discard_it;
-       if ((skb->ip_summed != CHECKSUM_UNNECESSARY) &&
-           (sctp_rcv_checksum(skb) < 0))
+       if (!skb_csum_unnecessary(skb) && sctp_rcv_checksum(skb) < 0)
                goto discard_it;
 
        skb_pull(skb, sizeof(struct sctphdr));
index 634885b0c04dcc5e6e4909297b7368e73898086d..1d377d1ab7f4a5018a18a876f87e337c022346c3 100644 (file)
@@ -154,7 +154,7 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
        desc.offset = sizeof(struct udphdr);
        desc.count = skb->len - desc.offset;
 
-       if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+       if (skb_csum_unnecessary(skb))
                goto no_checksum;
 
        desc.csum = csum_partial(skb->data, desc.offset, skb->csum);