diff --git a/iperf/.gitignore b/iperf/.gitignore new file mode 100644 index 0000000..8c2bef2 --- /dev/null +++ b/iperf/.gitignore @@ -0,0 +1,3 @@ +iperf/ +install/ +/*.tar.gz diff --git a/iperf/Makefile b/iperf/Makefile new file mode 100644 index 0000000..666c993 --- /dev/null +++ b/iperf/Makefile @@ -0,0 +1,68 @@ +# Copyright (C) 2024 Gramine contributors +# SPDX-License-Identifier: BSD-3-Clause + +ARCH_LIBDIR ?= /lib/$(shell $(CC) -dumpmachine) + +IPERF_DIR = iperf +IPERF_SHA256 ?= cc740c6bbea104398cc3e466befc515a25896ec85e44a662d5f4a767b9cf713e +IPERF_SRC ?= iperf-3.16.tar.gz +IPERF_MIRRORS ?= https://github.com/esnet/iperf/releases/download/3.16 + +ifeq ($(DEBUG),1) +GRAMINE_LOG_LEVEL = debug +else +GRAMINE_LOG_LEVEL = error +endif + +.PHONY: all +all: install/iperf3 install/libiperf.so.0 iperf3.manifest +ifeq ($(SGX),1) +all: iperf3.manifest.sgx iperf3.sig +endif + +$(IPERF_DIR)/configure: + ../common_tools/download --output $(IPERF_SRC) --sha256 $(IPERF_SHA256) \ + $(foreach mirror,$(IPERF_MIRRORS),--url $(mirror)/$(IPERF_SRC)) + mkdir $(IPERF_DIR) + tar -C $(IPERF_DIR) --strip-components=1 -xf $(IPERF_SRC) + +$(IPERF_DIR)/src/.libs/iperf3: $(IPERF_DIR)/configure + cd $(IPERF_DIR) && ./configure + $(MAKE) -C $(IPERF_DIR) + +iperf3.manifest: iperf3.manifest.template + gramine-manifest \ + -Dlog_level=$(GRAMINE_LOG_LEVEL) \ + -Darch_libdir=$(ARCH_LIBDIR) \ + $< > $@ + +# Make on Ubuntu <= 20.04 doesn't support "Rules with Grouped Targets" (`&:`), +# see the helloworld example for details on this workaround. +iperf3.sig iperf3.manifest.sgx: sgx_sign + @: + +.INTERMEDIATE: sgx_sign +sgx_sign: iperf3.manifest $(IPERF_DIR)/src/.libs/iperf3 + gramine-sgx-sign \ + --manifest $< \ + --output $<.sgx + +# for simplicity, copy iperf3 executable into our install directory +install/iperf3: $(IPERF_DIR)/src/.libs/iperf3 + mkdir -p install + cp $< $@ + +# for simplicity, copy libiperf library into our install directory +install/libiperf.so.0: $(IPERF_DIR)/src/.libs/libiperf.so.0 + mkdir -p install + cp $< $@ + +################################## CLEANUP #################################### + +.PHONY: clean +clean: + $(RM) -r *.token *.sig *.manifest.sgx *.manifest install + +.PHONY: distclean +distclean: clean + $(RM) -r $(IPERF_DIR) *.tar.gz diff --git a/iperf/README.md b/iperf/README.md new file mode 100644 index 0000000..2b3bb59 --- /dev/null +++ b/iperf/README.md @@ -0,0 +1,86 @@ +# iperf + +This directory contains the Makefile and the template manifest for the most +recent version of `iperf` as of this writing (3.16). + +# Prerequisites + +`iperf` has no prerequisites +([source](https://github.com/esnet/iperf/tree/3.16?tab=readme-ov-file#prerequisites)). + +# Building instructions + +We build `iperf` from source because Ubuntu 22.04 has `iperf3` v3.9 in its +package repositories which is built with `TCP_CONGESTION` requirement (i.e., +with `iperf3_cv_header_tcp_congestion="yes"` config option). Using the Ubuntu +package would fail with the following error: +``` +iperf3: error - unable to set TCP_CONGESTION: ... +``` + +Thus we build `iperf` manually. In this case, it is built without +`TCP_CONGESTION`, and can successfully execute under Gramine[^1]. + +[^1]: Starting from version 3.10, `iperf` supports environments that do not +implement congestion control algorithm. Thus, iperf 3.10+ prebuilt packages +should work under Gramine without problems. See [release +notes](https://github.com/esnet/iperf/blob/3.16/RELNOTES.md#iperf-310-2021-05-26) +for details. + + +## Building for Linux + +Run `make` in the current directory. + +## Building for SGX + +Run `make SGX=1` (non-debug) or `make SGX=1 DEBUG=1` (debug) in the current +directory. + +# Execution instructions + +Run `iperf` server natively: +``` +LD_LIBRARY_PATH=./install ./install/iperf3 -s +``` + +Run `iperf` server in Gramine without SGX: +``` +gramine-direct iperf3 +``` + +Run `iperf` server in Gramine with SGX: +``` +gramine-sgx iperf3 +``` + +To get measurements with the `iperf` client, run in another terminal: +``` +LD_LIBRARY_PATH=./install ./install/iperf3 -c localhost -p 5201 +``` + +# Useful iperf options + +(The options may be version-dependent. Below are the options for v3.16.) + +## Generic options (both for server and client): +- `-p, --port`: server port to listen on/connect to +- `--forceflush`: force flushing output at every interval +- `-d, --debug[=#]`: emit debugging output (optional "=" and debug level: 1-4) + +## Server-specific options: +- `-s, --server`: run in server mode +- `-1, --one-off`: handle one client connection then exit +- `--idle-timeout #`: restart idle server after # seconds in case it got stuck + +## Client-specific options: +- `-c, --client `: run in client mode, connecting to `` +- `-t, --time #`: time in seconds to transmit for (default 10 secs) +- `-n, --bytes #[KMG]`: number of bytes to transmit (instead of -t) +- `-P, --parallel #`: number of parallel client streams to run +- `-N, --no-delay`: set TCP/SCTP no delay, disabling Nagle's Algorithm + +# Notes +- Tested on Ubuntu 22.04. +- In the execution instructions, we use port `5201` for the client. + This is the default port used by `iperf`. diff --git a/iperf/iperf3.manifest.template b/iperf/iperf3.manifest.template new file mode 100644 index 0000000..26a6972 --- /dev/null +++ b/iperf/iperf3.manifest.template @@ -0,0 +1,43 @@ +# Copyright (C) 2024 Gramine contributors +# SPDX-License-Identifier: BSD-3-Clause + +# iperf3 manifest file example + +loader.entrypoint = "file:{{ gramine.libos }}" +libos.entrypoint = "/install/iperf3" + +loader.log_level = "{{ log_level }}" + +# Hardcode the argument to run the iperf3 server inside Gramine +loader.argv = ["/install/iperf3", "-s"] + +loader.env.LD_LIBRARY_PATH = "/install:/lib:{{ arch_libdir }}:/usr/{{ arch_libdir }}" + +sys.enable_sigterm_injection = true + +fs.mounts = [ + { path = "/lib", uri = "file:{{ gramine.runtimedir() }}" }, + { path = "{{ arch_libdir }}", uri = "file:{{ arch_libdir }}" }, + { path = "/usr/{{ arch_libdir }}", uri = "file:/usr/{{ arch_libdir }}" }, + { type = "tmpfs", path = "/tmp"}, + + # Mount iperf3 executable and libiperf (located in the install directory) + # in Gramine under the /install directory. + { path = "/install/iperf3", uri = "file:install/iperf3" }, + { path = "/install/libiperf.so.0", uri = "file:install/libiperf.so.0" }, +] + +sgx.edmm_enable = {{ 'true' if env.get('EDMM', '0') == '1' else 'false' }} +# iperf3 is single threaded; we choose 4 to accommodate Gramine additional +# threads for IPC and asynchronous events/alarms. +sgx.max_threads = {{ '1' if env.get('EDMM', '0') == '1' else '4' }} +sgx.enclave_size = "1024M" + +sgx.trusted_files = [ + "file:install/iperf3", + "file:install/libiperf.so.0", + "file:{{ gramine.runtimedir() }}/", + "file:{{ arch_libdir }}/", + "file:/usr/{{ arch_libdir }}/", + "file:{{ gramine.libos }}", +]