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
|
||||
#define NET_GNRC_SIXLOWPAN_INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "net/gnrc/pkt.h"
|
||||
#include "net/gnrc/netif.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
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,
|
||||
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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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 */
|
||||
if (netif->flags & GNRC_NETIF_FLAGS_6LO_HC) {
|
||||
gnrc_sixlowpan_iphc_send(pkt, NULL, 0);
|
||||
return;
|
||||
}
|
||||
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)) {
|
||||
#endif
|
||||
if (!_add_uncompr_disp(pkt)) {
|
||||
/* adding uncompressed dispatch failed */
|
||||
DEBUG("6lo: no space left in packet buffer\n");
|
||||
gnrc_pktbuf_release(pkt2);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
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);
|
||||
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)
|
||||
|
||||
@ -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"
|
||||
@ -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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user