FreeRTOS+TCP: problem with UDP communication

xterra wrote on Thursday, April 26, 2018:

Hi,

i´m trying to set up communication per udp between a pc and an embedded control board based on a renesas rx65n.

on the embedded control board (10.222.187.10) i open an udp socket on port 1230.
on pc (10.222.5.123) i also open an udp socket on port 1230.

if i send udp telegrams from pc to control board, i receive telegrams on control board (see receive_udp_filtered.pcapng).

my problem:
if i send upd telegrams from control board to pc, i don´t receive telegrams on pc, but telegrams are on wire (see send_udp_filtered.pcapng).

on wireshark files i can see one difference between the protocols:

  • telegrams from control board don´t set the identification field in internet protocol (see ip.png)
  • telegrams from pc set the identification field, each further telegram increments identification field

i don´t know if identification field is the problem, but is there a way to activate this counter?

if i use two pc programs i can send and receive telegrams and i can see in wireshark files that identification field is incremented each in both directions.

thanks!

Best regards

xterra wrote on Thursday, April 26, 2018:

attachment

heinbali01 wrote on Thursday, April 26, 2018:

Hi Wolfgang,

Are you sure that port 1230 is an available port on your host? Could you try the same with e.g. port 50123 ?

Normally, you would use a well-known port number on server-side, and an anonymous port number on the other side, i.e. bind to port 0, which results in a random port number.

i don´t know if identification field is the problem,
but is there a way to activate this counter?

This field is kept zero for UDP packets.

But if you want to test it, apply the following patch to FreeRTOS_UDP_IP.c,
around line 140 :

             /* Save options now, as they will be overwritten by memcpy */
             #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM == 0 )
             {
                 ucSocketOptions = pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ];
             }
             #endif
 
             memcpy( ( void *) &( pxUDPPacket->xEthernetHeader.xSourceAddress ), ( void * ) xDefaultPartUDPPacketHeader.ucBytes, sizeof( xDefaultPartUDPPacketHeader ) );
+
+            pxIPHeader->usIdentification = FreeRTOS_htons( usPacketIdentifier );
+            usPacketIdentifier++;
 
         #if ipconfigSUPPORT_OUTGOING_PINGS == 1
             if( pxNetworkBuffer->usPort == ipPACKET_CONTAINS_ICMP_DATA )

Do you use a standard application to receive UDP messages?

PS. Where did you get the FreeRTOS+TCP driver for rx65n? Did you write it your self?

xterra wrote on Friday, April 27, 2018:

Hi Hein,

I tried to use different ports and inserted your code for identification-field increment.

But the effect is the same, i only can receive in one direction.

Attached a wireshark file (send_receive_udp_filtered):
pc (10.222.5.123 / 50123) sends udp telegrams to embedded control board (10.222.187.10 / 50124), everything okay, i can receive telegrams on embedded board.

embedded board (10.222.187.10 / 50124) sends udp telegrams to pc (10.222.5.123 / 50123), telegrams are on wire (identification field is incrementing now), but on pc receive is not working (timeout, no data is received)?!?

I use a labview program on pc to send / receive udp telegrams, in labview i have functions for connect (with bind) / send / receive (with timeout/bytes to read).
if i use this labview program on two pcs i can connect/ send / receive in both directions…
laptop: 10.222.6.7 / 50124
pc: 10.222.5.123 / 50123
see wireshark file

I programed FreeRTOS+TCP drive for rx65n by myself on base of ethernet-driver (rx-ether from renesas fit-modules).

if i ping my embedded board if get answers.

conlusion:

  • identification field doesn´t matter
  • port number doesn´t matter

do you have any other ideas?

i just have another idea while writing these lines, perhaps i have a problem with virus scanner or firewall? perhaps i have to give access to this port number on my pc to get the udp telegrams?
i have to check…

thanks for your help
Wolfgang Schur

heinbali01 wrote on Monday, April 30, 2018:

perhaps i have a problem with virus scanner or firewall?

Sounds worth checking that out

Do you solve the problem by now?

xterra wrote on Wednesday, May 02, 2018:

