• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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