Skip to content
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
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,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const gnrc_netif_t *netif,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh... while in the current version of the code netif isn't changed, I can see a future version where netif is provided as to a _send() function which then again would require casting.

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);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const void *ctx,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not what is proposed in #8511 and we also shouldn't restrict the use of ctx within the execution path (examples were ctx is changed exist enough throughout the current code-base).


#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);
}

/** @} */