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

s2n-quic-dc: initial commit #2185

Merged
merged 15 commits into from
Apr 20, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,8 @@ updates:
directory: "/tools/xdp"
schedule:
interval: "daily"

- package-ecosystem: "cargo"
directory: "/dc"
schedule:
interval: "daily"
24 changes: 14 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
# find all child folders in the examples directory
# jq -R - raw content is passed in (not json, just strings)
# jq -s - slurp the content into an object
# jq '. += ' adds the s2n-quic-xdp crate to the list of crates we build
# jq '. += ' adds the s2n-quic-xdp and s2n-quic-dc crates to the list of crates we build
# Many of the xdp crates have much more complex build processes, so we
# don't try to build all of them.
# jq -c - output the object in (c)ompact mode on a single line, github
Expand All @@ -63,7 +63,7 @@ jobs:
export EXAMPLES=$(find examples/ -maxdepth 1 -mindepth 1 -type d | jq -R | jq -sc)
echo "examples=$EXAMPLES"
echo "examples=$EXAMPLES" >> $GITHUB_OUTPUT
export CRATES=$(find quic common -name *Cargo.toml | jq -R | jq -s | jq '. += ["tools/xdp/s2n-quic-xdp/Cargo.toml"]' | jq -c)
export CRATES=$(find quic common -name *Cargo.toml | jq -R | jq -s | jq '. += ["tools/xdp/s2n-quic-xdp/Cargo.toml","dc/s2n-quic-dc/Cargo.toml"]' | jq -c)
echo "crates=$CRATES"
echo "crates=$CRATES" >> $GITHUB_OUTPUT

Expand Down Expand Up @@ -115,7 +115,7 @@ jobs:
#
# manual_clamp will panic when min > max
# See https://github.com/rust-lang/rust-clippy/pull/10101
cargo clippy --all-features --all-targets -- -A clippy::derive_partial_eq_without_eq -A clippy::manual_clamp ${{ matrix.args }}
cargo clippy --all-features --all-targets --workspace -- -A clippy::derive_partial_eq_without_eq -A clippy::manual_clamp ${{ matrix.args }}

udeps:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -196,11 +196,13 @@ jobs:
env: [default]
include:
- os: windows-latest
# s2n-tls doesn't currently build on windows
exclude: --workspace --exclude s2n-quic-tls
# s2n-tls and s2n-quic-dc don't currently build on windows
exclude: --exclude s2n-quic-tls --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: aarch64-unknown-linux-gnu
# s2n-quic-dc doesn't currently build on aarch64
exclude: --exclude s2n-quic-tls --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: i686-unknown-linux-gnu
Expand All @@ -213,6 +215,8 @@ jobs:
os: ubuntu-latest
target: native
env: S2N_QUIC_PLATFORM_FEATURES_OVERRIDE=""
# s2n-quic-dc requires platform features
exclude: --exclude s2n-quic-dc
- rust: stable
os: ubuntu-latest
target: native
Expand Down Expand Up @@ -259,11 +263,11 @@ jobs:
# Build the tests before running to improve cross compilation speed
- name: Run cargo/cross build
run: |
${{ matrix.target != 'native' && 'cross' || 'cargo' }} build --tests ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
${{ matrix.target != 'native' && 'cross' || 'cargo' }} build --tests --workspace ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}

- name: Run cargo/cross test
run: |
${{ matrix.target != 'native' && 'cross' || 'cargo' }} test ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}
${{ matrix.target != 'native' && 'cross' || 'cargo' }} test --workspace ${{ matrix.exclude }} ${{ matrix.target != 'native' && format('--target {0}', matrix.target) || '' }} ${{ matrix.args }}

miri:
# miri needs quite a bit of memory so use a larger instance
Expand Down Expand Up @@ -593,7 +597,7 @@ jobs:

- name: Run cargo insta test
run: |
cargo insta test --delete-unreferenced-snapshots
cargo insta test --all --delete-unreferenced-snapshots

- name: Check to make sure there are no unused snapshots
run: |
Expand All @@ -618,7 +622,7 @@ jobs:
- name: Run cargo build
run: |
cd examples/echo
cargo build --timings --release
cargo build --timings --release --workspace

