P4 source files for BMv2 demo
Change-Id: I3adc57eb346e3cb34f17d54b82505d2d9e89b4ad
diff --git a/tools/test/p4src/default.p4 b/tools/test/p4src/default.p4
new file mode 100644
index 0000000..3d5629e
--- /dev/null
+++ b/tools/test/p4src/default.p4
@@ -0,0 +1,31 @@
+#include "include/defines.p4"
+#include "include/headers.p4"
+#include "include/parser.p4"
+#include "include/actions.p4"
+#include "include/port_counters.p4"
+
+table table0 {
+ reads {
+ standard_metadata.ingress_port : ternary;
+ ethernet.dstAddr : ternary;
+ ethernet.srcAddr : ternary;
+ ethernet.etherType : ternary;
+ }
+ actions {
+ set_egress_port;
+ send_to_cpu;
+ _drop;
+ }
+ support_timeout: true;
+}
+
+counter table0_counter {
+ type: packets;
+ direct: table0;
+ min_width : 32;
+}
+
+control ingress {
+ apply(table0);
+ process_port_counters();
+}
\ No newline at end of file
diff --git a/tools/test/p4src/ecmp.p4 b/tools/test/p4src/ecmp.p4
new file mode 100644
index 0000000..95af85f
--- /dev/null
+++ b/tools/test/p4src/ecmp.p4
@@ -0,0 +1,84 @@
+#include "include/defines.p4"
+#include "include/headers.p4"
+#include "include/parser.p4"
+#include "include/actions.p4"
+#include "include/port_counters.p4"
+
+header_type ecmp_metadata_t {
+ fields {
+ groupId : 16;
+ selector : 16;
+ }
+}
+
+metadata ecmp_metadata_t ecmp_metadata;
+
+field_list ecmp_hash_fields {
+ ipv4.srcAddr;
+ ipv4.dstAddr;
+ ipv4.protocol;
+ tcp.srcPort;
+ tcp.dstPort;
+ udp.srcPort;
+ udp.dstPort;
+}
+
+field_list_calculation ecmp_hash {
+ input {
+ ecmp_hash_fields;
+ }
+ algorithm : bmv2_hash;
+ output_width : 64;
+}
+
+action ecmp_group(groupId, groupSize) {
+ modify_field(ecmp_metadata.groupId, groupId);
+ modify_field_with_hash_based_offset(ecmp_metadata.selector, 0, ecmp_hash, groupSize);
+}
+
+table table0 {
+ reads {
+ standard_metadata.ingress_port : ternary;
+ ethernet.dstAddr : ternary;
+ ethernet.srcAddr : ternary;
+ ethernet.etherType : ternary;
+ }
+ actions {
+ set_egress_port;
+ ecmp_group;
+ send_to_cpu;
+ _drop;
+ }
+ support_timeout: true;
+}
+
+table ecmp_group_table {
+ reads {
+ ecmp_metadata.groupId : exact;
+ ecmp_metadata.selector : exact;
+ }
+ actions {
+ set_egress_port;
+ }
+}
+
+counter table0_counter {
+ type: packets;
+ direct: table0;
+ min_width : 32;
+}
+
+counter ecmp_group_table_counter {
+ type: packets;
+ direct: ecmp_group_table;
+ min_width : 32;
+}
+
+control ingress {
+ apply(table0) {
+ ecmp_group {
+ apply(ecmp_group_table);
+ }
+ }
+ process_port_counters();
+}
\ No newline at end of file
diff --git a/tools/test/p4src/empty.p4 b/tools/test/p4src/empty.p4
new file mode 100644
index 0000000..91e6e67
--- /dev/null
+++ b/tools/test/p4src/empty.p4
@@ -0,0 +1,28 @@
+header_type dummy_t {
+ fields {
+ dummyField : 8;
+ }
+}
+
+metadata dummy_t dummy_metadata;
+
+parser start {
+ return ingress;
+}
+
+table table0 {
+ reads {
+ dummy_metadata.dummyField : exact;
+ }
+ actions {
+ dummy_action;
+ }
+}
+
+action dummy_action() {
+ modify_field(dummy_metadata.dummyField, 1);
+}
+
+control ingress {
+ apply(table0);
+}
\ No newline at end of file
diff --git a/tools/test/p4src/include/actions.p4 b/tools/test/p4src/include/actions.p4
new file mode 100644
index 0000000..a8693e2
--- /dev/null
+++ b/tools/test/p4src/include/actions.p4
@@ -0,0 +1,11 @@
+action set_egress_port(port) {
+ modify_field(standard_metadata.egress_spec, port);
+}
+
+action _drop() {
+ modify_field(standard_metadata.egress_spec, DROP_PORT);
+}
+
+action send_to_cpu() {
+ modify_field(standard_metadata.egress_spec, CPU_PORT);
+}
\ No newline at end of file
diff --git a/tools/test/p4src/include/defines.p4 b/tools/test/p4src/include/defines.p4
new file mode 100644
index 0000000..c9229c9
--- /dev/null
+++ b/tools/test/p4src/include/defines.p4
@@ -0,0 +1,4 @@
+// Logic ports as defined in the simple_switch target
+#define MAX_PORTS 254
+#define CPU_PORT 255
+#define DROP_PORT 511
diff --git a/tools/test/p4src/include/headers.p4 b/tools/test/p4src/include/headers.p4
new file mode 100644
index 0000000..57bda87
--- /dev/null
+++ b/tools/test/p4src/include/headers.p4
@@ -0,0 +1,58 @@
+header_type intrinsic_metadata_t {
+ fields {
+ ingress_global_timestamp : 32;
+ lf_field_list : 32;
+ mcast_grp : 16;
+ egress_rid : 16;
+ }
+}
+
+header_type ethernet_t {
+ fields {
+ dstAddr : 48;
+ srcAddr : 48;
+ etherType : 16;
+ }
+}
+
+header_type ipv4_t {
+ fields {
+ version : 4;
+ ihl : 4;
+ diffserv : 8;
+ totalLen : 16;
+ identification : 16;
+ flags : 3;
+ fragOffset : 13;
+ ttl : 8;
+ protocol : 8;
+ hdrChecksum : 16;
+ srcAddr : 32;
+ dstAddr: 32;
+ }
+}
+
+header_type tcp_t {
+ fields {
+ srcPort : 16;
+ dstPort : 16;
+ seqNo : 32;
+ ackNo : 32;
+ dataOffset : 4;
+ res : 3;
+ ecn : 3;
+ ctrl : 6;
+ window : 16;
+ checksum : 16;
+ urgentPtr : 16;
+ }
+}
+
+header_type udp_t {
+ fields {
+ srcPort : 16;
+ dstPort : 16;
+ length_ : 16;
+ checksum : 16;
+ }
+}
\ No newline at end of file
diff --git a/tools/test/p4src/include/parser.p4 b/tools/test/p4src/include/parser.p4
new file mode 100644
index 0000000..6a205ec
--- /dev/null
+++ b/tools/test/p4src/include/parser.p4
@@ -0,0 +1,45 @@
+metadata intrinsic_metadata_t intrinsic_metadata;
+
+parser start {
+ return parse_ethernet;
+}
+
+#define ETHERTYPE_IPV4 0x0800
+
+header ethernet_t ethernet;
+
+parser parse_ethernet {
+ extract(ethernet);
+ return select(latest.etherType) {
+ ETHERTYPE_IPV4 : parse_ipv4;
+ default : ingress;
+ }
+}
+
+header ipv4_t ipv4;
+
+#define IP_PROTOCOLS_TCP 6
+#define IP_PROTOCOLS_UDP 17
+
+parser parse_ipv4 {
+ extract(ipv4);
+ return select(latest.fragOffset, latest.protocol) {
+ IP_PROTOCOLS_TCP : parse_tcp;
+ IP_PROTOCOLS_UDP : parse_udp;
+ default: ingress;
+ }
+}
+
+header tcp_t tcp;
+
+parser parse_tcp {
+ extract(tcp);
+ return ingress;
+}
+
+header udp_t udp;
+
+parser parse_udp {
+ extract(udp);
+ return ingress;
+}
\ No newline at end of file
diff --git a/tools/test/p4src/include/port_counters.p4 b/tools/test/p4src/include/port_counters.p4
new file mode 100644
index 0000000..06cba4f
--- /dev/null
+++ b/tools/test/p4src/include/port_counters.p4
@@ -0,0 +1,29 @@
+counter ingress_port_counter {
+ type : packets; // bmv2 always counts both bytes and packets
+ instance_count : MAX_PORTS;
+ min_width : 32;
+}
+
+counter egress_port_counter {
+ type: packets;
+ instance_count : MAX_PORTS;
+ min_width : 32;
+}
+
+table port_count_table {
+ actions {
+ count_packet;
+ }
+}
+
+action count_packet() {
+ count(ingress_port_counter, standard_metadata.ingress_port);
+ count(egress_port_counter, standard_metadata.egress_spec);
+}
+
+control process_port_counters {
+ // Avoid counting logical ports, such as drop and cpu
+ if (standard_metadata.egress_spec < MAX_PORTS) {
+ apply(port_count_table);
+ }
+}
\ No newline at end of file
diff --git a/tools/test/p4src/wcmp.p4 b/tools/test/p4src/wcmp.p4
new file mode 100644
index 0000000..1cb6a6c
--- /dev/null
+++ b/tools/test/p4src/wcmp.p4
@@ -0,0 +1,102 @@
+#include "include/defines.p4"
+#include "include/headers.p4"
+#include "include/parser.p4"
+#include "include/actions.p4"
+#include "include/port_counters.p4"
+
+#define SELECTOR_WIDTH 64
+
+header_type wcmp_meta_t {
+ fields {
+ groupId : 16;
+ numBits: 8;
+ selector : SELECTOR_WIDTH;
+ }
+}
+
+metadata wcmp_meta_t wcmp_meta;
+
+field_list wcmp_hash_fields {
+ ipv4.srcAddr;
+ ipv4.dstAddr;
+ ipv4.protocol;
+ tcp.srcPort;
+ tcp.dstPort;
+ udp.srcPort;
+ udp.dstPort;
+}
+
+field_list_calculation wcmp_hash {
+ input {
+ wcmp_hash_fields;
+ }
+ algorithm : bmv2_hash;
+ output_width : 64;
+}
+
+action wcmp_group(groupId) {
+ modify_field(wcmp_meta.groupId, groupId);
+ modify_field_with_hash_based_offset(wcmp_meta.numBits, 2, wcmp_hash, (SELECTOR_WIDTH - 2));
+}
+
+action wcmp_set_selector() {
+ modify_field(wcmp_meta.selector,
+ (((1 << wcmp_meta.numBits) - 1) << (SELECTOR_WIDTH - wcmp_meta.numBits)));
+}
+
+table table0 {
+ reads {
+ standard_metadata.ingress_port : ternary;
+ ethernet.dstAddr : ternary;
+ ethernet.srcAddr : ternary;
+ ethernet.etherType : ternary;
+ }
+ actions {
+ set_egress_port;
+ wcmp_group;
+ send_to_cpu;
+ _drop;
+ }
+ support_timeout: true;
+}
+
+table wcmp_set_selector_table {
+ actions {
+ wcmp_set_selector;
+ }
+}
+
+table wcmp_group_table {
+ reads {
+ wcmp_meta.groupId : exact;
+ wcmp_meta.selector : lpm;
+ }
+ actions {
+ set_egress_port;
+ }
+}
+
+counter table0_counter {
+ type: packets;
+ direct: table0;
+ min_width : 32;
+}
+
+counter wcmp_group_table_counter {
+ type: packets;
+ direct: wcmp_group_table;
+ min_width : 32;
+}
+
+control ingress {
+ apply(table0) {
+ wcmp_group {
+ apply(wcmp_set_selector_table) {
+ wcmp_set_selector {
+ apply(wcmp_group_table);
+ }
+ }
+ }
+ }
+ process_port_counters();
+}
\ No newline at end of file