Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

communication between two hosts using socktap and UDP #198

Open
razr opened this issue Sep 14, 2023 · 9 comments
Open

communication between two hosts using socktap and UDP #198

razr opened this issue Sep 14, 2023 · 9 comments

Comments

@razr
Copy link

razr commented Sep 14, 2023

I'd like to establish a UDP connection between docker and host both running socktap

This works

# Docker
sudo ./socktap -i eth0 --print-tx-cam

# Host
sudo ./socktap -i docker0 --print-rx-cam

This does not work

# Docker
 ./socktap -l udp -i eth0 --print-tx

# Host
./socktap -l udp -i docker0 --print-rx

However, I see on the receiver side the messages coming from the transmitter:

# Host

sudo tcpdump -nvvvXi docker0 net 239.118.122.97
tcpdump: listening on docker0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:46:01.890966 IP (tos 0x0, ttl 1, id 9917, offset 0, flags [DF], proto UDP (17), length 215)
    172.17.0.2.52764 > 239.118.122.97.8947: [bad udp cksum 0x16c0 -> 0x6c56!] UDP, length 187
        0x0000:  4500 00d7 26bd 4000 0111 3c6e ac11 0002  E...&.@...<n....
        0x0010:  ef76 7a61 ce1c 22f3 00c3 16c0 ffff ffff  .vza..".........
        0x0020:  ffff 0242 ac11 0002 8947 1200 1a01 0210  ...B.....G......
        0x0030:  0000 0235 8409 5436 ff02 0000 0024 8000  ...5..T6.....$..
        0x0040:  0151 2050 0080 002d 0100 8000 0242 ac11  .Q.P...-.....B..
        0x0050:  0002 c5a4 2e22 1d11 3b88 06d0 6527 8000  ....."..;...e'..
        0x0060:  0000 0000 0000 07d1 0000 0202 0000 0001  ................
        0x0070:  2e22 005a 56c4 918e 4346 e4ff ffff fc23  .".ZV...CF.....#
        0x0080:  b774 3e00 0001 2000 003f e1ed 0403 ffe3  .t>......?......
        0x0090:  fff4 0043 0100 0000 0000 0000 0000 0000  ...C............
        0x00a0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00b0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00c0:  0000 0000 0000 0000 0000 0000 0000 0000  ................
        0x00d0:  0000 0000 0000 00                        .......
@riebl
Copy link
Owner

riebl commented Sep 14, 2023

I suppose the low-level Ethernet frames in the former case are not filtered and thus receivable by the host. For the UDP-based link layer, we use IP multicast. Possibly some further configuration is required to forward multicast traffic from/to Docker containers?

@valt2017
Copy link

Maybe binding UDP multicast to the specific IP helps

@razr
Copy link
Author

razr commented Sep 15, 2023

Hi @riebl

I got on the receiver side the multicast packages from 172.17.0.2 to 239.118.122.97.8947 and wondering whether the command I'm using for the UDP communication on the receiver side (./socktap -l udp -i docker0 --print-rx) is correct.
I couldn't find any example apart for the lo interface

./socktap -l udp --mac-address 00:00:00:00:00:01 --print-rx

@riebl
Copy link
Owner

riebl commented Sep 17, 2023

Hi @razr,

socktap has no --print-rx flag but only --print-rx-cam. Apart from that, your invocation of socktap looks sane.
The IP address 239.118.122.97 is the multicast IP address used for the UDP link layer (see

ip::udp::endpoint multicast(ip::address::from_string("239.118.122.97"), 8947);
). According to moby/moby#23659, IP multicast traffics is tricky with Docker containers.

@valt2017
Copy link

I have no experience with multicast and docker, but these modifications in udp_link.cpp should work, when more network interaces are present. IP address of the device specified with -i parameter is stored in std::string ip.
You can give it a try if you want.

tx_socket_.open(multicast_endpoint_.protocol());
if(ip.size() != 0){
//select proper tx interface for udp in case there are more
boost::asio::ip::address_v4 local_interface = boost::asio::ip::address_v4::from_string(ip);
boost::asio::ip::multicast::outbound_interface option(local_interface);
tx_socket_.set_option(option);
}
rx_socket_.open(multicast_endpoint_.protocol());
rx_socket_.set_option(ip::udp::socket::reuse_address(true));
rx_socket_.bind(multicast_endpoint_);
rx_socket_.set_option(ip::multicast::enable_loopback(false));
if(ip.size() != 0){
//select rx interface for udp in case there are more
boost::asio::ip::address_v4 local_interface = boost::asio::ip::address_v4::from_string(ip);
rx_socket_.set_option(ip::multicast::join_group(multicast_endpoint_.address().to_v4(), local_interface));
}else{
	rx_socket_.set_option(ip::multicast::join_group(multicast_endpoint_.address()));
}
do_receive();

@razr
Copy link
Author

razr commented Sep 18, 2023

@riebl it looks like that socktap accepts (allow_guessing) partial command line arguments, e.g.

./socktap --print-t

I'm not sure whether it is an expected behavior, this extra line forces strict options:

diff --git a/tools/socktap/main.cpp b/tools/socktap/main.cpp
index de61b871..40c3a4f6 100644
--- a/tools/socktap/main.cpp
+++ b/tools/socktap/main.cpp
@@ -48,6 +48,7 @@ int main(int argc, const char** argv)
             po::command_line_parser(argc, argv)
                 .options(options)
                 .positional(positional_options)
+                .style(po::command_line_style::default_style & ~po::command_line_style::allow_guessing)
                 .run(),
             vm
         );

@razr
Copy link
Author

razr commented Sep 18, 2023

@valt2017 Thanks much for your reply. It is not docker-related, as you have mentioned it is about multiple network interfaces in the system. I have added a route on the host side:

sudo ip route add 239.118.122.97 dev docker0

After that socktap works properly. However, I still do not understand why I need to pass -i on the receiver side

# Docker
./bin/socktap -l udp --print-tx-cam

# Host
./bin/socktap -l udp -i docker0 --print-rx-cam

It looks like the interface is used for the raw sockets only.

@riebl
Copy link
Owner

riebl commented Sep 18, 2023

@riebl it looks like that socktap accepts (allow_guessing) partial command line arguments, e.g.

Right, obviously a feature I have completely forgotten :-)

@valt2017 binding the multicast sockets to a specific interface sounds reasonable. Can you create a PR for this change please?

@valt2017
Copy link

OK, I can try it during the weekend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants