Skip to content

Commit

Permalink
Merge pull request #3143 from authmillenon/ng_sixlowpan_ctx/api/comp-…
Browse files Browse the repository at this point in the history
…flag

ng_sixlowpan_ctx: add compression flag support
  • Loading branch information
OlegHahm committed Jul 17, 2015
2 parents 7779850 + e6747b8 commit 717a4c8
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 83 deletions.
39 changes: 32 additions & 7 deletions sys/include/net/ng_sixlowpan/ctx.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define NG_SIXLOWPAN_CTX_H_

#include <inttypes.h>
#include <stdbool.h>

#include "net/ng_ipv6/addr.h"

Expand All @@ -40,19 +41,32 @@ extern "C" {
#define NG_SIXLOWPAN_CTX_SIZE (16) /**< maximum number of entries in
* context buffer */

/**
* @{
* @name Context flags.
* @brief Flags to set in ng_sixlowpan_ctx_t::flags_id.
*/
#define NG_SIXLOWPAN_CTX_FLAGS_CID_MASK (0x0f) /**< mask for the Context ID. */
#define NG_SIXLOWPAN_CTX_FLAGS_COMP (0x10) /**< Use context for compression */
/**
* @}
*/

/**
* @brief Entry in the 6LoWPAN context buffer.
*/
typedef struct {
ng_ipv6_addr_t prefix; /**< The prefix associated to this context. */
uint8_t prefix_len; /**< Length of ng_sixlowpan_ctx_t::prefix in bit. */
/**
* @brief 4-bit Context ID.
* @brief 4-bit flags, 4-bit Context ID.
*
* @note This needs to be here to easily translate prefixes to
* ID.
*
* @details The flags are defined as above.
*/
uint8_t id;
uint8_t flags_id;
/**
* @brief Lifetime in minutes this context is valid.
*
Expand Down Expand Up @@ -89,17 +103,28 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_id(uint8_t id);
* @param[in] id The ID for the context.
* Must be < @ref NG_SIXLOWPAN_CTX_SIZE.
* @param[in] prefix The prefix for the context.
* @param[in] prefix_len Length of @p prefix in bits. Must be > 0, when
* @p ltime > 0.
* @param[in] ltime New lifetime of the context. The context will
* be removed if 0.
* @param[in] prefix_len Length of @p prefix in bits. Must be > 0.
* @param[in] ltime New lifetime of the context. @p comp will be
* implicitly set to `false` if @p ltime == 0.
* @param[in] comp Use for compression if true, do not use for
* compression, but still for decompression if false.
*
* @return The new context on success.
* @return NULL, on error or on removal.
*/
ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *prefix,
uint8_t prefix_len, uint16_t ltime);
uint8_t prefix_len, uint16_t ltime,
bool comp);

/**
* @brief Removes context.
*
* @param[in] id A context ID.
*/
static inline void ng_sixlowpan_ctx_remove(uint8_t id)
{
ng_sixlowpan_ctx_lookup_id(id)->prefix_len = 0;
}

#ifdef TEST_SUITES
/**
Expand Down
37 changes: 14 additions & 23 deletions sys/net/network_layer/ng_sixlowpan/ctx/ng_sixlowpan_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ static uint32_t _ctx_inval_times[NG_SIXLOWPAN_CTX_SIZE];
static mutex_t _ctx_mutex = MUTEX_INIT;

static uint32_t _current_minute(void);
static void _update_lifetime(unsigned int id);
static void _update_lifetime(uint8_t id);

#if ENABLE_DEBUG
static char ipv6str[NG_IPV6_ADDR_MAX_STR_LEN];
#endif

static inline bool _still_valid(unsigned int id)
static inline bool _valid(uint8_t id)
{
_update_lifetime(id);
return (_ctxs[id].ltime > 0);
return (_ctxs[id].prefix_len > 0);
}

ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_addr(const ng_ipv6_addr_t *addr)
Expand All @@ -47,7 +47,7 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_addr(const ng_ipv6_addr_t *addr)
mutex_lock(&_ctx_mutex);

for (unsigned int id = 0; id < NG_SIXLOWPAN_CTX_SIZE; id++) {
if (_still_valid(id)) {
if (_valid(id)) {
uint8_t match = ng_ipv6_addr_match_prefix(&_ctxs[id].prefix, addr);

if ((_ctxs[id].prefix_len <= match) && (match > best)) {
Expand Down Expand Up @@ -79,7 +79,7 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_id(uint8_t id)

mutex_lock(&_ctx_mutex);

if (_still_valid((unsigned int)id)) {
if (_valid(id)) {
DEBUG("6lo ctx: found context (%u, %s/%" PRIu8 ")\n", id,
ng_ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)),
_ctxs[id].prefix_len);
Expand All @@ -93,9 +93,10 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_lookup_id(uint8_t id)
}

ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *prefix,
uint8_t prefix_len, uint16_t ltime)
uint8_t prefix_len, uint16_t ltime,
bool comp)
{
if ((id >= NG_SIXLOWPAN_CTX_SIZE)) {
if ((id >= NG_SIXLOWPAN_CTX_SIZE) || (prefix_len == 0)) {
return NULL;
}

Expand All @@ -104,19 +105,7 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *pr
_ctxs[id].ltime = ltime;

if (ltime == 0) {
mutex_unlock(&_ctx_mutex);
DEBUG("6lo ctx: remove context (%u, %s/%" PRIu8 ")\n", id,
ng_ipv6_addr_to_str(ipv6str, &_ctxs[id].prefix, sizeof(ipv6str)),
_ctxs[id].prefix_len);
return NULL;
}

/* test prefix_len now so that invalidation is possible regardless of the
* value. */
if (prefix_len == 0) {
mutex_unlock(&_ctx_mutex);
_ctxs[id].ltime = 0;
return NULL;
comp = false;
}

