Skip to content

Commit

Permalink
Add TODOs and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
sujayakar committed Mar 31, 2021
1 parent 2c88ca0 commit 4137dad
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 17 deletions.
19 changes: 10 additions & 9 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,21 @@ These instructions are for setting up a clean build of Demeter on a clean instal
## Building

- On Debian systems, run `scripts/setup/debian.sh` to install prerequisites.
- Install Rust nightly. Run 'curl https://sh.rustup.rs -sSf | sh'
- You need to use a nightly build of Rust. Currently, the build is only tested to work with `nightly-2020-05-14`. You can install this by running `rustup override set nightly-2020-05-14` from the `src/rust` directory.
- Make a directory for the build. We suggest `$DATACENTEROS/build/debug` or `$DATACENTEROS/build/release`.
- Install Rustup, Rust's toolchain manager. Run 'curl https://sh.rustup.rs -sSf | sh'
- Make a directory for the build. We suggest `$REPO_ROOT:/build`.
- Run CMake from the build directory, passing the source directory in as an argument.
- Set the `CMAKE_BUILD_TYPE` variable to `Release` if you want an optimized build. You can do this with the CLI (`ccmake`) or the GUI (`cmake-gui`).
- Set the `DPDK_MLX4_SUPPORT` and/or `DPDK_MLX5_SUPPORT` option to `ON` if you need DPDK compiled with support for Mellanox NICs.
- Run `make` from the build directory.
- Run `make dpdk` from the build directory.
- Run `make` after DPDK has finished building.

### Cleaning

- You can clean the build by deleting the build directory and starting over.
- You can clean the build by deleting the build directory and starting over. Be sure that all of the submodules' repos are clean too.
- Run `scripts/build/clean.sh` to thouroughly clean the repository. Be warned that this will delete any untracked files that you have not yet staged.

## Configuring

The Demikernel libOSes and apps are configured through a config.yaml file. You can find an example in `src/c++/config.yaml`
The Demikernel libOSes and apps are configured through a config.yaml file. You can find an example in `$REPO_ROOT:/config.yaml`

DPDK requires a white list to ensure that it does not co-opt all of your network connections. Use 'ifconfig' to find the name of your DPDK network device, then 'ethtool -i' to find the PCI bus ID. Update the PCI bus ID in the eal args in your config.yaml file.

Expand All @@ -45,6 +44,9 @@ In addition, some system-wide configuration needs to be performed before DPDK wi
- Specify the number of pages for each node (e.g. `1024`).
- Once at the menu, select *Exit Script* (option `33`).

### SPDK initialization
Be sure to run the SPDK setup script if you're using SPDK: `$REPO_ROOT:/submodules/spdk/scripts/setup.sh`.

## Building on Azure

### VM Creation
Expand All @@ -65,7 +67,7 @@ az network nic create --resource-group centigo --name cassance596 --vnet-name ce
1. Clone git repo with recurse-submodules flag.
2. Install Azure packages by running `script/setup/ubuntu-azure.sh`.
3. Create a build directory, I use 'demikernel/build'.
4. Turn on Azure support and CX5 support by running `cmake -DAZURE_SUPPORT=ON -DDPDK_MLX5_SUPPORT=ON -DCMAKE_BUILD_TYPE=Release ..` in your build directory or using `ccmake ..` and setting the cmake flags manually.
4. Turn on Azure support and CX5 support by running `cmake -DAZURE_SUPPORT=ON -DDPDK_MLX5_SUPPORT=ON -DCMAKE_BUILD_TYPE=Release ..` in your build directory or using `ccmake ..` and setting the cmake flags manually.
5. Compile DPDK by running 'make dpdk' in the build directory. After this you should be able to run the testpmd single sender & receiver test below.
6. Use config options from testpmd in the config.yaml file. The DPDK interface is usually the slave interface listed first by `ifconfig`. Using that interface id, run `ethtool -i` to find your PCI ID.
7. Don't forget to turn on hugepage support and run as root. Running `scripts/setup/dpdk.sh` will turn on huge page support and install needed kernel modules.
Expand Down Expand Up @@ -93,4 +95,3 @@ testpmd -l 0-3 -n 1 -w aa89:00:02.0 --vdev="net_vdev_netvsc0,iface=eth1" -- --po

