diff --git a/Cargo.lock b/Cargo.lock index 7004d12..b9326aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,7 +56,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -67,7 +67,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -353,7 +353,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -729,7 +729,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1327,7 +1327,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi 0.5.2", "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1815,7 +1815,7 @@ dependencies = [ [[package]] name = "p4" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/p4?branch=main#334e3599d552b702cadc3fdb8e9ba880ce3a56f0" +source = "git+https://github.com/oxidecomputer/p4?branch=main#a94ebebaceba60f78aa8a4df64b8c26c306eb6e0" dependencies = [ "colored", "regex", @@ -1824,7 +1824,7 @@ dependencies = [ [[package]] name = "p4-macro" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/p4?branch=main#334e3599d552b702cadc3fdb8e9ba880ce3a56f0" +source = "git+https://github.com/oxidecomputer/p4?branch=main#a94ebebaceba60f78aa8a4df64b8c26c306eb6e0" dependencies = [ "p4", "p4-rust", @@ -1837,7 +1837,7 @@ dependencies = [ [[package]] name = "p4-rust" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/p4?branch=main#334e3599d552b702cadc3fdb8e9ba880ce3a56f0" +source = "git+https://github.com/oxidecomputer/p4?branch=main#a94ebebaceba60f78aa8a4df64b8c26c306eb6e0" dependencies = [ "p4", "prettyplease", @@ -1850,7 +1850,7 @@ dependencies = [ [[package]] name = "p4rs" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/p4?branch=main#334e3599d552b702cadc3fdb8e9ba880ce3a56f0" +source = "git+https://github.com/oxidecomputer/p4?branch=main#a94ebebaceba60f78aa8a4df64b8c26c306eb6e0" dependencies = [ "bitvec", "num", @@ -2426,7 +2426,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3075,7 +3075,7 @@ dependencies = [ "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3084,7 +3084,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8c27177b12a6399ffc08b98f76f7c9a1f4fe9fc967c784c5a071fa8d93cf7e1" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -3099,7 +3099,7 @@ dependencies = [ [[package]] name = "tests" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/p4?branch=main#334e3599d552b702cadc3fdb8e9ba880ce3a56f0" +source = "git+https://github.com/oxidecomputer/p4?branch=main#a94ebebaceba60f78aa8a4df64b8c26c306eb6e0" dependencies = [ "anyhow", "bitvec", @@ -3730,7 +3730,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/p4/sidecar-lite.p4 b/p4/sidecar-lite.p4 index bc5ea34..0708fe7 100644 --- a/p4/sidecar-lite.p4 +++ b/p4/sidecar-lite.p4 @@ -16,6 +16,7 @@ control ingress( inout ingress_metadata_t ingress, inout egress_metadata_t egress, ) { + attached() attached; local() local; router() router; nat_ingress() nat; @@ -53,6 +54,7 @@ control ingress( // rack and should be sent to the scrimlet. else { fwd_to_scrimlet(); return; } } else { + attached.apply(ingress, hdr); nat.apply(hdr, ingress, egress); // check for ingress nat } @@ -158,18 +160,28 @@ control nat_ingress( } apply { - if (hdr.ipv4.isValid()) { nat_v4.apply(); } - if (hdr.ipv6.isValid()) { nat_v6.apply(); } + if (ingress.forward_needed == false) { + if (hdr.ipv4.isValid()) { nat_v4.apply(); } + if (hdr.ipv6.isValid()) { nat_v6.apply(); } + } + if (ingress.forward_needed == true) { + forward_packet(); + } } action forward_to_sled(bit<128> target, bit<24> vni, bit<48> mac) { - ingress.nat = true; + ingress.forward_tgt = target; + ingress.forward_vni = vni; + ingress.forward_mac = mac; + ingress.forward_needed = true; + } + action forward_packet() { bit<16> orig_l3_len = 0; bit<16> orig_l3_csum = 0; hdr.inner_eth = hdr.ethernet; - hdr.inner_eth.dst = mac; + hdr.inner_eth.dst = ingress.forward_mac; hdr.inner_eth.setValid(); if (hdr.vlan.isValid()) { hdr.inner_eth.ether_type = hdr.vlan.ether_type; @@ -218,7 +230,7 @@ control nat_ingress( hdr.ipv6.hop_limit = 8w255; // XXX hardcoded boundary services addr hdr.ipv6.src = 128w0xfd000099000000000000000000000001; - hdr.ipv6.dst = target; + hdr.ipv6.dst = ingress.forward_tgt; hdr.ipv6.setValid(); // set up outer udp @@ -235,7 +247,7 @@ control nat_ingress( hdr.geneve.crit = 1w0; hdr.geneve.reserved = 6w0; hdr.geneve.protocol = 16w0x6558; - hdr.geneve.vni = vni; + hdr.geneve.vni = ingress.forward_vni; hdr.geneve.reserved2 = 8w0; hdr.geneve.setValid(); @@ -266,7 +278,6 @@ control nat_ingress( }); hdr.udp.checksum = 16w0; } - } control local( @@ -300,6 +311,42 @@ control local( action local() { is_local = true; } } +control attached( + inout ingress_metadata_t ingress, + inout headers_t hdr, +) { + table attached_subnet_v4 { + key = { + hdr.ipv4.dst: lpm; + } + actions = { forward_to_sled; } + default_action = NoAction; + } + + table attached_subnet_v6 { + key = { + hdr.ipv6.dst: lpm; + } + actions = { forward_to_sled; } + default_action = NoAction; + } + + apply { + if (hdr.ipv4.isValid()) { + attached_subnet_v4.apply(); + } else if (hdr.ipv6.isValid()) { + attached_subnet_v6.apply(); + } + } + + action forward_to_sled(bit<128> target, bit<24> vni, bit<48> mac) { + ingress.forward_tgt = target; + ingress.forward_vni = vni; + ingress.forward_mac = mac; + ingress.forward_needed = true; + } +} + control resolver( inout headers_t hdr, inout egress_metadata_t egress, diff --git a/p4/softnpu.p4 b/p4/softnpu.p4 index 32efac9..6db8a0b 100644 --- a/p4/softnpu.p4 +++ b/p4/softnpu.p4 @@ -3,10 +3,13 @@ #include struct ingress_metadata_t { + bit<128> forward_tgt; + bit<24> forward_vni; + bit<48> forward_mac; bit<16> port; bit<16> nat_id; bit<16> path_idx; - bool nat; + bool forward_needed; bool lldp; // Used as mutable scratchpad shared between parser states. diff --git a/scadm/src/main.rs b/scadm/src/main.rs index 0be5a91..bd6b8c1 100644 --- a/scadm/src/main.rs +++ b/scadm/src/main.rs @@ -213,6 +213,8 @@ const LOCAL_V6: &str = "ingress.local.local_v6"; const LOCAL_V4: &str = "ingress.local.local_v4"; const NAT_V4: &str = "ingress.nat.nat_v4"; const NAT_V6: &str = "ingress.nat.nat_v6"; +const ATTACHED_SUBNET_V4: &str = "ingress.attached.attached_subnet_v4"; +const ATTACHED_SUBNET_V6: &str = "ingress.attached.attached_subnet_v6"; const RESOLVER_V4: &str = "ingress.resolver.resolver_v4"; const RESOLVER_V6: &str = "ingress.resolver.resolver_v6"; const MAC_REWRITE: &str = "ingress.mac.mac_rewrite"; @@ -1005,7 +1007,36 @@ fn dump_tables(table: &BTreeMap>) { }; println!("{dst_nat_id} -> {target}"); } - + println!("attached subnet v4:"); + for e in table.get(ATTACHED_SUBNET_V4).unwrap() { + let subnet = match get_addr_subnet(&e.keyset_data) { + Some((a, m)) => format!("{a}/{m}"), + _ => continue, + }; + let target = match get_addr_vni_mac(&e.parameter_data) { + Some((addr, vni, m)) => format!( + "{} {}/{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", + addr, vni, m[5], m[4], m[3], m[2], m[1], m[0], + ), + None => "?".into(), + }; + println!("{subnet} -> {target}"); + } + println!("attached subnet v6:"); + for e in table.get(ATTACHED_SUBNET_V6).unwrap() { + let subnet = match get_addr_subnet(&e.keyset_data) { + Some((a, m)) => format!("{a}/{m}"), + _ => continue, + }; + let target = match get_addr_vni_mac(&e.parameter_data) { + Some((addr, vni, m)) => format!( + "{} {}/{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", + addr, vni, m[5], m[4], m[3], m[2], m[1], m[0], + ), + None => "?".into(), + }; + println!("{subnet} -> {target}"); + } println!("port_mac:"); for e in table.get(MAC_REWRITE).unwrap() { let port = u16::from_le_bytes([e.keyset_data[0], e.keyset_data[1]]);