if (prefix_len > NG_IPV6_ADDR_BIT_LEN) {
Expand All @@ -126,7 +115,7 @@ ng_sixlowpan_ctx_t *ng_sixlowpan_ctx_update(uint8_t id, const ng_ipv6_addr_t *pr
_ctxs[id].prefix_len = prefix_len;
}

_ctxs[id].id = id;
_ctxs[id].flags_id = (comp) ? (NG_SIXLOWPAN_CTX_FLAGS_COMP | id) : id;

if (!ng_ipv6_addr_equal(&(_ctxs[id].prefix), prefix)) {
ng_ipv6_addr_set_unspecified(&(_ctxs[id].prefix));
Expand All @@ -150,19 +139,21 @@ static uint32_t _current_minute(void)
return now.seconds / 60;
}

static void _update_lifetime(unsigned int id)
static void _update_lifetime(uint8_t id)
{
uint32_t now;

if (_ctxs[id].ltime == 0) {
_ctxs[id].flags_id &= ~NG_SIXLOWPAN_CTX_FLAGS_COMP;
return;
}

now = _current_minute();

if (now >= _ctx_inval_times[id]) {
DEBUG("6lo ctx: context %u was invalidated\n", id);
DEBUG("6lo ctx: context %u was invalidated for compression\n", id);
_ctxs[id].ltime = 0;
_ctxs[id].flags_id &= ~NG_SIXLOWPAN_CTX_FLAGS_COMP;
}
else {
_ctxs[id].ltime = (uint16_t)(_ctx_inval_times[id] - now);
Expand Down
80 changes: 43 additions & 37 deletions sys/net/network_layer/ng_sixlowpan/iphc/ng_sixlowpan_iphc.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ static inline bool _context_overlaps_iid(ng_sixlowpan_ctx_t *ctx,
{
uint8_t byte_mask[] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};

if (ctx == NULL) {
if ((ctx == NULL) || (ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP)) {
return false;
}

Expand Down Expand Up @@ -357,7 +357,7 @@ bool ng_sixlowpan_iphc_decode(ng_pktsnip_t *pkt)
payload_offset += 4;

ctx->prefix_len = orig_ctx_len;
} while (0); /* ANSI-C compatible block creation for orig_ctx_len allocation*/
} while (0); /* ANSI-C compatible block creation for orig_ctx_len allocation */
break;

default:
Expand Down Expand Up @@ -412,8 +412,12 @@ bool ng_sixlowpan_iphc_encode(ng_pktsnip_t *pkt)

/* if contexts available and both != 0 */
/* since this moves inline_pos we have to do this ahead*/
if (((src_ctx != NULL) && (src_ctx->id != 0)) ||
((dst_ctx != NULL) && (dst_ctx->id != 0))) {
if (((src_ctx != NULL) &&
((src_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_CID_MASK) != 0) &&
(src_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP)) ||
((dst_ctx != NULL) &&
((dst_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_CID_MASK) != 0) &&
(dst_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP))) {
/* add context identifier extension */
iphc_hdr[IPHC2_IDX] |= NG_SIXLOWPAN_IPHC2_CID_EXT;
iphc_hdr[CID_EXT_IDX] = 0;
Expand Down Expand Up @@ -485,51 +489,51 @@ bool ng_sixlowpan_iphc_encode(ng_pktsnip_t *pkt)
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_UNSPEC;
}
else {
if (src_ctx != NULL) {
if ((src_ctx != NULL) && (src_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP)) {
/* stateful source address compression */
iphc_hdr[IPHC2_IDX] |= NG_SIXLOWPAN_IPHC2_SAC;

if (src_ctx->id != 0) { /* context id is elided */
iphc_hdr[CID_EXT_IDX] |= (src_ctx->id << 4);
if (((src_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_CID_MASK) != 0)) {
iphc_hdr[CID_EXT_IDX] |= ((src_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_CID_MASK) << 4);
}
}

if ((src_ctx != NULL) || ng_ipv6_addr_is_link_local(&(ipv6_hdr->src))) {
eui64_t iid;
eui64_t iid = { 0 };

if ((netif_hdr->src_l2addr_len == 2) ||
(netif_hdr->src_l2addr_len == 4) ||
(netif_hdr->src_l2addr_len == 8)) {
/* prefer to create IID from netif header if available */
ng_ieee802154_get_iid(&iid, ng_netif_hdr_get_src_addr(netif_hdr),
netif_hdr->src_l2addr_len);
addr_comp = true;
}
else {
if (ng_netapi_get(netif_hdr->if_pid, NETCONF_OPT_IPV6_IID, 0,
&iid, sizeof(eui64_t)) >= 0) {
addr_comp = true;
}
/* but take from driver otherwise */
ng_netapi_get(netif_hdr->if_pid, NETCONF_OPT_IPV6_IID, 0, &iid,
sizeof(eui64_t));
}

if (addr_comp) {
if ((ipv6_hdr->src.u64[1].u64 == iid.uint64.u64) ||
_context_overlaps_iid(src_ctx, &ipv6_hdr->src, &iid)) {
/* 0 bits. The address is derived from link-layer address */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_L2;
}
else if ((byteorder_ntohl(ipv6_hdr->src.u32[2]) == 0x000000ff) &&
(byteorder_ntohs(ipv6_hdr->src.u16[6]) == 0xfe00)) {
/* 16 bits. The address is derived using 16 bits carried inline */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_16;
memcpy(iphc_hdr + inline_pos, ipv6_hdr->src.u16 + 7, 2);
inline_pos += 2;
}
else {
/* 64 bits. The address is derived using 64 bits carried inline */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_64;
memcpy(iphc_hdr + inline_pos, ipv6_hdr->src.u64 + 1, 8);
inline_pos += 8;
}
if ((ipv6_hdr->src.u64[1].u64 == iid.uint64.u64) ||
_context_overlaps_iid(src_ctx, &ipv6_hdr->src, &iid)) {
/* 0 bits. The address is derived from link-layer address */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_L2;
addr_comp = true;
}
else if ((byteorder_ntohl(ipv6_hdr->src.u32[2]) == 0x000000ff) &&
(byteorder_ntohs(ipv6_hdr->src.u16[6]) == 0xfe00)) {
/* 16 bits. The address is derived using 16 bits carried inline */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_16;
memcpy(iphc_hdr + inline_pos, ipv6_hdr->src.u16 + 7, 2);
inline_pos += 2;
addr_comp = true;
}
else {
/* 64 bits. The address is derived using 64 bits carried inline */
iphc_hdr[IPHC2_IDX] |= IPHC_SAC_SAM_64;
memcpy(iphc_hdr + inline_pos, ipv6_hdr->src.u64 + 1, 8);
inline_pos += 8;
addr_comp = true;
}
}

Expand Down Expand Up @@ -592,9 +596,11 @@ bool ng_sixlowpan_iphc_encode(ng_pktsnip_t *pkt)

ctx = ng_sixlowpan_ctx_lookup_addr(&unicast_prefix);

if ((ctx != NULL) && (ctx->prefix_len == ipv6_hdr->dst.u8[3])) {
/* Unicast prefix based IPv6 multicast address with given
* context for unicast prefix -> context based compression */
if ((ctx != NULL) && (ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP) &&
(ctx->prefix_len == ipv6_hdr->dst.u8[3])) {
/* Unicast prefix based IPv6 multicast address
* (https://tools.ietf.org/html/rfc3306) with given context
* for unicast prefix -> context based compression */
iphc_hdr[IPHC2_IDX] |= NG_SIXLOWPAN_IPHC2_DAC;
iphc_hdr[inline_pos++] = ipv6_hdr->dst.u8[1];
iphc_hdr[inline_pos++] = ipv6_hdr->dst.u8[2];
Expand All @@ -604,8 +610,8 @@ bool ng_sixlowpan_iphc_encode(ng_pktsnip_t *pkt)
}
}
}
else if (((dst_ctx != NULL) || ng_ipv6_addr_is_link_local(&ipv6_hdr->dst)) &&
(netif_hdr->dst_l2addr_len > 0)) {
else if ((((dst_ctx != NULL) && (dst_ctx->flags_id & NG_SIXLOWPAN_CTX_FLAGS_COMP)) ||
ng_ipv6_addr_is_link_local(&ipv6_hdr->dst)) && (netif_hdr->dst_l2addr_len > 0)) {
eui64_t iid;

ng_ieee802154_get_iid(&iid, ng_netif_hdr_get_dst_addr(netif_hdr),
Expand Down
Loading

0 comments on commit 717a4c8

Please sign in to comment.