diff --git a/sys/include/net/ng_fib.h b/sys/include/net/ng_fib.h index db7796e82fcf..f5b4715c882c 100644 --- a/sys/include/net/ng_fib.h +++ b/sys/include/net/ng_fib.h @@ -34,6 +34,14 @@ typedef struct rrp_address_msg_t { uint32_t address_flags; /**< The flags for the given address */ } rrp_address_msg_t; +/** + * @brief entry used to collect available destinations + */ +typedef struct fib_destination_set_entry_t { + uint8_t dest[16]; /**< The destination address */ + size_t dest_size; /**< The destination address size */ +} fib_destination_set_entry_t; + #define FIB_MSG_RRP_SIGNAL (0x99) /**< message type for RRP notifications */ /** @@ -121,6 +129,28 @@ int fib_get_next_hop(kernel_pid_t *iface_id, uint8_t *next_hop, size_t *next_hop_size, uint32_t* next_hop_flags, uint8_t *dst, size_t dst_size, uint32_t dst_flags); +/** +* @brief provides a set of destination addresses matching the bits specified with +* the provided bitmap and type. +* If the out buffer is insufficient low or passed as NULL, +* the function will continue to count the number of matching entries +* and provide the number to the caller. +* +* @param[in] bitmap the bitmap to mask the relevant bits +* @param[in] type the type holding the significant bits +* @param[out] dst_set the destination addresses matching the type +* @param[in, out] dst_size the number of entries available on in and used on out +* +* @return 0 on success +* -EHOSTUNREACH if no entry matches the type in the FIB +* -ENOBUFS if the size for the found entries is insufficient low +* The actual needed size is stored then in dst_set_size, +* however the required size may change in between calls. +*/ +int fib_get_destination_set(uint32_t bitmap, uint32_t type, + fib_destination_set_entry_t *dst_set, size_t* dst_set_size); + + /** * @brief returns the actual number of used FIB entries */ diff --git a/sys/net/network_layer/fib/fib.c b/sys/net/network_layer/fib/fib.c index 8c38cc0a8a3a..c55f1ab04ee4 100644 --- a/sys/net/network_layer/fib/fib.c +++ b/sys/net/network_layer/fib/fib.c @@ -424,6 +424,41 @@ int fib_get_next_hop(kernel_pid_t *iface_id, return 0; } +int fib_get_destination_set(uint32_t bitmap, uint32_t type, + fib_destination_set_entry_t *dst_set, size_t* dst_set_size) +{ + mutex_lock(&mtx_access); + int ret = -EHOSTUNREACH; + size_t found_entries = 0; + + for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { + if( (fib_table[i].global_flags & bitmap) == (type & bitmap) ) { + + if( (dst_set != NULL) && (found_entries < (*dst_set_size)-1) ) { + /* set the size to full byte usage */ + dst_set[found_entries].dest_size = sizeof(dst_set[found_entries].dest); + universal_address_get_address(fib_table[i].global, + dst_set[found_entries].dest, + &dst_set[found_entries].dest_size); + } + found_entries++; + } + } + + if( found_entries > *dst_set_size ) { + ret = -ENOBUFS; + } else if( found_entries > 0 ) { + ret = 0; + } + + *dst_set_size = found_entries; + + mutex_unlock(&mtx_access); + + return ret; + +} + void fib_init(void) { DEBUG("[fib_init] hello. Initializing some stuff."); diff --git a/tests/unittests/tests-fib/tests-fib.c b/tests/unittests/tests-fib/tests-fib.c index 407adaa0d062..9fd4a95640d5 100644 --- a/tests/unittests/tests-fib/tests-fib.c +++ b/tests/unittests/tests-fib/tests-fib.c @@ -529,6 +529,49 @@ static void test_fib_14_exact_and_prefix_match(void) fib_deinit(); } +/* +* @brief testing receiving an entry set matching specific type bits +*/ +static void test_fib_15_get_entry_set(void) +{ + size_t add_buf_size = 16; + char addr_dst[add_buf_size]; + char addr_nxt[add_buf_size]; + uint32_t addr_dst_flags = 0; + uint32_t addr_nxt_flags = 0x33333333; + + /* fill 20 addresses with distinct flags (0-19) for the destination address */ + for (size_t i = 0; i < 20; ++i) { + /* construct "addresses" for the FIB */ + snprintf(addr_dst, add_buf_size, "Test address %02d", (int)i); + snprintf(addr_nxt, add_buf_size, "Test address %02d", i % 11); + fib_add_entry(42, (uint8_t *)addr_dst, add_buf_size - 1, addr_dst_flags++, + (uint8_t *)addr_nxt, add_buf_size - 1, addr_nxt_flags, 10000); + } + + size_t arr_size = 10; + fib_destination_set_entry_t arr_dst[arr_size]; + /* we search entries iwits the lower 3 significant bits */ + uint32_t bitmap = 0x3; + /* an arbitrary type */ + uint32_t type = 0x22; + + int ret = fib_get_destination_set(bitmap, type, &arr_dst[0], &arr_size); + TEST_ASSERT_EQUAL_INT(0, ret); + + /* we should receive 5 entries 02, 06, 10, 14 and 18 */ + TEST_ASSERT_EQUAL_INT(5, arr_size); + +#if (TEST_FIB_SHOW_OUTPUT == 1) + puts(""); + for(size_t i = 0; i < arr_size; ++i) { + printf("%s\n", (char*)arr_dst[i].dest); + } + puts(""); +#endif + fib_deinit(); +} + Test *tests_fib_tests(void) { fib_init(); @@ -547,6 +590,7 @@ Test *tests_fib_tests(void) new_TestFixture(test_fib_12_get_next_hop_fail), new_TestFixture(test_fib_13_get_next_hop_fail_on_buffer_size), new_TestFixture(test_fib_14_exact_and_prefix_match), + new_TestFixture(test_fib_15_get_entry_set), }; EMB_UNIT_TESTCALLER(fib_tests, NULL, NULL, fixtures);