rpl-of-etx.c

Go to the documentation of this file.
00001 /**
00002  * \addtogroup uip6
00003  * @{
00004  */
00005 /*
00006  * Copyright (c) 2010, Swedish Institute of Computer Science.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  * 1. Redistributions of source code must retain the above copyright
00013  *    notice, this list of conditions and the following disclaimer.
00014  * 2. Redistributions in binary form must reproduce the above copyright
00015  *    notice, this list of conditions and the following disclaimer in the
00016  *    documentation and/or other materials provided with the distribution.
00017  * 3. Neither the name of the Institute nor the names of its contributors
00018  *    may be used to endorse or promote products derived from this software
00019  *    without specific prior written permission.
00020  *
00021  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * This file is part of the Contiki operating system.
00034  *
00035  */
00036 /**
00037  * \file
00038  *         The minrank-hysteresis objective function (OCP 1).
00039  *
00040  *         This implementation uses the estimated number of 
00041  *         transmissions (ETX) as the additive routing metric.
00042  *
00043  * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
00044  */
00045 
00046 #include "net/rpl/rpl-private.h"
00047 #include "net/neighbor-info.h"
00048 
00049 #define DEBUG DEBUG_NONE
00050 #include "net/uip-debug.h"
00051 
00052 static void reset(rpl_dag_t *);
00053 static void parent_state_callback(rpl_parent_t *, int, int);
00054 static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *);
00055 static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t);
00056 static void update_metric_container(rpl_dag_t *);
00057 
00058 rpl_of_t rpl_of_etx = {
00059   reset,
00060   parent_state_callback,
00061   best_parent,
00062   calculate_rank,
00063   update_metric_container,
00064   1
00065 };
00066 
00067 #define NI_ETX_TO_RPL_ETX(etx)                                          \
00068         ((etx) * (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
00069 #define RPL_ETX_TO_NI_ETX(etx)                                  \
00070         ((etx) / (RPL_DAG_MC_ETX_DIVISOR / NEIGHBOR_INFO_ETX_DIVISOR))
00071 
00072 /* Reject parents that have a higher link metric than the following. */
00073 #define MAX_LINK_METRIC                 10
00074 
00075 /* Reject parents that have a higher path cost than the following. */
00076 #define MAX_PATH_COST                   100
00077 
00078 /*
00079  * The rank must differ more than 1/PARENT_SWITCH_THRESHOLD_DIV in order
00080  * to switch preferred parent.
00081  */
00082 #define PARENT_SWITCH_THRESHOLD_DIV     2
00083 
00084 typedef uint16_t rpl_path_metric_t;
00085 
00086 static uint16_t
00087 calculate_path_metric(rpl_parent_t *p)
00088 {
00089   if(p->mc.obj.etx == 0 && p->rank > ROOT_RANK(p->dag)) {
00090     return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR;
00091   }
00092   return p->mc.obj.etx + NI_ETX_TO_RPL_ETX(p->link_metric);
00093 }
00094 
00095 static void
00096 reset(rpl_dag_t *dag)
00097 {
00098 }
00099 
00100 static void
00101 parent_state_callback(rpl_parent_t *parent, int known, int etx)
00102 {
00103 }
00104 
00105 static rpl_rank_t
00106 calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank)
00107 {
00108   rpl_rank_t new_rank;
00109   rpl_rank_t rank_increase;
00110 
00111   if(p == NULL) {
00112     if(base_rank == 0) {
00113       return INFINITE_RANK;
00114     }
00115     rank_increase = NEIGHBOR_INFO_FIX2ETX(INITIAL_LINK_METRIC) * DEFAULT_MIN_HOPRANKINC;
00116   } else {
00117     rank_increase = NEIGHBOR_INFO_FIX2ETX(p->link_metric) * p->dag->min_hoprankinc;
00118     if(base_rank == 0) {
00119       base_rank = p->rank;
00120     }
00121   }
00122 
00123   if(INFINITE_RANK - base_rank < rank_increase) {
00124     /* Reached the maximum rank. */
00125     new_rank = INFINITE_RANK;
00126   } else {
00127    /* Calculate the rank based on the new rank information from DIO or
00128       stored otherwise. */
00129     new_rank = base_rank + rank_increase;
00130   }
00131 
00132   return new_rank;
00133 }
00134 
00135 static rpl_parent_t *
00136 best_parent(rpl_parent_t *p1, rpl_parent_t *p2)
00137 {
00138   rpl_dag_t *dag;
00139   rpl_path_metric_t min_diff;
00140   rpl_path_metric_t p1_metric;
00141   rpl_path_metric_t p2_metric;
00142 
00143   dag = p1->dag; /* Both parents must be in the same DAG. */
00144 
00145   min_diff = RPL_DAG_MC_ETX_DIVISOR / 
00146              PARENT_SWITCH_THRESHOLD_DIV;
00147 
00148   p1_metric = calculate_path_metric(p1);
00149   p2_metric = calculate_path_metric(p2);
00150 
00151   /* Maintain stability of the preferred parent in case of similar ranks. */
00152   if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) {
00153     if(p1_metric < p2_metric + min_diff &&
00154        p1_metric > p2_metric - min_diff) {
00155       PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n",
00156              p2_metric - min_diff,
00157              p1_metric,
00158              p2_metric + min_diff);
00159       return dag->preferred_parent;
00160     }
00161   }
00162 
00163   return p1_metric < p2_metric ? p1 : p2;
00164 }
00165 
00166 static void
00167 update_metric_container(rpl_dag_t *dag)
00168 {
00169 #if RPL_DAG_MC == RPL_DAG_MC_ETX
00170   dag->mc.type = RPL_DAG_MC_ETX;
00171   dag->mc.flags = RPL_DAG_MC_FLAG_P;
00172   dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
00173   dag->mc.prec = 0;
00174   dag->mc.length = sizeof(dag->mc.obj.etx);
00175   if(dag->rank == ROOT_RANK(dag)) {
00176     dag->mc.obj.etx = 0;
00177   } else {
00178     dag->mc.obj.etx = calculate_path_metric(dag->preferred_parent);
00179   }
00180 
00181   PRINTF("RPL: My path ETX to the root is %u.%u\n",
00182         dag->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR,
00183         (dag->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / RPL_DAG_MC_ETX_DIVISOR);
00184 #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY
00185   dag->mc.type = RPL_DAG_MC_ENERGY;
00186   dag->mc.flags = RPL_DAG_MC_FLAG_P;
00187   dag->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE;
00188   dag->mc.prec = 0;
00189   dag->mc.length = sizeof(dag->mc.obj.energy);
00190   if(dag->rank == ROOT_RANK(dag)) {
00191     dag->mc.obj.energy.flags = RPL_DAG_MC_ENERGY_TYPE_MAINS << RPL_DAG_MC_ENERGY_TYPE;
00192   } else {
00193     dag->mc.obj.energy.flags = RPL_DAG_MC_ENERGY_TYPE_BATTERY << RPL_DAG_MC_ENERGY_TYPE;
00194   }
00195   dag->mc.obj.energy.energy_est = calculate_path_metric(dag->preferred_parent);
00196 #else
00197 #error "Unsupported RPL_DAG_MC configured. See rpl.h."
00198 #endif /* RPL_DAG_MC */
00199 }
00200 
00201 /** \} */

Generated on Mon Apr 11 14:23:31 2011 for Contiki 2.5 by  doxygen 1.6.1