Merge pull request #9485 from miri64/gnrc_sixlowpan_iphc/enh/i8511-send
gnrc_sixlowpan_iphc: refactor sending for #8511
This commit is contained in:
commit
7fef5e030a
@ -18,7 +18,10 @@
|
|||||||
#ifndef NET_GNRC_SIXLOWPAN_INTERNAL_H
|
#ifndef NET_GNRC_SIXLOWPAN_INTERNAL_H
|
||||||
#define NET_GNRC_SIXLOWPAN_INTERNAL_H
|
#define NET_GNRC_SIXLOWPAN_INTERNAL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "net/gnrc/pkt.h"
|
#include "net/gnrc/pkt.h"
|
||||||
|
#include "net/gnrc/netif.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -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,
|
void gnrc_sixlowpan_dispatch_send(gnrc_pktsnip_t *pkt, void *context,
|
||||||
unsigned page);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -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.
|
* @brief Compresses a 6LoWPAN for IPHC.
|
||||||
*
|
*
|
||||||
* @param[in,out] pkt A 6LoWPAN frame with an uncompressed IPv6 header to
|
* @pre (pkt != NULL)
|
||||||
* send. Will be translated to an 6LoWPAN IPHC frame.
|
*
|
||||||
|
* @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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
static void _receive(gnrc_pktsnip_t *pkt)
|
||||||
{
|
{
|
||||||
gnrc_pktsnip_t *payload;
|
gnrc_pktsnip_t *payload;
|
||||||
@ -225,8 +270,8 @@ static inline bool _add_uncompr_disp(gnrc_pktsnip_t *pkt)
|
|||||||
static void _send(gnrc_pktsnip_t *pkt)
|
static void _send(gnrc_pktsnip_t *pkt)
|
||||||
{
|
{
|
||||||
gnrc_netif_hdr_t *hdr;
|
gnrc_netif_hdr_t *hdr;
|
||||||
gnrc_pktsnip_t *pkt2;
|
gnrc_pktsnip_t *tmp;
|
||||||
gnrc_netif_t *iface;
|
gnrc_netif_t *netif;
|
||||||
/* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */
|
/* datagram_size: pure IPv6 packet without 6LoWPAN dispatches or compression */
|
||||||
size_t datagram_size;
|
size_t datagram_size;
|
||||||
|
|
||||||
@ -242,95 +287,37 @@ static void _send(gnrc_pktsnip_t *pkt)
|
|||||||
return;
|
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");
|
DEBUG("6lo: no space left in packet buffer\n");
|
||||||
gnrc_pktbuf_release(pkt);
|
gnrc_pktbuf_release(pkt);
|
||||||
return;
|
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;
|
if (netif == NULL) {
|
||||||
iface = gnrc_netif_get_by_pid(hdr->if_pid);
|
|
||||||
datagram_size = gnrc_pkt_len(pkt2->next);
|
|
||||||
|
|
||||||
if (iface == NULL) {
|
|
||||||
DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n");
|
DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n");
|
||||||
gnrc_pktbuf_release(pkt);
|
gnrc_pktbuf_release(pkt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||||
if (iface->flags & GNRC_NETIF_FLAGS_6LO_HC) {
|
if (netif->flags & GNRC_NETIF_FLAGS_6LO_HC) {
|
||||||
if (!gnrc_sixlowpan_iphc_encode(pkt2)) {
|
gnrc_sixlowpan_iphc_send(pkt, NULL, 0);
|
||||||
DEBUG("6lo: error on IPHC encoding\n");
|
return;
|
||||||
gnrc_pktbuf_release(pkt2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* IPHC dispatch does not count on dispatch length since it _shortens_
|
|
||||||
* the datagram */
|
|
||||||
}
|
}
|
||||||
else {
|
#endif
|
||||||
if (!_add_uncompr_disp(pkt2)) {
|
if (!_add_uncompr_disp(pkt)) {
|
||||||
/* 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 */
|
/* adding uncompressed dispatch failed */
|
||||||
DEBUG("6lo: no space left in packet buffer\n");
|
DEBUG("6lo: no space left in packet buffer\n");
|
||||||
gnrc_pktbuf_release(pkt2);
|
gnrc_pktbuf_release(pkt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
gnrc_sixlowpan_multiplex_by_size(pkt, datagram_size, netif, 0);
|
||||||
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);
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *_event_loop(void *args)
|
static void *_event_loop(void *args)
|
||||||
|
|||||||
@ -23,6 +23,7 @@
|
|||||||
#include "net/ipv6/hdr.h"
|
#include "net/ipv6/hdr.h"
|
||||||
#include "net/gnrc.h"
|
#include "net/gnrc.h"
|
||||||
#include "net/gnrc/sixlowpan/ctx.h"
|
#include "net/gnrc/sixlowpan/ctx.h"
|
||||||
|
#include "net/gnrc/sixlowpan/internal.h"
|
||||||
#include "net/sixlowpan.h"
|
#include "net/sixlowpan.h"
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
#include "net/gnrc/nettype.h"
|
#include "net/gnrc/nettype.h"
|
||||||
@ -581,20 +582,25 @@ static inline size_t iphc_nhc_udp_encode(gnrc_pktsnip_t *udp, ipv6_hdr_t *ipv6_h
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
gnrc_netif_hdr_t *netif_hdr = pkt->data;
|
||||||
ipv6_hdr_t *ipv6_hdr = pkt->next->data;
|
ipv6_hdr_t *ipv6_hdr = pkt->next->data;
|
||||||
uint8_t *iphc_hdr;
|
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_sixlowpan_ctx_t *src_ctx = NULL, *dst_ctx = NULL;
|
||||||
gnrc_pktsnip_t *dispatch = gnrc_pktbuf_add(NULL, NULL, pkt->next->size,
|
gnrc_pktsnip_t *dispatch = gnrc_pktbuf_add(NULL, NULL, pkt->next->size,
|
||||||
GNRC_NETTYPE_SIXLOWPAN);
|
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) {
|
if (dispatch == NULL) {
|
||||||
DEBUG("6lo iphc: error allocating dispatch space\n");
|
DEBUG("6lo iphc: error allocating dispatch space\n");
|
||||||
return false;
|
gnrc_pktbuf_release(pkt);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
iphc_hdr = dispatch->data;
|
iphc_hdr = dispatch->data;
|
||||||
@ -892,7 +898,9 @@ bool gnrc_sixlowpan_iphc_encode(gnrc_pktsnip_t *pkt)
|
|||||||
dispatch->next = pkt->next;
|
dispatch->next = pkt->next;
|
||||||
pkt->next = dispatch;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user