2015-01-08 12:31:35

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv4 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.

changes since v4:
- add spinlock for to prevent nhc from deletion while using. This can occur
if nhc module is unloading while compression/uncompression.
- move nhc handling for nhc compression/uncompression completely into
nhc_do_compression/nhc_do_uncompression.

Note about locking:

We have now a spinlock nhc_lowpan_lock which prevents manipulating the nhc
datastructures while using it. On receiving side it's easy to handle, at the
end we check if 6lowpan nh compressed flag is set and run uncompression.
On the other hand the transmit side is complicated, we check if next_hdr field
is registrated and run some other compression routines, at least we do the
finally nhc compression which depends on the first check if next_hdr was
registrated. The kernel will crash if we remove the using module between
"next_hdr check" and "do nhc compression", the lock will prevent that now.

Now in the transmit path exist a little window to remove a lowpan_nhc while
compression. This is exactly the part between "check if we support" and
"doing compression". This is a very unlikely case, if this occurs we drop
the packet while compression. Don't know how to better deal with that right
now. I will try to search a better solution later.

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 | 200 ++++++---------------------------
net/6lowpan/nhc.c | 241 ++++++++++++++++++++++++++++++++++++++++
net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
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, 802 insertions(+), 171 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.2.1


2015-01-09 13:55:55

by Alexander Aring

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

Hi,

On Fri, Jan 09, 2015 at 01:05:22PM +0000, Stefan Schmidt wrote:
> Hello.
>
> On 08/01/15 21:04, Alexander Aring wrote:
> >Hi,
> >
> >On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
> >...
> >>>>net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
> >>>>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 ++++++++++++++++++++++++++
> >>>
> >>>can we please remove the _rfc6282 from the filenames. RFCs get update and
> >>>thus change numbers. I do not want to carry RFC numbers in filenames
> >>>around. There is also almost no precedence in the kernel source code that
> >>>would justify doing this.
> >>
> >>They look indeed quite ugly in the filename. :)
> >>
> >>Moving them as a comment and starting point into the file should be
> >>enough.
> >>Maybe we can also rename nhc_mobil to nhc_mobility. The other
> >>abbreviations
> >>are clear in my opinion but for mobil I actually opened the rfc to look
> >>what
> >>you mean here.
> >>
> >
> >For the rfc6282 thing:
> >
> >Currently there exists two RFCs which describes an UDP compression. It's
> >rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
> >was pointed out by Martin Townsend [0].
>
> November 2014, thats really new.
>
> >We need to clarify how we should deal with multiple definitions for a
> >compression format. On receiving side we should always support what we
> >can which is decided by the variable nhcid length. While on transmit...
> >we need still some configuration interface (my dreams are to decide the
> >compression methods per socket, don't know how possible that is).
>
> As a general rule we should try to accept, identify and uncompress as many
> formats for the incoming side. For the sending side this decision is very
> unlikely to be made by the application but instead it is made by the system
> configurator / platform. Thus in my eyes it makes more sense to have the
> configure options either via netlink or sysfs but not over the socket
> interface.
>

yes, this is the next part which is also more easier than the per socket
interface. To make this just per socket is more granularity than have a
"global setting" for this. Maybe we can handle this in one net namespace
configuration, but this also seems after the a step to introduce a netlink
configuration framework. I already talked with Jukka and he also agree For
a netlink interface (this was in some previous series).

> >For the handling I thought that we have then two UDP nhc modules, both
> >can be loaded (at the moment _only_ one UDP nhc compressression should
> >implement the compress methods, both should implement uncompression
> >methods).
> >
> >I can rename it to nhc_udp.c for the standard compression methods
> >according to rfc6282, I am fine with that. But later there exists then
> >an another compression module with the naming "nhc_ghc_udp.c" or
> >something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
> >Is that okay for everybody?
>
> It would be ok for me. nhc_udp is the earlier spec and thus has a shorter
> name while we need to distinguish for later specs and add the ghc for it. In
> a later mail you mentioned using _iphc_ and _ghc_ I would avoid that because
> GHC is just plugged into NHC and thus is also a under the IPHC umbrella of
> compressions. :)
>

ok.

