rpl-of-etx.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
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
00073 #define MAX_LINK_METRIC 10
00074
00075
00076 #define MAX_PATH_COST 100
00077
00078
00079
00080
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
00125 new_rank = INFINITE_RANK;
00126 } else {
00127
00128
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;
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
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
00199 }
00200
00201