Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
07a591a
feat(net): add port-forwarding metadata flag
Fredi-raspall Feb 6, 2026
2c06202
feat(flow-filter): extend NatRequirement
Fredi-raspall Feb 6, 2026
73dd15c
feat(stateful-nat): simplify nat_packet() args
Fredi-raspall Feb 6, 2026
9107ae0
feat(net): impl Display for NextHeader
Fredi-raspall Feb 6, 2026
4541024
feat(flow-info): extend FlowInfoLocked
Fredi-raspall Feb 6, 2026
ff16b2e
feat(flow-entry): impl methods for [Tcp|Udp]ProtoKey
Fredi-raspall Feb 6, 2026
771ea0c
feat(port-forwarding): add port-forwarding nat submodule
Fredi-raspall Feb 6, 2026
8e88b64
feat(port-forwarding): add table and objects
Fredi-raspall Feb 6, 2026
c4f1f26
feat(port-forwarding): impl Display for tables
Fredi-raspall Feb 6, 2026
053a35a
feat(port-forwarding): add tests portfw table
Fredi-raspall Feb 6, 2026
e2b4828
feat(port-forwarding): use UnicastIpAddr instead of IpAddr
Fredi-raspall Feb 6, 2026
c783f6d
feat(port-forwarding): define PortFwState
Fredi-raspall Feb 6, 2026
12db9c4
feat(port-forwarding): add port-forwarding packet utils
Fredi-raspall Feb 7, 2026
fe493a4
feat(flow-entry,flow-info): change update_status()
Fredi-raspall Feb 9, 2026
0da67ec
feat(port-forwarding): add functions to deal with state
Fredi-raspall Feb 9, 2026
888af74
feat(port-forwarding): add NF for port-forwarding
Fredi-raspall Feb 9, 2026
21367cd
feat(datplane): add port-forwarding stage
Fredi-raspall Feb 9, 2026
e13ebfb
feat(net): use Udp::empty() in tests
Fredi-raspall Feb 9, 2026
8fe9103
feat(port-forwarding): add minimal test
Fredi-raspall Feb 9, 2026
2d6217e
feat(flow-info): impl Display for FlowInfoLocked
Fredi-raspall Feb 10, 2026
a4e9d22
feat(flow-entry): allow stripping vpcd from flow key
Fredi-raspall Feb 10, 2026
7329069
feat(port-forwarding): omit dst vpcd in flow keys
Fredi-raspall Feb 10, 2026
c59dc81
feat(port-forwarding): add state for forward path
Fredi-raspall Feb 10, 2026
3792b6b
feat(flow-entry): remove bidirectional flow keys
Fredi-raspall Feb 18, 2026
36ed06f
feat(flow-entry): remove trait SrcLeqDst
Fredi-raspall Feb 19, 2026
f4ccc90
feat(test-utils): add tcp packet builder
Fredi-raspall Feb 10, 2026
fa54ce4
feat(flow-entry): fix Display FlowTable
Fredi-raspall Feb 12, 2026
11006a0
feat(port-forwarding): add timeouts to rules
Fredi-raspall Feb 10, 2026
9becdd3
feat(port-forwarding): keep key in PortFwEntry
Fredi-raspall Feb 11, 2026
ec596b4
feat(port-forwarding): let state refer to rules
Fredi-raspall Feb 11, 2026
56a886d
feat(port-forwarding): early-expire flow entries
Fredi-raspall Feb 11, 2026
9cd67ae
feat(port-forwarding): adapt Display impls
Fredi-raspall Feb 11, 2026
817aedd
feat(port-forwarding): no state without TCP syn
Fredi-raspall Feb 10, 2026
d277f7b
feat(port-forwarding): add status enum to state
Fredi-raspall Feb 11, 2026
15db806
feat(port-forwarding): set flow status and refresh
Fredi-raspall Feb 11, 2026
adda01a
feat(port-forwarding): cleanup
Fredi-raspall Feb 11, 2026
bdcfd14
feat(port-forwarding): add test
Fredi-raspall Feb 11, 2026
99af354
feat(port-forwarding): reorg source code
Fredi-raspall Feb 12, 2026
cad607c
feat(port-forwarding): simplify PortFwTable api
Fredi-raspall Feb 12, 2026
610c413
feat(port-forwarding): change port forwarding table
Fredi-raspall Feb 12, 2026
fde2ec6
feat(port-forwarding): keep timers as AtomicU64
Fredi-raspall Feb 12, 2026
de3293a
feat(port-forwarding): move PortFwTableError
Fredi-raspall Feb 13, 2026
6319ed2
feat(port-forwarding): add portrange submodule
Fredi-raspall Feb 13, 2026
738572d
feat(port-forwarding): require Arc in methods
Fredi-raspall Feb 13, 2026
5a478e0
feat(port-forwarding): implement left-right access
Fredi-raspall Feb 13, 2026
bd2633e
feat(port-forwarding): misc. cleanup
Fredi-raspall Feb 13, 2026
8cd68ff
feat(port-fowarding): replace accessor
Fredi-raspall Feb 13, 2026
a261ae6
feat(dataplane,mgmt): propagate writer port forwarding
Fredi-raspall Feb 16, 2026
ec5db07
feat(config,nat,mgmt): scaffold port-forwarding config
Fredi-raspall Feb 16, 2026
11bf27e
feat(port-forwarding): implement port ranges
Fredi-raspall Feb 17, 2026
5f6572b
feat(port-forwarding): add methods PortRange
Fredi-raspall Feb 23, 2026
162d708
feat(net): add utils to get/set transport ports
Fredi-raspall Feb 18, 2026
8b610f3
feat(flow-emtry): make FlowTable::len() available
Fredi-raspall Feb 18, 2026
9ae1386
feat(port-forwarding): build flows in pairs
Fredi-raspall Feb 18, 2026
a341e1f
feat(port-forwarding): add tests
Fredi-raspall Feb 14, 2026
8f39c3a
feat(port-forwarding): require metadata to port-forward
Fredi-raspall Feb 19, 2026
3890d23
feat(flow-entry,flow-info): revisit flow status
Fredi-raspall Feb 19, 2026
14710b4
feat(port-forwarding): flow invalidation
Fredi-raspall Feb 19, 2026
eff8ecb
feat(lpm): add convenience Prefix methods
Fredi-raspall Feb 20, 2026
83b4fd2
feat(lpm): add fallible converters
Fredi-raspall Feb 22, 2026
b9d20d5
feat(port-forwarding): add support for prefix rules
Fredi-raspall Feb 23, 2026
77f2a1c
feat(flow-entry,dependencies): remove dst vpcd from FlowKey
Fredi-raspall Feb 23, 2026
0a0fbd6
feat(port-forwarding): rename fields for clarity
Fredi-raspall Feb 24, 2026
b62befb
feat(dataplane): add tracing targets for Vxlan
Fredi-raspall Feb 25, 2026
88d837a
feat(flow-entry): use Display in logs instead of Debug
Fredi-raspall Feb 25, 2026
2dfcb67
feat(net): fix Display of TCP flags
Fredi-raspall Feb 25, 2026
b16366a
feat(net): add method to reset packet metadata
Fredi-raspall Feb 26, 2026
6fefef0
feat(port-forwarding): add tcp rst builder
Fredi-raspall Feb 26, 2026
0cd26a0
feat(lpm): add IpPrefixTrie get(), iter() and iter_mut()
Fredi-raspall Feb 27, 2026
1b6f45e
feat(port-forwarding): add range sets and PrefixMap
Fredi-raspall Feb 20, 2026
182ebb8
feat(port-forwarding): add lpm map
Fredi-raspall Feb 27, 2026
780e56b
feat(port-forwarding): add port-forwarder object
Fredi-raspall Feb 23, 2026
9c89452
feat(port-forwarding): use the PortForwarder
Fredi-raspall Feb 24, 2026
37a3c5c
feat(port-forwarding): logging improvements
Fredi-raspall Feb 25, 2026
34b1949
feat(port-forwarding): move PortFwFlowStatus
Fredi-raspall Feb 28, 2026
123767b
feat(port-forwarding): fix dst vpcd in flow
Fredi-raspall Mar 1, 2026
f6a0d21
feat(port-forwarding): refine the TCP state machine
Fredi-raspall Mar 2, 2026
6088429
feat(port-forwarding): invalidate TCP flows if closed
Fredi-raspall Mar 2, 2026
0eab971
feat(port-forwarding): set default timeouts dep on proto
Fredi-raspall Mar 2, 2026
6497a7c
feat(flow-entry): aggressively reap cancelled flows
Fredi-raspall Mar 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ pub enum ConfigError {

#[error("Community {0} is mapped from distinct priorities")]
DuplicateCommunity(String),

#[error("Failed to apply port-forwarding configuration: {0}")]
PortForwarding(String),
}

