backports: backport ieee802154 6lowpan support down to 3.5
authorLuis R. Rodriguez <mcgrof@do-not-panic.com>
Mon, 31 Mar 2014 07:20:25 +0000 (07:20 +0000)
committerLuis R. Rodriguez <mcgrof@do-not-panic.com>
Wed, 9 Apr 2014 01:16:21 +0000 (18:16 -0700)
Commit 633fc86ff62 added the ieee802154_6lowpan namespace
and 7240cdec60b extended it (as on linux-next next-20140311).
Its important to note though that 633fc86ff62 also extends the
global net namespace. Since we cannot extend the global net
namespace we define our own backport namespace for 6lowpan
that can be used only be used by our backported subsystems,
nothing more. Since ieee802154_6lowpan requires support for
net_get_random_once() which uses static keys and a slew of
new skb fragment support we simply require at least 3.5 to
use 6lowpan. I did my best effort to backport this to kernels
older than 3.5 but quickly ran into a slew of hairy issues.

The last thing we needed to address was usage of the helper
inet_frag_evictor() added by Alexander via commit 6b102865e7
through v3.7. Since we can't backport that with macros or
inline helpers we add a patch to carry the changes there. If
that grows we can consider using Coccinelle.

If you are going to try to backport 6lowpan to kernels older
than 3.5 be warned that the litmus test for patches will be
to pass ckmake --allyesconfig for all supported kernels for
every patch you provide.

Cc: Alexander Aring <alex.aring@gmail.com>
Cc: Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
Cc: Amerigo Wang <amwang@redhat.com>
Cc: linux-zigbee-devel@lists.sourceforge.net
Signed-off-by: Luis R. Rodriguez <mcgrof@do-not-panic.com>
backport/backport-include/net/net_namespace.h
backport/compat/backport-3.15.c
copy-list
dependencies
patches/0000-upstream-backport-changes/0001-6lowpan-namespace.patch [new file with mode: 0644]
patches/0000-upstream-backport-changes/0002-include-new-netns-headers.patch [new file with mode: 0644]
patches/collateral-evolutions/network/0012-ieee802154-6lowpan-namespace.patch [new file with mode: 0644]
patches/collateral-evolutions/network/0013-net-user-ns.patch [new file with mode: 0644]
patches/collateral-evolutions/network/0014-inet_frag_evictor.patch [new file with mode: 0644]

index f23702f24d774636fd9dd581edb717e6b914612f..efad88ec805adfe7bfc7278395babc4a7bcc2d9f 100644 (file)
@@ -2,10 +2,8 @@
 #define _COMPAT_NET_NET_NAMESPACE_H 1
 
 #include <linux/version.h>
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23))
+#include <net/netns/ieee802154_6lowpan.h>
 #include_next <net/net_namespace.h>
-#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)) */
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
 #ifdef CONFIG_NET_NS
@@ -60,4 +58,22 @@ struct net *sock_net(const struct sock *sk)
 }
 #endif /* < 2.6.26 */
 
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
+/*
+ * we provide backport for 6lowpan as per the dependencies file
+ * down to 3.5 only.
+ */
+extern struct netns_ieee802154_lowpan ieee802154_lowpan;
+struct netns_ieee802154_lowpan *net_ieee802154_lowpan(struct net *net);
+#endif
+#else
+/* This can be removed once and if this gets upstream */
+static inline struct netns_ieee802154_lowpan *
+net_ieee802154_lowpan(struct net *net)
+{
+       return &net->ieee802154_lowpan;
+}
+#endif
+
 #endif /* _COMPAT_NET_NET_NAMESPACE_H */
index 67d672bce97fa68f8d34ecdbb818f2b9665d8193..545e0c297ea6b76e45d3316c090ad6053d21ce41 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014  Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright (c) 2015  Luis R. Rodriguez <mcgrof@do-not-panic.com>
  *
  * Backport functionality introduced in Linux 3.15.
  *
 #include <linux/kernel.h>
 #include <linux/device.h>
 #include <linux/of.h>
