W5100 SYN Problem


#1

I have designed an embedded board that includes W5100. I have to connect as TCP Client to a PLC and an IP Camera.
Camera IP: 192.168.0.10:80
PLC IP: 192.168.0.10:502
Embedded Board IP: 192.168.04
Gateway: 192.168.0.1
When I send CONNECT command to PLC or CAMERA while SOCK_INIT state, I can’t observe SYN flag(negotiation) via WIRESHARK but state changes to SOCK_ESTABLISHED.
When I try to connect to PLC or CAMERA by HERCULES software, I can observe SYN flag via WIRESHARK.
Because of no SYN flag, server(PLC or CAMERA) disconnects a few seconds later, i.e. state changes to SOCK_CLOSE_WAIT.
What is the problem or my mistake?


#2

Hi svsbaris,

I guess your computer running Wireshark and Hercules software is on the different network.
What is your computer’s IP address?

If you can connect to PLC or IP Camera with the embedded board, W5100 inside, then we can think of that all those work’s settings are correct.
Because your computer has different IP address range, Hercules running on your computer couldn’t connect to PLC or IP Camera.

And, the reason why you couldn’t see any SYN packet from your embedded borard is because you didn’t use Dummy Hub.
In order that Wireshark capture all packets between other systems, you have to connect all devices which communicate each other and monitoring system like your computer running wireshark to A DUMMY HUB.
If you use a switching hub, you can capture only packets from your computer or into it.
This is the answer to your first question.
Even though you couldn’t see any SYN packet, there is no problem for your embedded board to connect to PLC or IP camera.

Anyway, you’d better check your computer’s IP address. If it has different IP address range, then you already got the answer to your second question.

Thank you.

javakys.


#3

Unfortunately my computer’s IP is 192.168.0.3. All the devices are in same network (PC, Board, PLC, Camera).
Let me summarize all IP addresses:

PC: 192.168.0.3
Camera: 192.168.0.252
PLC:192.168.0.10
Board: 192.168.0.4 (retrieved by DHCP)
Gateway: 192.168.0.1

All Subnet Mask: 255.255.255.0

I can be connecting them during I keep connection alive by communicating them. If I don’t communicate with one of them (PLC or camera), it disconnects automatically. In the other words, W5100 doesn’t process 3-Way Negotiation (SYN, ACK, etc).


#4

Yes, I got there was no problem in your network configuration.

In order for you to go further, you need the packet capture file by wireshark.
According to your previous mention, it seems that you have no dummy hub.
Because your system having W5100 could connect to other devices and you found that the status of W5100 changed to SOCK_ESTABLISHED, I can say W5100 operates with 3-way handshaking properly.
If you set Hercules in your computer as server and make the embedded board connect to Hercules, MAYBE you can see W5100 send SYN packet to YOUR COMPUTER.

After doing test which I mentioned above, could you post the result and upload the capture file by wireshark?

Then I may help you a little more.

Thank you.

Javakys.


#5

As you wrote, I tried to connect to Hercules(192.168.0.3) form my board(3G Modem with Ethernet)(192.168.0.4), it was successful.
I observed that my problem is “No ARP Reply”:
PLC sends ARP Reply to Hercules,
Camera sends ARP Reply to Hercules,
Hercules sends ARP Reply to 3G Modem,
but
PLC Doesn’t send ARP Reply to 3G Modem,
Camera doesn’t send ARP Reply to 3G Modem.
When PLC, Camera or Hercules replies to ARP requests, I can see the SYN and ACK flags via Wireshark. If they don’t reply to ARP requests, I can’t see the SYN and ACK flags via Wireshark.
Shortly; PLC and Camera doesn’t reply the ARP requests from 3G Modem so I can’t connect to PLC & Camera regularly.
Any idea? :cry:


#6

Can you upload the packet capture file by wireshark?
If I see it, I may get some help.

Thank you.


#7

You will find 4 uploaded files at: http://sdrv.ms/1gt1z3m
1: 3G to Hercules connection:
3G IP: 192.168.0.3
3G Port: 58039
Hercules IP: 192.168.0.2
Hercules Port: 52000
In Frame #55, 60 and 61, SYN and ACK flags can be observed.

