• 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 cache 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 timeout_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 
377 #if (CHECKSUM_GEN_ICMP > 0)
378         iecho->chksum = inet_chksum((void *)iecho, iecho_len);
379 #endif
380 
381         ret = sendto(sfd, iecho, iecho_len, 0, (struct sockaddr *)&to, (socklen_t)sizeof(to));
382         if (ret < 0) {
383             perror("Ping: sending ICMP echo request failed\n");
384             goto FAILURE;
385         }
386 
387         /* capture the start time to calculate RTT */
388         (void)clock_gettime(CLOCK_MONOTONIC_RAW, &start);
389 
390         /* poll for ICMP echo response msg */
391         pfd.fd = sfd;
392 
393         do {
394             pfd.events = POLLIN;
395             pfd.revents = 0;
396             timeout_flag = FALSE;
397             ret = lwip_poll(&pfd, 1, LWIP_SHELL_CMD_PING_TIMEOUT);
398             if (ret < 0) {
399                 perror("Ping: poll\n");
400                 goto FAILURE;
401             } else if (ret == 0) {
402                 /* first type timeout event */
403                 timeout_flag = TRUE;
404                 break;
405             }
406 
407             ret = recv(sfd, pbuf_resp->payload, pbuf_resp->len, MSG_DONTWAIT);
408             if (ret < 0) {
409                 perror("Ping: recv echo reply failed\n");
410                 goto FAILURE;
411             }
412 
413             /* Accessing ip header and icmp header */
414             iphdr_resp = pbuf_resp->payload;
415 
416             ip_hlen = (IPH_HL(iphdr_resp) << 2); /* 2: offset */
417             if (pbuf_header(pbuf_resp, -ip_hlen)) {
418                 /* this failure will never happen, but failure handle is written just to be in safe side */
419                 PRINTK("Ping : memory management failure\n");
420                 goto FAILURE;
421             }
422             iecho_resp = (struct icmp_echo_hdr *)pbuf_resp->payload;
423             /* Reverting back pbuf to its original state */
424             if (pbuf_header(pbuf_resp, ip_hlen)) {
425                 /* this failure will never happen, but failure handle is written just to be in safe side */
426                 PRINTK("ping : memory management failure\n");
427                 goto FAILURE;
428             }
429 
430             if ((iphdr_resp->src.addr != to.sin_addr.s_addr) ||
431                 ((ICMPH_TYPE(iecho_resp) == ICMP_ECHO) && (iphdr_resp->src.addr == to.sin_addr.s_addr))) {
432                 /* second type timeout event */
433                 (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
434                 timeout_ms = ((end.tv_sec - start.tv_sec) * OS_SYS_MS_PER_SECOND + \
435                              (end.tv_nsec - start.tv_nsec) / OS_SYS_NS_PER_MS);
436                 timeout_ms = LWIP_SHELL_CMD_PING_TIMEOUT - timeout_ms;
437             } else {
438                 timeout_ms = 0;
439                 break;
440             }
441         } while (timeout_ms >= 0);
442 
443         /* all timeout events are true timeout */
444         if ((timeout_ms < 0) || (timeout_flag == TRUE)) {
445             failed_cnt++;
446             i++;
447             PRINTK("\nPing: destination unreachable ...");
448             continue;
449         }
450         /* capture the end time to calculate round trip time */
451         (void)clock_gettime(CLOCK_MONOTONIC_RAW, &end);
452         rtt = ((end.tv_sec - start.tv_sec) * OS_SYS_MS_PER_SECOND + \
453                (end.tv_nsec - start.tv_nsec) / OS_SYS_NS_PER_MS);
454 
455         if (iphdr_resp->src.addr == to.sin_addr.s_addr) {
456             switch (ICMPH_TYPE(iecho_resp)) {
457                 case ICMP_ER:
458                     PRINTK("\n[%u]Reply from %s: ", i, inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
459                     if (rtt > 0) {
460                         PRINTK("time=%ims ", rtt);
461                     } else {
462                         PRINTK("time<1ms ");
463                     }
464                     PRINTK("TTL=%u", iphdr_resp->_ttl);
465 
466                     /* delay 1s for every successful ping */
467                     intrvl = interval;
468                     do {
469                         if (intrvl < 1000) { /* 1000: 1000ms = 1s */
470                             sys_msleep(intrvl);
471                             break;
472                         }
473                         intrvl -= 1000; /* 1000: 1000ms = 1s */
474                         sys_msleep(1000); /* 1000: 1000ms = 1s */
475                         if (ping_kill == 1) {
476                             break;
477                         }
478                     } while (intrvl > 0);
479                     succ_cnt++;
480                     break;
481                 case ICMP_DUR:
482                     PRINTK("\nPing: destination host unreachable ...");
483                     break;
484                 case ICMP_SQ:
485                     PRINTK("\nPing: source quench ...");
486                     break;
487                 case ICMP_RD:
488                     PRINTK("\nPing: redirect ...");
489                     break;
490                 case ICMP_TE:
491                     PRINTK("\nPing: time exceeded ...");
492                     break;
493                 case ICMP_PP:
494                     PRINTK("\nPing: parameter problem ...");
495                     break;
496                 default:
497                     PRINTK("\nPing: unknown error ...");
498                     break;
499             }
500             i++;
501         }
502     }
503 
504     PRINTK("\n--- %s ping statistics ---\n", inet_ntop(AF_INET, &to.sin_addr, buf, sizeof(buf)));
505     PRINTK("%u packets transmitted, %u received, %u loss\n", i, succ_cnt, failed_cnt);
506 
507 FAILURE:
508     ping_kill = 0;
509     (void)lwip_close(sfd);
510     if (pbuf_resp != NULL) {
511         (void)pbuf_free(pbuf_resp);
512     }
513     if (iecho != NULL) {
514         mem_free(iecho);
515     }
516     return ret;
517 }
518 
ping_cmd(u32_t * parg)519 static void ping_cmd(u32_t *parg)
520 {
521     int ret;
522 
523     ret = OsPingFunc(parg);
524     if (ret < 0) {
525         PRINTK("Ping cmd failed due to some errors\n");
526     }
527     free(parg);
528     ping_taskid = -1;
529 }
530 
OsShellPing(int argc,const char ** argv)531 u32_t OsShellPing(int argc, const char **argv)
532 {
533     int ret;
534     u32_t i = 0;
535     u32_t count;
536     int count_set = 0;
537     u32_t interval = 1000; /* default ping interval */
538     u32_t data_len = 48; /* default data length */
539     ip4_addr_t dst_ipaddr;
540     TSK_INIT_PARAM_S stPingTask;
541     u32_t *parg = NULL;
542 
543     if ((argc < 1) || (argv == NULL)) {
544         PRINTK("Ping: require dest ipaddr at least\n");
545         goto ping_error;
546     }
547 
548     if (!count_set) {
549         count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
550     }
551 
552     /* initialize dst IP address */
553     if (argc <= 0) {
554         goto ping_error;
555     }
556 #if LWIP_DNS
557     dst_ipaddr.addr = get_hostip(argv[i]);
558 #endif /* LWIP_DNS */
559 
560     if (dst_ipaddr.addr == IPADDR_NONE || dst_ipaddr.addr == IPADDR_ANY) {
561         PRINTK("Invalid dest ipaddr: NONE or ANY\n");
562         return LOS_NOK;
563     }
564 
565     parg = (u32_t *)malloc(4 * sizeof(int)); /* 4: number of args */
566     if (parg == NULL) {
567         return LOS_NOK;
568     }
569     parg[0] = dst_ipaddr.addr;
570     parg[1] = count;
571     parg[2] = interval;
572     parg[3] = data_len;
573 
574     /* start one task if ping forever or ping count greater than 60 */
575     if (count == 0 || count > LWIP_SHELL_CMD_PING_RETRY_TIMES) {
576         if (ping_taskid > 0) {
577             free(parg);
578             PRINTK("Ping task already running and only support one now\n");
579             return LOS_NOK;
580         }
581         stPingTask.pfnTaskEntry = (TSK_ENTRY_FUNC)ping_cmd;
582         stPingTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
583         stPingTask.pcName = "ping_task";
584         stPingTask.usTaskPrio = 8; /* 8: higher than shell */
585         stPingTask.uwResved = LOS_TASK_STATUS_DETACHED;
586         stPingTask.uwArg = (UINTPTR)parg;
587         ret = LOS_TaskCreate((UINT32 *)(&ping_taskid), &stPingTask);
588         if (ret != LOS_OK) {
589             PRINTK("ping_task create failed 0x%08x.\n", ret);
590             count = LWIP_SHELL_CMD_PING_RETRY_TIMES;
591         } else {
592             return LOS_OK;
593         }
594     }
595 
596     /* two cases:
597      1, ping cout less than LWIP_SHELL_CMD_PING_RETRY_TIMES;
598      2, ping task create failed;
599     */
600     if (OsPingFunc(parg) < 0) {
601         PRINTK("Ping cmd failed due some errors\n");
602     }
603 
604     free(parg);
605 
606     return LOS_OK;
607 ping_error:
608     lwip_ping_usage();
609     return LOS_NOK;
610 }
611 
612