Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gnrc_sixlowpan_frag: Initial import of a fragment size hint feature #11061

Merged
merged 1 commit into from
May 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions makefiles/pseudomodules.inc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions sys/include/net/gnrc/sixlowpan/frag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;

/**
Expand Down
59 changes: 59 additions & 0 deletions sys/include/net/gnrc/sixlowpan/frag/hint.h
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>
*/
#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 */
/** @} */
52 changes: 44 additions & 8 deletions sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,48 @@ 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)
{
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,
Expand All @@ -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");
Expand All @@ -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);

Expand Down Expand Up @@ -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);

Expand All @@ -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 */
Expand Down
3 changes: 3 additions & 0 deletions sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down