mirror of
https://github.com/n0-computer/noq.git
synced 2026-09-18 17:26:19 +00:00
Implement spin bit
This commit is contained in:
committed by
Dirkjan Ochtman
parent
f2754f02dd
commit
0de976751e
@@ -71,6 +71,8 @@ pub struct Connection {
|
||||
events: VecDeque<Event>,
|
||||
/// Number of local connection IDs that have been issued in NEW_CONNECTION_ID frames.
|
||||
cids_issued: u64,
|
||||
/// Outgoing spin bit state
|
||||
spin: bool,
|
||||
|
||||
//
|
||||
// Loss Detection
|
||||
@@ -233,6 +235,7 @@ impl Connection {
|
||||
io: IoQueue::new(),
|
||||
events: VecDeque::new(),
|
||||
cids_issued: 0,
|
||||
spin: false,
|
||||
|
||||
crypto_count: 0,
|
||||
pto_count: 0,
|
||||
@@ -733,6 +736,7 @@ impl Connection {
|
||||
now: u64,
|
||||
ecn: Option<EcnCodepoint>,
|
||||
packet: Option<u64>,
|
||||
spin: bool,
|
||||
) {
|
||||
self.reset_idle_timeout(now);
|
||||
self.receiving_ecn |= ecn.is_some();
|
||||
@@ -753,6 +757,8 @@ impl Connection {
|
||||
if packet > self.rx_packet {
|
||||
self.rx_packet = packet;
|
||||
self.rx_packet_time = now;
|
||||
// Update outgoing spin bit, inverting iff we're the client
|
||||
self.spin = self.side.is_client() ^ spin;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,7 +856,7 @@ impl Connection {
|
||||
&mut io::Cursor::new(self.tls.get_quic_transport_parameters().unwrap()),
|
||||
)?;
|
||||
self.set_params(params)?;
|
||||
self.on_packet_authenticated(now, ecn, Some(packet_number));
|
||||
self.on_packet_authenticated(now, ecn, Some(packet_number), false);
|
||||
self.write_tls();
|
||||
Ok(())
|
||||
}
|
||||
@@ -960,7 +966,12 @@ impl Connection {
|
||||
}
|
||||
} else {
|
||||
if !was_closed {
|
||||
self.on_packet_authenticated(now, ecn, number);
|
||||
let spin = if let Header::Short { spin, .. } = packet.header {
|
||||
spin
|
||||
} else {
|
||||
false
|
||||
};
|
||||
self.on_packet_authenticated(now, ecn, number, spin);
|
||||
}
|
||||
self.handle_connected_inner(now, number, packet)
|
||||
}
|
||||
@@ -1638,6 +1649,7 @@ impl Connection {
|
||||
let header = Header::Short {
|
||||
dst_cid: self.rem_cid,
|
||||
number: PacketNumber::new(number, self.largest_acked_packet),
|
||||
spin: self.spin,
|
||||
key_phase: self.key_phase,
|
||||
};
|
||||
//}
|
||||
@@ -1940,6 +1952,7 @@ impl Connection {
|
||||
let header = Header::Short {
|
||||
dst_cid: self.rem_cid,
|
||||
number: PacketNumber::new(number, self.largest_acked_packet),
|
||||
spin: self.spin,
|
||||
key_phase: self.key_phase,
|
||||
};
|
||||
let partial_encode = header.encode(&mut buf);
|
||||
@@ -1980,6 +1993,7 @@ impl Connection {
|
||||
CryptoLevel::OneRtt => Header::Short {
|
||||
dst_cid: self.rem_cid,
|
||||
number,
|
||||
spin: self.spin,
|
||||
key_phase: self.key_phase,
|
||||
},
|
||||
CryptoLevel::Initial => Header::Long {
|
||||
|
||||
@@ -93,12 +93,14 @@ impl PartialDecode {
|
||||
|
||||
let sample_offset = 1 + dst_cid.len() + 4;
|
||||
let number = Self::decrypt_header(&mut buf, header_crypto, sample_offset)?;
|
||||
let spin = buf.get_ref()[0] & SPIN_BIT != 0;
|
||||
let key_phase = buf.get_ref()[0] & KEY_PHASE_BIT != 0;
|
||||
(
|
||||
buf.remaining(),
|
||||
Header::Short {
|
||||
dst_cid,
|
||||
number,
|
||||
spin,
|
||||
key_phase,
|
||||
},
|
||||
false,
|
||||
@@ -279,6 +281,7 @@ pub enum Header {
|
||||
Short {
|
||||
dst_cid: ConnectionId,
|
||||
number: PacketNumber,
|
||||
spin: bool,
|
||||
key_phase: bool,
|
||||
},
|
||||
VersionNegotiate {
|
||||
@@ -350,9 +353,15 @@ impl Header {
|
||||
Short {
|
||||
ref dst_cid,
|
||||
number,
|
||||
spin,
|
||||
key_phase,
|
||||
} => {
|
||||
w.write(FIXED_BIT | if key_phase { KEY_PHASE_BIT } else { 0 } | number.tag());
|
||||
w.write(
|
||||
FIXED_BIT
|
||||
| if key_phase { KEY_PHASE_BIT } else { 0 }
|
||||
| if spin { SPIN_BIT } else { 0 }
|
||||
| number.tag(),
|
||||
);
|
||||
w.put_slice(dst_cid);
|
||||
number.encode(w);
|
||||
PartialEncode {
|
||||
@@ -814,10 +823,11 @@ pub fn set_payload_length(packet: &mut [u8], header_len: usize, pn_len: usize) {
|
||||
pub const AEAD_TAG_SIZE: usize = 16;
|
||||
|
||||
pub const LONG_HEADER_FORM: u8 = 0x80;
|
||||
const KEY_PHASE_BIT: u8 = 0x04;
|
||||
const FIXED_BIT: u8 = 0x40;
|
||||
pub const SPIN_BIT: u8 = 0x20;
|
||||
pub const SHORT_RESERVED_BITS: u8 = 0x18;
|
||||
pub const LONG_RESERVED_BITS: u8 = 0x0c;
|
||||
const KEY_PHASE_BIT: u8 = 0x04;
|
||||
|
||||
/// Explicit congestion notification codepoint
|
||||
#[repr(u8)]
|
||||
|
||||
@@ -66,6 +66,9 @@ struct Pair {
|
||||
time: u64,
|
||||
// One-way
|
||||
latency: u64,
|
||||
/// Number of spin bit flips
|
||||
spins: u64,
|
||||
last_spin: bool,
|
||||
}
|
||||
|
||||
impl Default for Pair {
|
||||
@@ -148,6 +151,8 @@ impl Pair {
|
||||
client: TestEndpoint::new(Side::Client, client, client_addr),
|
||||
time: 0,
|
||||
latency: 0,
|
||||
spins: 0,
|
||||
last_spin: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +196,11 @@ impl Pair {
|
||||
trace!(self.log, "client running");
|
||||
self.client.drive(&self.log, self.time, self.server.addr);
|
||||
for (ecn, packet) in self.client.outbound.drain(..) {
|
||||
if packet[0] & packet::LONG_HEADER_FORM == 0 {
|
||||
let spin = packet[0] & packet::SPIN_BIT != 0;
|
||||
self.spins += (spin == self.last_spin) as u64;
|
||||
self.last_spin = spin;
|
||||
}
|
||||
if let Some(ref socket) = self.client.socket {
|
||||
socket.send_to(&packet, self.server.addr).unwrap();
|
||||
}
|
||||
@@ -441,6 +451,7 @@ fn lifecycle() {
|
||||
info!(pair.log, "closing");
|
||||
pair.client.close(pair.time, client_conn, 42, REASON.into());
|
||||
pair.drive();
|
||||
assert!(pair.spins > 0);
|
||||
assert_matches!(pair.server.poll(),
|
||||
Some((_, Event::ConnectionLost { reason: ConnectionError::ApplicationClosed {
|
||||
reason: ApplicationClose { error_code: 42, ref reason }
|
||||
|
||||
Reference in New Issue
Block a user