The Pedigree Project  0.1
ethernetif.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
26 /*
27  * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
28  * All rights reserved.
29  *
30  * Redistribution and use in source and binary forms, with or without modification,
31  * are permitted provided that the following conditions are met:
32  *
33  * 1. Redistributions of source code must retain the above copyright notice,
34  * this list of conditions and the following disclaimer.
35  * 2. Redistributions in binary form must reproduce the above copyright notice,
36  * this list of conditions and the following disclaimer in the documentation
37  * and/or other materials provided with the distribution.
38  * 3. The name of the author may not be used to endorse or promote products
39  * derived from this software without specific prior written permission.
40  *
41  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
42  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
43  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
44  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
46  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
47  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
48  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
49  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
50  * OF SUCH DAMAGE.
51  *
52  * This file is part of the lwIP TCP/IP stack.
53  *
54  * Author: Adam Dunkels <adam@sics.se>
55  *
56  */
57 
58 /*
59  * This file is a skeleton for developing Ethernet network interface
60  * drivers for lwIP. Add code to the low_level functions and do a
61  * search-and-replace for the word "ethernetif" to replace it with
62  * something that better describes your network interface.
63  */
64 
65 #include "lwip/opt.h"
66 
67 #if 0 /* don't build, this is only a skeleton, see previous comment */
68 
69 #include "lwip/def.h"
70 #include "lwip/mem.h"
71 #include "lwip/pbuf.h"
72 #include "lwip/stats.h"
73 #include "lwip/snmp.h"
74 #include "lwip/ethip6.h"
75 #include "lwip/etharp.h"
76 #include "netif/ppp/pppoe.h"
77 
78 /* Define those to better describe your network interface. */
79 #define IFNAME0 'e'
80 #define IFNAME1 'n'
81 
88 struct ethernetif {
89  struct eth_addr *ethaddr;
90  /* Add whatever per-interface state that is needed here. */
91 };
92 
93 /* Forward declarations. */
94 static void ethernetif_input(struct netif *netif);
95 
103 static void
104 low_level_init(struct netif *netif)
105 {
106  struct ethernetif *ethernetif = netif->state;
107 
108  /* set MAC hardware address length */
109  netif->hwaddr_len = ETHARP_HWADDR_LEN;
110 
111  /* set MAC hardware address */
112  netif->hwaddr[0] = ;
113  ...
114  netif->hwaddr[5] = ;
115 
116  /* maximum transfer unit */
117  netif->mtu = 1500;
118 
119  /* device capabilities */
120  /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
122 
123 #if LWIP_IPV6 && LWIP_IPV6_MLD
124  /*
125  * For hardware/netifs that implement MAC filtering.
126  * All-nodes link-local is handled by default, so we must let the hardware know
127  * to allow multicast packets in.
128  * Should set mld_mac_filter previously. */
129  if (netif->mld_mac_filter != NULL) {
130  ip6_addr_t ip6_allnodes_ll;
131  ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
132  netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
133  }
134 #endif /* LWIP_IPV6 && LWIP_IPV6_MLD */
135 
136  /* Do whatever else is needed to initialize interface. */
137 }
138 
155 static err_t
156 low_level_output(struct netif *netif, struct pbuf *p)
157 {
158  struct ethernetif *ethernetif = netif->state;
159  struct pbuf *q;
160 
161  initiate transfer();
162 
163 #if ETH_PAD_SIZE
164  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
165 #endif
166 
167  for (q = p; q != NULL; q = q->next) {
168  /* Send the data from the pbuf to the interface, one pbuf at a
169  time. The size of the data in each pbuf is kept in the ->len
170  variable. */
171  send data from(q->payload, q->len);
172  }
173 
174  signal that packet should be sent();
175 
176  MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
177  if (((u8_t*)p->payload)[0] & 1) {
178  /* broadcast or multicast packet*/
179  MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
180  } else {
181  /* unicast packet */
182  MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
183  }
184  /* increase ifoutdiscards or ifouterrors on error */
185 
186 #if ETH_PAD_SIZE
187  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
188 #endif
189 
190  LINK_STATS_INC(link.xmit);
191 
192  return ERR_OK;
193 }
194 
203 static struct pbuf *
204 low_level_input(struct netif *netif)
205 {
206  struct ethernetif *ethernetif = netif->state;
207  struct pbuf *p, *q;
208  u16_t len;
209 
210  /* Obtain the size of the packet and put it into the "len"
211  variable. */
212  len = ;
213 
214 #if ETH_PAD_SIZE
215  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
216 #endif
217 
218  /* We allocate a pbuf chain of pbufs from the pool. */
219  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
220 
221  if (p != NULL) {
222 
223 #if ETH_PAD_SIZE
224  pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
225 #endif
226 
227  /* We iterate over the pbuf chain until we have read the entire
228  * packet into the pbuf. */
229  for (q = p; q != NULL; q = q->next) {
230  /* Read enough bytes to fill this pbuf in the chain. The
231  * available data in the pbuf is given by the q->len
232  * variable.
233  * This does not necessarily have to be a memcpy, you can also preallocate
234  * pbufs for a DMA-enabled MAC and after receiving truncate it to the
235  * actually received size. In this case, ensure the tot_len member of the
236  * pbuf is the sum of the chained pbuf len members.
237  */
238  read data into(q->payload, q->len);
239  }
240  acknowledge that packet has been read();
241 
242  MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
243  if (((u8_t*)p->payload)[0] & 1) {
244  /* broadcast or multicast packet*/
245  MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
246  } else {
247  /* unicast packet*/
248  MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
249  }
250 #if ETH_PAD_SIZE
251  pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
252 #endif
253 
254  LINK_STATS_INC(link.recv);
255  } else {
256  drop packet();
257  LINK_STATS_INC(link.memerr);
258  LINK_STATS_INC(link.drop);
259  MIB2_STATS_NETIF_INC(netif, ifindiscards);
260  }
261 
262  return p;
263 }
264 
274 static void
275 ethernetif_input(struct netif *netif)
276 {
277  struct ethernetif *ethernetif;
278  struct eth_hdr *ethhdr;
279  struct pbuf *p;
280 
281  ethernetif = netif->state;
282 
283  /* move received packet into a new pbuf */
284  p = low_level_input(netif);
285  /* if no packet could be read, silently ignore this */
286  if (p != NULL) {
287  /* pass all packets to ethernet_input, which decides what packets it supports */
288  if (netif->input(p, netif) != ERR_OK) {
289  LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
290  pbuf_free(p);
291  p = NULL;
292  }
293  }
294 }
295 
308 err_t
309 ethernetif_init(struct netif *netif)
310 {
311  struct ethernetif *ethernetif;
312 
313  LWIP_ASSERT("netif != NULL", (netif != NULL));
314 
315  ethernetif = mem_malloc(sizeof(struct ethernetif));
316  if (ethernetif == NULL) {
317  LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
318  return ERR_MEM;
319  }
320 
321 #if LWIP_NETIF_HOSTNAME
322  /* Initialize interface hostname */
323  netif->hostname = "lwip";
324 #endif /* LWIP_NETIF_HOSTNAME */
325 
326  /*
327  * Initialize the snmp variables and counters inside the struct netif.
328  * The last argument should be replaced with your link speed, in units
329  * of bits per second.
330  */
331  MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
332 
333  netif->state = ethernetif;
334  netif->name[0] = IFNAME0;
335  netif->name[1] = IFNAME1;
336  /* We directly use etharp_output() here to save a function call.
337  * You can instead declare your own function an call etharp_output()
338  * from it if you have to do some checks before sending (e.g. if link
339  * is available...) */
340  netif->output = etharp_output;
341 #if LWIP_IPV6
342  netif->output_ip6 = ethip6_output;
343 #endif /* LWIP_IPV6 */
344  netif->linkoutput = low_level_output;
345 
346  ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
347 
348  /* initialize the hardware */
349  low_level_init(netif);
350 
351  return ERR_OK;
352 }
353 
354 #endif /* 0 */
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Definition: netif.h:322
u16_t tot_len
Definition: pbuf.h:175
Definition: pbuf.h:113
struct pbuf * next
Definition: pbuf.h:163
u16_t len
Definition: pbuf.h:178
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:684
#define NETIF_FLAG_BROADCAST
Definition: netif.h:100
u8_t hwaddr_len
Definition: netif.h:320
Definition: err.h:84
#define NETIF_FLAG_LINK_UP
Definition: netif.h:106
Definition: pbuf.h:161
u8_t flags
Definition: netif.h:324
Definition: netif.h:244
s8_t err_t
Definition: err.h:76
u16_t mtu
Definition: netif.h:318
#define LWIP_DEBUGF(debug, message)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:267
#define NETIF_FLAG_ETHARP
Definition: netif.h:110
void * state
Definition: netif.h:298
#define ETH_PAD_SIZE
Definition: opt.h:624
netif_input_fn input
Definition: netif.h:263
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:734
Definition: err.h:82
void * payload
Definition: pbuf.h:166
char name[2]
Definition: netif.h:326
void * mem_malloc(mem_size_t size)
Definition: mem.c:622
netif_linkoutput_fn linkoutput
Definition: netif.h:274
#define NETIF_DEBUG
Definition: opt.h:2657