2014-12-08 15:50:35

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv3 bluetooth-next 0/3] 6lowpan: introduce nhc framework

This patch series introduce the next header compression framework. Currently
we support udp compression/uncompression only. This framework allow to add new
next header compression formats easily.

If somebody wants to add a new header compression format and some information
are missing while calling compression and uncompression callbacks. Please
feel free to make framework changes according these callbacks.

changes since v2:
- make udp nhc as module as suggested by Marcel Holtmann
- fix comment header in nhc_udp.c

I didn't make the lowpan_nhc declaration "const" because this will occur
issues with rb_node, id and idmask array. Which will manipulated during
runtime.

changes since v3:
- add patch 3/3 for other known rfc6282 ipv6 extension headers compression
formats
- add request_modules for loading nhc default compression format modules.
Which was suggested by Jukka Rissanen. Thanks, this is really working.
- Add rtnl_lock for lowpan_nhc_add and del since we have no synced
request_modules call this could make trouble.
- Move some handling out of nhc_do_compression and uncompression function.
The complete handling is now inside of iphc.c and nhc_do_compression and
uncompression functions is only a wrapper call for the callback.
- rework some menuentries for Kconfig and compression format, they are
grouped by rfc now.
- move some generic handling like "skb_pull(skb, nhc->nexthdrlen);" into
iphc.c. It would be great if we have something also for uncompression
for the skb_cow. But this isn't possible right now.
- change warning if nhc was not found to "was not found" instead isn't
implemented. It isn't implemented if callbacks are NULL now.
- small cleanups.

Cc: Jukka Rissanen <[email protected]>
Cc: Martin Townsend <[email protected]>
Cc: Marcel Holtmann <[email protected]>

Alexander Aring (3):
6lowpan: add generic nhc layer interface
6lowpan: add udp compression via nhc layer
6lowpan: nhc: add other known rfc6282 compressions

net/6lowpan/Kconfig | 60 ++++++++++-
net/6lowpan/Makefile | 13 ++-
net/6lowpan/iphc.c | 223 +++++++++++-----------------------------
net/6lowpan/nhc.c | 140 +++++++++++++++++++++++++
net/6lowpan/nhc.h | 142 +++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_dest.c | 27 +++++
net/6lowpan/nhc_rfc6282_frag.c | 26 +++++
net/6lowpan/nhc_rfc6282_hop.c | 26 +++++
net/6lowpan/nhc_rfc6282_ipv6.c | 26 +++++
net/6lowpan/nhc_rfc6282_mobil.c | 26 +++++
net/6lowpan/nhc_rfc6282_route.c | 26 +++++
net/6lowpan/nhc_rfc6282_udp.c | 156 ++++++++++++++++++++++++++++
12 files changed, 724 insertions(+), 167 deletions(-)
create mode 100644 net/6lowpan/nhc.c
create mode 100644 net/6lowpan/nhc.h
create mode 100644 net/6lowpan/nhc_rfc6282_dest.c
create mode 100644 net/6lowpan/nhc_rfc6282_frag.c
create mode 100644 net/6lowpan/nhc_rfc6282_hop.c
create mode 100644 net/6lowpan/nhc_rfc6282_ipv6.c
create mode 100644 net/6lowpan/nhc_rfc6282_mobil.c
create mode 100644 net/6lowpan/nhc_rfc6282_route.c
create mode 100644 net/6lowpan/nhc_rfc6282_udp.c

--
2.1.3


2014-12-10 12:04:56

by Alexander Aring

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Jukka,

On Wed, Dec 10, 2014 at 01:56:14PM +0200, Jukka Rissanen wrote:
>
> Found the problem, in bt 6lowpan the skb that was freed was still used
> by network stack. I will send a patch for this soon.
>

ok.

> >
> > >
> > > > >
> > > > > Do this please on one node, the other node should send some 6LoWPAN IPHC
> > > > > packets to check if the error handling working there.
> > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> > > > > Another issue is that I see that skb->dev isn't set before calling
> > > > > lowpan_header_decompress. Because inside your log is a "NULL":
> > > > >
> > > > > (NULL net_device): received unknown nhc id which was not found.
> > > > >
> > > > > Can you change that? That skb->dev is set to before calling
> > > > > lowpan_header_decompress.
> > > >
> > > > I am setting the skb->dev after the call to lowpan_header_decompress().
> > > > And anyway the skb->dev is only used when printing the err.
> > > > Actually should we replace the skb->dev in lowpan_header_decompress()
> > > > with plain dev as that is given to the function as a parameter.
> > > >
> > >
> > > Ok, how we introduce this now? You wanna add this do the patch series for
> > > fixing the above issue, or should I add it to my patch series for
> > > introduce nhc framework?
> >
> > I am fine with either. If you have time, please go ahead and send a
> > patch or I can do it also after figuring what is causing the crash.
>
> After second though, can you do the change as actually what I had in
> mind was to change the
>
> netdev_warn(skb->dev, ...)
> to
> netdev_warn(dev, ...)
>
> and that code is part of patch 2 of your patchset.
>
> Another thing I noticed is that we need to rate limit the output as now
> it might be that the warning is printed for every udp packet which is
> way too much.
>

ok. Or maybe simple remove the output, or make it only visable on
debugging. I don't really know what's the best notice for use that the
packet was dropping because invalid/unsupported packets.

I will do it to ratelimit and add patches for the netdev_warn(dev, ...)
thing. Currently I am working a little bit on the 802154 branch again.

I will start this work when you are done with the above fix.

- Alex

2014-12-10 11:56:14

by Jukka Rissanen

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

