Contiki 2.5
radio-uip-uaodv.c
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: radio-uip-uaodv.c,v 1.10 2010/10/19 18:29:05 adamdunkels Exp $
32  */
33 
34 #include "radio-uip-uaodv.h"
35 #include "net/hc.h"
36 #include "net/uip.h"
37 #include "net/uaodv.h"
38 #include "net/uaodv-rt.h"
39 #include "net/uaodv-def.h"
40 #include "lib/crc16.h"
41 #include "list.h"
42 #include <string.h>
43 #include <stdio.h>
44 
45 /* Packet buffer size and retransmission settings */
46 #define MAX_BUFFERED_PACKETS 10
47 #define MAX_RETRANSMISSIONS_RREP 16
48 #define MAX_RETRANSMISSIONS_UNICAST 16
49 
50 /* Forward packet (header) */
51 #define FWD_ID "fWd:"
52 #define FWD_ID_LENGTH 4
53 #define FWD_NEXT_IP FWD_ID_LENGTH
54 #define FWD_PACKET_LENGTH (FWD_NEXT_IP + 4)
55 
56 /* Acknowledgement packet */
57 #define ACK_ID "aCk"
58 #define ACK_ID_LENGTH 3
59 #define ACK_CRC ACK_ID_LENGTH
60 #define ACK_PACKET_LENGTH (ACK_ID_LENGTH + 2)
61 #define ACK_TIMEOUT (CLOCK_SECOND / 50) * (random_rand() % 100)
62 
63 enum {
64  EVENT_SEND_ACK
65 };
66 
67 struct buf_packet {
68  struct buf_packet *next;
69  u8_t data[UIP_BUFSIZE];
70  int len;
71  u8_t resends;
72  u8_t acked;
73  u8_t want_ack;
74  u16_t crc;
75  uip_ipaddr_t finaldest;
76  struct etimer etimer;
77 };
78 
79 LIST(buf_packet_list);
80 MEMB(buf_packet_mem, struct buf_packet, MAX_BUFFERED_PACKETS);
81 
82 PROCESS(radio_uip_process, "radio uIP uAODV process");
83 
84 static const struct radio_driver *radio;
85 
86 
87 
88 /*---------------------------------------------------------------------------*/
89 static void receiver(const struct radio_driver *d);
90 u8_t radio_uip_uaodv_send(void);
91 void radio_uip_uaodv_init(const struct radio_driver *d);
92 int radio_uip_handle_ack(u8_t *buf, int len);
93 u16_t radio_uip_calc_crc(u8_t *buf, int len);
94 int radio_uip_buffer_outgoing_packet(u8_t *buf, int len, uip_ipaddr_t *dest, int max_sends);
95 int radio_uip_is_ack(u8_t *buf, int len);
96 int radio_uip_uaodv_add_header(u8_t *buf, int len, uip_ipaddr_t *addr);
97 int radio_uip_uaodv_remove_header(u8_t *buf, int len);
98 void radio_uip_uaodv_change_header(u8_t *buf, int len, uip_ipaddr_t *addr);
99 int radio_uip_uaodv_header_exists(u8_t *buf, int len);
100 int radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr);
101 int radio_uip_uaodv_fwd_is_broadcast(u8_t *buf, int len);
102 int radio_uip_uaodv_fwd_is_me(u8_t *buf, int len);
103 int radio_uip_uaodv_dest_is_me(u8_t *buf, int len);
104 int radio_uip_uaodv_dest_port(u8_t *buf, int len);
105 /*---------------------------------------------------------------------------*/
106 
107 /* Main process - handles (re)transmissions and acks */
108 PROCESS_THREAD(radio_uip_process, ev, data)
109 {
110  struct buf_packet *packet;
111 
112  PROCESS_BEGIN();
113 
114  while(1) {
115  PROCESS_YIELD();
116 
117  if(ev == EVENT_SEND_ACK) {
118 
119  /* Prepare and send ack for given 16-bit CRC */
120  u8_t ackPacket[ACK_PACKET_LENGTH];
121  memcpy(ackPacket, ACK_ID, ACK_ID_LENGTH);
122  ackPacket[ACK_CRC] = ((u16_t) data >> 8);
123  ackPacket[ACK_CRC+1] = ((u16_t) data & 0xff);
124  radio->send(ackPacket, ACK_PACKET_LENGTH);
125 
126  } else if(ev == PROCESS_EVENT_TIMER) {
127  /* Locate which packet acknowledgement timed out */
128  for(packet = list_head(buf_packet_list);
129  packet != NULL;
130  packet = packet->next) {
131  if (etimer_expired(&packet->etimer)) {
132 
133  if (packet->acked) {
134  /* Already acked packet, remove silently */
135  list_remove(buf_packet_list, packet);
136  memb_free(&buf_packet_mem, packet);
137 
138  } else if (packet->resends > 0) {
139  /* Resend packet */
140  packet->resends--;
141  etimer_set(&packet->etimer, ACK_TIMEOUT);
142 
143  radio->send(packet->data, packet->len);
144 
145  } else {
146  /* Packet was resent maximum number of times */
147 
148  /* If an ack was expected, flag destination to bad */
149  if (packet->want_ack && !uip_ipaddr_cmp(&packet->finaldest, &uip_broadcast_addr)) {
150  uaodv_bad_dest(&packet->finaldest);
151  }
152 
153  list_remove(buf_packet_list, packet);
154  memb_free(&buf_packet_mem, packet);
155  }
156  }
157  }
158  }
159  }
160  PROCESS_END();
161 }
162 /*---------------------------------------------------------------------------*/
163 static void
164 receiver(const struct radio_driver *d)
165 {
166  uip_len = d->read(&uip_buf[UIP_LLH_LEN], UIP_BUFSIZE - UIP_LLH_LEN);
167  if (uip_len <= 0) {
168  return;
169  }
170 
171  /* Detect and handle acknowledgements */
172  if (radio_uip_is_ack(&uip_buf[UIP_LLH_LEN], uip_len)) {
173  radio_uip_handle_ack(&uip_buf[UIP_LLH_LEN], uip_len);
174  return;
175  }
176 
177  /* If no uAODV header, receive as usual */
178  if (!radio_uip_uaodv_header_exists(&uip_buf[UIP_LLH_LEN], uip_len)) {
179  tcpip_input();
180  return;
181  }
182 
183  /* Drop packet unless we are the uAODV forwarder */
184  if (!radio_uip_uaodv_fwd_is_me(&uip_buf[UIP_LLH_LEN], uip_len)) {
185  return;
186  }
187 
188  {
189  /* Send ack as soon as possible */
190  u16_t crc;
191  crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len);
192  process_post(&radio_uip_process, EVENT_SEND_ACK, (void*) (u32_t) crc);
193  }
194 
195  /* Strip header and receive packet */
196  uip_len = radio_uip_uaodv_remove_header(&uip_buf[UIP_LLH_LEN], uip_len);
197  tcpip_input();
198 }
199 /*---------------------------------------------------------------------------*/
200 u8_t
201 radio_uip_uaodv_send(void)
202 {
203  struct uaodv_rt_entry *route;
204 
205  /* Transmit broadcast packets without header */
206  if (radio_uip_uaodv_is_broadcast(&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr)) {
207  return radio_uip_buffer_outgoing_packet(&uip_buf[UIP_LLH_LEN], uip_len, (void*) &uip_broadcast_addr, 1);
208  }
209 
210  /* Transmit uAODV packets with headers but without using route table */
211  if (((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->proto == UIP_PROTO_UDP
212  && radio_uip_uaodv_dest_port(&uip_buf[UIP_LLH_LEN], uip_len) == UIP_HTONS(UAODV_UDPPORT)) {
213  uip_ipaddr_t nexthop;
214  memcpy(&nexthop, &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr, 4);
215 
216  uip_len = radio_uip_uaodv_add_header(
217  &uip_buf[UIP_LLH_LEN],
218  uip_len,
219  &nexthop
220  );
221 
222  /* Buffer packet for persistent transmission */
223  return radio_uip_buffer_outgoing_packet(
224  &uip_buf[UIP_LLH_LEN],
225  uip_len,
226  &((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN + FWD_PACKET_LENGTH])->destipaddr,
227  MAX_RETRANSMISSIONS_RREP);
228  }
229 
230  /* Fetch already prepared uAODV route */
231  route = uaodv_rt_lookup_any((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr));
232  if (route == NULL || route->is_bad) {
233 
234  /* If we are forwarding, notify origin of this bad route */
235  if (tcpip_is_forwarding) {
236  uaodv_bad_dest((&((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])->destipaddr));
237  }
238 
239  return UIP_FW_DROPPED;
240  }
241 
242  /* Add header and buffer packet for persistent transmission */
243  uip_len = radio_uip_uaodv_add_header(&uip_buf[UIP_LLH_LEN], uip_len, &route->nexthop); /* TODO Correct? */
244  return radio_uip_buffer_outgoing_packet(
245  &uip_buf[UIP_LLH_LEN],
246  uip_len,
247  &route->dest,
248  MAX_RETRANSMISSIONS_UNICAST);
249 }
250 /*---------------------------------------------------------------------------*/
251 void
252 radio_uip_uaodv_init(const struct radio_driver *d)
253 {
254  /* Prepare buffers and start main process */
255  memb_init(&buf_packet_mem);
256  list_init(buf_packet_list);
257  process_start(&radio_uip_process, NULL);
258 
259  radio = d;
260  radio->set_receive_function(receiver);
261  radio->on();
262 }
263 /*---------------------------------------------------------------------------*/
264 u16_t
265 radio_uip_calc_crc(u8_t *buf, int len)
266 {
267  u16_t crcacc = 0xffff;
268  int counter;
269 
270  /* TODO Not effective */
271  for (counter = 0; counter < len; counter++) {
272  crcacc = crc16_add(buf[counter], crcacc);
273  }
274  return crcacc;
275 }
276 /*---------------------------------------------------------------------------*/
277 int
278 radio_uip_buffer_outgoing_packet(u8_t *buf, int len, uip_ipaddr_t *dest, int max_sends)
279 {
280  struct buf_packet *packet;
281 
282  u16_t crc;
283 
284  /* Calculate packet's unique CRC */
285  crc = radio_uip_calc_crc(&uip_buf[UIP_LLH_LEN], uip_len);
286 
287  /* Check if this packet is already being transmitted */
288  for(packet = list_head(buf_packet_list);
289  packet != NULL;
290  packet = packet->next) {
291  if (packet->crc == crc) {
292  return UIP_FW_DROPPED;
293  }
294  }
295 
296  /* Allocate storage memory */
297  packet = (struct buf_packet *)memb_alloc(&buf_packet_mem);
298  if (packet == NULL) {
299  return UIP_FW_DROPPED;
300  }
301 
302  /* Prepare packet buffer */
303  memcpy(packet->data, buf, len);
304  packet->len = len;
305  packet->resends = max_sends;
306  packet->acked = 0;
307  if (packet->resends > 1)
308  packet->want_ack = 1;
309  else
310  packet->want_ack = 0;
311  memcpy(&packet->finaldest, dest, 4);
312  packet->crc = crc;
313 
314  /* Set first transmission to as soon as possible */
315  PROCESS_CONTEXT_BEGIN(&radio_uip_process);
316  etimer_set(&packet->etimer, 0);
317  PROCESS_CONTEXT_END(&radio_uip_process);
318 
319  /* Add to buffered packets list */
320  list_add(buf_packet_list, packet);
321 
322  return UIP_FW_OK;
323 }
324 /*---------------------------------------------------------------------------*/
325 int
326 radio_uip_is_ack(u8_t *buf, int len)
327 {
328  if (len != ACK_PACKET_LENGTH)
329  return 0;
330 
331  return memcmp(buf, ACK_ID, ACK_ID_LENGTH) == 0;
332 
333 }
334 /*---------------------------------------------------------------------------*/
335 int
336 radio_uip_handle_ack(u8_t *buf, int len)
337 {
338  struct buf_packet *packet;
339  u16_t ackCRC;
340 
341  ackCRC = (u16_t) (buf[ACK_CRC] << 8) + (u16_t) (0xff&buf[ACK_CRC+1]);
342 
343  /* Locate which packet was acknowledged */
344  for(packet = list_head(buf_packet_list);
345  packet != NULL;
346  packet = packet->next) {
347  if (packet->crc == ackCRC) {
348  /* Signal packet has been acknowledged */
349  packet->acked = 1;
350  return 0;
351  }
352  }
353 
354  return 1;
355 }
356 /*---------------------------------------------------------------------------*/
357 int
358 radio_uip_uaodv_add_header(u8_t *buf, int len, uip_ipaddr_t *addr)
359 {
360  u8_t tempbuf[len];
361  memcpy(tempbuf, buf, len);
362  memcpy(&buf[FWD_PACKET_LENGTH], tempbuf, len);
363  memcpy(buf, FWD_ID, FWD_ID_LENGTH);
364  memcpy(&buf[FWD_NEXT_IP], (char*)addr, 4);
365  return FWD_PACKET_LENGTH + len;
366 }
367 /*---------------------------------------------------------------------------*/
368 int
369 radio_uip_uaodv_remove_header(u8_t *buf, int len)
370 {
371  u8_t tempbuf[len];
372  memcpy(tempbuf, &buf[FWD_PACKET_LENGTH], len);
373  memcpy(buf, tempbuf, len);
374  return len - FWD_PACKET_LENGTH;
375 }
376 /*---------------------------------------------------------------------------*/
377 void
378 radio_uip_uaodv_change_header(u8_t *buf, int len, uip_ipaddr_t *addr)
379 {
380  memcpy(&buf[FWD_NEXT_IP], addr, 4);
381 }
382 /*---------------------------------------------------------------------------*/
383 int
384 radio_uip_uaodv_header_exists(u8_t *buf, int len)
385 {
386  return !memcmp(buf, FWD_ID, FWD_ID_LENGTH);
387 }
388 /*---------------------------------------------------------------------------*/
389 int
390 radio_uip_uaodv_is_broadcast(uip_ipaddr_t *addr)
391 {
392  return uip_ipaddr_cmp(addr, &uip_broadcast_addr);
393 }
394 /*---------------------------------------------------------------------------*/
395 int
396 radio_uip_uaodv_fwd_is_broadcast(u8_t *buf, int len)
397 {
398  return radio_uip_uaodv_is_broadcast((uip_ipaddr_t*) &buf[FWD_NEXT_IP]);
399 }
400 /*---------------------------------------------------------------------------*/
401 int
402 radio_uip_uaodv_fwd_is_me(u8_t *buf, int len)
403 {
404  return !memcmp(&buf[FWD_NEXT_IP], &uip_hostaddr, 4);
405 }
406 /*---------------------------------------------------------------------------*/
407 int
408 radio_uip_uaodv_dest_is_me(u8_t *buf, int len)
409 {
410  return !memcmp((&((struct uip_udpip_hdr *)buf)->destipaddr), &uip_hostaddr, 4);
411 }
412 /*---------------------------------------------------------------------------*/
413 int
414 radio_uip_uaodv_dest_port(u8_t *buf, int len)
415 {
416  if (len < sizeof(struct uip_udpip_hdr))
417  return -1;
418  return (int) ((struct uip_udpip_hdr *)buf)->destport;
419 }
420 /*---------------------------------------------------------------------------*/