[SCTP]: Don't do CRC32C checksum over loopback.
authorSridhar Samudrala <sri@us.ibm.com>
Sun, 18 Jun 2006 05:57:28 +0000 (22:57 -0700)
committerDavid S. Miller <davem@davemloft.net>
Sun, 18 Jun 2006 05:57:28 +0000 (22:57 -0700)
Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/sctp/input.c
net/sctp/output.c

index 70d6606e2812e3eaaa9e39206b9c967c5e5e3d7e..42b66e74bbb504cf38b7ea088895ab49a7446280 100644 (file)
@@ -141,7 +141,8 @@ int sctp_rcv(struct sk_buff *skb)
        __skb_pull(skb, skb->h.raw - skb->data);
        if (skb->len < sizeof(struct sctphdr))
                goto discard_it;
-       if (sctp_rcv_checksum(skb) < 0)
+       if ((skb->ip_summed != CHECKSUM_UNNECESSARY) &&
+           (sctp_rcv_checksum(skb) < 0))
                goto discard_it;
 
        skb_pull(skb, sizeof(struct sctphdr));
index 437cba7260a4a1a6970546cbf36f650114a785ab..cdc5a393676657691a2421b573235fde8318b0f8 100644 (file)
@@ -295,14 +295,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        struct sctp_transport *tp = packet->transport;
        struct sctp_association *asoc = tp->asoc;
        struct sctphdr *sh;
-       __u32 crc32;
+       __u32 crc32 = 0;
        struct sk_buff *nskb;
        struct sctp_chunk *chunk, *tmp;
        struct sock *sk;
        int err = 0;
        int padding;            /* How much padding do we need?  */
        __u8 has_data = 0;
-       struct dst_entry *dst;
+       struct dst_entry *dst = tp->dst;
 
        SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
 
@@ -327,6 +327,19 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         */
        skb_set_owner_w(nskb, sk);
 
+       /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
+       if (!dst || (dst->obsolete > 1)) {
+               dst_release(dst);
+               sctp_transport_route(tp, NULL, sctp_sk(sk));
+               if (asoc && (asoc->param_flags & SPP_PMTUD_ENABLE)) {
+                       sctp_assoc_sync_pmtu(asoc);
+               }
+       }
+       nskb->dst = dst_clone(tp->dst);
+       if (!nskb->dst)
+               goto no_route;
+       dst = nskb->dst;
+
        /* Build the SCTP header.  */
        sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
        sh->source = htons(packet->source_port);
@@ -350,7 +363,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         * Note: Adler-32 is no longer applicable, as has been replaced
         * by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
         */
-       crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
+       if (!(dst->dev->features & NETIF_F_NO_CSUM))
+               crc32 = sctp_start_cksum((__u8 *)sh, sizeof(struct sctphdr));
 
        /**
         * 6.10 Bundling
@@ -402,9 +416,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                if (padding)
                        memset(skb_put(chunk->skb, padding), 0, padding);
 
-               crc32 = sctp_update_copy_cksum(skb_put(nskb, chunk->skb->len),
-                                              chunk->skb->data,
-                                              chunk->skb->len, crc32);
+               if (dst->dev->features & NETIF_F_NO_CSUM)
+                       memcpy(skb_put(nskb, chunk->skb->len),
+                              chunk->skb->data, chunk->skb->len);
+               else
+                       crc32 = sctp_update_copy_cksum(skb_put(nskb,
+                                                       chunk->skb->len),
+                                               chunk->skb->data,
+                                               chunk->skb->len, crc32);
 
                SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
                                  "*** Chunk", chunk,
@@ -427,7 +446,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        }
 
        /* Perform final transformation on checksum. */
-       crc32 = sctp_end_cksum(crc32);
+       if (!(dst->dev->features & NETIF_F_NO_CSUM))
+               crc32 = sctp_end_cksum(crc32);
 
        /* 3) Put the resultant value into the checksum field in the
         *    common header, and leave the rest of the bits unchanged.
@@ -477,20 +497,6 @@ int sctp_packet_transmit(struct sctp_packet *packet)
                }
        }
 
-       dst = tp->dst;
-       /* The 'obsolete' field of dst is set to 2 when a dst is freed. */
-       if (!dst || (dst->obsolete > 1)) {
-               dst_release(dst);
-               sctp_transport_route(tp, NULL, sctp_sk(sk));
-               if (asoc->param_flags & SPP_PMTUD_ENABLE) {
-                       sctp_assoc_sync_pmtu(asoc);
-               }
-       }
-
-       nskb->dst = dst_clone(tp->dst);
-       if (!nskb->dst)
-               goto no_route;
-
        SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
                          nskb->len);