xref: /minix/minix/lib/liblwip/dist/src/netif/ethernetif.c (revision 5d5fbe79)
1*5d5fbe79SDavid van Moolenbroek /**
2*5d5fbe79SDavid van Moolenbroek  * @file
3*5d5fbe79SDavid van Moolenbroek  * Ethernet Interface Skeleton
4*5d5fbe79SDavid van Moolenbroek  *
5*5d5fbe79SDavid van Moolenbroek  */
6*5d5fbe79SDavid van Moolenbroek 
7*5d5fbe79SDavid van Moolenbroek /*
8*5d5fbe79SDavid van Moolenbroek  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
9*5d5fbe79SDavid van Moolenbroek  * All rights reserved.
10*5d5fbe79SDavid van Moolenbroek  *
11*5d5fbe79SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without modification,
12*5d5fbe79SDavid van Moolenbroek  * are permitted provided that the following conditions are met:
13*5d5fbe79SDavid van Moolenbroek  *
14*5d5fbe79SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright notice,
15*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer.
16*5d5fbe79SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright notice,
17*5d5fbe79SDavid van Moolenbroek  *    this list of conditions and the following disclaimer in the documentation
18*5d5fbe79SDavid van Moolenbroek  *    and/or other materials provided with the distribution.
19*5d5fbe79SDavid van Moolenbroek  * 3. The name of the author may not be used to endorse or promote products
20*5d5fbe79SDavid van Moolenbroek  *    derived from this software without specific prior written permission.
21*5d5fbe79SDavid van Moolenbroek  *
22*5d5fbe79SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
23*5d5fbe79SDavid van Moolenbroek  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24*5d5fbe79SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
25*5d5fbe79SDavid van Moolenbroek  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26*5d5fbe79SDavid van Moolenbroek  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
27*5d5fbe79SDavid van Moolenbroek  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28*5d5fbe79SDavid van Moolenbroek  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29*5d5fbe79SDavid van Moolenbroek  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30*5d5fbe79SDavid van Moolenbroek  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
31*5d5fbe79SDavid van Moolenbroek  * OF SUCH DAMAGE.
32*5d5fbe79SDavid van Moolenbroek  *
33*5d5fbe79SDavid van Moolenbroek  * This file is part of the lwIP TCP/IP stack.
34*5d5fbe79SDavid van Moolenbroek  *
35*5d5fbe79SDavid van Moolenbroek  * Author: Adam Dunkels <adam@sics.se>
36*5d5fbe79SDavid van Moolenbroek  *
37*5d5fbe79SDavid van Moolenbroek  */
38*5d5fbe79SDavid van Moolenbroek 
39*5d5fbe79SDavid van Moolenbroek /*
40*5d5fbe79SDavid van Moolenbroek  * This file is a skeleton for developing Ethernet network interface
41*5d5fbe79SDavid van Moolenbroek  * drivers for lwIP. Add code to the low_level functions and do a
42*5d5fbe79SDavid van Moolenbroek  * search-and-replace for the word "ethernetif" to replace it with
43*5d5fbe79SDavid van Moolenbroek  * something that better describes your network interface.
44*5d5fbe79SDavid van Moolenbroek  */
45*5d5fbe79SDavid van Moolenbroek 
46*5d5fbe79SDavid van Moolenbroek #include "lwip/opt.h"
47*5d5fbe79SDavid van Moolenbroek 
48*5d5fbe79SDavid van Moolenbroek #if 0 /* don't build, this is only a skeleton, see previous comment */
49*5d5fbe79SDavid van Moolenbroek 
50*5d5fbe79SDavid van Moolenbroek #include "lwip/def.h"
51*5d5fbe79SDavid van Moolenbroek #include "lwip/mem.h"
52*5d5fbe79SDavid van Moolenbroek #include "lwip/pbuf.h"
53*5d5fbe79SDavid van Moolenbroek #include "lwip/stats.h"
54*5d5fbe79SDavid van Moolenbroek #include "lwip/snmp.h"
55*5d5fbe79SDavid van Moolenbroek #include "lwip/ethip6.h"
56*5d5fbe79SDavid van Moolenbroek #include "lwip/etharp.h"
57*5d5fbe79SDavid van Moolenbroek #include "netif/ppp/pppoe.h"
58*5d5fbe79SDavid van Moolenbroek 
59*5d5fbe79SDavid van Moolenbroek /* Define those to better describe your network interface. */
60*5d5fbe79SDavid van Moolenbroek #define IFNAME0 'e'
61*5d5fbe79SDavid van Moolenbroek #define IFNAME1 'n'
62*5d5fbe79SDavid van Moolenbroek 
63*5d5fbe79SDavid van Moolenbroek /**
64*5d5fbe79SDavid van Moolenbroek  * Helper struct to hold private data used to operate your ethernet interface.
65*5d5fbe79SDavid van Moolenbroek  * Keeping the ethernet address of the MAC in this struct is not necessary
66*5d5fbe79SDavid van Moolenbroek  * as it is already kept in the struct netif.
67*5d5fbe79SDavid van Moolenbroek  * But this is only an example, anyway...
68*5d5fbe79SDavid van Moolenbroek  */
69*5d5fbe79SDavid van Moolenbroek struct ethernetif {
70*5d5fbe79SDavid van Moolenbroek   struct eth_addr *ethaddr;
71*5d5fbe79SDavid van Moolenbroek   /* Add whatever per-interface state that is needed here. */
72*5d5fbe79SDavid van Moolenbroek };
73*5d5fbe79SDavid van Moolenbroek 
74*5d5fbe79SDavid van Moolenbroek /* Forward declarations. */
75*5d5fbe79SDavid van Moolenbroek static void  ethernetif_input(struct netif *netif);
76*5d5fbe79SDavid van Moolenbroek 
77*5d5fbe79SDavid van Moolenbroek /**
78*5d5fbe79SDavid van Moolenbroek  * In this function, the hardware should be initialized.
79*5d5fbe79SDavid van Moolenbroek  * Called from ethernetif_init().
80*5d5fbe79SDavid van Moolenbroek  *
81*5d5fbe79SDavid van Moolenbroek  * @param netif the already initialized lwip network interface structure
82*5d5fbe79SDavid van Moolenbroek  *        for this ethernetif
83*5d5fbe79SDavid van Moolenbroek  */
84*5d5fbe79SDavid van Moolenbroek static void
85*5d5fbe79SDavid van Moolenbroek low_level_init(struct netif *netif)
86*5d5fbe79SDavid van Moolenbroek {
87*5d5fbe79SDavid van Moolenbroek   struct ethernetif *ethernetif = netif->state;
88*5d5fbe79SDavid van Moolenbroek 
89*5d5fbe79SDavid van Moolenbroek   /* set MAC hardware address length */
90*5d5fbe79SDavid van Moolenbroek   netif->hwaddr_len = ETHARP_HWADDR_LEN;
91*5d5fbe79SDavid van Moolenbroek 
92*5d5fbe79SDavid van Moolenbroek   /* set MAC hardware address */
93*5d5fbe79SDavid van Moolenbroek   netif->hwaddr[0] = ;
94*5d5fbe79SDavid van Moolenbroek   ...
95*5d5fbe79SDavid van Moolenbroek   netif->hwaddr[5] = ;
96*5d5fbe79SDavid van Moolenbroek 
97*5d5fbe79SDavid van Moolenbroek   /* maximum transfer unit */
98*5d5fbe79SDavid van Moolenbroek   netif->mtu = 1500;
99*5d5fbe79SDavid van Moolenbroek 
100*5d5fbe79SDavid van Moolenbroek   /* device capabilities */
101*5d5fbe79SDavid van Moolenbroek   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
102*5d5fbe79SDavid van Moolenbroek   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
103*5d5fbe79SDavid van Moolenbroek 
104*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6 && LWIP_IPV6_MLD
105*5d5fbe79SDavid van Moolenbroek   /*
106*5d5fbe79SDavid van Moolenbroek    * For hardware/netifs that implement MAC filtering.
107*5d5fbe79SDavid van Moolenbroek    * All-nodes link-local is handled by default, so we must let the hardware know
108*5d5fbe79SDavid van Moolenbroek    * to allow multicast packets in.
109*5d5fbe79SDavid van Moolenbroek    * Should set mld_mac_filter previously. */
110*5d5fbe79SDavid van Moolenbroek   if (netif->mld_mac_filter != NULL) {
111*5d5fbe79SDavid van Moolenbroek     ip6_addr_t ip6_allnodes_ll;
112*5d5fbe79SDavid van Moolenbroek     ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
113*5d5fbe79SDavid van Moolenbroek     netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
114*5d5fbe79SDavid van Moolenbroek   }
115*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
116*5d5fbe79SDavid van Moolenbroek 
117*5d5fbe79SDavid van Moolenbroek   /* Do whatever else is needed to initialize interface. */
118*5d5fbe79SDavid van Moolenbroek }
119*5d5fbe79SDavid van Moolenbroek 
120*5d5fbe79SDavid van Moolenbroek /**
121*5d5fbe79SDavid van Moolenbroek  * This function should do the actual transmission of the packet. The packet is
122*5d5fbe79SDavid van Moolenbroek  * contained in the pbuf that is passed to the function. This pbuf
123*5d5fbe79SDavid van Moolenbroek  * might be chained.
124*5d5fbe79SDavid van Moolenbroek  *
125*5d5fbe79SDavid van Moolenbroek  * @param netif the lwip network interface structure for this ethernetif
126*5d5fbe79SDavid van Moolenbroek  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
127*5d5fbe79SDavid van Moolenbroek  * @return ERR_OK if the packet could be sent
128*5d5fbe79SDavid van Moolenbroek  *         an err_t value if the packet couldn't be sent
129*5d5fbe79SDavid van Moolenbroek  *
130*5d5fbe79SDavid van Moolenbroek  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
131*5d5fbe79SDavid van Moolenbroek  *       strange results. You might consider waiting for space in the DMA queue
132*5d5fbe79SDavid van Moolenbroek  *       to become available since the stack doesn't retry to send a packet
133*5d5fbe79SDavid van Moolenbroek  *       dropped because of memory failure (except for the TCP timers).
134*5d5fbe79SDavid van Moolenbroek  */
135*5d5fbe79SDavid van Moolenbroek 
136*5d5fbe79SDavid van Moolenbroek static err_t
137*5d5fbe79SDavid van Moolenbroek low_level_output(struct netif *netif, struct pbuf *p)
138*5d5fbe79SDavid van Moolenbroek {
139*5d5fbe79SDavid van Moolenbroek   struct ethernetif *ethernetif = netif->state;
140*5d5fbe79SDavid van Moolenbroek   struct pbuf *q;
141*5d5fbe79SDavid van Moolenbroek 
142*5d5fbe79SDavid van Moolenbroek   initiate transfer();
143*5d5fbe79SDavid van Moolenbroek 
144*5d5fbe79SDavid van Moolenbroek #if ETH_PAD_SIZE
145*5d5fbe79SDavid van Moolenbroek   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
146*5d5fbe79SDavid van Moolenbroek #endif
147*5d5fbe79SDavid van Moolenbroek 
148*5d5fbe79SDavid van Moolenbroek   for (q = p; q != NULL; q = q->next) {
149*5d5fbe79SDavid van Moolenbroek     /* Send the data from the pbuf to the interface, one pbuf at a
150*5d5fbe79SDavid van Moolenbroek        time. The size of the data in each pbuf is kept in the ->len
151*5d5fbe79SDavid van Moolenbroek        variable. */
152*5d5fbe79SDavid van Moolenbroek     send data from(q->payload, q->len);
153*5d5fbe79SDavid van Moolenbroek   }
154*5d5fbe79SDavid van Moolenbroek 
155*5d5fbe79SDavid van Moolenbroek   signal that packet should be sent();
156*5d5fbe79SDavid van Moolenbroek 
157*5d5fbe79SDavid van Moolenbroek   MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
158*5d5fbe79SDavid van Moolenbroek   if (((u8_t*)p->payload)[0] & 1) {
159*5d5fbe79SDavid van Moolenbroek     /* broadcast or multicast packet*/
160*5d5fbe79SDavid van Moolenbroek     MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
161*5d5fbe79SDavid van Moolenbroek   } else {
162*5d5fbe79SDavid van Moolenbroek     /* unicast packet */
163*5d5fbe79SDavid van Moolenbroek     MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
164*5d5fbe79SDavid van Moolenbroek   }
165*5d5fbe79SDavid van Moolenbroek   /* increase ifoutdiscards or ifouterrors on error */
166*5d5fbe79SDavid van Moolenbroek 
167*5d5fbe79SDavid van Moolenbroek #if ETH_PAD_SIZE
168*5d5fbe79SDavid van Moolenbroek   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
169*5d5fbe79SDavid van Moolenbroek #endif
170*5d5fbe79SDavid van Moolenbroek 
171*5d5fbe79SDavid van Moolenbroek   LINK_STATS_INC(link.xmit);
172*5d5fbe79SDavid van Moolenbroek 
173*5d5fbe79SDavid van Moolenbroek   return ERR_OK;
174*5d5fbe79SDavid van Moolenbroek }
175*5d5fbe79SDavid van Moolenbroek 
176*5d5fbe79SDavid van Moolenbroek /**
177*5d5fbe79SDavid van Moolenbroek  * Should allocate a pbuf and transfer the bytes of the incoming
178*5d5fbe79SDavid van Moolenbroek  * packet from the interface into the pbuf.
179*5d5fbe79SDavid van Moolenbroek  *
180*5d5fbe79SDavid van Moolenbroek  * @param netif the lwip network interface structure for this ethernetif
181*5d5fbe79SDavid van Moolenbroek  * @return a pbuf filled with the received packet (including MAC header)
182*5d5fbe79SDavid van Moolenbroek  *         NULL on memory error
183*5d5fbe79SDavid van Moolenbroek  */
184*5d5fbe79SDavid van Moolenbroek static struct pbuf *
185*5d5fbe79SDavid van Moolenbroek low_level_input(struct netif *netif)
186*5d5fbe79SDavid van Moolenbroek {
187*5d5fbe79SDavid van Moolenbroek   struct ethernetif *ethernetif = netif->state;
188*5d5fbe79SDavid van Moolenbroek   struct pbuf *p, *q;
189*5d5fbe79SDavid van Moolenbroek   u16_t len;
190*5d5fbe79SDavid van Moolenbroek 
191*5d5fbe79SDavid van Moolenbroek   /* Obtain the size of the packet and put it into the "len"
192*5d5fbe79SDavid van Moolenbroek      variable. */
193*5d5fbe79SDavid van Moolenbroek   len = ;
194*5d5fbe79SDavid van Moolenbroek 
195*5d5fbe79SDavid van Moolenbroek #if ETH_PAD_SIZE
196*5d5fbe79SDavid van Moolenbroek   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
197*5d5fbe79SDavid van Moolenbroek #endif
198*5d5fbe79SDavid van Moolenbroek 
199*5d5fbe79SDavid van Moolenbroek   /* We allocate a pbuf chain of pbufs from the pool. */
200*5d5fbe79SDavid van Moolenbroek   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
201*5d5fbe79SDavid van Moolenbroek 
202*5d5fbe79SDavid van Moolenbroek   if (p != NULL) {
203*5d5fbe79SDavid van Moolenbroek 
204*5d5fbe79SDavid van Moolenbroek #if ETH_PAD_SIZE
205*5d5fbe79SDavid van Moolenbroek     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
206*5d5fbe79SDavid van Moolenbroek #endif
207*5d5fbe79SDavid van Moolenbroek 
208*5d5fbe79SDavid van Moolenbroek     /* We iterate over the pbuf chain until we have read the entire
209*5d5fbe79SDavid van Moolenbroek      * packet into the pbuf. */
210*5d5fbe79SDavid van Moolenbroek     for (q = p; q != NULL; q = q->next) {
211*5d5fbe79SDavid van Moolenbroek       /* Read enough bytes to fill this pbuf in the chain. The
212*5d5fbe79SDavid van Moolenbroek        * available data in the pbuf is given by the q->len
213*5d5fbe79SDavid van Moolenbroek        * variable.
214*5d5fbe79SDavid van Moolenbroek        * This does not necessarily have to be a memcpy, you can also preallocate
215*5d5fbe79SDavid van Moolenbroek        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
216*5d5fbe79SDavid van Moolenbroek        * actually received size. In this case, ensure the tot_len member of the
217*5d5fbe79SDavid van Moolenbroek        * pbuf is the sum of the chained pbuf len members.
218*5d5fbe79SDavid van Moolenbroek        */
219*5d5fbe79SDavid van Moolenbroek       read data into(q->payload, q->len);
220*5d5fbe79SDavid van Moolenbroek     }
221*5d5fbe79SDavid van Moolenbroek     acknowledge that packet has been read();
222*5d5fbe79SDavid van Moolenbroek 
223*5d5fbe79SDavid van Moolenbroek     MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
224*5d5fbe79SDavid van Moolenbroek     if (((u8_t*)p->payload)[0] & 1) {
225*5d5fbe79SDavid van Moolenbroek       /* broadcast or multicast packet*/
226*5d5fbe79SDavid van Moolenbroek       MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
227*5d5fbe79SDavid van Moolenbroek     } else {
228*5d5fbe79SDavid van Moolenbroek       /* unicast packet*/
229*5d5fbe79SDavid van Moolenbroek       MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
230*5d5fbe79SDavid van Moolenbroek     }
231*5d5fbe79SDavid van Moolenbroek #if ETH_PAD_SIZE
232*5d5fbe79SDavid van Moolenbroek     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
233*5d5fbe79SDavid van Moolenbroek #endif
234*5d5fbe79SDavid van Moolenbroek 
235*5d5fbe79SDavid van Moolenbroek     LINK_STATS_INC(link.recv);
236*5d5fbe79SDavid van Moolenbroek   } else {
237*5d5fbe79SDavid van Moolenbroek     drop packet();
238*5d5fbe79SDavid van Moolenbroek     LINK_STATS_INC(link.memerr);
239*5d5fbe79SDavid van Moolenbroek     LINK_STATS_INC(link.drop);
240*5d5fbe79SDavid van Moolenbroek     MIB2_STATS_NETIF_INC(netif, ifindiscards);
241*5d5fbe79SDavid van Moolenbroek   }
242*5d5fbe79SDavid van Moolenbroek 
243*5d5fbe79SDavid van Moolenbroek   return p;
244*5d5fbe79SDavid van Moolenbroek }
245*5d5fbe79SDavid van Moolenbroek 
246*5d5fbe79SDavid van Moolenbroek /**
247*5d5fbe79SDavid van Moolenbroek  * This function should be called when a packet is ready to be read
248*5d5fbe79SDavid van Moolenbroek  * from the interface. It uses the function low_level_input() that
249*5d5fbe79SDavid van Moolenbroek  * should handle the actual reception of bytes from the network
250*5d5fbe79SDavid van Moolenbroek  * interface. Then the type of the received packet is determined and
251*5d5fbe79SDavid van Moolenbroek  * the appropriate input function is called.
252*5d5fbe79SDavid van Moolenbroek  *
253*5d5fbe79SDavid van Moolenbroek  * @param netif the lwip network interface structure for this ethernetif
254*5d5fbe79SDavid van Moolenbroek  */
255*5d5fbe79SDavid van Moolenbroek static void
256*5d5fbe79SDavid van Moolenbroek ethernetif_input(struct netif *netif)
257*5d5fbe79SDavid van Moolenbroek {
258*5d5fbe79SDavid van Moolenbroek   struct ethernetif *ethernetif;
259*5d5fbe79SDavid van Moolenbroek   struct eth_hdr *ethhdr;
260*5d5fbe79SDavid van Moolenbroek   struct pbuf *p;
261*5d5fbe79SDavid van Moolenbroek 
262*5d5fbe79SDavid van Moolenbroek   ethernetif = netif->state;
263*5d5fbe79SDavid van Moolenbroek 
264*5d5fbe79SDavid van Moolenbroek   /* move received packet into a new pbuf */
265*5d5fbe79SDavid van Moolenbroek   p = low_level_input(netif);
266*5d5fbe79SDavid van Moolenbroek   /* if no packet could be read, silently ignore this */
267*5d5fbe79SDavid van Moolenbroek   if (p != NULL) {
268*5d5fbe79SDavid van Moolenbroek     /* pass all packets to ethernet_input, which decides what packets it supports */
269*5d5fbe79SDavid van Moolenbroek     if (netif->input(p, netif) != ERR_OK) {
270*5d5fbe79SDavid van Moolenbroek       LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
271*5d5fbe79SDavid van Moolenbroek       pbuf_free(p);
272*5d5fbe79SDavid van Moolenbroek       p = NULL;
273*5d5fbe79SDavid van Moolenbroek     }
274*5d5fbe79SDavid van Moolenbroek   }
275*5d5fbe79SDavid van Moolenbroek }
276*5d5fbe79SDavid van Moolenbroek 
277*5d5fbe79SDavid van Moolenbroek /**
278*5d5fbe79SDavid van Moolenbroek  * Should be called at the beginning of the program to set up the
279*5d5fbe79SDavid van Moolenbroek  * network interface. It calls the function low_level_init() to do the
280*5d5fbe79SDavid van Moolenbroek  * actual setup of the hardware.
281*5d5fbe79SDavid van Moolenbroek  *
282*5d5fbe79SDavid van Moolenbroek  * This function should be passed as a parameter to netif_add().
283*5d5fbe79SDavid van Moolenbroek  *
284*5d5fbe79SDavid van Moolenbroek  * @param netif the lwip network interface structure for this ethernetif
285*5d5fbe79SDavid van Moolenbroek  * @return ERR_OK if the loopif is initialized
286*5d5fbe79SDavid van Moolenbroek  *         ERR_MEM if private data couldn't be allocated
287*5d5fbe79SDavid van Moolenbroek  *         any other err_t on error
288*5d5fbe79SDavid van Moolenbroek  */
289*5d5fbe79SDavid van Moolenbroek err_t
290*5d5fbe79SDavid van Moolenbroek ethernetif_init(struct netif *netif)
291*5d5fbe79SDavid van Moolenbroek {
292*5d5fbe79SDavid van Moolenbroek   struct ethernetif *ethernetif;
293*5d5fbe79SDavid van Moolenbroek 
294*5d5fbe79SDavid van Moolenbroek   LWIP_ASSERT("netif != NULL", (netif != NULL));
295*5d5fbe79SDavid van Moolenbroek 
296*5d5fbe79SDavid van Moolenbroek   ethernetif = mem_malloc(sizeof(struct ethernetif));
297*5d5fbe79SDavid van Moolenbroek   if (ethernetif == NULL) {
298*5d5fbe79SDavid van Moolenbroek     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
299*5d5fbe79SDavid van Moolenbroek     return ERR_MEM;
300*5d5fbe79SDavid van Moolenbroek   }
301*5d5fbe79SDavid van Moolenbroek 
302*5d5fbe79SDavid van Moolenbroek #if LWIP_NETIF_HOSTNAME
303*5d5fbe79SDavid van Moolenbroek   /* Initialize interface hostname */
304*5d5fbe79SDavid van Moolenbroek   netif->hostname = "lwip";
305*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_NETIF_HOSTNAME */
306*5d5fbe79SDavid van Moolenbroek 
307*5d5fbe79SDavid van Moolenbroek   /*
308*5d5fbe79SDavid van Moolenbroek    * Initialize the snmp variables and counters inside the struct netif.
309*5d5fbe79SDavid van Moolenbroek    * The last argument should be replaced with your link speed, in units
310*5d5fbe79SDavid van Moolenbroek    * of bits per second.
311*5d5fbe79SDavid van Moolenbroek    */
312*5d5fbe79SDavid van Moolenbroek   MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
313*5d5fbe79SDavid van Moolenbroek 
314*5d5fbe79SDavid van Moolenbroek   netif->state = ethernetif;
315*5d5fbe79SDavid van Moolenbroek   netif->name[0] = IFNAME0;
316*5d5fbe79SDavid van Moolenbroek   netif->name[1] = IFNAME1;
317*5d5fbe79SDavid van Moolenbroek   /* We directly use etharp_output() here to save a function call.
318*5d5fbe79SDavid van Moolenbroek    * You can instead declare your own function an call etharp_output()
319*5d5fbe79SDavid van Moolenbroek    * from it if you have to do some checks before sending (e.g. if link
320*5d5fbe79SDavid van Moolenbroek    * is available...) */
321*5d5fbe79SDavid van Moolenbroek   netif->output = etharp_output;
322*5d5fbe79SDavid van Moolenbroek #if LWIP_IPV6
323*5d5fbe79SDavid van Moolenbroek   netif->output_ip6 = ethip6_output;
324*5d5fbe79SDavid van Moolenbroek #endif /* LWIP_IPV6 */
325*5d5fbe79SDavid van Moolenbroek   netif->linkoutput = low_level_output;
326*5d5fbe79SDavid van Moolenbroek 
327*5d5fbe79SDavid van Moolenbroek   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
328*5d5fbe79SDavid van Moolenbroek 
329*5d5fbe79SDavid van Moolenbroek   /* initialize the hardware */
330*5d5fbe79SDavid van Moolenbroek   low_level_init(netif);
331*5d5fbe79SDavid van Moolenbroek 
332*5d5fbe79SDavid van Moolenbroek   return ERR_OK;
333*5d5fbe79SDavid van Moolenbroek }
334*5d5fbe79SDavid van Moolenbroek 
335*5d5fbe79SDavid van Moolenbroek #endif /* 0 */
336