Skip to content

Commit

Permalink
Merge pull request RIOT-OS#9485 from miri64/gnrc_sixlowpan_iphc/enh/i…
Browse files Browse the repository at this point in the history
…8511-send

gnrc_sixlowpan_iphc: refactor sending for RIOT-OS#8511
  • Loading branch information
cgundogan authored Jul 25, 2018
2 parents 0fe5ec1 + 80322cb commit 7fef5e0
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 84 deletions.
21 changes: 21 additions & 0 deletions sys/include/net/gnrc/sixlowpan/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
#ifndef NET_GNRC_SIXLOWPAN_INTERNAL_H
#define NET_GNRC_SIXLOWPAN_INTERNAL_H

#include <stddef.h>

#include "net/gnrc/pkt.h"
#include "net/gnrc/netif.h"

#ifdef __cplusplus
extern "C" {
Expand All @@ -44,6 +47,24 @@ void gnrc_sixlowpan_dispatch_recv(gnrc_pktsnip_t *pkt, void *context,
void gnrc_sixlowpan_dispatch_send(gnrc_pktsnip_t *pkt, void *context,
unsigned page);


/**
* @brief Checks if packet fits over interface (and fragments if @ref
* net_gnrc_sixlowpan_frag is available and required)
*
* @param[in] pkt The packet to fit. Must not be NULL.
* @param[in] orig_datagram_size The original (uncompressed) datagram size.
* Must be greater or equal to the length of
* @p pkt as of `pkt->next` (i.e. without
* the @ref gnrc_netif_hdr_t).
* @param[in] netif The interface to fit @p pkt over. Must not
* be NULL.
* @param[in] page Current 6Lo dispatch parsing page
*/
void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
size_t orig_datagram_size,
gnrc_netif_t *netif,
unsigned page);
#ifdef __cplusplus
}
#endif
Expand Down
12 changes: 7 additions & 5 deletions sys/include/net/gnrc/sixlowpan/iphc.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,15 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
/**
* @brief Compresses a 6LoWPAN for IPHC.
*
* @param[in,out] pkt A 6LoWPAN frame with an uncompressed IPv6 header to
* send. Will be translated to an 6LoWPAN IPHC frame.
* @pre (pkt != NULL)
*
* @param[in] pkt A 6LoWPAN frame with an uncompressed IPv6 header to send.
* Will be translated to an 6LoWPAN IPHC frame.
* @param[in] ctx Context for the packet. May be NULL.
* @param[in] page Current 6Lo dispatch parsing page.
*
* @return true, on success
* @return false, on error.
*/
bool gnrc_sixlowpan_iphc_encode(gnrc_pktsnip_t *pkt);
void gnrc_sixlowpan_iphc_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);

#ifdef __cplusplus
}
Expand Down
135 changes: 61 additions & 74 deletions sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,51 @@ void gnrc_sixlowpan_dispatch_send(gnrc_pktsnip_t *pkt, void *context,
}
}

