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

Fix ACK_MP preventing bundling a ping when eliciting an ACK #2

Open
wants to merge 71 commits into
base: multipath
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
c7352ad
lib: count reset and stopped streams
LPardue Oct 26, 2023
f637b77
ci: test both vendored boringssl and boring crate
ghedo Sep 13, 2023
f53e6cd
qlog: add MTUUpdated event
LPardue Nov 2, 2023
1f4f1f5
qlog: fixup MTUUpdated event types serialization/parsing
LPardue Nov 4, 2023
c8d10d2
crypto: avoid unnecessary allocations when generating keys
ghedo Oct 31, 2023
ebfdd3f
bump boring crate
ghedo Nov 10, 2023
1993e0d
qlog: release 0.10
ghedo Nov 10, 2023
af368e9
0.19.0
ghedo Nov 10, 2023
3e7ddfd
h3: fix event type conversion to FFI enum
ghedo Nov 13, 2023
4dfe0b9
add backstage catalog
ghedo Nov 13, 2023
a48c6f7
backstage: update catalog entry
ghedo Nov 15, 2023
5b5120e
stream: update clippy lint name
ghedo Nov 20, 2023
89aba91
qlog: add MtuUpdated event missing from EventImportance implementation
divyabhat1 Nov 20, 2023
06222e5
quiche.h: use socklen_t when passing sockaddr to C functions
normanmaurer Nov 22, 2023
48d2faa
cid: remove unused ConnectionIdIter
normanmaurer Nov 24, 2023
fb3aa78
rename CID methods to be more consistent
normanmaurer Nov 24, 2023
098b252
ffi: add C API for methods that are required to handle connection mig…
normanmaurer Nov 24, 2023
b91019e
allow access to a Connection's boring::ssl::SslRef
fisherdarling Nov 24, 2023
404f259
ffi: expose quiche_conn_retire_dcid(...)
normanmaurer Nov 27, 2023
177b0ca
ffi: expose connection source IDs
normanmaurer Nov 27, 2023
5796adc
ffi: expose C API to handle PathEvent
normanmaurer Nov 27, 2023
1a92311
ffi: fix quiche_conn_new_scid(...) return value
normanmaurer Nov 27, 2023
f8ec4d4
ffi: add functions to send packets on a specific path
normanmaurer Nov 27, 2023
b0944d8
ffi: expose functions related to client side connection migration
normanmaurer Nov 27, 2023
ec6d017
ffi: add quiche_conn_is_resumed
normanmaurer Dec 5, 2023
68b045f
ffi: add missing quiche_conn_is_dgram_send_queue_full(...) and quiche…
normanmaurer Dec 6, 2023
7815bce
build(deps): update ring requirement from 0.16 to 0.17
dependabot[bot] Dec 6, 2023
8f5c8e5
fix typos
xiaolou86 Dec 7, 2023
665d459
ffi: fix const-correctness for quiche_h3_send_* functions
rgacogne Dec 11, 2023
3d54e05
ffi: add missing config APIs
normanmaurer Dec 11, 2023
ec3e004
lib: limit queued PATH_CHALLENGE frames
LPardue Oct 25, 2023
5b1e3d2
0.20.0
ghedo Dec 11, 2023
d312a4f
path: reformat
ghedo Dec 12, 2023
12eebf3
feat(qlog): extend `From<EventType> for EventImportance` (#1684)
mxinden Dec 13, 2023
d82f37d
fix(qlog): update serde rename of PacketsAcked (#1682)
mxinden Dec 13, 2023
4269906
Flush qlog streamer before closing the connection (#1629)
FranzBusch Dec 13, 2023
5f8ed9e
qlog: extend serializer to support arbitrary types of event (#1675)
LPardue Dec 13, 2023
36a9e39
qlog: Add QlogSeqReader helper (#1672)
LPardue Dec 13, 2023
ea7eb85
lib: add getter for qlog streamer (#1687)
LPardue Dec 13, 2023
3ecde62
h3: make grease_value() public (#1688)
LPardue Dec 13, 2023
8e64c06
h3: allow the frame module to be public under a new feature (#1689)
LPardue Dec 13, 2023
3ace6a5
examples: update url dependency
gierens Dec 15, 2023
d4e5ed6
qlog: add ex_data to Event (#1692)
LPardue Dec 15, 2023
3ea528b
qlog: support reading JsonEvent too
LPardue Jan 8, 2024
65ceb81
fix dead code warnings for FFI types
ghedo Jan 8, 2024
af6da80
build(deps): update env_logger to mitigate RUSTSEC-2021-0145
PSUdaemon Jan 9, 2024
eac9005
clippy fixes for code excluded from workspace
PSUdaemon Jan 9, 2024
dd2be9a
qlog: release qlog 0.11
LPardue Jan 9, 2024
3c75ec1
stream: minimise calls to SendBuf off_front() during emit()
LPardue Jan 12, 2024
62e9104
frame: reject NEW_CONNECTION_ID frames with invalid CIDs
ghedo Jan 15, 2024
1684118
frame: stricter NEW_TOKEN frame checks (#1712)
LPardue Jan 15, 2024
dfeaa58
remove ProtocolViolation error
ghedo Jan 15, 2024
b1da497
refactoring to prepare multipath support without side effects
qdeconinck Oct 4, 2022
428cb7f
Multipath support with non-zero length Connection IDs
qdeconinck Oct 10, 2022
c094c94
quiche-server: ensure burst sending on same path
qdeconinck Nov 21, 2022
649be3d
apps: make the client's `A` flag less confusing
qdeconinck Jan 26, 2023
9c2a17a
apps: add warning if --max-active-cids is too low
qdeconinck Feb 6, 2023
c9381e1
clippy fixes
qdeconinck Feb 6, 2023
ac7445e
fix non-sending of ACK_MP when datagrams are enabled
qdeconinck Feb 9, 2023
bceb6d1
fix comment
qdeconinck Feb 13, 2023
720714e
tests: support multipath in decode_pkt
qdeconinck Feb 28, 2023
048b33d
no need for public API `find_scid_seq()`
qdeconinck Mar 1, 2023
ae5cb5a
remove unused function since rebase
qdeconinck Jun 13, 2023
2107189
move support to draft-ietf-quic-multipath-04
qdeconinck Jun 26, 2023
e1c4452
add temporary simultaneous support of 04 and 05 drafts
qdeconinck Jul 14, 2023
1b17165
also update applications to be able to run old multipath
qdeconinck Jul 22, 2023
7ab23d5
add some additional flags for the multipath interop @ IETF117 hackathon
qdeconinck Jul 22, 2023
90260f5
remove support for draft-ietf-quic-multipath-04
qdeconinck Sep 25, 2023
49082a6
move support to draft-ietf-quic-multipath-06
qdeconinck Oct 27, 2023
2d4b02b
apps: remove dangling --multipath-old flag
qdeconinck Oct 27, 2023
e66b27d
Make sure sending ACK_MP doesn't prevent bundling a ping when an ACK …
mpiraux Dec 20, 2023
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
13 changes: 9 additions & 4 deletions .github/workflows/stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ env:
jobs:
quiche:
runs-on: ubuntu-latest
strategy:
matrix:
tls-feature:
- "" # default, boringssl-vendored
- "boringssl-boring-crate"
# Only run on "pull_request" event for external PRs. This is to avoid
# duplicate builds for PRs created from internal branches.
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
Expand All @@ -30,15 +35,15 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --all-targets --features=ffi,qlog
args: --verbose --all-targets --features=ffi,qlog,${{ matrix.tls-feature }}

# Need to run doc tests separately.
# (https://github.com/rust-lang/cargo/issues/6669)
- name: Run cargo doc test
uses: actions-rs/cargo@v1
with:
command: test
args: --verbose --doc --features=ffi,qlog
args: --verbose --doc --features=ffi,qlog,${{ matrix.tls-feature }}

- name: Run cargo package
uses: actions-rs/cargo@v1
Expand All @@ -50,13 +55,13 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: clippy
args: --features=ffi,qlog -- -D warnings
args: --features=ffi,qlog,${{ matrix.tls-feature }} -- -D warnings

- name: Run cargo clippy on examples
uses: actions-rs/cargo@v1
with:
command: clippy
args: --examples --features=ffi,qlog -- -D warnings
args: --examples --features=ffi,qlog,${{ matrix.tls-feature }} -- -D warnings

- name: Run cargo doc
uses: actions-rs/cargo@v1
Expand Down
6 changes: 4 additions & 2 deletions apps/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ default = ["qlog", "sfv"]

[dependencies]
docopt = "1"
env_logger = "0.6"
env_logger = "0.10"
mio = { version = "0.8", features = ["net", "os-poll"] }
url = "1"
log = "0.4"
octets = { version = "0.2", path = "../octets" }
ring = "0.16"
ring = "0.17"
quiche = { path = "../quiche" }
libc = "0.2"
nix = { version = "0.27", features = ["net", "socket", "uio"] }
slab = "0.4"
itertools = "0.10"

[lib]
crate-type = ["lib"]
76 changes: 75 additions & 1 deletion apps/src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::net::SocketAddr;
use std::str::FromStr;

use super::common::alpns;

pub trait Args {
Expand Down Expand Up @@ -54,6 +57,7 @@ pub struct CommonArgs {
pub qpack_max_table_capacity: Option<u64>,
pub qpack_blocked_streams: Option<u64>,
pub initial_cwnd_packets: u64,
pub multipath: bool,
}

/// Creates a new `CommonArgs` structure using the provided [`Docopt`].
Expand All @@ -80,6 +84,7 @@ pub struct CommonArgs {
/// --qpack-max-table-capacity BYTES Max capacity of dynamic QPACK decoding.
/// --qpack-blocked-streams STREAMS Limit of blocked streams while decoding.
/// --initial-cwnd-packets Size of initial congestion window, in packets.
/// --multipath Enable multipath support.
///
/// [`Docopt`]: https://docs.rs/docopt/1.1.0/docopt/
impl Args for CommonArgs {
Expand Down Expand Up @@ -191,6 +196,8 @@ impl Args for CommonArgs {
.parse::<u64>()
.unwrap();

let multipath = args.get_bool("--multipath");

CommonArgs {
alpns,
max_data,
Expand All @@ -214,6 +221,7 @@ impl Args for CommonArgs {
qpack_max_table_capacity,
qpack_blocked_streams,
initial_cwnd_packets,
multipath,
}
}
}
Expand Down Expand Up @@ -243,6 +251,7 @@ impl Default for CommonArgs {
qpack_max_table_capacity: None,
qpack_blocked_streams: None,
initial_cwnd_packets: 10,
multipath: false,
}
}
}
Expand Down Expand Up @@ -271,7 +280,7 @@ Options:
--dump-responses PATH Dump response payload as files in the given directory.
--dump-json Dump response headers and payload to stdout in JSON format.
--max-json-payload BYTES Per-response payload limit when dumping JSON [default: 10000].
--connect-to ADDRESS Override ther server's address.
--connect-to ADDRESS Override the server's address.
--no-verify Don't verify server's certificate.
--trust-origin-ca-pem <file> Path to the pem file of the origin's CA, if not publicly trusted.
--no-grease Don't send GREASE.
Expand All @@ -280,6 +289,10 @@ Options:
--max-active-cids NUM The maximum number of active Connection IDs we can support [default: 2].
--enable-active-migration Enable active connection migration.
--perform-migration Perform connection migration on another source port.
--multipath Enable multipath support.
-A --address ADDR ... Specify addresses to be used instead of the unspecified address. Non-routable addresses will lead to connectivity issues.
-R --rm-addr TIMEADDR ... Specify addresses to stop using after the provided time (format time,addr).
-S --status TIMEADDRSTAT ... Specify availability status to advertise to the peer after the provided time (format time,addr,available).
-H --header HEADER ... Add a request header.
-n --requests REQUESTS Send the given number of identical requests [default: 1].
--send-priority-update Send HTTP/3 priority updates if the query string params 'u' or 'i' are present in URLs
Expand Down Expand Up @@ -309,6 +322,9 @@ pub struct ClientArgs {
pub source_port: u16,
pub perform_migration: bool,
pub send_priority_update: bool,
pub addrs: Vec<SocketAddr>,
pub rm_addrs: Vec<(std::time::Duration, SocketAddr)>,
pub status: Vec<(std::time::Duration, SocketAddr, bool)>,
}

impl Args for ClientArgs {
Expand Down Expand Up @@ -386,6 +402,57 @@ impl Args for ClientArgs {

let send_priority_update = args.get_bool("--send-priority-update");

let addrs = args
.get_vec("--address")
.into_iter()
.filter_map(|a| a.parse().ok())
.collect();

let rm_addrs = args
.get_vec("--rm-addr")
.into_iter()
.filter_map(|ta| {
let s = ta.split(',').collect::<Vec<_>>();
if s.len() != 2 {
return None;
}
let secs = match s[0].parse::<u64>() {
Ok(s) => s,
Err(_) => return None,
};
let addr = match SocketAddr::from_str(s[1]) {
Ok(a) => a,
Err(_) => return None,
};
Some((std::time::Duration::from_secs(secs), addr))
})
.collect();

let status = args
.get_vec("--status")
.into_iter()
.filter_map(|ta| {
let s = ta.split(',').collect::<Vec<_>>();
if s.len() != 3 {
return None;
}
let secs = match s[0].parse::<u64>() {
Ok(s) => s,
Err(_) => return None,
};
let addr = match SocketAddr::from_str(s[1]) {
Ok(a) => a,
Err(_) => return None,
};
let status = match s[2].parse::<u64>() {
Ok(0) => false,
Ok(_) => true,
Err(_) => return None,
};
Some((std::time::Duration::from_secs(secs), addr, status))
})
.collect();

ClientArgs {
version,
dump_response_path,
Expand All @@ -402,6 +469,9 @@ impl Args for ClientArgs {
source_port,
perform_migration,
send_priority_update,
addrs,
rm_addrs,
status,
}
}
}
Expand All @@ -424,6 +494,9 @@ impl Default for ClientArgs {
source_port: 0,
perform_migration: false,
send_priority_update: false,
addrs: vec![],
rm_addrs: vec![],
status: vec![],
}
}
}
Expand Down Expand Up @@ -464,6 +537,7 @@ Options:
--disable-gso Disable GSO (linux only).
--disable-pacing Disable pacing (linux only).
--initial-cwnd-packets PACKETS The initial congestion window size in terms of packet count [default: 10].
--multipath Enable multipath support.
-h --help Show this screen.
";

Expand Down
4 changes: 1 addition & 3 deletions apps/src/bin/quiche-client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ use quiche_apps::common::*;
use quiche_apps::client::*;

fn main() {
env_logger::builder()
.default_format_timestamp_nanos(true)
.init();
env_logger::builder().format_timestamp_nanos().init();

// Parse CLI parameters.
let docopt = docopt::Docopt::new(CLIENT_USAGE).unwrap();
Expand Down
66 changes: 48 additions & 18 deletions apps/src/bin/quiche-server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ fn main() {
let mut out = [0; MAX_BUF_SIZE];
let mut pacing = false;

env_logger::builder()
.default_format_timestamp_nanos(true)
.init();
env_logger::builder().format_timestamp_nanos().init();

// Parse CLI parameters.
let docopt = docopt::Docopt::new(SERVER_USAGE).unwrap();
Expand Down Expand Up @@ -124,6 +122,7 @@ fn main() {
config.set_initial_congestion_window_packets(
usize::try_from(conn_args.initial_cwnd_packets).unwrap(),
);
config.set_multipath(conn_args.multipath);

config.set_max_connection_window(conn_args.max_window);
config.set_max_stream_window(conn_args.max_stream_window);
Expand Down Expand Up @@ -512,13 +511,9 @@ fn main() {
}

// Provides as many CIDs as possible.
while client.conn.source_cids_left() > 0 {
while client.conn.scids_left() > 0 {
let (scid, reset_token) = generate_cid_and_reset_token(&rng);
if client
.conn
.new_source_cid(&scid, reset_token, false)
.is_err()
{
if client.conn.new_scid(&scid, reset_token, false).is_err() {
break;
}

Expand Down Expand Up @@ -547,16 +542,24 @@ fn main() {
client.max_datagram_size *
client.max_datagram_size;
let mut total_write = 0;
let mut dst_info = None;
let mut dst_info: Option<quiche::SendInfo> = None;

while total_write < max_send_burst {
let (write, send_info) = match client
.conn
.send(&mut out[total_write..max_send_burst])
{
let res = match dst_info {
Some(info) => client.conn.send_on_path(
&mut out[total_write..max_send_burst],
Some(info.from),
Some(info.to),
),
None =>
client.conn.send(&mut out[total_write..max_send_burst]),
};

let (write, send_info) = match res {
Ok(v) => v,

Err(quiche::Error::Done) => {
continue_write = dst_info.is_some();
trace!("{} done writing", client.conn.trace_id());
break;
},
Expand Down Expand Up @@ -602,6 +605,14 @@ fn main() {

trace!("{} written {} bytes", client.conn.trace_id(), total_write);

if continue_write {
trace!(
"{} pause writing and consider another path",
client.conn.trace_id()
);
break;
}

if total_write >= max_send_burst {
trace!("{} pause writing", client.conn.trace_id(),);
continue_write = true;
Expand Down Expand Up @@ -703,7 +714,8 @@ fn handle_path_events(client: &mut Client) {
client
.conn
.probe_path(local_addr, peer_addr)
.expect("cannot probe");
.map_err(|e| error!("cannot probe: {}", e))
.ok();
},

quiche::PathEvent::Validated(local_addr, peer_addr) => {
Expand All @@ -713,6 +725,13 @@ fn handle_path_events(client: &mut Client) {
local_addr,
peer_addr
);
if client.conn.is_multipath_enabled() {
client
.conn
.set_active(local_addr, peer_addr, true)
.map_err(|e| error!("cannot set path active: {}", e))
.ok();
}
},

quiche::PathEvent::FailedValidation(local_addr, peer_addr) => {
Expand All @@ -724,12 +743,14 @@ fn handle_path_events(client: &mut Client) {
);
},

quiche::PathEvent::Closed(local_addr, peer_addr) => {
quiche::PathEvent::Closed(local_addr, peer_addr, err, reason) => {
info!(
"{} Path ({}, {}) is now closed and unusable",
"{} Path ({}, {}) is now closed and unusable; err = {} reason = {:?}",
client.conn.trace_id(),
local_addr,
peer_addr
peer_addr,
err,
reason,
);
},

Expand All @@ -751,6 +772,15 @@ fn handle_path_events(client: &mut Client) {
peer_addr
);
},

quiche::PathEvent::PeerPathStatus(addr, path_status) => {
info!("Peer asks status {:?} for {:?}", path_status, addr,);
client
.conn
.set_path_status(addr.0, addr.1, path_status, false)
.map_err(|e| error!("cannot follow status request: {}", e))
.ok();
},
}
}
}
Expand Down
Loading