2 * Copyright (C) 2012-2019 Czech Technical University in Prague
9 * This document contains proprietary information belonging to Czech
10 * Technical University in Prague. Passing on and copying of this
11 * document, and communication of its contents is not permitted
12 * without prior written authorization.
26 #include "cmdproc_freertos.h"
31 #include "lwip/icmp.h"
32 #include "lwip/netif.h"
34 #include "lwip/timers.h"
35 #include "lwip/inet_chksum.h"
37 #include "lwip/sockets.h"
38 #include "lwip/inet.h"
41 #define PING_RCV_TIMEO 1000
42 #define PING_DATA_SIZE 32
43 #define PING_ID 0xAFAF
44 #define PING_DELAY 1000
46 static u16_t ping_seq_num;
47 static u32_t ping_time;
49 static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len){
52 size_t data_len = len - sizeof(struct icmp_echo_hdr);
54 ICMPH_TYPE_SET(iecho, ICMP_ECHO);
55 ICMPH_CODE_SET(iecho, 0);
58 iecho->seqno = htons(++ping_seq_num);
60 /* fill the additional data buffer with some data */
61 for(i = 0; i < data_len; i++) {
62 ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
65 iecho->chksum = inet_chksum(iecho, len);
68 static err_t ping_send(int s, ip_addr_t *addr) {
71 struct icmp_echo_hdr *iecho;
72 struct sockaddr_in to;
73 size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
74 LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
76 iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
81 ping_prepare_echo(iecho, (u16_t)ping_size);
83 to.sin_len = sizeof(to);
84 to.sin_family = AF_INET;
85 inet_addr_from_ipaddr(&to.sin_addr, addr);
87 err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
91 return (err ? ERR_OK : ERR_VAL);
94 static void ping_recv(int s){
98 struct sockaddr_in from;
100 struct icmp_echo_hdr *iecho;
102 while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0
103 && (unsigned long)(sys_now() - ping_time) < PING_DELAY-10) {
104 if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
107 inet_addr_to_ipaddr(&fromaddr, &from.sin_addr);
109 rpp_sci_printf(" time=%lu ms\n", (unsigned long)(sys_now() - ping_time));
111 iphdr = (struct ip_hdr *)buf;
112 iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
113 if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
114 /* do some ping result processing */
117 rpp_sci_printf(" droped\n");
121 rpp_sci_printf(" time=%lu ms - timeout \n", (unsigned long)(sys_now() - ping_time));
123 /* do some ping result processing */
128 int cmd_do_eth_ping(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]){
131 if (!isPostInitialized()) {
132 rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
138 ip_addr_t ping_target;
140 if ( (err = rpp_eth_stringToIP(&ping_target, (uint8_t *)param[1])) != SUCCESS ) {
141 rpp_sci_printf("ERR: IP address format\r\n");
147 int timeout = PING_RCV_TIMEO;
148 if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
149 rpp_sci_printf("ERR: lwip socket init\r\n");
154 lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
155 //rpp_sci_printf("Socket opt result %d \n", ret);
159 if (ping_send(s, &ping_target) == ERR_OK) {
160 rpp_sci_printf("ping: send to ");
161 rpp_sci_printf("%s", inet_ntoa(ping_target));
162 //rpp_sci_printf("\n");
164 ping_time = sys_now();
167 rpp_sci_printf("ping: send to ");
168 rpp_sci_printf("%s", inet_ntoa(ping_target));
169 rpp_sci_printf(" - error during sending \n");
171 sys_msleep(PING_DELAY);
179 cmd_des_t const cmd_des_ethping = {
181 "ethping","Command to send and receive ICMP packets",
182 "### Command syntax ###\n"
184 " ethping [IP_address] \n"
186 "### Description ###\n"
187 "basic implementation of outgoing ping"
191 " --> ethping 8.8.8.8\n",
192 CMD_HANDLER(cmd_do_eth_ping), (void *)&cmd_list_ping
195 /** List of commands for adc, defined as external */
196 cmd_des_t const *cmd_list_ping[] = {