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