++ nat64 update, discussion update

This commit is contained in:
Nico Schottelius 2019-03-14 14:37:45 +01:00
parent b5cd3aeb0e
commit 7c8f019b2a
3 changed files with 71 additions and 9 deletions

View file

@ -106,7 +106,7 @@
| 2019-03-14 | NAT64 static rewrite | | | 2019-03-14 | NAT64 static rewrite | |
| | - table support | | | | - table support | |
| | - checksum not yet ported for translations | | | | - checksum not yet ported for translations | |
| | - how to get mask from lpm table match? | | | | - how to get mask from lpm table match? | |
| | - how to get network from lpm match? | | | | - how to get network from lpm match? | |
| | | | | | | |
| | | | | | | |
@ -1053,6 +1053,64 @@ DEBUG:main:INCOMING: <Ether dst=33:33:ff:00:00:42 src=00:00:0a:00:00:01 type=0x
**** Requirements **** Requirements
*** Performance comparison *** Performance comparison
*** Feature/Functionality difference / overview / Challenges / limitations in P4 *** Feature/Functionality difference / overview / Challenges / limitations in P4
**** P4: cannot read key from table
Key and mask for matching destination is in table. We need this
information in the action. However this information is not exposed, so
we need to specify another parameter with the same information as in
the key(s).
Log from slack: (2019-03-14)
nico [1:55 PM]
If I use LPM for matching, can I easily get the network address from P4 or do I have to use a bitmask myself? In the latter case it is not exactly clear how to get the mask from the table
Nate Foster [1:58 PM]
You want to retrieve the address in the packet? In a table?
And do you want to do the retrieving from the data plane or the control plane? (edited)
nico [2:00 PM]
If I have a match in a table that matches on LPM, it can be any IP address in a network
For calculating the NAT64/NAT46 translation, I will need the base address, i.e. network address to do subtractions/additions
So it is fully data plane, what I would like to do
I'll commit sample code to show the use case more clearly
https://gitlab.ethz.ch/nicosc/master-thesis/blob/master/p4src/static-mapping.p4#L73
GitLab
p4src/static-mapping.p4 · master · nicosc / master-thesis
gitlab.ethz.ch
So the action nat64_static() is used in the table v6_networks.
In v6_networks I use a match on `hdr.ipv6.dst_addr: lpm;`
What I would like to be able is to get the network address ; I can do that manually, if I have the mask
I can also re-inject this parameter by another action argument, but I'd assume that I can somewhere read this out from the table / match
Nate Foster [2:15 PM]
To make sure I understand, in the data plane, you want to retrieve the address in the lpm pattern? (edited)
nico [2:16 PM]
I want to retrieve the key
Nate Foster [2:16 PM]
Wait. The value `hdr.ipv6.dst_addr` is the thing used in the match.
So you have that.
What you dont have is the IPv6 address and mask put into the table by the control plane.
I assume you want the latter, right?
nico [2:17 PM]
For example, if my matching key is 2001:db8::/32 and the real address is 2001:db8::f00, then I would like to retrieve 2001:db8:: and 32 from the table
exactly :slightly_smiling_face:
I can "fix" this by adding another argument, but it feels somewhat wrong to do that
Because the table already knows this information
Nate Foster [2:26 PM]
I cant think of a way other than the action parameter hack.
nico [2:26 PM]
Oh, ok
Is it because the information is "lost in hardware"?
Nate Foster [2:31 PM]
No youre right that most implementations have the value in memory. And one can imagine a different table API that allowed one to retrieve it in the data plane.
But unless I am missing something obvious, P4 hides it…
**** ICMP6: checksum over payload **** ICMP6: checksum over payload
- variable length, up to 65k - variable length, up to 65k
**** Synchronisation with the controller **** Synchronisation with the controller

View file

@ -117,7 +117,7 @@ class L2Controller(object):
self.nat64_map[mode].append({ self.nat64_map[mode].append({
"v6_network": v6_net, "v6_network": v6_net,
"v4_network": v4_net, "v4_network": v4_net,
"v6_nat64_prefix": self.info['nat64_nat_prefix'] "nat64_prefix": self.info['nat64_nat_prefix']
}) })
self.init_boilerplate(sw_name) self.init_boilerplate(sw_name)
@ -213,7 +213,7 @@ class L2Controller(object):
self.static_nat64_mapping(**nat64map) self.static_nat64_mapping(**nat64map)
def static_nat64_mapping(self, v6_nat64_prefix, v6_network, v4_network): def static_nat64_mapping(self, nat64_prefix, v6_network, v4_network):
nat64_prefix = str(v6_nat64_prefix) nat64_prefix = str(v6_nat64_prefix)
net_ipv6 = str(v6_network) net_ipv6 = str(v6_network)
net_ipv4 = str(v4_network) net_ipv4 = str(v4_network)

View file

@ -66,18 +66,22 @@ control MyIngress(inout headers hdr,
meta.cast_length = (bit<32>) hdr.ipv6.payload_length; meta.cast_length = (bit<32>) hdr.ipv6.payload_length;
} }
action nat64_static(ipv4_addr_t v6_network, ipv4_addr_t v4_network) { /* nat64_prefix is the same as the matching key, but without the mask */
action nat64_static(ipv4_addr_t v6_network, ipv4_addr_t v4_network, ipv6_addr_t nat64_prefix) {
ipv6_addr_t src_offset = hdr.ipv6.src_addr - v6_network; ipv6_addr_t src_offset = hdr.ipv6.src_addr - v6_network;
ipv4_addr_t src = v4_network + (ipv4_addr_t) src_offset; ipv4_addr_t src = v4_network + (ipv4_addr_t) src_offset;
ipv4_addr_t dst_offset = hdr.ipv6.dst_addr - LPM_MATCH_NETWORK_ADDRESS_IN_TABLE; ipv6_addr_t dst = (ipv4_addr_t) hdr.ipv6.dst_addr - nat64_prefix;
nat64_generic(src, dst); nat64_generic(src, dst);
} }
action nat46_static(ipv4_addr_t v4_network, ipv6_addr_t nat64_prefix ) { /* matching key: v4_network specified again */
ipv6_addr_t src = hdr.ipv4.dst_addr - v4_network; action nat46_static(ipv6_addr_t v6_network, ipv4_addr_t v4_network, ipv6_addr_t nat64_prefix ) {
ipv6_addr_t src = hdr.ipv4.dst_addr - v4_network; ipv6_addr_t src = nat64_prefix + (ipv6_addr_t) hdr.ipv4.src_addr;
ipv4_addr_t dst_offset = hdr.ipv4.dst_addr - v4_network;
ipv6_addr_t dst = v6_network + (ipv6_addr_t) dst_offset;
nat46_generic(src, dst); nat46_generic(src, dst);
} }