> >Maybe I should also add some modinfo information, which containing the
> >nhc->name.
>
> Maybe. For what would it be used? Having a human readable description would
> make sense for the configure interface in some cases I would say.
>

For `modinfo $NHC_MODULE`.

> >For the nexthdr names:
> >
> >I will try to change it according to the NEXTHDR IPv6 defines [1], so also
> >the linux IPv6 guys knows what it is.
>
> That looks good to me.
>

ok.

- Alex

2015-01-09 13:06:51

by Stefan Schmidt

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

Hello.

On 08/01/15 21:08, Alexander Aring wrote:
> On Thu, Jan 08, 2015 at 09:04:43PM +0100, Alexander Aring wrote:
>> Hi,
>>
>> On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
>> ...
>>>>> net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
>>>>> 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 ++++++++++++++++++++++++++
>>>>
>>>> can we please remove the _rfc6282 from the filenames. RFCs get update
>>>> and
>>>> thus change numbers. I do not want to carry RFC numbers in filenames
>>>> around. There is also almost no precedence in the kernel source code
>>>> that
>>>> would justify doing this.
>>>
>>> They look indeed quite ugly in the filename. :)
>>>
>>> Moving them as a comment and starting point into the file should be
>>> enough.
>>> Maybe we can also rename nhc_mobil to nhc_mobility. The other
>>> abbreviations
>>> are clear in my opinion but for mobil I actually opened the rfc to look
>>> what
>>> you mean here.
>>>
>>
>> For the rfc6282 thing:
>>
>> Currently there exists two RFCs which describes an UDP compression. It's
>> rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
>> was pointed out by Martin Townsend [0].
>>
>> We need to clarify how we should deal with multiple definitions for a
>> compression format. On receiving side we should always support what we
>> can which is decided by the variable nhcid length. While on transmit...
>> we need still some configuration interface (my dreams are to decide the
>> compression methods per socket, don't know how possible that is).
>>
>> For the handling I thought that we have then two UDP nhc modules, both
>> can be loaded (at the moment _only_ one UDP nhc compressression should
>> implement the compress methods, both should implement uncompression
>> methods).
>>
>> I can rename it to nhc_udp.c for the standard compression methods
>> according to rfc6282, I am fine with that. But later there exists then
>> an another compression module with the naming "nhc_ghc_udp.c" or
>> something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
>> Is that okay for everybody?
>>
>
> We can also put all udp compression formats into the nhc_udp.c file. But
> then all udp compressions are handled by one module then. We should not
> do that, because we can handle it per module.

I would keep them all in different modules for now.

regards
Stefan Schmidt

2015-01-09 13:05:22

by Stefan Schmidt

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

Hello.

On 08/01/15 21:04, Alexander Aring wrote:
> Hi,
>
> On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
> ...
>>>> net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
>>>> 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 ++++++++++++++++++++++++++
>>>
>>> can we please remove the _rfc6282 from the filenames. RFCs get update and
>>> thus change numbers. I do not want to carry RFC numbers in filenames
>>> around. There is also almost no precedence in the kernel source code that
>>> would justify doing this.
>>
>> They look indeed quite ugly in the filename. :)
>>
>> Moving them as a comment and starting point into the file should be
>> enough.
>> Maybe we can also rename nhc_mobil to nhc_mobility. The other
>> abbreviations
>> are clear in my opinion but for mobil I actually opened the rfc to look
>> what
>> you mean here.
>>
>
> For the rfc6282 thing:
>
> Currently there exists two RFCs which describes an UDP compression. It's
> rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
> was pointed out by Martin Townsend [0].

November 2014, thats really new.

