vpp_device: bind to vfio-pci before running tests
[csit.git] / resources / libraries / bash / function / device.sh
index 228a73b..1ad113d 100644 (file)
@@ -30,6 +30,7 @@ function activate_wrapper () {
 
     enter_mutex || die
     get_available_interfaces "${1}" "${2}" || die
+    bind_dut_interfaces_to_vpp_driver || die
     start_topology_containers "${3}" || die
     bind_interfaces_to_containers || die
     set_env_variables || die
@@ -38,6 +39,29 @@ function activate_wrapper () {
 }
 
 
+function bind_dut_interfaces_to_vpp_driver () {
+
+    # Bind DUT network interfaces to the driver that vpp will use
+    #
+    # Variables read:
+    # - DUT1_NETDEVS - List of network devices allocated to DUT1 container.
+    # Variables set:
+    # - NETDEV - Linux network interface.
+    # - DRIVER - Kernel driver to bind the interface to.
+    # - KRN_DRIVER - The original kernel driver of the network interface.
+
+    for NETDEV in "${DUT1_NETDEVS[@]}"; do
+        get_pci_addr || die
+        get_krn_driver || die
+        if [[ ${KRN_DRIVER} == "iavf" ]]; then
+            DRIVER="vfio-pci"
+            ADDR=${PCI_ADDR}
+            bind_interfaces_to_driver || die
+        fi
+    done
+}
+
+
 function bind_interfaces_to_containers () {
 
     # Bind linux network interface to container and create symlink for PCI
@@ -51,36 +75,42 @@ function bind_interfaces_to_containers () {
     # - TG_NETDEVS - List of network devices allocated to TG container.
     # Variables set:
     # - NETDEV - Linux network interface.
+    # - KRN_DRIVER - Kernel driver of network device.
 
     set -exuo pipefail
 
-    for NETDEV in "${TG_NETDEVS[@]}"; do
-        get_pci_addr || die
+    for PCI_ADDR in "${TG_PCIDEVS[@]}"; do
+        get_netdev_name || die
         link_target=$(readlink -f /sys/bus/pci/devices/"${PCI_ADDR}") || {
             die "Reading symlink for PCI address failed!"
         }
         cmd="ln -s ${link_target} /sys/bus/pci/devices/${PCI_ADDR}"
 
-        sudo ip link set ${NETDEV} netns ${DCR_CPIDS[tg]} || {
-            die "Moving interface to ${DCR_CPIDS[tg]} namespace failed!"
-        }
         docker exec "${DCR_UUIDS[tg]}" ${cmd} || {
             die "Linking PCI address in container failed!"
         }
+
+        sudo ip link set ${NETDEV} netns ${DCR_CPIDS[tg]} || {
+            die "Moving interface to ${DCR_CPIDS[tg]} namespace failed!"
+        }
     done
-    for NETDEV in "${DUT1_NETDEVS[@]}"; do
-        get_pci_addr || die
+    for PCI_ADDR in "${DUT1_PCIDEVS[@]}"; do
         link_target=$(readlink -f /sys/bus/pci/devices/"${PCI_ADDR}") || {
             die "Reading symlink for PCI address failed!"
         }
         cmd="ln -s ${link_target} /sys/bus/pci/devices/${PCI_ADDR}"
 
-        sudo ip link set ${NETDEV} netns ${DCR_CPIDS[dut1]} || {
-            die "Moving interface to ${DCR_CPIDS[dut1]} namespace failed!"
-        }
         docker exec "${DCR_UUIDS[dut1]}" ${cmd} || {
             die "Linking PCI address in container failed!"
         }
+
+        get_krn_driver
+        if [[ ${KRN_DRIVER} != "vfio-pci" ]]; then
+            get_netdev_name || die
+            sudo ip link set ${NETDEV} netns ${DCR_CPIDS[dut1]} || {
+                die "Moving interface to ${DCR_CPIDS[dut1]} namespace failed!"
+            }
+        fi
     done
 }
 
@@ -99,13 +129,22 @@ function bind_interfaces_to_driver () {
     pci_path="/sys/bus/pci/devices/${ADDR}"
     drv_path="/sys/bus/pci/drivers/${DRIVER}"
     if [ -d "${pci_path}/driver" ]; then
-        echo ${ADDR} | sudo tee ${pci_path}/driver/unbind || {
+        echo ${ADDR} | sudo tee ${pci_path}/driver/unbind > /dev/null || {
             die "Failed to unbind interface ${ADDR}!"
         }
     fi
-    echo ${ADDR} | sudo tee ${drv_path}/bind || {
+
+    echo ${DRIVER} | sudo tee /sys/bus/pci/devices/${ADDR}/driver_override \
+        > /dev/null || {
+        die "Failed to override driver to ${DRIVER} for ${ADDR}!"
+    }
+
+    echo ${ADDR} | sudo tee ${drv_path}/bind > /dev/null || {
         die "Failed to bind interface ${ADDR}!"
     }
+
+    echo | sudo tee /sys/bus/pci/devices/${ADDR}/driver_override > /dev/null \
+        || die "Failed to reset driver override for ${ADDR}!"
 }
 
 
@@ -415,6 +454,25 @@ function get_mac_addr () {
 }
 
 
+function get_netdev_name () {
+
+    # Get Linux network device name.
+    #
+    # Variables read:
+    # - PCI_ADDR - PCI address of the device.
+    # Variables set:
+    # - NETDEV - Linux network device name.
+
+    set -exuo pipefail
+
+    if [ -d /sys/bus/pci/devices/${PCI_ADDR}/net ]; then
+        NETDEV="$(basename /sys/bus/pci/devices/${PCI_ADDR}/net/*)" || {
+            die "Failed to get Linux interface name of ${PCI_ADDR}"
+        }
+    fi
+}
+
+
 function get_csit_model () {
 
     # Get CSIT model name from linux network device name.
@@ -467,6 +525,24 @@ function get_pci_addr () {
 }
 
 
+function get_vfio_group () {
+
+    # Get the VFIO group of a pci device.
+    #
+    # Variables read:
+    # - PCI_ADDR - PCI address of a device.
+    # Variables set:
+    # - VFIO_GROUP - The VFIO group of the PCI device.
+
+    if [[ -d /sys/bus/pci/devices/${PCI_ADDR}/iommu_group ]]; then
+        VFIO_GROUP="$(basename\
+            $(readlink /sys/bus/pci/devices/${PCI_ADDR}/iommu_group)\
+        )" || {
+            die "PCI device ${PCI_ADDR} does not have an iommu group!"
+        }
+    fi
+}
+
 function get_vlan_filter () {
 
     # Get VLAN stripping filter from PF searched by mac adress.
@@ -683,9 +759,19 @@ function start_topology_containers () {
     # Override access to PCI bus by attaching a filesystem mount to the
     # container.
     dcr_stc_params+="--mount type=tmpfs,destination=/sys/bus/pci/devices "
-    # Mount vfio to be able to bind to see bound interfaces. We cannot use
-    # --device=/dev/vfio as this does not see newly bound interfaces.
-    dcr_stc_params+="--volume /dev/vfio:/dev/vfio "
+    # Mount vfio devices to be able to use VFs inside the container.
+    vfio_bound="false"
+    for PCI_ADDR in ${DUT1_PCIDEVS[@]}; do
+        get_krn_driver
+        if [[ ${KRN_DRIVER} == "vfio-pci" ]]; then
+            get_vfio_group
+            dcr_stc_params+="--device /dev/vfio/${VFIO_GROUP} "
+            vfio_bound="true"
+        fi
+    done
+    if ! ${vfio_bound}; then
+        dcr_stc_params+="--volume /dev/vfio:/dev/vfio "
+    fi
     # Disable manipulation with hugepages by VPP.
     dcr_stc_params+="--volume /dev/null:/etc/sysctl.d/80-vpp.conf "
     # Mount docker.sock to be able to use docker deamon of the host.