• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of
9  *    conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12  *    of conditions and the following disclaimer in the documentation and/or other materials
13  *    provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16  *    to endorse or promote products derived from this software without specific prior written
17  *    permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #define LWIP_STATIC static
33 #define DHCP_STATE_OFF 0
34 #define LWIP_EXT_POLL_SUPPORT 1
35 
36 #include "lwip/api.h"
37 #include "lwip/netdb.h"
38 #include "lwip/stats.h"
39 #include "lwip/err.h"
40 #include "lwip/ip_addr.h"
41 #include "lwip/icmp.h"
42 #include "lwip/tcpip.h"
43 #include "lwip/inet_chksum.h"
44 #include "los_config.h"
45 #include <string.h>
46 #include <time.h>
47 #include <stdlib.h>
48 #include "los_debug.h"
49 #include "los_task.h"
50 
51 /* Forward Declarations [START] */
52 #ifndef LWIP_TESTBED
53 LWIP_STATIC
54 #endif
55 int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len);
56 
57 #ifndef LWIP_TESTBED
58 LWIP_STATIC
59 #endif
60 void lwip_ifconfig_show_internal(void *arg);
61 
62 #if LWIP_DNS
63 LWIP_STATIC unsigned int get_hostip(const char *hname);
64 
65 #ifndef LWIP_TESTBED
66 LWIP_STATIC
67 #endif
68 struct hostent *gethostnameinfo(const char *host, char *tmphstbuf, size_t hstbuflen);
69 #endif /* LWIP_DNS */
70 
71 #define PRINT_BUF_LEN 1024
72 
73 struct ifconfig_option {
74     char iface[IFNAMSIZ];
75     unsigned int option;
76     ip_addr_t ip_addr;
77     ip_addr_t netmask;
78     ip_addr_t gw;
79     unsigned char ethaddr[6];
80     u16_t mtu;
81     /* when using telnet, print to the telnet socket will result in system  */
82     /* deadlock. So we cahe the prinf data to a buf, and when the tcpip      */
83     /* callback returns, then print the data out to the telnet socket       */
84     sys_sem_t cb_completed;
85     char cb_print_buf[PRINT_BUF_LEN];
86     unsigned int print_len;
87 };
88 
89 #ifndef LWIP_TESTBED
90 LWIP_STATIC
91 #endif
print_netif(struct netif * netif,char * print_buf,unsigned int buf_len)92 int print_netif(struct netif *netif, char *print_buf, unsigned int buf_len)
93 {
94     int i, ret;
95     char *tmp = print_buf;
96 
97     if (buf_len < 1) {
98         goto out;
99     }
100     if (netif->link_layer_type == LOOPBACK_IF) {
101         ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%s\t", netif->name);
102     } else {
103         ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%s%u\t", netif->name, netif->num);
104     }
105 
106     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
107         goto out;
108     tmp += ret;
109     buf_len -= (unsigned int)ret;
110 #if LWIP_IPV4
111     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "ip:%s ", ipaddr_ntoa(&netif->ip_addr));
112     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
113         goto out;
114     tmp += ret;
115     buf_len -= (unsigned int)ret;
116 
117     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "netmask:%s ", ipaddr_ntoa(&netif->netmask));
118     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
119         goto out;
120     tmp += ret;
121     buf_len -= (unsigned int)ret;
122 
123     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "gateway:%s\n", ipaddr_ntoa(&netif->gw));
124     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
125         goto out;
126     tmp += ret;
127     buf_len -= (unsigned int)ret;
128 #endif
129     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "\tHWaddr ");
130     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
131         goto out;
132     tmp += ret;
133     buf_len -= (unsigned int)ret;
134 
135     for (i = 0; i < netif->hwaddr_len - 1; i++) {
136         ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x:", netif->hwaddr[i]);
137         if ((ret <= 0) || ((unsigned int)ret >= buf_len))
138             goto out;
139         tmp += ret;
140         buf_len -= (unsigned int)ret;
141     }
142 
143     ret = snprintf_s(tmp, buf_len, (buf_len - 1), "%02x", netif->hwaddr[i]);
144     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
145         goto out;
146     tmp += ret;
147     buf_len -= (unsigned int)ret;
148 
149     ret = snprintf_s(tmp, buf_len, (buf_len - 1), " MTU:%d %s", netif->mtu,
150                      netif->flags & NETIF_FLAG_UP ? "Running" : "Stop");
151     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
152         goto out;
153     tmp += ret;
154     buf_len -= (unsigned int)ret;
155 
156     if (netif_default == netif && netif_is_up(netif)) {
157         ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s", "Default");
158         if ((ret <= 0) || ((unsigned int)ret >= buf_len))
159             goto out;
160         tmp += ret;
161         buf_len -= (unsigned int)ret;
162     }
163 
164     ret = snprintf_s(tmp, buf_len, (buf_len - 1), " %s\n", netif->flags & NETIF_FLAG_LINK_UP ? "Link UP" : "Link Down");
165     if ((ret <= 0) || ((unsigned int)ret >= buf_len))
166         goto out;
167     tmp += ret;
168 
169 out:
170     return (int)(tmp - print_buf);
171 }
172 
173 #ifndef LWIP_TESTBED
174 LWIP_STATIC
175 #endif
lwip_ifconfig_show_internal(void * arg)176 void lwip_ifconfig_show_internal(void *arg)
177 {
178     struct netif *netif = NULL;
179     struct ifconfig_option *ifconfig_cmd = (struct ifconfig_option *)arg;
180     int ret;
181 
182     if (netif_list == NULL) {
183         ret = snprintf_s(ifconfig_cmd->cb_print_buf, PRINT_BUF_LEN - ifconfig_cmd->print_len,
184                          ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not init\n");
185         if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) {
186             ifconfig_cmd->print_len += (unsigned int)ret;
187         }
188         sys_sem_signal(&ifconfig_cmd->cb_completed);
189         return;
190     }
191 
192     if (ifconfig_cmd->iface[0] == '\0') {
193         /* display all netif */
194         for (netif = netif_list; netif != NULL; netif = netif->next) {
195             ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
196                               PRINT_BUF_LEN - ifconfig_cmd->print_len);
197             ifconfig_cmd->print_len += (unsigned int)ret;
198         }
199     } else {
200         netif = netif_find(ifconfig_cmd->iface);
201         if (netif == NULL) {
202             ret = snprintf_s(ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
203                              (PRINT_BUF_LEN - ifconfig_cmd->print_len),
204                              ((PRINT_BUF_LEN - ifconfig_cmd->print_len) - 1), "Device not found\n");
205             if ((ret > 0) && ((unsigned int)ret < (PRINT_BUF_LEN - ifconfig_cmd->print_len))) {
206                 ifconfig_cmd->print_len += (unsigned int)ret;
207             }
208 
209             sys_sem_signal(&ifconfig_cmd->cb_completed);
210             return;
211         }
212 
213         ret = print_netif(netif, ifconfig_cmd->cb_print_buf + ifconfig_cmd->print_len,
214                           PRINT_BUF_LEN - ifconfig_cmd->print_len);
215         ifconfig_cmd->print_len += (unsigned int)ret;
216     }
217     sys_sem_signal(&ifconfig_cmd->cb_completed);
218 }
219 
lwip_ifconfig(int argc,const char ** argv)220 u32_t lwip_ifconfig(int argc, const char **argv)
221 {
222     static struct ifconfig_option ifconfig_cmd;
223     err_t ret;
224 
225     (void)memset_s(&ifconfig_cmd, sizeof(ifconfig_cmd), 0, sizeof(ifconfig_cmd));
226     if (sys_sem_new(&ifconfig_cmd.cb_completed, 0) != ERR_OK) {
227         PRINTK("%s: sys_sem_new fail\n", __FUNCTION__);
228         return 1;
229     }
230 
231     /* Get the interface */
232 
233     /* no more arguments, show all the interface state. */
234     ret = tcpip_callback(lwip_ifconfig_show_internal, &ifconfig_cmd);
235     if (ret != ERR_OK) {
236         sys_sem_free(&ifconfig_cmd.cb_completed);
237         PRINTK("ifconfig : internal error, l:%d err:%d\n", __LINE__, ret);
238         return 1;
239     }
240     (void)sys_arch_sem_wait(&ifconfig_cmd.cb_completed, 0);
241     sys_sem_free(&ifconfig_cmd.cb_completed);
242     ifconfig_cmd.cb_print_buf[PRINT_BUF_LEN - 1] = '\0';
243     PRINTK("%s", ifconfig_cmd.cb_print_buf);
244 
245     return 0;
246 }
247 
248 #if LWIP_DNS
249 #ifndef LWIP_TESTBED
250 LWIP_STATIC
251 #endif
gethostnameinfo(const char * host,char * tmphstbuf,size_t hstbuflen)252 struct hostent *gethostnameinfo(const char *host, char *tmphstbuf, size_t hstbuflen)
253 {
254     static struct hostent hostbuf;
255     struct hostent *hp = NULL;
256     int res;
257     int herr;
258 
259     if (tmphstbuf == NULL)
260         return NULL;
261     res = lwip_gethostbyname_r(host, &hostbuf, tmphstbuf, hstbuflen, &hp, &herr);
262     /*  Check for errors.  */
263     if (res || hp == NULL) {
264         return NULL;
265     }
266     return hp;
267 }
268 
get_hostip(const char * hname)269 LWIP_STATIC unsigned int get_hostip(const char *hname)
270 {
271     unsigned int ip = 0;
272     errno_t ret;
273     const size_t hstbuflen = 1024;
274     char *tmphstbuf = NULL;
275 
276     tmphstbuf = (char *)zalloc(sizeof(char) * hstbuflen);
277     if (tmphstbuf == NULL)
278         return 0;
279 
280     struct hostent *pent = gethostnameinfo(hname, tmphstbuf, hstbuflen);
281     if (pent == NULL || pent->h_addr == NULL) {
282         free(tmphstbuf);
283         return 0;
284     }
285     ret = memcpy_s(&ip, sizeof(ip), pent->h_addr, sizeof(pent->h_addr));
286     if (ret != EOK) {
287         free(tmphstbuf);
288         return 0;
289     }
290     free(tmphstbuf);
291     return ip;
292 }
293 
294 #endif
295 
296 static int ping_taskid = -1;
297 static int ping_kill = 0;
298 #define LWIP_SHELL_CMD_PING_TIMEOUT 2000
299 #define LWIP_SHELL_CMD_PING_RETRY_TIMES 4
300 #define PING_ZERO_DATA_LEN 8
301 
lwip_ping_usage(void)302 static void lwip_ping_usage(void)
303 {
304     PRINTK("Usage:\n  ping [ip]\n");
305 }
306 
OsPingFunc(u32_t * parg)307 LWIP_STATIC int OsPingFunc(u32_t *parg)
308 {
309     int sfd;
310     struct sockaddr_in to;
311     struct pbuf *pbuf_resp = NULL;
312     struct icmp_echo_hdr *iecho = NULL;
313     struct icmp_echo_hdr *iecho_resp = NULL;
314     struct ip_hdr *iphdr_resp = NULL;
315     u32_t iecho_len;
316     s16_t ip_hlen;
317     u32_t forever;
318     u32_t i;
319     u32_t succ_cnt = 0;
320     u32_t failed_cnt = 0;
321     struct timespec start, end;
322     long timout_ms;
323     struct pollfd pfd;
324     long rtt;
325     int ret = 0;
326     u32_t intrvl;
327     char *data_buf = NULL;
328     BOOL timeout_flag = FALSE;
329     char buf[50];
330 
331     u32_t destip = parg[0];
332     u32_t cnt = parg[1];
333     u32_t interval = parg[2];
334     u32_t data_len = parg[3];
335 
336     iecho_len = sizeof(struct icmp_echo_hdr) + data_len;
337     sfd = lwip_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
338     if (sfd < 0) {
339         perror("Ping socket");
340         return -1;
341     }
342     pbuf_resp = pbuf_alloc(PBUF_RAW, IP_HLEN + sizeof(struct icmp_echo_hdr), PBUF_RAM);
343     if (pbuf_resp == NULL) {
344         PRINTK("Ping: pbuf_resp malloc failed\n");
345         ret = -1;
346         goto FAILURE;
347     }
348     iecho = (struct icmp_echo_hdr *)mem_malloc(iecho_len);
349     if (iecho == NULL) {
350         PRINTK("Ping: echo request malloc failed\n");
351         ret = -1;
352         goto FAILURE;
353     }
354 
355     to.sin_family = AF_INET;
356     to.sin_addr.s_addr = destip; /* already in network order */
357     to.sin_port = 0;
358 
359     if (data_len > PING_ZERO_DATA_LEN) {
360         (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN,
361                        0, sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN);
362         data_buf = (char *)iecho + sizeof(struct icmp_echo_hdr) + PING_ZERO_DATA_LEN;
363         for (i = 0; i < data_len - PING_ZERO_DATA_LEN; i++) {
364             *(data_buf + i) = i + 0x10;
365         }
366     } else {
367         (void)memset_s(iecho, sizeof(struct icmp_echo_hdr) + data_len, 0, sizeof(struct icmp_echo_hdr) + data_len);
368     }
369     iecho->id = htons((u16_t)LOS_CurTaskIDGet());
370     ICMPH_TYPE_SET(iecho, (u8_t)ICMP_ECHO);
371     forever = (cnt ? 0 : 1);
372     i = 0;
373     while (!ping_kill && (forever || (i < cnt))) {
374         iecho->seqno = htons((u16_t)i);
375         iecho->chksum = 0;
376 #if (CHECKSUM_GEN_ICMP > 0)
377         iecho->chksum = inet_chksum((void *)iecho, iecho_len);
378 #endif
379         ret = sendto(sfd, iecho, iecho_len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to));
380         if (ret < 0) {
381             perror("Ping: sending ICMP echo request failed\n");
382             goto FAILURE;
383         }
384 
385         /* capture the start time to calculate RTT */
386         (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start);
387 
388         /* poll for ICMP echo response msg */
389         pfd.fd = sfd;
390 
391         do {
392             pfd.events = POLLIN;
393             pfd.revents = 0;
394             timeout_flag = FALSE;
395             ret = lwip_poll(&pfd, 1, LWIP_SHELL_CMD_PING_TIMEOUT);
396             if (ret < 0) {
397                 perror("Ping: poll\n");
398                 goto FAILURE;
399             } else if (ret == 0) {
400                 /* first type timeout event */
401                 timeout_flag = TRUE;
402                 break;
403             }
404 
405             ret = recv(sfd, pbuf_resp->payload, pbuf_resp->len, MSG_DONTWAIT);
406             if (ret < 0) {
407                 perror("Ping: recv echo reply failed\n");
408                 goto FAILURE;
409             }
410 
411             /* Accessing ip header and icmp header */
412             iphdr_resp = pbuf_resp->payload;
413 
414             ip_hlen = (IPH_HL(iphdr_resp) << 2); /* 2: offset */
415             if (pbuf_header(pbuf_resp, -ip_hlen)) {
416                 /* this failure will never happen, but failure handle is written just to be in safe side */
417                 PRINTK("Ping : memory management failure\n");
418                 goto FAILURE;
419             }
420             iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload;
421             /* Reverting back pbuf to its original state */
422             if (pbuf_header(pbuf_resp, ip_hlen)) {
423                 /* this failure will never happen, but failure handle is written just to be in safe side */
424                 PRINTK("ping : memory management failure\n");
425                 goto FAILURE;
426             }
427 
428             if ((iphdr_resp->src.addr != to.sin_addr.s_addr) ||
429                 ((ICMPH_TYPE(iecho_resp) == ICMP_ECHO) && (iphdr_resp->src.addr == to.sin_addr.s_addr))) {
430                 /* second type timeout event */
431                 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
432                 timout_ms = ((end.tv_sec - start.tv_sec) * OS_SYS_MS_PER_SECOND + \
433                              (end.tv_nsec - start.tv_nsec) / OS_SYS_NS_PER_MS);
434                 timout_ms = LWIP_SHELL_CMD_PING_TIMEOUT - timout_ms;
435             } else {
436                 timout_ms = 0;
437                 break;
438             }
439         } while (timout_ms >= 0);
440 
441         /* all timeout events are true timeout */
442         if ((timout_ms < 0) || (timeout_flag == TRUE)) {
443             failed_cnt++;
444             i++;
445             PRINTK("\nPing: destination unreachable ...");
446             continue;
447         }
448         /* capture the end time to calculate round trip time */
449         (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
450         rtt = ((end.tv_sec - start.tv_sec) * OS_SYS_MS_PER_SECOND + \
451                (end.tv_nsec - start.tv_nsec) / OS_SYS_NS_PER_MS);
452 
453         if (iphdr_resp->src.addr == to.sin_addr.s_addr) {
454             switch (ICMPH_TYPE(iecho_resp)) {
455                 case ICMP_ER:
456                     PRINTK("\n[%u]Reply from %s: ", i, inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
457                     if (rtt > 0) {
458                         PRINTK("time=%ims ", rtt);
459                     } else {
460                         PRINTK("time<1ms ");
461                     }
462                     PRINTK("TTL=%u", iphdr_resp->_ttl);
463 
464                     /* delay 1s for every successful ping */
465                     intrvl = interval;
466                     do {
467                         if (intrvl < 1000) { /* 1000: 1000ms = 1s */
468                             sys_msleep(intrvl);
469                             break;
470                         }
471                         intrvl -= 1000; /* 1000: 1000ms = 1s */
472                         sys_msleep(1000); /* 1000: 1000ms = 1s */
473                         if (ping_kill == 1) {
474                             break;
475                         }
476                     } while (intrvl > 0);
477                     succ_cnt++;
478                     break;
479                 case ICMP_DUR:
480                     PRINTK("\nPing: destination host unreachable ...");
481                     break;
482                 case ICMP_SQ:
483                     PRINTK("\nPing: source quench ...");
484                     break;
485                 case ICMP_RD:
486                     PRINTK("\nPing: redirect ...");
487                     break;
488                 case ICMP_TE:
489                     PRINTK("\nPing: time exceeded ...");
490                     break;
491                 case ICMP_PP:
492                     PRINTK("\nPing: parameter problem ...");
493                     break;
494                 default:
495                     PRINTK("\nPing: unknown error ...");
496                     break;
497             }
498             i++;
499         }
500     }
501 
502     PRINTK("\n--- %s ping statistics ---\n", inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
503     PRINTK("%u packets transmitted, %u received, %u loss\n", i, succ_cnt, failed_cnt);
504 
505 FAILURE:
506     ping_kill = 0;
507     (void)lwip_close(sfd);
508     if (pbuf_resp != NULL) {
509         (void)pbuf_free(pbuf_resp);
510     }
511     if (iecho != NULL) {
512         mem_free(iecho);
513     }
514     return ret;
515 }
516 
ping_cmd(u32_t * parg)517 static void ping_cmd(u32_t *parg)
518 {
519     int ret;
520 
521     ret = OsPingFunc(parg);
522     if (ret < 0) {
523         PRINTK("Ping cmd failed due to some errors\n");
524     }
525     free(parg);
526     ping_taskid = -1;
527 }
528 
OsShellPing(int argc,const char ** argv)529 u32_t OsShellPing(int argc, const char **argv)
530 {
531     int ret;
532     u32_t i = 0;
533     u32_t count;
534     int count_set = 0;
535     u32_t interval = 1000; /* default ping interval */
536     u32_t data_len = 48; /* default data length */
537     ip4_addr_t dst_ipaddr;
538     TSK_INIT_PARAM_S stPingTask;
539     u32_t *parg = NULL;
540 
541     if ((argc < 1) || (argv == NULL)) {
542         PRINTK("Ping: require dest ipaddr at least\n");
543         goto ping_error;
544     }
545 
546     if (!count_set) {
547         count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
548     }
549 
550     /* initialize dst IP address */
551     if (argc <= 0) {
552         goto ping_error;
553     }
554 #if LWIP_DNS
555     dst_ipaddr.addr = get_hostip(argv[i]);
556 #endif /* LWIP_DNS */
557 
558     if (dst_ipaddr.addr == IPADDR_NONE || dst_ipaddr.addr == IPADDR_ANY) {
559         PRINTK("Invalid dest ipaddr: NONE or ANY\n");
560         return LOS_NOK;
561     }
562 
563     parg = (u32_t *)malloc(4 * sizeof(int)); /* 4: number of args */
564     if (parg == NULL) {
565         return LOS_NOK;
566     }
567     parg[0] = dst_ipaddr.addr;
568     parg[1] = count;
569     parg[2] = interval;
570     parg[3] = data_len;
571 
572     /* start one task if ping forever or ping count greater than 60 */
573     if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) {
574         if (ping_taskid > 0) {
575             free(parg);
576             PRINTK("Ping task already running and only support one now\n");
577             return LOS_NOK;
578         }
579         stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd;
580         stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
581         stPingTask.pcName = "ping_task";
582         stPingTask.usTaskPrio = 8; /* 8: higher than shell */
583         stPingTask.uwResved = LOS_TASK_STATUS_DETACHED;
584         stPingTask.uwArg = (UINTPTR)parg;
585         ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask);
586         if (ret != LOS_OK) {
587             PRINTK("ping_task create failed 0x%08x.\n", ret);
588             count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
589         } else {
590             return LOS_OK;
591         }
592     }
593 
594     /* two cases:
595      1, ping cout less than LWIP_SHELL_CMD_PING_RETRY_TIMES;
596      2, ping task create failed;
597     */
598     if (OsPingFunc(parg) < 0) {
599         PRINTK("Ping cmd failed due some errors\n");
600     }
601 
602     free(parg);
603 
604     return LOS_OK;
605 ping_error:
606     lwip_ping_usage();
607     return LOS_NOK;
608 }
609 
610