--- /dev/null
+/*
+ * Copyright (C) 2012-2019 Czech Technical University in Prague
+ *
+ * Created on: 7.3.2019
+ *
+ * Authors:
+ * - Jakub Nejedly
+ *
+ * This document contains proprietary information belonging to Czech
+ * Technical University in Prague. Passing on and copying of this
+ * document, and communication of its contents is not permitted
+ * without prior written authorization.
+ *
+ * File : cmd_ping.c
+ *
+ * Abstract:
+ *
+ *
+ */
+
+#include "cmd_ping.h"
+
+#ifndef DOCGEN
+
+
+#include "cmdproc_freertos.h"
+#include "rpp/rpp.h"
+
+#include "lwip/mem.h"
+#include "lwip/raw.h"
+#include "lwip/icmp.h"
+#include "lwip/netif.h"
+#include "lwip/sys.h"
+#include "lwip/timers.h"
+#include "lwip/inet_chksum.h"
+
+#include "lwip/sockets.h"
+#include "lwip/inet.h"
+
+
+#define PING_RCV_TIMEO 1000
+#define PING_DATA_SIZE 32
+#define PING_ID 0xAFAF
+#define PING_DELAY 1000
+
+static u16_t ping_seq_num;
+static u32_t ping_time;
+
+static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len){
+
+ size_t i;
+ size_t data_len = len - sizeof(struct icmp_echo_hdr);
+
+ ICMPH_TYPE_SET(iecho, ICMP_ECHO);
+ ICMPH_CODE_SET(iecho, 0);
+ iecho->chksum = 0;
+ iecho->id = PING_ID;
+ iecho->seqno = htons(++ping_seq_num);
+
+ /* fill the additional data buffer with some data */
+ for(i = 0; i < data_len; i++) {
+ ((char*)iecho)[sizeof(struct icmp_echo_hdr) + i] = (char)i;
+ }
+
+ iecho->chksum = inet_chksum(iecho, len);
+}
+
+static err_t ping_send(int s, ip_addr_t *addr) {
+
+ int err;
+ struct icmp_echo_hdr *iecho;
+ struct sockaddr_in to;
+ size_t ping_size = sizeof(struct icmp_echo_hdr) + PING_DATA_SIZE;
+ LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff);
+
+ iecho = (struct icmp_echo_hdr *)mem_malloc((mem_size_t)ping_size);
+ if (!iecho) {
+ return ERR_MEM;
+ }
+
+ ping_prepare_echo(iecho, (u16_t)ping_size);
+
+ to.sin_len = sizeof(to);
+ to.sin_family = AF_INET;
+ inet_addr_from_ipaddr(&to.sin_addr, addr);
+
+ err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*)&to, sizeof(to));
+
+ mem_free(iecho);
+
+ return (err ? ERR_OK : ERR_VAL);
+}
+
+static void ping_recv(int s){
+
+ char buf[256];
+ int fromlen, len;
+ struct sockaddr_in from;
+ struct ip_hdr *iphdr;
+ struct icmp_echo_hdr *iecho;
+
+ while((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*)&from, (socklen_t*)&fromlen)) > 0
+ && (unsigned long)(sys_now() - ping_time) < PING_DELAY-10) {
+ if (len >= (int)(sizeof(struct ip_hdr)+sizeof(struct icmp_echo_hdr))) {
+
+ ip_addr_t fromaddr;
+ inet_addr_to_ipaddr(&fromaddr, &from.sin_addr);
+
+ rpp_sci_printf(" time=%lu ms\n", (unsigned long)(sys_now() - ping_time));
+
+ iphdr = (struct ip_hdr *)buf;
+ iecho = (struct icmp_echo_hdr *)(buf + (IPH_HL(iphdr) * 4));
+ if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) {
+ /* do some ping result processing */
+ return;
+ } else {
+ rpp_sci_printf(" droped\n");
+ }
+ }
+ }
+ rpp_sci_printf(" time=%lu ms - timeout \n", (unsigned long)(sys_now() - ping_time));
+
+ /* do some ping result processing */
+ return;
+}
+
+
+int cmd_do_eth_ping(cmd_io_t *cmd_io, const struct cmd_des *des, char *param[]){
+
+ // test ethinit
+ if (!isPostInitialized()) {
+ rpp_sci_printf("Eth not initialized run 'ethinit' command first.\n");
+ return FAILURE;
+ }
+ err_t err = ERR_OK;
+
+ // parse params
+ ip_addr_t ping_target;
+
+ if ( (err = rpp_eth_stringToIP(&ping_target, (uint8_t *)param[1])) != SUCCESS ) {
+ rpp_sci_printf("ERR: IP address format\r\n");
+ return BAD_OPTION;
+ }
+
+ // socket creation
+ int s;
+ int timeout = PING_RCV_TIMEO;
+ if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) {
+ rpp_sci_printf("ERR: lwip socket init\r\n");
+ return FAILURE;
+ }
+
+ /*int ret = */
+ lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
+ //rpp_sci_printf("Socket opt result %d \n", ret);
+
+ while (1) {
+
+ if (ping_send(s, &ping_target) == ERR_OK) {
+ rpp_sci_printf("ping: send to ");
+ rpp_sci_printf("%s", inet_ntoa(ping_target));
+ //rpp_sci_printf("\n");
+
+ ping_time = sys_now();
+ ping_recv(s);
+ } else {
+ rpp_sci_printf("ping: send to ");
+ rpp_sci_printf("%s", inet_ntoa(ping_target));
+ rpp_sci_printf(" - error during sending \n");
+ }
+ sys_msleep(PING_DELAY);
+ }
+}
+
+
+
+#endif /* DOCGEN */
+
+cmd_des_t const cmd_des_ethping = {
+ 0, 0,
+ "ethping","Command to send and receive ICMP packets",
+ "### Command syntax ###\n"
+ "\n"
+ " ethping [IP_address] \n"
+ "\n"
+ "### Description ###\n"
+ "basic implementation of outgoing ping"
+ "\n"
+ "### Example ###\n"
+ "\n"
+ " --> ethping 8.8.8.8\n",
+ CMD_HANDLER(cmd_do_eth_ping), (void *)&cmd_list_ping
+};
+
+/** List of commands for adc, defined as external */
+cmd_des_t const *cmd_list_ping[] = {
+ &cmd_des_ethping,
+ NULL
+};