From c3f62b24c8ea0679833e8a3031297012a021eac8 Mon Sep 17 00:00:00 2001 From: Simon Duquennoy Date: Mon, 29 Jul 2013 21:50:33 +0200 Subject: [PATCH] Moved ETX management from neighbor-info to rpl-of-etx. Avoids conversions between different fixed point representations, and simplifies neighbor management. Makes more clear how default-ETX and noack-ETX actually affect the rank. Removed neighbor-info and neighbor-attr. --- core/net/Makefile.uip | 2 - core/net/neighbor-attr.c | 250 ------------------------------------ core/net/neighbor-attr.h | 163 ----------------------- core/net/neighbor-info.c | 193 ---------------------------- core/net/neighbor-info.h | 94 -------------- core/net/rpl/rpl-conf.h | 4 +- core/net/rpl/rpl-dag.c | 2 - core/net/rpl/rpl-mrhof.c | 38 +++++- core/net/rpl/rpl-of0.c | 8 +- core/net/rpl/rpl.c | 28 +--- core/net/rpl/rpl.h | 4 +- core/net/sicslowpan.c | 15 +-- core/net/uip-ds6-neighbor.c | 34 +++++ core/net/uip-ds6-neighbor.h | 1 + core/net/uip-ds6.h | 7 + 15 files changed, 86 insertions(+), 757 deletions(-) delete mode 100644 core/net/neighbor-attr.c delete mode 100644 core/net/neighbor-attr.h delete mode 100644 core/net/neighbor-info.c delete mode 100644 core/net/neighbor-info.h diff --git a/core/net/Makefile.uip b/core/net/Makefile.uip index 66ca1d0ec..6fb3facbd 100644 --- a/core/net/Makefile.uip +++ b/core/net/Makefile.uip @@ -1,8 +1,6 @@ NET = \ dhcpc.c \ hc.c \ -neighbor-attr.c \ -neighbor-info.c \ neighbor-table.c \ netstack.c \ packetbuf.c \ diff --git a/core/net/neighbor-attr.c b/core/net/neighbor-attr.c deleted file mode 100644 index 38b42839a..000000000 --- a/core/net/neighbor-attr.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Copyright (c) 2010, Vrije Universiteit Brussel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * Author: Joris Borms - * - */ - -#include "contiki.h" - -#include "lib/memb.h" -#include "lib/list.h" -#include -#include - -#include "net/neighbor-attr.h" - -#define DEBUG 0 - -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -static uint16_t timeout = 0; - -MEMB(neighbor_addr_mem, struct neighbor_addr, NEIGHBOR_ATTR_MAX_NEIGHBORS); - -LIST(neighbor_addrs); -LIST(neighbor_attrs); -/*---------------------------------------------------------------------------*/ -static struct neighbor_addr * -neighbor_addr_get(const rimeaddr_t *addr) -{ - struct neighbor_addr *item; - - /* check if addr is derived from table, inside memb */ - if(memb_inmemb(&neighbor_addr_mem, (char *)addr)) { - return (struct neighbor_addr *) - (((char *)addr) - offsetof(struct neighbor_addr, addr)); - } - - item = list_head(neighbor_addrs); - while(item != NULL) { - if(rimeaddr_cmp(addr, &item->addr)) { - return item; - } - item = item->next; - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -struct neighbor_addr * -neighbor_attr_list_neighbors(void) -{ - return list_head(neighbor_addrs); -} -/*---------------------------------------------------------------------------*/ -static void -set_attr(struct neighbor_attr *attr, uint16_t index) -{ - if(attr->default_value != NULL) { - memcpy((char *)attr->data + index * attr->size, - attr->default_value, attr->size); - } else { - /* fill with zeroes */ - memset((char *)attr->data + index * attr->size, 0, attr->size); - } -} -/*---------------------------------------------------------------------------*/ -int -neighbor_attr_register(struct neighbor_attr *def) -{ - struct neighbor_addr *addr; - - list_push(neighbor_attrs, def); - - /* set default values for already existing neighbors */ - for(addr = list_head(neighbor_addrs); addr != NULL; addr = addr->next) { - set_attr(def, addr->index); - } - return 1; -} -/*---------------------------------------------------------------------------*/ -int -neighbor_attr_has_neighbor(const rimeaddr_t *addr) -{ - return neighbor_addr_get(addr) != NULL; -} -/*---------------------------------------------------------------------------*/ -int -neighbor_attr_add_neighbor(const rimeaddr_t *addr) -{ - struct neighbor_attr *def; - struct neighbor_addr *item; - struct neighbor_addr *ptr; - uint16_t i; - - if(neighbor_attr_has_neighbor(addr)) { - return 0; - } - - item = memb_alloc(&neighbor_addr_mem); - if(item == NULL) { - return -1; - } - - list_push(neighbor_addrs, item); - - item->time = 0; - rimeaddr_copy(&item->addr, addr); - - /* look up index and set default values */ - ptr = neighbor_addr_mem.mem; - for(i = 0; i < neighbor_addr_mem.num; ++i) { - if(&ptr[i] == item) { - break; - } - } - - item->index = i; - - for(def = list_head(neighbor_attrs); def != NULL; def = def->next) { - set_attr(def, i); - } - - return 1; -} -/*---------------------------------------------------------------------------*/ -int -neighbor_attr_remove_neighbor(const rimeaddr_t *addr) -{ - struct neighbor_addr *item = neighbor_addr_get(addr); - - if(item != NULL) { - list_remove(neighbor_addrs, item); - memb_free(&neighbor_addr_mem, item); - return 0; - } - return -1; -} -/*---------------------------------------------------------------------------*/ -void * -neighbor_attr_get_data(struct neighbor_attr *def, const rimeaddr_t *addr) -{ - struct neighbor_addr *attr = neighbor_addr_get(addr); - - if(attr != NULL) { - return (char *)def->data + attr->index * def->size; - } - return NULL; -} -/*---------------------------------------------------------------------------*/ -int -neighbor_attr_set_data(struct neighbor_attr *def, const rimeaddr_t *addr, - void *data) -{ - struct neighbor_addr *attr = neighbor_addr_get(addr); - - if(attr == NULL) { - if(neighbor_attr_add_neighbor(addr)) { - attr = neighbor_addr_get(addr); - } - } - if(attr != NULL) { - attr->time = 0; - memcpy((char *)def->data + attr->index * def->size, data, def->size); - return 1; - } - return 0; -} -/*---------------------------------------------------------------------------*/ -void -neighbor_attr_tick(const rimeaddr_t * addr) -{ - struct neighbor_addr *attr = neighbor_addr_get(addr); - - if(attr != NULL) { - attr->time = 0; - } -} -/*---------------------------------------------------------------------------*/ -uint16_t -neighbor_attr_get_timeout(void) -{ - return timeout; -} -/*---------------------------------------------------------------------------*/ -static struct ctimer ct; - -#define TIMEOUT_SECONDS 5 -static void -timeout_check(void *ptr) -{ - if(timeout > 0) { - struct neighbor_addr *item = neighbor_attr_list_neighbors(); - - while(item != NULL) { - item->time += TIMEOUT_SECONDS; - if(item->time >= timeout) { - struct neighbor_addr *next_item = item->next; - - list_remove(neighbor_addrs, item); - memb_free(&neighbor_addr_mem, item); - item = next_item; - } else { - item = item->next; - } - } - ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, ptr); - } -} -/*---------------------------------------------------------------------------*/ -void -neighbor_attr_set_timeout(uint16_t time) -{ - if(timeout == 0 && time > 0) { - ctimer_set(&ct, TIMEOUT_SECONDS * CLOCK_SECOND, timeout_check, NULL); - } else if(timeout > 0 && time == 0) { - ctimer_stop(&ct); - } - timeout = time; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/neighbor-attr.h b/core/net/neighbor-attr.h deleted file mode 100644 index abf119c25..000000000 --- a/core/net/neighbor-attr.h +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2010, Vrije Universiteit Brussel - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * - * Author: Joris Borms - * - */ -#ifndef NEIGHBORATTR_H_ -#define NEIGHBORATTR_H_ - -#include "net/rime.h" - -/** - * define how many neighbors you can store - */ -#ifdef NEIGHBOR_CONF_MAX_NEIGHBORS -#define NEIGHBOR_ATTR_MAX_NEIGHBORS NEIGHBOR_CONF_MAX_NEIGHBORS -#else /* NEIGHBOR_CONF_MAX_NEIGHBORS */ -#define NEIGHBOR_ATTR_MAX_NEIGHBORS 12 -#endif /* NEIGHBOR_CONF_MAX_NEIGHBORS */ - -/** - * \brief properties of a single neighbor - */ -struct neighbor_addr { - struct neighbor_addr *next; - rimeaddr_t addr; - uint16_t time; - uint16_t index; -}; - -/** - * \brief properties that define a neighbor attribute - */ -struct neighbor_attr { - struct neighbor_attr *next; - uint16_t size; - void *default_value; - void *data; -}; - -/** - * \brief Define space for additional parameters in neighbor table entries. - * \param type The type of the attribute. - * \param name The name of the attribute. - * \param def A ptr to the default value for this attribute. If NULL, attribute will - * be filled with zeroes by default. - * - * The attribute 'name' should be registered with 'neighbor_attr_register' - * during initialization. - */ -#define NEIGHBOR_ATTRIBUTE(type, name, default_value_ptr) \ - static type _##name##_mem[NEIGHBOR_ATTR_MAX_NEIGHBORS]; \ - static struct neighbor_attr name = \ - {NULL, sizeof(type), default_value_ptr, (void *)_##name##_mem} - -/** Same as NEIGHBOR_ATTRIBUTE, only the attr is not declared static - * this way you can say extern struct neighbor_attr name in header to declare - * a global neighbor attribute - */ -#define NEIGHBOR_ATTRIBUTE_GLOBAL(type, name, default_value_ptr) \ - static type _##name##_mem[NEIGHBOR_ATTR_MAX_NEIGHBORS]; \ - struct neighbor_attr name = \ - {NULL, sizeof(type), default_value_ptr, (void *)_##name##_mem} - -#define NEIGHBOR_ATTRIBUTE_DECLARE(name) extern struct neighbor_attr name - -/** - * \brief register a neighbor attribute - * \retval non-zero if successful, zero if not - */ -int neighbor_attr_register(struct neighbor_attr *); - -/** - * \retval head of neighbor list, useful for iterating over all neighbors - */ -struct neighbor_addr *neighbor_attr_list_neighbors(void); - -/** - * \brief Check if a neighbor is already added to the neighbor table - * \retval non-zero if present, zero if not - */ -int neighbor_attr_has_neighbor(const rimeaddr_t *addr); - -/** - * \brief Add a neighbor entry to neighbor table - * \retval -1 if unsuccessful, 0 if the neighbor was already - * in the table, and 1 if successful - */ -int neighbor_attr_add_neighbor(const rimeaddr_t *addr); - -/** - * \brief Remove a neighbor entry to neighbor table - * \retval -1 if unsuccessful, 0 if the neighbor was removed - */ -int neighbor_attr_remove_neighbor(const rimeaddr_t *addr); - -/** - * \brief Get pointer to neighbor table data specified by id - * \param requested attribute - * \param addr requested neighbor - * \retval pointer to data, NULL if neighbor was not found - * - * Searches neighbor table for addr and returns pointer to data section - * specified by attribute type and addr. - * This pointer should not be saved, as it may point to data from another - * neighbor in the future if neighbors get removed/added over time. - */ -void *neighbor_attr_get_data(struct neighbor_attr *, const rimeaddr_t *addr); - -/** - * \brief Copy data to neighbor table - * \retval non-zero if successful, zero if not - * - * Copies data to specific part of the neighbor table, specified by - * neighbor and attribute type, and resets timeout for that neighbor. - * If neighbor was not found, this will add a new neighbor to the table. - */ -int neighbor_attr_set_data(struct neighbor_attr *, const rimeaddr_t *addr, - void *data); - -/** - * \brief Set global lifetime of neighbor entries. - * \param Lifetime in seconds. If 0, entries will not time out - */ -void neighbor_attr_set_timeout(uint16_t); - -/** - * \brief get global lifetime of neighbor entries. If 0, entries will not time out - */ -uint16_t neighbor_attr_get_timeout(void); - -/** - * \brief reset timeout of a neighbor to prevent it from being removed - */ -void neighbor_attr_tick(const rimeaddr_t *); - -#endif /* NEIGHBORATTR_H_ */ diff --git a/core/net/neighbor-info.c b/core/net/neighbor-info.c deleted file mode 100644 index dc232cf02..000000000 --- a/core/net/neighbor-info.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ -/** - * \file - * A generic module for management of neighbor information. - * - * \author Nicolas Tsiftes - */ - -#include "net/neighbor-info.h" -#include "net/neighbor-attr.h" -#include "net/uip-ds6.h" -#include "net/uip-nd6.h" - -#define DEBUG DEBUG_NONE -#include "net/uip-debug.h" - -#define ETX_LIMIT 15 -#define ETX_SCALE 100 -#define ETX_ALPHA 90 -#define ETX_NOACK_PENALTY ETX_LIMIT -/*---------------------------------------------------------------------------*/ -NEIGHBOR_ATTRIBUTE_GLOBAL(link_metric_t, attr_etx, NULL); -NEIGHBOR_ATTRIBUTE_GLOBAL(unsigned long, attr_timestamp, NULL); - -static neighbor_info_subscriber_t subscriber_callback; -/*---------------------------------------------------------------------------*/ -static void -update_metric(const rimeaddr_t *dest, int packet_metric) -{ - link_metric_t *metricp; - link_metric_t recorded_metric, new_metric; - unsigned long time; - int first_update = 0; - - metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, dest); - packet_metric = NEIGHBOR_INFO_ETX2FIX(packet_metric); - if(metricp == NULL || *metricp == 0) { - recorded_metric = NEIGHBOR_INFO_ETX2FIX(ETX_LIMIT); - new_metric = packet_metric; - first_update = 1; - } else { - recorded_metric = *metricp; - /* Update the EWMA of the ETX for the neighbor. */ - new_metric = ((uint16_t)recorded_metric * ETX_ALPHA + - (uint16_t)packet_metric * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE; - } - - PRINTF("neighbor-info: ETX changed from %d to %d (packet ETX = %d) %d\n", - NEIGHBOR_INFO_FIX2ETX(recorded_metric), - NEIGHBOR_INFO_FIX2ETX(new_metric), - NEIGHBOR_INFO_FIX2ETX(packet_metric), - dest->u8[7]); - - if(neighbor_attr_has_neighbor(dest)) { - time = clock_seconds(); - neighbor_attr_set_data(&attr_etx, dest, &new_metric); - neighbor_attr_set_data(&attr_timestamp, dest, &time); - if((first_update || new_metric != recorded_metric) && subscriber_callback != NULL) { - subscriber_callback(dest, 1, new_metric); - } - } -} -/*---------------------------------------------------------------------------*/ -static void -add_neighbor(const rimeaddr_t *addr) -{ - switch(neighbor_attr_add_neighbor(addr)) { - case -1: - PRINTF("neighbor-info: failed to add a node.\n"); - break; - case 0: - PRINTF("neighbor-info: The neighbor is already known\n"); - break; - default: - break; - } -} -/*---------------------------------------------------------------------------*/ -void -neighbor_info_packet_sent(int status, int numtx) -{ - const rimeaddr_t *dest; - link_metric_t packet_metric; -#if UIP_DS6_LL_NUD - uip_ds6_nbr_t *nbr; -#endif /* UIP_DS6_LL_NUD */ - - dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); - if(rimeaddr_cmp(dest, &rimeaddr_null)) { - return; - } - - packet_metric = numtx; - - PRINTF("neighbor-info: packet sent to %d.%d, status=%d, metric=%u\n", - dest->u8[sizeof(*dest) - 2], dest->u8[sizeof(*dest) - 1], - status, (unsigned)packet_metric); - - switch(status) { - case MAC_TX_OK: - add_neighbor(dest); -#if UIP_DS6_LL_NUD - nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); - if(nbr != NULL && - (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { - nbr->state = REACHABLE; - stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); - PRINTF("neighbor-info : received a link layer ACK : "); - PRINTLLADDR((uip_lladdr_t *)dest); - PRINTF(" is reachable.\n"); - } -#endif /* UIP_DS6_LL_NUD */ - break; - case MAC_TX_NOACK: - packet_metric = ETX_NOACK_PENALTY; - break; - default: - /* Do not penalize the ETX when collisions or transmission - errors occur. */ - return; - } - - update_metric(dest, packet_metric); -} -/*---------------------------------------------------------------------------*/ -void -neighbor_info_packet_received(void) -{ - const rimeaddr_t *src; - - src = packetbuf_addr(PACKETBUF_ADDR_SENDER); - if(rimeaddr_cmp(src, &rimeaddr_null)) { - return; - } - - PRINTF("neighbor-info: packet received from %d.%d\n", - src->u8[sizeof(*src) - 2], src->u8[sizeof(*src) - 1]); - - add_neighbor(src); -} -/*---------------------------------------------------------------------------*/ -int -neighbor_info_subscribe(neighbor_info_subscriber_t s) -{ - if(subscriber_callback == NULL) { - neighbor_attr_register(&attr_etx); - neighbor_attr_register(&attr_timestamp); - subscriber_callback = s; - return 1; - } - - return 0; -} -/*---------------------------------------------------------------------------*/ -link_metric_t -neighbor_info_get_metric(const rimeaddr_t *addr) -{ - link_metric_t *metricp; - - metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, addr); - return metricp == NULL ? ETX_LIMIT : *metricp; -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/neighbor-info.h b/core/net/neighbor-info.h deleted file mode 100644 index 4bfed1ade..000000000 --- a/core/net/neighbor-info.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2010, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ -/** - * \file - * Declarations for the neighbor information module. - * - * \author Nicolas Tsiftes - */ - -#ifndef NEIGHBOR_INFO_H -#define NEIGHBOR_INFO_H - -#include "net/neighbor-attr.h" -#include "net/rime.h" - -/* ETX_DIVISOR is the value that a fix-point representation of the ETX - should be divided by in order to obtain the integer representation. */ -#define NEIGHBOR_INFO_ETX_DIVISOR 16 - -/* Macros for converting between a fix-point representation of the ETX - and a integer representation. */ -#define NEIGHBOR_INFO_ETX2FIX(etx) ((etx) * NEIGHBOR_INFO_ETX_DIVISOR) -#define NEIGHBOR_INFO_FIX2ETX(fix) ((fix) / NEIGHBOR_INFO_ETX_DIVISOR) - -typedef void (*neighbor_info_subscriber_t)(const rimeaddr_t *, int known, int etx); -typedef uint8_t link_metric_t; - -NEIGHBOR_ATTRIBUTE_DECLARE(attr_etx); -NEIGHBOR_ATTRIBUTE_DECLARE(attr_timestamp); - -/** - * Notify the neighbor information module about the status of - * a packet transmission. - * - * \param status The MAC status code for this packet. - * - * \param numtx The amount of transmissions made for this packet. - */ -void neighbor_info_packet_sent(int status, int numtx); - -/** - * Notify the neighbor information module that a packet was received. - * - * \param status The MAC status code for this packet. - * - * \param numtx The amount of transmissions made for this packet. - */ -void neighbor_info_packet_received(void); - -/** - * Subscribe to notifications of changed neighbor information. - * - * \return Returns 1 if the subscription was successful, and 0 if not. - */ -int neighbor_info_subscribe(neighbor_info_subscriber_t); - - -/** - * Get link metric value for a specific neighbor. - * - * \return Returns link metric if the neighbor exists, and 0 if not. - */ -link_metric_t neighbor_info_get_metric(const rimeaddr_t *addr); - -#endif /* NEIGHBOR_INFO_H */ diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 2810bd6d3..197c5abbe 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -162,9 +162,9 @@ * Initial metric attributed to a link when the ETX is unknown */ #ifndef RPL_CONF_INIT_LINK_METRIC -#define RPL_INIT_LINK_METRIC NEIGHBOR_INFO_ETX2FIX(5) +#define RPL_INIT_LINK_METRIC 5 * RPL_MIN_HOPRANKINC #else -#define RPL_INIT_LINK_METRIC NEIGHBOR_INFO_ETX2FIX(RPL_CONF_INIT_LINK_METRIC) +#define RPL_INIT_LINK_METRIC RPL_CONF_INIT_LINK_METRIC #endif /* diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index dfd9c997c..74f0d3cf0 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -56,8 +56,6 @@ #define DEBUG DEBUG_NONE #include "net/uip-debug.h" -#include "net/neighbor-info.h" - #if UIP_CONF_IPV6 /*---------------------------------------------------------------------------*/ extern rpl_of_t RPL_OF; diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 567977c70..5f7e85f42 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -45,13 +45,13 @@ */ #include "net/rpl/rpl-private.h" -#include "net/neighbor-info.h" +#include "net/neighbor-table.h" #define DEBUG DEBUG_NONE #include "net/uip-debug.h" static void reset(rpl_dag_t *); -static void parent_state_callback(rpl_parent_t *, int, int); +static void neighbor_link_callback(rpl_parent_t *, int, int); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); @@ -59,7 +59,7 @@ static void update_metric_container(rpl_instance_t *); rpl_of_t rpl_mrhof = { reset, - parent_state_callback, + neighbor_link_callback, best_parent, best_dag, calculate_rank, @@ -67,6 +67,10 @@ rpl_of_t rpl_mrhof = { 1 }; +/* Constants for the ETX moving average */ +#define ETX_SCALE 100 +#define ETX_ALPHA 90 + /* Reject parents that have a higher link metric than the following. */ #define MAX_LINK_METRIC 10 @@ -88,7 +92,6 @@ calculate_path_metric(rpl_parent_t *p) return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; } else { long link_metric = p->link_metric; - link_metric = (link_metric * RPL_DAG_MC_ETX_DIVISOR) / NEIGHBOR_INFO_ETX_DIVISOR; #if RPL_DAG_MC == RPL_DAG_MC_NONE return p->rank + (uint16_t)link_metric; #elif RPL_DAG_MC == RPL_DAG_MC_ETX @@ -105,8 +108,29 @@ reset(rpl_dag_t *sag) } static void -parent_state_callback(rpl_parent_t *parent, int known, int etx) +neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { + /* Do not penalize the ETX when collisions or transmission errors occur. */ + if(status == MAC_TX_OK || status == MAC_TX_NOACK) { + int recorded_etx = p->link_metric; + int packet_etx = numtx; + int new_etx; + + if(status == MAC_TX_NOACK) { + packet_etx = MAX_LINK_METRIC; + } + + new_etx = ((uint16_t)recorded_etx * ETX_ALPHA + + (uint16_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE; + + PRINTF("RPL: ETX changed from %d to %d (packet ETX = %d) %d\n", + recorded_etx / p->dag->instance->min_hoprankinc, + new_etx / p->dag->instance->min_hoprankinc, + packet_etx / p->dag->instance->min_hoprankinc, + dest->u8[7]); + p->link_metric = new_etx; + + } } static rpl_rank_t @@ -119,10 +143,10 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) if(base_rank == 0) { return INFINITE_RANK; } - rank_increase = NEIGHBOR_INFO_FIX2ETX(RPL_INIT_LINK_METRIC) * RPL_MIN_HOPRANKINC; + rank_increase = RPL_INIT_LINK_METRIC; } else { /* multiply first, then scale down to avoid truncation effects */ - rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric * p->dag->instance->min_hoprankinc); + rank_increase = p->link_metric; if(base_rank == 0) { base_rank = p->rank; } diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index 49f3c99d0..36241c7ef 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -44,8 +44,6 @@ #define DEBUG DEBUG_NONE #include "net/uip-debug.h" -#include "net/neighbor-info.h" - static void reset(rpl_dag_t *); static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); @@ -64,7 +62,7 @@ rpl_of_t rpl_of0 = { #define DEFAULT_RANK_INCREMENT RPL_MIN_HOPRANKINC -#define MIN_DIFFERENCE (NEIGHBOR_INFO_ETX_DIVISOR + NEIGHBOR_INFO_ETX_DIVISOR / 2) +#define MIN_DIFFERENCE (RPL_MIN_HOPRANKINC + RPL_MIN_HOPRANKINC / 2) static void reset(rpl_dag_t *dag) @@ -137,9 +135,9 @@ best_parent(rpl_parent_t *p1, rpl_parent_t *p2) p2->link_metric, p2->rank); - r1 = DAG_RANK(p1->rank, p1->dag->instance) * NEIGHBOR_INFO_ETX_DIVISOR + + r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + p1->link_metric; - r2 = DAG_RANK(p2->rank, p1->dag->instance) * NEIGHBOR_INFO_ETX_DIVISOR + + r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + p2->link_metric; /* Compare two parents by looking both and their rank and at the ETX for that parent. We choose the parent that has the most diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index c57d4105d..cf01c286a 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -44,7 +44,6 @@ #include "net/tcpip.h" #include "net/uip-ds6.h" #include "net/rpl/rpl-private.h" -#include "net/neighbor-info.h" #define DEBUG DEBUG_NONE #include "net/uip-debug.h" @@ -168,8 +167,8 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, return rep; } /*---------------------------------------------------------------------------*/ -static void -rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) +void +rpl_link_neighbor_callback(const rimeaddr_t *addr, int status, int numtx) { uip_ipaddr_t ipaddr; rpl_parent_t *parent; @@ -178,9 +177,6 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr); - PRINTF("RPL: Neighbor "); - PRINT6ADDR(&ipaddr); - PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { if(instance->used == 1 ) { @@ -188,27 +184,12 @@ rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) if(parent != NULL) { /* Trigger DAG rank recalculation. */ parent->updated = 1; - parent->link_metric = etx; - - if(instance->of->parent_state_callback != NULL) { - instance->of->parent_state_callback(parent, known, etx); - } - if(!known) { - PRINTF("RPL: Removing parent "); - PRINT6ADDR(&parent->addr); - PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx); - parent->rank = INFINITE_RANK; + if(instance->of->neighbor_link_callback != NULL) { + instance->of->neighbor_link_callback(parent, status, numtx); } } } } - - if(!known) { - PRINTF("RPL: Deleting routes installed by DAOs received from "); - PRINT6ADDR(&ipaddr); - PRINTF("\n"); - uip_ds6_route_rm_by_nexthop(&ipaddr); - } } /*---------------------------------------------------------------------------*/ void @@ -242,7 +223,6 @@ rpl_init(void) rpl_dag_init(); rpl_reset_periodic_timer(); - neighbor_info_subscribe(rpl_link_neighbor_callback); /* add rpl multicast address */ uip_create_linklocal_rplnodes_mcast(&rplmaddr); diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index db89f38cd..6109874ef 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -156,7 +156,7 @@ typedef struct rpl_instance rpl_instance_t; * Resets the objective function state for a specific DAG. This function is * called when doing a global repair on the DAG. * - * parent_state_callback(parent, known, etx) + * neighbor_link_callback(parent, known, etx) * * Receives link-layer neighbor information. The parameter "known" is set * either to 0 or 1. The "etx" parameter specifies the current @@ -185,7 +185,7 @@ typedef struct rpl_instance rpl_instance_t; */ struct rpl_of { void (*reset)(struct rpl_dag *); - void (*parent_state_callback)(rpl_parent_t *, int, int); + void (*neighbor_link_callback)(rpl_parent_t *, int, int); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *); rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t); diff --git a/core/net/sicslowpan.c b/core/net/sicslowpan.c index ad9cc96c8..cdbe33fc8 100644 --- a/core/net/sicslowpan.c +++ b/core/net/sicslowpan.c @@ -65,7 +65,6 @@ #include "net/uip-ds6.h" #include "net/rime.h" #include "net/sicslowpan.h" -#include "net/neighbor-info.h" #include "net/netstack.h" #if UIP_CONF_IPV6 @@ -113,11 +112,6 @@ void uip_log(char *msg); #endif /* SICSLOWPAN_CONF_COMPRESSION */ #endif /* SICSLOWPAN_COMPRESSION */ -#ifndef SICSLOWPAN_CONF_NEIGHBOR_INFO -/* Default is to use neighbor info updates if using RPL */ -#define SICSLOWPAN_CONF_NEIGHBOR_INFO UIP_CONF_IPV6_RPL -#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */ - #define GET16(ptr,index) (((uint16_t)((ptr)[index] << 8)) | ((ptr)[(index) + 1])) #define SET16(ptr,index,value) do { \ (ptr)[index] = ((value) >> 8) & 0xff; \ @@ -1309,9 +1303,8 @@ compress_hdr_ipv6(rimeaddr_t *rime_destaddr) static void packet_sent(void *ptr, int status, int transmissions) { -#if SICSLOWPAN_CONF_NEIGHBOR_INFO - neighbor_info_packet_sent(status, transmissions); -#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */ + uip_ds6_link_neighbor_callback(status, transmissions); + if(callback != NULL) { callback->output_callback(status); } @@ -1834,10 +1827,6 @@ input(void) } #endif -#if SICSLOWPAN_CONF_NEIGHBOR_INFO - neighbor_info_packet_received(); -#endif /* SICSLOWPAN_CONF_NEIGHBOR_INFO */ - /* if callback is set then set attributes and call */ if(callback) { set_packet_attrs(); diff --git a/core/net/uip-ds6-neighbor.c b/core/net/uip-ds6-neighbor.c index e5dd36897..89371baf4 100644 --- a/core/net/uip-ds6-neighbor.c +++ b/core/net/uip-ds6-neighbor.c @@ -61,6 +61,13 @@ void NEIGHBOR_STATE_CHANGED(uip_ds6_nbr_t *n); #define NEIGHBOR_STATE_CHANGED(n) #endif /* UIP_DS6_CONF_NEIGHBOR_STATE_CHANGED */ +#ifdef UIP_CONF_DS6_LINK_NEIGHBOR_CALLBACK +#define LINK_NEIGHBOR_CALLBACK(addr, status, numtx) UIP_CONF_DS6_LINK_NEIGHBOR_CALLBACK(addr, status, numtx) +void LINK_NEIGHBOR_CALLBACK(const rimeaddr_t *addr, int status, int numtx); +#else +#define LINK_NEIGHBOR_CALLBACK(addr, status, numtx) +#endif /* UIP_CONF_DS6_LINK_NEIGHBOR_CALLBACK */ + NEIGHBOR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors); /*---------------------------------------------------------------------------*/ @@ -166,6 +173,33 @@ uip_ds6_nbr_lladdr_from_ipaddr(uip_ipaddr_t *ipaddr) uip_ds6_nbr_t *nbr = uip_ds6_nbr_lookup(ipaddr); return nbr ? uip_ds6_nbr_get_ll(nbr) : NULL; } +/*---------------------------------------------------------------------------*/ +void +uip_ds6_link_neighbor_callback(int status, int numtx) +{ + const rimeaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + if(rimeaddr_cmp(dest, &rimeaddr_null)) { + return; + } + + LINK_NEIGHBOR_CALLBACK(dest, status, numtx); + +#if UIP_DS6_LL_NUD + if(status == MAC_TX_OK) { + uip_ds6_nbr_t *nbr; + nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest); + if(nbr != NULL && + (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) { + nbr->state = REACHABLE; + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); + PRINTF("uip-ds6-neighbor : received a link layer ACK : "); + PRINTLLADDR((uip_lladdr_t *)dest); + PRINTF(" is reachable.\n"); + } + } +#endif /* UIP_DS6_LL_NUD */ + +} /*---------------------------------------------------------------------------*/ void diff --git a/core/net/uip-ds6-neighbor.h b/core/net/uip-ds6-neighbor.h index 686fb6abd..4de23cb03 100644 --- a/core/net/uip-ds6-neighbor.h +++ b/core/net/uip-ds6-neighbor.h @@ -81,6 +81,7 @@ uip_ds6_nbr_t *uip_ds6_nbr_lookup(uip_ipaddr_t *ipaddr); uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(uip_lladdr_t *lladdr); uip_ipaddr_t *uip_ds6_nbr_ipaddr_from_lladdr(uip_lladdr_t *lladdr); uip_lladdr_t *uip_ds6_nbr_lladdr_from_ipaddr(uip_ipaddr_t *ipaddr); +void uip_ds6_link_neighbor_callback(int status, int numtx); void uip_ds6_neighbor_periodic(); /** diff --git a/core/net/uip-ds6.h b/core/net/uip-ds6.h index e0d032c96..1ee6b176f 100644 --- a/core/net/uip-ds6.h +++ b/core/net/uip-ds6.h @@ -203,6 +203,13 @@ typedef struct uip_ds6_maddr { #endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ #endif /* UIP_CONF_IPV6_RPL */ +#if UIP_CONF_IPV6_RPL +#ifndef UIP_CONF_DS6_LINK_NEIGHBOR_CALLBACK +#define UIP_CONF_DS6_LINK_NEIGHBOR_CALLBACK rpl_link_neighbor_callback +#endif /* UIP_CONF_DS6_NEIGHBOR_STATE_CHANGED */ +#endif /* UIP_CONF_IPV6_RPL */ + + /** \brief Interface structure (contains all the interface variables) */ typedef struct uip_ds6_netif { uint32_t link_mtu;