Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / netif / ethernetif.c
1 /**
2  * @file
3  * Ethernet Interface Skeleton
4  *
5  */
6
7 /*
8  * Copyright (c) 2001-2004 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 /*
40  * This file is a skeleton for developing Ethernet network interface
41  * drivers for lwIP. Add code to the low_level functions and do a
42  * search-and-replace for the word "ethernetif" to replace it with
43  * something that better describes your network interface.
44  */
45
46 #include "lwip/opt.h"
47
48 #if 0 /* don't build, this is only a skeleton, see previous comment */
49
50 #include "lwip/def.h"
51 #include "lwip/mem.h"
52 #include "lwip/pbuf.h"
53 #include "lwip/sys.h"
54 #include <lwip/stats.h>
55 #include <lwip/snmp.h>
56 #include "netif/etharp.h"
57 #include "netif/ppp_oe.h"
58
59 /* Define those to better describe your network interface. */
60 #define IFNAME0 'e'
61 #define IFNAME1 'n'
62
63 /**
64  * Helper struct to hold private data used to operate your ethernet interface.
65  * Keeping the ethernet address of the MAC in this struct is not necessary
66  * as it is already kept in the struct netif.
67  * But this is only an example, anyway...
68  */
69 struct ethernetif {
70   struct eth_addr *ethaddr;
71   /* Add whatever per-interface state that is needed here. */
72 };
73
74 /* Forward declarations. */
75 static void  ethernetif_input(struct netif *netif);
76
77 /**
78  * In this function, the hardware should be initialized.
79  * Called from ethernetif_init().
80  *
81  * @param netif the already initialized lwip network interface structure
82  *        for this ethernetif
83  */
84 static void
85 low_level_init(struct netif *netif)
86 {
87   struct ethernetif *ethernetif = netif->state;
88   
89   /* set MAC hardware address length */
90   netif->hwaddr_len = ETHARP_HWADDR_LEN;
91
92   /* set MAC hardware address */
93   netif->hwaddr[0] = ;
94   ...
95   netif->hwaddr[5] = ;
96
97   /* maximum transfer unit */
98   netif->mtu = 1500;
99   
100   /* device capabilities */
101   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
102   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
103  
104   /* Do whatever else is needed to initialize interface. */  
105 }
106
107 /**
108  * This function should do the actual transmission of the packet. The packet is
109  * contained in the pbuf that is passed to the function. This pbuf
110  * might be chained.
111  *
112  * @param netif the lwip network interface structure for this ethernetif
113  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
114  * @return ERR_OK if the packet could be sent
115  *         an err_t value if the packet couldn't be sent
116  *
117  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
118  *       strange results. You might consider waiting for space in the DMA queue
119  *       to become availale since the stack doesn't retry to send a packet
120  *       dropped because of memory failure (except for the TCP timers).
121  */
122
123 static err_t
124 low_level_output(struct netif *netif, struct pbuf *p)
125 {
126   struct ethernetif *ethernetif = netif->state;
127   struct pbuf *q;
128
129   initiate transfer();
130   
131 #if ETH_PAD_SIZE
132   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
133 #endif
134
135   for(q = p; q != NULL; q = q->next) {
136     /* Send the data from the pbuf to the interface, one pbuf at a
137        time. The size of the data in each pbuf is kept in the ->len
138        variable. */
139     send data from(q->payload, q->len);
140   }
141
142   signal that packet should be sent();
143
144 #if ETH_PAD_SIZE
145   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
146 #endif
147   
148   LINK_STATS_INC(link.xmit);
149
150   return ERR_OK;
151 }
152
153 /**
154  * Should allocate a pbuf and transfer the bytes of the incoming
155  * packet from the interface into the pbuf.
156  *
157  * @param netif the lwip network interface structure for this ethernetif
158  * @return a pbuf filled with the received packet (including MAC header)
159  *         NULL on memory error
160  */
161 static struct pbuf *
162 low_level_input(struct netif *netif)
163 {
164   struct ethernetif *ethernetif = netif->state;
165   struct pbuf *p, *q;
166   u16_t len;
167
168   /* Obtain the size of the packet and put it into the "len"
169      variable. */
170   len = ;
171
172 #if ETH_PAD_SIZE
173   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
174 #endif
175
176   /* We allocate a pbuf chain of pbufs from the pool. */
177   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
178   
179   if (p != NULL) {
180
181 #if ETH_PAD_SIZE
182     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
183 #endif
184
185     /* We iterate over the pbuf chain until we have read the entire
186      * packet into the pbuf. */
187     for(q = p; q != NULL; q = q->next) {
188       /* Read enough bytes to fill this pbuf in the chain. The
189        * available data in the pbuf is given by the q->len
190        * variable. */
191       read data into(q->payload, q->len);
192     }
193     acknowledge that packet has been read();
194
195 #if ETH_PAD_SIZE
196     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
197 #endif
198
199     LINK_STATS_INC(link.recv);
200   } else {
201     drop packet();
202     LINK_STATS_INC(link.memerr);
203     LINK_STATS_INC(link.drop);
204   }
205
206   return p;  
207 }
208
209 /**
210  * This function should be called when a packet is ready to be read
211  * from the interface. It uses the function low_level_input() that
212  * should handle the actual reception of bytes from the network
213  * interface. Then the type of the received packet is determined and
214  * the appropriate input function is called.
215  *
216  * @param netif the lwip network interface structure for this ethernetif
217  */
218 static void
219 ethernetif_input(struct netif *netif)
220 {
221   struct ethernetif *ethernetif;
222   struct eth_hdr *ethhdr;
223   struct pbuf *p;
224
225   ethernetif = netif->state;
226
227   /* move received packet into a new pbuf */
228   p = low_level_input(netif);
229   /* no packet could be read, silently ignore this */
230   if (p == NULL) return;
231   /* points to packet payload, which starts with an Ethernet header */
232   ethhdr = p->payload;
233
234   switch (htons(ethhdr->type)) {
235   /* IP or ARP packet? */
236   case ETHTYPE_IP:
237   case ETHTYPE_ARP:
238 #if PPPOE_SUPPORT
239   /* PPPoE packet? */
240   case ETHTYPE_PPPOEDISC:
241   case ETHTYPE_PPPOE:
242 #endif /* PPPOE_SUPPORT */
243     /* full packet send to tcpip_thread to process */
244     if (netif->input(p, netif)!=ERR_OK)
245      { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
246        pbuf_free(p);
247        p = NULL;
248      }
249     break;
250
251   default:
252     pbuf_free(p);
253     p = NULL;
254     break;
255   }
256 }
257
258 /**
259  * Should be called at the beginning of the program to set up the
260  * network interface. It calls the function low_level_init() to do the
261  * actual setup of the hardware.
262  *
263  * This function should be passed as a parameter to netif_add().
264  *
265  * @param netif the lwip network interface structure for this ethernetif
266  * @return ERR_OK if the loopif is initialized
267  *         ERR_MEM if private data couldn't be allocated
268  *         any other err_t on error
269  */
270 err_t
271 ethernetif_init(struct netif *netif)
272 {
273   struct ethernetif *ethernetif;
274
275   LWIP_ASSERT("netif != NULL", (netif != NULL));
276     
277   ethernetif = mem_malloc(sizeof(struct ethernetif));
278   if (ethernetif == NULL) {
279     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
280     return ERR_MEM;
281   }
282
283 #if LWIP_NETIF_HOSTNAME
284   /* Initialize interface hostname */
285   netif->hostname = "lwip";
286 #endif /* LWIP_NETIF_HOSTNAME */
287
288   /*
289    * Initialize the snmp variables and counters inside the struct netif.
290    * The last argument should be replaced with your link speed, in units
291    * of bits per second.
292    */
293   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, ???);
294
295   netif->state = ethernetif;
296   netif->name[0] = IFNAME0;
297   netif->name[1] = IFNAME1;
298   /* We directly use etharp_output() here to save a function call.
299    * You can instead declare your own function an call etharp_output()
300    * from it if you have to do some checks before sending (e.g. if link
301    * is available...) */
302   netif->output = etharp_output;
303   netif->linkoutput = low_level_output;
304   
305   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
306   
307   /* initialize the hardware */
308   low_level_init(netif);
309
310   return ERR_OK;
311 }
312
313 #endif /* 0 */