veth of Linux Virtual Network Device

With the last article on Introduction of tun/tap After that, you should have a certain understanding of virtual network devices. This article will then introduce another virtual network device veth.

Characteristics of veth equipment

  • Like other network devices, veth connects to the kernel protocol stack at one end.

  • The veth device appears in pairs, and two devices at the other end are connected to each other.

  • When a device receives a request for data from the protocol stack, it sends the data to another device.

The following diagram clearly illustrates the characteristics of veth equipment:

+----------------------------------------------------------------+
|                                                                |
|       +------------------------------------------------+       |
|       |             Newwork Protocol Stack             |       |
|       +------------------------------------------------+       |
|              ↑               ↑               ↑                 |
|..............|...............|...............|.................|
|              ↓               ↓               ↓                 |
|        +----------+    +-----------+   +-----------+           |
|        |   eth0   |    |   veth0   |   |   veth1   |           |
|        +----------+    +-----------+   +-----------+           |
|192.168.1.11  ↑               ↑               ↑                 |
|              |               +---------------+                 |
|              |         192.168.2.11     192.168.2.1            |
+--------------|-------------------------------------------------+
               ↓
         Physical Network

In the figure above, we configure physical network card eth0 with IP 192.168.1.11, while veth0 and Veth 1 have IP 192.168.2.11 and 192.168.2.1, respectively.

Example

We take a step-by-step look at the characteristics of veth devices through examples.

Configure IP for only one veth device

First add veth0 and veth1 through the ip link command, then configure the IP of veth0 and start both devices

dev@debian:~$ sudo ip link add veth0 type veth peer name veth1
dev@debian:~$ sudo ip addr add 192.168.2.11/24 dev veth0
dev@debian:~$ sudo ip link set veth0 up
dev@debian:~$ sudo ip link set veth1 up

The reason why I don't configure IP for veth1 devices is to see if veth0 will forward data from the protocol stack to veth1 when veth1 does not have IP.

ping 192.168.2.1, because veth1 has not yet configured IP, it certainly does not work.

dev@debian:~$ ping -c 4 192.168.2.1
PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
From 192.168.2.11 icmp_seq=1 Destination Host Unreachable
From 192.168.2.11 icmp_seq=2 Destination Host Unreachable
From 192.168.2.11 icmp_seq=3 Destination Host Unreachable
From 192.168.2.11 icmp_seq=4 Destination Host Unreachable

--- 192.168.2.1 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3015ms
pipe 3

But why doesn't ping work? Where did it fail?

Looking at the case of packet grabbing, we can see from the following output that veth0 and veth1 received the same ARP request package, but did not see the ARP response package:

dev@debian:~$ sudo tcpdump -n -i veth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:20:18.285230 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:19.282018 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:20.282038 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:21.300320 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:22.298783 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:23.298923 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28

dev@debian:~$ sudo tcpdump -n -i veth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes
20:20:48.570459 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:49.570012 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:50.570023 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:51.570023 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:52.569988 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28
20:20:53.570833 ARP, Request who-has 192.168.2.1 tell 192.168.2.11, length 28

Why? Knowing what's going on behind ping is clear:

  1. The ping process constructs the ICMP echo request package and sends it to the protocol stack via socket.

  2. According to the destination IP address and the system routing table, the protocol stack knows that the data packet to 192.168.2.1 should be sent by 192.168.2.11 ports.

  3. Since it is the first time to visit 192.168.2.1 and the destination IP and local IP are in the same network segment, the protocol stack will send ARP first and ask the mac address of 192.168.2.1.

  4. The protocol stack handed the ARP package to veth0 and sent it out.

  5. Because the other end of veth0 is connected to veth2, the ARP request packet is forwarded to veth1.

  6. veth1 receives ARP packets and forwards them to the protocol stack at the other end

  7. When the protocol stack looks at its device list, it finds that there is no 192.168.2.1 IP locally, so it discards the ARP request package, which is why only the ARP request package can be seen and the response package can not be seen.

Configure IP for both veth devices

Configure IP to veth1 as well

dev@debian:~$ sudo ip addr add 192.168.2.1/24 dev veth1

Another ping 192.168.2.1 was successful (since 192.168.2.1 is a local IP, so the default will go to the lo device, in order to avoid this situation, using the ping command with the - I parameter, specify the data packet to go to the designated device)

dev@debian:~$ ping -c 4 192.168.2.1 -I veth0
PING 192.168.2.1 (192.168.2.1) from 192.168.2.11 veth0: 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=0.032 ms
64 bytes from 192.168.2.1: icmp_seq=2 ttl=64 time=0.048 ms
64 bytes from 192.168.2.1: icmp_seq=3 ttl=64 time=0.055 ms
64 bytes from 192.168.2.1: icmp_seq=4 ttl=64 time=0.050 ms