- uses: aws-actions/[email protected]
if: github.event_name == 'push' || github.repository == github.event.pull_request.head.repo.full_name
Expand Down Expand Up @@ -698,7 +702,7 @@ jobs:

- name: Run cargo build
working-directory: tools/memory-report
run: cargo build --release
run: cargo build --release --workspace

- name: Run server
working-directory: tools/memory-report
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
members = [
"common/s2n-*",
"quic/s2n-*",
"dc/s2n-*",
]
default-members = [
"common/s2n-*",
"quic/s2n-*",
]
resolver = "2"
# don't include any workspaces outside of the main project
Expand Down
36 changes: 36 additions & 0 deletions dc/s2n-quic-dc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[package]
name = "s2n-quic-dc"
version = "0.36.0"
description = "Internal crate used by s2n-quic"
repository = "https://github.com/aws/s2n-quic"
authors = ["AWS s2n"]
edition = "2021"
rust-version = "1.71"
license = "Apache-2.0"
# Exclude corpus files when publishing to crates.io
exclude = ["corpus.tar.gz"]

[features]
testing = []

[dependencies]
atomic-waker = "1"
aws-lc-rs = "1"
bytes = "1"
crossbeam-channel = "0.5"
libc = "0.2"
num-rational = { version = "0.4", default-features = false }
once_cell = "1"
s2n-codec = { version = "=0.36.0", path = "../../common/s2n-codec", default-features = false }
s2n-quic-core = { version = "=0.36.0", path = "../../quic/s2n-quic-core", default-features = false }
s2n-quic-platform = { version = "=0.36.0", path = "../../quic/s2n-quic-platform" }
thiserror = "1"
tokio = { version = "1", features = ["io-util"], optional = true }
tracing = "0.1"
zerocopy = { version = "0.7", features = ["derive"] }

[dev-dependencies]
bolero = "0.10"
s2n-codec = { path = "../../common/s2n-codec", features = ["testing"] }
s2n-quic-core = { path = "../../quic/s2n-quic-core", features = ["testing"] }
tokio = { version = "1", features = ["io-util"] }
28 changes: 28 additions & 0 deletions dc/s2n-quic-dc/benches/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[package]
name = "benches"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
aws-lc-rs = "1"
criterion = { version = "0.4", features = ["html_reports"] }
s2n-codec = { path = "../../../common/s2n-codec" }
s2n-quic-dc = { path = "../../s2n-quic-dc", features = ["testing"] }

[[bench]]
name = "bench"
harness = false

[workspace]
members = ["."]

[profile.release]
lto = true
codegen-units = 1
incremental = false

[profile.bench]
lto = true
codegen-units = 1
incremental = false
7 changes: 7 additions & 0 deletions dc/s2n-quic-dc/benches/benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{criterion_group, criterion_main};

criterion_group!(benches, ::benches::benchmarks);
criterion_main!(benches);
12 changes: 12 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::Criterion;

pub mod encrypt;
pub mod hkdf;

pub fn benchmarks(c: &mut Criterion) {
encrypt::benchmarks(c);
hkdf::benchmarks(c);
}
92 changes: 92 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto/encrypt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{black_box, BenchmarkId, Criterion, Throughput};

pub fn benchmarks(c: &mut Criterion) {
let mut group = c.benchmark_group("crypto/encrypt");

let headers = [0, 16];

let payloads = [1, 100, 1000, 8900];

let inline = [
("aes_128_gcm", &aws_lc_rs::aead::AES_128_GCM),
("aes_256_gcm", &aws_lc_rs::aead::AES_256_GCM),
];

for payload_size in payloads {
let payload = black_box(vec![42u8; payload_size]);
for header_size in headers {
let header = black_box(vec![42u8; header_size]);

group.throughput(Throughput::Elements(1));

let input_name = format!("payload={payload_size},header={header_size}");

for (name, algo) in inline {
group.bench_with_input(
BenchmarkId::new(format!("{name}_reuse"), &input_name),
&(&header[..], &payload[..]),
|b, (header, payload)| {
let key = black_box(awslc::key(algo));
let mut payload = black_box(payload.to_vec());
let mut packet_number = 0u32;
b.iter(move || {
let _ = black_box(awslc::encrypt(
&key,
&mut packet_number,
header,
&mut payload,
));
});
},
);

group.bench_with_input(
BenchmarkId::new(format!("{name}_fresh"), &input_name),
&(&header[..], &payload[..]),
|b, (header, payload)| {
let mut payload = black_box(payload.to_vec());
let mut packet_number = 0u32;
b.iter(move || {
let key = black_box(awslc::key(algo));
let _ = black_box(awslc::encrypt(
&key,
&mut packet_number,
header,
&mut payload,
));
});
},
);
}
}
}
}

