public inbox for b.a.t.m.a.n@lists.open-mesh.org
 help / color / mirror / Atom feed
* [B.A.T.M.A.N.] [RFC] batman-adv: Add function to calculate crc32c for the skb payload
@ 2012-10-17 15:59 Sven Eckelmann
  2012-10-17 16:11 ` Martin Hundebøll
  2012-10-17 17:18 ` [B.A.T.M.A.N.] [RFCv2] " Sven Eckelmann
  0 siblings, 2 replies; 5+ messages in thread
From: Sven Eckelmann @ 2012-10-17 15:59 UTC (permalink / raw)
  To: b.a.t.m.a.n

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
 main.c |   34 ++++++++++++++++++++++++++++++++++
 main.h |    1 +
 2 files changed, 35 insertions(+)

diff --git a/main.c b/main.c
index 70797de..122c675 100644
--- a/main.c
+++ b/main.c
@@ -33,6 +33,7 @@
 #include "vis.h"
 #include "hash.h"
 #include "bat_algo.h"
+#include <linux/crc32c.h>
 
 
 /* List manipulations on hardif_list have to be rtnl_lock()'ed,
@@ -432,6 +433,39 @@ int batadv_compat_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+/**
+ * batadv_crc32 - calculate CRC32 of the whole packet and skip bytes in header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to the point in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr)
+{
+	u32 crc = 0;
+	struct sk_buff *iter;
+	size_t skip_len, read_len;
+	const skb_frag_t *f;
+	int i;
+
+	skip_len = payload_ptr - skb->data;
+	read_len = skb_headlen(skb) - skip_len;
+	if (read_len)
+		crc = crc32c(crc, payload_ptr, read_len);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		f = &skb_shinfo(skb)->frags[i];
+		crc = crc32c(crc, skb_frag_address(f), skb_frag_size(f));
+	}
+
+	skb_walk_frags(skb, iter)
+		crc = crc32c(crc, iter->data, skb_headlen(iter));
+
+	return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
 	struct batadv_algo_ops *bat_algo_ops;
diff --git a/main.h b/main.h
index 2dfcf8c..bb0a710 100644
--- a/main.h
+++ b/main.h
@@ -177,6 +177,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_compat_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr);
 
 /**
  * enum batadv_dbg_level - available log levels
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [B.A.T.M.A.N.] [RFC] batman-adv: Add function to calculate crc32c for the skb payload
  2012-10-17 15:59 [B.A.T.M.A.N.] [RFC] batman-adv: Add function to calculate crc32c for the skb payload Sven Eckelmann
@ 2012-10-17 16:11 ` Martin Hundebøll
  2012-10-17 17:18 ` [B.A.T.M.A.N.] [RFCv2] " Sven Eckelmann
  1 sibling, 0 replies; 5+ messages in thread
From: Martin Hundebøll @ 2012-10-17 16:11 UTC (permalink / raw)
  To: b.a.t.m.a.n

On 2012-10-17 17:59, Sven Eckelmann wrote:
> +__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr)
> +{
> +	u32 crc = 0;
> +	struct sk_buff *iter;
> +	size_t skip_len, read_len;
> +	const skb_frag_t *f;
> +	int i;
> +
> +	skip_len = payload_ptr - skb->data;
> +	read_len = skb_headlen(skb) - skip_len;
> +	if (read_len)
> +		crc = crc32c(crc, payload_ptr, read_len);
> +
> +	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
> +		f = &skb_shinfo(skb)->frags[i];
> +		crc = crc32c(crc, skb_frag_address(f), skb_frag_size(f));
> +	}
> +
> +	skb_walk_frags(skb, iter)
> +		crc = crc32c(crc, iter->data, skb_headlen(iter));
> +
> +	return htonl(crc);
> +}

I tested the crc'ing of non-linear skb buffers and can confirm that it 
works as expected, so:

Tested-by: Martin Hundebøll <martin@hundeboll.net>

... at least for batadv_crc32() :)

-- 
Kind Regards
Martin Hundebøll
Frederiks Allé 99, 1.th
8000 Aarhus C
Denmark

+45 61 65 54 61
martin@hundeboll.net

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [B.A.T.M.A.N.] [RFCv2] batman-adv: Add function to calculate crc32c for the skb payload
  2012-10-17 15:59 [B.A.T.M.A.N.] [RFC] batman-adv: Add function to calculate crc32c for the skb payload Sven Eckelmann
  2012-10-17 16:11 ` Martin Hundebøll
@ 2012-10-17 17:18 ` Sven Eckelmann
  2012-10-17 19:10   ` [B.A.T.M.A.N.] [RFCv3] " Sven Eckelmann
  1 sibling, 1 reply; 5+ messages in thread
From: Sven Eckelmann @ 2012-10-17 17:18 UTC (permalink / raw)
  To: b.a.t.m.a.n

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
v2:
- Added compat code for kernel like 2.6.39
- Use kmap_atomic to get the page

 compat.h |   20 ++++++++++++++++++++
 main.c   |   38 ++++++++++++++++++++++++++++++++++++++
 main.h   |    1 +
 3 files changed, 59 insertions(+)

diff --git a/compat.h b/compat.h
index 0caf43b..4e059e8 100644
--- a/compat.h
+++ b/compat.h
@@ -146,6 +146,26 @@ static inline void skb_reset_mac_len(struct sk_buff *skb)
 #endif /* < KERNEL_VERSION(3, 0, 0) */
 
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+
+static inline struct page *skb_frag_page(const skb_frag_t *frag)
+{
+	return frag->page;
+}
+
+static inline void *skb_frag_address(const skb_frag_t *frag)
+{
+	return page_address(skb_frag_page(frag)) + frag->page_offset;
+}
+
+static inline unsigned int skb_frag_size(const skb_frag_t *frag)
+{
+	return frag->size;
+}
+
+#endif /* < KERNEL_VERSION(3, 2, 0) */
+
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
 
 static inline void eth_hw_addr_random(struct net_device *dev)
