Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sys/net/fib: added function to request a set of destination addresses #2818

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions sys/include/net/ng_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ typedef struct rp_address_msg_t {

#define FIB_MSG_RP_SIGNAL (0x99) /**< message type for RP notifications */

/**
* @brief the size in bytes of a full address
* TODO: replace with UNIVERSAL_ADDRESS_SIZE (#3022)
*/
#define FIB_DESTINATION_SIZE_SUBSTITUTE (16)

/**
* @brief entry used to collect available destinations
*/
typedef struct fib_destination_set_entry_t {
uint8_t dest[FIB_DESTINATION_SIZE_SUBSTITUTE]; /**< The destination address */
size_t dest_size; /**< The destination address size */
} fib_destination_set_entry_t;

/**
* @brief indicator of a lifetime that does not expire (2^32 - 1)
*/
Expand Down Expand Up @@ -130,6 +144,27 @@ 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 given prefix
* 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] prefix the destination address
* @param[in] prefix_size the destination address size
* @param[out] dst_set the destination addresses matching the prefix
* @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(uint8_t *prefix, size_t prefix_size,
fib_destination_set_entry_t *dst_set, size_t* dst_set_size);


/**
* @brief returns the actual number of used FIB entries
*/
Expand Down
36 changes: 30 additions & 6 deletions sys/include/net/ng_fib/ng_universal_address.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,43 @@ uint8_t* universal_address_get_address(universal_address_container_t *entry,

/**
* @brief determines if the entry equals the provided address
* This function requires to be provided with the full size of the used
* address type behind *addr to be compareable with the address stored in *entry.
*
* @param[in] entry pointer to the universal_address_container_t for compare
* @param[in] addr pointer to the address for compare
* @param[in, out] addr_size the number of bytes used for the address entry
* on sucessfull return this value is overwritten
* with the number of matching bytes till the
* first of trailing `0`s indicating a prefix
* @param[in, out] addr_size_in_bits the number of bits used for the address entry
* on sucessfull return this value is overwritten
* with the number of matching bits till the
* first of trailing `0`s
*
* @return 0 if the entries are equal or comperable
* @return 0 if the entries are equal
* 1 if the entry match to a certain prefix (trailing '0's in *entry)
* -ENOENT if the given adresses do not match
*/
int universal_address_compare(universal_address_container_t *entry,
uint8_t *addr, size_t *addr_size);
uint8_t *addr, size_t *addr_size_in_bits);


/**
* @brief determines if the entry equals the provided prefix
* This function requires to be provided with the full size of the used
* address type behind *prefix to be compareable with the address stored in *entry.
*
*
* @param[in] entry pointer to the universal_address_container_t for compare
* @param[in] prefix pointer to the address for compare
* @param[in] prefix_size_in_bits the number of bits used for the prefix entry.
* This size MUST be the full address size including trailing '0's,
* e.g. for an ng_ipv6_addr_t it would be sizeof(ng_ipv6_addr_t)
* regardless if the stored prefix is < ::/128
*
* @return 0 if the entries are equal
* 1 if the entry match to a certain prefix (trailing '0's in *prefix)
* -ENOENT if the given adresses do not match
*/
int universal_address_compare_prefix(universal_address_container_t *entry,
uint8_t *prefix, size_t prefix_size_in_bits);

/**
* @brief Prints the content of the given entry
Expand Down
55 changes: 43 additions & 12 deletions sys/net/network_layer/fib/fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ static int fib_find_entry(uint8_t *dst, size_t dst_size,

size_t count = 0;
size_t prefix_size = 0;
size_t match_size = dst_size;
size_t match_size = dst_size<<3;
int ret = -EHOSTUNREACH;
bool is_all_zeros_addr = true;

Expand Down Expand Up @@ -136,30 +136,28 @@ static int fib_find_entry(uint8_t *dst, size_t dst_size,
}
}

if ((prefix_size < dst_size) &&
(fib_table[i].global != NULL) &&
(universal_address_compare(fib_table[i].global, dst, &match_size) == 0)) {
if ((prefix_size < (dst_size<<3)) && (fib_table[i].global != NULL)) {

int ret_comp = universal_address_compare(fib_table[i].global, dst, &match_size);
/* If we found an exact match */
if (match_size == dst_size
|| (is_all_zeros_addr && match_size == 0)) {
if (ret_comp == 0 || (is_all_zeros_addr && match_size == 0)) {
entry_arr[0] = &(fib_table[i]);
*entry_arr_size = 1;
/* we will not find a better one so we return */
return 1;
}
else {
/* we try to find the most fitting prefix */
if (match_size > prefix_size) {
if (ret_comp == 1) {
entry_arr[0] = &(fib_table[i]);
/* we could find a better one so we move on */
ret = 0;

prefix_size = match_size;
match_size = dst_size<<3;
count = 1;
}
}

prefix_size = match_size;
match_size = dst_size;
count = 1;
}
}

