iris_core/protocols/packet/
ethernet.rs1use crate::memory::mbuf::Mbuf;
4use crate::protocols::packet::{Packet, PacketHeader, PacketParseError};
5use crate::utils::types::*;
6
7use anyhow::{bail, Result};
8use pnet::datalink::MacAddr;
9
10const VLAN_802_1Q: u16 = 0x8100;
11const VLAN_802_1AD: u16 = 0x88a8;
12
13const TAG_SIZE: usize = 4;
14const HDR_SIZE: usize = 14;
15const HDR_SIZE_802_1Q: usize = HDR_SIZE + TAG_SIZE;
16const HDR_SIZE_802_1AD: usize = HDR_SIZE_802_1Q + TAG_SIZE;
17
18#[derive(Debug)]
23pub struct Ethernet<'a> {
24 header: EthernetHeader,
26 offset: usize,
28 mbuf: &'a Mbuf,
30}
31
32impl Ethernet<'_> {
33 #[inline]
35 pub fn dst(&self) -> MacAddr {
36 self.header.dst
37 }
38
39 #[inline]
41 pub fn src(&self) -> MacAddr {
42 self.header.src
43 }
44
45 #[inline]
48 pub fn ether_type(&self) -> u16 {
49 self.next_header().unwrap_or(0) as u16
50 }
51
52 pub fn tci(&self) -> Option<u16> {
55 let ether_type: u16 = u16::from(self.header.ether_type);
56 match ether_type {
57 VLAN_802_1Q => {
58 if let Ok(dot1q) = self.mbuf.get_data(HDR_SIZE) {
59 let dot1q: Dot1q = unsafe { *dot1q };
60 Some(dot1q.tci.into())
61 } else {
62 None
63 }
64 }
65 _ => None,
66 }
67 }
68}
69
70impl<'a> Packet<'a> for Ethernet<'a> {
71 fn mbuf(&self) -> &Mbuf {
72 self.mbuf
73 }
74
75 fn header_len(&self) -> usize {
76 self.header.length()
77 }
78
79 fn next_header_offset(&self) -> usize {
80 self.offset + self.header_len()
81 }
82
83 fn next_header(&self) -> Option<usize> {
84 let ether_type: u16 = u16::from(self.header.ether_type);
85 match ether_type {
86 VLAN_802_1Q => {
87 if let Ok(dot1q) = self.mbuf.get_data(HDR_SIZE) {
88 let dot1q: Dot1q = unsafe { *dot1q };
89 Some(u16::from(dot1q.ether_type).into())
90 } else {
91 None
92 }
93 }
94 VLAN_802_1AD => {
95 None
97 }
98 _ => Some(ether_type.into()),
99 }
100 }
101
102 fn parse_from(outer: &'a impl Packet<'a>) -> Result<Self>
103 where
104 Self: Sized,
105 {
106 if let Ok(header) = outer.mbuf().get_data(0) {
107 Ok(Ethernet {
108 header: unsafe { *header },
109 offset: 0,
110 mbuf: outer.mbuf(),
111 })
112 } else {
113 bail!(PacketParseError::InvalidRead)
114 }
115 }
116}
117
118#[derive(Debug, Clone, Copy)]
120#[repr(C, packed)]
121struct EthernetHeader {
122 dst: MacAddr,
123 src: MacAddr,
124 ether_type: u16be,
125}
126
127impl PacketHeader for EthernetHeader {
128 fn length(&self) -> usize {
129 match self.ether_type.into() {
130 VLAN_802_1Q => HDR_SIZE_802_1Q,
131 VLAN_802_1AD => HDR_SIZE_802_1AD,
132 _ => HDR_SIZE,
133 }
134 }
135}
136
137#[derive(Debug, Clone, Copy)]
143#[repr(C, packed)]
144struct Dot1q {
145 tci: u16be,
146 ether_type: u16be,
147}
148
149impl PacketHeader for Dot1q {
150 fn length(&self) -> usize {
153 TAG_SIZE
154 }
155}
156
157