diff --git a/sys/include/net/gnrc/sixlowpan/frag.h b/sys/include/net/gnrc/sixlowpan/frag.h index 96841b882e..f557470ebc 100644 --- a/sys/include/net/gnrc/sixlowpan/frag.h +++ b/sys/include/net/gnrc/sixlowpan/frag.h @@ -74,26 +74,45 @@ typedef struct { */ typedef struct { 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 */ + size_t datagram_size; /**< Length of just the (uncompressed) IPv6 packet to be fragmented */ uint16_t offset; /**< Offset of the Nth fragment from the beginning of the * payload datagram */ kernel_pid_t pid; /**< PID of the interface */ } gnrc_sixlowpan_msg_frag_t; /** - * @brief Sends a packet fragmented. + * @brief Allocates a @ref gnrc_sixlowpan_msg_frag_t object * - * @param[in] fragment_msg Message containing status of the 6LoWPAN - * fragmentation progress + * @return A @ref gnrc_sixlowpan_msg_frag_t if available + * @return NULL, otherwise */ -void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg); +gnrc_sixlowpan_msg_frag_t *gnrc_sixlowpan_msg_frag_get(void); /** - * @brief Handles a packet containing a fragment header. + * @brief Sends a packet fragmented * - * @param[in] pkt The packet to handle. + * @pre `ctx != NULL` + * @pre gnrc_sixlowpan_msg_frag_t::pkt of @p ctx is equal to @p pkt or + * `pkt == NULL`. + * + * @param[in] pkt A packet. May be NULL. + * @param[in] ctx Message containing status of the 6LoWPAN fragmentation + * progress. Expected to be of type + * @ref gnrc_sixlowpan_msg_frag_t, with + * gnrc_sixlowpan_msg_frag_t set to @p pkt. Must not be + * NULL. + * @param[in] page Current 6Lo dispatch parsing page. */ -void gnrc_sixlowpan_frag_handle_pkt(gnrc_pktsnip_t *pkt); +void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page); + +/** + * @brief Handles a packet containing a fragment header + * + * @param[in] pkt The packet to handle + * @param[in] ctx Context for the packet. May be NULL. + * @param[in] page Current 6Lo dispatch parsing page. + */ +void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page); #ifdef __cplusplus } diff --git a/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c b/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c index ce137cdd73..6724dc929a 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c +++ b/sys/net/gnrc/network_layer/sixlowpan/frag/gnrc_sixlowpan_frag.c @@ -31,6 +31,10 @@ #define ENABLE_DEBUG (0) #include "debug.h" +static gnrc_sixlowpan_msg_frag_t _fragment_msg = { + NULL, 0, 0, KERNEL_PID_UNDEF + }; + #if ENABLE_DEBUG /* For PRIu16 etc. */ #include @@ -209,8 +213,15 @@ static uint16_t _send_nth_fragment(gnrc_netif_t *iface, gnrc_pktsnip_t *pkt, return local_offset; } -void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg) +gnrc_sixlowpan_msg_frag_t *gnrc_sixlowpan_msg_frag_get(void) { + return (_fragment_msg.pkt == NULL) ? &_fragment_msg : NULL; +} + +void gnrc_sixlowpan_frag_send(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) +{ + assert(ctx != NULL); + gnrc_sixlowpan_msg_frag_t *fragment_msg = ctx; gnrc_netif_t *iface = gnrc_netif_get_by_pid(fragment_msg->pid); uint16_t res; /* payload_len: actual size of the packet vs @@ -218,6 +229,9 @@ void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg) size_t payload_len = gnrc_pkt_len(fragment_msg->pkt->next); msg_t msg; + assert((fragment_msg->pkt == pkt) || (pkt == NULL)); + (void)page; + (void)pkt; #if defined(DEVELHELP) && ENABLE_DEBUG if (iface == NULL) { DEBUG("6lo frag: iface == NULL, expect segmentation fault.\n"); @@ -275,13 +289,15 @@ void gnrc_sixlowpan_frag_send(gnrc_sixlowpan_msg_frag_t *fragment_msg) } } -void gnrc_sixlowpan_frag_handle_pkt(gnrc_pktsnip_t *pkt) +void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page) { gnrc_netif_hdr_t *hdr = pkt->next->data; sixlowpan_frag_t *frag = pkt->data; uint16_t offset = 0; size_t frag_size; + (void)ctx; + (void)page; switch (frag->disp_size.u8[0] & SIXLOWPAN_FRAG_DISP_MASK) { case SIXLOWPAN_FRAG_1_DISP: frag_size = (pkt->size - sizeof(sixlowpan_frag_t)); diff --git a/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c b/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c index cd744dd051..18c615851c 100644 --- a/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c +++ b/sys/net/gnrc/network_layer/sixlowpan/gnrc_sixlowpan.c @@ -34,10 +34,6 @@ static kernel_pid_t _pid = KERNEL_PID_UNDEF; -#ifdef MODULE_GNRC_SIXLOWPAN_FRAG -static gnrc_sixlowpan_msg_frag_t fragment_msg = {NULL, 0, 0, KERNEL_PID_UNDEF}; -#endif - #if ENABLE_DEBUG static char _stack[GNRC_SIXLOWPAN_STACK_SIZE + THREAD_EXTRA_STACKSIZE_PRINTF]; #else @@ -164,7 +160,7 @@ static void _receive(gnrc_pktsnip_t *pkt) #ifdef MODULE_GNRC_SIXLOWPAN_FRAG else if (sixlowpan_frag_is((sixlowpan_frag_t *)dispatch)) { DEBUG("6lo: received 6LoWPAN fragment\n"); - gnrc_sixlowpan_frag_handle_pkt(pkt); + gnrc_sixlowpan_frag_recv(pkt, NULL, 0); return; } #endif @@ -305,27 +301,24 @@ 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 > %" PRIu8 ")\n", (unsigned int)datagram_size, iface->sixlo.max_frag_size); - msg_t msg; + gnrc_sixlowpan_msg_frag_t *fragment_msg; - fragment_msg.pid = hdr->if_pid; - fragment_msg.pkt = pkt2; - fragment_msg.datagram_size = datagram_size; + 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; + fragment_msg->offset = 0; - /* set the outgoing message's fields */ - msg.type = GNRC_SIXLOWPAN_MSG_FRAG_SND; - msg.content.ptr = &fragment_msg; - /* send message to self */ - msg_send_to_self(&msg); + gnrc_sixlowpan_frag_send(pkt2, fragment_msg, 0); } else { DEBUG("6lo: packet too big (%u > %" PRIu16 ")\n", @@ -380,7 +373,7 @@ static void *_event_loop(void *args) #ifdef MODULE_GNRC_SIXLOWPAN_FRAG case GNRC_SIXLOWPAN_MSG_FRAG_SND: DEBUG("6lo: send fragmented event received\n"); - gnrc_sixlowpan_frag_send(msg.content.ptr); + gnrc_sixlowpan_frag_send(NULL, msg.content.ptr, 0); break; #endif