On ke, 2014-12-10 at 11:04 +0200, Jukka Rissanen wrote:
> Hi Alex,
>
> On ti, 2014-12-09 at 19:42 +0100, Alexander Aring wrote:
> > Hi Jukka,
> >
> > On Tue, Dec 09, 2014 at 04:05:49PM +0200, Jukka Rissanen wrote:
> > > Hi Alex,
> > >
> > > On ti, 2014-12-09 at 12:52 +0100, Alexander Aring wrote:
> > > > Hi Jukka,
> > > >
> > > > On Tue, Dec 09, 2014 at 01:28:16PM +0200, Jukka Rissanen wrote:
> > > > > Hi Alex,
> > > > >
> > > > > the module unloading caused some issues in the receiving end.
> > > > >
> > > > > I tried this:
> > > > > * setup bluetooth 6lowpan connection
> > > > > * transfer some UDP data
> > > > > * unload the nhc_rfc6282_udp module (in one peer only, the other still
> > > > > had udp nhc module loaded)
> > > > > * try to send more data
> > > > >
> > > > > This caused kernel crash in peer that had udp module unloaded:
> > > > >
> > > > >
> > > >
> > > > mhh, okay. I don't know why this happens also the log gave me not much
> > > > information, but thanks anyway.
> > > >
> > > > Maybe this is a global issue with bluetooth 6LoWPAN error handling.
> > > >
> > > > Can you simple do something like this:
> > > >
> > > > diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> > > > index 32ffec6..2228dce 100644
> > > > --- a/net/6lowpan/iphc.c
> > > > +++ b/net/6lowpan/iphc.c
> > > > @@ -425,6 +425,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
> > > > return -EINVAL;
> > > > }
> > > >
> > > > + return -EINVAL;
> > > > +
> > > > /* UDP data uncompression */
> > > > if (iphc0 & LOWPAN_IPHC_NH_C) {
> > > > struct udphdr uh;
> > > >
> > > >
> > > > based on current bluetooth-next/master without the NHC framework.
> > > >
> > > > This should be working, maybe you never hit any error while calling
> > > > lowpan_header_decompress function. It's simple testing the error
> > > > handling not more.
> > >
> > > Hmm, I get the same crash here also without this patchset. So something
> > > goes wrong if <0 code is returned.
> > >
> >
> > Okay, do you already working on it?
>
> Yes, I will investigate this.

Found the problem, in bt 6lowpan the skb that was freed was still used
by network stack. I will send a patch for this soon.

>
> >
> > > >
> > > > Do this please on one node, the other node should send some 6LoWPAN IPHC
> > > > packets to check if the error handling working there.
> > > >
> > > >
> > > >
> > > >
> > > >
> > > > Another issue is that I see that skb->dev isn't set before calling
> > > > lowpan_header_decompress. Because inside your log is a "NULL":
> > > >
> > > > (NULL net_device): received unknown nhc id which was not found.
> > > >
> > > > Can you change that? That skb->dev is set to before calling
> > > > lowpan_header_decompress.
> > >
> > > I am setting the skb->dev after the call to lowpan_header_decompress().
> > > And anyway the skb->dev is only used when printing the err.
> > > Actually should we replace the skb->dev in lowpan_header_decompress()
> > > with plain dev as that is given to the function as a parameter.
> > >
> >
> > Ok, how we introduce this now? You wanna add this do the patch series for
> > fixing the above issue, or should I add it to my patch series for
> > introduce nhc framework?
>
> I am fine with either. If you have time, please go ahead and send a
> patch or I can do it also after figuring what is causing the crash.

After second though, can you do the change as actually what I had in
mind was to change the

netdev_warn(skb->dev, ...)
to
netdev_warn(dev, ...)

and that code is part of patch 2 of your patchset.

Another thing I noticed is that we need to rate limit the output as now
it might be that the warning is printed for every udp packet which is
way too much.


Cheers,
Jukka



2014-12-10 09:04:02

by Jukka Rissanen

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Alex,

On ti, 2014-12-09 at 19:42 +0100, Alexander Aring wrote:
> Hi Jukka,
>
> On Tue, Dec 09, 2014 at 04:05:49PM +0200, Jukka Rissanen wrote:
> > Hi Alex,
> >
> > On ti, 2014-12-09 at 12:52 +0100, Alexander Aring wrote:
> > > Hi Jukka,
> > >
> > > On Tue, Dec 09, 2014 at 01:28:16PM +0200, Jukka Rissanen wrote:
> > > > Hi Alex,
> > > >
> > > > the module unloading caused some issues in the receiving end.
> > > >
> > > > I tried this:
> > > > * setup bluetooth 6lowpan connection
> > > > * transfer some UDP data
> > > > * unload the nhc_rfc6282_udp module (in one peer only, the other still
> > > > had udp nhc module loaded)
> > > > * try to send more data
> > > >
> > > > This caused kernel crash in peer that had udp module unloaded:
> > > >
> > > >
> > >
> > > mhh, okay. I don't know why this happens also the log gave me not much
> > > information, but thanks anyway.
> > >
> > > Maybe this is a global issue with bluetooth 6LoWPAN error handling.
> > >
> > > Can you simple do something like this:
> > >
> > > diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> > > index 32ffec6..2228dce 100644
> > > --- a/net/6lowpan/iphc.c
> > > +++ b/net/6lowpan/iphc.c
> > > @@ -425,6 +425,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
> > > return -EINVAL;
> > > }
> > >
> > > + return -EINVAL;
> > > +
> > > /* UDP data uncompression */
> > > if (iphc0 & LOWPAN_IPHC_NH_C) {
> > > struct udphdr uh;
> > >
> > >
> > > based on current bluetooth-next/master without the NHC framework.
> > >
> > > This should be working, maybe you never hit any error while calling
> > > lowpan_header_decompress function. It's simple testing the error
> > > handling not more.
> >
> > Hmm, I get the same crash here also without this patchset. So something
> > goes wrong if <0 code is returned.
> >
>
> Okay, do you already working on it?

Yes, I will investigate this.

>
> > >
> > > Do this please on one node, the other node should send some 6LoWPAN IPHC
> > > packets to check if the error handling working there.
> > >
> > >
> > >
> > >
> > >
> > > Another issue is that I see that skb->dev isn't set before calling
> > > lowpan_header_decompress. Because inside your log is a "NULL":
> > >
> > > (NULL net_device): received unknown nhc id which was not found.
> > >
> > > Can you change that? That skb->dev is set to before calling
> > > lowpan_header_decompress.
> >
> > I am setting the skb->dev after the call to lowpan_header_decompress().
> > And anyway the skb->dev is only used when printing the err.
> > Actually should we replace the skb->dev in lowpan_header_decompress()
> > with plain dev as that is given to the function as a parameter.
> >
>
> Ok, how we introduce this now? You wanna add this do the patch series for
> fixing the above issue, or should I add it to my patch series for
> introduce nhc framework?

I am fine with either. If you have time, please go ahead and send a
patch or I can do it also after figuring what is causing the crash.


Cheers,
Jukka



2014-12-09 18:42:52

by Alexander Aring

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Jukka,

On Tue, Dec 09, 2014 at 04:05:49PM +0200, Jukka Rissanen wrote:
> Hi Alex,
>
> On ti, 2014-12-09 at 12:52 +0100, Alexander Aring wrote:
> > Hi Jukka,
> >
> > On Tue, Dec 09, 2014 at 01:28:16PM +0200, Jukka Rissanen wrote:
> > > Hi Alex,
> > >
> > > the module unloading caused some issues in the receiving end.
> > >
> > > I tried this:
> > > * setup bluetooth 6lowpan connection
> > > * transfer some UDP data
> > > * unload the nhc_rfc6282_udp module (in one peer only, the other still
> > > had udp nhc module loaded)
> > > * try to send more data
> > >
> > > This caused kernel crash in peer that had udp module unloaded:
> > >
> > >
> >
> > mhh, okay. I don't know why this happens also the log gave me not much
> > information, but thanks anyway.
> >
> > Maybe this is a global issue with bluetooth 6LoWPAN error handling.
> >
> > Can you simple do something like this:
> >
> > diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> > index 32ffec6..2228dce 100644
> > --- a/net/6lowpan/iphc.c
> > +++ b/net/6lowpan/iphc.c
> > @@ -425,6 +425,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
> > return -EINVAL;
> > }
> >
> > + return -EINVAL;
> > +
> > /* UDP data uncompression */
> > if (iphc0 & LOWPAN_IPHC_NH_C) {
> > struct udphdr uh;
> >
> >
> > based on current bluetooth-next/master without the NHC framework.
> >
> > This should be working, maybe you never hit any error while calling
> > lowpan_header_decompress function. It's simple testing the error
> > handling not more.
>
> Hmm, I get the same crash here also without this patchset. So something
> goes wrong if <0 code is returned.
>

Okay, do you already working on it?

> >
> > Do this please on one node, the other node should send some 6LoWPAN IPHC
> > packets to check if the error handling working there.
> >
> >
> >
> >
> >
> > Another issue is that I see that skb->dev isn't set before calling
> > lowpan_header_decompress. Because inside your log is a "NULL":
> >
> > (NULL net_device): received unknown nhc id which was not found.
> >
> > Can you change that? That skb->dev is set to before calling
> > lowpan_header_decompress.
>
> I am setting the skb->dev after the call to lowpan_header_decompress().
> And anyway the skb->dev is only used when printing the err.
> Actually should we replace the skb->dev in lowpan_header_decompress()
> with plain dev as that is given to the function as a parameter.
>

Ok, how we introduce this now? You wanna add this do the patch series for
fixing the above issue, or should I add it to my patch series for
introduce nhc framework?

- Alex

2014-12-09 14:05:49

by Jukka Rissanen

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Alex,

On ti, 2014-12-09 at 12:52 +0100, Alexander Aring wrote:
> Hi Jukka,
>
> On Tue, Dec 09, 2014 at 01:28:16PM +0200, Jukka Rissanen wrote:
> > Hi Alex,
> >
> > the module unloading caused some issues in the receiving end.
> >
> > I tried this:
> > * setup bluetooth 6lowpan connection
> > * transfer some UDP data
> > * unload the nhc_rfc6282_udp module (in one peer only, the other still
> > had udp nhc module loaded)
> > * try to send more data
> >
> > This caused kernel crash in peer that had udp module unloaded:
> >
> >
>
> mhh, okay. I don't know why this happens also the log gave me not much
> information, but thanks anyway.
>
> Maybe this is a global issue with bluetooth 6LoWPAN error handling.
>
> Can you simple do something like this:
>
> diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
> index 32ffec6..2228dce 100644
> --- a/net/6lowpan/iphc.c
> +++ b/net/6lowpan/iphc.c
> @@ -425,6 +425,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
> return -EINVAL;
> }
>
> + return -EINVAL;
> +
> /* UDP data uncompression */
> if (iphc0 & LOWPAN_IPHC_NH_C) {
> struct udphdr uh;
>
>
> based on current bluetooth-next/master without the NHC framework.
>
> This should be working, maybe you never hit any error while calling
> lowpan_header_decompress function. It's simple testing the error
> handling not more.

Hmm, I get the same crash here also without this patchset. So something
goes wrong if <0 code is returned.

>
> Do this please on one node, the other node should send some 6LoWPAN IPHC
> packets to check if the error handling working there.
>
>
>
>
>
> Another issue is that I see that skb->dev isn't set before calling
> lowpan_header_decompress. Because inside your log is a "NULL":
>
> (NULL net_device): received unknown nhc id which was not found.
>
> Can you change that? That skb->dev is set to before calling
> lowpan_header_decompress.

I am setting the skb->dev after the call to lowpan_header_decompress().
And anyway the skb->dev is only used when printing the err.
Actually should we replace the skb->dev in lowpan_header_decompress()
with plain dev as that is given to the function as a parameter.

>
>
> btw: 802154 has also issues with that the dev is a wpan interface but
> should be a lowpan interface. It's a complicated issue because we
> support more than one lowpan interface at the same time for _one_ wpan
> interface. I will change that later because this has not any useful usecase
> at the moment. The new behaviour is then _one_ wpan interface -> _one_ lowpan
> interface.
>
> First we need to know if global error handling is working there. Another
> solution for the NULL string would be "don't using netdev_foo printouts,
> but then nobody knows which interface has this issue.
>
> - Alex


Cheers,
Jukka



2014-12-09 11:52:53

by Alexander Aring

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Jukka,

On Tue, Dec 09, 2014 at 01:28:16PM +0200, Jukka Rissanen wrote:
> Hi Alex,
>
> the module unloading caused some issues in the receiving end.
>
> I tried this:
> * setup bluetooth 6lowpan connection
> * transfer some UDP data
> * unload the nhc_rfc6282_udp module (in one peer only, the other still
> had udp nhc module loaded)
> * try to send more data
>
> This caused kernel crash in peer that had udp module unloaded:
>
>

mhh, okay. I don't know why this happens also the log gave me not much
information, but thanks anyway.

Maybe this is a global issue with bluetooth 6LoWPAN error handling.

Can you simple do something like this:

diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 32ffec6..2228dce 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -425,6 +425,8 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
return -EINVAL;
}

