├── 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