+#include <net/net_namespace.h>
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
+/* the above kernel dependency is set to match the dependencies file */
+struct netns_ieee802154_lowpan ieee802154_lowpan;
+EXPORT_SYMBOL_GPL(ieee802154_lowpan);
+
+struct netns_ieee802154_lowpan *net_ieee802154_lowpan(struct net *net)
+{
+       return &ieee802154_lowpan;
+}
+EXPORT_SYMBOL_GPL(net_ieee802154_lowpan);
+#endif
 
 /**
  * devm_kstrdup - Allocate resource managed space and
index ceb80ba4bd5f8682a41d207ae0391b4f5540d838..76ce1c3df878e975c74bf0a5ed87083b4ff55df2 100644 (file)
--- a/copy-list
+++ b/copy-list
@@ -181,6 +181,7 @@ include/linux/platform_data/vsp1.h
 include/linux/platform_data/camera-rcar.h
 
 include/net/6lowpan.h
+include/net/netns/ieee802154_6lowpan.h
 include/net/nl802154.h
 include/net/mac802154.h
 include/net/ieee802154.h
index ec8348b4b4b6f85fed698adb259cb80df5ea7230..f5f7229c08a5c5f1fbc8ffc9eece039a9f198d83 100644 (file)
@@ -232,4 +232,5 @@ INTEL_IPS 3.2
 NFC_MEI_PHY 3.10
 
 IEEE802154_MRF24J40 3.5
-IEEE802154 2.6.38
+IEEE802154 3.1
+IEEE802154_6LOWPAN 3.5
diff --git a/patches/0000-upstream-backport-changes/0001-6lowpan-namespace.patch b/patches/0000-upstream-backport-changes/0001-6lowpan-namespace.patch
new file mode 100644 (file)
index 0000000..2f88b28
--- /dev/null
@@ -0,0 +1,143 @@
+This will be sent upstream, then we can remove this.
+The first hunk however was removed as it doesn't apply to
+our backport framework which declared net_ieee802154_lowpan(),
+for now we carry that for older and newer kernels in our own
+backport/backport-include/net/net_namespace.h file.
+
+From 2e509dac53558fda87061b06f081fde5a7cb8051 Mon Sep 17 00:00:00 2001
+From: "Luis R. Rodriguez" <mcgrof@suse.com>
+Date: Mon, 31 Mar 2014 01:53:22 -0700
+Subject: [PATCH] 6lowpan: add helper to get 6lowpan namespace
+
+This will simplify the new reassembly backport
+with no code changes.
+
+Cc:Alexander Aring <alex.aring@gmail.com>
+Signed-off-by: Luis R. Rodriguez <mcgrof@suse.com>
+---
+diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c
+index f4ac957..0bcbef3 100644
+-- 
+1.9.0
+
+--- a/net/ieee802154/reassembly.c
++++ b/net/ieee802154/reassembly.c
+@@ -123,6 +123,8 @@ fq_find(struct net *net, const struct ie
+       struct inet_frag_queue *q;
+       struct lowpan_create_arg arg;
+       unsigned int hash;
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
+       arg.tag = frag_info->d_tag;
+       arg.d_size = frag_info->d_size;
+@@ -132,7 +134,7 @@ fq_find(struct net *net, const struct ie
+       read_lock(&lowpan_frags.lock);
+       hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst);
+-      q = inet_frag_find(&net->ieee802154_lowpan.frags,
++      q = inet_frag_find(&ieee802154_lowpan->frags,
+                          &lowpan_frags, &arg, hash);
+       if (IS_ERR_OR_NULL(q)) {
+               inet_frag_maybe_warn_overflow(q, pr_fmt());
+@@ -361,16 +363,18 @@ int lowpan_frag_rcv(struct sk_buff *skb,
+       struct lowpan_frag_queue *fq;
+       struct net *net = dev_net(skb->dev);
+       struct ieee802154_frag_info *frag_info = &mac_cb(skb)->frag_info;
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
+       int err;
+       err = lowpan_get_frag_info(skb, frag_type, frag_info);
+       if (err < 0)
+               goto err;
+-      if (frag_info->d_size > net->ieee802154_lowpan.max_dsize)
++      if (frag_info->d_size > ieee802154_lowpan->max_dsize)
+               goto err;
+-      inet_frag_evictor(&net->ieee802154_lowpan.frags, &lowpan_frags, false);
++      inet_frag_evictor(&ieee802154_lowpan->frags, &lowpan_frags, false);
+       fq = fq_find(net, frag_info, &mac_cb(skb)->sa, &mac_cb(skb)->da);
+       if (fq != NULL) {
+@@ -453,6 +457,8 @@ static int __net_init lowpan_frags_ns_sy
+ {
+       struct ctl_table *table;
+       struct ctl_table_header *hdr;
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
+       table = lowpan_frags_ns_ctl_table;
+       if (!net_eq(net, &init_net)) {
+@@ -461,10 +467,10 @@ static int __net_init lowpan_frags_ns_sy
+               if (table == NULL)
+                       goto err_alloc;
+-              table[0].data = &net->ieee802154_lowpan.frags.high_thresh;
+-              table[1].data = &net->ieee802154_lowpan.frags.low_thresh;
+-              table[2].data = &net->ieee802154_lowpan.frags.timeout;
+-              table[3].data = &net->ieee802154_lowpan.max_dsize;
++              table[0].data = &ieee802154_lowpan->frags.high_thresh;
++              table[1].data = &ieee802154_lowpan->frags.low_thresh;
++              table[2].data = &ieee802154_lowpan->frags.timeout;
++              table[3].data = &ieee802154_lowpan->max_dsize;
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+@@ -475,7 +481,7 @@ static int __net_init lowpan_frags_ns_sy
+       if (hdr == NULL)
+               goto err_reg;
+-      net->ieee802154_lowpan.sysctl.frags_hdr = hdr;
++      ieee802154_lowpan->sysctl.frags_hdr = hdr;
+       return 0;
+ err_reg:
+@@ -488,9 +494,11 @@ err_alloc:
+ static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net)
+ {
+       struct ctl_table *table;
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
+-      table = net->ieee802154_lowpan.sysctl.frags_hdr->ctl_table_arg;
+-      unregister_net_sysctl_table(net->ieee802154_lowpan.sysctl.frags_hdr);
++      table = ieee802154_lowpan->sysctl.frags_hdr->ctl_table_arg;
++      unregister_net_sysctl_table(ieee802154_lowpan->sysctl.frags_hdr);
+       if (!net_eq(net, &init_net))
+               kfree(table);
+ }
+@@ -531,20 +539,26 @@ static inline void lowpan_frags_sysctl_u
+ static int __net_init lowpan_frags_init_net(struct net *net)
+ {
+-      net->ieee802154_lowpan.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
+-      net->ieee802154_lowpan.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
+-      net->ieee802154_lowpan.frags.timeout = IPV6_FRAG_TIMEOUT;
+-      net->ieee802154_lowpan.max_dsize = 0xFFFF;
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
+-      inet_frags_init_net(&net->ieee802154_lowpan.frags);
++      ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
++      ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH;
++      ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT;
++      ieee802154_lowpan->max_dsize = 0xFFFF;
++
++      inet_frags_init_net(&ieee802154_lowpan->frags);
+       return lowpan_frags_ns_sysctl_register(net);
+ }
+ static void __net_exit lowpan_frags_exit_net(struct net *net)
+ {
++      struct netns_ieee802154_lowpan *ieee802154_lowpan =
++              net_ieee802154_lowpan(net);
++
+       lowpan_frags_ns_sysctl_unregister(net);
+-      inet_frags_exit_net(&net->ieee802154_lowpan.frags, &lowpan_frags);
++      inet_frags_exit_net(&ieee802154_lowpan->frags, &lowpan_frags);
+ }
+ static struct pernet_operations lowpan_frags_ops = {
diff --git a/patches/0000-upstream-backport-changes/0002-include-new-netns-headers.patch b/patches/0000-upstream-backport-changes/0002-include-new-netns-headers.patch
new file mode 100644 (file)
index 0000000..3b00450
--- /dev/null
@@ -0,0 +1,12 @@
+This can reasonably be sent upstream.
+
+--- a/include/net/6lowpan.h
++++ b/include/net/6lowpan.h
+@@ -54,6 +54,7 @@
+ #define __6LOWPAN_H__
+ #include <net/ipv6.h>
++#include <net/net_namespace.h>
+ #define UIP_802154_SHORTADDR_LEN      2  /* compressed ipv6 address length */
+ #define UIP_IPH_LEN                   40 /* ipv6 fixed header size */
diff --git a/patches/collateral-evolutions/network/0012-ieee802154-6lowpan-namespace.patch b/patches/collateral-evolutions/network/0012-ieee802154-6lowpan-namespace.patch
new file mode 100644 (file)
index 0000000..218a768
--- /dev/null
@@ -0,0 +1,63 @@
+This is required unless we add some macro wrappers for this
+type of static work upstream but not sure if that is a good
+idea yet.
+
+--- a/net/ieee802154/reassembly.c
++++ b/net/ieee802154/reassembly.c
+@@ -104,7 +104,11 @@ static void lowpan_frag_expire(unsigned
+       struct net *net;
+       fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q);
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
+       net = container_of(fq->q.net, struct net, ieee802154_lowpan.frags);
++#else
++      net = &init_net;
++#endif
+       lowpan_expire_frag_queue(fq, &lowpan_frags);
+ }
+@@ -386,28 +390,44 @@ EXPORT_SYMBOL(lowpan_frag_rcv);
+ static struct ctl_table lowpan_frags_ns_ctl_table[] = {
+       {
+               .procname       = "6lowpanfrag_high_thresh",
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
+               .data           = &init_net.ieee802154_lowpan.frags.high_thresh,
++#else
++              .data           = &ieee802154_lowpan.frags.high_thresh,
++#endif
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {
+               .procname       = "6lowpanfrag_low_thresh",
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
+               .data           = &init_net.ieee802154_lowpan.frags.low_thresh,
++#else
++              .data           = &ieee802154_lowpan.frags.low_thresh,
++#endif
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
+       },
+       {
+               .procname       = "6lowpanfrag_time",
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
+               .data           = &init_net.ieee802154_lowpan.frags.timeout,
++#else
++              .data           = &ieee802154_lowpan.frags.timeout,
++#endif
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec_jiffies,
+       },
+       {
+               .procname       = "6lowpanfrag_max_datagram_size",
++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0))
+               .data           = &init_net.ieee802154_lowpan.max_dsize,
++#else
++              .data           = &ieee802154_lowpan.max_dsize,
++#endif
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec
diff --git a/patches/collateral-evolutions/network/0013-net-user-ns.patch b/patches/collateral-evolutions/network/0013-net-user-ns.patch
new file mode 100644 (file)
index 0000000..25752ca
--- /dev/null
@@ -0,0 +1,17 @@
+network namespaces didn't get usernamespaces pegged until 3.8
+via commit 038e7332b8.
+
+--- a/net/ieee802154/reassembly.c
++++ b/net/ieee802154/reassembly.c
+@@ -472,9 +472,11 @@ static int __net_init lowpan_frags_ns_sy
+               table[2].data = &ieee802154_lowpan->frags.timeout;
+               table[3].data = &ieee802154_lowpan->max_dsize;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0)
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       table[0].procname = NULL;
++#endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3,8,0) */
+       }
+       hdr = register_net_sysctl(net, "net/ieee802154/6lowpan", table);
diff --git a/patches/collateral-evolutions/network/0014-inet_frag_evictor.patch b/patches/collateral-evolutions/network/0014-inet_frag_evictor.patch
new file mode 100644 (file)
index 0000000..cfcbb4d
--- /dev/null
@@ -0,0 +1,20 @@
+We can't backport this with a macro or inline helper, so just
+carry the patch and if this grows consider Coccinelle SmPL version.
+
+--- a/net/ieee802154/reassembly.c
++++ b/net/ieee802154/reassembly.c
+@@ -374,7 +374,14 @@ int lowpan_frag_rcv(struct sk_buff *skb,
+       if (frag_info->d_size > ieee802154_lowpan->max_dsize)
+               goto err;
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
+       inet_frag_evictor(&ieee802154_lowpan->frags, &lowpan_frags, false);
++#else
++      if (atomic_read(&ieee802154_lowpan->frags.mem) <= &ieee802154_lowpan->frags.high_thresh)
++              return 0;
++      else
++              inet_frag_evictor(&ieee802154_lowpan->frags, &lowpan_frags);
++#endif
+       fq = fq_find(net, frag_info, &mac_cb(skb)->sa, &mac_cb(skb)->da);
+       if (fq != NULL) {