Contiki 2.5
ether.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2004, 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  * Author: Adam Dunkels <adam@sics.se>
32  *
33  * $Id: ether.c,v 1.17 2010/10/19 18:29:05 adamdunkels Exp $
34  */
35 /**
36  * \file
37  * This module implements a simple "ether", into which datapackets can
38  * be injected. The packets are delivered to all nodes that are in
39  * transmission range.
40  *
41  * \author Adam Dunkels <adam@sics.se>
42  *
43  */
44 
45 #include <sys/types.h>
46 #include <sys/socket.h>
47 #include <sys/time.h>
48 #include <unistd.h>
49 #include <stdlib.h>
50 #include <stdio.h>
51 #include <string.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54 
55 #include <errno.h>
56 
57 #include "ether.h"
58 #include "lib/memb.h"
59 #include "lib/list.h"
60 #include "nodes.h"
61 
62 #include "dev/radio-sensor.h"
63 
64 #include "dev/serial-line.h"
65 
66 #include "sensor.h"
67 
68 #include "node.h"
69 #include "net/uip.h"
70 #include "net/uip-fw.h"
71 
72 #ifndef NULL
73 #define NULL 0
74 #endif /* NULL */
75 
76 MEMB(packets, struct ether_packet, 20000);
77 LIST(active_packets);
78 
79 static u8_t rxbuffer[2048];
80 static clock_time_t timer;
81 
82 #define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
83 
84 #define PRINTF(...)
85 /*#define PRINTF(x) printf x*/
86 
87 static int s, sc;
88 
89 #define PTYPE_NONE 0
90 #define PTYPE_CLOCK 1
91 #define PTYPE_DATA 2
92 #define PTYPE_SENSOR 3
93 #define PTYPE_LEDS 4
94 #define PTYPE_TEXT 5
95 #define PTYPE_DONE 6
96 #define PTYPE_SERIAL 7
97 #define PTYPE_RADIO_STATUS 8
98 
99 #define SERIAL_LEN 80
100 
101 struct ether_hdr {
102  int type;
103  struct sensor_data sensor_data;
104  clock_time_t clock;
105  int linex, liney;
106  int signal;
107  int srcx, srcy;
108  int srcpid;
109  int srcid;
110  int srcnodetype;
111  int leds;
112  int radio_status;
113  char text[NODES_TEXTLEN + SERIAL_LEN];
114 };
115 
116 static int strength;
117 
118 static int collisions = 1;
119 static int num_collisions = 0;
120 static int num_sent = 0;
121 static int num_received = 0;
122 static int drop_probability = 0;
123 static int num_drops = 0;
124 
125 #include <sys/time.h>
126 
127 static struct timeval t1;
128 
129 static int linex, liney;
130 
131 /*-----------------------------------------------------------------------------------*/
132 void
133 ether_print_stats(void)
134 {
135  unsigned long time;
136  struct timeval t2;
137  gettimeofday(&t2, NULL);
138 
139  time = (t2.tv_sec * 1000 + t2.tv_usec / 1000) -
140  (t1.tv_sec * 1000 + t1.tv_usec / 1000);
141  /* printf("%d, %d, %f\n", num_packets, num_collisions, time/1000.0);*/
142  printf("Time: %f\n", time/1000.0);
143  printf("Total packets sent: %d\n", num_sent);
144  printf("Total collisions: %d\n", num_collisions);
145  printf("Total packets receptions: %d\n", num_received);
146  printf("Total randomly dropped packets: %d\n", num_drops);
147 }
148 /*-----------------------------------------------------------------------------------*/
149 void
150 ether_set_drop_probability(double p)
151 {
152  drop_probability = p * 65536;
153 }
154 /*-----------------------------------------------------------------------------------*/
155 void
156 ether_set_collisions(int c)
157 {
158  collisions = c;
159 }
160 /*-----------------------------------------------------------------------------------*/
161 void
162 ether_set_strength(int s)
163 {
164  strength = s;
165 }
166 /*-----------------------------------------------------------------------------------*/
167 int
168 ether_strength(void)
169 {
170  return strength;
171 }
172 /*-----------------------------------------------------------------------------------*/
173 void
174 ether_server_init(void)
175 {
176  struct sockaddr_in sa;
177 
178  gettimeofday(&t1, NULL);
179 
180  memb_init(&packets);
181  list_init(active_packets);
182 
183  timer = 0;
184 
185  s = socket(AF_INET,SOCK_DGRAM,0);
186 
187  if(s < 0) {
188  perror("ether_server_init: socket");
189  }
190 
191  memset((char *)&sa, 0, sizeof(sa));
192 
193  sa.sin_family = AF_INET;
194  sa.sin_addr.s_addr = inet_addr("127.0.0.1");/*uip_htonl(INADDR_ANY);*/
195 
196  sa.sin_port = uip_htons(ETHER_PORT);
197 
198  /* printf("Binding to port %d\n", ETHER_PORT);*/
199 
200  if(bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
201  printf("Bind to port %d\n", ETHER_PORT);
202  perror("bind");
203  exit(1);
204  }
205 
206 }
207 /*-----------------------------------------------------------------------------------*/
208 void
209 ether_client_init(int port)
210 {
211  struct sockaddr_in sa;
212 
213  sc = socket(AF_INET,SOCK_DGRAM,0);
214 
215  if(sc < 0) {
216  perror("socket");
217  }
218 
219  memset((char *)&sa, 0, sizeof(sa));
220 
221  sa.sin_family = AF_INET;
222  sa.sin_addr.s_addr = inet_addr("127.0.0.1");/*uip_htonl(INADDR_ANY);*/
223 
224  sa.sin_port = uip_htons(port);
225 
226  /* printf("ether_client_init: binding to port %d\n", port);*/
227  if(bind(sc, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
228  printf("Bind to port %d\n", port);
229  perror("bind");
230  exit(1);
231  }
232 }
233 /*-----------------------------------------------------------------------------------*/
234 int
235 ether_client_poll(void)
236 {
237  fd_set fdset;
238  struct timeval tv;
239  int ret;
240 
241  FD_ZERO(&fdset);
242  FD_SET(sc, &fdset);
243 
244  tv.tv_sec = 0;
245  tv.tv_usec = 1000;
246 
247  ret = select(sc + 1, &fdset, NULL, NULL, &tv);
248 
249  if(ret < 0) {
250  perror("ether_client_poll: select");
251  }
252  return ret == 1;
253 }
254 /*-----------------------------------------------------------------------------------*/
255 u16_t
256 ether_client_read(u8_t *buf, int bufsize)
257 {
258  int ret, len;
259  fd_set fdset;
260  struct timeval tv;
261  struct ether_hdr *hdr = (struct ether_hdr *)rxbuffer;
262 
263  FD_ZERO(&fdset);
264  FD_SET(sc, &fdset);
265 
266  tv.tv_sec = 0;
267  tv.tv_usec = 10000;
268 
269  ret = select(sc + 1, &fdset, NULL, NULL, &tv);
270 
271  if(ret == 0) {
272  /* printf("ret 0\n");*/
273  return 0;
274  }
275  if(FD_ISSET(sc, &fdset)) {
276  ret = recv(sc, &rxbuffer[0], sizeof(rxbuffer), 0);
277  if(ret == -1) {
278  perror("ether_client_poll: recv");
279  return 0;
280  }
281  len = ret;
282 
283  if(len > bufsize) {
284  PRINTF("ether_client_read: packet truncated from %d to %d\n",
285  len, bufsize);
286  len = bufsize;
287  }
288 
289  /* printf("Incoming len %d\n", len);*/
290  memcpy(buf, &rxbuffer[sizeof(struct ether_hdr)], len);
291  radio_sensor_signal = hdr->signal;
292 
293  if(hdr->type == PTYPE_DATA && hdr->srcid != node.id) {
294  return len - sizeof(struct ether_hdr);
295  } else if(hdr->type == PTYPE_CLOCK) {
296  node_set_time(hdr->clock);
297  } else if(hdr->type == PTYPE_SENSOR) {
298  int strength = sensor_strength() -
299  ((hdr->srcx - node_x()) * (hdr->srcx - node_x()) +
300  (hdr->srcy - node_y()) * (hdr->srcy - node_y())) / sensor_strength();
301  /* printf("Dist %d \n", strength);*/
302  if(strength > 0) {
303  sensor_input(&hdr->sensor_data, strength);
304  }
305  } else if(hdr->type == PTYPE_SERIAL) {
306  char *ptr = hdr->text;
307  printf("serial input %s\n", ptr);
308  for(ptr = hdr->text; *ptr != 0; ++ptr) {
309  serial_line_input_byte(*ptr);
310  }
311  }
312  }
313  return 0;
314 }
315 /*-----------------------------------------------------------------------------------*/
316 void
317 ether_server_poll(void)
318 {
319  int ret;
320  fd_set fdset;
321  struct timeval tv;
322  struct ether_hdr *hdr = (struct ether_hdr *)rxbuffer;
323  /* struct timeval rtime1, rtime2;
324  struct timespec ts;
325  struct timezone tz;*/
326 
327 
328  tv.tv_sec = 0;
329  tv.tv_usec = 100;
330 
331 
332  do {
333  FD_ZERO(&fdset);
334  FD_SET(s, &fdset);
335 
336  ret = select(s + 1, &fdset, NULL, NULL, &tv);
337  if(ret == 0) {
338  return;
339  }
340  if(FD_ISSET(s, &fdset)) {
341  ret = recv(s, &rxbuffer[0], sizeof(rxbuffer), 0);
342  if(ret == -1) {
343  perror("ether_poll: read");
344  return;
345  }
346  nodes_set_line(hdr->srcx, hdr->srcy, hdr->linex, hdr->liney);
347  switch(hdr->type) {
348  case PTYPE_DATA:
349  PRINTF("ether_poll: read %d bytes from (%d, %d)\n",
350  ret, hdr->srcx, hdr->srcy);
351  ether_put((char *)rxbuffer, ret, hdr->srcx, hdr->srcy);
352  break;
353  case PTYPE_LEDS:
354  nodes_set_leds(hdr->srcx, hdr->srcy, hdr->leds);
355  break;
356  case PTYPE_TEXT:
357  nodes_set_text(hdr->srcx, hdr->srcy, hdr->text);
358  break;
359  case PTYPE_DONE:
360  nodes_done(hdr->srcid);
361  break;
362  case PTYPE_SERIAL:
363  break;
364  case PTYPE_RADIO_STATUS:
365  nodes_set_radio_status(hdr->srcx, hdr->srcy, hdr->radio_status);
366  break;
367  }
368  }
369  /* tv.tv_sec = 0;
370  tv.tv_usec = 1;*/
371 
372  } while(1/*ret > 0*/);
373 }
374 /*-----------------------------------------------------------------------------------*/
375 void
376 ether_put(char *data, int len, int x, int y)
377 {
378  struct ether_packet *p;
379 
380  /* printf("ether_put: packet len %d at (%d, %d)\n", len, x, y);*/
381 
382  p = (struct ether_packet *)memb_alloc(&packets);
383 
384  if(p != NULL) {
385  if(len > 1500) {
386  len = 1500;
387  }
388  memcpy(p->data, data, len);
389  p->len = len;
390  p->x = x;
391  p->y = y;
392  list_push(active_packets, p);
393 
394 
395  }
396 }
397 /*-----------------------------------------------------------------------------------*/
398 static void
399 send_packet(char *data, int len, int port)
400 {
401  struct sockaddr_in sa;
402 
403  memset((char *)&sa, 0, sizeof(sa));
404  sa.sin_family = AF_INET;
405  sa.sin_addr.s_addr = inet_addr("127.0.0.1");
406  sa.sin_port = uip_htons(port);
407 
408  if(sendto(s, data, len, 0, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
409  perror("ether: send_packet: sendto");
410  }
411 }
412 /*-----------------------------------------------------------------------------------*/
413 void
414 ether_tick(void)
415 {
416  struct ether_packet *p, *q;
417  struct ether_hdr *hdr;
418  int port;
419  int x, y;
420  int i;
421  int interference;
422 
423  /* Go through every node and see if there are any packets destined
424  to them. If two or more packets are sent in the vicinity of the
425  node, they interfere with each otehr and none reaches the
426  node. */
427  for(i = 0; i < nodes_num(); ++i) {
428 
429  x = nodes_node(i)->x;
430  y = nodes_node(i)->y;
431  port = nodes_node(i)->port;
432 
433  /* Go through all active packets to see if anyone is sent within
434  range of this node. */
435  for(p = list_head(active_packets); p != NULL; p = p->next) {
436 
437  num_sent++;
438 
439  /* Update the node type. */
440  hdr = (struct ether_hdr *)p->data;
441  /* nodes_node(hdr->srcid)->type = hdr->srcnodetype;*/
442 
443  if(!(p->x == x && p->y == y) && /* Don't send packets back to
444  the sender. */
445  (p->x - x) * (p->x - x) +
446  (p->y - y) * (p->y - y) <=
447  ether_strength() * ether_strength()) {
448 
449  hdr->signal = ether_strength() * ether_strength() -
450  (p->x - x) * (p->x - x) -
451  (p->y - y) * (p->y - y);
452  /* This packet was sent in the reception range of this node,
453  so we check against all other packets to see if there is
454  more than one packet sent towards this node. If so, we have
455  interference and the node will not be able to receive any
456  data. */
457  interference = 0;
458  if(collisions) {
459  for(q = list_head(active_packets); q != NULL; q = q->next) {
460 
461  /* Compute the distance^2 and check against signal strength. */
462  if(p != q &&
463  ((q->x - x) * (q->x - x) +
464  (q->y - y) * (q->y - y) <=
465  ether_strength() * ether_strength())) {
466 
467  /* If the potentially interfering packets were sent from
468  the same node, then they don't interfere with each
469  other. Otherwise they interfere and we sent the
470  interference flag to 1. */
471  if(p->x != q->x ||
472  p->y != q->y) {
473  interference = 1;
474  }
475  break;
476  }
477  }
478  }
479 
480  if(interference) {
481  num_collisions++;
482  /* printf("Collisions %d\n", num_collisions);*/
483  }
484 
485  if(!interference) {
486  /* printf("ether: delivering packet from %d to %d\n",
487  hdr->srcid, port);*/
488  if((unsigned int)((rand() * 17) % 65536) >= drop_probability) {
489  send_packet(p->data, p->len, port);
490  num_received++;
491  } else {
492  num_drops++;
493  }
494  }
495  }
496 
497 
498  }
499  }
500 
501  /* Remove all packets from the active packets list. */
502  while((p = list_pop(active_packets)) != NULL) {
503  memb_free(&packets, (void *) p);
504  }
505 
506  ++timer;
507 }
508 /*-----------------------------------------------------------------------------------*/
509 struct ether_packet *
510 ether_packets(void)
511 {
512  return list_head(active_packets);
513 }
514 /*-----------------------------------------------------------------------------------*/
515 clock_time_t
516 ether_time(void)
517 {
518  return timer;
519 }
520 /*-----------------------------------------------------------------------------------*/
521 static void
522 node_send_packet(char *data, int len)
523 {
524  struct sockaddr_in sa;
525 
526  memset((char *)&sa, 0, sizeof(sa));
527  sa.sin_family = AF_INET;
528  sa.sin_addr.s_addr = inet_addr("127.0.0.1");
529  sa.sin_port = uip_htons(ETHER_PORT);
530 
531  if(sendto(sc, data, len, 0,
532  (struct sockaddr *)&sa, sizeof(sa)) == -1) {
533  perror("ether.c node_send_packet: sendto");
534  }
535 }
536 /*-----------------------------------------------------------------------------------*/
537 u8_t
538 ether_send(char *data, int len)
539 {
540  char tmpbuf[2048];
541  struct ether_hdr *hdr = (struct ether_hdr *)tmpbuf;
542 
543 
544  memcpy(&tmpbuf[sizeof(struct ether_hdr)], data, len);
545 
546  hdr->srcx = node.x;
547  hdr->srcy = node.y;
548  hdr->type = PTYPE_DATA;
549  /* hdr->srcnodetype = node.type;*/
550  hdr->srcid = node.id;
551 
552  hdr->linex = linex;
553  hdr->liney = liney;
554  node_send_packet(tmpbuf, len + sizeof(struct ether_hdr));
555 
556  return UIP_FW_OK;
557 }
558 /*-----------------------------------------------------------------------------------*/
559 void
560 ether_set_leds(int leds)
561 {
562  struct ether_hdr hdr;
563 
564  memset(&hdr, 0, sizeof (hdr));
565  hdr.srcx = node.x;
566  hdr.srcy = node.y;
567  hdr.type = PTYPE_LEDS;
568  hdr.leds = leds;
569  /* hdr.srcnodetype = node.type;*/
570  hdr.srcid = node.id;
571  hdr.linex = linex;
572  hdr.liney = liney;
573 
574  node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
575 
576 }
577 /*-----------------------------------------------------------------------------------*/
578 void
579 ether_set_text(char *text)
580 {
581  struct ether_hdr hdr;
582 
583  hdr.srcx = node.x;
584  hdr.srcy = node.y;
585  hdr.type = PTYPE_TEXT;
586  strncpy(hdr.text, text, NODES_TEXTLEN);
587  /* hdr.srcnodetype = node.type;*/
588  hdr.srcid = node.id;
589  hdr.linex = linex;
590  hdr.liney = liney;
591 
592  node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
593 
594 }
595 /*-----------------------------------------------------------------------------------*/
596 void
597 ether_set_radio_status(int onoroff)
598 {
599  struct ether_hdr hdr;
600 
601  hdr.srcx = node.x;
602  hdr.srcy = node.y;
603  hdr.type = PTYPE_RADIO_STATUS;
604  hdr.radio_status = onoroff;
605  hdr.srcid = node.id;
606  hdr.linex = linex;
607  hdr.liney = liney;
608 
609  node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
610 
611 }
612 /*-----------------------------------------------------------------------------------*/
613 void
614 ether_send_sensor_data(struct sensor_data *d, int srcx, int srcy, int strength)
615 {
616  int port;
617  int x, y;
618  int i;
619  struct ether_hdr hdr;
620 
621  /* printf("Sensor data at (%d, %d)\n", srcx, srcy);*/
622 
623  for(i = 0; i < nodes_num(); ++i) {
624 
625  x = nodes_node(i)->x;
626  y = nodes_node(i)->y;
627  port = nodes_node(i)->port;
628 
629  if((srcx - x) * (srcx - x) +
630  (srcy - y) * (srcy - y) <=
631  strength * strength) {
632 
633  hdr.srcx = srcx;
634  hdr.srcy = srcy;
635  hdr.type = PTYPE_SENSOR;
636  hdr.sensor_data = *d;
637  send_packet((char *)&hdr, sizeof(hdr), port);
638  }
639  }
640 
641 }
642 /*-----------------------------------------------------------------------------------*/
643 void
644 ether_send_done(void)
645 {
646  struct ether_hdr hdr;
647 
648  hdr.srcx = node.x;
649  hdr.srcy = node.y;
650  hdr.type = PTYPE_DONE;
651  hdr.srcid = node.id;
652 
653  node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
654 
655 }
656 /*-----------------------------------------------------------------------------------*/
657 void
658 ether_send_serial(char *str)
659 {
660  struct ether_hdr hdr;
661  int len;
662 
663 
664  hdr.srcx = node.x;
665  hdr.srcy = node.y;
666  hdr.type = PTYPE_SERIAL;
667  hdr.srcid = node.id;
668  len = strlen(str) + 1;
669  if(len > sizeof(hdr.text)) {
670  len = sizeof(hdr.text);
671  }
672  memcpy(&hdr.text, str, len);
673  hdr.text[len] = 0;
674 
675  /* printf("ether_send_serial '%s' to %d len %d\n", str, nodes_base_node_port, sizeof(struct ether_hdr));*/
676 
677  send_packet((char *)&hdr, sizeof(struct ether_hdr), nodes_base_node_port);
678 }
679 /*-----------------------------------------------------------------------------------*/
680 void
681 ether_set_line(int x, int y)
682 {
683  struct ether_hdr hdr;
684 
685  linex = x;
686  liney = y;
687 
688 
689  hdr.srcx = node.x;
690  hdr.srcy = node.y;
691  hdr.type = PTYPE_NONE;
692  hdr.srcid = node.id;
693  hdr.linex = linex;
694  hdr.liney = liney;
695 
696  node_send_packet((char *)&hdr, sizeof(struct ether_hdr));
697 }
698 /*-----------------------------------------------------------------------------------*/