Expand Down Expand Up @@ -412,7 +410,6 @@ int fib_get_next_hop(kernel_pid_t *iface_id,
fib_entry_t *entry[count];

int ret = fib_find_entry(dst, dst_size, &(entry[0]), &count);

if (!(ret == 0 || ret == 1)) {
/* notify all responsible RPs for unknown next-hop for the destination address */
if (fib_signal_rp(dst, dst_size, dst_flags) == 0) {
Expand Down Expand Up @@ -443,6 +440,40 @@ int fib_get_next_hop(kernel_pid_t *iface_id,
return 0;
}

int fib_get_destination_set(uint8_t *prefix, size_t prefix_size,
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 != NULL) &&
(universal_address_compare_prefix(fib_table[i].global, prefix, prefix_size<<3) >= 0)) {
if( (dst_set != NULL) && (found_entries < *dst_set_size) ) {
/* 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.");
Expand Down
83 changes: 77 additions & 6 deletions sys/net/network_layer/fib/universal_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,29 +168,100 @@ uint8_t* universal_address_get_address(universal_address_container_t *entry,
}

int universal_address_compare(universal_address_container_t *entry,
uint8_t *addr, size_t *addr_size)
uint8_t *addr, size_t *addr_size_in_bits)
{
mutex_lock(&mtx_access);

int ret = -ENOENT;

/* If we have distinct sizes, the addresses are probably not comperable */
if (entry->address_size != *addr_size) {
if ((size_t)(entry->address_size<<3) != *addr_size_in_bits) {
mutex_unlock(&mtx_access);
return ret;
}

/* Get the index of the first trailing `0` (indicates a network prefix) */
/* Get the index of the first trailing `0` (indicates a prefix) */
int i = 0;
for( i = entry->address_size-1; i >= 0; --i) {
if( entry->address[i] != 0 ) {
break;
}
}

if( memcmp(entry->address, addr, i+1) == 0 ) {
ret = 0;
*addr_size = i+1;
if( memcmp(entry->address, addr, i) == 0 ) {
/* if the bytes-1 equals we check the bits of the lowest byte */
uint8_t bitmask = 0x00;
uint8_t j = 0;
/* get a bitmask for the trailing 0b */
for( ; j < 8; ++j ) {
if ( (entry->address[i] >> j) & 0x01 ) {
bitmask = 0xff << j;
break;
}
}
if( (entry->address[i] & bitmask) == (addr[i] & bitmask) ) {
ret = entry->address[i] != addr[i];
*addr_size_in_bits = (i<<3) + j;
if( ret == 0 ) {
/* check if the remaining bits from addr are significant */
i++;
for(; i < entry->address_size; ++i) {
if( addr[i] != 0 ) {
ret = 1;
break;
}
}
}
}
}

mutex_unlock(&mtx_access);
return ret;
}

int universal_address_compare_prefix(universal_address_container_t *entry,
uint8_t *prefix, size_t prefix_size_in_bits)
{
mutex_lock(&mtx_access);
int ret = -ENOENT;
/* If we have distinct sizes, the prefix is not comperable */
if ((size_t)(entry->address_size<<3) != prefix_size_in_bits) {
mutex_unlock(&mtx_access);
return ret;
}

/* Get the index of the first trailing `0` */
int i = 0;
for( i = entry->address_size-1; i >= 0; --i) {
if( prefix[i] != 0 ) {
break;
}
}

if( memcmp(entry->address, prefix, i) == 0 ) {
/* if the bytes-1 equals we check the bits of the lowest byte */
uint8_t bitmask = 0x00;
/* get a bitmask for the trailing 0b */
for( uint8_t j = 0; j < 8; ++j ) {
if ( (prefix[i] >> j) & 0x01 ) {
bitmask = 0xff << j;
break;
}
}

if( (entry->address[i] & bitmask) == (prefix[i] & bitmask) ) {
ret = entry->address[i] != prefix[i];
if( ret == 0 ) {
/* check if the remaining bits from entry are significant */
i++;
for(; i < entry->address_size; ++i) {
if( entry->address[i] != 0 ) {
ret = 1;
break;
}
}
}
}
}

mutex_unlock(&mtx_access);
Expand Down
2 changes: 1 addition & 1 deletion tests/unittests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include ../Makefile.tests_common
BOARD_INSUFFICIENT_RAM := airfy-beacon chronos msb-430 msb-430h pca10000 \
pca10005 redbee-econotag spark-core stm32f0discovery \
telosb wsn430-v1_3b wsn430-v1_4 z1 nucleo-f334 \
yunjia-nrf51822
yunjia-nrf51822 samr21-xpro

USEMODULE += embunit

Expand Down
Loading