Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2007, 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: uip-over-mesh.c,v 1.19 2010/03/31 09:38:42 fros4943 Exp $ 00032 */ 00033 00034 /** 00035 * \file 00036 * Code for tunnelling uIP packets over the Rime mesh routing module 00037 * \author 00038 * Adam Dunkels <adam@sics.se> 00039 */ 00040 00041 #include <stdio.h> 00042 00043 #include "net/hc.h" 00044 #include "net/uip-fw.h" 00045 #include "net/uip-over-mesh.h" 00046 #include "net/rime/route-discovery.h" 00047 #include "net/rime/route.h" 00048 #include "net/rime/trickle.h" 00049 00050 #define ROUTE_TRICKLE_INTERVAL CLOCK_SECOND * 32 00051 #define ROUTE_DISCOVERY_INTERVAL CLOCK_SECOND * 4 00052 #define ROUTE_TIMEOUT CLOCK_SECOND * 4 00053 00054 static struct queuebuf *queued_packet; 00055 static rimeaddr_t queued_receiver; 00056 00057 /* Connection for route discovery: */ 00058 static struct route_discovery_conn route_discovery; 00059 00060 /* Connection for sending data packets to the next hop node: */ 00061 static struct unicast_conn dataconn; 00062 00063 /* Connection for sending gateway announcement message to the entire 00064 network: */ 00065 static struct trickle_conn gateway_announce_conn; 00066 00067 #define DEBUG 0 00068 #if DEBUG 00069 #include <stdio.h> 00070 #define PRINTF(...) printf(__VA_ARGS__) 00071 #else 00072 #define PRINTF(...) 00073 #endif 00074 00075 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) 00076 00077 static struct uip_fw_netif *gw_netif; 00078 static rimeaddr_t gateway; 00079 static uip_ipaddr_t netaddr, netmask; 00080 00081 /*---------------------------------------------------------------------------*/ 00082 static void 00083 recv_data(struct unicast_conn *c, const rimeaddr_t *from) 00084 { 00085 struct route_entry *e; 00086 rimeaddr_t source; 00087 00088 uip_len = packetbuf_copyto(&uip_buf[UIP_LLH_LEN]); 00089 00090 source.u8[0] = BUF->srcipaddr.u8[2]; 00091 source.u8[1] = BUF->srcipaddr.u8[3]; 00092 00093 e = route_lookup(&source); 00094 if(e == NULL) { 00095 route_add(&source, from, 10, 0); 00096 } else { 00097 route_refresh(e); 00098 } 00099 00100 /* If we received data via a gateway, we refresh the gateway route. 00101 * Note: we refresh OUR gateway route, although we are not sure it forwarded the data. */ 00102 if(!uip_ipaddr_maskcmp(&BUF->srcipaddr, &netaddr, &netmask)) { 00103 e = route_lookup(&gateway); 00104 if(e != NULL) { 00105 route_refresh(e); 00106 } 00107 } 00108 00109 /* uip_len = hc_inflate(&uip_buf[UIP_LLH_LEN], uip_len);*/ 00110 00111 PRINTF("uip-over-mesh: %d.%d: recv_data with len %d\n", 00112 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], uip_len); 00113 tcpip_input(); 00114 } 00115 /*---------------------------------------------------------------------------*/ 00116 static void 00117 send_data(rimeaddr_t *next) 00118 { 00119 PRINTF("uip-over-mesh: %d.%d: send_data with len %d\n", 00120 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00121 packetbuf_totlen()); 00122 unicast_send(&dataconn, next); 00123 } 00124 /*---------------------------------------------------------------------------*/ 00125 static void 00126 new_route(struct route_discovery_conn *c, const rimeaddr_t *to) 00127 { 00128 struct route_entry *rt; 00129 00130 if(queued_packet) { 00131 PRINTF("uip-over-mesh: new route, sending queued packet\n"); 00132 00133 queuebuf_to_packetbuf(queued_packet); 00134 queuebuf_free(queued_packet); 00135 queued_packet = NULL; 00136 00137 rt = route_lookup(&queued_receiver); 00138 if(rt) { 00139 route_decay(rt); 00140 send_data(&queued_receiver); 00141 } 00142 } 00143 } 00144 /*---------------------------------------------------------------------------*/ 00145 static void 00146 timedout(struct route_discovery_conn *c) 00147 { 00148 PRINTF("uip-over-mesh: packet timed out\n"); 00149 if(queued_packet) { 00150 PRINTF("uip-over-mesh: freeing queued packet\n"); 00151 queuebuf_free(queued_packet); 00152 queued_packet = NULL; 00153 } 00154 } 00155 /*---------------------------------------------------------------------------*/ 00156 static const struct unicast_callbacks data_callbacks = { recv_data }; 00157 static const struct route_discovery_callbacks rdc = { new_route, timedout }; 00158 /*---------------------------------------------------------------------------*/ 00159 struct gateway_msg { 00160 rimeaddr_t gateway; 00161 }; 00162 00163 static uint8_t is_gateway; 00164 00165 static void 00166 gateway_announce_recv(struct trickle_conn *c) 00167 { 00168 struct gateway_msg *msg; 00169 msg = packetbuf_dataptr(); 00170 PRINTF("%d.%d: gateway message: %d.%d\n", 00171 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00172 msg->gateway.u8[0], msg->gateway.u8[1]); 00173 00174 if(!is_gateway) { 00175 uip_over_mesh_set_gateway(&msg->gateway); 00176 } 00177 00178 } 00179 /*---------------------------------------------------------------------------*/ 00180 void 00181 uip_over_mesh_make_announced_gateway(void) 00182 { 00183 struct gateway_msg msg; 00184 /* Make this node the gateway node, unless it already is the 00185 gateway. */ 00186 if(!is_gateway) { 00187 PRINTF("%d.%d: making myself the gateway\n", 00188 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); 00189 uip_over_mesh_set_gateway(&rimeaddr_node_addr); 00190 rimeaddr_copy(&(msg.gateway), &rimeaddr_node_addr); 00191 packetbuf_copyfrom(&msg, sizeof(struct gateway_msg)); 00192 trickle_send(&gateway_announce_conn); 00193 is_gateway = 1; 00194 } 00195 } 00196 const static struct trickle_callbacks trickle_call = {gateway_announce_recv}; 00197 /*---------------------------------------------------------------------------*/ 00198 void 00199 uip_over_mesh_init(uint16_t channels) 00200 { 00201 00202 PRINTF("Our address is %d.%d (%d.%d.%d.%d)\n", 00203 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], 00204 uip_hostaddr.u8[0], uip_hostaddr.u8[1], 00205 uip_hostaddr.u8[2], uip_hostaddr.u8[3]); 00206 00207 unicast_open(&dataconn, channels, &data_callbacks); 00208 route_discovery_open(&route_discovery, ROUTE_DISCOVERY_INTERVAL, 00209 channels + 1, &rdc); 00210 trickle_open(&gateway_announce_conn, ROUTE_TRICKLE_INTERVAL, channels + 3, 00211 &trickle_call); 00212 00213 route_init(); 00214 /* Set lifetime to 30 seconds for non-refreshed routes. */ 00215 route_set_lifetime(30); 00216 } 00217 /*---------------------------------------------------------------------------*/ 00218 uint8_t 00219 uip_over_mesh_send(void) 00220 { 00221 rimeaddr_t receiver; 00222 struct route_entry *rt; 00223 00224 /* This function is called by the uip-fw module to send out an IP 00225 packet. We try to send the IP packet to the next hop route, or we 00226 queue the packet and send out a route request for the final 00227 receiver of the packet. */ 00228 00229 /* Packets destined to this network is sent using mesh, whereas 00230 packets destined to a network outside this network is sent towards 00231 the gateway node. */ 00232 00233 if(uip_ipaddr_maskcmp(&BUF->destipaddr, &netaddr, &netmask)) { 00234 receiver.u8[0] = BUF->destipaddr.u8[2]; 00235 receiver.u8[1] = BUF->destipaddr.u8[3]; 00236 } else { 00237 if(rimeaddr_cmp(&gateway, &rimeaddr_node_addr)) { 00238 PRINTF("uip_over_mesh_send: I am gateway, packet to %d.%d.%d.%d to local interface\n", 00239 uip_ipaddr_to_quad(&BUF->destipaddr)); 00240 if(gw_netif != NULL) { 00241 return gw_netif->output(); 00242 } 00243 return UIP_FW_DROPPED; 00244 } else if(rimeaddr_cmp(&gateway, &rimeaddr_null)) { 00245 PRINTF("uip_over_mesh_send: No gateway setup, dropping packet\n"); 00246 return UIP_FW_OK; 00247 } else { 00248 PRINTF("uip_over_mesh_send: forwarding packet to %d.%d.%d.%d towards gateway %d.%d\n", 00249 uip_ipaddr_to_quad(&BUF->destipaddr), 00250 gateway.u8[0], gateway.u8[1]); 00251 rimeaddr_copy(&receiver, &gateway); 00252 } 00253 } 00254 00255 PRINTF("uIP over mesh send to %d.%d with len %d\n", 00256 receiver.u8[0], receiver.u8[1], 00257 uip_len); 00258 00259 /* uip_len = hc_compress(&uip_buf[UIP_LLH_LEN], uip_len);*/ 00260 00261 packetbuf_copyfrom(&uip_buf[UIP_LLH_LEN], uip_len); 00262 00263 /* Send TCP data with the PACKETBUF_ATTR_ERELIABLE set so that 00264 an underlying power-saving MAC layer knows that it should be 00265 waiting for an ACK. */ 00266 if(BUF->proto == UIP_PROTO_TCP) { 00267 packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1); 00268 packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); 00269 /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/ 00270 } 00271 00272 rt = route_lookup(&receiver); 00273 if(rt == NULL) { 00274 PRINTF("uIP over mesh no route to %d.%d\n", receiver.u8[0], receiver.u8[1]); 00275 if(queued_packet == NULL) { 00276 queued_packet = queuebuf_new_from_packetbuf(); 00277 rimeaddr_copy(&queued_receiver, &receiver); 00278 route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT); 00279 } else if(!rimeaddr_cmp(&queued_receiver, &receiver)) { 00280 route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT); 00281 } 00282 } else { 00283 route_decay(rt); 00284 send_data(&rt->nexthop); 00285 } 00286 return UIP_FW_OK; 00287 } 00288 /*---------------------------------------------------------------------------*/ 00289 void 00290 uip_over_mesh_set_gateway_netif(struct uip_fw_netif *n) 00291 { 00292 gw_netif = n; 00293 } 00294 /*---------------------------------------------------------------------------*/ 00295 void 00296 uip_over_mesh_set_gateway(rimeaddr_t *gw) 00297 { 00298 rimeaddr_copy(&gateway, gw); 00299 } 00300 /*---------------------------------------------------------------------------*/ 00301 void 00302 uip_over_mesh_set_net(uip_ipaddr_t *addr, uip_ipaddr_t *mask) 00303 { 00304 uip_ipaddr_copy(&netaddr, addr); 00305 uip_ipaddr_copy(&netmask, mask); 00306 } 00307 /*---------------------------------------------------------------------------*/