Re: [EVL] Client UDP not receiving data
Hannes Diethelm <[email protected]>
| Newsgroups | dev.linux.lists.xenomai |
|---|---|
| Message-ID | <[email protected]> |
Am 21.05.26 um 11:49 schrieb Philippe Gerum: > Hannes Diethelm <[email protected]> writes: > >> Hello >> >> I have issue porting an application that runs as an UDP client to OOB networking. >> >> The standard client pattern: >> -connect >> -oob_sendmsg >> -oob_recvmsg >> does not work. >> >> In Wireshark, i see the packages going out and returning with the correct ip/port >> but oob_recvmsg() doesn't return. >> >> To debug, I modified the oob-net-udp example, attached. Additionally, I ported it back >> to posix networking where it works as expected. >> >> Send only mode / receive with bind works well. >> >> Config: >> Debian Trixie >> linux-evl v6.12.y-cip-evl-rebase 569beef0 >> libevl r57 877d5ca >> > > I believe oob-net-udp does work as is, but not the way you seem to > expect it, which led your to change the original logic so that two > instances of this program always run head to tail, each one running a > sender+receiver loop. > > The original intent was to implement half-duplex roles instead, starting > each instance either with the -S (send mode) or -R (receive mode, > default) option switch, in order to explicitly select a role. > > This allows for more configurations, like mixing the network stacks to > use for testing. For instance, we are currently able to broadcast > packets to listeners on port #42042 over the wire from a vanilla linux > system (no evl) to an evl-enabled one, using VLAN-based selection of > packets: > > /* > * From the vanilla system, through VLAN device eno2.1 > */ > > $ echo -n "Hello world" | sudo socat - udp-datagram:255.255.255.255:42042,broadcast,so-bindtodevice=eno2.1 > > /* > * From the evl system, listening to all oob interfaces using VLAN-based > * packet selection. > */ > > ~# oob-net-udp -R -a broadcast > == receiver mode (<= broadcast:42042) > == bound to port 42042 > = 11 bytes received: Hello world > > With a different setup, we could connect two evl-enabled systems, like: > > /* > * From the first evl-enabled system, sending through eth1 > * to 10.10.10.11:42042 > */ > > ~# oob-net-udp -S -a 10.10.10.11 > == sender mode (=> 10.10.10.11:42042) > > /* > * From the second evl-enabled system, receiving from eth0, > * bound to 10.10.10.11 on port #42042 > */ > > ~# oob-net-udp -R -a 10.10.10.11 > == receiver mode (<= 10.10.10.11:42042) > == bound to port 42042 > > This said, if you believe that a dual role setup like the one you > suggested would be nice to have to users as well, we could add it to > oob-net-udp alongside the existing half-duplex modes. For instance, > omitting the -R and -S keys on the command line currently defaults to > -R. Instead, we could select the new "dual role" mode. > > PS: please send (diff context, -u or git-diff) formatted patches instead > of entire modified files, so that we can immediately grasp the essence > of the proposed changes. Also, please make sure to separate unrelated > changes sets in distinct patches (e.g. those changing a particular > aspect of the logic from others which may be coding style > fixups). Generally speaking, we follow the linux kernel coding style and > process when it comes to submitting patches [1]. > > [1] https://docs.kernel.org/process/submitting-patches.html > Thanks for the detailed answer. I might have been not precise enough. The -S and the -R mode work as designed. To show the issue with connect() in evl, I changed the -S mode to: connect() while{ oob_sendmsg() oob_recvmsg() } This is the classical UDP client pattern. It works with vanilla linux (net-udp.c) but not with evl (oob-net-udp.c), I do not receive any data. By just sending the modified code, it is easy to explain and hopefully for you to reproduce. This is also why I attached the files instead of sending a patch. Be aware that this is just to demonstrate what is not working, not intended as a patch. I run Xenomai4 in a VM and communicate with the host for debugging but I have also a real PC as the final target where I have the same issues. First start on the host: echo Hello | nc -u -l 5201 Then in the VM: sudo evl net -ei enp7s0 sudo oob-net-udp -d -i enp7s0 -a 192.168.122.1 -p 5201 -S On the host: Mellow sword! In the VM: == bound to enp7s0 == sender mode (=> 192.168.122.1:5201) --------tx-------- IP-Adresse: 192.168.122.1 Port: 5201 Family: 512 --------rx-------- IP-Adresse: 192.168.122.155 Port: 58422 Family: 512 The package is visible in wireshark but oob_recvmsg does not return: No "= 6 bytes received: Hello" and no second transmit. It looks like the auto assigned and bound port from connect() is not forwarded to the oob stage, so no data is received in oob_recvmsg(). In wireshark in the VM, I see the outgoing package 41626->5201 and the incoming 5201->41626 where 41626 is an auto assigned port by connect. With the code ported to vanilla linux: connect() while{ sendmsg() recvmsg() } it works as expected: Host: echo Hello | nc -u -l 5201 VM: sudo evl net -di enp7s0 net-udp -d -i enp7s0 -a 192.168.122.1 -p 5201 -S Host: Mellow sword! Mellow sword! VM: == bound to enp7s0 == client mode (=> 192.168.122.1:5201) --------tx-------- IP-Adresse: 192.168.122.1 Port: 5201 Family: 512 --------rx-------- IP-Adresse: 192.168.122.155 Port: 43042 Family: 512 = 6 bytes received: Hello But might be evl was never intended to work using connect() in classical UDP client style? Meanwhile, I found a workaround. Instead of connect() I just use bind(). The only disadvantage is, that I have to manually assign a port: bind() while{ oob_sendmsg() oob_recvmsg() } Normally, bind() is only used for servers and point-to-point connections but you can (miss-) use it also for clients. A server would be: bind() while{ oob_recvmsg() -> Receives a message from any client oob_sendmsg() -> Sends the answer back to the ip/port from the address from recvmsg } If you think this this example is useful, I can finalize it (for now with the bind() workaround) and also add a server mode. So there would be 4 modes in total. With a server mode, you can run the server on one host, the client on the other and continuously send data forward / backward and measure delays. I would use: -T send (previously it was -S but then I have nothing for server) -R receive -S server: Waits for data and sends a response for each received package. -C client: Sends data and measures how long it takes for the server to response. As an alternative, I could just create a second example oob-net-udp-server-client.c. This would result in a bit of duplicated code but not to much. What do you prefer? I also created oob-net-ping in the same style as oob-net-icmp but this sends out a ping, receives the response and measures the delay, similar as the ping command: ./oob-net-ping -i enp7s0 -a 192.168.122.1 [0] count=98, proto=0x800, ifindex=3, type=0, halen=6, mac=52:54:00:6b:05:f1 rtt=317.1us [1] count=98, proto=0x800, ifindex=3, type=0, halen=6, mac=52:54:00:6b:05:f1 rtt=218.5us [2] count=98, proto=0x800, ifindex=3, type=0, halen=6, mac=52:54:00:6b:05:f1 rtt=252.5us [3] count=98, proto=0x800, ifindex=3, type=0, halen=6, mac=52:54:00:6b:05:f1 rtt=320.1us It has to be cleaned it up a bit and integrated it into the libevl repo but then I will also send a patch. Regards Hannes