Contiki 2.6

neighbor-info.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2010, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * $Id: neighbor-info.c,v 1.18 2010/12/15 14:35:07 nvt-se Exp $
00032  */
00033 /**
00034  * \file
00035  *         A generic module for management of neighbor information.
00036  *
00037  * \author Nicolas Tsiftes <nvt@sics.se>
00038  */
00039 
00040 #include "net/neighbor-info.h"
00041 #include "net/neighbor-attr.h"
00042 #include "net/uip-ds6.h"
00043 #include "net/uip-nd6.h"
00044 
00045 #define DEBUG DEBUG_NONE
00046 #include "net/uip-debug.h"
00047 
00048 #define ETX_LIMIT               15
00049 #define ETX_SCALE               100
00050 #define ETX_ALPHA               90
00051 #define ETX_NOACK_PENALTY       ETX_LIMIT
00052 /*---------------------------------------------------------------------------*/
00053 NEIGHBOR_ATTRIBUTE_GLOBAL(link_metric_t, attr_etx, NULL);
00054 NEIGHBOR_ATTRIBUTE_GLOBAL(unsigned long, attr_timestamp, NULL);
00055 
00056 static neighbor_info_subscriber_t subscriber_callback;
00057 /*---------------------------------------------------------------------------*/
00058 static void
00059 update_metric(const rimeaddr_t *dest, int packet_metric)
00060 {
00061   link_metric_t *metricp;
00062   link_metric_t recorded_metric, new_metric;
00063   unsigned long time;
00064 
00065   metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, dest);
00066   packet_metric = NEIGHBOR_INFO_ETX2FIX(packet_metric);
00067   if(metricp == NULL || *metricp == 0) {
00068     recorded_metric = NEIGHBOR_INFO_ETX2FIX(ETX_LIMIT);
00069     new_metric = packet_metric;
00070   } else {
00071     recorded_metric = *metricp;
00072     /* Update the EWMA of the ETX for the neighbor. */
00073     new_metric = ((uint16_t)recorded_metric * ETX_ALPHA +
00074                (uint16_t)packet_metric * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE;
00075   }
00076 
00077   PRINTF("neighbor-info: ETX changed from %d to %d (packet ETX = %d) %d\n",
00078          NEIGHBOR_INFO_FIX2ETX(recorded_metric),
00079          NEIGHBOR_INFO_FIX2ETX(new_metric),
00080          NEIGHBOR_INFO_FIX2ETX(packet_metric),
00081          dest->u8[7]);
00082 
00083   if(neighbor_attr_has_neighbor(dest)) {
00084     time = clock_seconds();
00085     neighbor_attr_set_data(&attr_etx, dest, &new_metric);
00086     neighbor_attr_set_data(&attr_timestamp, dest, &time);
00087     if(new_metric != recorded_metric && subscriber_callback != NULL) {
00088       subscriber_callback(dest, 1, new_metric);
00089     }
00090   }
00091 }
00092 /*---------------------------------------------------------------------------*/
00093 static void
00094 add_neighbor(const rimeaddr_t *addr)
00095 {
00096   switch(neighbor_attr_add_neighbor(addr)) {
00097   case -1:
00098     PRINTF("neighbor-info: failed to add a node.\n");
00099     break;
00100   case 0:
00101     PRINTF("neighbor-info: The neighbor is already known\n");
00102     break;
00103   default:
00104     break;
00105   }
00106 }
00107 /*---------------------------------------------------------------------------*/
00108 void
00109 neighbor_info_packet_sent(int status, int numtx)
00110 {
00111   const rimeaddr_t *dest;
00112   link_metric_t packet_metric;
00113 #if UIP_DS6_LL_NUD
00114   uip_ds6_nbr_t *nbr;
00115 #endif /* UIP_DS6_LL_NUD */
00116 
00117   dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER);
00118   if(rimeaddr_cmp(dest, &rimeaddr_null)) {
00119     return;
00120   }
00121 
00122   packet_metric = numtx;
00123 
00124   PRINTF("neighbor-info: packet sent to %d.%d, status=%d, metric=%u\n",
00125         dest->u8[sizeof(*dest) - 2], dest->u8[sizeof(*dest) - 1],
00126         status, (unsigned)packet_metric);
00127 
00128   switch(status) {
00129   case MAC_TX_OK:
00130     add_neighbor(dest);
00131 #if UIP_DS6_LL_NUD
00132     nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest);
00133     if(nbr != NULL &&
00134        (nbr->state == STALE || nbr->state == DELAY || nbr->state == PROBE)) {
00135       nbr->state = REACHABLE;
00136       stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
00137       PRINTF("neighbor-info : received a link layer ACK : ");
00138       PRINTLLADDR((uip_lladdr_t *)dest);
00139       PRINTF(" is reachable.\n");
00140     }
00141 #endif /* UIP_DS6_LL_NUD */
00142     break;
00143   case MAC_TX_NOACK:
00144     packet_metric = ETX_NOACK_PENALTY;
00145     break;
00146   default:
00147     /* Do not penalize the ETX when collisions or transmission
00148        errors occur. */
00149     return;
00150   }
00151 
00152   update_metric(dest, packet_metric);
00153 }
00154 /*---------------------------------------------------------------------------*/
00155 void
00156 neighbor_info_packet_received(void)
00157 {
00158   const rimeaddr_t *src;
00159 
00160   src = packetbuf_addr(PACKETBUF_ADDR_SENDER);
00161   if(rimeaddr_cmp(src, &rimeaddr_null)) {
00162     return;
00163   }
00164 
00165   PRINTF("neighbor-info: packet received from %d.%d\n",
00166         src->u8[sizeof(*src) - 2], src->u8[sizeof(*src) - 1]);
00167 
00168   add_neighbor(src);
00169 }
00170 /*---------------------------------------------------------------------------*/
00171 int
00172 neighbor_info_subscribe(neighbor_info_subscriber_t s)
00173 {
00174   if(subscriber_callback == NULL) {
00175     neighbor_attr_register(&attr_etx);
00176     neighbor_attr_register(&attr_timestamp);
00177     subscriber_callback = s;
00178     return 1;
00179   }
00180 
00181   return 0;
00182 }
00183 /*---------------------------------------------------------------------------*/
00184 link_metric_t
00185 neighbor_info_get_metric(const rimeaddr_t *addr)
00186 {
00187   link_metric_t *metricp;
00188 
00189   metricp = (link_metric_t *)neighbor_attr_get_data(&attr_etx, addr);
00190   return metricp == NULL ? ETX_LIMIT : *metricp;
00191 }
00192 /*---------------------------------------------------------------------------*/