> We need to clarify how we should deal with multiple definitions for a
> compression format. On receiving side we should always support what we
> can which is decided by the variable nhcid length. While on transmit...
> we need still some configuration interface (my dreams are to decide the
> compression methods per socket, don't know how possible that is).

As a general rule we should try to accept, identify and uncompress as
many formats for the incoming side. For the sending side this decision
is very unlikely to be made by the application but instead it is made by
the system configurator / platform. Thus in my eyes it makes more sense
to have the configure options either via netlink or sysfs but not over
the socket interface.

> For the handling I thought that we have then two UDP nhc modules, both
> can be loaded (at the moment _only_ one UDP nhc compressression should
> implement the compress methods, both should implement uncompression
> methods).
>
> I can rename it to nhc_udp.c for the standard compression methods
> according to rfc6282, I am fine with that. But later there exists then
> an another compression module with the naming "nhc_ghc_udp.c" or
> something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
> Is that okay for everybody?

It would be ok for me. nhc_udp is the earlier spec and thus has a
shorter name while we need to distinguish for later specs and add the
ghc for it. In a later mail you mentioned using _iphc_ and _ghc_ I would
avoid that because GHC is just plugged into NHC and thus is also a under
the IPHC umbrella of compressions. :)

> Maybe I should also add some modinfo information, which containing the
> nhc->name.

Maybe. For what would it be used? Having a human readable description
would make sense for the configure interface in some cases I would say.

> For the nexthdr names:
>
> I will try to change it according to the NEXTHDR IPv6 defines [1], so also
> the linux IPv6 guys knows what it is.

That looks good to me.

regards
Stefan Schmidt

2015-01-09 12:21:45

by Jukka Rissanen

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

Hi Alex,

On to, 2015-01-08 at 13:31 +0100, Alexander Aring wrote:
> 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.
>
> changes since v4:
> - add spinlock for to prevent nhc from deletion while using. This can occur
> if nhc module is unloading while compression/uncompression.
> - move nhc handling for nhc compression/uncompression completely into
> nhc_do_compression/nhc_do_uncompression.
>
> Note about locking:
>
> We have now a spinlock nhc_lowpan_lock which prevents manipulating the nhc
> datastructures while using it. On receiving side it's easy to handle, at the
> end we check if 6lowpan nh compressed flag is set and run uncompression.
> On the other hand the transmit side is complicated, we check if next_hdr field
> is registrated and run some other compression routines, at least we do the
> finally nhc compression which depends on the first check if next_hdr was
> registrated. The kernel will crash if we remove the using module between
> "next_hdr check" and "do nhc compression", the lock will prevent that now.
>
> Now in the transmit path exist a little window to remove a lowpan_nhc while
> compression. This is exactly the part between "check if we support" and
> "doing compression". This is a very unlikely case, if this occurs we drop
> the packet while compression. Don't know how to better deal with that right
> now. I will try to search a better solution later.
>

tried v4 shortly with Bluetooth and see no issues. Waiting next version
before giving final ack.


Cheers,
Jukka

2015-01-08 20:24:52

by Alexander Aring

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

