A veth virtual network device is connected to a protocol stack on one end and another veth device on the other end instead of a physical network. A packet sent out of a pair of veth devices goes directly to another veth device. Each veth device can be configured with an IP address and participate in the Layer 3 IP network routing process.

The following is an example of a typical veth device pair.

 an example of a typical veth device pair.

We configure the physical NIC eth0 with an IP of 12.124.10.11, and the veth devices that appear in pairs are veth0 and veth1 with IPs of 20.1.0.10 and 20.1.0.11, respectively.

1
2
3
4
5
# ip link add veth0 type veth peer name veth1
# ip addr add 20.1.0.10/24 dev veth0
# ip addr add 20.1.0.11/24 dev veth1
# ip link set veth0 up
# ip link set veth1 up

Then try to ping the other device veth1 from veth0 device:

1
2
3
4
5
6
7
# ping -c 2 20.1.0.11 -I veth0
PING 20.1.0.11 (20.1.0.11) from 20.1.0.11 veth0: 28(42) bytes of data.
64 bytes from 20.1.0.11: icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from 20.1.0.11: icmp_seq=2 ttl=64 time=0.052 ms

--- 20.1.0.11 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1500ms

Note: In some Ubuntu devices, the ping may not work because the default kernel network configuration causes the veth device pair to fail to return ARP packets. The solution is.

1
2
3
4
5
# echo 1 > /proc/sys/net/ipv4/conf/veth1/accept_local
# echo 1 > /proc/sys/net/ipv4/conf/veth0/accept_local
# echo 0 > /proc/sys/net/ipv4/conf/veth0/rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/veth1/rp_filter
# echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

You can try using tcpdump to see the request packets on the veth device pair.

1
2
3
4
5
6
7
# 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 458122 bytes
20:24:12.220002 ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
20:24:12.220198 ARP, Request who-has 20.1.0.11 tell 20.1.0.10, length 28
20:24:12.221372 IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 18174, seq 1, length 64
20:24:13.222089 IP 20.1.0.10 > 20.1.0.11: ICMP echo request, id 18174, seq 2, length 64

You can see that there are only ICMP echo request packets on veth1, but no answer packets. If you think about it, veth1 receives the ICMP echo request packet and forwards it to the protocol stack at the other end, but the protocol stack checks the current device list and finds that there is 20.1.0.10 locally, so it constructs the ICMP echo reply packet and forwards it to the lo device, which receives the packet and hands it directly to the protocol stack and then gives it to the ping process in user space. After receiving the packet, the lo device directly hands it over to the protocol stack and then to the ping process in user space.

We can try to capture the data on the lo device using tcpdump.

1
2
3
4
5
# 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 458122 bytes
20:25:49.486019 IP IP 20.1.0.11 > 20.1.0.10: ICMP echo reply, id 24177, seq 1, length 64
20:25:50.4861228 IP IP 20.1.0.11 > 20.1.0.10: ICMP echo reply, id 24177, seq 2, length 64

It follows that for pairs of veth devices that appear in pairs, packets going out from one device are sent directly to the other device. In practical application scenarios, such as container networks, pairs of veth device pairs are in different network namespaces and packets are forwarded between between network namespaces, which will be explained in detail later when introducing container networks.


Reference https://houmin.cc/posts/680a2369/