“Ping” is an important function in Networking. It is a function to see if the connectivity is alright, which is an essential tool for debugging. It is under Internet Control Management Protocol (ICMP), no wonder why it is important for debugging.
For “Ping”, or to “ping” a device, it technically means sending a message to a desired device/place and getting an echo(message with exactly the same data being sent), making sure the data is transferable and the connection is good to use. If the “Ping” process can not be completed, you may need to check the connectivity to see what actually happened in the route. Here we are not going deep into how to analyse the connectivity.
Other than most of the protocol, it neither bases on TCP or UDP, but ICMP, we may go further about the packet format below.
Before burning the bin file into your EVB:
-
-
- Connect W5500 EVB to the router/NAT that you are using, or any other device that allows you to connect to the internet
- Manually change the Network configuration:
-
- Go to the definition of function “set_default()” (Should be inside device.c), make sure the subnet mask, local IP address, gateway and DNS are set according to the internet setting you are using with your router/NAT
-
- Rebuild the sample code and burn it into W5500EVB
- Change your PC’s IP address to a static IP if you are not using router
-
Code Explanation
The sample code are basically divided into four states: Initialized, Established, To Be Closed, Closed.
int main(void) {
As usual, W5500EVB does the initialization about the network setting and communication setting and stuff. It then goes into do_ping(). Please notice that there is no while loop in main(), which means the do_ping() only does once and W5500EVB does nothing afterwards.
systick_init(72); USART1_Config(); i2c_CfgGpio(); gpio_for_w5500_config(); reset_w5500(); set_w5500_mac(); set_w5500_ip(); socket_buf_init(txsize, rxsize); printf("\r\n------------Start Ping Test!-----------------------\r\n\r\n"); do_ping(); }
/****************** These are all the necessary initialization ********************/
do_ping() is a function which leads you to the ping_count() function, the main function of this example.
Like when you ping other devices using your computer(command-line on windows), a total of four “ping” would be done consequently. It depends on what parameter you input, 4 “ping”s would be done by default if you do not make any changes.
void do_ping(void) { ping_count(SOCK_PING,4,remote_ip); }
ping_count()
It first goes into a for-loop (loop 4 times by default). It goes to the switch statement.
void ping_count(uint8 s, uint16 pCount, uint8 *addr) { uint16 rlen, cnt,i; cnt = 0; for(i=0; i<pCount+1;i++) { if(i!=0) { /* Output count number */ printf( "No.%d ",i); } switch(getSn_SR(s)) {
Initially no socket is opened, therefore it goes into case “SOCK_CLOSED”and open a socket in “IP RAW” mode. As mentioned above, the socket is opened in “IP RAW” mode rather than UDP or TCP mode since “Ping” is under ICMP.
Make sure the socket is opened in “IP RAW” mode. Do nothing until then.
case SOCK_CLOSED: close(s); IINCHIP_WRITE(Sn_PROTO(s), IPPROTO_ICMP); if(socket(s,Sn_MR_IPRAW,3000,0)!=0) { } while(getSn_SR(s)!=SOCK_IPRAW); break;
/*************** Make sure the socket is closed initially Open the socket with "IP RAW" mode Make sure the socket is opened in “IP RAW” mode. Do nothing until then. ****************/
When the socket is opened, it starts sending a Ping request with the function ping_request(), which will be discussed below.
Then it enters a while loop and waits until there is any data going in the RX buffer. If there is data received, it goes into the ping_reply() function to handle the replied message, else no data is detected for a certain amount of time, it sends a message to serial, showing “time out”, and breaks the for loop.
case SOCK_IPRAW: ping_request(s, addr); req++ while(1) { if ( (rlen = getSn_RX_RSR(s) ) > 0) { ping_reply(s, addr, rlen); rep++; if (ping_reply_received) break; } if ( (cnt > 1000) ) { printf("Request Time out\r\n\r\n") ; cnt = 0; break; } else { cnt++; delay_ms(1000); } } break; default: break;
/**************** Sending a Ping request Enters a while loop Waits until there is any data going in the RX buffer Handle the replied message packet No data is detected for a certain amount of time printf message, showing timeout ****************/
if(req>=pCount) { printf("Ping Request = %d, Ping Reply = %d, Lost = %d\r\n",req,rep,req-rep); } } }
ping_request()
This is a function for sending ping request packet to the target device
uint8 ping_request(uint8 s, uint8 *addr) {
The struct “PingRequest” is used to store the data and construct it into a packet with ping packet format, which would be discussed below.
uint16 i; ping_reply_received = 0; PingRequest.Type = PING_REQUEST; PingRequest.Code = CODE_ZERO; PingRequest.ID = htons(RandomID++); PingRequest.SeqNum =htons(RandomSeqNum++); for(i = 0 ; i < BUF_LEN; i++) { PingRequest.Data[i] = (i) % 8; }
htons() changes the order of the data to fit the data sequence for data transmission
checksum() helps calculate the checksum of the data packet. Please be reminded that checksum itself, in this example “PingRequest.CheckSum”, should be zero since the calculation of checksum excludes the value of checksum. Otherwise if checksum has value, the function checksum() would include the value and give a wrong checksum value, hence fail to get any reply from the target device.
PingRequest.CheckSum = 0; // ************The function for calculating checksum, explanation above************ PingRequest.CheckSum = htons(checksum((uint8*)&PingRequest,sizeof(PingRequest))); // ******************************************************************************** // Then internal-check to see if the message is sent, and send a message to serial to indicate the result. if(sendto(s,(uint8 *)&PingRequest,sizeof(PingRequest),addr,3000)==0) { printf("Fail to send ping-reply packet\r\n"); } else { printf("Ping:%d.%d.%d.%d\r\n",(addr[0]), (addr[1]), (addr[2]), (addr[3])); } return 0; }
ping_reply()
This is a function to check if the received packet is valid.
uint8 ping_reply(uint8 s, uint8 *addr, uint16 rlen) { uint16 tmp_checksum; uint16 len; uint16 i; uint8 data_buf[136]; uint16 port = 3000; PINGMSGR PingReply; len = recvfrom(s, data_buf,rlen,addr,&port);
First it checks if the packet is a reply or not. And the struct “PingReply” is used to store the data received, classify and divide it into its corresponding meaning.
// if(data_buf[0] == PING_REPLY) { PingReply.Type = data_buf[0]; PingReply.Code = data_buf[1]; PingReply.CheckSum = (data_buf[3]<<8) + data_buf[2]; PingReply.ID = (data_buf[5]<<8) + data_buf[4]; PingReply.SeqNum = (data_buf[7]<<8) + data_buf[6]; for(i=0; i<len-8 ; i++) { PingReply.Data[i] = data_buf[8+i]; } tmp_checksum = ~checksum(data_buf,len); if(tmp_checksum != 0xffff) printf("tmp_checksum = %x\r\n",tmp_checksum);
/**************** First it checks if the packet is a reply or not. Classify and divide the received packet Check if the checksum of the packet is correct ****************/
else { printf("Reply from %3d.%3d.%3d.%3d ID=%x Byte=%d\r\n\r\n",(addr[0]), (addr[1]), (addr[2]), (addr[3]),htons(PingReply.ID),(rlen+6)); ping_reply_received =1; // a counter indicating the success of the ping process. } }
Ping Packet Format
The related format of the packet would be as follows:

Type indicates the type of packet you receive. We have a couple of types under ICMP. For ping packets, you will probably see type 0(), type 8(), and type 3 () if unfortunately.
Code indicates more details about the packet. It should always be 0 for type 0 and type 8.
ICMP Header Checksum is a 16-bit one’s complement of the one’s complement sum of the ICMP message, starting with the ICMP Type field. In this example, it is the packet format you saw above, excluding some information such as sender’s IP address and receiver’s IP address. The following video on YouTube gives a good explanation of how to calculate checksum for internet data transfer: https://youtu.be/EmUuFRMJbss
Identifier is a 4 digit 16 bits hex number for better identification. It can be any number within 16 bits.
Sequence shows the sequence of how much ping packet has already been sent. It can be any hex number within 16 bits.
Data is the content of the message. However in case of pinging, the data is not necessary at all that it can be any value or even null, which would not affect the pinging at all.
Remarks