diff --git a/Makefile b/Makefile index 3ff8e5a9..204fc7db 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ CPPFLAGS += -Iinclude/ CPPFLAGS += $(EXTRA_CPPFLAGS) -CFLAGS += -std=gnu99 -O3 -g -Wall -Werror -march=native -fno-omit-frame-pointer -Wno-address-of-packed-member +CFLAGS += -std=gnu99 -O3 -g -Wall -march=native +CFLAGS += -Wno-address-of-packed-member CFLAGS += $(EXTRA_CFLAGS) CFLAGS_SHARED += $(CFLAGS) -fPIC LDFLAGS += -pthread -g @@ -13,6 +14,7 @@ LDFLAGS += $(EXTRA_LDFLAGS) LDLIBS += -lm -lpthread -lrt -ldl LDLIBS += $(EXTRA_LDLIBS) +PKG_CONFIG ?= pkg-config PREFIX ?= /usr/local SBINDIR ?= $(PREFIX)/sbin LIBDIR ?= $(PREFIX)/lib @@ -22,38 +24,8 @@ INCDIR ?= $(PREFIX)/include ############################################################################## # DPDK configuration -# Prefix for dpdk -RTE_SDK ?= /usr/ -# mpdts to compile -DPDK_PMDS ?= ixgbe i40e tap virtio - -DPDK_CPPFLAGS += -I$(RTE_SDK)/include -I$(RTE_SDK)/include/dpdk \ - -I$(RTE_SDK)/include/x86_64-linux-gnu/dpdk/ -DPDK_LDFLAGS+= -L$(RTE_SDK)/lib/ -DPDK_LDLIBS+= \ - -Wl,--whole-archive \ - $(addprefix -lrte_pmd_,$(DPDK_PMDS)) \ - -lrte_eal \ - -lrte_mempool \ - -lrte_mempool_ring \ - -lrte_hash \ - -lrte_ring \ - -lrte_kvargs \ - -lrte_ethdev \ - -lrte_mbuf \ - -lnuma \ - -lrte_bus_pci \ - -lrte_pci \ - -lrte_cmdline \ - -lrte_timer \ - -lrte_net \ - -lrte_kni \ - -lrte_bus_vdev \ - -lrte_gso \ - -Wl,--no-whole-archive \ - -ldl \ - $(EXTRA_LIBS_DPDK) - +DPDK_CPPFLAGS ?= $(shell $(PKG_CONFIG) --cflags libdpdk) +DPDK_LDLIBS ?= $(shell $(PKG_CONFIG) --static --libs libdpdk) ############################################################################## diff --git a/README.md b/README.md index 39415647..a1ab0fbb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,5 @@ # Virtualized TCP Acceleration Service -[![Build Status](https://travis-ci.org/tcp-acceleration-service/tas.svg?branch=master)](https://travis-ci.org/tcp-acceleration-service/tas) [![Documentation Status](https://readthedocs.org/projects/tas/badge/?version=latest)](https://tas.readthedocs.io/en/latest/?badge=latest) @@ -10,16 +9,36 @@ virtualized environments. ## Building Requirements: * vTAS is built on top of Intel DPDK for direct access to the NIC. We have - tested this version with dpdk versions (17.11.9, 18.11.5, 19.11). + tested this version with dpdk version 21. -Assuming that dpdk is installed in `~/dpdk-inst` vTAS can be built as follows: +Assuming that dpdk is installed through the system package manager, the +following suffices to build TAS: ``` -make RTE_SDK=~/dpdk-inst +make ``` This will build the vTAS service (binary `tas/tas`), client libraries (in `lib/`), and a few debugging tools (in `tools/`). + +### Using Separate DPDK Build + +The Makefile uses `pkg-config` to locate the dpdk libraries and headers. If you +want to build TAS against a non-system dpdk version, the +`PKG_CONFIG_PATH` environmental variable can point pkg-config to the right dpdk +location. For example, with dpdk installed in `/local/antoinek/dpdk` I set + +``` +PKG_CONFIG_PATH=/local/antoinek/dpdk/usr/local/lib/x86_64-linux-gnu/pkgconfig/ +``` + +Instead of manually exporting the environment variable every time, it can also +be set by creating a `Makefile.local` file including the following line: + +``` +PKG_CONFIG= PKG_CONFIG_PATH=/local/antoinek/dpdk/usr/local/lib/x86_64-linux-gnu/pkgconfig/ pkg-config +``` + ## Running Before running vTAS the following steps are necessary: diff --git a/experiments/components/client.py b/experiments/components/client.py index 09cee174..9c0f8c11 100644 --- a/experiments/components/client.py +++ b/experiments/components/client.py @@ -17,26 +17,32 @@ def __init__(self, defaults, machine_config, client_config, vm_config, wmanager) machine_config.is_remote) def run_bare(self, w_sudo, ld_preload): - self.run_benchmark_rpc(w_sudo, ld_preload) + self.run_benchmark_rpc(w_sudo, ld_preload, clean=False) def run_virt(self, w_sudo, ld_preload): ssh_com = utils.get_ssh_command(self.machine_config, self.vm_config) self.pane.send_keys(ssh_com) time.sleep(3) self.pane.send_keys("tas") - self.run_benchmark_rpc(w_sudo, ld_preload) + time.sleep(3) + self.run_benchmark_rpc(w_sudo, ld_preload, clean=False) - def run_benchmark_rpc(self, w_sudo, ld_preload): + def run_benchmark_rpc(self, w_sudo, ld_preload, clean): self.pane.send_keys('cd ' + self.client_config.comp_dir) + + if clean: + self.pane.send_keys(self.client_config.clean_cmd) + time.sleep(1) + self.pane.send_keys(self.client_config.comp_cmd) + time.sleep(1) self.pane.send_keys("cd " + self.client_config.tas_dir) time.sleep(3) - cmd = '' - stack = self.machine_config.stack + cmd = 'stdbuf -oL ' if w_sudo: - cmd = 'sudo ' + cmd += 'sudo -E ' if ld_preload: cmd += 'LD_PRELOAD=' + self.client_config.lib_so + ' ' @@ -46,7 +52,6 @@ def run_benchmark_rpc(self, w_sudo, ld_preload): ' | tee ' + \ self.client_config.out - print(cmd) self.pane.send_keys(cmd) def save_log_virt(self, exp_path): @@ -65,7 +70,18 @@ def save_log_virt(self, exp_path): self.save_logs_pane.send_keys(suppress_history=False, cmd='tas') time.sleep(1) + # Remove log from remote machine + ssh_com = utils.get_ssh_command(self.machine_config, self.vm_config) + ssh_com += " 'rm {}'".format(self.client_config.out) + self.save_logs_pane.send_keys(ssh_com) + time.sleep(3) + self.save_logs_pane.send_keys(suppress_history=False, cmd='tas') + time.sleep(1) + def save_log_bare(self, exp_path): + # kill process to force flush to file + # self.save_logs_pane.send_keys("sudo pkill testclient") + # self.exp_path is set in the run.py file split_path = exp_path.split("/") n = len(split_path) diff --git a/experiments/components/proxy.py b/experiments/components/proxy.py index f0ea467d..543f969b 100644 --- a/experiments/components/proxy.py +++ b/experiments/components/proxy.py @@ -22,9 +22,11 @@ def run(self): pane=self.pane, comp_dir=self.proxy_config.comp_dir, comp_cmd=self.proxy_config.comp_cmd, + clean_cmd=self.proxy_config.clean_cmd, exec_file=self.proxy_config.exec_file, out=self.proxy_config.out, - args='') + args='', + clean=False) class ProxyGuest(Proxy): @@ -44,7 +46,9 @@ def run(self): pane=self.pane, comp_dir=self.proxy_config.comp_dir, comp_cmd=self.proxy_config.comp_cmd, + clean_cmd=self.proxy_config.clean_cmd, exec_file=self.proxy_config.exec_file, out=self.proxy_config.out, args='', - bg=False) \ No newline at end of file + bg=False, + clean=False) \ No newline at end of file diff --git a/experiments/components/server.py b/experiments/components/server.py index ea714326..e41feef1 100644 --- a/experiments/components/server.py +++ b/experiments/components/server.py @@ -15,18 +15,24 @@ def __init__(self, defaults, machine_config, machine_config.is_remote) def run_bare(self, w_sudo, ld_preload): - self.run_benchmark_rpc(w_sudo, ld_preload) + self.run_benchmark_rpc(w_sudo, ld_preload, clean=False) def run_virt(self, w_sudo, ld_preload): ssh_com = utils.get_ssh_command(self.machine_config, self.vm_config) self.pane.send_keys(ssh_com) time.sleep(3) self.pane.send_keys("tas") - self.run_benchmark_rpc(w_sudo, ld_preload) + self.run_benchmark_rpc(w_sudo, ld_preload, clean=False) - def run_benchmark_rpc(self, w_sudo, ld_preload): + def run_benchmark_rpc(self, w_sudo, ld_preload, clean): self.pane.send_keys('cd ' + self.server_config.comp_dir) + + if clean: + self.pane.send_keys(self.server_config.clean_cmd) + time.sleep(1) + self.pane.send_keys(self.server_config.comp_cmd) + time.sleep(1) self.pane.send_keys("cd " + self.server_config.tas_dir) time.sleep(3) @@ -34,7 +40,7 @@ def run_benchmark_rpc(self, w_sudo, ld_preload): stack = self.machine_config.stack if w_sudo: - cmd = 'sudo ' + cmd = 'sudo -E ' if ld_preload: cmd += 'LD_PRELOAD=' + self.server_config.lib_so + ' ' @@ -45,5 +51,4 @@ def run_benchmark_rpc(self, w_sudo, ld_preload): # ' | tee ' + \ # self.server_config.out - print(cmd) self.pane.send_keys(cmd) \ No newline at end of file diff --git a/experiments/components/tas.py b/experiments/components/tas.py index 8fe9bb33..cdf4093d 100644 --- a/experiments/components/tas.py +++ b/experiments/components/tas.py @@ -19,27 +19,35 @@ def run_bare(self): utils.compile_and_run(pane=self.pane, comp_dir=self.tas_config.comp_dir, comp_cmd=self.tas_config.comp_cmd, + clean_cmd=self.tas_config.clean_cmd, exec_file=self.tas_config.exec_file, out=self.tas_config.out, args=tas_args, - save_log=True) + save_log=True, + clean=False) def run_virt(self): ssh_com = utils.get_ssh_command(self.machine_config, self.vm_config) self.pane.send_keys(ssh_com) time.sleep(3) self.pane.send_keys("tas") + time.sleep(3) tas_args = self.tas_config.args utils.compile_and_run(pane=self.pane, comp_dir=self.tas_config.comp_dir, comp_cmd=self.tas_config.comp_cmd, + clean_cmd=self.tas_config.clean_cmd, exec_file=self.tas_config.exec_file, out=self.tas_config.out, args=tas_args, - save_log=True) + save_log=True, + clean=False) def save_log_bare(self, exp_path): + # # kill process to force flush to file + # self.pane.send_keys("sudo pkill tas") + split_path = exp_path.split("/") n = len(split_path) diff --git a/experiments/components/vm.py b/experiments/components/vm.py index 00409e73..1005d4e3 100644 --- a/experiments/components/vm.py +++ b/experiments/components/vm.py @@ -12,25 +12,30 @@ def __init__(self, defaults, machine_config, vm_config, wmanager): def start(self): self.pane.send_keys('cd ' + self.vm_config.manager_dir) - start_vm_cmd = "sudo bash start-vm.sh {} {}".format( - self.machine_config.stack, self.vm_config.id) + start_vm_cmd = "sudo bash start-vm.sh {} {} {}".format( + self.machine_config.stack, self.vm_config.id, + self.machine_config.interface) self.pane.send_keys(start_vm_cmd) print("Started VM") - time.sleep(35) + time.sleep(25) self.login_vm() def enable_hugepages(self): cmd = "sudo mount -t hugetlbfs nodev /dev/hugepages" self.pane.send_keys(cmd) - cmd = "echo 1024 | sudo tee /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages" + time.sleep(1) + cmd = "echo 8192 | sudo tee /sys/devices/system/node/node*/hugepages/hugepages-2048kB/nr_hugepages" self.pane.send_keys(cmd) - time.sleep(3) + time.sleep(5) def enable_noiommu(self, vendor_id): self.pane.send_keys("sudo su -") + time.sleep(1) self.pane.send_keys("sudo echo 1 > /sys/module/vfio/parameters/enable_unsafe_noiommu_mode") + time.sleep(1) self.pane.send_keys("sudo echo {} > /sys/bus/pci/drivers/vfio-pci/new_id".format(vendor_id)) + time.sleep(1) self.pane.send_keys("exit") time.sleep(1) @@ -45,7 +50,7 @@ def init_interface(self, ip, interface): def dpdk_bind(self, ip, interface, pci_id): cmd = 'cd ' + self.vm_config.manager_dir_virt self.pane.send_keys(cmd) - cmd = 'bash dpdk_bind.sh {} {} {}'.format(ip, interface, pci_id) + cmd = 'bash dpdk-bind.sh {} {} {}'.format(ip, interface, pci_id) self.pane.send_keys(cmd) time.sleep(3) @@ -54,4 +59,16 @@ def login_vm(self): time.sleep(3) self.pane.send_keys(suppress_history=False, cmd='tas') self.pane.enter() - time.sleep(5) \ No newline at end of file + time.sleep(5) + + def shutdown(self): + self.pane.send_keys(suppress_history=False, cmd='whoami') + + captured_pane = self.pane.capture_pane() + user = captured_pane[len(captured_pane) - 2] + + # This means we are in the vm, so we don't + # accidentally shutdown machine + if user == 'tas': + self.pane.send_keys(suppress_history=False, cmd='sudo shutdown -h now') + time.sleep(2) \ No newline at end of file diff --git a/experiments/configs/gen_config.py b/experiments/configs/gen_config.py index 94e6e291..c5a93897 100644 --- a/experiments/configs/gen_config.py +++ b/experiments/configs/gen_config.py @@ -37,9 +37,9 @@ def __init__(self): # Network interface used to set ip for a VM self.vm_interface = "enp0s3" # Network interface used to bind TAS in tap VM - self.tas_interface = "enp0s4" + self.tas_interface = "enp0s3" # PCI Id of tas interface - self.pci_id = "0000:00:04.0" + self.pci_id = "0000:00:03.0" self.remote_connect_cmd = 'ssh swsnetlab04' @@ -82,13 +82,14 @@ def __init__(self, pane, machine_config, project_dir, ip, n_cores, self.out = self.out_dir + '/' + self.out_file self.comp_dir = self.project_dir - self.comp_cmd = 'make' + self.comp_cmd = 'make -j6' + self.clean_cmd = 'make clean' self.lib_so = self.comp_dir + 'lib/libtas_interpose.so' self.exec_file = self.comp_dir + '/tas/tas' self.args = '--ip-addr={}/24 --fp-cores-max={}'.format(ip, n_cores) + \ ' --cc=const-rate --cc-const-rate=0' + \ - ' --fp-no-autoscale --fp-no-ints' + \ - ' --dpdk-extra="-w{}"'.format(dpdk_extra) + ' --fp-no-autoscale --fp-no-ints --fp-no-xsumoffload --fp-no-rss' + \ + ' --dpdk-extra="-a{}"'.format(dpdk_extra) self.pane = pane self.ip = ip @@ -119,7 +120,8 @@ def __init__(self, machine_config, comp_dir): self.ivshm_socket_path = '/run/tasproxy' self.comp_dir = comp_dir - self.comp_cmd = 'make' + self.comp_cmd = 'make -j6' + self.clean_cmd = 'make clean' class HostProxyConfig(ProxyConfig): def __init__(self, pane, machine_config, comp_dir): @@ -152,7 +154,8 @@ def __init__(self, pane, idx, vmid, self.tas_dir = tas_dir self.comp_dir = bench_dir + "/micro_rpc" - self.comp_cmd = 'make' + self.comp_cmd = 'make -j6' + self.clean_cmd = 'make clean' self.bench_dir = bench_dir self.lib_so = tas_dir + '/lib/libtas_interpose.so' @@ -180,7 +183,8 @@ def __init__(self, pane, idx, vmid, self.bench_dir = bench_dir self.comp_dir = bench_dir + "/micro_rpc" - self.comp_cmd = 'make' + self.comp_cmd = 'make -j6' + self.clean_cmd = 'make clean' self.lib_so = tas_dir + '/lib/libtas_interpose.so' self.exec_file = self.comp_dir + '/echoserver_linux' self.args = '{} {} foo {} {}'.format(port, ncores, \ diff --git a/experiments/experiments.py b/experiments/experiments.py index 2c5dc1c8..2b54aa5c 100644 --- a/experiments/experiments.py +++ b/experiments/experiments.py @@ -15,6 +15,8 @@ from nodes.vtas_bare.vtasbare_client import VTasBareClient from nodes.ovs_linux.ovslinux_server import OvsLinuxServer from nodes.ovs_linux.ovslinux_client import OvsLinuxClient +from nodes.ovs_tas.ovstas_server import OvsTasServer +from nodes.ovs_tas.ovstas_client import OvsTasClient class Experiment: @@ -41,6 +43,8 @@ def init_server_node(self, stack): node = VTasBareServer(self.config, self.wmanager) elif stack == "ovs-linux": node = OvsLinuxServer(self.config, self.wmanager) + elif stack == "ovs-tas": + node = OvsTasServer(self.config, self.wmanager) return node @@ -59,6 +63,8 @@ def init_client_node(self, stack): node = VTasBareClient(self.config, self.wmanager) elif stack == "ovs-linux": node = OvsLinuxClient(self.config, self.wmanager) + elif stack == "ovs-tas": + node = OvsTasClient(self.config, self.wmanager) return node diff --git a/experiments/exps/perf_iso_latconn/configs/bare_tas.py b/experiments/exps/perf_iso_latconn/configs/bare_tas.py index cde50db2..87142d0e 100644 --- a/experiments/exps/perf_iso_latconn/configs/bare_tas.py +++ b/experiments/exps/perf_iso_latconn/configs/bare_tas.py @@ -28,17 +28,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, - port=1235, ncores=4, max_flows=1024, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) @@ -64,6 +65,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_otas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, @@ -77,7 +79,7 @@ def __init__(self, exp_name, nconns): client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=1, vmid=0, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, + ip=self.defaults.server_ip, port=1235, ncores=3, msize=64, mpending=64, nconns=nconns, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_obenchmark_dir_bare, diff --git a/experiments/exps/perf_iso_latconn/configs/bare_vtas.py b/experiments/exps/perf_iso_latconn/configs/bare_vtas.py index f848e124..084c9d98 100644 --- a/experiments/exps/perf_iso_latconn/configs/bare_vtas.py +++ b/experiments/exps/perf_iso_latconn/configs/bare_vtas.py @@ -10,7 +10,7 @@ def __init__(self, exp_name, nconns): self.defaults = Defaults() # Server Machine - self.sstack = 'bare-vtas' + self.sstack = 'bare-tas' self.snum = 2 self.snodenum = 1 self.s_tas_configs = [] @@ -26,22 +26,22 @@ def __init__(self, exp_name, nconns): tas_config = TasConfig(pane=self.defaults.s_tas_pane, machine_config=self.s_machine_config, - project_dir=self.defaults.default_vtas_dir_bare, + project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=0, vmid=0, groupid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=1024, - bench_dir=self.defaults.default_vbenchmark_dir_bare, - tas_dir=self.defaults.default_vtas_dir_bare) + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=1, vmid=0, groupid=1, - port=1235, ncores=4, max_flows=1024, max_bytes=1024, - bench_dir=self.defaults.default_vbenchmark_dir_bare, - tas_dir=self.defaults.default_vtas_dir_bare) - + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) self.server_configs.append(server1_config) @@ -65,6 +65,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, @@ -78,7 +79,7 @@ def __init__(self, exp_name, nconns): client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=1, vmid=0, groupid=1, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, + ip=self.defaults.server_ip, port=1235, ncores=3, msize=64, mpending=64, nconns=nconns, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_bare, diff --git a/experiments/exps/perf_iso_latconn/configs/ovs_linux.py b/experiments/exps/perf_iso_latconn/configs/ovs_linux.py new file mode 100644 index 00000000..5ee30ea6 --- /dev/null +++ b/experiments/exps/perf_iso_latconn/configs/ovs_linux.py @@ -0,0 +1,96 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, nconns): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-linux' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=1, + msize=64, mpending=64, nconns=1, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_vbenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=64, mpending=64, nconns=nconns, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_latconn/configs/ovs_tas.py b/experiments/exps/perf_iso_latconn/configs/ovs_tas.py new file mode 100644 index 00000000..3a79deab --- /dev/null +++ b/experiments/exps/perf_iso_latconn/configs/ovs_tas.py @@ -0,0 +1,114 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, nconns): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-tas' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + tas0_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm0_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas0_config.args = tas0_config.args + ' --shm-len=8589934592' + + + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + tas1_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm1_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas1_config.args = tas1_config.args + ' --shm-len=8589934592' + + + self.c_tas_configs.append(tas0_config) + self.c_tas_configs.append(tas1_config) + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=1, + msize=64, mpending=64, nconns=1, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=64, mpending=64, nconns=nconns, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_latconn/configs/virt_tas.py b/experiments/exps/perf_iso_latconn/configs/virt_tas.py index bc4e932a..b09bf4dd 100644 --- a/experiments/exps/perf_iso_latconn/configs/virt_tas.py +++ b/experiments/exps/perf_iso_latconn/configs/virt_tas.py @@ -13,9 +13,9 @@ def __init__(self, exp_name, nconns): self.defaults = Defaults() # Server Machine - self.sstack = 'virt-tas' - self.snum = 1 - self.snodenum = 2 + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 self.s_tas_configs = [] self.s_vm_configs = [] self.s_proxyg_configs = [] @@ -29,50 +29,22 @@ def __init__(self, exp_name, nconns): tas_config = TasConfig(pane=self.defaults.s_tas_pane, machine_config=self.s_machine_config, - project_dir=self.defaults.default_vtas_dir_bare, + project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) - self.s_proxyh_config = HostProxyConfig(pane=self.defaults.s_proxyh_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_bare) - - vm0_config = VMConfig(pane=self.defaults.s_vm_pane, - machine_config=self.s_machine_config, - tas_dir=self.defaults.default_vtas_dir_bare, - tas_dir_virt=self.defaults.default_vtas_dir_virt, - idx=0) - vm1_config = VMConfig(pane=self.defaults.s_vm_pane, - machine_config=self.s_machine_config, - tas_dir=self.defaults.default_vtas_dir_bare, - tas_dir_virt=self.defaults.default_vtas_dir_virt, - idx=1) - - self.s_vm_configs.append(vm0_config) - self.s_vm_configs.append(vm1_config) - - proxyg0_config = GuestProxyConfig(pane=self.defaults.s_proxyg_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_virt) - proxyg1_config = GuestProxyConfig(pane=self.defaults.s_proxyg_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_virt) - - self.s_proxyg_configs.append(proxyg0_config) - self.s_proxyg_configs.append(proxyg1_config) - server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=1024, - bench_dir=self.defaults.default_vbenchmark_dir_virt, - tas_dir=self.defaults.default_vtas_dir_virt) + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=0, vmid=1, - port=1235, ncores=4, max_flows=1024, max_bytes=1024, - bench_dir=self.defaults.default_vbenchmark_dir_virt, - tas_dir=self.defaults.default_vtas_dir_virt) - + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) self.server_configs.append(server1_config) @@ -96,6 +68,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) self.c_proxyh_config = HostProxyConfig(pane=self.defaults.c_proxyh_pane, @@ -137,7 +110,7 @@ def __init__(self, exp_name, nconns): client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=0, vmid=1, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, + ip=self.defaults.server_ip, port=1235, ncores=3, msize=64, mpending=64, nconns=nconns, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_virt, diff --git a/experiments/exps/perf_iso_latconn/parse.py b/experiments/exps/perf_iso_latconn/parse.py index e11d8eb3..5d0e0b9d 100644 --- a/experiments/exps/perf_iso_latconn/parse.py +++ b/experiments/exps/perf_iso_latconn/parse.py @@ -2,19 +2,9 @@ sys.path.append("../../../") import os -import re -import functools import experiments.plot_utils as putils -# For this experiment get the number of connections -# from the experiment name, since client 0 and client 1 -# have a different number of connections -def get_conns(fname): - regex = "(?<=_conns)[0-9]*" - nconns = re.search(regex, fname).group(0) - return nconns - def check_nconns(data, nconns): if nconns not in data: data[nconns] = {} @@ -23,29 +13,18 @@ def check_stack(data, nconns, stack): if stack not in data[nconns]: data[nconns][stack] = {} -def check_nid(data, nconns, stack, nid): - if nid not in data[nconns][stack]: - data[nconns][stack][nid] = {} - -def check_cid(data, nconns, stack, nid, cid): - if cid not in data[nconns][stack][nid]: - data[nconns][stack][nid][cid] = "" +def check_run(data, nconns, stack, run): + if run not in data[nconns][stack]: + data[nconns][stack][run] = {} -def get_latencies(fname_c0): - f = open(fname_c0) - lines = f.readlines() +def check_nid(data, nconns, stack, run, nid): + if nid not in data[nconns][stack][run]: + data[nconns][stack][run][nid] = {} - # Latencies are already accumulated over all time - # period in the logs - line = lines[len(lines) - 1] - latencies = {} - latencies["50p"] = putils.get_50p_lat(line) - latencies["90p"] = putils.get_90p_lat(line) - latencies["99p"] = putils.get_99p_lat(line) - latencies["99.9p"] = putils.get_99_9p_lat(line) - latencies["99.99p"] = putils.get_99_99p_lat(line) +def check_cid(data, nconns, stack, run, nid, cid): + if cid not in data[nconns][stack][run][nid]: + data[nconns][stack][run][nid][cid] = "" - return latencies def parse_metadata(): dir_path = "./out/" @@ -53,17 +32,23 @@ def parse_metadata(): for f in os.listdir(dir_path): fname = os.fsdecode(f) - nconns = get_conns(fname) + + if "tas_c" == fname: + continue + + run = putils.get_expname_run(fname) + nconns = putils.get_expname_conns(fname) cid = putils.get_client_id(fname) nid = putils.get_node_id(fname) stack = putils.get_stack(fname) check_nconns(data, nconns) check_stack(data, nconns, stack) - check_nid(data, nconns, stack, nid) - check_cid(data, nconns, stack, nid, cid) + check_run(data, nconns, stack, run) + check_nid(data, nconns, stack, run, nid) + check_cid(data, nconns, stack, run, nid, cid) - data[nconns][stack][nid][cid] = fname + data[nconns][stack][run][nid][cid] = fname return data @@ -73,8 +58,12 @@ def parse_data(parsed_md): for nconns in parsed_md: data_point = {} for stack in parsed_md[nconns]: - fname_c0 = out_dir + parsed_md[nconns][stack]['0']['0'] - latencies = get_latencies(fname_c0) + latencies = putils.init_latencies() + for run in parsed_md[nconns][stack]: + fname_c0 = out_dir + parsed_md[nconns][stack][run]['0']['0'] + putils.add_latencies(latencies, fname_c0) + + putils.divide_latencies(latencies, len(parsed_md[nconns][stack])) data_point[stack] = latencies lat_list[nconns] = data_point @@ -82,10 +71,10 @@ def parse_data(parsed_md): return lat_list def save_dat_file(exp_lats): - header = "nconns bare-tas bare-vtas virt-tas\n" + header = "nconns bare-tas bare-vtas\n" nconns = list(exp_lats.keys()) - nconns = sorted(nconns) + nconns = list(map(str, sorted(map(int, nconns)))) stacks = list(exp_lats[nconns[0]].keys()) percentiles = list(exp_lats[nconns[0]][stacks[0]].keys()) @@ -95,11 +84,10 @@ def save_dat_file(exp_lats): f.write(header) for nconn in nconns: - f.write("{} {} {} {}\n".format( + f.write("{} {} {}\n".format( nconn, exp_lats[nconn]['bare-tas'][percentile], - exp_lats[nconn]['bare-vtas'][percentile], - exp_lats[nconn]['virt-tas'][percentile]) + exp_lats[nconn]['bare-vtas'][percentile]) ) def main(): diff --git a/experiments/exps/perf_iso_latconn/perf_iso_latconn.py b/experiments/exps/perf_iso_latconn/perf_iso_latconn.py index fba71445..ee153ada 100644 --- a/experiments/exps/perf_iso_latconn/perf_iso_latconn.py +++ b/experiments/exps/perf_iso_latconn/perf_iso_latconn.py @@ -3,18 +3,26 @@ from exps.perf_iso_latconn.configs.bare_tas import Config as TasBareConf from exps.perf_iso_latconn.configs.bare_vtas import Config as VTasBareConf from exps.perf_iso_latconn.configs.virt_tas import Config as TasVirtConf +from exps.perf_iso_latconn.configs.ovs_linux import Config as OVSLinuxConf +from exps.perf_iso_latconn.configs.ovs_tas import Config as OVSTasConf experiments = [] -n_conns = [64, 128, 256, 512, 1024, 2048, 4096] +n_conns = [128, 256, 512, 1024, 2048, 4096, 8192, 16384] +n_runs = 3 -for n in n_conns: - exp_name = "perf-iso-latconn_conns{}_".format(n) - tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n), name=exp_name) - vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n), name=exp_name) - tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n), name=exp_name) +for n_r in range(n_runs): + for n_c in n_conns: + exp_name = "perf-iso-latconn-run{}-conns{}_".format(n_r, n_c) + tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n_c), name=exp_name) + vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n_c), name=exp_name) + tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n_c), name=exp_name) + ovs_linux_exp = exp.Experiment(OVSLinuxConf(exp_name + "ovs-linux", n_c), name=exp_name) + ovs_tas_exp = exp.Experiment(OVSTasConf(exp_name + "ovs-tas", n_c), name=exp_name) - experiments.append(tas_bare_exp) - experiments.append(vtas_bare_exp) - experiments.append(tas_virt_exp) + experiments.append(tas_bare_exp) + experiments.append(vtas_bare_exp) + experiments.append(tas_virt_exp) + experiments.append(ovs_tas_exp) + experiments.append(ovs_linux_exp) diff --git a/experiments/exps/perf_iso_latconn/plot.pdf b/experiments/exps/perf_iso_latconn/plot.pdf deleted file mode 100644 index 178aa312..00000000 Binary files a/experiments/exps/perf_iso_latconn/plot.pdf and /dev/null differ diff --git a/experiments/exps/perf_iso_latconn/plot_script b/experiments/exps/perf_iso_latconn/plot_script deleted file mode 100644 index aa050711..00000000 --- a/experiments/exps/perf_iso_latconn/plot_script +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/gnuplot -persist -set terminal pdf -set output "plot.pdf" -set colorsequence podo -set key autotitle columnhead -set key left top - -# margins: left,right,bottom,top -# spacing: xspacing,yspacing -set multiplot layout 2,2 \ - margins 0.1,0.95,0.15,0.90 \ - spacing 0.1,0.07 - -set label 1 "Aggresor Client # Connections" at screen 0.5, 0.03 center -set label 2 "Victim Client Latency (µs)" at screen 0.01, 0.5 rotate by 90 center - -set title offset 0,-0.6 - -# Plot 50p latency -unset xtics -set yrange [0:] -set title "50p Latency" -plot 'lat_50p.dat' using 1:2 title 'bare-tas' linetype 2 w lp, \ - 'lat_50p.dat' using 1:3 title 'bare-vtas' linetype 3 w lp, \ - 'lat_50p.dat' using 1:4 title 'virt-tas' linetype 4 w lp, \ - -# Plot 90p latency -unset xtics -set yrange [0:] -set title "90p Latency" -plot 'lat_90p.dat' using 1:2 title 'bare-tas' linetype 2 w lp, \ - 'lat_90p.dat' using 1:3 title 'bare-vtas' linetype 3 w lp, \ - 'lat_90p.dat' using 1:4 title 'virt-tas' linetype 4 w lp, \ - -# Plot 99p latency -set xtics -set yrange [0:] -set title "99p Latency" -plot 'lat_99p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 w lp, \ - 'lat_99p.dat' using 1:3:xtic(1) title 'bare-vtas' linetype 3 w lp, \ - 'lat_99p.dat' using 1:4:xtic(1) title 'virt-tas' linetype 4 w lp, \ - -# Plot 99.9p latency -set xtics -set yrange [0:] -set title "99.9p Latency" -plot 'lat_99.9p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 w lp, \ - 'lat_99.9p.dat' using 1:3:xtic(1) title 'bare-vtas' linetype 3 w lp, \ - 'lat_99.9p.dat' using 1:4:xtic(1) title 'virt-tas' linetype 4 w lp, \ diff --git a/experiments/exps/perf_iso_latconn/plot_script.plt b/experiments/exps/perf_iso_latconn/plot_script.plt new file mode 100644 index 00000000..40ecd88d --- /dev/null +++ b/experiments/exps/perf_iso_latconn/plot_script.plt @@ -0,0 +1,67 @@ +#!/usr/bin/gnuplot -persist +set terminal pdf +set output "plot.pdf" +set colorsequence podo +set logscale x 2 +set key autotitle columnhead + +set title font "Computer Modern Roman,6" +set key font "Computer Modern Roman,6" +set ytics font "Computer Modern Roman,6" + +# margins: left,right,bottom,top +# spacing: xspacing,yspacing +set multiplot layout 2,2 \ + margins 0.1,0.95,0.15,0.90 \ + spacing 0.1,0.07 + +set label 1 "Aggresor Client # Connections" at screen 0.5, 0.03 center font "Computer Modern Roman,8" +set label 2 "Victim Client Latency (µs)" at screen 0.01, 0.5 rotate by 90 center font "Computer Modern Roman,8" + +set title offset 0,-0.6 + +# Plot 50p latency +unset xtics +set yrange [0:] +set title "50p Latency" +set key center right +plot 'lat_50p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 ps 0.3 w lp, \ + 'lat_50p.dat' using 1:3:xtic(1) title 'bare-virtuoso' linetype 3 ps 0.3 w lp, \ + 'lat_50p.dat' using 1:4:xtic(1) title 'virtuoso' linetype 4 ps 0.3 w lp, \ + 'lat_50p.dat' using 1:5:xtic(1) title 'ovs-linux' linetype 5 ps 0.3 w lp, \ + 'lat_50p.dat' using 1:6:xtic(1) title 'ovs-tas' linetype 6 ps 0.3 w lp, \ + +# Plot 90p latency +unset xtics +set yrange [0:] +set title "90p Latency" +set key center right +plot 'lat_90p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 ps 0.3 w lp, \ + 'lat_90p.dat' using 1:3:xtic(1) title 'bare-virtuoso' linetype 3 ps 0.3 w lp, \ + 'lat_90p.dat' using 1:4:xtic(1) title 'virtuoso' linetype 4 ps 0.3 w lp, \ + 'lat_90p.dat' using 1:5:xtic(1) title 'ovs-linux' linetype 5 ps 0.3 w lp, \ + 'lat_90p.dat' using 1:6:xtic(1) title 'ovs-tas' linetype 6 ps 0.3 w lp, \ + +# Plot 99p latency +set xtics +set xtics font "Computer Modern Roman,6" +set yrange [0:] +set title "99p Latency" +set key center right +plot 'lat_99p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 ps 0.3 w lp, \ + 'lat_99p.dat' using 1:3:xtic(1) title 'bare-virtuoso' linetype 3 ps 0.3 w lp, \ + 'lat_99p.dat' using 1:4:xtic(1) title 'virtuoso' linetype 4 ps 0.3 w lp, \ + 'lat_99p.dat' using 1:5:xtic(1) title 'ovs-linux' linetype 5 ps 0.3 w lp, \ + 'lat_99p.dat' using 1:6:xtic(1) title 'ovs-tas' linetype 6 ps 0.3 w lp, \ + +# Plot 99.9p latency +set xtics +set xtics font "Computer Modern Roman,6" +set yrange [0:] +set title "99.9p Latency" +set key left top +plot 'lat_99.9p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 ps 0.3 w lp, \ + 'lat_99.9p.dat' using 1:3:xtic(1) title 'bare-virtuoso' linetype 3 ps 0.3 w lp, \ + 'lat_99.9p.dat' using 1:4:xtic(1) title 'virtuoso' linetype 4 ps 0.3 w lp, \ + 'lat_99.9p.dat' using 1:5:xtic(1) title 'ovs-linux' linetype 5 ps 0.3 w lp, \ + 'lat_99.9p.dat' using 1:6:xtic(1) title 'ovs-tas' linetype 6 ps 0.3 w lp, \ diff --git a/experiments/exps/perf_iso_latmsize/configs/bare_tas.py b/experiments/exps/perf_iso_latmsize/configs/bare_tas.py index fe57edde..c60422d4 100644 --- a/experiments/exps/perf_iso_latmsize/configs/bare_tas.py +++ b/experiments/exps/perf_iso_latmsize/configs/bare_tas.py @@ -28,17 +28,18 @@ def __init__(self, exp_name, msize): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=4096, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, - port=1235, ncores=4, max_flows=1024, max_bytes=4096, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) @@ -64,21 +65,22 @@ def __init__(self, exp_name, msize): project_dir=self.defaults.default_otas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=0, vmid=0, stack=self.cstack, ip=self.defaults.server_ip, port=1234, ncores=1, - msize=msize, mpending=64, nconns=1, + msize=64, mpending=64, nconns=1, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=1, vmid=0, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, - msize=msize, mpending=64, nconns=1, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) diff --git a/experiments/exps/perf_iso_latmsize/configs/bare_vtas.py b/experiments/exps/perf_iso_latmsize/configs/bare_vtas.py index 1cf332d9..f346fb50 100644 --- a/experiments/exps/perf_iso_latmsize/configs/bare_vtas.py +++ b/experiments/exps/perf_iso_latmsize/configs/bare_vtas.py @@ -10,7 +10,7 @@ def __init__(self, exp_name, msize): self.defaults = Defaults() # Server Machine - self.sstack = 'bare-vtas' + self.sstack = 'bare-tas' self.snum = 2 self.snodenum = 1 self.s_tas_configs = [] @@ -26,22 +26,22 @@ def __init__(self, exp_name, msize): tas_config = TasConfig(pane=self.defaults.s_tas_pane, machine_config=self.s_machine_config, - project_dir=self.defaults.default_vtas_dir_bare, + project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=0, vmid=0, groupid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=4096, - bench_dir=self.defaults.default_vbenchmark_dir_bare, - tas_dir=self.defaults.default_vtas_dir_bare) + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=1, vmid=0, groupid=1, - port=1235, ncores=4, max_flows=1024, max_bytes=4096, - bench_dir=self.defaults.default_vbenchmark_dir_bare, - tas_dir=self.defaults.default_vtas_dir_bare) - + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) self.server_configs.append(server1_config) @@ -65,21 +65,22 @@ def __init__(self, exp_name, msize): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=0, vmid=0, groupid=0, stack=self.cstack, ip=self.defaults.server_ip, port=1234, ncores=1, - msize=msize, mpending=64, nconns=1, + msize=64, mpending=64, nconns=1, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_bare, tas_dir=self.defaults.default_vtas_dir_bare) client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=1, vmid=0, groupid=1, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, - msize=msize, mpending=64, nconns=1, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_bare, tas_dir=self.defaults.default_vtas_dir_bare) diff --git a/experiments/exps/perf_iso_latmsize/configs/ovs_linux.py b/experiments/exps/perf_iso_latmsize/configs/ovs_linux.py new file mode 100644 index 00000000..fd0a8663 --- /dev/null +++ b/experiments/exps/perf_iso_latmsize/configs/ovs_linux.py @@ -0,0 +1,96 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-linux' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=1, + msize=64, mpending=64, nconns=1, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_vbenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_latmsize/configs/ovs_tas.py b/experiments/exps/perf_iso_latmsize/configs/ovs_tas.py new file mode 100644 index 00000000..131c4221 --- /dev/null +++ b/experiments/exps/perf_iso_latmsize/configs/ovs_tas.py @@ -0,0 +1,114 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-tas' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + tas0_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm0_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas0_config.args = tas0_config.args + ' --shm-len=8589934592' + + + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + tas1_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm1_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas1_config.args = tas1_config.args + ' --shm-len=8589934592' + + + self.c_tas_configs.append(tas0_config) + self.c_tas_configs.append(tas1_config) + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=1, + msize=64, mpending=64, nconns=1, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_latmsize/configs/virt_tas.py b/experiments/exps/perf_iso_latmsize/configs/virt_tas.py index b6861fdd..38ca219d 100644 --- a/experiments/exps/perf_iso_latmsize/configs/virt_tas.py +++ b/experiments/exps/perf_iso_latmsize/configs/virt_tas.py @@ -13,9 +13,9 @@ def __init__(self, exp_name, msize): self.defaults = Defaults() # Server Machine - self.sstack = 'virt-tas' - self.snum = 1 - self.snodenum = 2 + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 self.s_tas_configs = [] self.s_vm_configs = [] self.s_proxyg_configs = [] @@ -29,50 +29,22 @@ def __init__(self, exp_name, msize): tas_config = TasConfig(pane=self.defaults.s_tas_pane, machine_config=self.s_machine_config, - project_dir=self.defaults.default_vtas_dir_bare, + project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=8) + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) - self.s_proxyh_config = HostProxyConfig(pane=self.defaults.s_proxyh_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_bare) - - vm0_config = VMConfig(pane=self.defaults.s_vm_pane, - machine_config=self.s_machine_config, - tas_dir=self.defaults.default_vtas_dir_bare, - tas_dir_virt=self.defaults.default_vtas_dir_virt, - idx=0) - vm1_config = VMConfig(pane=self.defaults.s_vm_pane, - machine_config=self.s_machine_config, - tas_dir=self.defaults.default_vtas_dir_bare, - tas_dir_virt=self.defaults.default_vtas_dir_virt, - idx=1) - - self.s_vm_configs.append(vm0_config) - self.s_vm_configs.append(vm1_config) - - proxyg0_config = GuestProxyConfig(pane=self.defaults.s_proxyg_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_virt) - proxyg1_config = GuestProxyConfig(pane=self.defaults.s_proxyg_pane, - machine_config=self.s_machine_config, - comp_dir=self.defaults.default_vtas_dir_virt) - - self.s_proxyg_configs.append(proxyg0_config) - self.s_proxyg_configs.append(proxyg1_config) - server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=4, max_flows=1024, max_bytes=4096, - bench_dir=self.defaults.default_vbenchmark_dir_virt, - tas_dir=self.defaults.default_vtas_dir_virt) + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, - idx=0, vmid=1, - port=1235, ncores=4, max_flows=1024, max_bytes=4096, - bench_dir=self.defaults.default_vbenchmark_dir_virt, - tas_dir=self.defaults.default_vtas_dir_virt) - + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) self.server_configs.append(server1_config) @@ -96,6 +68,7 @@ def __init__(self, exp_name, msize): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) self.c_proxyh_config = HostProxyConfig(pane=self.defaults.c_proxyh_pane, @@ -130,15 +103,15 @@ def __init__(self, exp_name, msize): pane=self.defaults.c_client_pane, idx=0, vmid=0, stack=self.cstack, ip=self.defaults.server_ip, port=1234, ncores=1, - msize=msize, mpending=64, nconns=1, + msize=64, mpending=64, nconns=1, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_virt, tas_dir=self.defaults.default_vtas_dir_virt) client1_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=0, vmid=1, stack=self.cstack, - ip=self.defaults.server_ip, port=1235, ncores=1, - msize=msize, mpending=64, nconns=1, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_virt, tas_dir=self.defaults.default_vtas_dir_virt) diff --git a/experiments/exps/perf_iso_latmsize/parse.py b/experiments/exps/perf_iso_latmsize/parse.py index 58112f79..6370e2a1 100644 --- a/experiments/exps/perf_iso_latmsize/parse.py +++ b/experiments/exps/perf_iso_latmsize/parse.py @@ -2,19 +2,10 @@ sys.path.append("../../../") import os -import re -import functools +import numpy as np import experiments.plot_utils as putils -# For this experiment get the message size -# from the experiment name, since client 0 and client 1 -# have a different message size -def get_msize(fname): - regex = "(?<=_msize)[0-9]*" - nconns = re.search(regex, fname).group(0) - return nconns - def check_msize(data, msize): if msize not in data: data[msize] = {} @@ -23,29 +14,17 @@ def check_stack(data, nconns, stack): if stack not in data[nconns]: data[nconns][stack] = {} -def check_nid(data, nconns, stack, nid): - if nid not in data[nconns][stack]: - data[nconns][stack][nid] = {} - -def check_cid(data, nconns, stack, nid, cid): - if cid not in data[nconns][stack][nid]: - data[nconns][stack][nid][cid] = "" - -def get_latencies(fname_c0): - f = open(fname_c0) - lines = f.readlines() +def check_run(data, msize, stack, run): + if run not in data[msize][stack]: + data[msize][stack][run] = {} - # Latencies are already accumulated over all time - # period in the logs - line = lines[len(lines) - 1] - latencies = {} - latencies["50p"] = putils.get_50p_lat(line) - latencies["90p"] = putils.get_90p_lat(line) - latencies["99p"] = putils.get_99p_lat(line) - latencies["99.9p"] = putils.get_99_9p_lat(line) - latencies["99.99p"] = putils.get_99_99p_lat(line) +def check_nid(data, msize, stack, run, nid): + if nid not in data[msize][stack][run]: + data[msize][stack][run][nid] = {} - return latencies +def check_cid(data, msize, stack, run, nid, cid): + if cid not in data[msize][stack][run][nid]: + data[msize][stack][run][nid][cid] = "" def parse_metadata(): dir_path = "./out/" @@ -53,41 +32,56 @@ def parse_metadata(): for f in os.listdir(dir_path): fname = os.fsdecode(f) - msize = get_msize(fname) - cid = putils.get_client_id(fname) + + if "tas_c" == fname: + continue + + run = putils.get_expname_run(fname) + msize = putils.get_expname_msize(fname) nid = putils.get_node_id(fname) + cid = putils.get_client_id(fname) stack = putils.get_stack(fname) check_msize(data, msize) check_stack(data, msize, stack) - check_nid(data, msize, stack, nid) - check_cid(data, msize, stack, nid, cid) + check_run(data, msize, stack, run) + check_nid(data, msize, stack, run, nid) + check_cid(data, msize, stack, run, nid, cid) - data[msize][stack][nid][cid] = fname + data[msize][stack][run][nid][cid] = fname return data def parse_data(parsed_md): - lat_list = {} + data = {} out_dir = "./out/" for msize in parsed_md: data_point = {} for stack in parsed_md[msize]: - fname_c0 = out_dir + parsed_md[msize][stack]['0']['0'] - latencies = get_latencies(fname_c0) - data_point[stack] = latencies - - lat_list[msize] = data_point + latencies = putils.init_latencies() + for run in parsed_md[msize][stack]: + fname_c0 = out_dir + parsed_md[msize][stack][run]['0']['0'] + putils.append_latencies(latencies, fname_c0) + + data_point[stack] = { + "lat": putils.get_latency_avg(latencies), + "std": putils.get_latency_std(latencies) + } + data[msize] = data_point - return lat_list + return data -def save_dat_file(exp_lats): - header = "nconns bare-tas bare-vtas virt-tas\n" +def save_dat_file(data): + header = "msize " + \ + "bare-tas-avg bare-vtas-avg virt-tas-avg " + \ + "ovs-linux-avg " + \ + "bare-tas-std bare-vtas-std virt-tas-std " + \ + "ovs-linux-std\n" - msizes = list(exp_lats.keys()) - msizes = sorted(msizes) - stacks = list(exp_lats[msizes[0]].keys()) - percentiles = list(exp_lats[msizes[0]][stacks[0]].keys()) + msizes = list(data.keys()) + msizes = list(map(str, sorted(map(int, msizes)))) + stacks = list(data[msizes[0]].keys()) + percentiles = list(data[msizes[0]][stacks[0]]['lat'].keys()) for percentile in percentiles: fname = "./lat_{}.dat".format(percentile) @@ -95,12 +89,17 @@ def save_dat_file(exp_lats): f.write(header) for msize in msizes: - f.write("{} {} {} {}\n".format( + f.write("{} {} {} {} {} {} {} {} {}\n".format( msize, - exp_lats[msize]['bare-tas'][percentile], - exp_lats[msize]['bare-vtas'][percentile], - exp_lats[msize]['virt-tas'][percentile]) - ) + data[msize]['bare-tas']['lat'][percentile], + data[msize]['bare-vtas']["lat"][percentile], + data[msize]['virt-tas']["lat"][percentile], + data[msize]['ovs-linux']["lat"][percentile], + data[msize]['bare-tas']["std"][percentile], + data[msize]['bare-vtas']["std"][percentile], + data[msize]['virt-tas']["std"][percentile], + data[msize]['ovs-linux']["std"][percentile])) + def main(): parsed_md = parse_metadata() diff --git a/experiments/exps/perf_iso_latmsize/perf_iso_latmsize.py b/experiments/exps/perf_iso_latmsize/perf_iso_latmsize.py index d0913570..434b4b25 100644 --- a/experiments/exps/perf_iso_latmsize/perf_iso_latmsize.py +++ b/experiments/exps/perf_iso_latmsize/perf_iso_latmsize.py @@ -3,18 +3,26 @@ from exps.perf_iso_latmsize.configs.bare_tas import Config as TasBareConf from exps.perf_iso_latmsize.configs.bare_vtas import Config as VTasBareConf from exps.perf_iso_latmsize.configs.virt_tas import Config as TasVirtConf +from exps.perf_iso_latmsize.configs.ovs_linux import Config as OVSLinuxConf +from exps.perf_iso_latmsize.configs.ovs_tas import Config as OVSTasConf experiments = [] -msize = [64, 128, 256, 512, 1024, 2048, 4096] +msize = [64, 128, 256, 512, 1024, 2048] +n_runs = 3 -for n in msize: - exp_name = "perf-iso-latmsize_msize{}_".format(n) - tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n), name=exp_name) - vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n), name=exp_name) - tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n), name=exp_name) +for n_r in range(n_runs): + for n_m in msize: + exp_name = "perf-iso-latmsize-run{}-msize{}_".format(n_r, n_m) + tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n_m), name=exp_name) + vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n_m), name=exp_name) + tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n_m), name=exp_name) + ovs_linux_exp = exp.Experiment(OVSLinuxConf(exp_name + "ovs-linux", n_m), name=exp_name) + ovs_tas_exp = exp.Experiment(OVSTasConf(exp_name + "ovs-tas", n_m), name=exp_name) - experiments.append(tas_bare_exp) - experiments.append(vtas_bare_exp) - experiments.append(tas_virt_exp) + # experiments.append(tas_bare_exp) + # experiments.append(vtas_bare_exp) + # experiments.append(tas_virt_exp) + experiments.append(ovs_tas_exp) + # experiments.append(ovs_linux_exp) diff --git a/experiments/exps/perf_iso_latmsize/plot.pdf b/experiments/exps/perf_iso_latmsize/plot.pdf deleted file mode 100644 index 8b27073f..00000000 Binary files a/experiments/exps/perf_iso_latmsize/plot.pdf and /dev/null differ diff --git a/experiments/exps/perf_iso_latmsize/plot_script b/experiments/exps/perf_iso_latmsize/plot_script deleted file mode 100644 index 11c86971..00000000 --- a/experiments/exps/perf_iso_latmsize/plot_script +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/gnuplot -persist -set terminal pdf -set output "plot.pdf" -set colorsequence podo -set key autotitle columnhead -set key left top - -# margins: left,right,bottom,top -# spacing: xspacing,yspacing -set multiplot layout 2,2 \ - margins 0.1,0.95,0.15,0.90 \ - spacing 0.1,0.07 - -set label 1 "Aggressor Client Message Size (Bytes)" at screen 0.5, 0.03 center -set label 2 "Victim Client Latency (µs)" at screen 0.01, 0.5 rotate by 90 center - -set title offset 0,-0.6 - -# Plot 50p latency -unset xtics -set yrange [0:] -set title "50p Latency" -plot 'lat_50p.dat' using 1:2 title 'bare-tas' linetype 2 w lp, \ - 'lat_50p.dat' using 1:3 title 'bare-vtas' linetype 3 w lp, \ - 'lat_50p.dat' using 1:4 title 'virt-tas' linetype 4 w lp, \ - -# Plot 90p latency -unset xtics -set yrange [0:] -set title "90p Latency" -plot 'lat_90p.dat' using 1:2 title 'bare-tas' linetype 2 w lp, \ - 'lat_90p.dat' using 1:3 title 'bare-vtas' linetype 3 w lp, \ - 'lat_90p.dat' using 1:4 title 'virt-tas' linetype 4 w lp, \ - -# Plot 99p latency -set xtics -set yrange [0:] -set title "99p Latency" -plot 'lat_99p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 w lp, \ - 'lat_99p.dat' using 1:3:xtic(1) title 'bare-vtas' linetype 3 w lp, \ - 'lat_99p.dat' using 1:4:xtic(1) title 'virt-tas' linetype 4 w lp, \ - -# Plot 99.9p latency -set xtics -set yrange [0:] -set title "99.9p Latency" -plot 'lat_99.9p.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 w lp, \ - 'lat_99.9p.dat' using 1:3:xtic(1) title 'bare-vtas' linetype 3 w lp, \ - 'lat_99.9p.dat' using 1:4:xtic(1) title 'virt-tas' linetype 4 w lp, \ diff --git a/experiments/exps/perf_iso_latmsize/plot_script.plt b/experiments/exps/perf_iso_latmsize/plot_script.plt new file mode 100644 index 00000000..cfa26593 --- /dev/null +++ b/experiments/exps/perf_iso_latmsize/plot_script.plt @@ -0,0 +1,68 @@ +#!/usr/bin/gnuplot -persist +set terminal pdf +set output "plot.pdf" +set colorsequence podo +set logscale x 2 +set key autotitle columnhead + +set title font "Computer Modern Roman,6" +set key font "Computer Modern Roman,6" +set ytics font "Computer Modern Roman,6" + +# margins: left,right,bottom,top +# spacing: xspacing,yspacing +set multiplot layout 2,2 \ + margins 0.1,0.95,0.15,0.90 \ + spacing 0.1,0.07 + +set label 1 "Aggressor Client Message Size (Bytes)" at screen 0.5, 0.03 center font "Computer Modern Roman,8" +set label 2 "Victim Client Latency (µs)" at screen 0.01, 0.5 rotate by 90 center font "Computer Modern Roman,8" + +set title offset 0,-0.6 + +# Plot 50p latency +unset xtics +set key center left +set yrange [0:] +set title "50p Latency" +plot 'lat_50p.dat' using 1:2:6 with yerrorlines title 'bare-tas' linetype 2 ps 0.3, \ + 'lat_50p.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.3, \ + 'lat_50p.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.3, \ + 'lat_50p.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.3, \ + # 'lat_50p.dat' using 1:6: with yerrorlines title 'ovs-tas' linetype 6 ps 0.3, \ + +# Plot 90p latency +unset xtics +set key top right +set yrange [0:] +set title "90p Latency" +plot 'lat_90p.dat' using 1:2:6 with yerrorlines title 'bare-tas' linetype 2 ps 0.3, \ + 'lat_90p.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.3, \ + 'lat_90p.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.3, \ + 'lat_90p.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.3, \ + # 'lat_90p.dat' using 1:6: with yerrorlines title 'ovs-tas' linetype 6 ps 0.3, \ + + +# Plot 99p latency +set xtics +set xtics font "Computer Modern Roman,6" +set key center left +set yrange [0:] +set title "99p Latency" +plot 'lat_99p.dat' using 1:2:6 with yerrorlines title 'bare-tas' linetype 2 ps 0.3, \ + 'lat_99p.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.3, \ + 'lat_99p.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.3, \ + 'lat_99p.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.3, \ + # 'lat_99p.dat' using 1:6: with yerrorlines title 'ovs-tas' linetype 6 ps 0.3, \ + +# Plot 99.9p latency +set xtics +set xtics font "Computer Modern Roman,6" +set key center right +set yrange [0:] +set title "99.9p Latency" +plot 'lat_99.9p.dat' using 1:2:6 with yerrorlines title 'bare-tas' linetype 2 ps 0.3, \ + 'lat_99.9p.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.3, \ + 'lat_99.9p.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.3, \ + 'lat_99.9p.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.3, \ + # 'lat_99.9p.dat' using 1:6: with yerrorlines title 'ovs-tas' linetype 6 ps 0.3, \ diff --git a/experiments/exps/perf_iso_tpconn/configs/bare_tas.py b/experiments/exps/perf_iso_tpconn/configs/bare_tas.py index 5b482190..c5c95fc5 100644 --- a/experiments/exps/perf_iso_tpconn/configs/bare_tas.py +++ b/experiments/exps/perf_iso_tpconn/configs/bare_tas.py @@ -28,18 +28,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=12) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=8, max_flows=4096, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, - port=1235, ncores=8, max_flows=4096, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) @@ -65,7 +65,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_otas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, diff --git a/experiments/exps/perf_iso_tpconn/configs/bare_vtas.py b/experiments/exps/perf_iso_tpconn/configs/bare_vtas.py index ce0da0e5..9b9e5541 100644 --- a/experiments/exps/perf_iso_tpconn/configs/bare_vtas.py +++ b/experiments/exps/perf_iso_tpconn/configs/bare_vtas.py @@ -28,18 +28,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=12) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, groupid=0, - port=1234, ncores=8, max_flows=4096, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, groupid=1, - port=1235, ncores=8, max_flows=4096, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) @@ -66,7 +66,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) - tas_config.args = tas_config.args + ' --vm-shm-len=4294967296' + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, diff --git a/experiments/exps/perf_iso_tpconn/configs/ovs_linux.py b/experiments/exps/perf_iso_tpconn/configs/ovs_linux.py index d16a7c4b..838e5983 100644 --- a/experiments/exps/perf_iso_tpconn/configs/ovs_linux.py +++ b/experiments/exps/perf_iso_tpconn/configs/ovs_linux.py @@ -29,18 +29,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=12) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=8, max_flows=4096, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, - port=1235, ncores=8, max_flows=4096, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) diff --git a/experiments/exps/perf_iso_tpconn/configs/ovs_tas.py b/experiments/exps/perf_iso_tpconn/configs/ovs_tas.py new file mode 100644 index 00000000..4ada0270 --- /dev/null +++ b/experiments/exps/perf_iso_tpconn/configs/ovs_tas.py @@ -0,0 +1,113 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, nconns): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-tas' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + tas0_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm0_config.vm_ip, + n_cores=1, dpdk_extra="00:03.0") + tas0_config.args = tas0_config.args + ' --shm-len=8589934592' + + + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + tas1_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm1_config.vm_ip, + n_cores=1, dpdk_extra="00:03.0") + tas1_config.args = tas1_config.args + ' --shm-len=8589934592' + + + self.c_tas_configs.append(tas0_config) + self.c_tas_configs.append(tas1_config) + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=3, + msize=64, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=64, mpending=64, nconns=nconns, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpconn/configs/virt_tas.py b/experiments/exps/perf_iso_tpconn/configs/virt_tas.py index 36b06472..f7cd6534 100644 --- a/experiments/exps/perf_iso_tpconn/configs/virt_tas.py +++ b/experiments/exps/perf_iso_tpconn/configs/virt_tas.py @@ -31,18 +31,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=12) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, - port=1234, ncores=8, max_flows=4096, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, - port=1235, ncores=8, max_flows=4096, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) self.server_configs.append(server0_config) @@ -68,7 +68,7 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) - tas_config.args = tas_config.args + ' --vm-shm-len=4294967296' + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) self.c_proxyh_config = HostProxyConfig(pane=self.defaults.c_proxyh_pane, diff --git a/experiments/exps/perf_iso_tpconn/parse.py b/experiments/exps/perf_iso_tpconn/parse.py index 1f8bde1d..e139dba5 100644 --- a/experiments/exps/perf_iso_tpconn/parse.py +++ b/experiments/exps/perf_iso_tpconn/parse.py @@ -3,17 +3,9 @@ import os import re +import numpy as np import experiments.plot_utils as putils - -# For this experiment get the number of connections -# from the experiment name, since client 0 and client 1 -# have a different number of connections -def get_conns(fname): - regex = "(?<=_conns)[0-9]*" - nconns = re.search(regex, fname).group(0) - return nconns - def check_nconns(data, nconns): if nconns not in data: data[nconns] = {} @@ -22,13 +14,17 @@ def check_stack(data, nconns, stack): if stack not in data[nconns]: data[nconns][stack] = {} -def check_nid(data, nconns, stack, nid): - if nid not in data[nconns][stack]: - data[nconns][stack][nid] = {} +def check_run(data, nconns, stack, run): + if run not in data[nconns][stack]: + data[nconns][stack][run] = {} + +def check_nid(data, nconns, stack, run, nid): + if nid not in data[nconns][stack][run]: + data[nconns][stack][run][nid] = {} -def check_cid(data, nconns, stack, nid, cid): - if cid not in data[nconns][stack][nid]: - data[nconns][stack][nid][cid] = "" +def check_cid(data, nconns, stack, run, nid, cid): + if cid not in data[nconns][stack][run][nid]: + data[nconns][stack][run][nid][cid] = "" def get_avg_tp(fname_c0, fname_c1): n_messages = 0 @@ -48,7 +44,7 @@ def get_avg_tp(fname_c0, fname_c1): msize = int(putils.get_msize(fname_c0)) n = len(lines) - idx - return str((n_messages * msize * 8 / n) / 1000000) + return (n_messages * msize * 8 / n) / 1000000 def parse_metadata(): dir_path = "./out/" @@ -60,58 +56,72 @@ def parse_metadata(): if "tas_c" == fname: continue - nconns = get_conns(fname) + run = putils.get_expname_run(fname) + nconns = putils.get_expname_conns(fname) cid = putils.get_client_id(fname) nid = putils.get_node_id(fname) stack = putils.get_stack(fname) check_nconns(data, nconns) check_stack(data, nconns, stack) - check_nid(data, nconns, stack, nid) - check_cid(data, nconns, stack, nid, cid) + check_run(data, nconns, stack, run) + check_nid(data, nconns, stack, run, nid) + check_cid(data, nconns, stack, run, nid, cid) - data[nconns][stack][nid][cid] = fname + data[nconns][stack][run][nid][cid] = fname return data def parse_data(parsed_md): - tp = [] + data = [] out_dir = "./out/" for nconns in parsed_md: data_point = {"nconns": nconns} for stack in parsed_md[nconns]: - if stack == "virt-tas": - c0_fname = out_dir + parsed_md[nconns][stack]["0"]["0"] - c1_fname = out_dir + parsed_md[nconns][stack]["1"]["0"] - else: - c0_fname = out_dir + parsed_md[nconns][stack]["0"]["0"] - c1_fname = out_dir + parsed_md[nconns][stack]["0"]["1"] - - avg_tp = get_avg_tp(c0_fname, c1_fname) - - data_point[stack] = avg_tp + tp_x = np.array([]) + for run in parsed_md[nconns][stack]: + is_virt = stack == "virt-tas" or stack == "ovs-tas" or stack == "ovs-linux" + if is_virt: + c0_fname = out_dir + parsed_md[nconns][stack][run]["0"]["0"] + c1_fname = out_dir + parsed_md[nconns][stack][run]["1"]["0"] + else: + c0_fname = out_dir + parsed_md[nconns][stack][run]["0"]["0"] + c1_fname = out_dir + parsed_md[nconns][stack][run]["0"]["1"] + + tp = get_avg_tp(c0_fname, c1_fname) + if tp > 0: + tp_x = np.append(tp_x, tp) + + data_point[stack] = { + "tp": tp_x.mean(), + "std": tp_x.std(), + } - tp.append(data_point) + data.append(data_point) - tp = sorted(tp, key=lambda d: int(d['nconns'])) - return tp + data = sorted(data, key=lambda d: int(d['nconns'])) + return data -def save_dat_file(avg_tps, fname): +def save_dat_file(data, fname): f = open(fname, "w+") - header = "nconns bare-tas bare-vtas virt-tas\n" + header = "nconns " + \ + "bare-tas-avg bare-vtas-avg virt-tas-avg " + \ + "ovs-linux-avg " + \ + "bare-tas-std bare-vtas-std virt-tas-std " + \ + "ovs-linux-std\n" f.write(header) - for tp in avg_tps: - f.write("{} {} {} {}\n".format( - tp["nconns"], - tp["bare-tas"], - tp["bare-vtas"], - tp["virt-tas"] - )) + for dp in data: + f.write("{} {} {} {} {} {} {} {} {}\n".format( + dp["nconns"], + dp["bare-tas"]["tp"], dp["bare-vtas"]["tp"], dp["virt-tas"]["tp"], + dp["ovs-linux"]["tp"], + dp["bare-tas"]["std"], dp["bare-vtas"]["std"], dp["virt-tas"]["std"], + dp["ovs-linux"]["std"])) def main(): parsed_md = parse_metadata() - avg_tps = parse_data(parsed_md) - save_dat_file(avg_tps, "./tp.dat") + data = parse_data(parsed_md) + save_dat_file(data, "./tp.dat") if __name__ == '__main__': main() \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpconn/perf_iso_tpconn.py b/experiments/exps/perf_iso_tpconn/perf_iso_tpconn.py index 2b140a6a..319040af 100644 --- a/experiments/exps/perf_iso_tpconn/perf_iso_tpconn.py +++ b/experiments/exps/perf_iso_tpconn/perf_iso_tpconn.py @@ -4,21 +4,25 @@ from exps.perf_iso_tpconn.configs.bare_vtas import Config as VTasBareConf from exps.perf_iso_tpconn.configs.virt_tas import Config as TasVirtConf from exps.perf_iso_tpconn.configs.ovs_linux import Config as OVSLinuxConf +from exps.perf_iso_tpconn.configs.ovs_tas import Config as OVSTasConf experiments = [] -# n_conns = [128, 256, 512, 1024, 2048, 4096, 8192] -n_conns = [128] +n_conns = [128, 256, 512, 1024, 2048, 4096, 8192, 16384] +n_runs = 3 -for n in n_conns: - exp_name = "perf-iso-tpconn_conns{}_".format(n) - tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n), name=exp_name) - vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n), name=exp_name) - tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n), name=exp_name) - ovs_linux_exp = exp.Experiment(OVSLinuxConf(exp_name + "ovs-linux", n), name=exp_name) +for n_r in range(n_runs): + for n_c in n_conns: + exp_name = "perf-iso-tpconn-run{}-conns{}_".format(n_r, n_c) + tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n_c), name=exp_name) + vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n_c), name=exp_name) + tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n_c), name=exp_name) + ovs_linux_exp = exp.Experiment(OVSLinuxConf(exp_name + "ovs-linux", n_c), name=exp_name) + ovs_tas_exp = exp.Experiment(OVSTasConf(exp_name + "ovs-tas", n_c), name=exp_name) - # experiments.append(tas_bare_exp) - # experiments.append(vtas_bare_exp) - # experiments.append(tas_virt_exp) - experiments.append(ovs_linux_exp) + experiments.append(tas_bare_exp) + experiments.append(vtas_bare_exp) + experiments.append(tas_virt_exp) + experiments.append(ovs_tas_exp) + experiments.append(ovs_linux_exp) diff --git a/experiments/exps/perf_iso_tpconn/plot.pdf b/experiments/exps/perf_iso_tpconn/plot.pdf deleted file mode 100644 index 9720ac74..00000000 Binary files a/experiments/exps/perf_iso_tpconn/plot.pdf and /dev/null differ diff --git a/experiments/exps/perf_iso_tpconn/plot_script.plt b/experiments/exps/perf_iso_tpconn/plot_script.plt index 3b15fad2..19e6486f 100644 --- a/experiments/exps/perf_iso_tpconn/plot_script.plt +++ b/experiments/exps/perf_iso_tpconn/plot_script.plt @@ -7,11 +7,13 @@ set key left top set logscale x 2 set bmargin 4 -set key left bottom +set key top right set label 1 "Aggressor Client # Connections" at screen 0.5, 0.03 center set label 2 "Victim Client Throughput (Mbps)" at screen 0.01, 0.5 rotate by 90 center -set yrange [0:] -plot 'tp.dat' using 1:2:xtic(1) title 'bare-tas' linetype 2 w lp, \ - 'tp.dat' using 1:3:xtic(1) title 'bare-vtas' linetype 3 w lp, \ - 'tp.dat' using 1:4:xtic(1) title 'virt-tas' linetype 4 w lp, \ +set yrange [0:2000] +plot 'tp.dat' using 1:2:6 with yerrorlines title 'tas' linetype 2 ps 0.7, \ + 'tp.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.7, \ + 'tp.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.7, \ + 'tp.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.7, \ + # 'tp.dat' using 1:6:11 with yerrorlines title 'ovs-tas' linetype 6 ps 0.7, \ diff --git a/experiments/exps/perf_iso_tpmsize/configs/bare_tas.py b/experiments/exps/perf_iso_tpmsize/configs/bare_tas.py new file mode 100644 index 00000000..33275fbc --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/configs/bare_tas.py @@ -0,0 +1,88 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'bare-tas' + self.cnum = 2 + self.cnodenum = 1 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + tas_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.c_machine_config.ip, + n_cores=1) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.c_tas_configs.append(tas_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=3, + msize=64, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=1, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpconn/configs/bare_vtas_off.py b/experiments/exps/perf_iso_tpmsize/configs/bare_vtas.py similarity index 86% rename from experiments/exps/perf_iso_tpconn/configs/bare_vtas_off.py rename to experiments/exps/perf_iso_tpmsize/configs/bare_vtas.py index 7a5618e4..eeb52beb 100644 --- a/experiments/exps/perf_iso_tpconn/configs/bare_vtas_off.py +++ b/experiments/exps/perf_iso_tpmsize/configs/bare_vtas.py @@ -5,7 +5,7 @@ from configs.gen_config import ServerConfig class Config: - def __init__(self, exp_name, nconns): + def __init__(self, exp_name, msize): self.exp_name = exp_name self.defaults = Defaults() @@ -28,18 +28,18 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_bare, ip=self.s_machine_config.ip, - n_cores=12) - tas_config.args = tas_config.args + ' --shm-len=4294967296' + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' self.s_tas_configs.append(tas_config) server0_config = ServerConfig(pane=self.defaults.s_server_pane, idx=0, vmid=0, groupid=0, - port=1234, ncores=8, max_flows=4096, max_bytes=1024, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) server1_config = ServerConfig(pane=self.defaults.s_server_pane, idx=1, vmid=0, groupid=1, - port=1235, ncores=8, max_flows=4096, max_bytes=1024, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, bench_dir=self.defaults.default_obenchmark_dir_bare, tas_dir=self.defaults.default_otas_dir_bare) @@ -66,14 +66,14 @@ def __init__(self, exp_name, nconns): project_dir=self.defaults.default_vtas_dir_bare, ip=self.c_machine_config.ip, n_cores=1) - tas_config.args = tas_config.args + ' --vm-shm-len=4294967296 --bu-max-budget=2100000000 --bu-boost=2 --bu-update-freq=1000000' + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' self.c_tas_configs.append(tas_config) client0_config = ClientConfig(exp_name=exp_name, pane=self.defaults.c_client_pane, idx=0, vmid=0, groupid=0, stack=self.cstack, ip=self.defaults.server_ip, port=1234, ncores=3, - msize=64, mpending=64, nconns=512, + msize=64, mpending=64, nconns=128, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_bare, tas_dir=self.defaults.default_vtas_dir_bare) @@ -81,7 +81,7 @@ def __init__(self, exp_name, nconns): pane=self.defaults.c_client_pane, idx=1, vmid=0, groupid=1, stack=self.cstack, ip=self.defaults.server_ip, port=1235, ncores=3, - msize=64, mpending=64, nconns=nconns, + msize=msize, mpending=64, nconns=128, open_delay=15, max_msgs_conn=0, max_pend_conns=1, bench_dir=self.defaults.default_vbenchmark_dir_bare, tas_dir=self.defaults.default_vtas_dir_bare) diff --git a/experiments/exps/perf_iso_tpmsize/configs/ovs_linux.py b/experiments/exps/perf_iso_tpmsize/configs/ovs_linux.py new file mode 100644 index 00000000..92b0897a --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/configs/ovs_linux.py @@ -0,0 +1,96 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-linux' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=3, + msize=64, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_vbenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpmsize/configs/ovs_tas.py b/experiments/exps/perf_iso_tpmsize/configs/ovs_tas.py new file mode 100644 index 00000000..9a94a730 --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/configs/ovs_tas.py @@ -0,0 +1,114 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'ovs-tas' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + tas0_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm0_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas0_config.args = tas0_config.args + ' --shm-len=8589934592' + + + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + tas1_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_otas_dir_virt, + ip=vm1_config.tas_tap_ip, + n_cores=1, dpdk_extra="00:03.0") + tas1_config.args = tas1_config.args + ' --shm-len=8589934592' + + + self.c_tas_configs.append(tas0_config) + self.c_tas_configs.append(tas1_config) + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=3, + msize=64, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_obenchmark_dir_virt, + tas_dir=self.defaults.default_otas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpmsize/configs/virt_tas.py b/experiments/exps/perf_iso_tpmsize/configs/virt_tas.py new file mode 100644 index 00000000..1f6e939c --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/configs/virt_tas.py @@ -0,0 +1,120 @@ +from configs.gen_config import Defaults +from configs.gen_config import MachineConfig +from configs.gen_config import TasConfig +from configs.gen_config import VMConfig +from configs.gen_config import HostProxyConfig +from configs.gen_config import GuestProxyConfig +from configs.gen_config import ClientConfig +from configs.gen_config import ServerConfig + +class Config: + def __init__(self, exp_name, msize): + self.exp_name = exp_name + self.defaults = Defaults() + + # Server Machine + self.sstack = 'bare-tas' + self.snum = 2 + self.snodenum = 1 + self.s_tas_configs = [] + self.s_vm_configs = [] + self.s_proxyg_configs = [] + self.server_configs = [] + + self.s_machine_config = MachineConfig(ip=self.defaults.server_ip, + interface=self.defaults.server_interface, + stack=self.sstack, + is_remote=True, + is_server=True) + + tas_config = TasConfig(pane=self.defaults.s_tas_pane, + machine_config=self.s_machine_config, + project_dir=self.defaults.default_otas_dir_bare, + ip=self.s_machine_config.ip, + n_cores=14) + tas_config.args = tas_config.args + ' --shm-len=8589934592' + self.s_tas_configs.append(tas_config) + + server0_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=0, vmid=0, + port=1234, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + server1_config = ServerConfig(pane=self.defaults.s_server_pane, + idx=1, vmid=0, + port=1235, ncores=12, max_flows=4096, max_bytes=4096, + bench_dir=self.defaults.default_obenchmark_dir_bare, + tas_dir=self.defaults.default_otas_dir_bare) + self.server_configs.append(server0_config) + self.server_configs.append(server1_config) + + # Client Machine + self.cstack = 'virt-tas' + self.cnum = 1 + self.cnodenum = 2 + self.c_tas_configs = [] + self.c_vm_configs = [] + self.c_proxyg_configs = [] + self.client_configs = [] + + self.c_machine_config = MachineConfig(ip=self.defaults.client_ip, + interface=self.defaults.client_interface, + stack=self.cstack, + is_remote=False, + is_server=False) + + tas_config = TasConfig(pane=self.defaults.c_tas_pane, + machine_config=self.c_machine_config, + project_dir=self.defaults.default_vtas_dir_bare, + ip=self.c_machine_config.ip, + n_cores=1) + tas_config.args = tas_config.args + ' --vm-shm-len=8589934592' + self.c_tas_configs.append(tas_config) + + self.c_proxyh_config = HostProxyConfig(pane=self.defaults.c_proxyh_pane, + machine_config=self.c_machine_config, + comp_dir=self.defaults.default_vtas_dir_bare) + + vm0_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=0) + vm1_config = VMConfig(pane=self.defaults.c_vm_pane, + machine_config=self.c_machine_config, + tas_dir=self.defaults.default_vtas_dir_bare, + tas_dir_virt=self.defaults.default_vtas_dir_virt, + idx=1) + + self.c_vm_configs.append(vm0_config) + self.c_vm_configs.append(vm1_config) + + proxyg0_config = GuestProxyConfig(pane=self.defaults.c_proxyg_pane, + machine_config=self.c_machine_config, + comp_dir=self.defaults.default_vtas_dir_virt) + proxyg1_config = GuestProxyConfig(pane=self.defaults.c_proxyg_pane, + machine_config=self.c_machine_config, + comp_dir=self.defaults.default_vtas_dir_virt) + + self.c_proxyg_configs.append(proxyg0_config) + self.c_proxyg_configs.append(proxyg1_config) + + client0_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=0, stack=self.cstack, + ip=self.defaults.server_ip, port=1234, ncores=3, + msize=64, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_vbenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + client1_config = ClientConfig(exp_name=exp_name, + pane=self.defaults.c_client_pane, + idx=0, vmid=1, stack=self.cstack, + ip=self.defaults.server_ip, port=1235, ncores=3, + msize=msize, mpending=64, nconns=128, + open_delay=15, max_msgs_conn=0, max_pend_conns=1, + bench_dir=self.defaults.default_vbenchmark_dir_virt, + tas_dir=self.defaults.default_vtas_dir_virt) + + self.client_configs.append(client0_config) + self.client_configs.append(client1_config) \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpmsize/parse.py b/experiments/exps/perf_iso_tpmsize/parse.py new file mode 100644 index 00000000..5214b94d --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/parse.py @@ -0,0 +1,127 @@ +import sys +sys.path.append("../../../") + +import os +import numpy as np +import experiments.plot_utils as putils + + +def check_msize(data, msize): + if msize not in data: + data[msize] = {} + +def check_stack(data, msize, stack): + if stack not in data[msize]: + data[msize][stack] = {} + +def check_run(data, msize, stack, run): + if run not in data[msize][stack]: + data[msize][stack][run] = {} + +def check_nid(data, msize, stack, run, nid): + if nid not in data[msize][stack][run]: + data[msize][stack][run][nid] = {} + +def check_cid(data, msize, stack, run, nid, cid): + if cid not in data[msize][stack][run][nid]: + data[msize][stack][run][nid][cid] = "" + +def get_avg_tp(fname_c0, fname_c1): + n_messages = 0 + n = 0 + + f = open(fname_c0) + lines = f.readlines() + + c1_first_ts = putils.get_first_ts(fname_c1) + idx, _ = putils.get_min_idx(fname_c0, c1_first_ts) + + first_line = lines[idx] + last_line = lines[len(lines) - 1] + + n_messages = int(putils.get_n_messages(last_line)) - \ + int(putils.get_n_messages(first_line)) + msize = int(putils.get_msize(fname_c0)) + n = len(lines) - idx + + return (n_messages * msize * 8 / n) / 1000000 + +def parse_metadata(): + dir_path = "./out/" + data = {} + + for f in os.listdir(dir_path): + fname = os.fsdecode(f) + + if "tas_c" == fname: + continue + + run = putils.get_expname_run(fname) + msize = putils.get_expname_msize(fname) + cid = putils.get_client_id(fname) + nid = putils.get_node_id(fname) + stack = putils.get_stack(fname) + + check_msize(data, msize) + check_stack(data, msize, stack) + check_run(data, msize, stack, run) + check_nid(data, msize, stack, run, nid) + check_cid(data, msize, stack, run, nid, cid) + + data[msize][stack][run][nid][cid] = fname + + return data + +def parse_data(parsed_md): + data = [] + out_dir = "./out/" + for msize in parsed_md: + data_point = {"msize": msize} + for stack in parsed_md[msize]: + tp_x = np.array([]) + for run in parsed_md[msize][stack]: + is_virt = stack == "virt-tas" or stack == "ovs-tas" or stack == "ovs-linux" + if is_virt: + c0_fname = out_dir + parsed_md[msize][stack][run]["0"]["0"] + c1_fname = out_dir + parsed_md[msize][stack][run]["1"]["0"] + else: + c0_fname = out_dir + parsed_md[msize][stack][run]["0"]["0"] + c1_fname = out_dir + parsed_md[msize][stack][run]["0"]["1"] + + tp = get_avg_tp(c0_fname, c1_fname) + if tp > 0: + tp_x = np.append(tp_x, tp) + + data_point[stack] = { + "tp": tp_x.mean(), + "std": tp_x.std(), + } + + data.append(data_point) + + data = sorted(data, key=lambda d: int(d['msize'])) + return data + +def save_dat_file(data, fname): + f = open(fname, "w+") + header = "msize " + \ + "bare-tas-avg bare-vtas-avg virt-tas-avg " + \ + "ovs-linux-avg " + \ + "bare-tas-std bare-vtas-std virt-tas-std " + \ + "ovs-linux-std\n" + f.write(header) + for dp in data: + f.write("{} {} {} {} {} {} {} {} {}\n".format( + dp["msize"], + dp["bare-tas"]["tp"], dp["bare-vtas"]["tp"], dp["virt-tas"]["tp"], + dp["ovs-linux"]["tp"], + dp["bare-tas"]["std"], dp["bare-vtas"]["std"], dp["virt-tas"]["std"], + dp["ovs-linux"]["std"])) + +def main(): + parsed_md = parse_metadata() + data = parse_data(parsed_md) + save_dat_file(data, "./tp.dat") + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/experiments/exps/perf_iso_tpmsize/perf_iso_tpmsize.py b/experiments/exps/perf_iso_tpmsize/perf_iso_tpmsize.py new file mode 100644 index 00000000..bf391ba9 --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/perf_iso_tpmsize.py @@ -0,0 +1,28 @@ +import experiments as exp + +from exps.perf_iso_tpmsize.configs.bare_tas import Config as TasBareConf +from exps.perf_iso_tpmsize.configs.bare_vtas import Config as VTasBareConf +from exps.perf_iso_tpmsize.configs.virt_tas import Config as TasVirtConf +from exps.perf_iso_tpmsize.configs.ovs_linux import Config as OVSLinuxConf +from exps.perf_iso_tpmsize.configs.ovs_tas import Config as OVSTasConf + +experiments = [] + +msize = [64, 128, 256, 512, 1024, 2048] +n_runs = 3 + +for n_r in range(n_runs): + for n_m in msize: + exp_name = "perf-iso-tpconn-run{}-msize{}_".format(n_r, n_m) + tas_bare_exp = exp.Experiment(TasBareConf(exp_name + "bare-tas", n_m), name=exp_name) + vtas_bare_exp = exp.Experiment(VTasBareConf(exp_name + "bare-vtas", n_m), name=exp_name) + tas_virt_exp = exp.Experiment(TasVirtConf(exp_name + "virt-tas", n_m), name=exp_name) + ovs_linux_exp = exp.Experiment(OVSLinuxConf(exp_name + "ovs-linux", n_m), name=exp_name) + ovs_tas_exp = exp.Experiment(OVSTasConf(exp_name + "ovs-tas", n_m), name=exp_name) + + # experiments.append(tas_bare_exp) + # experiments.append(vtas_bare_exp) + # experiments.append(tas_virt_exp) + experiments.append(ovs_tas_exp) + # experiments.append(ovs_linux_exp) + diff --git a/experiments/exps/perf_iso_tpmsize/plot_script.plt b/experiments/exps/perf_iso_tpmsize/plot_script.plt new file mode 100644 index 00000000..584b0580 --- /dev/null +++ b/experiments/exps/perf_iso_tpmsize/plot_script.plt @@ -0,0 +1,19 @@ +#!/usr/bin/gnuplot -persist +set terminal pdf +set output "plot.pdf" +set colorsequence podo +set key autotitle columnhead +set key left top +set logscale x 2 +set bmargin 4 + +set key top right +set label 1 "Aggressor Client Message Size" at screen 0.5, 0.03 center +set label 2 "Victim Client Throughput (Mbps)" at screen 0.01, 0.5 rotate by 90 center + +set yrange [0:2000] +plot 'tp.dat' using 1:2:6 with yerrorlines title 'tas' linetype 2 ps 0.7, \ + 'tp.dat' using 1:3:7 with yerrorlines title 'bare-virtuoso' linetype 3 ps 0.7, \ + 'tp.dat' using 1:4:8 with yerrorlines title 'virtuoso' linetype 4 ps 0.7, \ + 'tp.dat' using 1:5:9 with yerrorlines title 'ovs-linux' linetype 5 ps 0.7, \ + # 'tp.dat' using 1:6:11 with yerrorlines title 'ovs-tas' linetype 6 ps 0.7, \ diff --git a/experiments/exps/scalability/configs/tap_tas.py b/experiments/exps/scalability/configs/tap_tas.py index 5a247c5d..b4529c79 100644 --- a/experiments/exps/scalability/configs/tap_tas.py +++ b/experiments/exps/scalability/configs/tap_tas.py @@ -37,7 +37,7 @@ def __init__(self, exp_name, nconns): machine_config=self.s_machine_config, project_dir=self.defaults.default_otas_dir_virt, ip=vm_config.tas_tap_ip, - n_cores=10, dpdk_extra="00:04.0") + n_cores=10, dpdk_extra="00:03.0") self.s_tas_configs.append(tas_config) for j in range(self.snum): @@ -75,7 +75,7 @@ def __init__(self, exp_name, nconns): machine_config=self.c_machine_config, project_dir=self.defaults.default_otas_dir_virt, ip=vm_config.tas_tap_ip, - n_cores=10, dpdk_extra="00:04.0") + n_cores=10, dpdk_extra="00:03.0") self.c_tas_configs.append(tas_config) for j in range(self.cnum): diff --git a/experiments/nodes/node.py b/experiments/nodes/node.py index 57734c4d..72fb704c 100644 --- a/experiments/nodes/node.py +++ b/experiments/nodes/node.py @@ -22,7 +22,7 @@ def tap_up(self, interface, script_dir, multi_queue): cmd = "cd {}".format(script_dir) self.setup_pane.send_keys(cmd) time.sleep(1) - cmd = "sudo bash tap_up.sh {} {}".format(interface, multi_queue) + cmd = "sudo bash tap-up.sh {} {}".format(interface, multi_queue) self.setup_pane.send_keys(cmd) time.sleep(2) @@ -30,7 +30,7 @@ def tap_down(self, interface, script_dir): cmd = "cd {}".format(script_dir) self.cleanup_pane.send_keys(cmd) time.sleep(1) - cmd = "sudo bash tap_down.sh {}".format(interface) + cmd = "sudo bash tap-down.sh {}".format(interface) self.cleanup_pane.send_keys(cmd) time.sleep(2) @@ -40,7 +40,7 @@ def bridge_up(self, ip, interface, script_dir): cmd = "cd {}".format(script_dir) self.setup_pane.send_keys(cmd) time.sleep(1) - cmd = "sudo bash br_up.sh {} {}/24".format(interface, ip) + cmd = "sudo bash br-up.sh {} {}/24".format(interface, ip) self.setup_pane.send_keys(cmd) time.sleep(2) @@ -50,17 +50,23 @@ def bridge_down(self, ip, interface, script_dir): cmd = "cd {}".format(script_dir) self.cleanup_pane.send_keys(cmd) time.sleep(1) - cmd = "sudo bash br_down.sh {} {}/24".format(interface, ip) + cmd = "sudo bash br-down.sh {} {}/24".format(interface, ip) self.cleanup_pane.send_keys(cmd) time.sleep(2) - def start_ovs(self, ovsctl_path): - cmd = "sudo {} start".format(ovsctl_path) + def start_ovs(self, script_dir): + cmd = "cd {}".format(script_dir) self.setup_pane.send_keys(cmd) - time.sleep(2) + time.sleep(1) + cmd = "sudo bash ovs-start.sh" + self.setup_pane.send_keys(cmd) + time.sleep(4) - def stop_ovs(self, ovsctl_path): - cmd = "sudo {} stop".format(ovsctl_path) + def stop_ovs(self, script_dir): + cmd = "cd {}".format(script_dir) + self.cleanup_pane.send_keys(cmd) + time.sleep(1) + cmd = "sudo bash ovs-stop.sh" self.cleanup_pane.send_keys(cmd) time.sleep(2) @@ -70,18 +76,28 @@ def ovsbr_add(self, br_name, ip, interface, script_dir): time.sleep(1) cmd = "sudo bash ovsbr-add.sh {} {} {}".format(br_name, ip, interface) self.setup_pane.send_keys(cmd) - time.sleep(2) + time.sleep(4) def ovsbr_del(self, br_name): cmd = "sudo ovs-vsctl del-br {}".format(br_name) self.cleanup_pane.send_keys(cmd) time.sleep(2) - def ovstap_add(self, br_name, tap_name, script_dir): + def ovsvhost_add(self, br_name, vhost_name, script_dir): + cmd = "cd {}".format(script_dir) + self.setup_pane.send_keys(cmd) + time.sleep(1) + cmd = "sudo bash ovsvhost-add.sh {} {}".format( + br_name, vhost_name) + self.setup_pane.send_keys(cmd) + time.sleep(4) + + def ovstap_add(self, br_name, tap_name, multi_queue, script_dir): cmd = "cd {}".format(script_dir) self.setup_pane.send_keys(cmd) time.sleep(1) - cmd = "sudo bash ovstap-add.sh {} {}".format(br_name, tap_name) + cmd = "sudo bash ovstap-add.sh {} {} {}".format( + br_name, tap_name, multi_queue) self.setup_pane.send_keys(cmd) time.sleep(2) diff --git a/experiments/nodes/ovs_linux/ovslinux.py b/experiments/nodes/ovs_linux/ovslinux.py index 805675f6..afac2d21 100644 --- a/experiments/nodes/ovs_linux/ovslinux.py +++ b/experiments/nodes/ovs_linux/ovslinux.py @@ -1,4 +1,6 @@ import time +import threading + from components.vm import VM from nodes.node import Node @@ -17,7 +19,7 @@ def __init__(self, defaults, machine_config, def setup(self): super().setup() - self.start_ovs(self.defaults.ovs_ctl_path) + self.start_ovs(self.vm_configs[0].manager_dir) self.ovsbr_add("br0", self.machine_config.ip + "/24", self.machine_config.interface, @@ -25,14 +27,14 @@ def setup(self): for vm_config in self.vm_configs: # Tap that allows us to ssh to VM - self.ovstap_add("br0", - "tap{}".format(vm_config.id), - vm_config.manager_dir) + self.ovsvhost_add("br0", + "vhost{}".format(vm_config.id), + vm_config.manager_dir) def cleanup(self): super().cleanup() self.ovsbr_del("br0") - self.stop_ovs(self.defaults.ovs_ctl_path) + self.stop_ovs(self.vm_configs[0].manager_dir) cmd = "sudo ip addr add {} dev {}".format(self.machine_config.ip + "/24", self.machine_config.interface) @@ -43,12 +45,21 @@ def cleanup(self): self.cleanup_pane.send_keys(cmd) time.sleep(1) - for vm_config in self.vm_configs: - self.tap_down("tap{}".format(vm_config.id), vm_config.manager_dir) + for vm in self.vms: + vm.shutdown() + def start_vm(self, vm, vm_config): + vm.start() + vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) + def start_vms(self): + threads = [] for vm_config in self.vm_configs: vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) self.vms.append(vm) - vm.start() - vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) \ No newline at end of file + vm_thread = threading.Thread(target=self.start_vm, args=(vm, vm_config)) + threads.append(vm_thread) + vm_thread.start() + + for t in threads: + t.join() diff --git a/experiments/nodes/ovs_linux/ovslinux_client.py b/experiments/nodes/ovs_linux/ovslinux_client.py index e25bef41..755afdd2 100644 --- a/experiments/nodes/ovs_linux/ovslinux_client.py +++ b/experiments/nodes/ovs_linux/ovslinux_client.py @@ -17,6 +17,9 @@ def __init__(self, config, wmanager): self.cnum = config.cnum self.clients = [] + def cleanup(self): + super().cleanup() + def start_clients(self): for i in range(self.nodenum): vm_config = self.vm_configs[i] diff --git a/experiments/nodes/ovs_tas/ovslinux_client.py b/experiments/nodes/ovs_tas/ovslinux_client.py deleted file mode 100644 index 571bca63..00000000 --- a/experiments/nodes/ovs_tas/ovslinux_client.py +++ /dev/null @@ -1,42 +0,0 @@ -import time - -from nodes.ovs_linux.ovslinux import OvsLinux -from components.client import Client - -class OVSLinuxClient(OvsLinux): - - def __init__(self, config, wmanager): - - OvsLinux.__init__(self, config.defaults, config.c_machine_config, - config.c_vm_configs, wmanager, - config.defaults.c_setup_pane, - config.defaults.c_cleanup_pane) - - self.client_configs = config.client_configs - self.nodenum = config.cnodenum - self.cnum = config.cnum - self.clients = [] - - def start_clients(self): - for i in range(self.nodenum): - vm_config = self.vm_configs[i] - for j in range(self.cnum): - cidx = self.cnum * i + j - client_config = self.client_configs[cidx] - client = Client(self.defaults, - self.machine_config, - client_config, - vm_config, - self.wmanager) - self.clients.append(client) - client.run_virt(False, False) - time.sleep(3) - - def run(self): - self.setup() - self.start_vms() - self.start_clients() - - def save_logs(self, exp_path): - for client in self.clients: - client.save_log_virt(exp_path) diff --git a/experiments/nodes/ovs_tas/ovslinux_server.py b/experiments/nodes/ovs_tas/ovslinux_server.py deleted file mode 100644 index 2ce13fc7..00000000 --- a/experiments/nodes/ovs_tas/ovslinux_server.py +++ /dev/null @@ -1,36 +0,0 @@ -import time - -from nodes.ovs_linux.ovslinux import OvsLinux -from components.server import Server - -class OVSLinuxServer(OvsLinux): - - def __init__(self, config, wmanager): - - OvsLinux.__init__(self, config.defaults, config.s_machine_config, - config.s_vm_configs, wmanager, - config.defaults.s_setup_pane, - config.defaults.s_cleanup_pane) - - self.server_configs = config.server_configs - self.nodenum = config.snodenum - self.snum = config.snum - - def start_servers(self): - for i in range(self.nodenum): - vm_config = self.vm_configs[i] - for j in range(self.snum): - sidx = self.snum * i + j - server_config = self.server_configs[sidx] - server = Server(self.defaults, - self.machine_config, - server_config, - vm_config, - self.wmanager) - server.run_virt(False, False) - time.sleep(3) - - def run(self): - self.setup() - self.start_vms() - self.start_servers() diff --git a/experiments/nodes/ovs_tas/ovstas.py b/experiments/nodes/ovs_tas/ovstas.py index 2d6cb4f3..b7f8d85d 100644 --- a/experiments/nodes/ovs_tas/ovstas.py +++ b/experiments/nodes/ovs_tas/ovstas.py @@ -1,4 +1,5 @@ import time +import threading from components.tas import TAS from components.vm import VM @@ -21,26 +22,21 @@ def __init__(self, defaults, machine_config, tas_configs, def setup(self): super().setup() - self.start_ovs(self.defaults.ovs_ctl_path) + self.start_ovs(self.vm_configs[0].manager_dir) self.ovsbr_add("br0", - self.machine_config.ip + "/24", + self.machine_config.ip + "/24", self.machine_config.interface, self.vm_configs[0].manager_dir) for vm_config in self.vm_configs: - # Tap that allows us to ssh to VM - self.ovstap_add("br0", - "tap{}".format(vm_config.id), - vm_config.manager_dir) - # TAP used by OvS - self.ovstap_add("br0", - "ovstap{}".format(vm_config.id), - vm_config.manager_dir) + self.ovsvhost_add("br0", + "vhost{}".format(vm_config.id), + vm_config.manager_dir) def cleanup(self): super().cleanup() self.ovsbr_del("br0") - self.stop_ovs(self.defaults.ovs_ctl_path) + self.stop_ovs(self.vm_configs[0].manager_dir) cmd = "sudo ip addr add {} dev {}".format(self.machine_config.ip + "/24", self.machine_config.interface) @@ -51,9 +47,8 @@ def cleanup(self): self.cleanup_pane.send_keys(cmd) time.sleep(1) - for vm_config in self.vm_configs: - self.tap_down("tap{}".format(vm_config.id), vm_config.manager_dir) - self.tap_down("ovstap{}".format(vm_config.id), vm_config.manager_dir) + for vm in self.vms: + vm.shutdown() def start_tas(self): for i in range(self.nodenum): @@ -69,14 +64,23 @@ def start_tas(self): tas.run_virt() time.sleep(3) + def start_vm(self, vm, vm_config): + vm.start() + vm.enable_hugepages() + vm.enable_noiommu("1af4 1110") + vm.init_interface(vm_config.vm_ip, self.defaults.tas_interface) + vm.dpdk_bind(vm_config.vm_ip, self.defaults.tas_interface, + self.defaults.pci_id) + def start_vms(self): + threads = [] for vm_config in self.vm_configs: vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) self.vms.append(vm) - vm.start() - vm.enable_hugepages() - vm.enable_noiommu("1af4 1110") - vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) - vm.init_interface(vm_config.tas_tap_ip, self.defaults.tas_interface) - vm.dpdk_bind(vm_config.tas_tap_ip, self.defaults.tas_interface, - self.defaults.pci_id) \ No newline at end of file + vm_thread = threading.Thread(target=self.start_vm, args=(vm, vm_config)) + threads.append(vm_thread) + vm_thread.start() + + for t in threads: + t.join() + \ No newline at end of file diff --git a/experiments/nodes/ovs_tas/ovstas_client.py b/experiments/nodes/ovs_tas/ovstas_client.py index a8e2143f..b9bd0240 100644 --- a/experiments/nodes/ovs_tas/ovstas_client.py +++ b/experiments/nodes/ovs_tas/ovstas_client.py @@ -3,13 +3,13 @@ from nodes.ovs_tas.ovstas import OvsTas from components.client import Client -class OVSLinuxClient(OvsTas): +class OvsTasClient(OvsTas): def __init__(self, config, wmanager): OvsTas.__init__(self, config.defaults, config.c_machine_config, - config.c_vm_configs, wmanager, - config.defaults.c_setup_pane, + config.c_tas_configs, config.c_vm_configs, + wmanager, config.defaults.c_setup_pane, config.defaults.c_cleanup_pane) self.client_configs = config.client_configs @@ -29,7 +29,7 @@ def start_clients(self): vm_config, self.wmanager) self.clients.append(client) - client.run_virt(False, True) + client.run_virt(True, True) time.sleep(3) def run(self): diff --git a/experiments/nodes/ovs_tas/ovstas_server.py b/experiments/nodes/ovs_tas/ovstas_server.py index 8cbe1ac7..87a6cca3 100644 --- a/experiments/nodes/ovs_tas/ovstas_server.py +++ b/experiments/nodes/ovs_tas/ovstas_server.py @@ -8,8 +8,8 @@ class OvsTasServer(OvsTas): def __init__(self, config, wmanager): OvsTas.__init__(self, config.defaults, config.s_machine_config, - config.s_vm_configs, wmanager, - config.defaults.s_setup_pane, + config.s_tas_configs, config.s_vm_configs, + wmanager, config.defaults.s_setup_pane, config.defaults.s_cleanup_pane) self.server_configs = config.server_configs diff --git a/experiments/nodes/tap_tas/ttas.py b/experiments/nodes/tap_tas/ttas.py index 55717f82..a5a325bb 100644 --- a/experiments/nodes/tap_tas/ttas.py +++ b/experiments/nodes/tap_tas/ttas.py @@ -1,4 +1,5 @@ import time +import threading from components.tas import TAS from components.vm import VM @@ -38,6 +39,9 @@ def cleanup(self): self.tap_down("tap{}".format(vm_config.id), vm_config.manager_dir) self.tap_down("tastap{}".format(vm_config.id), vm_config.manager_dir) + for vm in self.vms: + vm.shutdown() + def start_tas(self): for i in range(self.nodenum): tas_config = self.tas_configs[i] @@ -52,14 +56,23 @@ def start_tas(self): tas.run_virt() time.sleep(3) - def start_vms(self): - for vm_config in self.vm_configs: - vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) - self.vms.append(vm) + def start_vm(self, vm, vm_config): vm.start() vm.enable_hugepages() vm.enable_noiommu("1af4 1110") - vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) + vm.init_interface(vm_config.vm_ip, self.defaults.tas_interface) vm.init_interface(vm_config.tas_tap_ip, self.defaults.tas_interface) vm.dpdk_bind(vm_config.tas_tap_ip, self.defaults.tas_interface, - self.defaults.pci_id) \ No newline at end of file + self.defaults.pci_id) + + def start_vms(self): + threads = [] + for vm_config in self.vm_configs: + vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) + self.vms.append(vm) + vm_thread = threading.Thread(target=self.start_vm, args=(vm, vm_config)) + threads.append(vm_thread) + vm_thread.start() + + for t in threads: + t.join() \ No newline at end of file diff --git a/experiments/nodes/virt_linux/vlinux.py b/experiments/nodes/virt_linux/vlinux.py index ff0e86cd..0b78471f 100644 --- a/experiments/nodes/virt_linux/vlinux.py +++ b/experiments/nodes/virt_linux/vlinux.py @@ -1,3 +1,5 @@ +import threading + from components.vm import VM from nodes.node import Node @@ -31,9 +33,21 @@ def cleanup(self): for vm_config in self.vm_configs: self.tap_down("tap{}".format(vm_config.id), vm_config.manager_dir) + for vm in self.vms: + vm.shutdown() + + def start_vm(self, vm, vm_config): + vm.start() + vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) + def start_vms(self): + threads = [] for vm_config in self.vm_configs: vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) self.vms.append(vm) - vm.start() - vm.init_interface(vm_config.vm_ip, self.defaults.vm_interface) \ No newline at end of file + vm_thread = threading.Thread(target=self.start_vm, args=(vm, vm_config)) + threads.append(vm_thread) + vm_thread.start() + + for t in threads: + t.join() \ No newline at end of file diff --git a/experiments/nodes/virt_tas/vtas.py b/experiments/nodes/virt_tas/vtas.py index da99b830..59b09b9a 100644 --- a/experiments/nodes/virt_tas/vtas.py +++ b/experiments/nodes/virt_tas/vtas.py @@ -1,4 +1,5 @@ import time +import threading from components.vm import VM from components.proxy import ProxyGuest @@ -19,12 +20,26 @@ def __init__(self, defaults, machine_config, tas_config, self.proxyg_configs = proxyg_configs self.vms = [] + def start_vm(self, vm): + vm.start() + vm.enable_noiommu("1af4 1110") + + def cleanup(self): + super().cleanup() + for vm in self.vms: + vm.shutdown() + def start_vms(self): + threads = [] for vm_config in self.vm_configs: vm = VM(self.defaults, self.machine_config, vm_config, self.wmanager) self.vms.append(vm) - vm.start() - vm.enable_noiommu("1af4 1110") + vm_thread = threading.Thread(target=self.start_vm, args=(vm,)) + threads.append(vm_thread) + vm_thread.start() + + for t in threads: + t.join() def start_guest_proxies(self): for i in range(len(self.vm_configs)): diff --git a/experiments/plot_utils.py b/experiments/plot_utils.py index d72fdc08..7e875644 100644 --- a/experiments/plot_utils.py +++ b/experiments/plot_utils.py @@ -1,5 +1,80 @@ +import numpy as np import re +def init_latencies(): + latencies = { + "50p": np.array([]), + "90p": np.array([]), + "99p": np.array([]), + "99.9p": np.array([]), + "99.99p": np.array([]) + } + + return latencies + +def append_latencies(latencies, fname_c0): + f = open(fname_c0) + lines = f.readlines() + + # Latencies are already accumulated over all time + # period in the logs + line = lines[len(lines) - 1] + + lat = int(get_50p_lat(line)) + if lat > 0: + latencies["50p"] = np.append(latencies["50p"], lat) + + lat = int(get_90p_lat(line)) + if lat > 0: + latencies["90p"] = np.append(latencies["90p"], lat) + + lat = int(get_99p_lat(line)) + if lat > 0: + latencies["99p"] = np.append(latencies["99p"], lat) + + lat = int(get_99_9p_lat(line)) + if lat > 0: + latencies["99.9p"] = np.append(latencies["99.9p"], lat) + + lat = int(get_99_99p_lat(line)) + if lat > 0: + latencies["99.99p"] = np.append(latencies["99.99p"], lat) + +def get_latency_avg(latencies): + avg_lats = { + "50p": latencies["50p"].mean(), + "90p": latencies["90p"].mean(), + "99p": latencies["99p"].mean(), + "99.9p": latencies["99.9p"].mean(), + "99.99p": latencies["99.99p"].mean() + } + + return avg_lats + +def get_latency_std(latencies): + return { + "50p": latencies["50p"].std(), + "90p": latencies["90p"].std(), + "99p": latencies["99p"].std(), + "99.9p": latencies["99.9p"].std(), + "99.99p": latencies["99.99p"].std() + } + +def get_expname_msize(fname): + regex = "(?<=-msize)[0-9]*" + msize = re.search(regex, fname).group(0) + return msize + +def get_expname_run(fname): + run_id_regex = "(?<=-run)[0-9]*" + run_id = re.search(run_id_regex, fname).group(0) + return run_id + +def get_expname_conns(fname): + regex = "(?<=-conns)[0-9]*" + nconns = re.search(regex, fname).group(0) + return nconns + def get_stack(line): stack_regex = "(?<=_)([a-z]+-[a-z]+)(?=_)" stack = re.search(stack_regex, line).group(0) diff --git a/experiments/run.py b/experiments/run.py index f28b449d..8cc8e279 100644 --- a/experiments/run.py +++ b/experiments/run.py @@ -29,7 +29,6 @@ for path in args.experiments: modname, _ = os.path.splitext(os.path.basename(path)) - print(modname) spec = importlib.util.spec_from_file_location(modname, path) mod = importlib.util.module_from_spec(spec) spec.loader.exec_module(mod) @@ -53,8 +52,6 @@ continue print('******' + e.get_name() + '********') e.run() - print(e.get_name()) - time.sleep(80) + time.sleep(120) e.save_logs() - time.sleep(3) e.reset() \ No newline at end of file diff --git a/experiments/run_perf_iso.sh b/experiments/run_perf_iso.sh index 34334e16..8686af5c 100644 --- a/experiments/run_perf_iso.sh +++ b/experiments/run_perf_iso.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash python run.py exps/perf_iso_tpconn/perf_iso_tpconn.py +python run.py exps/perf_iso_tpmsize/perf_iso_tpmsize.py python run.py exps/perf_iso_latconn/perf_iso_latconn.py python run.py exps/perf_iso_latmsize/perf_iso_latmsize.py diff --git a/experiments/utils.py b/experiments/utils.py index 7c9a035a..58a95669 100644 --- a/experiments/utils.py +++ b/experiments/utils.py @@ -2,7 +2,7 @@ def get_ssh_command(machine_config, vm_config): stack = machine_config.stack - if stack == "virt-tas": + if stack == "virt-tas" or stack == "ovs-tas" or stack == "ovs-linux": ssh_com = "ssh -p 222{} tas@localhost".format(vm_config.id) else: ssh_com = "ssh tas@{}".format(vm_config.vm_ip) @@ -12,25 +12,35 @@ def get_ssh_command(machine_config, vm_config): def get_scp_command(machine_config, vm_config, src_path, save_path): ip = vm_config.vm_ip idx = vm_config.id - if machine_config.stack == "virt-tas": + stack = machine_config.stack + if stack == "virt-tas" or stack == "ovs-tas" or stack == "ovs-linux": ssh_com = "scp -P 222{} tas@localhost:{} {}".format(idx, src_path, save_path) else: ssh_com = "scp tas@{}:{} {}".format(ip, src_path, save_path) return ssh_com -def compile_and_run(pane, comp_dir, comp_cmd, +def compile_and_run(pane, comp_dir, comp_cmd, clean_cmd, exec_file, args, out, - bg=False, gdb=False, + bg=False, gdb=False, + valgrind=False, clean=False, break_file=None, line_break=None, save_log=False): pane.send_keys('cd ' + comp_dir) pane.send_keys('git pull') time.sleep(1) + + if clean: + pane.send_keys(clean_cmd) + time.sleep(1) + pane.send_keys(comp_cmd) + time.sleep(3) if gdb: cmd = 'sudo gdb --args ' + exec_file + ' ' + args + elif valgrind: + cmd = 'sudo valgrind --leak-check=yes ' + exec_file + ' ' + args else: cmd = 'sudo ' + exec_file + ' ' + args diff --git a/images/br_down.sh b/images/br-down.sh similarity index 100% rename from images/br_down.sh rename to images/br-down.sh diff --git a/images/br_up.sh b/images/br-up.sh similarity index 100% rename from images/br_up.sh rename to images/br-up.sh diff --git a/images/dpdk_bind.sh b/images/dpdk-bind.sh similarity index 90% rename from images/dpdk_bind.sh rename to images/dpdk-bind.sh index 312c6352..2b23ae4d 100644 --- a/images/dpdk_bind.sh +++ b/images/dpdk-bind.sh @@ -24,5 +24,5 @@ sudo ip link set $interface down # Bind vnic to dpdk sudo modprobe vfio-pci -cd /home/tas/programs/dpdk-stable-19.11.14/usertools +cd /home/tas/programs/dpdk-stable-21.11.3/usertools sudo python3 dpdk-devbind.py -b vfio-pci $pci_id diff --git a/images/ovs-start.sh b/images/ovs-start.sh new file mode 100644 index 00000000..1a33e90b --- /dev/null +++ b/images/ovs-start.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# Start database server +export DB_SOCK=/usr/local/var/run/openvswitch/db.sock +echo "Creating conf.db and ovsschema" +ovsdb-tool create /usr/local/etc/openvswitch/conf.db /usr/local/share/openvswitch/vswitch.ovsschema +echo "Starting serverver at ${DB_SOCK}" +ovsdb-server --remote=punix:${DB_SOCK} --remote=db:Open_vSwitch,Open_vSwitch,manager_options --pidfile --detach + +# Start OVS +echo "Starting OVS" +ovs-vsctl --no-wait init +ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-lcore-mask=0xf +ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem=1024 +ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true + +ovs-vswitchd unix:${DB_SOCK} --pidfile --detach --log-file=/usr/local/var/log/openvswitch/ovs-vswitchd.log \ No newline at end of file diff --git a/images/ovs-stop.sh b/images/ovs-stop.sh new file mode 100644 index 00000000..cc057d37 --- /dev/null +++ b/images/ovs-stop.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +killall ovsdb-server ovs-vswitchd +rm -f /var/run/openvswitch/vhost-user* +rm -f /usr/local/etc/openvswitch/conf.db \ No newline at end of file diff --git a/images/ovsbr-add.sh b/images/ovsbr-add.sh index d3d92248..9fae4fb5 100644 --- a/images/ovsbr-add.sh +++ b/images/ovsbr-add.sh @@ -13,6 +13,7 @@ interface=$3 # Create bridge using OvS ovs-vsctl add-br $br_name + ovs-vsctl add-port $br_name $interface # Delete ip config from interface so that it can be added to bridge diff --git a/images/ovstap-add.sh b/images/ovstap-add.sh index 4212b36a..e8a62836 100644 --- a/images/ovstap-add.sh +++ b/images/ovstap-add.sh @@ -1,16 +1,23 @@ #!/usr/bin/env bash -if [ "$#" -ne 2 ]; then +if [ "$#" -ne 3 ]; then echo "Illegal number of parameters" echo "usage:" - echo "[br_name tap_name]" + echo "[br_name tap_name multi_queue]" exit fi br_name=$1 tap_name=$2 +multi_queue=$3 + +if [ $multi_queue -eq 1 ]; then + sudo ip tuntap add mode tap multi_queue name $tap_name + echo "Set ${tap_name} for multi queue" +else + ip tuntap add mode tap $tap_name +fi -ip tuntap add mode tap $tap_name ifconfig $tap_name up ovs-vsctl add-port $br_name $tap_name \ No newline at end of file diff --git a/images/ovsvhost-add.sh b/images/ovsvhost-add.sh new file mode 100644 index 00000000..518997b7 --- /dev/null +++ b/images/ovsvhost-add.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +if [ "$#" -ne 2 ]; then + echo "Illegal number of parameters" + echo "usage:" + echo "[br_name vhost_name]" + exit +fi + +br_name=$1 +vhost_name=$2 + +echo "Set bridge datapath type to netdev" +ovs-vsctl set bridge ${br_name} datapath_type=netdev + +echo "Adding interface ${vhost_name} to port" +ovs-vsctl add-port ${br_name} ${vhost_name} -- set Interface ${vhost_name} type=dpdkvhostuser + diff --git a/images/start-vm.sh b/images/start-vm.sh index 3689a652..583742ff 100755 --- a/images/start-vm.sh +++ b/images/start-vm.sh @@ -4,6 +4,7 @@ set -ex stack=$1 vm_id=$2 +interface=$3 stty intr ^] stty susp ^] @@ -17,6 +18,7 @@ disk_img_snapshot="base.snapshot.qcow2" tap=tap$vm_id tastap=tastap$vm_id ovstap=ovstap$vm_id +vhost=vhost$vm_id printf -v mac '02:00:00:%02X:%02X:%02X' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) printf -v alt_mac '02:00:00:%02X:%02X:%02X' $((RANDOM%256)) $((RANDOM%256)) $((RANDOM%256)) @@ -24,13 +26,15 @@ printf -v alt_mac '02:00:00:%02X:%02X:%02X' $((RANDOM%256)) $((RANDOM%256)) $((R echo $mac echo $alt_mac +# Note: vectors=<2 + 2 * queues_nr> + if [[ "$stack" == 'virt-tas' ]]; then sudo qemu-system-x86_64 \ -nographic -monitor none -serial stdio \ -machine accel=kvm,type=q35 \ -cpu host \ -smp 12 \ - -m 12G \ + -m 25G \ -snapshot \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net0,hostfwd=tcp::222${vm_id}-:22 \ @@ -45,7 +49,7 @@ elif [[ "$stack" == 'virt-linux' ]]; then -machine accel=kvm,type=q35 \ -cpu host \ -smp 12 \ - -m 12G \ + -m 25G \ -snapshot \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ @@ -60,12 +64,33 @@ elif [[ "$stack" == 'ovs-linux' ]]; then -machine accel=kvm,type=q35 \ -cpu host \ -smp 12 \ - -m 12G \ + -m 25G \ -snapshot \ - -netdev user,id=net0 \ + -netdev user,id=net0,hostfwd=tcp::222${vm_id}-:22 \ -device virtio-net-pci,netdev=net0 \ - -netdev tap,ifname=$tap,script=no,downscript=no,vhost=on,id=net1 \ - -device virtio-net-pci,mac=$mac,netdev=net1 \ + -chardev socket,id=char0,path=/usr/local/var/run/openvswitch/$vhost \ + -netdev type=vhost-user,chardev=char0,vhostforce=on,queues=12,id=net1 \ + -device virtio-net-pci,netdev=net1,mac=$alt_mac,mq=on,vectors=26 \ + -object memory-backend-file,id=mem,size=25G,mem-path=/dev/hugepages,share=on \ + -numa node,memdev=mem -mem-prealloc \ + -drive if=virtio,format=qcow2,file="base.snapshot.qcow2" \ + -drive if=virtio,format=raw,file="seed.img" \ + ; +elif [[ "$stack" == 'ovs-tas' ]]; then + sudo qemu-system-x86_64 \ + -nographic -monitor none -serial stdio \ + -machine accel=kvm,type=q35 \ + -cpu host \ + -smp 12 \ + -m 25G \ + -snapshot \ + -netdev user,id=net0,hostfwd=tcp::222${vm_id}-:22 \ + -device virtio-net-pci,netdev=net0 \ + -chardev socket,id=char0,path=/usr/local/var/run/openvswitch/$vhost \ + -netdev type=vhost-user,chardev=char0,vhostforce=on,queues=12,id=net1 \ + -device virtio-net-pci,netdev=net1,mac=$alt_mac,mq=on,vectors=26 \ + -object memory-backend-file,id=mem,size=25G,mem-path=/dev/hugepages,share=on \ + -numa node,memdev=mem -mem-prealloc \ -drive if=virtio,format=qcow2,file="base.snapshot.qcow2" \ -drive if=virtio,format=raw,file="seed.img" \ ; @@ -75,7 +100,7 @@ elif [[ "$stack" == 'tap-tas' ]]; then -machine accel=kvm,type=q35 \ -cpu host \ -smp 12 \ - -m 12G \ + -m 25G \ -snapshot \ -netdev user,id=net0 \ -device virtio-net-pci,netdev=net0 \ diff --git a/images/tap_down.sh b/images/tap-down.sh similarity index 100% rename from images/tap_down.sh rename to images/tap-down.sh diff --git a/images/tap_up.sh b/images/tap-up.sh similarity index 100% rename from images/tap_up.sh rename to images/tap-up.sh diff --git a/lib/sockets/context.c b/lib/sockets/context.c index 651cd494..94e0587d 100644 --- a/lib/sockets/context.c +++ b/lib/sockets/context.c @@ -192,20 +192,6 @@ static inline void ev_listen_open(struct flextcp_context *ctx, static inline void ev_listen_newconn(struct flextcp_context *ctx, struct flextcp_event *ev) { - struct flextcp_listener *l; - struct socket *s; - - l = ev->ev.listen_newconn.listener; - s = (struct socket *) - ((uint8_t *) l - offsetof(struct socket, data.listener.l)); - - socket_lock(s); - - assert(s->type == SOCK_LISTENER); - - flextcp_epoll_set(s, EPOLLIN); - - socket_unlock(s); } static inline void ev_listen_accept(struct flextcp_context *ctx, @@ -218,13 +204,13 @@ static inline void ev_listen_accept(struct flextcp_context *ctx, s = (struct socket *) ((uint8_t *) c - offsetof(struct socket, data.connection.c)); - socket_lock(s); - assert(s->type == SOCK_CONNECTION); - assert(s->data.connection.status == SOC_CONNECTING); sl = s->data.connection.listener; assert(sl != NULL); + socket_lock(sl); + socket_lock(s); + assert(s->data.connection.status == SOC_CONNECTING); flextcp_epoll_set(sl, EPOLLIN); if (ev->ev.listen_accept.status == 0) { @@ -236,6 +222,7 @@ static inline void ev_listen_accept(struct flextcp_context *ctx, } socket_unlock(s); + socket_unlock(sl); } static inline void ev_conn_open(struct flextcp_context *ctx, diff --git a/lib/sockets/control.c b/lib/sockets/control.c index 8f6f4635..e971eedd 100644 --- a/lib/sockets/control.c +++ b/lib/sockets/control.c @@ -364,11 +364,60 @@ int tas_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) return ret; } +/** Enqueue accept requests for backlog. Lock on s has to be held. */ +static int enqueue_accept(struct flextcp_context *ctx, struct socket *s) +{ + int newfd; + struct socket *ns; + struct socket_listen *l = &s->data.listener; + struct socket_backlog *bl; + + /* try to fill backlog */ + while (l->backlog_num != l->backlog_len) { + /* allocate socket structure */ + if ((newfd = flextcp_fd_salloc(&ns)) < 0) { + break; + } + + ns->type = SOCK_CONNECTION; + ns->flags = 0; + ns->data.connection.status = SOC_CONNECTING; + ns->data.connection.listener = s; + ns->data.connection.rx_len_1 = 0; + ns->data.connection.rx_len_2 = 0; + ns->data.connection.ctx = ctx; + + bl = l->backlog + ((l->backlog_next + l->backlog_num) % l->backlog_len); + bl->s = ns; + bl->fd = newfd; + + /* send accept request to kernel */ + if (flextcp_listen_accept(ctx, &l->l, &ns->data.connection.c) != 0) + { + /* TODO: check error code... */ + flextcp_fd_close(newfd); + break; + } + + socket_unlock(ns); + l->backlog_num = l->backlog_num + 1; + } + + if (l->backlog_num == 0) { + errno = ENOBUFS; + return -1; + } + + return 0; +} + int tas_listen(int sockfd, int backlog) { struct socket *s; + struct socket_backlog *bl; + struct socket_listen *l; struct flextcp_context *ctx; - int ret = 0, block; + int block; uint32_t flags = 0; if (flextcp_fd_slookup(sockfd, &s) != 0) { @@ -379,16 +428,14 @@ int tas_listen(int sockfd, int backlog) /* socket already used */ if (s->type != SOCK_SOCKET) { errno = EOPNOTSUPP; - ret = -1; - goto out; + goto err; } /* socket not bound */ /* TODO: technically sohuld probably bind to an ephemeral port */ if ((s->flags & SOF_BOUND) != SOF_BOUND) { errno = EADDRINUSE; - ret = -1; - goto out; + goto err; } /* pass on reuseport flags */ @@ -401,21 +448,28 @@ int tas_listen(int sockfd, int backlog) backlog = 8; } + if ((bl = calloc(backlog, sizeof(*bl))) == NULL) { + errno = ENOMEM; + goto err; + } + /* open flextcp listener */ ctx = flextcp_sockctx_get(); if (flextcp_listen_open(ctx, &s->data.listener.l, ntohs(s->addr.sin_port), backlog, flags)) { - /* TODO */ + free (bl); errno = ECONNREFUSED; - ret = -1; - goto out; + goto err_bl; } s->type = SOCK_LISTENER; - s->data.listener.backlog = backlog; - s->data.listener.status = SOL_OPENING; - s->data.listener.pending = NULL; + l = &s->data.listener; + l->backlog = bl; + l->backlog_len = backlog; + l->backlog_next = 0; + l->backlog_num = 0; + l->status = SOL_OPENING; /* wait for listen to complete */ block = 0; @@ -430,29 +484,41 @@ int tas_listen(int sockfd, int backlog) /* check whether listen failed */ if (s->data.listener.status == SOL_FAILED) { - /* TODO */ errno = ENOBUFS; - ret = -1; - goto out; + goto err_bl; + } + + /* enqueue accepts */ + if (enqueue_accept(ctx, s)) { + goto err_close; } -out: flextcp_fd_srelease(sockfd, s); - return ret; + return 0; + +err_close: + /* TODO: close listener */ +err_bl: + free(bl); +err: + flextcp_fd_srelease(sockfd, s); + return -1; } int tas_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { struct socket *s, *ns; + struct socket_listen *sl; struct flextcp_context *ctx; - struct socket_pending *sp, *spp; + struct socket_backlog *bl; int ret = 0, nonblock = 0, cloexec = 0, newfd, block; if (flextcp_fd_slookup(sockfd, &s) != 0) { errno = EBADF; return -1; } + sl = &s->data.listener; /* validate flags */ if ((flags & SOCK_NONBLOCK) == SOCK_NONBLOCK) { @@ -477,112 +543,72 @@ int tas_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, } ctx = flextcp_sockctx_get(); - - /* lookup pending connection for this context/thread */ - for (sp = s->data.listener.pending; sp != NULL; sp = sp->next) { - if (sp->ctx == ctx) { - break; - } - } - - /* if there is no pending request, send out a request */ - if (sp == NULL) { - if ((sp = malloc(sizeof(*sp))) == NULL) { - errno = ENOMEM; - ret = -1; - goto out; - } - - /* allocate socket structure */ - if ((newfd = flextcp_fd_salloc(&ns)) < 0) { - free(sp); - ret = -1; - goto out; - } - - ns->type = SOCK_CONNECTION; - ns->flags = (nonblock ? SOF_NONBLOCK : 0) | (cloexec ? SOF_CLOEXEC : 0); - ns->data.connection.status = SOC_CONNECTING; - ns->data.connection.listener = s; - ns->data.connection.rx_len_1 = 0; - ns->data.connection.rx_len_2 = 0; - ns->data.connection.ctx = ctx; - - sp->fd = newfd; - sp->s = ns; - sp->ctx = ctx; - sp->next = NULL; - - /* send accept request to kernel */ - if (flextcp_listen_accept(ctx, &s->data.listener.l, - &ns->data.connection.c) != 0) - { - /* TODO */ + block = 0; + while (1) { + /* grab next pending accept */ + if (sl->backlog_num == 0 && enqueue_accept(ctx, s)) { errno = ENOBUFS; ret = -1; - free(sp); - flextcp_fd_close(newfd); - free(s); goto out; } + bl = sl->backlog + sl->backlog_next; + ns = bl->s; + newfd = bl->fd; - /* append entry to pending list */ - spp = s->data.listener.pending; - if (spp == NULL) { - s->data.listener.pending = sp; + socket_lock(ns); + if (ns->data.connection.status != SOC_CONNECTING) { + /* connection is ready */ + break; } else { - while (spp->next != NULL) { - spp = spp->next; - } - spp->next = sp; - } - } else { - ns = sp->s; - newfd = sp->fd; - } + /* connection is still pending */ + socket_unlock(ns); - /* check if connection is still pending */ - if (ns->data.connection.status == SOC_CONNECTING) { - flextcp_epoll_clear(s, EPOLLIN); - if ((s->flags & SOF_NONBLOCK) == SOF_NONBLOCK) { - /* if non-blocking, just return */ - errno = EAGAIN; - ret = -1; - flextcp_fd_srelease(newfd, ns); - goto out; - } else { - /* if this is blocking, wait for connection to complete */ - block = 0; - do { - socket_unlock(ns); + if ((s->flags & SOF_NONBLOCK) == SOF_NONBLOCK) { + /* if non-blocking, just return */ + errno = EAGAIN; + ret = -1; + goto out; + } else { + /* if this is blocking, wait for a connection to complete */ socket_unlock(s); + if (block) flextcp_context_wait(ctx, -1); flextcp_sockctx_poll(ctx); block = 1; + socket_lock(s); - socket_lock(ns); - } while (ns->data.connection.status == SOC_CONNECTING); + } } } /* connection is opened now */ assert(ns->data.connection.status == SOC_CONNECTED); - /* remove entry from pending list */ - if (s->data.listener.pending == sp) { - s->data.listener.pending = sp->next; + if (cloexec) + ns->flags |= SOF_CLOEXEC; + if (nonblock) + ns->flags |= SOF_NONBLOCK; + + /* remove this connection from backlog now */ + sl->backlog_next = (sl->backlog_next + 1) % sl->backlog_len; + --sl->backlog_num; + + flextcp_fd_srelease(newfd, ns); + + /* refill backlog */ + enqueue_accept(ctx, s); + + /* clear epollin on listening socket if no more connections */ + if (!sl->backlog_num) { + flextcp_epoll_clear(s, EPOLLIN); } else { - spp = s->data.listener.pending; - assert(spp != NULL); - while (spp->next != sp) { - assert(spp->next != NULL); - spp = spp->next; - } - spp->next = sp->next; + struct socket *next = sl->backlog[sl->backlog_next].s; + socket_lock(next); + if (next->data.connection.status == SOC_CONNECTING) + flextcp_epoll_clear(s, EPOLLIN); + socket_unlock(next); } - free(sp); - flextcp_fd_srelease(newfd, ns); // fill in addr if given if(addr != NULL) { @@ -749,6 +775,15 @@ int tas_getsockopt(int sockfd, int level, int optname, void *optval, errno = ENOPROTOOPT; ret = -1; goto out; + } else if (level == SOL_TCP && optname == TCP_MAXSEG) { + fprintf(stderr, "flextcp getsockopt: warning TCP_MAXSEG hardcoded\n"); + res = 1460; + } else if (level == SOL_TCP && optname == TCP_INFO) { + fprintf(stderr, "flextcp getsockopt: warning TCP_INFO hardcoded\n"); + len = MIN(*optlen, sizeof(struct tcp_info)); + memset(optval, 0, len); + *optlen = len; + goto out; } else { /* unknown option */ fprintf(stderr, "flextcp getsockopt: unknown level optname combination " @@ -825,13 +860,11 @@ int tas_setsockopt(int sockfd, int level, int optname, const void *optval, } else if (level == SOL_SOCKET && optname == SO_PRIORITY) { /* ignore silently */ } else if (level == IPPROTO_TCP && (optname == TCP_KEEPIDLE || - optname == TCP_KEEPINTVL || optname == TCP_KEEPCNT)) { + optname == TCP_KEEPINTVL || optname == TCP_KEEPCNT || + optname == TCP_DEFER_ACCEPT)) { /* ignore silently */ } else if (level == SOL_SOCKET && optname == SO_LINGER) { - fprintf(stderr, "flextcp setsockopt: SO_LINGER not implemented\n"); - errno = ENOPROTOOPT; - ret = -1; - goto out; + fprintf(stderr, "flextcp setsockopt: warning SO_LINGER not implemented\n"); } else { /* unknown option */ fprintf(stderr, "flextcp setsockopt: unknown level optname combination " diff --git a/lib/sockets/internal.h b/lib/sockets/internal.h index 6dffd380..431996c5 100644 --- a/lib/sockets/internal.h +++ b/lib/sockets/internal.h @@ -70,13 +70,6 @@ enum conn_stflags { CSTF_TXCLOSED_ACK = 4, }; -struct socket_pending { - struct socket *s; - struct flextcp_context *ctx; - struct socket_pending *next; - int fd; -}; - struct socket_conn { struct flextcp_connection c; uint8_t status; @@ -91,10 +84,17 @@ struct socket_conn { int move_status; }; +struct socket_backlog { + struct socket *s; + int fd; +}; + struct socket_listen { struct flextcp_listener l; - struct socket_pending *pending; - int backlog; + struct socket_backlog *backlog; + int backlog_len; + int backlog_next; + int backlog_num; uint8_t status; }; diff --git a/proxy/channel.c b/proxy/channel.c index d78b400e..34da6166 100644 --- a/proxy/channel.c +++ b/proxy/channel.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "channel.h" #include "shmring.h" @@ -18,8 +19,6 @@ struct channel * channel_init(void* tx_addr, void* rx_addr, uint64_t size) goto free_chan; } - /* Only init the tx channel, since the other side will - already have initialized the rx channel */ tx_buf = shmring_init(tx_addr, CHAN_SIZE); if (tx_buf == NULL) { @@ -34,10 +33,6 @@ struct channel * channel_init(void* tx_addr, void* rx_addr, uint64_t size) goto free_tx_buf; } - /* Only reset tx_ring since other side will have already - reset the rx_ring */ - shmring_reset(tx_buf, CHAN_SIZE); - chan->tx = tx_buf; chan->rx = rx_buf; return chan; @@ -53,18 +48,18 @@ struct channel * channel_init(void* tx_addr, void* rx_addr, uint64_t size) size_t channel_write(struct channel *chan, void *buf, size_t size) { - size_t free_sz; - size_t ret; + size_t ret, free_sz; - /* If channel is full try again until - a read clears enough space */ do { shmring_lock(chan->tx); free_sz = shmring_get_freesz(chan->tx); - - if (free_sz >= size) + if (free_sz >= size) + { ret = shmring_push(chan->tx, buf, size); - + assert(ret == size || ret == 0); + shmring_unlock(chan->tx); + break; + } shmring_unlock(chan->tx); } while(free_sz < size); diff --git a/proxy/guest/flextcp.c b/proxy/guest/flextcp.c index 157ef943..8918ca58 100644 --- a/proxy/guest/flextcp.c +++ b/proxy/guest/flextcp.c @@ -332,14 +332,14 @@ static int vflextcp_uxsocket_accept(struct guest_proxy *pxy) req_msg.msg_type = MSG_TYPE_NEWAPP_REQ; req_msg.cfd = cfd; ret = channel_write(pxy->chan, &req_msg, sizeof(req_msg)); + printf("MSG_TYPE_NEWAPP_REQ\n"); if (ret != sizeof(req_msg)) { fprintf(stderr, "vflextcp_uxsocket_accept: " "failed to write req_msg to chan.\n"); return -1; } - /* Notify host and retrieve response from channel to continue - registration */ + /* Notify host */ ivshmem_notify_host(pxy); return 0; @@ -500,6 +500,7 @@ static int vflextcp_uxsocket_handle_msg(struct guest_proxy *pxy, msg.actx_evfd = ctx_req->actx_evfd; ret = channel_write(pxy->chan, &msg, sizeof(struct context_req_msg)); + printf("MSG_TYPE_CONTEXT_REQ\n"); if (ret < sizeof(struct context_req_msg)) { fprintf(stderr, "vflextcp_uxsocket_handle_msg: " @@ -519,9 +520,9 @@ static int vflextcp_uxsocket_handle_msg(struct guest_proxy *pxy, static int vflextcp_tas_poke_poll(struct guest_proxy *pxy) { int n, i; struct poke_event *poke_ev; - struct epoll_event evs[32]; + struct epoll_event evs[2]; - n = epoll_wait(pxy->epfd, evs, 32, 0); + n = epoll_wait(pxy->epfd, evs, 2, 0); if (n < 0) { perror("vflextcp_tas_poke_poll: epoll_wait"); @@ -553,6 +554,7 @@ static int vflextcp_handle_tas_kernel_poke(struct guest_proxy *pxy, ivshmem_drain_evfd(pxy->kernel_notifyfd); ret = channel_write(pxy->chan, msg, sizeof(struct poke_tas_kernel_msg)); + printf("MSG_TYPE_POKE_TAS_KERNEL\n"); if (ret != sizeof(struct poke_tas_kernel_msg)) { @@ -572,6 +574,7 @@ static int vflextcp_handle_tas_core_poke(struct guest_proxy *pxy, ivshmem_drain_evfd(pxy->core_evfds[msg->core_id]); ret = channel_write(pxy->chan, msg, sizeof(struct poke_tas_core_msg)); + printf("MSG_TYPE_POKE_TAS_CORE\n"); if (ret != sizeof(struct poke_tas_core_msg)) { diff --git a/proxy/guest/ivshmem.c b/proxy/guest/ivshmem.c index 6a8404c9..ed57765b 100644 --- a/proxy/guest/ivshmem.c +++ b/proxy/guest/ivshmem.c @@ -85,9 +85,12 @@ int ivshmem_channel_poll(struct guest_proxy *pxy) size_t msg_size; /* Return if there are no messages in channel */ + MEM_BARRIER(); shmring_lock(pxy->chan->rx); is_empty = shmring_is_empty(pxy->chan->rx); shmring_unlock(pxy->chan->rx); + + MEM_BARRIER(); if (is_empty) { return 0; @@ -107,25 +110,30 @@ int ivshmem_channel_poll(struct guest_proxy *pxy) switch(msg_type) { case MSG_TYPE_HELLO: + printf("MSG_TYPE_HELLO\n"); channel_handle_hello(pxy); break; case MSG_TYPE_TASINFO_RES: + printf("MSG_TYPE_TASINFO_RES\n"); channel_handle_tasinfo_res(pxy, (struct tasinfo_res_msg *) msg); break; case MSG_TYPE_NEWAPP_RES: + printf("MSG_TYPE_NEWAPP_RES\n"); channel_handle_newapp_res(pxy, (struct newapp_res_msg *) msg); break; case MSG_TYPE_CONTEXT_RES: + printf("MSG_TYPE_CONTEXT_RES\n"); channel_handle_ctx_res(pxy, (struct context_res_msg *) msg); break; case MSG_TYPE_POKE_APP_CTX: + printf("MSG_TYPE_POKE_APP_CTX\n"); channel_handle_vpoke(pxy, (struct poke_app_ctx_msg *) msg); break; default: fprintf(stderr, "ivshmem_channel_poll: unknown message.\n"); } - return 0; + return 1; } static int channel_handle_hello(struct guest_proxy *pxy) @@ -136,6 +144,7 @@ static int channel_handle_hello(struct guest_proxy *pxy) /* Send tasinfo request and wait for the response in the channel poll */ treq_msg.msg_type = MSG_TYPE_TASINFO_REQ; ret = channel_write(pxy->chan, &treq_msg, sizeof(struct tasinfo_req_msg)); + printf("MSG_TYPE_TASINFO_REQ\n"); if (ret != sizeof(struct tasinfo_req_msg)) { fprintf(stderr, "channel_handle_hello: failed to write tasinfo req msg.\n"); diff --git a/proxy/host/ivshmem.c b/proxy/host/ivshmem.c index db506c04..2806f0de 100644 --- a/proxy/host/ivshmem.c +++ b/proxy/host/ivshmem.c @@ -42,7 +42,7 @@ static int uxsocket_handle_error(); static int uxsocket_send_int(int fd, int64_t i); static int uxsocket_sendfd(int uxfd, int fd, int64_t i); -static int ctxs_poll(); +static int app_ctxs_poll(); static int channel_poll(); static int channel_poll_vm(struct v_machine *vm); @@ -130,7 +130,7 @@ int ivshmem_poll() return -1; } - if (ctxs_poll() != 0) + if (app_ctxs_poll() != 0) { fprintf(stderr, "ivshmem_poll: failed to poll ctxs fds.\n"); return -1; @@ -370,11 +370,18 @@ static int uxsocket_accept() goto close_ifd; } + shmring_reset(chan->tx, CHAN_SIZE); + shmring_reset(chan->rx, CHAN_SIZE); + + shmring_init_mux(chan->tx); + shmring_init_mux(chan->rx); + /* Write number of cores to channel for guest proxy to receive */ h_msg.msg_type = MSG_TYPE_HELLO; h_msg.n_cores = flexnic_info_pxy->cores_num; ret = channel_write(chan, &h_msg, sizeof(struct hello_msg)); + printf("MSG_TYPE_HELLO\n"); if (ret < 0) { fprintf(stderr, "ivshmem_uxsocket_accept: failed to send number " @@ -445,7 +452,8 @@ static int channel_poll_vm(struct v_machine *vm) /* Move on if rx channel for this vm is empty */ shmring_lock(vm->chan->rx); is_empty = shmring_is_empty(vm->chan->rx); - shmring_unlock(vm->chan->rx); + shmring_unlock(vm->chan->rx); + if (is_empty) { return 0; @@ -465,25 +473,30 @@ static int channel_poll_vm(struct v_machine *vm) switch(msg_type) { case MSG_TYPE_TASINFO_REQ: + printf("MSG_TYPE_TASINFO_REQ\n"); channel_handle_tasinforeq_msg(vm); break; case MSG_TYPE_CONTEXT_REQ: + printf("MSG_TYPE_CONTEXT_REQ\n"); channel_handle_ctx_req(vm, msg); break; case MSG_TYPE_NEWAPP_REQ: + printf("MSG_TYPE_NEWAPP_REQ\n"); channel_handle_newapp(vm, msg); break; case MSG_TYPE_POKE_TAS_CORE: + printf("MSG_TYPE_POKE_TAS_CORE\n"); channel_handle_poke_tas_core(vm, msg); break; case MSG_TYPE_POKE_TAS_KERNEL: + printf("MSG_TYPE_POKE_TAS_KERNEL\n"); channel_handle_poke_tas_kernel(vm, msg); break; default: fprintf(stderr, "ivshmem_uxsocket_handle_msg: unknown message.\n"); } - return 0; + return 1; } /* Handles tasinfo request */ @@ -510,6 +523,7 @@ static int channel_handle_tasinforeq_msg(struct v_machine *vm) } ret = channel_write(vm->chan, msg, sizeof(struct tasinfo_res_msg)); + printf("MSG_TYPE_TASINFO_RES\n"); if (ret < sizeof(struct tasinfo_res_msg)) { fprintf(stderr, "ivshmem_handle_tasinforeq_msg: " @@ -580,6 +594,7 @@ static int channel_handle_ctx_req(struct v_machine *vm, res_msg.app_id = msg->app_id; ret = channel_write(vm->chan, &res_msg, sizeof(struct context_res_msg)); + printf("MSG_TYPE_CONTEXT_RES\n"); if (ret < sizeof(struct context_res_msg)) { fprintf(stderr, "ivshmem_handle_ctxreq: failed to send ctx res.\n"); @@ -619,6 +634,7 @@ static int channel_handle_newapp(struct v_machine *vm, msg_res.cfd = msg_req->cfd; ret = channel_write(vm->chan, &msg_res, sizeof(msg_res)); + printf("MSG_TYPE_NEWAPP_RES\n"); if (ret != sizeof(msg_res)) { @@ -629,7 +645,6 @@ static int channel_handle_newapp(struct v_machine *vm, notify_guest(vm->ifd); - return 0; } @@ -652,15 +667,15 @@ static void channel_handle_poke_tas_core(struct v_machine *vm, /*****************************************************************************/ /* App contexts */ -static int ctxs_poll() +static int app_ctxs_poll() { int i, n, ret; struct vmcontext_req *vctx; struct _msg; - struct epoll_event evs[32]; + struct epoll_event evs[2]; struct poke_app_ctx_msg msg; - n = epoll_wait(ctx_epfd, evs, 32, 0); + n = epoll_wait(ctx_epfd, evs, 2, 0); if (n < 0) { @@ -678,6 +693,7 @@ static int ctxs_poll() msg.msg_type = MSG_TYPE_POKE_APP_CTX; msg.ctxreq_id = vctx->ctxreq_id; ret = channel_write(vctx->vm->chan, &msg, sizeof(struct poke_app_ctx_msg)); + printf("MSG_TYPE_POKE_APP_CTX\n"); if (ret != sizeof(struct poke_app_ctx_msg)) diff --git a/proxy/shmring.c b/proxy/shmring.c index c5167581..638e9f03 100644 --- a/proxy/shmring.c +++ b/proxy/shmring.c @@ -15,50 +15,32 @@ pthread_mutexattr_t * init_mutex_attr(); struct ring_buffer* shmring_init(void *base_addr, size_t size) { - struct ring_buffer *ring; - struct ring_header *hdr; - pthread_mutexattr_t *attr; - - ring = (struct ring_buffer *) malloc(sizeof(struct ring_buffer)); - if (ring == NULL) - { - fprintf(stderr, "shmring_init: failed to allocate ring buffer.\n"); - return NULL; - } - - ring->hdr_addr = base_addr; - ring->buf_addr = base_addr + sizeof(struct ring_header); - ring->size = size; - - if ((attr = init_mutex_attr()) == NULL) - { - fprintf(stderr, "shmring_init: failed to init mutex attr.\n"); - return NULL; - } - - hdr = ring->hdr_addr; - if (pthread_mutex_init(&hdr->mux, attr) < 0) - { - fprintf(stderr, "shmring_init: failed to init mutex.\n"); - goto free_attr; - } - - return ring; + struct ring_buffer *ring; -free_attr: - free(attr); + ring = (struct ring_buffer *) malloc(sizeof(struct ring_buffer)); + if (ring == NULL) + { + fprintf(stderr, "shmring_init: failed to allocate ring buffer.\n"); return NULL; + } + + ring->hdr_addr = base_addr; + ring->buf_addr = base_addr + sizeof(struct ring_header); + ring->size = size; + + return ring; } /* Resets read and write pos to zero and sets ring size to full */ void shmring_reset(struct ring_buffer *ring, size_t size) { - struct ring_header *hdr = ring->hdr_addr; + struct ring_header *hdr = ring->hdr_addr; - hdr->read_pos = 0; - hdr->write_pos = 0; - hdr->full = 0; - hdr->ring_size = size - sizeof(struct ring_header); + memset(ring->hdr_addr, 0, size); + hdr->read_pos = 0; + hdr->write_pos = 0; + hdr->full = 0; + hdr->ring_size = size - sizeof(struct ring_header); } int shmring_is_empty(struct ring_buffer *ring) @@ -73,26 +55,48 @@ int shmring_is_empty(struct ring_buffer *ring) return 0; } -int shmring_lock(struct ring_buffer *ring) +int shmring_init_mux(struct ring_buffer *ring) { struct ring_header *hdr = ring->hdr_addr; - if (pthread_mutex_lock(&hdr->mux) < 0) + pthread_mutexattr_t *attr; + + if ((attr = init_mutex_attr()) == NULL) { - fprintf(stderr, "shmring_lock: failed to acquire lock.\n"); + fprintf(stderr, "shmring_init: failed to init mutex attr.\n"); return -1; } + hdr = ring->hdr_addr; + if (pthread_mutex_init(&hdr->mux, attr) < 0) + { + fprintf(stderr, "shmring_init: failed to init mutex.\n"); + free(attr); + return -1; + } + + return 0; +} + +int shmring_lock(struct ring_buffer *ring) +{ + // struct ring_header *hdr = ring->hdr_addr; + // if (pthread_mutex_lock(&hdr->mux) < 0) + // { + // fprintf(stderr, "shmring_lock: failed to acquire lock.\n"); + // return -1; + // } + return 0; } int shmring_unlock(struct ring_buffer *ring) { - struct ring_header *hdr = ring->hdr_addr; - if (pthread_mutex_unlock(&hdr->mux) < 0) - { - fprintf(stderr, "shmring_lock: failed to release lock.\n"); - return -1; - } + // struct ring_header *hdr = ring->hdr_addr; + // if (pthread_mutex_unlock(&hdr->mux) < 0) + // { + // fprintf(stderr, "shmring_lock: failed to release lock.\n"); + // return -1; + // } return 0; } @@ -129,12 +133,11 @@ size_t shmring_pop(struct ring_buffer *rx_ring, void *dst, size_t size) hdr->read_pos += size; hdr->read_pos %= hdr->ring_size; + hdr->full = 0; - /* Mark the ring as not full */ - if (hdr->write_pos != hdr->read_pos) - { - hdr->full = 0; - } + int is_empty = shmring_is_empty(rx_ring); + printf("shmring_pop: write_pos=%d read_pos=%d ring_size=%ld full=%d is_empty=%d size=%ld\n", + hdr->write_pos, hdr->read_pos, hdr->ring_size, hdr->full, is_empty, size); return size; } @@ -168,12 +171,11 @@ size_t pop_fragmented(struct ring_buffer *rx_ring, hdr->read_pos += size; hdr->read_pos %= hdr->ring_size; + hdr->full = 0; - /* Mark the ring as not full */ - if (hdr->write_pos != hdr->read_pos) - { - hdr->full = 0; - } + int is_empty = shmring_is_empty(rx_ring); + printf("pop_fragmented: write_pos=%d read_pos=%d ring_size=%ld full=%d is_empty=%d size=%ld\n", + hdr->write_pos, hdr->read_pos, hdr->ring_size, hdr->full, is_empty, size); return size; } @@ -282,6 +284,9 @@ size_t shmring_push(struct ring_buffer *tx_ring, void *src, size_t size) hdr->full = 1; } + int is_empty = shmring_is_empty(tx_ring); + printf("shmring_push: write_pos=%d read_pos=%d ring_size=%ld full=%d is_empty=%d size=%ld\n", + hdr->write_pos, hdr->read_pos, hdr->ring_size, hdr->full, is_empty, size); return size; } @@ -318,6 +323,10 @@ size_t push_fragmented(struct ring_buffer *tx_ring, hdr->full = 1; } + int is_empty = shmring_is_empty(tx_ring); + printf("push_fragmented: write_pos=%d read_pos=%d ring_size=%ld full=%d is_empty=%d size=%ld\n", + hdr->write_pos, hdr->read_pos, hdr->ring_size, hdr->full, is_empty, size); + return size; } @@ -358,7 +367,15 @@ pthread_mutexattr_t * init_mutex_attr() { fprintf(stderr, "init_mutex_attr: failed to set attr to shared.\n"); goto free_attr; - }; + } + + /* Set mutex to normal type. Default type may have + underfined behaviour when relocking */ + if (pthread_mutexattr_settype(attr, PTHREAD_MUTEX_NORMAL) < 0) + { + fprintf(stderr, "init_mutex_attr: failed to set mutex type to normal.\n"); + goto free_attr; + } // Subsequent attempts to lock will succeed if process dies with lock if (pthread_mutexattr_setrobust(attr, PTHREAD_MUTEX_ROBUST) < 0) diff --git a/proxy/shmring.h b/proxy/shmring.h index 3be15033..0916c154 100644 --- a/proxy/shmring.h +++ b/proxy/shmring.h @@ -21,6 +21,7 @@ struct ring_buffer { struct ring_buffer* shmring_init(void *base_addr, size_t size); void shmring_reset(struct ring_buffer *ring, size_t size); int shmring_is_empty(struct ring_buffer *ring); +int shmring_init_mux(struct ring_buffer *ring); int shmring_lock(struct ring_buffer *ring); int shmring_unlock(struct ring_buffer *ring); size_t shmring_pop(struct ring_buffer *rx_ring, void *buf, size_t size); diff --git a/tas/config.c b/tas/config.c index aaaea9a8..ec72195a 100644 --- a/tas/config.c +++ b/tas/config.c @@ -74,6 +74,7 @@ enum cfg_params { CP_FP_NO_INTS, CP_FP_NO_XSUMOFFLOAD, CP_FP_NO_AUTOSCALE, + CP_FP_NO_RSS, CP_FP_NO_HUGEPAGES, CP_FP_VLAN_STRIP, CP_FP_POLL_INTERVAL_TAS, @@ -207,6 +208,9 @@ static struct option opts[] = { { .name = "fp-no-autoscale", .has_arg = no_argument, .val = CP_FP_NO_AUTOSCALE }, + { .name = "fp-no-rss", + .has_arg = no_argument, + .val = CP_FP_NO_RSS }, { .name = "fp-no-hugepages", .has_arg = no_argument, .val = CP_FP_NO_HUGEPAGES }, @@ -222,8 +226,7 @@ static struct option opts[] = { { .name = "bu-max-budget", .has_arg = required_argument, .val = CP_BU_MAX_BUDGET }, - { - .name = "bu-use-ratio", + { .name = "bu-use-ratio", .has_arg = required_argument, .val = CP_BU_USE_RATIO }, { .name = "bu-update-freq", @@ -505,6 +508,7 @@ int config_parse(struct configuration *c, int argc, char *argv[]) case CP_FP_NO_INTS: c->fp_interrupts = 0; c->fp_poll_interval_tas = UINT32_MAX; + c->fp_poll_interval_app = UINT32_MAX; break; case CP_FP_NO_XSUMOFFLOAD: c->fp_xsumoffload = 0; @@ -512,6 +516,9 @@ int config_parse(struct configuration *c, int argc, char *argv[]) case CP_FP_NO_AUTOSCALE: c->fp_autoscale = 0; break; + case CP_FP_NO_RSS: + c->fp_rss = 0; + break; case CP_FP_NO_HUGEPAGES: c->fp_hugepages = 0; break; @@ -654,6 +661,7 @@ static int config_defaults(struct configuration *c, char *progname) c->fp_interrupts = 1; c->fp_xsumoffload = 1; c->fp_autoscale = 1; + c->fp_rss = 1; c->fp_hugepages = 1; c->fp_vlan_strip = 0; c->fp_poll_interval_tas = 10000; @@ -765,6 +773,8 @@ static void print_usage(struct configuration *c, char *progname) "[default: enabled]\n" " --fp-no-autoscale Disable autoscaling " "[default: enabled]\n" + " --fp-no-rss Disable rss " + "[default: enabled]\n" " --fp-no-hugepages Disable hugepages for SHM " "[default: enabled]\n" " --fp-poll-interval-tas TAS polling interval before blocking " diff --git a/tas/fast/fast_flows.c b/tas/fast/fast_flows.c index ee924c7a..fc924d37 100644 --- a/tas/fast/fast_flows.c +++ b/tas/fast/fast_flows.c @@ -129,7 +129,7 @@ int fast_flows_qman(struct dataplane_context *ctx, uint32_t vm_id, uint32_t queu } /* clear queue manager queue */ - if (qman_set(&ctx->qman, vm_id, flow_id, 0, 0, 0, + if (tas_qman_set(&ctx->qman, vm_id, flow_id, 0, 0, 0, QMAN_SET_RATE | QMAN_SET_MAXCHUNK | QMAN_SET_AVAIL) != 0) { fprintf(stderr, "flast_flows_qman: qman_set clear failed, UNEXPECTED\n"); @@ -218,7 +218,7 @@ int fast_flows_qman_fwd(struct dataplane_context *ctx, avail = tcp_txavail(fs, NULL); /* re-arm queue manager */ - if (qman_set(&ctx->qman, vm_id, flow_id, fs->tx_rate, avail, TCP_MSS, + if (tas_qman_set(&ctx->qman, vm_id, flow_id, fs->tx_rate, avail, TCP_MSS, QMAN_SET_RATE | QMAN_SET_MAXCHUNK | QMAN_SET_AVAIL) != 0) { fprintf(stderr, "fast_flows_qman_fwd: qman_set failed, UNEXPECTED\n"); @@ -419,7 +419,7 @@ int fast_flows_packet(struct dataplane_context *ctx, } } -#ifdef FLEXNIC_PL_OOO_RECV +#ifdef FLEXNIC_PL_OOO_RECV /* check if we should drop this segment */ if (UNLIKELY(tcp_trim_rxbuf(fs, seq, payload_bytes, &trim_start, &trim_end) != 0)) { /* packet is completely outside of unused receive buffer */ @@ -623,7 +623,7 @@ int fast_flows_packet(struct dataplane_context *ctx, new_avail = tcp_txavail(fs, NULL); if (new_avail > old_avail) { /* update qman queue */ - if (qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - + if (tas_qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - old_avail, TCP_MSS, QMAN_SET_RATE | QMAN_SET_MAXCHUNK | QMAN_ADD_AVAIL) != 0) { @@ -745,7 +745,7 @@ int fast_flows_bump(struct dataplane_context *ctx, uint32_t flow_id, /* update queue manager queue */ if (old_avail < new_avail) { - if (qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - + if (tas_qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - old_avail, TCP_MSS, QMAN_SET_RATE | QMAN_SET_MAXCHUNK | QMAN_ADD_AVAIL) != 0) { @@ -822,7 +822,7 @@ void fast_flows_retransmit(struct dataplane_context *ctx, uint32_t flow_id) /* update queue manager */ if (new_avail > old_avail) { - if (qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - old_avail, + if (tas_qman_set(&ctx->qman, fs->vm_id, flow_id, fs->tx_rate, new_avail - old_avail, TCP_MSS, QMAN_SET_RATE | QMAN_SET_MAXCHUNK | QMAN_ADD_AVAIL) != 0) { fprintf(stderr, "flast_flows_bump: qman_set 1 failed, UNEXPECTED\n"); diff --git a/tas/fast/fastemu.c b/tas/fast/fastemu.c index d1c24884..7424e909 100644 --- a/tas/fast/fastemu.c +++ b/tas/fast/fastemu.c @@ -144,8 +144,7 @@ int dataplane_context_init(struct dataplane_context *ctx) } /* initialize queue manager */ - if (qman_thread_init(ctx) != 0) - { + if (tas_qman_thread_init(ctx) != 0) { fprintf(stderr, "initializing qman thread failed\n"); return -1; } @@ -238,7 +237,7 @@ void dataplane_loop(struct dataplane_context *ctx) if (!was_idle) ctx->loadmon_cyc_busy += cyc - prev_cyc; - ts = qman_timestamp(cyc); + ts = tas_qman_timestamp(cyc); STATS_TS(start); @@ -299,7 +298,7 @@ static void dataplane_block(struct dataplane_context *ctx, uint32_t ts) return; } - max_timeout = qman_next_ts(&ctx->qman, ts); + max_timeout = tas_qman_next_ts(&ctx->qman, ts); ret = rte_epoll_wait(RTE_EPOLL_PER_THREAD, event, 2, max_timeout == (uint32_t)-1 ? -1 : max_timeout / 1000); @@ -608,7 +607,7 @@ static unsigned poll_qman(struct dataplane_context *ctx, uint32_t ts) max = bufcache_prealloc(ctx, max, &handles); /* poll queue manager */ - ret = qman_poll(ctx, max, vq_ids, fq_ids, q_bytes); + ret = tas_qman_poll(ctx, max, vq_ids, fq_ids, q_bytes); if (ret <= 0) { diff --git a/tas/fast/internal.h b/tas/fast/internal.h index 72eec789..ba52aebb 100644 --- a/tas/fast/internal.h +++ b/tas/fast/internal.h @@ -68,13 +68,13 @@ extern volatile unsigned fp_scale_to; #define IDXLIST_INVAL (-1U) /** Qman functions */ -int qman_thread_init(struct dataplane_context *ctx); -int qman_poll(struct dataplane_context *ctx, unsigned num, unsigned *vm_id, +int tas_qman_thread_init(struct dataplane_context *ctx); +int tas_qman_poll(struct dataplane_context *ctx, unsigned num, unsigned *vm_id, unsigned *q_ids, uint16_t *q_bytes); -int qman_set(struct qman_thread *t, uint32_t vm_id, uint32_t flow_id, uint32_t rate, +int tas_qman_set(struct qman_thread *t, uint32_t vm_id, uint32_t flow_id, uint32_t rate, uint32_t avail, uint16_t max_chunk, uint8_t flags); -uint32_t qman_timestamp(uint64_t tsc); -uint32_t qman_next_ts(struct qman_thread *t, uint32_t cur_ts); +uint32_t tas_qman_timestamp(uint64_t tsc); +uint32_t tas_qman_next_ts(struct qman_thread *t, uint32_t cur_ts); /** Helper functions for unit tests */ uint32_t qman_vm_get_avail(struct dataplane_context *ctx, uint32_t vm_id); void qman_free_vm_cont(struct dataplane_context *ctx); diff --git a/tas/fast/network.c b/tas/fast/network.c index f49e9c88..c24dd903 100644 --- a/tas/fast/network.c +++ b/tas/fast/network.c @@ -134,6 +134,12 @@ int network_init(unsigned n_threads) goto error_exit; } + /* turn off rss */ + if (config.fp_rss == 0) + { + port_conf.rxmode.mq_mode = ETH_MQ_RX_NONE; + } + /* mask unsupported RSS hash functions */ if ((port_conf.rx_adv_conf.rss_conf.rss_hf & eth_devinfo.flow_type_rss_offloads) != @@ -270,6 +276,7 @@ int network_thread_init(struct dataplane_context *ctx) } } + /* setting up RETA failed */ if (reta_setup() != 0) { fprintf(stderr, "RETA setup failed\n"); goto error_tx_queue; diff --git a/tas/fast/network.h b/tas/fast/network.h index 8df48ca4..cf624ff4 100644 --- a/tas/fast/network.h +++ b/tas/fast/network.h @@ -180,7 +180,8 @@ static inline uint16_t network_buf_tcpxsums(struct network_buf_handle *bh, uint8 /*mb->l2_len = l2l; mb->l3_len = l3l; mb->l4_len = 0;*/ - mb->ol_flags = PKT_TX_IPV4 | PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM; + mb->ol_flags = RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM | + RTE_MBUF_F_TX_TCP_CKSUM; return network_ip_phdr_xsum(ip_s, ip_d, ip_proto, l3_paylen); } @@ -189,7 +190,8 @@ static inline int network_buf_flowgroup(struct network_buf_handle *bh, uint16_t *fg, uint16_t core) { struct rte_mbuf *mb = (struct rte_mbuf *) bh; - if (!(mb->ol_flags & PKT_RX_RSS_HASH)) { + + if (!(mb->ol_flags & RTE_MBUF_F_RX_RSS_HASH)) { *fg = core; return 0; } diff --git a/tas/fast/qman.c b/tas/fast/qman.c index eeeed644..8480ae24 100644 --- a/tas/fast/qman.c +++ b/tas/fast/qman.c @@ -178,7 +178,7 @@ static inline uint32_t flow_queue_new_ts(struct qman_thread *t, struct flow_queu /*****************************************************************************/ /* Top level queue manager */ -int qman_thread_init(struct dataplane_context *ctx) +int tas_qman_thread_init(struct dataplane_context *ctx) { struct qman_thread *t = &ctx->qman; @@ -195,7 +195,7 @@ int qman_thread_init(struct dataplane_context *ctx) return 0; } -int qman_poll(struct dataplane_context *ctx, unsigned num, unsigned *vm_ids, +int tas_qman_poll(struct dataplane_context *ctx, unsigned num, unsigned *vm_ids, unsigned *q_ids, uint16_t *q_bytes) { int ret; @@ -207,7 +207,7 @@ int qman_poll(struct dataplane_context *ctx, unsigned num, unsigned *vm_ids, return ret; } -int qman_set(struct qman_thread *t, uint32_t vm_id, uint32_t flow_id, uint32_t rate, +int tas_qman_set(struct qman_thread *t, uint32_t vm_id, uint32_t flow_id, uint32_t rate, uint32_t avail, uint16_t max_chunk, uint8_t flags) { int ret; @@ -216,7 +216,7 @@ int qman_set(struct qman_thread *t, uint32_t vm_id, uint32_t flow_id, uint32_t r return ret; } -uint32_t qman_next_ts(struct qman_thread *t, uint32_t cur_ts) +uint32_t tas_qman_next_ts(struct qman_thread *t, uint32_t cur_ts) { struct vm_queue *vq; struct flow_qman *fqman; @@ -260,7 +260,7 @@ uint32_t qman_next_ts(struct qman_thread *t, uint32_t cur_ts) return -1; } -uint32_t qman_timestamp(uint64_t cycles) +uint32_t tas_qman_timestamp(uint64_t cycles) { static uint64_t freq = 0; @@ -579,6 +579,7 @@ int flowcont_init(struct vm_queue *vq) static inline int flow_qman_poll(struct qman_thread *t, struct vm_queue *vqueue, struct flow_qman *fqman, unsigned num, unsigned *q_ids, uint16_t *q_bytes) + { unsigned x, y; uint32_t ts = timestamp(); diff --git a/tas/include/config.h b/tas/include/config.h index 1cb924eb..7928bd1f 100644 --- a/tas/include/config.h +++ b/tas/include/config.h @@ -129,6 +129,8 @@ struct configuration { uint32_t fp_xsumoffload; /** FP: auto scaling enabled */ uint32_t fp_autoscale; + /** FP: rss enabled */ + uint32_t fp_rss; /** FP: use huge pages for internal and buffer memory */ uint32_t fp_hugepages; /** FP: enable vlan stripping */ diff --git a/tas/slow/cc.c b/tas/slow/cc.c index 9c84b198..de37f918 100644 --- a/tas/slow/cc.c +++ b/tas/slow/cc.c @@ -29,13 +29,12 @@ #include #include "internal.h" +#include "appif.h" #define CONF_MSS 1400 -int cc_init(void) -{ - return 0; -} +static void cc_next_ts_vm(uint32_t cur_ts, int vmid, uint32_t *ts); +static unsigned cc_poll_vm(int vmid, unsigned n, uint32_t diff_ts); static inline void issue_retransmits(struct connection *c, struct nicif_connection_stats *stats, uint32_t cur_ts); @@ -59,50 +58,89 @@ static inline void const_rate_update(struct connection *c, static inline uint32_t window_to_rate(uint32_t window, uint32_t rtt); static uint32_t last_ts = 0; -static struct connection *cc_conns = NULL; -static struct connection *next_conn = NULL; +int next_vm = 0; +static struct connection *cc_conns[FLEXNIC_PL_VMST_NUM]; +static struct connection *next_conn[FLEXNIC_PL_VMST_NUM]; + +int cc_init(void) +{ + int i; + + for (i = 0; i < FLEXNIC_PL_VMST_NUM; i++) + { + cc_conns[i] = NULL; + next_conn[i] = NULL; + } + + return 0; +} uint32_t cc_next_ts(uint32_t cur_ts) { - struct connection *c; + int i; assert(cur_ts >= last_ts); uint32_t ts = -1U; - for (c = cc_conns; c != NULL; c = c->cc_next) { + for (i = 0; i < FLEXNIC_PL_VMST_NUM; i++) + { + cc_next_ts_vm(cur_ts, i, &ts); + } + + return (ts == -1U ? -1U : MAX(ts, config.cc_control_granularity - (cur_ts - last_ts))); +} + +static void cc_next_ts_vm(uint32_t cur_ts, int vmid, uint32_t *ts) +{ + struct connection *c; + + for (c = cc_conns[vmid]; c != NULL; c = c->cc_next) { if (c->status != CONN_OPEN) continue; int32_t next_ts = (c->cc_rtt * config.cc_control_interval) - (cur_ts - c->cc_last_ts); if(next_ts >= 0) { - ts = MIN(ts, next_ts); + *ts = MIN(*ts, next_ts); } else { - ts = 0; + *ts = 0; } } - - return (ts == -1U ? -1U : MAX(ts, config.cc_control_granularity - (cur_ts - last_ts))); } unsigned cc_poll(uint32_t cur_ts) { - struct connection *c, *c_first; - struct nicif_connection_stats stats; - uint32_t diff_ts; - uint32_t last; + int i, vmid; unsigned n = 0; + uint32_t diff_ts; diff_ts = cur_ts - last_ts; if (0 && diff_ts < config.cc_control_granularity) return 0; - c = c_first = (next_conn != NULL ? next_conn : cc_conns); + + for(i = 0; i < FLEXNIC_PL_VMST_NUM && n < 128; i++) + { + vmid = (next_vm + i) % FLEXNIC_PL_VMST_NUM; + n = cc_poll_vm(vmid, n, diff_ts); + } + + last_ts = cur_ts; + next_vm = (vmid + 1) % FLEXNIC_PL_VMST_NUM; + return n; +} + +static unsigned cc_poll_vm(int vmid, unsigned n, uint32_t diff_ts) +{ + struct connection *c, *c_first; + struct nicif_connection_stats stats; + uint32_t last; + + c = c_first = (next_conn[vmid] != NULL ? next_conn[vmid] : cc_conns[vmid]); if (c == NULL) { - last_ts = cur_ts; - return 0; + return n; } for (; n < 128 && (n == 0 || c != c_first); - c = (c->cc_next != NULL ? c->cc_next : cc_conns), n++) + c = (c->cc_next != NULL ? c->cc_next : cc_conns[vmid]), n++) { if (c->status != CONN_OPEN) continue; @@ -164,18 +202,17 @@ unsigned cc_poll(uint32_t cur_ts) nicif_connection_setrate(c->flow_id, c->cc_rate); c->cc_last_ts = cur_ts; - } - next_conn = c; - last_ts = cur_ts; + next_conn[vmid] = c; return n; } void cc_conn_init(struct connection *conn) { - conn->cc_next = cc_conns; - cc_conns = conn; + int vmid = conn->ctx->app->vm_id; + conn->cc_next = cc_conns[vmid]; + cc_conns[vmid] = conn; conn->cc_last_ts = cur_ts; conn->cc_rtt = config.tcp_rtt_init; @@ -209,15 +246,16 @@ void cc_conn_init(struct connection *conn) void cc_conn_remove(struct connection *conn) { struct connection *cp = NULL; + int vmid = conn->ctx->app->vm_id; - if (next_conn == conn) { - next_conn = conn->cc_next; + if (next_conn[vmid] == conn) { + next_conn[vmid] = conn->cc_next; } - if (cc_conns == conn) { - cc_conns = conn->cc_next; + if (cc_conns[vmid] == conn) { + cc_conns[vmid] = conn->cc_next; } else { - for (cp = cc_conns; cp != NULL && cp->cc_next != conn; + for (cp = cc_conns[vmid]; cp != NULL && cp->cc_next != conn; cp = cp->cc_next); if (cp == NULL) { fprintf(stderr, "conn_unregister: connection not found\n"); diff --git a/tas/slow/internal.h b/tas/slow/internal.h index d489cd3c..81cd5e45 100644 --- a/tas/slow/internal.h +++ b/tas/slow/internal.h @@ -589,8 +589,11 @@ struct listener { uint16_t *backlog_fgs; /**@}*/ - /** List of waiting connections from accept calls */ + /** List of waiting connections from accept calls (head) */ struct connection *wait_conns; + /** List of waiting connections from accept calls (tail) */ + struct connection *wait_conns_last; + /** Listener port */ uint16_t port; /** Flags: see #nicif_connection_flags */ diff --git a/tas/slow/tcp.c b/tas/slow/tcp.c index 9fe8b7bc..7e608677 100644 --- a/tas/slow/tcp.c +++ b/tas/slow/tcp.c @@ -298,6 +298,7 @@ int tcp_listen(struct app_context *ctx, uint64_t opaque, uint16_t local_port, lst->opaque = opaque; lst->port = local_port; lst->wait_conns = NULL; + lst->wait_conns_last = NULL; lst->backlog_len = backlog; lst->backlog_pos = 0; lst->backlog_used = 0; @@ -339,8 +340,14 @@ int tcp_accept(struct app_context *ctx, uint64_t opaque, conn->flags = listen->flags; conn->cnt_tx_pending = 0; - conn->ht_next = listen->wait_conns; - listen->wait_conns = conn; + conn->ht_next = NULL; + if (listen->wait_conns == NULL) { + listen->wait_conns = conn; + listen->wait_conns_last = conn; + } else { + listen->wait_conns_last->ht_next = conn; + listen->wait_conns_last = conn; + } if (listen->backlog_used > 0) { listener_accept(listen); @@ -960,6 +967,9 @@ static void listener_accept(struct listener *l) } l->wait_conns = c->ht_next; + if (l->wait_conns == NULL) { + l->wait_conns_last = NULL; + } conn_register(c); nbqueue_enq(&conn_async_q, &c->comp.el); diff --git a/tas/tas.c b/tas/tas.c index c7042c22..a8309c02 100644 --- a/tas/tas.c +++ b/tas/tas.c @@ -221,7 +221,7 @@ static int start_threads(void) } /* start common threads */ - RTE_LCORE_FOREACH_SLAVE(core) { + RTE_LCORE_FOREACH_WORKER(core) { if (threads_launched < fp_cores_max) { arg = (void *) (uintptr_t) threads_launched; if (rte_eal_remote_launch(common_thread, arg, core) != 0) { diff --git a/tests/bench_ll_echo.c b/tests/bench_ll_echo.c index 3a166d09..e17982b6 100644 --- a/tests/bench_ll_echo.c +++ b/tests/bench_ll_echo.c @@ -304,7 +304,7 @@ int main(int argc, char *argv[]) for (i = 0; i < num_threads; i++) { cs->cn = i; - if (flextcp_context_create(&cs->context) != 0) { + if (flextcp_context_create(&cs->context, NULL, NULL) != 0) { fprintf(stderr, "flextcp_context_create failed %d\n", i); return EXIT_FAILURE; } diff --git a/tests/full/fulltest.c b/tests/full/fulltest.c index bba8be07..a37ec165 100644 --- a/tests/full/fulltest.c +++ b/tests/full/fulltest.c @@ -104,6 +104,7 @@ static pid_t start_tas(void) "--fp-no-autoscale", "--fp-no-hugepages", "--dpdk-extra=--vdev", "--dpdk-extra=eth_tap0,iface=vethtas1", "--dpdk-extra=--no-shconf", "--dpdk-extra=--no-huge", + "--dpdk-extra=--no-pci", "--dpdk-extra=--no-telemetry", "--ip-addr=192.168.1.1/24", readyfdopt, NULL); perror("exec failed"); @@ -221,6 +222,12 @@ static int run_child(int (*tas_entry)(void *), int (*linux_entry)(void *), return 1; } + /* dpdk stores control files/sockets in /var/run */ + if (mount("tmpfs", "/var/run", "tmpfs", 0, "") != 0) { + perror("mounting /var/run failed"); + return 1; + } + umask(0022); /* start tas */ diff --git a/tests/full/netperf/netperf-shortsend.patch b/tests/full/netperf/netperf-shortsend.patch new file mode 100644 index 00000000..c9c7ab65 --- /dev/null +++ b/tests/full/netperf/netperf-shortsend.patch @@ -0,0 +1,70 @@ +Only in netperf-netperf-2.7.0: config.h +Only in netperf-netperf-2.7.0: config.log +Only in netperf-netperf-2.7.0: config.status +Only in netperf-netperf-2.7.0/doc/examples: Makefile +Only in netperf-netperf-2.7.0/doc: Makefile +Only in netperf-netperf-2.7.0: Makefile +Only in netperf-netperf-2.7.0: netperf.spec +Only in netperf-netperf-2.7.0/src: .deps +Only in netperf-netperf-2.7.0/src: dscp.o +Only in netperf-netperf-2.7.0/src: Makefile +Only in netperf-netperf-2.7.0/src/missing: .deps +Only in netperf-netperf-2.7.0/src/missing/m4: Makefile +Only in netperf-netperf-2.7.0/src/missing: Makefile +Only in netperf-netperf-2.7.0/src: netcpu_procstat.o +Only in netperf-netperf-2.7.0/src: netlib.o +Only in netperf-netperf-2.7.0/src: netperf +Only in netperf-netperf-2.7.0/src: netperf.o +Only in netperf-netperf-2.7.0/src: netperf_version.h +Only in netperf-netperf-2.7.0/src: netserver +Only in netperf-netperf-2.7.0/src: netserver.o +Only in netperf-netperf-2.7.0/src: netsh.o +Only in netperf-netperf-2.7.0/src: nettest_bsd.o +Only in netperf-netperf-2.7.0/src: nettest_dlpi.o +diff -ur netperf-netperf-2.7.0.orig/src/nettest_omni.c netperf-netperf-2.7.0/src/nettest_omni.c +--- netperf-netperf-2.7.0.orig/src/nettest_omni.c 2015-07-20 19:39:35.000000000 +0200 ++++ netperf-netperf-2.7.0/src/nettest_omni.c 2023-01-16 23:37:55.531646323 +0100 +@@ -2916,24 +2916,39 @@ + } + } + else { ++ int ret; ++ len = 0; ++ ++ while ((uint32_t) len != bytes_to_send) { + if (!use_write) { +- len = send(data_socket, ++ ret = send(data_socket, + send_ring->buffer_ptr, +- bytes_to_send, ++ bytes_to_send - len, + 0); + } + else { + #ifndef WIN32 +- len = write(data_socket, ++ ret = write(data_socket, + send_ring->buffer_ptr, +- bytes_to_send); ++ bytes_to_send - len); + #else + fprintf(where,"I'm sorry Dave I cannot write() under Windows\n"); + fflush(where); + return -3; + #endif + } ++ ++ if (ret <= 0) { ++ len = ret; ++ break; ++ } else if (SOCKET_EINTR(ret)) { ++ len = ret; ++ break; ++ } ++ len += ret; ++ } + } ++ + if(len != bytes_to_send) { + /* don't forget that some platforms may do a partial send upon + receipt of the interrupt and not return an EINTR... */ diff --git a/tests/full/netperf/rules.mk b/tests/full/netperf/rules.mk new file mode 100644 index 00000000..09c58595 --- /dev/null +++ b/tests/full/netperf/rules.mk @@ -0,0 +1,53 @@ +include mk/subdir_pre.mk + +ft_netperf_parentdir := $(TEST_DISTFILES)/full-netperf + +################################### +# Build netperf + +ft_netperf_ver := 2.7.0 +ft_netperf_tar := $(ft_netperf_parentdir)/netperf-$(ft_netperf_ver).tar.gz +ft_netperf_build := $(ft_netperf_parentdir)/netperf-netperf-$(ft_netperf_ver) +ft_netperf_server := $(ft_netperf_build)/src/netserver +ft_netperf_client := $(ft_netperf_build)/src/netperf +ft_netperf_patch := $(d)/netperf-shortsend.patch + +# Download netperf tarball +$(ft_netperf_tar): + mkdir -p $(dir $@) + wget -O $@ https://github.com/HewlettPackard/netperf/archive/refs/tags/netperf-$(ft_netperf_ver).tar.gz + +# Extract netperf tarball +$(ft_netperf_build): $(ft_netperf_tar) + tar xf $< -C $(ft_netperf_parentdir) + patch -d $(ft_netperf_build) -p1 <$(ft_netperf_patch) + touch $(@) + +# Build netperf +$(ft_netperf_server) $(ft_netperf_client): $(ft_netperf_build) + (cd $(ft_netperf_build) && ./configure CFLAGS=-fcommon) + $(MAKE) -C $(ft_netperf_build) + touch $(ft_netperf_server) $(ft_netperf_client) + +################################### + +tests-full-netperf: $(ft_netperf_server) $(ft_netperf_client) +tests-full: tests-full-netperf + +run-tests-full-netperf-server: tests-full-netperf test-full-wrapdeps + $(FTWRAP) -d 500 \ + -P '$(ft_netperf_server) -D -f' \ + -c '$(ft_netperf_client) -H $$TAS_IP -l 5 -t TCP_STREAM' + +run-tests-full-netperf-client: tests-full-netperf test-full-wrapdeps + $(FTWRAP) -d 500 \ + -C '$(ft_netperf_server) -D -f' \ + -p '$(ft_netperf_client) -H $$LINUX_IP -l 5 -t TCP_STREAM' + +run-tests-full-netperf: run-tests-full-netperf-server run-tests-full-netperf-client +run-tests-full: run-tests-full-netperf + +.PHONY: tests-full-netperf run-tests-full-netperf \ + run-tests-full-netperf-server run-tests-full-netperf-client + +include mk/subdir_post.mk diff --git a/tests/full/rules.mk b/tests/full/rules.mk index cb077cd7..1b995f3d 100644 --- a/tests/full/rules.mk +++ b/tests/full/rules.mk @@ -39,6 +39,9 @@ include $(dir)/rules.mk dir := $(d)/lighttpd include $(dir)/rules.mk +dir := $(d)/netperf +include $(dir)/rules.mk + ######################### DEPS += $(FULLTEST_OBJS:.o=.d) $(FTWRAP_OBJS:.o=.d) diff --git a/tests/libtas/tas_ll.c b/tests/libtas/tas_ll.c index 6d90e97e..debc5fc6 100644 --- a/tests/libtas/tas_ll.c +++ b/tests/libtas/tas_ll.c @@ -23,7 +23,7 @@ static void test_poll_empty(void *p) test_error("flextcp_init failed"); test_randinit(&ctx, sizeof(ctx)); - if (flextcp_context_create(&ctx) != 0) + if (flextcp_context_create(&ctx, NULL, NULL) != 0) test_error("flextcp_context_create failed"); num = flextcp_context_poll(&ctx, 4, evs); @@ -47,7 +47,7 @@ static void test_connect_success(void *p) test_error("flextcp_init failed"); test_randinit(&ctx, sizeof(ctx)); - if (flextcp_context_create(&ctx) != 0) + if (flextcp_context_create(&ctx, NULL, NULL) != 0) test_error("flextcp_context_create failed"); /* initiate connect */ @@ -107,7 +107,7 @@ static void test_connect_fail(void *p) test_error("flextcp_init failed"); test_randinit(&ctx, sizeof(ctx)); - if (flextcp_context_create(&ctx) != 0) + if (flextcp_context_create(&ctx, NULL, NULL) != 0) test_error("flextcp_context_create failed"); /* initiate connect */ @@ -148,7 +148,7 @@ static void test_full_rxbuf(void *p) test_error("flextcp_init failed"); test_randinit(&ctx, sizeof(ctx)); - if (flextcp_context_create(&ctx) != 0) + if (flextcp_context_create(&ctx, NULL, NULL) != 0) test_error("flextcp_context_create failed"); /* initiate connect */ @@ -249,7 +249,7 @@ static void test_full_txbuf(void *p) test_error("flextcp_init failed"); test_randinit(&ctx, sizeof(ctx)); - if (flextcp_context_create(&ctx) != 0) + if (flextcp_context_create(&ctx, NULL, NULL) != 0) test_error("flextcp_context_create failed"); /* initiate connect */ diff --git a/tests/lowlevel.c b/tests/lowlevel.c index 25a229d7..ee7ed5a3 100644 --- a/tests/lowlevel.c +++ b/tests/lowlevel.c @@ -158,7 +158,7 @@ int main(int argc, char *argv[]) return -1; } - if (flextcp_context_create(&ctx)) { + if (flextcp_context_create(&ctx, NULL, NULL)) { fprintf(stderr, "flextcp_context_create failed\n"); return -1; } diff --git a/tests/lowlevel_echo.c b/tests/lowlevel_echo.c index 229d4160..2aa5e60d 100644 --- a/tests/lowlevel_echo.c +++ b/tests/lowlevel_echo.c @@ -149,12 +149,12 @@ int main(int argc, char *argv[]) } port = atoi(argv[argc - 1]); - if (flextcp_init()) { + if (flextcp_init(0)) { fprintf(stderr, "flextcp_init failed\n"); return -1; } - if (flextcp_context_create(&ctx)) { + if (flextcp_context_create(&ctx, NULL, NULL)) { fprintf(stderr, "flextcp_context_create failed\n"); return -1; } diff --git a/tests/rules.mk b/tests/rules.mk index 84f8655c..a40a321b 100644 --- a/tests/rules.mk +++ b/tests/rules.mk @@ -25,6 +25,7 @@ TESTS_AUTO := \ tests/libtas/tas_ll \ tests/libtas/tas_sockets \ tests/tas_unit/fastpath \ + tests/tas_unit/shmring \ tests/tas_unit/qman_rr \ tests/tas_unit/activelist @@ -65,6 +66,13 @@ tests/tas_unit/fastpath: LDLIBS+= -lrte_eal tests/tas_unit/fastpath: tests/tas_unit/fastpath.o tests/testutils.o \ tas/fast/fast_flows.o +tests/tas_unit/shmring: CPPFLAGS+= -Itas/include $(DPDK_CPPFLAGS) +tests/tas_unit/shmring: CFLAGS+= $(DPDK_CFLAGS) +tests/tas_unit/shmring: LDFLAGS+= $(DPDK_LDFLAGS) +tests/tas_unit/shmring: LDLIBS+= -lrte_eal +tests/tas_unit/shmring: tests/tas_unit/shmring.o tests/testutils.o \ + proxy/shmring.o + tests/tas_unit/qman_rr: CPPFLAGS+= -Itas/include -Ilib/tas/include/ $(DPDK_CPPFLAGS) tests/tas_unit/qman_rr: CFLAGS+= $(DPDK_CFLAGS) tests/tas_unit/qman_rr: LDFLAGS+= $(DPDK_LDFLAGS) @@ -87,6 +95,7 @@ run-tests: $(TESTS_AUTO) tests/libtas/tas_ll tests/libtas/tas_sockets tests/tas_unit/fastpath + tests/tas_unit/shmring tests/tas_unit/qman_rr tests/tas_unit/activelist diff --git a/tests/tas_unit/activelist.c b/tests/tas_unit/activelist.c index e71022fa..6ed1c978 100644 --- a/tests/tas_unit/activelist.c +++ b/tests/tas_unit/activelist.c @@ -16,7 +16,7 @@ /* Redefined so tests compile properly */ /***************************************************************************/ -void *tas_shm = (void *) 0; +void **vm_shm = (void *) 0; struct flextcp_pl_mem state_base; struct flextcp_pl_mem *fp_state = &state_base; struct configuration config; @@ -28,21 +28,21 @@ int fast_flows_bump(struct dataplane_context *ctx, uint32_t flow_id, return 0; } -static void polled_app_init(struct polled_app *app, uint16_t id) +static void polled_vm_init(struct polled_vm *vm, uint16_t id) { - app->id = id; - app->next = IDXLIST_INVAL; - app->prev = IDXLIST_INVAL; - app->flags = 0; - app->poll_next_ctx = 0; - app->act_ctx_head = IDXLIST_INVAL; - app->act_ctx_tail = IDXLIST_INVAL; + vm->id = id; + vm->next = IDXLIST_INVAL; + vm->prev = IDXLIST_INVAL; + vm->flags = 0; + vm->poll_next_ctx = 0; + vm->act_ctx_head = IDXLIST_INVAL; + vm->act_ctx_tail = IDXLIST_INVAL; } -static void polled_ctx_init(struct polled_context *ctx, uint32_t id, uint32_t aid) +static void polled_ctx_init(struct polled_context *ctx, uint32_t id, uint32_t vmid) { ctx->id = id; - ctx->aid = aid; + ctx->vmid = vmid; ctx->next = IDXLIST_INVAL; ctx->prev = IDXLIST_INVAL; ctx->flags = 0; @@ -51,7 +51,7 @@ static void polled_ctx_init(struct polled_context *ctx, uint32_t id, uint32_t ai /***************************************************************************/ -void test_enqueue_app(void *arg) +void test_enqueue_vm(void *arg) { struct dataplane_context *ctx; @@ -60,40 +60,40 @@ void test_enqueue_app(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 0 is tail", ctx->act_tail == 0); - test_assert("app 0 is active", - (ctx->polled_apps[0].flags & FLAG_ACTIVE) != 0); - enqueue_app_to_active(ctx, 1); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 1 is tail", ctx->act_tail == 1); - test_assert("app 1 is active", - (ctx->polled_apps[1].flags & FLAG_ACTIVE) != 0); - enqueue_app_to_active(ctx, 2); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 2 is tail", ctx->act_tail == 2); - test_assert("app 2 is active", - (ctx->polled_apps[2].flags & FLAG_ACTIVE) != 0); + enqueue_vm_to_active(ctx, 0); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 0 is tail", ctx->act_tail == 0); + test_assert("vm 0 is active", + (ctx->polled_vms[0].flags & FLAG_ACTIVE) != 0); + enqueue_vm_to_active(ctx, 1); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 1 is tail", ctx->act_tail == 1); + test_assert("vm 1 is active", + (ctx->polled_vms[1].flags & FLAG_ACTIVE) != 0); + enqueue_vm_to_active(ctx, 2); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 2 is tail", ctx->act_tail == 2); + test_assert("vm 2 is active", + (ctx->polled_vms[2].flags & FLAG_ACTIVE) != 0); } void test_enqueue_ctx(void *arg) { - struct polled_app *app0, *app1; + struct polled_vm *vm0, *vm1; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; - app1 = &ctx->polled_apps[1]; + vm0 = &ctx->polled_vms[0]; + vm1 = &ctx->polled_vms[1]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); - polled_ctx_init(&app0->ctxs[1], 1, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); + polled_ctx_init(&vm0->ctxs[1], 1, 0); - polled_app_init(app1, 1); - polled_ctx_init(&app0->ctxs[0], 0, 1); + polled_vm_init(vm1, 1); + polled_ctx_init(&vm0->ctxs[0], 0, 1); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -101,24 +101,24 @@ void test_enqueue_ctx(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); - test_assert("app0: ctx 0 is head", app0->act_ctx_head == 0); - test_assert("app0: ctx 0 is tail", app0->act_ctx_tail == 0); - test_assert("app0: ctx 0 is active", - (app0->ctxs[0].flags & FLAG_ACTIVE) != 0); - enqueue_ctx_to_active(app0, 1); - test_assert("app0: ctx 0 is head", app0->act_ctx_head == 0); - test_assert("app0: ctx 1 is tail", app0->act_ctx_tail == 1); - test_assert("app0: ctx 1 is active", - (app0->ctxs[1].flags & FLAG_ACTIVE) != 0); - enqueue_ctx_to_active(app1, 0); - test_assert("app1: ctx 0 is head", app1->act_ctx_head == 0); - test_assert("app1: ctx 0 is tail", app1->act_ctx_tail == 0); - test_assert("app1: ctx 0 is active", - (app1->ctxs[0].flags & FLAG_ACTIVE) != 0); + enqueue_ctx_to_active(vm0, 0); + test_assert("vm0: ctx 0 is head", vm0->act_ctx_head == 0); + test_assert("vm0: ctx 0 is tail", vm0->act_ctx_tail == 0); + test_assert("vm0: ctx 0 is active", + (vm0->ctxs[0].flags & FLAG_ACTIVE) != 0); + enqueue_ctx_to_active(vm0, 1); + test_assert("vm0: ctx 0 is head", vm0->act_ctx_head == 0); + test_assert("vm0: ctx 1 is tail", vm0->act_ctx_tail == 1); + test_assert("vm0: ctx 1 is active", + (vm0->ctxs[1].flags & FLAG_ACTIVE) != 0); + enqueue_ctx_to_active(vm1, 0); + test_assert("vm1: ctx 0 is head", vm1->act_ctx_head == 0); + test_assert("vm1: ctx 0 is tail", vm1->act_ctx_tail == 0); + test_assert("vm1: ctx 0 is active", + (vm1->ctxs[0].flags & FLAG_ACTIVE) != 0); } -void test_remove_app(void *arg) +void test_remove_vm(void *arg) { struct dataplane_context *ctx; @@ -127,18 +127,18 @@ void test_remove_app(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); - enqueue_app_to_active(ctx, 1); - enqueue_app_to_active(ctx, 2); - - remove_app_from_active(ctx, &ctx->polled_apps[1]); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 2 is tail", ctx->act_tail == 2); - test_assert("app 1 is not active", - (ctx->polled_apps[1].flags & FLAG_ACTIVE) == 0); + enqueue_vm_to_active(ctx, 0); + enqueue_vm_to_active(ctx, 1); + enqueue_vm_to_active(ctx, 2); + + remove_vm_from_active(ctx, &ctx->polled_vms[1]); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 2 is tail", ctx->act_tail == 2); + test_assert("vm 1 is not active", + (ctx->polled_vms[1].flags & FLAG_ACTIVE) == 0); } -void test_remove_app_head(void *arg) +void test_remove_vm_head(void *arg) { struct dataplane_context *ctx; @@ -147,18 +147,18 @@ void test_remove_app_head(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); - enqueue_app_to_active(ctx, 1); - enqueue_app_to_active(ctx, 2); - - remove_app_from_active(ctx, &ctx->polled_apps[0]); - test_assert("app 1 is head", ctx->act_head == 1); - test_assert("app 2 is tail", ctx->act_tail == 2); - test_assert("app 0 is not active", - (ctx->polled_apps[0].flags & FLAG_ACTIVE) == 0); + enqueue_vm_to_active(ctx, 0); + enqueue_vm_to_active(ctx, 1); + enqueue_vm_to_active(ctx, 2); + + remove_vm_from_active(ctx, &ctx->polled_vms[0]); + test_assert("vm 1 is head", ctx->act_head == 1); + test_assert("vm 2 is tail", ctx->act_tail == 2); + test_assert("vm 0 is not active", + (ctx->polled_vms[0].flags & FLAG_ACTIVE) == 0); } -void test_remove_app_tail(void *arg) +void test_remove_vm_tail(void *arg) { struct dataplane_context *ctx; @@ -167,18 +167,18 @@ void test_remove_app_tail(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); - enqueue_app_to_active(ctx, 1); - enqueue_app_to_active(ctx, 2); - - remove_app_from_active(ctx, &ctx->polled_apps[2]); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 1 is tail", ctx->act_tail == 1); - test_assert("app 2 is not active", - (ctx->polled_apps[2].flags & FLAG_ACTIVE) == 0); + enqueue_vm_to_active(ctx, 0); + enqueue_vm_to_active(ctx, 1); + enqueue_vm_to_active(ctx, 2); + + remove_vm_from_active(ctx, &ctx->polled_vms[2]); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 1 is tail", ctx->act_tail == 1); + test_assert("vm 2 is not active", + (ctx->polled_vms[2].flags & FLAG_ACTIVE) == 0); } -void test_remove_app_one_elt(void *arg) +void test_remove_vm_one_elt(void *arg) { struct dataplane_context *ctx; @@ -187,16 +187,16 @@ void test_remove_app_one_elt(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); + enqueue_vm_to_active(ctx, 0); - remove_app_from_active(ctx, &ctx->polled_apps[0]); + remove_vm_from_active(ctx, &ctx->polled_vms[0]); test_assert("head is invalid", ctx->act_head == IDXLIST_INVAL); test_assert("tail is invalid", ctx->act_tail == IDXLIST_INVAL); - test_assert("app 0 is not active", - (ctx->polled_apps[0].flags & FLAG_ACTIVE) == 0); + test_assert("vm 0 is not active", + (ctx->polled_vms[0].flags & FLAG_ACTIVE) == 0); } -void test_remove_multiple_apps(void *arg) +void test_remove_multiple_vms(void *arg) { struct dataplane_context *ctx; @@ -205,43 +205,43 @@ void test_remove_multiple_apps(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_app_to_active(ctx, 0); - enqueue_app_to_active(ctx, 1); - enqueue_app_to_active(ctx, 2); - - remove_app_from_active(ctx, &ctx->polled_apps[1]); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 2 is tail", ctx->act_tail == 2); - test_assert("app 1 is not active", - (ctx->polled_apps[1].flags & FLAG_ACTIVE) == 0); - - remove_app_from_active(ctx, &ctx->polled_apps[2]); - test_assert("app 0 is head", ctx->act_head == 0); - test_assert("app 0 is tail", ctx->act_tail == 0); - test_assert("app 2 is not active", - (ctx->polled_apps[1].flags & FLAG_ACTIVE) == 0); - - remove_app_from_active(ctx, &ctx->polled_apps[0]); + enqueue_vm_to_active(ctx, 0); + enqueue_vm_to_active(ctx, 1); + enqueue_vm_to_active(ctx, 2); + + remove_vm_from_active(ctx, &ctx->polled_vms[1]); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 2 is tail", ctx->act_tail == 2); + test_assert("vm 1 is not active", + (ctx->polled_vms[1].flags & FLAG_ACTIVE) == 0); + + remove_vm_from_active(ctx, &ctx->polled_vms[2]); + test_assert("vm 0 is head", ctx->act_head == 0); + test_assert("vm 0 is tail", ctx->act_tail == 0); + test_assert("vm 2 is not active", + (ctx->polled_vms[1].flags & FLAG_ACTIVE) == 0); + + remove_vm_from_active(ctx, &ctx->polled_vms[0]); test_assert("head is invalid", ctx->act_head == IDXLIST_INVAL); test_assert("tail is invalid", ctx->act_tail == IDXLIST_INVAL); - test_assert("app 0 is not active", - (ctx->polled_apps[0].flags & FLAG_ACTIVE) == 0); + test_assert("vm 0 is not active", + (ctx->polled_vms[0].flags & FLAG_ACTIVE) == 0); } void test_remove_ctx(void *arg) { - struct polled_app *app0; + struct polled_vm *vm0; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; + vm0 = &ctx->polled_vms[0]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); - polled_ctx_init(&app0->ctxs[1], 1, 0); - polled_ctx_init(&app0->ctxs[2], 2, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); + polled_ctx_init(&vm0->ctxs[1], 1, 0); + polled_ctx_init(&vm0->ctxs[2], 2, 0); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -249,31 +249,31 @@ void test_remove_ctx(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); - enqueue_ctx_to_active(app0, 1); - enqueue_ctx_to_active(app0, 2); + enqueue_ctx_to_active(vm0, 0); + enqueue_ctx_to_active(vm0, 1); + enqueue_ctx_to_active(vm0, 2); - remove_ctx_from_active(app0, &app0->ctxs[1]); - test_assert("ctx0 is head", app0->act_ctx_head == 0); - test_assert("ctx2 is tail", app0->act_ctx_tail == 2); + remove_ctx_from_active(vm0, &vm0->ctxs[1]); + test_assert("ctx0 is head", vm0->act_ctx_head == 0); + test_assert("ctx2 is tail", vm0->act_ctx_tail == 2); test_assert("ctx1 is not active", - (app0->ctxs[1].flags & FLAG_ACTIVE) == 0); + (vm0->ctxs[1].flags & FLAG_ACTIVE) == 0); } void test_remove_ctx_head(void *arg) { - struct polled_app *app0; + struct polled_vm *vm0; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; + vm0 = &ctx->polled_vms[0]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); - polled_ctx_init(&app0->ctxs[1], 1, 0); - polled_ctx_init(&app0->ctxs[2], 2, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); + polled_ctx_init(&vm0->ctxs[1], 1, 0); + polled_ctx_init(&vm0->ctxs[2], 2, 0); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -281,31 +281,31 @@ void test_remove_ctx_head(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); - enqueue_ctx_to_active(app0, 1); - enqueue_ctx_to_active(app0, 2); + enqueue_ctx_to_active(vm0, 0); + enqueue_ctx_to_active(vm0, 1); + enqueue_ctx_to_active(vm0, 2); - remove_ctx_from_active(app0, &app0->ctxs[0]); - test_assert("ctx1 is head", app0->act_ctx_head == 1); - test_assert("ctx2 is tail", app0->act_ctx_tail == 2); + remove_ctx_from_active(vm0, &vm0->ctxs[0]); + test_assert("ctx1 is head", vm0->act_ctx_head == 1); + test_assert("ctx2 is tail", vm0->act_ctx_tail == 2); test_assert("ctx0 is not active", - (app0->ctxs[0].flags & FLAG_ACTIVE) == 0); + (vm0->ctxs[0].flags & FLAG_ACTIVE) == 0); } void test_remove_ctx_tail(void *arg) { - struct polled_app *app0; + struct polled_vm *vm0; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; + vm0 = &ctx->polled_vms[0]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); - polled_ctx_init(&app0->ctxs[1], 1, 0); - polled_ctx_init(&app0->ctxs[2], 2, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); + polled_ctx_init(&vm0->ctxs[1], 1, 0); + polled_ctx_init(&vm0->ctxs[2], 2, 0); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -313,29 +313,29 @@ void test_remove_ctx_tail(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); - enqueue_ctx_to_active(app0, 1); - enqueue_ctx_to_active(app0, 2); + enqueue_ctx_to_active(vm0, 0); + enqueue_ctx_to_active(vm0, 1); + enqueue_ctx_to_active(vm0, 2); - remove_ctx_from_active(app0, &app0->ctxs[2]); - test_assert("ctx0 is head", app0->act_ctx_head == 0); - test_assert("ctx1 is tail", app0->act_ctx_tail == 1); + remove_ctx_from_active(vm0, &vm0->ctxs[2]); + test_assert("ctx0 is head", vm0->act_ctx_head == 0); + test_assert("ctx1 is tail", vm0->act_ctx_tail == 1); test_assert("ctx2 is not active", - (app0->ctxs[2].flags & FLAG_ACTIVE) == 0); + (vm0->ctxs[2].flags & FLAG_ACTIVE) == 0); } void test_remove_ctx_one_elt(void *arg) { - struct polled_app *app0; + struct polled_vm *vm0; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; + vm0 = &ctx->polled_vms[0]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -343,35 +343,35 @@ void test_remove_ctx_one_elt(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); + enqueue_ctx_to_active(vm0, 0); - remove_ctx_from_active(app0, &app0->ctxs[0]); - test_assert("head is invalid", app0->act_ctx_head == IDXLIST_INVAL); - test_assert("tail is invalid", app0->act_ctx_tail == IDXLIST_INVAL); + remove_ctx_from_active(vm0, &vm0->ctxs[0]); + test_assert("head is invalid", vm0->act_ctx_head == IDXLIST_INVAL); + test_assert("tail is invalid", vm0->act_ctx_tail == IDXLIST_INVAL); test_assert("ctx0 is not active", - (app0->ctxs[0].flags & FLAG_ACTIVE) == 0); + (vm0->ctxs[0].flags & FLAG_ACTIVE) == 0); } void test_remove_multiple_ctx(void *arg) { - struct polled_app *app0, *app1; + struct polled_vm *vm0, *vm1; struct dataplane_context *ctx; ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); - app0 = &ctx->polled_apps[0]; - app1 = &ctx->polled_apps[1]; + vm0 = &ctx->polled_vms[0]; + vm1 = &ctx->polled_vms[1]; - polled_app_init(app0, 0); - polled_ctx_init(&app0->ctxs[0], 0, 0); - polled_ctx_init(&app0->ctxs[1], 1, 0); - polled_ctx_init(&app0->ctxs[2], 2, 0); + polled_vm_init(vm0, 0); + polled_ctx_init(&vm0->ctxs[0], 0, 0); + polled_ctx_init(&vm0->ctxs[1], 1, 0); + polled_ctx_init(&vm0->ctxs[2], 2, 0); - polled_app_init(app1, 1); - polled_ctx_init(&app1->ctxs[0], 0, 1); - polled_ctx_init(&app1->ctxs[1], 1, 1); - polled_ctx_init(&app1->ctxs[2], 2, 1); + polled_vm_init(vm1, 1); + polled_ctx_init(&vm1->ctxs[0], 0, 1); + polled_ctx_init(&vm1->ctxs[1], 1, 1); + polled_ctx_init(&vm1->ctxs[2], 2, 1); ctx = malloc(sizeof(*ctx)); memset(ctx, 0, sizeof(*ctx)); @@ -379,76 +379,76 @@ void test_remove_multiple_ctx(void *arg) ctx->act_head = IDXLIST_INVAL; ctx->act_tail = IDXLIST_INVAL; - enqueue_ctx_to_active(app0, 0); - enqueue_ctx_to_active(app0, 1); - enqueue_ctx_to_active(app0, 2); - - enqueue_ctx_to_active(app1, 0); - enqueue_ctx_to_active(app1, 1); - enqueue_ctx_to_active(app1, 2); - - /* Remove contexts from app 0 */ - remove_ctx_from_active(app0, &app0->ctxs[1]); - test_assert("app0: ctx0 is head", app0->act_ctx_head == 0); - test_assert("app0: ctx2 is tail", app0->act_ctx_tail == 2); - test_assert("app0: ctx1 is not active", - (app0->ctxs[1].flags & FLAG_ACTIVE) == 0); - - remove_ctx_from_active(app0, &app0->ctxs[2]); - test_assert("app0: ctx0 is head", app0->act_ctx_head == 0); - test_assert("app0: ctx0 is tail", app0->act_ctx_tail == 0); - test_assert("app0: ctx2 is not active", - (app0->ctxs[2].flags & FLAG_ACTIVE) == 0); - - remove_ctx_from_active(app0, &app0->ctxs[0]); - test_assert("app0: head is invalid", app0->act_ctx_head == IDXLIST_INVAL); - test_assert("app0: tail is invalid", app0->act_ctx_tail == IDXLIST_INVAL); - test_assert("app0: ctx0 is not active", - (app0->ctxs[0].flags & FLAG_ACTIVE) == 0); - - /* Remove contexts from app 1 */ - remove_ctx_from_active(app1, &app1->ctxs[1]); - test_assert("app1: ctx0 is head", app1->act_ctx_head == 0); - test_assert("app1: ctx2 is tail", app1->act_ctx_tail == 2); - test_assert("app1: ctx1 is not active", - (app1->ctxs[1].flags & FLAG_ACTIVE) == 0); - - remove_ctx_from_active(app1, &app1->ctxs[2]); - test_assert("app1: ctx0 is head", app1->act_ctx_head == 0); - test_assert("app1: ctx0 is tail", app1->act_ctx_tail == 0); - test_assert("app1: ctx2 is not active", - (app1->ctxs[2].flags & FLAG_ACTIVE) == 0); - - remove_ctx_from_active(app1, &app1->ctxs[0]); - test_assert("app1: head is invalid", app1->act_ctx_head == IDXLIST_INVAL); - test_assert("app1: tail is invalid", app1->act_ctx_tail == IDXLIST_INVAL); - test_assert("app1: ctx0 is not active", - (app1->ctxs[0].flags & FLAG_ACTIVE) == 0); + enqueue_ctx_to_active(vm0, 0); + enqueue_ctx_to_active(vm0, 1); + enqueue_ctx_to_active(vm0, 2); + + enqueue_ctx_to_active(vm1, 0); + enqueue_ctx_to_active(vm1, 1); + enqueue_ctx_to_active(vm1, 2); + + /* Remove contexts from vm 0 */ + remove_ctx_from_active(vm0, &vm0->ctxs[1]); + test_assert("vm0: ctx0 is head", vm0->act_ctx_head == 0); + test_assert("vm0: ctx2 is tail", vm0->act_ctx_tail == 2); + test_assert("vm0: ctx1 is not active", + (vm0->ctxs[1].flags & FLAG_ACTIVE) == 0); + + remove_ctx_from_active(vm0, &vm0->ctxs[2]); + test_assert("vm0: ctx0 is head", vm0->act_ctx_head == 0); + test_assert("vm0: ctx0 is tail", vm0->act_ctx_tail == 0); + test_assert("vm0: ctx2 is not active", + (vm0->ctxs[2].flags & FLAG_ACTIVE) == 0); + + remove_ctx_from_active(vm0, &vm0->ctxs[0]); + test_assert("vm0: head is invalid", vm0->act_ctx_head == IDXLIST_INVAL); + test_assert("vm0: tail is invalid", vm0->act_ctx_tail == IDXLIST_INVAL); + test_assert("vm0: ctx0 is not active", + (vm0->ctxs[0].flags & FLAG_ACTIVE) == 0); + + /* Remove contexts from vm 1 */ + remove_ctx_from_active(vm1, &vm1->ctxs[1]); + test_assert("vm1: ctx0 is head", vm1->act_ctx_head == 0); + test_assert("vm1: ctx2 is tail", vm1->act_ctx_tail == 2); + test_assert("vm1: ctx1 is not active", + (vm1->ctxs[1].flags & FLAG_ACTIVE) == 0); + + remove_ctx_from_active(vm1, &vm1->ctxs[2]); + test_assert("vm1: ctx0 is head", vm1->act_ctx_head == 0); + test_assert("vm1: ctx0 is tail", vm1->act_ctx_tail == 0); + test_assert("vm1: ctx2 is not active", + (vm1->ctxs[2].flags & FLAG_ACTIVE) == 0); + + remove_ctx_from_active(vm1, &vm1->ctxs[0]); + test_assert("vm1: head is invalid", vm1->act_ctx_head == IDXLIST_INVAL); + test_assert("vm1: tail is invalid", vm1->act_ctx_tail == IDXLIST_INVAL); + test_assert("vm1: ctx0 is not active", + (vm1->ctxs[0].flags & FLAG_ACTIVE) == 0); } int main(int argc, char *argv[]) { int ret = 0; - if (test_subcase("enqueue app", test_enqueue_app, NULL)) + if (test_subcase("enqueue vm", test_enqueue_vm, NULL)) ret = 1; if (test_subcase("enqueue ctx", test_enqueue_ctx, NULL)) ret = 1; - if (test_subcase("remove app", test_remove_app, NULL)) + if (test_subcase("remove vm", test_remove_vm, NULL)) ret = 1; - if (test_subcase("remove app head", test_remove_app_head, NULL)) + if (test_subcase("remove vm head", test_remove_vm_head, NULL)) ret = 1; - if (test_subcase("remove app tail", test_remove_app_tail, NULL)) + if (test_subcase("remove vm tail", test_remove_vm_tail, NULL)) ret = 1; - if (test_subcase("remove app one elt", test_remove_app_one_elt, NULL)) + if (test_subcase("remove vm one elt", test_remove_vm_one_elt, NULL)) ret = 1; - if (test_subcase("remove mult apps", test_remove_multiple_apps, NULL)) + if (test_subcase("remove mult vm", test_remove_multiple_vms, NULL)) ret = 1; if (test_subcase("remove ctx", test_remove_ctx, NULL)) diff --git a/tests/tas_unit/fastpath.c b/tests/tas_unit/fastpath.c index 15127ce9..a7f4387e 100644 --- a/tests/tas_unit/fastpath.c +++ b/tests/tas_unit/fastpath.c @@ -29,7 +29,7 @@ #endif macaddr_t eth_addr; -void *tas_shm = (void *) 0; +void **vm_shm = (void *) 0; struct flextcp_pl_mem state_base; struct flextcp_pl_mem *fp_state = &state_base; @@ -47,7 +47,8 @@ struct qman_set_op { uint8_t flags; } qm_set_op = { .got_op = 0 }; -int qman_set(struct qman_thread *t, uint32_t app_id, uint32_t flow_id, uint32_t rate, uint32_t avail, +int tas_qman_set(struct qman_thread *t, uint32_t app_id, uint32_t flow_id, + uint32_t rate, uint32_t avail, uint16_t max_chunk, uint8_t flags) { qm_set_op.got_op = 1; diff --git a/tests/tas_unit/qman_rr.c b/tests/tas_unit/qman_rr.c index 8ca62aae..ff76f227 100644 --- a/tests/tas_unit/qman_rr.c +++ b/tests/tas_unit/qman_rr.c @@ -21,10 +21,10 @@ void test_qman_rr_base(void *arg) unsigned num; struct qman_thread *t; uint32_t avail; - int all_app1, all_app2, ret; + int all_vm1, all_vm2, ret; struct dataplane_context *ctx; uint16_t q_bytes[TEST_BATCH_SIZE]; - unsigned app_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; + unsigned vm_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; ret = rte_eal_init(3, arg); test_assert("rte_eal_init", ret > -1); @@ -32,56 +32,56 @@ void test_qman_rr_base(void *arg) // Allocate memory for one context in 1 core ctx = rte_calloc("context", 1, sizeof(ctx), 0); - ret = qman_thread_init(ctx); + ret = tas_qman_thread_init(ctx); test_assert("init qman thread", ret > -1); t = &ctx->qman; - // Set 1 packet for 4 flows in app 1 - qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 1 check app 1", avail == 64 * 4); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 1 check app 2", avail == 0); - - // Set 1 packet for 4 flows in app 2 - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 2 check app 1", avail == 64 * 4); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 2 check app 2", avail == 64 * 4); + // Set 1 packet for 4 flows in vm 1 + tas_qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 1 check vm 1", avail == 64 * 4); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 1 check vm 2", avail == 0); + + // Set 1 packet for 4 flows in vm 2 + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 2 check vm 1", avail == 64 * 4); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 2 check vm 2", avail == 64 * 4); num = TEST_BATCH_SIZE; - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app1 = (app_ids[0] == 1) && (app_ids[1] == 1) - && (app_ids[2] == 1) && (app_ids[3] == 1); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll poll app 1 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll poll app 1 check avail app 2", avail == 64 * 4); - test_assert("scheduled all packets from app 1", all_app1); - - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm1 = (vm_ids[0] == 1) && (vm_ids[1] == 1) + && (vm_ids[2] == 1) && (vm_ids[3] == 1); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll poll vm 1 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll poll vm 1 check avail vm 2", avail == 64 * 4); + test_assert("scheduled all packets from vm 1", all_vm1); + + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); num = TEST_BATCH_SIZE; - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app2 = (app_ids[0] == 2) && (app_ids[1] == 2) - && (app_ids[2] == 2) && (app_ids[3] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll poll app 2 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll poll app 2 check avail app 2", avail == 0); - test_assert("scheduled all packets from app 2", all_app2); - - qman_free_app_cont(ctx); + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm2 = (vm_ids[0] == 2) && (vm_ids[1] == 2) + && (vm_ids[2] == 2) && (vm_ids[3] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll poll vm 2 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll poll vm 2 check avail vm 2", avail == 0); + test_assert("scheduled all packets from vm 2", all_vm2); + + qman_free_vm_cont(ctx); rte_free(ctx); } @@ -89,10 +89,10 @@ void test_qman_rr_full_loop(void *arg) { struct qman_thread *t; uint32_t avail; - int all_app1, all_app2, ret; + int all_vm1, all_vm2, ret; struct dataplane_context *ctx; uint16_t q_bytes[TEST_BATCH_SIZE]; - unsigned app_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; + unsigned vm_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; unsigned num = TEST_BATCH_SIZE; ret = rte_eal_init(3, arg); @@ -101,92 +101,92 @@ void test_qman_rr_full_loop(void *arg) // Allocate memory for one context in 1 core ctx = rte_calloc("context", 1, sizeof(ctx), 0); - ret = qman_thread_init(ctx); + ret = tas_qman_thread_init(ctx); test_assert("init qman thread", ret > -1); t = &ctx->qman; - // Set 8 packets in app 1 - qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 1 check app 1", avail == 64 * 8); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 1 check app 2", avail == 0); - - // Set 8 packets in app 2 - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 5, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 2 check app 1", avail == 64 * 8); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 2 check app 2", avail == 64 * 8); + // Set 8 packets in vm 1 + tas_qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 1 check vm 1", avail == 64 * 8); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 1 check vm 2", avail == 0); + + // Set 8 packets in vm 2 + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 5, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 2 check vm 1", avail == 64 * 8); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 2 check vm 2", avail == 64 * 8); - // Poll and expect app 1 - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app1 = (app_ids[0] == 1) && (app_ids[1] == 1) - && (app_ids[2] == 1) && (app_ids[3] == 1); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (1) poll app 1 check avail app 1", avail == 64 * 4); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (1) poll app 1 check avail app 2", avail == 64 * 8); - test_assert("scheduled all packets from app 1", all_app1); - - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + // Poll and expect vm 1 + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm1 = (vm_ids[0] == 1) && (vm_ids[1] == 1) + && (vm_ids[2] == 1) && (vm_ids[3] == 1); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (1) poll vm 1 check avail vm 1", avail == 64 * 4); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (1) poll vm 1 check avail vm 2", avail == 64 * 8); + test_assert("scheduled all packets from vm 1", all_vm1); + + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); - // Poll and expect app 2 - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app2 = (app_ids[0] == 2) && (app_ids[1] == 2) - && (app_ids[2] == 2) && (app_ids[3] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (2) poll app 2 check avail app 1", avail == 64 * 4); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (2) poll app 2 check avail app 2", avail == 64 * 4); - test_assert("scheduled all packets from app 2", all_app2); - - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + // Poll and expect vm 2 + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm2 = (vm_ids[0] == 2) && (vm_ids[1] == 2) + && (vm_ids[2] == 2) && (vm_ids[3] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (2) poll vm 2 check avail vm 1", avail == 64 * 4); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (2) poll vm 2 check avail vm 2", avail == 64 * 4); + test_assert("scheduled all packets from vm 2", all_vm2); + + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); - // Poll and expect app 1 again - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app1 = (app_ids[0] == 1) && (app_ids[1] == 1) - && (app_ids[2] == 1) && (app_ids[3] == 1); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (3) poll app 1 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (3) poll app 1 check avail app 2", avail == 64 * 4); - test_assert("scheduled all packets from app 1", all_app1); - - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + // Poll and expect vm 1 again + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm1 = (vm_ids[0] == 1) && (vm_ids[1] == 1) + && (vm_ids[2] == 1) && (vm_ids[3] == 1); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (3) poll vm 1 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (3) poll vm 1 check avail vm 2", avail == 64 * 4); + test_assert("scheduled all packets from vm 1", all_vm1); + + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); - // Poll and expect app 2 again - qman_poll(t, num, app_ids, q_ids, q_bytes); - all_app2 = (app_ids[0] == 2) && (app_ids[1] == 2) - && (app_ids[2] == 2) && (app_ids[3] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (4) poll app 2 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (4) poll app 2 check avail app 2", avail == 0); - test_assert("scheduled all packets from app 2", all_app2); - - qman_free_app_cont(ctx); + // Poll and expect vm 2 again + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + all_vm2 = (vm_ids[0] == 2) && (vm_ids[1] == 2) + && (vm_ids[2] == 2) && (vm_ids[3] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (4) poll vm 2 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (4) poll vm 2 check avail vm 2", avail == 0); + test_assert("scheduled all packets from vm 2", all_vm2); + + qman_free_vm_cont(ctx); rte_free(ctx); } @@ -196,7 +196,7 @@ void test_qman_rr_mix_round(void *arg) { int packs_exp, ret; struct dataplane_context *ctx; uint16_t q_bytes[TEST_BATCH_SIZE]; - unsigned app_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; + unsigned vm_ids[TEST_BATCH_SIZE], q_ids[TEST_BATCH_SIZE]; unsigned num = TEST_BATCH_SIZE; ret = rte_eal_init(3, arg); @@ -205,72 +205,72 @@ void test_qman_rr_mix_round(void *arg) { // Allocate memory for one context in 1 core ctx = rte_calloc("context", 1, sizeof(ctx), 0); - ret = qman_thread_init(ctx); + ret = tas_qman_thread_init(ctx); test_assert("init qman thread", ret > -1); t = &ctx->qman; - // Set 8 packets in app 1 - qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 1 check app 1", avail == 64 * 3); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 1 check app 2", avail == 0); - - // Set 8 packets in app 2 - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); - - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_set set app 2 check app 1", avail == 64 * 3); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_set set app 2 check app 2", avail == 64 * 6); + // Set 8 packets in vm 1 + tas_qman_set(t, 1, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 1, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 1 check vm 1", avail == 64 * 3); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 1 check vm 2", avail == 0); + + // Set 8 packets in vm 2 + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 1, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 2, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 3, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + tas_qman_set(t, 2, 0, 0, 64, TEST_TCP_MSS, QMAN_ADD_AVAIL | QMAN_SET_MAXCHUNK); + + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_set set vm 2 check vm 1", avail == 64 * 3); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_set set vm 2 check vm 2", avail == 64 * 6); - // Poll and expect app 1 and 2 - qman_poll(t, num, app_ids, q_ids, q_bytes); - packs_exp = (app_ids[0] == 1) && (app_ids[1] == 1) - && (app_ids[2] == 1) && (app_ids[3] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (1) poll app 1 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (1) poll app 1 check avail app 2", avail == 64 * 5); + // Poll and expect vm 1 and 2 + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + packs_exp = (vm_ids[0] == 1) && (vm_ids[1] == 1) + && (vm_ids[2] == 1) && (vm_ids[3] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (1) poll vm 1 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (1) poll vm 1 check avail vm 2", avail == 64 * 5); test_assert("qman poll (1) check correct packets scheduled", packs_exp); - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); - // Poll and expect app 2 - qman_poll(t, num, app_ids, q_ids, q_bytes); - packs_exp = (app_ids[0] == 2) && (app_ids[1] == 2) - && (app_ids[2] == 2) && (app_ids[3] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (2) poll app 2 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (2) poll app 2 check avail app 2", avail == 64); + // Poll and expect vm 2 + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + packs_exp = (vm_ids[0] == 2) && (vm_ids[1] == 2) + && (vm_ids[2] == 2) && (vm_ids[3] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (2) poll vm 2 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (2) poll vm 2 check avail vm 2", avail == 64); test_assert("qman poll (2) check correct packets scheduled", packs_exp); - memset(app_ids, 0, sizeof(*app_ids) * TEST_BATCH_SIZE); + memset(vm_ids, 0, sizeof(*vm_ids) * TEST_BATCH_SIZE); memset(q_ids, 0, sizeof(*q_ids) * TEST_BATCH_SIZE); memset(q_bytes, 0, sizeof(*q_bytes) * TEST_BATCH_SIZE); - // Poll and expect app 2 again - qman_poll(t, num, app_ids, q_ids, q_bytes); - packs_exp = (app_ids[0] == 2); - avail = qman_app_get_avail(ctx, 1); - test_assert("qman_poll (3) poll app 1 check avail app 1", avail == 0); - avail = qman_app_get_avail(ctx, 2); - test_assert("qman_poll (3) poll app 1 check avail app 2", avail == 0); + // Poll and expect vm 2 again + tas_qman_poll(ctx, num, vm_ids, q_ids, q_bytes); + packs_exp = (vm_ids[0] == 2); + avail = qman_vm_get_avail(ctx, 1); + test_assert("qman_poll (3) poll vm 1 check avail vm 1", avail == 0); + avail = qman_vm_get_avail(ctx, 2); + test_assert("qman_poll (3) poll vm 1 check avail vm 2", avail == 0); test_assert("qman poll (3) check correct packets scheduled", packs_exp); - qman_free_app_cont(ctx); + qman_free_vm_cont(ctx); rte_free(ctx); } diff --git a/tests/tas_unit/shmring.c b/tests/tas_unit/shmring.c new file mode 100644 index 00000000..84f93ea2 --- /dev/null +++ b/tests/tas_unit/shmring.c @@ -0,0 +1,469 @@ +#include +#include +#include +#include + +#include "../testutils.h" +#include "../../proxy/shmring.h" + + +void test_reset_ring() +{ + void *base_addr; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + test_assert("read_pos reset", hdr->read_pos == 0); + test_assert("write_pos reset", hdr->write_pos == 0); + test_assert("full set to not full", hdr->full == 0); + test_assert("ring size set", hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); +} + +void test_push_ring() +{ + int ret; + void *base_addr, *msg; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = 10; + msg = malloc(write_sz); + + ret = shmring_push(ring, msg, write_sz); + test_assert("returned correct number of bytes written", + ret == write_sz); + test_assert("write_pos updated", hdr->write_pos == write_sz); + test_assert("read not updated", hdr->read_pos == 0); + test_assert("ring is not full", hdr->full == 0); + test_assert("hdr_size stayed the same", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(msg); +} + +void test_push_full_ring() +{ + int ret; + void *base_addr, *msg; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = RING_SIZE - hdr_size; + msg = malloc(write_sz); + + ret = shmring_push(ring, msg, write_sz); + test_assert("returned correct number of bytes written", + ret == write_sz); + test_assert("write_pos updated", hdr->write_pos == 0); + test_assert("read not updated", hdr->read_pos == 0); + test_assert("ring is full", hdr->full == 1); + test_assert("hdr_size stayed the same", + hdr->ring_size == (RING_SIZE - hdr_size)); + + ret = shmring_push(ring, msg, 1); + test_assert("write to full ring failed", ret == 0); + test_assert("write_pos not updated", hdr->write_pos == 0); + test_assert("read not updated", hdr->read_pos == 0); + test_assert("ring is still full", hdr->full == 1); + test_assert("hdr_size still stayed the same", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(msg); +} + +void test_fragmented_push() +{ + int ret; + void *base_addr, *msg, *dst; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = RING_SIZE - hdr_size - 5; + msg = malloc(write_sz); + ret = shmring_push(ring, msg, write_sz); + + test_assert("returned correct number of bytes written", + ret == write_sz); + test_assert("write_pos updated", hdr->write_pos == write_sz); + test_assert("read not updated", hdr->read_pos == 0); + test_assert("ring is full", hdr->full == 0); + test_assert("hdr_size stayed the same", + hdr->ring_size == (RING_SIZE - hdr_size)); + + size_t read_sz = 10; + dst = malloc(read_sz); + shmring_pop(ring, dst, read_sz); + + size_t fwrite_sz = 8; + assert(fwrite_sz < write_sz); + ret = shmring_push(ring, msg, fwrite_sz); + + test_assert("returned correct number of bytes written for frag write", + ret == fwrite_sz); + test_assert("write_pos updated for frag write", + hdr->write_pos == 3); + test_assert("read not updated for frag write", hdr->read_pos == read_sz); + test_assert("ring is not full", hdr->full == 0); + test_assert("hdr_size stayed the same for frag write", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(msg); + free(dst); +} + + +void test_pop_ring() +{ + int ret; + void *base_addr; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + uint8_t write_msg[3] = {0, 1, 2}; + uint8_t *dst; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = 3; + shmring_push(ring, write_msg, write_sz); + + dst = malloc(write_sz); + ret = shmring_pop(ring, dst, write_sz); + + test_assert("returned correct number of bytes read", ret == write_sz); + test_assert("read did not update write pos", hdr->write_pos == write_sz); + test_assert("read pos updated", hdr->read_pos == write_sz); + test_assert("ring is not full", hdr->full == 0); + test_assert("values are correct", + dst[0] == 0 && dst[1] == 1 && dst[2] == 2); + test_assert("ring size stayed the same after read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(dst); +} + +void test_pop_too_large() +{ + int ret; + void *base_addr, *write_msg; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + uint8_t *dst; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = 3; + write_msg = malloc(write_sz); + shmring_push(ring, write_msg, write_sz); + + size_t read_sz = 4; + dst = malloc(read_sz); + ret = shmring_pop(ring, dst, read_sz); + + test_assert("returned no bytes read", ret == 0); + test_assert("read did not update write pos", hdr->write_pos == write_sz); + test_assert("read pos was not updated", hdr->read_pos == 0); + test_assert("ring is not full", hdr->full == 0); + test_assert("ring size stayed the same after read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(write_msg); + free(dst); +} + +void test_pop_empty_ring() +{ + int ret; + void *base_addr, *write_msg; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + size_t msg_sz = 4; + uint8_t *dst; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + dst = malloc(msg_sz); + ret = shmring_pop(ring, dst, msg_sz); + + test_assert("returned no bytes read", ret == 0); + test_assert("read did not update write pos", hdr->write_pos == 0); + test_assert("read pos was not updated", hdr->read_pos == 0); + test_assert("ring is not full", hdr->full == 0); + test_assert("ring size stayed the same after read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + write_msg = malloc(msg_sz); + shmring_push(ring, write_msg, msg_sz); + shmring_pop(ring, dst, msg_sz); + + ret = shmring_pop(ring, dst, msg_sz); + + test_assert("second empty read returned no bytes", ret == 0); + test_assert("second empty read did not update write pos", + hdr->write_pos == msg_sz); + test_assert("second empty read pos was not updated", + hdr->read_pos == msg_sz); + test_assert("ring is not full after second empty read", + hdr->full == 0); + test_assert("ring size stayed the same after second empty read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(write_msg); + free(dst); +} + +void test_pop_ring_till_empty() +{ + int ret; + void *base_addr, *msg, *dst; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = RING_SIZE - hdr_size; + msg = malloc(write_sz); + shmring_push(ring, msg, write_sz); + + dst = malloc(write_sz); + ret = shmring_pop(ring, dst, write_sz); + test_assert("returned correct number of bytes read", ret == write_sz); + test_assert("read did not update write pos", hdr->write_pos == 0); + test_assert("read pos updated", hdr->read_pos == 0); + test_assert("ring is not full", hdr->full == 0); + test_assert("ring size stayed the same after read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + ret = shmring_pop(ring, dst, 1); + test_assert("returned no read bytes", ret == 0); + test_assert("second read did not update write pos", + hdr->write_pos == 0); + test_assert("read pos not updated", hdr->read_pos == 0); + test_assert("ring is still not full", hdr->full == 0); + test_assert("ring size stayed the same after second read", + hdr->ring_size == (RING_SIZE - hdr_size)); + +} + +void test_fragmented_pop() +{ + int ret; + void *base_addr, *jumbled_msg; + struct ring_buffer *ring; + struct ring_header *hdr; + size_t RING_SIZE = 100; + uint8_t write_msg[3] = {0, 1, 2}; + uint8_t *read_msg; + uint8_t *dst; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + hdr = ring->hdr_addr; + + size_t write_sz = RING_SIZE - hdr_size - 1; + jumbled_msg = malloc(write_sz); + shmring_push(ring, write_msg, write_sz); + dst = malloc(write_sz); + shmring_pop(ring, dst, write_sz); + shmring_push(ring, write_msg, 3); + + read_msg = malloc(3); + ret = shmring_pop(ring, read_msg, 3); + + test_assert("returned correct number of bytes read", ret = 3); + test_assert("read did not update write pos", hdr->write_pos == 2); + test_assert("read pos got updated", hdr->read_pos == 2); + test_assert("ring is not full", hdr->full == 0); + test_assert("values are correct", + read_msg[0] == 0 && read_msg[1] == 1 && read_msg[2] == 2); + test_assert("ring size statyed the same after read", + hdr->ring_size == (RING_SIZE - hdr_size)); + + free(base_addr); + free(dst); + free(read_msg); + free(jumbled_msg); +} + +void test_ring_is_empty() +{ + int ret; + void *base_addr, *msg, *dst; + struct ring_buffer *ring; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + + ret = shmring_is_empty(ring); + test_assert("ring is empty after initialization", ret); + + size_t hdr_size = sizeof(struct ring_header); + msg = malloc(RING_SIZE - hdr_size); + dst = malloc(RING_SIZE - hdr_size); + + shmring_push(ring, msg, 10); + ret = shmring_is_empty(ring); + test_assert("ring is not empty after pushing one message", ret == 0); + + shmring_pop(ring, dst, 10); + ret = shmring_is_empty(ring); + test_assert("ring is empty after pushing and popping message", ret); + + shmring_push(ring, msg, RING_SIZE - hdr_size); + ret = shmring_is_empty(ring); + test_assert("ring is not empty when full", ret == 0); + + shmring_pop(ring, dst, RING_SIZE - hdr_size); + ret = shmring_is_empty(ring); + test_assert("ring is empty after being full and popped completely", ret); + + shmring_push(ring, msg, RING_SIZE - hdr_size); + shmring_pop(ring, dst, 10); + shmring_push(ring, msg, 5); + ret = shmring_is_empty(ring); + test_assert("ring is not empty when write_pos < read_pos", ret == 0); +} + +void test_ring_get_freesz() +{ + int ret; + void *base_addr, *msg, *dst; + struct ring_buffer *ring; + size_t RING_SIZE = 100; + + base_addr = malloc(RING_SIZE); + ring = shmring_init(base_addr, RING_SIZE); + shmring_reset(ring, RING_SIZE); + size_t hdr_size = sizeof(struct ring_header); + + ret = shmring_get_freesz(ring); + test_assert("get free size after initialization", + ret == RING_SIZE - hdr_size); + + msg = malloc(RING_SIZE - hdr_size); + dst = malloc(RING_SIZE - hdr_size); + + shmring_push(ring, msg, 10); + ret = shmring_get_freesz(ring); + test_assert("get free size after pushing one message", + ret == RING_SIZE - hdr_size - 10); + + shmring_pop(ring, dst, 10); + ret = shmring_get_freesz(ring); + test_assert("get free size after pushing and popping message", + ret == RING_SIZE - hdr_size); + + shmring_push(ring, msg, RING_SIZE - hdr_size); + ret = shmring_get_freesz(ring); + test_assert("get free size when full", ret == 0); + + shmring_pop(ring, dst, RING_SIZE - hdr_size); + ret = shmring_get_freesz(ring); + test_assert("get free size after being full and popped completely", + ret == RING_SIZE - hdr_size); + + shmring_push(ring, msg, RING_SIZE - hdr_size); + shmring_pop(ring, dst, 10); + shmring_push(ring, msg, 5); + ret = shmring_get_freesz(ring); + test_assert("get free size when write_pos < read_pos", ret == 5); +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + + if (test_subcase("reset ring", test_reset_ring, NULL)) + ret = 1; + + if (test_subcase("push ring", test_push_ring, NULL)) + ret = 1; + + if (test_subcase("push full ring", test_push_full_ring, NULL)) + ret = 1; + + if (test_subcase("push frag write to ring", test_fragmented_push, NULL)) + ret = 1; + + if (test_subcase("pop ring", test_pop_ring, NULL)) + ret = 1; + + if (test_subcase("pop too large", test_pop_too_large, NULL)) + ret = 1; + + if (test_subcase("pop empty ring", test_pop_empty_ring, NULL)) + ret = 1; + + if (test_subcase("pop ring until empty", test_pop_ring_till_empty, NULL)) + ret = 1; + + if (test_subcase("pop frag write to ring", test_fragmented_pop, NULL)) + ret = 1; + + if (test_subcase("ring is empty check", test_ring_is_empty, NULL)) + ret = 1; + + if (test_subcase("get free size", test_ring_get_freesz, NULL)) + ret = 1; + + + return ret; +} \ No newline at end of file