-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sixlowpan.iphc_cbuf: Initial import of an IPHC context buffer
- Loading branch information
Showing
13 changed files
with
789 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
/* | ||
* Copyright (C) 2014 Martin Lenders <mlenders@inf.fu-berlin.de> | ||
* | ||
* 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 directory for | ||
* more details. | ||
*/ | ||
|
||
/** | ||
* @defgroup net_sixlowpan_iphc_cbuf Context buffer for 6LoWPAN IP header compression | ||
* @addtogroup net_sixlowpan | ||
* @{ | ||
* | ||
* @file iphc_cbuf.h | ||
* @brief Context buffer for 6LoWPAN IP header compression | ||
* | ||
* @see <a href="https://tools.ietf.org/html/rfc6282#section-3.1.2"> | ||
* RFC 6282, section 3.1.2 | ||
* </a> | ||
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2"> | ||
* RFC 6775, section 4.2 | ||
* </a> | ||
* | ||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> | ||
*/ | ||
|
||
|
||
#ifndef __SIXLOWPAN_IPHC_CBUF_H_ | ||
#define __SIXLOWPAN_IPHC_CBUF_H_ | ||
|
||
#include "ipv6.h" | ||
|
||
#define SIXLOWPAN_IPHC_CBUF_SIZE (16) | ||
|
||
/** | ||
* @brief Data type to configure 6LoWPAN contexts | ||
* @see <a href="http://tools.ietf.org/html/rfc6282#section-3.1"> | ||
* RFC 6282, section 3.1 | ||
* </a> | ||
*/ | ||
typedef struct { | ||
uint8_t cid; /**< Context ID */ | ||
uint8_t prefix_len; /**< Length of the prefix in bits, if 0 on | ||
NETAPI_CMD_SET the context will be removed. */ | ||
ipv6_addr_t prefix; /**< The prefix associated to this context */ | ||
|
||
/** | ||
* @brief Lifetime in minutes this context is valid. | ||
* | ||
* @see <a href="http://tools.ietf.org/html/rfc6775#section-4.2"> | ||
* 6LoWPAN Context Option | ||
* </a> | ||
*/ | ||
uint32_t lifetime; | ||
} sixlowpan_iphc_cbuf_t; | ||
|
||
/** | ||
* @brief Lookup best context for an IPv6 address. | ||
* | ||
* @param[in] addr An IPv6 address. | ||
* | ||
* @return best fitting context for given IPv6 address. | ||
* @return NULL, if no fitting context can be found. | ||
*/ | ||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_addr(const ipv6_addr_t *addr); | ||
|
||
/** | ||
* @brief Lookup best context for a context ID. | ||
* | ||
* @param[in] cid A context ID, must be < 16. | ||
* | ||
* @return best fitting context for given context ID. | ||
* @return NULL, if no fitting context can be found. | ||
*/ | ||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_cid(uint8_t cid); | ||
|
||
/** | ||
* @brief Returns number of currently saved contexts. | ||
* | ||
* @return Number of currently saved contexts. | ||
*/ | ||
uint8_t sixlowpan_iphc_cbuf_num(void); | ||
|
||
/** | ||
* @brief Remove context by context ID. | ||
* @param[in] cid A context ID, must be < 16. | ||
*/ | ||
void sixlowpan_iphc_cbuf_remove_by_cid(uint8_t cid); | ||
|
||
/** | ||
* @brief Remove context by best address match. | ||
* | ||
* @param[in] addr An IPv6 address. | ||
*/ | ||
static inline void sixlowpan_iphc_cbuf_remove_by_addr(const ipv6_addr_t *addr) | ||
{ | ||
sixlowpan_iphc_cbuf_t *context = sixlowpan_iphc_cbuf_lookup_addr(addr); | ||
|
||
if (context) { | ||
sixlowpan_iphc_cbuf_remove_by_cid(context->cid); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Removes all context with expired lifetime | ||
*/ | ||
void sixlowpan_iphc_cbuf_remove_invalid(void); | ||
|
||
/** | ||
* @brief Update a context | ||
* | ||
* @param[in] cid A context ID, must be < 16. | ||
* @param[in] prefix An IPv6 prefix to associate with *cid*. | ||
* @param[in] prefix_len Length of prefix in bits. If *prefix_len* is longer | ||
* then 128, it will be set to 128. Must be > 0. | ||
* @param[in] lifetime Lifetime the context is valid in minutes. Must be > 0. | ||
* | ||
* @return The updated context on success. | ||
* @return NULL, if cid is >= 16, prefix_len is 0, or lifetime is 0. | ||
*/ | ||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_update(uint8_t cid, const ipv6_addr_t *prefix, | ||
uint8_t prefix_len, uint16_t lifetime); | ||
|
||
#endif /* __SIXLOWPAN_IPHC_CBUF_H_ */ | ||
/** | ||
* @} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE = sixlowpan_iphc_cbuf | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
/* | ||
* Copyright (C) 2014 Martin Lenders <mlenders@inf.fu-berlin.de> | ||
* | ||
* 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 directory for | ||
* more details. | ||
*/ | ||
|
||
/** | ||
* @addtogroup net_sixlowpan_iphc_cbuf | ||
* @{ | ||
* | ||
* @file iphc_cbuf.c | ||
* | ||
* @author Martine Lenders <mlenders@inf.fu-berlin.de> | ||
*/ | ||
|
||
#include <string.h> | ||
|
||
#include "mutex.h" | ||
#include "vtimer.h" | ||
|
||
#include "ipv6.h" | ||
#include "sixlowpan/iphc_cbuf.h" | ||
|
||
static sixlowpan_iphc_cbuf_t _cbuf[SIXLOWPAN_IPHC_CBUF_SIZE]; | ||
static uint32_t _cbuf_invalid_time[SIXLOWPAN_IPHC_CBUF_SIZE]; | ||
static mutex_t _cbuf_mutex = MUTEX_INIT; | ||
|
||
#ifndef MODULE_IPV6 | ||
void ipv6_addr_init_prefix(ipv6_addr_t *out, const ipv6_addr_t *prefix, | ||
uint8_t bits) | ||
{ | ||
if (bits > 128) { | ||
bits = 128; | ||
} | ||
|
||
uint8_t bytes = bits / 8, mask; | ||
|
||
if (bits % 8) { | ||
mask = 0xff << (8 - (bits - (bytes * 8))); | ||
} | ||
else { | ||
mask = 0x00; | ||
} | ||
|
||
memcpy(out, prefix, bytes); | ||
out->u8[bytes] = prefix->u8[bytes] & mask; | ||
memset(&(out[bytes + 1]), 0, 15 - bytes); | ||
} | ||
#endif /* MODULE_IPV6 */ | ||
|
||
static uint32_t _now_in_minutes(void) | ||
{ | ||
timex_t now; | ||
|
||
vtimer_now(&now); | ||
|
||
return now.seconds / 60; | ||
} | ||
|
||
static void _cid_update_lifetime(uint8_t cid) | ||
{ | ||
uint32_t now = _now_in_minutes(); | ||
#ifdef DEVELHELP | ||
|
||
if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { | ||
return; | ||
} | ||
|
||
#endif | ||
|
||
if (now >= _cbuf_invalid_time[cid]) { | ||
_cbuf[cid].lifetime = 0; | ||
} | ||
else { | ||
_cbuf[cid].lifetime = _cbuf_invalid_time[cid] - now; | ||
} | ||
} | ||
|
||
static int _cid_still_valid(uint8_t cid) | ||
{ | ||
#ifdef DEVELHELP | ||
|
||
if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { | ||
return 0; | ||
} | ||
|
||
#endif | ||
_cid_update_lifetime(cid); | ||
|
||
return (_cbuf[cid].lifetime > 0); | ||
} | ||
|
||
void _iphc_cbuf_internal_remove(uint8_t cid) | ||
{ | ||
if (cid < SIXLOWPAN_IPHC_CBUF_SIZE) { | ||
_cbuf[cid].cid = 0; | ||
_cbuf[cid].prefix_len = 0; | ||
memset(&(_cbuf[cid].prefix), 0, sizeof(ipv6_addr_t)); | ||
_cbuf[cid].lifetime = 0; | ||
_cbuf_invalid_time[cid] = 0; | ||
} | ||
} | ||
|
||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_addr(const ipv6_addr_t *addr) | ||
{ | ||
sixlowpan_iphc_cbuf_t *c = NULL; | ||
uint8_t bytes; | ||
|
||
mutex_lock(&_cbuf_mutex); | ||
|
||
for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { | ||
bytes = _cbuf[i].prefix_len / 8; | ||
|
||
if (_cbuf[i].prefix_len > 0 && memcmp(addr, &(_cbuf[i].prefix), bytes) == 0) { | ||
if (_cbuf[i].prefix_len % 8) { | ||
uint8_t mask = 0xff << (8 - (_cbuf[i].prefix_len - (bytes * 8))); | ||
|
||
if ((addr->u8[bytes] & mask) != (_cbuf[i].prefix.u8[bytes] & mask)) { | ||
continue; | ||
} | ||
} | ||
|
||
if (_cid_still_valid(i)) { | ||
if (c == NULL || c->prefix_len < _cbuf[i].prefix_len) { | ||
c = &_cbuf[i]; | ||
} | ||
} | ||
else { | ||
_iphc_cbuf_internal_remove(i); | ||
} | ||
} | ||
} | ||
|
||
mutex_unlock(&_cbuf_mutex); | ||
|
||
return c; | ||
} | ||
|
||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_lookup_cid(uint8_t cid) | ||
{ | ||
sixlowpan_iphc_cbuf_t *c = NULL; | ||
|
||
if (cid >= SIXLOWPAN_IPHC_CBUF_SIZE) { | ||
return NULL; | ||
} | ||
|
||
mutex_lock(&_cbuf_mutex); | ||
|
||
if (_cid_still_valid(cid)) { | ||
c = &(_cbuf[cid]); | ||
} | ||
else { | ||
_iphc_cbuf_internal_remove(cid); | ||
} | ||
|
||
mutex_unlock(&_cbuf_mutex); | ||
|
||
return c; | ||
} | ||
|
||
uint8_t sixlowpan_iphc_cbuf_num(void) | ||
{ | ||
uint8_t num = 0; | ||
|
||
mutex_lock(&_cbuf_mutex); | ||
|
||
for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { | ||
if (_cid_still_valid(i) && _cbuf[i].prefix_len > 0) { | ||
num++; | ||
} | ||
else { | ||
_iphc_cbuf_internal_remove(i); | ||
} | ||
} | ||
|
||
mutex_unlock(&_cbuf_mutex); | ||
|
||
return num; | ||
} | ||
|
||
void sixlowpan_iphc_cbuf_remove_by_cid(uint8_t cid) | ||
{ | ||
mutex_lock(&_cbuf_mutex); | ||
_iphc_cbuf_internal_remove(cid); | ||
mutex_unlock(&_cbuf_mutex); | ||
} | ||
|
||
void sixlowpan_iphc_cbuf_remove_invalid(void) | ||
{ | ||
mutex_lock(&_cbuf_mutex); | ||
|
||
for (int i = 0; i < SIXLOWPAN_IPHC_CBUF_SIZE; i++) { | ||
if (!_cid_still_valid(i)) { | ||
_iphc_cbuf_internal_remove(i); | ||
} | ||
} | ||
|
||
mutex_unlock(&_cbuf_mutex); | ||
} | ||
|
||
sixlowpan_iphc_cbuf_t *sixlowpan_iphc_cbuf_update(uint8_t cid, const ipv6_addr_t *prefix, | ||
uint8_t prefix_len, uint16_t lifetime) | ||
{ | ||
sixlowpan_iphc_cbuf_t *c = NULL; | ||
|
||
mutex_lock(&_cbuf_mutex); | ||
|
||
if (cid < SIXLOWPAN_IPHC_CBUF_SIZE && prefix_len > 0 && lifetime > 0) { | ||
_cbuf[cid].cid = cid; | ||
_cbuf[cid].prefix_len = (prefix_len < IPV6_ADDR_BIT_LEN) ? prefix_len : IPV6_ADDR_BIT_LEN; | ||
_cbuf[cid].lifetime = lifetime; | ||
ipv6_addr_init_prefix(&(_cbuf[cid].prefix), prefix, prefix_len); | ||
_cbuf_invalid_time[cid] = _now_in_minutes() + lifetime; | ||
|
||
c = &(_cbuf[cid]); | ||
} | ||
|
||
mutex_unlock(&_cbuf_mutex); | ||
|
||
return c; | ||
} | ||
|
||
/** | ||
* @} | ||
*/ |
Oops, something went wrong.