use crate::extractor::{Extracted, FlowExtractor};
use crate::view::PacketView;
use super::{InnerGre, InnerGtpU, InnerVxlan, StripMpls, StripVlan};
#[derive(Debug, Clone, Copy)]
pub struct AutoEncapVariants {
pub vlan: bool,
pub mpls: bool,
pub vxlan: bool,
pub gtp_u: bool,
pub gre: bool,
}
impl AutoEncapVariants {
pub fn all() -> Self {
Self {
vlan: true,
mpls: true,
vxlan: true,
gtp_u: true,
gre: true,
}
}
pub fn none() -> Self {
Self {
vlan: false,
mpls: false,
vxlan: false,
gtp_u: false,
gre: false,
}
}
}
impl Default for AutoEncapVariants {
fn default() -> Self {
Self::all()
}
}
#[derive(Debug, Clone)]
pub struct AutoDetectEncap<E> {
pub extractor: E,
pub variants: AutoEncapVariants,
}
impl<E> AutoDetectEncap<E> {
pub fn new(extractor: E) -> Self {
Self {
extractor,
variants: AutoEncapVariants::all(),
}
}
pub fn with_variants(extractor: E, variants: AutoEncapVariants) -> Self {
Self {
extractor,
variants,
}
}
}
impl<E: FlowExtractor + Clone> FlowExtractor for AutoDetectEncap<E> {
type Key = E::Key;
fn extract(&self, view: PacketView<'_>) -> Option<Extracted<E::Key>> {
if let Some(e) = self.extractor.extract(view) {
return Some(e);
}
if self.variants.vlan
&& let Some(e) = StripVlan(self.extractor.clone()).extract(view)
{
return Some(e);
}
if self.variants.mpls
&& let Some(e) = StripMpls(self.extractor.clone()).extract(view)
{
return Some(e);
}
if self.variants.vxlan
&& let Some(e) = InnerVxlan::new(self.extractor.clone()).extract(view)
{
return Some(e);
}
if self.variants.gtp_u
&& let Some(e) = InnerGtpU::new(self.extractor.clone()).extract(view)
{
return Some(e);
}
if self.variants.gre
&& let Some(e) = InnerGre::new(self.extractor.clone()).extract(view)
{
return Some(e);
}
None
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Timestamp;
use crate::extract::FiveTuple;
use crate::extract::parse::test_frames::ipv4_tcp;
#[test]
fn plain_traffic_works() {
let bytes = ipv4_tcp(
[0; 6],
[0; 6],
[10, 0, 0, 1],
[10, 0, 0, 2],
1234,
80,
0,
0,
0x02,
b"",
);
let v = PacketView::new(&bytes, Timestamp::default());
let e = AutoDetectEncap::new(FiveTuple::bidirectional());
assert!(e.extract(v).is_some());
}
#[test]
fn variants_none_falls_back_to_plain_only() {
let bytes = ipv4_tcp(
[0; 6],
[0; 6],
[10, 0, 0, 1],
[10, 0, 0, 2],
1234,
80,
0,
0,
0x02,
b"",
);
let v = PacketView::new(&bytes, Timestamp::default());
let e =
AutoDetectEncap::with_variants(FiveTuple::bidirectional(), AutoEncapVariants::none());
assert!(e.extract(v).is_some());
}
#[test]
fn unknown_traffic_returns_none() {
let bytes: Vec<u8> = vec![0u8; 14]; let v = PacketView::new(&bytes, Timestamp::default());
let e = AutoDetectEncap::new(FiveTuple::bidirectional());
assert!(e.extract(v).is_none());
}
#[test]
fn variants_default_is_all() {
let v = AutoEncapVariants::default();
assert!(v.vlan && v.mpls && v.vxlan && v.gtp_u && v.gre);
}
}