Hello Hein,

unfortunately it´s still not working!

Firewall or virus scanner is not the problem.

In wireshark file I can see udp telegram is on wire.
In case of send_receive_labview_filtered.pcapng labview program receives data.
In case of send_receive_upd_filtered.pcapng labview program receives nothing.

I checked ARP table in embedded board, there is an entry for 10.222.5.123
embedded board is sending out gratuitous arp for himself (10.222.187.10) every 40s.
embedded board is answering on ping requests.
on pc arp table is also set for 10.222.187.10

What I am wondering:
Do you know if wireshark would show an error if UDP-CRC-calculation is false?
ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM is set to (1), but this is only for receiving, not for sending, isn´t it?

I disabled the following options:
ipconfigUSE_LLMNR / ipconfigUSE_NBNS / ipconfigUSE_DNS / ipconfigUSE_DHCP
could this be a problem?

Could there be a problem in my rx65-driver? But ping request / ARPs are received on pc?

I tried another application on pc: https://packetsender.com/
It´s the same, i can send telegrams to my embedded board, but i don´t receive telegrams from my board!
If I try this application on an laptop i can send and receive from laptop to pc!

thanks for your help
best regards
Wolfgang

heinbali01 wrote on Thursday, May 03, 2018:

Hi Wolfgang,

What I am wondering:
Do you know if wireshark would show an error if UDP-CRC-calculation
is false?

PC’s often have a network card that calculates all checksums, while the applications and Wireshark don’t get to see the actual CRC received. This feature is called “checksum offloading”.

You can have Wireshark check the checksums:

Edit -> Preferences -> Protocols ->

IPv4 : set Validate the IPv4 checksum if possible
UDP : set Validate the UDP checksum if possible
TCP : set Validate the TCP checksum if possible

Then go to the settings of your network card and look for the hardware configuration ( not the protocols ).
Under Advanced, you can probably disable checksum offloading:

IPv4 Checksum Offload
UDP Checksum Offload (IPv4)
TCP Checksum Offload (IPv4)

or at least do not enable it for the RX path.

Once checksum offloading is disabled, you can see the original CRC’s as sent by the embedded device.
Now I would be curious to see if the IP and UDP checksumsfrom the device are correct.

ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM is set to (1),
but this is only for receiving, not for sending, isn´t it?

Yes, the RX stands for reception of packets.

If you have ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM (TX) defined as 1, your driver or he MAC peripheral must set all IPv4, UDP, and TCP checksums.
If it is defined as 0, the library will set them.

I disabled the following options:
ipconfigUSE_LLMNR / ipconfigUSE_NBNS / ipconfigUSE_DNS / ipconfigUSE_DHCP
could this be a problem?

That should not be a problem

Could there be a problem in my rx65-driver? But ping
request / ARPs are received on pc?

ARP only has checksums at the hardware layer that we don’t see.
The checksum for ping is being set in-line.

kenchang1 wrote on Thursday, May 03, 2018:

When you checked the ARP tables at both sides, did you also compare the MAC addresses with the wireshark captures? Do they match?

kenchang1 wrote on Thursday, May 03, 2018:

You said that the embedded board is answering ping requests from the PC. I think in this case the other way is important. Does the PC answer ping requests from the Renesas?

xterra wrote on Thursday, May 17, 2018:

Hi all,

sorry, that i didn´t answer so long, I was claimed with other things…

@Ken:
MAC addresses matches in arp tables

@Hein:
I did configure network adapter and wireshark to show ‘real’ checksum.
And now I see that checksum is not correct!

For test I disabled checksum calculation in tcp stack by setting ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM to 0 (see file included_tx_checksum_0.PNG).
Result is that no checksum at all is calculated, that makes sense, okay!

If checksum calculation in tcp stack is enabled (as it was before), then I see, that checksum is not correct (see file included_tx_checksum_1.PNG).
That could be the reason I don´t receive telegrams on pc, okay, perfect!

What could be the problem that chechsum is not correct?

