diff --git a/doc/plan.org b/doc/plan.org index d588a2c..1f193c6 100644 --- a/doc/plan.org +++ b/doc/plan.org @@ -422,7 +422,24 @@ Problem: task field might be overriden for controller use in different table -> need different task field! ***** try2: checksum ok, but no packets on h3 -****** Setup a default rule for the IPv4 world to debug on controller +****** DONE Setup a default rule for the IPv4 world to debug on controller +Still not seeing the converted packet, however seeing icmp6_ns packets +which should not be there: + +table entry for ns: + +ff:02:00:00:00:00:00:00:00:00:00:01:ff:00:00:42/128 + +debug packet seen in controller: + +DEBUG:main:v6 reassambled=>>> +DEBUG:main:v6 reassambled=>>> +DEBUG:main:v6 reassambled=>>> + +DEBUG:main:v6 reassambled=>> + +debugging MIGHT come from nat64 table! + *** TODO Get p4 VM / vagrant running **** DONE install libvirtd-daemon @@ -1219,8 +1236,8 @@ debug packets - analyse code - goto 1 [21:26] line:~% sudo apt install thrift-compiler libnanomsg-dev libjudy-dev *** Performance comparison -*** Feature/Functionality difference / overview / CHALLENGES / LIMITATIONS in P4 -**** P4: cannot read key from table +*** Challenges / Limitations in P4 +**** DONE 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 @@ -1285,7 +1302,7 @@ Need to duplicate information **** DONE ICMP6: checksum over payload - variable length, up to 65k Exists! -**** Synchronisation with the controller +**** DONE Synchronisation with the controller - Double data type definition -> might differ - TYPE_CPU for ethernet - Port ingress offset (9 vs. 16 bit) @@ -1315,18 +1332,29 @@ Code: } #+END_SRC -**** (current) Implementation limitations -***** No fragmentation support (yet) -***** No session handling (yet) +**** No table meta information for default actions (asked 2019-03-25) +Is there any meta information for "from which table was the action +called" available? My use case is having a debug action that sends +packets to the controller and I use it as a default_action in various +tables; however know I don't know anymore from which table the action +was called. Is there any kind of meta information which table called +me available? + +I could work around this by using if(! .. .hit) { my_action(table_id) +}, but it would not work with using default_action = ... + +*** Implementation limitations +**** No fragmentation support (yet) +**** No session handling (yet) 1:1 mappings. No (automatic) session. -***** IPv4 / IPv6 embedding +**** IPv4 / IPv6 embedding Currently offset based - probably not following the RFC! -***** No DNS64 +**** No DNS64 has already been solved in a different domain - could even do transparent / in network modification -***** Incomplete NDP - Very limited option support -***** NAT64 mappings not source network dependent +**** Incomplete NDP + Very limited option support +**** NAT64 mappings not source network dependent Only the destination network is matched for deciding on NAT64, as priority based double LPM is not supported. This limits a prefix to be used only in one network. diff --git a/p4app/controller.py b/p4app/controller.py index 428d2b0..cfad97f 100755 --- a/p4app/controller.py +++ b/p4app/controller.py @@ -23,11 +23,20 @@ log = logging.getLogger("main") cpu_fields = { + 0: 'UNSET', 1: 'ICMP6_NS', 2: 'ICMP6_GENERAL', 3: 'DEBUG' } +table_id_fields = { + 0: 'UNSET_TABLE', + 1: 'TABLE_NAT64', + 2: 'TABLE_ICMP6, + 3: 'TABLE_V6_NETWORKS, + 4: 'TABLE_NAT46', + 5: 'TABLE_V4_NETWORKS' +} class CpuHeader(Packet): name = 'CpuPacket' @@ -35,6 +44,7 @@ class CpuHeader(Packet): ShortEnumField('task', 1, cpu_fields ), ShortField('ingress_port', 0), XShortEnumField("type", 0x9000, ETHER_TYPES) + ShortEnumField('table_id', 1, table_id_fields ), ] @@ -421,8 +431,6 @@ class L2Controller(object): def recv_msg_cpu(self, pkg): packet = Ether(str(pkg)) - - if packet.type == 0x0800: log.debug("Received raw (untagged) packet - BUG") self.debug_print_pkg(pkg) @@ -432,13 +440,14 @@ class L2Controller(object): cpu_header = CpuHeader(packet.payload) ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type) orig_packet = ether_orig / IP(cpu_header.load) + log.debug("cpu = {}".format(cpu_header.__repr__())) log.debug("v4 reassambled={}".format(orig_packet.__repr__())) elif packet.type == 0x4242: cpu_header = CpuHeader(packet.payload) # Not necessary anymore - cpu decoding works -# log.debug("cpu = {}".format(cpu_header.__repr__())) + log.debug("cpu = {}".format(cpu_header.__repr__())) ether_orig = Ether(src=packet.src, dst=packet.dst, type=cpu_header.type) @@ -454,7 +463,7 @@ class L2Controller(object): src = orig_packet['IPv6'].src log.debug("Router solicitation from {} -- should probably handle this?".format(src)) elif cpu_header.task == self.task['DEBUG']: - log.debug("v6 reassambled={}".format(orig_packet.__repr__())) + log.debug("[debug] v6 reassambled={}".format(orig_packet.__repr__())) elif cpu_header.task == self.task['ICMP6_NS']: log.info("Doing neighbor solicitation for the switch in the controller") self.handle_icmp6_ns(orig_packet) diff --git a/p4src/headers.p4 b/p4src/headers.p4 index 9fbcf96..6e82484 100644 --- a/p4src/headers.p4 +++ b/p4src/headers.p4 @@ -12,6 +12,14 @@ typedef bit<9> port_t; typedef bit<16> mcast_t; typedef bit<16> task_t; +typedef bit<8> table_t; /* to map debug messages */ + +const bit<8> TABLE_NAT64 = 1; +const bit<8> TABLE_ICMP6 = 2; +const bit<8> TABLE_V6_NETWORKS = 3; +const bit<8> TABLE_NAT46 = 4; +const bit<8> TABLE_V4_NETWORKS = 5; + const bit<16> TYPE_IPV4 = 0x0800; const bit<16> TYPE_IPV6 = 0x86DD; @@ -148,6 +156,7 @@ header cpu_t { task_t task; bit<16> ingress_port; bit<16> ethertype; + table_t table_id; } struct headers { @@ -169,6 +178,7 @@ struct metadata { task_t switch_task; bit<16> tcp_length; bit<32> cast_length; + table_t table_id; } #endif \ No newline at end of file diff --git a/p4src/static-mapping.p4 b/p4src/static-mapping.p4 index 4e894cd..f03bbc7 100644 --- a/p4src/static-mapping.p4 +++ b/p4src/static-mapping.p4 @@ -32,6 +32,11 @@ control MyIngress(inout headers hdr, clone3(CloneType.I2E, 100, meta); } + action controller_debug_table_id(table_t table_id) { + hdr.cpu.table_id = table_id; + controller_reply(TASK_DEBUG); + } + action controller_debug() { controller_reply(TASK_DEBUG); } @@ -242,7 +247,6 @@ control MyIngress(inout headers hdr, } size = NDP_TABLE_SIZE; default_action = NoAction; -// default_action = controller_debug; } /* Handle multicast registration of NDP */ @@ -257,7 +261,6 @@ control MyIngress(inout headers hdr, } size = NDP_TABLE_SIZE; default_action = NoAction; -// default_action = controller_debug; } /********************** NDP support for OTHERS (unused ATM) ***********************************/ @@ -273,7 +276,7 @@ control MyIngress(inout headers hdr, NoAction; } size = NDP_TABLE_SIZE; - default_action = controller_debug; + default_action = NoAction; } @@ -306,7 +309,7 @@ control MyIngress(inout headers hdr, NoAction; } size = ROUTING_TABLE_SIZE; - default_action = controller_debug; + default_action = NoAction; } table v4_networks { @@ -319,19 +322,30 @@ control MyIngress(inout headers hdr, NoAction; } size = ROUTING_TABLE_SIZE; - default_action = controller_debug; + default_action = NoAction; } /********************** APPLYING TABLES ***********************************/ apply { if(hdr.ipv6.isValid()) { - icmp6.apply(); /* icmp6 echo, icmp6 ndp */ - nat64.apply(); /* v6 -> v4 */ - v6_networks.apply(); /* routing, egress */ + if(!icmp6.apply().hit) { /* icmp6 echo, icmp6 ndp */ + controller_debug_table_id(TABLE_ICMP6); + } + + if(!nat64.apply().hit) { /* v6 -> v4 */ + controller_debug_table_id(TABLE_NAT64); + } + if(!v6_networks.apply().hit) { + controller_debug_table_id(TABLE_V6_NETWORKS); + } } if(hdr.ipv4.isValid()) { - nat46.apply(); /* v4->v6 */ - v4_networks.apply(); /* routing, egress */ + if(!nat46.apply().hit) { /* v4->v6 */ + controller_debug_table_id(TABLE_NAT46); + } + if(!v4_networks.apply().hit) { /* routing, egress */ + controller_debug_table_id(TABLE_V4_NETWORKS) + } } } } @@ -351,6 +365,7 @@ control MyEgress(inout headers hdr, hdr.cpu.ethertype = hdr.ethernet.ethertype; hdr.cpu.ingress_port = (bit<16>) meta.ingress_port; + hdr.ethernet.ethertype = TYPE_CPU; } }