2: 3G to PLC connection:
3G IP: 192.168.0.3
3G Port: 58039
PLC IP: 192.168.0.10
PLC Port: 80
No ARP Reply.

3: Hercules to Camera connection:
Camera IP: 192.168.0.252
Camera Port: 80
Hercules IP: 192.168.0.2
Hercules Port: 52741
In Frame #105, 107 and 108, SYN and ACK flags can be observed.

4: Hercules to PLC connection:
PLC IP: 192.168.0.10
PLC Port: 80
Hercules IP: 192.168.0.2
Hercules Port: 52738
In Frame #21, 23 and 24, SYN and ACK flags can be observed.


#8

Hi,
I also wonder which problem is happenned.
I have a question which have ip configruation of them, static or dynamic ip?

I propose the test scheme that all ip is static configruation.

thanks.


#9

Hi,
In real, 3 device will be used: 3G Modem, PLC and Camera. For testing I use Hercules,
Camera and PLC have static, Hercules and 3G Modem has dynamic IP. I also tried when 3G Modem has static IP.
I couldn’t observe SYN and ACK flags because of no ARP Reply whenever 3G Modem(as client) tries to connect to PLC or Camera in neither with dynamic IP nor static IP.


#10

Hi svsbaris,

My colleagues and I investigated the capture file you attached to here.
[color=#FF0000]We could see something strange from packet # 80 to packet # 99 in “3G to PLC.pcapng”.[/color]
[color=#FF0000]Twice ARP packets came out from W5100 every 200ms[/color].
This never happens in normal situation.

You seem not to wait for command clear or command timeout in send() function of W5100 driver.

[code]/**
@brief This function used to send the data in TCP mode
@return 1 for success else 0.
*/
uint16 send(
SOCKET s, /< the socket index */
const uint8 * buf, /
< a pointer to data */
uint16 len /**< the data size to be send */
)
{
uint8 status=0;
uint16 ret=0;
uint16 freesize=0;
#ifdef DEF_IINCHIP_DBG
printf(“send()\r\n”);
#endif

if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
else ret = len;

// if freebuf is available, start.
do
{
freesize = getSn_TX_FSR(s);
status = IINCHIP_READ(Sn_SR(s));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
{
ret = 0;
break;
}
#ifdef DEF_IINCHIP_DBG
printf(“socket %d freesize(%d) empty or error\r\n”, s, freesize);
#endif
} while (freesize < ret);

  // copy data

send_data_processing(s, (uint8 *)buf, ret);
IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);

/* +20071122[chungs]:wait to process the command… /
while( IINCHIP_READ(Sn_CR(s)) )
;
/
------- */

/* +2008.01 bj /
#ifdef DEF_IINCHIP_INT
while ( (getISR(s) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#else
while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#endif
{
/
m2008.01 [bj] : reduce code /
if ( IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED )
{
#ifdef DEF_IINCHIP_DBG
printf(“SOCK_CLOSED.\r\n”);
#endif
close(s);
return 0;
}
}
/
+2008.01 bj */
#ifdef DEF_IINCHIP_INT
putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
#endif
return ret;
}[/code]
Above is the send() function of W5100 driver.

After copying data to send into TX buffer of W5100,

You can give SEND command to W5100.

And you have to wait for command clear.

/* +20071122[chungs]:wait to process the command... */ while( IINCHIP_READ(Sn_CR(s)) ) ;

And next, you have to check whether SEND_OK happened or not.

#ifdef __DEF_IINCHIP_INT__ while ( (getISR(s) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK ) #else while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK ) #endif { /* m2008.01 [bj] : reduce code */ if ( IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED ) { #ifdef __DEF_IINCHIP_DBG__ printf("SOCK_CLOSED.\r\n"); #endif close(s); return 0; }

Now, I question the possibility of that you missed this process.
[color=#FF0000]Maybe you could have given another command to W5100 before you got SEND_OK.[/color]
Can you check this again in you driver code?

If possible, can you upload your driver’s source code onto here?

I hope to hear your prompt response.

Thank you.

javakys


#11

You’ll find my voids that are same as you sent below:

SOCKET:

uint8 socket( SOCKET s, /**< for socket number */ uint8 protocol, /**< for socket protocol */ uint16 port, /**< the source port for the socket */ uint8 flag /**< the option for the socket */ ) { uint8 ret; #ifdef __DEF_IINCHIP_DBG__ printf("socket()\r\n"); printf("protocol=%d\r\n",protocol); // printf("port=%d\r\n",port); // printf("flag=%d\r\n",flag); #endif if( (protocol == (Sn_MR_TCP)) || (protocol == Sn_MR_UDP) || (protocol == Sn_MR_IPRAW) || (protocol == Sn_MR_MACRAW) || (protocol == Sn_MR_PPPOE) ) { close(s); ret = 1; // printf("Socket kapatıldı. Yeniden yaratılıyor.\r\n"); IINCHIP_WRITE(Sn_MR(s),protocol | flag ); if (port != 0) { IINCHIP_WRITE(Sn_PORT0(s),(uint8)((port & 0xff00) >> 8)); IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(port & 0x00ff)); } else { local_port++; // if don't set the source port, set local_port number. IINCHIP_WRITE(Sn_PORT0(s),(uint8)((local_port & 0xff00) >> 8)); IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(local_port & 0x00ff)); } // printf("Sn_CR_OPEN gönderildi (socket).\r\n"); IINCHIP_WRITE(Sn_CR(s),Sn_CR_OPEN); // run sockinit Sn_CR while(IINCHIP_READ(Sn_CR(s))) // wait for command processing { if (IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED) { #ifdef __DEF_IINCHIP_DBG__ printf("SOCK_CLOSED.(socket)\r\n"); #endif ret = 0; break; } } printf("Socket(%d) created!\r\n",s); } else { ret = 0; } #ifdef __DEF_IINCHIP_DBG__ // printf("Socket_%d_Status_R=0x%.2x\r\n", s,IINCHIP_READ(Sn_SR(s))); #endif return ret; }

CLOSE:

void close(SOCKET s) { #ifdef __DEF_IINCHIP_DBG__ printf("close()\r\n"); #endif IINCHIP_WRITE(Sn_CR(s),Sn_CR_CLOSE); while(IINCHIP_READ(Sn_CR(s))); // wait for command processing }

CONNECT:

[code]uint8 connect(SOCKET s, uint8 * addr, uint16 port)
{
uint8 ret;
#ifdef DEF_IINCHIP_DBG
printf(“connect()\r\n”);
printf(“Socket_%d_Status_R=0x%.2x\r\n”, s,IINCHIP_READ(Sn_SR(s)));
#endif
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
{
ret = 0;
#ifdef DEF_IINCHIP_DBG
printf(“Fail[Invalid IP or Port]\r\n”);
#endif
}
else
{
ret = 1;
//setSn_MSS(s,1024);
printf(“DIPR= %d.%d.%d.%d\r\n”,addr[0],addr[1],addr[2],addr[3]);
printf(“Dport0= %d\r\n”,port);
IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
IINCHIP_WRITE(Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE((Sn_DPORT0(s) + 1),(uint8)(port & 0x00ff));
IINCHIP_WRITE(Sn_CR(s),Sn_CR_CONNECT);
// wait for completion
// while (IINCHIP_READ(Sn_CR(s)));
while (IINCHIP_READ(Sn_CR(s)))
{
/#ifdef DEF_IINCHIP_INT
if( ((getSn_IR(s) & Sn_IR_TIMEOUT)==Sn_IR_TIMEOUT) )
{
printf(“connect timeout\r\n”);ret = 0; break;
}
#endif
/

		if (IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED)
		{

#ifdef DEF_IINCHIP_DBG
printf(“SOCK_CLOSED.(connect1)\r\n”);
#endif
ret = 0; break;
}

	}
	
	
	
	eth_conn_ms_sayac=0;
	while(IINCHIP_READ(Sn_SR(s))==0x01)
	{
		if(eth_conn_ms_sayac==2000*8) 
		{
			printf("0x15 beklerken timeout\r\n");
			ret = 0; //break;
		}
	}
	eth_conn_ms_sayac=0;
	while(IINCHIP_READ(Sn_SR(s))==0x15)
	{
		if(eth_conn_ms_sayac==(10000*8))
		{
			printf("0x17 beklerken timeout\r\n");
			ret = 0; break;
		}
	}
	
}

return ret;

}
[/code]

To solve the problem I have shortened the main() without sending data as below: The main purpose is connecting to PLC( IP: 192.168.0.10 Port:502). You’ll find .pcapng file at http://sdrv.ms/1gt1z3m/shortened_trial.pcapng

[code]main(void)
{

                            if(link.flag_pc)
			{
				switch(IINCHIP_READ(Sn_SR(1)))
				{
					case SOCK_CLOSED:
						printf("CLOSED\r\n");
						if(socket(1,Sn_MR_TCP,set_eth.app_port,0x00))
							if(connect(1, (uint8*) &plc.ip_address[0], plc_port_no))
								printf("Connected\r\n");
					break;

					case SOCK_CLOSE_WAIT:
						printf("CLOSE_WAIT\r\n");
						disconnect(1);
						if(socket(1,Sn_MR_TCP,set_eth.app_port,0x00))
							if(connect(1, (uint8*) &plc.ip_address[0], plc_port_no))
								printf("Connected\r\n");	
					break;

					case SOCK_INIT:
						printf("INIT\r\n");
						if(connect(1, (uint8*) &plc.ip_address[0], plc_port_no))
							printf("Connected\r\n");	
					break;
				}
				if(IINCHIP_READ(Sn_SR(1))==SOCK_ESTABLISHED) 
				{
					printf("SOCK_ESTABLISHED\r\n");
				}
			}

}[/code]

In this case, I can see “SOCK_ESTABLISHED” message for 2-3 seconds and then the other messages are displayed on HERCULES as below:

SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED SOCK_ESTABLISHED CLOSE_WAIT disconnect() socket() protocol=1 close() Socket(1) created! connect() Socket_1_Status_R=0x13 DIPR= 192.168.0.10 Dport0= 502 0x17 beklerken timeout CLOSED socket() protocol=1 close() Socket(1) created! connect() Socket_1_Status_R=0x13 DIPR= 192.168.0.10 Dport0= 502 0x17 beklerken timeout

As you see, PLC(192.168.0.10) doesn’t respond ARP Request so timeout occurs while waiting for SOCK_ESTABLISHED (0x17)


#12

I can’t access to the capture file which you linked to your post.
Can you upload it again? :wink:


#13

You’ll find at http://sdrv.ms/19BOxba


#14

Hi svsbaris,

I saw your code again.

And I’d like to recommend you change the sequence of driver for W5100.

Your code is written like below.

IINCHIP_WRITE(Sn_CR(s),Sn_CR_CONNECT); // wait for completion while (IINCHIP_READ(Sn_CR(s))){ if( ((getSn_IR(s) & Sn_IR_TIMEOUT)==Sn_IR_TIMEOUT) ){ printf("connect timeout\r\n");ret = 0; break; } if (IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED){ printf("SOCK_CLOSED.(connect1)\r\n"); ret = 0; break; } }

But, Our reference code is like this.

IINCHIP_WRITE(Sn_CR(s),Sn_CR_CONNECT); /* m2008.01 [bj] : wait for completion */ while ( IINCHIP_READ(Sn_CR(s)) ); // check the SYN packet sending... while ( IINCHIP_READ(Sn_SR(s)) != SOCK_SYNSENT ){ if(IINCHIP_READ(Sn_SR(s)) == SOCK_ESTABLISHED){ break; } if (getSn_IR(s) & Sn_IR_TIMEOUT) { setSn_IR(s,(Sn_IR_TIMEOUT )); // clear TIMEOUT Interrupt ret = 0; break; } }

Main difference is that ours is waiting until COMMAND register is clear but yours aren’t.
With your code, MCU may enter while loop

while (IINCHIP_READ(Sn_CR(s))){
and get the SOCK_CLOSED status because the corresponding socket is closed and CONNECT command is not executed yet.
Then your code think thant the corresponding socket is closed by TCP timeout mechanism, peer’s refusal and so on.
And another CONNECT command can be issued by your code in main.c file.

You should wait that COMMAND register is clear before you check the status of the corresponding socket.

Thank you.

javakys