Contiki 2.6

uip-over-mesh.c

Go to the documentation of this file.
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 /*---------------------------------------------------------------------------*/