Contiki 2.5
uip-over-mesh.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  * $Id: uip-over-mesh.c,v 1.19 2010/03/31 09:38:42 fros4943 Exp $
32  */
33 
34 /**
35  * \file
36  * Code for tunnelling uIP packets over the Rime mesh routing module
37  * \author
38  * Adam Dunkels <adam@sics.se>
39  */
40 
41 #include <stdio.h>
42 
43 #include "net/hc.h"
44 #include "net/uip-fw.h"
45 #include "net/uip-over-mesh.h"
47 #include "net/rime/route.h"
48 #include "net/rime/trickle.h"
49 
50 #define ROUTE_TRICKLE_INTERVAL CLOCK_SECOND * 32
51 #define ROUTE_DISCOVERY_INTERVAL CLOCK_SECOND * 4
52 #define ROUTE_TIMEOUT CLOCK_SECOND * 4
53 
54 static struct queuebuf *queued_packet;
55 static rimeaddr_t queued_receiver;
56 
57  /* Connection for route discovery: */
58 static struct route_discovery_conn route_discovery;
59 
60 /* Connection for sending data packets to the next hop node: */
61 static struct unicast_conn dataconn;
62 
63 /* Connection for sending gateway announcement message to the entire
64  network: */
65 static struct trickle_conn gateway_announce_conn;
66 
67 #define DEBUG 0
68 #if DEBUG
69 #include <stdio.h>
70 #define PRINTF(...) printf(__VA_ARGS__)
71 #else
72 #define PRINTF(...)
73 #endif
74 
75 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
76 
77 static struct uip_fw_netif *gw_netif;
78 static rimeaddr_t gateway;
79 static uip_ipaddr_t netaddr, netmask;
80 
81 /*---------------------------------------------------------------------------*/
82 static void
83 recv_data(struct unicast_conn *c, const rimeaddr_t *from)
84 {
85  struct route_entry *e;
86  rimeaddr_t source;
87 
89 
90  source.u8[0] = BUF->srcipaddr.u8[2];
91  source.u8[1] = BUF->srcipaddr.u8[3];
92 
93  e = route_lookup(&source);
94  if(e == NULL) {
95  route_add(&source, from, 10, 0);
96  } else {
97  route_refresh(e);
98  }
99 
100  /* If we received data via a gateway, we refresh the gateway route.
101  * Note: we refresh OUR gateway route, although we are not sure it forwarded the data. */
102  if(!uip_ipaddr_maskcmp(&BUF->srcipaddr, &netaddr, &netmask)) {
103  e = route_lookup(&gateway);
104  if(e != NULL) {
105  route_refresh(e);
106  }
107  }
108 
109  /* uip_len = hc_inflate(&uip_buf[UIP_LLH_LEN], uip_len);*/
110 
111  PRINTF("uip-over-mesh: %d.%d: recv_data with len %d\n",
113  tcpip_input();
114 }
115 /*---------------------------------------------------------------------------*/
116 static void
117 send_data(rimeaddr_t *next)
118 {
119  PRINTF("uip-over-mesh: %d.%d: send_data with len %d\n",
121  packetbuf_totlen());
122  unicast_send(&dataconn, next);
123 }
124 /*---------------------------------------------------------------------------*/
125 static void
126 new_route(struct route_discovery_conn *c, const rimeaddr_t *to)
127 {
128  struct route_entry *rt;
129 
130  if(queued_packet) {
131  PRINTF("uip-over-mesh: new route, sending queued packet\n");
132 
133  queuebuf_to_packetbuf(queued_packet);
134  queuebuf_free(queued_packet);
135  queued_packet = NULL;
136 
137  rt = route_lookup(&queued_receiver);
138  if(rt) {
139  route_decay(rt);
140  send_data(&queued_receiver);
141  }
142  }
143 }
144 /*---------------------------------------------------------------------------*/
145 static void
146 timedout(struct route_discovery_conn *c)
147 {
148  PRINTF("uip-over-mesh: packet timed out\n");
149  if(queued_packet) {
150  PRINTF("uip-over-mesh: freeing queued packet\n");
151  queuebuf_free(queued_packet);
152  queued_packet = NULL;
153  }
154 }
155 /*---------------------------------------------------------------------------*/
156 static const struct unicast_callbacks data_callbacks = { recv_data };
157 static const struct route_discovery_callbacks rdc = { new_route, timedout };
158 /*---------------------------------------------------------------------------*/
159 struct gateway_msg {
160  rimeaddr_t gateway;
161 };
162 
163 static uint8_t is_gateway;
164 
165 static void
166 gateway_announce_recv(struct trickle_conn *c)
167 {
168  struct gateway_msg *msg;
169  msg = packetbuf_dataptr();
170  PRINTF("%d.%d: gateway message: %d.%d\n",
172  msg->gateway.u8[0], msg->gateway.u8[1]);
173 
174  if(!is_gateway) {
175  uip_over_mesh_set_gateway(&msg->gateway);
176  }
177 
178 }
179 /*---------------------------------------------------------------------------*/
180 void
181 uip_over_mesh_make_announced_gateway(void)
182 {
183  struct gateway_msg msg;
184  /* Make this node the gateway node, unless it already is the
185  gateway. */
186  if(!is_gateway) {
187  PRINTF("%d.%d: making myself the gateway\n",
189  uip_over_mesh_set_gateway(&rimeaddr_node_addr);
190  rimeaddr_copy(&(msg.gateway), &rimeaddr_node_addr);
191  packetbuf_copyfrom(&msg, sizeof(struct gateway_msg));
192  trickle_send(&gateway_announce_conn);
193  is_gateway = 1;
194  }
195 }
196 const static struct trickle_callbacks trickle_call = {gateway_announce_recv};
197 /*---------------------------------------------------------------------------*/
198 void
199 uip_over_mesh_init(u16_t channels)
200 {
201 
202  PRINTF("Our address is %d.%d (%d.%d.%d.%d)\n",
204  uip_hostaddr.u8[0], uip_hostaddr.u8[1],
205  uip_hostaddr.u8[2], uip_hostaddr.u8[3]);
206 
207  unicast_open(&dataconn, channels, &data_callbacks);
208  route_discovery_open(&route_discovery, ROUTE_DISCOVERY_INTERVAL,
209  channels + 1, &rdc);
210  trickle_open(&gateway_announce_conn, ROUTE_TRICKLE_INTERVAL, channels + 3,
211  &trickle_call);
212 
213  route_init();
214  /* Set lifetime to 30 seconds for non-refreshed routes. */
215  route_set_lifetime(30);
216 }
217 /*---------------------------------------------------------------------------*/
218 u8_t
219 uip_over_mesh_send(void)
220 {
221  rimeaddr_t receiver;
222  struct route_entry *rt;
223 
224  /* This function is called by the uip-fw module to send out an IP
225  packet. We try to send the IP packet to the next hop route, or we
226  queue the packet and send out a route request for the final
227  receiver of the packet. */
228 
229  /* Packets destined to this network is sent using mesh, whereas
230  packets destined to a network outside this network is sent towards
231  the gateway node. */
232 
233  if(uip_ipaddr_maskcmp(&BUF->destipaddr, &netaddr, &netmask)) {
234  receiver.u8[0] = BUF->destipaddr.u8[2];
235  receiver.u8[1] = BUF->destipaddr.u8[3];
236  } else {
237  if(rimeaddr_cmp(&gateway, &rimeaddr_node_addr)) {
238  PRINTF("uip_over_mesh_send: I am gateway, packet to %d.%d.%d.%d to local interface\n",
239  uip_ipaddr_to_quad(&BUF->destipaddr));
240  if(gw_netif != NULL) {
241  return gw_netif->output();
242  }
243  return UIP_FW_DROPPED;
244  } else if(rimeaddr_cmp(&gateway, &rimeaddr_null)) {
245  PRINTF("uip_over_mesh_send: No gateway setup, dropping packet\n");
246  return UIP_FW_OK;
247  } else {
248  PRINTF("uip_over_mesh_send: forwarding packet to %d.%d.%d.%d towards gateway %d.%d\n",
249  uip_ipaddr_to_quad(&BUF->destipaddr),
250  gateway.u8[0], gateway.u8[1]);
251  rimeaddr_copy(&receiver, &gateway);
252  }
253  }
254 
255  PRINTF("uIP over mesh send to %d.%d with len %d\n",
256  receiver.u8[0], receiver.u8[1],
257  uip_len);
258 
259  /* uip_len = hc_compress(&uip_buf[UIP_LLH_LEN], uip_len);*/
260 
262 
263  /* Send TCP data with the PACKETBUF_ATTR_ERELIABLE set so that
264  an underlying power-saving MAC layer knows that it should be
265  waiting for an ACK. */
266  if(BUF->proto == UIP_PROTO_TCP) {
267  packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1);
268  packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
269  /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/
270  }
271 
272  rt = route_lookup(&receiver);
273  if(rt == NULL) {
274  PRINTF("uIP over mesh no route to %d.%d\n", receiver.u8[0], receiver.u8[1]);
275  if(queued_packet == NULL) {
276  queued_packet = queuebuf_new_from_packetbuf();
277  rimeaddr_copy(&queued_receiver, &receiver);
278  route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
279  } else if(!rimeaddr_cmp(&queued_receiver, &receiver)) {
280  route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
281  }
282  } else {
283  route_decay(rt);
284  send_data(&rt->nexthop);
285  }
286  return UIP_FW_OK;
287 }
288 /*---------------------------------------------------------------------------*/
289 void
290 uip_over_mesh_set_gateway_netif(struct uip_fw_netif *n)
291 {
292  gw_netif = n;
293 }
294 /*---------------------------------------------------------------------------*/
295 void
296 uip_over_mesh_set_gateway(rimeaddr_t *gw)
297 {
298  rimeaddr_copy(&gateway, gw);
299 }
300 /*---------------------------------------------------------------------------*/
301 void
302 uip_over_mesh_set_net(uip_ipaddr_t *addr, uip_ipaddr_t *mask)
303 {
304  uip_ipaddr_copy(&netaddr, addr);
305  uip_ipaddr_copy(&netmask, mask);
306 }
307 /*---------------------------------------------------------------------------*/