1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
//! Encapsulates a network interface card.
//!
//! Also permits software emulation or implementation of one as well, of course.
pub mod common;
pub mod loopback;
pub mod external;
mod personality;

#[cfg(feature = "sys")]
#[path="sys/mod.rs"]
mod sys_internal;

use crate::wire::Payload;
use crate::layer::{Result, FnHandler};
#[cfg(feature = "std")]
use crate::wire::{ethernet, pretty_print::{Formatter, PrettyPrinter}};
use crate::time::Instant;

pub use self::personality::{
    Capabilities,
    Personality,
    Protocol};

#[cfg(feature = "sys")]
pub use self::sys_internal::exports as sys;

pub use crate::layer::loss::{Lossy, PrngLoss};

/// A reference to memory holding packet data and a handle.
///
/// The `Payload` is as an interface into internal library types for packet parsing while the
/// `Handle` is an interface to the device to provide operations for packet handling.
pub struct Packet<'a, H, P>
where
    H: Handle + ?Sized + 'a,
    P: Payload + ?Sized + 'a,
{
    /// A control handle to the network interface and current buffer.
    pub handle: &'a mut H,
    /// One buffer containing an Ethernet frame.
    pub payload: &'a mut P,
}

/// A controller for the network operations of the payload buffer.
///
/// Provides the meta data of the payload. This trait is split from the main payload since it must
/// be possible to use its method even while the payload itself is borrowed (e.g. within a parsed
/// packet representation).
pub trait Handle {
    /// Queue this packet to be sent.
    ///
    /// This operation may fail for cards that can only send packets that have been previously
    /// allocated for that specific purpose and can, for lack of logic for this, not implement
    /// ad-hoc allocation for this purpose. Another reason for failure is simply a lack of
    /// resources to queue the packet.
    fn queue(&mut self) -> Result<()>;

    /// Information on the packet intended for lower layers.
    ///
    /// Note that technically the information may change after a call to `queue` or in the future
    /// after changing the target interface of an outgoing packet. That is intentional.
    fn info(&self) -> &dyn Info;
    // TODO: multiple interfaces (=zerocopy forwarding).
}

/// The metadata associated with a packet buffer.
///
/// This is the central source of information for the ethox implementation that can be customized
/// by the network interface. The data can differ per buffer, although certain constraints should
/// hold such as the timestamp should also be monotonically increasing. Violating them is not a
/// memory safety concern but could hinder forward progress or harm performance, trough discarded
/// caches or otherwise.
pub trait Info {
    /// The reference time stamp for this packet.
    fn timestamp(&self) -> Instant;

    /// Capabilities used for the packet.
    ///
    /// Indicates pre-checked checksums for incoming packets and hardware support for checksums of
    /// outgoing packets across the layers of the network stack.
    fn capabilities(&self) -> Capabilities;
}

/// A layer 2 device.
pub trait Device {
    /// The control handle type also providing packet meta information.
    type Handle: Handle + ?Sized;
    /// The payload buffer type of this device.
    ///
    /// It can be an owning buffer such as `Vec<u8>` or a non-owning buffer or even only emulate a
    /// buffer containing an Ethernet packet. Note that the buffer trait should stay a type
    /// parameter so that upper layers can make use of additional methods and not be constrained to
    /// the `Payload` trait. (Although smart use of `Any` might in some cases suffice in a real,
    /// specific network stack that is not this library).
    type Payload: Payload + ?Sized;

    /// A description of the device.
    ///
    /// Could be dynamically configured but the optimizer and the user is likely happier if the
    /// implementation does not take advantage of this fact.
    fn personality(&self) -> Personality;

    /// Transmit some packets utilizing the `sender`.
    ///
    /// Up to `max` packet buffers are chosen by the device. They are provided to the sender callback
    /// which may initialize their contents and decide to queue them. Afterwards, the device is
    /// responsible for cleaning up unused buffers and physically sending queued buffers.
    fn tx(&mut self, max: usize, sender: impl Send<Self::Handle, Self::Payload>)
        -> Result<usize>;

    /// Receive packet utilizing the `receptor`.
    ///
    /// Dequeue up to `max` received packets and provide them to the receiver callback.
    fn rx(&mut self, max: usize, receiver: impl Recv<Self::Handle, Self::Payload>)
        -> Result<usize>;
}

