1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: Ethernet Interface Skeleton
15 * Author: none
16 * Create: 2020
17 */
18
19 #include "lwip/opt.h"
20 #include "lwip/def.h"
21 #include "lwip/mem.h"
22 #include "lwip/pbuf.h"
23 #include "lwip/dhcp.h"
24 #include "lwip/stats.h"
25 #include "lwip/snmp.h"
26 #include "lwip/raw.h"
27 #include "netif/etharp.h"
28 #include "netif/driverif.h"
29 #include <string.h>
30
31 #if PF_PKT_SUPPORT
32 extern struct raw_pcb *all_pkt_raw_pcbs;
33 #endif
34
35 #if defined(LWIP_ACHBA_SUPPORT) && (LWIP_ACHBA_SUPPORT)
36 lwip_achba_func driverif_input_achba_func = NULL;
37
38 void
driverif_achba_register_hook(void * func)39 driverif_achba_register_hook(void *func)
40 {
41 driverif_input_achba_func = (lwip_achba_func)func;
42 }
43
44 void
driverif_achba_unregister_hook(void)45 driverif_achba_unregister_hook(void)
46 {
47 driverif_input_achba_func = NULL;
48 }
49 #endif
50
51 static err_t
52 driverif_output(struct netif *netif, struct pbuf *p);
53
54 /*
55 * This function should do the actual transmission of the packet. The packet is
56 * contained in the pbuf that is passed to the function. This pbuf
57 * might be chained.
58 *
59 * @param netif the lwip network interface structure for this driverif
60 * @param p the MAC packet to send (e.g. IP packet including MAC_addresses and type)
61 * @return ERR_OK if the packet could be sent
62 * an err_t value if the packet couldn't be sent
63 *
64 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
65 * strange results. You might consider waiting for space in the DMA queue
66 * to become availale since the stack doesn't retry to send a packet
67 * dropped because of memory failure (except for the TCP timers).
68 */
69
70 static err_t
driverif_output(struct netif * netif,struct pbuf * p)71 driverif_output(struct netif *netif, struct pbuf *p)
72 {
73 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_output : going to send packet pbuf 0x%p of length %"U16_F" through netif 0x%p\n", \
74 (void *)p, p->tot_len, (void *)netif));
75
76 #if PF_PKT_SUPPORT
77 if (all_pkt_raw_pcbs != NULL) {
78 p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST));
79 p->flags |= PBUF_FLAG_OUTGOING;
80 raw_pkt_input(p, netif, NULL);
81 }
82 #endif
83
84 #if ETH_PAD_SIZE
85 (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
86 #endif
87
88 netif->drv_send(netif, p);
89
90 #if ETH_PAD_SIZE
91 (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
92 #endif
93 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
94 LINK_STATS_INC(link.xmit);
95
96 return ERR_OK;
97 }
98
99 /*
100 * This function should be called by network driver to pass the input packet to LwIP.
101 * Before calling this API, driver has to keep the packet in pbuf structure. Driver has to
102 * call pbuf_alloc() with type as PBUF_RAM to create pbuf structure. Then driver
103 * has to pass the pbuf structure to this API. This will add the pbuf into the TCPIP thread.
104 * Once this packet is processed by TCPIP thread, pbuf will be freed. Driver is not required to
105 * free the pbuf.
106 *
107 * @param netif the lwip network interface structure for this driverif
108 * @param p packet in pbuf structure format
109 */
110 void
driverif_input(struct netif * netif,struct pbuf * p)111 driverif_input(struct netif *netif, struct pbuf *p)
112 {
113 #if PF_PKT_SUPPORT
114 #if (DRIVERIF_DEBUG & LWIP_DBG_OFF)
115 u16_t ethhdr_type;
116 struct eth_hdr *ethhdr = NULL;
117 #endif
118 #else
119 u16_t ethhdr_type;
120 struct eth_hdr *ethhdr = NULL;
121 #endif
122 err_t ret = ERR_VAL;
123
124 LWIP_ERROR("driverif_input : invalid arguments", ((netif != NULL) && (p != NULL)), return);
125
126 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : going to receive input packet. netif 0x%p, pbuf 0x%p, \
127 packet_length %"U16_F"\n", (void *)netif, (void *)p, p->tot_len));
128
129 #if defined(LWIP_ACHBA_SUPPORT) && (LWIP_ACHBA_SUPPORT)
130 if ((driverif_input_achba_func != NULL) && (driverif_input_achba_func(netif, p) != true)) {
131 return;
132 }
133 #endif
134
135 /* points to packet payload, which starts with an Ethernet header */
136 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
137 if (p->len < SIZEOF_ETH_HDR) {
138 (void)pbuf_free(p);
139 LINK_STATS_INC(link.drop);
140 LINK_STATS_INC(link.link_rx_drop);
141 return;
142 }
143
144 #if PF_PKT_SUPPORT
145 #if (DRIVERIF_DEBUG & LWIP_DBG_OFF)
146 ethhdr = (struct eth_hdr *)p->payload;
147 ethhdr_type = ntohs(ethhdr->type);
148 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F" netif->input=%p\n", \
149 ethhdr_type, netif->input));
150 #endif
151
152 /* full packet send to tcpip_thread to process */
153 if (netif->input) {
154 ret = netif->input(p, netif);
155 }
156 if (ret != ERR_OK) {
157 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
158 (void)pbuf_free(p);
159 LINK_STATS_INC(link.drop);
160 LINK_STATS_INC(link.link_rx_drop);
161 if (ret == ERR_MEM) {
162 LINK_STATS_INC(link.link_rx_overrun);
163 }
164 } else {
165 LINK_STATS_INC(link.recv);
166 }
167
168 #else
169 ethhdr = (struct eth_hdr *)p->payload;
170 ethhdr_type = ntohs(ethhdr->type);
171
172 switch (ethhdr_type) {
173 /* IP or ARP packet? */
174 case ETHTYPE_IP:
175 case ETHTYPE_IPV6:
176 case ETHTYPE_ARP:
177 #if ETHARP_SUPPORT_VLAN
178 case ETHTYPE_VLAN:
179 #endif /* ETHARP_SUPPORT_VLAN */
180 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F"\n", ethhdr_type));
181 /* full packet send to tcpip_thread to process */
182 if (netif->input != NULL) {
183 ret = netif->input(p, netif);
184 }
185
186 if (ret != ERR_OK) {
187 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
188 (void)pbuf_free(p);
189 LINK_STATS_INC(link.drop);
190 LINK_STATS_INC(link.link_rx_drop);
191 if (ret == ERR_MEM) {
192 MIB2_STATS_NETIF_INC(netif, ifinoverruns);
193 LINK_STATS_INC(link.link_rx_overrun);
194 }
195 } else {
196 LINK_STATS_INC(link.recv);
197 }
198 break;
199
200 default:
201 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is of unsupported type %"U16_F"\n", ethhdr_type));
202 (void)pbuf_free(p);
203 LINK_STATS_INC(link.drop);
204 LINK_STATS_INC(link.link_rx_drop);
205 break;
206 }
207 #endif
208
209 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is processed\n"));
210 }
211
212 /*
213 * Should be called at the beginning of the program to set up the
214 * network interface. It calls the function low_level_init() to do the
215 * actual setup of the hardware.
216 *
217 * This function should be passed as a parameter to netif_add().
218 *
219 * @param netif the lwip network interface structure for this driverif
220 * @return ERR_OK if the loopif is initialized
221 * ERR_MEM on Allocation Failure
222 * any other err_t on error
223 */
224 err_t
driverif_init(struct netif * netif)225 driverif_init(struct netif *netif)
226 {
227 u16_t link_layer_type;
228
229 link_layer_type = netif->link_layer_type;
230 LWIP_ERROR("driverif_init : invalid link_layer_type in netif", \
231 ((link_layer_type == ETHERNET_DRIVER_IF) || (link_layer_type == WIFI_DRIVER_IF)), \
232 return ERR_IF);
233
234 LWIP_ERROR("driverif_init : netif hardware length is greater than maximum supported", \
235 (netif->hwaddr_len <= NETIF_MAX_HWADDR_LEN), return ERR_IF);
236
237 LWIP_ERROR("driverif_init : drv_send is null", (netif->drv_send != NULL), return ERR_IF);
238
239 #if LWIP_NETIF_PROMISC
240 LWIP_ERROR("driverif_init : drv_config is null", (netif->drv_config != NULL), return ERR_IF);
241 #endif
242
243 #if LWIP_NETIF_HOSTNAME
244 /* Initialize interface hostname */
245 if (strncpy_s(netif->hostname, NETIF_HOSTNAME_MAX_LEN,
246 LWIP_NETIF_HOSTNAME_DEFAULT, NETIF_HOSTNAME_MAX_LEN - 1) == EOK) {
247 netif->hostname[NETIF_HOSTNAME_MAX_LEN - 1] = '\0';
248 } else {
249 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init: hostname %s in invalid\n", LWIP_NETIF_HOSTNAME_DEFAULT));
250 netif->hostname[0] = '\0';
251 }
252 #endif /* LWIP_NETIF_HOSTNAME */
253
254 /*
255 * Initialize the snmp variables and counters inside the struct netif.
256 * The last argument should be replaced with your link speed, in units
257 * of bits per second.
258 */
259 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 0);
260
261 netif->output = etharp_output;
262 netif->linkoutput = driverif_output;
263
264 if (strlen(netif->name) == 0) {
265 if (link_layer_type == ETHERNET_DRIVER_IF) {
266 (void)strncpy_s(netif->name, NETIF_NAMESIZE, ETHERNET_IFNAME, NETIF_NAMESIZE - 1);
267 } else {
268 (void)strncpy_s(netif->name, NETIF_NAMESIZE, WIFI_IFNAME, NETIF_NAMESIZE - 1);
269 }
270 }
271
272 /* maximum transfer unit */
273 netif->mtu = IP_FRAG_MAX_MTU;
274
275 /* device capabilities */
276 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
277 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
278 #if DRIVER_STATUS_CHECK
279 NETIF_FLAG_DRIVER_RDY |
280 #endif
281 #if LWIP_IGMP
282 NETIF_FLAG_IGMP |
283 #endif
284
285 /**
286 @page RFC-2710 RFC-2710
287 @par Compliant Sections
288 Section 5. Node State Transition Diagram
289 @par Behavior Description
290 MLD messages are sent for multicast addresses whose scope is 2
291 (link-local), including Solicited-Node multicast addresses.\n
292 Behavior:Stack will send MLD6 report /Done to solicited node multicast address
293 if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled.
294 */
295 /* Enable sending MLD report /done for solicited address during neighbour discovery */
296 #if LWIP_IPV6 && LWIP_IPV6_MLD
297 #if LWIP_MLD6_ENABLE_MLD_ON_DAD
298 NETIF_FLAG_MLD6 |
299 #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */
300 #endif
301 NETIF_FLAG_LINK_UP;
302 #if LWIP_NETIF_DEFAULT_LINK_DOWN
303 netif->flags = netif->flags & (~NETIF_FLAG_LINK_UP);
304 #endif
305 #if DRIVER_STATUS_CHECK
306 netif->waketime = -1;
307 #endif /* DRIVER_STATUS_CHECK */
308 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init : Initialized netif 0x%p\n", (void *)netif));
309 return ERR_OK;
310 }
311
312