本文参考博客(https://blog.csdn.net/illina/article/details/81669944)来学习一下利用vpp实现虚拟机上网功能。主要是为了学习虚拟网卡功能在vpn场景中应用比较广泛。
vpp提供了创建tap口的命令行如下(参数比较多没有详细研究):
create tap {id <if-id>} [hw-addr <mac-address>] [num-rx-queues <n>] [rx-ring-size <size>] [tx-ring-size <size>] [host-ns <netns>] [host-bridge <bridge-name>] [host-ip4-addr <ip4addr/mask>] [host-ip6-addr <ip6-addr>] [host-ip4-gw <ip4-addr>] [host-ip6-gw <ip6-addr>] [host-mac-addr <host-mac-address>] [host-if-name <name>] [host-mtu-size <size>] [no-gso|gso [gro-coalesce]|csum-offload] [persist] [attach] [tun] [packed] [in-order]
说明:Id:是vpp内部管理的ID,一般情况创建以0开头,这样linux系统也创景一个类似名字的tap0口。 host-if-name:这个意思应该是Linux已经存在一个tap口,vpp创建的tap接口和linux host-if-name口进行绑定,可以实现1对1通信。
下图是在本地环境使用Vmware虚拟机使用vpp实现上网的功能:
配置命令如下:
#1、创建tap0网卡,创建完后对应在linux系统下也生成一个tap0接口
vppctl create tap id 0
vppctl set int l2 bridge GigabitEthernet2/3/0 1
vppctl set int state GigabitEthernet2/3/0 up
vppctl set int l2 bridge tap0 1
vppctl set int state tap0 up
#2、配置linux tap0接口ip 地址(这里本地环境网关是192.168.124.1)
ifconfig tap0 192.168.124.18/24
在虚拟机上ping www.baidu.com 然后在vpp上进行trace抓包查询转发流程处理。
#1、在虚拟机上来ping 百度,能ping通
[root@localhost ~]# ping www.baidu.com
PING www.baidu.com (182.61.200.6) 56(84) bytes of data.
64 bytes from 182.61.200.6 (182.61.200.6): icmp_seq=1 ttl=52 time=6.43 ms
# 2、设置trace 抓包:
vpp#clear trace
vpp#travppce add virtio-input 100
vpp#show trace
#3、抓取访问百度的报文
Packet 5
04:18:45:691575: virtio-input
virtio: hw_if_index 3 next-index 4 vring 0 len 98
hdr: flags 0x00 gso_type 0x00 hdr_len 0 gso_size 0 csum_start 0 csum_offset 0 num_buffers 1
04:18:45:691582: ethernet-input
IP4: 02:fe:0e:90:87:26 -> 04:d7:a5:5e:fc:f9
04:18:45:691587: l2-input
l2-input: sw_if_index 3 dst 04:d7:a5:5e:fc:f9 src 02:fe:0e:90:87:26
04:18:45:691589: l2-learn
l2-learn: sw_if_index 3 dst 04:d7:a5:5e:fc:f9 src 02:fe:0e:90:87:26 bd_index 1
04:18:45:691592: l2-fwd
l2-fwd: sw_if_index 3 dst 04:d7:a5:5e:fc:f9 src 02:fe:0e:90:87:26 bd_index 1 result [0x1910000000001, 1] none
04:18:45:691594: l2-output
l2-output: sw_if_index 1 dst 04:d7:a5:5e:fc:f9 src 02:fe:0e:90:87:26 data 08 00 45 00 00 54 ba 7c 40 00 40 01
04:18:45:691596: GigabitEthernet2/3/0-output
GigabitEthernet2/3/0
IP4: 02:fe:0e:90:87:26 -> 04:d7:a5:5e:fc:f9
ICMP: 192.168.124.18 -> 182.61.200.6
tos 0x00, ttl 64, length 84, checksum 0xc52d dscp CS0 ecn NON_ECN
fragment id 0xba7c, flags DONT_FRAGMENT
ICMP echo_request checksum 0xcaf8
04:18:45:691598: GigabitEthernet2/3/0-tx
GigabitEthernet2/3/0 tx queue 0
buffer 0x9e135: current data 0, length 98, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x4
l2-hdr-offset 0 l3-hdr-offset 14
PKT MBUF: port 65535, nb_segs 1, pkt_len 98
buf_len 2176, data_len 98, ol_flags 0x0, data_off 128, phys_addr 0xad84dc0
packet_type 0x0 l2_len 0 l3_len 0 outer_l2_len 0 outer_l3_len 0
rss 0x0 fdir.hi 0x0 fdir.lo 0x0
IP4: 02:fe:0e:90:87:26 -> 04:d7:a5:5e:fc:f9
ICMP: 192.168.124.18 -> 182.61.200.6
tos 0x00, ttl 64, length 84, checksum 0xc52d dscp CS0 ecn NON_ECN
fragment id 0xba7c, flags DONT_FRAGMENT
ICMP echo_request checksum 0xcaf8
在vpn业务上应用比较广泛,可以利用vpp来创建gre、ipsec隧道。来看下图的流程:
假设192.168.0.5发出了一个对192.168.0.3的ARP请求,该ARP请求在网络中经过的路径如下: 1、192.168.0.5发出ARP请求,询问192.168.0.3的MAC地址。 2、该ARP请求将被发送到以太网交换机上。 3、以太网交换机对该请求进行泛洪,发送到其包括Eth1在内的所有端口上。 4、由于Eth1被加入了VPN主机上的Linux Bridge,因此Linux Bridge收到该ARP请求。 5、Linux Bridge对该ARP请求进行泛洪,发送到连到其上面的Tap虚拟网卡上。 6、VPN程序通过/dev/net/tun字符设备读取到该ARP请求,然后封装到TCP/UDP包中,发送到对端站点的VPN主机。 7、对端站点的VPN程序通过监听TCP/UDP端口接收到封装的ARP请求,将ARP请求通过/dev/net/tun字符设备写入到Tap设备中。 8、Linux Bridge泛洪,将ARP请求发送往Eth1,由于Eth1连接到了以太网交换机上,以太网交换机接收到了该ARP请求。 9、以太网交换机进行泛洪,将ARP请求发送给了包括192.168.0.3的所有主机。 10、192.168.0.3收到了APR请求,判断iP地址和自己相同,对此请求进行响应。 11、同理,ARP响应包也可以按照该路径返回到图左边包括192.168.0.5在内的站点中。
veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。配置组网如下:
#虚拟机配置如下:
ip link add veth0 type veth peer name veth1
ifconfig veth0 192.168.124.18
#需要添加缺省网关,否则路由可能不通,导致无法上网。
route add default gw 192.168.124.1
#Vpp 配置如下:
vppctl set int l2 bridge GigabitEthernet2/3/0 1
vppctl set int state GigabitEthernet2/3/0 up
vppctl create host-interface name veth1
vppctl set int l2 bridge host-veth1 1
vppctl set int state host-veth1 up
veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连着。
#设置trace抓包,注意这里需要设置af-packet-input类型。
vpp# clear trace
vpp# trace add af-packet-input 100
vpp# show trace
------------------- Start of thread 0 vpp_main -------------------
05:33:26:350890: af-packet-input
af_packet: hw_if_index 3 next-index 4
tpacket2_hdr:
status 0x20000009 len 118 snaplen 118 mac 66 net 80
sec 0x5fe67880 nsec 0xcf238a0 vlan 0 vlan_tpid 0
05:33:26:350898: ethernet-input
IP4: 2a:28:c7:53:7d:37 -> c8:b2:9b:90:ee:08
05:33:26:350901: l2-input
l2-input: sw_if_index 3 dst c8:b2:9b:90:ee:08 src 2a:28:c7:53:7d:37
05:33:26:350903: l2-learn
l2-learn: sw_if_index 3 dst c8:b2:9b:90:ee:08 src 2a:28:c7:53:7d:37 bd_index 1
05:33:26:350904: l2-fwd
l2-fwd: sw_if_index 3 dst c8:b2:9b:90:ee:08 src 2a:28:c7:53:7d:37 bd_index 1 result [0x1910000000001, 1] none
05:33:26:350906: l2-output
l2-output: sw_if_index 1 dst c8:b2:9b:90:ee:08 src 2a:28:c7:53:7d:37 data 08 00 45 10 00 68 4e b7 40 00 40 06
05:33:26:350907: GigabitEthernet2/3/0-output
GigabitEthernet2/3/0
IP4: 2a:28:c7:53:7d:37 -> c8:b2:9b:90:ee:08
TCP: 192.168.124.18 -> 192.168.124.13
tos 0x10, ttl 64, length 104, checksum 0x7258 dscp unknown ecn NON_ECN
fragment id 0x4eb7, flags DONT_FRAGMENT
TCP: 22 -> 53774
seq. 0x7f5bdb61 ack 0x3ad89b33
flags 0x18 PSH ACK, tcp header: 20 bytes
window 324, checksum 0x0000
05:33:26:350909: GigabitEthernet2/3/0-tx
GigabitEthernet2/3/0 tx queue 0
buffer 0x9c1d3: current data 0, length 118, buffer-pool 0, ref-count 1, totlen-nifb 0, trace handle 0x2
ip4 offload-tcp-cksum l2-hdr-offset 0 l3-hdr-offset 14
PKT MBUF: port 65535, nb_segs 1, pkt_len 118
buf_len 2176, data_len 118, ol_flags 0x90000000000000, data_off 128, phys_addr 0xad07540
packet_type 0x0 l2_len 14 l3_len 20 outer_l2_len 0 outer_l3_len 0
rss 0x0 fdir.hi 0x0 fdir.lo 0x0
Packet Offload Flags
PKT_TX_TCP_CKSUM (0x0000) TCP cksum of TX pkt. computed by NIC
IP4: 2a:28:c7:53:7d:37 -> c8:b2:9b:90:ee:08
TCP: 192.168.124.18 -> 192.168.124.13
tos 0x10, ttl 64, length 104, checksum 0x7258 dscp unknown ecn NON_ECN
fragment id 0x4eb7, flags DONT_FRAGMENT
TCP: 22 -> 53774
seq. 0x7f5bdb61 ack 0x3ad89b33
flags 0x18 PSH ACK, tcp header: 20 bytes
window 324, checksum 0x79cb
1、VPP和Linux内核协议栈通信的方法 https://blog.csdn.net/illina/article/details/81669944 2、Linux Tun/Tap 介绍 https://zhaohuabing.com/post/2020-02-24-linux-taptun/ 3、Linux Veth设备简介 https://www.cnblogs.com/bakari/p/10613710.html
本文分享自 DPDK VPP源码分析 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!