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