+ return -EINVAL;
+
/* UDP data uncompression */
if (iphc0 & LOWPAN_IPHC_NH_C) {
struct udphdr uh;


based on current bluetooth-next/master without the NHC framework.

This should be working, maybe you never hit any error while calling
lowpan_header_decompress function. It's simple testing the error
handling not more.

Do this please on one node, the other node should send some 6LoWPAN IPHC
packets to check if the error handling working there.





Another issue is that I see that skb->dev isn't set before calling
lowpan_header_decompress. Because inside your log is a "NULL":

(NULL net_device): received unknown nhc id which was not found.

Can you change that? That skb->dev is set to before calling
lowpan_header_decompress.


btw: 802154 has also issues with that the dev is a wpan interface but
should be a lowpan interface. It's a complicated issue because we
support more than one lowpan interface at the same time for _one_ wpan
interface. I will change that later because this has not any useful usecase
at the moment. The new behaviour is then _one_ wpan interface -> _one_ lowpan
interface.

First we need to know if global error handling is working there. Another
solution for the NULL string would be "don't using netdev_foo printouts,
but then nobody knows which interface has this issue.

- Alex

2014-12-09 11:40:02

by Jukka Rissanen

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

On ti, 2014-12-09 at 13:28 +0200, Jukka Rissanen wrote:
> Hi Alex,
>
> the module unloading caused some issues in the receiving end.

After more debugging, it was not necessary to unload the module. Just
removing the module file so that it is not loaded at all caused this
crash when UDP data was received.

Unloading the UDP nhc module in both peers works as expected. It is just
this unbalanced case that does not work.

>
> I tried this:
> * setup bluetooth 6lowpan connection
> * transfer some UDP data
> * unload the nhc_rfc6282_udp module (in one peer only, the other still
> had udp nhc module loaded)
> * try to send more data
>
> This caused kernel crash in peer that had udp module unloaded:
>
>
> [ 154.430480] (NULL net_device): received unknown nhc id which was not
> found.
> [ 154.846307] kmemleak: Cannot insert 0xcc4e2c00 into the object search
> tree (overlaps existing)
> [ 154.847036] CPU: 0 PID: 291 Comm: systemd-journal Not tainted
> 3.17.0-bt6lowpan #2
> [ 154.847036] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
> VirtualBox 12/01/2006
> [ 154.847036] cc4e2c00 00000000 ce06fd34 c1898b02 cd096320 ce06fd68
> c11716ac c1afdb94
> [ 154.847036] cc4e2c00 00000286 cd09634c 0000000e 00000010 cd09638c
> 00000000 000000d0
> [ 154.847036] cf001c00 cf001c00 ce06fd9c c1895ac8 000000d0 ce06fd80
> c10729cb 00000001
> [ 154.847036] Call Trace:
> [ 154.847036] [<c1898b02>] dump_stack+0x4b/0x75
> [ 154.847036] [<c11716ac>] create_object+0x22c/0x280
> [ 154.847036] [<c1895ac8>] kmemleak_alloc+0x38/0xb0
> [ 154.847036] [<c10729cb>] ? get_parent_ip+0xb/0x40
> [ 154.847036] [<c1072a4b>] ? preempt_count_add+0x4b/0xa0
> [ 154.847036] [<c1165123>] kmem_cache_alloc_trace+0x1c3/0x2a0
> [ 154.847036] [<c1196674>] ? seq_open+0xa4/0xc0
> [ 154.847036] [<c1196674>] seq_open+0xa4/0xc0
> [ 154.847036] [<c11c7750>] ? proc_setattr+0x50/0x50
> [ 154.847036] [<c1196f1f>] single_open+0x4f/0x90
> [ 154.847036] [<c11c8749>] proc_single_open+0x19/0x20
> [ 154.847036] [<c1172ecc>] do_dentry_open+0x19c/0x2d0
> [ 154.847036] [<c11c8730>] ? sched_open+0x20/0x20
> [ 154.847036] [<c117354b>] finish_open+0x2b/0x50
> [ 154.847036] [<c118249a>] do_last.isra.40+0x5fa/0xcc0
> [ 154.847036] [<c117fa1e>] ? link_path_walk+0x5e/0x790
> [ 154.847036] [<c1182c06>] path_openat+0xa6/0x5c0
> [ 154.847036] [<c13e0112>] ? debug_smp_processor_id+0x12/0x20
> [ 154.847036] [<c11842b1>] do_filp_open+0x31/0x90
> [ 154.847036] [<c1174727>] do_sys_open+0x117/0x210
> [ 154.847036] [<c18a192f>] ? restore_all+0xf/0xf
> [ 154.847036] [<c13e012f>] ? __this_cpu_preempt_check+0xf/0x20
> [ 154.847036] [<c1080000>] ? pick_next_task_fair+0x340/0x550
> [ 154.847036] [<c1174842>] SyS_open+0x22/0x30
> [ 154.847036] [<c18a18f6>] syscall_call+0x7/0x7
> [ 154.847036] [<c18a0000>] ? __account_scheduler_latency+0x60/0x2a0
> [ 154.847036] kmemleak: Kernel memory leak detector disabled
> [ 154.847036] kmemleak: Object 0xcc4e2c00 (size 192):
> [ 154.847036] kmemleak: comm "systemd-journal", pid 291, jiffies
> 4294822142
> [ 154.847036] kmemleak: min_count = 1
> [ 154.847036] kmemleak: count = 0
> [ 154.847036] kmemleak: flags = 0x1
> [ 154.847036] kmemleak: checksum = 0
> [ 154.847036] kmemleak: backtrace:
> [ 154.847036] [<c1895ac8>] kmemleak_alloc+0x38/0xb0
> [ 154.847036] [<c1164e83>] kmem_cache_alloc+0x1c3/0x2a0
> [ 154.847036] [<c177a5d1>] __alloc_skb+0x41/0x1b0
> [ 154.847036] [<c177a84b>] alloc_skb_with_frags+0x4b/0x1c0
> [ 154.847036] [<c177394a>] sock_alloc_send_pskb+0x1aa/0x210
> [ 154.847036] [<c1826d28>] unix_dgram_sendmsg+0x138/0x560
> [ 154.847036] [<c17702b9>] sock_sendmsg+0x59/0x80
> [ 154.847036] [<c177179f>] ___sys_sendmsg.part.30+0x2df/0x2f0
> [ 154.847036] [<c1772724>] __sys_sendmsg+0x44/0x80
> [ 154.847036] [<c1772d80>] SyS_socketcall+0xd0/0x2b0
> [ 154.847036] [<c18a18f6>] syscall_after_call+0x0/0x4
> [ 154.847036] [<ffffffff>] 0xffffffff
> [ 172.825327] Clocksource tsc unstable (delta = 14060914275 ns)
> [ 173.175027] INFO: trying to register non-static key.
> [ 173.175694] the code is fine but needs lockdep annotation.
> [ 173.175694] turning off the locking correctness validator.
> [ 173.175694] CPU: 0 PID: 378 Comm: syslogd Not tainted
> 3.17.0-bt6lowpan #2
> [ 173.175694] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
> VirtualBox 12/01/2006
> [ 173.175694] 00000000 00000000 cd669cf4 c1898b02 c22f0890 cd669d70
> c109412a c1ae4b78
> [ 173.175694] cf794500 c1ead500 00000000 cd669d44 c107770f 00000000
> 007b23e7 00000000
> [ 173.175694] c1ead500 00004a25 00004a25 c1d67cc0 00000000 cc4e58e8
> c13e0112 cd669d4c
> [ 173.175694] Call Trace:
> [ 173.175694] [<c1898b02>] dump_stack+0x4b/0x75
> [ 173.175694] [<c109412a>] __lock_acquire+0x189a/0x1d20
> [ 173.175694] [<c107770f>] ? sched_clock_cpu+0x10f/0x160
> [ 173.175694] [<c13e0112>] ? debug_smp_processor_id+0x12/0x20
> [ 173.175694] [<c108e584>] ? get_lock_stats+0x24/0x40
> [ 173.175694] [<c189fa95>] ? schedule_timeout+0x145/0x200
> [ 173.175694] [<c1090a34>] ? mark_held_locks+0x64/0x90
> [ 173.175694] [<c1094c56>] lock_acquire+0xb6/0x170
> [ 173.175694] [<c177e385>] ? __skb_recv_datagram+0x65/0x480
> [ 173.175694] [<c18a0899>] _raw_spin_lock_irqsave+0x59/0x90
> [ 173.175694] [<c177e385>] ? __skb_recv_datagram+0x65/0x480
> [ 173.175694] [<c177e385>] __skb_recv_datagram+0x65/0x480
> [ 173.175694] [<c1090cab>] ? trace_hardirqs_on+0xb/0x10
> [ 173.175694] [<c177e7e0>] ? skb_recv_datagram+0x40/0x40
> [ 173.175694] [<c182747f>] unix_dgram_recvmsg+0x7f/0x3e0
> [ 173.175694] [<c1770f06>] sock_aio_read+0xc6/0x100
> [ 173.175694] [<c10bde45>] ? clockevents_program_event+0xa5/0x150
> [ 173.175694] [<c1174ce7>] do_sync_read+0x57/0x90
> [ 173.175694] [<c1175878>] vfs_read+0x108/0x140
> [ 173.175694] [<c1175e22>] SyS_read+0x52/0xb0
> [ 173.175694] [<c18a18f6>] syscall_call+0x7/0x7
> [ 173.175694] BUG: unable to handle kernel NULL pointer dereference at
> 0000006a
> [ 173.175694] IP: [<c177e397>] __skb_recv_datagram+0x77/0x480
> [ 173.175694] *pde = 00000000
> [ 173.175694] Oops: 0000 [#1] PREEMPT SMP
> [ 173.175694] Modules linked in: nhc_rfc6282_route nhc_rfc6282_dest
> bluetooth_6lowpan nhc_rfc6282_mobil nhc_rfc6282_frag nhc_rfc6282_hop
> nhc_rfc6282_ipv6 6lowpan ecb btusb bluetooth nfc rfkill snd_intel8x0
> snd_ac97_codec ohci_pci ac97_bus parport_pc parport uvesafb [last
> unloaded: nhc_rfc6282_udp]
>

Cheers,
Jukka



2014-12-09 11:28:16

by Jukka Rissanen

[permalink] [raw]
Subject: Re: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

Hi Alex,

the module unloading caused some issues in the receiving end.

I tried this:
* setup bluetooth 6lowpan connection
* transfer some UDP data
* unload the nhc_rfc6282_udp module (in one peer only, the other still
had udp nhc module loaded)
* try to send more data

This caused kernel crash in peer that had udp module unloaded:


[ 154.430480] (NULL net_device): received unknown nhc id which was not
found.
[ 154.846307] kmemleak: Cannot insert 0xcc4e2c00 into the object search
tree (overlaps existing)
[ 154.847036] CPU: 0 PID: 291 Comm: systemd-journal Not tainted
3.17.0-bt6lowpan #2
[ 154.847036] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
VirtualBox 12/01/2006
[ 154.847036] cc4e2c00 00000000 ce06fd34 c1898b02 cd096320 ce06fd68
c11716ac c1afdb94
[ 154.847036] cc4e2c00 00000286 cd09634c 0000000e 00000010 cd09638c
00000000 000000d0
[ 154.847036] cf001c00 cf001c00 ce06fd9c c1895ac8 000000d0 ce06fd80
c10729cb 00000001
[ 154.847036] Call Trace:
[ 154.847036] [<c1898b02>] dump_stack+0x4b/0x75
[ 154.847036] [<c11716ac>] create_object+0x22c/0x280
[ 154.847036] [<c1895ac8>] kmemleak_alloc+0x38/0xb0
[ 154.847036] [<c10729cb>] ? get_parent_ip+0xb/0x40
[ 154.847036] [<c1072a4b>] ? preempt_count_add+0x4b/0xa0
[ 154.847036] [<c1165123>] kmem_cache_alloc_trace+0x1c3/0x2a0
[ 154.847036] [<c1196674>] ? seq_open+0xa4/0xc0
[ 154.847036] [<c1196674>] seq_open+0xa4/0xc0
[ 154.847036] [<c11c7750>] ? proc_setattr+0x50/0x50
[ 154.847036] [<c1196f1f>] single_open+0x4f/0x90
[ 154.847036] [<c11c8749>] proc_single_open+0x19/0x20
[ 154.847036] [<c1172ecc>] do_dentry_open+0x19c/0x2d0
[ 154.847036] [<c11c8730>] ? sched_open+0x20/0x20
[ 154.847036] [<c117354b>] finish_open+0x2b/0x50
[ 154.847036] [<c118249a>] do_last.isra.40+0x5fa/0xcc0
[ 154.847036] [<c117fa1e>] ? link_path_walk+0x5e/0x790
[ 154.847036] [<c1182c06>] path_openat+0xa6/0x5c0
[ 154.847036] [<c13e0112>] ? debug_smp_processor_id+0x12/0x20
[ 154.847036] [<c11842b1>] do_filp_open+0x31/0x90
[ 154.847036] [<c1174727>] do_sys_open+0x117/0x210
[ 154.847036] [<c18a192f>] ? restore_all+0xf/0xf
[ 154.847036] [<c13e012f>] ? __this_cpu_preempt_check+0xf/0x20
[ 154.847036] [<c1080000>] ? pick_next_task_fair+0x340/0x550
[ 154.847036] [<c1174842>] SyS_open+0x22/0x30
[ 154.847036] [<c18a18f6>] syscall_call+0x7/0x7
[ 154.847036] [<c18a0000>] ? __account_scheduler_latency+0x60/0x2a0
[ 154.847036] kmemleak: Kernel memory leak detector disabled
[ 154.847036] kmemleak: Object 0xcc4e2c00 (size 192):
[ 154.847036] kmemleak: comm "systemd-journal", pid 291, jiffies
4294822142
[ 154.847036] kmemleak: min_count = 1
[ 154.847036] kmemleak: count = 0
[ 154.847036] kmemleak: flags = 0x1
[ 154.847036] kmemleak: checksum = 0
[ 154.847036] kmemleak: backtrace:
[ 154.847036] [<c1895ac8>] kmemleak_alloc+0x38/0xb0
[ 154.847036] [<c1164e83>] kmem_cache_alloc+0x1c3/0x2a0
[ 154.847036] [<c177a5d1>] __alloc_skb+0x41/0x1b0
[ 154.847036] [<c177a84b>] alloc_skb_with_frags+0x4b/0x1c0
[ 154.847036] [<c177394a>] sock_alloc_send_pskb+0x1aa/0x210
[ 154.847036] [<c1826d28>] unix_dgram_sendmsg+0x138/0x560
[ 154.847036] [<c17702b9>] sock_sendmsg+0x59/0x80
[ 154.847036] [<c177179f>] ___sys_sendmsg.part.30+0x2df/0x2f0
[ 154.847036] [<c1772724>] __sys_sendmsg+0x44/0x80
[ 154.847036] [<c1772d80>] SyS_socketcall+0xd0/0x2b0
[ 154.847036] [<c18a18f6>] syscall_after_call+0x0/0x4
[ 154.847036] [<ffffffff>] 0xffffffff
[ 172.825327] Clocksource tsc unstable (delta = 14060914275 ns)
[ 173.175027] INFO: trying to register non-static key.
[ 173.175694] the code is fine but needs lockdep annotation.
[ 173.175694] turning off the locking correctness validator.
[ 173.175694] CPU: 0 PID: 378 Comm: syslogd Not tainted
3.17.0-bt6lowpan #2
[ 173.175694] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS
VirtualBox 12/01/2006
[ 173.175694] 00000000 00000000 cd669cf4 c1898b02 c22f0890 cd669d70
c109412a c1ae4b78
[ 173.175694] cf794500 c1ead500 00000000 cd669d44 c107770f 00000000
007b23e7 00000000
[ 173.175694] c1ead500 00004a25 00004a25 c1d67cc0 00000000 cc4e58e8
c13e0112 cd669d4c
[ 173.175694] Call Trace:
[ 173.175694] [<c1898b02>] dump_stack+0x4b/0x75
[ 173.175694] [<c109412a>] __lock_acquire+0x189a/0x1d20
[ 173.175694] [<c107770f>] ? sched_clock_cpu+0x10f/0x160
[ 173.175694] [<c13e0112>] ? debug_smp_processor_id+0x12/0x20
[ 173.175694] [<c108e584>] ? get_lock_stats+0x24/0x40
[ 173.175694] [<c189fa95>] ? schedule_timeout+0x145/0x200
[ 173.175694] [<c1090a34>] ? mark_held_locks+0x64/0x90
[ 173.175694] [<c1094c56>] lock_acquire+0xb6/0x170
[ 173.175694] [<c177e385>] ? __skb_recv_datagram+0x65/0x480
[ 173.175694] [<c18a0899>] _raw_spin_lock_irqsave+0x59/0x90
[ 173.175694] [<c177e385>] ? __skb_recv_datagram+0x65/0x480
[ 173.175694] [<c177e385>] __skb_recv_datagram+0x65/0x480
[ 173.175694] [<c1090cab>] ? trace_hardirqs_on+0xb/0x10
[ 173.175694] [<c177e7e0>] ? skb_recv_datagram+0x40/0x40
[ 173.175694] [<c182747f>] unix_dgram_recvmsg+0x7f/0x3e0
[ 173.175694] [<c1770f06>] sock_aio_read+0xc6/0x100
[ 173.175694] [<c10bde45>] ? clockevents_program_event+0xa5/0x150
[ 173.175694] [<c1174ce7>] do_sync_read+0x57/0x90
[ 173.175694] [<c1175878>] vfs_read+0x108/0x140
[ 173.175694] [<c1175e22>] SyS_read+0x52/0xb0
[ 173.175694] [<c18a18f6>] syscall_call+0x7/0x7
[ 173.175694] BUG: unable to handle kernel NULL pointer dereference at
0000006a
[ 173.175694] IP: [<c177e397>] __skb_recv_datagram+0x77/0x480
[ 173.175694] *pde = 00000000
[ 173.175694] Oops: 0000 [#1] PREEMPT SMP
[ 173.175694] Modules linked in: nhc_rfc6282_route nhc_rfc6282_dest
bluetooth_6lowpan nhc_rfc6282_mobil nhc_rfc6282_frag nhc_rfc6282_hop
nhc_rfc6282_ipv6 6lowpan ecb btusb bluetooth nfc rfkill snd_intel8x0
snd_ac97_codec ohci_pci ac97_bus parport_pc parport uvesafb [last
unloaded: nhc_rfc6282_udp]



Cheers,
Jukka



2014-12-08 15:50:36

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv3 bluetooth-next 1/3] 6lowpan: add generic nhc layer interface

This patch adds a generic next header compression layer interface. There
exists various methods to do a header compression after 6LoWPAN header
to save payload. This introduce a generic nhc header which allow a
simple adding of a new header compression format instead of a static
implementation inside the 6LoWPAN header compression and uncompression
function.

Signed-off-by: Alexander Aring <[email protected]>
Cc: Jukka Rissanen <[email protected]>
Cc: Martin Townsend <[email protected]>
---
net/6lowpan/Makefile | 2 +-
net/6lowpan/nhc.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++
net/6lowpan/nhc.h | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 283 insertions(+), 1 deletion(-)
create mode 100644 net/6lowpan/nhc.c
create mode 100644 net/6lowpan/nhc.h

diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile
index 415886b..4215602 100644
--- a/net/6lowpan/Makefile
+++ b/net/6lowpan/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_6LOWPAN) := 6lowpan.o

-6lowpan-y := iphc.o
+6lowpan-y := iphc.o nhc.o
diff --git a/net/6lowpan/nhc.c b/net/6lowpan/nhc.c
new file mode 100644
index 0000000..8c4438c
--- /dev/null
+++ b/net/6lowpan/nhc.c
@@ -0,0 +1,140 @@
+/*
+ * 6LoWPAN next header compression
+ *
+ *
+ * Authors:
+ * Alexander Aring <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/netdevice.h>
+
+#include <net/ipv6.h>
+
+#include "nhc.h"
+
+static struct rb_root rb_root = RB_ROOT;
+static struct lowpan_nhc *lowpan_nexthdr_nhcs[NEXTHDR_MAX];
+
+static int lowpan_nhc_insert(struct lowpan_nhc *nhc)
+{
+ struct rb_node **new = &rb_root.rb_node, *parent = NULL;
+
+ /* Figure out where to put new node */
+ while (*new) {
+ struct lowpan_nhc *this = container_of(*new, struct lowpan_nhc,
+ node);
+ int result, len_dif, len;
+
+ len_dif = nhc->idlen - this->idlen;
+
+ if (nhc->idlen < this->idlen)
+ len = nhc->idlen;
+ else
+ len = this->idlen;
+
+ result = memcmp(nhc->id, this->id, len);
+ if (!result)
+ result = len_dif;
+
+ parent = *new;
+ if (result < 0)
+ new = &((*new)->rb_left);
+ else if (result > 0)
+ new = &((*new)->rb_right);
+ else
+ return -EEXIST;
+ }
+
+ /* Add new node and rebalance tree. */
+ rb_link_node(&nhc->node, parent, new);
+ rb_insert_color(&nhc->node, &rb_root);
+
+ return 0;
+}
+
+static void lowpan_nhc_remove(struct lowpan_nhc *nhc)
+{
+ rb_erase(&nhc->node, &rb_root);
+}
+
+struct lowpan_nhc *lowpan_nhc_by_nhcid(const struct sk_buff *skb)
+{
+ struct rb_node *node = rb_root.rb_node;
+ const u8 *nhcid_skb_ptr = skb->data;
+
+ while (node) {
+ struct lowpan_nhc *nhc = container_of(node, struct lowpan_nhc,
+ node);
+ u8 nhcid_skb_ptr_masked[LOWPAN_NHC_MAX_ID_LEN];
+ int result, i;
+
+ if (nhcid_skb_ptr + nhc->idlen > skb->data + skb->len)
+ return NULL;
+
+ /* copy and mask afterwards the nhid value from skb */
+ memcpy(nhcid_skb_ptr_masked, nhcid_skb_ptr, nhc->idlen);
+ for (i = 0; i < nhc->idlen; i++)
+ nhcid_skb_ptr_masked[i] &= nhc->idmask[i];
+
+ result = memcmp(nhcid_skb_ptr_masked, nhc->id, nhc->idlen);
+ if (result < 0)
+ node = node->rb_left;
+ else if (result > 0)
+ node = node->rb_right;
+ else
+ return nhc;
+ }
+
+ return NULL;
+}
+
+struct lowpan_nhc *lowpan_nhc_by_nexthdr(u8 nexthdr)
+{
+ return lowpan_nexthdr_nhcs[nexthdr];
+}
+
+int lowpan_nhc_add(struct lowpan_nhc *nhc)
+{
+ int ret;
+
+ if (!nhc->idlen || !nhc->idsetup)
+ return -EINVAL;
+
+ WARN_ONCE(nhc->idlen > LOWPAN_NHC_MAX_ID_LEN,
+ "LOWPAN_NHC_MAX_ID_LEN should be updated to %d.\n",
+ nhc->idlen);
+
+ nhc->idsetup(nhc);
+
+ rtnl_lock();
+ if (lowpan_nexthdr_nhcs[nhc->nexthdr]) {
+ ret = -EEXIST;
+ goto out;
+ }
+
+ ret = lowpan_nhc_insert(nhc);
+ if (ret < 0)
+ goto out;
+
+ lowpan_nexthdr_nhcs[nhc->nexthdr] = nhc;
+out:
+ rtnl_unlock();
+ return ret;
+}
+EXPORT_SYMBOL(lowpan_nhc_add);
+
+void lowpan_nhc_del(struct lowpan_nhc *nhc)
+{
+ rtnl_lock();
+ lowpan_nhc_remove(nhc);
+ lowpan_nexthdr_nhcs[nhc->nexthdr] = NULL;
+
+ synchronize_net();
+ rtnl_unlock();
+}
+EXPORT_SYMBOL(lowpan_nhc_del);
diff --git a/net/6lowpan/nhc.h b/net/6lowpan/nhc.h
new file mode 100644
index 0000000..7141b94
--- /dev/null
+++ b/net/6lowpan/nhc.h
@@ -0,0 +1,142 @@
+#ifndef __6LOWPAN_NHC_H
+#define __6LOWPAN_NHC_H
+
+#include <linux/skbuff.h>
+#include <linux/rbtree.h>
+#include <linux/module.h>
+
+#include <net/6lowpan.h>
+#include <net/ipv6.h>
+
+#define LOWPAN_NHC_MAX_ID_LEN 1
+
+/**
+ * LOWPAN_NHC - helper macro to generate nh id fields and lowpan_nhc struct
+ *
+ * @__nhc: variable name of the lowpan_nhc struct.
+ * @_name: const char * of common header compression name.
+ * @_nexthdr: ipv6 nexthdr field for the header compression.
+ * @_nexthdrlen: ipv6 nexthdr len for the reserved space.
+ * @_idsetup: callback to setup id and mask values.
+ * @_idlen: len for the next header id and mask, should be always the same.
+ * @_uncompress: callback for uncompression call.
+ * @_compress: callback for compression call.
+ */
+#define LOWPAN_NHC(__nhc, _name, _nexthdr, \
+ _hdrlen, _idsetup, _idlen, \
+ _uncompress, _compress) \
+static u8 __nhc##_val[_idlen]; \
+static u8 __nhc##_mask[_idlen]; \
+static struct lowpan_nhc __nhc = { \
+ .name = _name, \
+ .nexthdr = _nexthdr, \
+ .nexthdrlen = _hdrlen, \
+ .id = __nhc##_val, \
+ .idmask = __nhc##_mask, \
+ .idlen = _idlen, \
+ .idsetup = _idsetup, \
+ .uncompress = _uncompress, \
+ .compress = _compress, \
+}
+
+#define module_lowpan_nhc(__nhc) \
+static int __init __nhc##_init(void) \
+{ \
+ return lowpan_nhc_add(&(__nhc)); \
+} \
+module_init(__nhc##_init); \
+static void __exit __nhc##_exit(void) \
+{ \
+ lowpan_nhc_del(&(__nhc)); \
+} \
+module_exit(__nhc##_exit);
+
+/**
+ * struct lowpan_nhc - hold 6lowpan next hdr compression ifnformation
+ *
+ * @node: holder for the rbtree.
+ * @name: name of the specific next header compression
+ * @nexthdr: next header value of the protocol which should be compressed.
+ * @nexthdrlen: ipv6 nexthdr len for the reserved space.
+ * @id: array for nhc id. Note this need to be in network byteorder.
+ * @mask: array for nhc id mask. Note this need to be in network byteorder.
+ * @len: the length of the next header id and mask.
+ * @setup: callback to setup fill the next header id value and mask.
+ * @compress: callback to do the header compression.
+ * @uncompress: callback to do the header uncompression.
+ */
+struct lowpan_nhc {
+ struct rb_node node;
+ const char *name;
+ const u8 nexthdr;
+ const size_t nexthdrlen;
+ u8 *id;
+ u8 *idmask;
+ const size_t idlen;
+
+ void (*idsetup)(struct lowpan_nhc *nhc);
+ int (*uncompress)(struct sk_buff *skb, size_t needed);
+ int (*compress)(struct sk_buff *skb, u8 **hc_ptr);
+};
+
+/**
+ * lowpan_nhc_by_nhcid - returns the 6lowpan nhc by nhcid
+ *
+ * @skb: skb with skb->data which is pointed to 6lowpan nhc id.
+ */
+struct lowpan_nhc *lowpan_nhc_by_nhcid(const struct sk_buff *skb);
+
+/**
+ * lowpan_nhc_by_nexthdr - return the 6lowpan nhc by ipv6 nexthdr.
+ *
+ * @nexthdr: ipv6 nexthdr value.
+ */
+struct lowpan_nhc *lowpan_nhc_by_nexthdr(u8 nexthdr);
+
+/**
+ * lowpan_nhc_do_compression - calling compress callback for nhc
+ *
+ * @nhc: 6LoWPAN nhc context, get by lowpan_nhc_by_ functions.
+ * @skb: skb of 6LoWPAN header to read nhc and replace header.
+ * @hc_ptr: pointer for 6LoWPAN header which should increment at the end of
+ * replaced header.
+ */
+static inline int
+lowpan_nhc_do_compression(struct lowpan_nhc *nhc, struct sk_buff *skb,
+ u8 **hc_ptr)
+{
+ return nhc->compress(skb, hc_ptr);
+}
+
+/**
+ * lowpan_nhc_do_uncompression - calling uncompress callback for nhc
+ *
+ * @nhc: 6LoWPAN nhc context, get by lowpan_nhc_by_ functions.
+ * @skb: skb of 6LoWPAN header, skb->data should be pointed to nhc id value.
+ */
+static inline int
+lowpan_nhc_do_uncompression(struct lowpan_nhc *nhc, struct sk_buff *skb)
+{
+ return nhc->uncompress(skb, sizeof(struct ipv6hdr) + nhc->nexthdrlen);
+}
+
+/**
+ * lowpan_nhc_add - register a next header compression to framework
+ *
+ * @nhc: nhc which should be add.
+ */
+int lowpan_nhc_add(struct lowpan_nhc *nhc);
+
+/**
+ * lowpan_nhc_del - delete a next header compression from framework
+ *
+ * @nhc: nhc which should be delete.
+ */
+void lowpan_nhc_del(struct lowpan_nhc *nhc);
+
+/**
+ * lowpan_nhc_init - adding all default nhcs
+ */
+void lowpan_nhc_init(void);
+
+#endif /* __6LOWPAN_NHC_H */
--
2.1.3


2014-12-08 15:50:38

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv3 bluetooth-next 3/3] 6lowpan: nhc: add other known rfc6282 compressions

This patch adds other known rfc6282 compression formats to the nhc
framework. These compression formats are known but not implemented yet.
For now this is useful to printout a warning which compression format
isn't supported.

Signed-off-by: Alexander Aring <[email protected]>
Cc: Jukka Rissanen <[email protected]>
Cc: Martin Townsend <[email protected]>
---
net/6lowpan/Kconfig | 44 +++++++++++++++++++++++++++++++++++++++++
net/6lowpan/Makefile | 6 ++++++
net/6lowpan/iphc.c | 6 ++++++
net/6lowpan/nhc_rfc6282_dest.c | 27 +++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_frag.c | 26 ++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_hop.c | 26 ++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_ipv6.c | 26 ++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_mobil.c | 26 ++++++++++++++++++++++++
net/6lowpan/nhc_rfc6282_route.c | 26 ++++++++++++++++++++++++
9 files changed, 213 insertions(+)
create mode 100644 net/6lowpan/nhc_rfc6282_dest.c
create mode 100644 net/6lowpan/nhc_rfc6282_frag.c
create mode 100644 net/6lowpan/nhc_rfc6282_hop.c
create mode 100644 net/6lowpan/nhc_rfc6282_ipv6.c
create mode 100644 net/6lowpan/nhc_rfc6282_mobil.c
create mode 100644 net/6lowpan/nhc_rfc6282_route.c

diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig
index bef92b2..b6faf4f 100644
--- a/net/6lowpan/Kconfig
+++ b/net/6lowpan/Kconfig
@@ -18,3 +18,47 @@ config 6LOWPAN_NHC_RFC6282_UDP
default y
---help---
6LoWPAN IPv6 UDP Header compression according to RFC6282
+
+config 6LOWPAN_NHC_RFC6282_DEST
+ tristate "Destination Options Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Destination Options Header compression according to
+ RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_FRAG
+ tristate "Fragment Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Fragment Header compression according to RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_HOP
+ tristate "Hop-by-Hop Options Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Hop-by-Hop Options Header compression according to
+ RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_IPV6
+ tristate "IPv6 Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Header compression according to RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_MOBIL
+ tristate "Mobility Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Mobility Header compression according to RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_ROUTE
+ tristate "Routing Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 Routing Header compression according to RFC6282.
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile
index 9593f48..5466fe5 100644
--- a/net/6lowpan/Makefile
+++ b/net/6lowpan/Makefile
@@ -4,3 +4,9 @@ obj-$(CONFIG_6LOWPAN) += 6lowpan.o

#rfc6282 nhc
obj-$(CONFIG_6LOWPAN_NHC_RFC6282_UDP) += nhc_rfc6282_udp.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_DEST) += nhc_rfc6282_dest.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_FRAG) += nhc_rfc6282_frag.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_HOP) += nhc_rfc6282_hop.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_IPV6) += nhc_rfc6282_ipv6.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_MOBIL) += nhc_rfc6282_mobil.o
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_ROUTE) += nhc_rfc6282_route.o
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index d7b624d..7f106c5 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -644,6 +644,12 @@ EXPORT_SYMBOL_GPL(lowpan_header_compress);

