VPP和Linux内核协议栈通信方法(转载)

  原文基础上,对vpp tap命令进行更新调整, 截至目前vpp版本20.01。原文地址https://blog.csdn.net/illina/article/details/81669944

背景介绍

  基于VPP开发一款网络设备,除使用VPP框架实现端口数据报文转发外,还需要对设备进行配置和管理,比较常用的是要实现ssh、web等相关服务,另外,由于VPP并未实现dhcp server的功能,控制面可能还需移植isc-dhcp类似的dhcp server。相关的用户态程序是基于Linux内核的socket来收发包的,因此,需要实现VPP和Linux内核协议栈通信的方法,可以将访问控制面的报文由VPP上送至Linux协议的协议栈。

实现原理

  VPP和Linux内核协议栈通信有两种方法,分别是基于Linux的TAP/TUN和VETH两种机制,对这两种机制不了解的朋友,建议先阅读下如下两个衔接的内容:
TUN/TAP:https://segmentfault.com/a/1190000009249039
VETH:https://segmentfault.com/a/1190000009251098

基于TAP/TUN的方法:

  如上图,PC的地址是192.168.1.2,Linux Kernel的管理接口地址是192.168.1.1,需要PC通过VPP可以ping通Linux内核的192.168.1.1地址。

  技术原理图如上,物理网卡对应VPP中的GE4/0/0,VPP创建tap接口,使用l2 bridge机制将GE4/0/0和tap桥接,进入GE4/0/0的报文通过l2 bridge转发到TAP,VPP的TAP相当于用户态进程,另一端对应的是Linux内核中的TAP接口,报文通过TAP机制重入到Linux内核,实现了VPP到控制面的通信。

  创建虚拟网卡 create tap范式,建议序号从0开始依次编号,以和linux端创建对应网卡保持一致;

vpp# create tap ?
  create tap        create tap {id <if-id>} [hw-addr <mac-address>] [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]

查看tap网卡 

vpp# create tap id 10
tap10
vpp# show tap tap10
  Interface: tap10 (ifindex 1)
  name "ens38"
  host-ns "(nil)"
  fd 18
  tap-fd 19
  gso-enabled 0
  Mac Address: 02:fe:74:1a:a3:32
  Device instance: 0
  flags 0x1
    admin-up (0)
  features 0x110008000
    VIRTIO_NET_F_MRG_RXBUF (15)
    VIRTIO_RING_F_INDIRECT_DESC (28)
    VIRTIO_F_VERSION_1 (32)
  remote-features 0x33d008000
    VIRTIO_NET_F_MRG_RXBUF (15)
    VIRTIO_F_NOTIFY_ON_EMPTY (24)
    VHOST_F_LOG_ALL (26)
    VIRTIO_F_ANY_LAYOUT (27)
    VIRTIO_RING_F_INDIRECT_DESC (28)
    VIRTIO_RING_F_EVENT_IDX (29)
    VIRTIO_F_VERSION_1 (32)
  Number of RX Virtqueue  1
  Number of TX Virtqueue  1
  Virtqueue (RX) 0
    qsz 256, last_used_idx 7, desc_next 0, desc_in_use 249
    avail.flags 0x1 avail.idx 256 used.flags 0x1 used.idx 7
    kickfd 21, callfd 20
  Virtqueue (TX) 1
    qsz 256, last_used_idx 0, desc_next 0, desc_in_use 0
    avail.flags 0x1 avail.idx 0 used.flags 0x0 used.idx 0
    kickfd 23, callfd 22

   实现命令:

#创建tap0网卡
vpp#create tap id 0
#将网络接口tap0和g0绑定到网桥1上,并启动。可以不设ip
vpp#set int l2 bridge G0 1
vpp#set int state G0 up
vpp#set int l2 bridge tap0 1
vpp#set int state tap0 up
#这里不需要添加任何路由信息

  上述操作完成后,在linux后台,ifconfig发现多了一个tap0接口,给tap0接口配置好IP地址,就可以实现PC和设备的通信了。

##部分机型可用ip命令ip addr add 192.168.1.1/24 dev tap0
#ifconfig tap0 192.168.1.1 netmask 255.255.255.0

基于VETH方法:

VETH技术原理如上图,通过在vpp上创建host-interface的方式实现,使用VETH方式的效率更高,实际使用时推荐此种方法。配置步骤如下:

linux后台配置:

~# ip netns add ns0
~# ip link add vpp0 type veth peer name vethns0
~# ip link set vethns0 netns ns0
~# ip netns exec ns0 ip link set lo up
~# ip netns exec ns0 ip link set vethns0 up
~# ip netns exec ns0 ip addr add 192.168.1.1/24 dev vethns0
~# ip netns exec ns0 ethtool -K vethns0 rx off tx off

  VPP配置:

vpp# set int l2 bridge GigabitEthernet4/0/0 1
vpp# set int state GigabitEthernet4/0/0 up
vpp# create host-interface name vpp0
vpp# set interface state host-vpp0 up
vpp# set interface l2 bridge host-vpp0 1

发表评论

邮箱地址不会被公开。 必填项已用*标注