/// Result-like type for configurations
Expand Down
1 change: 1 addition & 0 deletions dataplane/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ fn main() {
nattablesw: setup.nattablesw,
natallocatorw: setup.natallocatorw,
flowfilterw: setup.flowfiltertablesw,
portfw_w: setup.portfw_w,
vpc_stats_store: setup.vpc_stats_store,
dp_status_r: dp_status.clone(),
bmp_options: bmp_client_opts,
Expand Down
14 changes: 9 additions & 5 deletions dataplane/src/packet_processor/ipforward.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,14 @@ use net::packet::VpcDiscriminant;
use net::udp::UdpEncap;
use net::vxlan::{Vxlan, VxlanEncap};

use tracectl::trace_target;
use tracectl::{custom_target, tdebug, trace_target};
trace_target!("ip-forward", LevelFilter::WARN, &["pipeline"]);

const VXLAN_D: &str = "vxlan-decap";
const VXLAN_E: &str = "vxlan-encap";
custom_target!(VXLAN_D, LevelFilter::OFF, &["vxlan"]);
custom_target!(VXLAN_E, LevelFilter::OFF, &["vxlan"]);

pub struct IpForwarder {
name: String,
fibtr: FibTableReader,
Expand Down Expand Up @@ -131,8 +136,8 @@ impl IpForwarder {
match packet.vxlan_decap() {
Some(Ok(vxlan)) => {
let vni = vxlan.vni();
debug!("{nfi}: DECAPSULATED vxlan packet:\n {packet}");
debug!("{nfi}: Packet comes with vni {vni}");
tdebug!(VXLAN_D, "DECAPSULATED vxlan packet (vni={vni}):\n{packet}");
debug!("{nfi}: DECAPSULATED vxlan packet, vni = {vni}");

// access fib for Vni vni
let fibkey = FibKey::from_vni(vni);
Expand Down Expand Up @@ -274,8 +279,6 @@ impl IpForwarder {
}
Ok(vxlan_headers) => match packet.vxlan_encap(&vxlan_headers) {
Ok(()) => {
debug!("{nfi}: ENCAPSULATED packet with VxLAN:\n {packet}");

let vni = vxlan_headers
.headers()
.udp_encap
Expand All @@ -284,6 +287,7 @@ impl IpForwarder {
.vxlan_vni();

packet.meta_mut().dst_vpcd = vni.map(VpcDiscriminant::VNI);
tdebug!(VXLAN_E, "ENCAPSULATED packet with VxLAN:\n{packet}");
}
Err(e) => {
error!("{nfi}: Failed to ENCAPSULATE packet with VxLAN: {e}");
Expand Down
11 changes: 11 additions & 0 deletions dataplane/src/packet_processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use concurrency::sync::Arc;
use flow_entry::flow_table::{ExpirationsNF, FlowLookup, FlowTable};
use flow_filter::{FlowFilter, FlowFilterTableWriter};

use nat::portfw::{PortForwarder, PortFwTableWriter};
use nat::stateful::NatAllocatorWriter;
use nat::stateless::NatTablesWriter;
use nat::{StatefulNat, StatelessNat};
Expand All @@ -41,6 +42,7 @@ where
pub flowfiltertablesw: FlowFilterTableWriter,
pub stats: StatsCollector,
pub vpc_stats_store: Arc<VpcStatsStore>,
pub portfw_w: PortFwTableWriter,
}

/// Start a router and provide the associated pipeline
Expand All @@ -52,6 +54,7 @@ pub(crate) fn start_router<Buf: PacketBufferMut>(
let flowfiltertablesw = FlowFilterTableWriter::new();
let router = Router::new(params)?;
let vpcmapw = VpcMapWriter::<VpcMapName>::new();
let portfw_w = PortFwTableWriter::new();

// Allocate the shared VPC stats store (returns Arc<VpcStatsStore>)
let vpc_stats_store: Arc<VpcStatsStore> = VpcStatsStore::new();
Expand All @@ -69,6 +72,7 @@ pub(crate) fn start_router<Buf: PacketBufferMut>(
let atabler_factory = router.get_atabler_factory();
let nattabler_factory = nattablesw.get_reader_factory();
let natallocator_factory = natallocatorw.get_reader_factory();
let portfw_factory = portfw_w.reader().factory();

let pipeline_builder = move || {
// Build network functions
Expand All @@ -87,6 +91,11 @@ pub(crate) fn start_router<Buf: PacketBufferMut>(
let flow_filter = FlowFilter::new("flow-filter", flowfiltertablesr_factory.handle());
let flow_lookup = FlowLookup::new("flow-lookup", flow_table.clone());
let flow_expirations_nf = ExpirationsNF::new(flow_table.clone());
let portfw = PortForwarder::new(
"port-forwarder",
portfw_factory.handle(),
flow_table.clone(),
);

// Build the pipeline for a router. The composition of the pipeline (in stages) is currently
// hard-coded. In any pipeline, the Stats and ExpirationsNF stages should go last
Expand All @@ -95,6 +104,7 @@ pub(crate) fn start_router<Buf: PacketBufferMut>(
.add_stage(iprouter1)
.add_stage(flow_lookup)
.add_stage(flow_filter)
.add_stage(portfw)
.add_stage(stateless_nat)
.add_stage(stateful_nat)
.add_stage(iprouter2)
Expand All @@ -113,5 +123,6 @@ pub(crate) fn start_router<Buf: PacketBufferMut>(
flowfiltertablesw,
stats,
vpc_stats_store,
portfw_w,
})
}
34 changes: 12 additions & 22 deletions flow-entry/src/flow_table/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,44 +49,34 @@ impl Display for FlowKeyData {
};

match self.src_vpcd() {
Some(vpcd) => write!(f, "{{ VPCs({vpcd}->"),
Some(vpcd) => write!(f, "{{ VPCs({vpcd}"),
None => write!(f, "{{ VPCs(None->"),
}?;
match self.dst_vpcd() {
Some(vpcd) => write!(f, "{vpcd})"),
None => write!(f, "None)"),
}?;
write!(f, " {protocol} ({source}, {destination}){icmp_data} }}")
}
}

impl Display for FlowKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FlowKey::Unidirectional(data) | FlowKey::Bidirectional(data) => write!(f, "{data}"),
FlowKey::Unidirectional(data) => write!(f, "{data}"),
}
}
}

impl Display for FlowTable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let table = self.table.read().unwrap();
Heading(format!("Flow Table ({})", table.len())).fmt(f)?;
for entry in table.iter() {
if let Some(value) = entry.value().upgrade() {
let value = value.locked.read().unwrap();
let nat_state = value.nat_state.as_ref();
let dst_vpcd = value.dst_vpcd.as_ref();
write!(f, "{} -> ", entry.key())?;
match nat_state {
Some(state) => write!(f, "{{ {state}, "),
None => write!(f, "{{ None, "),
}?;
match dst_vpcd {
Some(vpcd) => writeln!(f, "dst_vpcd: {vpcd} }}"),
None => writeln!(f, "dst_vpcd: None }}"),
}?;
if let Ok(table) = self.table.try_read() {
Heading(format!("Flow Table ({} entries)", table.len())).fmt(f)?;
for entry in table.iter() {
let key = entry.key();
match entry.value().upgrade() {
Some(value) => writeln!(f, "key = {key}\ndata = {value}")?,
None => writeln!(f, "key = {key} NONE")?,
}
}
} else {
write!(f, "Failed to lock flow table")?;
}
Ok(())
}
Expand Down
Loading
Loading