diff --git a/doc/plan.org b/doc/plan.org index 107ee51..0003f17 100644 --- a/doc/plan.org +++ b/doc/plan.org @@ -228,13 +228,61 @@ | 2019-04-23 | | | | | Meet Laurent | | | | | | +| | General | | +| | - Get a better understanding of what others did | | +| | | | | | Review docs / specs | | -| | - Jool EAMT/SIIT | | +| | - Jool EAMT/SIIT fully | | +| | | | | | - IPv4 embedding | | +| | * Motivation/objective: working with real world DNS64 | | | | * RFC6052 suffix support | | | | * RFC4291 IPv4-Compatible IPv6 Address (16 0s) | | | | * RFC4291 IPv4-Mapped IPv6 Address (16 1s) | | | | | | +| | - Session handling | | +| | * RFC6145: Translation ip/icmp, obsoleted by RFC 7915 | | +| | * RFC6146: NAT64 definition, only TCP, UDP, and ICMP traffic | | +| | * RFC6052: embedding support | | +| | * Mode: IPv6 outgoing -> "masquarading" | | +| | * Mode: IPv4 | | +| | | | +| | - Translation details | | +| | * How to handle ICMP4->icmp6 correctly (RFC7915) | | +| | | | +| | - Hardware | | +| | * NetFPGA | | +| | * Hardware machine for software comparison? | | +| | | | +| | | | +| | New todos: | | +| | | | +| | - Translate fragment header | | +| | - Support MTU / packet too big | | +| | - Support PMTU, tcp mss | | +| | | | +| | | | +| | Meeting notes | | +| | - difference based | | +| | - first physical access | | +| | - tofino: if it compiles -> line rate | | +| | - chaining switches / OS -> single port rate | | +| | - netpfga | | +| | - reason about what in hardware and what in software -> reason tradeoff | !!! | +| | - table gets full | | +| | | | +| | | | +| | Follow up: | | +| | | | +| | - what's the MTU of an interface? have a table | | +| | - have port/mtu | | +| | - total packeth length -> from IP | | +| | - tables not in data plane | | +| | - Meeting Hendrik | | +| | - Meeting Kamila | | +| | | | +| | | | +| | - 768k | | | | | | | | | | | | | | @@ -1386,7 +1434,6 @@ Please make sure that it is installed and available in your $PATH: - ** Motivation TBD ** Translation mechanisms @@ -1775,7 +1822,6 @@ restart controller - check whether tables are applied correctly (type conversion 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 - *** Setting up a system for working on P4 on devuan **** Scripts in the wild https://github.com/nsg-ethz/p4-learning/blob/master/vm/bin/update-p4c.sh @@ -1786,13 +1832,42 @@ debug packets - analyse code - goto 1 [21:24] line:~% sudo apt install libthrift-dev [21:26] line:~% sudo apt install thrift-compiler libnanomsg-dev libjudy-dev + +*** TODO Session / dynamice mappings +**** General + - Have 1..n session IPv4 addresses + - Handle outgoing IPv6: create new session + - Handle in +***** TODO Case IPv6 initiator + - Mapping whole IPv4 Internet in /96 prefix + - Session information for mapping reply + - Timeout handling in controller +****** TODO IPv6 udp -> IPv4 + - Got 4-5 tuple ([proto], src ip, src port, dst ip, dst port) + - Does not / never signal end + - Needs timeout for cleaning up +****** TODO IPv6 tcp -> IPv4 + - Similar to udp + - react on FIN/RST (?) -- could be an addition +****** TODO IPv6 icmp6 -> IPv4 + - usual protocol specific changes + - Session?? + - src ip, dst ip, code ? + +***** TODO Case IPv4 initiator + - Needs upper level protol +**** TODO tcp session +**** TODO udp session +**** TODO tcp session ** TODO Comparison with existing tools (Performance, Features) *** Features -| What? | Description | State in P4 | References | -|-----------+------------------------------------------+-------------------+-----------------------------------------------| -| Jool EAMT | Mapping with tables, multiple entries | Supported | https://www.jool.mx/en/run-eam.html, RFC 7757 | -| Jool SIIT | Mapping IPv6 to range of IPv4, one entry | Supported by EAMT | | -| | | | | +| What? | Description | State in P4 | References | +|---------------------+------------------------------------------+-------------------+---------------------------------------------------------------------------------| +| Jool EAMT | Mapping with tables, multiple entries | Supported | https://www.jool.mx/en/eamt.html, https://www.jool.mx/en/run-eam.html, RFC 7757 | +| Jool SIIT | Mapping IPv6 to range of IPv4, one entry | Supported by EAMT | | +| Jool Stateful NAT64 | | | https://www.jool.mx/en/intro-xlat.html#stateful-nat64 | +| | | | https://www.jool.mx/en/run-nat64.html | +| | | | | ** P4 Possible Improvements / Current Challenges / Limitations *** DONE cannot read key from table **** log @@ -1990,6 +2065,23 @@ Linux package management, handling updates, etc. Many constants double defined. Easy to make errors. ** Implementation description and limitations +*** Implementation description [move todos here] +**** TODO Support (non-) fragmentation + - if DF bit is not set in ipv4 +**** TODO Supporting [different] MTUs + - sizes of headers are different + - packet might not fit into same mtu anymore + - send back "ICMP Packet Too Big messages to the sender." RFC7915 +**** TODO pmtud support + - mss change +#+BEGIN_QUOTE +translator MUST send a + Packet Too Big error message or fragment the packet when the packet + size exceeds the MTU of the next-hop interface. +#+END_QUOTE + +https://tools.ietf.org/html/rfc7915 + *** Limitations **** IPv4 embedding (RFC6052, RFC4291) Supported is similar to the "IPv4-Compatible IPv6 Address" as defined by @@ -2006,7 +2098,14 @@ Also section 2.5.5.2 "IPv4-Mapped IPv6 Address" Mac addresses: bit 0 = unicast (0)/multicast(1), bit 1 = local (1)/global (0) - site wiki/mac + +U/L bit is universal/local, bit 2; inverting: local = 0, global = 1 + **** No fragmentation support (yet) +In line with RFC7915 +#+BEGIN_QUOTE +Fragmented ICMP/ICMPv6 packets will not be translated by IP/ICMP translators. +#+END_QUOTE **** No session handling (yet) 1:1 mappings. No (automatic) session. **** IPv4 / IPv6 embedding @@ -2027,6 +2126,13 @@ bit 1 = local (1)/global (0) - site wiki/mac handle packet. Only has to be set, when packets originate from the switch/controller. +**** TODO No support of IPv4 options + - header is assumed to be always 20 octets + + +**** TODO Security issue: not checking checksums before + - Could be implemented + ** References / Follow up *** RFC 791 IPv4 https://tools.ietf.org/html/rfc791 *** RFC 792 ICMP https://tools.ietf.org/html/rfc792 @@ -2051,8 +2157,20 @@ bit 1 = local (1)/global (0) - site wiki/mac *** RFC 4443 ICMPv6 https://tools.ietf.org/html/rfc4443 *** RFC 4861: https://tools.ietf.org/html/rfc4861 Neighbor discovery *** RFC 6052: https://tools.ietf.org/html/rfc6052 IPv6 Addressing of IPv4/IPv6 Translators - first NAT64?? +*** RFC 6145 IP/ICMP Translation Algorithm + - Obsoleted by 7915 +*** RFC 6146 Stateful nat http://tools.ietf.org/html/rfc6146 + - Referenced from Jool +*** RFC 6147 DNS64 https://tools.ietf.org/html/rfc6147 *** RFC 6586 for deployment experiences using Stateful NAT64. *** RFC 7757 Explicit Address Mappings for Stateless IP/ICMP Translation - https://tools.ietf.org/html/rfc7757 +*** RFC 7915 IP/ICMP Translation Algorithm https://tools.ietf.org/html/rfc7915 + - Requires RFC 6144 + - MUST support one or more address mapping algorithms, which + are defined in Section 6. + - does not translate IPv6 extension headers except the Fragment Header. + + *** EAMT/Jool: https://www.jool.mx/en/eamt.html *** Solicited node multicast address https://en.wikipedia.org/wiki/Solicited-node_multicast_address *** Scapy / IPv6: https://www.idsv6.de/Downloads/IPv6PacketCreationWithScapy.pdf diff --git a/p4app/controller.py b/p4app/controller.py index d10839d..b09f256 100755 --- a/p4app/controller.py +++ b/p4app/controller.py @@ -38,7 +38,11 @@ table_id_fields = { 5: 'TABLE_V4_NETWORKS', 6: 'TABLE_ARP', 7: 'TABLE_ARP_EGRESS', - 8: 'TABLE_ICMP' + 8: 'TABLE_ICMP', + 9: 'TABLE_NAT64_TCP', + 10: 'TABLE_NAT64_UDP', + 11: 'TABLE_NAT64_ICMP6', + 12: 'TABLE_NAT64_SESSION' } table_proto = { @@ -85,7 +89,7 @@ class L2Controller(object): self.info['v6_mask'] = 64 self.info['v6_nat64_mask'] = 96 - self.info['v6_base'] = ipaddress.ip_network("2001:db8::/32") + self.info['v6_base'] = ipaddress.ip_network("2001:db8::/40") self.info['v6_base_hostnet'] = ipaddress.ip_network("2001:db8::/48") self.info['v6_gen'] = self.info['v6_base_hostnet'].subnets(new_prefix=self.info['v6_mask']) @@ -106,6 +110,9 @@ class L2Controller(object): self.info['switch_suffix'] = 0x42 self.info['nat64_prefix'] = ipaddress.ip_network("64:ff9b::/96") + # /96 after the /40 pool we use above + self.info['nat64_prefix_dynamic'] = ipaddress.ip_network("2001:db8:100::/96") + self.v6_routes = {} self.v6_routes[None] = [] self.v6_routes['base'] = [] diff --git a/p4src/headers.p4 b/p4src/headers.p4 index 24dea27..4c271f5 100644 --- a/p4src/headers.p4 +++ b/p4src/headers.p4 @@ -25,6 +25,10 @@ const bit<16> TABLE_V4_NETWORKS = 5; const bit<16> TABLE_ARP = 6; const bit<16> TABLE_ARP_EGRESS = 7; const bit<16> TABLE_ICMP = 8; +const bit<16> TABLE_NAT64_TCP = 9; +const bit<16> TABLE_NAT64_UDP = 10; +const bit<16> TABLE_NAT64_ICMP6 = 11; +const bit<16> TABLE_NAT64_SESSION = 12; const bit<16> TYPE_IPV4 = 0x0800; diff --git a/p4src/static-mapping.p4 b/p4src/static-mapping.p4 index f2d7adf..67d9b0a 100644 --- a/p4src/static-mapping.p4 +++ b/p4src/static-mapping.p4 @@ -232,6 +232,42 @@ Echo or Echo Reply Message default_action = controller_debug_table_id(TABLE_NAT46); } + /********************** NAT64 sessions ***********************************/ + + action nat64_create_session() + { + + } + + /* Used for detecting traffic that should have a session */ + table nat64_session { + key = { + hdr.ipv6.dst_addr: lpm; + } + actions = { + controller_debug_table_id; + NoAction; + } + size = NAT64_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_NAT64_SESSION); + } + + table nat64_tcp { + key = { + hdr.ipv6.src_addr: exact; + hdr.ipv6.dst_addr: exact; + hdr.tcp.src_port: exact; + hdr.tcp.dst_port: exact; + } + actions = { + controller_debug_table_id; + NoAction; + } + size = NAT64_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_NAT64_TCP); + } + + /********************** ICMP6 + NDP + ICMP ***********************************/ @@ -433,7 +469,7 @@ Echo or Echo Reply Message /********************** APPLYING TABLES ***********************************/ apply { if(hdr.ipv6.isValid()) { - if(nat64.apply().hit) { /* generic nat64 done */ + if(nat64.apply().hit) { /* generic / static nat64 done */ if(hdr.icmp6.isValid()) { nat64_icmp6_generic();