Skip to content

Commit ae51a41

Browse files
committed
support vlan tagged traffic in pcap mode
1 parent 9554a9a commit ae51a41

File tree

1 file changed

+84
-0
lines changed

1 file changed

+84
-0
lines changed

rustiflow/src/pcap.rs

+84
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ use tokio::sync::mpsc::Sender;
1616
// Define constants for Linux cooked capture EtherTypes
1717
const SLL_IPV4: u16 = 0x0800;
1818
const SLL_IPV6: u16 = 0x86DD;
19+
// Define constant for 802.1Q VLAN EtherType
20+
const ETHERTYPE_VLAN: u16 = 0x8100;
1921

2022
pub async fn read_pcap_file<T>(
2123
path: &str,
@@ -87,6 +89,47 @@ where
8789
.await;
8890
}
8991
}
92+
EtherTypes::Vlan => {
93+
// Handle 802.1Q VLAN tagged packets
94+
// VLAN header is 4 bytes: 2 bytes for VLAN tag and 2 bytes for inner EtherType
95+
if ethernet.payload().len() >= 4 {
96+
let inner_ethertype =
97+
u16::from_be_bytes([ethernet.payload()[2], ethernet.payload()[3]]);
98+
99+
match inner_ethertype {
100+
SLL_IPV4 => {
101+
if let Some(packet) = Ipv4Packet::new(&ethernet.payload()[4..]) {
102+
process_packet::<T, Ipv4Packet>(
103+
&packet,
104+
timestamp_us,
105+
&shard_senders,
106+
num_threads,
107+
PacketFeatures::from_ipv4_packet,
108+
)
109+
.await;
110+
}
111+
}
112+
SLL_IPV6 => {
113+
if let Some(packet) = Ipv6Packet::new(&ethernet.payload()[4..]) {
114+
process_packet::<T, Ipv6Packet>(
115+
&packet,
116+
timestamp_us,
117+
&shard_senders,
118+
num_threads,
119+
PacketFeatures::from_ipv6_packet,
120+
)
121+
.await;
122+
}
123+
}
124+
_ => debug!(
125+
"Unsupported inner EtherType in VLAN packet: 0x{:04x}",
126+
inner_ethertype
127+
),
128+
}
129+
} else {
130+
debug!("VLAN packet too short to contain inner EtherType");
131+
}
132+
}
90133
_ => {
91134
// Check if it is a Linux cooked capture
92135
let ethertype = u16::from_be_bytes([packet.data[14], packet.data[15]]);
@@ -115,6 +158,47 @@ where
115158
.await;
116159
}
117160
}
161+
ETHERTYPE_VLAN => {
162+
// Handle VLAN in Linux cooked capture
163+
if packet.data.len() >= 20 {
164+
// 16 bytes SLL header + 4 bytes VLAN header
165+
let inner_ethertype =
166+
u16::from_be_bytes([packet.data[18], packet.data[19]]);
167+
168+
match inner_ethertype {
169+
SLL_IPV4 => {
170+
if let Some(packet) = Ipv4Packet::new(&packet.data[20..]) {
171+
process_packet::<T, Ipv4Packet>(
172+
&packet,
173+
timestamp_us,
174+
&shard_senders,
175+
num_threads,
176+
PacketFeatures::from_ipv4_packet,
177+
)
178+
.await;
179+
}
180+
}
181+
SLL_IPV6 => {
182+
if let Some(packet) = Ipv6Packet::new(&packet.data[20..]) {
183+
process_packet::<T, Ipv6Packet>(
184+
&packet,
185+
timestamp_us,
186+
&shard_senders,
187+
num_threads,
188+
PacketFeatures::from_ipv6_packet,
189+
)
190+
.await;
191+
}
192+
}
193+
_ => debug!(
194+
"Unsupported inner EtherType in VLAN packet: 0x{:04x}",
195+
inner_ethertype
196+
),
197+
}
198+
} else {
199+
debug!("VLAN packet in Linux cooked capture too short");
200+
}
201+
}
118202
_ => debug!("Failed to parse packet as IPv4 or IPv6..."),
119203
}
120204
}

0 commit comments

Comments
 (0)