Contiki 2.6
|
00001 /** 00002 * \addtogroup rimemesh 00003 * @{ 00004 */ 00005 00006 /* 00007 * Copyright (c) 2007, Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without 00011 * modification, are permitted provided that the following conditions 00012 * are met: 00013 * 1. Redistributions of source code must retain the above copyright 00014 * notice, this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright 00016 * notice, this list of conditions and the following disclaimer in the 00017 * documentation and/or other materials provided with the distribution. 00018 * 3. Neither the name of the Institute nor the names of its contributors 00019 * may be used to endorse or promote products derived from this software 00020 * without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00026 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00027 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00028 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00029 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00031 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00032 * SUCH DAMAGE. 00033 * 00034 * This file is part of the Contiki operating system. 00035 * 00036 * $Id: mesh.c,v 1.20 2009/12/18 14:57:15 nvt-se Exp $ 00037 */ 00038 00039 /** 00040 * \file 00041 * A mesh routing protocol 00042 * \author 00043 * Adam Dunkels <adam@sics.se> 00044 */ 00045 00046 #include "contiki.h" 00047 #include "net/rime.h" 00048 #include "net/rime/route.h" 00049 #include "net/rime/mesh.h" 00050 00051 #include <stddef.h> /* For offsetof */ 00052 00053 #define PACKET_TIMEOUT (CLOCK_SECOND * 10) 00054 00055 #define DEBUG 0 00056 #if DEBUG 00057 #include <stdio.h> 00058 #define PRINTF(...) printf(__VA_ARGS__) 00059 #else 00060 #define PRINTF(...) 00061 #endif 00062 00063 /*---------------------------------------------------------------------------*/ 00064 static void 00065 data_packet_received(struct multihop_conn *multihop, 00066 const rimeaddr_t *from, 00067 const rimeaddr_t *prevhop, uint8_t hops) 00068 { 00069 struct mesh_conn *c = (struct mesh_conn *) 00070 ((char *)multihop - offsetof(struct mesh_conn, multihop)); 00071 00072 struct route_entry *rt; 00073 00074 /* Refresh the route when we hear a packet from a neighbor. */ 00075 rt = route_lookup(from); 00076 if(rt != NULL) { 00077 route_refresh(rt); 00078 } 00079 00080 if(c->cb->recv) { 00081 c->cb->recv(c, from, hops); 00082 } 00083 } 00084 /*---------------------------------------------------------------------------*/ 00085 static rimeaddr_t * 00086 data_packet_forward(struct multihop_conn *multihop, 00087 const rimeaddr_t *originator, 00088 const rimeaddr_t *dest, 00089 const rimeaddr_t *prevhop, uint8_t hops) 00090 { 00091 struct route_entry *rt; 00092 struct mesh_conn *c = (struct mesh_conn *) 00093 ((char *)multihop - offsetof(struct mesh_conn, multihop)); 00094 00095 rt = route_lookup(dest); 00096 if(rt == NULL) { 00097 if(c->queued_data != NULL) { 00098 queuebuf_free(c->queued_data); 00099 } 00100 00101 PRINTF("data_packet_forward: queueing data, sending rreq\n"); 00102 c->queued_data = queuebuf_new_from_packetbuf(); 00103 rimeaddr_copy(&c->queued_data_dest, dest); 00104 route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT); 00105 00106 return NULL; 00107 } else { 00108 route_refresh(rt); 00109 } 00110 00111 return &rt->nexthop; 00112 } 00113 /*---------------------------------------------------------------------------*/ 00114 static void 00115 found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest) 00116 { 00117 struct route_entry *rt; 00118 struct mesh_conn *c = (struct mesh_conn *) 00119 ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn)); 00120 00121 PRINTF("found_route\n"); 00122 00123 if(c->queued_data != NULL && 00124 rimeaddr_cmp(dest, &c->queued_data_dest)) { 00125 queuebuf_to_packetbuf(c->queued_data); 00126 queuebuf_free(c->queued_data); 00127 c->queued_data = NULL; 00128 00129 rt = route_lookup(dest); 00130 if (rt != NULL) { 00131 multihop_resend(&c->multihop, &rt->nexthop); 00132 c->cb->sent(c); 00133 } else { 00134 c->cb->timedout(c); 00135 } 00136 } 00137 } 00138 /*---------------------------------------------------------------------------*/ 00139 static void 00140 route_timed_out(struct route_discovery_conn *rdc) 00141 { 00142 struct mesh_conn *c = (struct mesh_conn *) 00143 ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn)); 00144 00145 if(c->queued_data != NULL) { 00146 queuebuf_free(c->queued_data); 00147 c->queued_data = NULL; 00148 } 00149 00150 if(c->cb->timedout) { 00151 c->cb->timedout(c); 00152 } 00153 } 00154 /*---------------------------------------------------------------------------*/ 00155 static const struct multihop_callbacks data_callbacks = { data_packet_received, 00156 data_packet_forward }; 00157 static const struct route_discovery_callbacks route_discovery_callbacks = 00158 { found_route, route_timed_out }; 00159 /*---------------------------------------------------------------------------*/ 00160 void 00161 mesh_open(struct mesh_conn *c, uint16_t channels, 00162 const struct mesh_callbacks *callbacks) 00163 { 00164 route_init(); 00165 multihop_open(&c->multihop, channels, &data_callbacks); 00166 route_discovery_open(&c->route_discovery_conn, 00167 CLOCK_SECOND * 2, 00168 channels + 1, 00169 &route_discovery_callbacks); 00170 c->cb = callbacks; 00171 } 00172 /*---------------------------------------------------------------------------*/ 00173 void 00174 mesh_close(struct mesh_conn *c) 00175 { 00176 multihop_close(&c->multihop); 00177 route_discovery_close(&c->route_discovery_conn); 00178 } 00179 /*---------------------------------------------------------------------------*/ 00180 int 00181 mesh_send(struct mesh_conn *c, const rimeaddr_t *to) 00182 { 00183 int could_send; 00184 00185 PRINTF("%d.%d: mesh_send to %d.%d\n", 00186 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00187 to->u8[0], to->u8[1]); 00188 00189 could_send = multihop_send(&c->multihop, to); 00190 00191 if(!could_send) { 00192 PRINTF("mesh_send: could not send\n"); 00193 return 0; 00194 } 00195 c->cb->sent(c); 00196 return 1; 00197 } 00198 /*---------------------------------------------------------------------------*/ 00199 /** @} */