static int __init lowpan_module_init(void)
{
+ request_module_nowait("nhc_rfc6282_dest");
+ request_module_nowait("nhc_rfc6282_frag");
+ request_module_nowait("nhc_rfc6282_hop");
+ request_module_nowait("nhc_rfc6282_ipv6");
+ request_module_nowait("nhc_rfc6282_mobil");
+ request_module_nowait("nhc_rfc6282_route");
request_module_nowait("nhc_rfc6282_udp");

return 0;
diff --git a/net/6lowpan/nhc_rfc6282_dest.c b/net/6lowpan/nhc_rfc6282_dest.c
new file mode 100644
index 0000000..6306907
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_dest.c
@@ -0,0 +1,27 @@
+/*
+ * 6LoWPAN IPv6 Destination Options Header compression according to
+ * RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_DEST_IDLEN 1
+#define LOWPAN_NHC_DEST_ID_0 0xe6
+#define LOWPAN_NHC_DEST_MASK_0 0xfe
+
+static void dest_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_DEST_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_DEST_MASK_0;
+}
+
+LOWPAN_NHC(nhc_dest, "RFC6282 Destination Options", NEXTHDR_DEST, 0,
+ dest_nhid_setup, LOWPAN_NHC_DEST_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_dest);
+MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_frag.c b/net/6lowpan/nhc_rfc6282_frag.c
new file mode 100644
index 0000000..1ca80ab
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_frag.c
@@ -0,0 +1,26 @@
+/*
+ * 6LoWPAN IPv6 Fragment Header compression according to RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_FRAG_IDLEN 1
+#define LOWPAN_NHC_FRAG_ID_0 0xe4
+#define LOWPAN_NHC_FRAG_MASK_0 0xfe
+
+static void frag_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_FRAG_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_FRAG_MASK_0;
+}
+
+LOWPAN_NHC(nhc_frag, "RFC6282 Fragment", NEXTHDR_FRAGMENT, 0,
+ frag_nhid_setup, LOWPAN_NHC_FRAG_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_frag);
+MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_hop.c b/net/6lowpan/nhc_rfc6282_hop.c
new file mode 100644
index 0000000..c4fa968
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_hop.c
@@ -0,0 +1,26 @@
+/*
+ * 6LoWPAN IPv6 Hop-by-Hop Options Header compression according to RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_HOP_IDLEN 1
+#define LOWPAN_NHC_HOP_ID_0 0xe0
+#define LOWPAN_NHC_HOP_MASK_0 0xfe
+
+static void hop_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_HOP_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_HOP_MASK_0;
+}
+
+LOWPAN_NHC(nhc_hop, "RFC6282 Hop-by-Hop Options", NEXTHDR_HOP, 0,
+ hop_nhid_setup, LOWPAN_NHC_HOP_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_hop);
+MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_ipv6.c b/net/6lowpan/nhc_rfc6282_ipv6.c
new file mode 100644
index 0000000..306295f
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_ipv6.c
@@ -0,0 +1,26 @@
+/*
+ * 6LoWPAN IPv6 Header compression according to RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_IPV6_IDLEN 1
+#define LOWPAN_NHC_IPV6_ID_0 0xee
+#define LOWPAN_NHC_IPV6_MASK_0 0xfe
+
+static void ipv6_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_IPV6_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_IPV6_MASK_0;
+}
+
+LOWPAN_NHC(nhc_ipv6, "RFC6282 IPv6", NEXTHDR_IPV6, 0, ipv6_nhid_setup,
+ LOWPAN_NHC_IPV6_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_ipv6);
+MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_mobil.c b/net/6lowpan/nhc_rfc6282_mobil.c
new file mode 100644
index 0000000..b2ed933
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_mobil.c
@@ -0,0 +1,26 @@
+/*
+ * 6LoWPAN IPv6 Mobility Header compression according to RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_MOBIL_IDLEN 1
+#define LOWPAN_NHC_MOBIL_ID_0 0xe8
+#define LOWPAN_NHC_MOBIL_MASK_0 0xfe
+
+static void mobil_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_MOBIL_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_MOBIL_MASK_0;
+}
+
+LOWPAN_NHC(nhc_mobil, "RFC6282 Mobility", NEXTHDR_MOBILITY, 0,
+ mobil_nhid_setup, LOWPAN_NHC_MOBIL_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_mobil);
+MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_route.c b/net/6lowpan/nhc_rfc6282_route.c
new file mode 100644
index 0000000..f4b065a
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_route.c
@@ -0,0 +1,26 @@
+/*
+ * 6LoWPAN IPv6 Routing Header compression according to RFC6282
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_ROUTE_IDLEN 1
+#define LOWPAN_NHC_ROUTE_ID_0 0xe2
+#define LOWPAN_NHC_ROUTE_MASK_0 0xfe
+
+static void route_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_ROUTE_ID_0;
+ nhc->idmask[0] = LOWPAN_NHC_ROUTE_MASK_0;
+}
+
+LOWPAN_NHC(nhc_route, "RFC6282 Routing", NEXTHDR_ROUTING, 0, route_nhid_setup,
+ LOWPAN_NHC_ROUTE_IDLEN, NULL, NULL);
+
+module_lowpan_nhc(nhc_route);
+MODULE_LICENSE("GPL");
--
2.1.3


2014-12-08 15:50:37

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv3 bluetooth-next 2/3] 6lowpan: add udp compression via nhc layer

This patch move UDP header compression and uncompression into the
generic 6LoWPAN nhc header compression layer. Moreover this patch
activates the nhc layer compression in iphc compression and
uncompression functions.

Signed-off-by: Alexander Aring <[email protected]>
Cc: Jukka Rissanen <[email protected]>
Cc: Martin Townsend <[email protected]>
---
net/6lowpan/Kconfig | 16 +++-
net/6lowpan/Makefile | 5 +-
net/6lowpan/iphc.c | 217 +++++++++++-------------------------------
net/6lowpan/nhc_rfc6282_udp.c | 156 ++++++++++++++++++++++++++++++
4 files changed, 228 insertions(+), 166 deletions(-)
create mode 100644 net/6lowpan/nhc_rfc6282_udp.c

diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig
index e4a02ef..bef92b2 100644
--- a/net/6lowpan/Kconfig
+++ b/net/6lowpan/Kconfig
@@ -1,6 +1,20 @@
-config 6LOWPAN
+menuconfig 6LOWPAN
tristate "6LoWPAN Support"
depends on IPV6
---help---
This enables IPv6 over Low power Wireless Personal Area Network -
"6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks.
+
+menuconfig 6LOWPAN_NHC_RFC6282
+ tristate "NHC RFC6282"
+ depends on 6LOWPAN
+ default y
+ ---help---
+ Support for next header compression accroding to RFC6282.
+
+config 6LOWPAN_NHC_RFC6282_UDP
+ tristate "UDP Header Support"
+ depends on 6LOWPAN_NHC_RFC6282
+ default y
+ ---help---
+ 6LoWPAN IPv6 UDP Header compression according to RFC6282
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile
index 4215602..9593f48 100644
--- a/net/6lowpan/Makefile
+++ b/net/6lowpan/Makefile
@@ -1,3 +1,6 @@
-obj-$(CONFIG_6LOWPAN) := 6lowpan.o
+obj-$(CONFIG_6LOWPAN) += 6lowpan.o

6lowpan-y := iphc.o nhc.o
+
+#rfc6282 nhc
+obj-$(CONFIG_6LOWPAN_NHC_RFC6282_UDP) += nhc_rfc6282_udp.o
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
index 32ffec6..d7b624d 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -54,6 +54,8 @@
#include <net/ipv6.h>
#include <net/af_ieee802154.h>

+#include "nhc.h"
+
/* Uncompress address function for source and
* destination address(non-multicast).
*
@@ -224,77 +226,6 @@ static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
return 0;
}

-static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
- bool fail;
- u8 tmp = 0, val = 0;
-
- fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
-
- if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
- pr_debug("UDP header uncompression\n");
- switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
- case LOWPAN_NHC_UDP_CS_P_00:
- fail |= lowpan_fetch_skb(skb, &uh->source,
- sizeof(uh->source));
- fail |= lowpan_fetch_skb(skb, &uh->dest,
- sizeof(uh->dest));
- break;
- case LOWPAN_NHC_UDP_CS_P_01:
- fail |= lowpan_fetch_skb(skb, &uh->source,
- sizeof(uh->source));
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
- break;
- case LOWPAN_NHC_UDP_CS_P_10:
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
- fail |= lowpan_fetch_skb(skb, &uh->dest,
- sizeof(uh->dest));
- break;
- case LOWPAN_NHC_UDP_CS_P_11:
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
- (val >> 4));
- uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
- (val & 0x0f));
- break;
- default:
- pr_debug("ERROR: unknown UDP format\n");
- goto err;
- }
-
- pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
- ntohs(uh->source), ntohs(uh->dest));
-
- /* checksum */
- if (tmp & LOWPAN_NHC_UDP_CS_C) {
- pr_debug_ratelimited("checksum elided currently not supported\n");
- goto err;
- } else {
- fail |= lowpan_fetch_skb(skb, &uh->check,
- sizeof(uh->check));
- }
-
- /* UDP length needs to be infered from the lower layers
- * here, we obtain the hint from the remaining size of the
- * frame
- */
- uh->len = htons(skb->len + sizeof(struct udphdr));
- pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
- } else {
- pr_debug("ERROR: unsupported NH format\n");
- goto err;
- }
-
- if (fail)
- goto err;
-
- return 0;
-err:
- return -EINVAL;
-}
-
/* TTL uncompression values */
static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };

