本篇主要是简单了解CNI的一个第三方插件SRIOV,这里需要说明的是有两个版本,一个是腾讯员工的原版,代码链接在此,另一个是intel fork后修改的版本,代码连接在此。我们会以intel版本为主进行学习,因为intel版本在原版上添加了mellanox网卡以及一些其他参数的支持。

概览

带有SR-IOV功能的网卡引入了PF和VF的概念,PF一般被主机使用,VF可以给容器使用,每个VF都可以看做是一个单独的物理网卡,分配给一个容器,并且配置单独的MAC、VLAN和IP等信息。

使用

我们展示怎么使用,首先要做的就是使能SR-IOV,然后是配置文件的各个配置项。

原版

# vi /etc/modprobe.conf
options ixgbe max_vfs=8,8

配置文件

# cat > /etc/cni/net.d/10-mynet.conf <<EOF
{
    "name": "mynet",
    "type": "sriov",
    "master": "eth1",
    "ipam": {
        "type": "fixipam",
        "subnet": "10.55.206.0/26",
        "routes": [
            { "dst": "0.0.0.0/0" }
        ],
        "gateway": "10.55.206.1"
    }
}
EOF
  • name (string, required): 网络配置名字
  • type (string, required): "sriov"
  • master (string, required): PF的名字
  • ipam (dictionary, required): 使用的IPAM配置
  • pfOnly (bool, optional): 跳过VF,只使用PF
  • vf (int, optional): VF的index
  • vlan (int, optional): VF的VLAN
  • mac (string, optional): VF的MAC

Intel版本

除了支持上述的intel网卡,还支持了Mellanox的网卡。

# mst start
Starting MST (Mellanox Software Tools) driver set
Loading MST PCI module - Success
Loading MST PCI configuration module - Success
Create devices

# mst status
MST modules:
------------
    MST PCI module loaded
    MST PCI configuration module loaded
MST devices:
------------
/dev/mst/mt4115_pciconf0         - PCI configuration cycles access.
...

# mlxconfig -d /dev/mst/mt4115_pciconf0 q set SRIOV_EN=1 NUM_OF_VFS=8
...
Apply new Configuration? ? (y/n) [n] : y
Applying... Done!
-I- Please reboot machine to load new configurations.

# reboot

# ibdev2netdev
mlx5_0 port 1 ==> enp2s0f0 (Up)
mlx5_1 port 1 ==> enp2s0f1 (Up)

# echo 4 > /sys/class/net/enp2s0f0/device/sriov_numvfs
# ibdev2netdev -v
0000:02:00.0 mlx5_0 (MT4115 - MT1523X04353) CX456A - ConnectX-4 QSFP fw 12.23.1020 port 1 (ACTIVE) ==> enp2s0f0 (Up)
0000:02:00.1 mlx5_1 (MT4115 - MT1523X04353) CX456A - ConnectX-4 QSFP fw 12.23.1020 port 1 (ACTIVE) ==> enp2s0f1 (Up)
0000:02:00.5 mlx5_2 (MT4116 - NA)  fw 12.23.1020 port 1 (DOWN  ) ==> enp2s0f2 (Down)
0000:02:00.6 mlx5_3 (MT4116 - NA)  fw 12.23.1020 port 1 (DOWN  ) ==> enp2s0f3 (Down)
0000:02:00.7 mlx5_4 (MT4116 - NA)  fw 12.23.1020 port 1 (DOWN  ) ==> enp2s0f4 (Down)
0000:02:00.2 mlx5_5 (MT4116 - NA)  fw 12.23.1020 port 1 (DOWN  ) ==> enp2s0f5 (Down)

# lspci | grep Mellanox
02:00.0 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4]
02:00.1 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4]
02:00.2 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]
02:00.3 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]
02:00.4 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]
02:00.5 Ethernet controller: Mellanox Technologies MT27700 Family [ConnectX-4 Virtual Function]

# ip link show
...
enp2s0f2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether c6:6d:7d:dd:2a:d5 brd ff:ff:ff:ff:ff:ff
enp2s0f3: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 42:3e:07:68:da:fb brd ff:ff:ff:ff:ff:ff
enp2s0f4: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 42:68:f2:aa:c2:27 brd ff:ff:ff:ff:ff:ff
enp2s0f5: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
...

