|
@@ -295,14 +295,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
struct sctp_transport *tp = packet->transport;
|
|
struct sctp_transport *tp = packet->transport;
|
|
struct sctp_association *asoc = tp->asoc;
|
|
struct sctp_association *asoc = tp->asoc;
|
|
struct sctphdr *sh;
|
|
struct sctphdr *sh;
|
|
- __u32 crc32;
|
|
|
|
|
|
+ __u32 crc32 = 0;
|
|
struct sk_buff *nskb;
|
|
struct sk_buff *nskb;
|
|
struct sctp_chunk *chunk, *tmp;
|
|
struct sctp_chunk *chunk, *tmp;
|
|
struct sock *sk;
|
|
struct sock *sk;
|
|
int err = 0;
|
|
int err = 0;
|
|
int padding; /* How much padding do we need? */
|
|
int padding; /* How much padding do we need? */
|
|
__u8 has_data = 0;
|
|
__u8 has_data = 0;
|
|
- struct dst_entry *dst;
|
|
|
|
|
|
+ struct dst_entry *dst = tp->dst;
|
|
|
|
|
|
SCTP_DEBUG_PRINTK("%s: packet:%p\n", __FUNCTION__, packet);
|
|
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);
|
|
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. */
|
|
/* Build the SCTP header. */
|
|
sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
|
|
sh = (struct sctphdr *)skb_push(nskb, sizeof(struct sctphdr));
|
|
sh->source = htons(packet->source_port);
|
|
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
|
|
* Note: Adler-32 is no longer applicable, as has been replaced
|
|
* by CRC32-C as described in <draft-ietf-tsvwg-sctpcsum-02.txt>.
|
|
* 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
|
|
* 6.10 Bundling
|
|
@@ -402,9 +416,14 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
if (padding)
|
|
if (padding)
|
|
memset(skb_put(chunk->skb, padding), 0, 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",
|
|
SCTP_DEBUG_PRINTK("%s %p[%s] %s 0x%x, %s %d, %s %d, %s %d\n",
|
|
"*** Chunk", chunk,
|
|
"*** Chunk", chunk,
|
|
@@ -427,7 +446,8 @@ int sctp_packet_transmit(struct sctp_packet *packet)
|
|
}
|
|
}
|
|
|
|
|
|
/* Perform final transformation on checksum. */
|
|
/* 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
|
|
/* 3) Put the resultant value into the checksum field in the
|
|
* common header, and leave the rest of the bits unchanged.
|
|
* 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",
|
|
SCTP_DEBUG_PRINTK("***sctp_transmit_packet*** skb len %d\n",
|
|
nskb->len);
|
|
nskb->len);
|
|
|
|
|