Merge pull request #3494 from authmillenon/ng_sixlowpan_frag/fix/rbuf

ng_sixlowpan: Fixes
dev/timer
Martine Lenders 8 years ago
commit 8960be109d

@ -26,6 +26,7 @@
#include "net/ng_netapi.h"
#include "net/ng_netif.h"
#include "net/ng_netif/hdr.h"
#include "net/ng_sixlowpan/netif.h"
#include "net/ng_ipv6/netif.h"
@ -474,14 +475,24 @@ void ng_ipv6_netif_init_by_dev(void)
sizeof(if_type)) != -ENOTSUP) &&
(if_type == NG_NETTYPE_SIXLOWPAN)) {
uint16_t src_len = 8;
DEBUG("Set 6LoWPAN flag\n");
uint16_t max_frag_size = UINT16_MAX;
DEBUG("ipv6 netif: Set 6LoWPAN flag\n");
ipv6_ifs[i].flags |= NG_IPV6_NETIF_FLAGS_SIXLOWPAN;
/* use EUI-64 (8-byte address) for IID generation and for sending
* packets */
ng_netapi_set(ifs[i], NG_NETOPT_SRC_LEN, 0, &src_len,
sizeof(src_len)); /* don't care for result */
}
if (ng_netapi_get(ifs[i], NG_NETOPT_MAX_PACKET_SIZE,
0, &max_frag_size, sizeof(max_frag_size)) < 0) {
/* if error we assume it works */
DEBUG("ipv6 netif: Can not get max packet size from interface %"
PRIkernel_pid "\n", ifs[i]);
}
ng_sixlowpan_netif_add(ifs[i], max_frag_size);
}
#endif
if ((ng_netapi_get(ifs[i], NG_NETOPT_IPV6_IID, 0, &iid,

@ -191,7 +191,7 @@ static uint16_t _send_nth_fragment(ng_sixlowpan_netif_t *iface, ng_pktsnip_t *pk
}
}
DEBUG("6lo frag: send first fragment (datagram size: %u, "
DEBUG("6lo frag: send subsequent fragment (datagram size: %u, "
"datagram tag: %" PRIu16 ", offset: %" PRIu8 " (%u bytes), "
"fragment size: %" PRIu16 ")\n",
(unsigned int)datagram_size, _tag, hdr->offset, hdr->offset << 3,
@ -217,6 +217,7 @@ void ng_sixlowpan_frag_send(kernel_pid_t pid, ng_pktsnip_t *pkt,
if ((res = _send_1st_fragment(iface, pkt, payload_len, datagram_size)) == 0) {
/* error sending first fragment */
DEBUG("6lo frag: error sending 1st fragment\n");
ng_pktbuf_release(pkt);
return;
}
@ -226,7 +227,9 @@ void ng_sixlowpan_frag_send(kernel_pid_t pid, ng_pktsnip_t *pkt,
while (offset < datagram_size) {
if ((res = _send_nth_fragment(iface, pkt, payload_len, datagram_size,
offset)) == 0) {
/* error sending first fragment */
/* error sending subsequent fragment */
DEBUG("6lo frag: error sending subsequent fragment (offset = %" PRIu16
")\n", offset);
ng_pktbuf_release(pkt);
return;
}

@ -16,10 +16,7 @@
#include <stdbool.h>
#include "rbuf.h"
#include "net/ng_netapi.h"
#include "net/ng_netif.h"
#include "net/ng_netif/hdr.h"
#include "net/ng_pktbuf.h"
#include "net/ng_netbase.h"
#include "net/ng_ipv6/netif.h"
#include "net/ng_sixlowpan.h"
#include "net/ng_sixlowpan/frag.h"
@ -67,7 +64,6 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
rbuf_t *entry;
rbuf_int_t *ptr;
uint8_t *data = ((uint8_t *)frag) + sizeof(ng_sixlowpan_frag_t);
uint16_t dg_frag_size = frag_size; /* may differ on first fragment */
_rbuf_gc();
entry = _rbuf_get(ng_netif_hdr_get_src_addr(netif_hdr), netif_hdr->src_l2addr_len,
@ -83,10 +79,12 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
ptr = entry->ints;
/* dispatches in the first fragment are ignored */
if (offset != 0) {
switch (((uint8_t *)(entry->pkt->data))[0]) {
if (offset == 0) {
switch (data[0]) {
case NG_SIXLOWPAN_UNCOMPRESSED:
offset++;
data++; /* skip 6LoWPAN dispatch */
frag_size--;
entry->compressed = 0; /* datagram is not compressed */
break;
@ -94,19 +92,9 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
break;
}
data++; /* also don't take offset field */
}
else {
switch (data[0]) {
case NG_SIXLOWPAN_UNCOMPRESSED:
dg_frag_size--;
break;
default:
break;
}
data++; /* FRAGN header is one byte longer (offset) */
}
if ((offset + frag_size) > entry->pkt->size) {
@ -117,7 +105,7 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
}
while (ptr != NULL) {
if (_rbuf_int_in(ptr, offset, offset + dg_frag_size - 1)) {
if (_rbuf_int_in(ptr, offset, offset + frag_size - 1)) {
DEBUG("6lo rfrag: overlapping or same intervals, discarding datagram\n");
ng_pktbuf_release(entry->pkt);
_rbuf_rem(entry);
@ -127,31 +115,13 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
ptr = ptr->next;
}
if (_rbuf_update_ints(entry, offset, dg_frag_size)) {
if (dg_frag_size < frag_size) {
/* some dispatches do not count to datagram size and we need
* more space because of that */
if (ng_pktbuf_realloc_data(entry->pkt, entry->pkt->size +
(frag_size - dg_frag_size)) < 0) {
DEBUG("6lo rbuf: could not reallocate packet data.\n");
return;
}
/* move already inserted fragments (frag_size - dg_frag_size) to the right */
if (entry->cur_size > 0) {
for (int i = entry->pkt->size - (frag_size - dg_frag_size); i > 0; i--) {
uint8_t *d = ((uint8_t *)(entry->pkt->data)) + i;
*d = *(d - 1);
}
}
}
if (_rbuf_update_ints(entry, offset, frag_size)) {
DEBUG("6lo rbuf: add fragment data\n");
entry->cur_size += (uint16_t)dg_frag_size;
entry->cur_size += (uint16_t)frag_size;
memcpy(((uint8_t *)entry->pkt->data) + offset, data, frag_size);
}
if (entry->cur_size == entry->datagram_size) {
if (entry->cur_size == entry->pkt->size) {
kernel_pid_t iface = netif_hdr->if_pid;
ng_pktsnip_t *netif = ng_netif_hdr_build(entry->src, entry->src_len,
entry->dst, entry->dst_len);
@ -159,6 +129,7 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
if (netif == NULL) {
DEBUG("6lo rbuf: error allocating netif header\n");
ng_pktbuf_release(entry->pkt);
_rbuf_rem(entry);
return;
}
@ -166,8 +137,18 @@ void rbuf_add(ng_netif_hdr_t *netif_hdr, ng_sixlowpan_frag_t *frag,
netif_hdr->if_pid = iface;
LL_APPEND(entry->pkt, netif);
DEBUG("6lo rbuf: datagram complete, send to self\n");
ng_netapi_receive(thread_getpid(), entry->pkt);
if (entry->compressed) {
DEBUG("6lo rbuf: datagram complete, send to self for decompression\n");
ng_netapi_receive(thread_getpid(), entry->pkt);
}
else {
DEBUG("6lo rbuf: datagram complete, send to IPv6 listeners\n");
if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL,
entry->pkt)) {
DEBUG("6lo rbuf: No receivers for this packet found\n");
ng_pktbuf_release(entry->pkt);
}
}
_rbuf_rem(entry);
}
}
@ -222,9 +203,9 @@ static bool _rbuf_update_ints(rbuf_t *entry, uint16_t offset, size_t frag_size)
DEBUG("6lo rfrag: add interval (%" PRIu16 ", %" PRIu16 ") to entry (%s, ",
new->start, new->end, ng_netif_addr_to_str(l2addr_str,
sizeof(l2addr_str), entry->src, entry->src_len));
DEBUG("%s, %u, %" PRIu16 ")\n", ng_netif_addr_to_str(l2addr_str,
sizeof(l2addr_str), entry->dst, entry->dst_len), entry->datagram_size,
entry->tag);
DEBUG("%s, %u, %u)\n", ng_netif_addr_to_str(l2addr_str,
sizeof(l2addr_str), entry->dst, entry->dst_len),
(unsigned)entry->pkt->size, entry->tag);
LL_PREPEND(entry->ints, new);
@ -247,10 +228,10 @@ static void _rbuf_gc(void)
((now.seconds - rbuf[i].arrival) > RBUF_TIMEOUT)) {
DEBUG("6lo rfrag: entry (%s, ", ng_netif_addr_to_str(l2addr_str,
sizeof(l2addr_str), rbuf[i].src, rbuf[i].src_len));
DEBUG("%s, %u, %" PRIu16 ") timed out\n",
DEBUG("%s, %u, %u) timed out\n",
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), rbuf[i].dst,
rbuf[i].dst_len),
rbuf[i].datagram_size, rbuf[i].tag);
(unsigned)rbuf[i].pkt->size, rbuf[i].tag);
ng_pktbuf_release(rbuf[i].pkt);
_rbuf_rem(&(rbuf[i]));
@ -278,7 +259,7 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
for (unsigned int i = 0; i < RBUF_SIZE; i++) {
/* check first if entry already available */
if ((rbuf[i].pkt != NULL) && (rbuf[i].datagram_size == size) &&
if ((rbuf[i].pkt != NULL) && (rbuf[i].pkt->size == size) &&
(rbuf[i].tag == tag) && (rbuf[i].src_len == src_len) &&
(rbuf[i].dst_len == dst_len) &&
(memcmp(rbuf[i].src, src, src_len) == 0) &&
@ -286,10 +267,10 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
DEBUG("6lo rfrag: entry %p (%s, ", (void *)(&rbuf[i]),
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str),
rbuf[i].src, rbuf[i].src_len));
DEBUG("%s, %u, %" PRIu16 ") found\n",
DEBUG("%s, %u, %u) found\n",
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str),
rbuf[i].dst, rbuf[i].dst_len),
rbuf[i].datagram_size, rbuf[i].tag);
(unsigned)rbuf[i].pkt->size, rbuf[i].tag);
rbuf[i].arrival = now.seconds;
return &(rbuf[i]);
}
@ -315,15 +296,16 @@ static rbuf_t *_rbuf_get(const void *src, size_t src_len,
res->src_len = src_len;
res->dst_len = dst_len;
res->tag = tag;
res->datagram_size = size;
res->cur_size = 0;
res->compressed = 1;
DEBUG("6lo rfrag: entry %p (%s, ", (void *)res,
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->src,
res->src_len));
DEBUG("%s, %u, %" PRIu16 ") created\n",
DEBUG("%s, %u, %u) created\n",
ng_netif_addr_to_str(l2addr_str, sizeof(l2addr_str), res->dst,
res->dst_len), res->datagram_size, res->tag);
res->dst_len), (unsigned)res->pkt->size,
res->tag);
}
return res;

@ -77,8 +77,8 @@ typedef struct {
uint8_t src_len; /**< length of source address */
uint8_t dst_len; /**< length of destination address */
uint16_t tag; /**< the datagram's tag */
uint16_t datagram_size; /**< the datagram's size (without 6lo dispatches) */
uint16_t cur_size; /**< the datagram's current size */
uint16_t compressed; /**< the datagram has a compressed header */
} rbuf_t;
/**

@ -141,23 +141,36 @@ static void _receive(ng_pktsnip_t *pkt)
payload->type = NG_NETTYPE_IPV6;
if (!ng_netapi_dispatch_receive(NG_NETTYPE_IPV6, NG_NETREG_DEMUX_CTX_ALL, pkt)) {
DEBUG("ipv6: No receivers for this packet found\n");
DEBUG("6lo: No receivers for this packet found\n");
ng_pktbuf_release(pkt);
}
}
static inline bool _add_uncompr_disp(ng_pktsnip_t *pkt)
{
ng_pktsnip_t *sixlowpan;
uint8_t *disp;
DEBUG("6lo: Send uncompressed\n");
sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN);
if (sixlowpan == NULL) {
return false;
}
sixlowpan->next = pkt->next;
pkt->next = sixlowpan;
disp = sixlowpan->data;
disp[0] = NG_SIXLOWPAN_UNCOMPRESSED;
return true;
}
static void _send(ng_pktsnip_t *pkt)
{
ng_netif_hdr_t *hdr;
ng_pktsnip_t *ipv6, *sixlowpan;
ng_pktsnip_t *pkt2;
ng_sixlowpan_netif_t *iface;
/* cppcheck: datagram_size will be read by frag */
/* cppcheck-suppress unreadVariable */
size_t payload_len, datagram_size;
uint16_t max_frag_size;
/* cppcheck: disp is needed in other build paths on this level already */
/* cppcheck-suppress variableScope */
uint8_t *disp;
size_t datagram_size, dispatch_len = 0;
if ((pkt == NULL) || (pkt->size < sizeof(ng_netif_hdr_t))) {
DEBUG("6lo: Sending packet has no netif header\n");
@ -165,120 +178,84 @@ static void _send(ng_pktsnip_t *pkt)
return;
}
hdr = pkt->data;
ipv6 = pkt->next;
if ((ipv6 == NULL) || (ipv6->type != NG_NETTYPE_IPV6)) {
if ((pkt->next == NULL) || (pkt->next->type != NG_NETTYPE_IPV6)) {
DEBUG("6lo: Sending packet has no IPv6 header\n");
ng_pktbuf_release(pkt);
return;
}
/* payload length and datagram size are different in that the payload
* length is the length of the IPv6 datagram + 6LoWPAN dispatches,
* while the datagram size is the size of only the IPv6 datagram */
payload_len = ng_pkt_len(ipv6);
/* cppcheck: datagram_size will be read by ng_sixlowpan_frag implementation */
/* cppcheck-suppress unreadVariable */
datagram_size = (uint16_t)payload_len;
pkt2 = ng_pktbuf_start_write(pkt);
/* use sixlowpan packet snip as temporary one */
sixlowpan = ng_pktbuf_start_write(pkt);
if (sixlowpan == NULL) {
if (pkt2 == NULL) {
DEBUG("6lo: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
return;
}
pkt = sixlowpan;
hdr = pkt2->data;
iface = ng_sixlowpan_netif_get(hdr->if_pid);
if (iface == NULL) {
if (ng_netapi_get(hdr->if_pid, NG_NETOPT_MAX_PACKET_SIZE,
0, &max_frag_size, sizeof(max_frag_size)) < 0) {
/* if error we assume it works */
DEBUG("6lo: can not get max packet size from interface %"
PRIkernel_pid "\n", hdr->if_pid);
max_frag_size = UINT16_MAX;
}
ng_sixlowpan_netif_add(hdr->if_pid, max_frag_size);
iface = ng_sixlowpan_netif_get(hdr->if_pid);
}
else {
max_frag_size = iface->max_frag_size;
DEBUG("6lo: Can not get 6LoWPAN specific interface information.\n");
ng_pktbuf_release(pkt);
return;
}
#ifdef MODULE_NG_SIXLOWPAN_IPHC
if (iface->iphc_enabled) {
if (!ng_sixlowpan_iphc_encode(pkt)) {
if (!ng_sixlowpan_iphc_encode(pkt2)) {
DEBUG("6lo: error on IPHC encoding\n");
ng_pktbuf_release(pkt);
ng_pktbuf_release(pkt2);
return;
}
/* IPHC dispatch does not count on dispatch length since it _shortens_
* the datagram */
}
else {
DEBUG("6lo: Send uncompressed\n");
sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t),
NG_NETTYPE_SIXLOWPAN);
if (sixlowpan == NULL) {
if (!_add_uncompr_disp(pkt2)) {
/* adding uncompressed dispatch failed */
DEBUG("6lo: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
ng_pktbuf_release(pkt2);
return;
}
sixlowpan->next = ipv6;
pkt->next = sixlowpan;
disp = sixlowpan->data;
disp[0] = NG_SIXLOWPAN_UNCOMPRESSED;
payload_len++;
dispatch_len += 1;
}
#else
/* suppress clang-analyzer report about iface being not read */
(void) iface;
DEBUG("6lo: Send uncompressed\n");
sixlowpan = ng_pktbuf_add(NULL, NULL, sizeof(uint8_t), NG_NETTYPE_SIXLOWPAN);
if (sixlowpan == NULL) {
if (!_add_uncompr_disp(pkt2)) {
/* adding uncompressed dispatch failed */
DEBUG("6lo: no space left in packet buffer\n");
ng_pktbuf_release(pkt);
ng_pktbuf_release(pkt2);
return;
}
sixlowpan->next = ipv6;
pkt->next = sixlowpan;
disp = sixlowpan->data;
disp[0] = NG_SIXLOWPAN_UNCOMPRESSED;
payload_len++;
dispatch_len += 1;
#endif
datagram_size = ng_pkt_len(pkt2->next);
DEBUG("6lo: max_frag_size = %" PRIu16 " for interface %"
PRIkernel_pid "\n", max_frag_size, hdr->if_pid);
DEBUG("6lo: iface->max_frag_size = %" PRIu16 " for interface %"
PRIkernel_pid "\n", iface->max_frag_size, hdr->if_pid);
/* IP should not send anything here if it is not a 6LoWPAN interface,
* so we don't need to check for NULL pointers */
if (payload_len <= max_frag_size) {
if ((datagram_size + dispatch_len) <= iface->max_frag_size) {
DEBUG("6lo: Send SND command for %p to %" PRIu16 "\n",
(void *)pkt, hdr->if_pid);
ng_netapi_send(hdr->if_pid, pkt);
(void *)pkt2, hdr->if_pid);
ng_netapi_send(hdr->if_pid, pkt2);
return;
}
#ifdef MODULE_NG_SIXLOWPAN_FRAG
else {
DEBUG("6lo: Send fragmented (%u > %" PRIu16 ")\n",
(unsigned int)payload_len, max_frag_size);
ng_sixlowpan_frag_send(hdr->if_pid, pkt, payload_len, datagram_size);
(unsigned int)datagram_size + dispatch_len, iface->max_frag_size);
ng_sixlowpan_frag_send(hdr->if_pid, pkt2, datagram_size + dispatch_len,
datagram_size);
}
#else
(void)datagram_size;
DEBUG("6lo: packet too big (%u> %" PRIu16 ")\n",
(unsigned int)payload_len, max_frag_size);
(unsigned int)(datagram_size + dispatch_len), iface->max_frag_size);
#endif
}

Loading…
Cancel
Save