aboutsummaryrefslogtreecommitdiffstats
path: root/src/wireguard/router/inbound.rs
diff options
context:
space:
mode:
authorMathias Hall-Andersen <mathias@hall-andersen.dk>2020-02-16 18:12:43 +0100
committerMathias Hall-Andersen <mathias@hall-andersen.dk>2020-02-16 18:12:43 +0100
commit106c5e8b5c865c8396f824f4f5aa14d1bf0952b1 (patch)
tree68101553c62d301921b84776a9e18fc627c7a731 /src/wireguard/router/inbound.rs
parentWork on reducing context switches (diff)
downloadwireguard-rs-106c5e8b5c865c8396f824f4f5aa14d1bf0952b1.tar.xz
wireguard-rs-106c5e8b5c865c8396f824f4f5aa14d1bf0952b1.zip
Work on router optimizationsrouter
Diffstat (limited to 'src/wireguard/router/inbound.rs')
-rw-r--r--src/wireguard/router/inbound.rs190
1 files changed, 0 insertions, 190 deletions
diff --git a/src/wireguard/router/inbound.rs b/src/wireguard/router/inbound.rs
deleted file mode 100644
index dc2c44e..0000000
--- a/src/wireguard/router/inbound.rs
+++ /dev/null
@@ -1,190 +0,0 @@
-use std::mem;
-use std::sync::atomic::Ordering;
-use std::sync::Arc;
-
-use crossbeam_channel::Receiver;
-use ring::aead::{Aad, LessSafeKey, Nonce, UnboundKey, CHACHA20_POLY1305};
-use zerocopy::{AsBytes, LayoutVerified};
-
-use super::constants::MAX_INORDER_CONSUME;
-use super::device::DecryptionState;
-use super::device::Device;
-use super::messages::TransportHeader;
-use super::peer::Peer;
-use super::pool::*;
-use super::types::Callbacks;
-use super::{tun, udp, Endpoint};
-use super::{REJECT_AFTER_MESSAGES, SIZE_TAG};
-
-pub struct Inbound<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> {
- msg: Vec<u8>,
- failed: bool,
- state: Arc<DecryptionState<E, C, T, B>>,
- endpoint: Option<E>,
-}
-
-impl<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>> Inbound<E, C, T, B> {
- pub fn new(
- msg: Vec<u8>,
- state: Arc<DecryptionState<E, C, T, B>>,
- endpoint: E,
- ) -> Inbound<E, C, T, B> {
- Inbound {
- msg,
- state,
- failed: false,
- endpoint: Some(endpoint),
- }
- }
-}
-
-#[inline(always)]
-pub fn parallel<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
- device: Device<E, C, T, B>,
- receiver: Receiver<Job<Peer<E, C, T, B>, Inbound<E, C, T, B>>>,
-) {
- // parallel work to apply
- #[inline(always)]
- fn work<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
- peer: &Peer<E, C, T, B>,
- body: &mut Inbound<E, C, T, B>,
- ) {
- log::trace!("worker, parallel section, obtained job");
-
- // cast to header followed by payload
- let (header, packet): (LayoutVerified<&mut [u8], TransportHeader>, &mut [u8]) =
- match LayoutVerified::new_from_prefix(&mut body.msg[..]) {
- Some(v) => v,
- None => {
- log::debug!("inbound worker: failed to parse message");
- return;
- }
- };
-
- // authenticate and decrypt payload
- {
- // create nonce object
- let mut nonce = [0u8; 12];
- debug_assert_eq!(nonce.len(), CHACHA20_POLY1305.nonce_len());
- nonce[4..].copy_from_slice(header.f_counter.as_bytes());
- let nonce = Nonce::assume_unique_for_key(nonce);
-
- // do the weird ring AEAD dance
- let key = LessSafeKey::new(
- UnboundKey::new(&CHACHA20_POLY1305, &body.state.keypair.recv.key[..]).unwrap(),
- );
-
- // attempt to open (and authenticate) the body
- match key.open_in_place(nonce, Aad::empty(), packet) {
- Ok(_) => (),
- Err(_) => {
- // fault and return early
- log::trace!("inbound worker: authentication failure");
- body.failed = true;
- return;
- }
- }
- }
-
- // check that counter not after reject
- if header.f_counter.get() >= REJECT_AFTER_MESSAGES {
- body.failed = true;
- return;
- }
-
- // cryptokey route and strip padding
- let inner_len = {
- let length = packet.len() - SIZE_TAG;
- if length > 0 {
- peer.device.table.check_route(&peer, &packet[..length])
- } else {
- Some(0)
- }
- };
-
- // truncate to remove tag
- match inner_len {
- None => {
- log::trace!("inbound worker: cryptokey routing failed");
- body.failed = true;
- }
- Some(len) => {
- log::trace!(
- "inbound worker: good route, length = {} {}",
- len,
- if len == 0 { "(keepalive)" } else { "" }
- );
- body.msg.truncate(mem::size_of::<TransportHeader>() + len);
- }
- }
- }
-
- worker_parallel(device, |dev| &dev.run_inbound, receiver, work)
-}
-
-#[inline(always)]
-pub fn sequential<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
- device: Device<E, C, T, B>,
-) {
- // sequential work to apply
- fn work<E: Endpoint, C: Callbacks, T: tun::Writer, B: udp::Writer<E>>(
- peer: &Peer<E, C, T, B>,
- body: &mut Inbound<E, C, T, B>,
- ) {
- log::trace!("worker, sequential section, obtained job");
-
- // decryption failed, return early
- if body.failed {
- log::trace!("job faulted, remove from queue and ignore");
- return;
- }
-
- // cast transport header
- let (header, packet): (LayoutVerified<&[u8], TransportHeader>, &[u8]) =
- match LayoutVerified::new_from_prefix(&body.msg[..]) {
- Some(v) => v,
- None => {
- log::debug!("inbound worker: failed to parse message");
- return;
- }
- };
-
- // check for replay
- if !body.state.protector.lock().update(header.f_counter.get()) {
- log::debug!("inbound worker: replay detected");
- return;
- }
-
- // check for confirms key
- if !body.state.confirmed.swap(true, Ordering::SeqCst) {
- log::debug!("inbound worker: message confirms key");
- peer.confirm_key(&body.state.keypair);
- }
-
- // update endpoint
- *peer.endpoint.lock() = body.endpoint.take();
-
- // check if should be written to TUN
- let mut sent = false;
- if packet.len() > 0 {
- sent = match peer.device.inbound.write(&packet[..]) {
- Err(e) => {
- log::debug!("failed to write inbound packet to TUN: {:?}", e);
- false
- }
- Ok(_) => true,
- }
- } else {
- log::debug!("inbound worker: received keepalive")
- }
-
- // trigger callback
- C::recv(&peer.opaque, body.msg.len(), sent, &body.state.keypair);
- }
-
- // handle message from the peers inbound queue
- device.run_inbound.run(|peer| {
- peer.inbound
- .handle(|body| work(&peer, body), MAX_INORDER_CONSUME)
- });
-}