Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iperf example #87

Merged
merged 1 commit into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions iperf/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
iperf/
install/
/*.tar.gz
68 changes: 68 additions & 0 deletions iperf/Makefile
Original file line number Diff line number Diff line change
@@ -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
86 changes: 86 additions & 0 deletions iperf/README.md
Original file line number Diff line number Diff line change
@@ -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 <host>`: run in client mode, connecting to `<host>`
- `-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`.
43 changes: 43 additions & 0 deletions iperf/iperf3.manifest.template
Original file line number Diff line number Diff line change
@@ -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 }}",
]