Contiki 2.5
ethernode.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: ethernode.c,v 1.18 2010/06/14 19:19:17 adamdunkels Exp $
34  */
35 /**
36  * \file
37  * uIP virtual network interface using UDP tunnels.
38  * \author Adam Dunkels
39  *
40  */
41 
42 #include "net/ethernode.h"
43 #include "net/uip_arch.h"
44 #include "net/uip-fw.h"
45 #include "ether.h"
46 
47 #include "dev/radio.h"
48 #include "net/netstack.h"
49 #include "net/packetbuf.h"
50 
51 #include "node.h"
52 
53 #include "lib/random.h"
54 
55 #include <stdio.h>
56 #include <sys/select.h>
57 #include <unistd.h>
58 
59 #include "net/ethernode.h"
60 
61 #define BUF ((uip_tcpip_hdr *)&uip_buf[HDR_LEN])
62 
63 #define PRINTF(...)
64 /*#define PRINTF(x) printf x; fflush(NULL)*/
65 
66 struct {
67  u8_t id;
68  int timer;
69  u8_t seqno;
70 } state;
71 
72 #define TYPE_DATA 1
73 #define TYPE_ACK 2
74 
75 struct hdr {
76  u8_t type;
77  u8_t src;
78  u8_t dest;
79  u8_t seqno;
80 };
81 
82 static int radio_is_on = 1;
83 
84 /*---------------------------------------------------------------------------*/
85 static int
86 ethernode_on(void)
87 {
88  radio_is_on = 1;
89  ether_set_radio_status(radio_is_on);
90 
91  return 1;
92 }
93 /*---------------------------------------------------------------------------*/
94 static int
95 ethernode_safe_off(void)
96 {
97  radio_is_on = 0;
98  ether_set_radio_status(radio_is_on);
99  return 1;
100 }
101 /*---------------------------------------------------------------------------*/
102 static int
103 channel_clear(void)
104 {
105  return 1;
106 }
107 /*---------------------------------------------------------------------------*/
108 static int
109 receiving(void)
110 {
111  return 0;
112 }
113 /*---------------------------------------------------------------------------*/
114 static int
115 pending(void)
116 {
117  return 0;
118 }
119 /*---------------------------------------------------------------------------*/
120 
121 
122 #define HDR_LEN UIP_LLH_LEN
123 
124 #define ID_BROADCAST 0x80
125 
126 PROCESS(ethernode_process, "Ethernode");
127 /*-------------------------------------------------------------------------------*/
128 static u8_t
129 do_send(u8_t type, u8_t dest, struct hdr *hdr, int len)
130 {
131 
132  hdr->type = type;
133  hdr->src = state.id;
134 
135  hdr->dest = dest;
136 
137  hdr->seqno = state.seqno;
138 
139  ++state.seqno;
140 
141  PRINTF("ether_send len %d\n", len);
142  return ether_send((char *)hdr, len);
143 
144 }
145 /*-------------------------------------------------------------------------------*/
146 /**
147  * Initialize the virtual UDP tunnel network interface.
148  *
149  * \param sid The ID number of this node.
150  *
151  */
152 /*-------------------------------------------------------------------------------*/
153 void
154 ethernode_init(int port)
155 {
156  ether_client_init(port);
157 
158  do {
159  state.id = random_rand() & 0x7f;
160  } while(state.id == ID_BROADCAST);
161 
162  state.seqno = 0;
163 }
164 /*-------------------------------------------------------------------------------*/
165 /**
166  * Poll the network device to see if a packet has arrived.
167  *
168  * \return The length of the incoming packet, or zero if no packet was
169  * found.
170  */
171 /*-------------------------------------------------------------------------------*/
172 int
174 {
175  return ether_client_poll();
176 }
177 /*-------------------------------------------------------------------------------*/
178 int
179 ethernode_read(void *buf, unsigned short bufsize)
180 {
181  int len;
182  u8_t tmpbuf[2048];
183  struct hdr *hdr = (struct hdr *)tmpbuf;
184 
185  len = ether_client_read(tmpbuf, sizeof(tmpbuf));
186  if(len == 0) {
187  return 0;
188  }
189 
190  if(radio_is_on == 0) {
191  /* Drop the incoming packet if the simulated radio is switched off. */
192  return 0;
193  }
194  /* printf("ethernode_poll: received data packet with len %d type %d\n", len, hdr->type);*/
195 
196  switch(hdr->type) {
197  case TYPE_DATA:
198  if(hdr->dest == state.id ||
199  hdr->dest == ID_BROADCAST) {
200  memcpy(buf, tmpbuf + HDR_LEN, bufsize);
201  return len - HDR_LEN;
202  }
203  break;
204  case TYPE_ACK:
205  printf("<%d>: Received ack packet from %d\n", state.id, hdr->src);
206  break;
207  default:
208  printf("<%d>: Received unknown packet type %d from %d\n", state.id, hdr->type, hdr->src);
209  break;
210  }
211 
212  return 0;
213 
214 }
215 /*-------------------------------------------------------------------------------*/
216 /**
217  * Send a packet from the uip_buf buffer over the UDP tunnel.
218  *
219  *
220  * \retval UIP_FW_TOOLARGE A transmission of packet that was too large was attempted.
221  *
222  * \retval UIP_FW_DROPPED The packet is known to be dropped.
223  *
224  * \retval UIP_FW_OK The packet was transmitted.
225  */
226 /*-------------------------------------------------------------------------------*/
227 u8_t
229 {
230  int len;
231  static char tmpbuf[2048];
232  struct hdr *hdr = (struct hdr *)tmpbuf;
233  u8_t dest;
234  struct timeval tv;
235 
236  if(uip_len > sizeof(tmpbuf)) {
237  PRINTF(("Ethernode_send: too large uip_len %d\n", uip_len));
238  return UIP_FW_TOOLARGE;
239  }
240 
241  memcpy(&tmpbuf[HDR_LEN], &uip_buf[HDR_LEN], uip_len);
242  len = uip_len + HDR_LEN;
243 
244  dest = ID_BROADCAST;
245  tv.tv_sec = 0;
246  tv.tv_usec = (random_rand() % 1000);
247  select(0, NULL, NULL, NULL, &tv);
248 
249  do_send(TYPE_DATA, dest, hdr, len);
250 
251  return UIP_FW_OK;
252 }
253 /*-------------------------------------------------------------------------------*/
254 static char tmpbuf[2048];
255 static struct hdr *hdr = (struct hdr *)tmpbuf;
256 static u8_t dest;
257 
258 static int
259 prepare(const void *buf, unsigned short len)
260 {
261  memcpy(&tmpbuf[HDR_LEN], buf, len);
262  len = len + HDR_LEN;
263 
264  dest = ID_BROADCAST;
265  return len;
266 }
267 /*-------------------------------------------------------------------------------*/
268 static int
269 transmit(unsigned short len)
270 {
271  do_send(TYPE_DATA, dest, hdr, len + HDR_LEN);
272  return RADIO_TX_OK;
273 }
274 /*-------------------------------------------------------------------------------*/
275 static int
276 send(const void *payload, unsigned short payload_len)
277 {
278  prepare(payload, payload_len);
279  return transmit(payload_len);
280 }
281 /*---------------------------------------------------------------------------*/
282 PROCESS_THREAD(ethernode_process, ev, data)
283 {
284  int len;
285  PROCESS_BEGIN();
286 
287  while(1) {
288  process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL);
289  PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE);
290 
291  len = ethernode_poll();
292  if(len > 0) {
293 
294  packetbuf_clear();
295  len = ethernode_read(packetbuf_dataptr(), PACKETBUF_SIZE);
296  if(len > 0) {
298  NETSTACK_RDC.input();
299  }
300 
301  /* if(receiver_callback) {
302  receiver_callback(&ethernode_driver);
303  }*/
304  }
305  }
306  PROCESS_END();
307 }
308 /*-------------------------------------------------------------------------------*/
309 const struct radio_driver ethernode_driver =
310  {
311  (int (*)(void))ethernode_init,
312  prepare,
313  transmit,
314  send,
315  ethernode_read,
317  receiving,
318  pending,
319  ethernode_on,
320  ethernode_safe_off,
321  };
322 
323