117 lines
2.6 KiB
Markdown
117 lines
2.6 KiB
Markdown
|
## 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 {
|
||
|
^^^^^
|
||
|
```
|
||
|
|
||
|
### 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)
|
||
|
|
||
|
- Have to investigate
|