On Thu, Jan 08, 2015 at 09:04:43PM +0100, Alexander Aring wrote:
> Hi,
>
> On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
> ...
> > >>net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
> > >>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 ++++++++++++++++++++++++++
> > >
> > >can we please remove the _rfc6282 from the filenames. RFCs get update and
> > >thus change numbers. I do not want to carry RFC numbers in filenames
> > >around. There is also almost no precedence in the kernel source code that
> > >would justify doing this.
> >
> > They look indeed quite ugly in the filename. :)
> >
> > Moving them as a comment and starting point into the file should be enough.
> > Maybe we can also rename nhc_mobil to nhc_mobility. The other abbreviations
> > are clear in my opinion but for mobil I actually opened the rfc to look what
> > you mean here.
> >
>
> For the rfc6282 thing:
>
> Currently there exists two RFCs which describes an UDP compression. It's
> rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
> was pointed out by Martin Townsend [0].
>
> We need to clarify how we should deal with multiple definitions for a
> compression format. On receiving side we should always support what we
> can which is decided by the variable nhcid length. While on transmit...
> we need still some configuration interface (my dreams are to decide the
> compression methods per socket, don't know how possible that is).
>
> For the handling I thought that we have then two UDP nhc modules, both
> can be loaded (at the moment _only_ one UDP nhc compressression should
> implement the compress methods, both should implement uncompression
> methods).
>
> I can rename it to nhc_udp.c for the standard compression methods
> according to rfc6282, I am fine with that. But later there exists then
> an another compression module with the naming "nhc_ghc_udp.c" or
> something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
> Is that okay for everybody?
>

Another idea, we drop the rfc6282 and replace it with "iphc", so we
should have then some little word which describes from which RFC the
compression comes from like "nhc_iphc_udp.ko" or "nhc_ghc_udp.ko".

- Alex

2015-01-08 20:08:22

by Alexander Aring

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

On Thu, Jan 08, 2015 at 09:04:43PM +0100, Alexander Aring wrote:
> Hi,
>
> On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
> ...
> > >>net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
> > >>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 ++++++++++++++++++++++++++
> > >
> > >can we please remove the _rfc6282 from the filenames. RFCs get update and
> > >thus change numbers. I do not want to carry RFC numbers in filenames
> > >around. There is also almost no precedence in the kernel source code that
> > >would justify doing this.
> >
> > They look indeed quite ugly in the filename. :)
> >
> > Moving them as a comment and starting point into the file should be enough.
> > Maybe we can also rename nhc_mobil to nhc_mobility. The other abbreviations
> > are clear in my opinion but for mobil I actually opened the rfc to look what
> > you mean here.
> >
>
> For the rfc6282 thing:
>
> Currently there exists two RFCs which describes an UDP compression. It's
> rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
> was pointed out by Martin Townsend [0].
>
> We need to clarify how we should deal with multiple definitions for a
> compression format. On receiving side we should always support what we
> can which is decided by the variable nhcid length. While on transmit...
> we need still some configuration interface (my dreams are to decide the
> compression methods per socket, don't know how possible that is).
>
> For the handling I thought that we have then two UDP nhc modules, both
> can be loaded (at the moment _only_ one UDP nhc compressression should
> implement the compress methods, both should implement uncompression
> methods).
>
> I can rename it to nhc_udp.c for the standard compression methods
> according to rfc6282, I am fine with that. But later there exists then
> an another compression module with the naming "nhc_ghc_udp.c" or
> something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
> Is that okay for everybody?
>

We can also put all udp compression formats into the nhc_udp.c file. But
then all udp compressions are handled by one module then. We should not
do that, because we can handle it per module.

- Alex

2015-01-08 20:04:46

by Alexander Aring

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

Hi,

On Thu, Jan 08, 2015 at 07:18:57PM +0000, Stefan Schmidt wrote:
...
> >>net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
> >>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 ++++++++++++++++++++++++++
> >
> >can we please remove the _rfc6282 from the filenames. RFCs get update and
> >thus change numbers. I do not want to carry RFC numbers in filenames
> >around. There is also almost no precedence in the kernel source code that
> >would justify doing this.
>
> They look indeed quite ugly in the filename. :)
>
> Moving them as a comment and starting point into the file should be enough.
> Maybe we can also rename nhc_mobil to nhc_mobility. The other abbreviations
> are clear in my opinion but for mobil I actually opened the rfc to look what
> you mean here.
>

For the rfc6282 thing:

Currently there exists two RFCs which describes an UDP compression. It's
rfc6282 (the well known 6LoWPAN IPHC compression RFC) and RFC7400 which
was pointed out by Martin Townsend [0].