echo 0 > /sys/class/net/enp2s0f0/device/sriov_numvfs
echo 8 > /sys/class/net/enp2s0f0/device/sriov_numvfs

配置文件

# cat > /etc/cni/net.d/20-mynet-dpdk.conf <<EOF
{
    "cniVersion": "0.3.1",
    "name": "sriov-dpdk",
    "type": "sriov",
    "deviceID": "0000:03:02.0",
    "vlan": 1000,
    "ipam": {
        "type": "host-local",
        "subnet": "10.56.217.0/24",
        "rangeStart": "10.56.217.171",
        "rangeEnd": "10.56.217.181",
        "routes": [
            { "dst": "0.0.0.0/0" }
        ],
        "gateway": "10.56.217.1"
    }
    "min_tx_rate": 100,
    "max_tx_rate": 200,
    "spoofchk": "off",
    "trust": "on"
    "link_state": "enable"
}
EOF
  • name (string, required): 网络配置名字
  • type (string, required): "sriov"
  • deviceID (string, required): 网卡VF的pci地址,比如"0000:03:02.3"。
  • vlan (int, optional): VF的VLAN
  • vlanQoS (int, optional): VF的VLAN QoS(0-7),这个依赖vlan配置,不能为0。
  • mac (string, optional): VF的MAC
  • ipam (dictionary, required): 使用的IPAM配置
  • spoofchk (string, optional): VF的报文欺骗检查开关。
  • trust (string, optional): VF的信任设置开关。
  • link_state (string, optional): VF的连接状态,支持auto, enable, disable。这个取决于网卡驱动的支持程度,比如i40e支持,igb不支持。
  • min_tx_rate (int, optional): 更改VF允许的最小传输带宽(Mbps),将此设置为0将禁用速率限制,min_tx_rate应该小于等于max_tx_rate,是否支持此功能取决于NIC和驱动。
  • max_tx_rate (int, optional): 同上。

代码

原版

cmdAdd操作

  • 调用LoadConf解析配置以及参数
  • 调用ns.GetNS获取当前的namespace
  • 如果是pfOnly不为true的话,调用setupVF寻找一个可用的vf端口

    • 如果vfIdx不是0的话,getVFDeviceName会获取vf对应的端口
    • 如果vfIdx为0的话,allocFreeVF会寻找一个可用的vf端口
    • netlink.LinkByName获取vf端口的句柄
    • netlink.LinkSetUp up端口
    • netlink.LinkSetNsFd将端口配置到namespace中
    • netlink.LinkByName获取pf端口的句柄
    • net.ParseMAC解析配置中的mac地址
    • netlink.LinkSetVfHardwareAddr将mac地址配置给namespace中的vf端口
    • netlink.LinkSetVfVlan给namespace中的vf端口配置vlan
    • 在namespace中调用renameLink将vf端口名称修改为namespace中的端口名称
  • 如果pfOnly是true的话,调用setupPF寻找一个可用的pf端口

    • netlink.LinkByName获取pf端口的句柄
    • netlink.LinkSetUp up端口
    • netlink.LinkSetNsFd将端口配置到namespace中
    • 在namespace中调用renameLink将vf端口名称修改为namespace中的端口名称
  • ipam.ExecAdd获取ip地址
  • 在namespace中调用ipam.ConfigureIface将IP配置给端口

cmdDel操作

  • 调用LoadConf解析配置以及参数
  • 调用ns.GetNS获取当前的namespace
  • 如果是pfOnly不为true的话,调用releaseVF释放vf

    • ns.GetCurrentNS获取当前的namespace
    • 在容器中做以下所有的操作
    • netlink.LinkByName获取容器中的端口句柄
    • netlink.LinkSetDown down掉端口
    • renameLink更改回原来的名字
    • netlink.LinkSetNsFd将端口从namespace中移回宿主机
  • 如果pfOnly是true的话,调用releasePF释放pf

    • ns.GetCurrentNS获取当前的namespace
    • 在容器中做以下所有的操作
    • netlink.LinkByName获取容器中的端口句柄
    • netlink.LinkSetDown down掉端口
    • renameLink更改回原来的名字
    • netlink.LinkSetNsFd将端口从namespace中移回宿主机
  • ipam.ExecDel释放IP

