#include #include #include "headers.p4" /******************************************************************************** * Possible bugs / things to fix: - Does NoAction exist? - Aligment of "meta" - replace metadate with our own */ /******************************************************************************** * Header */ typedef bit<48> EthAddr_t; header Ethernet_h { EthAddr_t dstAddr; EthAddr_t srcAddr; bit<16> etherType; } struct Parsed_packet { Ethernet_h ethernet; } // digest_data, MUST be 256 bits -- what is this used for? struct digest_data_t { bit<256> unused; } /******************************************************************************** * Parser */ @Xilinx_MaxPacketRegion(1024) parser TopParser(packet_in b, out Parsed_packet p, out metadata meta, out digest_data_t digest_data, inout sume_metadata_t sume_metadata) { state start { b.extract(p.ethernet); digest_data.unused = 0; transition accept; } } /******************************************************************************** * Main */ control TopPipe(inout Parsed_packet p, inout metadata meta, inout digest_data_t digest_data, inout sume_metadata_t sume_metadata) { /* FIXME: not sure what to do on netpfga */ action drop() { #ifndef _SUME_SWITCH_P4_ mark_to_drop(); #endif } action set_egress_port (port_t out_port) { #ifdef _SUME_SWITCH_P4_ sume_metadata.dst_port = out_port; #else standard_metadata.egress_spec = out_port; #endif } action set_egress_port_and_mac (port_t out_port, mac_addr_t mac_addr) { hdr.ethernet.dst_addr = mac_addr; set_egress_port(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); // } // action multicast_pkg(mcast_t mcast_grp) { /* Output PKG on correct ports (plural) */ // standard_metadata.mcast_grp = mcast_grp; // } // /********************** 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 swap_eth_addresses() { EthAddr_t temp = p.ethernet.dstAddr; p.ethernet.dstAddr = p.ethernet.srcAddr; p.ethernet.srcAddr = temp; /* set egress port */ sume_metadata.dst_port = sume_metadata.src_port; } action send_to_port1() { set_egress_port(1); // sume_metadata.dst_port = 1; } // action send_to_all_ports() { // /* Taken from commands.txt of the "int" project: // table_cam_add_entry forward set_output_port 0xffffffffffff => 0b01010101 // python convert: // >>> 0b01010101 // 85 // */ // sume_metadata.dst_port = 85; // } action do_nothing() { EthAddr_t temp = p.ethernet.dstAddr; } table lookup_table { key = { p.ethernet.dstAddr: exact; } actions = { swap_eth_addresses; do_nothing; send_to_port1; // send_to_all_ports; } size = TEST_TABLE_SIZE; // default_action = swap_eth_addresses; // test_mirror(): in gen_testdata.py default_action = send_to_port1; // test_port1() // default_action = send_to_all_ports; // test_allports(): } apply { lookup_table.apply(); } } /******************************************************************************** * Deparser */ @Xilinx_MaxPacketRegion(1024) control TopDeparser(packet_out b, in Parsed_packet p, in user_metadata_t user_metadata, inout digest_data_t digest_data, inout sume_metadata_t sume_metadata) { apply { b.emit(p.ethernet); } } /******************************************************************************** * Switch */ SimpleSumeSwitch( TopParser(), TopPipe(), TopDeparser() ) main;