nex_packet/
flowcontrol.rs

1//! Ethernet Flow Control \[IEEE 802.3x\] abstraction.
2use core::fmt;
3
4use bytes::{Buf, BufMut, Bytes};
5use nex_core::bitfield::u16be;
6
7use crate::packet::{GenericMutablePacket, Packet};
8
9/// Represents the opcode field in an Ethernet Flow Control packet.
10///
11/// Flow control opcodes are defined in IEEE 802.3x
12#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[repr(u16)]
14pub enum FlowControlOpcode {
15    Pause = 0x0001,
16    Unknown(u16),
17}
18
19impl FlowControlOpcode {
20    pub fn new(value: u16) -> Self {
21        match value {
22            0x0001 => FlowControlOpcode::Pause,
23            other => FlowControlOpcode::Unknown(other),
24        }
25    }
26
27    pub fn value(&self) -> u16 {
28        match *self {
29            FlowControlOpcode::Pause => 0x0001,
30            FlowControlOpcode::Unknown(v) => v,
31        }
32    }
33}
34
35impl fmt::Display for FlowControlOpcode {
36    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37        write!(
38            f,
39            "{}",
40            match self {
41                FlowControlOpcode::Pause => "pause",
42                FlowControlOpcode::Unknown(_) => "unknown",
43            }
44        )
45    }
46}
47
48/// Represents an Ethernet Flow Control packet defined by IEEE 802.3x.
49///
50/// [EtherType::FlowControl](crate::ethernet::EtherType::FlowControl) ethertype (0x8808).
51pub struct FlowControlPacket {
52    pub command: FlowControlOpcode,
53    pub quanta: u16be,
54    pub payload: Bytes,
55}
56
57impl Packet for FlowControlPacket {
58    type Header = ();
59    fn from_buf(mut bytes: &[u8]) -> Option<Self> {
60        if bytes.len() < 4 {
61            return None;
62        }
63
64        let command = FlowControlOpcode::new(bytes.get_u16());
65        let quanta = bytes.get_u16();
66
67        // Payload including padding; its contents are not specified by the standard
68        let payload = Bytes::copy_from_slice(bytes);
69
70        Some(Self {
71            command,
72            quanta: quanta.into(),
73            payload,
74        })
75    }
76
77    fn from_bytes(bytes: Bytes) -> Option<Self> {
78        Self::from_buf(&bytes)
79    }
80
81    fn to_bytes(&self) -> Bytes {
82        let mut buf = bytes::BytesMut::with_capacity(4 + self.payload.len());
83
84        buf.put_u16(self.command.value());
85        buf.put_u16(self.quanta.into());
86        buf.put_slice(&self.payload);
87
88        buf.freeze()
89    }
90    fn header(&self) -> Bytes {
91        let mut buf = bytes::BytesMut::with_capacity(4);
92
93        buf.put_u16(self.command.value());
94        buf.put_u16(self.quanta.into());
95
96        buf.freeze()
97    }
98
99    fn payload(&self) -> Bytes {
100        self.payload.clone()
101    }
102
103    fn header_len(&self) -> usize {
104        4
105    }
106
107    fn payload_len(&self) -> usize {
108        self.payload.len()
109    }
110
111    fn total_len(&self) -> usize {
112        self.header_len() + self.payload_len()
113    }
114
115    fn into_parts(self) -> (Self::Header, Bytes) {
116        ((), self.to_bytes())
117    }
118}
119
120/// Represents a mutable Ethernet Flow Control packet.
121pub type MutableFlowControlPacket<'a> = GenericMutablePacket<'a, FlowControlPacket>;
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126    use crate::packet::MutablePacket;
127
128    #[test]
129    fn flowcontrol_pause_test() {
130        let packet = Bytes::from_static(&[
131            0x00, 0x01, // Opcode: Pause
132            0x12, 0x34, // Quanta: 0x1234
133            0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // Padding ...
134        ]);
135
136        let fc_packet = FlowControlPacket::from_bytes(packet.clone()).unwrap();
137        assert_eq!(fc_packet.command, FlowControlOpcode::Pause);
138        assert_eq!(fc_packet.quanta, 0x1234);
139        assert_eq!(fc_packet.to_bytes(), packet);
140    }
141
142    #[test]
143    fn flowcontrol_mutable_packet() {
144        let mut raw = [
145            0x00, 0x01, // Opcode: Pause
146            0x12, 0x34, // Quanta: 0x1234
147            0xaa, 0xbb,
148        ];
149
150        let mut packet = <MutableFlowControlPacket as MutablePacket>::new(&mut raw)
151            .expect("mutable flowcontrol");
152        packet.header_mut()[0] = 0x00;
153        packet.header_mut()[1] = 0x02;
154        packet.payload_mut()[0] = 0xff;
155
156        let frozen = packet.freeze().expect("freeze");
157        assert_eq!(frozen.command, FlowControlOpcode::Unknown(2));
158        assert_eq!(frozen.payload[0], 0xff);
159    }
160}