diff options
author | David S. Miller <davem@davemloft.net> | 2013-11-03 23:05:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-03 23:05:16 -0500 |
commit | b397f99921827e114d7f5600447e172a99c50165 (patch) | |
tree | de3bbb3dc4e08fd17fcde46aedb239d274e45d6b /net | |
parent | 296c10639a33941d0090afa17b7535fcbf81d97a (diff) | |
parent | e6d8b64b34aa8a9fe39609bc2db8a243b0331ceb (diff) |
Merge branch 'sctp_csum'
Daniel Borkmann says:
====================
SCTP fix/updates
Please see patch 5 for the main description/motivation, the rest just
brings in the needed functionality for that. Although this is actually
a fix, I've based it against net-next as some additional work for
fixing it was needed.
====================
Acked-by: Neil Horman <nhorman@tuxdriver.com>
Acked-by: Vlad Yasevich <vyasevich@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/skbuff.c | 31 | ||||
-rw-r--r-- | net/sctp/output.c | 9 |
2 files changed, 22 insertions, 18 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 0ab32faa520f..31aab5376cb4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -1928,9 +1928,8 @@ fault: | |||
1928 | EXPORT_SYMBOL(skb_store_bits); | 1928 | EXPORT_SYMBOL(skb_store_bits); |
1929 | 1929 | ||
1930 | /* Checksum skb data. */ | 1930 | /* Checksum skb data. */ |
1931 | 1931 | __wsum __skb_checksum(const struct sk_buff *skb, int offset, int len, | |
1932 | __wsum skb_checksum(const struct sk_buff *skb, int offset, | 1932 | __wsum csum, const struct skb_checksum_ops *ops) |
1933 | int len, __wsum csum) | ||
1934 | { | 1933 | { |
1935 | int start = skb_headlen(skb); | 1934 | int start = skb_headlen(skb); |
1936 | int i, copy = start - offset; | 1935 | int i, copy = start - offset; |
@@ -1941,7 +1940,7 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, | |||
1941 | if (copy > 0) { | 1940 | if (copy > 0) { |
1942 | if (copy > len) | 1941 | if (copy > len) |
1943 | copy = len; | 1942 | copy = len; |
1944 | csum = csum_partial(skb->data + offset, copy, csum); | 1943 | csum = ops->update(skb->data + offset, copy, csum); |
1945 | if ((len -= copy) == 0) | 1944 | if ((len -= copy) == 0) |
1946 | return csum; | 1945 | return csum; |
1947 | offset += copy; | 1946 | offset += copy; |
@@ -1962,10 +1961,10 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, | |||
1962 | if (copy > len) | 1961 | if (copy > len) |
1963 | copy = len; | 1962 | copy = len; |
1964 | vaddr = kmap_atomic(skb_frag_page(frag)); | 1963 | vaddr = kmap_atomic(skb_frag_page(frag)); |
1965 | csum2 = csum_partial(vaddr + frag->page_offset + | 1964 | csum2 = ops->update(vaddr + frag->page_offset + |
1966 | offset - start, copy, 0); | 1965 | offset - start, copy, 0); |
1967 | kunmap_atomic(vaddr); | 1966 | kunmap_atomic(vaddr); |
1968 | csum = csum_block_add(csum, csum2, pos); | 1967 | csum = ops->combine(csum, csum2, pos, copy); |
1969 | if (!(len -= copy)) | 1968 | if (!(len -= copy)) |
1970 | return csum; | 1969 | return csum; |
1971 | offset += copy; | 1970 | offset += copy; |
@@ -1984,9 +1983,9 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, | |||
1984 | __wsum csum2; | 1983 | __wsum csum2; |
1985 | if (copy > len) | 1984 | if (copy > len) |
1986 | copy = len; | 1985 | copy = len; |
1987 | csum2 = skb_checksum(frag_iter, offset - start, | 1986 | csum2 = __skb_checksum(frag_iter, offset - start, |
1988 | copy, 0); | 1987 | copy, 0, ops); |
1989 | csum = csum_block_add(csum, csum2, pos); | 1988 | csum = ops->combine(csum, csum2, pos, copy); |
1990 | if ((len -= copy) == 0) | 1989 | if ((len -= copy) == 0) |
1991 | return csum; | 1990 | return csum; |
1992 | offset += copy; | 1991 | offset += copy; |
@@ -1998,6 +1997,18 @@ __wsum skb_checksum(const struct sk_buff *skb, int offset, | |||
1998 | 1997 | ||
1999 | return csum; | 1998 | return csum; |
2000 | } | 1999 | } |
2000 | EXPORT_SYMBOL(__skb_checksum); | ||
2001 | |||
2002 | __wsum skb_checksum(const struct sk_buff *skb, int offset, | ||
2003 | int len, __wsum csum) | ||
2004 | { | ||
2005 | const struct skb_checksum_ops ops = { | ||
2006 | .update = csum_partial, | ||
2007 | .combine = csum_block_add_ext, | ||
2008 | }; | ||
2009 | |||
2010 | return __skb_checksum(skb, offset, len, csum, &ops); | ||
2011 | } | ||
2001 | EXPORT_SYMBOL(skb_checksum); | 2012 | EXPORT_SYMBOL(skb_checksum); |
2002 | 2013 | ||
2003 | /* Both of above in one bottle. */ | 2014 | /* Both of above in one bottle. */ |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 319137340d15..e650978daf27 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -390,7 +390,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
390 | __u8 has_data = 0; | 390 | __u8 has_data = 0; |
391 | struct dst_entry *dst = tp->dst; | 391 | struct dst_entry *dst = tp->dst; |
392 | unsigned char *auth = NULL; /* pointer to auth in skb data */ | 392 | unsigned char *auth = NULL; /* pointer to auth in skb data */ |
393 | __u32 cksum_buf_len = sizeof(struct sctphdr); | ||
394 | 393 | ||
395 | pr_debug("%s: packet:%p\n", __func__, packet); | 394 | pr_debug("%s: packet:%p\n", __func__, packet); |
396 | 395 | ||
@@ -493,7 +492,6 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
493 | if (chunk == packet->auth) | 492 | if (chunk == packet->auth) |
494 | auth = skb_tail_pointer(nskb); | 493 | auth = skb_tail_pointer(nskb); |
495 | 494 | ||
496 | cksum_buf_len += chunk->skb->len; | ||
497 | memcpy(skb_put(nskb, chunk->skb->len), | 495 | memcpy(skb_put(nskb, chunk->skb->len), |
498 | chunk->skb->data, chunk->skb->len); | 496 | chunk->skb->data, chunk->skb->len); |
499 | 497 | ||
@@ -538,12 +536,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
538 | if (!sctp_checksum_disable) { | 536 | if (!sctp_checksum_disable) { |
539 | if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || | 537 | if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || |
540 | (dst_xfrm(dst) != NULL) || packet->ipfragok) { | 538 | (dst_xfrm(dst) != NULL) || packet->ipfragok) { |
541 | __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); | 539 | sh->checksum = sctp_compute_cksum(nskb, 0); |
542 | |||
543 | /* 3) Put the resultant value into the checksum field in the | ||
544 | * common header, and leave the rest of the bits unchanged. | ||
545 | */ | ||
546 | sh->checksum = sctp_end_cksum(crc32); | ||
547 | } else { | 540 | } else { |
548 | /* no need to seed pseudo checksum for SCTP */ | 541 | /* no need to seed pseudo checksum for SCTP */ |
549 | nskb->ip_summed = CHECKSUM_PARTIAL; | 542 | nskb->ip_summed = CHECKSUM_PARTIAL; |