• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   VDE (virtual distributed ethernet) interface for ale4net
3  *   (based on tapif interface Adam Dunkels <adam@sics.se>)
4  *   2005,2010,2011,2023 Renzo Davoli University of Bologna - Italy
5  */
6 
7 /*
8  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without modification,
12  * are permitted provided that the following conditions are met:
13  *
14  * 1. Redistributions of source code must retain the above copyright notice,
15  *    this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright notice,
17  *    this list of conditions and the following disclaimer in the documentation
18  *    and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31  * OF SUCH DAMAGE.
32  *
33  * This file is part of the lwIP TCP/IP stack.
34  *
35  * Author: Adam Dunkels <adam@sics.se>
36  *
37  */
38 
39 #include <fcntl.h>
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/types.h>
47 #include <sys/time.h>
48 #include <sys/uio.h>
49 #include <sys/socket.h>
50 
51 #include "lwip/opt.h"
52 
53 #include "lwip/debug.h"
54 #include "lwip/def.h"
55 #include "lwip/ip.h"
56 #include "lwip/mem.h"
57 #include "lwip/stats.h"
58 #include "lwip/snmp.h"
59 #include "lwip/pbuf.h"
60 #include "lwip/sys.h"
61 #include "lwip/timeouts.h"
62 #include "netif/etharp.h"
63 #include "lwip/ethip6.h"
64 #include <libvdeplug.h>
65 
66 #include "netif/vdeif.h"
67 
68 /* Define those to better describe your network interface. */
69 #define IFNAME0 'v'
70 #define IFNAME1 'd'
71 
72 #ifndef VDEIF_DEBUG
73 #define VDEIF_DEBUG LWIP_DBG_OFF
74 #endif
75 
76 static char vdedescr[] = "lwip";
77 
78 struct vdeif {
79   VDECONN *vdeconn;
80 };
81 
82 /* Forward declarations. */
83 static void vdeif_input(struct netif *netif);
84 #if !NO_SYS
85 static void vdeif_thread(void *arg);
86 #endif /* !NO_SYS */
87 
88 /*-----------------------------------------------------------------------------------*/
89 static void
low_level_init(struct netif * netif,char * vderl)90 low_level_init(struct netif *netif, char *vderl)
91 {
92   struct vdeif *vdeif;
93   int randaddr;
94   struct timeval now;
95 
96   vdeif = (struct vdeif *)netif->state;
97   gettimeofday(&now, NULL);
98   srand(now.tv_sec + now.tv_usec);
99   randaddr = rand();
100 
101   /* Obtain MAC address from network interface. */
102 
103   /* (We just fake an address...) */
104   netif->hwaddr[0] = 0x02;
105   netif->hwaddr[1] = 0x2;
106   netif->hwaddr[2] = randaddr >> 24;
107   netif->hwaddr[3] = randaddr >> 16;
108   netif->hwaddr[4] = randaddr >> 8;
109   netif->hwaddr[5] = randaddr;
110   netif->hwaddr_len = 6;
111 
112   /* device capabilities */
113   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
114 
115   vdeif->vdeconn = vde_open(vderl, vdedescr, NULL);
116   LWIP_DEBUGF(VDEIF_DEBUG, ("vdeif_init: ok = %d\n", !!vdeif->vdeconn));
117   if (vdeif->vdeconn == NULL) {
118     perror("vdeif_init: cannot open vde net");
119     exit(1);
120   }
121 
122   netif_set_link_up(netif);
123 
124 #if !NO_SYS
125   sys_thread_new("vdeif_thread", vdeif_thread, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
126 #endif /* !NO_SYS */
127 }
128 /*-----------------------------------------------------------------------------------*/
129 /*
130  * low_level_output():
131  *
132  * Should do the actual transmission of the packet. The packet is
133  * contained in the pbuf that is passed to the function. This pbuf
134  * might be chained.
135  *
136  */
137 /*-----------------------------------------------------------------------------------*/
138 
139 static err_t
low_level_output(struct netif * netif,struct pbuf * p)140 low_level_output(struct netif *netif, struct pbuf *p)
141 {
142   struct vdeif *vdeif = (struct vdeif *)netif->state;
143   char buf[1518]; /* max packet size including VLAN excluding CRC */
144   ssize_t written;
145 
146   if (p->tot_len > sizeof(buf)) {
147     MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
148     perror("vdeif: packet too large");
149     return ERR_IF;
150   }
151 
152   /* initiate transfer(); */
153   pbuf_copy_partial(p, buf, p->tot_len, 0);
154 
155   /* signal that packet should be sent(); */
156   written = vde_send(vdeif->vdeconn, buf, p->tot_len, 0);
157   if (written < p->tot_len) {
158     MIB2_STATS_NETIF_INC(netif, ifoutdiscards);
159     perror("vdeif: write");
160     return ERR_IF;
161   } else {
162     MIB2_STATS_NETIF_ADD(netif, ifoutoctets, (u32_t)written);
163     return ERR_OK;
164   }
165 }
166 /*-----------------------------------------------------------------------------------*/
167 /*
168  * low_level_input():
169  *
170  * Should allocate a pbuf and transfer the bytes of the incoming
171  * packet from the interface into the pbuf.
172  *
173  */
174 /*-----------------------------------------------------------------------------------*/
175 static struct pbuf *
low_level_input(struct netif * netif)176 low_level_input(struct netif *netif)
177 {
178   struct pbuf *p;
179   u16_t len;
180   ssize_t readlen;
181   char buf[1518]; /* max packet size including VLAN excluding CRC */
182   struct vdeif *vdeif = (struct vdeif *)netif->state;
183 
184   /* Obtain the size of the packet and put it into the "len"
185      variable. */
186   readlen = vde_recv(vdeif->vdeconn, buf, sizeof(buf), 0);
187   if (readlen < 0) {
188     perror("read returned -1");
189     exit(1);
190   }
191   len = (u16_t)readlen;
192 
193   MIB2_STATS_NETIF_ADD(netif, ifinoctets, len);
194 
195   /* We allocate a pbuf chain of pbufs from the pool. */
196   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
197   if (p != NULL) {
198     pbuf_take(p, buf, len);
199     /* acknowledge that packet has been read(); */
200   } else {
201     /* drop packet(); */
202     MIB2_STATS_NETIF_INC(netif, ifindiscards);
203     LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_input: could not allocate pbuf\n"));
204   }
205 
206   return p;
207 }
208 
209 /*-----------------------------------------------------------------------------------*/
210 /*
211  * vdeif_input():
212  *
213  * This function should be called when a packet is ready to be read
214  * from the interface. It uses the function low_level_input() that
215  * should handle the actual reception of bytes from the network
216  * interface.
217  *
218  */
219 /*-----------------------------------------------------------------------------------*/
220 static void
vdeif_input(struct netif * netif)221 vdeif_input(struct netif *netif)
222 {
223   struct pbuf *p = low_level_input(netif);
224 
225   if (p == NULL) {
226 #if LINK_STATS
227     LINK_STATS_INC(link.recv);
228 #endif /* LINK_STATS */
229     LWIP_DEBUGF(VDEIF_DEBUG, ("vdeif_input: low_level_input returned NULL\n"));
230     return;
231   }
232 
233   if (netif->input(p, netif) != ERR_OK) {
234     LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_input: netif input error\n"));
235     pbuf_free(p);
236   }
237 }
238 /*-----------------------------------------------------------------------------------*/
239 /*
240  * vdeif_init():
241  *
242  * Should be called at the beginning of the program to set up the
243  * network interface. It calls the function low_level_init() to do the
244  * actual setup of the hardware.
245  *
246  */
247 /*-----------------------------------------------------------------------------------*/
248 err_t
vdeif_init(struct netif * netif)249 vdeif_init(struct netif *netif)
250 {
251   char *vderl = (char *) netif->state;
252   struct vdeif *vdeif = (struct vdeif *)mem_malloc(sizeof(struct vdeif));
253 
254   if (vdeif == NULL) {
255     LWIP_DEBUGF(NETIF_DEBUG, ("vdeif_init: out of memory for vdeif\n"));
256     return ERR_MEM;
257   }
258   netif->state = vdeif;
259   MIB2_INIT_NETIF(netif, snmp_ifType_other, 100000000);
260 
261   netif->name[0] = IFNAME0;
262   netif->name[1] = IFNAME1;
263 #if LWIP_IPV4
264   netif->output = etharp_output;
265 #endif /* LWIP_IPV4 */
266 #if LWIP_IPV6
267   netif->output_ip6 = ethip6_output;
268 #endif /* LWIP_IPV6 */
269   netif->linkoutput = low_level_output;
270   netif->mtu = 1500;
271 
272   low_level_init(netif, vderl);
273 
274   return ERR_OK;
275 }
276 
277 
278 /*-----------------------------------------------------------------------------------*/
279 void
vdeif_poll(struct netif * netif)280 vdeif_poll(struct netif *netif)
281 {
282   vdeif_input(netif);
283 }
284 
285 #if NO_SYS
286 
287 int
vdeif_select(struct netif * netif)288 vdeif_select(struct netif *netif)
289 {
290   fd_set fdset;
291   int ret;
292   struct timeval tv;
293   struct vdeif *vdeif;
294   u32_t msecs = sys_timeouts_sleeptime();
295   int datafd;
296 
297   vdeif = (struct vdeif *)netif->state;
298   datafd = vde_datafd(vdeif->vdeconn);
299 
300   tv.tv_sec = msecs / 1000;
301   tv.tv_usec = (msecs % 1000) * 1000;
302 
303   FD_ZERO(&fdset);
304   FD_SET(datafd, &fdset);
305 
306   ret = select(datafd + 1, &fdset, NULL, NULL, &tv);
307   if (ret > 0) {
308     vdeif_input(netif);
309   }
310   return ret;
311 }
312 
313 #else /* NO_SYS */
314 
315 static void
vdeif_thread(void * arg)316 vdeif_thread(void *arg)
317 {
318   struct netif *netif;
319   struct vdeif *vdeif;
320   fd_set fdset;
321   int ret;
322   int datafd;
323 
324   netif = (struct netif *)arg;
325   vdeif = (struct vdeif *)netif->state;
326   datafd = vde_datafd(vdeif->vdeconn);
327 
328   while(1) {
329     FD_ZERO(&fdset);
330     FD_SET(datafd, &fdset);
331 
332     /* Wait for a packet to arrive. */
333     ret = select(datafd + 1, &fdset, NULL, NULL, NULL);
334 
335     if(ret == 1) {
336       /* Handle incoming packet. */
337       vdeif_input(netif);
338     } else if(ret == -1) {
339       perror("vdeif_thread: select");
340     }
341   }
342 }
343 
344 #endif /* NO_SYS */
345