We need to clarify how we should deal with multiple definitions for a
compression format. On receiving side we should always support what we
can which is decided by the variable nhcid length. While on transmit...
we need still some configuration interface (my dreams are to decide the
compression methods per socket, don't know how possible that is).

For the handling I thought that we have then two UDP nhc modules, both
can be loaded (at the moment _only_ one UDP nhc compressression should
implement the compress methods, both should implement uncompression
methods).

I can rename it to nhc_udp.c for the standard compression methods
according to rfc6282, I am fine with that. But later there exists then
an another compression module with the naming "nhc_ghc_udp.c" or
something else. So we have "nhc_udp.ko" and "nhc_ghc_udp.ko".
Is that okay for everybody?

Maybe I should also add some modinfo information, which containing the
nhc->name.


For the nexthdr names:

I will try to change it according to the NEXTHDR IPv6 defines [1], so also
the linux IPv6 guys knows what it is.

- Alex

[0] https://tools.ietf.org/html/rfc7400
[1] http://lxr.free-electrons.com/source/include/net/ipv6.h#L33

2015-01-08 19:18:57

by Stefan Schmidt

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

Hello.

On 08/01/15 20:06, Marcel Holtmann wrote:
> Hi Alex,
>
>> 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.
>>
>> changes since v4:
>> - add spinlock for to prevent nhc from deletion while using. This can
> occur
>> if nhc module is unloading while compression/uncompression.
>> - move nhc handling for nhc compression/uncompression completely into
>> nhc_do_compression/nhc_do_uncompression.
>>
>> Note about locking:
>>
>> We have now a spinlock nhc_lowpan_lock which prevents manipulating the
> nhc
>> datastructures while using it. On receiving side it's easy to handle, at
> the
>> end we check if 6lowpan nh compressed flag is set and run uncompression.
>> On the other hand the transmit side is complicated, we check if next_hdr
> field
>> is registrated and run some other compression routines, at least we do
> the
>> finally nhc compression which depends on the first check if next_hdr was
>> registrated. The kernel will crash if we remove the using module between
>> "next_hdr check" and "do nhc compression", the lock will prevent that
> now.
>>
>> Now in the transmit path exist a little window to remove a lowpan_nhc
> while
>> compression. This is exactly the part between "check if we support" and
>> "doing compression". This is a very unlikely case, if this occurs we
> drop
>> the packet while compression. Don't know how to better deal with that
> right
>> now. I will try to search a better solution later.
>>
>> 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 | 200 ++++++---------------------------
>> net/6lowpan/nhc.c | 241
> ++++++++++++++++++++++++++++++++++++++++
>> net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
>> 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 ++++++++++++++++++++++++++
>
> can we please remove the _rfc6282 from the filenames. RFCs get update and
> thus change numbers. I do not want to carry RFC numbers in filenames
> around. There is also almost no precedence in the kernel source code that
> would justify doing this.

They look indeed quite ugly in the filename. :)

Moving them as a comment and starting point into the file should be
enough. Maybe we can also rename nhc_mobil to nhc_mobility. The other
abbreviations are clear in my opinion but for mobil I actually opened
the rfc to look what you mean here.

regards
Stefan Schmidt

2015-01-08 19:06:15

by Marcel Holtmann

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

Hi Alex,

> 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.
>
> changes since v4:
> - add spinlock for to prevent nhc from deletion while using. This can occur
> if nhc module is unloading while compression/uncompression.
> - move nhc handling for nhc compression/uncompression completely into
> nhc_do_compression/nhc_do_uncompression.
>
> Note about locking:
>
> We have now a spinlock nhc_lowpan_lock which prevents manipulating the nhc
> datastructures while using it. On receiving side it's easy to handle, at the
> end we check if 6lowpan nh compressed flag is set and run uncompression.
> On the other hand the transmit side is complicated, we check if next_hdr field
> is registrated and run some other compression routines, at least we do the
> finally nhc compression which depends on the first check if next_hdr was
> registrated. The kernel will crash if we remove the using module between
> "next_hdr check" and "do nhc compression", the lock will prevent that now.
>
> Now in the transmit path exist a little window to remove a lowpan_nhc while
> compression. This is exactly the part between "check if we support" and
> "doing compression". This is a very unlikely case, if this occurs we drop
> the packet while compression. Don't know how to better deal with that right
> now. I will try to search a better solution later.
>
> 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 | 200 ++++++---------------------------
> net/6lowpan/nhc.c | 241 ++++++++++++++++++++++++++++++++++++++++
> net/6lowpan/nhc.h | 146 ++++++++++++++++++++++++
> 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 ++++++++++++++++++++++++++

can we please remove the _rfc6282 from the filenames. RFCs get update and thus change numbers. I do not want to carry RFC numbers in filenames around. There is also almost no precedence in the kernel source code that would justify doing this.

Regards

Marcel


2015-01-08 12:31:38

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv4 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 e576164..391b73a 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 f58fab9..0db6c11 100644
--- a/net/6lowpan/iphc.c
+++ b/net/6lowpan/iphc.c
@@ -613,6 +613,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.2.1


