1 /*
2 * Copyright (c) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved.
3 *
4 * UniProton is licensed under Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 * http://license.coscl.org.cn/MulanPSL2
8 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
9 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
10 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
11 * See the Mulan PSL v2 for more details.
12 * Create: 2022-09-21
13 * Description: 网络
14 */
15
16 #include <lwip/sys.h>
17 #include <lwip/netif.h>
18 #include <lwip/snmp.h>
19 #include <lwip/etharp.h>
20 #include <lwip/sockets.h>
21 #include <lwip/ethip6.h>
22
23 #define LWIP_NETIF_HOSTNAME_DEFAULT "default"
24 #define LINK_SPEED_OF_YOUR_NETIF_IN_BPS 100000000 // 100Mbps
25
26 #define link_rx_drop cachehit
27 #define link_rx_overrun cachehit
28
29 #define NETIF_NAME_PREFIX_MAX_LENGTH 10
30 #define NETIF_NAME_PREFIX_ETH "eth"
31 #define NETIF_NAME_PREFIX_WIFI "wlan"
32 #define NETIF_NAME_PREFIX_BT "bt"
33
34 #ifndef LWIP_NETIF_IFINDEX_MAX_EX
35 #define LWIP_NETIF_IFINDEX_MAX_EX 255
36 #endif
37
OsDriverifGetIfnamePrefix(struct netif * netif,char * prefix,int prefixLen)38 static void OsDriverifGetIfnamePrefix(struct netif *netif, char *prefix, int prefixLen)
39 {
40 if (prefix == NULL || netif == NULL) {
41 LWIP_ASSERT("invalid param", 0);
42 return;
43 }
44 switch (netif->link_layer_type) {
45 case ETHERNET_DRIVER_IF:
46 strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_ETH);
47 break;
48 case WIFI_DRIVER_IF:
49 strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_WIFI);
50 break;
51 case BT_PROXY_IF:
52 strcpy_s(prefix, prefixLen, NETIF_NAME_PREFIX_BT);
53 break;
54 default:
55 LWIP_ASSERT("invalid link_layer_type", 0);
56 break;
57 }
58 }
59
OsDriverifInitIfname(struct netif * netif)60 static void OsDriverifInitIfname(struct netif *netif)
61 {
62 struct netif *tmpNetif = NULL;
63 char prefix[NETIF_NAME_PREFIX_MAX_LENGTH] = {0};
64
65 OsDriverifGetIfnamePrefix(netif, prefix, NETIF_NAME_PREFIX_MAX_LENGTH);
66 netif->name[0] = prefix[0];
67 netif->name[1] = prefix[1];
68
69 if (netif->full_name[0] != '\0') {
70 LWIP_DEBUGF(DRIVERIF_DEBUG, ("netif already has fullname %s\n", netif->full_name));
71 return;
72 }
73 for (int i = 0; i < LWIP_NETIF_IFINDEX_MAX_EX; ++i) {
74 if (snprintf_s(netif->full_name, sizeof(netif->full_name), sizeof(netif->full_name) - 1,
75 "%s%d", prefix, i) < 0) {
76 break;
77 }
78 NETIF_FOREACH(tmpNetif) {
79 if (strcmp(tmpNetif->full_name, netif->full_name) == 0) {
80 break;
81 }
82 }
83 if (tmpNetif == NULL) {
84 LWIP_DEBUGF(DRIVERIF_DEBUG, ("set fullname success %s\n", netif->full_name));
85 return;
86 }
87 }
88 netif->full_name[0] = '\0';
89 }
90
91 /*
92 * This function should do the actual transmission of the packet. The packet is
93 * contained in the pbuf that is passed to the function. This pbuf
94 * might be chained.
95 *
96 * @param netif the lwip network interface structure for this driverif
97 * @param p the MAC packet to send (e.g. IP packet including MAC_addresses and type)
98 * @return ERR_OK if the packet could be sent
99 * an err_t value if the packet couldn't be sent
100 *
101 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
102 * strange results. You might consider waiting for space in the DMA queue
103 * to become availale since the stack doesn't retry to send a packet
104 * dropped because of memory failure (except for the TCP timers).
105 */
106
OsDriverifOutput(struct netif * netif,struct pbuf * p)107 static err_t OsDriverifOutput(struct netif *netif, struct pbuf *p)
108 {
109 LWIP_DEBUGF(DRIVERIF_DEBUG, ("OsDriverifOutput : send packet pbuf 0x%p of length %"U16_F" through netif 0x%p\n", \
110 (void *)p, p->tot_len, (void *)netif));
111
112 #if PF_PKT_SUPPORT
113 if (all_pkt_raw_pcbs != NULL) {
114 p->flags = (u16_t)(p->flags & ~(PBUF_FLAG_LLMCAST | PBUF_FLAG_LLBCAST | PBUF_FLAG_HOST));
115 p->flags |= PBUF_FLAG_OUTGOING;
116 (void)raw_pkt_input(p, netif, NULL);
117 }
118 #endif
119
120 #if ETH_PAD_SIZE
121 (void)pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
122 #endif
123
124 netif->drv_send(netif, p);
125
126 #if ETH_PAD_SIZE
127 (void)pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
128 #endif
129 MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
130 LINK_STATS_INC(link.xmit);
131
132 return ERR_OK;
133 }
134
OsDriverifInputProc(struct netif * netif,struct pbuf * p)135 static void OsDriverifInputProc(struct netif *netif, struct pbuf *p)
136 {
137 err_t ret = ERR_VAL;
138 struct eth_hdr * ethhdr = (struct eth_hdr *)p->payload;
139 U16 ethhdrType = ntohs(ethhdr->type);
140
141 switch (ethhdrType) {
142 /* IP or ARP packet? */
143 case ETHTYPE_IP:
144 case ETHTYPE_IPV6:
145 case ETHTYPE_ARP:
146 #if ETHARP_SUPPORT_VLAN
147 case ETHTYPE_VLAN:
148 #endif /* ETHARP_SUPPORT_VLAN */
149 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F"\n", ethhdrType));
150 /* full packet send to tcpip_thread to process */
151 if (netif->input != NULL) {
152 ret = netif->input(p, netif);
153 }
154
155 if (ret != ERR_OK) {
156 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
157 (void)pbuf_free(p);
158 LINK_STATS_INC(link.drop);
159 LINK_STATS_INC(link.link_rx_drop);
160 if (ret == ERR_MEM) {
161 MIB2_STATS_NETIF_INC(netif, ifinoverruns);
162 LINK_STATS_INC(link.link_rx_overrun);
163 }
164 } else {
165 LINK_STATS_INC(link.recv);
166 }
167 break;
168
169 default:
170 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is of unsupported type %"U16_F"\n", \
171 ethhdrType));
172 (void)pbuf_free(p);
173 LINK_STATS_INC(link.drop);
174 LINK_STATS_INC(link.link_rx_drop);
175 break;
176 }
177 }
178
179 /*
180 * This function should be called by network driver to pass the input packet to LwIP.
181 * Before calling this API, driver has to keep the packet in pbuf structure. Driver has to
182 * call pbuf_alloc() with type as PBUF_RAM to create pbuf structure. Then driver
183 * has to pass the pbuf structure to this API. This will add the pbuf into the TCPIP thread.
184 * Once this packet is processed by TCPIP thread, pbuf will be freed. Driver is not required to
185 * free the pbuf.
186 *
187 * @param netif the lwip network interface structure for this driverif
188 * @param p packet in pbuf structure format
189 */
driverif_input(struct netif * netif,struct pbuf * p)190 void driverif_input(struct netif *netif, struct pbuf *p)
191 {
192 #if PF_PKT_SUPPORT
193 #if (DRIVERIF_DEBUG & LWIP_DBG_OFF)
194 U16 ethhdrType;
195 struct eth_hdr* ethhdr = NULL;
196 #endif
197 err_t ret = ERR_VAL;
198 #endif
199
200 LWIP_ERROR("driverif_input : invalid arguments", ((netif != NULL) && (p != NULL)), return);
201
202 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : going to receive input packet. netif 0x%p, pbuf 0x%p, \
203 packet_length %"U16_F"\n", (void *)netif, (void *)p, p->tot_len));
204
205 /* points to packet payload, which starts with an Ethernet header */
206 MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
207 if (p->len < SIZEOF_ETH_HDR) {
208 (void)pbuf_free(p);
209 LINK_STATS_INC(link.drop);
210 LINK_STATS_INC(link.link_rx_drop);
211 return;
212 }
213
214 #if PF_PKT_SUPPORT
215 #if (DRIVERIF_DEBUG & LWIP_DBG_OFF)
216 ethhdr = (struct eth_hdr *)p->payload;
217 ethhdrType = ntohs(ethhdr->type);
218 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet of type %"U16_F" netif->input=%p\n", \
219 ethhdrType, netif->input));
220 #endif
221
222 /* full packet send to tcpip_thread to process */
223 if (netif->input) {
224 ret = netif->input(p, netif);
225 }
226 if (ret != ERR_OK) {
227 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input: IP input error\n"));
228 (void)pbuf_free(p);
229 LINK_STATS_INC(link.drop);
230 LINK_STATS_INC(link.link_rx_drop);
231 if (ret == ERR_MEM) {
232 LINK_STATS_INC(link.link_rx_overrun);
233 }
234 } else {
235 LINK_STATS_INC(link.recv);
236 }
237
238 #else
239 OsDriverifInputProc(netif, p);
240 #endif
241
242 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_input : received packet is processed\n"));
243 }
244
245 /*
246 * Should be called at the beginning of the program to set up the
247 * network interface. It calls the function low_level_init() to do the
248 * actual setup of the hardware.
249 *
250 * This function should be passed as a parameter to netif_add().
251 *
252 * @param netif the lwip network interface structure for this driverif
253 * @return ERR_OK if the loopif is initialized
254 * ERR_MEM on Allocation Failure
255 * any other err_t on error
256 */
driverif_init(struct netif * netif)257 err_t driverif_init(struct netif *netif)
258 {
259 U16 linkLayerType;
260
261 if (netif == NULL) {
262 return ERR_IF;
263 }
264 linkLayerType = netif->link_layer_type;
265 LWIP_ERROR("driverif_init : invalid link_layer_type in netif", \
266 ((linkLayerType == ETHERNET_DRIVER_IF) \
267 || (linkLayerType == WIFI_DRIVER_IF \
268 || linkLayerType == BT_PROXY_IF)), \
269 return ERR_IF);
270
271 LWIP_ERROR("driverif_init : netif hardware length is greater than maximum supported", \
272 (netif->hwaddr_len <= NETIF_MAX_HWADDR_LEN), return ERR_IF);
273
274 LWIP_ERROR("driverif_init : drv_send is null", (netif->drv_send != NULL), return ERR_IF);
275
276 #if LWIP_NETIF_PROMISC
277 LWIP_ERROR("driverif_init : drv_config is null", (netif->drv_config != NULL), return ERR_IF);
278 #endif
279
280 #if LWIP_NETIF_HOSTNAME
281 /* Initialize interface hostname */
282 netif->hostname = LWIP_NETIF_HOSTNAME_DEFAULT;
283 #endif /* LWIP_NETIF_HOSTNAME */
284
285 /*
286 * Initialize the snmp variables and counters inside the struct netif.
287 * The last argument should be replaced with your link speed, in units
288 * of bits per second.
289 */
290 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
291
292 netif->output = etharp_output;
293 netif->linkoutput = OsDriverifOutput;
294
295 /* init the netif's full name */
296 OsDriverifInitIfname(netif);
297
298 /* maximum transfer unit */
299 netif->mtu = IP_FRAG_MAX_MTU;
300
301 /* device capabilities */
302 /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
303 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP |
304 #if DRIVER_STATUS_CHECK
305 NETIF_FLAG_DRIVER_RDY |
306 #endif
307 #if LWIP_IGMP
308 NETIF_FLAG_IGMP |
309 #endif
310
311 /**
312 @page RFC-2710 RFC-2710
313 @par Compliant Sections
314 Section 5. Node State Transition Diagram
315 @par Behavior Description
316 MLD messages are sent for multicast addresses whose scope is 2
317 (link-local), including Solicited-Node multicast addresses.\n
318 Behavior:Stack will send MLD6 report /Done to solicited node multicast address
319 if the LWIP_MLD6_ENABLE_MLD_ON_DAD is enabled. By default, this is disabled.
320 */
321 /* Enable sending MLD report /done for solicited address during neighbour discovery */
322 #if LWIP_IPV6 && LWIP_IPV6_MLD
323 #if LWIP_MLD6_ENABLE_MLD_ON_DAD
324 NETIF_FLAG_MLD6 |
325 #endif /* LWIP_MLD6_ENABLE_MLD_ON_DAD */
326 #endif
327 NETIF_FLAG_LINK_UP;
328
329 #if DRIVER_STATUS_CHECK
330 netif->waketime = -1;
331 #endif /* DRIVER_STATUS_CHECK */
332 LWIP_DEBUGF(DRIVERIF_DEBUG, ("driverif_init : Initialized netif 0x%p\n", (void *)netif));
333 return ERR_OK;
334 }
335