Merge pull request #4279 from BytesGalore/fib_prefix_handling_change

fib: changed handling of the net prefix by the FIB
pr/gpio
Cenk Gündoğan 7 years ago
commit 9dbfdcac0b

@ -78,9 +78,14 @@ typedef struct fib_destination_set_entry_t {
#define FIB_FLAG_RPL_ROUTE (1UL << 0)
/**
* @brief flag to identify if the FIB-Entry is a net prefix (MSB == 1)
* @brief flag used as shift for the net prefix length in bits
*/
#define FIB_FLAG_NET_PREFIX (1UL<<31)
#define FIB_FLAG_NET_PREFIX_SHIFT (24)
/**
* @brief flag used as mask for the net prefix length in bits
*/
#define FIB_FLAG_NET_PREFIX_MASK (0xffUL << FIB_FLAG_NET_PREFIX_SHIFT)
/**
* @brief initializes all FIB entries with 0

@ -42,6 +42,17 @@ extern "C" {
#define UNIVERSAL_ADDRESS_SIZE (IPV6_ADDR_BIT_LEN >> 3)
#endif
/** @brief return value indicating the compared addresses are equal */
#define UNIVERSAL_ADDRESS_EQUAL (0)
/** @brief return value indicating the compared addresses match up to a certain prefix */
#define UNIVERSAL_ADDRESS_MATCHING_PREFIX (1)
/** @brief return value indicating all address bits of the entry are `0`.
* Its considered as default route address that matches any other prefix.
*/
#define UNIVERSAL_ADDRESS_IS_ALL_ZERO_ADDRESS (2)
/**
* @brief The container descriptor used to identify a universal address entry
*/
@ -69,7 +80,7 @@ void universal_address_reset(void);
* @param[in] addr_size the number of bytes required for the address entry
*
* @return pointer to the universal_address_container_t containing the address on success
* NULL if the address could not be inserted
* @return NULL if the address could not be inserted
*/
universal_address_container_t *universal_address_add(uint8_t *addr, size_t addr_size);
@ -90,7 +101,7 @@ void universal_address_rem(universal_address_container_t *entry);
* this value is overwritten with the actual size required
*
* @return addr if the address is copied to the addr destination
* NULL if the size is unsufficient for copy
* @return NULL if the size is unsufficient for copy
*/
uint8_t* universal_address_get_address(universal_address_container_t *entry,
uint8_t *addr, size_t *addr_size);
@ -107,9 +118,12 @@ uint8_t* universal_address_get_address(universal_address_container_t *entry,
* with the number of matching bits till the
* first of trailing `0`s
*
* @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
* @return UNIVERSAL_ADDRESS_EQUAL if the entries are equal
* @return UNIVERSAL_ADDRESS_MATCHING_PREFIX if the entry matches to a certain prefix
* (trailing '0's in @p entry)
* @return UNIVERSAL_ADDRESS_IS_ALL_ZERO_ADDRESS if the entry address is all `0`s
* and considered as default route
* @return -ENOENT if the given adresses do not match
*/
int universal_address_compare(universal_address_container_t *entry,
uint8_t *addr, size_t *addr_size_in_bits);
@ -128,9 +142,10 @@ int universal_address_compare(universal_address_container_t *entry,
* e.g. for an ipv6_addr_t it would be sizeof(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
* @return UNIVERSAL_ADDRESS_EQUAL if the entries are equal
* @return UNIVERSAL_ADDRESS_MATCHING_PREFIX if the entry matches to a certain prefix
* (trailing '0's in @p prefix)
* @return -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);

@ -475,7 +475,7 @@ bool _parse_options(int msg_type, gnrc_rpl_instance_t *inst, gnrc_rpl_opt_t *opt
uint32_t fib_dst_flags = 0;
if (target->prefix_length < IPV6_ADDR_BIT_LEN) {
fib_dst_flags |= FIB_FLAG_NET_PREFIX;
fib_dst_flags = ((uint32_t)(target->prefix_length) << FIB_FLAG_NET_PREFIX_SHIFT);
}
DEBUG("RPL: adding fib entry %s/%d 0x%x\n",
@ -856,16 +856,7 @@ void gnrc_rpl_send_DAO(gnrc_rpl_instance_t *inst, ipv6_addr_t *destination, uint
}
addr = (ipv6_addr_t *) fentry->global->address;
if (ipv6_addr_is_global(addr)) {
size_t prefix_length;
if (fentry->global_flags & FIB_FLAG_NET_PREFIX) {
universal_address_compare(fentry->global,
fentry->global->address,
&prefix_length);
}
else {
prefix_length = IPV6_ADDR_BIT_LEN;
}
size_t prefix_length = (fentry->global_flags >> FIB_FLAG_NET_PREFIX_SHIFT);
DEBUG("RPL: Send DAO - building target %s/%d\n",
ipv6_addr_to_str(addr_str, addr, sizeof(addr_str)),

@ -230,7 +230,7 @@ bool gnrc_rpl_parent_remove(gnrc_rpl_parent_t *parent)
dodag->iface,
(uint8_t *) ipv6_addr_unspecified.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_NET_PREFIX,
0x0,
parent->next->addr.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_RPL_ROUTE,
@ -277,7 +277,7 @@ void gnrc_rpl_parent_update(gnrc_rpl_dodag_t *dodag, gnrc_rpl_parent_t *parent)
dodag->iface,
(uint8_t *) ipv6_addr_unspecified.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_NET_PREFIX,
0x00,
parent->addr.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_RPL_ROUTE,
@ -337,7 +337,7 @@ static gnrc_rpl_parent_t *_gnrc_rpl_find_preferred_parent(gnrc_rpl_dodag_t *doda
dodag->iface,
(uint8_t *) ipv6_addr_unspecified.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_NET_PREFIX,
0x00,
dodag->parents->addr.u8,
sizeof(ipv6_addr_t),
FIB_FLAG_RPL_ROUTE,

@ -132,8 +132,7 @@ static int fib_find_entry(fib_table_t *table, uint8_t *dst, size_t dst_size,
int ret_comp = universal_address_compare(table->data.entries[i].global, dst, &match_size);
/* If we found an exact match */
if (ret_comp == 0 || (is_all_zeros_addr && match_size == 0)) {
DEBUG("[fib_find_entry] found an exact match");
if ((ret_comp == 0) || (is_all_zeros_addr && (match_size == 0) && (ret_comp == 2))) {
entry_arr[0] = &(table->data.entries[i]);
*entry_arr_size = 1;
/* we will not find a better one so we return */
@ -141,14 +140,31 @@ static int fib_find_entry(fib_table_t *table, uint8_t *dst, size_t dst_size,
}
else {
/* we try to find the most fitting prefix */
if ((ret_comp == 1)
&& (table->data.entries[i].global_flags & FIB_FLAG_NET_PREFIX)) {
if ((prefix_size == 0) || (match_size > prefix_size)) {
if (ret_comp == 1) {
if (table->data.entries[i].global_flags & FIB_FLAG_NET_PREFIX_MASK) {
/* we shift the most upper flag byte back to get the number of prefix bits */
size_t global_prefix_len = (table->data.entries[i].global_flags
& FIB_FLAG_NET_PREFIX_MASK) >> FIB_FLAG_NET_PREFIX_SHIFT;
if ((match_size >= global_prefix_len) &&
((prefix_size == 0) || (match_size > prefix_size))) {
entry_arr[0] = &(table->data.entries[i]);
/* we could find a better one so we move on */
ret = 0;
prefix_size = match_size;
count = 1;
}
}
}
else if (ret_comp == 2) {
/* we found the default gateway entry, e.g. ::/0 for IPv6
* and we keep it only if there is no better one
*/
if (prefix_size == 0) {
entry_arr[0] = &(table->data.entries[i]);
/* we could find a better one so we move on */
ret = 0;
prefix_size = match_size;
count = 1;
}
}
@ -1516,17 +1532,19 @@ void fib_print_routes(fib_table_t *table)
uint64_t now = xtimer_now64();
if (table->table_type == FIB_TABLE_TYPE_SH) {
printf("%-" FIB_ADDR_PRINT_LENS "s %-10s %-" FIB_ADDR_PRINT_LENS "s %-10s %-16s"
printf("%-" FIB_ADDR_PRINT_LENS "s %-17s %-" FIB_ADDR_PRINT_LENS "s %-10s %-16s"
" Interface\n" , "Destination", "Flags", "Next Hop", "Flags", "Expires");
for (size_t i = 0; i < table->size; ++i) {
if (table->data.entries[i].lifetime != 0) {
fib_print_address(table->data.entries[i].global);
printf(" 0x%08"PRIx32" ", table->data.entries[i].global_flags);
if(table->data.entries[i].global_flags & FIB_FLAG_NET_PREFIX) {
printf("N ");
if(table->data.entries[i].global_flags & FIB_FLAG_NET_PREFIX_MASK) {
uint32_t prefix = (table->data.entries[i].global_flags
& FIB_FLAG_NET_PREFIX_MASK);
printf("N /%-3d ", (int)(prefix >> FIB_FLAG_NET_PREFIX_SHIFT));
} else {
printf("H ");
printf("H ");
}
fib_print_address(table->data.entries[i].next_hop);

@ -33,7 +33,7 @@
#define INFO1_TXT "fibroute add <destination> via <next hop> [dev <device>]"
#define INFO2_TXT " [lifetime <lifetime>]"
#define INFO3_TXT " <destination> - the destination address\n" \
#define INFO3_TXT " <destination> - the destination address with optional prefix size, e.g. /116\n" \
" <next hop> - the address of the next-hop towards the <destination>\n" \
" <device> - the device id of the Interface to use." \
" Optional if only one interface is available.\n"
@ -79,15 +79,33 @@ static void _fib_usage(int info)
static void _fib_add(const char *dest, const char *next, kernel_pid_t pid, uint32_t lifetime)
{
unsigned char *dst = (unsigned char *)dest;
size_t dst_size = (strlen(dest));
uint32_t prefix = 0;
/* Get the prefix length */
size_t i = 0;
for (i = strlen(dest); i > 0; --i) {
if (dest[i] == '/') {
prefix = atoi(&dest[i+1]);
break;
}
if (dest[i] == ':' || dest[i] == '.') {
i = strlen(dest);
break;
}
}
size_t dst_size = (i+1);
unsigned char dst_arr[dst_size];
memset(dst_arr, 0, dst_size);
memcpy(dst_arr, dest, i);
unsigned char *dst = &dst_arr[0];
uint32_t dst_flags = 0;
unsigned char *nxt = (unsigned char *)next;
size_t nxt_size = (strlen(next));
uint32_t nxt_flags = 0;
/* determine destination address */
if (inet_pton(AF_INET6, dest, tmp_ipv6_dst)) {
if (inet_pton(AF_INET6, (char*)dst, tmp_ipv6_dst)) {
dst = tmp_ipv6_dst;
dst_size = IN6ADDRSZ;
}
@ -106,16 +124,7 @@ static void _fib_add(const char *dest, const char *next, kernel_pid_t pid, uint3
nxt_size = INADDRSZ;
}
/* Set the prefix flag for a network */
dst_flags |= FIB_FLAG_NET_PREFIX;
for (size_t i = 0; i < dst_size; ++i) {
if (dst[i] != 0) {
/* and clear the bit if its not the default route */
dst_flags = (dst_flags & ~FIB_FLAG_NET_PREFIX);
break;
}
}
dst_flags |= (prefix << FIB_FLAG_NET_PREFIX_SHIFT);
fib_add_entry(&gnrc_ipv6_fib_table, pid, dst, dst_size, dst_flags, nxt,
nxt_size, nxt_flags, lifetime);
}

@ -196,41 +196,47 @@ int universal_address_compare(universal_address_container_t *entry,
return ret;
}
/* 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 ) {
/* compare up to fist distinct byte, pretty clumsy method for now */
int idx = -1;
bool test_all_zeros = true;
for (size_t i = 0; i < entry->address_size; i++) {
if ((idx == -1) && (entry->address[i] != addr[i])) {
idx = i;
}
if (test_all_zeros) {
test_all_zeros = (entry->address[i] == 0);
}
if ((idx != -1) && !test_all_zeros) {
break;
}
}
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) + (8-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;
}
}
}
/* if the address is all 0 its a default route address */
if (test_all_zeros) {
*addr_size_in_bits = 0;
mutex_unlock(&mtx_access);
return UNIVERSAL_ADDRESS_IS_ALL_ZERO_ADDRESS;
}
/* if we have no distinct bytes the addresses are equal */
if (idx == -1) {
mutex_unlock(&mtx_access);
return UNIVERSAL_ADDRESS_EQUAL;
}
/* count equal bits */
uint8_t xor = entry->address[idx]^addr[idx];
int8_t j = 7;
for ( ; j > 0; --j) {
if ((xor >> j) & 0x01) {
break;
}
}
/* get the total number of matching bits */
*addr_size_in_bits = (idx << 3) + j;
ret = UNIVERSAL_ADDRESS_MATCHING_PREFIX;
mutex_unlock(&mtx_access);
return ret;
}
@ -248,31 +254,31 @@ int universal_address_compare_prefix(universal_address_container_t *entry,
/* Get the index of the first trailing `0` */
int i = 0;
for( i = entry->address_size-1; i >= 0; --i) {
if( prefix[i] != 0 ) {
for (i = entry->address_size-1; i >= 0; --i) {
if (prefix[i] != 0) {
break;
}
}
if( memcmp(entry->address, prefix, i) == 0 ) {
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 ) {
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) ) {
if ((entry->address[i] & bitmask) == (prefix[i] & bitmask)) {
ret = entry->address[i] != prefix[i];
if( ret == 0 ) {
if (ret == UNIVERSAL_ADDRESS_EQUAL) {
/* check if the remaining bits from entry are significant */
i++;
for(; i < entry->address_size; ++i) {
if( entry->address[i] != 0 ) {
ret = 1;
for ( ; i < entry->address_size; ++i) {
if (entry->address[i] != 0) {
ret = UNIVERSAL_ADDRESS_MATCHING_PREFIX;
break;
}
}

@ -35,8 +35,8 @@ static void _fill_FIB_unique(size_t entries)
size_t add_buf_size = 16;
char addr_dst[add_buf_size];
char addr_nxt[add_buf_size];
uint32_t addr_dst_flags = 0x77777777;
uint32_t addr_nxt_flags = 0x77777777;
uint32_t addr_dst_flags = 0x00777777;
uint32_t addr_nxt_flags = 0x00777777;
for (size_t i = 0; i < entries; ++i) {
/* construct "addresses" for the FIB */
@ -59,8 +59,8 @@ static void _fill_FIB_multiple(size_t entries, size_t modulus)
size_t add_buf_size = 16;
char addr_dst[add_buf_size];
char addr_nxt[add_buf_size];
uint32_t addr_dst_flags = 0x33333333;
uint32_t addr_nxt_flags = 0x33333333;
uint32_t addr_dst_flags = 0x00333333;
uint32_t addr_nxt_flags = 0x00333333;
for (size_t i = 0; i < entries; ++i) {
/* construct "addresses" for the FIB */
@ -73,6 +73,29 @@ static void _fill_FIB_multiple(size_t entries, size_t modulus)
}
}
/*
* @brief helper to determine the prefix bits
*/
static size_t _get_prefix_bits_num(char* addr, size_t addr_len)
{
/* Get the index of the first trailing `0` */
int i = 0;
for (i = addr_len-1; i > 0; --i) {
if (addr[i] != 0) {
break;
}
}
/* now we check the bits of the lowest byte */
uint8_t j = 0;
for ( ; j < 8; ++j) {
if ((addr[i] >> j) & 0x01) {
break;
}
}
return (i << 3) + (8 - j);
}
/*
* @brief filling the FIB with entries
* It is expected to have 20 FIB entries and 40 used universal address entries
@ -493,22 +516,27 @@ static void test_fib_14_exact_and_prefix_match(void)
snprintf(addr_dst, add_buf_size, "Test addr12");
snprintf(addr_nxt, add_buf_size, "Test address %02d", 12);
/* get the prefix in bits */
uint32_t prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x12),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x12),
(uint8_t *)addr_nxt, add_buf_size - 1,
0x12, 100000);
snprintf(addr_dst, add_buf_size, "Test addr123");
snprintf(addr_nxt, add_buf_size, "Test address %02d", 23);
prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size - 1,
0x23, 100000);
snprintf(addr_dst, add_buf_size, "Test addr1234");
snprintf(addr_nxt, add_buf_size, "Test address %02d", 34);
prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x1234),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x1234),
(uint8_t *)addr_nxt, add_buf_size - 1,
0x34, 100000);
@ -612,14 +640,16 @@ static void test_fib_16_prefix_match(void)
addr_dst[14] = (char)0x80; /* 1000 0000 */
addr_lookup[14] = (char)0x87; /* 1000 0111 */
uint32_t prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size - 1,
0x23, 100000);
addr_dst[14] = (char)0x3c; /* 0011 1100 */
prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size - 1,
0x23, 100000);
@ -634,10 +664,12 @@ static void test_fib_16_prefix_match(void)
/* test fail */
addr_dst[14] = (char)0x3c; /* 0011 1100 */
addr_lookup[14] = (char)0x34; /* 0011 0100 */
addr_lookup[13] += 1;
add_buf_size = 16;
prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size - 1, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size - 1, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size -
1, 0x23, 100000);
@ -651,6 +683,7 @@ static void test_fib_16_prefix_match(void)
/* test success (again) by adjusting the lsb */
addr_lookup[14] = (char)0x3e; /* 0011 1110 */
addr_lookup[13] -= 1;
add_buf_size = 16;
memset(addr_nxt, 0, add_buf_size);
@ -813,7 +846,7 @@ static void test_fib_19_default_gateway(void)
/* add a default gateway entry */
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size, 0x123,
(uint8_t *)addr_nxt, add_buf_size, 0x23,
100000);
@ -888,9 +921,10 @@ static void test_fib_20_replace_prefix(void)
addr_lookup[i] = i+1;
}
uint32_t prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
/* add a prefix entry */
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size, 0x23,
100000);
@ -918,9 +952,10 @@ static void test_fib_20_replace_prefix(void)
addr_dst[i] = i+1;
}
prefix_len = _get_prefix_bits_num(addr_dst, strlen(addr_dst));
/* change the prefix entry */
fib_add_entry(&test_fib_table, 42, (uint8_t *)addr_dst,
add_buf_size, (FIB_FLAG_NET_PREFIX | 0x123),
add_buf_size, ((prefix_len << FIB_FLAG_NET_PREFIX_SHIFT) | 0x123),
(uint8_t *)addr_nxt, add_buf_size, 0x24,
100000);

Loading…
Cancel
Save