By setting ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM to 1, TCP stack is calculating checksum for IP / UDP.
xNetworkInterfaceOutput() function gets the network buffer with including checksum and sends it out, isn´t it?

I really would appreciate your help!

Thanks
Wolfgang

xterra wrote on Thursday, May 17, 2018:

one more thing:

It looks like IP checksum is correct, only UDP checksum is not correct? see file included_tx_checksum_1.png

Is it so that IP checksum is calculated including all data (that means including the udp datagram)?

Why would the outer checksum (IP) be correct, but the inner checksum (UDP) is not correct?

heinbali01 wrote on Thursday, May 17, 2018:

Hi Wolfgang, often checksums appear to be incorrect, but WireShark will warn you that the IP or protocol checksum may be have been “offloaded”.
This means that your adapter has already checked the checksum. For some reason, the checksum field gets cluttered and Wireshark will show an error.
Could you try the following:
Go to the adapter’s settings, go to “Advanced”, and look for “UDP Checksum Offload (IPv4)”
Likewise, there is also a setting for “TCP Checksum Offload (IPv4)”

heinbali01 wrote on Friday, May 18, 2018:

Reading back the above post, I notice that I am repeating my self. Still I’d like to know whether CRC offloading explains the checksum errors that you’re seeing. Can you check that?

We’re not aware of any problem with these the checksum routines:

uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, BaseType_t xOutgoingPacket );
uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes );

The only thing I could think of is that your compiler has a different interpretation of the code. That can be investigated with a few tests. Regards,

xterra wrote on Friday, May 18, 2018:

Hi Hein,

I disabled “checksum offload (IPv4)” and “UDP checksum offload (IPv4)” in network adapter.

For test I also configured socket option FREERTOS_SO_UDPCKSUM_OUT for no checksum in UDP telegram.
Then I receive UDP telegram on pc!

So I think, here we are on the right way! Something is wrong in checksum calculation.

Wireshark shows:
First telegram
calculated checksum: 0x3874
should be (wireshark): 0x6547
Second telegram (one data byte changed)
calculated checksum: 0x3873
should be (wireshark): 0x6546

Best regards
Wolfgang

xterra wrote on Friday, May 18, 2018:

Hi Hein and all,

thanks a lot for your help, the problem is solved:

It was alignement of network buffer.

In “NetworkInterface.c” I declare a buffer ucNetworkPackets which was not aligned!
Function vNetworkInterfaceAllocateRAMToBuffers delievers this unaligned buffer to the tcp stack and checksum calculation on this memory fails!

After aligning buffer ucNetworkPackets in “NetworkInterface.c” communication works (wireshark says no error) and I can receive udp telegrams on pc!!!

Best regards
Wolfgang

heinbali01 wrote on Friday, May 18, 2018:

Hi Wolfgang, we worked through this by email. I sent you a testing module to test the 2 checksum routines on several Ethernet packets ( see attachment ‘tcp_udp_packets.c’ ). When running this test, you realised that Ethernet buffers in FreeRTOS+TCP must be aligned in a special way.

In the example code, the checksum routines work on this buffer in RAM:

    uint8_t ucRAMBuffer[2 + 1500] __attribute__ ((aligned (4)));
    uint8_t *ucContents = ucRAMBuffer + 2;

The +2 bytes are defined in the library as:

#define ipconfigPACKET_FILLER_SIZE    2

They are necessary because an Ethernet header is 14 bytes long.
The IP-header starts at ‘ucRAMBuffer + 2 + 14’ = ‘ucRAMBuffer + 16’, which is well-aligned. The IP-header is always a multiple of 4 bytes, so the protocol header is also 4-byte aligned.

Thanks for your investigations. Hein

xterra wrote on Thursday, May 24, 2018:

Hi all,

attached is my network interface for renesas RX65N and renesas rx-compiler.
It´s based on renesas example code and not zero-copying.

Memory alignment is done by linker settings, see picture.

heinbali01 wrote on Thursday, May 24, 2018:

Hi Wolfgang, thanks a lot for sharing your RX65N driver for FreeRTOS+TCP!
I had a quick look at NetworkInterface.c : it looks good!