/** * @brief signals (sends a message to) all registered routing protocols * registered with a matching prefix (usually this should be only one). * The message informs the recipient that no next-hop is available for the * requested destination address. * The receiver MUST copy the content, i.e. the address before reply. * * @param[in] dst the destination address * @param[in] dst_size the destination address size * * @return 0 on a new available entry, * -ENOENT if no suiting entry is provided. */ static int fib_signal_rp(uint8_t *dst, size_t dst_size, uint32_t dst_flags) { msg_t msg, reply; rp_address_msg_t content; content.address = dst; content.address_size = dst_size; content.address_flags = dst_flags; int ret = -ENOENT; msg.type = FIB_MSG_RP_SIGNAL; msg.content.ptr = (void *)&content; for (size_t i = 0; i < FIB_MAX_REGISTERED_RP; ++i) { if (notify_rp[i] != KERNEL_PID_UNDEF) { DEBUG("[fib_signal_rp] send msg@: %p to pid[%d]: %d\n", \ msg.content.ptr, (int)i, (int)notify_rp[i]); /* do only signal a RP if its registered prefix matches */ size_t dst_size_in_bits = dst_size<<3; if (universal_address_compare(prefix_rp[i], dst, &dst_size_in_bits) == 1) { /* the receiver, i.e. the RP, MUST copy the content value. * using the provided pointer after replying this message * will lead to errors */ msg_send_receive(&msg, &reply, notify_rp[i]); DEBUG("[fib_signal_rp] got reply.\n"); } } } return ret; }
/** * @brief returns pointer to the entry for the given destination address * * @param[in] dst the destination address * @param[in] dst_size the destination address size * @param[out] entry_arr the array to scribe the found match * @param[in, out] entry_arr_size the number of entries provided by entry_arr (should be always 1) * this value is overwritten with the actual found number * * @return 0 if we found a next-hop prefix * 1 if we found the exact address next-hop * -EHOSTUNREACH if no fitting next-hop is available */ static int fib_find_entry(uint8_t *dst, size_t dst_size, fib_entry_t **entry_arr, size_t *entry_arr_size) { timex_t now; vtimer_now(&now); size_t count = 0; size_t prefix_size = 0; size_t match_size = dst_size; int ret = -EHOSTUNREACH; for (size_t i = 0; i < FIB_MAX_FIB_TABLE_ENTRIES; ++i) { /* autoinvalidate if the entry lifetime is not set to not expire */ if ((fib_table[i].lifetime.seconds != FIB_LIFETIME_NO_EXPIRE) || (fib_table[i].lifetime.microseconds != FIB_LIFETIME_NO_EXPIRE)) { /* check if the lifetime expired */ if (timex_cmp(now, fib_table[i].lifetime) > -1) { /* remove this entry if its lifetime expired */ fib_table[i].lifetime.seconds = 0; fib_table[i].lifetime.microseconds = 0; if (fib_table[i].global != NULL) { universal_address_rem(fib_table[i].global); fib_table[i].global = NULL; } if (fib_table[i].next_hop != NULL) { universal_address_rem(fib_table[i].next_hop); fib_table[i].next_hop = NULL; } } } if ((prefix_size < dst_size) && (fib_table[i].global != NULL) && (universal_address_compare(fib_table[i].global, dst, &match_size) == 0)) { /* If we found an exact match */ if (match_size == dst_size) { 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) { 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; count = 1; } } *entry_arr_size = count; return ret; }
/** * @brief returns pointer to the entry for the given destination address * * @param[in] table the FIB table to search in * @param[in] dst the destination address * @param[in] dst_size the destination address size * @param[out] entry_arr the array to scribe the found match * @param[in, out] entry_arr_size the number of entries provided by entry_arr (should be always 1) * this value is overwritten with the actual found number * * @return 0 if we found a next-hop prefix * 1 if we found the exact address next-hop * -EHOSTUNREACH if no fitting next-hop is available */ static int fib_find_entry(fib_table_t *table, uint8_t *dst, size_t dst_size, fib_entry_t **entry_arr, size_t *entry_arr_size) { uint64_t now = xtimer_now64(); size_t count = 0; size_t prefix_size = 0; size_t match_size = dst_size<<3; int ret = -EHOSTUNREACH; bool is_all_zeros_addr = true; for(size_t i = 0; i < dst_size; ++i) { if (dst[i] != 0) { is_all_zeros_addr = false; break; } } for (size_t i = 0; i < table->size; ++i) { /* autoinvalidate if the entry lifetime is not set to not expire */ if (table->entries[i].lifetime != FIB_LIFETIME_NO_EXPIRE) { /* check if the lifetime expired */ if (table->entries[i].lifetime < now) { /* remove this entry if its lifetime expired */ table->entries[i].lifetime = 0; table->entries[i].global_flags = 0; table->entries[i].next_hop_flags = 0; table->entries[i].iface_id = KERNEL_PID_UNDEF; if (table->entries[i].global != NULL) { universal_address_rem(table->entries[i].global); table->entries[i].global = NULL; } if (table->entries[i].next_hop != NULL) { universal_address_rem(table->entries[i].next_hop); table->entries[i].next_hop = NULL; } } } if ((prefix_size < (dst_size<<3)) && (table->entries[i].global != NULL)) { int ret_comp = universal_address_compare(table->entries[i].global, dst, &match_size); /* If we found an exact match */ if (ret_comp == 0 || (is_all_zeros_addr && match_size == 0)) { entry_arr[0] = &(table->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) { entry_arr[0] = &(table->entries[i]); /* we could find a better one so we move on */ ret = 0; prefix_size = match_size; match_size = dst_size<<3; count = 1; } } } } *entry_arr_size = count; return ret; }