From 60f33bbbf52b57ceb84b02087b4247b66261ad6b Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Wed, 25 Sep 2019 16:52:57 +0200 Subject: [PATCH 1/2] sixlowpan_sfr: initial import Selective Fragment Recovery definitions --- sys/include/net/sixlowpan.h | 21 ++ sys/include/net/sixlowpan/sfr.h | 381 ++++++++++++++++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 sys/include/net/sixlowpan/sfr.h diff --git a/sys/include/net/sixlowpan.h b/sys/include/net/sixlowpan.h index 083f4adb5669..97b7a714bd7e 100644 --- a/sys/include/net/sixlowpan.h +++ b/sys/include/net/sixlowpan.h @@ -61,6 +61,27 @@ extern "C" { */ #define SIXLOWPAN_IPHC1_DISP (0x60) +/** + * @brief Dispatch mask for 6LoWPAN selective fragment recovery + * @see [draft-ietf-6lo-fragment-recovery-05, + * section 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5) + */ +#define SIXLOWPAN_SFR_DISP_MASK (0xfe) + +/** + * @brief Dispatch for 6LoWPAN recoverable fragment + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1) + */ +#define SIXLOWPAN_SFR_RFRAG_DISP (0xe8) + +/** + * @brief Dispatch for 6LoWPAN recoverable fragment acknowledgment + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2) + */ +#define SIXLOWPAN_SFR_ACK_DISP (0xea) + /** * @brief Checks if dispatch indicates that frame is not a 6LoWPAN (NALP) frame. * diff --git a/sys/include/net/sixlowpan/sfr.h b/sys/include/net/sixlowpan/sfr.h new file mode 100644 index 000000000000..b2a2fe21b24b --- /dev/null +++ b/sys/include/net/sixlowpan/sfr.h @@ -0,0 +1,381 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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_sfr 6LoWPAN selective fragment recovery + * @ingroup net_sixlowpan + * @brief Provides dispatches for 6LoWPAN selective fragment recovery and + * helper functions + * @{ + * + * @file + * @brief 6LoWPAN selective fragment recovery dispatch type and helper + * function definitions. + * + * @author Martine Lenders + */ +#ifndef NET_SIXLOWPAN_SFR_H +#define NET_SIXLOWPAN_SFR_H + +#include +#include +#include + +#include "bitfield.h" +#include "byteorder.h" +#include "net/sixlowpan.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Mask for generic dispatch of both selective fragment recovery + * headers + * + * @see SIXLOWPAN_SFR_GEN_DISP + * @see SIXLOWPAN_SFR_DISP_MASK + * @see SIXLOWPAN_SFR_RFRAG_DISP + * @see SIXLOWPAN_SFR_ACK_DISP + */ +#define SIXLOWPAN_SFR_GEN_DISP_MASK (0xfc) +#define SIXLOWPAN_SFR_GEN_DISP (0xe8) /**< generic dispatch for both SFR headers */ +#define SIXLOWPAN_SFR_ECN (0x01U) /**< explicit congestion notification flag */ +#define SIXLOWPAN_SFR_ACK_REQ (0x80U) /**< Acknowledgment request flag (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_MASK (0x7cU) /**< Sequence number mask (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_POS (2U) /**< Sequence number position (for 8 MSB) */ +#define SIXLOWPAN_SFR_SEQ_MAX (0x1fU) /**< Maximum value for sequence number */ +#define SIXLOWPAN_SFR_FRAG_SIZE_MASK (0x03ffU) /**< Fragment size mask */ +#define SIXLOWPAN_SFR_FRAG_SIZE_MAX (0x03ffU) /**< Maximum value for fragment size */ +#define SIXLOWPAN_SFR_ACK_BITMAP_SIZE (32U) /**< Acknowledgment bitmap size in bits */ + +/** + * @brief Generic type for selective fragment recovery headers + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5) + */ +typedef struct __attribute__((packed)) { + /** + * @brief Dispatch and explicit congestion notification (ECN) flag + * + * In network byte-order the 7 most significant bits are the dispatch (7 + * bits) and the least significant bit is the ECN flag: + * + * +-+-+-+-+-+-+-+-+ + * | Dispatch |E| + * +-+-+-+-+-+-+-+-+ + * + * For @ref sixlowpan_sfr_ack_t the ECN flag represents the ECN echo flag. + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_is() + * - sixlowpan_sfr_set_ecn() + * - sixlowpan_sfr_clear_ecn() + * - sixlowpan_sfr_ecn() + * - sixlowpan_sfr_rfrag_set_disp() + * - sixlowpan_sfr_rfrag_is() + * - sixlowpan_sfr_ack_set_disp() + * - sixlowpan_sfr_ack_is() + */ + uint8_t disp_ecn; + uint8_t tag; /**< Datagram tag */ +} sixlowpan_sfr_t; + +/** + * @brief Recoverable fragment header + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.1](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.1) + */ +typedef struct __attribute__((packed)) { + sixlowpan_sfr_t base; /**< generic part */ + /** + * @brief Acknowledgment request flag, sequence number, and fragment size + * + * In network byte-order the most significant bit is the acknowledgment + * request flag, the second to sixth most significant bits are the sequence + * number (5 bits), and the 10 least significant bits are the fragment size + * (10 bits): + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |X| sequence| fragment_size | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_rfrag_set_ack_req() + * - sixlowpan_sfr_rfrag_clear_ack_req() + * - sixlowpan_sfr_rfrag_ack_req() + * - sixlowpan_sfr_rfrag_set_seq() + * - sixlowpan_sfr_rfrag_get_seq() + * - sixlowpan_sfr_rfrag_set_frag_size() + * - sixlowpan_sfr_rfrag_get_frag_size() + */ + network_uint16_t ar_seq_fs; + + /** + * @brief Fragment offset + * + * This module provides helper functions to set, get, check these fields + * accordingly: + * + * - sixlowpan_sfr_rfrag_set_offset() + * - sixlowpan_sfr_rfrag_get_offset() + */ + network_uint16_t offset; +} sixlowpan_sfr_rfrag_t; + +/** + * @brief Recoverable fragment (RFRAG) acknowledgment header + * + * @see [draft-ietf-6lo-fragment-recovery-05, section + * 5.2](https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-05#section-5.2) + */ +typedef struct __attribute__((packed)) { + sixlowpan_sfr_t base; /**< generic part */ + /** + * @brief RFRAG acknowledgment bitmap + */ + BITFIELD(bitmap, SIXLOWPAN_SFR_ACK_BITMAP_SIZE); +} sixlowpan_sfr_ack_t; + +/** + * @brief Check if given header is a 6LoWPAN selective fragment recovery + * header (either RFRAG or RFRAG ACK) + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN selective fragment recovery header + * return false, if @p hdr is not a 6LoWPAN selective fragment recovery header + */ +static inline bool sixlowpan_sfr_is(sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_GEN_DISP_MASK) == SIXLOWPAN_SFR_GEN_DISP); +} + +/** + * @brief Set the ECN flag in a 6LoWPAN selective fragment recovery header + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_set_ecn(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn |= SIXLOWPAN_SFR_ECN; +} + +/** + * @brief Clear the ECN flag in a 6LoWPAN recoverable fragment header + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_clear_ecn(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_ECN; +} + +/** + * @brief Check if the ECN flag in a 6LoWPAN recoverable fragment header is + * set + * + * @param[in] hdr A 6LoWPAN selective fragment recovery header + * + * return true, if ECN flag in @p hdr is set + * return false, if ECN flag in @p hdr is cleared + */ +static inline bool sixlowpan_sfr_ecn(const sixlowpan_sfr_t *hdr) +{ + return (hdr->disp_ecn & SIXLOWPAN_SFR_ECN); +} + +/** + * @brief Initialize 6LoWPAN recoverable fragment dispatch + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_rfrag_set_disp(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_DISP_MASK; + hdr->disp_ecn |= SIXLOWPAN_SFR_RFRAG_DISP; +} + +/** + * @brief Check if given header is a 6LoWPAN recoverable fragment header + * + * @see @ref SIXLOWPAN_SFR_RFRAG_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN recoverable fragment header + * return false, if @p hdr is not a 6LoWPAN recoverable fragment header + */ +static inline bool sixlowpan_sfr_rfrag_is(const sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_DISP_MASK) == SIXLOWPAN_SFR_RFRAG_DISP); +} + +/** + * @brief Set the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + */ +static inline void sixlowpan_sfr_rfrag_set_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + hdr->ar_seq_fs.u8[0] |= SIXLOWPAN_SFR_ACK_REQ; +} + +/** + * @brief Clear the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + */ +static inline void sixlowpan_sfr_rfrag_clear_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + hdr->ar_seq_fs.u8[0] &= ~SIXLOWPAN_SFR_ACK_REQ; +} + +/** + * @brief Check if the Acknowledgment request flag in a 6LoWPAN recoverable + * fragment header is set + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * return true, if Acknowledgment request flag in @p hdr is set + * return false, if Acknowledgment request flag in @p hdr is cleared + */ +static inline bool sixlowpan_sfr_rfrag_ack_req(sixlowpan_sfr_rfrag_t *hdr) +{ + return (hdr->ar_seq_fs.u8[0] & SIXLOWPAN_SFR_ACK_REQ); +} + +/** + * @brief Set sequence number in a 6LoWPAN recoverable fragment header + * + * @pre `seq <= SIXLOWPAN_SFR_SEQ_MAX` + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] seq The sequence number to set. Must be lesser or equal + * to @ref SIXLOWPAN_SFR_SEQ_MAX. + */ +static inline void sixlowpan_sfr_rfrag_set_seq(sixlowpan_sfr_rfrag_t *hdr, + uint8_t seq) +{ + assert(seq <= SIXLOWPAN_SFR_SEQ_MAX); + hdr->ar_seq_fs.u8[0] &= ~SIXLOWPAN_SFR_SEQ_MASK; + hdr->ar_seq_fs.u8[0] |= (seq << SIXLOWPAN_SFR_SEQ_POS); +} + +/** + * @brief Get sequence number from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The sequence number of the 6LoWPAN recoverable fragment + */ +static inline uint8_t sixlowpan_sfr_rfrag_get_seq(const sixlowpan_sfr_rfrag_t *hdr) +{ + return ((hdr->ar_seq_fs.u8[0] & SIXLOWPAN_SFR_SEQ_MASK) >> + SIXLOWPAN_SFR_SEQ_POS); +} + +/** + * @brief Set fragment size in a 6LoWPAN recoverable fragment header + * + * @pre `frag_size <= SIXLOWPAN_SFR_FRAG_SIZE_MAX` + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] frag_size The fragment size to set. Must be lesser or equal to + * @ref SIXLOWPAN_SFR_FRAG_SIZE_MAX. + */ +static inline void sixlowpan_sfr_rfrag_set_frag_size(sixlowpan_sfr_rfrag_t *hdr, + uint16_t frag_size) +{ + assert(frag_size <= SIXLOWPAN_SFR_FRAG_SIZE_MAX); + hdr->ar_seq_fs.u16 &= ~htons(SIXLOWPAN_SFR_FRAG_SIZE_MASK); + hdr->ar_seq_fs.u16 |= htons(frag_size); +} + +/** + * @brief Get fragment size from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The fragment size of the 6LoWPAN recoverable fragment + */ +static inline uint16_t sixlowpan_sfr_rfrag_get_frag_size(const sixlowpan_sfr_rfrag_t *hdr) +{ + return (byteorder_ntohs(hdr->ar_seq_fs) & SIXLOWPAN_SFR_FRAG_SIZE_MASK); +} + +/** + * @brief Set fragment offset in a 6LoWPAN recoverable fragment header + * + * @param[in,out] hdr A 6LoWPAN recoverable fragment header + * @param[in] offset The fragment offset to set. + */ +static inline void sixlowpan_sfr_rfrag_set_offset(sixlowpan_sfr_rfrag_t *hdr, + uint16_t offset) +{ + hdr->offset = byteorder_htons(offset); +} + +/** + * @brief Get fragment offset from a 6LoWPAN recoverable fragment header + * + * @param[in] hdr A 6LoWPAN recoverable fragment header + * + * @return The fragment offset of the 6LoWPAN recoverable fragment + */ +static inline uint16_t sixlowpan_sfr_rfrag_get_offset(const sixlowpan_sfr_rfrag_t *hdr) +{ + return byteorder_ntohs(hdr->offset); +} + +/** + * @brief Initialize 6LoWPAN RFRAG acknowledgment dispatch + * + * @see @ref SIXLOWPAN_SFR_ACK_DISP + * + * @param[in,out] hdr A 6LoWPAN selective fragment recovery header + */ +static inline void sixlowpan_sfr_ack_set_disp(sixlowpan_sfr_t *hdr) +{ + hdr->disp_ecn &= ~SIXLOWPAN_SFR_DISP_MASK; + hdr->disp_ecn |= SIXLOWPAN_SFR_ACK_DISP; +} + +/** + * @brief Check if given header is a 6LoWPAN RFRAG acknowledgment header + * + * @see @ref SIXLOWPAN_SFR_ACK_DISP + * + * @param[in] hdr The 6LoWPAN selective fragment recovery header to check + * + * return true, if @p hdr is a 6LoWPAN RFRAG acknowledgment header + * return false, if @p hdr is not a 6LoWPAN RFRAG acknowledgment header + */ +static inline bool sixlowpan_sfr_ack_is(const sixlowpan_sfr_t *hdr) +{ + return ((hdr->disp_ecn & SIXLOWPAN_SFR_DISP_MASK) == SIXLOWPAN_SFR_ACK_DISP); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NET_SIXLOWPAN_SFR_H */ +/** @} */ From 38571c66fe077a5b3259b6fedd30cdadc5561bb0 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Wed, 25 Sep 2019 18:01:37 +0200 Subject: [PATCH 2/2] tests: add unittests for net/sixlowpan/sfr.h helpers --- tests/unittests/tests-sixlowpan_sfr/Makefile | 1 + .../tests-sixlowpan_sfr/tests-sixlowpan_sfr.c | 223 ++++++++++++++++++ .../tests-sixlowpan_sfr/tests-sixlowpan_sfr.h | 37 +++ 3 files changed, 261 insertions(+) create mode 100644 tests/unittests/tests-sixlowpan_sfr/Makefile create mode 100644 tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.c create mode 100644 tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.h diff --git a/tests/unittests/tests-sixlowpan_sfr/Makefile b/tests/unittests/tests-sixlowpan_sfr/Makefile new file mode 100644 index 000000000000..48422e909a47 --- /dev/null +++ b/tests/unittests/tests-sixlowpan_sfr/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.c b/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.c new file mode 100644 index 000000000000..faa830ac1803 --- /dev/null +++ b/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.c @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + +#include + +#include "net/sixlowpan/sfr.h" + +#include "tests-sixlowpan_sfr.h" + +static void test_sixlowpan_sfr_disp(void) +{ + sixlowpan_sfr_t hdr = { .disp_ecn = 0U }; + + TEST_ASSERT(!sixlowpan_sfr_is(&hdr)); + sixlowpan_sfr_rfrag_set_disp(&hdr); + TEST_ASSERT(sixlowpan_sfr_is(&hdr)); + hdr.disp_ecn = 0U; + sixlowpan_sfr_ack_set_disp(&hdr); + TEST_ASSERT(sixlowpan_sfr_is(&hdr)); +} + +static void test_sixlowpan_sfr_ecn(void) +{ + /* initialize with canary (but ECN unset) */ + sixlowpan_sfr_t hdr = { .disp_ecn = 218U }; + + /* ECN should not be set */ + TEST_ASSERT(!sixlowpan_sfr_ecn(&hdr)); + + sixlowpan_sfr_set_ecn(&hdr); + TEST_ASSERT(sixlowpan_sfr_ecn(&hdr)); + /* check if non-ECN field stays unset */ + TEST_ASSERT_EQUAL_INT(218U, + hdr.disp_ecn & ~SIXLOWPAN_SFR_ECN); + + sixlowpan_sfr_clear_ecn(&hdr); + TEST_ASSERT(!sixlowpan_sfr_ecn(&hdr)); + /* check if non-ECN field stays unset */ + TEST_ASSERT_EQUAL_INT(218U, + hdr.disp_ecn & ~SIXLOWPAN_SFR_ECN); +} + +static void test_sixlowpan_sfr_rfrag_disp(void) +{ + /* initialize with canary bit (but dispatch unset) */ + sixlowpan_sfr_t hdr = { .disp_ecn = 1U }; + + TEST_ASSERT(!sixlowpan_sfr_rfrag_is(&hdr)); + sixlowpan_sfr_rfrag_set_disp(&hdr); + TEST_ASSERT(sixlowpan_sfr_rfrag_is(&hdr)); + /* check if preset value stays the same */ + TEST_ASSERT_EQUAL_INT(1U, hdr.disp_ecn & ~SIXLOWPAN_SFR_DISP_MASK); + /* check if it stays the same when ECN is cleared */ + sixlowpan_sfr_clear_ecn(&hdr); + TEST_ASSERT(sixlowpan_sfr_rfrag_is(&hdr)); + /* check if it stays the same when ECN is set */ + sixlowpan_sfr_set_ecn(&hdr); + TEST_ASSERT(sixlowpan_sfr_rfrag_is(&hdr)); +} + +static void test_sixlowpan_sfr_rfrag_ack_req(void) +{ + /* initialize with canary bit (but ack_req unset) */ + sixlowpan_sfr_rfrag_t hdr = { .ar_seq_fs = { .u8 = { 0x74, 0x32 } } }; + + TEST_ASSERT(!sixlowpan_sfr_rfrag_ack_req(&hdr)); + sixlowpan_sfr_rfrag_set_ack_req(&hdr); + TEST_ASSERT(sixlowpan_sfr_rfrag_ack_req(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x74, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_ACK_REQ); + TEST_ASSERT_EQUAL_INT(0x32, hdr.ar_seq_fs.u8[1]); + + sixlowpan_sfr_rfrag_clear_ack_req(&hdr); + TEST_ASSERT(!sixlowpan_sfr_rfrag_ack_req(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x74, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_ACK_REQ); + TEST_ASSERT_EQUAL_INT(0x32, hdr.ar_seq_fs.u8[1]); +} + +static void test_sixlowpan_sfr_rfrag_seq(void) +{ + /* initialize with canary bit (but seq unset) */ + sixlowpan_sfr_rfrag_t hdr = { .ar_seq_fs = { .u8 = { 0x83, 0xaa } } }; + + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_seq(&hdr)); + + sixlowpan_sfr_rfrag_set_seq(&hdr, SIXLOWPAN_SFR_SEQ_MAX); + TEST_ASSERT_EQUAL_INT(SIXLOWPAN_SFR_SEQ_MAX, + sixlowpan_sfr_rfrag_get_seq(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x83, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_SEQ_MASK); + TEST_ASSERT_EQUAL_INT(0xaa, hdr.ar_seq_fs.u8[1]); + + sixlowpan_sfr_rfrag_set_seq(&hdr, 19U); + TEST_ASSERT_EQUAL_INT(19U, sixlowpan_sfr_rfrag_get_seq(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x83, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_SEQ_MASK); + TEST_ASSERT_EQUAL_INT(0xaa, hdr.ar_seq_fs.u8[1]); + + sixlowpan_sfr_rfrag_set_seq(&hdr, 7U); + TEST_ASSERT_EQUAL_INT(7U, sixlowpan_sfr_rfrag_get_seq(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x83, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_SEQ_MASK); + TEST_ASSERT_EQUAL_INT(0xaa, hdr.ar_seq_fs.u8[1]); + + sixlowpan_sfr_rfrag_set_seq(&hdr, 0U); + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_seq(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x83, hdr.ar_seq_fs.u8[0] & ~SIXLOWPAN_SFR_SEQ_MASK); + TEST_ASSERT_EQUAL_INT(0xaa, hdr.ar_seq_fs.u8[1]); +} + +static void test_sixlowpan_sfr_rfrag_frag_size(void) +{ + /* initialize with canary bit (but seq unset) */ + sixlowpan_sfr_rfrag_t hdr = { .ar_seq_fs = { .u8 = { 0x6c, 0x00 } } }; + + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_frag_size(&hdr)); + + sixlowpan_sfr_rfrag_set_frag_size(&hdr, SIXLOWPAN_SFR_FRAG_SIZE_MAX); + TEST_ASSERT_EQUAL_INT(SIXLOWPAN_SFR_FRAG_SIZE_MAX, + sixlowpan_sfr_rfrag_get_frag_size(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x6c, + hdr.ar_seq_fs.u8[0] & + (SIXLOWPAN_SFR_ACK_REQ | SIXLOWPAN_SFR_SEQ_MASK)); + + sixlowpan_sfr_rfrag_set_frag_size(&hdr, 113); + TEST_ASSERT_EQUAL_INT(113U, sixlowpan_sfr_rfrag_get_frag_size(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x6c, + hdr.ar_seq_fs.u8[0] & + (SIXLOWPAN_SFR_ACK_REQ | SIXLOWPAN_SFR_SEQ_MASK)); + + sixlowpan_sfr_rfrag_set_frag_size(&hdr, 964); + TEST_ASSERT_EQUAL_INT(964, sixlowpan_sfr_rfrag_get_frag_size(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x6c, + hdr.ar_seq_fs.u8[0] & + (SIXLOWPAN_SFR_ACK_REQ | SIXLOWPAN_SFR_SEQ_MASK)); + + sixlowpan_sfr_rfrag_set_frag_size(&hdr, 0U); + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_frag_size(&hdr)); + /* check if preset values stay the same */ + TEST_ASSERT_EQUAL_INT(0x6c, + hdr.ar_seq_fs.u8[0] & + (SIXLOWPAN_SFR_ACK_REQ | SIXLOWPAN_SFR_SEQ_MASK)); +} + +static void test_sixlowpan_sfr_rfrag_offset(void) +{ + /* initialize with canary bit (but seq unset) */ + sixlowpan_sfr_rfrag_t hdr = { .offset = { .u16 = 0 } }; + + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_offset(&hdr)); + + sixlowpan_sfr_rfrag_set_offset(&hdr, UINT16_MAX); + TEST_ASSERT_EQUAL_INT(UINT16_MAX, sixlowpan_sfr_rfrag_get_offset(&hdr)); + + sixlowpan_sfr_rfrag_set_offset(&hdr, 58937U); + TEST_ASSERT_EQUAL_INT(58937U, sixlowpan_sfr_rfrag_get_offset(&hdr)); + + sixlowpan_sfr_rfrag_set_offset(&hdr, 173U); + TEST_ASSERT_EQUAL_INT(173U, sixlowpan_sfr_rfrag_get_offset(&hdr)); + + sixlowpan_sfr_rfrag_set_offset(&hdr, 0U); + TEST_ASSERT_EQUAL_INT(0U, sixlowpan_sfr_rfrag_get_offset(&hdr)); +} + +static void test_sixlowpan_sfr_ack_disp(void) +{ + /* initialize with canary bit (but dispatch unset) */ + sixlowpan_sfr_t hdr = { .disp_ecn = 1U }; + + TEST_ASSERT(!sixlowpan_sfr_ack_is(&hdr)); + sixlowpan_sfr_ack_set_disp(&hdr); + TEST_ASSERT(sixlowpan_sfr_ack_is(&hdr)); + /* check if preset value stays the same */ + TEST_ASSERT_EQUAL_INT(1U, hdr.disp_ecn & ~SIXLOWPAN_SFR_DISP_MASK); + /* check if it stays the same when ECN is cleared */ + sixlowpan_sfr_clear_ecn(&hdr); + TEST_ASSERT(sixlowpan_sfr_ack_is(&hdr)); + /* check if it stays the same when ECN is set */ + sixlowpan_sfr_set_ecn(&hdr); + TEST_ASSERT(sixlowpan_sfr_ack_is(&hdr)); +} + +static Test *tests_sixlowpan_sfr_tests(void) +{ + EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_sixlowpan_sfr_disp), + new_TestFixture(test_sixlowpan_sfr_ecn), + new_TestFixture(test_sixlowpan_sfr_rfrag_disp), + new_TestFixture(test_sixlowpan_sfr_rfrag_ack_req), + new_TestFixture(test_sixlowpan_sfr_rfrag_seq), + new_TestFixture(test_sixlowpan_sfr_rfrag_frag_size), + new_TestFixture(test_sixlowpan_sfr_rfrag_offset), + new_TestFixture(test_sixlowpan_sfr_ack_disp), + }; + + EMB_UNIT_TESTCALLER(sixlowpan_sfr_tests, NULL, NULL, fixtures); + + return (Test *)&sixlowpan_sfr_tests; +} + +void tests_sixlowpan_sfr(void) +{ + TESTS_RUN(tests_sixlowpan_sfr_tests()); +} + +/** @} */ diff --git a/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.h b/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.h new file mode 100644 index 000000000000..5edb4e28169b --- /dev/null +++ b/tests/unittests/tests-sixlowpan_sfr/tests-sixlowpan_sfr.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2019 Freie Universität Berlin + * + * 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 unittests + * @{ + * + * @file + * @brief Unittests for the `sixlowpan_sfr` header + * + * @author Martine Lenders + */ +#ifndef TESTS_SIXLOWPAN_SFR_H +#define TESTS_SIXLOWPAN_SFR_H + +#include "embUnit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The entry point of this test suite. + */ +void tests_sixlowpan_sfr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TESTS_SIXLOWPAN_SFR_H */ +/** @} */