mod awslc {
use aws_lc_rs::aead::{Aad, Algorithm, LessSafeKey, Nonce, UnboundKey, NONCE_LEN};

#[inline(never)]
pub fn key(algo: &'static Algorithm) -> LessSafeKey {
let max_key = [42u8; 32];
let key = &max_key[..algo.key_len()];
let key = UnboundKey::new(algo, key).unwrap();
LessSafeKey::new(key)
}

#[inline(never)]
pub fn encrypt(key: &LessSafeKey, packet_number: &mut u32, header: &[u8], payload: &mut [u8]) {
let mut nonce = [0u8; NONCE_LEN];
nonce[NONCE_LEN - 8..].copy_from_slice(&(*packet_number as u64).to_be_bytes());
let nonce = Nonce::assume_unique_for_key(nonce);

let aad = Aad::from(header);
let mut tag = [0u8; 16];
key.seal_in_place_scatter(nonce, aad, payload, &[][..], &mut tag)
.unwrap();

*packet_number += 1;
}
}
92 changes: 92 additions & 0 deletions dc/s2n-quic-dc/benches/src/crypto/hkdf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::{black_box, BenchmarkId, Criterion, Throughput};

pub fn benchmarks(c: &mut Criterion) {
psk(c);
}

fn psk(c: &mut Criterion) {
let mut group = c.benchmark_group("crypto/hkdf/psk");

group.throughput(Throughput::Elements(1));

let prk_lens = [16, 32];
let key_lens = [16, 32, 64];
let label_lens = [1, 8, 16, 32, 64];
let algs = [
("sha256", awslc::HKDF_SHA256),
("sha384", awslc::HKDF_SHA384),
("sha512", awslc::HKDF_SHA512),
];

for prk_len in prk_lens {
for key_len in key_lens {
for label_len in label_lens {
for (alg_name, alg) in algs {
group.bench_with_input(
BenchmarkId::new(
format!("{alg_name}_reuse"),
format!("prk_len={prk_len},label_len={label_len},out_len={key_len}"),
),
&key_len,
|b, &key_len| {
let prk = black_box(awslc::prk(&vec![42u8; prk_len], alg));
let label = black_box(vec![42u8; label_len]);
let mut out = black_box(vec![0u8; key_len]);
b.iter(move || {
let _ = black_box(awslc::derive_psk(&prk, &label, &mut out));
});
},
);
group.bench_with_input(
BenchmarkId::new(
format!("{alg_name}_fresh"),
format!("prk_len={prk_len},label_len={label_len},out_len={key_len}"),
),
&key_len,
|b, &key_len| {
let key = black_box(vec![42u8; prk_len]);
let label = black_box(vec![42u8; label_len]);
let mut out = black_box(vec![0u8; key_len]);
b.iter(move || {
let prk = black_box(awslc::prk(&key, alg));
let _ = black_box(awslc::derive_psk(&prk, &label, &mut out));
});
},
);
}
}
}
}
}

mod awslc {
pub use aws_lc_rs::hkdf::*;

#[inline(never)]
pub fn prk(prk: &[u8], alg: Algorithm) -> Prk {
Prk::new_less_safe(alg, prk)
}

#[inline(never)]
pub fn derive_psk(prk: &Prk, label: &[u8], out: &mut [u8]) {
let out_len = out.len();
let out_len = OutLen(out_len);

prk.expand(&[&label], out_len)
.unwrap()
.fill(&mut out[..out_len.0])
.unwrap();
}

#[derive(Clone, Copy)]
struct OutLen(usize);

impl KeyType for OutLen {
fn len(&self) -> usize {
self.0
}
}
}
12 changes: 12 additions & 0 deletions dc/s2n-quic-dc/benches/src/datagram.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use criterion::Criterion;

mod recv;
mod send;

pub fn benchmarks(c: &mut Criterion) {
send::benches(c);
recv::benches(c);
}
Loading
Loading