mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
gnrc_sixlowpan_frag: Initial import of a fragment size hint feature
This allows for sending of fragments smaller than the restrictions set by the link-layer PDU. E.g. to put some slack for IPHC into the first fragment (see https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-02#section-4.1).
This commit is contained in:
parent
8fe12bc82c
commit
2534cfb3fa
@ -29,6 +29,7 @@ PSEUDOMODULES += gnrc_netif_dedup
|
||||
PSEUDOMODULES += gnrc_sixloenc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_border_router_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_default
|
||||
PSEUDOMODULES += gnrc_sixlowpan_frag_hint
|
||||
PSEUDOMODULES += gnrc_sixlowpan_iphc_nhc
|
||||
PSEUDOMODULES += gnrc_sixlowpan_nd_border_router
|
||||
PSEUDOMODULES += gnrc_sixlowpan_router
|
||||
|
@ -32,6 +32,9 @@
|
||||
#include "msg.h"
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/netif/hdr.h"
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
#include "net/gnrc/sixlowpan/frag/hint.h"
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
#include "net/gnrc/sixlowpan/internal.h"
|
||||
#include "net/ieee802154.h"
|
||||
#include "net/sixlowpan.h"
|
||||
@ -94,6 +97,13 @@ typedef struct {
|
||||
uint16_t tag; /**< Tag used for the fragment */
|
||||
uint16_t offset; /**< Offset of the Nth fragment from the beginning of the
|
||||
* payload datagram */
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
/**
|
||||
* @brief Hint for the size (smaller than link-layer PDU) for the next
|
||||
* fragment to sent
|
||||
*/
|
||||
gnrc_sixlowpan_frag_hint_t hint;
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
} gnrc_sixlowpan_msg_frag_t;
|
||||
|
||||
/**
|
||||
|
59
sys/include/net/gnrc/sixlowpan/frag/hint.h
Normal file
59
sys/include/net/gnrc/sixlowpan/frag/hint.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup net_gnrc_sixlowpan_frag_hint Fragment size hint
|
||||
* @ingroup net_gnrc_sixlowpan_frag
|
||||
* @brief Provides a hint for smaller fragment sizes than the link-layer
|
||||
* PDU for the next fragment to sent
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Definitions to provide a hint on the final fragment size
|
||||
*
|
||||
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||
*/
|
||||
#ifndef NET_GNRC_SIXLOWPAN_FRAG_HINT_H
|
||||
#define NET_GNRC_SIXLOWPAN_FRAG_HINT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief A fragment size hint
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Provides a hint of the size for the next fragment to send
|
||||
*
|
||||
* Set to 0 for fitting to the maximum fragment size of the interface the
|
||||
* datagram is sent over.
|
||||
*
|
||||
* @see gnrc_netif_6lo_t::max_frag_size
|
||||
*/
|
||||
uint16_t fragsz;
|
||||
/**
|
||||
* @brief The size of the data bound by gnrc_sixlowpan_frag_hint_t::fragsz
|
||||
* uncompressed
|
||||
*
|
||||
* This is only evaluated when gnrc_sixlowpan_frag_hint_t::fragsz is greater
|
||||
* than 0.
|
||||
* Required to calculate the proper offset for the next fragment.
|
||||
*/
|
||||
uint16_t fragsz_uncomp;
|
||||
} gnrc_sixlowpan_frag_hint_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NET_GNRC_SIXLOWPAN_FRAG_HINT_H */
|
||||
/** @} */
|
@ -50,6 +50,32 @@ static inline size_t _min(size_t a, size_t b)
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint8_t _max_frag_size(gnrc_netif_t *iface,
|
||||
gnrc_sixlowpan_msg_frag_t *fragment_msg)
|
||||
{
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
if (fragment_msg->hint.fragsz > 0) {
|
||||
/* account for rounding down to 8*/
|
||||
return (fragment_msg->hint.fragsz & 0x7)
|
||||
? (fragment_msg->hint.fragsz + 8U)
|
||||
: fragment_msg->hint.fragsz;
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
(void)fragment_msg;
|
||||
return iface->sixlo.max_frag_size;
|
||||
}
|
||||
|
||||
static inline int _payload_diff(gnrc_sixlowpan_msg_frag_t *fragment_msg,
|
||||
size_t payload_len)
|
||||
{
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
if (fragment_msg->hint.fragsz > 0) {
|
||||
return fragment_msg->hint.fragsz_uncomp - fragment_msg->hint.fragsz;
|
||||
}
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
return (fragment_msg->datagram_size - payload_len);
|
||||
}
|
||||
|
||||
static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt,
|
||||
gnrc_sixlowpan_msg_frag_t *fragment_msg,
|
||||
size_t payload_len, size_t size)
|
||||
@ -57,6 +83,15 @@ static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt,
|
||||
sixlowpan_frag_t *frag_hdr;
|
||||
gnrc_netif_hdr_t *netif_hdr = pkt->data, *new_netif_hdr;
|
||||
gnrc_pktsnip_t *netif, *frag;
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
size_t fragment_size = ((fragment_msg->hint.fragsz > 0) &&
|
||||
(fragment_msg->offset == 0))
|
||||
? size /* we want the calculated fragment size
|
||||
* to include full IPHC header */
|
||||
: _min(size, payload_len);
|
||||
#else /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
size_t fragment_size = _min(size, payload_len);
|
||||
#endif /* MODULE_GNRC_SIXLOWPAN_FRAG_HINT */
|
||||
|
||||
netif = gnrc_netif_hdr_build(gnrc_netif_hdr_get_src_addr(netif_hdr),
|
||||
netif_hdr->src_l2addr_len,
|
||||
@ -74,8 +109,7 @@ static gnrc_pktsnip_t *_build_frag_pkt(gnrc_pktsnip_t *pkt,
|
||||
new_netif_hdr->rssi = netif_hdr->rssi;
|
||||
new_netif_hdr->lqi = netif_hdr->lqi;
|
||||
|
||||
frag = gnrc_pktbuf_add(NULL, NULL, _min(size, payload_len),
|
||||
GNRC_NETTYPE_SIXLOWPAN);
|
||||
frag = gnrc_pktbuf_add(NULL, NULL, fragment_size, GNRC_NETTYPE_SIXLOWPAN);
|
||||
|
||||
if (frag == NULL) {
|
||||
DEBUG("6lo frag: error allocating first fragment\n");
|
||||
@ -102,12 +136,13 @@ static uint16_t _send_1st_fragment(gnrc_netif_t *iface,
|
||||
uint8_t *data;
|
||||
/* payload_len: actual size of the packet vs
|
||||
* datagram_size: size of the uncompressed IPv6 packet */
|
||||
int payload_diff = (fragment_msg->datagram_size - payload_len);
|
||||
int payload_diff = _payload_diff(fragment_msg, payload_len);
|
||||
uint16_t local_offset = 0;
|
||||
/* virtually add payload_diff to flooring to account for offset (must be divisable by 8)
|
||||
* in uncompressed datagram */
|
||||
uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size + payload_diff -
|
||||
sizeof(sixlowpan_frag_t)) - payload_diff;
|
||||
uint16_t max_frag_size = _floor8(_max_frag_size(iface, fragment_msg) +
|
||||
payload_diff - sizeof(sixlowpan_frag_t)) -
|
||||
payload_diff;
|
||||
|
||||
DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);
|
||||
|
||||
@ -158,7 +193,8 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
|
||||
uint16_t local_offset = 0, offset_count = 0, offset = fragment_msg->offset;
|
||||
/* since dispatches aren't supposed to go into subsequent fragments, we need not account
|
||||
* for payload difference as for the first fragment */
|
||||
uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size - sizeof(sixlowpan_frag_n_t));
|
||||
uint16_t max_frag_size = _floor8(iface->sixlo.max_frag_size -
|
||||
sizeof(sixlowpan_frag_n_t));
|
||||
|
||||
DEBUG("6lo frag: determined max_frag_size = %" PRIu16 "\n", max_frag_size);
|
||||
|
||||
@ -174,8 +210,8 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface,
|
||||
data = (uint8_t *)(hdr + 1);
|
||||
hdr->disp_size.u8[0] |= SIXLOWPAN_FRAG_N_DISP;
|
||||
/* don't mention payload diff in offset */
|
||||
hdr->offset = (uint8_t)((offset +
|
||||
(fragment_msg->datagram_size - payload_len)) >> 3);
|
||||
hdr->offset = (uint8_t)((offset + _payload_diff(fragment_msg,
|
||||
payload_len)) >> 3);
|
||||
pkt = pkt->next; /* don't copy netif header */
|
||||
|
||||
while ((pkt != NULL) && (offset_count != offset)) { /* go to offset */
|
||||
|
@ -134,6 +134,9 @@ void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
|
||||
fragment_msg->tag = gnrc_sixlowpan_frag_next_tag();
|
||||
/* Sending the first fragment has an offset==0 */
|
||||
fragment_msg->offset = 0;
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG_HINT
|
||||
fragment_msg->hint.fragsz = 0;
|
||||
#endif
|
||||
|
||||
gnrc_sixlowpan_frag_send(pkt, fragment_msg, page);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user