-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathethernetif_driver.c
140 lines (116 loc) · 4.09 KB
/
ethernetif_driver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <stdint.h>
#include <string.h>
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "lwip/stats.h"
#include "lwip/snmp.h"
#include "netif/etharp.h"
#include "ethernetif.h"
#include "lowlevel_wigig.h"
#define IFNAME0 'w'
#define IFNAME1 'g'
#ifndef ETHERNETIF_MAXFRAMES
#define ETHERNETIF_MAXFRAMES 0
#endif
void ethernetif_input(void *arg)
{
struct netif *netif = (struct netif *)arg;
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p, *q;
int len;
int frames = 0;
uint16_t offset = 0;
ethernetif = (struct ethernetif *)netif->state;
do {
if((len = ethernetif->low_level_startinput(ethernetif->internals)) == 0)
break;
/* move received packet into a new pbuf */
#if ETH_PAD_SIZE
len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
if (p != NULL) {
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
for(q = p; q != NULL; q = q->next) {
ethernetif->low_level_input(ethernetif->internals,
q->payload, q->len, offset);
offset += q->len;
}
ethernetif->low_level_endinput(ethernetif->internals);
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.recv);
} else {
#if ETH_PAD_SIZE
len -= ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif
ethernetif->low_level_input_nomem(ethernetif->internals, len);
LINK_STATS_INC(link.memerr);
LINK_STATS_INC(link.drop);
return;
}
ethhdr = (struct eth_hdr *)p->payload;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
case ETHTYPE_ARP:
if (netif->input(p, netif)!=ERR_OK)
{ LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
}
} while((!ETHERNETIF_MAXFRAMES) || (++frames < ETHERNETIF_MAXFRAMES));
}
static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p)
{
struct ethernetif *ethernetif = (struct ethernetif *)netif->state;
struct pbuf *q;
uint16_t offset = 0;
if(!ethernetif->low_level_startoutput(ethernetif->internals))
return ERR_IF;
#if ETH_PAD_SIZE
pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
#endif
for(q = p; q != NULL; q = q->next) {
ethernetif->low_level_output(ethernetif->internals,
q->payload, q->len, offset);
offset += q->len;
}
ethernetif->low_level_endoutput(ethernetif->internals, p->tot_len);
#if ETH_PAD_SIZE
pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif
LINK_STATS_INC(link.xmit);
return ERR_OK;
}
err_t ethernetif_init(struct netif *netif)
{
struct ethernetif *ethernetif;
LWIP_ASSERT("netif != NULL", (netif != NULL));
LWIP_ASSERT("state != NULL", (netif->state != NULL));
ethernetif = (struct ethernetif *)netif->state;
NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 1000000000);
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->output = etharp_output;
netif->linkoutput = ethernetif_linkoutput;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
memcpy(netif->hwaddr, ethernetif->address, ETHARP_HWADDR_LEN);
netif->mtu = ETHERNET_MTU;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
ethernetif->low_level_init(ðernetif->internals, ethernetif->address, NULL);
sys_thread_new("ethernetif_thread", ethernetif_input, netif, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
return ERR_OK;
}