[...] > +static int ping_raw_init(void *recv_arg) > +{ > + ping_pcb = raw_new(IP_PROTO_ICMP); > + if (!ping_pcb) > + return -ENOMEM; > + > + raw_recv(ping_pcb, ping_recv, recv_arg); > + raw_bind(ping_pcb, IP_ADDR_ANY); > + > + return 0; > +} > + > +static void ping_raw_stop(void) > +{ > + if (ping_pcb != NULL) {
nits, but we usually do if (!ping_pcb) for NULL pointers and variables that have a value of 0. Please change it in other files as well > + raw_remove(ping_pcb); > + ping_pcb = NULL; > + } > +} > + > +static void ping_prepare_echo(struct icmp_echo_hdr *iecho) > +{ > + ICMPH_TYPE_SET(iecho, ICMP_ECHO); > + ICMPH_CODE_SET(iecho, 0); > + iecho->chksum = 0; > + iecho->id = PING_ID; > + iecho->seqno = lwip_htons(++ping_seq_num); > + > + iecho->chksum = inet_chksum(iecho, sizeof(*iecho)); > +} > + > +static void ping_send_icmp(struct raw_pcb *raw, const ip_addr_t *addr) > +{ > + struct pbuf *p; > + struct icmp_echo_hdr *iecho; > + size_t ping_size = sizeof(struct icmp_echo_hdr); > + > + p = pbuf_alloc(PBUF_IP, (u16_t)ping_size, PBUF_RAM); > + if (!p) > + return; > + > + if ((p->len == p->tot_len) && (p->next == NULL)) { && !p->next > + iecho = (struct icmp_echo_hdr *)p->payload; > + ping_prepare_echo(iecho); > + raw_sendto(raw, p, addr); > + } > + > + pbuf_free(p); > +} > + > +static void ping_send(void *arg) > +{ > + struct raw_pcb *pcb = (struct raw_pcb *)arg; > + > + ping_send_icmp(pcb, ping_target); > + sys_timeout(PING_DELAY_MS, ping_send, ping_pcb); > +} > + > +static int ping_loop(const ip_addr_t* addr) > +{ > + bool alive; > + ulong start; > + int ret; > + > + printf("Using %s device\n", eth_get_name()); > + > + ret = ping_raw_init(&alive); > + if (ret < 0) > + return ret; > + ping_target = addr; > + ping_seq_num = 0; > + > + start = get_timer(0); > + ping_send(ping_pcb); > + > + do { > + eth_rx(); > + if (alive) > + break; > + sys_check_timeouts(); > + if (ctrlc()) { > + printf("\nAbort\n"); > + break; > + } > + } while (get_timer(start) < PING_TIMEOUT_MS); I am a bit confused about what happens here. ping_send() will send the packet, but it will also schedule itself to rerun after 1 ms and send another ping? > + > + sys_untimeout(ping_send, ping_pcb); So we need the sys_untimeout() because we queued 2 pings? Because sys_timeout() is supposed to be an one shot. Thanks /Ilias > + ping_raw_stop(); > + ping_target = NULL; > + > + if (alive) { > + alive = false; > + return 0; > + } > + printf("ping failed; host %s is not alive\n", ipaddr_ntoa(addr)); > + return -1; > +} > + > +int do_ping(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) > +{ > + ip_addr_t addr; > + > + if (argc < 2) > + return CMD_RET_USAGE; > + > + if (!ipaddr_aton(argv[1], &addr)) > + return CMD_RET_USAGE; > + > + if (ping_loop(&addr) < 0) > + return CMD_RET_FAILURE; > + > + return CMD_RET_SUCCESS; > +} > -- > 2.40.1 >