mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 10:03:50 +01:00
Merge pull request #9484 from miri64/gnrc_sixlowpan_iphc/enh/i8511-recv
gnrc_sixlowpan_iphc: refactor reception for #8511
This commit is contained in:
commit
f03e52d157
@ -32,23 +32,17 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief Decompresses a received 6LoWPAN IPHC frame.
|
* @brief Decompresses a received 6LoWPAN IPHC frame.
|
||||||
*
|
*
|
||||||
* @pre (dec_hdr != NULL) && (*dec_hdr != NULL) && ((*dec_hdr)->size >= sizeof(gnrc_ipv6_hdr_t))
|
* @pre (pkt != NULL)
|
||||||
*
|
*
|
||||||
* @param[out] dec_hdr A pre-allocated IPv6 header. Will not be inserted into
|
* @param[in] pkt A received 6LoWPAN IPHC frame. The first snip is to
|
||||||
* @p pkt. May change due to next headers being added in NHC.
|
* be expected to start with the IPHC dispatch.
|
||||||
* @param[in] pkt A received 6LoWPAN IPHC frame. IPHC dispatch will not
|
* @param[in,out] ctx Context for the packet. May be NULL. If not NULL it
|
||||||
* be marked.
|
* is expected to be of type
|
||||||
* @param[in] datagram_size Size of the full uncompressed IPv6 datagram. May be 0, if @p pkt
|
* @ref gnrc_sixlowpan_rbuf_t. This function might
|
||||||
* contains the full (unfragmented) IPv6 datagram.
|
* change the content of that.
|
||||||
* @param[in] offset Offset of the IPHC dispatch in 6LoWPaN frame.
|
* @param[in] page Current 6Lo dispatch parsing page.
|
||||||
* @param[in, out] nh_len Pointer to next header length
|
|
||||||
*
|
|
||||||
* @return length of the HC dispatches + inline values on success.
|
|
||||||
* @return 0 on error.
|
|
||||||
*/
|
*/
|
||||||
size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
|
void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page);
|
||||||
size_t datagram_size, size_t offset,
|
|
||||||
size_t *nh_len);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compresses a 6LoWPAN for IPHC.
|
* @brief Compresses a 6LoWPAN for IPHC.
|
||||||
|
|||||||
@ -312,8 +312,6 @@ void gnrc_sixlowpan_frag_recv(gnrc_pktsnip_t *pkt, void *ctx, unsigned page)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rbuf_add(hdr, pkt, offset, page);
|
rbuf_add(hdr, pkt, offset, page);
|
||||||
|
|
||||||
gnrc_pktbuf_release(pkt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gnrc_sixlowpan_frag_rbuf_gc(void)
|
void gnrc_sixlowpan_frag_rbuf_gc(void)
|
||||||
|
|||||||
@ -69,9 +69,6 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
size_t offset, unsigned page)
|
size_t offset, unsigned page)
|
||||||
{
|
{
|
||||||
rbuf_t *entry;
|
rbuf_t *entry;
|
||||||
/* cppcheck-suppress variableScope
|
|
||||||
* (reason: cppcheck is clearly wrong here) */
|
|
||||||
unsigned int data_offset = 0;
|
|
||||||
sixlowpan_frag_t *frag = pkt->data;
|
sixlowpan_frag_t *frag = pkt->data;
|
||||||
rbuf_int_t *ptr;
|
rbuf_int_t *ptr;
|
||||||
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
|
uint8_t *data = ((uint8_t *)pkt->data) + sizeof(sixlowpan_frag_t);
|
||||||
@ -96,27 +93,6 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
if (data[0] == SIXLOWPAN_UNCOMP) {
|
if (data[0] == SIXLOWPAN_UNCOMP) {
|
||||||
frag_size--;
|
frag_size--;
|
||||||
}
|
}
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
|
||||||
else if (sixlowpan_iphc_is(data)) {
|
|
||||||
size_t iphc_len, nh_len = 0;
|
|
||||||
iphc_len = gnrc_sixlowpan_iphc_decode(&entry->super.pkt, pkt,
|
|
||||||
entry->super.pkt->size,
|
|
||||||
sizeof(sixlowpan_frag_t),
|
|
||||||
&nh_len);
|
|
||||||
if (iphc_len == 0) {
|
|
||||||
DEBUG("6lo rfrag: could not decode IPHC dispatch\n");
|
|
||||||
gnrc_pktbuf_release(entry->super.pkt);
|
|
||||||
rbuf_rm(entry);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
data += iphc_len; /* take remaining data as data */
|
|
||||||
frag_size -= iphc_len; /* and reduce frag size by IPHC dispatch length */
|
|
||||||
/* but add IPv6 header + next header lengths */
|
|
||||||
frag_size += sizeof(ipv6_hdr_t) + nh_len;
|
|
||||||
/* start copying after IPv6 header and next headers */
|
|
||||||
data_offset += sizeof(ipv6_hdr_t) + nh_len;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
frag_size = pkt->size - sizeof(sixlowpan_frag_n_t);
|
frag_size = pkt->size - sizeof(sixlowpan_frag_n_t);
|
||||||
@ -153,11 +129,30 @@ void rbuf_add(gnrc_netif_hdr_t *netif_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
if (_rbuf_update_ints(entry, offset, frag_size)) {
|
if (_rbuf_update_ints(entry, offset, frag_size)) {
|
||||||
DEBUG("6lo rbuf: add fragment data\n");
|
DEBUG("6lo rbuf: add fragment data\n");
|
||||||
entry->super.current_size += (uint16_t)frag_size;
|
entry->super.current_size += (uint16_t)frag_size;
|
||||||
memcpy(((uint8_t *)entry->super.pkt->data) + offset + data_offset, data,
|
if (offset == 0) {
|
||||||
frag_size - data_offset);
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||||
|
if (sixlowpan_iphc_is(data)) {
|
||||||
|
gnrc_pktsnip_t *frag_hdr = gnrc_pktbuf_mark(pkt,
|
||||||
|
sizeof(sixlowpan_frag_t), GNRC_NETTYPE_SIXLOWPAN);
|
||||||
|
if (frag_hdr == NULL) {
|
||||||
|
gnrc_pktbuf_release(entry->super.pkt);
|
||||||
|
rbuf_rm(entry);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gnrc_sixlowpan_iphc_recv(pkt, &entry->super, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (data[0] == SIXLOWPAN_UNCOMP) {
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memcpy(((uint8_t *)entry->super.pkt->data) + offset, data,
|
||||||
|
frag_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr);
|
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(&entry->super, netif_hdr);
|
||||||
|
gnrc_pktbuf_release(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool _rbuf_int_overlap_partially(rbuf_int_t *i, uint16_t start, uint16_t end)
|
static inline bool _rbuf_int_overlap_partially(rbuf_int_t *i, uint16_t start, uint16_t end)
|
||||||
|
|||||||
@ -211,32 +211,9 @@ static void _receive(gnrc_pktsnip_t *pkt)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC
|
||||||
else if (sixlowpan_iphc_is(dispatch)) {
|
else if (sixlowpan_iphc_is(dispatch)) {
|
||||||
size_t dispatch_size, nh_len;
|
DEBUG("6lo: received 6LoWPAN IPHC comressed datagram\n");
|
||||||
gnrc_pktsnip_t *sixlowpan;
|
gnrc_sixlowpan_iphc_recv(pkt, NULL, 0);
|
||||||
gnrc_pktsnip_t *dec_hdr = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t),
|
return;
|
||||||
GNRC_NETTYPE_IPV6);
|
|
||||||
if ((dec_hdr == NULL) ||
|
|
||||||
(dispatch_size = gnrc_sixlowpan_iphc_decode(&dec_hdr, pkt, 0, 0,
|
|
||||||
&nh_len)) == 0) {
|
|
||||||
DEBUG("6lo: error on IPHC decoding\n");
|
|
||||||
if (dec_hdr != NULL) {
|
|
||||||
gnrc_pktbuf_release(dec_hdr);
|
|
||||||
}
|
|
||||||
gnrc_pktbuf_release(pkt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sixlowpan = gnrc_pktbuf_mark(pkt, dispatch_size, GNRC_NETTYPE_SIXLOWPAN);
|
|
||||||
if (sixlowpan == NULL) {
|
|
||||||
DEBUG("6lo: error on marking IPHC dispatch\n");
|
|
||||||
gnrc_pktbuf_release(dec_hdr);
|
|
||||||
gnrc_pktbuf_release(pkt);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove IPHC dispatches */
|
|
||||||
/* Insert decoded header instead */
|
|
||||||
pkt = gnrc_pktbuf_replace_snip(pkt, sixlowpan, dec_hdr);
|
|
||||||
payload->type = GNRC_NETTYPE_UNDEF;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else {
|
else {
|
||||||
|
|||||||
@ -22,7 +22,9 @@
|
|||||||
#include "net/ieee802154.h"
|
#include "net/ieee802154.h"
|
||||||
#include "net/ipv6/hdr.h"
|
#include "net/ipv6/hdr.h"
|
||||||
#include "net/gnrc.h"
|
#include "net/gnrc.h"
|
||||||
|
#include "net/gnrc/sixlowpan.h"
|
||||||
#include "net/gnrc/sixlowpan/ctx.h"
|
#include "net/gnrc/sixlowpan/ctx.h"
|
||||||
|
#include "net/gnrc/sixlowpan/frag.h"
|
||||||
#include "net/gnrc/sixlowpan/internal.h"
|
#include "net/gnrc/sixlowpan/internal.h"
|
||||||
#include "net/sixlowpan.h"
|
#include "net/sixlowpan.h"
|
||||||
#include "utlist.h"
|
#include "utlist.h"
|
||||||
@ -112,36 +114,47 @@ static inline bool _context_overlaps_iid(gnrc_sixlowpan_ctx_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
||||||
static inline size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t **dec_hdr,
|
/**
|
||||||
size_t datagram_size, size_t offset)
|
* @brief Decodes UDP NHC
|
||||||
|
*
|
||||||
|
* @param[in] pkt The IPHC encoded packet
|
||||||
|
* @param[in] offset The offset of the NHC encoded header
|
||||||
|
* @param[in] ipv6_payload_len Length of the unencoded, reassembled IPv6
|
||||||
|
* datagram in @p ipv6 with out the outer-most
|
||||||
|
* IPv6 header
|
||||||
|
* @param[out] ipv6 The packet to write the decoded data to
|
||||||
|
* @param[in,out] uncomp_hdr_len Number of bytes already decoded into @p ipv6
|
||||||
|
* by IPHC and other NHC. Adds size of @ref
|
||||||
|
* udp_hdr_t after successful UDP header
|
||||||
|
* decompression
|
||||||
|
*
|
||||||
|
* @return The offset after UDP NHC header on success.
|
||||||
|
* @return 0 on error.
|
||||||
|
*/
|
||||||
|
static size_t _iphc_nhc_udp_decode(gnrc_pktsnip_t *sixlo, size_t offset,
|
||||||
|
gnrc_pktsnip_t *ipv6, size_t *uncomp_hdr_len)
|
||||||
{
|
{
|
||||||
uint8_t *payload = pkt->data;
|
uint8_t *payload = sixlo->data;
|
||||||
gnrc_pktsnip_t *ipv6 = *dec_hdr;
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
ipv6_hdr_t *ipv6_hdr = ipv6->data;
|
udp_hdr_t *udp_hdr;
|
||||||
#ifdef MODULE_GNRC_UDP
|
bool frag = true; /* datagram is fragmented => infer payload length from
|
||||||
const gnrc_nettype_t snip_type = GNRC_NETTYPE_UDP;
|
* ipv6 snip (== reassembly buffer space) */
|
||||||
#else
|
uint16_t payload_len;
|
||||||
const gnrc_nettype_t snip_type = GNRC_NETTYPE_UNDEF;
|
|
||||||
#endif
|
|
||||||
gnrc_pktsnip_t *udp = NULL;
|
|
||||||
uint8_t udp_nhc = payload[offset++];
|
uint8_t udp_nhc = payload[offset++];
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
udp_hdr_t *udp_hdr;
|
|
||||||
|
|
||||||
if (datagram_size == 0) { /* received packet is not fragmented */
|
/* realloc size for uncompressed snip, if too small */
|
||||||
udp = gnrc_pktbuf_add(NULL, NULL, sizeof(udp_hdr_t),
|
if (ipv6->size < (*uncomp_hdr_len + sizeof(udp_hdr_t))) {
|
||||||
snip_type);
|
if (gnrc_pktbuf_realloc_data(ipv6,
|
||||||
if (udp == NULL) {
|
*uncomp_hdr_len + sizeof(udp_hdr_t))) {
|
||||||
DEBUG("6lo: error on IPHC NHC UDP decoding\n");
|
DEBUG("6lo: unable to decode UDP NHC (not enough buffer space)\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
udp_hdr = udp->data;
|
frag = false; /* datagram was not fragmented => infer payload length
|
||||||
}
|
* from original 6Lo packet*/
|
||||||
else { /* received packet is fragmented */
|
|
||||||
/* reassembly is in-place => don't allocate new packet snip */
|
|
||||||
/* TODO: account for extension headers */
|
|
||||||
udp_hdr = (udp_hdr_t *)(ipv6_hdr + 1);
|
|
||||||
}
|
}
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
udp_hdr = (udp_hdr_t *)((uint8_t *)ipv6->data + *uncomp_hdr_len);
|
||||||
network_uint16_t *src_port = &(udp_hdr->src_port);
|
network_uint16_t *src_port = &(udp_hdr->src_port);
|
||||||
network_uint16_t *dst_port = &(udp_hdr->dst_port);
|
network_uint16_t *dst_port = &(udp_hdr->dst_port);
|
||||||
|
|
||||||
@ -182,7 +195,6 @@ static inline size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t **d
|
|||||||
|
|
||||||
if ((udp_nhc & NHC_UDP_C_ELIDED) != 0) {
|
if ((udp_nhc & NHC_UDP_C_ELIDED) != 0) {
|
||||||
DEBUG("6lo iphc nhc: unsupported elided checksum\n");
|
DEBUG("6lo iphc nhc: unsupported elided checksum\n");
|
||||||
gnrc_pktbuf_release(udp);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -190,43 +202,58 @@ static inline size_t iphc_nhc_udp_decode(gnrc_pktsnip_t *pkt, gnrc_pktsnip_t **d
|
|||||||
udp_hdr->checksum.u8[1] = payload[offset++];
|
udp_hdr->checksum.u8[1] = payload[offset++];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO subtract extension header length */
|
if (frag) {
|
||||||
if (udp != NULL) {
|
payload_len = ipv6->size - *uncomp_hdr_len;
|
||||||
udp_hdr->length = byteorder_htons(pkt->size - offset + sizeof(udp_hdr_t));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
udp_hdr->length = byteorder_htons(datagram_size - sizeof(ipv6_hdr_t));
|
payload_len = sixlo->size + sizeof(udp_hdr_t) - offset;
|
||||||
}
|
}
|
||||||
|
udp_hdr->length = byteorder_htons(payload_len);
|
||||||
|
*uncomp_hdr_len += sizeof(udp_hdr_t);
|
||||||
ipv6_hdr->nh = PROTNUM_UDP;
|
ipv6_hdr->nh = PROTNUM_UDP;
|
||||||
ipv6_hdr->len = udp_hdr->length;
|
|
||||||
|
|
||||||
if (udp != NULL) { /* prepend udp header in case of packet not being fragmented */
|
|
||||||
udp->next = ipv6;
|
|
||||||
*dec_hdr = udp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
|
static inline void _recv_error_release(gnrc_pktsnip_t *sixlo,
|
||||||
size_t datagram_size, size_t offset,
|
gnrc_pktsnip_t *ipv6,
|
||||||
size_t *nh_len)
|
gnrc_sixlowpan_rbuf_t *rbuf) {
|
||||||
|
if (rbuf != NULL) {
|
||||||
|
gnrc_sixlowpan_frag_rbuf_remove(rbuf);
|
||||||
|
}
|
||||||
|
gnrc_pktbuf_release(ipv6);
|
||||||
|
gnrc_pktbuf_release(sixlo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gnrc_sixlowpan_iphc_recv(gnrc_pktsnip_t *sixlo, void *rbuf_ptr,
|
||||||
|
unsigned page)
|
||||||
{
|
{
|
||||||
gnrc_pktsnip_t *ipv6;
|
assert(sixlo != NULL);
|
||||||
gnrc_netif_hdr_t *netif_hdr = pkt->next->data;
|
gnrc_pktsnip_t *ipv6, *netif;
|
||||||
|
gnrc_netif_hdr_t *netif_hdr;
|
||||||
ipv6_hdr_t *ipv6_hdr;
|
ipv6_hdr_t *ipv6_hdr;
|
||||||
uint8_t *iphc_hdr = pkt->data;
|
uint8_t *iphc_hdr = sixlo->data;
|
||||||
size_t payload_offset = SIXLOWPAN_IPHC_HDR_LEN;
|
size_t payload_offset = SIXLOWPAN_IPHC_HDR_LEN;
|
||||||
|
size_t uncomp_hdr_len = sizeof(ipv6_hdr_t);
|
||||||
gnrc_sixlowpan_ctx_t *ctx = NULL;
|
gnrc_sixlowpan_ctx_t *ctx = NULL;
|
||||||
|
gnrc_sixlowpan_rbuf_t *rbuf = rbuf_ptr;
|
||||||
|
|
||||||
|
if (rbuf != NULL) {
|
||||||
|
ipv6 = rbuf->pkt;
|
||||||
|
assert(ipv6 != NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ipv6 = gnrc_pktbuf_add(NULL, NULL, sizeof(ipv6_hdr_t),
|
||||||
|
GNRC_NETTYPE_IPV6);
|
||||||
|
if (ipv6 == NULL) {
|
||||||
|
gnrc_pktbuf_release(sixlo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(dec_hdr != NULL);
|
|
||||||
ipv6 = *dec_hdr;
|
|
||||||
assert(ipv6 != NULL);
|
|
||||||
assert(ipv6->size >= sizeof(ipv6_hdr_t));
|
assert(ipv6->size >= sizeof(ipv6_hdr_t));
|
||||||
|
|
||||||
ipv6_hdr = ipv6->data;
|
ipv6_hdr = ipv6->data;
|
||||||
iphc_hdr += offset;
|
|
||||||
|
|
||||||
if (iphc_hdr[IPHC2_IDX] & SIXLOWPAN_IPHC2_CID_EXT) {
|
if (iphc_hdr[IPHC2_IDX] & SIXLOWPAN_IPHC2_CID_EXT) {
|
||||||
payload_offset++;
|
payload_offset++;
|
||||||
@ -295,11 +322,15 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
|
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
DEBUG("6lo iphc: could not find source context\n");
|
DEBUG("6lo iphc: could not find source context\n");
|
||||||
return 0;
|
_recv_error_release(sixlo, ipv6, rbuf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
netif = gnrc_pktsnip_search_type(sixlo, GNRC_NETTYPE_NETIF);
|
||||||
|
assert(netif != NULL);
|
||||||
|
netif_hdr = netif->data;
|
||||||
switch (iphc_hdr[IPHC2_IDX] & (SIXLOWPAN_IPHC2_SAC | SIXLOWPAN_IPHC2_SAM)) {
|
switch (iphc_hdr[IPHC2_IDX] & (SIXLOWPAN_IPHC2_SAC | SIXLOWPAN_IPHC2_SAM)) {
|
||||||
|
|
||||||
case IPHC_SAC_SAM_FULL:
|
case IPHC_SAC_SAM_FULL:
|
||||||
@ -373,7 +404,8 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
|
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
DEBUG("6lo iphc: could not find destination context\n");
|
DEBUG("6lo iphc: could not find destination context\n");
|
||||||
return 0;
|
_recv_error_release(sixlo, ipv6, rbuf);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,42 +514,61 @@ size_t gnrc_sixlowpan_iphc_decode(gnrc_pktsnip_t **dec_hdr, gnrc_pktsnip_t *pkt,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
DEBUG("6lo iphc: unspecified or reserved M, DAC, DAM combination\n");
|
DEBUG("6lo iphc: unspecified or reserved M, DAC, DAM combination\n");
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set IPv6 header payload length field to the length of whatever is left
|
|
||||||
* after removing the 6LoWPAN header */
|
|
||||||
if (datagram_size == 0) {
|
|
||||||
ipv6_hdr->len = byteorder_htons((uint16_t)(pkt->size - payload_offset));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ipv6_hdr->len = byteorder_htons((uint16_t)(datagram_size - sizeof(ipv6_hdr_t)));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
||||||
if (iphc_hdr[IPHC1_IDX] & SIXLOWPAN_IPHC1_NH) {
|
if (iphc_hdr[IPHC1_IDX] & SIXLOWPAN_IPHC1_NH) {
|
||||||
switch (iphc_hdr[payload_offset] & NHC_ID_MASK) {
|
switch (iphc_hdr[payload_offset] & NHC_ID_MASK) {
|
||||||
case NHC_UDP_ID:
|
case NHC_UDP_ID: {
|
||||||
payload_offset = iphc_nhc_udp_decode(pkt, dec_hdr, datagram_size,
|
payload_offset = _iphc_nhc_udp_decode(sixlo, payload_offset,
|
||||||
payload_offset + offset);
|
ipv6, &uncomp_hdr_len);
|
||||||
|
if (payload_offset == 0) {
|
||||||
if (payload_offset != 0) {
|
_recv_error_release(sixlo, ipv6, rbuf);
|
||||||
payload_offset -= offset;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*nh_len += sizeof(udp_hdr_t);
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
(void)nh_len;
|
|
||||||
#endif
|
#endif
|
||||||
|
uint16_t payload_len;
|
||||||
return payload_offset;
|
if (rbuf != NULL) {
|
||||||
|
/* for a fragmented datagram we know the overall length already */
|
||||||
|
payload_len = (uint16_t)(rbuf->pkt->size - sizeof(ipv6_hdr_t));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* set IPv6 header payload length field to the length of whatever is left
|
||||||
|
* after removing the 6LoWPAN header and adding uncompressed headers */
|
||||||
|
payload_len = (sixlo->size + uncomp_hdr_len -
|
||||||
|
payload_offset - sizeof(ipv6_hdr_t));
|
||||||
|
}
|
||||||
|
if ((rbuf == NULL) &&
|
||||||
|
(gnrc_pktbuf_realloc_data(ipv6, uncomp_hdr_len + payload_len) != 0)) {
|
||||||
|
DEBUG("6lo iphc: no space left to copy payload\n");
|
||||||
|
_recv_error_release(sixlo, ipv6, rbuf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* re-assign IPv6 header in case realloc changed the address */
|
||||||
|
ipv6_hdr = ipv6->data;
|
||||||
|
ipv6_hdr->len = byteorder_htons(payload_len);
|
||||||
|
memcpy(((uint8_t *)ipv6->data) + uncomp_hdr_len,
|
||||||
|
((uint8_t *)sixlo->data) + payload_offset,
|
||||||
|
sixlo->size - payload_offset);
|
||||||
|
if (rbuf != NULL) {
|
||||||
|
rbuf->current_size += (uncomp_hdr_len - payload_offset);
|
||||||
|
gnrc_sixlowpan_frag_rbuf_dispatch_when_complete(rbuf, netif_hdr);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LL_DELETE(sixlo, netif);
|
||||||
|
LL_APPEND(ipv6, netif);
|
||||||
|
gnrc_sixlowpan_dispatch_recv(ipv6, NULL, page);
|
||||||
|
}
|
||||||
|
gnrc_pktbuf_release(sixlo);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
#ifdef MODULE_GNRC_SIXLOWPAN_IPHC_NHC
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user