diff --git a/main.c b/main.c
index 70797de..009c9b0 100644
--- a/main.c
+++ b/main.c
@@ -33,6 +33,8 @@
 #include "vis.h"
 #include "hash.h"
 #include "bat_algo.h"
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
 
 
 /* List manipulations on hardif_list have to be rtnl_lock()'ed,
@@ -432,6 +434,42 @@ int batadv_compat_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+/**
+ * batadv_crc32 - calculate CRC32 of the whole packet and skip bytes in header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to the point in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr)
+{
+	u32 crc = 0;
+	struct sk_buff *iter;
+	size_t skip_len, read_len;
+	const skb_frag_t *f;
+	u8 *vaddr;
+	int i;
+
+	skip_len = payload_ptr - skb->data;
+	read_len = skb_headlen(skb) - skip_len;
+	if (read_len)
+		crc = crc32c(crc, payload_ptr, read_len);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		f = &skb_shinfo(skb)->frags[i];
+		vaddr = kmap_atomic(skb_frag_page(f));
+		crc = crc32c(crc, vaddr + f->page_offset, skb_frag_size(f));
+		kunmap_atomic(vaddr);
+	}
+
+	skb_walk_frags(skb, iter)
+		crc = crc32c(crc, iter->data, skb_headlen(iter));
+
+	return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
 	struct batadv_algo_ops *bat_algo_ops;
diff --git a/main.h b/main.h
index 2dfcf8c..bb0a710 100644
--- a/main.h
+++ b/main.h
@@ -177,6 +177,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_compat_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr);
 
 /**
  * enum batadv_dbg_level - available log levels
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [B.A.T.M.A.N.] [RFCv3] batman-adv: Add function to calculate crc32c for the skb payload
  2012-10-17 17:18 ` [B.A.T.M.A.N.] [RFCv2] " Sven Eckelmann
@ 2012-10-17 19:10   ` Sven Eckelmann
  2012-10-17 19:57     ` Marek Lindner
  0 siblings, 1 reply; 5+ messages in thread
From: Sven Eckelmann @ 2012-10-17 19:10 UTC (permalink / raw)
  To: b.a.t.m.a.n

Signed-off-by: Sven Eckelmann <sven@narfation.org>
---
v3: Now with support for kernels till 2.6.29

 compat.h |   34 ++++++++++++++++++++++++++++++++++
 main.c   |   38 ++++++++++++++++++++++++++++++++++++++
 main.h   |    1 +
 3 files changed, 73 insertions(+)

diff --git a/compat.h b/compat.h
index 0caf43b..83befd1 100644
--- a/compat.h
+++ b/compat.h
@@ -37,6 +37,9 @@
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
 
+#define skb_walk_frags(skb, iter)       \
+	for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next)
+
 #define __compat__module_param_call(p1, p2, p3, p4, p5, p6, p7) \
 	__module_param_call(p1, p2, p3, p4, p5, p7)
 
@@ -78,6 +81,17 @@
 #endif /* < KERNEL_VERSION(2, 6, 35) */
 
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
+
+#define kmap_atomic(p)  kmap_atomic(p, KM_SKB_DATA_SOFTIRQ)
+
+#ifdef kunmap_atomic
+#undef kunmap_atomic
+#endif
+#define kunmap_atomic(x, arg...)        do { pagefault_enable(); } while (0)
+
+#endif /* < KERNEL_VERSION(2, 6, 37) */
+
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
 