Intel版本

cmdAdd操作

  • 调用config.LoadConf解析配置以及参数

    • 调用json.Unmarshal解析配置
    • 如果配置了DeviceID,则调用getVfInfo获取pf名字以及vfID
    • 调用utils.GetVFLinkNames根据给定的pci地址获取端口名字,如果没有找到则调用utils.HasDpdkDriver查看该端口是否有dpdk驱动
  • getEnvArgs-->types.LoadArgs解析参数
  • 调用ns.GetNS获取当前的namespace
  • sm.ApplyVFConfig存储vf的配置

    • s.nLink.LinkByName获取vf的句柄
    • 如果有vlan的配置项,会继续判断vlanqos的配置,如果有则调用s.nLink.LinkSetVfVlanQos配置,没有则只配置vlan,调用s.nLink.LinkSetVfVlan
    • 如果有mac配置项,则调用net.ParseMAC解析mac地址,然后调用getVfInfo获取之前的mac,并且保存起来,调用s.nLink.LinkSetVfHardwareAddr将配置的mac地址配置到端口
    • 如果配置了速率限制,调用s.nLink.LinkSetVfRate设置速率限制
    • 如果配置了spoofchk,则调用s.nLink.LinkSetVfSpoofchk进行配置
    • 如果配置了trust,则调用s.nLink.LinkSetVfTrust
    • 如果配置了link state,则调用s.nLink.LinkSetVfState
  • 如果是dpdk模式,调用utils.SaveNetConf存储配置信息,为了后续的cmdDel使用,直接返回,不做后续操作
  • sm.SetupVF配置vf,并且转移到namespace中

    • s.nLink.LinkByName获取端口句柄
    • s.nLink.LinkSetDown设置端口为down
    • s.nLink.LinkSetName修改端口名字
    • net.ParseMAC解析mac地址,s.nLink.LinkSetHardwareAddr设置mac
    • s.nLink.LinkSetNsFd将端口转移到namespace
    • 在namespace中调用s.nLink.LinkSetName修改端口名称
    • 在namespace中调用s.nLink.LinkSetUp使端口up
  • 如果配置了IPAM,则调用ipam.ExecAdd申请IP地址,在namespace中执行ipam.ConfigureIface配置IP地址
  • 调用utils.SaveNetConf保存配置,为后续的cmdDel使用。

cmdDel操作

  • 调用config.LoadConfFromCache从之前存储的缓存中获取配置
  • 如果不是dpdk模式,配置了IPAM的话,调用ipam.ExecDel释放之前申请的IP,然后获取配置的namespace,如果不存在直接退出,如果存在则调用sm.ReleaseVF释放vf

    • 以下操作都是namespace中进行
    • s.nLink.LinkByName获取vf的句柄
    • s.nLink.LinkSetDown设置端口为down
    • s.nLink.LinkSetName修改端口名字
    • 如果有mac的配置,则需要调用net.ParseMAC获取之前的有效mac,然后调用s.nLink.LinkSetHardwareAddr设置mac
    • s.nLink.LinkSetNsFd将namespace中的端口移出来
  • sm.ResetVFConfig恢复vf配置

    • s.nLink.LinkByName获取vf的句柄
    • 只配置了vlan的话调用s.nLink.LinkSetVfVlan将vlan配置为0,如果也配置了vlanqos的话,不调用前面,直接调用s.nLink.LinkSetVfVlanQos,将vlan配置为0,qos也配置为0
    • 配置了mac的话,调用net.ParseMAC解析admin mac,然后调用s.nLink.LinkSetVfHardwareAddr将mac恢复
    • s.nLink.LinkSetVfSpoofchk将spoofchk设置为on
    • s.nLink.LinkSetVfTrust将trust配置为off
    • s.nLink.LinkSetVfRate关闭限速
    • 如果配置过linkstate的话,调用s.nLink.LinkSetVfState将连接状态设置为auto

cmdCheck

无代码

最后修改:2021 年 08 月 18 日
如果觉得我的文章对你有用,请随意赞赏