Skip to content

Commit

Permalink
fib: changed handling of the net prefix
Browse files Browse the repository at this point in the history
Until now the prefix length has been determined automatically by the FIB
This PR changes it to be provided as msb(yte) in the global_flags of an entry
  • Loading branch information
BytesGalore authored and BytesGalore committed Mar 30, 2016
1 parent 18b7c8e commit 1bc9c3b
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 82 deletions.
9 changes: 7 additions & 2 deletions sys/include/net/fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 2 additions & 11 deletions sys/net/gnrc/routing/rpl/gnrc_rpl_control_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,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",
Expand Down Expand Up @@ -816,16 +816,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)),
Expand Down
6 changes: 3 additions & 3 deletions sys/net/gnrc/routing/rpl/gnrc_rpl_dodag.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,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,
Expand Down Expand Up @@ -248,7 +248,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,
Expand Down Expand Up @@ -300,7 +300,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,
Expand Down
40 changes: 29 additions & 11 deletions sys/net/network_layer/fib/fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,23 +132,39 @@ 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 */
return 1;
}
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;
}
}
Expand Down Expand Up @@ -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);
Expand Down
37 changes: 23 additions & 14 deletions sys/shell/commands/sc_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}
Expand All @@ -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);
}
Expand Down
62 changes: 34 additions & 28 deletions sys/universal_address/universal_address.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 2;
}

/* if we have no distinct bytes the addresses are equal */
if (idx == -1) {
mutex_unlock(&mtx_access);
return 0;
}

/* 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 = 1;

mutex_unlock(&mtx_access);
return ret;
}
Expand Down
Loading

0 comments on commit 1bc9c3b

Please sign in to comment.