--- 192.168.2.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3002ms
rtt min/avg/max/mdev = 0.032/0.046/0.055/0.009 ms

Let's take a look at the case of packet grabbing. We have seen ICMP echo request packages on veth0 and veth1, but why not reply packages? Didn't it show that the ping process has successfully received the reply package?

dev@debian:~$ sudo tcpdump -n -i veth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth0, link-type EN10MB (Ethernet), capture size 262144 bytes
20:23:43.113062 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 1, length 64
20:23:44.112078 IP 192.168.2.11 
> 192.168.2.1: ICMP echo request, id 24169, seq 2, length 64
20:23:45.111091 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 3, length 64
20:23:46.110082 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24169, seq 4, length 64


dev@debian:~$ sudo tcpdump -n -i veth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes
20:24:12.221372 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 1, length 64
20:24:13.222089 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 2, length 64
20:24:14.224836 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 3, length 64
20:24:15.223826 IP 192.168.2.11 > 192.168.2.1: ICMP echo request, id 24174, seq 4, length 64

Look at the flow of the data package and see:

  1. The ping process constructs the ICMP echo request package and sends it to the protocol stack via socket.

  2. Because the ping program specifies to go veth0 and the local ARP cache contains records of all local devices, the protocol stack handed the data packet to veth0 directly without sending ARP out.

  3. Because the other end of veth0 is connected to veth2, the ICMP echo request packet is forwarded to veth1.

  4. veth1 receives the ICMP echo request packet and forwards it to the protocol stack at the other end

  5. The protocol stack looks at its own device list and finds 192.168.2.1 IP locally, so it constructs the ICMP echo reply package and is ready to return.

  6. The protocol stack checks its routing table and finds that the packet returned to 192.168.2.11 should go to the lo port, so it gives the reply package to the lo device.

  7. When Lo receives the reply package from the protocol stack, he does nothing, and then returns the data package to the protocol stack (equivalent to the protocol stack sending the data package to lo through the sending process, and then Lo delivers the data package to the receiving process of the protocol stack)

  8. When the protocol stack receives the reply package, it finds that a socket needs the package, and gives it to the corresponding socket.

  9. This socket happens to be the socket created by the Ping process, so the ping process receives the reply package.

Grabbing the data on the lo device, we found that the reply package did come back from the lo port.

dev@debian:~$ sudo tcpdump -n -i lo
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
20:25:49.590273 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 1, length 64
20:25:50.590018 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 2, length 64
20:25:51.590027 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 3, length 64
20:25:52.590030 IP 192.168.2.1 > 192.168.2.11: ICMP echo reply, id 24177, seq 4, length 64

Try other IP under ping

Other IP failures in ping 192.168.2.0/24 segment and IP failures in ping a public network:

dev@debian:~$ ping -c 1 -I veth0 192.168.2.2
PING 192.168.2.2 (192.168.2.2) from 192.168.2.11 veth0: 56(84) bytes of data.
From 192.168.2.11 icmp_seq=1 Destination Host Unreachable

--- 192.168.2.2 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

dev@debian:~$ ping -c 1 -I veth0 baidu.com
PING baidu.com (111.13.101.208) from 192.168.2.11 veth0: 56(84) bytes of data.
From 192.168.2.11 icmp_seq=1 Destination Host Unreachable

--- baidu.com ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms

From the point of view of packet grabbing, as in the case of the first veth1 without IP configuration above, ARP requests are not processed.

dev@debian:~$ sudo tcpdump -i veth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on veth1, link-type EN10MB (Ethernet), capture size 262144 bytes
02:25:23.223947 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28
02:25:24.224352 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28
02:25:25.223471 ARP, Request who-has 192.168.2.2 tell 192.168.2.11, length 28
02:25:27.946539 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28
02:25:28.946633 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28
02:25:29.948055 ARP, Request who-has 123.125.114.144 tell 192.168.2.11, length 28

Concluding remarks

From the introduction above, we can see that the packets from the veth0 device will be forwarded to veth1. If the destination address is the IP of veth1, they can be processed by the protocol stack. Otherwise, even the ARP can't pass, IP forward can't be used, so without the help of other virtual devices, such packets can only be in this way. In the protocol stack, it can't go to eth0, that is, it can't be sent to the outside network.

The next article will introduce the bridge under Linux, when veth devices will be useful.

Reference resources

Keywords: Linux sudo network socket

Added by Steve Mellor on Thu, 04 Jul 2019 21:10:27 +0300