mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
net: Remove NHDP module
NHDP has been flagged as deprecated in
056bd35e6c
, due to lack of maintenance.
This commit is contained in:
parent
7cacc594cd
commit
9026823bb9
@ -64,12 +64,6 @@ ifneq (,$(filter gnrc_lorawan,$(USEMODULE)))
|
||||
USEMODULE += gnrc_neterr
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nhdp,$(USEMODULE)))
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += xtimer
|
||||
USEMODULE += oonf_rfc5444
|
||||
endif
|
||||
|
||||
ifneq (,$(filter sntp,$(USEMODULE)))
|
||||
USEMODULE += sock_udp
|
||||
USEMODULE += xtimer
|
||||
|
@ -67,9 +67,6 @@ endif
|
||||
ifneq (,$(filter cipher_modes,$(USEMODULE)))
|
||||
DIRS += crypto/modes
|
||||
endif
|
||||
ifneq (,$(filter nhdp,$(USEMODULE)))
|
||||
DIRS += net/routing/nhdp
|
||||
endif
|
||||
ifneq (,$(filter fib,$(USEMODULE)))
|
||||
DIRS += net/network_layer/fib
|
||||
endif
|
||||
|
@ -1,7 +1,3 @@
|
||||
ifneq (,$(filter nhdp,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/routing/nhdp
|
||||
endif
|
||||
|
||||
ifneq (,$(filter gnrc_sixlowpan_frag_rb,$(USEMODULE)))
|
||||
USEMODULE_INCLUDES += $(RIOTBASE)/sys/net/gnrc/network_layer/sixlowpan/frag
|
||||
endif
|
||||
|
@ -1 +0,0 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
@ -1,925 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Interface Information Base implementation for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mutex.h"
|
||||
#include "timex.h"
|
||||
#include "xtimer.h"
|
||||
#include "utlist.h"
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "rfc5444/rfc5444.h"
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "iib_table.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_metric.h"
|
||||
#include "nhdp_writer.h"
|
||||
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/* Internal variables */
|
||||
static mutex_t mtx_iib_access = MUTEX_INIT;
|
||||
static iib_base_entry_t *iib_base_entry_head = NULL;
|
||||
|
||||
#if (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
static const double const_dat = (((double)DAT_CONSTANT) / DAT_MAXIMUM_LOSS);
|
||||
#endif
|
||||
|
||||
/* Internal function prototypes */
|
||||
static void rem_link_set_entry(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry);
|
||||
static void cleanup_link_sets(void);
|
||||
static iib_link_set_entry_t *add_default_link_set_entry(iib_base_entry_t *base_entry, timex_t *now,
|
||||
uint64_t val_time);
|
||||
static void reset_link_set_entry(iib_link_set_entry_t *ls_entry, timex_t *now, uint64_t val_time);
|
||||
static iib_link_set_entry_t *update_link_set(iib_base_entry_t *base_entry, nib_entry_t *nb_elt,
|
||||
timex_t *now, uint64_t val_time,
|
||||
uint8_t sym, uint8_t lost);
|
||||
static void release_link_tuple_addresses(iib_link_set_entry_t *ls_entry);
|
||||
|
||||
static int update_two_hop_set(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry,
|
||||
timex_t *now, uint64_t val_time);
|
||||
static int add_two_hop_entry(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry,
|
||||
nhdp_addr_t *th_addr, timex_t *now, uint64_t val_time);
|
||||
static void rem_two_hop_entry(iib_base_entry_t *base_entry, iib_two_hop_set_entry_t *th_entry);
|
||||
|
||||
static void wr_update_ls_status(iib_base_entry_t *base_entry,
|
||||
iib_link_set_entry_t *ls_elt, timex_t *now);
|
||||
static void update_nb_tuple_symmetry(iib_base_entry_t *base_entry,
|
||||
iib_link_set_entry_t *ls_entry, timex_t *now);
|
||||
static void rem_not_heard_nb_tuple(iib_link_set_entry_t *ls_entry, timex_t *now);
|
||||
|
||||
static inline timex_t get_max_timex(timex_t time_one, timex_t time_two);
|
||||
static iib_link_tuple_status_t get_tuple_status(iib_link_set_entry_t *ls_entry, timex_t *now);
|
||||
|
||||
#if (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
static void queue_rem(uint8_t *queue);
|
||||
static uint16_t queue_sum(uint8_t *queue);
|
||||
static void dat_metric_refresh(void);
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* Interface Information Base API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
int iib_register_if(kernel_pid_t pid)
|
||||
{
|
||||
iib_base_entry_t *new_entry = (iib_base_entry_t *) malloc(sizeof(iib_base_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_entry->if_pid = pid;
|
||||
new_entry->link_set_head = NULL;
|
||||
new_entry->two_hop_set_head = NULL;
|
||||
LL_PREPEND(iib_base_entry_head, new_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
iib_link_set_entry_t *iib_process_hello(kernel_pid_t if_pid, nib_entry_t *nb_elt,
|
||||
uint64_t validity_time, uint8_t is_sym_nb,
|
||||
uint8_t is_lost)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_entry = NULL;
|
||||
timex_t now;
|
||||
|
||||
mutex_lock(&mtx_iib_access);
|
||||
|
||||
/* Remove link tuple addresses that are included in the Removed Addr List */
|
||||
cleanup_link_sets();
|
||||
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
/* Find the link set and two hop set for the interface */
|
||||
if (base_elt->if_pid == if_pid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_elt) {
|
||||
xtimer_now_timex(&now);
|
||||
|
||||
/* Create a new link tuple for the neighbor that originated the hello */
|
||||
ls_entry = update_link_set(base_elt, nb_elt, &now, validity_time, is_sym_nb, is_lost);
|
||||
|
||||
/* Create new two hop tuples for signaled symmetric neighbors */
|
||||
if (ls_entry) {
|
||||
update_two_hop_set(base_elt, ls_entry, &now, validity_time);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_iib_access);
|
||||
|
||||
return ls_entry;
|
||||
}
|
||||
|
||||
void iib_fill_wr_addresses(kernel_pid_t if_pid, struct rfc5444_writer *wr)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_elt = NULL;
|
||||
nhdp_addr_entry_t *addr_elt = NULL;
|
||||
timex_t now;
|
||||
|
||||
mutex_lock(&mtx_iib_access);
|
||||
|
||||
xtimer_now_timex(&now);
|
||||
|
||||
/* Before adding addresses first update the status of all link tuples */
|
||||
iib_update_lt_status(&now);
|
||||
|
||||
/* Add all addresses of Link Tuples of the given interface's Link Set to the current HELLO */
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
if (base_elt->if_pid == if_pid) {
|
||||
LL_FOREACH(base_elt->link_set_head, ls_elt) {
|
||||
if (ls_elt->last_status != IIB_LT_STATUS_PENDING) {
|
||||
/* Exclude addresses from tuples with L_STATUS = PENDING */
|
||||
LL_FOREACH(ls_elt->address_list_head, addr_elt) {
|
||||
if (!NHDP_ADDR_TMP_IN_ANY(addr_elt->address)) {
|
||||
/* Add address to the writers next packet */
|
||||
switch (ls_elt->last_status) {
|
||||
case IIB_LT_STATUS_SYM:
|
||||
nhdp_writer_add_addr(wr, addr_elt->address,
|
||||
RFC5444_ADDRTLV_LINK_STATUS,
|
||||
RFC5444_LINKSTATUS_SYMMETRIC,
|
||||
rfc5444_metric_encode(ls_elt->metric_in),
|
||||
rfc5444_metric_encode(ls_elt->metric_out));
|
||||
addr_elt->address->in_tmp_table = NHDP_ADDR_TMP_SYM;
|
||||
break;
|
||||
|
||||
case IIB_LT_STATUS_HEARD:
|
||||
nhdp_writer_add_addr(wr, addr_elt->address,
|
||||
RFC5444_ADDRTLV_LINK_STATUS,
|
||||
RFC5444_LINKSTATUS_HEARD,
|
||||
rfc5444_metric_encode(ls_elt->metric_in),
|
||||
rfc5444_metric_encode(ls_elt->metric_out));
|
||||
addr_elt->address->in_tmp_table = NHDP_ADDR_TMP_ANY;
|
||||
break;
|
||||
|
||||
case IIB_LT_STATUS_UNKNOWN:
|
||||
/* Fall through */
|
||||
|
||||
case IIB_LT_STATUS_LOST:
|
||||
nhdp_writer_add_addr(wr, addr_elt->address,
|
||||
RFC5444_ADDRTLV_LINK_STATUS,
|
||||
RFC5444_LINKSTATUS_LOST,
|
||||
rfc5444_metric_encode(ls_elt->metric_in),
|
||||
rfc5444_metric_encode(ls_elt->metric_out));
|
||||
addr_elt->address->in_tmp_table = NHDP_ADDR_TMP_ANY;
|
||||
break;
|
||||
|
||||
case IIB_LT_STATUS_PENDING:
|
||||
/* Pending link tuples are not included */
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Should not happen */
|
||||
DEBUG("%s:%d in %s: [WARNING] Unknown link tuple status\n",
|
||||
RIOT_FILE_RELATIVE, __LINE__, DEBUG_FUNC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* IF's link set found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_iib_access);
|
||||
}
|
||||
|
||||
void iib_update_lt_status(timex_t *now)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_elt = NULL, *ls_tmp = NULL;
|
||||
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
LL_FOREACH_SAFE(base_elt->link_set_head, ls_elt, ls_tmp) {
|
||||
wr_update_ls_status(base_elt, ls_elt, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iib_propagate_nb_entry_change(nib_entry_t *old_entry, nib_entry_t *new_entry)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_elt = NULL;
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
LL_FOREACH(base_elt->link_set_head, ls_elt) {
|
||||
if (ls_elt->nb_elt == old_entry) {
|
||||
ls_elt->nb_elt = new_entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void iib_process_metric_msg(iib_link_set_entry_t *ls_entry, uint64_t int_time)
|
||||
{
|
||||
#if (NHDP_METRIC == NHDP_LMT_HOP_COUNT)
|
||||
/* Hop metric value for an existing direct link is always 1 */
|
||||
(void)int_time;
|
||||
ls_entry->metric_in = 1;
|
||||
ls_entry->metric_out = 1;
|
||||
if (ls_entry->nb_elt) {
|
||||
ls_entry->nb_elt->metric_in = 1;
|
||||
ls_entry->nb_elt->metric_out = 1;
|
||||
}
|
||||
#elif (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
/* Process required DAT metric steps */
|
||||
ls_entry->hello_interval = rfc5444_timetlv_encode(int_time);
|
||||
if (ls_entry->last_seq_no == 0) {
|
||||
timex_t now, i_time;
|
||||
xtimer_now_timex(&now);
|
||||
i_time = timex_from_uint64(int_time * US_PER_MS * DAT_HELLO_TIMEOUT_FACTOR);
|
||||
ls_entry->dat_received[0]++;
|
||||
ls_entry->dat_total[0]++;
|
||||
ls_entry->dat_time = timex_add(now, i_time);
|
||||
}
|
||||
#else
|
||||
/* NHDP_METRIC is not set properly */
|
||||
(void)ls_entry;
|
||||
(void)int_time;
|
||||
DEBUG("%s:%d in %s: [WARNING] Unknown NHDP_METRIC setting\n",
|
||||
RIOT_FILE_RELATIVE, __LINE__, DEBUG_FUNC);
|
||||
#endif
|
||||
}
|
||||
|
||||
void iib_process_metric_pckt(iib_link_set_entry_t *ls_entry, uint32_t metric_out, uint16_t seq_no)
|
||||
{
|
||||
#if (NHDP_METRIC == NHDP_LMT_HOP_COUNT)
|
||||
/* Nothing to do here */
|
||||
(void)ls_entry;
|
||||
(void)metric_out;
|
||||
(void)seq_no;
|
||||
#elif (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
/* Metric packet processing */
|
||||
if (ls_entry->last_seq_no == 0) {
|
||||
ls_entry->dat_received[0] = 1;
|
||||
ls_entry->dat_total[0] = 1;
|
||||
}
|
||||
/* Don't add values to the queue for duplicate packets */
|
||||
else if (seq_no != ls_entry->last_seq_no) {
|
||||
uint16_t seq_diff;
|
||||
if (seq_no < ls_entry->last_seq_no) {
|
||||
seq_diff = (uint16_t) ((((uint32_t) seq_no) + 0xFFFF) - ls_entry->last_seq_no);
|
||||
}
|
||||
else {
|
||||
seq_diff = seq_no - ls_entry->last_seq_no;
|
||||
}
|
||||
ls_entry->dat_total[0] += (seq_diff > NHDP_SEQNO_RESTART_DETECT) ? 1 : seq_diff;
|
||||
ls_entry->dat_received[0]++;
|
||||
}
|
||||
|
||||
ls_entry->last_seq_no = seq_no;
|
||||
ls_entry->lost_hellos = 0;
|
||||
|
||||
if (ls_entry->hello_interval != 0) {
|
||||
timex_t now, i_time;
|
||||
xtimer_now_timex(&now);
|
||||
i_time = timex_from_uint64(rfc5444_timetlv_decode(ls_entry->hello_interval)
|
||||
* US_PER_MS * DAT_HELLO_TIMEOUT_FACTOR);
|
||||
ls_entry->dat_time = timex_add(now, i_time);
|
||||
}
|
||||
|
||||
/* Refresh metric value for link tuple and corresponding neighbor tuple */
|
||||
if (ls_entry->nb_elt) {
|
||||
if ((metric_out <= ls_entry->nb_elt->metric_out) ||
|
||||
(ls_entry->nb_elt->metric_out == NHDP_METRIC_UNKNOWN)) {
|
||||
/* Better value, use it also for your neighbor */
|
||||
ls_entry->nb_elt->metric_out = metric_out;
|
||||
}
|
||||
else if (ls_entry->metric_out == ls_entry->nb_elt->metric_out){
|
||||
/* The corresponding neighbor tuples metric needs to be updated */
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_elt;
|
||||
ls_entry->nb_elt->metric_out = metric_out;
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
LL_FOREACH(base_elt->link_set_head, ls_elt) {
|
||||
if ((ls_elt->nb_elt == ls_entry->nb_elt) && (ls_elt != ls_entry)) {
|
||||
if (ls_elt->metric_out < ls_entry->nb_elt->metric_out) {
|
||||
/* Smaller DAT value is better */
|
||||
ls_entry->nb_elt->metric_out = ls_elt->metric_out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ls_entry->metric_out = metric_out;
|
||||
#else
|
||||
/* NHDP_METRIC is not set properly */
|
||||
(void)ls_entry;
|
||||
(void)metric_out;
|
||||
(void)seq_no;
|
||||
DEBUG("%s:%d in %s: [WARNING] Unknown NHDP_METRIC setting\n",
|
||||
RIOT_FILE_RELATIVE, __LINE__, DEBUG_FUNC);
|
||||
#endif
|
||||
}
|
||||
|
||||
void iib_process_metric_refresh(void)
|
||||
{
|
||||
#if (NHDP_METRIC == NHDP_LMT_HOP_COUNT)
|
||||
/* Nothing to do here */
|
||||
#elif (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
dat_metric_refresh();
|
||||
#else
|
||||
/* NHDP_METRIC is not set properly */
|
||||
DEBUG("%s:%d in %s: [WARNING] Unknown NHDP_METRIC setting\n",
|
||||
RIOT_FILE_RELATIVE, __LINE__, DEBUG_FUNC);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Remove addresses included in the Removed Address List from all existing Link Tuples
|
||||
*/
|
||||
static void cleanup_link_sets(void)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
|
||||
/* Loop through all link sets */
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
/* Loop through all link tuples of the link set */
|
||||
iib_link_set_entry_t *ls_elt = NULL, *ls_tmp = NULL;
|
||||
LL_FOREACH_SAFE(base_elt->link_set_head, ls_elt, ls_tmp) {
|
||||
/* Loop through all addresses of the link tuples */
|
||||
nhdp_addr_entry_t *lt_elt = NULL, *lt_tmp = NULL;
|
||||
LL_FOREACH_SAFE(ls_elt->address_list_head, lt_elt, lt_tmp) {
|
||||
if (NHDP_ADDR_TMP_IN_REM_LIST(lt_elt->address)) {
|
||||
/* Remove link tuple address if included in the Removed Addr List */
|
||||
LL_DELETE(ls_elt->address_list_head, lt_elt);
|
||||
nhdp_free_addr_entry(lt_elt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove link tuples with empty address list */
|
||||
if (!ls_elt->address_list_head) {
|
||||
if (ls_elt->last_status == IIB_LT_STATUS_SYM) {
|
||||
/* Remove all two hop entries for the corresponding link tuple */
|
||||
iib_two_hop_set_entry_t *th_elt = NULL, *th_tmp = NULL;
|
||||
LL_FOREACH_SAFE(base_elt->two_hop_set_head, th_elt, th_tmp) {
|
||||
if (th_elt->ls_elt == ls_elt) {
|
||||
rem_two_hop_entry(base_elt, th_elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rem_link_set_entry(base_elt, ls_elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Link Set for the receiving interface during HELLO message processing
|
||||
*/
|
||||
static iib_link_set_entry_t *update_link_set(iib_base_entry_t *base_entry, nib_entry_t *nb_elt,
|
||||
timex_t *now, uint64_t val_time,
|
||||
uint8_t sym, uint8_t lost)
|
||||
{
|
||||
iib_link_set_entry_t *ls_elt = NULL, *ls_tmp = NULL;
|
||||
iib_link_set_entry_t *matching_lt = NULL;
|
||||
nhdp_addr_entry_t *lt_elt = NULL;
|
||||
timex_t v_time, l_hold;
|
||||
uint8_t matches = 0;
|
||||
|
||||
/* Loop through every link tuple of the interface to update the link set */
|
||||
LL_FOREACH_SAFE(base_entry->link_set_head, ls_elt, ls_tmp) {
|
||||
/* Loop through all addresses of the link tuple */
|
||||
LL_FOREACH(ls_elt->address_list_head, lt_elt) {
|
||||
if (NHDP_ADDR_TMP_IN_SEND_LIST(lt_elt->address)) {
|
||||
/* If link tuple address matches a sending addr we found a fitting tuple */
|
||||
matches++;
|
||||
|
||||
if (matches > 1) {
|
||||
/* Multiple matching link tuples, delete the previous one */
|
||||
if (matching_lt->last_status == IIB_LT_STATUS_SYM) {
|
||||
update_nb_tuple_symmetry(base_entry, matching_lt, now);
|
||||
}
|
||||
|
||||
rem_link_set_entry(base_entry, matching_lt);
|
||||
}
|
||||
|
||||
matching_lt = ls_elt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matches > 1) {
|
||||
/* Multiple matching link tuples, reset the last one for reuse */
|
||||
if (matching_lt->last_status == IIB_LT_STATUS_SYM) {
|
||||
update_nb_tuple_symmetry(base_entry, matching_lt, now);
|
||||
}
|
||||
|
||||
reset_link_set_entry(matching_lt, now, val_time);
|
||||
}
|
||||
else if (matches == 1) {
|
||||
/* A single matching link tuple, only release the address list */
|
||||
release_link_tuple_addresses(matching_lt);
|
||||
}
|
||||
else {
|
||||
/* No single matching link tuple existent, create a new one */
|
||||
matching_lt = add_default_link_set_entry(base_entry, now, val_time);
|
||||
|
||||
if (!matching_lt) {
|
||||
/* Insufficient memory */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
v_time = timex_from_uint64(val_time * US_PER_MS);
|
||||
l_hold = timex_from_uint64(((uint64_t)NHDP_L_HOLD_TIME_MS) * US_PER_MS);
|
||||
|
||||
/* Set Sending Address List as this tuples address list */
|
||||
matching_lt->address_list_head = nhdp_generate_addr_list_from_tmp(NHDP_ADDR_TMP_SEND_LIST);
|
||||
|
||||
if (!matching_lt->address_list_head) {
|
||||
/* Insufficient memory */
|
||||
rem_link_set_entry(base_entry, matching_lt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
matching_lt->nb_elt = nb_elt;
|
||||
|
||||
/* Set values dependent on link status */
|
||||
if (sym) {
|
||||
if (matching_lt->last_status != IIB_LT_STATUS_SYM) {
|
||||
/* Set corresponding neighbor tuple to symmetric (Section 13.1 of RFC 6130) */
|
||||
if (matching_lt->nb_elt) {
|
||||
nib_set_nb_entry_sym(matching_lt->nb_elt);
|
||||
}
|
||||
}
|
||||
|
||||
matching_lt->sym_time = timex_add(*now, v_time);
|
||||
matching_lt->last_status = IIB_LT_STATUS_SYM;
|
||||
}
|
||||
else if (lost) {
|
||||
matching_lt->sym_time.microseconds = 0;
|
||||
matching_lt->sym_time.seconds = 0;
|
||||
|
||||
if (matching_lt->last_status == IIB_LT_STATUS_SYM) {
|
||||
update_nb_tuple_symmetry(base_entry, matching_lt, now);
|
||||
}
|
||||
|
||||
if (get_tuple_status(matching_lt, now) == IIB_LT_STATUS_HEARD) {
|
||||
matching_lt->last_status = IIB_LT_STATUS_HEARD;
|
||||
matching_lt->exp_time = timex_add(*now, l_hold);
|
||||
}
|
||||
else {
|
||||
matching_lt->last_status = IIB_LT_STATUS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set time values */
|
||||
matching_lt->heard_time = get_max_timex(timex_add(*now, v_time), matching_lt->sym_time);
|
||||
|
||||
if (matching_lt->pending) {
|
||||
/* L_status is PENDING */
|
||||
matching_lt->exp_time = get_max_timex(matching_lt->exp_time, matching_lt->heard_time);
|
||||
}
|
||||
else if (!matching_lt->lost) {
|
||||
if ((timex_cmp(matching_lt->sym_time, *now) == 1)
|
||||
|| (timex_cmp(matching_lt->heard_time, *now) == 1)) {
|
||||
/* L_status is HEARD or SYMMETRIC */
|
||||
matching_lt->exp_time = get_max_timex(matching_lt->exp_time,
|
||||
timex_add(matching_lt->heard_time, l_hold));
|
||||
}
|
||||
}
|
||||
|
||||
return matching_lt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the status of a link tuple and process necessary changes and execute
|
||||
* necessary changes in the 2-Hop Set and in the Neighbor Information Base
|
||||
* Implements logic of Section 13 of RFC 6130
|
||||
*/
|
||||
static void wr_update_ls_status(iib_base_entry_t *base_entry,
|
||||
iib_link_set_entry_t *ls_elt, timex_t *now)
|
||||
{
|
||||
if (timex_cmp(ls_elt->exp_time, *now) != 1) {
|
||||
/* Entry expired and has to be removed */
|
||||
if (ls_elt->last_status == IIB_LT_STATUS_SYM) {
|
||||
update_nb_tuple_symmetry(base_entry, ls_elt, now);
|
||||
}
|
||||
|
||||
rem_not_heard_nb_tuple(ls_elt, now);
|
||||
rem_link_set_entry(base_entry, ls_elt);
|
||||
}
|
||||
else if ((ls_elt->last_status == IIB_LT_STATUS_SYM)
|
||||
&& (timex_cmp(ls_elt->sym_time, *now) != 1)) {
|
||||
/* Status changed from SYMMETRIC to HEARD */
|
||||
update_nb_tuple_symmetry(base_entry, ls_elt, now);
|
||||
ls_elt->last_status = IIB_LT_STATUS_HEARD;
|
||||
|
||||
if (timex_cmp(ls_elt->heard_time, *now) != 1) {
|
||||
/* New status is LOST (equals IIB_LT_STATUS_UNKNOWN) */
|
||||
rem_not_heard_nb_tuple(ls_elt, now);
|
||||
ls_elt->nb_elt = NULL;
|
||||
ls_elt->last_status = IIB_LT_STATUS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
else if ((ls_elt->last_status == IIB_LT_STATUS_HEARD)
|
||||
&& (timex_cmp(ls_elt->heard_time, *now) != 1)) {
|
||||
/* Status changed from HEARD to LOST (equals IIB_LT_STATUS_UNKNOWN) */
|
||||
rem_not_heard_nb_tuple(ls_elt, now);
|
||||
ls_elt->nb_elt = NULL;
|
||||
ls_elt->last_status = IIB_LT_STATUS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Link Tuple with default values to the given Link Set
|
||||
*/
|
||||
static iib_link_set_entry_t *add_default_link_set_entry(iib_base_entry_t *base_entry, timex_t *now,
|
||||
uint64_t val_time)
|
||||
{
|
||||
iib_link_set_entry_t *new_entry;
|
||||
|
||||
new_entry = (iib_link_set_entry_t *) malloc(sizeof(iib_link_set_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_entry->address_list_head = NULL;
|
||||
reset_link_set_entry(new_entry, now, val_time);
|
||||
LL_PREPEND(base_entry->link_set_head, new_entry);
|
||||
|
||||
return new_entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset a given Link Tuple for reusage
|
||||
*/
|
||||
static void reset_link_set_entry(iib_link_set_entry_t *ls_entry, timex_t *now, uint64_t val_time)
|
||||
{
|
||||
timex_t v_time = timex_from_uint64(val_time * US_PER_MS);
|
||||
|
||||
release_link_tuple_addresses(ls_entry);
|
||||
ls_entry->sym_time.microseconds = 0;
|
||||
ls_entry->sym_time.seconds = 0;
|
||||
ls_entry->heard_time.microseconds = 0;
|
||||
ls_entry->heard_time.seconds = 0;
|
||||
ls_entry->pending = NHDP_INITIAL_PENDING;
|
||||
ls_entry->lost = 0;
|
||||
ls_entry->exp_time = timex_add(*now, v_time);
|
||||
ls_entry->nb_elt = NULL;
|
||||
ls_entry->last_status = IIB_LT_STATUS_UNKNOWN;
|
||||
ls_entry->metric_in = NHDP_METRIC_UNKNOWN;
|
||||
ls_entry->metric_out = NHDP_METRIC_UNKNOWN;
|
||||
#if (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
memset(ls_entry->dat_received, 0, NHDP_Q_MEM_LENGTH);
|
||||
memset(ls_entry->dat_total, 0, NHDP_Q_MEM_LENGTH);
|
||||
ls_entry->dat_time.microseconds = 0;
|
||||
ls_entry->dat_time.seconds = 0;
|
||||
ls_entry->hello_interval = 0;
|
||||
ls_entry->lost_hellos = 0;
|
||||
ls_entry->rx_bitrate = 100000;
|
||||
ls_entry->last_seq_no = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given Link Tuple
|
||||
*/
|
||||
static void rem_link_set_entry(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry)
|
||||
{
|
||||
LL_DELETE(base_entry->link_set_head, ls_entry);
|
||||
release_link_tuple_addresses(ls_entry);
|
||||
free(ls_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free all address entries of a link tuple
|
||||
*/
|
||||
static void release_link_tuple_addresses(iib_link_set_entry_t *ls_entry)
|
||||
{
|
||||
nhdp_free_addr_list(ls_entry->address_list_head);
|
||||
ls_entry->address_list_head = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the 2-Hop Set during HELLO message processing
|
||||
*/
|
||||
static int update_two_hop_set(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry,
|
||||
timex_t *now, uint64_t val_time)
|
||||
{
|
||||
/* Check whether a corresponding link tuple was created */
|
||||
if (ls_entry == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If the link to the neighbor is still symmetric */
|
||||
if (get_tuple_status(ls_entry, now) == IIB_LT_STATUS_SYM) {
|
||||
iib_two_hop_set_entry_t *ths_elt = NULL, *ths_tmp = NULL;
|
||||
nhdp_addr_t *addr_elt = NULL;
|
||||
|
||||
/* Loop through all the two hop tuples of the two hop set */
|
||||
LL_FOREACH_SAFE(base_entry->two_hop_set_head, ths_elt, ths_tmp) {
|
||||
if (timex_cmp(ths_elt->exp_time, *now) != 1) {
|
||||
/* Entry is expired, remove it */
|
||||
rem_two_hop_entry(base_entry, ths_elt);
|
||||
}
|
||||
else if (ths_elt->ls_elt == ls_entry) {
|
||||
if (ths_elt->th_nb_addr->in_tmp_table &
|
||||
(NHDP_ADDR_TMP_TH_REM_LIST | NHDP_ADDR_TMP_TH_SYM_LIST)) {
|
||||
rem_two_hop_entry(base_entry, ths_elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add a new entry for every signaled symmetric neighbor address */
|
||||
LL_FOREACH(nhdp_get_addr_db_head(), addr_elt) {
|
||||
if (NHDP_ADDR_TMP_IN_TH_SYM_LIST(addr_elt)) {
|
||||
if (add_two_hop_entry(base_entry, ls_entry, addr_elt, now, val_time)) {
|
||||
/* No more memory available, return error */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a 2-Hop Tuple for a given address
|
||||
*/
|
||||
static int add_two_hop_entry(iib_base_entry_t *base_entry, iib_link_set_entry_t *ls_entry,
|
||||
nhdp_addr_t *th_addr, timex_t *now, uint64_t val_time)
|
||||
{
|
||||
iib_two_hop_set_entry_t *new_entry;
|
||||
timex_t v_time = timex_from_uint64(val_time * US_PER_MS);
|
||||
|
||||
new_entry = (iib_two_hop_set_entry_t *) malloc(sizeof(iib_two_hop_set_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Increment usage counter of address in central NHDP address storage */
|
||||
th_addr->usg_count++;
|
||||
new_entry->th_nb_addr = th_addr;
|
||||
new_entry->ls_elt = ls_entry;
|
||||
new_entry->exp_time = timex_add(*now, v_time);
|
||||
if (th_addr->tmp_metric_val != NHDP_METRIC_UNKNOWN) {
|
||||
new_entry->metric_in = rfc5444_metric_decode(th_addr->tmp_metric_val);
|
||||
new_entry->metric_out = rfc5444_metric_decode(th_addr->tmp_metric_val);
|
||||
}
|
||||
else {
|
||||
new_entry->metric_in = NHDP_METRIC_UNKNOWN;
|
||||
new_entry->metric_out = NHDP_METRIC_UNKNOWN;
|
||||
}
|
||||
|
||||
LL_PREPEND(base_entry->two_hop_set_head, new_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given 2-Hop Tuple
|
||||
*/
|
||||
static void rem_two_hop_entry(iib_base_entry_t *base_entry, iib_two_hop_set_entry_t *th_entry)
|
||||
{
|
||||
LL_DELETE(base_entry->two_hop_set_head, th_entry);
|
||||
nhdp_decrement_addr_usage(th_entry->th_nb_addr);
|
||||
free(th_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all corresponding two hop entries for a given link tuple that lost symmetry status.
|
||||
* Additionally reset the neighbor tuple's symmmetry flag (for the neighbor tuple this link
|
||||
* tuple is represented in), if no more corresponding symmetric link tuples are left.
|
||||
* Implements section 13.2 of RFC 6130
|
||||
*/
|
||||
static void update_nb_tuple_symmetry(iib_base_entry_t *base_entry,
|
||||
iib_link_set_entry_t *ls_entry, timex_t *now)
|
||||
{
|
||||
iib_two_hop_set_entry_t *th_elt = NULL, *th_tmp = NULL;
|
||||
|
||||
/* First remove all two hop entries for the corresponding link tuple */
|
||||
LL_FOREACH_SAFE(base_entry->two_hop_set_head, th_elt, th_tmp) {
|
||||
if (th_elt->ls_elt == ls_entry) {
|
||||
rem_two_hop_entry(base_entry, th_elt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Afterwards check the neighbor tuple containing the link tuple's addresses */
|
||||
if ((ls_entry->nb_elt != NULL) && (ls_entry->nb_elt->symmetric == 1)) {
|
||||
iib_base_entry_t *base_tmp = NULL;
|
||||
LL_FOREACH(iib_base_entry_head, base_tmp) {
|
||||
iib_link_set_entry_t *ls_tmp = NULL;
|
||||
LL_FOREACH(base_tmp->link_set_head, ls_tmp) {
|
||||
if ((ls_entry->nb_elt == ls_tmp->nb_elt) && (ls_entry != ls_tmp)) {
|
||||
if (timex_cmp(ls_tmp->sym_time, *now) == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No remaining symmetric link tuple for the neighbor tuple */
|
||||
nib_reset_nb_entry_sym(ls_entry->nb_elt, now);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a neighbor tuple if no more corresponding heard link tuples are left
|
||||
* Implements section 13.3 of RFC 6130
|
||||
*/
|
||||
static void rem_not_heard_nb_tuple(iib_link_set_entry_t *ls_entry, timex_t *now)
|
||||
{
|
||||
/* Check whether the corresponding neighbor tuple still exists */
|
||||
if (ls_entry->nb_elt) {
|
||||
iib_base_entry_t *base_tmp = NULL;
|
||||
LL_FOREACH(iib_base_entry_head, base_tmp) {
|
||||
iib_link_set_entry_t *ls_tmp = NULL;
|
||||
LL_FOREACH(base_tmp->link_set_head, ls_tmp) {
|
||||
if ((ls_entry->nb_elt == ls_tmp->nb_elt) && (ls_entry != ls_tmp)) {
|
||||
if (timex_cmp(ls_tmp->heard_time, *now) == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
ls_tmp->nb_elt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No remaining heard link tuple for the neighbor tuple */
|
||||
nib_rem_nb_entry(ls_entry->nb_elt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the L_STATUS value of a given link tuple
|
||||
*/
|
||||
static iib_link_tuple_status_t get_tuple_status(iib_link_set_entry_t *ls_entry, timex_t *now)
|
||||
{
|
||||
if (ls_entry->pending) {
|
||||
return IIB_LT_STATUS_PENDING;
|
||||
}
|
||||
else if (ls_entry->lost) {
|
||||
return IIB_LT_STATUS_LOST;
|
||||
}
|
||||
else if (timex_cmp(ls_entry->sym_time, *now) == 1) {
|
||||
return IIB_LT_STATUS_SYM;
|
||||
}
|
||||
else if (timex_cmp(ls_entry->heard_time, *now) == 1) {
|
||||
return IIB_LT_STATUS_HEARD;
|
||||
}
|
||||
|
||||
return IIB_LT_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the later one of two timex representation
|
||||
*/
|
||||
static inline timex_t get_max_timex(timex_t time_one, timex_t time_two)
|
||||
{
|
||||
if (timex_cmp(time_one, time_two) != -1) {
|
||||
return time_one;
|
||||
}
|
||||
|
||||
return time_two;
|
||||
}
|
||||
|
||||
#if (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
/**
|
||||
* Sum all elements in the queue
|
||||
*/
|
||||
static uint16_t queue_sum(uint8_t *queue)
|
||||
{
|
||||
uint16_t sum = 0;
|
||||
|
||||
for (int i = 0; i < NHDP_Q_MEM_LENGTH; i++) {
|
||||
sum += queue[i];
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the oldest element in the queue
|
||||
*/
|
||||
static void queue_rem(uint8_t *queue)
|
||||
{
|
||||
uint8_t temp;
|
||||
uint8_t prev_value = queue[0];
|
||||
|
||||
/* Clear spot for a new element */
|
||||
queue[0] = 0;
|
||||
|
||||
/* Shift elements */
|
||||
for (int i = 1; i < NHDP_Q_MEM_LENGTH; i++) {
|
||||
temp = queue[i];
|
||||
queue[i] = prev_value;
|
||||
prev_value = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update DAT metric values for all Link Tuples
|
||||
*/
|
||||
static void dat_metric_refresh(void)
|
||||
{
|
||||
iib_base_entry_t *base_elt = NULL;
|
||||
iib_link_set_entry_t *ls_elt;
|
||||
uint32_t metric_temp;
|
||||
double sum_total, sum_rcvd, loss;
|
||||
|
||||
LL_FOREACH(iib_base_entry_head, base_elt) {
|
||||
LL_FOREACH(base_elt->link_set_head, ls_elt) {
|
||||
sum_rcvd = queue_sum(ls_elt->dat_received);
|
||||
sum_total = queue_sum(ls_elt->dat_total);
|
||||
metric_temp = ls_elt->metric_in;
|
||||
|
||||
if ((ls_elt->hello_interval != 0) && (ls_elt->lost_hellos > 0)) {
|
||||
/* Compute lost time proportion */
|
||||
loss = (((double)ls_elt->hello_interval) * ((double)ls_elt->lost_hellos))
|
||||
/ DAT_MEMORY_LENGTH;
|
||||
if (loss >= 1.0) {
|
||||
sum_rcvd = 0.0;
|
||||
}
|
||||
else {
|
||||
sum_rcvd *= (1.0 - loss);
|
||||
}
|
||||
}
|
||||
|
||||
if (sum_rcvd < 1.0) {
|
||||
ls_elt->metric_in = NHDP_METRIC_MAXIMUM;
|
||||
}
|
||||
else {
|
||||
loss = sum_total / sum_rcvd;
|
||||
if (loss > DAT_MAXIMUM_LOSS) {
|
||||
loss = DAT_MAXIMUM_LOSS;
|
||||
}
|
||||
ls_elt->metric_in = (const_dat * loss) / (ls_elt->rx_bitrate / DAT_MINIMUM_BITRATE);
|
||||
if (ls_elt->metric_in > NHDP_METRIC_MAXIMUM) {
|
||||
ls_elt->metric_in = NHDP_METRIC_MAXIMUM;
|
||||
}
|
||||
}
|
||||
|
||||
if (ls_elt->nb_elt) {
|
||||
if (ls_elt->metric_in <= ls_elt->nb_elt->metric_in ||
|
||||
(ls_elt->nb_elt->metric_in == NHDP_METRIC_UNKNOWN)) {
|
||||
/* Better value, use it also for your neighbor */
|
||||
ls_elt->nb_elt->metric_in = ls_elt->metric_in;
|
||||
}
|
||||
else if (metric_temp == ls_elt->nb_elt->metric_in){
|
||||
/* The corresponding neighbor tuples metric needs to be updated */
|
||||
iib_base_entry_t *base_entry;
|
||||
iib_link_set_entry_t *ls_entry;
|
||||
ls_elt->nb_elt->metric_in = ls_elt->metric_in;
|
||||
LL_FOREACH(iib_base_entry_head, base_entry) {
|
||||
LL_FOREACH(base_entry->link_set_head, ls_entry) {
|
||||
if ((ls_elt->nb_elt == ls_entry->nb_elt) && (ls_elt != ls_entry)) {
|
||||
if (ls_entry->metric_in < ls_elt->nb_elt->metric_in) {
|
||||
/* Smaller DAT value is better */
|
||||
ls_elt->nb_elt->metric_in = ls_entry->metric_in;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
queue_rem(ls_elt->dat_received);
|
||||
queue_rem(ls_elt->dat_total);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Interface Information Base interface for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef IIB_TABLE_H
|
||||
#define IIB_TABLE_H
|
||||
|
||||
#include "timex.h"
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "nib_table.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_metric.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Possible L_STATUS values of a link tuple
|
||||
*/
|
||||
typedef enum {
|
||||
IIB_LT_STATUS_PENDING,
|
||||
IIB_LT_STATUS_LOST,
|
||||
IIB_LT_STATUS_HEARD,
|
||||
IIB_LT_STATUS_SYM,
|
||||
IIB_LT_STATUS_UNKNOWN
|
||||
} iib_link_tuple_status_t;
|
||||
|
||||
/**
|
||||
* @brief Link Set entry (link tuple)
|
||||
*/
|
||||
typedef struct iib_link_set_entry {
|
||||
nhdp_addr_entry_t *address_list_head; /**< Pointer to head of this tuple's addresses */
|
||||
timex_t heard_time; /**< Time at which entry leaves heard status */
|
||||
timex_t sym_time; /**< Time at which entry leaves symmetry status */
|
||||
uint8_t pending; /**< Flag whether link is pending */
|
||||
uint8_t lost; /**< Flag whether link is lost */
|
||||
timex_t exp_time; /**< Time at which entry expires */
|
||||
nib_entry_t *nb_elt; /**< Pointer to corresponding nb tuple */
|
||||
iib_link_tuple_status_t last_status; /**< Last processed status of link tuple */
|
||||
uint32_t metric_in; /**< Metric value for incoming link */
|
||||
uint32_t metric_out; /**< Metric value for outgoing link */
|
||||
#if (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
uint8_t dat_received[NHDP_Q_MEM_LENGTH]; /**< Queue for containing sums of rcvd packets */
|
||||
uint8_t dat_total[NHDP_Q_MEM_LENGTH]; /**< Queue for containing sums of xpctd packets */
|
||||
timex_t dat_time; /**< Time next HELLO is expected */
|
||||
uint8_t hello_interval; /**< Encoded HELLO interval value */
|
||||
uint8_t lost_hellos; /**< Lost HELLO count after last received HELLO */
|
||||
uint32_t rx_bitrate; /**< Incoming Bitrate for this link in Bit/s */
|
||||
uint16_t last_seq_no; /**< The last received packet sequence number */
|
||||
#endif
|
||||
struct iib_link_set_entry *next; /**< Pointer to next list entry */
|
||||
} iib_link_set_entry_t;
|
||||
|
||||
/**
|
||||
* @brief 2-Hop Set entry (2-Hop tuple)
|
||||
*/
|
||||
typedef struct iib_two_hop_set_entry {
|
||||
iib_link_set_entry_t *ls_elt; /**< Pointer to corresponding link tuple */
|
||||
nhdp_addr_t *th_nb_addr; /**< Address of symmetric 2-hop neighbor */
|
||||
timex_t exp_time; /**< Time at which entry expires */
|
||||
uint32_t metric_in; /**< Metric value for incoming link */
|
||||
uint32_t metric_out; /**< Metric value for outgoing link */
|
||||
struct iib_two_hop_set_entry *next; /**< Pointer to next list entry */
|
||||
} iib_two_hop_set_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Link set for a registered interface
|
||||
*/
|
||||
typedef struct iib_base_entry {
|
||||
kernel_pid_t if_pid; /**< PID of the interface */
|
||||
iib_link_set_entry_t *link_set_head; /**< Pointer to this if's link tuples */
|
||||
iib_two_hop_set_entry_t *two_hop_set_head; /**< Pointer to this if's 2-hop tuples */
|
||||
struct iib_base_entry *next; /**< Pointer to next list entry */
|
||||
} iib_base_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Register a new interface in the IIB
|
||||
*
|
||||
* This function creates a new empty Link Set and a new empty 2-Hop Set for the
|
||||
* given interface.
|
||||
*
|
||||
* @param[in] pid PID of the interface
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
*/
|
||||
int iib_register_if(kernel_pid_t pid);
|
||||
|
||||
/**
|
||||
* @brief Process a received HELLO message in the IIB
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP reader's message processing.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface the message was received on
|
||||
* @param[in] nb_elt Pointer to the Neighbor Tuple for the message originator
|
||||
* @param[in] validity_time Validity time in milliseconds for the originator's information
|
||||
* @param[in] is_sym_nb Flag whether the link to the originator is symmetric
|
||||
* @param[in] is_lost Flag whether the originator marked this link as lost
|
||||
*
|
||||
* @return Pointer to the new or updated Link Tuple
|
||||
* @return NULL on error
|
||||
*/
|
||||
iib_link_set_entry_t *iib_process_hello(kernel_pid_t if_pid, nib_entry_t *nb_elt,
|
||||
uint64_t validity_time, uint8_t is_sym_nb,
|
||||
uint8_t is_lost);
|
||||
|
||||
/**
|
||||
* @brief Add addresses to the currently constructed HELLO message
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP writer's message creation process.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface the message is constructed for
|
||||
* @param[in] wr The NHDP writer used for message construction
|
||||
*/
|
||||
void iib_fill_wr_addresses(kernel_pid_t if_pid, struct rfc5444_writer *wr);
|
||||
|
||||
/**
|
||||
* @brief Update L_STATUS of all existing Link Tuples
|
||||
*
|
||||
* @note
|
||||
* If a status change appears the steps described in section 13 of RFC 6130 are executed.
|
||||
*
|
||||
* @param[in] now Pointer to current time timex representation
|
||||
*/
|
||||
void iib_update_lt_status(timex_t *now);
|
||||
|
||||
/**
|
||||
* @brief Exchange the corresponding Neighbor Tuple of existing Link Tuples
|
||||
*
|
||||
* This function exchanges the corresponding Neighbor Tuple of every Link Tuple that
|
||||
* was assigned to old_entry. Primarily used on Neighbor Tuple deletion of old_entry.
|
||||
*
|
||||
* @param[in] old_entry Pointer to the old corresponding Neighbor Tuple
|
||||
* @param[in] new_entry Pointer to the new corresponding Neighbor Tuple
|
||||
*/
|
||||
void iib_propagate_nb_entry_change(nib_entry_t *old_entry, nib_entry_t *new_entry);
|
||||
|
||||
/**
|
||||
* @brief Process steps for the chosen NHDP metric for a message
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP reader's message processing.
|
||||
*
|
||||
* @param[in] ls_entry Pointer to the Link Tuple that needs to be updated
|
||||
* @param[in] int_time Interval time in milliseconds for the originator's HELLO
|
||||
*/
|
||||
void iib_process_metric_msg(iib_link_set_entry_t *ls_entry, uint64_t int_time);
|
||||
|
||||
/**
|
||||
* @brief Process steps for the chosen NHDP metric for a packet
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP reader's packet processing.
|
||||
*
|
||||
* @param[in] ls_entry Pointer to the Link Tuple that needs to be updated
|
||||
* @param[in] metric_out Metric value for outgoing link direction
|
||||
* @param[in] seq_no The sequence number from the received packet
|
||||
*/
|
||||
void iib_process_metric_pckt(iib_link_set_entry_t *ls_entry, uint32_t metric_out, uint16_t seq_no);
|
||||
|
||||
/**
|
||||
* @brief Update metric values for the chosen NHDP metric for all Link Tuples
|
||||
*/
|
||||
void iib_process_metric_refresh(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IIB_TABLE_H */
|
||||
/** @} */
|
@ -1,211 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Local Information Base implementation for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "mutex.h"
|
||||
#include "utlist.h"
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "lib_table.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_writer.h"
|
||||
|
||||
/* Internal variables */
|
||||
static mutex_t mtx_lib_access = MUTEX_INIT;
|
||||
static lib_entry_t *lib_entry_head = NULL;
|
||||
|
||||
/* Internal function prototypes */
|
||||
static int create_if_entry(kernel_pid_t if_pid, nhdp_addr_t *addr);
|
||||
static int add_address_to_if(lib_entry_t *if_entry, nhdp_addr_t *addr);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* Local Information Base API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
int lib_add_if_addr(kernel_pid_t if_pid, nhdp_addr_t *addr)
|
||||
{
|
||||
lib_entry_t *lib_elt = NULL;
|
||||
nhdp_addr_entry_t *addr_elt = NULL;
|
||||
int result = -1;
|
||||
|
||||
mutex_lock(&mtx_lib_access);
|
||||
|
||||
/* Check whether the given interface is already registered */
|
||||
LL_FOREACH(lib_entry_head, lib_elt) {
|
||||
if (lib_elt->if_pid == if_pid) {
|
||||
LL_FOREACH(lib_entry_head->if_addr_list_head, addr_elt) {
|
||||
if (addr_elt->address == addr) {
|
||||
/* Address already known for the interface */
|
||||
result = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
/* Existing interface entry, but new address */
|
||||
result = add_address_to_if(lib_elt, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
/* New interface, create a lib entry */
|
||||
result = create_if_entry(if_pid, addr);
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_lib_access);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lib_rem_if(kernel_pid_t if_pid)
|
||||
{
|
||||
lib_entry_t *lib_elt = NULL, *lib_tmp = NULL;
|
||||
|
||||
mutex_lock(&mtx_lib_access);
|
||||
|
||||
LL_FOREACH_SAFE(lib_entry_head, lib_elt, lib_tmp) {
|
||||
if (lib_elt->if_pid == if_pid) {
|
||||
nhdp_free_addr_list(lib_elt->if_addr_list_head);
|
||||
LL_DELETE(lib_entry_head, lib_elt);
|
||||
free(lib_elt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_lib_access);
|
||||
}
|
||||
|
||||
void lib_fill_wr_addresses(kernel_pid_t if_pid, struct rfc5444_writer *wr)
|
||||
{
|
||||
lib_entry_t *lib_elt = NULL;
|
||||
nhdp_addr_entry_t *add_tmp = NULL;
|
||||
|
||||
mutex_lock(&mtx_lib_access);
|
||||
|
||||
/* First fill the list for LOCAL_IF = THIS_IF */
|
||||
LL_FOREACH(lib_entry_head, lib_elt) {
|
||||
if (lib_elt->if_pid == if_pid) {
|
||||
LL_FOREACH(lib_elt->if_addr_list_head, add_tmp) {
|
||||
nhdp_writer_add_addr(wr, add_tmp->address,
|
||||
RFC5444_ADDRTLV_LOCAL_IF, RFC5444_LOCALIF_THIS_IF,
|
||||
NHDP_METRIC_UNKNOWN, NHDP_METRIC_UNKNOWN);
|
||||
add_tmp->address->in_tmp_table = NHDP_ADDR_TMP_ANY;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Second fill the list for LOCAL_IF = OTHER_IF */
|
||||
LL_FOREACH(lib_entry_head, lib_elt) {
|
||||
if (lib_elt->if_pid != if_pid) {
|
||||
LL_FOREACH(lib_elt->if_addr_list_head, add_tmp) {
|
||||
/* Check if this address is not already included in a list */
|
||||
if (!NHDP_ADDR_TMP_IN_ANY(add_tmp->address)) {
|
||||
/* Address can be added */
|
||||
nhdp_writer_add_addr(wr, add_tmp->address,
|
||||
RFC5444_ADDRTLV_LOCAL_IF, RFC5444_LOCALIF_OTHER_IF,
|
||||
NHDP_METRIC_UNKNOWN, NHDP_METRIC_UNKNOWN);
|
||||
add_tmp->address->in_tmp_table = NHDP_ADDR_TMP_ANY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_lib_access);
|
||||
}
|
||||
|
||||
uint8_t lib_is_reg_addr(kernel_pid_t if_pid, nhdp_addr_t *addr)
|
||||
{
|
||||
lib_entry_t *lib_elt = NULL;
|
||||
nhdp_addr_entry_t *addr_elt = NULL;
|
||||
|
||||
LL_FOREACH(lib_entry_head, lib_elt) {
|
||||
LL_FOREACH(lib_elt->if_addr_list_head, addr_elt) {
|
||||
if (addr_elt->address == addr) {
|
||||
if (lib_elt->if_pid == if_pid) {
|
||||
/* Given address is assigned to the given IF */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Given address is assigned to any other IF */
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Create an entry for a newly registered interface
|
||||
*/
|
||||
static int create_if_entry(kernel_pid_t if_pid, nhdp_addr_t *addr)
|
||||
{
|
||||
lib_entry_t *new_entry;
|
||||
|
||||
new_entry = (lib_entry_t *) malloc(sizeof(lib_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_entry->if_addr_list_head = NULL;
|
||||
new_entry->if_pid = if_pid;
|
||||
|
||||
if (add_address_to_if(new_entry, addr)) {
|
||||
/* Insufficient memory */
|
||||
free(new_entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LL_PREPEND(lib_entry_head, new_entry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add another address to an interface entry
|
||||
*/
|
||||
static int add_address_to_if(lib_entry_t *if_entry, nhdp_addr_t *addr)
|
||||
{
|
||||
nhdp_addr_entry_t *new_entry = (nhdp_addr_entry_t *) malloc(sizeof(nhdp_addr_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Increment usage counter of address in central NHDP address storage */
|
||||
addr->usg_count++;
|
||||
new_entry->address = addr;
|
||||
LL_PREPEND(if_entry->if_addr_list_head, new_entry);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Local Information Base interface for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef LIB_TABLE_H
|
||||
#define LIB_TABLE_H
|
||||
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "nhdp_address.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Local Interface Set entry (local interface tuple)
|
||||
*/
|
||||
typedef struct lib_entry {
|
||||
kernel_pid_t if_pid; /**< PID of the interface's handling thread */
|
||||
nhdp_addr_entry_t *if_addr_list_head; /**< Pointer to head of this interface's addr list */
|
||||
struct lib_entry *next; /**< Pointer to next list entry */
|
||||
} lib_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Add an interface to the Local Information Base
|
||||
*
|
||||
* This function can also be used to add an additional address to an existing LIB tuple.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface
|
||||
* @param[in] addr The (additional) NHDP address to register for the interface
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
*/
|
||||
int lib_add_if_addr(kernel_pid_t if_pid, nhdp_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Remove a given interface's Local Information Base entry
|
||||
*
|
||||
* @param[in] if_pid PID of the interface that should be removed
|
||||
*/
|
||||
void lib_rem_if(kernel_pid_t if_pid);
|
||||
|
||||
/**
|
||||
* @brief Add addresses to the currently constructed HELLO message
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP writer's message creation process.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface the message is constructed for
|
||||
* @param[in] wr The NHDP writer used for message construction
|
||||
*/
|
||||
void lib_fill_wr_addresses(kernel_pid_t if_pid, struct rfc5444_writer *wr);
|
||||
|
||||
/**
|
||||
* @brief Check whether a given NHDP address is used as a local address
|
||||
*
|
||||
* @param[in] if_pid PID of the interface to check for
|
||||
* @param[in] addr Pointer to the NHDP address that has to be checked
|
||||
*
|
||||
* @return 1 if the given address is assigned to the given interface
|
||||
* @return 2 if the given address is assigned to any other local interface
|
||||
* @return 0 otherwise
|
||||
*/
|
||||
uint8_t lib_is_reg_addr(kernel_pid_t if_pid, nhdp_addr_t *addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIB_TABLE_H */
|
||||
/** @} */
|
@ -1,337 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Implementation of NHDP's core functionality
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "net/sock/udp.h"
|
||||
#include "msg.h"
|
||||
#include "net/gnrc/netapi.h"
|
||||
#include "thread.h"
|
||||
#include "utlist.h"
|
||||
#include "mutex.h"
|
||||
#include "net/ipv6/addr.h"
|
||||
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "lib_table.h"
|
||||
#include "iib_table.h"
|
||||
#include "nib_table.h"
|
||||
#include "nhdp.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_writer.h"
|
||||
#include "nhdp_reader.h"
|
||||
|
||||
#define HELLO_TIMER (12345)
|
||||
|
||||
char nhdp_stack[NHDP_STACK_SIZE];
|
||||
char nhdp_rcv_stack[NHDP_STACK_SIZE];
|
||||
|
||||
/* Internal variables */
|
||||
static kernel_pid_t nhdp_pid = KERNEL_PID_UNDEF;
|
||||
static kernel_pid_t nhdp_rcv_pid = KERNEL_PID_UNDEF;
|
||||
static kernel_pid_t helper_pid = KERNEL_PID_UNDEF;
|
||||
static nhdp_if_entry_t nhdp_if_table[GNRC_NETIF_NUMOF];
|
||||
static mutex_t send_rcv_mutex = MUTEX_INIT;
|
||||
static sock_udp_t sock;
|
||||
|
||||
#if (NHDP_METRIC_NEEDS_TIMER)
|
||||
static xtimer_t metric_timer;
|
||||
static timex_t metric_interval;
|
||||
static msg_t metric_msg;
|
||||
#endif
|
||||
|
||||
/* Internal function prototypes */
|
||||
static void *_nhdp_runner(void *arg __attribute__((unused)));
|
||||
static void *_nhdp_receiver(void *arg __attribute__((unused)));
|
||||
static void write_packet(struct rfc5444_writer *wr __attribute__((unused)),
|
||||
struct rfc5444_writer_target *iface __attribute__((unused)),
|
||||
void *buffer, size_t length);
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* NHDP Core API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
void nhdp_init(void)
|
||||
{
|
||||
if (nhdp_pid != KERNEL_PID_UNDEF) {
|
||||
/* do not initialize twice */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Prepare interface table */
|
||||
for (int i = 0; i < GNRC_NETIF_NUMOF; i++) {
|
||||
nhdp_if_table[i].if_pid = KERNEL_PID_UNDEF;
|
||||
memset(&nhdp_if_table[i].wr_target, 0, sizeof(struct rfc5444_writer_target));
|
||||
}
|
||||
|
||||
/* Initialize reader and writer */
|
||||
nhdp_writer_init();
|
||||
nhdp_reader_init();
|
||||
}
|
||||
|
||||
kernel_pid_t nhdp_start(void)
|
||||
{
|
||||
if (nhdp_pid == KERNEL_PID_UNDEF) {
|
||||
/* Init destination address for NHDP's packets */
|
||||
|
||||
/* Start the NHDP thread */
|
||||
nhdp_pid = thread_create(nhdp_stack, sizeof(nhdp_stack), THREAD_PRIORITY_MAIN - 1,
|
||||
THREAD_CREATE_STACKTEST, _nhdp_runner, NULL, "NHDP");
|
||||
|
||||
#if (NHDP_METRIC_NEEDS_TIMER)
|
||||
/* Configure periodic timer message to refresh metric values */
|
||||
if (nhdp_pid != KERNEL_PID_UNDEF) {
|
||||
metric_interval = timex_from_uint64(DAT_REFRESH_INTERVAL * US_PER_SEC);
|
||||
metric_msg.type = NHDP_METRIC_TIMER;
|
||||
metric_msg.content.ptr = NULL;
|
||||
xtimer_set_msg64(&metric_timer, timex_uint64(metric_interval),
|
||||
metric_msg, nhdp_pid);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return nhdp_pid;
|
||||
}
|
||||
|
||||
int nhdp_register_if_default(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size,
|
||||
uint8_t addr_type, uint16_t max_pl_size)
|
||||
{
|
||||
return nhdp_register_if(if_pid, addr, addr_size, addr_type, max_pl_size,
|
||||
NHDP_DEFAULT_HELLO_INT_MS, NHDP_DEFAULT_HOLD_TIME_MS);
|
||||
}
|
||||
|
||||
int nhdp_register_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type,
|
||||
uint16_t max_pl_size, uint16_t hello_int_ms, uint16_t val_time_ms)
|
||||
{
|
||||
nhdp_if_entry_t *if_entry = NULL;
|
||||
nhdp_addr_t *nhdp_addr;
|
||||
msg_t signal_msg;
|
||||
|
||||
if (nhdp_rcv_pid != KERNEL_PID_UNDEF) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < GNRC_NETIF_NUMOF; i++) {
|
||||
if (nhdp_if_table[i].if_pid == KERNEL_PID_UNDEF) {
|
||||
if_entry = &nhdp_if_table[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!if_entry) {
|
||||
/* Maximum number of registerable interfaces reached */
|
||||
return -2;
|
||||
}
|
||||
|
||||
uint16_t payload_size = max_pl_size > NHDP_MAX_RFC5444_PACKET_SZ
|
||||
? NHDP_MAX_RFC5444_PACKET_SZ : max_pl_size;
|
||||
if_entry->wr_target.packet_buffer = (uint8_t *) calloc(payload_size, sizeof(uint8_t));
|
||||
|
||||
if (!if_entry->wr_target.packet_buffer) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if_entry->wr_target.packet_size = payload_size;
|
||||
if_entry->wr_target.sendPacket = write_packet;
|
||||
|
||||
/* Get NHDP address entry for the given address */
|
||||
nhdp_addr = nhdp_addr_db_get_address(addr, addr_size, addr_type);
|
||||
|
||||
if (!nhdp_addr) {
|
||||
/* Insufficient memory */
|
||||
free(if_entry->wr_target.packet_buffer);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add the interface to the LIB */
|
||||
if (lib_add_if_addr(if_pid, nhdp_addr) != 0) {
|
||||
free(if_entry->wr_target.packet_buffer);
|
||||
nhdp_decrement_addr_usage(nhdp_addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Create new IIB for the interface */
|
||||
if (iib_register_if(if_pid) != 0) {
|
||||
/* TODO: Cleanup lib entry */
|
||||
free(if_entry->wr_target.packet_buffer);
|
||||
nhdp_decrement_addr_usage(nhdp_addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set Interface's PID */
|
||||
if_entry->if_pid = if_pid;
|
||||
/* Set HELLO_INTERVAL and H_HOLD_TIME (validity time) */
|
||||
if_entry->hello_interval.seconds = 0;
|
||||
if_entry->hello_interval.microseconds = US_PER_MS * hello_int_ms;
|
||||
if_entry->validity_time.seconds = 0;
|
||||
if_entry->validity_time.microseconds = US_PER_MS * val_time_ms;
|
||||
timex_normalize(&if_entry->hello_interval);
|
||||
timex_normalize(&if_entry->validity_time);
|
||||
/* Reset sequence number */
|
||||
if_entry->seq_no = 0;
|
||||
|
||||
/* Everything went well */
|
||||
nhdp_decrement_addr_usage(nhdp_addr);
|
||||
nhdp_writer_register_if(&if_entry->wr_target);
|
||||
helper_pid = if_pid;
|
||||
|
||||
/* Start the receiving thread */
|
||||
nhdp_rcv_pid = thread_create(nhdp_rcv_stack, sizeof(nhdp_rcv_stack), THREAD_PRIORITY_MAIN - 1,
|
||||
THREAD_CREATE_STACKTEST, _nhdp_receiver, NULL, "nhdp_rcv_thread");
|
||||
|
||||
/* Start sending periodic HELLO */
|
||||
signal_msg.type = HELLO_TIMER;
|
||||
signal_msg.content.ptr = if_entry;
|
||||
/* TODO: msg_send or msg_try_send? */
|
||||
msg_try_send(&signal_msg, nhdp_pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nhdp_register_non_manet_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size,
|
||||
uint8_t addr_type)
|
||||
{
|
||||
return nhdp_add_address(if_pid, addr, addr_size, addr_type);
|
||||
}
|
||||
|
||||
int nhdp_add_address(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type)
|
||||
{
|
||||
int result;
|
||||
|
||||
/* Get NHDP address entry for the given address */
|
||||
nhdp_addr_t *nhdp_addr = nhdp_addr_db_get_address(addr, addr_size, addr_type);
|
||||
|
||||
if (!nhdp_addr) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
result = lib_add_if_addr(if_pid, nhdp_addr);
|
||||
nhdp_decrement_addr_usage(nhdp_addr);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Function executed by NHDP thread receiving messages in an endless loop
|
||||
*/
|
||||
static void *_nhdp_runner(void *arg)
|
||||
{
|
||||
nhdp_if_entry_t *if_entry;
|
||||
msg_t msg_rcvd, msg_queue[NHDP_MSG_QUEUE_SIZE];
|
||||
|
||||
(void)arg;
|
||||
msg_init_queue(msg_queue, NHDP_MSG_QUEUE_SIZE);
|
||||
|
||||
while (1) {
|
||||
msg_receive(&msg_rcvd);
|
||||
|
||||
switch (msg_rcvd.type) {
|
||||
case HELLO_TIMER:
|
||||
mutex_lock(&send_rcv_mutex);
|
||||
if_entry = msg_rcvd.content.ptr;
|
||||
|
||||
nhdp_writer_send_hello(if_entry);
|
||||
|
||||
/* TODO: Add jitter */
|
||||
|
||||
/* Schedule next sending */
|
||||
xtimer_set_msg64(&if_entry->if_timer,
|
||||
timex_uint64(if_entry->hello_interval),
|
||||
&msg_rcvd, thread_getpid());
|
||||
mutex_unlock(&send_rcv_mutex);
|
||||
break;
|
||||
|
||||
#if (NHDP_METRIC_NEEDS_TIMER)
|
||||
case NHDP_METRIC_TIMER:
|
||||
mutex_lock(&send_rcv_mutex);
|
||||
/* Process necessary metric computations */
|
||||
iib_process_metric_refresh();
|
||||
|
||||
/* Schedule next sending */
|
||||
metric_msg.type = NHDP_METRIC_TIMER;
|
||||
metric_msg.content.ptr = NULL;
|
||||
xtimer_set_msg64(&metric_timer, timex_uint64(metric_interval),
|
||||
metric_msg, thread_getpid());
|
||||
mutex_unlock(&send_rcv_mutex);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receive HELLOs over the configured socket and handle them
|
||||
*/
|
||||
static void *_nhdp_receiver(void *arg __attribute__((unused)))
|
||||
{
|
||||
static const sock_udp_ep_t ep = { .family = AF_INET6,
|
||||
.netif = SOCK_ADDR_ANY_NETIF,
|
||||
.port = MANET_PORT };
|
||||
char nhdp_rcv_buf[NHDP_MAX_RFC5444_PACKET_SZ];
|
||||
msg_t msg_q[NHDP_MSG_QUEUE_SIZE];
|
||||
|
||||
msg_init_queue(msg_q, NHDP_MSG_QUEUE_SIZE);
|
||||
|
||||
/* Bind UDP socket to socket address */
|
||||
if (sock_udp_create(&sock, &ep, NULL, 0) < 0) {
|
||||
/* Failed creating the connection */
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int32_t rcv_size = sock_udp_recv(&sock, (void *)nhdp_rcv_buf,
|
||||
NHDP_MAX_RFC5444_PACKET_SZ,
|
||||
SOCK_NO_TIMEOUT, NULL);
|
||||
|
||||
if (rcv_size > 0) {
|
||||
/* Packet received, let the reader handle it */
|
||||
mutex_lock(&send_rcv_mutex);
|
||||
nhdp_reader_handle_packet(helper_pid, (void *)nhdp_rcv_buf, rcv_size);
|
||||
mutex_unlock(&send_rcv_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
sock_udp_close(&sock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send packet for the registered interface
|
||||
* Called by oonf_api to send packet over the configured socket
|
||||
*/
|
||||
static void write_packet(struct rfc5444_writer *wr __attribute__((unused)),
|
||||
struct rfc5444_writer_target *iface __attribute__((unused)),
|
||||
void *buffer, size_t length)
|
||||
{
|
||||
sock_udp_ep_t ep = { .family = AF_INET6, .netif = SOCK_ADDR_ANY_NETIF,
|
||||
.port = MANET_PORT };
|
||||
memcpy(ep.addr.ipv6, &ipv6_addr_all_nodes_link_local, sizeof(ep.addr.ipv6));
|
||||
sock_udp_send(&sock, buffer, length, &ep);
|
||||
}
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup nhdp NHDP
|
||||
* @ingroup net
|
||||
* @deprecated Unmaintained for nearly 5 years and uncertain if it still
|
||||
* works; will be removed after the 2020.04 release.
|
||||
* @brief The MANET Neighborhood Discovery Protocol (RFC 6130)
|
||||
* @deprecated Unmaintained for 5 years and uncertain if it still works.
|
||||
* Will be removed after the 2020.04 release.
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Interface for core functionality of NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NHDP_H
|
||||
#define NHDP_H
|
||||
|
||||
#include "timex.h"
|
||||
#include "xtimer.h"
|
||||
#include "kernel_types.h"
|
||||
|
||||
#include "nhdp_metric.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief Definition for RIOTs debugging option */
|
||||
#define ENABLE_DEBUG (0)
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* @name NHDP protocol macros
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#ifndef MANET_PORT
|
||||
/** @brief Well-known MANET port from RFC 5498 */
|
||||
#define MANET_PORT (269)
|
||||
#endif
|
||||
|
||||
/** @brief Stack size for NHDP thread */
|
||||
#if ENABLE_DEBUG
|
||||
#define NHDP_STACK_SIZE (THREAD_STACKSIZE_DEFAULT + THREAD_EXTRA_STACKSIZE_PRINTF)
|
||||
#else
|
||||
#define NHDP_STACK_SIZE (THREAD_STACKSIZE_DEFAULT)
|
||||
#endif
|
||||
|
||||
/** @brief Buffer size in bytes for NHDP writer's msg buffer */
|
||||
#define NHDP_WR_MSG_BUF_SIZE (256)
|
||||
/** @brief Buffer size in bytes for NHDP writer's tlv buffer */
|
||||
#define NHDP_WR_TLV_BUF_SIZE (512)
|
||||
|
||||
/* TODO: Determine a good value */
|
||||
/** @brief Queue size for msg queue of NHDP */
|
||||
#define NHDP_MSG_QUEUE_SIZE (16)
|
||||
|
||||
/** @brief Maximum size of handled RFC5444 packets */
|
||||
#define NHDP_MAX_RFC5444_PACKET_SZ (128)
|
||||
|
||||
/** @brief Default hello interval in milliseconds */
|
||||
#define NHDP_DEFAULT_HELLO_INT_MS (2000)
|
||||
/** @brief Default hold time in milliseconds */
|
||||
#define NHDP_DEFAULT_HOLD_TIME_MS (3 * NHDP_DEFAULT_HELLO_INT_MS)
|
||||
|
||||
/**
|
||||
* @brief Initial pending flag value for new link tuples
|
||||
*
|
||||
* Do not change (link quality currently not considered)
|
||||
*/
|
||||
#define NHDP_INITIAL_PENDING (0)
|
||||
|
||||
/** @brief Maximum jitter for nhdp messages in milliseconds */
|
||||
#define NHDP_HP_MAXJITTER_MS (200)
|
||||
|
||||
#define NHDP_L_HOLD_TIME_MS (NHDP_DEFAULT_HOLD_TIME_MS)
|
||||
#define NHDP_N_HOLD_TIME_MS (NHDP_DEFAULT_HOLD_TIME_MS)
|
||||
#define NHDP_I_HOLD_TIME_MS (NHDP_DEFAULT_HOLD_TIME_MS)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief MANET interface representation
|
||||
*/
|
||||
typedef struct {
|
||||
kernel_pid_t if_pid; /**< PID of the interface's handling thread */
|
||||
xtimer_t if_timer; /**< xtimer used for the periodic signaling */
|
||||
timex_t hello_interval; /**< Interval time for periodic HELLOs */
|
||||
timex_t validity_time; /**< Validity time for propagated information */
|
||||
uint16_t seq_no; /**< Sequence number of last send RFC5444 packet */
|
||||
struct rfc5444_writer_target wr_target; /**< Interface specific writer target */
|
||||
} nhdp_if_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Additional address types for link layer operation
|
||||
*/
|
||||
enum nhdp_address_type_t {
|
||||
AF_CC110X = AF_MAX + 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize NHDP for operation
|
||||
*
|
||||
* Sets up NHDP's reader and writer. Call first before starting NHDP's thread
|
||||
* and registering interfaces.
|
||||
*/
|
||||
void nhdp_init(void) __attribute__
|
||||
((deprecated("The nhdp module will be removed after 2020.04")));
|
||||
|
||||
/**
|
||||
* @brief Start NHDP's operational thread
|
||||
*
|
||||
* @return PID of NHDP's operational thread
|
||||
* @return KERNEL_PID_UNDEF on error
|
||||
*/
|
||||
kernel_pid_t nhdp_start(void);
|
||||
|
||||
/**
|
||||
* @brief Register an interface for NHDP operation with default values
|
||||
*
|
||||
* Registers the interface completely for NHDP operation. Registration includes a new
|
||||
* Local Information Base entry, a new Interface Information Base and starting
|
||||
* the periodical HELLO messaging.
|
||||
*
|
||||
* @note
|
||||
* Default values are a hello interval of 2 seconds and a validity time
|
||||
* of 6 seconds for propagated information.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface
|
||||
* @param[in] addr A local address of this interface represented in bytes
|
||||
* @param[in] addr_size Length in bytes of the local address
|
||||
* @param[in] addr_type AF type of the local address
|
||||
* @param[in] max_pl_size Maximum payload size for packets send over this interface
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
* @return -2 on maximum number of interfaces registered
|
||||
*/
|
||||
int nhdp_register_if_default(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size,
|
||||
uint8_t addr_type, uint16_t max_pl_size);
|
||||
|
||||
/**
|
||||
* @brief Register an interface for NHDP operation
|
||||
*
|
||||
* Registers the interface completely for NHDP operation. Registration includes a new
|
||||
* Local Information Base entry, a new Interface Information Base and starting
|
||||
* the periodical HELLO messaging.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface
|
||||
* @param[in] addr A local address of this interface represented in bytes
|
||||
* @param[in] addr_size Length of the local address (number of bytes)
|
||||
* @param[in] addr_type AF type of the given address
|
||||
* @param[in] max_pl_size Maximum payload size for packets send over this interface
|
||||
* @param[in] hello_int_ms Hello interval in ms for periodic message generation
|
||||
* @param[in] val_time_ms Validity time in ms for propagated information
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
* @return -2 on maximum number of interfaces registered
|
||||
*/
|
||||
int nhdp_register_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type,
|
||||
uint16_t max_pl_size, uint16_t hello_int_ms, uint16_t val_time_ms);
|
||||
|
||||
/**
|
||||
* @brief Register a non MANET interface in NHDP
|
||||
*
|
||||
* The registered interface does not take part in NHDP operation. Its addresses
|
||||
* will be represented only in other interfaces' messages. No periodical messages
|
||||
* are created for this interface and no message processing is done.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface
|
||||
* @param[in] addr A local address of this interface represented in bytes
|
||||
* @param[in] addr_size Length of the local address (number of bytes)
|
||||
* @param[in] addr_type AF type of the given address
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
*/
|
||||
int nhdp_register_non_manet_if(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size,
|
||||
uint8_t addr_type);
|
||||
|
||||
/**
|
||||
* @brief Register an additional address for an interface in NHDP
|
||||
*
|
||||
* The address is added to the Local Information Base entry of this interface and
|
||||
* will afterwards be propagated as a local address in newly created HELLO messages.
|
||||
*
|
||||
* @param[in] if_pid PID of the interface
|
||||
* @param[in] addr Additional local address of this interface represented in bytes
|
||||
* @param[in] addr_size Length of the local address (number of bytes)
|
||||
* @param[in] addr_type AF type of the given address
|
||||
*
|
||||
* @return 0 on success
|
||||
* @return -1 on error
|
||||
*/
|
||||
int nhdp_add_address(kernel_pid_t if_pid, uint8_t *addr, size_t addr_size, uint8_t addr_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NHDP_H */
|
||||
/** @} */
|
@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Centralized address storage implementation for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "mutex.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "nhdp.h"
|
||||
#include "nhdp_address.h"
|
||||
|
||||
/* Internal variables */
|
||||
static mutex_t mtx_addr_access = MUTEX_INIT;
|
||||
static nhdp_addr_t *nhdp_addr_db_head = NULL;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* Centralized Address Storage API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
nhdp_addr_t *nhdp_addr_db_get_address(uint8_t *addr, size_t addr_size, uint8_t addr_type)
|
||||
{
|
||||
nhdp_addr_t *addr_elt = NULL;
|
||||
|
||||
mutex_lock(&mtx_addr_access);
|
||||
|
||||
LL_FOREACH(nhdp_addr_db_head, addr_elt) {
|
||||
if ((addr_elt->addr_size == addr_size) && (addr_elt->addr_type == addr_type)) {
|
||||
if (memcmp(addr_elt->addr, addr, addr_size) == 0) {
|
||||
/* Found a matching entry */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!addr_elt) {
|
||||
/* No matching entry, create a new one */
|
||||
addr_elt = (nhdp_addr_t *) malloc(sizeof(nhdp_addr_t));
|
||||
|
||||
if (!addr_elt) {
|
||||
/* Insufficient memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Allocate space for the address */
|
||||
addr_elt->addr = (uint8_t *) malloc(addr_size * sizeof(uint8_t));
|
||||
|
||||
if (!addr_elt->addr) {
|
||||
/* Insufficient memory */
|
||||
free(addr_elt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(addr_elt->addr, addr, addr_size);
|
||||
addr_elt->addr_size = addr_size;
|
||||
addr_elt->addr_type = addr_type;
|
||||
addr_elt->usg_count = 0;
|
||||
addr_elt->in_tmp_table = NHDP_ADDR_TMP_NONE;
|
||||
addr_elt->tmp_metric_val = NHDP_METRIC_UNKNOWN;
|
||||
LL_PREPEND(nhdp_addr_db_head, addr_elt);
|
||||
}
|
||||
|
||||
addr_elt->usg_count++;
|
||||
|
||||
mutex_unlock(&mtx_addr_access);
|
||||
|
||||
return addr_elt;
|
||||
}
|
||||
|
||||
void nhdp_decrement_addr_usage(nhdp_addr_t *addr)
|
||||
{
|
||||
mutex_lock(&mtx_addr_access);
|
||||
|
||||
/* Decrement usage count and delete address if no longer used */
|
||||
if (addr) {
|
||||
addr->usg_count--;
|
||||
if (addr->usg_count == 0) {
|
||||
/* Free address space if address is no longer used */
|
||||
LL_DELETE(nhdp_addr_db_head, addr);
|
||||
free(addr->addr);
|
||||
free(addr);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&mtx_addr_access);
|
||||
}
|
||||
|
||||
void nhdp_free_addr_list(nhdp_addr_entry_t *list_head)
|
||||
{
|
||||
nhdp_addr_entry_t *list_elt = NULL, *list_tmp = NULL;
|
||||
|
||||
LL_FOREACH_SAFE(list_head, list_elt, list_tmp) {
|
||||
nhdp_free_addr_entry(list_elt);
|
||||
}
|
||||
}
|
||||
|
||||
void nhdp_free_addr_entry(nhdp_addr_entry_t *addr_entry)
|
||||
{
|
||||
nhdp_decrement_addr_usage(addr_entry->address);
|
||||
free(addr_entry);
|
||||
}
|
||||
|
||||
nhdp_addr_entry_t *nhdp_generate_addr_list_from_tmp(uint8_t tmp_type)
|
||||
{
|
||||
nhdp_addr_entry_t *new_list_head;
|
||||
nhdp_addr_t *addr_elt = NULL;
|
||||
|
||||
new_list_head = NULL;
|
||||
LL_FOREACH(nhdp_addr_db_head, addr_elt) {
|
||||
if (addr_elt->in_tmp_table & tmp_type) {
|
||||
nhdp_addr_entry_t *new_entry = (nhdp_addr_entry_t *) malloc(sizeof(nhdp_addr_entry_t));
|
||||
|
||||
if (!new_entry) {
|
||||
/* Insufficient memory, free all previously allocated memory */
|
||||
nhdp_free_addr_list(new_list_head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_entry->address = addr_elt;
|
||||
/* Increment usage counter of address in central NHDP address storage */
|
||||
addr_elt->usg_count++;
|
||||
LL_PREPEND(new_list_head, new_entry);
|
||||
}
|
||||
}
|
||||
|
||||
return new_list_head;
|
||||
}
|
||||
|
||||
void nhdp_reset_addresses_tmp_usg(uint8_t decr_usg)
|
||||
{
|
||||
nhdp_addr_t *addr_elt = NULL, *addr_tmp = NULL;
|
||||
|
||||
LL_FOREACH_SAFE(nhdp_addr_db_head, addr_elt, addr_tmp) {
|
||||
addr_elt->tmp_metric_val = NHDP_METRIC_UNKNOWN;
|
||||
if (addr_elt->in_tmp_table) {
|
||||
addr_elt->in_tmp_table = NHDP_ADDR_TMP_NONE;
|
||||
if (decr_usg) {
|
||||
nhdp_decrement_addr_usage(addr_elt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nhdp_addr_t *nhdp_get_addr_db_head(void)
|
||||
{
|
||||
return nhdp_addr_db_head;
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Centralized address storage interface for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NHDP_ADDRESS_H
|
||||
#define NHDP_ADDRESS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief NHDP address representation
|
||||
*/
|
||||
typedef struct nhdp_addr {
|
||||
uint8_t *addr; /**< Pointer to the address data */
|
||||
size_t addr_size; /**< Size in bytes of the address */
|
||||
uint8_t addr_type; /**< AF type for the address */
|
||||
uint8_t usg_count; /**< Usage count in information bases */
|
||||
uint8_t in_tmp_table; /**< Signals usage in a writers temp table */
|
||||
uint16_t tmp_metric_val; /**< Encoded metric value used during HELLO processing */
|
||||
struct nhdp_addr *next; /**< Pointer to next address (used in central storage) */
|
||||
} nhdp_addr_t;
|
||||
|
||||
/**
|
||||
* @brief Container for NHDP address storage in a list
|
||||
*/
|
||||
typedef struct nhdp_addr_entry {
|
||||
struct nhdp_addr *address; /**< Pointer to NHDP address storage entry */
|
||||
struct nhdp_addr_entry *next; /**< Pointer to the next address list element */
|
||||
} nhdp_addr_entry_t;
|
||||
|
||||
/**
|
||||
* @name NHDP address temp usage helper macros
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define NHDP_ADDR_TMP_NONE (0x00)
|
||||
#define NHDP_ADDR_TMP_ANY (0x01)
|
||||
#define NHDP_ADDR_TMP_SYM (0x03)
|
||||
#define NHDP_ADDR_TMP_REM_LIST (0x04)
|
||||
#define NHDP_ADDR_TMP_TH_REM_LIST (0x08)
|
||||
#define NHDP_ADDR_TMP_TH_SYM_LIST (0x10)
|
||||
#define NHDP_ADDR_TMP_NB_LIST (0x20)
|
||||
#define NHDP_ADDR_TMP_SEND_LIST (0x60)
|
||||
|
||||
#define NHDP_ADDR_TMP_IN_ANY(addr) ((addr->in_tmp_table & 0x01))
|
||||
#define NHDP_ADDR_TMP_IN_SYM(addr) ((addr->in_tmp_table & 0x02) >> 1)
|
||||
#define NHDP_ADDR_TMP_IN_REM_LIST(addr) ((addr->in_tmp_table & 0x04) >> 2)
|
||||
#define NHDP_ADDR_TMP_IN_TH_REM_LIST(addr) ((addr->in_tmp_table & 0x08) >> 3)
|
||||
#define NHDP_ADDR_TMP_IN_TH_SYM_LIST(addr) ((addr->in_tmp_table & 0x10) >> 4)
|
||||
#define NHDP_ADDR_TMP_IN_NB_LIST(addr) ((addr->in_tmp_table & 0x20) >> 5)
|
||||
#define NHDP_ADDR_TMP_IN_SEND_LIST(addr) ((addr->in_tmp_table & 0x40) >> 6)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Get or create a NHDP address for the given address
|
||||
*
|
||||
* @param[in] addr Pointer to the given address
|
||||
* @param[in] addr_size Length in bytes of the given address
|
||||
* @param[in] addr_type AF type of the given address
|
||||
*
|
||||
* @return Pointer to the NHDP address representation of the given address
|
||||
* @return NULL on error
|
||||
*/
|
||||
nhdp_addr_t *nhdp_addr_db_get_address(uint8_t *addr, size_t addr_size, uint8_t addr_type);
|
||||
|
||||
/**
|
||||
* @brief Decrement the usage counter of a given NHDP address
|
||||
*
|
||||
* The NHDP address is deleted if the usage counter reaches zero.
|
||||
*
|
||||
* @param[in] addr Pointer to the NHDP address
|
||||
*/
|
||||
void nhdp_decrement_addr_usage(nhdp_addr_t *addr);
|
||||
|
||||
/**
|
||||
* @brief Free the given address list
|
||||
*
|
||||
* This function frees every address list entry of the given address list.
|
||||
*
|
||||
* @param[in] list_head Pointer to the head of the address list to free
|
||||
*/
|
||||
void nhdp_free_addr_list(nhdp_addr_entry_t *list_head);
|
||||
|
||||
/**
|
||||
* @brief Free the given address list entry
|
||||
*
|
||||
* Additionally to freeing the address entry, this function takes care that
|
||||
* the usage counter of the list entry's address is decremented.
|
||||
*
|
||||
* @param[in] addr_entry Pointer to the address list entry to free
|
||||
*/
|
||||
void nhdp_free_addr_entry(nhdp_addr_entry_t *addr_entry);
|
||||
|
||||
/**
|
||||
* @brief Construct an addr list containing all addresses with
|
||||
* the given tmp_type
|
||||
*
|
||||
* @return Pointer to the head of the newly created address list
|
||||
* @return NULL on error
|
||||
*/
|
||||
nhdp_addr_entry_t *nhdp_generate_addr_list_from_tmp(uint8_t tmp_type);
|
||||
|
||||
/**
|
||||
* @brief Reset in_tmp_table flag of all NHDP addresses
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP writer's or reader's message creation process.
|
||||
*
|
||||
* @param[in] decr_usg Flag whether the usage counter of a reset addr has to be decremented
|
||||
*/
|
||||
void nhdp_reset_addresses_tmp_usg(uint8_t decr_usg);
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the head of the address storage list
|
||||
*
|
||||
* @return Pointer to the head of the central storage address list
|
||||
* @return NULL if no addresses are registered
|
||||
*/
|
||||
nhdp_addr_t *nhdp_get_addr_db_head(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NHDP_ADDRESS_H */
|
||||
/** @} */
|
@ -1,93 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Macros for NHDP metric computation
|
||||
*
|
||||
* The used infrastructure for exchanging metric values is based on the rules defined in the RFC
|
||||
* of <a href="https://tools.ietf.org/html/rfc7181">OLSRv2</a>. The calculations for the
|
||||
* Directional Airtime Metric (DAT) are based on
|
||||
* <a href="https://tools.ietf.org/html/draft-ietf-manet-olsrv2-dat-metric-05">DAT Draft v5</a>.
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NHDP_METRIC_H
|
||||
#define NHDP_METRIC_H
|
||||
|
||||
#include "rfc5444/rfc5444.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name NHDP protocol macros
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** @brief Hop Count metric extension value for metric TLV extension field */
|
||||
#define NHDP_LMT_HOP_COUNT (163)
|
||||
/** @brief DAT metric extension value for metric TLV extension field */
|
||||
#define NHDP_LMT_DAT (165)
|
||||
|
||||
/** @brief Used metric (change to switch to another metric type) */
|
||||
#define NHDP_METRIC (NHDP_LMT_HOP_COUNT)
|
||||
|
||||
/** @brief Randomly chosen number for NHDP's metric timer event */
|
||||
#define NHDP_METRIC_TIMER (5445)
|
||||
/** @brief Macro controlling the start of a periodic timer event for matric computation */
|
||||
#define NHDP_METRIC_NEEDS_TIMER (NHDP_METRIC == NHDP_LMT_DAT)
|
||||
|
||||
#define NHDP_METRIC_UNKNOWN (0)
|
||||
#define NHDP_METRIC_MINIMUM (RFC5444_METRIC_MIN)
|
||||
#define NHDP_METRIC_MAXIMUM (RFC5444_METRIC_MAX)
|
||||
|
||||
/** @brief Default queue size for metrics using a queue to determine link loss */
|
||||
#define NHDP_Q_MEM_LENGTH (64)
|
||||
/** @brief Restart detection value for packet sequence number based link loss computation */
|
||||
#define NHDP_SEQNO_RESTART_DETECT (256)
|
||||
|
||||
/** @brief Encoding for an incoming link metric value in metric TLV */
|
||||
#define NHDP_KD_LM_INC (0x8000)
|
||||
/** @brief Encoding for an outgoing link metric value in metric TLV */
|
||||
#define NHDP_KD_LM_OUT (0x4000)
|
||||
/** @brief Encoding for an incoming neighbor metric value in metric TLV */
|
||||
#define NHDP_KD_NM_INC (0x2000)
|
||||
/** @brief Encoding for an outgoing neighbor metric value in metric TLV */
|
||||
#define NHDP_KD_NM_OUT (0x1000)
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name DAT metric specific macros
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** @brief Length of RCVD and TOTAL queue of DAT metric */
|
||||
#define DAT_MEMORY_LENGTH (NHDP_Q_MEM_LENGTH)
|
||||
/** @brief Time between DAT metric refreshal */
|
||||
#define DAT_REFRESH_INTERVAL (1)
|
||||
/** @brief Factor to spread HELLO interval */
|
||||
#define DAT_HELLO_TIMEOUT_FACTOR (1.2)
|
||||
/** @brief Minimal supported bit rate in bps (default value for new links) */
|
||||
#define DAT_MINIMUM_BITRATE (1000)
|
||||
/** @brief Maximum allowed loss in expected/rcvd HELLOs (should not be changed) */
|
||||
#define DAT_MAXIMUM_LOSS (8)
|
||||
/** @brief Constant value needed for DAT metric computation (should not be changed) */
|
||||
#define DAT_CONSTANT (16777216)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NHDP_METRIC_H */
|
@ -1,471 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Reader implementation for message processing in NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "mutex.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "rfc5444/rfc5444.h"
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_reader.h"
|
||||
|
||||
#include "lib_table.h"
|
||||
#include "nib_table.h"
|
||||
#include "iib_table.h"
|
||||
#include "nhdp.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_reader.h"
|
||||
|
||||
/* Internal variables */
|
||||
struct rfc5444_reader reader;
|
||||
static mutex_t mtx_packet_handler = MUTEX_INIT;
|
||||
|
||||
static iib_link_set_entry_t *originator_link_tuple = NULL;
|
||||
static uint32_t lt_metric_val = NHDP_METRIC_UNKNOWN;
|
||||
|
||||
static kernel_pid_t if_pid;
|
||||
static uint64_t val_time;
|
||||
static uint64_t int_time;
|
||||
static uint8_t sym = 0;
|
||||
static uint8_t lost = 0;
|
||||
|
||||
/* Internal function prototypes */
|
||||
static enum rfc5444_result _nhdp_pkt_end_cb(struct rfc5444_reader_tlvblock_context *context,
|
||||
bool dropped);
|
||||
static enum rfc5444_result _nhdp_blocktlv_msg_cb(struct rfc5444_reader_tlvblock_context *cont);
|
||||
static enum rfc5444_result _nhdp_blocktlv_address_cb(struct rfc5444_reader_tlvblock_context *cont);
|
||||
static enum rfc5444_result _nhdp_msg_end_cb(struct rfc5444_reader_tlvblock_context *cont,
|
||||
bool dropped);
|
||||
static enum rfc5444_result check_msg_validity(struct rfc5444_reader_tlvblock_context *cont);
|
||||
static enum rfc5444_result check_addr_validity(nhdp_addr_t *addr);
|
||||
static nhdp_addr_t *get_nhdp_db_addr(uint8_t *addr, uint8_t prefix);
|
||||
static void add_temp_metric_value(nhdp_addr_t *address);
|
||||
static void process_temp_tables(void);
|
||||
|
||||
/* Array containing the processable message TLVs for HELLO messages */
|
||||
static struct rfc5444_reader_tlvblock_consumer_entry _nhdp_msg_tlvs[] = {
|
||||
[RFC5444_MSGTLV_INTERVAL_TIME] = { .type = RFC5444_MSGTLV_INTERVAL_TIME, .mandatory = false },
|
||||
[RFC5444_MSGTLV_VALIDITY_TIME] = { .type = RFC5444_MSGTLV_VALIDITY_TIME, .mandatory = true },
|
||||
};
|
||||
|
||||
/* Array containing the processable address TLVs for HELLO message address blocks */
|
||||
static struct rfc5444_reader_tlvblock_consumer_entry _nhdp_addr_tlvs[] = {
|
||||
[RFC5444_ADDRTLV_LOCAL_IF] = { .type = RFC5444_ADDRTLV_LOCAL_IF },
|
||||
[RFC5444_ADDRTLV_LINK_STATUS] = { .type = RFC5444_ADDRTLV_LINK_STATUS },
|
||||
[RFC5444_ADDRTLV_OTHER_NEIGHB] = { .type = RFC5444_ADDRTLV_OTHER_NEIGHB },
|
||||
[RFC5444_ADDRTLV_LINK_METRIC] = { .type = RFC5444_ADDRTLV_LINK_METRIC, .type_ext = NHDP_METRIC,
|
||||
.match_type_ext = true, .min_length = 0x02,
|
||||
.max_length = 0x02, .match_length = true },
|
||||
};
|
||||
|
||||
/* oonf_api packet consumer used for RFC5444 packet consumption */
|
||||
static struct rfc5444_reader_tlvblock_consumer _nhdp_packet_consumer = {
|
||||
.end_callback = _nhdp_pkt_end_cb,
|
||||
};
|
||||
|
||||
/* oonf_api message consumer used for HELLO message consumption */
|
||||
static struct rfc5444_reader_tlvblock_consumer _nhdp_msg_consumer = {
|
||||
.msg_id = RFC5444_MSGTYPE_HELLO,
|
||||
.block_callback = _nhdp_blocktlv_msg_cb,
|
||||
.end_callback = _nhdp_msg_end_cb,
|
||||
};
|
||||
|
||||
/* oonf_api message consumer user for HELLO message address block consumption */
|
||||
static struct rfc5444_reader_tlvblock_consumer _nhdp_address_consumer = {
|
||||
.msg_id = RFC5444_MSGTYPE_HELLO,
|
||||
.addrblock_consumer = true,
|
||||
.block_callback = _nhdp_blocktlv_address_cb,
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* NHDP Reader API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
void nhdp_reader_init(void)
|
||||
{
|
||||
/* Initialize reader */
|
||||
rfc5444_reader_init(&reader);
|
||||
|
||||
/* Register packet consumer for sequence number processing */
|
||||
rfc5444_reader_add_packet_consumer(&reader, &_nhdp_packet_consumer, NULL, 0);
|
||||
|
||||
/* Register HELLO message consumer */
|
||||
rfc5444_reader_add_message_consumer(&reader, &_nhdp_msg_consumer,
|
||||
_nhdp_msg_tlvs, ARRAY_SIZE(_nhdp_msg_tlvs));
|
||||
rfc5444_reader_add_message_consumer(&reader, &_nhdp_address_consumer,
|
||||
_nhdp_addr_tlvs, ARRAY_SIZE(_nhdp_addr_tlvs));
|
||||
}
|
||||
|
||||
int nhdp_reader_handle_packet(kernel_pid_t rcvg_if_pid, void *buffer, size_t length)
|
||||
{
|
||||
int result;
|
||||
|
||||
mutex_lock(&mtx_packet_handler);
|
||||
|
||||
/* Store PID of interface this packet was received on */
|
||||
if_pid = rcvg_if_pid;
|
||||
/* Parse packet with reader */
|
||||
result = rfc5444_reader_handle_packet(&reader, buffer, length);
|
||||
|
||||
mutex_unlock(&mtx_packet_handler);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void nhdp_reader_cleanup(void)
|
||||
{
|
||||
rfc5444_reader_cleanup(&reader);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Process metric steps for packet with packet sequence number
|
||||
* Called by oonf_api after the whole packet was processed
|
||||
*/
|
||||
static enum rfc5444_result _nhdp_pkt_end_cb(struct rfc5444_reader_tlvblock_context *context,
|
||||
bool dropped __attribute__((unused)))
|
||||
{
|
||||
/* Process metric changes */
|
||||
if ((originator_link_tuple != NULL) && (context->has_pktseqno)) {
|
||||
iib_process_metric_pckt(originator_link_tuple, lt_metric_val, context->pkt_seqno);
|
||||
}
|
||||
|
||||
/* Reset originator temp fields */
|
||||
originator_link_tuple = NULL;
|
||||
lt_metric_val = NHDP_METRIC_UNKNOWN;
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle one address and its corresponding TLVs
|
||||
* Called by oonf_api for every included address to allow parsing
|
||||
*/
|
||||
static enum rfc5444_result
|
||||
_nhdp_blocktlv_address_cb(struct rfc5444_reader_tlvblock_context *cont)
|
||||
{
|
||||
uint8_t tmp_result;
|
||||
|
||||
/* Get NHDP address for the current netaddr */
|
||||
nhdp_addr_t *current_addr = get_nhdp_db_addr(&cont->addr._addr[0], cont->addr._prefix_len);
|
||||
|
||||
if (!current_addr) {
|
||||
/* Insufficient memory */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
/* Check validity of address tlvs */
|
||||
if (check_addr_validity(current_addr) != RFC5444_OKAY) {
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
/* Handle address and add it to proper temporary list */
|
||||
if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv) {
|
||||
switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv->single_value) {
|
||||
case RFC5444_LOCALIF_THIS_IF:
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_SEND_LIST;
|
||||
break;
|
||||
|
||||
case RFC5444_LOCALIF_OTHER_IF:
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_NB_LIST;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Wrong value, drop message */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
}
|
||||
else if ((tmp_result = lib_is_reg_addr(if_pid, current_addr))) {
|
||||
/* The address is one of our local addresses (do not add it for processing) */
|
||||
if ((!sym) && (tmp_result == 1) && _nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv) {
|
||||
/* If address is a local address of the receiving interface, check */
|
||||
/* whether we can derive a status for this link (symmetry or lost) */
|
||||
switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv->single_value) {
|
||||
case RFC5444_LINKSTATUS_SYMMETRIC:
|
||||
/* Fall - through */
|
||||
|
||||
case RFC5444_LINKSTATUS_HEARD:
|
||||
sym = 1;
|
||||
break;
|
||||
|
||||
case RFC5444_LINKSTATUS_LOST:
|
||||
lost = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Wrong value, drop message */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
}
|
||||
|
||||
if (lt_metric_val == NHDP_METRIC_UNKNOWN
|
||||
&& _nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC].tlv != NULL) {
|
||||
/* Determine our outgoing link metric value to the originator interface */
|
||||
uint16_t metric_enc = *((uint16_t*)_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC]
|
||||
.tlv->single_value);
|
||||
if (metric_enc & NHDP_KD_LM_INC) {
|
||||
/* Incoming metric value at the neighbor if is outgoing value for our if */
|
||||
lt_metric_val = rfc5444_metric_decode(metric_enc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Address is one of our own addresses, ignore it */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
}
|
||||
else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv) {
|
||||
switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv->single_value) {
|
||||
case RFC5444_LINKSTATUS_SYMMETRIC:
|
||||
add_temp_metric_value(current_addr);
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
|
||||
break;
|
||||
|
||||
case RFC5444_LINKSTATUS_HEARD:
|
||||
/* Fall-through */
|
||||
|
||||
case RFC5444_LINKSTATUS_LOST:
|
||||
if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv
|
||||
&& *_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv->single_value
|
||||
== RFC5444_OTHERNEIGHB_SYMMETRIC) {
|
||||
/* Symmetric has higher priority */
|
||||
add_temp_metric_value(current_addr);
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
|
||||
}
|
||||
else {
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_REM_LIST;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Wrong value, drop message */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
}
|
||||
else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv) {
|
||||
switch (*_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv->single_value) {
|
||||
case RFC5444_OTHERNEIGHB_SYMMETRIC:
|
||||
add_temp_metric_value(current_addr);
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_SYM_LIST;
|
||||
break;
|
||||
|
||||
case RFC5444_OTHERNEIGHB_LOST:
|
||||
current_addr->in_tmp_table = NHDP_ADDR_TMP_TH_REM_LIST;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Wrong value, drop message */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Addresses without expected TLV are ignored */
|
||||
nhdp_decrement_addr_usage(current_addr);
|
||||
return RFC5444_DROP_ADDRESS;
|
||||
}
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle message TLVs of received HELLO
|
||||
* Called by oonf_api to allow message TLV parsing
|
||||
*/
|
||||
static enum rfc5444_result
|
||||
_nhdp_blocktlv_msg_cb(struct rfc5444_reader_tlvblock_context *cont)
|
||||
{
|
||||
/* Check whether specified message TLVs are correctly included */
|
||||
if (check_msg_validity(cont) != RFC5444_OKAY) {
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
/* Validity time must be included as message tlv */
|
||||
val_time = rfc5444_timetlv_decode(
|
||||
*_nhdp_msg_tlvs[RFC5444_MSGTLV_VALIDITY_TIME].tlv->single_value);
|
||||
|
||||
/* Interval time is not mandatory as message tlv */
|
||||
if (_nhdp_msg_tlvs[RFC5444_MSGTLV_INTERVAL_TIME].tlv) {
|
||||
int_time = rfc5444_timetlv_decode(
|
||||
*_nhdp_msg_tlvs[RFC5444_MSGTLV_INTERVAL_TIME].tlv->single_value);
|
||||
}
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process received addresses and clean up temporary stuff
|
||||
* Called by oonf_api after message was parsed
|
||||
*/
|
||||
static enum rfc5444_result
|
||||
_nhdp_msg_end_cb(struct rfc5444_reader_tlvblock_context *cont __attribute__((unused)),
|
||||
bool dropped)
|
||||
{
|
||||
if (!dropped) {
|
||||
/* Only process the received addresses if message was valid */
|
||||
process_temp_tables();
|
||||
}
|
||||
|
||||
/* Clean all temporary stuff */
|
||||
val_time = 0ULL;
|
||||
int_time = 0ULL;
|
||||
sym = 0;
|
||||
lost = 0;
|
||||
nhdp_reset_addresses_tmp_usg(1);
|
||||
|
||||
if (dropped) {
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validity of HELLO message header and message TLVs
|
||||
*/
|
||||
static enum rfc5444_result check_msg_validity(struct rfc5444_reader_tlvblock_context *cont)
|
||||
{
|
||||
if (cont->has_hoplimit && cont->hoplimit != 1) {
|
||||
/* Hop Limit other than 1 */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
if (cont->has_hopcount && cont->hopcount != 0) {
|
||||
/* Hop Count other than zero */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
if (!(_nhdp_msg_tlvs[RFC5444_MSGTLV_VALIDITY_TIME].tlv)) {
|
||||
/* No validity time tlv */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
else if (_nhdp_msg_tlvs[RFC5444_MSGTLV_VALIDITY_TIME].tlv->next_entry) {
|
||||
/* Multiple validity time tlvs */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
if (_nhdp_msg_tlvs[RFC5444_MSGTLV_INTERVAL_TIME].tlv
|
||||
&& _nhdp_msg_tlvs[RFC5444_MSGTLV_INTERVAL_TIME].tlv->next_entry) {
|
||||
/* Multiple interval time tlvs */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check validity of address block TLVs
|
||||
*/
|
||||
static enum rfc5444_result check_addr_validity(nhdp_addr_t *addr)
|
||||
{
|
||||
if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv) {
|
||||
if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv
|
||||
|| _nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv) {
|
||||
/* Conflicting tlv types for the address */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LOCAL_IF].tlv->next_entry) {
|
||||
/* Multiple tlvs of the same type are not allowed */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
else if (lib_is_reg_addr(if_pid, addr)) {
|
||||
/* Address of one of neighbor's IFs equals one of ours */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
}
|
||||
else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv
|
||||
&& _nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_STATUS].tlv->next_entry) {
|
||||
/* Multiple tlvs of the same type are not allowed */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
else if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv
|
||||
&& _nhdp_addr_tlvs[RFC5444_ADDRTLV_OTHER_NEIGHB].tlv->next_entry) {
|
||||
/* Multiple tlvs of the same type are not allowed */
|
||||
return RFC5444_DROP_MESSAGE;
|
||||
}
|
||||
|
||||
return RFC5444_OKAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a new or existing NHDP address entry from the centralized address storage
|
||||
* for the given address data
|
||||
*/
|
||||
static nhdp_addr_t *get_nhdp_db_addr(uint8_t *addr, uint8_t prefix)
|
||||
{
|
||||
switch (prefix) {
|
||||
case 8:
|
||||
return nhdp_addr_db_get_address(addr, 1, AF_CC110X);
|
||||
|
||||
case 32:
|
||||
return nhdp_addr_db_get_address(addr, 4, AF_INET);
|
||||
|
||||
default:
|
||||
if (prefix < 32) {
|
||||
return nhdp_addr_db_get_address(addr, 4, AF_INET);
|
||||
}
|
||||
else {
|
||||
return nhdp_addr_db_get_address(addr, 16, AF_INET6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a metric value to the address if a corresponding TLV exists in the message
|
||||
*/
|
||||
static void add_temp_metric_value(nhdp_addr_t *address)
|
||||
{
|
||||
if (_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC].tlv) {
|
||||
uint16_t metric_enc = *((uint16_t*)_nhdp_addr_tlvs[RFC5444_ADDRTLV_LINK_METRIC]
|
||||
.tlv->single_value);
|
||||
if (metric_enc & (NHDP_KD_LM_INC | NHDP_KD_NM_INC)) {
|
||||
address->tmp_metric_val = metric_enc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process address lists from the HELLO msg in the information bases
|
||||
*/
|
||||
static void process_temp_tables(void)
|
||||
{
|
||||
nib_entry_t *nib_elt;
|
||||
timex_t now;
|
||||
|
||||
xtimer_now_timex(&now);
|
||||
iib_update_lt_status(&now);
|
||||
|
||||
nib_elt = nib_process_hello();
|
||||
|
||||
if (nib_elt) {
|
||||
originator_link_tuple = iib_process_hello(if_pid, nib_elt, val_time, sym, lost);
|
||||
|
||||
if (originator_link_tuple) {
|
||||
iib_process_metric_msg(originator_link_tuple, int_time != 0 ? int_time : val_time);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Reader interface for message processing in NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NHDP_READER_H
|
||||
#define NHDP_READER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set up the NHDP reader
|
||||
*
|
||||
* Initializes the reader and registers HELLO messages as a message
|
||||
* type consumed by this reader.
|
||||
*/
|
||||
void nhdp_reader_init(void);
|
||||
|
||||
/**
|
||||
* @brief Clean up the NHDP reader
|
||||
*/
|
||||
void nhdp_reader_cleanup(void);
|
||||
|
||||
/**
|
||||
* @brief Handle a packet received from a registered interface
|
||||
*
|
||||
* @note
|
||||
* HELLO message processing is triggered from this function.
|
||||
*
|
||||
* @param[in] rcvg_if_pid PID of the interface the packet was received on
|
||||
* @param[in] buffer Pointer to start of packet data
|
||||
* @param[in] length Length in bytes of the packet data
|
||||
*
|
||||
* @return rfc5444_result of the packet handling process
|
||||
*/
|
||||
int nhdp_reader_handle_packet(kernel_pid_t rcvg_if_pid, void *buffer, size_t length);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NHDP_READER_H */
|
||||
/** @} */
|
@ -1,278 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Writer implementation for message generation in NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "timex.h"
|
||||
#include "mutex.h"
|
||||
|
||||
#include "rfc5444/rfc5444.h"
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "nhdp.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_writer.h"
|
||||
#include "lib_table.h"
|
||||
#include "nib_table.h"
|
||||
#include "iib_table.h"
|
||||
|
||||
/* Internal variables */
|
||||
static mutex_t mtx_packet_write = MUTEX_INIT;
|
||||
static struct rfc5444_writer nhdp_writer;
|
||||
static nhdp_if_entry_t *nhdp_wr_curr_if_entry;
|
||||
static uint8_t msg_buffer[NHDP_WR_MSG_BUF_SIZE];
|
||||
static uint8_t msg_addrtlvs[NHDP_WR_TLV_BUF_SIZE];
|
||||
|
||||
/* Internal function prototypes */
|
||||
static void _nhdp_add_hello_msg_header_cb(struct rfc5444_writer *wr,
|
||||
struct rfc5444_writer_message *msg);
|
||||
static void _nhdp_add_message_tlvs_cb(struct rfc5444_writer *wr);
|
||||
static void _nhdp_add_addresses_cb(struct rfc5444_writer *wr);
|
||||
static void _nhdp_add_packet_header_cb(struct rfc5444_writer *writer,
|
||||
struct rfc5444_writer_target *rfc5444_target);
|
||||
static void netaddr_from_nhdp_address(struct netaddr *target, nhdp_addr_t *n_addr);
|
||||
|
||||
/* Array containing the known Address TLVs */
|
||||
static struct rfc5444_writer_tlvtype _nhdp_addrtlvs[] = {
|
||||
[RFC5444_ADDRTLV_LOCAL_IF] = { .type = RFC5444_ADDRTLV_LOCAL_IF },
|
||||
[RFC5444_ADDRTLV_LINK_STATUS] = { .type = RFC5444_ADDRTLV_LINK_STATUS },
|
||||
[RFC5444_ADDRTLV_OTHER_NEIGHB] = { .type = RFC5444_ADDRTLV_OTHER_NEIGHB },
|
||||
[RFC5444_ADDRTLV_LINK_METRIC] = { .type = RFC5444_ADDRTLV_LINK_METRIC, .exttype = NHDP_METRIC }
|
||||
};
|
||||
|
||||
/* Writer content provider for HELLO messages */
|
||||
static struct rfc5444_writer_content_provider _nhdp_message_content_provider = {
|
||||
.msg_type = RFC5444_MSGTYPE_HELLO,
|
||||
.addMessageTLVs = _nhdp_add_message_tlvs_cb,
|
||||
.addAddresses = _nhdp_add_addresses_cb,
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* NHDP Writer API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
void nhdp_writer_init(void)
|
||||
{
|
||||
struct rfc5444_writer_message *_hello_msg;
|
||||
|
||||
mutex_lock(&mtx_packet_write);
|
||||
|
||||
/* Reset current interface */
|
||||
nhdp_wr_curr_if_entry = NULL;
|
||||
|
||||
/* Configure NHDP writer */
|
||||
nhdp_writer.msg_buffer = msg_buffer;
|
||||
nhdp_writer.msg_size = sizeof(msg_buffer);
|
||||
nhdp_writer.addrtlv_buffer = msg_addrtlvs;
|
||||
nhdp_writer.addrtlv_size = sizeof(msg_addrtlvs);
|
||||
|
||||
/* Initialize writer */
|
||||
rfc5444_writer_init(&nhdp_writer);
|
||||
|
||||
/* Register HELLO msg with 16 byte addresses and content provider */
|
||||
rfc5444_writer_register_msgcontentprovider(&nhdp_writer,
|
||||
&_nhdp_message_content_provider, _nhdp_addrtlvs, ARRAY_SIZE(_nhdp_addrtlvs));
|
||||
_hello_msg = rfc5444_writer_register_message(&nhdp_writer, RFC5444_MSGTYPE_HELLO, false, 16);
|
||||
_hello_msg->addMessageHeader = _nhdp_add_hello_msg_header_cb;
|
||||
|
||||
mutex_unlock(&mtx_packet_write);
|
||||
}
|
||||
|
||||
void nhdp_writer_cleanup(void)
|
||||
{
|
||||
mutex_lock(&mtx_packet_write);
|
||||
|
||||
nhdp_wr_curr_if_entry = NULL;
|
||||
rfc5444_writer_cleanup(&nhdp_writer);
|
||||
|
||||
mutex_unlock(&mtx_packet_write);
|
||||
}
|
||||
|
||||
void nhdp_writer_register_if(struct rfc5444_writer_target *new_if)
|
||||
{
|
||||
mutex_lock(&mtx_packet_write);
|
||||
|
||||
/* Add packet header callback to writer target of the interface */
|
||||
new_if->addPacketHeader = _nhdp_add_packet_header_cb;
|
||||
/* Register target interface in writer */
|
||||
rfc5444_writer_register_target(&nhdp_writer, new_if);
|
||||
|
||||
mutex_unlock(&mtx_packet_write);
|
||||
}
|
||||
|
||||
void nhdp_writer_send_hello(nhdp_if_entry_t *if_entry)
|
||||
{
|
||||
mutex_lock(&mtx_packet_write);
|
||||
|
||||
/* Register interface as current sending interface */
|
||||
nhdp_wr_curr_if_entry = if_entry;
|
||||
|
||||
/* Create HELLO message and send it using the given interface */
|
||||
rfc5444_writer_create_message(&nhdp_writer, RFC5444_MSGTYPE_HELLO,
|
||||
rfc5444_writer_singletarget_selector, &if_entry->wr_target);
|
||||
rfc5444_writer_flush(&nhdp_writer, &if_entry->wr_target, false);
|
||||
|
||||
mutex_unlock(&mtx_packet_write);
|
||||
}
|
||||
|
||||
void nhdp_writer_add_addr(struct rfc5444_writer *wr, nhdp_addr_t *addr,
|
||||
enum rfc5444_addrtlv_iana type, uint8_t value,
|
||||
uint16_t metric_in, uint16_t metric_out)
|
||||
{
|
||||
struct rfc5444_writer_address *wr_addr;
|
||||
struct netaddr n_addr;
|
||||
|
||||
netaddr_from_nhdp_address(&n_addr, addr);
|
||||
|
||||
switch (type) {
|
||||
case RFC5444_ADDRTLV_LOCAL_IF:
|
||||
/* Address is mandatory for every sub-msg (if message is split) */
|
||||
wr_addr = rfc5444_writer_add_address(wr, _nhdp_message_content_provider.creator,
|
||||
&n_addr, true);
|
||||
break;
|
||||
|
||||
case RFC5444_ADDRTLV_LINK_STATUS:
|
||||
/* Fall through */
|
||||
|
||||
case RFC5444_ADDRTLV_OTHER_NEIGHB:
|
||||
/* Address only has to be included in one sub-msg (if message is split) */
|
||||
wr_addr = rfc5444_writer_add_address(wr, _nhdp_message_content_provider.creator,
|
||||
&n_addr, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown type, extend switch if other types are allowed */
|
||||
return;
|
||||
}
|
||||
|
||||
rfc5444_writer_add_addrtlv(wr, wr_addr, &_nhdp_addrtlvs[type],
|
||||
&value, sizeof(uint8_t), false);
|
||||
|
||||
/* Add LINK_METRIC TLV if necessary */
|
||||
if ((NHDP_METRIC == NHDP_LMT_DAT) && (metric_in != NHDP_METRIC_UNKNOWN)) {
|
||||
switch(type) {
|
||||
case RFC5444_ADDRTLV_LINK_STATUS:
|
||||
metric_in |= NHDP_KD_LM_INC;
|
||||
metric_in |= (metric_in == metric_out) ? NHDP_KD_LM_OUT : 0x00;
|
||||
break;
|
||||
case RFC5444_ADDRTLV_OTHER_NEIGHB:
|
||||
metric_in |= NHDP_KD_NM_INC;
|
||||
metric_in |= (metric_in == metric_out) ? NHDP_KD_NM_OUT : 0x00;
|
||||
break;
|
||||
default:
|
||||
/* Other types are not used and therefore no address tlv is added */
|
||||
return;
|
||||
}
|
||||
rfc5444_writer_add_addrtlv(wr, wr_addr, &_nhdp_addrtlvs[RFC5444_ADDRTLV_LINK_METRIC],
|
||||
&metric_in, sizeof(metric_in), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Set the header for the currently constructed HELLO message
|
||||
* Called by oonf_api during message creation
|
||||
*/
|
||||
static void
|
||||
_nhdp_add_hello_msg_header_cb(struct rfc5444_writer *wr, struct rfc5444_writer_message *msg)
|
||||
{
|
||||
/* No originator, no hopcount, no hoplimit, no sequence number */
|
||||
rfc5444_writer_set_msg_header(wr, msg, false, false, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add validity time and interval time message TLVs to current message
|
||||
* Called by oonf_api during message creation
|
||||
*/
|
||||
static void _nhdp_add_message_tlvs_cb(struct rfc5444_writer *wr)
|
||||
{
|
||||
uint8_t validity_time, interval_time;
|
||||
/* Convert validity time and interval time to milliseconds */
|
||||
uint64_t val_tmp = (uint64_t) nhdp_wr_curr_if_entry->validity_time.seconds * MS_PER_SEC
|
||||
+ (nhdp_wr_curr_if_entry->validity_time.microseconds / 1000ULL);
|
||||
uint64_t int_tmp = (uint64_t) nhdp_wr_curr_if_entry->hello_interval.seconds * MS_PER_SEC
|
||||
+ (nhdp_wr_curr_if_entry->hello_interval.microseconds / 1000ULL);
|
||||
|
||||
/* Add validity time (mandatory) and interval time to msg */
|
||||
validity_time = rfc5444_timetlv_encode(val_tmp);
|
||||
interval_time = rfc5444_timetlv_encode(int_tmp);
|
||||
rfc5444_writer_add_messagetlv(wr, RFC5444_MSGTLV_VALIDITY_TIME, 0, &validity_time,
|
||||
sizeof(validity_time));
|
||||
rfc5444_writer_add_messagetlv(wr, RFC5444_MSGTLV_INTERVAL_TIME, 0, &interval_time,
|
||||
sizeof(interval_time));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add addresses and corresponding TLVs to current message
|
||||
* Called by oonf_api during message creation
|
||||
*/
|
||||
static void _nhdp_add_addresses_cb(struct rfc5444_writer *wr)
|
||||
{
|
||||
lib_fill_wr_addresses(nhdp_wr_curr_if_entry->if_pid, wr);
|
||||
iib_fill_wr_addresses(nhdp_wr_curr_if_entry->if_pid, wr);
|
||||
nib_fill_wr_addresses(wr);
|
||||
nhdp_reset_addresses_tmp_usg(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add packet header with sequence number to current packet
|
||||
* Called by oonf_api during packet creation
|
||||
*/
|
||||
static void _nhdp_add_packet_header_cb(struct rfc5444_writer *writer,
|
||||
struct rfc5444_writer_target *rfc5444_target)
|
||||
{
|
||||
rfc5444_writer_set_pkt_header(writer, rfc5444_target, true);
|
||||
rfc5444_writer_set_pkt_seqno(writer, rfc5444_target, ++nhdp_wr_curr_if_entry->seq_no);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a netaddr from a given NHDP address
|
||||
*/
|
||||
static void netaddr_from_nhdp_address(struct netaddr *target, nhdp_addr_t *n_addr)
|
||||
{
|
||||
memset(target->_addr, 0, NETADDR_MAX_LENGTH);
|
||||
memcpy(target->_addr, n_addr->addr, n_addr->addr_size);
|
||||
|
||||
switch (n_addr->addr_type) {
|
||||
case AF_CC110X:
|
||||
target->_prefix_len = 8u;
|
||||
target->_type = AF_CC110X;
|
||||
break;
|
||||
|
||||
case AF_INET:
|
||||
target->_prefix_len = 32u;
|
||||
target->_type = AF_INET;
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
/* Fall-through */
|
||||
|
||||
default:
|
||||
target->_prefix_len = 128u;
|
||||
target->_type = AF_INET6;
|
||||
break;
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Writer interface for message generation in NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NHDP_WRITER_H
|
||||
#define NHDP_WRITER_H
|
||||
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "nhdp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set up the NHDP writer
|
||||
*
|
||||
* Sets the writer's buffers, initializes the writer and registers HELLO messages
|
||||
* as new message type.
|
||||
*/
|
||||
void nhdp_writer_init(void);
|
||||
|
||||
/**
|
||||
* @brief Clean up the NHDP writer
|
||||
*/
|
||||
void nhdp_writer_cleanup(void);
|
||||
|
||||
/**
|
||||
* @brief Register a new target interface in the writer
|
||||
*
|
||||
* @param[in] new_if Pointer to the writer target of the NHDP interface entry
|
||||
*/
|
||||
void nhdp_writer_register_if(struct rfc5444_writer_target *new_if);
|
||||
|
||||
/**
|
||||
* @brief Construct and send a HELLO message using the given interface
|
||||
*
|
||||
* @param[in] if_entry Pointer to NHDP interface entry the message must be created for
|
||||
*/
|
||||
void nhdp_writer_send_hello(nhdp_if_entry_t *if_entry);
|
||||
|
||||
/**
|
||||
* @brief Add a NHDP address to the currently constructed message
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP writer's message creation process.
|
||||
*
|
||||
* @param[in] wr Pointer to the current NHDP writer used for message creation
|
||||
* @param[in] addr Pointer to a NHDP address to add to the HELLO message
|
||||
* @param[in] type TLV type for the address
|
||||
* @param[in] value TLV value for the address
|
||||
* @param[in] metric_in Encoded incoming link metric value
|
||||
* @param[in] metric_out Encoded outgoing link metric value
|
||||
*/
|
||||
void nhdp_writer_add_addr(struct rfc5444_writer *wr, nhdp_addr_t *addr,
|
||||
enum rfc5444_addrtlv_iana type, uint8_t value,
|
||||
uint16_t metric_in, uint16_t metric_out);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NHDP_WRITER_H */
|
||||
/** @} */
|
@ -1,312 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Neighbor Information Base implementation for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "timex.h"
|
||||
#include "mutex.h"
|
||||
#include "xtimer.h"
|
||||
#include "utlist.h"
|
||||
|
||||
#include "rfc5444/rfc5444_iana.h"
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "nib_table.h"
|
||||
#include "iib_table.h"
|
||||
#include "nhdp_address.h"
|
||||
#include "nhdp_writer.h"
|
||||
|
||||
/* Internal variables */
|
||||
static mutex_t mtx_nib_access = MUTEX_INIT;
|
||||
static nib_entry_t *nib_entry_head = NULL;
|
||||
static nib_lost_address_entry_t *nib_lost_address_entry_head = NULL;
|
||||
|
||||
/* Internal function prototypes */
|
||||
static nib_entry_t *add_nib_entry_for_nb_addr_list(void);
|
||||
static void rem_nib_entry(nib_entry_t *nib_entry, timex_t *now);
|
||||
static void clear_nb_addresses(nib_entry_t *nib_entry, timex_t *now);
|
||||
static int add_lost_neighbor_address(nhdp_addr_t *lost_addr, timex_t *now);
|
||||
static void rem_ln_entry(nib_lost_address_entry_t *ln_entry);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*
|
||||
* Neighbor Information Base API *
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
nib_entry_t *nib_process_hello(void)
|
||||
{
|
||||
nib_entry_t *nb_match = NULL;
|
||||
nib_entry_t *nib_elt = NULL, *nib_tmp = NULL;
|
||||
timex_t now;
|
||||
uint8_t matches = 0;
|
||||
|
||||
mutex_lock(&mtx_nib_access);
|
||||
|
||||
xtimer_now_timex(&now);
|
||||
|
||||
LL_FOREACH_SAFE(nib_entry_head, nib_elt, nib_tmp) {
|
||||
nhdp_addr_entry_t *list_elt = NULL;
|
||||
LL_FOREACH(nib_elt->address_list_head, list_elt) {
|
||||
if (NHDP_ADDR_TMP_IN_NB_LIST(list_elt->address)) {
|
||||
/* Matching neighbor tuple */
|
||||
matches++;
|
||||
|
||||
if (matches > 1) {
|
||||
/* Multiple matching nb tuples, delete the previous one */
|
||||
iib_propagate_nb_entry_change(nb_match, nib_elt);
|
||||
rem_nib_entry(nb_match, &now);
|
||||
}
|
||||
|
||||
nb_match = nib_elt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add or update nb tuple */
|
||||
if (matches > 0) {
|
||||
/* We found matching nb tuples, reuse the last one */
|
||||
clear_nb_addresses(nb_match, &now);
|
||||
|
||||
if (matches > 1) {
|
||||
nb_match->symmetric = 0;
|
||||
}
|
||||
|
||||
nb_match->address_list_head = nhdp_generate_addr_list_from_tmp(NHDP_ADDR_TMP_NB_LIST);
|
||||
|
||||
if (!nb_match->address_list_head) {
|
||||
/* Insufficient memory */
|
||||
LL_DELETE(nib_entry_head, nb_match);
|
||||
free(nb_match);
|
||||
nb_match = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nb_match = add_nib_entry_for_nb_addr_list();
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_nib_access);
|
||||
return nb_match;
|
||||
}
|
||||
|
||||
void nib_fill_wr_addresses(struct rfc5444_writer *wr)
|
||||
{
|
||||
nib_entry_t *nib_elt = NULL;
|
||||
nhdp_addr_entry_t *addr_elt = NULL;
|
||||
nib_lost_address_entry_t *lost_elt = NULL, *lost_tmp = NULL;
|
||||
timex_t now;
|
||||
|
||||
mutex_lock(&mtx_nib_access);
|
||||
|
||||
xtimer_now_timex(&now);
|
||||
|
||||
/* Add addresses of symmetric neighbors to HELLO msg */
|
||||
LL_FOREACH(nib_entry_head, nib_elt) {
|
||||
if (nib_elt->symmetric) {
|
||||
LL_FOREACH(nib_elt->address_list_head, addr_elt) {
|
||||
/* Check whether address is not already included with link status symmetric */
|
||||
if (!NHDP_ADDR_TMP_IN_SYM(addr_elt->address)) {
|
||||
nhdp_writer_add_addr(wr, addr_elt->address, RFC5444_ADDRTLV_OTHER_NEIGHB,
|
||||
RFC5444_OTHERNEIGHB_SYMMETRIC,
|
||||
rfc5444_metric_encode(nib_elt->metric_in),
|
||||
rfc5444_metric_encode(nib_elt->metric_out));
|
||||
addr_elt->address->in_tmp_table = NHDP_ADDR_TMP_SYM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add lost addresses of neighbors to HELLO msg */
|
||||
LL_FOREACH_SAFE(nib_lost_address_entry_head, lost_elt, lost_tmp) {
|
||||
if (timex_cmp(lost_elt->expiration_time, now) != 1) {
|
||||
/* Entry expired, remove it */
|
||||
rem_ln_entry(lost_elt);
|
||||
}
|
||||
else {
|
||||
/* Check if address is not already present in one of the temporary lists */
|
||||
if (!NHDP_ADDR_TMP_IN_ANY(lost_elt->address)) {
|
||||
/* Address is not present in one of the lists, add it */
|
||||
nhdp_writer_add_addr(wr, lost_elt->address, RFC5444_ADDRTLV_OTHER_NEIGHB,
|
||||
RFC5444_OTHERNEIGHB_LOST, NHDP_METRIC_UNKNOWN,
|
||||
NHDP_METRIC_UNKNOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mtx_nib_access);
|
||||
}
|
||||
|
||||
void nib_rem_nb_entry(nib_entry_t *nib_entry)
|
||||
{
|
||||
nhdp_free_addr_list(nib_entry->address_list_head);
|
||||
LL_DELETE(nib_entry_head, nib_entry);
|
||||
free(nib_entry);
|
||||
}
|
||||
|
||||
void nib_set_nb_entry_sym(nib_entry_t *nib_entry)
|
||||
{
|
||||
nib_lost_address_entry_t *ln_elt = NULL, *ln_tmp = NULL;
|
||||
nhdp_addr_entry_t *nb_elt = NULL;
|
||||
|
||||
nib_entry->symmetric = 1;
|
||||
LL_FOREACH(nib_entry->address_list_head, nb_elt) {
|
||||
LL_FOREACH_SAFE(nib_lost_address_entry_head, ln_elt, ln_tmp) {
|
||||
/* Remove all Lost Neighbor Tuples matching an address of the newly sym nb */
|
||||
if (ln_elt->address == nb_elt->address) {
|
||||
rem_ln_entry(ln_elt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nib_reset_nb_entry_sym(nib_entry_t *nib_entry, timex_t *now)
|
||||
{
|
||||
nhdp_addr_entry_t *nb_elt = NULL;
|
||||
|
||||
nib_entry->symmetric = 0;
|
||||
LL_FOREACH(nib_entry->address_list_head, nb_elt) {
|
||||
/* Add a Lost Neighbor Tuple for each address of the neighbor */
|
||||
if (add_lost_neighbor_address(nb_elt->address, now) == -1) {
|
||||
/* Insufficient memory */
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
/* Internal functions */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Add a Neighbor Tuple for the neighbor address list
|
||||
*/
|
||||
static nib_entry_t *add_nib_entry_for_nb_addr_list(void)
|
||||
{
|
||||
nib_entry_t *new_elem;
|
||||
|
||||
new_elem = malloc(sizeof(nib_entry_t));
|
||||
|
||||
if (!new_elem) {
|
||||
/* Insufficient memory */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy neighbor address list to new neighbor tuple */
|
||||
new_elem->address_list_head = nhdp_generate_addr_list_from_tmp(NHDP_ADDR_TMP_NB_LIST);
|
||||
|
||||
if (!new_elem->address_list_head) {
|
||||
/* Insufficient memory */
|
||||
free(new_elem);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_elem->symmetric = 0;
|
||||
new_elem->metric_in = NHDP_METRIC_UNKNOWN;
|
||||
new_elem->metric_out = NHDP_METRIC_UNKNOWN;
|
||||
LL_PREPEND(nib_entry_head, new_elem);
|
||||
|
||||
return new_elem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given Neighbor Tuple
|
||||
*/
|
||||
static void rem_nib_entry(nib_entry_t *nib_entry, timex_t *now)
|
||||
{
|
||||
clear_nb_addresses(nib_entry, now);
|
||||
LL_DELETE(nib_entry_head, nib_entry);
|
||||
free(nib_entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear address list of a Neighbor Tuple and add Lost Neighbor Tuple for addresses
|
||||
* no longer used by this neighbor
|
||||
*/
|
||||
static void clear_nb_addresses(nib_entry_t *nib_entry, timex_t *now)
|
||||
{
|
||||
nhdp_addr_entry_t *nib_elt = NULL, *nib_tmp = NULL;;
|
||||
|
||||
LL_FOREACH_SAFE(nib_entry->address_list_head, nib_elt, nib_tmp) {
|
||||
/* Check whether address is still present in the new neighbor address list */
|
||||
if (!NHDP_ADDR_TMP_IN_NB_LIST(nib_elt->address)) {
|
||||
/* Address is not in the newly received address list of the neighbor */
|
||||
/* Add it to the Removed Address List */
|
||||
nib_elt->address->in_tmp_table |= NHDP_ADDR_TMP_REM_LIST;
|
||||
/* Increment usage counter of address in central NHDP address storage */
|
||||
nib_elt->address->usg_count++;
|
||||
|
||||
if (nib_entry->symmetric) {
|
||||
/* Additionally create a Lost Neighbor Tuple for symmetric neighbors */
|
||||
add_lost_neighbor_address(nib_elt->address, now);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the address entry */
|
||||
nhdp_free_addr_entry(nib_elt);
|
||||
}
|
||||
nib_entry->address_list_head = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add or update a Lost Neighbor Tuple
|
||||
*/
|
||||
static int add_lost_neighbor_address(nhdp_addr_t *lost_addr, timex_t *now)
|
||||
{
|
||||
nib_lost_address_entry_t *elt = NULL;
|
||||
timex_t n_hold = timex_from_uint64(((uint64_t)NHDP_N_HOLD_TIME_MS) * US_PER_MS);
|
||||
|
||||
LL_FOREACH(nib_lost_address_entry_head, elt) {
|
||||
if (elt->address == lost_addr) {
|
||||
/* Existing entry for this address, no need to add a new one */
|
||||
if (timex_cmp(elt->expiration_time, *now) == -1) {
|
||||
/* Entry expired, so just update expiration time */
|
||||
elt->expiration_time = timex_add(*now, n_hold);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* No existing entry, create a new one */
|
||||
elt = malloc(sizeof(nib_lost_address_entry_t));
|
||||
|
||||
if (!elt) {
|
||||
/* Insufficient memory */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Increment usage counter of address in central NHDP address storage */
|
||||
lost_addr->usg_count++;
|
||||
elt->address = lost_addr;
|
||||
elt->expiration_time = timex_add(*now, n_hold);
|
||||
LL_PREPEND(nib_lost_address_entry_head, elt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a given Lost Neighbor Tuple
|
||||
*/
|
||||
static void rem_ln_entry(nib_lost_address_entry_t *ln_entry)
|
||||
{
|
||||
nhdp_decrement_addr_usage(ln_entry->address);
|
||||
LL_DELETE(nib_lost_address_entry_head, ln_entry);
|
||||
free(ln_entry);
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Freie Universität Berlin
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nhdp
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Neighbor Information Base interface for NHDP
|
||||
*
|
||||
* @author Fabian Nack <nack@inf.fu-berlin.de>
|
||||
*/
|
||||
|
||||
#ifndef NIB_TABLE_H
|
||||
#define NIB_TABLE_H
|
||||
|
||||
#include "timex.h"
|
||||
|
||||
#include "rfc5444/rfc5444_writer.h"
|
||||
|
||||
#include "nhdp_address.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Neighbor Set entry (neighbor tuple)
|
||||
*/
|
||||
typedef struct nib_entry {
|
||||
nhdp_addr_entry_t *address_list_head; /**< Pointer to this tuple's addresses*/
|
||||
uint8_t symmetric; /**< Flag whether sym link to this nb exists */
|
||||
uint32_t metric_in; /**< Lowest metric value for incoming link */
|
||||
uint32_t metric_out; /**< Lowest metric value for outgoing link */
|
||||
struct nib_entry *next; /**< Pointer to next list entry */
|
||||
} nib_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Lost Neighbor Set entry (lost neighbor tuple, lnt)
|
||||
*/
|
||||
typedef struct nib_lost_address_entry {
|
||||
nhdp_addr_t *address; /**< Pointer to addr represented by this lnt */
|
||||
timex_t expiration_time; /**< Time at which entry expires */
|
||||
struct nib_lost_address_entry *next; /**< Pointer to next list entry */
|
||||
} nib_lost_address_entry_t;
|
||||
|
||||
/**
|
||||
* @brief Process a received HELLO message in the NIB
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP reader's message processing.
|
||||
*
|
||||
* @return Pointer to the new Neighbor Tuple
|
||||
* @return NULL on error
|
||||
*/
|
||||
nib_entry_t *nib_process_hello(void);
|
||||
|
||||
/**
|
||||
* @brief Add addresses to the currently constructed HELLO message
|
||||
*
|
||||
* @note
|
||||
* Must not be called from outside the NHDP writer's message creation process.
|
||||
*
|
||||
* @param[in] wr The NHDP writer used for message construction
|
||||
*/
|
||||
void nib_fill_wr_addresses(struct rfc5444_writer *wr);
|
||||
|
||||
/**
|
||||
* @brief Remove a Neighbor Tuple
|
||||
*
|
||||
* @param[in] nib_entry Pointer to the Neighbor Tuple
|
||||
*/
|
||||
void nib_rem_nb_entry(nib_entry_t *nib_entry);
|
||||
|
||||
/**
|
||||
* @brief Set a Neighbor Tuple's symmetry flag
|
||||
*
|
||||
* Removes all Lost Neighbor Tuples representing addresses included in the
|
||||
* Neighbor Tuple's address list.
|
||||
*
|
||||
* @param[in] nib_entry Pointer to the Neighbor Tuple
|
||||
*/
|
||||
void nib_set_nb_entry_sym(nib_entry_t *nib_entry);
|
||||
|
||||
/**
|
||||
* @brief Reset a Neighbor Tuple's symmetry flag
|
||||
*
|
||||
* Adds a Lost Neighbor Tuple for every address in the Neighbor Tuple's
|
||||
* address list.
|
||||
*
|
||||
* @param[in] nib_entry Pointer to the Neighbor Tuple
|
||||
* @param[in] now Pointer to current time timex representation
|
||||
*/
|
||||
void nib_reset_nb_entry_sym(nib_entry_t *nib_entry, timex_t *now);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NIB_TABLE_H */
|
||||
/** @} */
|
Loading…
Reference in New Issue
Block a user