diff --git a/doc/plan.org b/doc/plan.org index 601d7b0..19ed586 100644 --- a/doc/plan.org +++ b/doc/plan.org @@ -173,6 +173,10 @@ | 2019-04-02 | | | | | ARP egress support | | | | | | +| 2019-04-03 | | | +| | ARP corrections -- ARP working for the switch! | | +| | | | +| | | | | 2019-04-04 | NAT64 1:1 table ICMP, ICMPv6 working | | | | Will need some switch local ip addresses | | | | | | @@ -681,16 +685,17 @@ INFO:main:unhandled reassambled= should be 1 ***** DONE figure out switch() syntax -***** TODO transform protocol specific: icmp6 -> icmp +***** DONE transform protocol specific: icmp6 -> icmp ****** DONE Implement double table, as there are no if's in actions ****** DONE Debug Ethernet frame check sequence error -> need to compute checksum https://en.wikipedia.org/wiki/Frame_check_sequence According to Edgar this should not be seen anyway. -****** TODO Calculate ICMP checksum -****** TODO Check field lengths +****** DONE Calculate ICMP checksum +****** DONE Check field lengths ***** TODO transform protocol specific: icmp -> icmp6 -**** TODO Make switch answer IPv4 icmp echo request for +****** TODO Make switch answer IPv4 icmp echo request for +******* DONE Make switch respond to ARP **** TODO Add / check default route for v4 hosts **** TODO Update p4c to avoid compiler bug ***** TODO Updating p4c diff --git a/p4app/controller.py b/p4app/controller.py index 70277b3..cf43998 100755 --- a/p4app/controller.py +++ b/p4app/controller.py @@ -37,7 +37,8 @@ table_id_fields = { 4: 'TABLE_NAT46', 5: 'TABLE_V4_NETWORKS', 6: 'TABLE_ARP', - 7: 'TABLE_ARP_EGRESS' + 7: 'TABLE_ARP_EGRESS', + 8: 'TABLE_ICMP' } table_proto = { @@ -224,7 +225,7 @@ class L2Controller(object): def init_ndp_in_switch(self, addr): icmp6_addr = self.gen_ndp_multicast_addr(addr) icmp6_net = "{}/128".format(icmp6_addr) - icmp6_type = 135 + icmp6_type = table_proto['ICMP_NS'] mac_addr = self.info['mac_addr'] self.controller.table_add("icmp6", @@ -233,13 +234,21 @@ class L2Controller(object): def init_icmp6_echo_in_switch(self, addr): icmp6_addr = addr - icmp6_type = 128 + icmp6_type = table_proto['ICMP6_ECHO_REQUEST'] icmp6_net = "{}/128".format(icmp6_addr) self.controller.table_add("icmp6", "icmp6_echo_reply", [str(icmp6_net), str(icmp6_type)], []) + def init_icmp_echo_in_switch(self, addr): + icmp_addr = addr + icmp_type = table_proto['ICMP_ECHO_REQUEST'] + icmp_net = "{}/32".format(icmp_addr) + + self.controller.table_add("icmp", + "icmp_echo_reply", + [str(icmp_net), str(icmp_type)], []) def ipv4_router(self, net): return net[self.info['switch_suffix']] @@ -251,6 +260,7 @@ class L2Controller(object): self.controller.table_clear("v4_networks") self.controller.table_clear("v4_arp") + self.controller.table_clear("v4_arp_egress") for v4route in self.v4_routes[self.mode]: self.controller.table_add("v4_networks", "set_egress_port", [str(v4route['net'])], [str(v4route['port'])]) @@ -267,11 +277,17 @@ class L2Controller(object): if self.args.multicast_to_controller: self.listen_to_icmp6_multicast() + # icmp6 echo request + NDP self.controller.table_clear("icmp6") for v6addr in self.v6_addresses[self.mode]: self.init_ndp_in_switch(v6addr) self.init_icmp6_echo_in_switch(v6addr) + # icmp echo request + self.controller.table_clear("icmp") + for addr in self.v4_addresses[self.mode]: + self.init_icmp_echo_in_switch(addr) + self.controller.table_clear("nat64") self.controller.table_clear("nat46") for nat64map in self.nat64_map[self.mode]: diff --git a/p4src/headers.p4 b/p4src/headers.p4 index 1c542ef..1a25d0c 100644 --- a/p4src/headers.p4 +++ b/p4src/headers.p4 @@ -24,6 +24,7 @@ const bit<16> TABLE_NAT46 = 4; 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> TYPE_IPV4 = 0x0800; diff --git a/p4src/settings.p4 b/p4src/settings.p4 index d719176..120fef1 100644 --- a/p4src/settings.p4 +++ b/p4src/settings.p4 @@ -11,6 +11,7 @@ #define ADDRESS_TABLE_SIZE 64 /* maximum number of addresses per protocol */ #define NDP_TABLE_SIZE 64 /* maximum number of multicast groups */ #define ICMP6_TABLE_SIZE 64 /* icmp6 handlers */ +#define ICMP_TABLE_SIZE 64 /* icmp6 handlers */ #define NAT64_TABLE_SIZE 64 /* nat64 and nat46 entries */ #endif diff --git a/p4src/static-mapping.p4 b/p4src/static-mapping.p4 index 6a4bece..a2b8540 100644 --- a/p4src/static-mapping.p4 +++ b/p4src/static-mapping.p4 @@ -225,9 +225,9 @@ Echo or Echo Reply Message } - /********************** ICMP6 + NDP ***********************************/ + /********************** ICMP6 + NDP + ICMP ***********************************/ - /* old/unused action */ + /* old/unused action -- is it??*/ action icmp6_answer() { if(hdr.icmp6.isValid()) { if(hdr.icmp6.code == ICMP6_ECHO_REQUEST) { @@ -299,7 +299,28 @@ Echo or Echo Reply Message } size = ICMP6_TABLE_SIZE; default_action = controller_debug_table_id(TABLE_ICMP6); -// default_action = NoAction; + } + + action icmp_echo_reply() { + ipv4_addr_t tmp = hdr.ipv4.src_addr; + + hdr.icmp.type = ICMP_ECHO_REPLY; + hdr.ipv4.src_addr = hdr.ipv4.dst_addr; + hdr.ipv4.dst_addr = tmp; + } + + table icmp { + key = { + hdr.ipv4.dst_addr: lpm; + hdr.icmp.type: exact; + } + actions = { + icmp_echo_reply; + controller_debug_table_id; + NoAction; + } + size = ICMP_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_ICMP); } /********************** debugging / general support ***********************************/ @@ -440,7 +461,10 @@ Echo or Echo Reply Message v6_networks.apply(); /* regular egress / routing */ } else if(hdr.ipv4.isValid()) { - if(nat46.apply().hit) { + if(icmp.apply().hit()) { + v4_networks.apply(); + exit; + } else if(nat46.apply().hit) { if(hdr.icmp.isValid()) { nat46_icmp_generic();