Implement spin bit

This commit is contained in:
Benjamin Saunders
2018-12-26 11:41:12 -08:00
committed by Dirkjan Ochtman
parent f2754f02dd
commit 0de976751e
3 changed files with 39 additions and 4 deletions
+16 -2
View File
@@ -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 {
+12 -2
View File
@@ -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)]
+11
View File
@@ -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 }