- [Set up DPDK in a Linux virtual machine](https://docs.microsoft.com/en-us/azure/virtual-network/setup-dpdk).
- [Create a Linux virtual machine with Accelerated Networking](https://docs.microsoft.com/en-us/azure/virtual-network/create-vm-accelerated-networking-cli).

52 changes: 52 additions & 0 deletions TODOs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Build
- [ ] Building DPDK creates src/ and tmp/ directories under submodules/dpdk instead of in the build
directory (build/ExternalProject/dpdk). These directories causes `make dpdk` to fail if the
developer deletes the build directory and starts from a fresh state.
- [ ] The DPDK dependency management doesn't work: The developer has to call `make dpdk` before
doing any other build (e.g. `make catnip-libos-echo`).
- [ ] Both [SPDK](https://github.com/sujayakar/spdk-rs) and [DPDK](https://github.com/sujayakar/dpdk-rs)
require calls to `load_pcie_driver` and `load_mlx5_driver`, respectively. If we
could get Cargo to pass `--no-as-needed` and `-rpath` to the linker, the developer
would not need to call this function and set the `LD_LIBRARY_PATH` environment
variable for Rust builds. See [this section](https://github.com/sujayakar/dpdk-rs#shortcomings)
repo for more details.

# Catnip
- [ ] Add some warnings when it's been too long since the user entered the kernel. I spent a lot of
time debugging spurious retransmissions that were killing throughput when really the issue was
that the application had been hogging the CPU for ~100ms.
- [ ] Generalize DPDK memory management. Currently, we only use zero-copy when the application
allocates data within a pretty small range (default: 1kb-9kb). Instead, we should use DPDK
external memory and use a standard memory allocator on a large region of virtual memory pinned
and registered with DPDK.
- [ ] Clean up the ARP code, which predates the Catnip rewrite and just needs a rewrite itself.

- [ ] Pull out the C API into a separate crate that then calls into a LibOS layer
- [ ] Lift up the LibOS layer to be the public Rust interface
- [ ] Create a "module" trait that lets the developer dynamically install DPDK, SPDK, and RDMA at
runtime. The file table maps file descriptors to a module, which then implements all of the
LibOS interface.
- A Rust Catnip application would link against the LibOS crate and create an empty LibOS with
no modules loaded at initialization time.
- Then, it'd additionally link against the DPDK crate and create a `DPDKRuntime`, passing that
to the Catnip UDP and TCP stacks, which are then dynamically loaded into the LibOS.
- The application could also initialize SPDK, initialize a module implementing the LibOS API
for storage, and then load that in as well.

- [ ] SPDK support: There's a prototype on the `spdk-build` branch that has the bindings and
operations working but fakes the LibOS integration.

- [ ] RDMA support

- [ ] Integration testing for the TCP stack
- [ ] Add a simulation test that sets up two peers and sends some data back and forth.
- [ ] Assert some invariants about the execution (e.g. all data eventually makes it)
- [ ] Psuedorandomly introduce faults (packet drops, reordering) and check that our
invariants still hold.
- [ ] Check protocol state coverage.

# C++
- [ ] LWIP build is currently broken: `dmtr_sgalloc` and `dmtr_sgafree` need to be implemented in C
for all of the C++ queue implementations.
- [ ] Fix TCP and UDP echo server applications -- they have some memory unsafety with their
memory management for the scatter gather arrays.
24 changes: 17 additions & 7 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,30 @@

client:
connect_to:
host: 192.168.1.1
host: 198.19.200.5
port: 12345
client:
host: 198.19.200.3
port: 12345
server:
bind:
host: 192.168.1.1
host: 198.19.200.5
port: 12345
client:
host: 198.19.200.3
port: 12345
catnip:
my_ipv4_addr: 192.168.1.1
my_ipv4_addr: 198.19.200.3
arp_table:
"24:8a:07:50:95:08": 192.168.1.1
disable_arp: false
"b8:83:03:70:88:a0": 198.19.200.4
"b8:83:03:70:98:44": 198.19.200.5
"b8:83:03:70:88:98": 198.19.200.6
"b8:83:03:70:98:9c": 198.19.200.7
"b8:83:03:79:af:2c": 198.19.200.8
"b8:83:03:79:af:38": 198.19.200.9
dpdk:
# eal_init: ["-l", "0-3", "-n", "1", "-w", "aa89:00:02.0", "--vdev=net_vdev_netvsc0,iface=eth1"]
eal_init: ["-c", "0xff", "-n", "4", "-w", "03:00.1","--proc-type=auto"]
eal_init: ["-c", "0xff", "-n", "4", "-w", "37:00.0","--proc-type=auto"]
#spdk:
# transport: "PCIe"
# devAddr: ""
Expand All @@ -25,5 +35,5 @@ lwip:
known_hosts:
"24:8a:07:50:95:08": 192.168.1.1
"50:6b:4b:48:f8:f2": 192.168.1.2

# vim: set tabstop=2 shiftwidth=2
2 changes: 2 additions & 0 deletions scripts/setup/debian.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ repo_root=$(git rev-parse --show-toplevel)

apt-get -y install $APT_PACKAGES

pip3 install pyelftools ninja meson

$SHELL ${repo_root}/submodules/spdk/scripts/pkgdep.sh
3 changes: 2 additions & 1 deletion src/rust/catnip_libos/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ To build this crate outside of the CMake build, you need to set the `PKG_CONFIG_

For example,
```
~/src/demikernel/src/rust/catnip_libos $ LD_LIBRARY_PATH=~/src/dpdk/install/lib/x86_64-linux-gnu PKG_CONFIG_PATH=~/src/dpdk/install/lib/x86_64-linux-gnu/pkgconfig cargo test mbuf
~/src/demikernel/src/rust/catnip_libos $ LD_LIBRARY_PATH=~/src/dpdk/build/ExternalProject/dpdk/lib PKG_CONFIG_PATH=/src/dpdk/build/ExternalProject/dpdk/lib/pkgconfig cargo test mbuf
```

Similarly, running a binary outside of Cargo will require setting `LD_LIBRARY_PATH` as well.
138 changes: 138 additions & 0 deletions src/rust/experiments/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Rust implementations of our latency and throughput experiments
This crate includes simple echo servers that use both Catnip's TCP and UDP stacks as well as
directly implementing UDP on top of DPDK.

- `{tcp,udp,raw_udp}_echo.rs`: Closed loop echo application with a single client
- `{tcp,udp,raw_udp}_throughput.rs`: Server that returns whatever's sent to it (and for TCP accepts
any number of connections), continuously logging throughput, with multiple clients that
periodically log latency histograms.

As with the `catnip_libos` crate, be sure to set `PKG_CONFIG_PATH` and `LD_LIBRARY_PATH` when
building and running these experiments.

## Table 2 (latency for 64 byte messages)
### Catnip/UDP
Client:
```
root@prometheus3:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=64 USE_JUMBO=1 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/udp_echo ~/config3.yaml
```
Server:
```
root@prometheus5:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=64 USE_JUMBO=1 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/udp_echo ~/config5.yaml
```

### Catnip/TCP
Client:
```
root@prometheus3:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=64 USE_JUMBO=1 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/tcp_echo ~/config3.yaml
```
Server:
```
root@prometheus5:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=64 USE_JUMBO=1 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/tcp_echo ~/config5.yaml
```

## Table 3 (latency for 64 bytes messages with logging)
See the `spdk-build` branch.

## Figure 4 (throughput with varying message sizes)
For each of these experiments, vary the `BUFFER_SIZE` environment variable to change the message size.

### Catnip/UDP
Client:
```
root@prometheus3:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=$((256 * 1024)) USE_JUMBO=1 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/udp_echo ~/config3.yaml
```
Server:
```
root@prometheus5:~/src/demikernel/src/rust/catnip_libos# BUFFER_SIZE=$((256 * 1024)) USE_JUMBO=1 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 MTU=9216 ../target/release/udp_echo ~/config5.yaml
```

### Raw/UDP
Client:
```
root@prometheus3:~/src/demikernel/src/rust/catnip_libos# UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 SRC_MAC=b8:83:03:70:98:34 DST_MAC=b8:83:03:70:98:44 BUFFER_SIZE=$((256 * 1024)) ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 ../target/release/raw_udp_echo ~/config3.yaml
```
Server:
```
root@prometheus5:~/src/demikernel/src/rust/catnip_libos# UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 DST_MAC=b8:83:03:70:98:34 SRC_MAC=b8:83:03:70:98:44 BUFFER_SIZE=$((256 * 1024)) ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 ../target/release/raw_udp_echo ~/config5.yaml
```

### Catnip/TCP
Client:
```
root@prometheus3:~/src/demikernel/src/rust/catnip_libos# TCP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 BUFFER_SIZE=$((256 * 1024)) ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 ../target/release/tcp_echo ~/config3.yaml
```
Server:
```
root@prometheus5:~/src/demikernel/src/rust/catnip_libos# TCP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 BUFFER_SIZE=$((256 * 1024)) ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=1000 MSS=9000 ../target/release/tcp_echo ~/config5.yaml
```

## Figure 5 (latency vs. throughput for a single core server)
### Catnip/UDP
Server:
```
root@prometheus5:~/src/demikernel/src/rust/experiments# BUFFER_SIZE=$((1024)) UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 DST_MAC=b8:83:03:70:98:34 SRC_MAC=b8:83:03:70:98:44 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 ../target/release/udp_throughput ~/config5.yaml
```
Clients (I maxed out throughput with two machines running 8 clients each):
```
root@prometheus6:~/src/demikernel/src/rust/experiments# NUM_CLIENTS=8 BUFFER_SIZE=$((1024)) UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 SRC_MAC=b8:83:03:70:98:34 DST_MAC=b8:83:03:70:98:44 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 ../target/release/udp_throughput ~/config6.yaml
```

### Raw/UDP
Server:
```
root@prometheus5:~/src/demikernel/src/rust/experiments# BUFFER_SIZE=1024 UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 DST_MAC=b8:83:03:70:98:34 SRC_MAC=b8:83:03:70:98:44 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 numactl -N0 -m0 ../target/release/raw_udp_throughput ~/config5.yaml
```
Clients:
```
root@prometheus6:~/src/demikernel/src/rust/experiments# NUM_CLIENTS=8 BUFFER_SIZE=1024 UDP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 DST_MAC=b8:83:03:70:98:44 SRC_MAC=b8:83:03:70:88:98 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 numactl -N0 -m0 ../target/release/raw_udp_throughput ~/config3.yaml
```

### Catnip/TCP
Server:
```
root@prometheus5:~/src/demikernel/src/rust/experiments# BUFFER_SIZE=$((1024)) RUST_LOG=error,catnip::protocols::tcp::established::background=error TCP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 DST_MAC=b8:83:03:70:98:34 SRC_MAC=b8:83:03:70:98:44 ECHO_SERVER=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 ../target/release/tcp_throughput ~/config5.yaml
```
Clients:
```
root@prometheus3:~/src/demikernel/src/rust/experiments# RUST_LOG=error NUM_CLIENTS=8 BUFFER_SIZE=$((1024)) TCP_CHECKSUM_OFFLOAD=1 USE_JUMBO=1 MTU=9216 SRC_MAC=b8:83:03:70:98:34 DST_MAC=b8:83:03:70:98:44 ECHO_CLIENT=1 LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/install/lib/x86_64-linux-gnu NUM_ITERS=10000 MSS=9000 ../target/release/tcp_throughput ~/config3.yaml
```

## Figure 7 (Redis throughput)
This doesn't strictly belong here, but here are the commands for reproducing the Redis
experiments. There's a hack to pass in the YAML configuration path as a `CONFIG_PATH` environment
variable (rather than through `dmtr_init`), so be sure to set that.

Also, be sure to change `bind` in the Redis config to the interface's IP.

### Without logging
Build:
```
sujayakar@prometheus3:~/src/demikernel/build$ make redis-dpdk-catnip
```
Server:
```
sujayakar@prometheus3:~/src/demikernel/build$ LD_LIBRARY_PATH=~/src/demikernel/build/ExternalProject/dpdk/lib/ CONFIG_PATH=$HOME/config3.yaml submodules/redis-dpdk-catnip/bin/redis-server ~/redis3.conf
```

Since we only care about throughput for this experiment, we can just use Redis's built-in benchmark
on a few other machines.

Gets:
```
sujayakar@prometheus3:~$ for i in $(seq 5 9); do nohup ssh prometheus$i -- 'echo $(hostname):$(~/src/demikernel/submodules/redis-vanilla/src/redis-benchmark -h 198.19.200.3 -p 6379 -t get -n 500000 -r 1000000 -d 64 -c 24 -q --csv)' < /dev/null &> /tmp/get$i.out & done
sujayakar@prometheus3:~$ cat /tmp/get*.out | cut -d ',' -f2 | sed 's/"//g' | awk '{total += $1} END {print total}'
207271
```

Sets:
```
sujayakar@prometheus3:~$ for i in $(seq 5 9); do nohup ssh prometheus$i -- 'echo $(hostname):$(~/src/demikernel/submodules/redis-vanilla/src/redis-benchmark -h 198.19.200.3 -p 6379 -t set -n 500000 -r 1000000 -d 64 -c 24 -q --csv)' < /dev/null &> /tmp/set$i.out & done
sujayakar@prometheus3:~$ cat /tmp/set*.out | cut -d ',' -f2 | sed 's/"//g' | awk '{total += $1} END {print total}'
157590
```

### With logging
See `spdk-build` branch. Set `appendonly yes` in the Redis config to turn on logging.

0 comments on commit 4137dad

Please sign in to comment.