Refactor fabric.p4 INT support to allow compilation on more P4 targets
Also use constant entries for instruction mask tables to avoid
programming them at runtime.
Change-Id: Ia1ab1ecd42a433daec171f9a30bcdba3b8484061
diff --git a/pipelines/fabric/src/main/resources/include/parser.p4 b/pipelines/fabric/src/main/resources/include/parser.p4
index 20c310c..3f77df9 100644
--- a/pipelines/fabric/src/main/resources/include/parser.p4
+++ b/pipelines/fabric/src/main/resources/include/parser.p4
@@ -25,6 +25,8 @@
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
+ bit<6> last_ipv4_dscp = 0;
+
state start {
transition select(standard_metadata.ingress_port) {
CPU_PORT: parse_packet_out;
@@ -82,6 +84,7 @@
state parse_ipv4 {
packet.extract(hdr.ipv4);
fabric_metadata.ip_proto = hdr.ipv4.protocol;
+ last_ipv4_dscp = hdr.ipv4.dscp;
//Need header verification?
transition select(hdr.ipv4.protocol) {
PROTO_TCP: parse_tcp;
@@ -114,10 +117,7 @@
fabric_metadata.l4_src_port = hdr.tcp.src_port;
fabric_metadata.l4_dst_port = hdr.tcp.dst_port;
#ifdef WITH_INT
- transition select(hdr.ipv4.isValid() && ((hdr.ipv4.dscp & INT_DSCP) == INT_DSCP)) {
- true: parse_intl4_shim;
- default: accept;
- }
+ transition parse_int;
#else
transition accept;
#endif // WITH_INT
@@ -127,19 +127,16 @@
packet.extract(hdr.udp);
fabric_metadata.l4_src_port = hdr.udp.src_port;
fabric_metadata.l4_dst_port = hdr.udp.dst_port;
-#ifdef WITH_SPGW
transition select(hdr.udp.dst_port) {
+#ifdef WITH_SPGW
UDP_PORT_GTPU: parse_gtpu;
- default: accept;
- }
-#elif WITH_INT
- transition select(hdr.ipv4.isValid() && (hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
- true: parse_intl4_shim;
- default: accept;
- }
+#endif // WITH_SPGW
+#ifdef WITH_INT
+ default: parse_int;
#else
- transition accept;
-#endif // WITH_SPGW, WITH_INT
+ default: accept;
+#endif // WITH_INT
+ }
}
state parse_icmp {
@@ -147,36 +144,6 @@
transition accept;
}
-#ifdef WITH_INT
- state parse_intl4_shim {
- packet.extract(hdr.intl4_shim);
- transition parse_int_header;
- }
-
- state parse_int_header {
- packet.extract(hdr.int_header);
- // If there is no INT metadata but the INT header (and corresponding shim header
- // and tail header) exists, default value of length field in shim header
- // should be INT_HEADER_LEN_WORD.
- fabric_metadata.int_meta.metadata_len = hdr.intl4_shim.len - INT_HEADER_LEN_WORD;
- transition select (fabric_metadata.int_meta.metadata_len) {
- 0: parse_intl4_tail;
- default: parse_int_data;
- }
- }
-
- state parse_int_data {
- // Parse INT metadata, not INT header, INT shim header and INT tail header
- packet.extract(hdr.int_data, (bit<32>) ((hdr.intl4_shim.len - INT_HEADER_LEN_WORD) << 5));
- transition parse_intl4_tail;
- }
-
- state parse_intl4_tail {
- packet.extract(hdr.intl4_tail);
- transition accept;
- }
-#endif // WITH_INT
-
#ifdef WITH_SPGW
state parse_gtpu {
transition select(hdr.ipv4.dst_addr[31:32-S1U_SGW_PREFIX_LEN]) {
@@ -196,6 +163,7 @@
state parse_inner_ipv4 {
packet.extract(hdr.inner_ipv4);
+ last_ipv4_dscp = hdr.inner_ipv4.dscp;
transition select(hdr.inner_ipv4.protocol) {
PROTO_TCP: parse_tcp;
PROTO_UDP: parse_inner_udp;
@@ -209,26 +177,63 @@
fabric_metadata.l4_src_port = hdr.inner_udp.src_port;
fabric_metadata.l4_dst_port = hdr.inner_udp.dst_port;
#ifdef WITH_INT
- transition select(hdr.ipv4.isValid() && (hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
- true: parse_intl4_shim;
- default: accept;
- }
+ transition parse_int;
#else
transition accept;
#endif // WITH_INT
}
#endif // WITH_SPGW
+
+#ifdef WITH_INT
+ state parse_int {
+ transition select(last_ipv4_dscp) {
+ INT_DSCP &&& INT_DSCP: parse_intl4_shim;
+ default: accept;
+ }
+ }
+
+ state parse_intl4_shim {
+ packet.extract(hdr.intl4_shim);
+ transition parse_int_header;
+ }
+
+ state parse_int_header {
+ packet.extract(hdr.int_header);
+ // If there is no INT metadata but the INT header (plus shim and tail)
+ // exists, default value of length field in shim header should be
+ // INT_HEADER_LEN_WORDS.
+ transition select (hdr.intl4_shim.len_words) {
+ INT_HEADER_LEN_WORDS: parse_intl4_tail;
+ default: parse_int_data;
+ }
+ }
+
+ state parse_int_data {
+#ifdef WITH_INT_SINK
+ // Parse INT metadata stack, but not tail
+ packet.extract(hdr.int_data, (bit<32>) (hdr.intl4_shim.len_words - INT_HEADER_LEN_WORDS) << 5);
+ transition parse_intl4_tail;
+#else // not interested in INT data
+ transition accept;
+#endif // WITH_INT_SINK
+ }
+
+ state parse_intl4_tail {
+ packet.extract(hdr.intl4_tail);
+ transition accept;
+ }
+#endif // WITH_INT
}
control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
apply {
packet.emit(hdr.packet_in);
-#ifdef WITH_INT
+#ifdef WITH_INT_SINK
packet.emit(hdr.report_ethernet);
packet.emit(hdr.report_ipv4);
packet.emit(hdr.report_udp);
packet.emit(hdr.report_fixed_header);
-#endif // WITH_INT
+#endif // WITH_INT_SINK
packet.emit(hdr.ethernet);
packet.emit(hdr.vlan_tag);
packet.emit(hdr.mpls);
@@ -248,6 +253,7 @@
#ifdef WITH_INT
packet.emit(hdr.intl4_shim);
packet.emit(hdr.int_header);
+#ifdef WITH_INT_TRANSIT
packet.emit(hdr.int_switch_id);
packet.emit(hdr.int_port_ids);
packet.emit(hdr.int_hop_latency);
@@ -256,6 +262,7 @@
packet.emit(hdr.int_egress_tstamp);
packet.emit(hdr.int_q_congestion);
packet.emit(hdr.int_egress_tx_util);
+#endif // WITH_INT_TRANSIT
packet.emit(hdr.int_data);
packet.emit(hdr.intl4_tail);
#endif // WITH_INT