@@ -425,29 +356,29 @@ lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
return -EINVAL;
}

- /* UDP data uncompression */
+ /* Next header data uncompression */
if (iphc0 & LOWPAN_IPHC_NH_C) {
- struct udphdr uh;
- const int needed = sizeof(struct udphdr) + sizeof(hdr);
-
- if (uncompress_udp_header(skb, &uh))
- return -EINVAL;
-
- /* replace the compressed UDP head by the uncompressed UDP
- * header
- */
- err = skb_cow(skb, needed);
- if (unlikely(err))
- return err;
+ struct lowpan_nhc *nhc = lowpan_nhc_by_nhcid(skb);
+
+ if (nhc) {
+ if (nhc->uncompress) {
+ err = lowpan_nhc_do_uncompression(nhc, skb);
+ if (err < 0)
+ return err;
+ } else {
+ netdev_warn(skb->dev, "received nhc id for %s which is not implemented.\n",
+ nhc->name);
+ return -ENOTSUPP;
+ }
+ } else {
+ netdev_warn(skb->dev, "received unknown nhc id which was not found.\n");
+ return -ENOENT;
+ }

- skb_push(skb, sizeof(struct udphdr));
+ hdr.nexthdr = nhc->nexthdr;
skb_reset_transport_header(skb);
- skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
- raw_dump_table(__func__, "raw UDP header dump",
- (u8 *)&uh, sizeof(uh));
-
- hdr.nexthdr = UIP_PROTO_UDP;
+ raw_dump_table(__func__, "raw transport header dump",
+ skb_transport_header(skb), nhc->nexthdrlen);
} else {
err = skb_cow(skb, sizeof(hdr));
if (unlikely(err))
@@ -500,79 +431,15 @@ static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
return rol8(val, shift);
}