/// A raw network packet receiver.
pub trait Recv<H: Handle + ?Sized, P: Payload + ?Sized> {
    /// Receive a single packet.
    ///
    /// Some `Packet` types will allow you not only to access but also modify their contents (i.e.
    /// they also implement `AsMut<[u8]>`
    fn receive(&mut self, packet: Packet<H, P>);

    /// Vectored receive.
    ///
    /// The default implementation will simply receive all packets in sequence.
    fn receivev<'a>(&mut self, packets: impl IntoIterator<Item=Packet<'a, H, P>>)
        where P: 'a, H: 'a
    {
        for packet in packets.into_iter() {
            self.receive(packet);
        }
    }
}

/// A raw network packet sender.
pub trait Send<H: Handle + ?Sized, P: Payload + ?Sized> {
    /// Fill a single packet for sending.
    fn send(&mut self, packet: Packet<H, P>);

    /// Vectored sending.
    ///
    /// The default implementation will simply send all packets in sequence.
    fn sendv<'a>(&mut self, packets: impl IntoIterator<Item=Packet<'a, H, P>>)
        where P: 'a, H: 'a
    {
        for packet in packets.into_iter() {
            self.send(packet)
        }
    }
}

impl<F, H: Handle + ?Sized, P: Payload + ?Sized> Recv<H, P> for FnHandler<F>
    where F: FnMut(Packet<H, P>)
{
    fn receive(&mut self, packet: Packet<H, P>) {
        (self.0)(packet)
    }
}

impl<F, H: Handle + ?Sized, P: Payload + ?Sized> Send<H, P> for FnHandler<F>
    where F: FnMut(Packet<H, P>)
{
    fn send(&mut self, packet: Packet<H, P>) {
        (self.0)(packet)
    }
}

impl<F, H: Handle + ?Sized, P: Payload + ?Sized> Recv<H, P> for &'_ mut F
    where F: Recv<H, P>
{
    fn receive(&mut self, packet: Packet<H, P>) {
        (**self).receive(packet)
    }

    fn receivev<'a>(&mut self, packets: impl IntoIterator<Item=Packet<'a, H, P>>)
        where P: 'a, H: 'a
    {
        (**self).receivev(packets)
    }
}

impl<F, H: Handle + ?Sized, P: Payload + ?Sized> Send<H, P> for &'_ mut F
    where F: Send<H, P>
{
    fn send(&mut self, packet: Packet<H, P>) {
        (**self).send(packet)
    }

    fn sendv<'a>(&mut self, packets: impl IntoIterator<Item=Packet<'a, H, P>>)
        where P: 'a, H: 'a
    {
        (**self).sendv(packets)
    }
}

/// Available only on `std` because it prints to standard out.
#[cfg(feature = "std")]
impl<H: Handle + ?Sized, P: Payload + ?Sized> Recv<H, P> for Formatter<ethernet::frame> {
    fn receive(&mut self, frame: Packet<H, P>) {
        let printer = PrettyPrinter::<ethernet::frame>
            ::new("", frame.payload.payload().as_slice());
        eprintln!("{}", printer);
    }
}

/// Some base types and methods for other tests.
#[cfg(test)]
mod tests {
    use super::*;
    use crate::wire::PayloadMut;

    /// Sender and receiver verifying packet lengths.
    #[derive(Copy, Clone)]
    pub(crate) struct LengthIo;

    impl LengthIo {
        fn signature<P: Payload + ?Sized>(&mut self, payload: &P) -> [u8; 8] {
            payload.payload()
                .as_slice()
                .len()
                .to_le_bytes()
        }
    }

    impl<H, P> Recv<H, P> for LengthIo
        where H: Handle + ?Sized, P: Payload + ?Sized,
    {
        fn receive(&mut self, packet: Packet<H, P>) {
            let bytes = self.signature(&packet.payload);
            for (p, b) in packet.payload.payload().as_slice().iter().zip(bytes.iter().cycle()) {
                assert!(p == b)
            }
        }
    }

    impl<H, P> Send<H, P> for LengthIo 
        where H: Handle + ?Sized, P: Payload + PayloadMut + ?Sized,
    {
        fn send(&mut self, packet: Packet<H, P>) {
            let bytes = self.signature(&packet.payload);
            for (p, b) in packet.payload.payload_mut().as_mut_slice().iter_mut().zip(bytes.iter().cycle()) {
                *p = *b;
            }
            assert_eq!(packet.handle.queue(), Ok(()));
        }
    }
}