From 4db7530f283472cda065f26e82810cd1f3a07069 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 27 May 2021 14:55:57 +0200 Subject: [PATCH] ci: Add OVS-DPDK integration test In order to avoid regression regarding OVS-DPDK support, a new integration test is added. This test consists of running two VMs, both attached to a distinct OVS port, where both ports are connected to an OVS bridge. Once the VM are running, the test validates the connection between the two VMs works correctly. Signed-off-by: Sebastien Boeuf --- Jenkinsfile | 3 + scripts/run_integration_tests_aarch64.sh | 7 ++ scripts/run_integration_tests_x86_64.sh | 10 +- tests/integration.rs | 123 +++++++++++++++++++++++ 4 files changed, 141 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 779014931..3d7c60994 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -46,6 +46,7 @@ pipeline{ timeout(time: 1, unit: 'HOURS') } steps { + sh "sudo modprobe openvswitch" sh "scripts/dev_cli.sh tests --integration" } } @@ -69,6 +70,7 @@ pipeline{ timeout(time: 1, unit: 'HOURS') } steps { + sh "sudo modprobe openvswitch" sh "scripts/dev_cli.sh tests --integration" } } @@ -98,6 +100,7 @@ pipeline{ timeout(time: 1, unit: 'HOURS') } steps { + sh "sudo modprobe openvswitch" sh "scripts/dev_cli.sh tests --integration --libc musl" } } diff --git a/scripts/run_integration_tests_aarch64.sh b/scripts/run_integration_tests_aarch64.sh index ee6b887a9..491c54679 100755 --- a/scripts/run_integration_tests_aarch64.sh +++ b/scripts/run_integration_tests_aarch64.sh @@ -227,6 +227,13 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan" sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs" sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run" +# Setup ovs-dpdk +echo 2048 | sudo tee /proc/sys/vm/nr_hugepages +service openvswitch-switch start +ovs-vsctl init +ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true +service openvswitch-switch restart + time cargo test $features_test_fdt "tests::parallel::$test_filter" RES=$? echo "Integration test on FDT finished with result $RES." diff --git a/scripts/run_integration_tests_x86_64.sh b/scripts/run_integration_tests_x86_64.sh index f53b8c51c..9973033aa 100755 --- a/scripts/run_integration_tests_x86_64.sh +++ b/scripts/run_integration_tests_x86_64.sh @@ -198,10 +198,16 @@ sudo bash -c "echo 1000000 > /sys/kernel/mm/ksm/pages_to_scan" sudo bash -c "echo 10 > /sys/kernel/mm/ksm/sleep_millisecs" sudo bash -c "echo 1 > /sys/kernel/mm/ksm/run" -# test_vfio relies on hugepages -echo 4096 | sudo tee /proc/sys/vm/nr_hugepages +# Both test_vfio and ovs-dpdk rely on hugepages +echo 6144 | sudo tee /proc/sys/vm/nr_hugepages sudo chmod a+rwX /dev/hugepages +# Setup ovs-dpdk +service openvswitch-switch start +ovs-vsctl init +ovs-vsctl set Open_vSwitch . other_config:dpdk-init=true +service openvswitch-switch restart + export RUST_BACKTRACE=1 time cargo test $features_test "tests::parallel::$test_filter" RES=$? diff --git a/tests/integration.rs b/tests/integration.rs index 4bd1c9e85..790fcdb22 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -5255,6 +5255,129 @@ mod tests { handle_child_output(r, &output); } + + #[test] + fn test_ovs_dpdk() { + // Create OVS-DPDK bridge and ports + std::process::Command::new("bash") + .args(&[ + "-c", + "ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev", + ]) + .status() + .expect("Expected 'ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev' to work"); + std::process::Command::new("bash") + .args(&[ + "-c", + "ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser", + ]) + .status() + .expect("Expected 'ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser' to work"); + std::process::Command::new("bash") + .args(&[ + "-c", + "ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser", + ]) + .status() + .expect("Expected 'ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser' to work"); + std::process::Command::new("bash") + .args(&["-c", "ip link set up dev ovsbr0"]) + .status() + .expect("Expected 'ip link set up dev ovsbr0' to work"); + std::process::Command::new("bash") + .args(&["-c", "service openvswitch-switch restart"]) + .status() + .expect("Expected 'service openvswitch-switch restart' to work"); + + let focal1 = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string()); + let guest1 = Guest::new(Box::new(focal1)); + let mut child1 = GuestCommand::new(&guest1) + .args(&["--cpus", "boot=2"]) + .args(&["--memory", "size=1G,shared=on"]) + .args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()]) + .args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE]) + .default_disks() + .args(&["--net", guest1.default_net_string().as_str(), "vhost_user=true,socket=/var/run/openvswitch/vhost-user1,num_queues=2,queue_size=256,vhost_mode=client"]) + .capture_output() + .spawn() + .unwrap(); + + #[cfg(target_arch = "x86_64")] + let guest_net_iface = "ens5"; + #[cfg(target_arch = "aarch64")] + let guest_net_iface = "enp0s5"; + + let r = std::panic::catch_unwind(|| { + guest1.wait_vm_boot(None).unwrap(); + + assert!(guest1 + .ssh_command_ok(&format!( + "sudo ip addr add 172.100.0.1/24 dev {}", + guest_net_iface + )) + .unwrap()); + assert!(guest1 + .ssh_command_ok(&format!("sudo ip link set up dev {}", guest_net_iface)) + .unwrap()); + + let guest_ip = guest1.network.guest_ip.clone(); + thread::spawn(move || { + ssh_command_ip( + "iperf3 -s -p 4444", + &guest_ip, + DEFAULT_SSH_RETRIES, + DEFAULT_SSH_TIMEOUT, + ) + .unwrap(); + }); + }); + if r.is_err() { + let _ = child1.kill(); + let output = child1.wait_with_output().unwrap(); + handle_child_output(r, &output); + panic!("Test should already be failed/panicked"); // To explicitly mark this block never return + } + + let focal2 = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string()); + let guest2 = Guest::new(Box::new(focal2)); + let mut child2 = GuestCommand::new(&guest2) + .args(&["--cpus", "boot=2"]) + .args(&["--memory", "size=1G,shared=on"]) + .args(&["--kernel", direct_kernel_boot_path().to_str().unwrap()]) + .args(&["--cmdline", DIRECT_KERNEL_BOOT_CMDLINE]) + .default_disks() + .args(&["--net", guest2.default_net_string().as_str(), "vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=2,queue_size=256,vhost_mode=client"]) + .capture_output() + .spawn() + .unwrap(); + + let r = std::panic::catch_unwind(|| { + guest2.wait_vm_boot(None).unwrap(); + + assert!(guest2 + .ssh_command_ok(&format!( + "sudo ip addr add 172.100.0.2/24 dev {}", + guest_net_iface + )) + .unwrap()); + assert!(guest2 + .ssh_command_ok(&format!("sudo ip link set up dev {}", guest_net_iface)) + .unwrap()); + + // Check the connection works properly between the two VMs + assert!(guest2 + .ssh_command_ok("iperf3 -c 172.100.0.1 -t 10 -p 4444") + .unwrap()); + }); + + let _ = child1.kill(); + let _ = child2.kill(); + + let output = child1.wait_with_output().unwrap(); + child2.wait().unwrap(); + + handle_child_output(r, &output); + } } mod sequential {