Contiki 2.5
mesh.c
Go to the documentation of this file.
1 /**
2  * \addtogroup rimemesh
3  * @{
4  */
5 
6 /*
7  * Copyright (c) 2007, Swedish Institute of Computer Science.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in the
17  * documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the Institute nor the names of its contributors
19  * may be used to endorse or promote products derived from this software
20  * without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * This file is part of the Contiki operating system.
35  *
36  * $Id: mesh.c,v 1.20 2009/12/18 14:57:15 nvt-se Exp $
37  */
38 
39 /**
40  * \file
41  * A mesh routing protocol
42  * \author
43  * Adam Dunkels <adam@sics.se>
44  */
45 
46 #include "contiki.h"
47 #include "net/rime.h"
48 #include "net/rime/route.h"
49 #include "net/rime/mesh.h"
50 
51 #include <stddef.h> /* For offsetof */
52 
53 #define PACKET_TIMEOUT (CLOCK_SECOND * 10)
54 
55 #define DEBUG 0
56 #if DEBUG
57 #include <stdio.h>
58 #define PRINTF(...) printf(__VA_ARGS__)
59 #else
60 #define PRINTF(...)
61 #endif
62 
63 /*---------------------------------------------------------------------------*/
64 static void
65 data_packet_received(struct multihop_conn *multihop,
66  const rimeaddr_t *from,
67  const rimeaddr_t *prevhop, uint8_t hops)
68 {
69  struct mesh_conn *c = (struct mesh_conn *)
70  ((char *)multihop - offsetof(struct mesh_conn, multihop));
71 
72  struct route_entry *rt;
73 
74  /* Refresh the route when we hear a packet from a neighbor. */
75  rt = route_lookup(from);
76  if(rt != NULL) {
77  route_refresh(rt);
78  }
79 
80  if(c->cb->recv) {
81  c->cb->recv(c, from, hops);
82  }
83 }
84 /*---------------------------------------------------------------------------*/
85 static rimeaddr_t *
86 data_packet_forward(struct multihop_conn *multihop,
87  const rimeaddr_t *originator,
88  const rimeaddr_t *dest,
89  const rimeaddr_t *prevhop, uint8_t hops)
90 {
91  struct route_entry *rt;
92  struct mesh_conn *c = (struct mesh_conn *)
93  ((char *)multihop - offsetof(struct mesh_conn, multihop));
94 
95  rt = route_lookup(dest);
96  if(rt == NULL) {
97  if(c->queued_data != NULL) {
98  queuebuf_free(c->queued_data);
99  }
100 
101  PRINTF("data_packet_forward: queueing data, sending rreq\n");
102  c->queued_data = queuebuf_new_from_packetbuf();
103  rimeaddr_copy(&c->queued_data_dest, dest);
104  route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT);
105 
106  return NULL;
107  } else {
108  route_refresh(rt);
109  }
110 
111  return &rt->nexthop;
112 }
113 /*---------------------------------------------------------------------------*/
114 static void
115 found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest)
116 {
117  struct route_entry *rt;
118  struct mesh_conn *c = (struct mesh_conn *)
119  ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));
120 
121  PRINTF("found_route\n");
122 
123  if(c->queued_data != NULL &&
124  rimeaddr_cmp(dest, &c->queued_data_dest)) {
125  queuebuf_to_packetbuf(c->queued_data);
126  queuebuf_free(c->queued_data);
127  c->queued_data = NULL;
128 
129  rt = route_lookup(dest);
130  if (rt != NULL) {
131  multihop_resend(&c->multihop, &rt->nexthop);
132  c->cb->sent(c);
133  } else {
134  c->cb->timedout(c);
135  }
136  }
137 }
138 /*---------------------------------------------------------------------------*/
139 static void
140 route_timed_out(struct route_discovery_conn *rdc)
141 {
142  struct mesh_conn *c = (struct mesh_conn *)
143  ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));
144 
145  if(c->queued_data != NULL) {
146  queuebuf_free(c->queued_data);
147  c->queued_data = NULL;
148  }
149 
150  if(c->cb->timedout) {
151  c->cb->timedout(c);
152  }
153 }
154 /*---------------------------------------------------------------------------*/
155 static const struct multihop_callbacks data_callbacks = { data_packet_received,
156  data_packet_forward };
157 static const struct route_discovery_callbacks route_discovery_callbacks =
158  { found_route, route_timed_out };
159 /*---------------------------------------------------------------------------*/
160 void
161 mesh_open(struct mesh_conn *c, uint16_t channels,
162  const struct mesh_callbacks *callbacks)
163 {
164  route_init();
165  multihop_open(&c->multihop, channels, &data_callbacks);
166  route_discovery_open(&c->route_discovery_conn,
167  CLOCK_SECOND * 2,
168  channels + 1,
169  &route_discovery_callbacks);
170  c->cb = callbacks;
171 }
172 /*---------------------------------------------------------------------------*/
173 void
174 mesh_close(struct mesh_conn *c)
175 {
176  multihop_close(&c->multihop);
177  route_discovery_close(&c->route_discovery_conn);
178 }
179 /*---------------------------------------------------------------------------*/
180 int
181 mesh_send(struct mesh_conn *c, const rimeaddr_t *to)
182 {
183  int could_send;
184 
185  PRINTF("%d.%d: mesh_send to %d.%d\n",
187  to->u8[0], to->u8[1]);
188 
189  could_send = multihop_send(&c->multihop, to);
190 
191  if(!could_send) {
192  PRINTF("mesh_send: could not send\n");
193  return 0;
194  }
195  c->cb->sent(c);
196  return 1;
197 }
198 /*---------------------------------------------------------------------------*/
199 /** @} */