2015-01-08 12:31:36

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv4 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 | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++
net/6lowpan/nhc.h | 146 +++++++++++++++++++++++++++++++
3 files changed, 388 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..3c0dc77b0
--- /dev/null
+++ b/net/6lowpan/nhc.c
@@ -0,0 +1,241 @@
+/*
+ * 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 DEFINE_SPINLOCK(lowpan_nhc_lock);
+
+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);
+}
+
+static 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;
+}
+
+int lowpan_nhc_check_compression(struct sk_buff *skb,
+ const struct ipv6hdr *hdr, u8 **hc_ptr,
+ u8 *iphc0)
+{
+ struct lowpan_nhc *nhc;
+
+ spin_lock_bh(&lowpan_nhc_lock);
+
+ nhc = lowpan_nexthdr_nhcs[hdr->nexthdr];
+ if (nhc && nhc->compress)
+ *iphc0 |= LOWPAN_IPHC_NH_C;
+ else
+ lowpan_push_hc_data(hc_ptr, &hdr->nexthdr,
+ sizeof(hdr->nexthdr));
+
+ spin_unlock_bh(&lowpan_nhc_lock);
+
+ return 0;
+}
+
+int lowpan_nhc_do_compression(struct sk_buff *skb, const struct ipv6hdr *hdr,
+ u8 **hc_ptr)
+{
+ int ret;
+ struct lowpan_nhc *nhc;
+
+ spin_lock_bh(&lowpan_nhc_lock);
+
+ nhc = lowpan_nexthdr_nhcs[hdr->nexthdr];
+ /* check if the nhc module was removed in unlocked part.
+ * TODO: this is a workaround we should prevent unloading
+ * of nhc modules while unlocked part, this will always drop
+ * the lowpan packet but it's very unlikely.
+ *
+ * Solution isn't easy because we need to decide at
+ * lowpan_nhc_check_compression if we do a compression or not.
+ * Because the inline data which is added to skb, we can't move this
+ * handling.
+ */
+ if (unlikely(!nhc || !nhc->compress)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* 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 = nhc->compress(skb, hc_ptr);
+ if (ret < 0)
+ goto out;
+
+ /* skip the transport header */
+ skb_pull(skb, nhc->nexthdrlen);
+
+out:
+ spin_unlock_bh(&lowpan_nhc_lock);
+
+ return ret;
+}
+
+int lowpan_nhc_do_uncompression(struct sk_buff *skb, struct net_device *dev,
+ struct ipv6hdr *hdr)
+{
+ struct lowpan_nhc *nhc;
+ int ret;
+
+ spin_lock_bh(&lowpan_nhc_lock);
+
+ nhc = lowpan_nhc_by_nhcid(skb);
+ if (nhc) {
+ if (nhc->uncompress) {
+ ret = nhc->uncompress(skb, sizeof(struct ipv6hdr) +
+ nhc->nexthdrlen);
+ if (ret < 0) {
+ spin_unlock_bh(&lowpan_nhc_lock);
+ return ret;
+ }
+ } else {
+ spin_unlock_bh(&lowpan_nhc_lock);
+ netdev_warn(dev, "received nhc id for %s which is not implemented.\n",
+ nhc->name);
+ return -ENOTSUPP;
+ }
+ } else {
+ spin_unlock_bh(&lowpan_nhc_lock);
+ netdev_warn(dev, "received unknown nhc id which was not found.\n");
+ return -ENOENT;
+ }
+
+ hdr->nexthdr = nhc->nexthdr;
+ skb_reset_transport_header(skb);
+ raw_dump_table(__func__, "raw transport header dump",
+ skb_transport_header(skb), nhc->nexthdrlen);
+
+ spin_unlock_bh(&lowpan_nhc_lock);
+
+ return 0;
+}
+
+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);
+
+ spin_lock_bh(&lowpan_nhc_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:
+ spin_unlock_bh(&lowpan_nhc_lock);
+ return ret;
+}
+EXPORT_SYMBOL(lowpan_nhc_add);
+
+void lowpan_nhc_del(struct lowpan_nhc *nhc)
+{
+ spin_lock_bh(&lowpan_nhc_lock);
+
+ lowpan_nhc_remove(nhc);
+ lowpan_nexthdr_nhcs[nhc->nexthdr] = NULL;
+
+ spin_unlock_bh(&lowpan_nhc_lock);
+
+ synchronize_net();
+}
+EXPORT_SYMBOL(lowpan_nhc_del);
diff --git a/net/6lowpan/nhc.h b/net/6lowpan/nhc.h
new file mode 100644
index 0000000..ed44938
--- /dev/null
+++ b/net/6lowpan/nhc.h
@@ -0,0 +1,146 @@
+#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_nexthdr - return the 6lowpan nhc by ipv6 nexthdr.
+ *
+ * @nexthdr: ipv6 nexthdr value.
+ */
+struct lowpan_nhc *lowpan_nhc_by_nexthdr(u8 nexthdr);
+
+/**
+ * lowpan_nhc_check_compression - checks if we support compression format. If
+ * we support the nhc by nexthdr field, the 6LoWPAN iphc NHC bit will be
+ * set. If we don't support nexthdr will be added as inline data to the
+ * 6LoWPAN header.
+ *
+ * @skb: skb of 6LoWPAN header to read nhc and replace header.
+ * @hdr: ipv6hdr to check the nexthdr value
+ * @hc_ptr: pointer for 6LoWPAN header which should increment at the end of
+ * replaced header.
+ * @iphc0: iphc0 pointer to set the 6LoWPAN NHC bit
+ */
+int lowpan_nhc_check_compression(struct sk_buff *skb,
+ const struct ipv6hdr *hdr, u8 **hc_ptr,
+ u8 *iphc0);
+
+/**
+ * lowpan_nhc_do_compression - calling compress callback for nhc
+ *
+ * @skb: skb of 6LoWPAN header to read nhc and replace header.
+ * @hdr: ipv6hdr to set the nexthdr value
+ * @hc_ptr: pointer for 6LoWPAN header which should increment at the end of
+ * replaced header.
+ */
+int lowpan_nhc_do_compression(struct sk_buff *skb, const struct ipv6hdr *hdr,
+ u8 **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.
+ * @dev: netdevice for print logging information.
+ * @hdr: ipv6hdr for setting nexthdr value.
+ */
+int lowpan_nhc_do_uncompression(struct sk_buff *skb, struct net_device *dev,
+ struct ipv6hdr *hdr);
+
+/**
+ * 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.2.1


2015-01-08 12:31:37

by Alexander Aring

[permalink] [raw]
Subject: [PATCHv4 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 | 194 ++++++------------------------------------
net/6lowpan/nhc_rfc6282_udp.c | 156 +++++++++++++++++++++++++++++++++
4 files changed, 201 insertions(+), 170 deletions(-)
create mode 100644 net/6lowpan/nhc_rfc6282_udp.c

diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig
index e4a02ef..e576164 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..f58fab9 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,11 @@ 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))
+ err = lowpan_nhc_do_uncompression(skb, dev, &hdr);
+ if (err < 0)
return err;
-
- skb_push(skb, sizeof(struct udphdr));
- 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;
} else {
err = skb_cow(skb, sizeof(hdr));
if (unlikely(err))
@@ -500,71 +413,6 @@ 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)
@@ -572,7 +420,7 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
u8 tmp, iphc0, iphc1, *hc_ptr;
struct ipv6hdr *hdr;
u8 head[100] = {};
- int addr_type;
+ int ret, addr_type;

if (type != ETH_P_IPV6)
return -EINVAL;
@@ -649,13 +497,12 @@ 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)
- iphc0 |= LOWPAN_IPHC_NH_C;
-
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
- lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
- sizeof(hdr->nexthdr));
+ /* Check if we provide the nhc format for nexthdr and compression
+ * functionality. If not nexthdr is handled inline and not compressed.
+ */
+ ret = lowpan_nhc_check_compression(skb, hdr, &hc_ptr, &iphc0);
+ if (ret < 0)
+ return ret;

/* Hop limit
* if 1: compress, encoding is 01
@@ -741,9 +588,12 @@ 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) {
+ ret = lowpan_nhc_do_compression(skb, hdr, &hc_ptr);
+ if (ret < 0)
+ return ret;
+ }

head[0] = iphc0;
head[1] = iphc1;
@@ -761,4 +611,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.2.1