+ reorg +add simple nat64 w/o protocol specific translations

This commit is contained in:
Nico Schottelius 2019-03-23 16:20:13 +01:00
parent 4972f550d8
commit a408d7a803
3 changed files with 130 additions and 87 deletions

View File

@ -1161,9 +1161,15 @@ check whether tables are applied correctly (type conversion
problems) - start tcpdump - start test program - stop tcpdump - add
pcap to git repo - git add-commit-push - git pull - start wireshark -
debug packets - analyse code - goto 1
**** Static NAT64
Asymmetric maps: v6->v4 can match whole IPv4 Internet (/96)
But v4->v6 can only map sub range!
Using /24s (for convience) in IPv4
*** Performance comparison
*** Feature/Functionality difference / overview / Challenges / limitations in P4
*** Feature/Functionality difference / overview / CHALLENGES / LIMITATIONS in P4
**** P4: cannot read key from table
***** log
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
@ -1221,9 +1227,12 @@ 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
***** Result
Need to duplicate information
**** DONE ICMP6: checksum over payload
- variable length, up to 65k
Exists:
Exists!
**** Synchronisation with the controller
- Double data type definition -> might differ
- TYPE_CPU for ethernet

View File

@ -115,16 +115,17 @@ class L2Controller(object):
for mode in self.modes:
self.nat64_map[mode] = []
# specific settings -- only need the address (=offset), no mask
# specific settings - mapping 256 IPv6 IPs max statically (based on /24)
for mode in ["range_router"]:
for net in self.v6_routes[mode]:
v6_net = net['net']
v4_net = self.info['v4_nat64_map'].next()
for v6_net in self.v6_routes[mode]:
for v4_net in self.v4_routes[mode]:
v4_dst = self.info['v4_nat64_map'].next()
self.nat64_map[mode].append({
"v6_network": v6_net,
"v4_network": v4_net,
"nat64_prefix": self.info['nat64_prefix']
"v6_src": v6_net['net'],
"v6_dst": self.info['nat64_prefix'] # static
"v4_src": v4_net['net'],
"v4_dst": v4_dst
})
self.init_boilerplate(sw_name)
@ -201,6 +202,10 @@ class L2Controller(object):
for v6route in self.v6_routes[self.mode]:
self.controller.table_add("v6_networks", "set_egress_port", [str(v6route['net'])], [str(v6route['port'])])
self.controller.table_clear("v4_networks")
for v4route in self.v4_routes[self.mode]:
self.controller.table_add("v4_networks", "set_egress_port", [str(v4route['net'])], [str(v4route['port'])])
if self.args.multicast_to_controller:
self.listen_to_icmp6_multicast()
@ -209,10 +214,10 @@ class L2Controller(object):
self.init_ndp_in_switch(v6addr)
self.init_icmp6_echo_in_switch(v6addr)
self.controller.table_clear("v4_networks")
for v4route in self.v4_routes[self.mode]:
self.controller.table_add("v4_networks", "set_egress_port", [str(v4route['net'])], [str(v4route['port'])])
self.controller.table_clear("nat64")
self.controller.table_clear("nat46")
for nat64map in self.nat64_map[self.mode]:
self.static_nat64_mapping(**nat64map)
# Disable icmp handling in the controller
@ -230,23 +235,25 @@ class L2Controller(object):
# # Experimental: controller does NDP, switch does ICMP6 echo reply
# self.controller.table_add("v6_addresses", "controller_reply", [str(another_addr_ns)], [str(self.task['ICMP6_NS'])])
def static_nat64_mapping(self, v6_src, v6_dst, v4_src, v4_dst):
log.info("NAT64 map: ({} -> {} => {}), ({} -> {} -> {} (only /24)))".format(
v6_src, v6_dst, v4_dst,
v4_src, v4_dst, v6_src)
for nat64map in self.nat64_map[self.mode]:
self.static_nat64_mapping(**nat64map)
def static_nat64_mapping(self, nat64_prefix, v6_network, v4_network):
log.info("NAT64 map: {} -> {} -> {}".format(nat64_prefix, v6_network, v4_network))
self.controller.table_add("v6_networks", "nat64_static", [str(nat64_prefix)],
[str(v6_network.network_address),
str(v4_network.network_address),
str(nat64_prefix.network_address)]
self.controller.table_add("nat64", "nat64_static",
[str(v6_src)
str(v6_dst)],
[str(v6_src.network_address),
str(v4_dst.network_address),
str(v6_dst.network_address)]
)
self.controller.table_add("v4_networks", "nat46_static", [str(v4_network)],
[str(v6_network.network_address),
str(v4_network.network_address),
str(nat64_prefix.network_address)]
self.controller.table_add("nat46", "nat46_static",
[str(v4_src)
str(v4_dst)],
[str(v6_src.network_address),
str(v4_dst.network_address),
str(v6_dst.network_address)]
)

View File

@ -52,7 +52,7 @@ control MyIngress(inout headers hdr,
hdr.ipv4.diff_serv = (bit<6>)0; // no ToS
hdr.ipv4.ecn = (bit<2>)0; // unsupported
hdr.ipv4.ihl = (bit<4>) 5; // internet header length -- needs to be dynamic!
hdr.ipv4.ihl = (bit<4>) 5; // internet header length -- needs to be dynamic!?
hdr.ipv4.totalLen = (bit<16>) hdr.ipv6.payload_length + 5; // should probably also dynamic
hdr.ipv4.identification = (bit<16>) 0; // no support for fragments
@ -93,25 +93,58 @@ control MyIngress(inout headers hdr,
/* nat64_prefix is the same as the matching key, but without the mask */
action nat64_static(ipv6_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;
ipv4_addr_t src = v4_network + (ipv4_addr_t) src_offset;
action nat64_static(ipv6_addr_t v6_src, ipv4_addr_t v4_dst, ipv6_addr_t nat64_prefix) {
ipv6_addr_t src_offset = hdr.ipv6.src_addr - v6_src;
ipv4_addr_t src = v4_dst + (ipv4_addr_t) src_offset;
ipv4_addr_t dst = (ipv4_addr_t) (hdr.ipv6.dst_addr - nat64_prefix);
nat64_generic(src, dst);
/* fix the protocol specific translations */
// switch() ...
}
/* matching key: v4_network specified again */
action nat46_static(ipv6_addr_t v6_network, ipv4_addr_t v4_network, ipv6_addr_t nat64_prefix ) {
action nat46_static(ipv6_addr_t v6_src, ipv4_addr_t v4_dst, ipv6_addr_t nat64_prefix) {
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;
ipv4_addr_t dst_offset = hdr.ipv4.dst_addr - v4_dst;
ipv6_addr_t dst = v6_src + (ipv6_addr_t) dst_offset;
nat46_generic(src, dst);
/* fix the protocol specific translations */
// switch() ...
}
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;
}
table nat46 {
key = {
hdr.ipv4.src_addr: lpm;
hdr.ipv4.dst_addr: lpm;
}
actions = {
controller_debug;
nat46_static;
NoAction;
}
size = NAT64_TABLE_SIZE;
default_action = controller_debug;
}
/********************** ICMP6 ***********************************/
@ -272,8 +305,6 @@ control MyIngress(inout headers hdr,
set_egress_port;
controller_debug;
controller_reply;
nat64_static;
icmp6_neighbor_solicitation;
NoAction;
}
size = ROUTING_TABLE_SIZE;
@ -287,7 +318,6 @@ control MyIngress(inout headers hdr,
}
actions = {
set_egress_port;
nat46_static;
NoAction;
}
size = ROUTING_TABLE_SIZE;
@ -297,12 +327,9 @@ control MyIngress(inout headers hdr,
/********************** APPLYING TABLES ***********************************/
apply {
if(hdr.ipv6.isValid()) {
/* FIXME: structure / use .hit to do logic */
// ndp_answer.apply();
//ndp.apply(); /* flood or if it is us - answer */
icmp6.apply();
v6_networks.apply();
icmp6.apply(); /* icmp6 echo, icmp6 ndp */
v6_networks.apply(); /* routing, egress */
}
if(hdr.ipv4.isValid()) {
v4_networks.apply();