@@ -146,6 +160,26 @@ static inline void skb_reset_mac_len(struct sk_buff *skb)
 #endif /* < KERNEL_VERSION(3, 0, 0) */
 
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
+
+static inline struct page *skb_frag_page(const skb_frag_t *frag)
+{
+	return frag->page;
+}
+
+static inline void *skb_frag_address(const skb_frag_t *frag)
+{
+	return page_address(skb_frag_page(frag)) + frag->page_offset;
+}
+
+static inline unsigned int skb_frag_size(const skb_frag_t *frag)
+{
+	return frag->size;
+}
+
+#endif /* < KERNEL_VERSION(3, 2, 0) */
+
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
 
 static inline void eth_hw_addr_random(struct net_device *dev)
diff --git a/main.c b/main.c
index 70797de..df5f7d6 100644
--- a/main.c
+++ b/main.c
@@ -17,6 +17,8 @@
  * 02110-1301, USA
  */
 
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
 #include "main.h"
 #include "sysfs.h"
 #include "debugfs.h"
@@ -432,6 +434,42 @@ int batadv_compat_seq_print_text(struct seq_file *seq, void *offset)
 	return 0;
 }
 
+/**
+ * batadv_crc32 - calculate CRC32 of the whole packet and skip bytes in header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to the point in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr)
+{
+	u32 crc = 0;
+	struct sk_buff *iter;
+	size_t skip_len, read_len;
+	const skb_frag_t *f;
+	u8 *vaddr;
+	int i;
+
+	skip_len = payload_ptr - skb->data;
+	read_len = skb_headlen(skb) - skip_len;
+	if (read_len)
+		crc = crc32c(crc, payload_ptr, read_len);
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		f = &skb_shinfo(skb)->frags[i];
+		vaddr = kmap_atomic(skb_frag_page(f));
+		crc = crc32c(crc, vaddr + f->page_offset, skb_frag_size(f));
+		kunmap_atomic(vaddr);
+	}
+
+	skb_walk_frags(skb, iter)
+		crc = crc32c(crc, iter->data, skb_headlen(iter));
+
+	return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
 	struct batadv_algo_ops *bat_algo_ops;
diff --git a/main.h b/main.h
index 2dfcf8c..bb0a710 100644
--- a/main.h
+++ b/main.h
@@ -177,6 +177,7 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
 int batadv_compat_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_crc32(const struct sk_buff *skb, u8 *payload_ptr);
 
 /**
  * enum batadv_dbg_level - available log levels
-- 
1.7.10.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [B.A.T.M.A.N.] [RFCv3] batman-adv: Add function to calculate crc32c for the skb payload
  2012-10-17 19:10   ` [B.A.T.M.A.N.] [RFCv3] " Sven Eckelmann
@ 2012-10-17 19:57     ` Marek Lindner
  0 siblings, 0 replies; 5+ messages in thread
From: Marek Lindner @ 2012-10-17 19:57 UTC (permalink / raw)
  To: The list for a Better Approach To Mobile Ad-hoc Networking

On Thursday, October 18, 2012 03:10:39 Sven Eckelmann wrote:
> Signed-off-by: Sven Eckelmann <sven@narfation.org>
> ---
> v3: Now with support for kernels till 2.6.29
> 
>  compat.h |   34 ++++++++++++++++++++++++++++++++++
>  main.c   |   38 ++++++++++++++++++++++++++++++++++++++
>  main.h   |    1 +
>  3 files changed, 73 insertions(+)

Applied in revision a7fe307.

Thanks,
Marek

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-10-17 19:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-17 15:59 [B.A.T.M.A.N.] [RFC] batman-adv: Add function to calculate crc32c for the skb payload Sven Eckelmann
2012-10-17 16:11 ` Martin Hundebøll
2012-10-17 17:18 ` [B.A.T.M.A.N.] [RFCv2] " Sven Eckelmann
2012-10-17 19:10   ` [B.A.T.M.A.N.] [RFCv3] " Sven Eckelmann
2012-10-17 19:57     ` Marek Lindner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox