├── LICENSE ├── README.md ├── misc └── testbed.png ├── redplane-p4 ├── README.md ├── firewall │ ├── firewall.p4 │ ├── fw_redplane.p4 │ ├── headers.p4 │ ├── l3_routing.p4 │ ├── parsers.p4 │ ├── redplane_core.p4 │ ├── replication.p4 │ └── types.p4 ├── load_balancing │ ├── headers.p4 │ ├── l3_routing.p4 │ ├── lb_redplane.p4 │ ├── load_balance.p4 │ ├── parsers.p4 │ ├── redplane_core.p4 │ ├── replication.p4 │ └── types.p4 ├── nat │ ├── headers.p4 │ ├── l3_routing.p4 │ ├── nat.p4 │ ├── nat_redplane.p4 │ ├── parsers.p4 │ ├── redplane_core.p4 │ ├── replication.p4 │ └── types.p4 ├── simple-kv │ ├── headers.p4 │ ├── kv_redplane.p4 │ ├── l3_routing.p4 │ ├── parsers.p4 │ ├── redplane_core.p4 │ ├── replication.p4 │ ├── simple_kv.p4 │ └── types.p4 └── sketch-snapshot │ ├── count_min.p4 │ ├── headers.p4 │ ├── l3_routing.p4 │ ├── parsers.p4 │ ├── redplane_core.p4 │ ├── replication.p4 │ ├── sketch.p4 │ ├── sketch_snapshot_redplane.p4 │ └── types.p4 ├── redplane-store ├── CMakeLists.txt ├── README.md ├── apps │ ├── pktgen │ │ ├── m57_summary.txt │ │ ├── parse_pcap.py │ │ ├── pktgen.h │ │ ├── pktgen_bw.cc │ │ ├── pktgen_lat.cc │ │ ├── redplane_header.h │ │ └── tests │ │ │ ├── pktgen.py │ │ │ └── recv.py │ ├── server_nat │ │ ├── nat_main.cc │ │ ├── nat_main.h │ │ ├── redplane_header.h │ │ ├── store_chain.cc │ │ ├── store_chain.h │ │ └── tests │ │ │ ├── pktgen.py │ │ │ └── recv.py │ ├── state_store │ │ ├── redplane_header.h │ │ ├── store_chain.cc │ │ ├── store_chain.h │ │ ├── store_main.cc │ │ ├── store_main.h │ │ ├── store_tester.cc │ │ ├── store_tester.h │ │ └── tests │ │ │ ├── pktgen.py │ │ │ └── recv.py │ └── transport_test │ │ ├── common.h │ │ ├── receiver.cc │ │ ├── receiver.h │ │ ├── sender.cc │ │ └── sender.h └── raw_transport │ ├── common.h │ ├── raw_transport.cc │ └── raw_transport.h ├── redplane-tla └── redplane_lease.tla └── scripts ├── servers ├── 01-netcfg.yaml ├── cpu_performance.sh ├── install_mlnx_ofed_all.py ├── ip_list.txt ├── pingall.sh ├── setup_all.py ├── setup_hugepages.sh └── setup_packages.sh └── tofino_build ├── p4_build.sh ├── set_sde.bash ├── veth_setup.sh └── veth_teardown.sh /README.md: -------------------------------------------------------------------------------- 1 | # RedPlane: Enabling Fault-Tolerant Stateful In-Switch Applications 2 | 3 | This is the source code repository of the RedPlane project. 4 | Check out [our paper](https://github.com/daehyeok-kim/redplane-public) for more details. 5 | 6 | This repository contains key components to run the RedPlane protocol. 7 | ## Directory Structure 8 | 9 | Subdirectory | Description 10 | ------------------| --------------- 11 | `redplane-p4` | P4 source code for RedPlane-enabled in-switch applications 12 | `redplane-store` | C++ source code for RedPlane state store 13 | `redplane-tla` | TLA+ specification of the RedPlane protocol 14 | `scripts` | Scripts for setup regular switches, servers, and building P4 applications 15 | 16 | Each subdirectory includes build instructions for the components. 17 | 18 | ## System Requirements and Dependencies 19 | We tested the current implementation in the following enviornments: 20 | - **RedPlane P4:** Tofino-based Arista 7170s switch with Intel P4 studio 9.1.1 21 | - **RedPlane state store:** Ubuntu 18.04 with Mellanox OFED 4.7-4.2.9.0 22 | 23 | Our testbed consists of two Tofino-based Arista 7170 switches, three Arista 7060CX regular switches, and servers connected as follows: 24 | 25 | 26 | 27 | ## Contact 28 | Daehyeok Kim (daehyeok@cs.cmu.edu) 29 | -------------------------------------------------------------------------------- /misc/testbed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daehyeok-kim/redplane-public/da1f80ee50f977c6e7f01bbaa9c4c6b2fb82122b/misc/testbed.png -------------------------------------------------------------------------------- /redplane-p4/README.md: -------------------------------------------------------------------------------- 1 | # RedPlane-enabled P4 applications 2 | 3 | We built and tested our implementation with Tofino-baed Arista 7170 switches and Intel P4 Studio 9.1.1. 4 | 5 | ## Build Instructions 6 | 1. Set up the P4 studio SDE environment variables. For example, run the following command in the bf-sde-9.1.1 directory in your system, 7 | ```bash 8 | bf-sde-9.1.1$ . $PROJ_ROOT/scripts/set_sde.sh 9 | ``` 10 | 2. Compile each P4 application using the build script included in `scripts`. For example, to build RedPlane-enabled NAT, 11 | ```bash 12 | nat_dir$ $PROJ_ROOT/scripts/p4_build.sh nat_redplane.p4 13 | ``` 14 | -------------------------------------------------------------------------------- /redplane-p4/firewall/firewall.p4: -------------------------------------------------------------------------------- 1 | #ifndef _FIREWALL_ 2 | #define _FIREWALL_ 3 | 4 | #include "headers.p4" 5 | 6 | /***************** M A T C H - A C T I O N *********************/ 7 | control Fw_Ingress( 8 | /* User */ 9 | inout ingress_headers_t hdr, 10 | inout ingress_metadata_t ig_md, 11 | /* Intrinsic */ 12 | in ingress_intrinsic_metadata_t ig_intr_md, 13 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 14 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 15 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 16 | { 17 | action drop() { 18 | ig_dprsr_md.drop_ctl = 1; 19 | } 20 | 21 | table fw_ext_to_int { 22 | key = { 23 | hdr.ipv4.dst_addr: exact; 24 | hdr.tcp.dst_port: exact; 25 | } 26 | actions = { drop; NoAction; } 27 | default_action = drop(); 28 | } 29 | 30 | apply { 31 | if(hdr.ipv4.isValid()) { 32 | if(ig_md.nat_meta.is_ext == true){ // from internal 33 | fw_ext_to_int.apply(); 34 | } 35 | } 36 | } 37 | } 38 | 39 | #endif /* _FIREWALL_ */ -------------------------------------------------------------------------------- /redplane-p4/firewall/fw_redplane.p4: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if __TARGET_TOFINO__ == 2 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "types.p4" 10 | #include "headers.p4" 11 | #include "parsers.p4" 12 | #include "l3_routing.p4" 13 | #include "replication.p4" 14 | #include "redplane_core.p4" 15 | #include "firewall.p4" //FW P4 we want to make fault-tolerant 16 | 17 | control Ingress( 18 | inout ingress_headers_t hdr, 19 | inout ingress_metadata_t ig_md, 20 | in ingress_intrinsic_metadata_t ig_intr_md, 21 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 22 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 23 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 24 | // COMPILER: This line should be added by Redplane compiler. 25 | RedplaneIngress() redplane_ig; 26 | Fw_Ingress() Fw_Ingress; // Instantiate the original application 27 | L3Routing() L3_routing; 28 | Replication() replication; 29 | 30 | apply { 31 | //if (hdr.redplane_ack.isValid() == false && hdr.redplane_req.isValid() == false) { 32 | //if (hdr.redplane_req.isValid() == false) { 33 | //} 34 | //if (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_NEW_ACK) { 35 | // hdr.tstamp.in_time = ig_intr_md.ingress_mac_tstamp; 36 | //} 37 | // COMPILER: This line should be added by Redplane compiler. 38 | redplane_ig.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 39 | 40 | // COMPILER: This line should be added by Redplane compiler. 41 | // If the packet is an Redplane ACK from the state store, the app must not process it. 42 | if (ig_md.is_renew_req == true) { 43 | // App's ingress logic. 44 | // hdr.tstamp.out_time = ig_intr_md.ingress_mac_tstamp; 45 | Fw_Ingress.apply(hdr, ig_md, ig_intr_md, ig_prsr_md, ig_dprsr_md, ig_tm_md); 46 | } 47 | 48 | if ((ig_md.is_renew_req == true || (hdr.redplane_ack.isValid() == true && hdr.ipv4.isValid() == true)) && ig_tm_md.ucast_egress_port != CPU_PORT) { 49 | L3_routing.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 50 | } 51 | 52 | if ((hdr.bridged_md.is_write == 0 && hdr.redplane_req.isValid() == true && hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) || // If it's a read renew request, 53 | (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_RENEW_ACK && hdr.ipv4.isValid() == true)) // if it's an ack with a piggybacked original packet 54 | { 55 | //then replicate it! 56 | replication.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 57 | } 58 | } 59 | } 60 | 61 | control Egress( 62 | inout egress_headers_t hdr, 63 | inout egress_metadata_t eg_md, 64 | in egress_intrinsic_metadata_t eg_intr_md, 65 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 66 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 67 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 68 | 69 | // COMPILER: This line should be added by Redplane compiler. 70 | RedplaneEgress() redplane_eg; 71 | 72 | action invalidate_redplane_hdr() { 73 | hdr.redplane_ipv4.setInvalid(); 74 | hdr.redplane_udp.setInvalid(); 75 | hdr.redplane_req.setInvalid(); 76 | hdr.redplane_ack.setInvalid(); 77 | hdr.redplane_values.setInvalid(); 78 | } 79 | apply { 80 | // Redplane packet destined to the state store OR Write packet is processed 81 | if (eg_intr_md.egress_rid_first == 1 // replicated packet (RENEW ACK or RENEW REQ) 82 | || eg_md.bridged_md.is_write == 1 // RENEW REQ with write 83 | || (hdr.redplane_ack.isValid() && hdr.ipv4.isValid() ==false) // RENEW ACK without payload 84 | || eg_md.is_logged_req == true) 85 | { 86 | if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 87 | redplane_eg.apply(hdr, eg_md, eg_intr_md, eg_prsr_md, eg_dprsr_md); 88 | } 89 | } else if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 90 | invalidate_redplane_hdr(); 91 | } 92 | } 93 | } 94 | 95 | Pipeline( 96 | IngressParser(), 97 | Ingress(), 98 | IngressDeparser(), 99 | EgressParser(), 100 | Egress(), 101 | EgressDeparser() 102 | ) pipe; 103 | 104 | Switch(pipe) main; 105 | -------------------------------------------------------------------------------- /redplane-p4/firewall/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | #include "types.p4" 5 | 6 | const PortId_t CPU_PORT = 320; 7 | const PortId_t DEFAULT_STORE_PORT = 8; 8 | //const PortId_t CPU_PORT = 64; 9 | //const PortId_t DEFAULT_STORE_PORT = 1; 10 | 11 | const ether_type_t ETHERTYPE_IPV4 = 0x0800; 12 | const ether_type_t ETHERTYPE_TO_CPU = 0xBF01; 13 | 14 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 15 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 16 | 17 | const mirror_type_t MIRROR_TYPE_E2E = 2; 18 | 19 | const bit<48> LEASE_PERIOD = 100000000000; // 5 secs 20 | const bit<48> TIMEOUT = 1000000; // 1 msec 21 | const bit<16> MAX_SEQ_NUM = 65533; 22 | const bit<16> SWITCH_UDP_PORT = 4000; 23 | const bit<16> STORE_UDP_PORT = 8000; 24 | 25 | const pkt_type_t PKT_TYPE_NORMAL = 0; // Normal packets (just coming in); 26 | const pkt_type_t PKT_TYPE_EGR_MIRROR = 1; // Transaction for logging 27 | 28 | header ethernet_h { 29 | mac_addr_t dst_addr; 30 | mac_addr_t src_addr; 31 | bit<16> ether_type; 32 | } 33 | 34 | header ipv4_h { 35 | bit<4> version; 36 | bit<4> ihl; 37 | bit<8> diffserv; 38 | bit<16> total_len; 39 | bit<16> identification; 40 | bit<3> flags; 41 | bit<13> frag_offset; 42 | bit<8> ttl; 43 | bit<8> protocol; 44 | bit<16> hdr_checksum; 45 | ipv4_addr_t src_addr; 46 | ipv4_addr_t dst_addr; 47 | } 48 | 49 | header tcp_h { 50 | bit<16> src_port; 51 | bit<16> dst_port; 52 | bit<32> seq_no; 53 | bit<32> ack_no; 54 | bit<4> data_offset; 55 | bit<4> res; 56 | bit<1> cwr; 57 | bit<1> ece; 58 | bit<1> urg; 59 | bit<1> ack; 60 | bit<1> psh; 61 | bit<1> rst; 62 | bit<1> syn; 63 | bit<1> fin; 64 | bit<16> window; 65 | bit<16> checksum; 66 | bit<16> urgent_ptr; 67 | } 68 | 69 | header udp_h { 70 | bit<16> src_port; 71 | bit<16> dst_port; 72 | bit<16> hdr_length; 73 | bit<16> checksum; 74 | } 75 | 76 | header tstamp_h{ 77 | bit<48> in_time; 78 | bit<48> out_time; 79 | } 80 | 81 | header redplane_req_h { 82 | req_type_t req_type; //1 83 | bit<16> seq_num; // 2 84 | flow_key_t flow_key; //6 85 | flow_value_t values; //6 86 | } 87 | 88 | const bit<16> REDPLANE_REQ_IP_LEN = 20 + 8 + 15; 89 | const bit<16> REDPLANE_REQ_UDP_LEN = 8 + 15; 90 | 91 | header redplane_ack_h { 92 | ack_type_t ack_type; // 1 93 | bit<16> seq_num; // 2 94 | flow_key_t flow_key; // 6 95 | } 96 | const bit<16> REDPLANE_ACK_IP_LEN = 20 + 8 + 9; 97 | 98 | header redplane_flow_value_h { 99 | flow_value_t values; 100 | } 101 | 102 | header egr_mirror_h { 103 | pkt_type_t pkt_type; 104 | bit<48> tstamp; 105 | @padding 106 | bit<7> pad; 107 | bit<1> is_first_time; 108 | } 109 | 110 | header bridged_md_h { 111 | pkt_type_t pkt_type; //8 112 | PortId_t store_egress_port; //9 113 | PortId_t original_port; //9 114 | bit<1> is_write; 115 | @padding 116 | bit<5> pad; 117 | } 118 | struct ingress_headers_t { 119 | bridged_md_h bridged_md; 120 | ethernet_h cpu_ethernet; 121 | ethernet_h ethernet; 122 | ipv4_h redplane_ipv4; 123 | udp_h redplane_udp; 124 | redplane_req_h redplane_req; 125 | redplane_ack_h redplane_ack; 126 | redplane_flow_value_h redplane_values; 127 | ipv4_h ipv4; 128 | tcp_h tcp; 129 | udp_h udp; 130 | tstamp_h tstamp; 131 | } 132 | 133 | struct egress_headers_t { 134 | ethernet_h ethernet; 135 | ipv4_h redplane_ipv4; 136 | udp_h redplane_udp; 137 | redplane_req_h redplane_req; 138 | redplane_ack_h redplane_ack; 139 | redplane_flow_value_h redplane_values; 140 | ipv4_h ipv4; 141 | tcp_h tcp; 142 | udp_h udp; 143 | } 144 | 145 | struct ingress_metadata_t { 146 | bit<2> hashed_key; 147 | bool is_renew_req; 148 | bool lease_expired; 149 | nat_meta_t nat_meta; 150 | // checksum stuff 151 | bool ipv4_checksum_err; 152 | bool checksum_update_ipv4; 153 | bool checksum_update_redplane_ipv4; 154 | bool checksum_update_tcp; 155 | bit<16> checksum_tcp_tmp; 156 | flow_key_t flow_key; 157 | bit<32> new_lease_expire_time; 158 | bit<32> current_time; 159 | } 160 | 161 | struct egress_metadata_t { 162 | bridged_md_h bridged_md; 163 | bit<48> tstamp; 164 | bit<16> time_diff_hi; 165 | bit<16> time_diff_lo; 166 | MirrorId_t egr_mir_ses; 167 | pkt_type_t pkt_type; 168 | bool is_acked_req; 169 | bool is_logged_req; 170 | bit<16> seq_same; 171 | bit<16> last_sent; 172 | bit<16> last_acked; 173 | bit<16> seq_diff; 174 | bit<16> seq_diff1; 175 | bit<16> seq_diff2; 176 | bit<16> cur_seq_num; 177 | bit<1> is_first_time; 178 | // checksum stuff 179 | bool checksum_err_ipv4; 180 | flow_key_t flow_key; 181 | } 182 | 183 | #endif /* _HEADERS_ */ 184 | -------------------------------------------------------------------------------- /redplane-p4/firewall/l3_routing.p4: -------------------------------------------------------------------------------- 1 | #ifndef _L3_ROUTING_ 2 | #define _L3_ROUTING_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control L3Routing ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | action set_nhop(bit<9> port){ 15 | ig_tm_md.ucast_egress_port = port; 16 | } 17 | 18 | table ipv4_lpm { 19 | key = {hdr.ipv4.dst_addr : lpm;} 20 | actions = { set_nhop; } 21 | } 22 | 23 | apply { 24 | ipv4_lpm.apply(); 25 | } 26 | } 27 | #endif /* _L3_ROUTING_ */ -------------------------------------------------------------------------------- /redplane-p4/firewall/parsers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _PARSERS_ 2 | #define _PARSERS_ 3 | 4 | parser IngressParser(packet_in pkt, 5 | out ingress_headers_t hdr, 6 | out ingress_metadata_t ig_md, 7 | out ingress_intrinsic_metadata_t ig_intr_md) 8 | { 9 | Checksum() ipv4_checksum; 10 | Checksum() tcp_checksum; 11 | state start { 12 | pkt.extract(ig_intr_md); 13 | pkt.advance(PORT_METADATA_SIZE); 14 | transition meta_init; 15 | } 16 | 17 | state meta_init { 18 | //Initialize ingress metadata 19 | ig_md.checksum_update_redplane_ipv4 = false; 20 | ig_md.ipv4_checksum_err = false; 21 | ig_md.is_renew_req = false; 22 | ig_md.lease_expired = true; 23 | transition parse_ethernet; 24 | } 25 | 26 | state parse_ethernet { 27 | pkt.extract (hdr.ethernet); 28 | transition select (hdr.ethernet.ether_type) { 29 | ETHERTYPE_IPV4: parse_ipv4; 30 | default: accept; 31 | } 32 | } 33 | 34 | state parse_ipv4 { 35 | ipv4_h tmp_ipv4 = pkt.lookahead(); 36 | transition select(tmp_ipv4.protocol) { 37 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 38 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 39 | default: reject; 40 | } 41 | } 42 | 43 | state parse_regular_or_redplane_ipv4 { 44 | transition select(pkt.lookahead>()[15:0]) { 45 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 46 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 47 | default: parse_regular_ipv4; 48 | } 49 | } 50 | 51 | state parse_redplane_ipv4_udp_ack { 52 | pkt.extract (hdr.redplane_ipv4); 53 | pkt.extract (hdr.redplane_udp); 54 | pkt.extract (hdr.redplane_ack); 55 | 56 | ig_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 57 | ig_md.flow_key.port = hdr.redplane_ack.flow_key.port; 58 | 59 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 60 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 61 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 62 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 63 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 64 | default: reject; // reject all other invalid ack packets. 65 | } 66 | } 67 | 68 | state parse_lease_migrate_ack { 69 | pkt.extract(hdr.redplane_values); 70 | transition parse_regular_ipv4; 71 | } 72 | 73 | state parse_redplane_ipv4_udp_req { 74 | pkt.extract (hdr.redplane_ipv4); 75 | pkt.extract (hdr.redplane_udp); 76 | pkt.extract (hdr.redplane_req); 77 | 78 | ig_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 79 | ig_md.flow_key.port = hdr.redplane_req.flow_key.port; 80 | 81 | transition parse_regular_ipv4; 82 | } 83 | 84 | state parse_regular_ipv4 { 85 | pkt.extract (hdr.ipv4); 86 | ipv4_checksum.add(hdr.ipv4); 87 | ig_md.ipv4_checksum_err = ipv4_checksum.verify(); 88 | 89 | tcp_checksum.subtract({hdr.ipv4.src_addr}); 90 | tcp_checksum.subtract({hdr.ipv4.dst_addr}); 91 | 92 | transition select (hdr.ipv4.protocol) { 93 | IP_PROTOCOLS_TCP: parse_tcp; 94 | IP_PROTOCOLS_UDP: parse_udp; 95 | default: reject; 96 | } 97 | } 98 | 99 | state parse_tcp { 100 | pkt.extract(hdr.tcp); 101 | // The tcp checksum cannot be verified, since we cannot compute 102 | // the payload's checksum. 103 | tcp_checksum.subtract({hdr.tcp.checksum}); 104 | tcp_checksum.subtract({hdr.tcp.src_port}); 105 | tcp_checksum.subtract({hdr.tcp.dst_port}); 106 | ig_md.checksum_tcp_tmp = tcp_checksum.get(); 107 | 108 | transition accept; 109 | } 110 | 111 | state parse_tstamp { 112 | pkt.extract(hdr.tstamp); 113 | transition accept; 114 | } 115 | 116 | state parse_udp { 117 | pkt.extract(hdr.udp); 118 | transition accept; 119 | } 120 | } 121 | 122 | control IngressDeparser(packet_out pkt, 123 | inout ingress_headers_t hdr, 124 | in ingress_metadata_t ig_md, 125 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) 126 | { 127 | Checksum() ipv4_checksum; 128 | Checksum() tcp_checksum; 129 | Checksum() redplane_ipv4_checksum; 130 | Mirror() mirror; 131 | 132 | apply { 133 | if (ig_md.checksum_update_redplane_ipv4) { 134 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 135 | hdr.redplane_ipv4.version, 136 | hdr.redplane_ipv4.ihl, 137 | hdr.redplane_ipv4.diffserv, 138 | hdr.redplane_ipv4.total_len, 139 | hdr.redplane_ipv4.identification, 140 | hdr.redplane_ipv4.flags, 141 | hdr.redplane_ipv4.frag_offset, 142 | hdr.redplane_ipv4.ttl, 143 | hdr.redplane_ipv4.protocol, 144 | hdr.redplane_ipv4.src_addr, 145 | hdr.redplane_ipv4.dst_addr 146 | }); 147 | } 148 | 149 | if (ig_md.checksum_update_ipv4) { 150 | hdr.ipv4.hdr_checksum = ipv4_checksum.update({ 151 | hdr.ipv4.version, 152 | hdr.ipv4.ihl, 153 | hdr.ipv4.diffserv, 154 | hdr.ipv4.total_len, 155 | hdr.ipv4.identification, 156 | hdr.ipv4.flags, 157 | hdr.ipv4.frag_offset, 158 | hdr.ipv4.ttl, 159 | hdr.ipv4.protocol, 160 | hdr.ipv4.src_addr, 161 | hdr.ipv4.dst_addr 162 | }); 163 | } 164 | 165 | if (ig_md.checksum_update_tcp) { 166 | hdr.tcp.checksum = tcp_checksum.update({ 167 | hdr.ipv4.src_addr, 168 | hdr.ipv4.dst_addr, 169 | hdr.tcp.src_port, 170 | hdr.tcp.dst_port, 171 | ig_md.checksum_tcp_tmp 172 | }); 173 | } 174 | 175 | pkt.emit(hdr); 176 | } 177 | } 178 | 179 | parser EgressParser(packet_in pkt, 180 | out egress_headers_t hdr, 181 | out egress_metadata_t eg_md, 182 | out egress_intrinsic_metadata_t eg_intr_md) 183 | { 184 | state start { 185 | pkt.extract(eg_intr_md); 186 | transition parse_metadata; 187 | } 188 | 189 | state parse_metadata { 190 | eg_md.is_logged_req = false; 191 | eg_md.is_acked_req = false; 192 | eg_md.is_first_time = 0; 193 | eg_md.tstamp = 0; 194 | 195 | egr_mirror_h mirror_md = pkt.lookahead(); 196 | transition select(mirror_md.pkt_type) { 197 | PKT_TYPE_EGR_MIRROR : parse_egr_mirror_md; // cloned from egress 198 | PKT_TYPE_NORMAL : parse_bridged_md; // from the ingress 199 | default : accept; 200 | } 201 | } 202 | 203 | state parse_egr_mirror_md { 204 | egr_mirror_h mirror_md; 205 | pkt.extract(mirror_md); 206 | eg_md.is_logged_req = true; 207 | eg_md.tstamp = mirror_md.tstamp; // store the logged timestamp 208 | eg_md.is_first_time = mirror_md.is_first_time; 209 | transition parse_ethernet; 210 | } 211 | 212 | state parse_bridged_md { 213 | pkt.extract(eg_md.bridged_md); 214 | transition parse_ethernet; 215 | } 216 | 217 | state parse_ethernet { 218 | pkt.extract (hdr.ethernet); 219 | transition select (hdr.ethernet.ether_type) { 220 | ETHERTYPE_IPV4: parse_ipv4; 221 | default: accept; 222 | } 223 | } 224 | 225 | state parse_ipv4 { 226 | ipv4_h tmp_ipv4 = pkt.lookahead(); 227 | transition select(tmp_ipv4.protocol) { 228 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 229 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 230 | default: reject; 231 | } 232 | } 233 | 234 | state parse_regular_or_redplane_ipv4 { 235 | transition select(pkt.lookahead>()[15:0]) { 236 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 237 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 238 | default: parse_regular_ipv4; 239 | } 240 | } 241 | 242 | state parse_redplane_ipv4_udp_ack { 243 | pkt.extract (hdr.redplane_ipv4); 244 | pkt.extract (hdr.redplane_udp); 245 | pkt.extract (hdr.redplane_ack); 246 | 247 | eg_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 248 | eg_md.flow_key.port = hdr.redplane_ack.flow_key.port; 249 | eg_md.cur_seq_num = hdr.redplane_ack.seq_num; 250 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 251 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 252 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 253 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 254 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 255 | default: reject; // reject all other invalid ack packets. 256 | } 257 | } 258 | 259 | state parse_lease_migrate_ack { 260 | pkt.extract(hdr.redplane_values); 261 | transition parse_regular_ipv4; 262 | } 263 | 264 | state parse_redplane_ipv4_udp_req { 265 | pkt.extract (hdr.redplane_ipv4); 266 | pkt.extract (hdr.redplane_udp); 267 | pkt.extract (hdr.redplane_req); 268 | 269 | eg_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 270 | eg_md.flow_key.port = hdr.redplane_req.flow_key.port; 271 | eg_md.cur_seq_num = hdr.redplane_req.seq_num; 272 | 273 | transition parse_regular_ipv4; 274 | } 275 | 276 | state parse_regular_ipv4 { 277 | pkt.extract (hdr.ipv4); 278 | transition accept; 279 | } 280 | } 281 | 282 | control EgressDeparser(packet_out pkt, 283 | inout egress_headers_t hdr, 284 | in egress_metadata_t eg_md, 285 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 286 | { 287 | Mirror() mirror; 288 | Checksum() redplane_ipv4_checksum; 289 | apply { 290 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 291 | hdr.redplane_ipv4.version, 292 | hdr.redplane_ipv4.ihl, 293 | hdr.redplane_ipv4.diffserv, 294 | hdr.redplane_ipv4.total_len, 295 | hdr.redplane_ipv4.identification, 296 | hdr.redplane_ipv4.flags, 297 | hdr.redplane_ipv4.frag_offset, 298 | hdr.redplane_ipv4.ttl, 299 | hdr.redplane_ipv4.protocol, 300 | hdr.redplane_ipv4.src_addr, 301 | hdr.redplane_ipv4.dst_addr 302 | }); 303 | 304 | if (eg_dprsr_md.mirror_type == MIRROR_TYPE_E2E) { 305 | mirror.emit(eg_md.egr_mir_ses, {eg_md.pkt_type, eg_md.tstamp, 0, eg_md.is_first_time}); 306 | } 307 | 308 | pkt.emit(hdr); 309 | 310 | } 311 | } 312 | 313 | #endif /* _PARSERS_ */ -------------------------------------------------------------------------------- /redplane-p4/firewall/replication.p4: -------------------------------------------------------------------------------- 1 | #ifndef _Replication_ 2 | #define _Replication_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control Replication ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | // Instead of mirroring, let's use replication. 15 | action set_multicast (MulticastGroupId_t mcast_grp) { 16 | ig_tm_md.mcast_grp_a = mcast_grp; 17 | hdr.bridged_md.pkt_type = PKT_TYPE_NORMAL; 18 | } 19 | 20 | // We do this for (1) Read-only packet (2) ACK packets 21 | table replication { 22 | key = { 23 | hdr.bridged_md.store_egress_port : exact; // egress port for state store 24 | } 25 | actions = { 26 | set_multicast; 27 | } 28 | } 29 | 30 | apply { 31 | replication.apply(); 32 | } 33 | } 34 | #endif /* _Replication_ */ -------------------------------------------------------------------------------- /redplane-p4/firewall/types.p4: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_ 2 | #define _TYPES_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<16> ether_type_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<8> ip_protocol_t; 8 | typedef bit<16> udp_port_t; 9 | 10 | typedef bit<3> mirror_type_t; 11 | typedef bit<8> pkt_type_t; 12 | 13 | enum bit<8> req_type_t { 14 | LEASE_NEW_REQ = 0x0, 15 | LEASE_RENEW_REQ = 0x1, 16 | LEASE_NEW_ACK = 0x3, 17 | LEASE_RENEW_ACK = 0x4, 18 | LEASE_MIGRATE_ACK = 0x5 19 | } 20 | 21 | enum bit<8> ack_type_t { 22 | LEASE_NEW_ACK = 0x0, 23 | LEASE_RENEW_ACK = 0x1, 24 | LEASE_MIGRATE_ACK = 0x2 25 | } 26 | 27 | // NAT 28 | // COMPILER: this structure should be generated by redplane compiler or given as a user-input. 29 | struct flow_key_t { 30 | ipv4_addr_t ip_addr; 31 | bit<16> port; 32 | } 33 | 34 | struct flow_value_t { 35 | ipv4_addr_t ip_addr; 36 | bit<16> port; 37 | } 38 | 39 | struct nat_meta_t { 40 | bool is_ext; 41 | } 42 | 43 | #endif /* _TYPES_ */ -------------------------------------------------------------------------------- /redplane-p4/load_balancing/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | #include "types.p4" 5 | 6 | const PortId_t CPU_PORT = 320; 7 | const PortId_t DEFAULT_STORE_PORT = 8; 8 | //const PortId_t CPU_PORT = 64; 9 | //const PortId_t DEFAULT_STORE_PORT = 1; 10 | 11 | const ether_type_t ETHERTYPE_IPV4 = 0x0800; 12 | const ether_type_t ETHERTYPE_TO_CPU = 0xBF01; 13 | 14 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 15 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 16 | 17 | const mirror_type_t MIRROR_TYPE_E2E = 2; 18 | 19 | const bit<48> LEASE_PERIOD = 100000000000; // 5 secs 20 | const bit<48> TIMEOUT = 1000000; // 1 msec 21 | const bit<16> MAX_SEQ_NUM = 65533; 22 | const bit<16> SWITCH_UDP_PORT = 4000; 23 | const bit<16> STORE_UDP_PORT = 8000; 24 | 25 | const pkt_type_t PKT_TYPE_NORMAL = 0; // Normal packets (just coming in); 26 | const pkt_type_t PKT_TYPE_EGR_MIRROR = 1; // Transaction for logging 27 | 28 | header ethernet_h { 29 | mac_addr_t dst_addr; 30 | mac_addr_t src_addr; 31 | bit<16> ether_type; 32 | } 33 | 34 | header ipv4_h { 35 | bit<4> version; 36 | bit<4> ihl; 37 | bit<8> diffserv; 38 | bit<16> total_len; 39 | bit<16> identification; 40 | bit<3> flags; 41 | bit<13> frag_offset; 42 | bit<8> ttl; 43 | bit<8> protocol; 44 | bit<16> hdr_checksum; 45 | ipv4_addr_t src_addr; 46 | ipv4_addr_t dst_addr; 47 | } 48 | 49 | header tcp_h { 50 | bit<16> src_port; 51 | bit<16> dst_port; 52 | bit<32> seq_no; 53 | bit<32> ack_no; 54 | bit<4> data_offset; 55 | bit<4> res; 56 | bit<1> cwr; 57 | bit<1> ece; 58 | bit<1> urg; 59 | bit<1> ack; 60 | bit<1> psh; 61 | bit<1> rst; 62 | bit<1> syn; 63 | bit<1> fin; 64 | bit<16> window; 65 | bit<16> checksum; 66 | bit<16> urgent_ptr; 67 | } 68 | 69 | header udp_h { 70 | bit<16> src_port; 71 | bit<16> dst_port; 72 | bit<16> hdr_length; 73 | bit<16> checksum; 74 | } 75 | 76 | header tstamp_h{ 77 | bit<48> in_time; 78 | bit<48> out_time; 79 | } 80 | 81 | header redplane_req_h { 82 | req_type_t req_type; //1 83 | bit<16> seq_num; // 2 84 | flow_key_t flow_key; //6 85 | flow_value_t values; //6 86 | } 87 | 88 | const bit<16> REDPLANE_REQ_IP_LEN = 20 + 8 + 15; 89 | const bit<16> REDPLANE_REQ_UDP_LEN = 8 + 15; 90 | 91 | header redplane_ack_h { 92 | ack_type_t ack_type; // 1 93 | bit<16> seq_num; // 2 94 | flow_key_t flow_key; // 6 95 | } 96 | const bit<16> REDPLANE_ACK_IP_LEN = 20 + 8 + 9; 97 | 98 | header redplane_flow_value_h { 99 | flow_value_t values; 100 | } 101 | 102 | header egr_mirror_h { 103 | pkt_type_t pkt_type; 104 | bit<48> tstamp; 105 | @padding 106 | bit<7> pad; 107 | bit<1> is_first_time; 108 | } 109 | 110 | header bridged_md_h { 111 | pkt_type_t pkt_type; //8 112 | PortId_t store_egress_port; //9 113 | PortId_t original_port; //9 114 | bit<1> is_write; 115 | @padding 116 | bit<5> pad; 117 | } 118 | struct ingress_headers_t { 119 | bridged_md_h bridged_md; 120 | ethernet_h cpu_ethernet; 121 | ethernet_h ethernet; 122 | ipv4_h redplane_ipv4; 123 | udp_h redplane_udp; 124 | redplane_req_h redplane_req; 125 | redplane_ack_h redplane_ack; 126 | redplane_flow_value_h redplane_values; 127 | ipv4_h ipv4; 128 | tcp_h tcp; 129 | udp_h udp; 130 | tstamp_h tstamp; 131 | } 132 | 133 | struct egress_headers_t { 134 | ethernet_h ethernet; 135 | ipv4_h redplane_ipv4; 136 | udp_h redplane_udp; 137 | redplane_req_h redplane_req; 138 | redplane_ack_h redplane_ack; 139 | redplane_flow_value_h redplane_values; 140 | ipv4_h ipv4; 141 | tcp_h tcp; 142 | udp_h udp; 143 | } 144 | 145 | struct ingress_metadata_t { 146 | bit<2> hashed_key; 147 | bool is_renew_req; 148 | bool lease_expired; 149 | nat_meta_t nat_meta; 150 | // checksum stuff 151 | bool ipv4_checksum_err; 152 | bool checksum_update_ipv4; 153 | bool checksum_update_redplane_ipv4; 154 | bool checksum_update_tcp; 155 | bit<16> checksum_tcp_tmp; 156 | flow_key_t flow_key; 157 | bit<32> new_lease_expire_time; 158 | bit<32> current_time; 159 | } 160 | 161 | struct egress_metadata_t { 162 | bridged_md_h bridged_md; 163 | bit<48> tstamp; 164 | bit<16> time_diff_hi; 165 | bit<16> time_diff_lo; 166 | MirrorId_t egr_mir_ses; 167 | pkt_type_t pkt_type; 168 | bool is_acked_req; 169 | bool is_logged_req; 170 | bit<16> seq_same; 171 | bit<16> last_sent; 172 | bit<16> last_acked; 173 | bit<16> seq_diff; 174 | bit<16> seq_diff1; 175 | bit<16> seq_diff2; 176 | bit<16> cur_seq_num; 177 | bit<1> is_first_time; 178 | // checksum stuff 179 | bool checksum_err_ipv4; 180 | flow_key_t flow_key; 181 | } 182 | 183 | #endif /* _HEADERS_ */ 184 | -------------------------------------------------------------------------------- /redplane-p4/load_balancing/l3_routing.p4: -------------------------------------------------------------------------------- 1 | #ifndef _L3_ROUTING_ 2 | #define _L3_ROUTING_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control L3Routing ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | action set_nhop(bit<9> port){ 15 | ig_tm_md.ucast_egress_port = port; 16 | } 17 | 18 | table ipv4_lpm { 19 | key = {hdr.ipv4.dst_addr : lpm;} 20 | actions = { set_nhop; } 21 | } 22 | 23 | apply { 24 | ipv4_lpm.apply(); 25 | } 26 | } 27 | #endif /* _L3_ROUTING_ */ -------------------------------------------------------------------------------- /redplane-p4/load_balancing/lb_redplane.p4: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if __TARGET_TOFINO__ == 2 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "types.p4" 10 | #include "headers.p4" 11 | #include "parsers.p4" 12 | #include "l3_routing.p4" 13 | #include "replication.p4" 14 | #include "redplane_core.p4" 15 | #include "load_balance.p4" // LB P4 we want to make fault-tolerant 16 | 17 | control Ingress( 18 | inout ingress_headers_t hdr, 19 | inout ingress_metadata_t ig_md, 20 | in ingress_intrinsic_metadata_t ig_intr_md, 21 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 22 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 23 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 24 | // COMPILER: This line should be added by Redplane compiler. 25 | RedplaneIngress() redplane_ig; 26 | Lb_Ingress() Lb_Ingress; // Instantiate the original application 27 | L3Routing() L3_routing; 28 | Replication() replication; 29 | 30 | apply { 31 | //if (hdr.redplane_ack.isValid() == false && hdr.redplane_req.isValid() == false) { 32 | //if (hdr.redplane_req.isValid() == false) { 33 | //} 34 | //if (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_NEW_ACK) { 35 | // hdr.tstamp.in_time = ig_intr_md.ingress_mac_tstamp; 36 | //} 37 | // COMPILER: This line should be added by Redplane compiler. 38 | redplane_ig.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 39 | 40 | // COMPILER: This line should be added by Redplane compiler. 41 | // If the packet is an Redplane ACK from the state store, the app must not process it. 42 | if (ig_md.is_renew_req == true) { 43 | // App's ingress logic. 44 | // hdr.tstamp.out_time = ig_intr_md.ingress_mac_tstamp; 45 | Lb_Ingress.apply(hdr, ig_md, ig_intr_md, ig_prsr_md, ig_dprsr_md, ig_tm_md); 46 | } 47 | 48 | if ((ig_md.is_renew_req == true || (hdr.redplane_ack.isValid() == true && hdr.ipv4.isValid() == true)) && ig_tm_md.ucast_egress_port != CPU_PORT) { 49 | L3_routing.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 50 | } 51 | 52 | if ((hdr.bridged_md.is_write == 0 && hdr.redplane_req.isValid() == true && hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) || // If it's a read renew request, 53 | (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_RENEW_ACK && hdr.ipv4.isValid() == true)) // if it's an ack with a piggybacked original packet 54 | { 55 | //then replicate it! 56 | replication.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 57 | } 58 | } 59 | } 60 | 61 | control Egress( 62 | inout egress_headers_t hdr, 63 | inout egress_metadata_t eg_md, 64 | in egress_intrinsic_metadata_t eg_intr_md, 65 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 66 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 67 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 68 | 69 | // COMPILER: This line should be added by Redplane compiler. 70 | RedplaneEgress() redplane_eg; 71 | 72 | action invalidate_redplane_hdr() { 73 | hdr.redplane_ipv4.setInvalid(); 74 | hdr.redplane_udp.setInvalid(); 75 | hdr.redplane_req.setInvalid(); 76 | hdr.redplane_ack.setInvalid(); 77 | hdr.redplane_values.setInvalid(); 78 | } 79 | apply { 80 | // Redplane packet destined to the state store OR Write packet is processed 81 | if (eg_intr_md.egress_rid_first == 1 // replicated packet (RENEW ACK or RENEW REQ) 82 | || eg_md.bridged_md.is_write == 1 // RENEW REQ with write 83 | || (hdr.redplane_ack.isValid() && hdr.ipv4.isValid() ==false) // RENEW ACK without payload 84 | || eg_md.is_logged_req == true) 85 | { 86 | if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 87 | redplane_eg.apply(hdr, eg_md, eg_intr_md, eg_prsr_md, eg_dprsr_md); 88 | } 89 | } else if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 90 | invalidate_redplane_hdr(); 91 | } 92 | } 93 | } 94 | 95 | Pipeline( 96 | IngressParser(), 97 | Ingress(), 98 | IngressDeparser(), 99 | EgressParser(), 100 | Egress(), 101 | EgressDeparser() 102 | ) pipe; 103 | 104 | Switch(pipe) main; 105 | -------------------------------------------------------------------------------- /redplane-p4/load_balancing/load_balance.p4: -------------------------------------------------------------------------------- 1 | #ifndef _LOAD_BALANCE_ 2 | #define _LOAD_BALANCE_ 3 | 4 | #include "headers.p4" 5 | 6 | /***************** M A T C H - A C T I O N *********************/ 7 | control Lb_Ingress( 8 | /* User */ 9 | inout ingress_headers_t hdr, 10 | inout ingress_metadata_t ig_md, 11 | /* Intrinsic */ 12 | in ingress_intrinsic_metadata_t ig_intr_md, 13 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 14 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 15 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 16 | { 17 | action drop() { 18 | ig_dprsr_md.drop_ctl = 1; 19 | } 20 | action lb_hit_int_to_ext(bit<32> front_addr) { 21 | hdr.ipv4.src_addr = front_addr; 22 | ig_md.checksum_update_ipv4 = true; 23 | ig_md.checksum_update_tcp = true; 24 | } 25 | table lb_int_to_ext { 26 | key = { 27 | hdr.ipv4.src_addr: exact; 28 | hdr.ipv4.dst_addr: exact; 29 | hdr.tcp.src_port: exact; 30 | hdr.tcp.dst_port: exact; 31 | } 32 | actions = {drop; lb_hit_int_to_ext; } 33 | default_action = drop(); 34 | } 35 | 36 | action lb_hit_ext_to_int(bit<32> back_addr) { 37 | hdr.ipv4.dst_addr = back_addr; 38 | ig_md.checksum_update_ipv4 = true; 39 | ig_md.checksum_update_tcp = true; 40 | } 41 | table lb_ext_to_int { 42 | key = { 43 | hdr.ipv4.src_addr: exact; 44 | hdr.ipv4.dst_addr: exact; 45 | hdr.tcp.src_port: exact; 46 | hdr.tcp.dst_port: exact; 47 | } 48 | actions = { drop; lb_hit_ext_to_int; } 49 | default_action = drop(); 50 | } 51 | 52 | apply { 53 | //if(hdr.ipv4.isValid() && !ig_md.ipv4_checksum_err) { 54 | if(hdr.ipv4.isValid()) { 55 | //if(if_info.apply().hit) 56 | { // check whether the pkt comes from internal or external 57 | if(ig_md.nat_meta.is_ext == false){ // from internal 58 | lb_int_to_ext.apply(); 59 | } else { // from external 60 | lb_ext_to_int.apply(); 61 | } 62 | } 63 | } 64 | } 65 | } 66 | 67 | #endif /* _LOAD_BALANCE_ */ -------------------------------------------------------------------------------- /redplane-p4/load_balancing/replication.p4: -------------------------------------------------------------------------------- 1 | #ifndef _Replication_ 2 | #define _Replication_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control Replication ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | // Instead of mirroring, let's use replication. 15 | action set_multicast (MulticastGroupId_t mcast_grp) { 16 | ig_tm_md.mcast_grp_a = mcast_grp; 17 | hdr.bridged_md.pkt_type = PKT_TYPE_NORMAL; 18 | } 19 | 20 | // We do this for (1) Read-only packet (2) ACK packets 21 | table replication { 22 | key = { 23 | hdr.bridged_md.store_egress_port : exact; // egress port for state store 24 | } 25 | actions = { 26 | set_multicast; 27 | } 28 | } 29 | 30 | apply { 31 | replication.apply(); 32 | } 33 | } 34 | #endif /* _Replication_ */ -------------------------------------------------------------------------------- /redplane-p4/load_balancing/types.p4: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_ 2 | #define _TYPES_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<16> ether_type_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<8> ip_protocol_t; 8 | typedef bit<16> udp_port_t; 9 | 10 | typedef bit<3> mirror_type_t; 11 | typedef bit<8> pkt_type_t; 12 | 13 | enum bit<8> req_type_t { 14 | LEASE_NEW_REQ = 0x0, 15 | LEASE_RENEW_REQ = 0x1, 16 | LEASE_NEW_ACK = 0x3, 17 | LEASE_RENEW_ACK = 0x4, 18 | LEASE_MIGRATE_ACK = 0x5 19 | } 20 | 21 | enum bit<8> ack_type_t { 22 | LEASE_NEW_ACK = 0x0, 23 | LEASE_RENEW_ACK = 0x1, 24 | LEASE_MIGRATE_ACK = 0x2 25 | } 26 | 27 | // NAT 28 | // COMPILER: this structure should be generated by redplane compiler or given as a user-input. 29 | struct flow_key_t { 30 | ipv4_addr_t ip_addr; 31 | bit<16> port; 32 | } 33 | 34 | struct flow_value_t { 35 | ipv4_addr_t ip_addr; 36 | bit<16> port; 37 | } 38 | 39 | struct nat_meta_t { 40 | bool is_ext; 41 | } 42 | 43 | #endif /* _TYPES_ */ -------------------------------------------------------------------------------- /redplane-p4/nat/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | #include "types.p4" 5 | 6 | const PortId_t CPU_PORT = 320; 7 | const PortId_t DEFAULT_STORE_PORT = 8; 8 | //const PortId_t CPU_PORT = 64; 9 | //const PortId_t DEFAULT_STORE_PORT = 1; 10 | 11 | const ether_type_t ETHERTYPE_IPV4 = 0x0800; 12 | const ether_type_t ETHERTYPE_TO_CPU = 0xBF01; 13 | 14 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 15 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 16 | 17 | const mirror_type_t MIRROR_TYPE_E2E = 2; 18 | 19 | const bit<48> LEASE_PERIOD = 100000000000; // 5 secs 20 | const bit<48> TIMEOUT = 1000000; // 1 msec 21 | const bit<16> MAX_SEQ_NUM = 65533; 22 | const bit<16> SWITCH_UDP_PORT = 4000; 23 | const bit<16> STORE_UDP_PORT = 8000; 24 | 25 | const pkt_type_t PKT_TYPE_NORMAL = 0; // Normal packets (just coming in); 26 | const pkt_type_t PKT_TYPE_EGR_MIRROR = 1; // Transaction for logging 27 | 28 | header ethernet_h { 29 | mac_addr_t dst_addr; 30 | mac_addr_t src_addr; 31 | bit<16> ether_type; 32 | } 33 | 34 | header ipv4_h { 35 | bit<4> version; 36 | bit<4> ihl; 37 | bit<8> diffserv; 38 | bit<16> total_len; 39 | bit<16> identification; 40 | bit<3> flags; 41 | bit<13> frag_offset; 42 | bit<8> ttl; 43 | bit<8> protocol; 44 | bit<16> hdr_checksum; 45 | ipv4_addr_t src_addr; 46 | ipv4_addr_t dst_addr; 47 | } 48 | 49 | header tcp_h { 50 | bit<16> src_port; 51 | bit<16> dst_port; 52 | bit<32> seq_no; 53 | bit<32> ack_no; 54 | bit<4> data_offset; 55 | bit<4> res; 56 | bit<1> cwr; 57 | bit<1> ece; 58 | bit<1> urg; 59 | bit<1> ack; 60 | bit<1> psh; 61 | bit<1> rst; 62 | bit<1> syn; 63 | bit<1> fin; 64 | bit<16> window; 65 | bit<16> checksum; 66 | bit<16> urgent_ptr; 67 | } 68 | 69 | header udp_h { 70 | bit<16> src_port; 71 | bit<16> dst_port; 72 | bit<16> hdr_length; 73 | bit<16> checksum; 74 | } 75 | 76 | header tstamp_h{ 77 | bit<48> in_time; 78 | bit<48> out_time; 79 | } 80 | 81 | header redplane_req_h { 82 | req_type_t req_type; //1 83 | bit<16> seq_num; // 2 84 | flow_key_t flow_key; //6 85 | flow_value_t values; //6 86 | } 87 | 88 | const bit<16> REDPLANE_REQ_IP_LEN = 20 + 8 + 15; 89 | const bit<16> REDPLANE_REQ_UDP_LEN = 8 + 15; 90 | 91 | header redplane_ack_h { 92 | ack_type_t ack_type; // 1 93 | bit<16> seq_num; // 2 94 | flow_key_t flow_key; // 6 95 | } 96 | const bit<16> REDPLANE_ACK_IP_LEN = 20 + 8 + 9; 97 | 98 | header redplane_flow_value_h { 99 | flow_value_t values; 100 | } 101 | 102 | header egr_mirror_h { 103 | pkt_type_t pkt_type; 104 | bit<48> tstamp; 105 | @padding 106 | bit<7> pad; 107 | bit<1> is_first_time; 108 | } 109 | 110 | header bridged_md_h { 111 | pkt_type_t pkt_type; //8 112 | PortId_t store_egress_port; //9 113 | PortId_t original_port; //9 114 | bit<1> is_write; 115 | @padding 116 | bit<5> pad; 117 | } 118 | struct ingress_headers_t { 119 | bridged_md_h bridged_md; 120 | ethernet_h cpu_ethernet; 121 | ethernet_h ethernet; 122 | ipv4_h redplane_ipv4; 123 | udp_h redplane_udp; 124 | redplane_req_h redplane_req; 125 | redplane_ack_h redplane_ack; 126 | redplane_flow_value_h redplane_values; 127 | ipv4_h ipv4; 128 | tcp_h tcp; 129 | udp_h udp; 130 | tstamp_h tstamp; 131 | } 132 | 133 | struct egress_headers_t { 134 | ethernet_h ethernet; 135 | ipv4_h redplane_ipv4; 136 | udp_h redplane_udp; 137 | redplane_req_h redplane_req; 138 | redplane_ack_h redplane_ack; 139 | redplane_flow_value_h redplane_values; 140 | ipv4_h ipv4; 141 | tcp_h tcp; 142 | udp_h udp; 143 | } 144 | 145 | struct ingress_metadata_t { 146 | bit<2> hashed_key; 147 | bool is_renew_req; 148 | bool lease_expired; 149 | nat_meta_t nat_meta; 150 | // checksum stuff 151 | bool ipv4_checksum_err; 152 | bool checksum_update_ipv4; 153 | bool checksum_update_redplane_ipv4; 154 | bool checksum_update_tcp; 155 | bit<16> checksum_tcp_tmp; 156 | flow_key_t flow_key; 157 | bit<32> new_lease_expire_time; 158 | bit<32> current_time; 159 | } 160 | 161 | struct egress_metadata_t { 162 | bridged_md_h bridged_md; 163 | bit<48> tstamp; 164 | bit<16> time_diff_hi; 165 | bit<16> time_diff_lo; 166 | MirrorId_t egr_mir_ses; 167 | pkt_type_t pkt_type; 168 | bool is_acked_req; 169 | bool is_logged_req; 170 | bit<16> seq_same; 171 | bit<16> last_sent; 172 | bit<16> last_acked; 173 | bit<16> seq_diff; 174 | bit<16> seq_diff1; 175 | bit<16> seq_diff2; 176 | bit<16> cur_seq_num; 177 | bit<1> is_first_time; 178 | // checksum stuff 179 | bool checksum_err_ipv4; 180 | flow_key_t flow_key; 181 | } 182 | 183 | #endif /* _HEADERS_ */ 184 | -------------------------------------------------------------------------------- /redplane-p4/nat/l3_routing.p4: -------------------------------------------------------------------------------- 1 | #ifndef _L3_ROUTING_ 2 | #define _L3_ROUTING_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control L3Routing ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | action set_nhop(bit<9> port){ 15 | ig_tm_md.ucast_egress_port = port; 16 | } 17 | 18 | table ipv4_lpm { 19 | key = {hdr.ipv4.dst_addr : lpm;} 20 | actions = { set_nhop; } 21 | } 22 | 23 | apply { 24 | ipv4_lpm.apply(); 25 | } 26 | } 27 | #endif /* _L3_ROUTING_ */ -------------------------------------------------------------------------------- /redplane-p4/nat/nat.p4: -------------------------------------------------------------------------------- 1 | #ifndef _NAT_ 2 | #define _NAT_ 3 | 4 | #include "headers.p4" 5 | 6 | /***************** M A T C H - A C T I O N *********************/ 7 | control Nat_Ingress( 8 | /* User */ 9 | inout ingress_headers_t hdr, 10 | inout ingress_metadata_t ig_md, 11 | /* Intrinsic */ 12 | in ingress_intrinsic_metadata_t ig_intr_md, 13 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 14 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 15 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 16 | { 17 | action drop() { 18 | ig_dprsr_md.drop_ctl = 1; 19 | } 20 | /***************************** NAT control *****************************************/ 21 | action nat_hit_int_to_ext(bit<32> src_addr, bit<16> src_port) { 22 | hdr.ipv4.src_addr= src_addr; 23 | hdr.tcp.src_port = src_port; 24 | 25 | /******************* For RTT measurement **************/ 26 | //hdr.ipv4.dst_addr= src_addr; 27 | //hdr.tcp.dst_port = src_port; 28 | ///////////////////////////////////////////////////////// 29 | 30 | ig_md.checksum_update_ipv4 = true; 31 | ig_md.checksum_update_tcp = true; 32 | } 33 | table nat_int_to_ext { 34 | key = { 35 | hdr.ipv4.src_addr: exact; 36 | hdr.tcp.src_port: exact; 37 | } 38 | actions = {nat_hit_int_to_ext; } 39 | //default_action = natTcp_learn(); 40 | } 41 | 42 | action nat_hit_ext_to_int(bit<32> dst_addr, bit<16> dst_port) { 43 | hdr.ipv4.dst_addr = dst_addr; 44 | hdr.tcp.dst_port = dst_port; 45 | 46 | ig_md.checksum_update_ipv4 = true; 47 | ig_md.checksum_update_tcp = true; 48 | } 49 | table nat_ext_to_int { 50 | key = { 51 | hdr.ipv4.dst_addr: exact; 52 | hdr.tcp.dst_port: exact; 53 | } 54 | actions = { drop; nat_hit_ext_to_int; } 55 | default_action = drop(); 56 | } 57 | 58 | apply { 59 | if(hdr.ipv4.isValid()) 60 | { // check whether the pkt comes from internal or external 61 | if(ig_md.nat_meta.is_ext == false){ // from internal 62 | nat_int_to_ext.apply(); 63 | } else { // from external 64 | nat_ext_to_int.apply(); 65 | } 66 | } 67 | } 68 | } 69 | 70 | #endif /* _NAT_ */ -------------------------------------------------------------------------------- /redplane-p4/nat/nat_redplane.p4: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if __TARGET_TOFINO__ == 2 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "types.p4" 10 | #include "headers.p4" 11 | #include "parsers.p4" 12 | #include "l3_routing.p4" 13 | #include "replication.p4" 14 | #include "redplane_core.p4" 15 | #include "nat.p4" // NAT P4 we want to make fault-tolerant 16 | 17 | control Ingress( 18 | inout ingress_headers_t hdr, 19 | inout ingress_metadata_t ig_md, 20 | in ingress_intrinsic_metadata_t ig_intr_md, 21 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 22 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 23 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 24 | // COMPILER: This line should be added by Redplane compiler. 25 | RedplaneIngress() redplane_ig; 26 | Nat_Ingress() Nat_Ingress; // Instantiate the original application 27 | L3Routing() L3_routing; 28 | Replication() replication; 29 | 30 | apply { 31 | //if (hdr.redplane_ack.isValid() == false && hdr.redplane_req.isValid() == false) { 32 | //if (hdr.redplane_req.isValid() == false) { 33 | //} 34 | //if (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_NEW_ACK) { 35 | // hdr.tstamp.in_time = ig_intr_md.ingress_mac_tstamp; 36 | //} 37 | // COMPILER: This line should be added by Redplane compiler. 38 | redplane_ig.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 39 | 40 | // COMPILER: This line should be added by Redplane compiler. 41 | // If the packet is an Redplane ACK from the state store, the app must not process it. 42 | if (ig_md.is_renew_req == true) { 43 | // App's ingress logic. 44 | // hdr.tstamp.out_time = ig_intr_md.ingress_mac_tstamp; 45 | Nat_Ingress.apply(hdr, ig_md, ig_intr_md, ig_prsr_md, ig_dprsr_md, ig_tm_md); 46 | } 47 | 48 | if ((ig_md.is_renew_req == true || (hdr.redplane_ack.isValid() == true && hdr.ipv4.isValid() == true)) && ig_tm_md.ucast_egress_port != CPU_PORT) { 49 | L3_routing.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 50 | } 51 | 52 | if ((hdr.bridged_md.is_write == 0 && hdr.redplane_req.isValid() == true && hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) || // If it's a read renew request, 53 | (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_RENEW_ACK && hdr.ipv4.isValid() == true)) // if it's an ack with a piggybacked original packet 54 | { 55 | //then replicate it! 56 | replication.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 57 | } 58 | } 59 | } 60 | 61 | control Egress( 62 | inout egress_headers_t hdr, 63 | inout egress_metadata_t eg_md, 64 | in egress_intrinsic_metadata_t eg_intr_md, 65 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 66 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 67 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 68 | 69 | // COMPILER: This line should be added by Redplane compiler. 70 | RedplaneEgress() redplane_eg; 71 | 72 | action invalidate_redplane_hdr() { 73 | hdr.redplane_ipv4.setInvalid(); 74 | hdr.redplane_udp.setInvalid(); 75 | hdr.redplane_req.setInvalid(); 76 | hdr.redplane_ack.setInvalid(); 77 | hdr.redplane_values.setInvalid(); 78 | } 79 | apply { 80 | // Redplane packet destined to the state store OR Write packet is processed 81 | if (eg_intr_md.egress_rid_first == 1 // replicated packet (RENEW ACK or RENEW REQ) 82 | || eg_md.bridged_md.is_write == 1 // RENEW REQ with write 83 | || (hdr.redplane_ack.isValid() && hdr.ipv4.isValid() ==false) // RENEW ACK without payload 84 | || eg_md.is_logged_req == true) 85 | { 86 | if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 87 | redplane_eg.apply(hdr, eg_md, eg_intr_md, eg_prsr_md, eg_dprsr_md); 88 | } 89 | } else if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 90 | invalidate_redplane_hdr(); 91 | } 92 | } 93 | } 94 | 95 | Pipeline( 96 | IngressParser(), 97 | Ingress(), 98 | IngressDeparser(), 99 | EgressParser(), 100 | Egress(), 101 | EgressDeparser() 102 | ) pipe; 103 | 104 | Switch(pipe) main; 105 | -------------------------------------------------------------------------------- /redplane-p4/nat/parsers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _PARSERS_ 2 | #define _PARSERS_ 3 | 4 | parser IngressParser(packet_in pkt, 5 | out ingress_headers_t hdr, 6 | out ingress_metadata_t ig_md, 7 | out ingress_intrinsic_metadata_t ig_intr_md) 8 | { 9 | Checksum() ipv4_checksum; 10 | Checksum() tcp_checksum; 11 | state start { 12 | pkt.extract(ig_intr_md); 13 | pkt.advance(PORT_METADATA_SIZE); 14 | transition meta_init; 15 | } 16 | 17 | state meta_init { 18 | //Initialize ingress metadata 19 | ig_md.checksum_update_redplane_ipv4 = false; 20 | ig_md.ipv4_checksum_err = false; 21 | ig_md.is_renew_req = false; 22 | ig_md.lease_expired = true; 23 | transition parse_ethernet; 24 | } 25 | 26 | state parse_ethernet { 27 | pkt.extract (hdr.ethernet); 28 | transition select (hdr.ethernet.ether_type) { 29 | ETHERTYPE_IPV4: parse_ipv4; 30 | default: accept; 31 | } 32 | } 33 | 34 | state parse_ipv4 { 35 | ipv4_h tmp_ipv4 = pkt.lookahead(); 36 | transition select(tmp_ipv4.protocol) { 37 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 38 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 39 | default: reject; 40 | } 41 | } 42 | 43 | state parse_regular_or_redplane_ipv4 { 44 | transition select(pkt.lookahead>()[15:0]) { 45 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 46 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 47 | default: parse_regular_ipv4; 48 | } 49 | } 50 | 51 | state parse_redplane_ipv4_udp_ack { 52 | pkt.extract (hdr.redplane_ipv4); 53 | pkt.extract (hdr.redplane_udp); 54 | pkt.extract (hdr.redplane_ack); 55 | 56 | ig_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 57 | ig_md.flow_key.port = hdr.redplane_ack.flow_key.port; 58 | 59 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 60 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 61 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 62 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 63 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 64 | default: reject; // reject all other invalid ack packets. 65 | } 66 | } 67 | 68 | state parse_lease_migrate_ack { 69 | pkt.extract(hdr.redplane_values); 70 | transition parse_regular_ipv4; 71 | } 72 | 73 | state parse_redplane_ipv4_udp_req { 74 | pkt.extract (hdr.redplane_ipv4); 75 | pkt.extract (hdr.redplane_udp); 76 | pkt.extract (hdr.redplane_req); 77 | 78 | ig_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 79 | ig_md.flow_key.port = hdr.redplane_req.flow_key.port; 80 | 81 | transition parse_regular_ipv4; 82 | } 83 | 84 | state parse_regular_ipv4 { 85 | pkt.extract (hdr.ipv4); 86 | ipv4_checksum.add(hdr.ipv4); 87 | ig_md.ipv4_checksum_err = ipv4_checksum.verify(); 88 | 89 | tcp_checksum.subtract({hdr.ipv4.src_addr}); 90 | tcp_checksum.subtract({hdr.ipv4.dst_addr}); 91 | 92 | transition select (hdr.ipv4.protocol) { 93 | IP_PROTOCOLS_TCP: parse_tcp; 94 | IP_PROTOCOLS_UDP: parse_udp; 95 | default: reject; 96 | } 97 | } 98 | 99 | state parse_tcp { 100 | pkt.extract(hdr.tcp); 101 | // The tcp checksum cannot be verified, since we cannot compute 102 | // the payload's checksum. 103 | tcp_checksum.subtract({hdr.tcp.checksum}); 104 | tcp_checksum.subtract({hdr.tcp.src_port}); 105 | tcp_checksum.subtract({hdr.tcp.dst_port}); 106 | ig_md.checksum_tcp_tmp = tcp_checksum.get(); 107 | 108 | transition accept; 109 | } 110 | 111 | state parse_tstamp { 112 | pkt.extract(hdr.tstamp); 113 | transition accept; 114 | } 115 | 116 | state parse_udp { 117 | pkt.extract(hdr.udp); 118 | transition accept; 119 | } 120 | } 121 | 122 | control IngressDeparser(packet_out pkt, 123 | inout ingress_headers_t hdr, 124 | in ingress_metadata_t ig_md, 125 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) 126 | { 127 | Checksum() ipv4_checksum; 128 | Checksum() tcp_checksum; 129 | Checksum() redplane_ipv4_checksum; 130 | Mirror() mirror; 131 | 132 | apply { 133 | if (ig_md.checksum_update_redplane_ipv4) { 134 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 135 | hdr.redplane_ipv4.version, 136 | hdr.redplane_ipv4.ihl, 137 | hdr.redplane_ipv4.diffserv, 138 | hdr.redplane_ipv4.total_len, 139 | hdr.redplane_ipv4.identification, 140 | hdr.redplane_ipv4.flags, 141 | hdr.redplane_ipv4.frag_offset, 142 | hdr.redplane_ipv4.ttl, 143 | hdr.redplane_ipv4.protocol, 144 | hdr.redplane_ipv4.src_addr, 145 | hdr.redplane_ipv4.dst_addr 146 | }); 147 | } 148 | 149 | if (ig_md.checksum_update_ipv4) { 150 | hdr.ipv4.hdr_checksum = ipv4_checksum.update({ 151 | hdr.ipv4.version, 152 | hdr.ipv4.ihl, 153 | hdr.ipv4.diffserv, 154 | hdr.ipv4.total_len, 155 | hdr.ipv4.identification, 156 | hdr.ipv4.flags, 157 | hdr.ipv4.frag_offset, 158 | hdr.ipv4.ttl, 159 | hdr.ipv4.protocol, 160 | hdr.ipv4.src_addr, 161 | hdr.ipv4.dst_addr 162 | }); 163 | } 164 | 165 | if (ig_md.checksum_update_tcp) { 166 | hdr.tcp.checksum = tcp_checksum.update({ 167 | hdr.ipv4.src_addr, 168 | hdr.ipv4.dst_addr, 169 | hdr.tcp.src_port, 170 | hdr.tcp.dst_port, 171 | ig_md.checksum_tcp_tmp 172 | }); 173 | } 174 | 175 | pkt.emit(hdr); 176 | } 177 | } 178 | 179 | parser EgressParser(packet_in pkt, 180 | out egress_headers_t hdr, 181 | out egress_metadata_t eg_md, 182 | out egress_intrinsic_metadata_t eg_intr_md) 183 | { 184 | state start { 185 | pkt.extract(eg_intr_md); 186 | transition parse_metadata; 187 | } 188 | 189 | state parse_metadata { 190 | eg_md.is_logged_req = false; 191 | eg_md.is_acked_req = false; 192 | eg_md.is_first_time = 0; 193 | eg_md.tstamp = 0; 194 | 195 | egr_mirror_h mirror_md = pkt.lookahead(); 196 | transition select(mirror_md.pkt_type) { 197 | PKT_TYPE_EGR_MIRROR : parse_egr_mirror_md; // cloned from egress 198 | PKT_TYPE_NORMAL : parse_bridged_md; // from the ingress 199 | default : accept; 200 | } 201 | } 202 | 203 | state parse_egr_mirror_md { 204 | egr_mirror_h mirror_md; 205 | pkt.extract(mirror_md); 206 | eg_md.is_logged_req = true; 207 | eg_md.tstamp = mirror_md.tstamp; // store the logged timestamp 208 | eg_md.is_first_time = mirror_md.is_first_time; 209 | transition parse_ethernet; 210 | } 211 | 212 | state parse_bridged_md { 213 | pkt.extract(eg_md.bridged_md); 214 | transition parse_ethernet; 215 | } 216 | 217 | state parse_ethernet { 218 | pkt.extract (hdr.ethernet); 219 | transition select (hdr.ethernet.ether_type) { 220 | ETHERTYPE_IPV4: parse_ipv4; 221 | default: accept; 222 | } 223 | } 224 | 225 | state parse_ipv4 { 226 | ipv4_h tmp_ipv4 = pkt.lookahead(); 227 | transition select(tmp_ipv4.protocol) { 228 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 229 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 230 | default: reject; 231 | } 232 | } 233 | 234 | state parse_regular_or_redplane_ipv4 { 235 | transition select(pkt.lookahead>()[15:0]) { 236 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 237 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 238 | default: parse_regular_ipv4; 239 | } 240 | } 241 | 242 | state parse_redplane_ipv4_udp_ack { 243 | pkt.extract (hdr.redplane_ipv4); 244 | pkt.extract (hdr.redplane_udp); 245 | pkt.extract (hdr.redplane_ack); 246 | 247 | eg_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 248 | eg_md.flow_key.port = hdr.redplane_ack.flow_key.port; 249 | eg_md.cur_seq_num = hdr.redplane_ack.seq_num; 250 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 251 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 252 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 253 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 254 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 255 | default: reject; // reject all other invalid ack packets. 256 | } 257 | } 258 | 259 | state parse_lease_migrate_ack { 260 | pkt.extract(hdr.redplane_values); 261 | transition parse_regular_ipv4; 262 | } 263 | 264 | state parse_redplane_ipv4_udp_req { 265 | pkt.extract (hdr.redplane_ipv4); 266 | pkt.extract (hdr.redplane_udp); 267 | pkt.extract (hdr.redplane_req); 268 | 269 | eg_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 270 | eg_md.flow_key.port = hdr.redplane_req.flow_key.port; 271 | eg_md.cur_seq_num = hdr.redplane_req.seq_num; 272 | 273 | transition parse_regular_ipv4; 274 | } 275 | 276 | state parse_regular_ipv4 { 277 | pkt.extract (hdr.ipv4); 278 | transition accept; 279 | } 280 | } 281 | 282 | control EgressDeparser(packet_out pkt, 283 | inout egress_headers_t hdr, 284 | in egress_metadata_t eg_md, 285 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 286 | { 287 | Mirror() mirror; 288 | Checksum() redplane_ipv4_checksum; 289 | apply { 290 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 291 | hdr.redplane_ipv4.version, 292 | hdr.redplane_ipv4.ihl, 293 | hdr.redplane_ipv4.diffserv, 294 | hdr.redplane_ipv4.total_len, 295 | hdr.redplane_ipv4.identification, 296 | hdr.redplane_ipv4.flags, 297 | hdr.redplane_ipv4.frag_offset, 298 | hdr.redplane_ipv4.ttl, 299 | hdr.redplane_ipv4.protocol, 300 | hdr.redplane_ipv4.src_addr, 301 | hdr.redplane_ipv4.dst_addr 302 | }); 303 | 304 | if (eg_dprsr_md.mirror_type == MIRROR_TYPE_E2E) { 305 | mirror.emit(eg_md.egr_mir_ses, {eg_md.pkt_type, eg_md.tstamp, 0, eg_md.is_first_time}); 306 | } 307 | 308 | pkt.emit(hdr); 309 | 310 | } 311 | } 312 | 313 | #endif /* _PARSERS_ */ -------------------------------------------------------------------------------- /redplane-p4/nat/replication.p4: -------------------------------------------------------------------------------- 1 | #ifndef _Replication_ 2 | #define _Replication_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control Replication ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | // Instead of mirroring, let's use replication. 15 | action set_multicast (MulticastGroupId_t mcast_grp) { 16 | ig_tm_md.mcast_grp_a = mcast_grp; 17 | hdr.bridged_md.pkt_type = PKT_TYPE_NORMAL; 18 | } 19 | 20 | // We do this for (1) Read-only packet (2) ACK packets 21 | table replication { 22 | key = { 23 | hdr.bridged_md.store_egress_port : exact; // egress port for state store 24 | } 25 | actions = { 26 | set_multicast; 27 | } 28 | } 29 | 30 | apply { 31 | replication.apply(); 32 | } 33 | } 34 | #endif /* _Replication_ */ -------------------------------------------------------------------------------- /redplane-p4/nat/types.p4: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_ 2 | #define _TYPES_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<16> ether_type_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<8> ip_protocol_t; 8 | typedef bit<16> udp_port_t; 9 | 10 | typedef bit<3> mirror_type_t; 11 | typedef bit<8> pkt_type_t; 12 | 13 | enum bit<8> req_type_t { 14 | LEASE_NEW_REQ = 0x0, 15 | LEASE_RENEW_REQ = 0x1, 16 | LEASE_NEW_ACK = 0x3, 17 | LEASE_RENEW_ACK = 0x4, 18 | LEASE_MIGRATE_ACK = 0x5 19 | } 20 | 21 | enum bit<8> ack_type_t { 22 | LEASE_NEW_ACK = 0x0, 23 | LEASE_RENEW_ACK = 0x1, 24 | LEASE_MIGRATE_ACK = 0x2 25 | } 26 | 27 | // NAT 28 | // COMPILER: this structure should be generated by redplane compiler or given as a user-input. 29 | struct flow_key_t { 30 | ipv4_addr_t ip_addr; 31 | bit<16> port; 32 | } 33 | 34 | struct flow_value_t { 35 | ipv4_addr_t ip_addr; 36 | bit<16> port; 37 | } 38 | 39 | struct nat_meta_t { 40 | bool is_ext; 41 | } 42 | 43 | #endif /* _TYPES_ */ -------------------------------------------------------------------------------- /redplane-p4/simple-kv/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | #include "types.p4" 5 | 6 | const PortId_t CPU_PORT = 320; 7 | const PortId_t DEFAULT_STORE_PORT = 8; 8 | //const PortId_t CPU_PORT = 64; 9 | //const PortId_t DEFAULT_STORE_PORT = 1; 10 | 11 | const ether_type_t ETHERTYPE_IPV4 = 0x0800; 12 | const ether_type_t ETHERTYPE_TO_CPU = 0xBF01; 13 | 14 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 15 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 16 | 17 | const mirror_type_t MIRROR_TYPE_E2E = 2; 18 | 19 | const bit<48> LEASE_PERIOD = 100000000000; // 5 secs 20 | const bit<48> TIMEOUT = 1000000; // 1 msec 21 | const bit<16> MAX_SEQ_NUM = 65533; 22 | const bit<16> SWITCH_UDP_PORT = 4000; 23 | const bit<16> STORE_UDP_PORT = 8000; 24 | 25 | const pkt_type_t PKT_TYPE_NORMAL = 0; // Normal packets (just coming in); 26 | const pkt_type_t PKT_TYPE_EGR_MIRROR = 1; // Transaction for logging 27 | 28 | header ethernet_h { 29 | mac_addr_t dst_addr; 30 | mac_addr_t src_addr; 31 | bit<16> ether_type; 32 | } 33 | 34 | header ipv4_h { 35 | bit<4> version; 36 | bit<4> ihl; 37 | bit<8> diffserv; 38 | bit<16> total_len; 39 | bit<16> identification; 40 | bit<3> flags; 41 | bit<13> frag_offset; 42 | bit<8> ttl; 43 | bit<8> protocol; 44 | bit<16> hdr_checksum; 45 | ipv4_addr_t src_addr; 46 | ipv4_addr_t dst_addr; 47 | } 48 | 49 | header tcp_h { 50 | bit<16> src_port; 51 | bit<16> dst_port; 52 | bit<32> seq_no; 53 | bit<32> ack_no; 54 | bit<4> data_offset; 55 | bit<4> res; 56 | bit<1> cwr; 57 | bit<1> ece; 58 | bit<1> urg; 59 | bit<1> ack; 60 | bit<1> psh; 61 | bit<1> rst; 62 | bit<1> syn; 63 | bit<1> fin; 64 | bit<16> window; 65 | bit<16> checksum; 66 | bit<16> urgent_ptr; 67 | } 68 | 69 | header udp_h { 70 | bit<16> src_port; 71 | bit<16> dst_port; 72 | bit<16> hdr_length; 73 | bit<16> checksum; 74 | } 75 | 76 | header tstamp_h{ 77 | bit<48> in_time; 78 | bit<48> out_time; 79 | } 80 | 81 | header redplane_req_h { 82 | req_type_t req_type; //1 83 | bit<16> seq_num; // 2 84 | flow_key_t flow_key; //6 85 | flow_value_t values; //6 86 | } 87 | 88 | const bit<16> REDPLANE_REQ_IP_LEN = 20 + 8 + 15; 89 | const bit<16> REDPLANE_REQ_UDP_LEN = 8 + 15; 90 | 91 | header redplane_ack_h { 92 | ack_type_t ack_type; // 1 93 | bit<16> seq_num; // 2 94 | flow_key_t flow_key; // 6 95 | } 96 | const bit<16> REDPLANE_ACK_IP_LEN = 20 + 8 + 9; 97 | 98 | header redplane_flow_value_h { 99 | flow_value_t values; 100 | } 101 | 102 | header egr_mirror_h { 103 | pkt_type_t pkt_type; 104 | bit<48> tstamp; 105 | @padding 106 | bit<7> pad; 107 | bit<1> is_first_time; 108 | } 109 | 110 | header bridged_md_h { 111 | pkt_type_t pkt_type; //8 112 | PortId_t store_egress_port; //9 113 | PortId_t original_port; //9 114 | bit<1> is_write; 115 | @padding 116 | bit<5> pad; 117 | } 118 | struct ingress_headers_t { 119 | bridged_md_h bridged_md; 120 | ethernet_h cpu_ethernet; 121 | ethernet_h ethernet; 122 | ipv4_h redplane_ipv4; 123 | udp_h redplane_udp; 124 | redplane_req_h redplane_req; 125 | redplane_ack_h redplane_ack; 126 | redplane_flow_value_h redplane_values; 127 | ipv4_h ipv4; 128 | tcp_h tcp; 129 | udp_h udp; 130 | tstamp_h tstamp; 131 | } 132 | 133 | struct egress_headers_t { 134 | ethernet_h ethernet; 135 | ipv4_h redplane_ipv4; 136 | udp_h redplane_udp; 137 | redplane_req_h redplane_req; 138 | redplane_ack_h redplane_ack; 139 | redplane_flow_value_h redplane_values; 140 | ipv4_h ipv4; 141 | tcp_h tcp; 142 | udp_h udp; 143 | } 144 | 145 | struct ingress_metadata_t { 146 | bit<2> hashed_key; 147 | bool is_renew_req; 148 | bool lease_expired; 149 | nat_meta_t nat_meta; 150 | // checksum stuff 151 | bool ipv4_checksum_err; 152 | bool checksum_update_ipv4; 153 | bool checksum_update_redplane_ipv4; 154 | bool checksum_update_tcp; 155 | bit<16> checksum_tcp_tmp; 156 | flow_key_t flow_key; 157 | bit<32> new_lease_expire_time; 158 | bit<32> current_time; 159 | } 160 | 161 | struct egress_metadata_t { 162 | bridged_md_h bridged_md; 163 | bit<48> tstamp; 164 | bit<16> time_diff_hi; 165 | bit<16> time_diff_lo; 166 | MirrorId_t egr_mir_ses; 167 | pkt_type_t pkt_type; 168 | bool is_acked_req; 169 | bool is_logged_req; 170 | bit<16> seq_same; 171 | bit<16> last_sent; 172 | bit<16> last_acked; 173 | bit<16> seq_diff; 174 | bit<16> seq_diff1; 175 | bit<16> seq_diff2; 176 | bit<16> cur_seq_num; 177 | bit<1> is_first_time; 178 | // checksum stuff 179 | bool checksum_err_ipv4; 180 | flow_key_t flow_key; 181 | } 182 | 183 | #endif /* _HEADERS_ */ 184 | -------------------------------------------------------------------------------- /redplane-p4/simple-kv/kv_redplane.p4: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if __TARGET_TOFINO__ == 2 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "types.p4" 10 | #include "headers.p4" 11 | #include "parsers.p4" 12 | #include "l3_routing.p4" 13 | #include "replication.p4" 14 | #include "redplane_core.p4" 15 | #include "nat.p4" // NAT P4 we want to make fault-tolerant 16 | 17 | control Ingress( 18 | inout ingress_headers_t hdr, 19 | inout ingress_metadata_t ig_md, 20 | in ingress_intrinsic_metadata_t ig_intr_md, 21 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 22 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 23 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 24 | // COMPILER: This line should be added by Redplane compiler. 25 | RedplaneIngress() redplane_ig; 26 | Nat_Ingress() Nat_Ingress; // Instantiate the original application 27 | L3Routing() L3_routing; 28 | Replication() replication; 29 | 30 | apply { 31 | //if (hdr.redplane_ack.isValid() == false && hdr.redplane_req.isValid() == false) { 32 | //if (hdr.redplane_req.isValid() == false) { 33 | //} 34 | //if (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_NEW_ACK) { 35 | // hdr.tstamp.in_time = ig_intr_md.ingress_mac_tstamp; 36 | //} 37 | // COMPILER: This line should be added by Redplane compiler. 38 | redplane_ig.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 39 | 40 | // COMPILER: This line should be added by Redplane compiler. 41 | // If the packet is an Redplane ACK from the state store, the app must not process it. 42 | if (ig_md.is_renew_req == true) { 43 | // App's ingress logic. 44 | // hdr.tstamp.out_time = ig_intr_md.ingress_mac_tstamp; 45 | Nat_Ingress.apply(hdr, ig_md, ig_intr_md, ig_prsr_md, ig_dprsr_md, ig_tm_md); 46 | } 47 | 48 | if ((ig_md.is_renew_req == true || (hdr.redplane_ack.isValid() == true && hdr.ipv4.isValid() == true)) && ig_tm_md.ucast_egress_port != CPU_PORT) { 49 | L3_routing.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 50 | } 51 | 52 | if ((hdr.bridged_md.is_write == 0 && hdr.redplane_req.isValid() == true && hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) || // If it's a read renew request, 53 | (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_RENEW_ACK && hdr.ipv4.isValid() == true)) // if it's an ack with a piggybacked original packet 54 | { 55 | //then replicate it! 56 | replication.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 57 | } 58 | } 59 | } 60 | 61 | control Egress( 62 | inout egress_headers_t hdr, 63 | inout egress_metadata_t eg_md, 64 | in egress_intrinsic_metadata_t eg_intr_md, 65 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 66 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 67 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 68 | 69 | // COMPILER: This line should be added by Redplane compiler. 70 | RedplaneEgress() redplane_eg; 71 | 72 | action invalidate_redplane_hdr() { 73 | hdr.redplane_ipv4.setInvalid(); 74 | hdr.redplane_udp.setInvalid(); 75 | hdr.redplane_req.setInvalid(); 76 | hdr.redplane_ack.setInvalid(); 77 | hdr.redplane_values.setInvalid(); 78 | } 79 | apply { 80 | // Redplane packet destined to the state store OR Write packet is processed 81 | if (eg_intr_md.egress_rid_first == 1 // replicated packet (RENEW ACK or RENEW REQ) 82 | || eg_md.bridged_md.is_write == 1 // RENEW REQ with write 83 | || (hdr.redplane_ack.isValid() && hdr.ipv4.isValid() ==false) // RENEW ACK without payload 84 | || eg_md.is_logged_req == true) 85 | { 86 | if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 87 | redplane_eg.apply(hdr, eg_md, eg_intr_md, eg_prsr_md, eg_dprsr_md); 88 | } 89 | } else if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 90 | invalidate_redplane_hdr(); 91 | } 92 | } 93 | } 94 | 95 | Pipeline( 96 | IngressParser(), 97 | Ingress(), 98 | IngressDeparser(), 99 | EgressParser(), 100 | Egress(), 101 | EgressDeparser() 102 | ) pipe; 103 | 104 | Switch(pipe) main; 105 | -------------------------------------------------------------------------------- /redplane-p4/simple-kv/l3_routing.p4: -------------------------------------------------------------------------------- 1 | #ifndef _L3_ROUTING_ 2 | #define _L3_ROUTING_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control L3Routing ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | action set_nhop(bit<9> port){ 15 | ig_tm_md.ucast_egress_port = port; 16 | } 17 | 18 | table ipv4_lpm { 19 | key = {hdr.ipv4.dst_addr : lpm;} 20 | actions = { set_nhop; } 21 | } 22 | 23 | apply { 24 | ipv4_lpm.apply(); 25 | } 26 | } 27 | #endif /* _L3_ROUTING_ */ -------------------------------------------------------------------------------- /redplane-p4/simple-kv/parsers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _PARSERS_ 2 | #define _PARSERS_ 3 | 4 | parser IngressParser(packet_in pkt, 5 | out ingress_headers_t hdr, 6 | out ingress_metadata_t ig_md, 7 | out ingress_intrinsic_metadata_t ig_intr_md) 8 | { 9 | Checksum() ipv4_checksum; 10 | Checksum() tcp_checksum; 11 | state start { 12 | pkt.extract(ig_intr_md); 13 | pkt.advance(PORT_METADATA_SIZE); 14 | transition meta_init; 15 | } 16 | 17 | state meta_init { 18 | //Initialize ingress metadata 19 | ig_md.checksum_update_redplane_ipv4 = false; 20 | ig_md.ipv4_checksum_err = false; 21 | ig_md.is_renew_req = false; 22 | ig_md.lease_expired = true; 23 | transition parse_ethernet; 24 | } 25 | 26 | state parse_ethernet { 27 | pkt.extract (hdr.ethernet); 28 | transition select (hdr.ethernet.ether_type) { 29 | ETHERTYPE_IPV4: parse_ipv4; 30 | default: accept; 31 | } 32 | } 33 | 34 | state parse_ipv4 { 35 | ipv4_h tmp_ipv4 = pkt.lookahead(); 36 | transition select(tmp_ipv4.protocol) { 37 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 38 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 39 | default: reject; 40 | } 41 | } 42 | 43 | state parse_regular_or_redplane_ipv4 { 44 | transition select(pkt.lookahead>()[15:0]) { 45 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 46 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 47 | default: parse_regular_ipv4; 48 | } 49 | } 50 | 51 | state parse_redplane_ipv4_udp_ack { 52 | pkt.extract (hdr.redplane_ipv4); 53 | pkt.extract (hdr.redplane_udp); 54 | pkt.extract (hdr.redplane_ack); 55 | 56 | ig_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 57 | ig_md.flow_key.port = hdr.redplane_ack.flow_key.port; 58 | 59 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 60 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 61 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 62 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 63 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 64 | default: reject; // reject all other invalid ack packets. 65 | } 66 | } 67 | 68 | state parse_lease_migrate_ack { 69 | pkt.extract(hdr.redplane_values); 70 | transition parse_regular_ipv4; 71 | } 72 | 73 | state parse_redplane_ipv4_udp_req { 74 | pkt.extract (hdr.redplane_ipv4); 75 | pkt.extract (hdr.redplane_udp); 76 | pkt.extract (hdr.redplane_req); 77 | 78 | ig_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 79 | ig_md.flow_key.port = hdr.redplane_req.flow_key.port; 80 | 81 | transition parse_regular_ipv4; 82 | } 83 | 84 | state parse_regular_ipv4 { 85 | pkt.extract (hdr.ipv4); 86 | ipv4_checksum.add(hdr.ipv4); 87 | ig_md.ipv4_checksum_err = ipv4_checksum.verify(); 88 | 89 | tcp_checksum.subtract({hdr.ipv4.src_addr}); 90 | tcp_checksum.subtract({hdr.ipv4.dst_addr}); 91 | 92 | transition select (hdr.ipv4.protocol) { 93 | IP_PROTOCOLS_TCP: parse_tcp; 94 | IP_PROTOCOLS_UDP: parse_udp; 95 | default: reject; 96 | } 97 | } 98 | 99 | state parse_tcp { 100 | pkt.extract(hdr.tcp); 101 | // The tcp checksum cannot be verified, since we cannot compute 102 | // the payload's checksum. 103 | tcp_checksum.subtract({hdr.tcp.checksum}); 104 | tcp_checksum.subtract({hdr.tcp.src_port}); 105 | tcp_checksum.subtract({hdr.tcp.dst_port}); 106 | ig_md.checksum_tcp_tmp = tcp_checksum.get(); 107 | 108 | transition accept; 109 | } 110 | 111 | state parse_tstamp { 112 | pkt.extract(hdr.tstamp); 113 | transition accept; 114 | } 115 | 116 | state parse_udp { 117 | pkt.extract(hdr.udp); 118 | transition accept; 119 | } 120 | } 121 | 122 | control IngressDeparser(packet_out pkt, 123 | inout ingress_headers_t hdr, 124 | in ingress_metadata_t ig_md, 125 | in ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md) 126 | { 127 | Checksum() ipv4_checksum; 128 | Checksum() tcp_checksum; 129 | Checksum() redplane_ipv4_checksum; 130 | Mirror() mirror; 131 | 132 | apply { 133 | if (ig_md.checksum_update_redplane_ipv4) { 134 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 135 | hdr.redplane_ipv4.version, 136 | hdr.redplane_ipv4.ihl, 137 | hdr.redplane_ipv4.diffserv, 138 | hdr.redplane_ipv4.total_len, 139 | hdr.redplane_ipv4.identification, 140 | hdr.redplane_ipv4.flags, 141 | hdr.redplane_ipv4.frag_offset, 142 | hdr.redplane_ipv4.ttl, 143 | hdr.redplane_ipv4.protocol, 144 | hdr.redplane_ipv4.src_addr, 145 | hdr.redplane_ipv4.dst_addr 146 | }); 147 | } 148 | 149 | if (ig_md.checksum_update_ipv4) { 150 | hdr.ipv4.hdr_checksum = ipv4_checksum.update({ 151 | hdr.ipv4.version, 152 | hdr.ipv4.ihl, 153 | hdr.ipv4.diffserv, 154 | hdr.ipv4.total_len, 155 | hdr.ipv4.identification, 156 | hdr.ipv4.flags, 157 | hdr.ipv4.frag_offset, 158 | hdr.ipv4.ttl, 159 | hdr.ipv4.protocol, 160 | hdr.ipv4.src_addr, 161 | hdr.ipv4.dst_addr 162 | }); 163 | } 164 | 165 | if (ig_md.checksum_update_tcp) { 166 | hdr.tcp.checksum = tcp_checksum.update({ 167 | hdr.ipv4.src_addr, 168 | hdr.ipv4.dst_addr, 169 | hdr.tcp.src_port, 170 | hdr.tcp.dst_port, 171 | ig_md.checksum_tcp_tmp 172 | }); 173 | } 174 | 175 | pkt.emit(hdr); 176 | } 177 | } 178 | 179 | parser EgressParser(packet_in pkt, 180 | out egress_headers_t hdr, 181 | out egress_metadata_t eg_md, 182 | out egress_intrinsic_metadata_t eg_intr_md) 183 | { 184 | state start { 185 | pkt.extract(eg_intr_md); 186 | transition parse_metadata; 187 | } 188 | 189 | state parse_metadata { 190 | eg_md.is_logged_req = false; 191 | eg_md.is_acked_req = false; 192 | eg_md.is_first_time = 0; 193 | eg_md.tstamp = 0; 194 | 195 | egr_mirror_h mirror_md = pkt.lookahead(); 196 | transition select(mirror_md.pkt_type) { 197 | PKT_TYPE_EGR_MIRROR : parse_egr_mirror_md; // cloned from egress 198 | PKT_TYPE_NORMAL : parse_bridged_md; // from the ingress 199 | default : accept; 200 | } 201 | } 202 | 203 | state parse_egr_mirror_md { 204 | egr_mirror_h mirror_md; 205 | pkt.extract(mirror_md); 206 | eg_md.is_logged_req = true; 207 | eg_md.tstamp = mirror_md.tstamp; // store the logged timestamp 208 | eg_md.is_first_time = mirror_md.is_first_time; 209 | transition parse_ethernet; 210 | } 211 | 212 | state parse_bridged_md { 213 | pkt.extract(eg_md.bridged_md); 214 | transition parse_ethernet; 215 | } 216 | 217 | state parse_ethernet { 218 | pkt.extract (hdr.ethernet); 219 | transition select (hdr.ethernet.ether_type) { 220 | ETHERTYPE_IPV4: parse_ipv4; 221 | default: accept; 222 | } 223 | } 224 | 225 | state parse_ipv4 { 226 | ipv4_h tmp_ipv4 = pkt.lookahead(); 227 | transition select(tmp_ipv4.protocol) { 228 | IP_PROTOCOLS_TCP: parse_regular_ipv4; 229 | IP_PROTOCOLS_UDP: parse_regular_or_redplane_ipv4; 230 | default: reject; 231 | } 232 | } 233 | 234 | state parse_regular_or_redplane_ipv4 { 235 | transition select(pkt.lookahead>()[15:0]) { 236 | SWITCH_UDP_PORT: parse_redplane_ipv4_udp_ack; 237 | STORE_UDP_PORT &&& 0xffc0 : parse_redplane_ipv4_udp_req; // 8000-8063 238 | default: parse_regular_ipv4; 239 | } 240 | } 241 | 242 | state parse_redplane_ipv4_udp_ack { 243 | pkt.extract (hdr.redplane_ipv4); 244 | pkt.extract (hdr.redplane_udp); 245 | pkt.extract (hdr.redplane_ack); 246 | 247 | eg_md.flow_key.ip_addr = hdr.redplane_ack.flow_key.ip_addr; 248 | eg_md.flow_key.port = hdr.redplane_ack.flow_key.port; 249 | eg_md.cur_seq_num = hdr.redplane_ack.seq_num; 250 | transition select (hdr.redplane_ack.ack_type, hdr.redplane_ipv4.total_len){ 251 | (ack_type_t.LEASE_NEW_ACK, _) : parse_regular_ipv4; 252 | (ack_type_t.LEASE_MIGRATE_ACK, _) : parse_lease_migrate_ack; 253 | (ack_type_t.LEASE_RENEW_ACK, REDPLANE_ACK_IP_LEN) : accept; // no trailer (i.e., original payload) 254 | (ack_type_t.LEASE_RENEW_ACK, _) : parse_regular_ipv4; 255 | default: reject; // reject all other invalid ack packets. 256 | } 257 | } 258 | 259 | state parse_lease_migrate_ack { 260 | pkt.extract(hdr.redplane_values); 261 | transition parse_regular_ipv4; 262 | } 263 | 264 | state parse_redplane_ipv4_udp_req { 265 | pkt.extract (hdr.redplane_ipv4); 266 | pkt.extract (hdr.redplane_udp); 267 | pkt.extract (hdr.redplane_req); 268 | 269 | eg_md.flow_key.ip_addr = hdr.redplane_req.flow_key.ip_addr; 270 | eg_md.flow_key.port = hdr.redplane_req.flow_key.port; 271 | eg_md.cur_seq_num = hdr.redplane_req.seq_num; 272 | 273 | transition parse_regular_ipv4; 274 | } 275 | 276 | state parse_regular_ipv4 { 277 | pkt.extract (hdr.ipv4); 278 | transition accept; 279 | } 280 | } 281 | 282 | control EgressDeparser(packet_out pkt, 283 | inout egress_headers_t hdr, 284 | in egress_metadata_t eg_md, 285 | in egress_intrinsic_metadata_for_deparser_t eg_dprsr_md) 286 | { 287 | Mirror() mirror; 288 | Checksum() redplane_ipv4_checksum; 289 | apply { 290 | hdr.redplane_ipv4.hdr_checksum = redplane_ipv4_checksum.update({ 291 | hdr.redplane_ipv4.version, 292 | hdr.redplane_ipv4.ihl, 293 | hdr.redplane_ipv4.diffserv, 294 | hdr.redplane_ipv4.total_len, 295 | hdr.redplane_ipv4.identification, 296 | hdr.redplane_ipv4.flags, 297 | hdr.redplane_ipv4.frag_offset, 298 | hdr.redplane_ipv4.ttl, 299 | hdr.redplane_ipv4.protocol, 300 | hdr.redplane_ipv4.src_addr, 301 | hdr.redplane_ipv4.dst_addr 302 | }); 303 | 304 | if (eg_dprsr_md.mirror_type == MIRROR_TYPE_E2E) { 305 | mirror.emit(eg_md.egr_mir_ses, {eg_md.pkt_type, eg_md.tstamp, 0, eg_md.is_first_time}); 306 | } 307 | 308 | pkt.emit(hdr); 309 | 310 | } 311 | } 312 | 313 | #endif /* _PARSERS_ */ -------------------------------------------------------------------------------- /redplane-p4/simple-kv/replication.p4: -------------------------------------------------------------------------------- 1 | #ifndef _Replication_ 2 | #define _Replication_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control Replication ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | // Instead of mirroring, let's use replication. 15 | action set_multicast (MulticastGroupId_t mcast_grp) { 16 | ig_tm_md.mcast_grp_a = mcast_grp; 17 | hdr.bridged_md.pkt_type = PKT_TYPE_NORMAL; 18 | } 19 | 20 | // We do this for (1) Read-only packet (2) ACK packets 21 | table replication { 22 | key = { 23 | hdr.bridged_md.store_egress_port : exact; // egress port for state store 24 | } 25 | actions = { 26 | set_multicast; 27 | } 28 | } 29 | 30 | apply { 31 | replication.apply(); 32 | } 33 | } 34 | #endif /* _Replication_ */ -------------------------------------------------------------------------------- /redplane-p4/simple-kv/simple_kv.p4: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * nat.p4: 3 | * NAT implementaton in P4 for TNA. 4 | * 5 | * Author: Daehyeok Kim 6 | **********************************************************************/ 7 | 8 | #ifndef _NAT_ 9 | #define _NAT_ 10 | 11 | #include "headers.p4" 12 | 13 | /***************** M A T C H - A C T I O N *********************/ 14 | control KV_Ingress( 15 | /* User */ 16 | inout ingress_headers_t hdr, 17 | inout ingress_metadata_t ig_md, 18 | /* Intrinsic */ 19 | in ingress_intrinsic_metadata_t ig_intr_md, 20 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 21 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 22 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 23 | { 24 | action drop() { 25 | ig_dprsr_md.drop_ctl = 1; 26 | } 27 | action kv_hit(bit<32> src_addr, bit<16> src_port) { 28 | hdr.ipv4.src_addr= src_addr; 29 | hdr.tcp.src_port = src_port; 30 | 31 | ig_md.checksum_update_ipv4 = true; 32 | ig_md.checksum_update_tcp = true; 33 | } 34 | table handle_kv_query { 35 | key = { 36 | hdr.ipv4.src_addr: exact; 37 | hdr.tcp.src_port: exact; 38 | } 39 | actions = {kv_hit; } 40 | //default_action = natTcp_learn(); 41 | } 42 | 43 | apply { 44 | //if(hdr.ipv4.isValid() && !ig_md.ipv4_checksum_err) { 45 | if(hdr.ipv4.isValid()) { 46 | handle_kv_query.apply(); 47 | } 48 | } 49 | } 50 | 51 | #endif /* _NAT_ */ -------------------------------------------------------------------------------- /redplane-p4/simple-kv/types.p4: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_ 2 | #define _TYPES_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<16> ether_type_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<8> ip_protocol_t; 8 | typedef bit<16> udp_port_t; 9 | 10 | typedef bit<3> mirror_type_t; 11 | typedef bit<8> pkt_type_t; 12 | 13 | enum bit<8> req_type_t { 14 | LEASE_NEW_REQ = 0x0, 15 | LEASE_RENEW_REQ = 0x1, 16 | LEASE_NEW_ACK = 0x3, 17 | LEASE_RENEW_ACK = 0x4, 18 | LEASE_MIGRATE_ACK = 0x5 19 | } 20 | 21 | enum bit<8> ack_type_t { 22 | LEASE_NEW_ACK = 0x0, 23 | LEASE_RENEW_ACK = 0x1, 24 | LEASE_MIGRATE_ACK = 0x2 25 | } 26 | 27 | // NAT 28 | // COMPILER: this structure should be generated by redplane compiler or given as a user-input. 29 | struct flow_key_t { 30 | ipv4_addr_t ip_addr; 31 | bit<16> port; 32 | } 33 | 34 | struct flow_value_t { 35 | ipv4_addr_t ip_addr; 36 | bit<16> port; 37 | } 38 | 39 | struct nat_meta_t { 40 | bool is_ext; 41 | } 42 | 43 | #endif /* _TYPES_ */ -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/count_min.p4: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | * count_min.p4: 3 | * 64 x 3 count-min sketch implementaton in P4 for TNA. 4 | * 5 | * Author: Daehyeok Kim 6 | **********************************************************************/ 7 | 8 | #ifndef _COUNT_MIN_ 9 | #define _COUNT_MIN_ 10 | 11 | #include "headers.p4" 12 | #include "sketch.p4" 13 | 14 | control CM_Ingress( 15 | /* User */ 16 | inout ingress_headers_t hdr, 17 | inout ingress_metadata_t ig_md, 18 | /* Intrinsic */ 19 | in ingress_intrinsic_metadata_t ig_intr_md, 20 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 21 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 22 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) 23 | { 24 | Hash>(HashAlgorithm_t.CRC32) hash_crc32; 25 | action hash_flow_key1() { 26 | ig_md.sketch_key1 = hash_crc32.get({ 27 | ig_md.flow_key.ip_addr, 28 | ig_md.flow_key.port 29 | }); 30 | } 31 | Hash>(HashAlgorithm_t.CRC64) hash_crc64; 32 | action hash_flow_key2() { 33 | ig_md.sketch_key2 = hash_crc64.get({ 34 | ig_md.flow_key.ip_addr, 35 | ig_md.flow_key.port 36 | }); 37 | } 38 | Hash>(HashAlgorithm_t.CRC16) hash_crc16; 39 | action hash_flow_key3() { 40 | ig_md.sketch_key3 = hash_crc16.get({ 41 | ig_md.flow_key.ip_addr, 42 | ig_md.flow_key.port 43 | }); 44 | } 45 | 46 | /* Definition of sketches (64 x 3)*/ 47 | Sketch() sketch1; 48 | Sketch() sketch2; 49 | Sketch() sketch3; 50 | 51 | ////////////////////////////////////////////////////////////////////////////// 52 | apply { 53 | // is this a snapshot packet? 54 | if (hdr.pktgen_hdr.isValid() == true) { 55 | // yes, copy packet_id to sketch_keys 56 | ig_md.sketch_key1 = (bit<8>)(hdr.pktgen_hdr.packet_id); 57 | ig_md.sketch_key2 = (bit<8>)(hdr.pktgen_hdr.packet_id); 58 | ig_md.sketch_key3 = (bit<8>)(hdr.pktgen_hdr.packet_id); 59 | ig_md.update_val = 0; 60 | } else { 61 | // no, get sketch keys by hashing flow key 62 | hash_flow_key1(); 63 | hash_flow_key2(); 64 | hash_flow_key3(); 65 | ig_md.update_val = 1; 66 | } 67 | sketch1.apply(hdr, ig_md.active_buffer1, ig_md.last_updated_buffer_for_index1, ig_md.sketch_key1, ig_md.update_val, hdr.redplane_req.values.sketch_1); 68 | sketch2.apply(hdr, ig_md.active_buffer2, ig_md.last_updated_buffer_for_index2, ig_md.sketch_key2, ig_md.update_val, hdr.redplane_req.values.sketch_2); 69 | sketch3.apply(hdr, ig_md.active_buffer3, ig_md.last_updated_buffer_for_index3, ig_md.sketch_key3, ig_md.update_val, hdr.redplane_req.values.sketch_3); 70 | } 71 | } 72 | 73 | #endif /* _COUNT_MIN_ */ -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/headers.p4: -------------------------------------------------------------------------------- 1 | #ifndef _HEADERS_ 2 | #define _HEADERS_ 3 | 4 | #include "types.p4" 5 | 6 | const PortId_t CPU_PORT = 320; 7 | const PortId_t DEFAULT_STORE_PORT = 8; 8 | //const PortId_t CPU_PORT = 64; 9 | //const PortId_t DEFAULT_STORE_PORT = 1; 10 | 11 | const ether_type_t ETHERTYPE_IPV4 = 0x0800; 12 | const ether_type_t ETHERTYPE_TO_CPU = 0xBF01; 13 | 14 | const ip_protocol_t IP_PROTOCOLS_TCP = 6; 15 | const ip_protocol_t IP_PROTOCOLS_UDP = 17; 16 | 17 | const mirror_type_t MIRROR_TYPE_E2E = 2; 18 | 19 | const bit<48> LEASE_PERIOD = 100000000000; // 5 secs 20 | const bit<48> TIMEOUT = 1000000; // 1 msec 21 | const bit<16> MAX_SEQ_NUM = 65533; 22 | const bit<16> SWITCH_UDP_PORT = 4000; 23 | const bit<16> STORE_UDP_PORT = 8000; 24 | 25 | const pkt_type_t PKT_TYPE_NORMAL = 0; // Normal packets (just coming in); 26 | const pkt_type_t PKT_TYPE_EGR_MIRROR = 1; // Transaction for logging 27 | 28 | header ethernet_h { 29 | mac_addr_t dst_addr; 30 | mac_addr_t src_addr; 31 | bit<16> ether_type; 32 | } 33 | 34 | header vlan_tag_h { 35 | bit<3> pcp; 36 | bit<1> cfi; 37 | bit<12> vid; 38 | bit<16> ether_type; 39 | } 40 | 41 | header ipv4_h { 42 | bit<4> version; 43 | bit<4> ihl; 44 | bit<8> diffserv; 45 | bit<16> total_len; 46 | bit<16> identification; 47 | bit<3> flags; 48 | bit<13> frag_offset; 49 | bit<8> ttl; 50 | bit<8> protocol; 51 | bit<16> hdr_checksum; 52 | ipv4_addr_t src_addr; 53 | ipv4_addr_t dst_addr; 54 | } 55 | 56 | header tcp_h { 57 | bit<16> src_port; 58 | bit<16> dst_port; 59 | bit<32> seq_no; 60 | bit<32> ack_no; 61 | bit<4> data_offset; 62 | bit<4> res; 63 | bit<1> cwr; 64 | bit<1> ece; 65 | bit<1> urg; 66 | bit<1> ack; 67 | bit<1> psh; 68 | bit<1> rst; 69 | bit<1> syn; 70 | bit<1> fin; 71 | bit<16> window; 72 | bit<16> checksum; 73 | bit<16> urgent_ptr; 74 | } 75 | 76 | header udp_h { 77 | bit<16> src_port; 78 | bit<16> dst_port; 79 | bit<16> hdr_length; 80 | bit<16> checksum; 81 | } 82 | 83 | header tstamp_h{ 84 | bit<48> in_time; 85 | bit<48> out_time; 86 | } 87 | 88 | header redplane_req_h { 89 | req_type_t req_type; //1 90 | bit<16> seq_num; // 2 91 | flow_key_t flow_key; //1 92 | flow_value_t values; //12 93 | } 94 | 95 | const bit<16> REDPLANE_REQ_IP_LEN = 20 + 8 + 16; 96 | const bit<16> REDPLANE_REQ_UDP_LEN = 8 + 16; 97 | 98 | header redplane_ack_h { 99 | ack_type_t ack_type; // 1 100 | bit<16> seq_num; // 2 101 | flow_key_t flow_key; // 1 102 | } 103 | const bit<16> REDPLANE_ACK_IP_LEN = 20 + 8 + 4; 104 | 105 | header redplane_flow_value_h { 106 | flow_value_t values; 107 | } 108 | 109 | header egr_mirror_h { 110 | pkt_type_t pkt_type; 111 | bit<48> tstamp; 112 | @padding 113 | bit<7> pad; 114 | bit<1> is_first_time; 115 | } 116 | 117 | header bridged_md_h { 118 | pkt_type_t pkt_type; //8 119 | PortId_t store_egress_port; //9 120 | PortId_t original_port; //9 121 | bit<1> is_write; 122 | @padding 123 | bit<5> pad; 124 | } 125 | 126 | struct ingress_headers_t { 127 | pktgen_timer_header_t pktgen_hdr; 128 | bridged_md_h bridged_md; 129 | ethernet_h cpu_ethernet; 130 | ethernet_h ethernet; 131 | vlan_tag_h vlan_tag; 132 | ipv4_h redplane_ipv4; 133 | udp_h redplane_udp; 134 | redplane_req_h redplane_req; 135 | redplane_ack_h redplane_ack; 136 | redplane_flow_value_h redplane_values; 137 | ipv4_h ipv4; 138 | tcp_h tcp; 139 | udp_h udp; 140 | tstamp_h tstamp; 141 | } 142 | 143 | struct egress_headers_t { 144 | ethernet_h ethernet; 145 | ipv4_h redplane_ipv4; 146 | udp_h redplane_udp; 147 | redplane_req_h redplane_req; 148 | redplane_ack_h redplane_ack; 149 | redplane_flow_value_h redplane_values; 150 | ipv4_h ipv4; 151 | tcp_h tcp; 152 | udp_h udp; 153 | } 154 | 155 | struct ingress_metadata_t { 156 | bit<2> hashed_key; 157 | bool is_renew_req; 158 | bool lease_expired; 159 | nat_meta_t nat_meta; 160 | // snapshot 161 | bit<32> update_val; 162 | snapshot_meta_t active_buffer1; 163 | snapshot_meta_t active_buffer2; 164 | snapshot_meta_t active_buffer3; 165 | snapshot_meta_t last_updated_buffer_for_index1; 166 | snapshot_meta_t last_updated_buffer_for_index2; 167 | snapshot_meta_t last_updated_buffer_for_index3; 168 | 169 | // checksum stuff 170 | bool ipv4_checksum_err; 171 | bool checksum_update_ipv4; 172 | bool checksum_update_redplane_ipv4; 173 | bool checksum_update_tcp; 174 | bit<16> checksum_tcp_tmp; 175 | flow_key_t flow_key; 176 | bit<32> new_lease_expire_time; 177 | bit<32> current_time; 178 | 179 | //SKETCH 180 | bit<8> sketch_key1; 181 | bit<8> sketch_key2; 182 | bit<8> sketch_key3; 183 | } 184 | 185 | struct egress_metadata_t { 186 | bridged_md_h bridged_md; 187 | bit<48> tstamp; 188 | bit<16> time_diff_hi; 189 | bit<16> time_diff_lo; 190 | MirrorId_t egr_mir_ses; 191 | pkt_type_t pkt_type; 192 | bool is_acked_req; 193 | bool is_logged_req; 194 | bit<16> seq_same; 195 | bit<16> last_sent; 196 | bit<16> last_acked; 197 | bit<16> seq_diff; 198 | bit<16> seq_diff1; 199 | bit<16> seq_diff2; 200 | bit<16> cur_seq_num; 201 | bit<1> is_first_time; 202 | // checksum stuff 203 | bool checksum_err_ipv4; 204 | flow_key_t flow_key; 205 | } 206 | 207 | #endif /* _HEADERS_ */ 208 | -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/l3_routing.p4: -------------------------------------------------------------------------------- 1 | #ifndef _L3_ROUTING_ 2 | #define _L3_ROUTING_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control L3Routing ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | action set_nhop(bit<9> port){ 15 | ig_tm_md.ucast_egress_port = port; 16 | } 17 | 18 | table ipv4_lpm { 19 | key = {hdr.ipv4.dst_addr : lpm;} 20 | actions = { set_nhop; } 21 | } 22 | 23 | apply { 24 | ipv4_lpm.apply(); 25 | } 26 | } 27 | #endif /* _L3_ROUTING_ */ -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/replication.p4: -------------------------------------------------------------------------------- 1 | #ifndef _Replication_ 2 | #define _Replication_ 3 | 4 | #include "headers.p4" 5 | #include "types.p4" 6 | 7 | control Replication ( 8 | inout ingress_headers_t hdr, 9 | inout ingress_metadata_t ig_md, 10 | in ingress_intrinsic_metadata_t ig_intr_md, 11 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 12 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 13 | 14 | // Instead of mirroring, let's use replication. 15 | action set_multicast (MulticastGroupId_t mcast_grp) { 16 | ig_tm_md.mcast_grp_a = mcast_grp; 17 | hdr.bridged_md.pkt_type = PKT_TYPE_NORMAL; 18 | } 19 | 20 | // We do this for (1) Read-only packet (2) ACK packets 21 | table replication { 22 | key = { 23 | hdr.bridged_md.store_egress_port : exact; // egress port for state store 24 | } 25 | actions = { 26 | set_multicast; 27 | } 28 | } 29 | 30 | apply { 31 | replication.apply(); 32 | } 33 | } 34 | #endif /* _Replication_ */ -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/sketch.p4: -------------------------------------------------------------------------------- 1 | #ifndef _SKETCH_ 2 | #define _SKETCH_ 3 | 4 | #include "headers.p4" 5 | 6 | struct pair { 7 | bit<32> first; 8 | bit<32> second; 9 | } 10 | 11 | control Sketch ( 12 | /* User */ 13 | inout ingress_headers_t hdr, 14 | inout snapshot_meta_t active_buffer_md, 15 | inout snapshot_meta_t last_updated_buffer_for_index_md, 16 | in bit<8> sketch_key, 17 | in bit<32> update_val, 18 | out bit<32> result) 19 | { 20 | /***************************** ACTIVE BUFFER *******************************/ 21 | Register>(1, 0) active_buffer; 22 | RegisterAction, snapshot_meta_t>(active_buffer) swap_active_buffer = { 23 | void apply(inout snapshot_meta_t reg_val, out snapshot_meta_t new_val) { 24 | reg_val = ~reg_val; 25 | new_val = reg_val; 26 | } 27 | }; 28 | RegisterAction, snapshot_meta_t>(active_buffer) get_active_buffer = { 29 | void apply(inout snapshot_meta_t reg_val, out snapshot_meta_t new_val) { 30 | new_val = reg_val; 31 | } 32 | }; 33 | 34 | /**************************** LAST UPDATED BUFFER *************************/ 35 | Register>(64, 0) last_updated_buffer; 36 | RegisterAction, snapshot_meta_t>(last_updated_buffer) update_last_updated_buffer = { 37 | void apply(inout snapshot_meta_t reg_val, out snapshot_meta_t cur_val) { 38 | cur_val = reg_val; 39 | reg_val = active_buffer_md; 40 | } 41 | }; 42 | 43 | /******************************** CM SKETCH ************************************/ 44 | Register>(64) SKETCH; 45 | RegisterAction, bit<32>>(SKETCH) copy_update_and_read_buffer_0 = { 46 | void apply(inout pair reg_val, out bit<32> cur_val) { 47 | reg_val.first = reg_val.second + update_val; 48 | cur_val = reg_val.first; 49 | } 50 | }; 51 | RegisterAction, bit<32>>(SKETCH) copy_update_and_read_buffer_1 = { 52 | void apply(inout pair reg_val, out bit<32> cur_val) { 53 | reg_val.second = reg_val.first + update_val; 54 | cur_val = reg_val.second; 55 | } 56 | }; 57 | RegisterAction, bit<32>>(SKETCH) update_and_read_buffer_0 = { 58 | void apply(inout pair reg_val, out bit<32> cur_val) { 59 | reg_val.first = reg_val.first + update_val; 60 | cur_val = reg_val.first; 61 | } 62 | }; 63 | RegisterAction, bit<32>>(SKETCH) update_and_read_buffer_1 = { 64 | void apply(inout pair reg_val, out bit<32> cur_val) { 65 | reg_val.second = reg_val.second + update_val; 66 | cur_val = reg_val.second; 67 | } 68 | }; 69 | /************************Snapshot update_and/or_read logic***********************/ 70 | action act_copy_update_and_read_buffer_0() { 71 | result = copy_update_and_read_buffer_0.execute(sketch_key); 72 | } 73 | 74 | action act_copy_update_and_read_buffer_1() { 75 | result = copy_update_and_read_buffer_1.execute(sketch_key); 76 | } 77 | 78 | action act_update_and_read_buffer_0() { 79 | result = update_and_read_buffer_0.execute(sketch_key); 80 | } 81 | 82 | action act_update_and_read_buffer_1() { 83 | result = update_and_read_buffer_1.execute(sketch_key); 84 | } 85 | 86 | table sketch_snapshot_tbl { 87 | key = { 88 | hdr.pktgen_hdr.isValid(): exact; 89 | active_buffer_md: exact; 90 | last_updated_buffer_for_index_md: exact; 91 | } 92 | actions = { 93 | act_copy_update_and_read_buffer_0; 94 | act_copy_update_and_read_buffer_1; 95 | act_update_and_read_buffer_0; 96 | act_update_and_read_buffer_1; 97 | } 98 | const entries = { 99 | (true, 0, 1): act_copy_update_and_read_buffer_0(); 100 | (true, 1, 0): act_copy_update_and_read_buffer_1(); 101 | (true, 0, 0): act_update_and_read_buffer_1(); 102 | (true, 1, 1): act_update_and_read_buffer_0(); 103 | (false, 0, 1): act_copy_update_and_read_buffer_0(); 104 | (false, 1, 0): act_copy_update_and_read_buffer_1(); 105 | (false, 0, 0): act_update_and_read_buffer_0(); 106 | (false, 1, 1): act_update_and_read_buffer_1(); 107 | } 108 | } 109 | 110 | apply { 111 | // is this the first packet of a snapshot read burst? 112 | if (hdr.pktgen_hdr.isValid() == true && hdr.pktgen_hdr.packet_id == 0) { 113 | // yes, so swap buffers 114 | active_buffer_md = swap_active_buffer.execute(0); 115 | } else { 116 | // no, so active buffer is unchanged 117 | active_buffer_md = get_active_buffer.execute(0); 118 | } 119 | last_updated_buffer_for_index_md = update_last_updated_buffer.execute(sketch_key); 120 | sketch_snapshot_tbl.apply(); 121 | } 122 | } 123 | 124 | #endif /* _SKETCH_ */ -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/sketch_snapshot_redplane.p4: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if __TARGET_TOFINO__ == 2 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | #include "types.p4" 10 | #include "headers.p4" 11 | #include "parsers.p4" 12 | #include "l3_routing.p4" 13 | #include "replication.p4" 14 | #include "redplane_core.p4" 15 | #include "count_min.p4" 16 | 17 | control Ingress( 18 | inout ingress_headers_t hdr, 19 | inout ingress_metadata_t ig_md, 20 | in ingress_intrinsic_metadata_t ig_intr_md, 21 | in ingress_intrinsic_metadata_from_parser_t ig_prsr_md, 22 | inout ingress_intrinsic_metadata_for_deparser_t ig_dprsr_md, 23 | inout ingress_intrinsic_metadata_for_tm_t ig_tm_md) { 24 | // COMPILER: This line should be added by Redplane compiler. 25 | RedplaneIngress() redplane_ig; 26 | CM_Ingress() CM_ig; // Instantiate the original application 27 | L3Routing() L3_routing; 28 | Replication() replication; 29 | 30 | apply { 31 | //if (hdr.redplane_ack.isValid() == false && hdr.redplane_req.isValid() == false) { 32 | //if (hdr.redplane_req.isValid() == false) { 33 | //} 34 | //if (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_NEW_ACK) { 35 | // hdr.tstamp.in_time = ig_intr_md.ingress_mac_tstamp; 36 | //} 37 | // COMPILER: This line should be added by Redplane compiler. 38 | redplane_ig.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 39 | 40 | // COMPILER: This line should be added by Redplane compiler. 41 | // If the packet is an Redplane ACK from the state store, the app must not process it. 42 | if (ig_md.is_renew_req == false) { 43 | // App's ingress logic. 44 | // hdr.tstamp.out_time = ig_intr_md.ingress_mac_tstamp; 45 | CM_ig.apply(hdr, ig_md, ig_intr_md, ig_prsr_md, ig_dprsr_md, ig_tm_md); 46 | } 47 | 48 | if ((ig_md.is_renew_req == true || (hdr.redplane_ack.isValid() == true && hdr.ipv4.isValid() == true)) && ig_tm_md.ucast_egress_port != CPU_PORT) { 49 | L3_routing.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 50 | } 51 | 52 | if ((hdr.bridged_md.is_write == 0 && hdr.redplane_req.isValid() == true && hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) || // If it's a read renew request, 53 | (hdr.redplane_ack.isValid() == true && hdr.redplane_ack.ack_type == ack_type_t.LEASE_RENEW_ACK && hdr.ipv4.isValid() == true)) // if it's an ack with a piggybacked original packet 54 | { 55 | //then replicate it! 56 | replication.apply(hdr, ig_md, ig_intr_md, ig_dprsr_md, ig_tm_md); 57 | } 58 | } 59 | } 60 | 61 | control Egress( 62 | inout egress_headers_t hdr, 63 | inout egress_metadata_t eg_md, 64 | in egress_intrinsic_metadata_t eg_intr_md, 65 | in egress_intrinsic_metadata_from_parser_t eg_prsr_md, 66 | inout egress_intrinsic_metadata_for_deparser_t eg_dprsr_md, 67 | inout egress_intrinsic_metadata_for_output_port_t eg_oport_md) { 68 | 69 | // COMPILER: This line should be added by Redplane compiler. 70 | RedplaneEgress() redplane_eg; 71 | 72 | action invalidate_redplane_hdr() { 73 | hdr.redplane_ipv4.setInvalid(); 74 | hdr.redplane_udp.setInvalid(); 75 | hdr.redplane_req.setInvalid(); 76 | hdr.redplane_ack.setInvalid(); 77 | hdr.redplane_values.setInvalid(); 78 | } 79 | apply { 80 | // Redplane packet destined to the state store OR Write packet is processed 81 | if (eg_intr_md.egress_rid_first == 1 // replicated packet (RENEW ACK or RENEW REQ) 82 | || eg_md.bridged_md.is_write == 1 // RENEW REQ with write 83 | || (hdr.redplane_ack.isValid() && hdr.ipv4.isValid() ==false) // RENEW ACK without payload 84 | || eg_md.is_logged_req == true) 85 | { 86 | if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 87 | redplane_eg.apply(hdr, eg_md, eg_intr_md, eg_prsr_md, eg_dprsr_md); 88 | } 89 | } else if (hdr.redplane_req.req_type != req_type_t.LEASE_NEW_REQ) { 90 | invalidate_redplane_hdr(); 91 | } 92 | } 93 | } 94 | 95 | Pipeline( 96 | IngressParser(), 97 | Ingress(), 98 | IngressDeparser(), 99 | EgressParser(), 100 | Egress(), 101 | EgressDeparser() 102 | ) pipe; 103 | 104 | Switch(pipe) main; 105 | -------------------------------------------------------------------------------- /redplane-p4/sketch-snapshot/types.p4: -------------------------------------------------------------------------------- 1 | #ifndef _TYPES_ 2 | #define _TYPES_ 3 | 4 | typedef bit<48> mac_addr_t; 5 | typedef bit<16> ether_type_t; 6 | typedef bit<32> ipv4_addr_t; 7 | typedef bit<8> ip_protocol_t; 8 | typedef bit<16> udp_port_t; 9 | 10 | typedef bit<3> mirror_type_t; 11 | typedef bit<8> pkt_type_t; 12 | 13 | 14 | typedef bit<8> snapshot_meta_t; 15 | 16 | enum bit<8> req_type_t { 17 | LEASE_NEW_REQ = 0x0, 18 | LEASE_RENEW_REQ = 0x1, 19 | LEASE_NEW_ACK = 0x3, 20 | LEASE_RENEW_ACK = 0x4, 21 | LEASE_MIGRATE_ACK = 0x5 22 | } 23 | 24 | enum bit<8> ack_type_t { 25 | LEASE_NEW_ACK = 0x0, 26 | LEASE_RENEW_ACK = 0x1, 27 | LEASE_MIGRATE_ACK = 0x2 28 | } 29 | 30 | // Sketching 31 | // COMPILER: this structure should be generated by redplane compiler or given as a user-input. 32 | struct flow_key_t { 33 | bit<8> sketch_key; 34 | } 35 | 36 | struct flow_value_t { 37 | bit<32> sketch_1; 38 | bit<32> sketch_2; 39 | bit<32> sketch_3; 40 | } 41 | 42 | struct nat_meta_t { 43 | bool is_ext; 44 | } 45 | 46 | #endif /* _TYPES_ */ -------------------------------------------------------------------------------- /redplane-store/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.5) 2 | 3 | project(redplane-store) 4 | 5 | set(CMAKE_CXX_COMPILER g++) 6 | add_definitions(-std=c++11 -march=native -O3) 7 | add_definitions(-Wall -Wextra -Werror -pedantic -Wsign-conversion -Wold-style-cast) 8 | add_definitions(-Wno-unused-function -Wno-nested-anon-types -Wno-keyword-macro) 9 | 10 | set(LIBRARIES ${LIBRARIES} rt numa pthread gflags) 11 | 12 | find_library(IBVERBS_LIB ibverbs) 13 | if(NOT IBVERBS_LIB) 14 | message(FATAL_ERROR "ibverbs library not found") 15 | endif() 16 | 17 | set(LIBRARIES ${LIBRARIES} ibverbs) 18 | 19 | #Generate the shared library from the library sources 20 | add_library(raw_transport SHARED 21 | raw_transport/raw_transport.cc 22 | ) 23 | target_include_directories(raw_transport 24 | PUBLIC 25 | ${PROJECT_SOURCE_DIR} 26 | ) 27 | 28 | target_link_libraries(raw_transport ${LIBRARIES}) 29 | 30 | # Add an executable with the above sources 31 | #add_executable(sender 32 | # apps/transport_test/sender.cc 33 | #) 34 | #add_executable(receiver 35 | # apps/transport_test/receiver.cc 36 | #) 37 | #add_executable(test_cc 38 | # apps/test/test.cc 39 | #) 40 | 41 | add_executable(store_main 42 | apps/state_store/store_main.cc 43 | ) 44 | add_executable(store_chain 45 | apps/state_store/store_chain.cc 46 | ) 47 | add_executable(store_tester 48 | apps/state_store/store_tester.cc 49 | ) 50 | add_executable(raw_pktgen_lat 51 | apps/pktgen/pktgen_lat.cc 52 | ) 53 | add_executable(raw_pktgen_bw 54 | apps/pktgen/pktgen_bw.cc 55 | ) 56 | add_executable(server_nat 57 | apps/server_nat/nat_main.cc 58 | ) 59 | add_executable(nat_chain 60 | apps/server_nat/store_chain.cc 61 | ) 62 | 63 | # link the new hello_library target with the hello_binary target 64 | #target_link_libraries(sender 65 | # PRIVATE 66 | # raw_transport 67 | #) 68 | #target_link_libraries(receiver 69 | # PRIVATE 70 | # raw_transport 71 | #) 72 | 73 | target_link_libraries(store_main 74 | PRIVATE 75 | raw_transport 76 | ) 77 | 78 | target_link_libraries(store_chain 79 | PRIVATE 80 | raw_transport 81 | ) 82 | 83 | target_link_libraries(store_tester 84 | PRIVATE 85 | raw_transport 86 | ) 87 | 88 | target_link_libraries(raw_pktgen_lat 89 | PRIVATE 90 | raw_transport 91 | ) 92 | target_link_libraries(raw_pktgen_bw 93 | PRIVATE 94 | raw_transport 95 | ) 96 | 97 | target_link_libraries(server_nat 98 | PRIVATE 99 | raw_transport 100 | ) 101 | target_link_libraries(nat_chain 102 | PRIVATE 103 | raw_transport 104 | ) 105 | -------------------------------------------------------------------------------- /redplane-store/README.md: -------------------------------------------------------------------------------- 1 | # RedPlane state store 2 | 3 | Our state store implementation is built based on Mellanox's Raw ethernet verbs library and tested on Ubuntu 18.04 system with Mellanox ConnectX-5 NICs. 4 | It is compatible with `MLNX_OFED_LINUX-4.7-3.2.9.0`. 5 | 6 | ## Build Instructions 7 | 1. Create a build folder 8 | ```bash 9 | redplane-store$ mkdir build && cd build 10 | ``` 11 | 2. Build the applications using cmake 12 | ```bash 13 | build$ cmake .. && make 14 | ``` 15 | 16 | ## Acknowledgement 17 | We implemented the raw transport library based on the transport implementation in the [eRPC](https://github.com/erpc-io/eRPC) project. 18 | -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/m57_summary.txt: -------------------------------------------------------------------------------- 1 | 68.71.209.238 50810 80 40 2 | 68.71.209.238 50810 80 40 3 | 205.203.139.162 50812 80 40 4 | 68.71.209.238 50810 80 40 5 | 74.125.164.102 1636 80 40 6 | 74.125.164.102 1636 80 40 7 | 198.189.255.89 50839 80 40 8 | 205.203.139.162 50812 80 40 9 | 198.189.255.89 50839 80 40 10 | 68.71.209.238 50810 80 40 11 | 74.125.164.102 1637 80 48 12 | 74.125.164.102 1637 80 40 13 | 74.125.164.102 1637 80 728 14 | 74.125.164.102 1637 80 40 15 | 74.125.164.102 1637 80 40 16 | 74.125.164.102 1637 80 40 17 | 74.125.164.102 1637 80 40 18 | 74.125.164.102 1637 80 721 19 | 74.125.164.102 1637 80 40 20 | 74.125.164.102 1637 80 40 21 | 74.125.164.102 1637 80 40 22 | 74.125.164.102 1637 80 745 23 | 74.125.164.102 1637 80 40 24 | 74.125.164.102 1637 80 40 25 | 74.125.164.102 1637 80 710 26 | 74.125.164.102 1637 80 40 27 | 74.125.164.102 1637 80 710 28 | -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/parse_pcap.py: -------------------------------------------------------------------------------- 1 | from scapy.all import * 2 | import sys 3 | 4 | print(sys.argv[1]) 5 | packets = rdpcap(sys.argv[1], count = 100) 6 | out_file = open('m57_summary.txt',"w") 7 | ip_list = [] 8 | tcp_flows = [] 9 | udp_flows = [] 10 | total = 0 11 | for packet in packets: 12 | print (packet.time) 13 | if packet.haslayer(IP) and packet.haslayer(TCP): 14 | total += 1 15 | flow_key = (packet[IP].src, packet[IP].dst, packet[TCP].sport, packet[TCP].dport) 16 | if flow_key not in tcp_flows: 17 | tcp_flows.append(flow_key) 18 | elif packet.haslayer(IP) and packet.haslayer(UDP): 19 | total += 1 20 | flow_key = (packet[IP].src, packet[IP].dst, packet[UDP].sport, packet[UDP].dport) 21 | if flow_key not in udp_flows: 22 | udp_flows.append(flow_key) 23 | if packet.haslayer(TCP) and packet[IP].src.find('192.168') != -1: 24 | if packet[IP].dst not in ip_list: 25 | ip_list.append(packet[IP].dst) 26 | out_file.write('%s %d %d %d\n'%(packet[IP].dst, packet[TCP].sport, packet[TCP].dport, packet[IP].len)) 27 | if packet.haslayer(TCP) and packet[IP].dst.find('192.168') != -1: 28 | print (packet.show()) 29 | #if packet[IP].dst not in ip_list: 30 | # ip_list.append(packet[IP].dst) 31 | #out_file.write('%s %d %d %d\n'%(packet[IP].dst, packet[TCP].sport, packet[TCP].dport, packet[IP].len)) 32 | print ("Unique dest IP: %d" % len(ip_list)) 33 | print ("UDP flows: %d"%(len(udp_flows))) 34 | print ("TCP flows: %d"%(len(tcp_flows))) 35 | print ("Total packets: %d"%(total)) -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/pktgen.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "raw_transport/raw_transport.h" 14 | #include "redplane_header.h" 15 | 16 | DEFINE_bool(m_lat, false, "Measure per-packet processing latency"); 17 | DEFINE_uint32(threads, 1, "Number of workers"); 18 | DEFINE_string(filename, "", "Pcap filename"); 19 | DEFINE_string(destip, "198.19.10.0", "Destination IP address"); 20 | 21 | static constexpr uint16_t kUDPPort = 8000; 22 | static constexpr uint16_t kSwitchUDPPort = 4000; 23 | static constexpr uint16_t kNumThreads = 20; 24 | static constexpr uint16_t kLeasePeriod = 5; 25 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 26 | //static const uint8_t kDestMacAddr[6] = {0x28, 0x99, 0x3a, 0x73, 0x37, 0x6d}; // ToR2 27 | //static const uint8_t kDestMacAddr[6] = {0x98,0x5d,0x82,0x9c,0xef,0xb5}; // ToR3 28 | static const uint8_t kDestMacAddr[6] = {0x28,0x99,0x3a,0x9f,0xe7,0x5d}; // ToR3 29 | //static const uint8_t kDestMacAddr[6] = {0x28, 0x99, 0x3a, 0x73, 0xbc, 0xf9}; // ToR1 30 | // Globals 31 | volatile sig_atomic_t ctrl_c_pressed = 0; 32 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 33 | 34 | static std::vector 35 | get_lcores_for_numa_node(size_t numa_node) 36 | { 37 | assert(numa_node <= static_cast(numa_max_node())); 38 | 39 | std::vector ret; 40 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 41 | 42 | for (size_t i = 0; i < num_lcores; i++) 43 | { 44 | if (numa_node == static_cast(numa_node_of_cpu(i))) 45 | { 46 | ret.push_back(i); 47 | } 48 | } 49 | return ret; 50 | } 51 | 52 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 53 | { 54 | cpu_set_t cpuset; 55 | CPU_ZERO(&cpuset); 56 | assert(numa_node <= static_cast(numa_max_node())); 57 | 58 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 59 | size_t global_index = lcore_vec.at(numa_local_index); 60 | 61 | CPU_SET(global_index, &cpuset); 62 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 63 | &cpuset); 64 | assert(rc == 0); 65 | } 66 | 67 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 68 | { 69 | unsigned long sum = 0; 70 | const uint16_t *ip1; 71 | 72 | ip1 = reinterpret_cast(buf); 73 | while (hdr_len > 1) 74 | { 75 | sum += *ip1++; 76 | if (sum & 0x80000000) 77 | sum = (sum & 0xFFFF) + (sum >> 16); 78 | hdr_len -= 2; 79 | } 80 | 81 | while (sum >> 16) 82 | sum = (sum & 0xFFFF) + (sum >> 16); 83 | 84 | return (~sum); 85 | } 86 | 87 | void print_bytes(uint8_t *buffer) 88 | { 89 | size_t k, j, base; 90 | for (base = 0; base < 1; base++) 91 | { 92 | for (k = base * 256; k < (base * 256) + 256; k += 16) 93 | { 94 | for (j = 0; j < 15; j++) 95 | { 96 | fprintf(stderr, "%02x ", *(buffer + k + j)); 97 | } 98 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 99 | } 100 | fprintf(stderr, "\n"); 101 | } 102 | fprintf(stderr, "\n"); 103 | } 104 | -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/pktgen_bw.cc: -------------------------------------------------------------------------------- 1 | #include "pktgen.h" 2 | 3 | void pktgen_handler(std::string DestIpAddr) 4 | { 5 | std::random_device rd; //Get a random seed from the OS entropy device, or whatever 6 | std::mt19937_64 eng(rd()); //Use the 64-bit Mersenne Twister 19937 generator 7 | //and seed it with entropy. 8 | 9 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kSendRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 10 | if (send_buf == MAP_FAILED) 11 | { 12 | std::ostringstream xmsg; // The exception message 13 | xmsg << "Hugepage map failed "; 14 | throw std::runtime_error(xmsg.str()); 15 | } 16 | memset(send_buf, 0, redplane::RawTransport::kSendRingSize); 17 | redplane::RawTransport *raw_transport = new redplane::RawTransport(0, kPhyPorts, send_buf, redplane::RawTransport::kSendRingSize); 18 | //uint8_t **rx_ring = raw_transport->getRxRing(); 19 | 20 | std::vector send_pkt_addr; 21 | std::vector send_pkt_size; 22 | tcp_pkt_t *tcp_pkt_buf = reinterpret_cast(send_buf); 23 | // Get a routing info and fill in packet headers 24 | struct redplane::RawTransport::RoutingInfo local_ri; 25 | raw_transport->fill_local_routing_info(&local_ri); 26 | auto *ri = reinterpret_cast(&local_ri); 27 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 28 | { 29 | memcpy(tcp_pkt_buf[i].eth_hdr.src_mac, ri->mac, 6); 30 | memcpy(tcp_pkt_buf[i].eth_hdr.dst_mac, kDestMacAddr, 6); 31 | tcp_pkt_buf[i].eth_hdr.eth_type = htons(redplane::kIPEtherType); 32 | tcp_pkt_buf[i].ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 33 | tcp_pkt_buf[i].ipv4_hdr.dst_ip = redplane::ipv4_from_str(DestIpAddr.c_str()); 34 | tcp_pkt_buf[i].ipv4_hdr.version = 4; 35 | tcp_pkt_buf[i].ipv4_hdr.ihl = 5; 36 | tcp_pkt_buf[i].ipv4_hdr.ecn = 0; 37 | tcp_pkt_buf[i].ipv4_hdr.dscp = 0; 38 | tcp_pkt_buf[i].ipv4_hdr.id = htons(1); 39 | tcp_pkt_buf[i].ipv4_hdr.frag_off = htons(0); 40 | tcp_pkt_buf[i].ipv4_hdr.ttl = 64; 41 | tcp_pkt_buf[i].ipv4_hdr.protocol = redplane::kIPHdrTCPProtocol; 42 | tcp_pkt_buf[i].ipv4_hdr.check = 0; 43 | tcp_pkt_buf[i].ipv4_hdr.tot_len = htons(64); 44 | tcp_pkt_buf[i].ipv4_hdr.check = ip_checksum(&tcp_pkt_buf[i].ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 45 | tcp_pkt_buf[i].tcp_hdr.src_port = htons(1234); // UDP port of this thread 46 | tcp_pkt_buf[i].tcp_hdr.dst_port = htons(5678); 47 | tcp_pkt_buf[i].tcp_hdr.check = 0; 48 | send_pkt_addr.push_back(reinterpret_cast(&(tcp_pkt_buf[i]))); 49 | send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + 64); 50 | } 51 | 52 | while (true) 53 | { 54 | raw_transport->tx_burst(send_pkt_addr, send_pkt_size, send_pkt_size.size()); 55 | 56 | if (unlikely(ctrl_c_pressed == 1)) 57 | break; 58 | } 59 | munmap(send_buf, redplane::RawTransport::kSendRingSize); 60 | } 61 | 62 | int main(int argc, char **argv) 63 | { 64 | signal(SIGINT, ctrl_c_handler); 65 | gflags::ParseCommandLineFlags(&argc, &argv, true); 66 | 67 | assert(FLAGS_threads <= kNumThreads); 68 | 69 | std::thread req_handler_thread[kNumThreads]; 70 | 71 | for (size_t i = 0; i < FLAGS_threads; i++) 72 | { 73 | //req_handler_thread[i] = std::thread(req_handler, kUDPPort + i + 1, FLAGS_m_lat); 74 | req_handler_thread[i] = std::thread(pktgen_handler, FLAGS_destip); 75 | bind_to_core(req_handler_thread[i], 0, i); 76 | } 77 | 78 | while (1) 79 | { 80 | std::chrono::milliseconds dura(2000); 81 | std::this_thread::sleep_for(dura); 82 | if (unlikely(ctrl_c_pressed == 1)) 83 | break; 84 | } 85 | 86 | for (size_t i = 0; i < FLAGS_threads; i++) 87 | { 88 | req_handler_thread[i].join(); 89 | } 90 | 91 | return 0; 92 | } -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/pktgen_lat.cc: -------------------------------------------------------------------------------- 1 | #include "pktgen.h" 2 | 3 | void pktgen_handler(std::string pcap_file) 4 | { 5 | std::random_device rd; //Get a random seed from the OS entropy device, or whatever 6 | std::mt19937_64 eng(rd()); //Use the 64-bit Mersenne Twister 19937 generator 7 | //and seed it with entropy. 8 | 9 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kSendRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 10 | if (send_buf == MAP_FAILED) 11 | { 12 | std::ostringstream xmsg; // The exception message 13 | xmsg << "Hugepage map failed "; 14 | throw std::runtime_error(xmsg.str()); 15 | } 16 | memset(send_buf, 0, redplane::RawTransport::kSendRingSize); 17 | redplane::RawTransport *raw_transport = new redplane::RawTransport(0, kPhyPorts, send_buf, redplane::RawTransport::kSendRingSize); 18 | //uint8_t **rx_ring = raw_transport->getRxRing(); 19 | 20 | tcp_pkt_t *tcp_pkt_buf = reinterpret_cast(send_buf); 21 | // Get a routing info and fill in packet headers 22 | struct redplane::RawTransport::RoutingInfo local_ri; 23 | raw_transport->fill_local_routing_info(&local_ri); 24 | auto *ri = reinterpret_cast(&local_ri); 25 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 26 | { 27 | memcpy(tcp_pkt_buf[i].eth_hdr.src_mac, ri->mac, 6); 28 | memcpy(tcp_pkt_buf[i].eth_hdr.dst_mac, kDestMacAddr, 6); 29 | tcp_pkt_buf[i].eth_hdr.eth_type = htons(redplane::kIPEtherType); 30 | tcp_pkt_buf[i].ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 31 | tcp_pkt_buf[i].ipv4_hdr.version = 4; 32 | tcp_pkt_buf[i].ipv4_hdr.ihl = 5; 33 | tcp_pkt_buf[i].ipv4_hdr.ecn = 0; 34 | tcp_pkt_buf[i].ipv4_hdr.dscp = 0; 35 | tcp_pkt_buf[i].ipv4_hdr.id = htons(1); 36 | tcp_pkt_buf[i].ipv4_hdr.frag_off = htons(0); 37 | tcp_pkt_buf[i].ipv4_hdr.ttl = 64; 38 | tcp_pkt_buf[i].ipv4_hdr.protocol = redplane::kIPHdrTCPProtocol; 39 | tcp_pkt_buf[i].tcp_hdr.check = 0; 40 | } 41 | 42 | size_t send_ring_idx = 0; 43 | std::ifstream infile (pcap_file); 44 | std::string line; 45 | std::vector send_pkt_addr; 46 | std::vector send_pkt_size; 47 | 48 | std::unordered_map dst_ip_map; 49 | std::uniform_int_distribution distr; 50 | 51 | FILE* flat = fopen("latency.txt", "w"); 52 | 53 | size_t count = 0; 54 | while (std::getline(infile, line)) { 55 | std::istringstream iss(line); 56 | std::string dst_ip; 57 | uint16_t sport, dport, len; 58 | iss >> dst_ip >> sport >> dport >> len; 59 | uint32_t dst_ip_translated = 0; 60 | if (dst_ip_map.find(dst_ip) != dst_ip_map.end()) { 61 | dst_ip_translated = dst_ip_map[dst_ip]; 62 | } else { 63 | //dst_ip_translated = 0xc6130a00 + distr(eng) % 255 + 1; 64 | dst_ip_translated = 0xc6130b00; // For server-NAT emulation 65 | dst_ip_map[dst_ip] = dst_ip_translated; 66 | } 67 | tcp_pkt_buf[send_ring_idx].ipv4_hdr.check = 0; 68 | tcp_pkt_buf[send_ring_idx].ipv4_hdr.dst_ip = htonl(dst_ip_translated); 69 | tcp_pkt_buf[send_ring_idx].ipv4_hdr.tot_len = htons(len); 70 | tcp_pkt_buf[send_ring_idx].ipv4_hdr.check = ip_checksum(&tcp_pkt_buf[send_ring_idx].ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 71 | tcp_pkt_buf[send_ring_idx].tcp_hdr.src_port = htons(sport); // UDP port of this thread 72 | tcp_pkt_buf[send_ring_idx].tcp_hdr.dst_port = htons(dport); 73 | 74 | send_pkt_addr.push_back(reinterpret_cast(&(tcp_pkt_buf[send_ring_idx]))); 75 | send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + len); 76 | 77 | auto start = std::chrono::high_resolution_clock::now(); 78 | raw_transport->tx_burst(send_pkt_addr, send_pkt_size, 1); 79 | 80 | size_t num_pkts = 0; 81 | while (1) 82 | { 83 | num_pkts = raw_transport->rx_burst(); 84 | if (num_pkts == 1) { 85 | break; 86 | } 87 | if (unlikely(ctrl_c_pressed == 1)) 88 | return; 89 | } 90 | auto stop = std::chrono::high_resolution_clock::now(); 91 | raw_transport->post_recvs(num_pkts); 92 | auto duration = std::chrono::duration_cast(stop - start); 93 | uint32_t latency_us = (static_cast(duration.count())); 94 | fprintf(stderr, "%ld end\n", count); 95 | fprintf(flat, "%d\n", latency_us); 96 | count ++; 97 | send_ring_idx = (send_ring_idx + 1) % redplane::RawTransport::kSQDepth; 98 | send_pkt_addr.clear(); 99 | send_pkt_size.clear(); 100 | if (count == 100) { 101 | break; 102 | } 103 | usleep(5000); 104 | } 105 | fclose(flat); 106 | munmap(send_buf, redplane::RawTransport::kSendRingSize); 107 | } 108 | 109 | int main(int argc, char **argv) 110 | { 111 | signal(SIGINT, ctrl_c_handler); 112 | gflags::ParseCommandLineFlags(&argc, &argv, true); 113 | 114 | assert(FLAGS_threads <= kNumThreads); 115 | 116 | std::thread req_handler_thread[kNumThreads]; 117 | 118 | for (size_t i = 0; i < FLAGS_threads; i++) 119 | { 120 | //req_handler_thread[i] = std::thread(req_handler, kUDPPort + i + 1, FLAGS_m_lat); 121 | req_handler_thread[i] = std::thread(pktgen_handler, FLAGS_filename); 122 | bind_to_core(req_handler_thread[i], 0, i); 123 | } 124 | 125 | while (1) 126 | { 127 | std::chrono::milliseconds dura(2000); 128 | std::this_thread::sleep_for(dura); 129 | if (unlikely(ctrl_c_pressed == 1)) 130 | break; 131 | } 132 | 133 | for (size_t i = 0; i < FLAGS_threads; i++) 134 | { 135 | req_handler_thread[i].join(); 136 | } 137 | 138 | return 0; 139 | } -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/redplane_header.h: -------------------------------------------------------------------------------- 1 | #include "raw_transport/raw_transport.h" 2 | 3 | static constexpr size_t kOriginMTU = 2048; 4 | enum class req_type_t: uint8_t { 5 | LEASE_NEW_REQ = 0x0, 6 | LEASE_RENEW_REQ = 0x1, 7 | }; 8 | 9 | enum class ack_type_t: uint8_t { 10 | LEASE_NEW_ACK = 0x0, 11 | LEASE_RENEW_ACK = 0x1, 12 | LEASE_MIGRATE_ACK = 0x2 13 | }; 14 | 15 | /* NAT NF example */ 16 | struct req_flow_key_t 17 | { 18 | uint32_t ip_addr; 19 | uint16_t port; 20 | 21 | bool operator == (const req_flow_key_t &key) const { 22 | return (ip_addr == key.ip_addr 23 | && port == key.port); 24 | } 25 | } __attribute__((packed)); 26 | 27 | struct req_value_t { 28 | uint32_t ip_addr; 29 | uint16_t port; 30 | bool operator == (const req_value_t &value) const { 31 | return (ip_addr == value.ip_addr 32 | && port == value.port); 33 | } 34 | } __attribute__((packed)); 35 | 36 | struct hash_fn_t { 37 | size_t operator()(const req_flow_key_t &key) const 38 | { 39 | return (std::hash()(key.ip_addr) 40 | ^ std::hash()(key.port)); 41 | } 42 | size_t operator()(const req_value_t &value ) const 43 | { 44 | return (std::hash()(value.ip_addr) 45 | ^ std::hash()(value.port)); 46 | } 47 | }; 48 | 49 | struct equal_fn_t { 50 | bool operator()(const req_flow_key_t &key1, const req_flow_key_t &key2) const 51 | { 52 | return (key1.ip_addr == key2.ip_addr 53 | && key1.port == key2.port); 54 | } 55 | size_t operator()(const req_value_t &value1, const req_value_t &value2 ) const 56 | { 57 | return (value1.ip_addr == value2.ip_addr 58 | && value1.port == value2.port); 59 | } 60 | }; 61 | 62 | struct tcp_pkt_t 63 | { 64 | redplane::eth_hdr_t eth_hdr; 65 | redplane::ipv4_hdr_t ipv4_hdr; 66 | redplane::tcp_hdr_t tcp_hdr; 67 | uint8_t payload[kOriginMTU-sizeof(redplane::ipv4_hdr_t)-sizeof(redplane::tcp_hdr_t)]; 68 | } __attribute__((packed)); 69 | -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/tests/pktgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | import threading 10 | 11 | if os.getuid() !=0: 12 | print """ 13 | ERROR: This script requires root privileges. 14 | Use 'sudo' to run it. 15 | """ 16 | quit() 17 | 18 | from scapy.all import * 19 | 20 | flow_vals = {} 21 | NUM_TEST_KEYS = 1000 22 | 23 | txn_type_enum = { 0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ", 24 | 0x2: "LEASE_NEW_ACK", 0x3: "LEASE_RENEW_ACK", 25 | 0x4: "LEASE_MIGRATE_ACK" } 26 | class RedplaneAck (Packet): 27 | name = "RedPlane ACK header" 28 | fields_desc = [ BitEnumField("ack_type", 0, 8, txn_type_enum), 29 | BitField("seq_num", 0, 32), 30 | BitField("lease_expire_time", 0, 32), 31 | BitField("flow_key", 0, 104) 32 | ] 33 | class RedplaneState (Packet): 34 | name = "RedPlane State header" 35 | fields_desc = [ BitField("State", 0, 32) 36 | ] 37 | 38 | bind_layers(UDP, RedplaneAck, dport=4000) 39 | bind_layers(RedplaneAck, RedplaneState, ack_type=0x4) 40 | bind_layers(RedplaneState, IP) 41 | bind_layers(RedplaneAck, IP, ack_type=0x2) 42 | bind_layers(RedplaneAck, IP, ack_type=0x3) 43 | 44 | class RedplaneTxn (Packet): 45 | name = "RedPlane transaction header" 46 | fields_desc = [ BitEnumField("txn_type", 0, 8, txn_type_enum), 47 | BitField("seq_num", 0, 32), 48 | BitField("flow_key", 0, 104), 49 | BitField("flow_value", 0, 32) 50 | ] 51 | 52 | bind_layers(UDP, RedplaneTxn, sport=4000) 53 | bind_layers(RedplaneTxn, IP) 54 | 55 | # Send txn from a switch to a state store 56 | def send_write_txn (src_ip, dst_ip, dest_port, flow_key, flow_val, txn_type, seq_num, payload_size): 57 | p = (Ether()/ 58 | IP(dst=dst_ip, src=src_ip)/ 59 | UDP(sport=4000, dport=dest_port)/ 60 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=flow_key, flow_value=flow_val)/ 61 | IP()/ 62 | #TCP()/ 63 | Raw(RandString(size=payload_size))) 64 | 65 | sendp(p, iface="ens1", count = 1) 66 | 67 | def send_read_txn (src_ip, dst_ip, dest_port, txn_type, seq_num): 68 | p = (Ether()/ 69 | IP(dst=dst_ip, src=src_ip)/ 70 | UDP(sport=4000, dport=dest_port)/ 71 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=0)) 72 | 73 | sendp(p, iface="ens1", count = 1) 74 | 75 | def print_pkt (pkt): 76 | flow_key = int(pkt[RedplaneAck].flow_key) 77 | assert(flow_vals[flow_key] == int(pkt[RedplaneState].State)) 78 | 79 | def sniff_thread(): 80 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt, count = NUM_TEST_KEYS) 81 | 82 | if __name__ == "__main__": 83 | 84 | payload_size = int(sys.argv[1]) 85 | flow_keys = [] 86 | 87 | print ("LEASE_NEW_REQ") 88 | # send LEASE_NEW_REQ 89 | for i in range(0, NUM_TEST_KEYS): 90 | while True: 91 | flow_key = random.getrandbits(104) 92 | if flow_key in flow_keys: 93 | continue 94 | flow_keys.append(flow_key) 95 | break 96 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_key, 0, 0x0, 0, payload_size) 97 | 98 | print ("LEASE_RENEW_REQ (WRITE)") 99 | # send LEASE_RENEW_REQ (WRITE) 100 | accessed = [] 101 | count = 0 102 | while True: 103 | idx = random.randint(0, NUM_TEST_KEYS-1) 104 | if idx in accessed: 105 | continue 106 | flow_val = random.getrandbits(32) 107 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[idx], flow_val, 0x1, 1, payload_size) 108 | accessed.append(idx) 109 | flow_vals[flow_keys[idx]] = flow_val 110 | count = count + 1 111 | if count == NUM_TEST_KEYS: 112 | break 113 | 114 | print ("LEASE_NEW_REQ (MIGRATE))") 115 | ## send LEASE_NEW_REQ (MIGRATE) 116 | sniff_th = threading.Thread(target=sniff_thread, args=()) 117 | sniff_th.start() 118 | time.sleep(1) 119 | for i in range(0, NUM_TEST_KEYS): 120 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[i], 0, 0x0, 0, payload_size) 121 | sniff_th.join() 122 | -------------------------------------------------------------------------------- /redplane-store/apps/pktgen/tests/recv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | 10 | if os.getuid() !=0: 11 | print """ 12 | ERROR: This script requires root privileges. 13 | Use 'sudo' to run it. 14 | """ 15 | quit() 16 | 17 | from scapy.all import * 18 | ######### Redplane packet definition ########### 19 | req_type_enum = {0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ"} 20 | ack_type_enum = {0x0: "LEASE_NEW_ACK", 0x1: "LEASE_RENEW_ACK", 21 | 0x2: "LEASE_MIGRATE_ACK"} 22 | 23 | 24 | class RedplaneAck (Packet): 25 | name = "RedPlane ACK header" 26 | fields_desc = [BitEnumField("ack_type", 0, 8, ack_type_enum), 27 | BitField("seq_num", 0, 16), 28 | IPField("src_addr_k", None), 29 | IPField("dst_addr_k", None), 30 | ShortField("src_port_k", None), 31 | ShortField("dst_port_k", None), 32 | ByteField("protocol_k", None) 33 | ] 34 | 35 | 36 | class RedplaneValue (Packet): 37 | name = "RedPlane State header" 38 | fields_desc = [ 39 | IPField("dst_addr_v", None), 40 | ShortField("dst_port_v", None) 41 | ] 42 | 43 | 44 | bind_layers(UDP, RedplaneAck, dport=4000) 45 | bind_layers(RedplaneAck, RedplaneValue, ack_type=0x2) 46 | bind_layers(RedplaneValue, IP) 47 | bind_layers(RedplaneAck, IP, ack_type=0x0) 48 | bind_layers(RedplaneAck, IP, ack_type=0x1) 49 | 50 | 51 | class RedplaneReq (Packet): 52 | name = "RedPlane transaction header" 53 | fields_desc = [BitEnumField("req_type", 0, 8, req_type_enum), 54 | BitField("seq_num", 0, 16), 55 | IPField("src_addr_k", None), 56 | IPField("dst_addr_k", None), 57 | ShortField("src_port_k", None), 58 | ShortField("dst_port_k", None), 59 | ByteField("protocol_k", None), 60 | IPField("dst_addr_v", None), 61 | ShortField("dst_port_v", None) 62 | ] 63 | 64 | 65 | bind_layers(UDP, RedplaneReq, sport=4000) 66 | bind_layers(RedplaneReq, IP) 67 | 68 | def print_pkt (pkt): 69 | print(pkt.show()) 70 | 71 | if __name__ == "__main__": 72 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt) -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/nat_main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "raw_transport/raw_transport.h" 14 | #include "redplane_header.h" 15 | 16 | DEFINE_uint32(threads, 1, "Number of workers"); 17 | DEFINE_bool(chain, false, "Enabling chain replication"); 18 | DEFINE_string(nextip, "198.19.11.1", "Next node's IP"); 19 | DEFINE_string(tailip, "198.19.13.0", "Tail node's IP"); 20 | 21 | static constexpr uint16_t kChainUDPPort = 9000; 22 | static constexpr uint16_t kSwitchUDPPort = 4000; 23 | static constexpr uint16_t kNumThreads = 20; 24 | static constexpr uint16_t kLeasePeriod = 5; 25 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 26 | static const uint8_t kDestMacAddr[6] = {0x28, 0x99, 0x3a, 0x73, 0x37, 0x6d}; 27 | 28 | // Globals 29 | volatile sig_atomic_t ctrl_c_pressed = 0; 30 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 31 | 32 | static std::vector 33 | get_lcores_for_numa_node(size_t numa_node) 34 | { 35 | assert(numa_node <= static_cast(numa_max_node())); 36 | 37 | std::vector ret; 38 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 39 | 40 | for (size_t i = 0; i < num_lcores; i++) 41 | { 42 | if (numa_node == static_cast(numa_node_of_cpu(i))) 43 | { 44 | ret.push_back(i); 45 | } 46 | } 47 | return ret; 48 | } 49 | 50 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 51 | { 52 | cpu_set_t cpuset; 53 | CPU_ZERO(&cpuset); 54 | assert(numa_node <= static_cast(numa_max_node())); 55 | 56 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 57 | size_t global_index = lcore_vec.at(numa_local_index); 58 | 59 | CPU_SET(global_index, &cpuset); 60 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 61 | &cpuset); 62 | assert(rc == 0); 63 | } 64 | 65 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 66 | { 67 | unsigned long sum = 0; 68 | const uint16_t *ip1; 69 | 70 | ip1 = reinterpret_cast(buf); 71 | while (hdr_len > 1) 72 | { 73 | sum += *ip1++; 74 | if (sum & 0x80000000) 75 | sum = (sum & 0xFFFF) + (sum >> 16); 76 | hdr_len -= 2; 77 | } 78 | 79 | while (sum >> 16) 80 | sum = (sum & 0xFFFF) + (sum >> 16); 81 | 82 | return (~sum); 83 | } 84 | 85 | void print_bytes(uint8_t *buffer) 86 | { 87 | size_t k, j, base; 88 | for (base = 0; base < 1; base++) 89 | { 90 | for (k = base * 256; k < (base * 256) + 256; k += 16) 91 | { 92 | for (j = 0; j < 15; j++) 93 | { 94 | fprintf(stderr, "%02x ", *(buffer + k + j)); 95 | } 96 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 97 | } 98 | fprintf(stderr, "\n"); 99 | } 100 | fprintf(stderr, "\n"); 101 | } -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/redplane_header.h: -------------------------------------------------------------------------------- 1 | #include "raw_transport/raw_transport.h" 2 | 3 | static constexpr size_t kOriginMTU = 2048; 4 | enum class req_type_t: uint8_t { 5 | LEASE_NEW_REQ = 0x0, 6 | LEASE_RENEW_REQ = 0x1, 7 | }; 8 | 9 | enum class ack_type_t: uint8_t { 10 | LEASE_NEW_ACK = 0x0, 11 | LEASE_RENEW_ACK = 0x1, 12 | LEASE_MIGRATE_ACK = 0x2 13 | }; 14 | 15 | /* NAT NF example */ 16 | struct req_flow_key_t 17 | { 18 | uint32_t ip_addr; 19 | uint16_t port; 20 | 21 | bool operator == (const req_flow_key_t &key) const { 22 | return (ip_addr == key.ip_addr 23 | && port == key.port); 24 | } 25 | } __attribute__((packed)); 26 | 27 | struct req_value_t { 28 | uint32_t ip_addr; 29 | uint16_t port; 30 | bool operator == (const req_value_t &value) const { 31 | return (ip_addr == value.ip_addr 32 | && port == value.port); 33 | } 34 | } __attribute__((packed)); 35 | 36 | struct hash_fn_t { 37 | size_t operator()(const req_flow_key_t &key) const 38 | { 39 | return (std::hash()(key.ip_addr) 40 | ^ std::hash()(key.port)); 41 | } 42 | size_t operator()(const req_value_t &value ) const 43 | { 44 | return (std::hash()(value.ip_addr) 45 | ^ std::hash()(value.port)); 46 | } 47 | }; 48 | 49 | struct equal_fn_t { 50 | bool operator()(const req_flow_key_t &key1, const req_flow_key_t &key2) const 51 | { 52 | return (key1.ip_addr == key2.ip_addr 53 | && key1.port == key2.port); 54 | } 55 | size_t operator()(const req_value_t &value1, const req_value_t &value2 ) const 56 | { 57 | return (value1.ip_addr == value2.ip_addr 58 | && value1.port == value2.port); 59 | } 60 | }; 61 | 62 | // Redplane request header 63 | struct req_header_t { 64 | redplane::ipv4_hdr_t ipv4_hdr; 65 | redplane::udp_hdr_t udp_hdr; 66 | req_type_t req_type; 67 | uint16_t seq_num; 68 | req_flow_key_t flow_key; 69 | req_value_t value; 70 | } __attribute__((packed)); 71 | 72 | // Redplane ack header 73 | struct ack_header_t { 74 | redplane::ipv4_hdr_t ipv4_hdr; 75 | redplane::udp_hdr_t udp_hdr; 76 | ack_type_t ack_type; 77 | uint16_t seq_num; 78 | req_flow_key_t flow_key; 79 | } __attribute__((packed)); 80 | 81 | struct redplane_req_pkt_t 82 | { 83 | redplane::eth_hdr_t eth_hdr; 84 | req_header_t req_header; 85 | redplane::ipv4_hdr_t original_ipv4_hdr; 86 | uint8_t original_packet[kOriginMTU-sizeof(redplane::ipv4_hdr_t)]; 87 | } __attribute__((packed)); 88 | 89 | struct redplane_ack_pkt_t 90 | { 91 | redplane::eth_hdr_t eth_hdr; 92 | ack_header_t ack_header; 93 | uint8_t reserved[kOriginMTU]; 94 | } __attribute__((packed)); 95 | 96 | struct tcp_pkt_t 97 | { 98 | redplane::eth_hdr_t eth_hdr; 99 | redplane::ipv4_hdr_t ipv4_hdr; 100 | redplane::tcp_hdr_t tcp_hdr; 101 | uint8_t payload[kOriginMTU-sizeof(redplane::ipv4_hdr_t)-sizeof(redplane::tcp_hdr_t)]; 102 | } __attribute__((packed)); 103 | -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/store_chain.cc: -------------------------------------------------------------------------------- 1 | #include "store_chain.h" 2 | 3 | void req_handler(std::string NextIpAddr) 4 | { 5 | // Key-value store 6 | std::unordered_map state_store; 7 | 8 | /********************************************* Setup chain replication *****************************************************/ 9 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kSendRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 10 | if (send_buf == MAP_FAILED) 11 | { 12 | std::ostringstream xmsg; // The exception message 13 | xmsg << "Hugepage map failed "; 14 | throw std::runtime_error(xmsg.str()); 15 | } 16 | memset(send_buf, 0, redplane::RawTransport::kSendRingSize); 17 | redplane::RawTransport *raw_transport = new redplane::RawTransport(kChainUDPPort, kPhyPorts, send_buf, redplane::RawTransport::kSendRingSize); 18 | uint8_t **rx_ring_chain = raw_transport->getRxRing(); 19 | redplane_req_pkt_t *redplane_req_pkt_buf = reinterpret_cast(send_buf); 20 | // Get a routing info and fill in packet headers 21 | struct redplane::RawTransport::RoutingInfo local_ri_chain; 22 | raw_transport->fill_local_routing_info(&local_ri_chain); 23 | // Prepare a template of ack packets 24 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 25 | { 26 | auto *ri = reinterpret_cast(&local_ri_chain); 27 | memcpy(redplane_req_pkt_buf[i].eth_hdr.src_mac, ri->mac, 6); 28 | redplane_req_pkt_buf[i].eth_hdr.eth_type = htons(redplane::kIPEtherType); 29 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 30 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dst_ip = redplane::ipv4_from_str(NextIpAddr.c_str()); 31 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.version = 4; 32 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ihl = 5; 33 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ecn = 0; 34 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dscp = 0; 35 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.id = htons(1); 36 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.frag_off = htons(0); 37 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.tot_len = htons(sizeof(req_header_t)); 38 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ttl = 64; 39 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.protocol = redplane::kIPHdrProtocol; 40 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.check = ip_checksum(&redplane_req_pkt_buf[i].req_header.ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 41 | redplane_req_pkt_buf[i].req_header.udp_hdr.src_port = htons(kChainUDPPort); // UDP port of this thread 42 | redplane_req_pkt_buf[i].req_header.udp_hdr.dst_port = htons(kChainUDPPort); 43 | redplane_req_pkt_buf[i].req_header.udp_hdr.len = htons(sizeof(req_header_t)-sizeof(redplane::ipv4_hdr_t)); 44 | redplane_req_pkt_buf[i].req_header.udp_hdr.check = 0; 45 | } 46 | /*************************************************************************************************************************/ 47 | 48 | redplane_req_pkt_t *req_pkt; 49 | size_t send_ring_idx = 0; 50 | size_t last_rx_ring_idx = 0; 51 | std::vector send_pkt_addr; 52 | std::vector send_pkt_size; 53 | while (true) 54 | { 55 | size_t num_pkts = raw_transport->rx_burst(); 56 | if (num_pkts > 0) 57 | { 58 | //fprintf(stderr, "Chain received! %ld\n", num_pkts); 59 | for (size_t i = last_rx_ring_idx; i < last_rx_ring_idx + num_pkts; i++) 60 | { 61 | size_t idx = i % redplane::RawTransport::kNumRxRingEntries; 62 | req_pkt = reinterpret_cast(rx_ring_chain[idx]); 63 | state_store[req_pkt->req_header.flow_key] = req_pkt->req_header.value; 64 | 65 | redplane_req_pkt_buf[send_ring_idx].req_header.seq_num = req_pkt->req_header.seq_num; 66 | memcpy(&(redplane_req_pkt_buf[send_ring_idx].req_header.flow_key), &(req_pkt->req_header.flow_key), sizeof(req_flow_key_t)); 67 | memcpy(&(redplane_req_pkt_buf[send_ring_idx].req_header.value), &(req_pkt->req_header.value), sizeof(req_value_t)); 68 | memcpy(redplane_req_pkt_buf[send_ring_idx].eth_hdr.dst_mac, req_pkt->eth_hdr.src_mac, 6); 69 | send_pkt_addr.push_back(reinterpret_cast(&(redplane_req_pkt_buf[send_ring_idx]))); 70 | send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + sizeof(req_header_t)); 71 | send_ring_idx = (send_ring_idx + 1) % redplane::RawTransport::kSQDepth; 72 | } 73 | raw_transport->tx_burst(send_pkt_addr, send_pkt_size, send_pkt_size.size()); 74 | raw_transport->post_recvs(num_pkts); 75 | send_pkt_size.clear(); 76 | send_pkt_addr.clear(); 77 | last_rx_ring_idx = (last_rx_ring_idx + num_pkts) % redplane::RawTransport::kNumRxRingEntries; 78 | } 79 | 80 | if (unlikely(ctrl_c_pressed == 1)) 81 | break; 82 | } 83 | munmap(send_buf, redplane::RawTransport::kSendRingSize); 84 | } 85 | 86 | int main(int argc, char **argv) 87 | { 88 | signal(SIGINT, ctrl_c_handler); 89 | gflags::ParseCommandLineFlags(&argc, &argv, true); 90 | 91 | assert(FLAGS_threads <= kNumThreads); 92 | 93 | std::thread req_handler_thread[kNumThreads]; 94 | 95 | for (size_t i = 0; i < FLAGS_threads; i++) 96 | { 97 | req_handler_thread[i] = std::thread(req_handler, FLAGS_nextip); 98 | bind_to_core(req_handler_thread[i], 0, i); 99 | } 100 | 101 | while (1) 102 | { 103 | std::chrono::milliseconds dura(2000); 104 | std::this_thread::sleep_for(dura); 105 | if (unlikely(ctrl_c_pressed == 1)) 106 | break; 107 | } 108 | 109 | for (size_t i = 0; i < FLAGS_threads; i++) 110 | { 111 | req_handler_thread[i].join(); 112 | } 113 | 114 | return 0; 115 | } -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/store_chain.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "raw_transport/raw_transport.h" 11 | #include "redplane_header.h" 12 | 13 | DEFINE_uint32(threads, 1, "Number of workers"); 14 | DEFINE_string(nextip, "198.19.11.1", "Next node's IP"); 15 | 16 | static constexpr uint16_t kChainUDPPort = 9000; 17 | static constexpr uint16_t kSwitchUDPPort = 4000; 18 | static constexpr uint16_t kNumThreads = 20; 19 | static constexpr uint16_t kLeasePeriod = 5; 20 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 21 | 22 | // Globals 23 | volatile sig_atomic_t ctrl_c_pressed = 0; 24 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 25 | 26 | static std::vector 27 | get_lcores_for_numa_node(size_t numa_node) 28 | { 29 | assert(numa_node <= static_cast(numa_max_node())); 30 | 31 | std::vector ret; 32 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 33 | 34 | for (size_t i = 0; i < num_lcores; i++) 35 | { 36 | if (numa_node == static_cast(numa_node_of_cpu(i))) 37 | { 38 | ret.push_back(i); 39 | } 40 | } 41 | return ret; 42 | } 43 | 44 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 45 | { 46 | cpu_set_t cpuset; 47 | CPU_ZERO(&cpuset); 48 | assert(numa_node <= static_cast(numa_max_node())); 49 | 50 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 51 | size_t global_index = lcore_vec.at(numa_local_index); 52 | 53 | CPU_SET(global_index, &cpuset); 54 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 55 | &cpuset); 56 | assert(rc == 0); 57 | } 58 | 59 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 60 | { 61 | unsigned long sum = 0; 62 | const uint16_t *ip1; 63 | 64 | ip1 = reinterpret_cast(buf); 65 | while (hdr_len > 1) 66 | { 67 | sum += *ip1++; 68 | if (sum & 0x80000000) 69 | sum = (sum & 0xFFFF) + (sum >> 16); 70 | hdr_len -= 2; 71 | } 72 | 73 | while (sum >> 16) 74 | sum = (sum & 0xFFFF) + (sum >> 16); 75 | 76 | return (~sum); 77 | } 78 | 79 | void print_bytes(uint8_t *buffer) 80 | { 81 | size_t k, j, base; 82 | for (base = 0; base < 1; base++) 83 | { 84 | for (k = base * 256; k < (base * 256) + 256; k += 16) 85 | { 86 | for (j = 0; j < 15; j++) 87 | { 88 | fprintf(stderr, "%02x ", *(buffer + k + j)); 89 | } 90 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 91 | } 92 | fprintf(stderr, "\n"); 93 | } 94 | fprintf(stderr, "\n"); 95 | } -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/tests/pktgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | import threading 10 | 11 | if os.getuid() !=0: 12 | print """ 13 | ERROR: This script requires root privileges. 14 | Use 'sudo' to run it. 15 | """ 16 | quit() 17 | 18 | from scapy.all import * 19 | 20 | flow_vals = {} 21 | NUM_TEST_KEYS = 1000 22 | 23 | txn_type_enum = { 0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ", 24 | 0x2: "LEASE_NEW_ACK", 0x3: "LEASE_RENEW_ACK", 25 | 0x4: "LEASE_MIGRATE_ACK" } 26 | class RedplaneAck (Packet): 27 | name = "RedPlane ACK header" 28 | fields_desc = [ BitEnumField("ack_type", 0, 8, txn_type_enum), 29 | BitField("seq_num", 0, 32), 30 | BitField("lease_expire_time", 0, 32), 31 | BitField("flow_key", 0, 104) 32 | ] 33 | class RedplaneState (Packet): 34 | name = "RedPlane State header" 35 | fields_desc = [ BitField("State", 0, 32) 36 | ] 37 | 38 | bind_layers(UDP, RedplaneAck, dport=4000) 39 | bind_layers(RedplaneAck, RedplaneState, ack_type=0x4) 40 | bind_layers(RedplaneState, IP) 41 | bind_layers(RedplaneAck, IP, ack_type=0x2) 42 | bind_layers(RedplaneAck, IP, ack_type=0x3) 43 | 44 | class RedplaneTxn (Packet): 45 | name = "RedPlane transaction header" 46 | fields_desc = [ BitEnumField("txn_type", 0, 8, txn_type_enum), 47 | BitField("seq_num", 0, 32), 48 | BitField("flow_key", 0, 104), 49 | BitField("flow_value", 0, 32) 50 | ] 51 | 52 | bind_layers(UDP, RedplaneTxn, sport=4000) 53 | bind_layers(RedplaneTxn, IP) 54 | 55 | # Send txn from a switch to a state store 56 | def send_write_txn (src_ip, dst_ip, dest_port, flow_key, flow_val, txn_type, seq_num, payload_size): 57 | p = (Ether()/ 58 | IP(dst=dst_ip, src=src_ip)/ 59 | UDP(sport=4000, dport=dest_port)/ 60 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=flow_key, flow_value=flow_val)/ 61 | IP()/ 62 | #TCP()/ 63 | Raw(RandString(size=payload_size))) 64 | 65 | sendp(p, iface="ens1", count = 1) 66 | 67 | def send_read_txn (src_ip, dst_ip, dest_port, txn_type, seq_num): 68 | p = (Ether()/ 69 | IP(dst=dst_ip, src=src_ip)/ 70 | UDP(sport=4000, dport=dest_port)/ 71 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=0)) 72 | 73 | sendp(p, iface="ens1", count = 1) 74 | 75 | def print_pkt (pkt): 76 | flow_key = int(pkt[RedplaneAck].flow_key) 77 | assert(flow_vals[flow_key] == int(pkt[RedplaneState].State)) 78 | 79 | def sniff_thread(): 80 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt, count = NUM_TEST_KEYS) 81 | 82 | if __name__ == "__main__": 83 | 84 | payload_size = int(sys.argv[1]) 85 | flow_keys = [] 86 | 87 | print ("LEASE_NEW_REQ") 88 | # send LEASE_NEW_REQ 89 | for i in range(0, NUM_TEST_KEYS): 90 | while True: 91 | flow_key = random.getrandbits(104) 92 | if flow_key in flow_keys: 93 | continue 94 | flow_keys.append(flow_key) 95 | break 96 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_key, 0, 0x0, 0, payload_size) 97 | 98 | print ("LEASE_RENEW_REQ (WRITE)") 99 | # send LEASE_RENEW_REQ (WRITE) 100 | accessed = [] 101 | count = 0 102 | while True: 103 | idx = random.randint(0, NUM_TEST_KEYS-1) 104 | if idx in accessed: 105 | continue 106 | flow_val = random.getrandbits(32) 107 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[idx], flow_val, 0x1, 1, payload_size) 108 | accessed.append(idx) 109 | flow_vals[flow_keys[idx]] = flow_val 110 | count = count + 1 111 | if count == NUM_TEST_KEYS: 112 | break 113 | 114 | print ("LEASE_NEW_REQ (MIGRATE))") 115 | ## send LEASE_NEW_REQ (MIGRATE) 116 | sniff_th = threading.Thread(target=sniff_thread, args=()) 117 | sniff_th.start() 118 | time.sleep(1) 119 | for i in range(0, NUM_TEST_KEYS): 120 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[i], 0, 0x0, 0, payload_size) 121 | sniff_th.join() 122 | -------------------------------------------------------------------------------- /redplane-store/apps/server_nat/tests/recv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | 10 | if os.getuid() !=0: 11 | print """ 12 | ERROR: This script requires root privileges. 13 | Use 'sudo' to run it. 14 | """ 15 | quit() 16 | 17 | from scapy.all import * 18 | ######### Redplane packet definition ########### 19 | req_type_enum = {0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ"} 20 | ack_type_enum = {0x0: "LEASE_NEW_ACK", 0x1: "LEASE_RENEW_ACK", 21 | 0x2: "LEASE_MIGRATE_ACK"} 22 | 23 | 24 | class RedplaneAck (Packet): 25 | name = "RedPlane ACK header" 26 | fields_desc = [BitEnumField("ack_type", 0, 8, ack_type_enum), 27 | BitField("seq_num", 0, 16), 28 | IPField("src_addr_k", None), 29 | IPField("dst_addr_k", None), 30 | ShortField("src_port_k", None), 31 | ShortField("dst_port_k", None), 32 | ByteField("protocol_k", None) 33 | ] 34 | 35 | 36 | class RedplaneValue (Packet): 37 | name = "RedPlane State header" 38 | fields_desc = [ 39 | IPField("dst_addr_v", None), 40 | ShortField("dst_port_v", None) 41 | ] 42 | 43 | 44 | bind_layers(UDP, RedplaneAck, dport=4000) 45 | bind_layers(RedplaneAck, RedplaneValue, ack_type=0x2) 46 | bind_layers(RedplaneValue, IP) 47 | bind_layers(RedplaneAck, IP, ack_type=0x0) 48 | bind_layers(RedplaneAck, IP, ack_type=0x1) 49 | 50 | 51 | class RedplaneReq (Packet): 52 | name = "RedPlane transaction header" 53 | fields_desc = [BitEnumField("req_type", 0, 8, req_type_enum), 54 | BitField("seq_num", 0, 16), 55 | IPField("src_addr_k", None), 56 | IPField("dst_addr_k", None), 57 | ShortField("src_port_k", None), 58 | ShortField("dst_port_k", None), 59 | ByteField("protocol_k", None), 60 | IPField("dst_addr_v", None), 61 | ShortField("dst_port_v", None) 62 | ] 63 | 64 | 65 | bind_layers(UDP, RedplaneReq, sport=4000) 66 | bind_layers(RedplaneReq, IP) 67 | 68 | def print_pkt (pkt): 69 | print(pkt.show()) 70 | 71 | if __name__ == "__main__": 72 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt) -------------------------------------------------------------------------------- /redplane-store/apps/state_store/redplane_header.h: -------------------------------------------------------------------------------- 1 | #include "raw_transport/raw_transport.h" 2 | 3 | static constexpr size_t kOriginMTU = 2048; 4 | enum class req_type_t: uint8_t { 5 | LEASE_NEW_REQ = 0x0, 6 | LEASE_RENEW_REQ = 0x1, 7 | }; 8 | 9 | enum class ack_type_t: uint8_t { 10 | LEASE_NEW_ACK = 0x0, 11 | LEASE_RENEW_ACK = 0x1, 12 | LEASE_MIGRATE_ACK = 0x2 13 | }; 14 | 15 | /* NAT NF example */ 16 | //struct req_flow_key_t 17 | //{ 18 | // uint32_t ip_addr; 19 | // uint16_t port; 20 | // 21 | // bool operator == (const req_flow_key_t &key) const { 22 | // return (ip_addr == key.ip_addr 23 | // && port == key.port); 24 | // } 25 | //} __attribute__((packed)); 26 | // 27 | //struct req_value_t { 28 | // uint32_t ip_addr; 29 | // uint16_t port; 30 | // bool operator == (const req_value_t &value) const { 31 | // return (ip_addr == value.ip_addr 32 | // && port == value.port); 33 | // } 34 | //} __attribute__((packed)); 35 | // 36 | //struct hash_fn_t { 37 | // size_t operator()(const req_flow_key_t &key) const 38 | // { 39 | // return (std::hash()(key.ip_addr) 40 | // ^ std::hash()(key.port)); 41 | // } 42 | // size_t operator()(const req_value_t &value ) const 43 | // { 44 | // return (std::hash()(value.ip_addr) 45 | // ^ std::hash()(value.port)); 46 | // } 47 | //}; 48 | // 49 | //struct equal_fn_t { 50 | // bool operator()(const req_flow_key_t &key1, const req_flow_key_t &key2) const 51 | // { 52 | // return (key1.ip_addr == key2.ip_addr 53 | // && key1.port == key2.port); 54 | // } 55 | // size_t operator()(const req_value_t &value1, const req_value_t &value2 ) const 56 | // { 57 | // return (value1.ip_addr == value2.ip_addr 58 | // && value1.port == value2.port); 59 | // } 60 | //}; 61 | 62 | /* Sequencer example */ 63 | struct req_flow_key_t 64 | { 65 | uint32_t ip_addr; 66 | 67 | bool operator == (const req_flow_key_t &key) const { 68 | return (ip_addr == key.ip_addr 69 | ); 70 | } 71 | } __attribute__((packed)); 72 | 73 | struct req_value_t { 74 | uint32_t ip_addr; 75 | bool operator == (const req_value_t &value) const { 76 | return (ip_addr == value.ip_addr 77 | ); 78 | } 79 | } __attribute__((packed)); 80 | 81 | struct hash_fn_t { 82 | size_t operator()(const req_flow_key_t &key) const 83 | { 84 | return (std::hash()(key.ip_addr) 85 | ); 86 | } 87 | size_t operator()(const req_value_t &value ) const 88 | { 89 | return (std::hash()(value.ip_addr) 90 | ); 91 | } 92 | }; 93 | 94 | struct equal_fn_t { 95 | bool operator()(const req_flow_key_t &key1, const req_flow_key_t &key2) const 96 | { 97 | return (key1.ip_addr == key2.ip_addr 98 | ); 99 | } 100 | size_t operator()(const req_value_t &value1, const req_value_t &value2 ) const 101 | { 102 | return (value1.ip_addr == value2.ip_addr 103 | ); 104 | } 105 | }; 106 | 107 | // Redplane request header 108 | struct req_header_t { 109 | redplane::ipv4_hdr_t ipv4_hdr; 110 | redplane::udp_hdr_t udp_hdr; 111 | req_type_t req_type; 112 | uint16_t seq_num; 113 | req_flow_key_t flow_key; 114 | req_value_t value; 115 | } __attribute__((packed)); 116 | 117 | // Redplane ack header 118 | struct ack_header_t { 119 | redplane::ipv4_hdr_t ipv4_hdr; 120 | redplane::udp_hdr_t udp_hdr; 121 | ack_type_t ack_type; 122 | uint16_t seq_num; 123 | req_flow_key_t flow_key; 124 | } __attribute__((packed)); 125 | 126 | struct redplane_req_pkt_t 127 | { 128 | redplane::eth_hdr_t eth_hdr; 129 | req_header_t req_header; 130 | redplane::ipv4_hdr_t original_ipv4_hdr; 131 | uint8_t original_packet[kOriginMTU-sizeof(redplane::ipv4_hdr_t)]; 132 | } __attribute__((packed)); 133 | 134 | struct redplane_ack_pkt_t 135 | { 136 | redplane::eth_hdr_t eth_hdr; 137 | ack_header_t ack_header; 138 | uint8_t reserved[kOriginMTU]; 139 | } __attribute__((packed)); -------------------------------------------------------------------------------- /redplane-store/apps/state_store/store_chain.cc: -------------------------------------------------------------------------------- 1 | #include "store_chain.h" 2 | 3 | void req_handler(uint16_t port_num, std::string NextIpAddr) 4 | { 5 | // Key-value store 6 | std::unordered_map state_store; 7 | 8 | /********************************************* Setup chain replication *****************************************************/ 9 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kSendRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 10 | if (send_buf == MAP_FAILED) 11 | { 12 | std::ostringstream xmsg; // The exception message 13 | xmsg << "Hugepage map failed "; 14 | throw std::runtime_error(xmsg.str()); 15 | } 16 | memset(send_buf, 0, redplane::RawTransport::kSendRingSize); 17 | redplane::RawTransport *raw_transport = new redplane::RawTransport(port_num, kPhyPorts, send_buf, redplane::RawTransport::kSendRingSize); 18 | uint8_t **rx_ring_chain = raw_transport->getRxRing(); 19 | redplane_req_pkt_t *redplane_req_pkt_buf = reinterpret_cast(send_buf); 20 | // Get a routing info and fill in packet headers 21 | struct redplane::RawTransport::RoutingInfo local_ri_chain; 22 | raw_transport->fill_local_routing_info(&local_ri_chain); 23 | auto *ri = reinterpret_cast(&local_ri_chain); 24 | // Prepare a template of ack packets 25 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 26 | { 27 | memcpy(redplane_req_pkt_buf[i].eth_hdr.src_mac, ri->mac, 6); 28 | redplane_req_pkt_buf[i].eth_hdr.eth_type = htons(redplane::kIPEtherType); 29 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 30 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dst_ip = redplane::ipv4_from_str(NextIpAddr.c_str()); 31 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.version = 4; 32 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ihl = 5; 33 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ecn = 0; 34 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dscp = 0; 35 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.id = htons(1); 36 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.frag_off = htons(0); 37 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.tot_len = htons(sizeof(req_header_t)); 38 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ttl = 64; 39 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.protocol = redplane::kIPHdrProtocol; 40 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.check = ip_checksum(&redplane_req_pkt_buf[i].req_header.ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 41 | redplane_req_pkt_buf[i].req_header.udp_hdr.src_port = htons(port_num); // UDP port of this thread 42 | redplane_req_pkt_buf[i].req_header.udp_hdr.dst_port = htons(port_num); 43 | redplane_req_pkt_buf[i].req_header.udp_hdr.check = 0; 44 | } 45 | /*************************************************************************************************************************/ 46 | 47 | redplane_req_pkt_t *req_pkt; 48 | size_t send_ring_idx = 0; 49 | size_t last_rx_ring_idx = 0; 50 | std::vector send_pkt_addr; 51 | std::vector send_pkt_size; 52 | while (true) 53 | { 54 | size_t num_pkts = raw_transport->rx_burst(); 55 | fprintf(stderr, "Chain received! %ld\n", num_pkts); 56 | if (num_pkts > 0) 57 | { 58 | for (size_t i = last_rx_ring_idx; i < last_rx_ring_idx + num_pkts; i++) 59 | { 60 | size_t idx = i % redplane::RawTransport::kNumRxRingEntries; 61 | req_pkt = reinterpret_cast(rx_ring_chain[idx]); 62 | redplane_req_pkt_buf[send_ring_idx].req_header.seq_num = req_pkt->req_header.seq_num; 63 | memcpy(&(redplane_req_pkt_buf[send_ring_idx].req_header.flow_key), &(req_pkt->req_header.flow_key), sizeof(req_flow_key_t)); 64 | memcpy(&(redplane_req_pkt_buf[send_ring_idx].req_header.value), &(req_pkt->req_header.value), sizeof(req_value_t)); 65 | memcpy(redplane_req_pkt_buf[send_ring_idx].eth_hdr.dst_mac, req_pkt->eth_hdr.src_mac, 6); 66 | send_pkt_addr.push_back(reinterpret_cast(&(redplane_req_pkt_buf[send_ring_idx]))); 67 | send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + sizeof(req_header_t)); 68 | send_ring_idx = (send_ring_idx + 1) % redplane::RawTransport::kSQDepth; 69 | } 70 | raw_transport->tx_burst(send_pkt_addr, send_pkt_size, send_pkt_size.size()); 71 | raw_transport->post_recvs(num_pkts); 72 | send_pkt_size.clear(); 73 | send_pkt_addr.clear(); 74 | last_rx_ring_idx = (last_rx_ring_idx + num_pkts) % redplane::RawTransport::kNumRxRingEntries; 75 | } 76 | 77 | if (unlikely(ctrl_c_pressed == 1)) 78 | break; 79 | } 80 | munmap(send_buf, redplane::RawTransport::kSendRingSize); 81 | } 82 | 83 | int main(int argc, char **argv) 84 | { 85 | signal(SIGINT, ctrl_c_handler); 86 | gflags::ParseCommandLineFlags(&argc, &argv, true); 87 | 88 | assert(FLAGS_threads <= kNumThreads); 89 | 90 | std::thread req_handler_thread[kNumThreads]; 91 | 92 | for (size_t i = 0; i < FLAGS_threads; i++) 93 | { 94 | req_handler_thread[i] = std::thread(req_handler, kUDPPort + i + 1, FLAGS_nextip); 95 | bind_to_core(req_handler_thread[i], 0, i); 96 | } 97 | 98 | while (1) 99 | { 100 | std::chrono::milliseconds dura(2000); 101 | std::this_thread::sleep_for(dura); 102 | if (unlikely(ctrl_c_pressed == 1)) 103 | break; 104 | } 105 | 106 | for (size_t i = 0; i < FLAGS_threads; i++) 107 | { 108 | req_handler_thread[i].join(); 109 | } 110 | 111 | return 0; 112 | } -------------------------------------------------------------------------------- /redplane-store/apps/state_store/store_chain.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "raw_transport/raw_transport.h" 11 | #include "redplane_header.h" 12 | 13 | DEFINE_uint32(threads, 1, "Number of workers"); 14 | DEFINE_string(nextip, "198.19.11.0", "Next server IP"); 15 | 16 | static constexpr uint16_t kUDPPort = 8000; 17 | static constexpr uint16_t kSwitchUDPPort = 4000; 18 | static constexpr uint16_t kNumThreads = 20; 19 | static constexpr uint16_t kLeasePeriod = 5; 20 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 21 | 22 | // Globals 23 | volatile sig_atomic_t ctrl_c_pressed = 0; 24 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 25 | 26 | static std::vector 27 | get_lcores_for_numa_node(size_t numa_node) 28 | { 29 | assert(numa_node <= static_cast(numa_max_node())); 30 | 31 | std::vector ret; 32 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 33 | 34 | for (size_t i = 0; i < num_lcores; i++) 35 | { 36 | if (numa_node == static_cast(numa_node_of_cpu(i))) 37 | { 38 | ret.push_back(i); 39 | } 40 | } 41 | return ret; 42 | } 43 | 44 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 45 | { 46 | cpu_set_t cpuset; 47 | CPU_ZERO(&cpuset); 48 | assert(numa_node <= static_cast(numa_max_node())); 49 | 50 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 51 | size_t global_index = lcore_vec.at(numa_local_index); 52 | 53 | CPU_SET(global_index, &cpuset); 54 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 55 | &cpuset); 56 | assert(rc == 0); 57 | } 58 | 59 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 60 | { 61 | unsigned long sum = 0; 62 | const uint16_t *ip1; 63 | 64 | ip1 = reinterpret_cast(buf); 65 | while (hdr_len > 1) 66 | { 67 | sum += *ip1++; 68 | if (sum & 0x80000000) 69 | sum = (sum & 0xFFFF) + (sum >> 16); 70 | hdr_len -= 2; 71 | } 72 | 73 | while (sum >> 16) 74 | sum = (sum & 0xFFFF) + (sum >> 16); 75 | 76 | return (~sum); 77 | } 78 | 79 | void print_bytes(uint8_t *buffer) 80 | { 81 | size_t k, j, base; 82 | for (base = 0; base < 1; base++) 83 | { 84 | for (k = base * 256; k < (base * 256) + 256; k += 16) 85 | { 86 | for (j = 0; j < 15; j++) 87 | { 88 | fprintf(stderr, "%02x ", *(buffer + k + j)); 89 | } 90 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 91 | } 92 | fprintf(stderr, "\n"); 93 | } 94 | fprintf(stderr, "\n"); 95 | } -------------------------------------------------------------------------------- /redplane-store/apps/state_store/store_main.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "raw_transport/raw_transport.h" 11 | #include "redplane_header.h" 12 | 13 | DEFINE_bool(m_lat, false, "Measure per-request processing latency"); 14 | DEFINE_bool(chain, false, "Chain replication"); 15 | DEFINE_string(nextip, "198.19.11.0", "Next server IP"); 16 | DEFINE_uint32(threads, 1, "Number of workers"); 17 | 18 | static constexpr uint16_t kUDPPort = 8000; 19 | static constexpr uint16_t kSwitchUDPPort = 4000; 20 | static constexpr uint16_t kNumThreads = 20; 21 | static constexpr uint16_t kLeasePeriod = 5; 22 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 23 | static const std::string kPrimaryIpAddr = "198.19.11.0"; 24 | static const std::string kBackupIpAddr = "198.19.12.0"; 25 | 26 | // Globals 27 | volatile sig_atomic_t ctrl_c_pressed = 0; 28 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 29 | 30 | static std::vector 31 | get_lcores_for_numa_node(size_t numa_node) 32 | { 33 | assert(numa_node <= static_cast(numa_max_node())); 34 | 35 | std::vector ret; 36 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 37 | 38 | for (size_t i = 0; i < num_lcores; i++) 39 | { 40 | if (numa_node == static_cast(numa_node_of_cpu(i))) 41 | { 42 | ret.push_back(i); 43 | } 44 | } 45 | return ret; 46 | } 47 | 48 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 49 | { 50 | cpu_set_t cpuset; 51 | CPU_ZERO(&cpuset); 52 | assert(numa_node <= static_cast(numa_max_node())); 53 | 54 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 55 | size_t global_index = lcore_vec.at(numa_local_index); 56 | 57 | CPU_SET(global_index, &cpuset); 58 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 59 | &cpuset); 60 | assert(rc == 0); 61 | } 62 | 63 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 64 | { 65 | unsigned long sum = 0; 66 | const uint16_t *ip1; 67 | 68 | ip1 = reinterpret_cast(buf); 69 | while (hdr_len > 1) 70 | { 71 | sum += *ip1++; 72 | if (sum & 0x80000000) 73 | sum = (sum & 0xFFFF) + (sum >> 16); 74 | hdr_len -= 2; 75 | } 76 | 77 | while (sum >> 16) 78 | sum = (sum & 0xFFFF) + (sum >> 16); 79 | 80 | return (~sum); 81 | } 82 | 83 | void print_bytes(uint8_t *buffer) 84 | { 85 | size_t k, j, base; 86 | for (base = 0; base < 1; base++) 87 | { 88 | for (k = base * 256; k < (base * 256) + 256; k += 16) 89 | { 90 | for (j = 0; j < 15; j++) 91 | { 92 | fprintf(stderr, "%02x ", *(buffer + k + j)); 93 | } 94 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 95 | } 96 | fprintf(stderr, "\n"); 97 | } 98 | fprintf(stderr, "\n"); 99 | } -------------------------------------------------------------------------------- /redplane-store/apps/state_store/store_tester.cc: -------------------------------------------------------------------------------- 1 | #include "store_tester.h" 2 | 3 | void req_handler(uint16_t dest_port_num, size_t payload_size) 4 | { 5 | std::srand(std::time(nullptr)); 6 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kSendRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 7 | if (send_buf == MAP_FAILED) 8 | { 9 | std::ostringstream xmsg; // The exception message 10 | xmsg << "Hugepage map failed "; 11 | throw std::runtime_error(xmsg.str()); 12 | } 13 | memset(send_buf, 0, redplane::RawTransport::kSendRingSize); 14 | redplane::RawTransport *raw_transport = new redplane::RawTransport(dest_port_num, kPhyPorts, send_buf, redplane::RawTransport::kSendRingSize); 15 | //uint8_t **rx_ring = raw_transport->getRxRing(); 16 | redplane_req_pkt_t *redplane_req_pkt_buf = reinterpret_cast(send_buf); 17 | // Get a routing info and fill in packet headers 18 | struct redplane::RawTransport::RoutingInfo local_ri; 19 | raw_transport->fill_local_routing_info(&local_ri); 20 | 21 | //uint32_t flow_key = static_cast(std::rand()); 22 | uint32_t flow_key = static_cast(dest_port_num); 23 | uint32_t value = static_cast(std::rand()); 24 | 25 | // Prepare a template of ack packets 26 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 27 | { 28 | auto *ri = reinterpret_cast(&local_ri); 29 | memcpy(redplane_req_pkt_buf[i].eth_hdr.src_mac, ri->mac, 6); 30 | memcpy(redplane_req_pkt_buf[i].eth_hdr.dst_mac, kDestMacAddr, 6); 31 | redplane_req_pkt_buf[i].eth_hdr.eth_type = htons(redplane::kIPEtherType); 32 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 33 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dst_ip = redplane::ipv4_from_str(kReceiverIpAddr.c_str()); 34 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.version = 4; 35 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ihl = 5; 36 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ecn = 0; 37 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.dscp = 0; 38 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.id = htons(1); 39 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.frag_off = htons(0); 40 | //redplane_req_pkt_buf[i].req_header.ipv4_hdr.tot_len = htons(sizeof(req_header_t) + sizeof(redplane::ipv4_hdr_t) + payload_size); 41 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.tot_len = htons(sizeof(req_header_t) + payload_size); 42 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.ttl = 64; 43 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.protocol = redplane::kIPHdrProtocol; 44 | redplane_req_pkt_buf[i].req_header.ipv4_hdr.check = ip_checksum(&redplane_req_pkt_buf[i].req_header.ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 45 | redplane_req_pkt_buf[i].req_header.udp_hdr.src_port = htons(dest_port_num); // Common UDP port of switch 46 | redplane_req_pkt_buf[i].req_header.udp_hdr.dst_port = htons(dest_port_num); // UDP port of this thread 47 | //redplane_req_pkt_buf[i].req_header.udp_hdr.len = htons(sizeof(req_header_t) - sizeof(redplane::ipv4_hdr_t) + payload_size); 48 | redplane_req_pkt_buf[i].req_header.udp_hdr.len = htons(sizeof(req_header_t) - sizeof(redplane::ipv4_hdr_t) + payload_size); 49 | redplane_req_pkt_buf[i].req_header.udp_hdr.check = 0; 50 | redplane_req_pkt_buf[i].req_header.flow_key.ip_addr = flow_key; 51 | redplane_req_pkt_buf[i].req_header.value.ip_addr = value; 52 | } 53 | 54 | std::vector send_pkt_addr; 55 | std::vector send_pkt_size; 56 | //redplane_req_pkt_buf[0].req_header.req_type = req_type_t::LEASE_NEW_REQ; 57 | //redplane_req_pkt_buf[0].req_header.seq_num = 0; 58 | //raw_transport->tx_one(reinterpret_cast(&redplane_req_pkt_buf[0]), sizeof(redplane::eth_hdr_t) + sizeof(req_header_t) + sizeof(redplane::ipv4_hdr_t) + payload_size); 59 | 60 | while (true) 61 | { 62 | size_t num_pkts = raw_transport->rx_burst(); 63 | for (size_t i = 0; i < redplane::RawTransport::kSQDepth; i++) 64 | { 65 | if (i == 0) 66 | { 67 | redplane_req_pkt_buf[i].req_header.req_type = req_type_t::LEASE_NEW_REQ; 68 | } 69 | else 70 | { 71 | redplane_req_pkt_buf[i].req_header.req_type = req_type_t::LEASE_RENEW_REQ; 72 | } 73 | redplane_req_pkt_buf[i].req_header.seq_num = i % MAX_SEQ; 74 | send_pkt_addr.push_back(reinterpret_cast(&redplane_req_pkt_buf[i])); 75 | //send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + sizeof(req_header_t) + sizeof(redplane::ipv4_hdr_t) + payload_size); 76 | send_pkt_size.push_back(sizeof(redplane::eth_hdr_t) + sizeof(req_header_t) + payload_size); 77 | } 78 | raw_transport->tx_burst(send_pkt_addr, send_pkt_size, send_pkt_size.size()); 79 | send_pkt_addr.clear(); 80 | send_pkt_size.clear(); 81 | 82 | raw_transport->post_recvs(num_pkts); 83 | 84 | if (unlikely(ctrl_c_pressed == 1)) 85 | break; 86 | } 87 | munmap(send_buf, redplane::RawTransport::kSendRingSize); 88 | } 89 | 90 | int main(int argc, char **argv) 91 | { 92 | signal(SIGINT, ctrl_c_handler); 93 | gflags::ParseCommandLineFlags(&argc, &argv, true); 94 | assert(FLAGS_threads <= kNumThreads); 95 | 96 | std::thread req_handler_thread[kNumThreads]; 97 | 98 | for (size_t i = 0; i < FLAGS_threads; i++) 99 | { 100 | req_handler_thread[i] = std::thread(req_handler, kUDPPort + i + 1, FLAGS_payload_size); 101 | bind_to_core(req_handler_thread[i], 0, i+1); 102 | } 103 | 104 | while (1) 105 | { 106 | std::chrono::milliseconds dura(2000); 107 | std::this_thread::sleep_for(dura); 108 | if (unlikely(ctrl_c_pressed == 1)) 109 | break; 110 | } 111 | 112 | for (size_t i = 0; i < FLAGS_threads; i++) 113 | { 114 | req_handler_thread[i].join(); 115 | } 116 | 117 | return 0; 118 | } -------------------------------------------------------------------------------- /redplane-store/apps/state_store/store_tester.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "raw_transport/raw_transport.h" 12 | #include "redplane_header.h" 13 | 14 | DEFINE_uint32(threads, 1, "Number of workers"); 15 | DEFINE_uint32(payload_size, 1, "payload size"); 16 | 17 | static constexpr uint16_t kUDPPort = 8000; 18 | static constexpr uint16_t kNumThreads = 20; 19 | static constexpr uint16_t kLeasePeriod = 5; 20 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 21 | static const std::string kReceiverIpAddr = "198.19.13.0"; 22 | static const uint16_t MAX_SEQ = UINT16_MAX; 23 | static const uint8_t kDestMacAddr[6] = {0x28, 0x99, 0x3a, 0x9f, 0xe7, 0x5d}; 24 | // Globals 25 | volatile sig_atomic_t ctrl_c_pressed = 0; 26 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 27 | 28 | static std::vector 29 | get_lcores_for_numa_node(size_t numa_node) 30 | { 31 | assert(numa_node <= static_cast(numa_max_node())); 32 | 33 | std::vector ret; 34 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 35 | 36 | for (size_t i = 0; i < num_lcores; i++) 37 | { 38 | if (numa_node == static_cast(numa_node_of_cpu(i))) 39 | { 40 | ret.push_back(i); 41 | } 42 | } 43 | return ret; 44 | } 45 | 46 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 47 | { 48 | cpu_set_t cpuset; 49 | CPU_ZERO(&cpuset); 50 | assert(numa_node <= static_cast(numa_max_node())); 51 | 52 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 53 | size_t global_index = lcore_vec.at(numa_local_index); 54 | 55 | CPU_SET(global_index, &cpuset); 56 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 57 | &cpuset); 58 | assert(rc == 0); 59 | } 60 | 61 | static uint16_t ip_checksum(const redplane::ipv4_hdr_t *buf, size_t hdr_len) 62 | { 63 | unsigned long sum = 0; 64 | const uint16_t *ip1; 65 | 66 | ip1 = reinterpret_cast(buf); 67 | while (hdr_len > 1) 68 | { 69 | sum += *ip1++; 70 | if (sum & 0x80000000) 71 | sum = (sum & 0xFFFF) + (sum >> 16); 72 | hdr_len -= 2; 73 | } 74 | 75 | while (sum >> 16) 76 | sum = (sum & 0xFFFF) + (sum >> 16); 77 | 78 | return (~sum); 79 | } 80 | 81 | void print_bytes(uint8_t *buffer) 82 | { 83 | size_t k, j, base; 84 | for (base = 0; base < 1; base++) 85 | { 86 | for (k = base * 256; k < (base * 256) + 256; k += 16) 87 | { 88 | for (j = 0; j < 15; j++) 89 | { 90 | fprintf(stderr, "%02x ", *(buffer + k + j)); 91 | } 92 | fprintf(stderr, "%02x\n", *(buffer + k + j)); 93 | } 94 | fprintf(stderr, "\n"); 95 | } 96 | fprintf(stderr, "\n"); 97 | } 98 | -------------------------------------------------------------------------------- /redplane-store/apps/state_store/tests/pktgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | import threading 10 | 11 | if os.getuid() !=0: 12 | print """ 13 | ERROR: This script requires root privileges. 14 | Use 'sudo' to run it. 15 | """ 16 | quit() 17 | 18 | from scapy.all import * 19 | 20 | flow_vals = {} 21 | NUM_TEST_KEYS = 1000 22 | 23 | txn_type_enum = { 0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ", 24 | 0x2: "LEASE_NEW_ACK", 0x3: "LEASE_RENEW_ACK", 25 | 0x4: "LEASE_MIGRATE_ACK" } 26 | class RedplaneAck (Packet): 27 | name = "RedPlane ACK header" 28 | fields_desc = [ BitEnumField("ack_type", 0, 8, txn_type_enum), 29 | BitField("seq_num", 0, 32), 30 | BitField("lease_expire_time", 0, 32), 31 | BitField("flow_key", 0, 104) 32 | ] 33 | class RedplaneState (Packet): 34 | name = "RedPlane State header" 35 | fields_desc = [ BitField("State", 0, 32) 36 | ] 37 | 38 | bind_layers(UDP, RedplaneAck, dport=4000) 39 | bind_layers(RedplaneAck, RedplaneState, ack_type=0x4) 40 | bind_layers(RedplaneState, IP) 41 | bind_layers(RedplaneAck, IP, ack_type=0x2) 42 | bind_layers(RedplaneAck, IP, ack_type=0x3) 43 | 44 | class RedplaneTxn (Packet): 45 | name = "RedPlane transaction header" 46 | fields_desc = [ BitEnumField("txn_type", 0, 8, txn_type_enum), 47 | BitField("seq_num", 0, 32), 48 | BitField("flow_key", 0, 104), 49 | BitField("flow_value", 0, 32) 50 | ] 51 | 52 | bind_layers(UDP, RedplaneTxn, sport=4000) 53 | bind_layers(RedplaneTxn, IP) 54 | 55 | # Send txn from a switch to a state store 56 | def send_write_txn (src_ip, dst_ip, dest_port, flow_key, flow_val, txn_type, seq_num, payload_size): 57 | p = (Ether()/ 58 | IP(dst=dst_ip, src=src_ip)/ 59 | UDP(sport=4000, dport=dest_port)/ 60 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=flow_key, flow_value=flow_val)/ 61 | IP()/ 62 | #TCP()/ 63 | Raw(RandString(size=payload_size))) 64 | 65 | sendp(p, iface="ens1", count = 1) 66 | 67 | def send_read_txn (src_ip, dst_ip, dest_port, txn_type, seq_num): 68 | p = (Ether()/ 69 | IP(dst=dst_ip, src=src_ip)/ 70 | UDP(sport=4000, dport=dest_port)/ 71 | RedplaneTxn(txn_type=txn_type, seq_num=seq_num, flow_key=0)) 72 | 73 | sendp(p, iface="ens1", count = 1) 74 | 75 | def print_pkt (pkt): 76 | flow_key = int(pkt[RedplaneAck].flow_key) 77 | assert(flow_vals[flow_key] == int(pkt[RedplaneState].State)) 78 | 79 | def sniff_thread(): 80 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt, count = NUM_TEST_KEYS) 81 | 82 | if __name__ == "__main__": 83 | 84 | payload_size = int(sys.argv[1]) 85 | flow_keys = [] 86 | 87 | print ("LEASE_NEW_REQ") 88 | # send LEASE_NEW_REQ 89 | for i in range(0, NUM_TEST_KEYS): 90 | while True: 91 | flow_key = random.getrandbits(104) 92 | if flow_key in flow_keys: 93 | continue 94 | flow_keys.append(flow_key) 95 | break 96 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_key, 0, 0x0, 0, payload_size) 97 | 98 | print ("LEASE_RENEW_REQ (WRITE)") 99 | # send LEASE_RENEW_REQ (WRITE) 100 | accessed = [] 101 | count = 0 102 | while True: 103 | idx = random.randint(0, NUM_TEST_KEYS-1) 104 | if idx in accessed: 105 | continue 106 | flow_val = random.getrandbits(32) 107 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[idx], flow_val, 0x1, 1, payload_size) 108 | accessed.append(idx) 109 | flow_vals[flow_keys[idx]] = flow_val 110 | count = count + 1 111 | if count == NUM_TEST_KEYS: 112 | break 113 | 114 | print ("LEASE_NEW_REQ (MIGRATE))") 115 | ## send LEASE_NEW_REQ (MIGRATE) 116 | sniff_th = threading.Thread(target=sniff_thread, args=()) 117 | sniff_th.start() 118 | time.sleep(1) 119 | for i in range(0, NUM_TEST_KEYS): 120 | send_write_txn ("198.19.10.0","198.19.11.0", 4001, flow_keys[i], 0, 0x0, 0, payload_size) 121 | sniff_th.join() 122 | -------------------------------------------------------------------------------- /redplane-store/apps/state_store/tests/recv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | ###################################################### 3 | # Copyright (C) Microsoft. All rights reserved. # 4 | ###################################################### 5 | 6 | import os 7 | import sys 8 | import random 9 | 10 | if os.getuid() !=0: 11 | print """ 12 | ERROR: This script requires root privileges. 13 | Use 'sudo' to run it. 14 | """ 15 | quit() 16 | 17 | from scapy.all import * 18 | ######### Redplane packet definition ########### 19 | req_type_enum = {0x0: "LEASE_NEW_REQ", 0x1: "LEASE_RENEW_REQ"} 20 | ack_type_enum = {0x0: "LEASE_NEW_ACK", 0x1: "LEASE_RENEW_ACK", 21 | 0x2: "LEASE_MIGRATE_ACK"} 22 | 23 | 24 | class RedplaneAck (Packet): 25 | name = "RedPlane ACK header" 26 | fields_desc = [BitEnumField("ack_type", 0, 8, ack_type_enum), 27 | BitField("seq_num", 0, 16), 28 | IPField("src_addr_k", None), 29 | IPField("dst_addr_k", None), 30 | ShortField("src_port_k", None), 31 | ShortField("dst_port_k", None), 32 | ByteField("protocol_k", None) 33 | ] 34 | 35 | 36 | class RedplaneValue (Packet): 37 | name = "RedPlane State header" 38 | fields_desc = [ 39 | IPField("dst_addr_v", None), 40 | ShortField("dst_port_v", None) 41 | ] 42 | 43 | 44 | bind_layers(UDP, RedplaneAck, dport=4000) 45 | bind_layers(RedplaneAck, RedplaneValue, ack_type=0x2) 46 | bind_layers(RedplaneValue, IP) 47 | bind_layers(RedplaneAck, IP, ack_type=0x0) 48 | bind_layers(RedplaneAck, IP, ack_type=0x1) 49 | 50 | 51 | class RedplaneReq (Packet): 52 | name = "RedPlane transaction header" 53 | fields_desc = [BitEnumField("req_type", 0, 8, req_type_enum), 54 | BitField("seq_num", 0, 16), 55 | IPField("src_addr_k", None), 56 | IPField("dst_addr_k", None), 57 | ShortField("src_port_k", None), 58 | ShortField("dst_port_k", None), 59 | ByteField("protocol_k", None), 60 | IPField("dst_addr_v", None), 61 | ShortField("dst_port_v", None) 62 | ] 63 | 64 | 65 | bind_layers(UDP, RedplaneReq, sport=4000) 66 | bind_layers(RedplaneReq, IP) 67 | 68 | def print_pkt (pkt): 69 | print(pkt.show()) 70 | 71 | if __name__ == "__main__": 72 | sniff (iface="ens1", filter='udp dst port 4000', prn=print_pkt) -------------------------------------------------------------------------------- /redplane-store/apps/transport_test/common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "raw_transport/raw_transport.h" 12 | 13 | // Globals 14 | volatile sig_atomic_t ctrl_c_pressed = 0; 15 | void ctrl_c_handler(int) { ctrl_c_pressed = 1; } 16 | 17 | struct redplane_test_key_t 18 | { 19 | uint32_t src_ip; 20 | uint32_t dst_ip; 21 | uint16_t src_port; 22 | uint16_t dst_port; 23 | uint8_t protocol; 24 | }; 25 | 26 | struct redplane_test_kv_t 27 | { 28 | //redplane_test_key_t state_key; 29 | uint32_t state_key; 30 | uint32_t state_value; 31 | }; 32 | 33 | std::map redplane_test_state_store; 34 | 35 | struct redplane_test_pkt_t 36 | { 37 | redplane::eth_hdr_t eth_hdr; 38 | redplane::ipv4_hdr_t ipv4_hdr; 39 | redplane::udp_hdr_t udp_hdr; 40 | redplane_test_kv_t replane_kv; 41 | uint8_t data[redplane::RawTransport::kRecvSize-sizeof(redplane::eth_hdr_t)-sizeof(redplane::ipv4_hdr_t)-sizeof(redplane::udp_hdr_t)-sizeof(redplane_test_kv_t)]; 42 | }; 43 | 44 | static const std::string kReceiverIpAddr = "11.0.0.20"; // Prometheus 20 45 | static const std::string kReturnIpAddr = "11.0.0.21"; // Prometheus 21 46 | static const uint8_t kReceiverMacAddr[6] = {0xb8, 0x83, 0x03, 0x79, 0xaf, 0x30}; // Prometheus 20 47 | static const uint8_t kReturnMacAddr[6] = {0xb8, 0x83, 0x03, 0x70, 0x88, 0xb4}; // Prometheus 21 48 | static const size_t kPhyPorts = 1; // Number of physical ports in CX-5 NIC 49 | 50 | static constexpr uint16_t kUDPPort = 3001; 51 | 52 | static std::vector 53 | get_lcores_for_numa_node(size_t numa_node) 54 | { 55 | assert(numa_node <= static_cast(numa_max_node())); 56 | 57 | std::vector ret; 58 | size_t num_lcores = static_cast(numa_num_configured_cpus()); 59 | 60 | for (size_t i = 0; i < num_lcores; i++) 61 | { 62 | if (numa_node == static_cast(numa_node_of_cpu(i))) 63 | { 64 | ret.push_back(i); 65 | } 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | static void bind_to_core(std::thread &thread, size_t numa_node, size_t numa_local_index) 72 | { 73 | cpu_set_t cpuset; 74 | CPU_ZERO(&cpuset); 75 | assert(numa_node <= static_cast(numa_max_node())); 76 | 77 | auto lcore_vec = get_lcores_for_numa_node(numa_node); 78 | size_t global_index = lcore_vec.at(numa_local_index); 79 | 80 | CPU_SET(global_index, &cpuset); 81 | int rc = pthread_setaffinity_np(thread.native_handle(), sizeof(cpu_set_t), 82 | &cpuset); 83 | assert(rc == 0); 84 | } -------------------------------------------------------------------------------- /redplane-store/apps/transport_test/receiver.cc: -------------------------------------------------------------------------------- 1 | #include "receiver.h" 2 | 3 | void run_receiver(bool process_req, bool batch) 4 | { 5 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 6 | if (send_buf == MAP_FAILED) 7 | { 8 | std::ostringstream xmsg; // The exception message 9 | xmsg << "Hugepage map failed "; 10 | throw std::runtime_error(xmsg.str()); 11 | } 12 | memset(send_buf, 0, redplane::RawTransport::kRingSize); 13 | redplane::RawTransport *raw_transport = new redplane::RawTransport(kUDPPort, kPhyPorts, send_buf, redplane::RawTransport::kRingSize); 14 | uint8_t **rx_ring = raw_transport->getRxRing(); 15 | 16 | if (process_req) 17 | { 18 | // Get a routing info and fill in packet headers 19 | struct redplane::RawTransport::RoutingInfo local_ri; 20 | raw_transport->fill_local_routing_info(&local_ri); 21 | 22 | redplane::eth_hdr_t eth_hdr; 23 | redplane::ipv4_hdr_t ipv4_hdr; 24 | redplane::udp_hdr_t udp_hdr; 25 | 26 | auto *ri = reinterpret_cast(&local_ri); 27 | memcpy(eth_hdr.src_mac, ri->mac, 6); 28 | memcpy(eth_hdr.dst_mac, &kReturnMacAddr, 6); 29 | eth_hdr.eth_type = htons(redplane::kIPEtherType); 30 | ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 31 | ipv4_hdr.dst_ip = redplane::ipv4_from_str(kReturnIpAddr.c_str()); 32 | ipv4_hdr.version = 4; 33 | ipv4_hdr.ihl = 5; 34 | ipv4_hdr.ecn = 1; 35 | ipv4_hdr.dscp = 0; 36 | ipv4_hdr.tot_len = htons(sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t)); 37 | ipv4_hdr.id = htons(0); 38 | ipv4_hdr.frag_off = htons(0); 39 | ipv4_hdr.ttl = 128; 40 | ipv4_hdr.protocol = redplane::kIPHdrProtocol; 41 | ipv4_hdr.check = 0; 42 | udp_hdr.src_port = htons(8000); 43 | udp_hdr.dst_port = htons(kUDPPort); 44 | udp_hdr.len = htons(sizeof(redplane::udp_hdr_t)); 45 | udp_hdr.check = 0; 46 | 47 | memcpy(send_buf, ð_hdr, sizeof(redplane::eth_hdr_t)); 48 | memcpy(send_buf + sizeof(redplane::eth_hdr_t), &ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 49 | memcpy(send_buf + sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t), &udp_hdr, sizeof(redplane::udp_hdr_t)); 50 | } 51 | size_t total_recvd = 0; 52 | size_t total_recvd_bytes = 0; 53 | size_t last_rx_ring_idx = 0; 54 | redplane_test_pkt_t *test_pkt; 55 | 56 | auto start = std::chrono::high_resolution_clock::now(); 57 | auto stop = std::chrono::high_resolution_clock::now(); 58 | 59 | while (1) 60 | { 61 | size_t num_pkts = raw_transport->rx_burst(); 62 | if (num_pkts > 0) 63 | { 64 | stop = std::chrono::high_resolution_clock::now(); 65 | if (total_recvd == 0) 66 | { 67 | start = std::chrono::high_resolution_clock::now(); 68 | } 69 | 70 | for (size_t i = last_rx_ring_idx; i < last_rx_ring_idx + num_pkts; i++) 71 | { 72 | size_t idx = i % redplane::RawTransport::kNumRxRingEntries; 73 | test_pkt = reinterpret_cast(rx_ring[idx]); 74 | if (process_req && batch == false) 75 | { 76 | redplane_test_state_store[test_pkt->replane_kv.state_key] = test_pkt->replane_kv.state_value; 77 | //raw_transport->tx_one(reinterpret_cast(send_buf), sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t)); 78 | } 79 | total_recvd_bytes += ntohs(test_pkt->ipv4_hdr.tot_len); 80 | } 81 | if (process_req == true && batch == true) 82 | { 83 | redplane_test_state_store[test_pkt->replane_kv.state_key] = test_pkt->replane_kv.state_value; 84 | //raw_transport->tx_one(reinterpret_cast(send_buf), sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t)); 85 | } 86 | last_rx_ring_idx = (last_rx_ring_idx + num_pkts) % redplane::RawTransport::kNumRxRingEntries; 87 | total_recvd += num_pkts; 88 | raw_transport->post_recvs(num_pkts); 89 | } 90 | if (unlikely(ctrl_c_pressed == 1)) 91 | break; 92 | } 93 | auto duration = std::chrono::duration_cast(stop - start); 94 | 95 | fprintf(stderr, "%ld packets received during %f seconds.\n", total_recvd, static_cast(duration.count()) / 1000 / 1000); 96 | fprintf(stderr, "%f Mreqs/seconds.\n", static_cast(total_recvd) / (static_cast(duration.count()) / 1000 / 1000) / 1000000); 97 | fprintf(stderr, "%f Gbits/seconds.\n", static_cast(total_recvd_bytes) * 8 / (static_cast(duration.count()) / 1000 / 1000) / 1000000000); 98 | munmap(send_buf, redplane::RawTransport::kRingSize); 99 | } 100 | 101 | int main(int argc, char **argv) 102 | { 103 | signal(SIGINT, ctrl_c_handler); 104 | gflags::ParseCommandLineFlags(&argc, &argv, true); 105 | 106 | std::thread receiver_thread; 107 | receiver_thread = std::thread(run_receiver, FLAGS_process_req, FLAGS_batch); 108 | bind_to_core(receiver_thread, 0, 1); 109 | 110 | while (1) 111 | { 112 | std::chrono::milliseconds dura(2000); 113 | std::this_thread::sleep_for(dura); 114 | if (unlikely(ctrl_c_pressed == 1)) 115 | break; 116 | } 117 | 118 | receiver_thread.join(); 119 | 120 | return 0; 121 | } -------------------------------------------------------------------------------- /redplane-store/apps/transport_test/receiver.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DEFINE_bool(process_req, false, "Process requests (true: receive and process, false: just receive)"); 4 | DEFINE_bool(batch, false, "Request batch (true: batch requests, false: no batch request)"); 5 | -------------------------------------------------------------------------------- /redplane-store/apps/transport_test/sender.cc: -------------------------------------------------------------------------------- 1 | #include "sender.h" 2 | 3 | std::thread sender_thread[20]; 4 | size_t per_thread_sent[20]; 5 | 6 | void run_sender(size_t idx, size_t req_size, size_t req_num) 7 | { 8 | // Initialize the memory region for SENDs 9 | uint8_t *send_buf = static_cast(mmap(NULL, redplane::RawTransport::kRingSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB, -1, 0)); 10 | if (send_buf == MAP_FAILED) 11 | { 12 | std::ostringstream xmsg; // The exception message 13 | xmsg << "Hugepage map failed "; 14 | throw std::runtime_error(xmsg.str()); 15 | } 16 | memset(send_buf, 0, redplane::RawTransport::kRingSize); 17 | redplane::RawTransport *raw_transport = new redplane::RawTransport(kUDPPort, kPhyPorts, send_buf, redplane::RawTransport::kRingSize); 18 | 19 | // Get a routing info and fill in packet headers 20 | struct redplane::RawTransport::RoutingInfo local_ri; 21 | raw_transport->fill_local_routing_info(&local_ri); 22 | 23 | redplane::eth_hdr_t eth_hdr; 24 | redplane::ipv4_hdr_t ipv4_hdr; 25 | redplane::udp_hdr_t udp_hdr; 26 | 27 | uint8_t *data = static_cast(malloc(req_size + sizeof(redplane_test_kv_t))); 28 | memset(data, 0, req_size + sizeof(redplane_test_kv_t)); 29 | 30 | auto *ri = reinterpret_cast(&local_ri); 31 | memcpy(eth_hdr.src_mac, ri->mac, 6); 32 | memcpy(eth_hdr.dst_mac, &kReceiverMacAddr, 6); 33 | eth_hdr.eth_type = htons(redplane::kIPEtherType); 34 | ipv4_hdr.src_ip = htonl(ri->ipv4_addr); 35 | ipv4_hdr.dst_ip = redplane::ipv4_from_str(kReceiverIpAddr.c_str()); 36 | ipv4_hdr.version = 4; 37 | ipv4_hdr.ihl = 5; 38 | ipv4_hdr.ecn = 1; 39 | ipv4_hdr.dscp = 0; 40 | ipv4_hdr.tot_len = htons(sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t) + req_size);// + sizeof(redplane_test_kv_t)); 41 | ipv4_hdr.id = htons(0); 42 | ipv4_hdr.frag_off = htons(0); 43 | ipv4_hdr.ttl = 128; 44 | ipv4_hdr.protocol = redplane::kIPHdrProtocol; 45 | ipv4_hdr.check = 0; 46 | udp_hdr.src_port = htons(8000 + idx); 47 | udp_hdr.dst_port = htons(kUDPPort); 48 | udp_hdr.len = htons(sizeof(redplane::udp_hdr_t) + req_size);// + sizeof(redplane_test_kv_t)); 49 | udp_hdr.check = 0; 50 | 51 | memcpy(send_buf, ð_hdr, sizeof(redplane::eth_hdr_t)); 52 | memcpy(send_buf + sizeof(redplane::eth_hdr_t), &ipv4_hdr, sizeof(redplane::ipv4_hdr_t)); 53 | memcpy(send_buf + sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t), &udp_hdr, sizeof(redplane::udp_hdr_t)); 54 | memcpy(send_buf + sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t), data, req_size);// + sizeof(redplane_test_kv_t)); 55 | 56 | fprintf(stderr, "Thread %ld: ready to send\n", idx); 57 | per_thread_sent[idx] = 0; 58 | while (1) 59 | { 60 | raw_transport->tx_one(reinterpret_cast (send_buf), sizeof(redplane::eth_hdr_t) + sizeof(redplane::ipv4_hdr_t) + sizeof(redplane::udp_hdr_t) + req_size);// + sizeof(redplane_test_kv_t)); 61 | per_thread_sent[idx]++; 62 | if (unlikely(ctrl_c_pressed == 1)) 63 | break; 64 | if (per_thread_sent[idx] == req_num) 65 | break; 66 | } 67 | 68 | fprintf(stderr, "Thread %ld: Sent %ld\n", idx, per_thread_sent[idx]); 69 | munmap(send_buf, redplane::RawTransport::kRingSize); 70 | } 71 | 72 | int main(int argc, char **argv) 73 | { 74 | signal(SIGINT, ctrl_c_handler); 75 | gflags::ParseCommandLineFlags(&argc, &argv, true); 76 | fprintf(stderr, "Num UDP flows: %d\tRequest size: %d\n", FLAGS_num_sessions, FLAGS_req_size); 77 | 78 | assert(FLAGS_num_sessions <= 20); 79 | 80 | for (size_t i = 0; i < FLAGS_num_sessions; i++) 81 | { 82 | sender_thread[i] = std::thread(run_sender, i, FLAGS_req_size, FLAGS_req_num); 83 | bind_to_core(sender_thread[i], 0, i); 84 | } 85 | 86 | while (1) 87 | { 88 | std::chrono::milliseconds dura(2000); 89 | std::this_thread::sleep_for(dura); 90 | if (unlikely(ctrl_c_pressed == 1)) 91 | break; 92 | } 93 | 94 | size_t total_sent = 0; 95 | for (size_t i = 0; i < FLAGS_num_sessions; i++) 96 | { 97 | sender_thread[i].join(); 98 | total_sent += per_thread_sent[i]; 99 | } 100 | fprintf(stderr, "Total sent %ld\n", total_sent); 101 | return 0; 102 | } -------------------------------------------------------------------------------- /redplane-store/apps/transport_test/sender.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | DEFINE_uint32(num_sessions, 1, "Number of UDP sessions"); 4 | DEFINE_uint32(req_size, 0, "Request size (excluding Ethernet, IP, UDP headers)"); 5 | DEFINE_uint32(req_num, 0, "Number of requests (0: infinite)"); -------------------------------------------------------------------------------- /redplane-store/raw_transport/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace redplane 18 | { 19 | #define _unused(x) ((void)(x)) 20 | #define likely(x) __builtin_expect(!!(x), 1) 21 | #define unlikely(x) __builtin_expect(!!(x), 0) 22 | 23 | #define KB(x) (static_cast(x) << 10) 24 | #define MB(x) (static_cast(x) << 20) 25 | #define GB(x) (static_cast(x) << 30) 26 | 27 | // General constants 28 | 29 | /// Array size to hold registered request handler functions 30 | static constexpr size_t kReqTypeArraySize = 1ull + UINT8_MAX; 31 | 32 | static constexpr size_t kHugepageSize = (2 * 1024 * 1024); ///< Hugepage size 33 | static constexpr size_t kMaxHostnameLen = 128; ///< Max hostname length 34 | static constexpr size_t kMaxIssueMsgLen = ///< Max debug issue message length 35 | (240 + kMaxHostnameLen * 2); // Three lines and two hostnames 36 | 37 | /// Check a condition at runtime. If the condition is false, throw exception. 38 | static inline void rt_assert(bool condition, std::string throw_str, char *s) 39 | { 40 | if (unlikely(!condition)) 41 | { 42 | throw std::runtime_error(throw_str + std::string(s)); 43 | } 44 | } 45 | 46 | /// Check a condition at runtime. If the condition is false, throw exception. 47 | static inline void rt_assert(bool condition, const char *throw_str) 48 | { 49 | if (unlikely(!condition)) 50 | throw std::runtime_error(throw_str); 51 | } 52 | 53 | /// Check a condition at runtime. If the condition is false, throw exception. 54 | static inline void rt_assert(bool condition, std::string throw_str) 55 | { 56 | if (unlikely(!condition)) 57 | throw std::runtime_error(throw_str); 58 | } 59 | 60 | /// Check a condition at runtime. If the condition is false, throw exception. 61 | /// This is faster than rt_assert(cond, str) as it avoids string construction. 62 | static inline void rt_assert(bool condition) 63 | { 64 | if (unlikely(!condition)) 65 | throw std::runtime_error("Error"); 66 | } 67 | 68 | /// Check a condition at runtime. If the condition is false, print error message 69 | /// and exit. 70 | static inline void exit_assert(bool condition, std::string error_msg) 71 | { 72 | if (unlikely(!condition)) 73 | { 74 | fprintf(stderr, "%s. Exiting.\n", error_msg.c_str()); 75 | fflush(stderr); 76 | exit(-1); 77 | } 78 | } 79 | } // namespace redplane 80 | -------------------------------------------------------------------------------- /scripts/servers/01-netcfg.yaml: -------------------------------------------------------------------------------- 1 | # This file describes the network interfaces available on your system 2 | # For more information, see netplan(5). 3 | network: 4 | version: 2 5 | renderer: networkd 6 | ethernets: 7 | eno5: 8 | dhcp4: yes 9 | ens1: 10 | addresses: 11 | - 198.19.200.30/24 12 | - 198.19.10.0/31 13 | routes: 14 | - to: 198.19.10.0/24 15 | via: 198.19.10.1 16 | - to: 198.19.11.0/24 17 | via: 198.19.10.1 18 | - to: 198.19.12.0/24 19 | via: 198.19.10.1 20 | - to: 198.19.13.0/24 21 | via: 198.19.10.1 22 | - to: 198.19.14.0/24 23 | via: 198.19.10.1 24 | - to: 198.19.15.0/24 25 | via: 198.19.10.1 26 | -------------------------------------------------------------------------------- /scripts/servers/cpu_performance.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | for i in {0..39} 3 | do 4 | echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor 5 | done 6 | -------------------------------------------------------------------------------- /scripts/servers/install_mlnx_ofed_all.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | 5 | if __name__ == "__main__": 6 | os.system ('mkdir -p logs') 7 | for i in range(20, 31, 1): 8 | print ('Setup prometheus%s'%(i)) 9 | os.system ('ssh pro%s sudo /h/daehyeok/mlnx_ofed_firmware/MLNX_OFED_LINUX-4.7-3.2.9.0-ubuntu18.04-x86_64/mlnxofedinstall --all --force > logs/setup_log_%s 2>&1'%(i, i)) 10 | os.system ('ssh pro%s sudo /etc/init.d/openibd restart >> logs/setup_log_%s 2>&1'%(i, i)) 11 | print ('End setup prometheus%s'%(i)) 12 | -------------------------------------------------------------------------------- /scripts/servers/ip_list.txt: -------------------------------------------------------------------------------- 1 | 198.19.10.2 2 | 198.19.10.4 3 | 198.19.10.6 4 | 198.19.11.0 5 | 198.19.11.2 6 | 198.19.12.0 7 | 198.19.12.2 8 | 198.19.13.0 9 | 198.19.13.2 10 | -------------------------------------------------------------------------------- /scripts/servers/pingall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | date 3 | cat ip_list.txt | while read output 4 | do 5 | ping -c 1 "$output" > /dev/null 6 | if [ $? -eq 0 ]; then 7 | echo "node $output is up" 8 | else 9 | echo "node $output is down" 10 | fi 11 | done 12 | -------------------------------------------------------------------------------- /scripts/servers/setup_all.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import logging 4 | import threading 5 | import os 6 | 7 | if __name__ == "__main__": 8 | os.system ('mkdir -p logs') 9 | for i in range(19, 31, 1): 10 | print ('Setup prometheus%s'%(i)) 11 | os.system ('ssh pro%s /h/daehyeok/redplane-dev/scripts/servers/setup_hugepages.sh > logs/setup_log_%s 2>&1'%(i, i)) 12 | os.system ('ssh pro%s /h/daehyeok/redplane-dev/scripts/servers/setup_packages.sh >> logs/setup_log_%s 2>&1'%(i, i)) 13 | if i in [26, 24, 22]: 14 | os.system ('ssh pro%s sudo ifconfig ens1 mtu 9000' % (i)) 15 | print ('End setup prometheus%s'%(i)) 16 | 17 | -------------------------------------------------------------------------------- /scripts/servers/setup_hugepages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo 8192 | sudo tee /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages 3 | sudo sysctl -p /etc/sysctl.conf 4 | cat /proc/meminfo | grep -i huge 5 | -------------------------------------------------------------------------------- /scripts/servers/setup_packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | sudo apt-get update 3 | sudo apt-get -y install g++ cmake make flowgrind qperf netpipe-tcp 4 | 5 | sudo apt-get -y install libnuma-dev libgflags-dev libgtest-dev 6 | (cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/) 7 | -------------------------------------------------------------------------------- /scripts/tofino_build/veth_setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | noOfVeths=64 3 | if [ $# -eq 1 ]; then 4 | noOfVeths=$1 5 | fi 6 | echo "No of Veths is $noOfVeths" 7 | let "vethpairs=$noOfVeths/2" 8 | last=`expr $vethpairs - 1` 9 | veths=`seq 0 1 $last` 10 | # add CPU port 11 | veths+=" 125" 12 | 13 | for i in $veths; do 14 | intf0="veth$(($i*2))" 15 | intf1="veth$(($i*2+1))" 16 | if ! ip link show $intf0 &> /dev/null; then 17 | ip link add name $intf0 type veth peer name $intf1 &> /dev/null 18 | fi 19 | ip link set dev $intf0 up 20 | sysctl net.ipv6.conf.$intf0.disable_ipv6=1 &> /dev/null 21 | sysctl net.ipv6.conf.$intf1.disable_ipv6=1 &> /dev/null 22 | ip link set dev $intf0 up mtu 10240 23 | ip link set dev $intf1 up mtu 10240 24 | TOE_OPTIONS="rx tx sg tso ufo gso gro lro rxvlan txvlan rxhash" 25 | for TOE_OPTION in $TOE_OPTIONS; do 26 | /sbin/ethtool --offload $intf0 "$TOE_OPTION" off &> /dev/null 27 | /sbin/ethtool --offload $intf1 "$TOE_OPTION" off &> /dev/null 28 | done 29 | done 30 | -------------------------------------------------------------------------------- /scripts/tofino_build/veth_teardown.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | noOfVeths=64 3 | if [ $# -eq 1 ]; then 4 | noOfVeths=$1 5 | fi 6 | echo "No of Veths is $noOfVeths" 7 | idx=0 8 | while [ $idx -lt $noOfVeths ] 9 | do 10 | #for idx in 0 1 2 3 4 5 6 7 125; do 11 | intf="veth$(($idx*2))" 12 | if ip link show $intf &> /dev/null; then 13 | ip link delete $intf type veth 14 | fi 15 | idx=$((idx + 1)) 16 | done 17 | idx=125 18 | intf="veth$(($idx*2))" 19 | if ip link show $intf &> /dev/null; then 20 | ip link delete $intf type veth 21 | fi 22 | --------------------------------------------------------------------------------