-static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
-{
- struct udphdr *uh;
- u8 tmp;
-
- /* In the case of RAW sockets the transport header is not set by
- * the ip6 stack so we must set it ourselves
- */
- if (skb->transport_header == skb->network_header)
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
-
- uh = udp_hdr(skb);
-
- if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT) &&
- ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT)) {
- pr_debug("UDP header: both ports compression to 4 bits\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_11;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source and destination port */
- tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
- ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of dest\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_01;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
- /* destination port */
- tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of source\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_10;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* destination port */
- lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
- } else {
- pr_debug("UDP header: can't compress\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_00;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
- /* destination port */
- lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
- }
-
- /* checksum is always inline */
- lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
-
- /* skip the UDP header */
- skb_pull(skb, sizeof(struct udphdr));
-}
-
int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len)
{
u8 tmp, iphc0, iphc1, *hc_ptr;
+ struct lowpan_nhc *nhc;
struct ipv6hdr *hdr;
u8 head[100] = {};
- int addr_type;
+ int ret, addr_type;

if (type != ETH_P_IPV6)
return -EINVAL;
@@ -649,11 +516,13 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,

/* NOTE: payload length is always compressed */

- /* Next Header is compress if UDP */
- if (hdr->nexthdr == UIP_PROTO_UDP)
+ /* Check if we provide the nhc format for nexthdr and compression
+ * functionality. If not nexthdr is handled inline and not compressed.
+ */
+ nhc = lowpan_nhc_by_nexthdr(hdr->nexthdr);
+ if (nhc && nhc->compress)
iphc0 |= LOWPAN_IPHC_NH_C;
-
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
+ else
lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
sizeof(hdr->nexthdr));

