Contiki 3.x
route-discovery.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  */
32 
33 /**
34  * \file
35  * Route discovery protocol
36  * \author
37  * Adam Dunkels <adam@sics.se>
38  */
39 
40 /**
41  * \addtogroup routediscovery
42  * @{
43  */
44 
45 #include "contiki.h"
46 #include "net/rime/rime.h"
47 #include "net/rime/route.h"
49 
50 #include <stddef.h> /* For offsetof */
51 #include <stdio.h>
52 
53 struct route_msg {
54  linkaddr_t dest;
55  uint8_t rreq_id;
56  uint8_t pad;
57 };
58 
59 struct rrep_hdr {
60  uint8_t rreq_id;
61  uint8_t hops;
62  linkaddr_t dest;
63  linkaddr_t originator;
64 };
65 
66 #if CONTIKI_TARGET_NETSIM
67 #include "ether.h"
68 #endif
69 
70 
71 #define DEBUG 0
72 #if DEBUG
73 #include <stdio.h>
74 #define PRINTF(...) printf(__VA_ARGS__)
75 #else
76 #define PRINTF(...)
77 #endif
78 
79 /*---------------------------------------------------------------------------*/
80 static char rrep_pending; /* A reply for a request is pending. */
81 /*---------------------------------------------------------------------------*/
82 static void
83 send_rreq(struct route_discovery_conn *c, const linkaddr_t *dest)
84 {
85  linkaddr_t dest_copy;
86  struct route_msg *msg;
87 
88  linkaddr_copy(&dest_copy, dest);
89  dest = &dest_copy;
90 
92  msg = packetbuf_dataptr();
93  packetbuf_set_datalen(sizeof(struct route_msg));
94 
95  msg->pad = 0;
96  msg->rreq_id = c->rreq_id;
97  linkaddr_copy(&msg->dest, dest);
98 
99  netflood_send(&c->rreqconn, c->rreq_id);
100  c->rreq_id++;
101 }
102 /*---------------------------------------------------------------------------*/
103 static void
104 send_rrep(struct route_discovery_conn *c, const linkaddr_t *dest)
105 {
106  struct rrep_hdr *rrepmsg;
107  struct route_entry *rt;
108  linkaddr_t saved_dest;
109 
110  linkaddr_copy(&saved_dest, dest);
111 
112  packetbuf_clear();
113  dest = &saved_dest;
114  rrepmsg = packetbuf_dataptr();
115  packetbuf_set_datalen(sizeof(struct rrep_hdr));
116  rrepmsg->hops = 0;
117  linkaddr_copy(&rrepmsg->dest, dest);
118  linkaddr_copy(&rrepmsg->originator, &linkaddr_node_addr);
119  rt = route_lookup(dest);
120  if(rt != NULL) {
121  PRINTF("%d.%d: send_rrep to %d.%d via %d.%d\n",
123  dest->u8[0],dest->u8[1],
124  rt->nexthop.u8[0],rt->nexthop.u8[1]);
125  unicast_send(&c->rrepconn, &rt->nexthop);
126  } else {
127  PRINTF("%d.%d: no route for rrep to %d.%d\n",
129  dest->u8[0],dest->u8[1]);
130  }
131 }
132 /*---------------------------------------------------------------------------*/
133 static void
134 insert_route(const linkaddr_t *originator, const linkaddr_t *last_hop,
135  uint8_t hops)
136 {
137  PRINTF("%d.%d: Inserting %d.%d into routing table, next hop %d.%d, hop count %d\n",
139  originator->u8[0], originator->u8[1],
140  last_hop->u8[0], last_hop->u8[1],
141  hops);
142 
143  route_add(originator, last_hop, hops, 0);
144  /*
145  struct route_entry *rt;
146 
147  rt = route_lookup(originator);
148  if(rt == NULL || hops < rt->hop_count) {
149  PRINTF("%d.%d: Inserting %d.%d into routing table, next hop %d.%d, hop count %d\n",
150  linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1],
151  originator->u8[0], originator->u8[1],
152  last_hop->u8[0], last_hop->u8[1],
153  hops);
154  route_add(originator, last_hop, hops, 0);
155 #if CONTIKI_TARGET_NETSIM
156  ether_set_line(last_hop->u8[0], last_hop->u8[1]);
157 #endif
158 
159 }*/
160 }
161 /*---------------------------------------------------------------------------*/
162 static void
163 rrep_packet_received(struct unicast_conn *uc, const linkaddr_t *from)
164 {
165  struct rrep_hdr *msg = packetbuf_dataptr();
166  struct route_entry *rt;
167  linkaddr_t dest;
168  struct route_discovery_conn *c = (struct route_discovery_conn *)
169  ((char *)uc - offsetof(struct route_discovery_conn, rrepconn));
170 
171  PRINTF("%d.%d: rrep_packet_received from %d.%d towards %d.%d len %d\n",
173  from->u8[0],from->u8[1],
174  msg->dest.u8[0],msg->dest.u8[1],
176 
177  PRINTF("from %d.%d hops %d rssi %d lqi %d\n",
178  from->u8[0], from->u8[1],
179  msg->hops,
180  packetbuf_attr(PACKETBUF_ATTR_RSSI),
181  packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));
182 
183  insert_route(&msg->originator, from, msg->hops);
184 
185  if(linkaddr_cmp(&msg->dest, &linkaddr_node_addr)) {
186  PRINTF("rrep for us!\n");
187  rrep_pending = 0;
188  ctimer_stop(&c->t);
189  if(c->cb->new_route) {
190  linkaddr_t originator;
191 
192  /* If the callback modifies the packet, the originator address
193  will be lost. Therefore, we need to copy it into a local
194  variable before calling the callback. */
195  linkaddr_copy(&originator, &msg->originator);
196  c->cb->new_route(c, &originator);
197  }
198 
199  } else {
200  linkaddr_copy(&dest, &msg->dest);
201 
202  rt = route_lookup(&msg->dest);
203  if(rt != NULL) {
204  PRINTF("forwarding to %d.%d\n", rt->nexthop.u8[0], rt->nexthop.u8[1]);
205  msg->hops++;
206  unicast_send(&c->rrepconn, &rt->nexthop);
207  } else {
208  PRINTF("%d.%d: no route to %d.%d\n", linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], msg->dest.u8[0], msg->dest.u8[1]);
209  }
210  }
211 }
212 /*---------------------------------------------------------------------------*/
213 static int
214 rreq_packet_received(struct netflood_conn *nf, const linkaddr_t *from,
215  const linkaddr_t *originator, uint8_t seqno, uint8_t hops)
216 {
217  struct route_msg *msg = packetbuf_dataptr();
218  struct route_discovery_conn *c = (struct route_discovery_conn *)
219  ((char *)nf - offsetof(struct route_discovery_conn, rreqconn));
220 
221  PRINTF("%d.%d: rreq_packet_received from %d.%d hops %d rreq_id %d last %d.%d/%d\n",
223  from->u8[0], from->u8[1],
224  hops, msg->rreq_id,
225  c->last_rreq_originator.u8[0],
226  c->last_rreq_originator.u8[1],
227  c->last_rreq_id);
228 
229  if(!(linkaddr_cmp(&c->last_rreq_originator, originator) &&
230  c->last_rreq_id == msg->rreq_id)) {
231 
232  PRINTF("%d.%d: rreq_packet_received: request for %d.%d originator %d.%d / %d\n",
234  msg->dest.u8[0], msg->dest.u8[1],
235  originator->u8[0], originator->u8[1],
236  msg->rreq_id);
237 
238  linkaddr_copy(&c->last_rreq_originator, originator);
239  c->last_rreq_id = msg->rreq_id;
240 
241  if(linkaddr_cmp(&msg->dest, &linkaddr_node_addr)) {
242  PRINTF("%d.%d: route_packet_received: route request for our address\n",
244  PRINTF("from %d.%d hops %d rssi %d lqi %d\n",
245  from->u8[0], from->u8[1],
246  hops,
247  packetbuf_attr(PACKETBUF_ATTR_RSSI),
248  packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));
249 
250  insert_route(originator, from, hops);
251 
252  /* Send route reply back to source. */
253  send_rrep(c, originator);
254  return 0; /* Don't continue to flood the rreq packet. */
255  } else {
256  /* PRINTF("route request for %d\n", msg->dest_id);*/
257  PRINTF("from %d.%d hops %d rssi %d lqi %d\n",
258  from->u8[0], from->u8[1],
259  hops,
260  packetbuf_attr(PACKETBUF_ATTR_RSSI),
261  packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));
262  insert_route(originator, from, hops);
263  }
264 
265  return 1;
266  }
267  return 0; /* Don't forward packet. */
268 }
269 /*---------------------------------------------------------------------------*/
270 static const struct unicast_callbacks rrep_callbacks = {rrep_packet_received};
271 static const struct netflood_callbacks rreq_callbacks = {rreq_packet_received, NULL, NULL};
272 /*---------------------------------------------------------------------------*/
273 void
274 route_discovery_explicit_open(struct route_discovery_conn *c,
275  clock_time_t time,
276  uint16_t netflood_channel,
277  uint16_t unicast_channel,
278  const struct route_discovery_callbacks *callbacks)
279 {
280  netflood_open(&c->rreqconn, time, netflood_channel, &rreq_callbacks);
281  unicast_open(&c->rrepconn, unicast_channel, &rrep_callbacks);
282  c->cb = callbacks;
283 }
284 /*---------------------------------------------------------------------------*/
285 void
286 route_discovery_open(struct route_discovery_conn *c,
287  clock_time_t time,
288  uint16_t channels,
289  const struct route_discovery_callbacks *callbacks)
290 {
291  route_discovery_explicit_open(c, time, channels + 0, channels + 1, callbacks);
292 }
293 /*---------------------------------------------------------------------------*/
294 void
295 route_discovery_close(struct route_discovery_conn *c)
296 {
297  unicast_close(&c->rrepconn);
298  netflood_close(&c->rreqconn);
299  ctimer_stop(&c->t);
300 }
301 /*---------------------------------------------------------------------------*/
302 static void
303 timeout_handler(void *ptr)
304 {
305  struct route_discovery_conn *c = ptr;
306  PRINTF("route_discovery: timeout, timed out\n");
307  rrep_pending = 0;
308  if(c->cb->timedout) {
309  c->cb->timedout(c);
310  }
311 }
312 /*---------------------------------------------------------------------------*/
313 int
314 route_discovery_discover(struct route_discovery_conn *c, const linkaddr_t *addr,
315  clock_time_t timeout)
316 {
317  if(rrep_pending) {
318  PRINTF("route_discovery_send: ignoring request because of pending response\n");
319  return 0;
320  }
321 
322  PRINTF("route_discovery_send: sending route request\n");
323  ctimer_set(&c->t, timeout, timeout_handler, c);
324  rrep_pending = 1;
325  send_rreq(c, addr);
326  return 1;
327 }
328 /*---------------------------------------------------------------------------*/
329 /** @} */
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:158
static uip_ds6_addr_t * addr
Pointer to a router list entry.
Definition: uip-nd6.c:124
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:76
Header file for the Rime mesh routing protocol
Header file for the Rime stack
#define NULL
The null pointer.
Header file for the Rime route table
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:151
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:170
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:149
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
Definition: linkaddr.c:66
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48