Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b397f999 authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarNeil Horman <nhorman@tuxdriver.com>
Acked-by: default avatarVlad Yasevich <vyasevich@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 296c1063 e6d8b64b
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -11,8 +11,48 @@
extern u32  crc32_le(u32 crc, unsigned char const *p, size_t len);
extern u32  crc32_be(u32 crc, unsigned char const *p, size_t len);

/**
 * crc32_le_combine - Combine two crc32 check values into one. For two
 * 		      sequences of bytes, seq1 and seq2 with lengths len1
 * 		      and len2, crc32_le() check values were calculated
 * 		      for each, crc1 and crc2.
 *
 * @crc1: crc32 of the first block
 * @crc2: crc32 of the second block
 * @len2: length of the second block
 *
 * Return: The crc32_le() check value of seq1 and seq2 concatenated,
 * 	   requiring only crc1, crc2, and len2. Note: If seq_full denotes
 * 	   the concatenated memory area of seq1 with seq2, and crc_full
 * 	   the crc32_le() value of seq_full, then crc_full ==
 * 	   crc32_le_combine(crc1, crc2, len2) when crc_full was seeded
 * 	   with the same initializer as crc1, and crc2 seed was 0. See
 * 	   also crc32_combine_test().
 */
extern u32  crc32_le_combine(u32 crc1, u32 crc2, size_t len2);

extern u32  __crc32c_le(u32 crc, unsigned char const *p, size_t len);

/**
 * __crc32c_le_combine - Combine two crc32c check values into one. For two
 * 			 sequences of bytes, seq1 and seq2 with lengths len1
 * 			 and len2, __crc32c_le() check values were calculated
 * 			 for each, crc1 and crc2.
 *
 * @crc1: crc32c of the first block
 * @crc2: crc32c of the second block
 * @len2: length of the second block
 *
 * Return: The __crc32c_le() check value of seq1 and seq2 concatenated,
 * 	   requiring only crc1, crc2, and len2. Note: If seq_full denotes
 * 	   the concatenated memory area of seq1 with seq2, and crc_full
 * 	   the __crc32c_le() value of seq_full, then crc_full ==
 * 	   __crc32c_le_combine(crc1, crc2, len2) when crc_full was
 * 	   seeded with the same initializer as crc1, and crc2 seed
 * 	   was 0. See also crc32c_combine_test().
 */
extern u32  __crc32c_le_combine(u32 crc1, u32 crc2, size_t len2);

#define crc32(seed, data, length)  crc32_le(seed, (unsigned char const *)(data), length)

/*
+10 −3
Original line number Diff line number Diff line
@@ -2360,8 +2360,6 @@ int skb_copy_datagram_const_iovec(const struct sk_buff *from, int offset,
void skb_free_datagram(struct sock *sk, struct sk_buff *skb);
void skb_free_datagram_locked(struct sock *sk, struct sk_buff *skb);
int skb_kill_datagram(struct sock *sk, struct sk_buff *skb, unsigned int flags);
__wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
		    __wsum csum);
int skb_copy_bits(const struct sk_buff *skb, int offset, void *to, int len);
int skb_store_bits(struct sk_buff *skb, int offset, const void *from, int len);
__wsum skb_copy_and_csum_bits(const struct sk_buff *skb, int offset, u8 *to,
@@ -2373,9 +2371,18 @@ void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
void skb_scrub_packet(struct sk_buff *skb, bool xnet);

struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features);

struct skb_checksum_ops {
	__wsum (*update)(const void *mem, int len, __wsum wsum);
	__wsum (*combine)(__wsum csum, __wsum csum2, int offset, int len);
};

__wsum __skb_checksum(const struct sk_buff *skb, int offset, int len,
		      __wsum csum, const struct skb_checksum_ops *ops);
__wsum skb_checksum(const struct sk_buff *skb, int offset, int len,
		    __wsum csum);

static inline void *skb_header_pointer(const struct sk_buff *skb, int offset,
				       int len, void *buffer)
{
+6 −0
Original line number Diff line number Diff line
@@ -78,6 +78,12 @@ csum_block_add(__wsum csum, __wsum csum2, int offset)
	return csum_add(csum, (__force __wsum)sum);
}

static inline __wsum
csum_block_add_ext(__wsum csum, __wsum csum2, int offset, int len)
{
	return csum_block_add(csum, csum2, offset);
}

static inline __wsum
csum_block_sub(__wsum csum, __wsum csum2, int offset)
{
+19 −37
Original line number Diff line number Diff line
@@ -42,56 +42,38 @@
#include <linux/types.h>
#include <net/sctp/sctp.h>
#include <linux/crc32c.h>
#include <linux/crc32.h>

static inline __u32 sctp_crc32c(__u32 crc, u8 *buffer, u16 length)
static inline __wsum sctp_csum_update(const void *buff, int len, __wsum sum)
{
	return crc32c(crc, buffer, length);
}

static inline __u32 sctp_start_cksum(__u8 *buffer, __u16 length)
{
	__u32 crc = ~(__u32)0;
	__u8  zero[sizeof(__u32)] = {0};

	/* Optimize this routine to be SCTP specific, knowing how
	 * to skip the checksum field of the SCTP header.
	/* This uses the crypto implementation of crc32c, which is either
	 * implemented w/ hardware support or resolves to __crc32c_le().
	 */

	/* Calculate CRC up to the checksum. */
	crc = sctp_crc32c(crc, buffer, sizeof(struct sctphdr) - sizeof(__u32));

	/* Skip checksum field of the header. */
	crc = sctp_crc32c(crc, zero, sizeof(__u32));

	/* Calculate the rest of the CRC. */
	crc = sctp_crc32c(crc, &buffer[sizeof(struct sctphdr)],
			    length - sizeof(struct sctphdr));
	return crc;
}

static inline __u32 sctp_update_cksum(__u8 *buffer, __u16 length, __u32 crc32)
{
	return sctp_crc32c(crc32, buffer, length);
	return crc32c(sum, buff, len);
}

static inline __le32 sctp_end_cksum(__u32 crc32)
static inline __wsum sctp_csum_combine(__wsum csum, __wsum csum2,
				       int offset, int len)
{
	return cpu_to_le32(~crc32);
	return __crc32c_le_combine(csum, csum2, len);
}

/* Calculate the CRC32C checksum of an SCTP packet.  */
static inline __le32 sctp_compute_cksum(const struct sk_buff *skb,
					unsigned int offset)
{
	const struct sk_buff *iter;
	struct sctphdr *sh = sctp_hdr(skb);
        __le32 ret, old = sh->checksum;
	const struct skb_checksum_ops ops = {
		.update  = sctp_csum_update,
		.combine = sctp_csum_combine,
	};

	__u32 crc32 = sctp_start_cksum(skb->data + offset,
				       skb_headlen(skb) - offset);
	skb_walk_frags(skb, iter)
		crc32 = sctp_update_cksum((__u8 *) iter->data,
					  skb_headlen(iter), crc32);
	sh->checksum = 0;
	ret = cpu_to_le32(~__skb_checksum(skb, offset, skb->len - offset,
					  ~(__u32)0, &ops));
	sh->checksum = old;

	return sctp_end_cksum(crc32);
	return ret;
}

#endif /* __sctp_checksum_h__ */
+253 −200

File changed.

Preview size limit exceeded, changes collapsed.

Loading