@@ -741,9 +610,21 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
}
}

- /* UDP header compression */
- if (hdr->nexthdr == UIP_PROTO_UDP)
- compress_udp_header(&hc_ptr, skb);
+ /* next header compression */
+ if (iphc0 & LOWPAN_IPHC_NH_C) {
+ /* In the case of RAW sockets the transport header is not set by
+ * the ip6 stack so we must set it ourselves
+ */
+ if (skb->transport_header == skb->network_header)
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
+
+ ret = lowpan_nhc_do_compression(nhc, skb, &hc_ptr);
+ if (ret < 0)
+ return ret;
+
+ /* skip the transport header */
+ skb_pull(skb, nhc->nexthdrlen);
+ }

head[0] = iphc0;
head[1] = iphc1;
@@ -761,4 +642,12 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
}
EXPORT_SYMBOL_GPL(lowpan_header_compress);

+static int __init lowpan_module_init(void)
+{
+ request_module_nowait("nhc_rfc6282_udp");
+
+ return 0;
+}
+module_init(lowpan_module_init);
+
MODULE_LICENSE("GPL");
diff --git a/net/6lowpan/nhc_rfc6282_udp.c b/net/6lowpan/nhc_rfc6282_udp.c
new file mode 100644
index 0000000..65400a9
--- /dev/null
+++ b/net/6lowpan/nhc_rfc6282_udp.c
@@ -0,0 +1,156 @@
+/*
+ * 6LoWPAN IPv6 UDP compression according to RFC6282
+ *
+ *
+ * Authors:
+ * Alexander Aring <[email protected]>
+ *
+ * Orignal written by:
+ * Alexander Smirnov <[email protected]>
+ * Jon Smirl <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include "nhc.h"
+
+#define LOWPAN_NHC_UDP_IDLEN 1
+
+static int udp_uncompress(struct sk_buff *skb, size_t needed)
+{
+ u8 tmp = 0, val = 0;
+ struct udphdr uh;
+ bool fail;
+ int err;
+
+ fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
+
+ pr_debug("UDP header uncompression\n");
+ switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
+ case LOWPAN_NHC_UDP_CS_P_00:
+ fail |= lowpan_fetch_skb(skb, &uh.source, sizeof(uh.source));
+ fail |= lowpan_fetch_skb(skb, &uh.dest, sizeof(uh.dest));
+ break;
+ case LOWPAN_NHC_UDP_CS_P_01:
+ fail |= lowpan_fetch_skb(skb, &uh.source, sizeof(uh.source));
+ fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
+ uh.dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
+ break;
+ case LOWPAN_NHC_UDP_CS_P_10:
+ fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
+ uh.source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
+ fail |= lowpan_fetch_skb(skb, &uh.dest, sizeof(uh.dest));
+ break;
+ case LOWPAN_NHC_UDP_CS_P_11:
+ fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
+ uh.source = htons(LOWPAN_NHC_UDP_4BIT_PORT + (val >> 4));
+ uh.dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + (val & 0x0f));
+ break;
+ default:
+ BUG();
+ }
+
+ pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
+ ntohs(uh.source), ntohs(uh.dest));
+
+ /* checksum */
+ if (tmp & LOWPAN_NHC_UDP_CS_C) {
+ pr_debug_ratelimited("checksum elided currently not supported\n");
+ fail = true;
+ } else {
+ fail |= lowpan_fetch_skb(skb, &uh.check, sizeof(uh.check));
+ }
+
+ if (fail)
+ return -EINVAL;
+
+ /* UDP length needs to be infered from the lower layers
+ * here, we obtain the hint from the remaining size of the
+ * frame
+ */
+ uh.len = htons(skb->len + sizeof(struct udphdr));
+ pr_debug("uncompressed UDP length: src = %d", ntohs(uh.len));
+
+ /* replace the compressed UDP head by the uncompressed UDP
+ * header
+ */
+ err = skb_cow(skb, needed);
+ if (unlikely(err))
+ return err;
+
+ skb_push(skb, sizeof(struct udphdr));
+ skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
+
+ return 0;
+}
+
+static int udp_compress(struct sk_buff *skb, u8 **hc_ptr)
+{
+ const struct udphdr *uh = udp_hdr(skb);
+ u8 tmp;
+
+ if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT) &&
+ ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
+ LOWPAN_NHC_UDP_4BIT_PORT)) {
+ pr_debug("UDP header: both ports compression to 4 bits\n");
+ /* compression value */
+ tmp = LOWPAN_NHC_UDP_CS_P_11;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ /* source and destination port */
+ tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
+ ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of dest\n");
+ /* compression value */
+ tmp = LOWPAN_NHC_UDP_CS_P_01;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ /* source port */
+ lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
+ /* destination port */
+ tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
+ LOWPAN_NHC_UDP_8BIT_PORT) {
+ pr_debug("UDP header: remove 8 bits of source\n");
+ /* compression value */
+ tmp = LOWPAN_NHC_UDP_CS_P_10;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ /* source port */
+ tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ /* destination port */
+ lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
+ } else {
+ pr_debug("UDP header: can't compress\n");
+ /* compression value */
+ tmp = LOWPAN_NHC_UDP_CS_P_00;
+ lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
+ /* source port */
+ lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
+ /* destination port */
+ lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
+ }
+
+ /* checksum is always inline */
+ lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
+
+ return 0;
+}
+
+static void udp_nhid_setup(struct lowpan_nhc *nhc)
+{
+ nhc->id[0] = LOWPAN_NHC_UDP_ID;
+ nhc->idmask[0] = LOWPAN_NHC_UDP_MASK;
+}
+
+LOWPAN_NHC(nhc_udp, "RFC6282 UDP", NEXTHDR_UDP, sizeof(struct udphdr),
+ udp_nhid_setup, LOWPAN_NHC_UDP_IDLEN, udp_uncompress, udp_compress);
+
+module_lowpan_nhc(nhc_udp);
+MODULE_LICENSE("GPL");
--
2.1.3