Contiki 2.6
|
00001 /** 00002 * \addtogroup uip6 00003 * @{ 00004 */ 00005 /* 00006 * Copyright (c) 2009, 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 * \file 00037 * ContikiRPL, an implementation of RPL: IPv6 Routing Protocol 00038 * for Low-Power and Lossy Networks (IETF RFC 6550) 00039 * 00040 * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se> 00041 */ 00042 00043 #include "net/uip.h" 00044 #include "net/tcpip.h" 00045 #include "net/uip-ds6.h" 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 #include <limits.h> 00053 #include <string.h> 00054 00055 #if RPL_CONF_STATS 00056 rpl_stats_t rpl_stats; 00057 #endif 00058 00059 /************************************************************************/ 00060 extern uip_ds6_route_t uip_ds6_routing_table[UIP_DS6_ROUTE_NB]; 00061 /************************************************************************/ 00062 void 00063 rpl_purge_routes(void) 00064 { 00065 int i; 00066 00067 for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { 00068 if(uip_ds6_routing_table[i].isused) { 00069 if(uip_ds6_routing_table[i].state.lifetime <= 1) { 00070 uip_ds6_route_rm(&uip_ds6_routing_table[i]); 00071 } else { 00072 uip_ds6_routing_table[i].state.lifetime--; 00073 } 00074 } 00075 } 00076 } 00077 /************************************************************************/ 00078 void 00079 rpl_remove_routes(rpl_dag_t *dag) 00080 { 00081 int i; 00082 00083 for(i = 0; i < UIP_DS6_ROUTE_NB; i++) { 00084 if(uip_ds6_routing_table[i].state.dag == dag) { 00085 uip_ds6_route_rm(&uip_ds6_routing_table[i]); 00086 } 00087 } 00088 } 00089 /************************************************************************/ 00090 void 00091 rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) 00092 { 00093 uip_ds6_route_t *locroute; 00094 00095 for(locroute = uip_ds6_routing_table; 00096 locroute < uip_ds6_routing_table + UIP_DS6_ROUTE_NB; 00097 locroute++) { 00098 if(locroute->isused 00099 && uip_ipaddr_cmp(&locroute->nexthop, nexthop) 00100 && locroute->state.dag == dag) { 00101 locroute->isused = 0; 00102 } 00103 } 00104 ANNOTATE("#L %u 0\n",nexthop->u8[sizeof(uip_ipaddr_t) - 1]); 00105 } 00106 /************************************************************************/ 00107 uip_ds6_route_t * 00108 rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, 00109 uip_ipaddr_t *next_hop) 00110 { 00111 uip_ds6_route_t *rep; 00112 00113 rep = uip_ds6_route_lookup(prefix); 00114 if(rep == NULL) { 00115 if((rep = uip_ds6_route_add(prefix, prefix_len, next_hop, 0)) == NULL) { 00116 PRINTF("RPL: No space for more route entries\n"); 00117 return NULL; 00118 } 00119 } else { 00120 PRINTF("RPL: Updated the next hop for prefix "); 00121 PRINT6ADDR(prefix); 00122 PRINTF(" to "); 00123 PRINT6ADDR(next_hop); 00124 PRINTF("\n"); 00125 uip_ipaddr_copy(&rep->nexthop, next_hop); 00126 } 00127 rep->state.dag = dag; 00128 rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime); 00129 rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; 00130 00131 PRINTF("RPL: Added a route to "); 00132 PRINT6ADDR(prefix); 00133 PRINTF("/%d via ", prefix_len); 00134 PRINT6ADDR(next_hop); 00135 PRINTF("\n"); 00136 00137 return rep; 00138 } 00139 /************************************************************************/ 00140 static void 00141 rpl_link_neighbor_callback(const rimeaddr_t *addr, int known, int etx) 00142 { 00143 uip_ipaddr_t ipaddr; 00144 rpl_parent_t *parent; 00145 rpl_instance_t *instance; 00146 rpl_instance_t *end; 00147 00148 uip_ip6addr(&ipaddr, 0xfe80, 0, 0, 0, 0, 0, 0, 0); 00149 uip_ds6_set_addr_iid(&ipaddr, (uip_lladdr_t *)addr); 00150 PRINTF("RPL: Neighbor "); 00151 PRINT6ADDR(&ipaddr); 00152 PRINTF(" is %sknown. ETX = %u\n", known ? "" : "no longer ", NEIGHBOR_INFO_FIX2ETX(etx)); 00153 00154 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { 00155 if(instance->used == 1 ) { 00156 parent = rpl_find_parent_any_dag(instance, &ipaddr); 00157 if(parent != NULL) { 00158 /* Trigger DAG rank recalculation. */ 00159 parent->updated = 1; 00160 parent->link_metric = etx; 00161 00162 if(instance->of->parent_state_callback != NULL) { 00163 instance->of->parent_state_callback(parent, known, etx); 00164 } 00165 if(!known) { 00166 PRINTF("RPL: Removing parent "); 00167 PRINT6ADDR(&parent->addr); 00168 PRINTF(" in instance %u because of bad connectivity (ETX %d)\n", instance->instance_id, etx); 00169 parent->rank = INFINITE_RANK; 00170 } 00171 } 00172 } 00173 } 00174 00175 if(!known) { 00176 PRINTF("RPL: Deleting routes installed by DAOs received from "); 00177 PRINT6ADDR(&ipaddr); 00178 PRINTF("\n"); 00179 uip_ds6_route_rm_by_nexthop(&ipaddr); 00180 } 00181 } 00182 /************************************************************************/ 00183 void 00184 rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) 00185 { 00186 rpl_parent_t *p; 00187 rpl_instance_t *instance; 00188 rpl_instance_t *end; 00189 00190 if(!nbr->isused) { 00191 PRINTF("RPL: Removing neighbor "); 00192 PRINT6ADDR(&nbr->ipaddr); 00193 PRINTF("\n"); 00194 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { 00195 if(instance->used == 1 ) { 00196 p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); 00197 if(p != NULL) { 00198 p->rank = INFINITE_RANK; 00199 /* Trigger DAG rank recalculation. */ 00200 p->updated = 1; 00201 } 00202 } 00203 } 00204 } 00205 } 00206 /************************************************************************/ 00207 void 00208 rpl_init(void) 00209 { 00210 uip_ipaddr_t rplmaddr; 00211 PRINTF("RPL started\n"); 00212 default_instance = NULL; 00213 00214 rpl_reset_periodic_timer(); 00215 neighbor_info_subscribe(rpl_link_neighbor_callback); 00216 00217 /* add rpl multicast address */ 00218 uip_create_linklocal_rplnodes_mcast(&rplmaddr); 00219 uip_ds6_maddr_add(&rplmaddr); 00220 00221 #if RPL_CONF_STATS 00222 memset(&rpl_stats, 0, sizeof(rpl_stats)); 00223 #endif 00224 } 00225 /************************************************************************/