Skip to content

Commit f5d2633

Browse files
committed
feat(flow-filter): Add support for "default" destination VpcExpose
Make sure that we account for "default" VpcExpose when we retrieve the destination VPC discriminant for the packet. Internally, we don't add a prefix for the default destination into the tables, because we'd have to handle overlap to some extent. Instead, we add a per-source-VPC value to use as a fallback when no other destination prefix match. At the moment, the code assumes that each VPC accepts at most one "default" destination. Signed-off-by: Quentin Monnet <[email protected]>
1 parent d9d5566 commit f5d2633

File tree

3 files changed

+189
-64
lines changed

3 files changed

+189
-64
lines changed

flow-filter/src/lib.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,16 @@ impl FlowFilter {
7777
});
7878
let log_str = format_packet_addrs_ports(&src_ip, &dst_ip, ports);
7979

80-
let Some(VpcdLookupResult::Single(dst_vpcd)) =
81-
tablesr.lookup(src_vpcd, &src_ip, &dst_ip, ports)
82-
else {
83-
debug!("{nfi}: Flow not allowed, dropping packet: {log_str}");
84-
packet.done(DoneReason::Filtered);
85-
return;
86-
};
87-
88-
debug!("{nfi}: Flow allowed: {log_str}, setting packet dst_vpcd to {dst_vpcd}");
89-
packet.meta.dst_vpcd = Some(dst_vpcd);
80+
match tablesr.lookup(src_vpcd, &src_ip, &dst_ip, ports) {
81+
Some(VpcdLookupResult::Single(dst_vpcd) | VpcdLookupResult::Default(dst_vpcd)) => {
82+
debug!("{nfi}: Flow allowed: {log_str}, setting packet dst_vpcd to {dst_vpcd}");
83+
packet.meta.dst_vpcd = Some(dst_vpcd);
84+
}
85+
None => {
86+
debug!("{nfi}: Flow not allowed, dropping packet: {log_str}");
87+
packet.done(DoneReason::Filtered);
88+
}
89+
}
9090
}
9191
}
9292

@@ -188,7 +188,7 @@ mod tests {
188188
table
189189
.insert(
190190
src_vpcd,
191-
VpcdLookupResult::Single(dst_vpcd),
191+
dst_vpcd,
192192
Prefix::from("10.0.0.0/24"),
193193
OptionalPortRange::NoPortRangeMeansAllPorts,
194194
Prefix::from("20.0.0.0/24"),
@@ -227,7 +227,7 @@ mod tests {
227227
table
228228
.insert(
229229
src_vpcd,
230-
VpcdLookupResult::Single(dst_vpcd),
230+
dst_vpcd,
231231
Prefix::from("10.0.0.0/24"),
232232
OptionalPortRange::NoPortRangeMeansAllPorts,
233233
Prefix::from("20.0.0.0/24"),
@@ -288,7 +288,7 @@ mod tests {
288288
table
289289
.insert(
290290
src_vpcd,
291-
VpcdLookupResult::Single(dst_vpcd),
291+
dst_vpcd,
292292
Prefix::from("10.0.0.0/24"),
293293
OptionalPortRange::NoPortRangeMeansAllPorts,
294294
Prefix::from("20.0.0.0/24"),
@@ -326,7 +326,7 @@ mod tests {
326326
table
327327
.insert(
328328
src_vpcd,
329-
VpcdLookupResult::Single(dst_vpcd),
329+
dst_vpcd,
330330
Prefix::from("2001:db8::/32"),
331331
OptionalPortRange::NoPortRangeMeansAllPorts,
332332
Prefix::from("2001:db9::/32"),
@@ -365,7 +365,7 @@ mod tests {
365365
table
366366
.insert(
367367
src_vpcd,
368-
VpcdLookupResult::Single(dst_vpcd),
368+
dst_vpcd,
369369
Prefix::from("10.0.0.0/24"),
370370
OptionalPortRange::NoPortRangeMeansAllPorts,
371371
Prefix::from("20.0.0.0/24"),

flow-filter/src/setup.rs

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// Copyright Open Network Fabric Authors
33

44
use crate::FlowFilterTable;
5-
use crate::tables::VpcdLookupResult;
65
use config::ConfigError;
76
use config::external::overlay::Overlay;
87
use config::external::overlay::vpc::{Peering, Vpc};
@@ -42,20 +41,46 @@ impl FlowFilterTable {
4241
.remote
4342
.exposes
4443
.iter()
45-
.flat_map(|expose| expose.public_ips());
46-
47-
// For each local prefix, add one entry for each associated remote prefix
48-
for local_prefix in local_prefixes {
49-
for remote_prefix in remote_prefixes.clone() {
50-
self.insert(
44+
.flat_map(|expose| expose.public_ips())
45+
.collect::<Vec<_>>();
46+
// We support one default at most for now
47+
let remote_has_default = peering.remote.exposes.iter().any(|expose| expose.default);
48+
49+
if remote_prefixes.is_empty() && !remote_has_default {
50+
return Err(ConfigError::FailureApply(
51+
"No remote prefixes found".to_string(),
52+
));
53+
} else if remote_prefixes.is_empty() && remote_has_default {
54+
// Corner case: all prefixes go to the default remote. In this case we need to build
55+
// entries for the source prefixes, so that we can validate that packets come from
56+
// legitimate source prefixes, but we do not associate any destination (we'll fall back
57+
// to the default destination)
58+
for local_prefix in local_prefixes {
59+
self.insert_default_only(
5160
local_vpcd,
52-
VpcdLookupResult::Single(dst_vpcd),
5361
local_prefix.prefix(),
5462
local_prefix.ports().into(),
55-
remote_prefix.prefix(),
56-
remote_prefix.ports().into(),
5763
)?;
5864
}
65+
} else {
66+
// remote_prefixes is not empty: for each local prefix, add one entry for each
67+
// associated remote prefix
68+
for local_prefix in local_prefixes {
69+
for remote_prefix in &remote_prefixes {
70+
self.insert(
71+
local_vpcd,
72+
dst_vpcd,
73+
local_prefix.prefix(),
74+
local_prefix.ports().into(),
75+
remote_prefix.prefix(),
76+
remote_prefix.ports().into(),
77+
)?;
78+
}
79+
}
80+
}
81+
82+
if remote_has_default {
83+
self.add_default_remote(local_vpcd, dst_vpcd)?;
5984
}
6085
Ok(())
6186
}

0 commit comments

Comments
 (0)