From a6623f834f3d7af12f1557aba0745a40597f29df Mon Sep 17 00:00:00 2001 From: Martine Lenders Date: Wed, 20 Nov 2019 18:45:58 +0100 Subject: [PATCH 1/3] bitfield: unify order Currently the bitfield type mixes up the order of bits: While the byte order is big-endian (most significant byte first), the bit order of each single byte within the bitfield is little-endian (most significant bit last). While this isn't a problem for most applications of the bitfield type it becomes one when sending the bitfield over the network (as done e.g. in the [ACKs of Selective Fragment Recovery][SFR-ACKs]). This change unifies byte order and bit order to both be most significant bX first. [SFR-ACKs]: https://tools.ietf.org/html/draft-ietf-6lo-fragment-recovery-07 --- sys/include/bitfield.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sys/include/bitfield.h b/sys/include/bitfield.h index a0e89acd62..73225ef14f 100644 --- a/sys/include/bitfield.h +++ b/sys/include/bitfield.h @@ -10,6 +10,10 @@ * @defgroup sys_bitfield Bitfields * @ingroup sys * @brief Bitfields of arbitrary length + * + * The bitfields in this module have their most significant bytes first and + * their most significant bits within each byte of the bitfield also first. + * * @file * @{ * @@ -49,7 +53,7 @@ extern "C" { */ static inline void bf_set(uint8_t field[], size_t idx) { - field[idx / 8] |= (1u << (idx % 8)); + field[idx / 8] |= (1u << (7 - (idx % 8))); } /** @@ -60,7 +64,7 @@ static inline void bf_set(uint8_t field[], size_t idx) */ static inline void bf_unset(uint8_t field[], size_t idx) { - field[idx / 8] &= ~(1u << (idx % 8)); + field[idx / 8] &= ~(1u << (7 - (idx % 8))); } /** @@ -71,7 +75,7 @@ static inline void bf_unset(uint8_t field[], size_t idx) */ static inline void bf_toggle(uint8_t field[], size_t idx) { - field[idx / 8] ^= (1u << (idx % 8)); + field[idx / 8] ^= (1u << (7 - (idx % 8))); } /** @@ -82,7 +86,7 @@ static inline void bf_toggle(uint8_t field[], size_t idx) */ static inline bool bf_isset(uint8_t field[], size_t idx) { - return (field[idx / 8] & (1u << (idx % 8))); + return (field[idx / 8] & (1u << (7 - (idx % 8)))); } /** From 880a68c11f331ce0ddcbafbbd4c6cec24e38c9dd Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 21 Nov 2019 11:43:31 +0100 Subject: [PATCH 2/3] tests/unittests: fix existing bitfield tests for new bit-order --- .../unittests/tests-bitfield/tests-bitfield.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unittests/tests-bitfield/tests-bitfield.c b/tests/unittests/tests-bitfield/tests-bitfield.c index 8df527cc52..5877bc9818 100644 --- a/tests/unittests/tests-bitfield/tests-bitfield.c +++ b/tests/unittests/tests-bitfield/tests-bitfield.c @@ -53,15 +53,15 @@ static void test_bf_get_unset_firstbyte(void) res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(0, res); - field[0] = 0x01; + field[0] = 0x80; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(1, res); - field[0] = 0x0f; + field[0] = 0xf0; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(4, res); - field[0] = 0x7f; + field[0] = 0xfe; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(7, res); @@ -80,15 +80,15 @@ static void test_bf_get_unset_middle(void) res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(16, res); - field[2] = 0x01; + field[2] = 0x80; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(17, res); - field[2] = 0x0f; + field[2] = 0xf0; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(20, res); - field[2] = 0x7f; + field[2] = 0xfe; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(23, res); } @@ -103,15 +103,15 @@ static void test_bf_get_unset_lastbyte(void) res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(32, res); - field[4] = 0x01; + field[4] = 0x80; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(33, res); - field[4] = 0x0f; + field[4] = 0xf0; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(36, res); - field[4] = 0x7f; + field[4] = 0xfe; res = bf_get_unset(field, 40); TEST_ASSERT_EQUAL_INT(39, res); } From 27510b72f8746dd8c89b63a1f8d9b8b5d33df769 Mon Sep 17 00:00:00 2001 From: "Martine S. Lenders" Date: Thu, 21 Nov 2019 12:05:07 +0100 Subject: [PATCH 3/3] tests/unittests: add tests for missing bitfield functions --- .../unittests/tests-bitfield/tests-bitfield.c | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/tests/unittests/tests-bitfield/tests-bitfield.c b/tests/unittests/tests-bitfield/tests-bitfield.c index 5877bc9818..1e61dd471b 100644 --- a/tests/unittests/tests-bitfield/tests-bitfield.c +++ b/tests/unittests/tests-bitfield/tests-bitfield.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2015 Kaspar Schleiser + * 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 @@ -13,6 +14,86 @@ #include "bitfield.h" +static void test_bf_set(void) +{ + BITFIELD(field, 32U); + + memset(field, 0x00, sizeof(field)); + bf_set(field, 3); + /* bit idx: 3/8 + 01234567 + * 0x10 == 0b00010000 */ + TEST_ASSERT_EQUAL_INT(0x10, field[3 / 8]); + bf_set(field, 1); + /* bit idx: 1/8 + 01234567 + * 0x50 == 0b01010000 */ + TEST_ASSERT_EQUAL_INT(0x50, field[1 / 8]); + bf_set(field, 25); + /* bit idx: 25/8 + 01234567 + * 0x40 == 0b01000000 */ + TEST_ASSERT_EQUAL_INT(0x40, field[25 / 8]); +} + +static void test_bf_unset(void) +{ + BITFIELD(field, 32U); + + memset(field, 0xff, sizeof(field)); + bf_unset(field, 5); + /* bit idx: 5/8 + 01234567 + * 0xfb == 0b11111011 */ + TEST_ASSERT_EQUAL_INT(0xfb, field[5 / 8]); + bf_unset(field, 8); + /* cppcheck-suppress duplicateExpression + * reason: intentionally dividing 8 by itself to make test more readable + * bit idx: 8/8 + 01234567 + * 0x7f == 0b01111111 */ + TEST_ASSERT_EQUAL_INT(0x7f, field[8 / 8]); + bf_unset(field, 10); + /* bit idx: 10/8 + 01234567 + * 0x5f == 0b01011111 */ + TEST_ASSERT_EQUAL_INT(0x5f, field[10 / 8]); +} + +static void test_bf_toggle(void) +{ + BITFIELD(field, 32U); + + memset(field, 0xff, sizeof(field)); + bf_toggle(field, 7); + /* bit idx: 7/8 + 01234567 + * 0xfe == 0b11111110 */ + TEST_ASSERT_EQUAL_INT(0xfe, field[7 / 8]); + bf_toggle(field, 0); + /* bit idx: 0/8 + 01234567 + * 0x7e == 0b01111110 */ + TEST_ASSERT_EQUAL_INT(0x7e, field[0 / 8]); + bf_toggle(field, 7); + /* bit idx: 7/8 + 01234567 + * 0x7f == 0b01111111 */ + TEST_ASSERT_EQUAL_INT(0x7f, field[7 / 8]); + bf_toggle(field, 0); + /* bit idx: 0/8 + 01234567 + * 0xff == 0b11111111 */ + TEST_ASSERT_EQUAL_INT(0xff, field[0 / 8]); + bf_toggle(field, 28); + /* bit idx: 28/8 + 01234567 + * 0xf7 == 0b11110111 */ + TEST_ASSERT_EQUAL_INT(0xf7, field[28 / 8]); +} + +static void test_bf_isset(void) +{ + BITFIELD(field, 32U); + + /* bf_set / bf_unset tested above */ + memset(field, 0x00, sizeof(field)); + TEST_ASSERT(!bf_isset(field, 25)); + bf_set(field, 25); + TEST_ASSERT(bf_isset(field, 25)); + bf_unset(field, 25); + TEST_ASSERT(!bf_isset(field, 25)); +} + static void test_bf_get_unset_empty(void) { int res = 0; @@ -119,6 +200,10 @@ static void test_bf_get_unset_lastbyte(void) Test *tests_bitfield_tests(void) { EMB_UNIT_TESTFIXTURES(fixtures) { + new_TestFixture(test_bf_set), + new_TestFixture(test_bf_unset), + new_TestFixture(test_bf_toggle), + new_TestFixture(test_bf_isset), new_TestFixture(test_bf_get_unset_empty), new_TestFixture(test_bf_get_unset_firstbyte), new_TestFixture(test_bf_get_unset_middle),