ethernode.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2004, Swedish Institute of Computer Science.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  * Author: Adam Dunkels <adam@sics.se>
00032  *
00033  * $Id: ethernode.c,v 1.18 2010/06/14 19:19:17 adamdunkels Exp $
00034  */
00035 /**
00036  * \file
00037  * uIP virtual network interface using UDP tunnels.
00038  * \author Adam Dunkels
00039  *
00040  */
00041 
00042 #include "net/ethernode.h"
00043 #include "net/uip_arch.h"
00044 #include "net/uip-fw.h"
00045 #include "ether.h"
00046 
00047 #include "dev/radio.h"
00048 #include "net/netstack.h"
00049 #include "net/packetbuf.h"
00050 
00051 #include "node.h"
00052 
00053 #include "lib/random.h"
00054 
00055 #include <stdio.h>
00056 #include <sys/select.h>
00057 #include <unistd.h>
00058 
00059 #include "net/ethernode.h"
00060 
00061 #define BUF ((uip_tcpip_hdr *)&uip_buf[HDR_LEN])
00062 
00063 #define PRINTF(...)
00064 /*#define PRINTF(x) printf x; fflush(NULL)*/
00065 
00066 struct {
00067   u8_t id;
00068   int timer;
00069   u8_t seqno;
00070 } state;
00071 
00072 #define TYPE_DATA      1
00073 #define TYPE_ACK       2
00074 
00075 struct hdr {
00076   u8_t type;
00077   u8_t src;
00078   u8_t dest;
00079   u8_t seqno;
00080 };
00081 
00082 static int radio_is_on = 1;
00083 
00084 /*---------------------------------------------------------------------------*/
00085 static int
00086 ethernode_on(void)
00087 {
00088   radio_is_on = 1;
00089   ether_set_radio_status(radio_is_on);
00090 
00091   return 1;
00092 }
00093 /*---------------------------------------------------------------------------*/
00094 static int
00095 ethernode_safe_off(void)
00096 {
00097   radio_is_on = 0;
00098   ether_set_radio_status(radio_is_on);
00099   return 1;
00100 }
00101 /*---------------------------------------------------------------------------*/
00102 static int
00103 channel_clear(void)
00104 {
00105   return 1;
00106 }
00107 /*---------------------------------------------------------------------------*/
00108 static int
00109 receiving(void)
00110 {
00111   return 0;
00112 }
00113 /*---------------------------------------------------------------------------*/
00114 static int
00115 pending(void)
00116 {
00117   return 0;
00118 }
00119 /*---------------------------------------------------------------------------*/
00120 
00121 
00122 #define HDR_LEN UIP_LLH_LEN
00123 
00124 #define ID_BROADCAST 0x80
00125 
00126 PROCESS(ethernode_process, "Ethernode");
00127 /*-------------------------------------------------------------------------------*/
00128 static u8_t
00129 do_send(u8_t type, u8_t dest, struct hdr *hdr, int len)
00130 {
00131   
00132   hdr->type = type;
00133   hdr->src = state.id;
00134 
00135   hdr->dest = dest;
00136 
00137   hdr->seqno = state.seqno;
00138 
00139   ++state.seqno;
00140 
00141   PRINTF("ether_send len %d\n", len);
00142   return ether_send((char *)hdr, len);
00143   
00144 }
00145 /*-------------------------------------------------------------------------------*/
00146 /**
00147  * Initialize the virtual UDP tunnel network interface.
00148  *
00149  * \param sid The ID number of this node.
00150  *
00151  */
00152 /*-------------------------------------------------------------------------------*/
00153 void
00154 ethernode_init(int port)
00155 {
00156   ether_client_init(port);
00157 
00158   do {
00159     state.id = random_rand() & 0x7f;
00160   } while(state.id == ID_BROADCAST);
00161 
00162   state.seqno = 0;
00163 }
00164 /*-------------------------------------------------------------------------------*/
00165 /**
00166  * Poll the network device to see if a packet has arrived.
00167  *
00168  * \return The length of the incoming packet, or zero if no packet was
00169  * found.
00170  */
00171 /*-------------------------------------------------------------------------------*/
00172 int
00173 ethernode_poll(void)
00174 {
00175   return ether_client_poll();
00176 }
00177 /*-------------------------------------------------------------------------------*/
00178 int
00179 ethernode_read(void *buf, unsigned short bufsize)
00180 {
00181   int len;
00182   u8_t tmpbuf[2048];
00183   struct hdr *hdr = (struct hdr *)tmpbuf;
00184   
00185   len = ether_client_read(tmpbuf, sizeof(tmpbuf));
00186   if(len == 0) {
00187     return 0;
00188   }
00189 
00190   if(radio_is_on == 0) {
00191     /* Drop the incoming packet if the simulated radio is switched off. */
00192     return 0;
00193   }
00194   /*  printf("ethernode_poll: received data packet with len %d type %d\n", len, hdr->type);*/
00195 
00196   switch(hdr->type) {
00197   case TYPE_DATA:
00198     if(hdr->dest == state.id ||
00199        hdr->dest == ID_BROADCAST) {
00200       memcpy(buf, tmpbuf + HDR_LEN, bufsize);
00201       return len - HDR_LEN;
00202     }
00203     break;
00204   case TYPE_ACK:
00205     printf("<%d>: Received ack packet from %d\n", state.id, hdr->src);
00206     break;
00207   default:
00208     printf("<%d>: Received unknown packet type %d from %d\n", state.id, hdr->type, hdr->src);
00209     break;
00210   }
00211   
00212   return 0;
00213     
00214 }
00215 /*-------------------------------------------------------------------------------*/
00216 /**
00217  * Send a packet from the uip_buf buffer over the UDP tunnel.
00218  *
00219  *
00220  * \retval UIP_FW_TOOLARGE A transmission of packet that was too large was attempted.
00221  *
00222  * \retval UIP_FW_DROPPED The packet is known to be dropped.
00223  *
00224  * \retval UIP_FW_OK The packet was transmitted.
00225  */
00226 /*-------------------------------------------------------------------------------*/
00227 u8_t
00228 ethernode_send(void)
00229 {
00230   int len;
00231   static char tmpbuf[2048];
00232   struct hdr *hdr = (struct hdr *)tmpbuf;
00233   u8_t dest;
00234   struct timeval tv;
00235 
00236   if(uip_len > sizeof(tmpbuf)) {
00237     PRINTF(("Ethernode_send: too large uip_len %d\n", uip_len));
00238     return UIP_FW_TOOLARGE;
00239   }
00240 
00241   memcpy(&tmpbuf[HDR_LEN], &uip_buf[HDR_LEN], uip_len);
00242   len = uip_len + HDR_LEN;
00243 
00244   dest = ID_BROADCAST;
00245   tv.tv_sec = 0;
00246   tv.tv_usec = (random_rand() % 1000);
00247   select(0, NULL, NULL, NULL, &tv);
00248 
00249   do_send(TYPE_DATA, dest, hdr, len);
00250 
00251   return UIP_FW_OK;
00252 }
00253 /*-------------------------------------------------------------------------------*/
00254 static char tmpbuf[2048];
00255 static struct hdr *hdr = (struct hdr *)tmpbuf;
00256 static u8_t dest;
00257 
00258 static int
00259 prepare(const void *buf, unsigned short len)
00260 {
00261   memcpy(&tmpbuf[HDR_LEN], buf, len);
00262   len = len + HDR_LEN;
00263 
00264   dest = ID_BROADCAST;
00265   return len;
00266 }
00267 /*-------------------------------------------------------------------------------*/
00268 static int
00269 transmit(unsigned short len)
00270 {
00271   do_send(TYPE_DATA, dest, hdr, len + HDR_LEN);
00272   return RADIO_TX_OK;
00273 }
00274 /*-------------------------------------------------------------------------------*/
00275 static int
00276 send(const void *payload, unsigned short payload_len)
00277 {
00278   prepare(payload, payload_len);
00279   return transmit(payload_len);
00280 }
00281 /*---------------------------------------------------------------------------*/
00282 PROCESS_THREAD(ethernode_process, ev, data)
00283 {
00284   int len;
00285   PROCESS_BEGIN();
00286 
00287   while(1) {
00288     process_post(PROCESS_CURRENT(), PROCESS_EVENT_CONTINUE, NULL);
00289     PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_CONTINUE);
00290 
00291     len = ethernode_poll();
00292     if(len > 0) {
00293 
00294       packetbuf_clear();
00295       len = ethernode_read(packetbuf_dataptr(), PACKETBUF_SIZE);
00296       if(len > 0) {
00297         packetbuf_set_datalen(len);
00298         NETSTACK_RDC.input();
00299       }
00300 
00301       /*      if(receiver_callback) {
00302         receiver_callback(&ethernode_driver);
00303         }*/
00304     }
00305   }
00306   PROCESS_END();
00307 }
00308 /*-------------------------------------------------------------------------------*/
00309 const struct radio_driver ethernode_driver =
00310   {
00311     (int (*)(void))ethernode_init,
00312     prepare,
00313     transmit,
00314     send,
00315     ethernode_read,
00316     channel_clear,
00317     receiving,
00318     pending,
00319     ethernode_on,
00320     ethernode_safe_off,
00321   };
00322 
00323 

Generated on Mon Apr 11 14:23:44 2011 for Contiki 2.5 by  doxygen 1.6.1