From 8309f4367c438b34a10f064a62290df5553e0cb8 Mon Sep 17 00:00:00 2001 From: Nico Schottelius Date: Wed, 10 Jul 2019 09:07:17 +0200 Subject: [PATCH] Split logic into smaller action blocks --- p4src/actions_arp.p4 | 60 ++++ p4src/actions_delta_checksum.p4 | 41 +++ p4src/actions_egress.p4 | 48 +++ p4src/actions_generic.p4 | 21 ++ p4src/actions_icmp6_ndp.p4 | 114 +++++++ p4src/actions_nat64_generic.p4 | 185 +++++++++++ p4src/actions_nat64_session.p4 | 91 ++++++ p4src/checksum_diff.p4 | 531 -------------------------------- 8 files changed, 560 insertions(+), 531 deletions(-) create mode 100644 p4src/actions_arp.p4 create mode 100644 p4src/actions_delta_checksum.p4 create mode 100644 p4src/actions_egress.p4 create mode 100644 p4src/actions_generic.p4 create mode 100644 p4src/actions_icmp6_ndp.p4 create mode 100644 p4src/actions_nat64_generic.p4 create mode 100644 p4src/actions_nat64_session.p4 diff --git a/p4src/actions_arp.p4 b/p4src/actions_arp.p4 new file mode 100644 index 0000000..596bf97 --- /dev/null +++ b/p4src/actions_arp.p4 @@ -0,0 +1,60 @@ +#ifndef NICO_ARP +#define NICO_ARP + + +/********************** ARP ***********************************/ + + action arp_reply(mac_addr_t mac_addr) { + /* swap */ + ipv4_addr_t ipv4_src = hdr.arp.dst_ipv4_addr; + ipv4_addr_t ipv4_dst = hdr.arp.src_ipv4_addr; + + /* swap/add */ + mac_addr_t mac_src = mac_addr; + mac_addr_t mac_dst = hdr.arp.src_mac_addr; + + /* fill the ethernet header */ + hdr.ethernet.dst_addr = mac_dst; + hdr.ethernet.src_addr = mac_src; + + /* fill the arp header */ + hdr.arp.dst_mac_addr = mac_dst; + hdr.arp.src_mac_addr = mac_src; + + /* swapping */ + hdr.arp.dst_ipv4_addr = ipv4_dst; + hdr.arp.src_ipv4_addr = ipv4_src; + + hdr.arp.opcode = ARP_REPLY; + } + + table v4_arp { + key = { + hdr.ethernet.dst_addr: exact; + hdr.arp.opcode: exact; + hdr.arp.dst_ipv4_addr: lpm; + } + actions = { + controller_debug_table_id; + arp_reply; + NoAction; + } + size = ICMP6_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_ARP); + } + + table v4_arp_egress { + key = { + hdr.arp.dst_ipv4_addr: lpm; + } + actions = { + controller_debug_table_id; + set_egress_port; + NoAction; + } + size = ICMP6_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_ARP_EGRESS); + } + + +#endif \ No newline at end of file diff --git a/p4src/actions_delta_checksum.p4 b/p4src/actions_delta_checksum.p4 new file mode 100644 index 0000000..4dfe624 --- /dev/null +++ b/p4src/actions_delta_checksum.p4 @@ -0,0 +1,41 @@ +#ifndef NICO_DELTA_CHECKSUM +#define NICO_DELTA_CHECKSUM + + action v4sum() { + bit<16> localsum = 0; + + localsum = localsum + hdr.ipv4.src_addr[15:0]; // 16 bit + localsum = localsum + hdr.ipv4.src_addr[31:16]; // 16 bit + localsum = localsum + hdr.ipv4.dst_addr[15:0]; // 16 bit + localsum = localsum + hdr.ipv4.dst_addr[31:16]; // 16 bit + + localsum = localsum + hdr.ipv4.totalLen -20; // 16 bit + localsum = localsum + (bit<16>) hdr.ipv4.protocol; // 8 bit + } + + action v6sum() { + bit<16> localsum = 0; + + localsum = localsum + hdr.ipv6.src_addr[15:0]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[31:16]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[47:32]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[63:48]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[79:64]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[95:80]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[111:96]; // 16 bit + localsum = localsum + hdr.ipv6.src_addr[127:112]; // 16 bit + + localsum = localsum + hdr.ipv6.dst_addr[15:0]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[31:16]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[47:32]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[63:48]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[79:64]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[95:80]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[111:96]; // 16 bit + localsum = localsum + hdr.ipv6.dst_addr[127:112]; // 16 bit + + localsum = localsum + hdr.ipv6.payload_length; // 16 bit + localsum = localsum + (bit<16>) hdr.ipv6.next_header; // 8 bit + } + +#endif \ No newline at end of file diff --git a/p4src/actions_egress.p4 b/p4src/actions_egress.p4 new file mode 100644 index 0000000..a3e505b --- /dev/null +++ b/p4src/actions_egress.p4 @@ -0,0 +1,48 @@ +#ifndef NICO_EGRESS +#define NICO_EGRESS + + +/********************** ROUTING (egress definiton) TABLES ***********************************/ + + action set_egress_port (port_t out_port) { + standard_metadata.egress_spec = out_port; + } + + action set_egress_port_and_mac (port_t out_port, mac_addr_t mac_addr) { + hdr.ethernet.dst_addr = mac_addr; + standard_metadata.egress_spec = out_port; + } + + table v6_networks { + key = { + hdr.ipv6.dst_addr: lpm; + } + actions = { + set_egress_port; + set_egress_port_and_mac; + controller_debug; + controller_reply; + controller_debug_table_id; + NoAction; + } + size = ROUTING_TABLE_SIZE; + + default_action = controller_debug_table_id(TABLE_V6_NETWORKS); + } + + table v4_networks { + key = { + hdr.ipv4.dst_addr: lpm; + } + actions = { + set_egress_port; + set_egress_port_and_mac; + controller_debug; + controller_debug_table_id; + NoAction; + } + size = ROUTING_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_V4_NETWORKS); + } + +#endif \ No newline at end of file diff --git a/p4src/actions_generic.p4 b/p4src/actions_generic.p4 new file mode 100644 index 0000000..a6fbabf --- /dev/null +++ b/p4src/actions_generic.p4 @@ -0,0 +1,21 @@ +#ifndef NICO_GENERIC +#define NICO_GENERIC + +/********************** GENERAL ACTIONS ***********************************/ + + action controller_reply(task_t task) { + meta.task = task; + meta.ingress_port = standard_metadata.ingress_port; + clone3(CloneType.I2E, 100, meta); + } + + action controller_debug_table_id(table_t table_id) { + meta.table_id = table_id; + controller_reply(TASK_DEBUG); + } + + action controller_debug() { + controller_reply(TASK_DEBUG); + } + +#endif \ No newline at end of file diff --git a/p4src/actions_icmp6_ndp.p4 b/p4src/actions_icmp6_ndp.p4 new file mode 100644 index 0000000..cff3e46 --- /dev/null +++ b/p4src/actions_icmp6_ndp.p4 @@ -0,0 +1,114 @@ +#ifndef NICO_ICMP6_NDP_ICMP +#define NICO_ICMP6_NDP_ICMP + + +/********************** ICMP6 + NDP + ICMP ***********************************/ + + /* old/unused action -- is it??*/ + action icmp6_answer() { + if(hdr.icmp6.isValid()) { + if(hdr.icmp6.code == ICMP6_ECHO_REQUEST) { + ipv6_addr_t tmp = hdr.ipv6.src_addr; + hdr.ipv6.src_addr = hdr.ipv6.dst_addr; + hdr.ipv6.dst_addr = tmp; + hdr.icmp6.code = ICMP6_ECHO_REPLY; + } + } + } + + action icmp6_neighbor_solicitation(ipv6_addr_t addr, mac_addr_t mac_addr) { + /* egress = ingress */ + standard_metadata.egress_spec = standard_metadata.ingress_port; + + /* 1. IPv6 changes */ + hdr.ipv6.dst_addr = hdr.ipv6.src_addr; + hdr.ipv6.src_addr = addr; + + /* 2. ICMP6 changes */ + hdr.icmp6.type = ICMP6_NA; + hdr.icmp6.code = 0; + hdr.icmp6.checksum = 42; // checksum is calculated in deparser - marking with 42 to see whether it is calculated + + /* 3. icmp6/neighbor advertisement: values taken from real world answers */ + hdr.icmp6_na_ns.router = 0; + hdr.icmp6_na_ns.solicitated = 1; + hdr.icmp6_na_ns.override = 1; + hdr.icmp6_na_ns.reserved = 0; + hdr.icmp6_na_ns.target_addr = addr; + + /* 4. Link layer options */ + hdr.icmp6_option_link_layer_addr.type = ICMP6_NDP_OPT_TARGET_LL; + hdr.icmp6_option_link_layer_addr.ll_length = 1; /* 1* 64 bit */ + hdr.icmp6_option_link_layer_addr.mac_addr = mac_addr; + + /* 5. Checksum trigger/info */ + meta.chk_icmp6_na_ns = 1; + meta.cast_length = (bit<32>) hdr.ipv6.payload_length; + } + + action icmp6_echo_reply() { + mac_addr_t mac_tmp = hdr.ethernet.dst_addr; + hdr.ethernet.dst_addr = hdr.ethernet.src_addr; + hdr.ethernet.src_addr = mac_tmp; + + ipv6_addr_t addr_tmp = hdr.ipv6.dst_addr; + hdr.ipv6.dst_addr = hdr.ipv6.src_addr; + hdr.ipv6.src_addr = addr_tmp; + + hdr.icmp6.type = ICMP6_ECHO_REPLY; + + meta.chk_icmp6 = 1; + + meta.cast_length = (bit<32>) hdr.ipv6.payload_length; + } + + table icmp6 { + key = { + hdr.ipv6.dst_addr: lpm; + hdr.icmp6.type: exact; + } + actions = { + controller_debug; + icmp6_neighbor_solicitation; + icmp6_echo_reply; + controller_debug_table_id; + NoAction; + } + size = ICMP6_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_ICMP6); + } + + action icmp_echo_reply() { + mac_addr_t mac_tmp = hdr.ethernet.dst_addr; + ipv4_addr_t ipv4_tmp = hdr.ipv4.src_addr; + + /* swap ethernet addresses */ + hdr.ethernet.dst_addr = hdr.ethernet.src_addr; + hdr.ethernet.src_addr = mac_tmp; + + /* swap ipv4 addresses */ + hdr.ipv4.src_addr = hdr.ipv4.dst_addr; + hdr.ipv4.dst_addr = ipv4_tmp; + + /* set correct type */ + hdr.icmp.type = ICMP_ECHO_REPLY; + + meta.chk_icmp = 1; + } + + 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); + default_action = NoAction; /* do not clone on miss */ + } + +#endif \ No newline at end of file diff --git a/p4src/actions_nat64_generic.p4 b/p4src/actions_nat64_generic.p4 new file mode 100644 index 0000000..680f4b9 --- /dev/null +++ b/p4src/actions_nat64_generic.p4 @@ -0,0 +1,185 @@ +#ifndef NICO_NAT64_GENERIC +#define NICO_NAT64_GENERIC + +/********************** NAT64 / NAT46 ACTIONS GENERIC ***********************************/ + + /* changes for icmp6 -> icmp */ + action nat64_icmp6_generic() + { + hdr.icmp.setValid(); + hdr.ipv4.protocol = PROTO_ICMP; // overwrite generic same protocol assumption + + /* trigger checksumming */ + meta.switch_task = TASK_CHECKSUM_ICMP; + + meta.chk_icmp = 1; + + hdr.icmp6.setInvalid(); + + /* not needed, as we don't translate them (yet/ever) */ + hdr.icmp6_na_ns.setInvalid(); + hdr.icmp6_option_link_layer_addr.setInvalid(); + } + + /* NAT64 protocol unspecific changes */ + action nat64_generic(ipv4_addr_t src, ipv4_addr_t dst) { + hdr.ipv4.setValid(); + meta.chk_ipv4 = 1; /* need to calculate the hdrchecksum */ + + /* Stuff that might need to be fixed */ + hdr.ipv4.version = (bit<4>)4; + hdr.ipv4.diff_serv = (bit<6>)0; // no ToS + hdr.ipv4.ecn = (bit<2>)0; // unsupported + + /* 5 is ok as long as we don't use options / padding / + anything after the destination address */ + hdr.ipv4.ihl = (bit<4>) 5; // internet header length: 4*5 = 20 + hdr.ipv4.totalLen = (bit<16>) hdr.ipv6.payload_length + 20; // ok under above constraints + + hdr.ipv4.identification = (bit<16>) 0; // no support for fragments + hdr.ipv4.flags = (bit<3>) 0; // DF bit and more fragments + hdr.ipv4.fragOffset = (bit<13>) 0; // 0 as there are no fragments + + /* Stuff that should be fine */ + hdr.ethernet.ethertype = TYPE_IPV4; + + hdr.ipv4.dst_addr = dst; + hdr.ipv4.src_addr = src; + + hdr.ipv4.ttl = hdr.ipv6.hop_limit; + + hdr.ipv4.protocol = hdr.ipv6.next_header; + + hdr.ipv6.setInvalid(); + } + + /* nat64_prefix is the same as the matching key, but without the mask */ + 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); + } + + /* From https://tools.ietf.org/html/rfc792 (IPv4) + +Echo or Echo Reply Message + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + + + From https://tools.ietf.org/html/rfc4443#section-4.1 + +4.1. Echo Request Message + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + +4.2. Echo Reply Message + + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Type | Code | Checksum | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Identifier | Sequence Number | + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + | Data ... + +-+-+-+-+- + + + Type / code are different in ICMP4 and ICMP6! + + */ + + + /* changes for icmp6 -> icmp */ + action nat46_icmp_generic() + { + hdr.icmp6.setValid(); + hdr.ipv6.next_header = PROTO_ICMP6; + + meta.chk_icmp6 = 1; + meta.cast_length = (bit<32>) hdr.ipv6.payload_length; + + hdr.icmp.setInvalid(); + } + + /* NAT46: protocol unspecific changes */ + action nat46_generic(ipv6_addr_t src, ipv6_addr_t dst) { + hdr.ipv6.setValid(); + hdr.ipv4.setInvalid(); + + hdr.ethernet.ethertype = TYPE_IPV6; + + hdr.ipv6.dst_addr = dst; + hdr.ipv6.src_addr = src; + + hdr.ipv6.version = (bit<4>)6; + hdr.ipv6.traffic_class = (bit<8>) hdr.ipv4.diff_serv; + hdr.ipv6.flow_label = (bit<20>) 0; + hdr.ipv6.payload_length = (bit<16>) hdr.ipv4.totalLen - 20; + + hdr.ipv6.next_header = hdr.ipv4.protocol; + hdr.ipv6.hop_limit = hdr.ipv4.ttl; + + } + + + /* matching key: v4_network specified again */ + 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_dst; + ipv6_addr_t dst = v6_src + (ipv6_addr_t) dst_offset; + + nat46_generic(src, dst); + } + + table nat64 { + key = { + hdr.ipv6.dst_addr: lpm; + } + actions = { + controller_debug; + nat64_static; + controller_debug_table_id; + NoAction; + } + size = NAT64_TABLE_SIZE; +// default_action = controller_debug_table_id(TABLE_NAT64); + default_action = NoAction; + } + + table nat46 { + key = { + hdr.ipv4.dst_addr: lpm; + } + actions = { + controller_debug; + nat46_static; + controller_debug_table_id; + NoAction; + } + size = NAT64_TABLE_SIZE; + default_action = controller_debug_table_id(TABLE_NAT46); + } + +#endif \ No newline at end of file diff --git a/p4src/actions_nat64_session.p4 b/p4src/actions_nat64_session.p4 new file mode 100644 index 0000000..3beab93 --- /dev/null +++ b/p4src/actions_nat64_session.p4 @@ -0,0 +1,91 @@ +#ifndef NICO_NAT64_SESSION +#define NICO_NAT64_SESSION + +/********************** NAT64 sessions ***********************************/ + + /* automatic translations */ + action nat64_tcp_session_translate( + ipv4_addr_t src_addr, + bit<16> src_port, + ipv4_addr_t dst_addr, + bit<16> dst_port) + { + hdr.ipv4.setValid(); + + hdr.tcp.src_port = src_port; + hdr.tcp.dst_port = dst_port; + + nat64_generic(src_addr, dst_addr); + } + + action nat46_tcp_session_translate( + ipv6_addr_t src_addr, + bit<16> src_port, + ipv6_addr_t dst_addr, + bit<16> dst_port) + { + hdr.ipv6.setValid(); + + hdr.tcp.src_port = src_port; + hdr.tcp.dst_port = dst_port; + + nat46_generic(src_addr, dst_addr); + } + + /* We are in the right range, need to create a session entry */ + action nat64_tcp_session_create() + { + controller_reply(TASK_NAT64_TCP_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_session { + 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; + nat64_tcp_session_create; + nat64_tcp_session_translate; + NoAction; + } + size = NAT64_TABLE_SIZE; + default_action = nat64_tcp_session_create; + } + + table nat46_tcp_session { + 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; + nat46_tcp_session_translate; + NoAction; + } + size = NAT64_TABLE_SIZE; + //default_action = controller_debug_table_id(TABLE_NAT64_TCP); + default_action = NoAction; + } + + +#endif \ No newline at end of file diff --git a/p4src/checksum_diff.p4 b/p4src/checksum_diff.p4 index abe29b7..ce4987d 100644 --- a/p4src/checksum_diff.p4 +++ b/p4src/checksum_diff.p4 @@ -75,7 +75,6 @@ parser MyParser(packet_in packet, transition accept; } - /* Leaf */ state tcp { packet.extract(hdr.tcp); @@ -138,536 +137,6 @@ control MyIngress(inout headers hdr, inout metadata meta, inout standard_metadata_t standard_metadata) { - /********************** GENERAL ACTIONS ***********************************/ - - action set_egress_port (port_t out_port) { - standard_metadata.egress_spec = out_port; - } - - action set_egress_port_and_mac (port_t out_port, mac_addr_t mac_addr) { - hdr.ethernet.dst_addr = mac_addr; - standard_metadata.egress_spec = out_port; - } - - action controller_reply(task_t task) { - meta.task = task; - meta.ingress_port = standard_metadata.ingress_port; - clone3(CloneType.I2E, 100, meta); - } - - - action controller_debug_table_id(table_t table_id) { - meta.table_id = table_id; - controller_reply(TASK_DEBUG); - } - - action controller_debug() { - controller_reply(TASK_DEBUG); - } - - /********************** NAT64 / NAT46 ACTIONS GENERIC ***********************************/ - - /* changes for icmp6 -> icmp */ - action nat64_icmp6_generic() - { - hdr.icmp.setValid(); - hdr.ipv4.protocol = PROTO_ICMP; // overwrite generic same protocol assumption - - /* trigger checksumming */ - meta.switch_task = TASK_CHECKSUM_ICMP; - - meta.chk_icmp = 1; - - hdr.icmp6.setInvalid(); - - /* not needed, as we don't translate them (yet/ever) */ - hdr.icmp6_na_ns.setInvalid(); - hdr.icmp6_option_link_layer_addr.setInvalid(); - } - - /* NAT64 protocol unspecific changes */ - action nat64_generic(ipv4_addr_t src, ipv4_addr_t dst) { - hdr.ipv4.setValid(); - meta.chk_ipv4 = 1; /* need to calculate the hdrchecksum */ - - /* Stuff that might need to be fixed */ - hdr.ipv4.version = (bit<4>)4; - hdr.ipv4.diff_serv = (bit<6>)0; // no ToS - hdr.ipv4.ecn = (bit<2>)0; // unsupported - - /* 5 is ok as long as we don't use options / padding / - anything after the destination address */ - hdr.ipv4.ihl = (bit<4>) 5; // internet header length: 4*5 = 20 - hdr.ipv4.totalLen = (bit<16>) hdr.ipv6.payload_length + 20; // ok under above constraints - - hdr.ipv4.identification = (bit<16>) 0; // no support for fragments - hdr.ipv4.flags = (bit<3>) 0; // DF bit and more fragments - hdr.ipv4.fragOffset = (bit<13>) 0; // 0 as there are no fragments - - /* Stuff that should be fine */ - hdr.ethernet.ethertype = TYPE_IPV4; - - hdr.ipv4.dst_addr = dst; - hdr.ipv4.src_addr = src; - - hdr.ipv4.ttl = hdr.ipv6.hop_limit; - - hdr.ipv4.protocol = hdr.ipv6.next_header; - - hdr.ipv6.setInvalid(); - } - - /* nat64_prefix is the same as the matching key, but without the mask */ - 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); - } - - /* From https://tools.ietf.org/html/rfc792 (IPv4) - -Echo or Echo Reply Message - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Code | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | Sequence Number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Data ... - +-+-+-+-+- - - - From https://tools.ietf.org/html/rfc4443#section-4.1 - -4.1. Echo Request Message - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Code | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | Sequence Number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Data ... - +-+-+-+-+- - -4.2. Echo Reply Message - - 0 1 2 3 - 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Type | Code | Checksum | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Identifier | Sequence Number | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Data ... - +-+-+-+-+- - - - Type / code are different in ICMP4 and ICMP6! - - */ - - - /* changes for icmp6 -> icmp */ - action nat46_icmp_generic() - { - hdr.icmp6.setValid(); - hdr.ipv6.next_header = PROTO_ICMP6; - - meta.chk_icmp6 = 1; - meta.cast_length = (bit<32>) hdr.ipv6.payload_length; - - hdr.icmp.setInvalid(); - } - - /* NAT46: protocol unspecific changes */ - action nat46_generic(ipv6_addr_t src, ipv6_addr_t dst) { - hdr.ipv6.setValid(); - hdr.ipv4.setInvalid(); - - hdr.ethernet.ethertype = TYPE_IPV6; - - hdr.ipv6.dst_addr = dst; - hdr.ipv6.src_addr = src; - - hdr.ipv6.version = (bit<4>)6; - hdr.ipv6.traffic_class = (bit<8>) hdr.ipv4.diff_serv; - hdr.ipv6.flow_label = (bit<20>) 0; - hdr.ipv6.payload_length = (bit<16>) hdr.ipv4.totalLen - 20; - - hdr.ipv6.next_header = hdr.ipv4.protocol; - hdr.ipv6.hop_limit = hdr.ipv4.ttl; - - } - - - /* matching key: v4_network specified again */ - 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_dst; - ipv6_addr_t dst = v6_src + (ipv6_addr_t) dst_offset; - - nat46_generic(src, dst); - } - - table nat64 { - key = { - hdr.ipv6.dst_addr: lpm; - } - actions = { - controller_debug; - nat64_static; - controller_debug_table_id; - NoAction; - } - size = NAT64_TABLE_SIZE; -// default_action = controller_debug_table_id(TABLE_NAT64); - default_action = NoAction; - } - - table nat46 { - key = { - hdr.ipv4.dst_addr: lpm; - } - actions = { - controller_debug; - nat46_static; - controller_debug_table_id; - NoAction; - } - size = NAT64_TABLE_SIZE; - default_action = controller_debug_table_id(TABLE_NAT46); - } - - /********************** NAT64 sessions ***********************************/ - - /* automatic translations */ - action nat64_tcp_session_translate( - ipv4_addr_t src_addr, - bit<16> src_port, - ipv4_addr_t dst_addr, - bit<16> dst_port) - { - hdr.ipv4.setValid(); - - hdr.tcp.src_port = src_port; - hdr.tcp.dst_port = dst_port; - - nat64_generic(src_addr, dst_addr); - } - - action nat46_tcp_session_translate( - ipv6_addr_t src_addr, - bit<16> src_port, - ipv6_addr_t dst_addr, - bit<16> dst_port) - { - hdr.ipv6.setValid(); - - hdr.tcp.src_port = src_port; - hdr.tcp.dst_port = dst_port; - - nat46_generic(src_addr, dst_addr); - } - - /* We are in the right range, need to create a session entry */ - action nat64_tcp_session_create() - { - controller_reply(TASK_NAT64_TCP_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_session { - 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; - nat64_tcp_session_create; - nat64_tcp_session_translate; - NoAction; - } - size = NAT64_TABLE_SIZE; - default_action = nat64_tcp_session_create; - } - - table nat46_tcp_session { - 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; - nat46_tcp_session_translate; - NoAction; - } - size = NAT64_TABLE_SIZE; - //default_action = controller_debug_table_id(TABLE_NAT64_TCP); - default_action = NoAction; - } - - - - /********************** ICMP6 + NDP + ICMP ***********************************/ - - /* old/unused action -- is it??*/ - action icmp6_answer() { - if(hdr.icmp6.isValid()) { - if(hdr.icmp6.code == ICMP6_ECHO_REQUEST) { - ipv6_addr_t tmp = hdr.ipv6.src_addr; - hdr.ipv6.src_addr = hdr.ipv6.dst_addr; - hdr.ipv6.dst_addr = tmp; - hdr.icmp6.code = ICMP6_ECHO_REPLY; - } - } - } - - action icmp6_neighbor_solicitation(ipv6_addr_t addr, mac_addr_t mac_addr) { - /* egress = ingress */ - standard_metadata.egress_spec = standard_metadata.ingress_port; - - /* 1. IPv6 changes */ - hdr.ipv6.dst_addr = hdr.ipv6.src_addr; - hdr.ipv6.src_addr = addr; - - /* 2. ICMP6 changes */ - hdr.icmp6.type = ICMP6_NA; - hdr.icmp6.code = 0; - hdr.icmp6.checksum = 42; // checksum is calculated in deparser - marking with 42 to see whether it is calculated - - /* 3. icmp6/neighbor advertisement: values taken from real world answers */ - hdr.icmp6_na_ns.router = 0; - hdr.icmp6_na_ns.solicitated = 1; - hdr.icmp6_na_ns.override = 1; - hdr.icmp6_na_ns.reserved = 0; - hdr.icmp6_na_ns.target_addr = addr; - - /* 4. Link layer options */ - hdr.icmp6_option_link_layer_addr.type = ICMP6_NDP_OPT_TARGET_LL; - hdr.icmp6_option_link_layer_addr.ll_length = 1; /* 1* 64 bit */ - hdr.icmp6_option_link_layer_addr.mac_addr = mac_addr; - - /* 5. Checksum trigger/info */ - meta.chk_icmp6_na_ns = 1; - meta.cast_length = (bit<32>) hdr.ipv6.payload_length; - } - - action icmp6_echo_reply() { - mac_addr_t mac_tmp = hdr.ethernet.dst_addr; - hdr.ethernet.dst_addr = hdr.ethernet.src_addr; - hdr.ethernet.src_addr = mac_tmp; - - ipv6_addr_t addr_tmp = hdr.ipv6.dst_addr; - hdr.ipv6.dst_addr = hdr.ipv6.src_addr; - hdr.ipv6.src_addr = addr_tmp; - - hdr.icmp6.type = ICMP6_ECHO_REPLY; - - meta.chk_icmp6 = 1; - - meta.cast_length = (bit<32>) hdr.ipv6.payload_length; - } - - table icmp6 { - key = { - hdr.ipv6.dst_addr: lpm; - hdr.icmp6.type: exact; - } - actions = { - controller_debug; - icmp6_neighbor_solicitation; - icmp6_echo_reply; - controller_debug_table_id; - NoAction; - } - size = ICMP6_TABLE_SIZE; - default_action = controller_debug_table_id(TABLE_ICMP6); - } - - action icmp_echo_reply() { - mac_addr_t mac_tmp = hdr.ethernet.dst_addr; - ipv4_addr_t ipv4_tmp = hdr.ipv4.src_addr; - - /* swap ethernet addresses */ - hdr.ethernet.dst_addr = hdr.ethernet.src_addr; - hdr.ethernet.src_addr = mac_tmp; - - /* swap ipv4 addresses */ - hdr.ipv4.src_addr = hdr.ipv4.dst_addr; - hdr.ipv4.dst_addr = ipv4_tmp; - - /* set correct type */ - hdr.icmp.type = ICMP_ECHO_REPLY; - - meta.chk_icmp = 1; - } - - 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); - default_action = NoAction; /* do not clone on miss */ - } - - /********************** ARP ***********************************/ - - action arp_reply(mac_addr_t mac_addr) { - /* swap */ - ipv4_addr_t ipv4_src = hdr.arp.dst_ipv4_addr; - ipv4_addr_t ipv4_dst = hdr.arp.src_ipv4_addr; - - /* swap/add */ - mac_addr_t mac_src = mac_addr; - mac_addr_t mac_dst = hdr.arp.src_mac_addr; - - /* fill the ethernet header */ - hdr.ethernet.dst_addr = mac_dst; - hdr.ethernet.src_addr = mac_src; - - /* fill the arp header */ - hdr.arp.dst_mac_addr = mac_dst; - hdr.arp.src_mac_addr = mac_src; - - /* swapping */ - hdr.arp.dst_ipv4_addr = ipv4_dst; - hdr.arp.src_ipv4_addr = ipv4_src; - - hdr.arp.opcode = ARP_REPLY; - } - - table v4_arp { - key = { - hdr.ethernet.dst_addr: exact; - hdr.arp.opcode: exact; - hdr.arp.dst_ipv4_addr: lpm; - } - actions = { - controller_debug_table_id; - arp_reply; - NoAction; - } - size = ICMP6_TABLE_SIZE; - default_action = controller_debug_table_id(TABLE_ARP); - } - - table v4_arp_egress { - key = { - hdr.arp.dst_ipv4_addr: lpm; - } - actions = { - controller_debug_table_id; - set_egress_port; - NoAction; - } - size = ICMP6_TABLE_SIZE; - default_action = controller_debug_table_id(TABLE_ARP_EGRESS); - } - - - /********************** ROUTING (egress definiton) TABLES ***********************************/ - - table v6_networks { - key = { - hdr.ipv6.dst_addr: lpm; - } - actions = { - set_egress_port; - set_egress_port_and_mac; - controller_debug; - controller_reply; - controller_debug_table_id; - NoAction; - } - size = ROUTING_TABLE_SIZE; - - default_action = controller_debug_table_id(TABLE_V6_NETWORKS); - } - - table v4_networks { - key = { - hdr.ipv4.dst_addr: lpm; - } - actions = { - set_egress_port; - set_egress_port_and_mac; - controller_debug; - controller_debug_table_id; - NoAction; - } - size = ROUTING_TABLE_SIZE; - default_action = controller_debug_table_id(TABLE_V4_NETWORKS); - } - - action v4sum() { - bit<16> localsum = 0; - - localsum = localsum + hdr.ipv4.src_addr[15:0]; // 16 bit - localsum = localsum + hdr.ipv4.src_addr[31:16]; // 16 bit - localsum = localsum + hdr.ipv4.dst_addr[15:0]; // 16 bit - localsum = localsum + hdr.ipv4.dst_addr[31:16]; // 16 bit - - localsum = localsum + hdr.ipv4.totalLen -20; // 16 bit - localsum = localsum + (bit<16>) hdr.ipv4.protocol; // 8 bit - } - - action v6sum() { - bit<16> localsum = 0; - - localsum = localsum + hdr.ipv6.src_addr[15:0]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[31:16]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[47:32]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[63:48]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[79:64]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[95:80]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[111:96]; // 16 bit - localsum = localsum + hdr.ipv6.src_addr[127:112]; // 16 bit - - localsum = localsum + hdr.ipv6.dst_addr[15:0]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[31:16]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[47:32]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[63:48]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[79:64]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[95:80]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[111:96]; // 16 bit - localsum = localsum + hdr.ipv6.dst_addr[127:112]; // 16 bit - - localsum = localsum + hdr.ipv6.payload_length; // 16 bit - localsum = localsum + (bit<16>) hdr.ipv6.next_header; // 8 bit - } /********************** APPLYING TABLES ***********************************/ apply {