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_open(struct route_discovery_conn *c,
275  clock_time_t time,
276  uint16_t channels,
277  const struct route_discovery_callbacks *callbacks)
278 {
279  netflood_open(&c->rreqconn, time, channels + 0, &rreq_callbacks);
280  unicast_open(&c->rrepconn, channels + 1, &rrep_callbacks);
281  c->cb = callbacks;
282 }
283 /*---------------------------------------------------------------------------*/
284 void
285 route_discovery_close(struct route_discovery_conn *c)
286 {
287  unicast_close(&c->rrepconn);
288  netflood_close(&c->rreqconn);
289  ctimer_stop(&c->t);
290 }
291 /*---------------------------------------------------------------------------*/
292 static void
293 timeout_handler(void *ptr)
294 {
295  struct route_discovery_conn *c = ptr;
296  PRINTF("route_discovery: timeout, timed out\n");
297  rrep_pending = 0;
298  if(c->cb->timedout) {
299  c->cb->timedout(c);
300  }
301 }
302 /*---------------------------------------------------------------------------*/
303 int
304 route_discovery_discover(struct route_discovery_conn *c, const linkaddr_t *addr,
305  clock_time_t timeout)
306 {
307  if(rrep_pending) {
308  PRINTF("route_discovery_send: ignoring request because of pending response\n");
309  return 0;
310  }
311 
312  PRINTF("route_discovery_send: sending route request\n");
313  ctimer_set(&c->t, timeout, timeout_handler, c);
314  rrep_pending = 1;
315  send_rreq(c, addr);
316  return 1;
317 }
318 /*---------------------------------------------------------------------------*/
319 /** @} */
linkaddr_t linkaddr_node_addr
The Rime address of the node.
Definition: linkaddr.c:48
#define NULL
The null pointer.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
Definition: packetbuf.c:200
Header file for the Rime stack
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
Definition: packetbuf.c:239
void linkaddr_copy(linkaddr_t *dest, const linkaddr_t *src)
Copy a Rime address.
Definition: linkaddr.c:60
void ctimer_set(struct ctimer *c, clock_time_t t, void(*f)(void *), void *ptr)
Set a callback timer.
Definition: ctimer.c:99
Header file for the Rime mesh routing protocol
void packetbuf_clear(void)
Clear and reset the packetbuf.
Definition: packetbuf.c:77
int linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two Rime addresses.
Definition: linkaddr.c:66
void * packetbuf_dataptr(void)
Get a pointer to the data in the packetbuf.
Definition: packetbuf.c:207
void ctimer_stop(struct ctimer *c)
Stop a pending callback timer.
Definition: ctimer.c:142
Header file for the Rime route table