Fragment size calculation previously failed for devices that are able to
transmit bigger layer 2 PDUs that 802.15.4 devices. This commit fixes the issue.
`gnrc_sixlowpan_frag` internally derives the offset value directly
from the fragment header, so for normal usage within GNRC this
assertion is redundant, but to make the tests of `rbuf_add` 100%
water-tide I added it.
While the recursion in `gnrc_sixlowpan_frag` shouldn't be infinite we
still should avoid using recursions in general (also to be able to
statically analyze stack usage). This unrolls the recursion.
When issueing the sending of the next fragment the current version of
`gnrc_sixlowpan_frag` doesn't check if the queue is full. This leads to
leakage of the packet buffer, since when it is full, the package never
gets released.
This change adds a checks and error exits in case the queue is full.
This refactors reception/decoding part of `gnrc_sixlowpan_iphc` to the
more layered approach modeled in #8511. Since the reception part is
already complicated enough I decided to divide send and receive up into
separate changes.
This will be used in the IPHC refactoring to control the reassembly
buffer as a context.
I also adapted the name of `gnrc_sixlowpan_frag_gc_rbuf()` to be in
line with the rest of the newer functions.
While refactoring IPHC I noticed that the page actually can already be
used for fragmentation: Given @cgundogan's work on [ICN LoWPAN] we can
already assume, that the page context may (among other thing) determine
the type of the reassembled packet. This PR provides the basis for
that.
[ICN LoWPAN]: https://tools.ietf.org/html/draft-gundogan-icnrg-ccnlowpan-01
While the current approach for garbage collection in the 6Lo reassembly
buffer is good for best-effort handling of
*fragmented* packets and nicely RAM saving, it has the problem that
incomplete, huge datagrams can basically DoS a node, if no further
fragmented datagram is received for a while (since the packet buffer is
full and GC is not triggered).
This change adds a asynchronous GC (utilizing the existing
functionality) to the reassembly buffer, so that even if there is no new
fragmented packet received, fragments older than `RBUF_TIMEOUT` will be
removed from the reassembly buffer, freeing up the otherwise wasted
packet buffer space.
Since IPHC also manipulates the total number of bytes of a received
datagram (by decompressing it), this also needs to be exposed. I guess
I was too focused on introducing a *generic* packet buffer for a future
virtual reassembly buffer (where it isn't needed, but so isn't `pkt` to
be honest), that I totally forgot about it in #9352.
This refactors the `gnrc_sixlowpan_frag` module for the API proposed
in #8511.
The `ctx` for `gnrc_sixlowpan_frag_send()` is required to be a
`gnrc_sixlowpan_msg_frag_t` object, so IPHC can later on use it to
provide the *original* datagram size (otherwise, we would need to adapt
the API just for that, which seems to me as convoluted as this
proposal).
I also provide an expose function with a future possibility to provide
more than just one `gnrc_sixlowpan_msg_frag_t` object later on (plus
having cleaner module separation in general).
This exposes the parts of the reassembly buffer to be usable as context
as proposed in #8511.
I only exposed *parts of* for two reasons:
1. I don't need to expose further types (like `rbuf_int_t`), that are
not of interest outside of fragmentation.
2. This allows for an easy future extension for the virtual reassembly
buffer as proposed in [[1]].
This makes this change a little bit more involved, because instead of
just renaming the type, I also need to add the usage of the `super`
member, but I think in the end this little preparation work will be
beneficial in the future.
[1]: https://tools.ietf.org/html/draft-watteyne-6lo-minimal-fragment-01#section-3