## What I want to do: NAT64 static mapping I want to use different mapped IPv4 networks for (possibly) the same destination IPv6 network. In other words: * Network A, 2001:db8::/64, sends to an address in 64:ff9b::/96 * The 8 bit sub network ("range") of 2001:db8::/64, 2001:db8::/120 should be mapped to 10.1.0.0/24 * Network B, 2001:db8:1::/64, sends to an address in 64:ff9b::/96 * The 8 bit sub network ("range") of 2001:db8:1::/64, 2001:db8:1::/120 should be mapped to 10.1.1.0/24 ## What I tried to do ### 2 LPM keys I tried to use one table with two LPM keys, which I would like to match "in order": ``` table nat64 { key = { hdr.ipv6.src_addr: lpm; hdr.ipv6.dst_addr: lpm; } actions = { controller_debug; nat64_static; NoAction; } size = NAT64_TABLE_SIZE; default_action = controller_debug; } ``` So matching hdr.ipv6.src_addr first and then if the destination packet is in 64:ff9b::/96, then do NAT64. This results into the compiler problem ``` ../p4src/static-mapping.p4(121): error: MyIngress.nat64, Multiple LPM keys in table table nat64 { ^^^^^ ``` ## How it could be solved ### 2 tables (recommendation of Nate) It does not work, when matching the source address first: ``` table nat64_src { key = { hdr.ipv6.src_addr: lpm; } actions = { NoAction; } size = NAT64_TABLE_SIZE; default_action = NoAction; } table nat64_dst { key = { hdr.ipv6.dst_addr: lpm; } actions = { controller_debug; nat64_static; NoAction; } size = NAT64_TABLE_SIZE; default_action = controller_debug; } ... apply { if (nat64_src.apply().hit) { nat64_dst.apply(); } } ``` The entries of nat64_dst.apply() will be all the same, i.e. there will be many 64:ff9b::/96 entries and thus this approach does not work. Trying to match the destination address first: ``` ... apply { if (nat64_dst.apply().hit) { nat64_src.apply(); } } ``` This way repeating destination addresses will still not be set, but this is not a problem as one is enough to proceed into the nat64_src table. Disadvantage of this approach is that entries from the nat64_dst table cannot be deleted safely anymore, as repeating destination addresses of other networks might be deleted. So while this approach works for testing / development, it does not work for a production setup. ### Ternary matching (recommendation of Andy) Could be a solution, because it offers priorities. Is not exactly what I want to achieve, because I want to do LPM matching, but it could be misused for it. ### Double table with using ID of first match (Andy + Nate ideas) Use the handle of the source network to match again on exact in the 2nd table. This might be a very reasonable approach.