mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #4381 from PeterKietzmann/sixlo_frag_unblocking
gnrc_sixlowpan_frag: Make fragmentation non-blocking
This commit is contained in:
commit
15220b26ad
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* Copyright (C) 2015 Hamburg University of Applied Sciences
|
||||
*
|
||||
* 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
|
||||
@ -19,6 +20,7 @@
|
||||
* @brief 6LoWPAN Fragmentation definitions
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*/
|
||||
#ifndef GNRC_SIXLOWPAN_FRAG_H_
|
||||
#define GNRC_SIXLOWPAN_FRAG_H_
|
||||
@ -35,17 +37,29 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Message type for passing one 6LoWPAN fragment down the network stack
|
||||
*/
|
||||
#define GNRC_SIXLOWPAN_MSG_FRAG_SND (0x0225)
|
||||
|
||||
/**
|
||||
* @brief Definition of 6LoWPAN fragmentation type.
|
||||
*/
|
||||
typedef struct {
|
||||
kernel_pid_t pid; /**< PID of the interface */
|
||||
gnrc_pktsnip_t *pkt; /**< Pointer to the IPv6 packet to be fragmented */
|
||||
size_t datagram_size; /**< Length of just the IPv6 packet to be fragmented */
|
||||
uint16_t offset; /**< Offset of the Nth fragment from the beginning of the
|
||||
* payload datagram */
|
||||
} gnrc_sixlowpan_msg_frag_t;
|
||||
|
||||
/**
|
||||
* @brief Sends a packet fragmented.
|
||||
*
|
||||
* @param[in] pid The interface to send the packet over.
|
||||
* @param[in] pkt The packet to send.
|
||||
* @param[in] datagram_size The length of just the IPv6 packet. It is the value
|
||||
* that the gnrc_sixlowpan_frag_t::disp_size field will be
|
||||
* set to.
|
||||
* @param[in] fragment_msg Message containing status of the 6LoWPAN
|
||||
* fragmentation progress
|
||||
*/
|
||||
void gnrc_sixlowpan_frag_send(kernel_pid_t pid, gnrc_pktsnip_t *pkt,
|
||||
size_t datagram_size);
|
||||
void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg);
|
||||
|
||||
/**
|
||||
* @brief Handles a packet containing a fragment header.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* Copyright (C) 2015 Hamburg University of Applied Sciences
|
||||
*
|
||||
* 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
|
||||
@ -10,6 +11,9 @@
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Martine Lenders <mlenders@inf.fu-berlin.de>
|
||||
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#include "kernel_types.h"
|
||||
@ -212,51 +216,70 @@ static uint16_t _send_nth_fragment(gnrc_sixlowpan_netif_t *iface, gnrc_pktsnip_t
|
||||
return local_offset;
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_send(kernel_pid_t pid, gnrc_pktsnip_t *pkt,
|
||||
size_t datagram_size)
|
||||
void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg)
|
||||
{
|
||||
gnrc_sixlowpan_netif_t *iface = gnrc_sixlowpan_netif_get(pid);
|
||||
uint16_t offset = 0, res;
|
||||
gnrc_sixlowpan_netif_t *iface = gnrc_sixlowpan_netif_get(fragment_msg->pid);
|
||||
uint16_t res;
|
||||
/* payload_len: actual size of the packet vs
|
||||
* datagram_size: size of the uncompressed IPv6 packet */
|
||||
size_t payload_len = gnrc_pkt_len(pkt->next);
|
||||
size_t payload_len = gnrc_pkt_len(fragment_msg->pkt->next);
|
||||
msg_t msg;
|
||||
|
||||
#if defined(DEVELHELP) && defined(ENABLE_DEBUG)
|
||||
if (iface == NULL) {
|
||||
DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
/* remove original packet from packet buffer */
|
||||
gnrc_pktbuf_release(fragment_msg->pkt);
|
||||
/* 6LoWPAN free for next fragmentation */
|
||||
fragment_msg->pkt = NULL;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((res = _send_1st_fragment(iface, pkt, payload_len, datagram_size)) == 0) {
|
||||
/* error sending first fragment */
|
||||
DEBUG("6lo frag: error sending 1st fragment\n");
|
||||
gnrc_pktbuf_release(pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
offset += res;
|
||||
thread_yield();
|
||||
|
||||
/* (offset + (datagram_size - payload_len) < datagram_size) simplified */
|
||||
while (offset < payload_len) {
|
||||
if ((res = _send_nth_fragment(iface, pkt, payload_len, datagram_size,
|
||||
offset)) == 0) {
|
||||
/* error sending subsequent fragment */
|
||||
DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16
|
||||
")\n", offset);
|
||||
gnrc_pktbuf_release(pkt);
|
||||
/* Check weater to send the first or an Nth fragment */
|
||||
if (fragment_msg->offset == 0) {
|
||||
/* increment tag for successive, fragmented datagrams */
|
||||
_tag++;
|
||||
if ((res = _send_1st_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size)) == 0) {
|
||||
/* error sending first fragment */
|
||||
DEBUG("6lo frag: error sending 1st fragment\n");
|
||||
gnrc_pktbuf_release(fragment_msg->pkt);
|
||||
fragment_msg->pkt = NULL;
|
||||
return;
|
||||
}
|
||||
fragment_msg->offset += res;
|
||||
|
||||
offset += res;
|
||||
/* send message to self*/
|
||||
msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND;
|
||||
msg.content.ptr = (void *)fragment_msg;
|
||||
msg_send_to_self(&msg);
|
||||
thread_yield();
|
||||
}
|
||||
else {
|
||||
/* (offset + (datagram_size - payload_len) < datagram_size) simplified */
|
||||
if (fragment_msg->offset < payload_len) {
|
||||
if ((res = _send_nth_fragment(iface, fragment_msg->pkt, payload_len, fragment_msg->datagram_size,
|
||||
fragment_msg->offset)) == 0) {
|
||||
/* error sending subsequent fragment */
|
||||
DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16
|
||||
")\n", fragment_msg->offset);
|
||||
gnrc_pktbuf_release(fragment_msg->pkt);
|
||||
fragment_msg->pkt = NULL;
|
||||
return;
|
||||
}
|
||||
fragment_msg->offset += res;
|
||||
|
||||
/* remove original packet from packet buffer */
|
||||
gnrc_pktbuf_release(pkt);
|
||||
_tag++;
|
||||
/* send message to self*/
|
||||
msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND;
|
||||
msg.content.ptr = (void *)fragment_msg;
|
||||
msg_send_to_self(&msg);
|
||||
thread_yield();
|
||||
}
|
||||
else {
|
||||
gnrc_pktbuf_release(fragment_msg->pkt);
|
||||
fragment_msg->pkt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gnrc_sixlowpan_frag_handle_pkt(gnrc_pktsnip_t *pkt)
|
||||
|
@ -34,6 +34,8 @@
|
||||
|
||||
static kernel_pid_t _pid = KERNEL_PID_UNDEF;
|
||||
|
||||
static gnrc_sixlowpan_msg_frag_t fragment_msg = {KERNEL_PID_UNDEF, NULL, 0, 0};
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
static char _stack[GNRC_SIXLOWPAN_STACK_SIZE + THREAD_EXTRA_STACKSIZE_PRINTF];
|
||||
#else
|
||||
@ -270,10 +272,27 @@ static void _send(gnrc_pktsnip_t *pkt)
|
||||
return;
|
||||
}
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
else if (fragment_msg.pkt != NULL) {
|
||||
DEBUG("6lo: Fragmentation already ongoing. Dropping packet\n");
|
||||
gnrc_pktbuf_release(pkt2);
|
||||
return;
|
||||
}
|
||||
else if (datagram_size <= SIXLOWPAN_FRAG_MAX_LEN) {
|
||||
DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n",
|
||||
(unsigned int)datagram_size, iface->max_frag_size);
|
||||
gnrc_sixlowpan_frag_send(hdr->if_pid, pkt2, datagram_size);
|
||||
msg_t msg;
|
||||
|
||||
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;
|
||||
|
||||
/* set the outgoing message's fields */
|
||||
msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND;
|
||||
msg.content.ptr = (void *)&fragment_msg;
|
||||
/* send message to self */
|
||||
msg_send_to_self(&msg);
|
||||
}
|
||||
else {
|
||||
DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n",
|
||||
@ -327,6 +346,12 @@ static void *_event_loop(void *args)
|
||||
reply.content.value = -ENOTSUP;
|
||||
msg_reply(&msg, &reply);
|
||||
break;
|
||||
#ifdef MODULE_GNRC_SIXLOWPAN_FRAG
|
||||
case GNRC_SIXLOWPAN_MSG_FRAG_SND:
|
||||
DEBUG("6lo: send fragmented event received\n");
|
||||
gnrc_sixlowpan_frag_send((gnrc_sixlowpan_msg_frag_t *)msg.content.ptr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
DEBUG("6lo: operation not supported\n");
|
||||
|
Loading…
Reference in New Issue
Block a user