void gnrc_sixlowpan_multiplex_by_size(gnrc_pktsnip_t *pkt,
size_t orig_datagram_size,
gnrc_netif_t *netif,
unsigned page)
{
assert(pkt != NULL);
assert(netif != NULL);
size_t datagram_size = gnrc_pkt_len(pkt->next);
DEBUG("6lo: iface->sixlo.max_frag_size = %u for interface %i\n",
netif->sixlo.max_frag_size, netif->pid);
if ((netif->sixlo.max_frag_size == 0) ||
(datagram_size <= netif->sixlo.max_frag_size)) {
DEBUG("6lo: Dispatch for sending\n");
gnrc_sixlowpan_dispatch_send(pkt, NULL, page);
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
else if (orig_datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) {
DEBUG("6lo: Send fragmented (%u > %u)\n",
(unsigned int)datagram_size, netif->sixlo.max_frag_size);
gnrc_sixlowpan_msg_frag_t *fragment_msg;

fragment_msg = gnrc_sixlowpan_msg_frag_get();
if (fragment_msg == NULL) {
DEBUG("6lo: Not enough resources to fragment packet. "
"Dropping packet\n");
gnrc_pktbuf_release_error(pkt, ENOMEM);
return;
}
fragment_msg->pid = netif->pid;
fragment_msg->pkt = pkt;
fragment_msg->datagram_size = orig_datagram_size;
/* Sending the first fragment has an offset==0 */
fragment_msg->offset = 0;

gnrc_sixlowpan_frag_send(pkt, fragment_msg, page);
}
#endif
else {
(void)orig_datagram_size;
DEBUG("6lo: packet too big (%u > %u)\n",
(unsigned int)datagram_size, netif->sixlo.max_frag_size);
gnrc_pktbuf_release_error(pkt, EMSGSIZE);
}
}

static void _receive(gnrc_pktsnip_t *pkt)
{
gnrc_pktsnip_t *payload;
Expand Down Expand Up @@ -225,8 +270,8 @@ static inline bool _add_uncompr_disp(gnrc_pktsnip_t *pkt)
static void _send(gnrc_pktsnip_t *pkt)
{
gnrc_netif_hdr_t *hdr;
gnrc_pktsnip_t *pkt2;
gnrc_netif_t *iface;
gnrc_pktsnip_t *tmp;
gnrc_netif_t *netif;
/* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */
size_t datagram_size;

Expand All @@ -242,95 +287,37 @@ static void _send(gnrc_pktsnip_t *pkt)
return;
}

pkt2 = gnrc_pktbuf_start_write(pkt);
tmp = gnrc_pktbuf_start_write(pkt);

if (pkt2 == NULL) {
if (tmp == NULL) {
DEBUG("6lo: no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return;
}
pkt = tmp;
hdr = pkt->data;
netif = gnrc_netif_get_by_pid(hdr->if_pid);
datagram_size = gnrc_pkt_len(pkt->next);

hdr = pkt2->data;
iface = gnrc_netif_get_by_pid(hdr->if_pid);
datagram_size = gnrc_pkt_len(pkt2->next);

if (iface == NULL) {
if (netif == NULL) {
DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n");
gnrc_pktbuf_release(pkt);
return;
}

#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
if (iface->flags & GNRC_NETIF_FLAGS_6LO_HC) {
if (!gnrc_sixlowpan_iphc_encode(pkt2)) {
DEBUG("6lo: error on IPHC encoding\n");
gnrc_pktbuf_release(pkt2);
return;
}
/* IPHC dispatch does not count on dispatch length since it _shortens_
* the datagram */
}
else {
if (!_add_uncompr_disp(pkt2)) {
/* adding uncompressed dispatch failed */
DEBUG("6lo: no space left in packet buffer\n");
gnrc_pktbuf_release(pkt2);
return;
}
}
#else
/* suppress clang-analyzer report about iface being not read */
(void) iface;
if (!_add_uncompr_disp(pkt2)) {
/* adding uncompressed dispatch failed */
DEBUG("6lo: no space left in packet buffer\n");
gnrc_pktbuf_release(pkt2);
if (netif->flags & GNRC_NETIF_FLAGS_6LO_HC) {
gnrc_sixlowpan_iphc_send(pkt, NULL, 0);
return;
}
#endif
DEBUG("6lo: iface->sixlo.max_frag_size = %" PRIu8 " for interface %"
PRIkernel_pid "\n", iface->sixlo.max_frag_size, hdr->if_pid);

/* Note, that datagram_size cannot be used here, because the header size
* might be changed by IPHC. */
if ((iface->sixlo.max_frag_size == 0) ||
(gnrc_pkt_len(pkt2->next) <= iface->sixlo.max_frag_size)) {
DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n",
(void *)pkt2, hdr->if_pid);
gnrc_sixlowpan_dispatch_send(pkt2, NULL, 0);
if (!_add_uncompr_disp(pkt)) {
/* adding uncompressed dispatch failed */
DEBUG("6lo: no space left in packet buffer\n");
gnrc_pktbuf_release(pkt);
return;
}
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
else if (datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) {
DEBUG("6lo: Send fragmented (%u > %" PRIu8 ")\n",
(unsigned int)datagram_size, iface->sixlo.max_frag_size);
gnrc_sixlowpan_msg_frag_t *fragment_msg;

fragment_msg = gnrc_sixlowpan_msg_frag_get();
if (fragment_msg == NULL) {
DEBUG("6lo: Not enough resources to fragment packet. Dropping packet\n");
gnrc_pktbuf_release(pkt2);
return;
}
fragment_msg->pid = hdr->if_pid;
fragment_msg->pkt = pkt2;
fragment_msg->datagram_size = datagram_size;
/* Sending the first fragment has an offset==0 */
fragment_msg->offset = 0;

gnrc_sixlowpan_frag_send(pkt2, fragment_msg, 0);
}
else {
DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n",
(unsigned int)datagram_size, (uint16_t)SIXLOWPAN_FRAG_MAX_LEN);
gnrc_pktbuf_release(pkt2);
}
#else
(void) datagram_size;
DEBUG("6lo: packet too big (%u > %" PRIu8 ")\n",
(unsigned int)datagram_size, iface->sixlo.max_frag_size);
gnrc_pktbuf_release(pkt2);
#endif
gnrc_sixlowpan_multiplex_by_size(pkt, datagram_size, netif, 0);
}

static void *_event_loop(void *args)
Expand Down
18 changes: 13 additions & 5 deletions sys/net/gnrc/network_layer/sixlowpan/iphc/gnrc_sixlowpan_iphc.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "net/ipv6/hdr.h"
#include "net/gnrc.h"
#include "net/gnrc/sixlowpan/ctx.h"
#include "net/gnrc/sixlowpan/internal.h"
#include "net/sixlowpan.h"
#include "utlist.h"
#include "net/gnrc/nettype.h"
Expand Down Expand Up @@ -581,20 +582,25 @@ static inline size_t iphc_nhc_udp_encode(gnrc_pktsnip_t *udp, ipv6_hdr_t *ipv6_h
}
#endif

bool gnrc_sixlowpan_iphc_encode(gnrc_pktsnip_t *pkt)
void gnrc_sixlowpan_iphc_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
{
assert(pkt != NULL);
gnrc_netif_hdr_t *netif_hdr = pkt->data;
ipv6_hdr_t *ipv6_hdr = pkt->next->data;
uint8_t *iphc_hdr;
uint16_t inline_pos = SIXLOWPAN_IPHC_HDR_LEN;
bool addr_comp = false, nhc_comp = false;
gnrc_sixlowpan_ctx_t *src_ctx = NULL, *dst_ctx = NULL;
gnrc_pktsnip_t *dispatch = gnrc_pktbuf_add(NULL, NULL, pkt->next->size,
GNRC_NETTYPE_SIXLOWPAN);
bool addr_comp = false, nhc_comp = false;
/* datagram size before compression */
size_t orig_datagram_size = gnrc_pkt_len(pkt->next);
uint16_t inline_pos = SIXLOWPAN_IPHC_HDR_LEN;

(void)ctx;
if (dispatch == NULL) {
DEBUG("6lo iphc: error allocating dispatch space\n");
return false;
gnrc_pktbuf_release(pkt);
return;
}

iphc_hdr = dispatch->data;
Expand Down Expand Up @@ -892,7 +898,9 @@ bool gnrc_sixlowpan_iphc_encode(gnrc_pktsnip_t *pkt)
dispatch->next = pkt->next;
pkt->next = dispatch;

return true;
gnrc_netif_t *netif = gnrc_netif_get_by_pid(netif_hdr->if_pid);
assert(netif != NULL);
gnrc_sixlowpan_multiplex_by_size(pkt, orig_datagram_size, netif, page);
}

/** @} */

0 comments on commit 7fef5e0

Please sign in to comment.