INT transit for tofino (only with spgw enabled)

Because of recent update in p4c that uses different names for
P4 entities, requires manual search/replace in p4info/context.json

Change-Id: If7d6ea738710ef0c8786d9ff07f21f240fb6cedc
diff --git a/pipelines/fabric/src/main/resources/include/checksum.p4 b/pipelines/fabric/src/main/resources/include/checksum.p4
index d920235..4d1b803 100644
--- a/pipelines/fabric/src/main/resources/include/checksum.p4
+++ b/pipelines/fabric/src/main/resources/include/checksum.p4
@@ -29,7 +29,8 @@
             {
                 hdr.ipv4.version,
                 hdr.ipv4.ihl,
-                hdr.ipv4.diffserv,
+                hdr.ipv4.dscp,
+                hdr.ipv4.ecn,
                 hdr.ipv4.total_len,
                 hdr.ipv4.identification,
                 hdr.ipv4.flags,
@@ -57,7 +58,8 @@
             {
                 hdr.ipv4.version,
                 hdr.ipv4.ihl,
-                hdr.ipv4.diffserv,
+                hdr.ipv4.dscp,
+                hdr.ipv4.ecn,
                 hdr.ipv4.total_len,
                 hdr.ipv4.identification,
                 hdr.ipv4.flags,
diff --git a/pipelines/fabric/src/main/resources/include/define.p4 b/pipelines/fabric/src/main/resources/include/define.p4
index eb61f91..a74f9ab 100644
--- a/pipelines/fabric/src/main/resources/include/define.p4
+++ b/pipelines/fabric/src/main/resources/include/define.p4
@@ -91,4 +91,6 @@
 const pcc_gate_status_t PCC_GATE_OPEN = 1w0;
 const pcc_gate_status_t PCC_GATE_CLOSED = 1w1;
 
+const bit<6> DSCP_INT = 0x1;
+
 #endif
diff --git a/pipelines/fabric/src/main/resources/include/header.p4 b/pipelines/fabric/src/main/resources/include/header.p4
index 6cff586..6a48452 100644
--- a/pipelines/fabric/src/main/resources/include/header.p4
+++ b/pipelines/fabric/src/main/resources/include/header.p4
@@ -55,7 +55,8 @@
 header ipv4_t {
     bit<4> version;
     bit<4> ihl;
-    bit<8> diffserv;
+    bit<6> dscp;
+    bit<2> ecn;
     bit<16> total_len;
     bit<16> identification;
     bit<3> flags;
@@ -131,7 +132,7 @@
 }
 
 struct spgw_meta_t {
-    bool              do_spgw;
+    bit<1>            do_spgw;
     direction_t       direction;
     bit<16>           ipv4_len;
     bit<32>           teid;
@@ -147,6 +148,78 @@
 }
 #endif // WITH_SPGW
 
+#ifdef WITH_INT_TRANSIT
+
+header intl4_shim_t {
+    bit<8> int_type;
+    bit<8> rsvd1;
+    bit<8> len;
+    bit<8> rsvd2;
+}
+
+// INT headers
+header int_header_t {
+    bit<4> ver;
+    bit<2> rep;
+    bit<1> c;
+    bit<1> e;
+    bit<3> rsvd1;
+    bit<5> ins_cnt;
+    bit<8> max_hop_cnt;
+    bit<8> total_hop_cnt;
+    bit<4> instruction_mask_0003; // split the bits for lookup
+    bit<4> instruction_mask_0407;
+    bit<4> instruction_mask_0811;
+    bit<4> instruction_mask_1215;
+    bit<16> rsvd2;
+}
+
+// INT meta-value headers - different header for each value type
+header int_switch_id_t {
+    bit<32> switch_id;
+}
+
+header int_port_ids_t {
+    bit<16> ingress_port_id;
+    bit<16> egress_port_id;
+}
+
+header int_hop_latency_t {
+    bit<32> hop_latency;
+}
+
+header int_q_occupancy_t {
+    bit<8> q_id;
+    bit<24> q_occupancy;
+}
+
+header int_ingress_tstamp_t {
+    bit<32> ingress_tstamp;
+}
+
+header int_egress_tstamp_t {
+    bit<32> egress_tstamp;
+}
+
+header int_q_congestion_t {
+    bit<8> q_id;
+    bit<24> q_congestion;
+}
+
+header int_egress_port_tx_util_t {
+    bit<32> egress_port_tx_util;
+}
+
+// switch internal variables for INT logic implementation
+struct int_metadata_t {
+    bit<16> insert_byte_cnt;
+    bit<8> int_hdr_word_len;
+    bit<32> switch_id;
+    bit<5> ins_cnt_tmp;
+}
+
+#endif // WITH_INT_TRANSIT
+
 //Custom metadata definition
 struct fabric_metadata_t {
     fwd_type_t fwd_type;
@@ -159,6 +232,9 @@
 #ifdef WITH_SPGW
     spgw_meta_t spgw;
 #endif // WITH_SPGW
+#ifdef WITH_INT_TRANSIT
+    int_metadata_t int_metadata;
+#endif // WITH_INT_TRANSIT
 }
 
 struct parsed_headers_t {
@@ -180,6 +256,18 @@
     icmp_t icmp;
     packet_out_header_t packet_out;
     packet_in_header_t packet_in;
+#ifdef WITH_INT_TRANSIT
+    intl4_shim_t intl4_shim;
+    int_header_t int_header;
+    int_switch_id_t int_switch_id;
+    int_port_ids_t int_port_ids;
+    int_hop_latency_t int_hop_latency;
+    int_q_occupancy_t int_q_occupancy;
+    int_ingress_tstamp_t int_ingress_tstamp;
+    int_egress_tstamp_t int_egress_tstamp;
+    int_q_congestion_t int_q_congestion;
+    int_egress_port_tx_util_t int_egress_port_tx_util;
+#endif // WITH_INT_TRANSIT
 }
 
 #endif
diff --git a/pipelines/fabric/src/main/resources/include/int_transit.p4 b/pipelines/fabric/src/main/resources/include/int_transit.p4
new file mode 100644
index 0000000..d09eab8
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/include/int_transit.p4
@@ -0,0 +1,299 @@
+control int_metadata_insert(inout parsed_headers_t hdr,
+                            in int_metadata_t int_metadata,
+                            inout standard_metadata_t standard_metadata) {
+    // this implementation covers only INT instructions 0, 1, 2, 4, 5
+    action int_set_header_0() {
+        hdr.int_switch_id.setValid();
+        hdr.int_switch_id.switch_id = int_metadata.switch_id;
+    }
+
+    action int_set_header_1() {
+        hdr.int_port_ids.setValid();
+        hdr.int_port_ids.ingress_port_id =
+            (bit<16>) standard_metadata.ingress_port;
+        hdr.int_port_ids.egress_port_id =
+            (bit<16>) standard_metadata.egress_port;
+    }
+
+    action int_set_header_2() {
+        hdr.int_hop_latency.setValid();
+        hdr.int_hop_latency.hop_latency = 0xffffffff;
+    }
+
+    action int_set_header_3() { // Queue ID + Queue occupancy, not supported
+        hdr.int_q_occupancy.setValid();
+        hdr.int_q_occupancy.q_id = 0x00;
+        hdr.int_q_occupancy.q_occupancy = (bit<24>) standard_metadata.deq_qdepth;
+    }
+
+    action int_set_header_4() {
+        hdr.int_ingress_tstamp.setValid();
+        hdr.int_ingress_tstamp.ingress_tstamp =
+            (bit<32>) standard_metadata.ingress_global_timestamp;
+    }
+
+    action int_set_header_5() {
+        hdr.int_egress_tstamp.setValid();
+        hdr.int_egress_tstamp.egress_tstamp =
+            (bit<32>) standard_metadata.egress_global_timestamp;
+    }
+
+    action int_set_header_6() { // Queue ID + Queue congestion status, not supported
+        hdr.int_q_congestion.setValid();
+        hdr.int_q_congestion.q_id = 0xff;
+        hdr.int_q_congestion.q_congestion = 0xffffff;
+    }
+
+    action int_set_header_7() { // Egress port tx utilization, not supported
+        hdr.int_egress_port_tx_util.setValid();
+        hdr.int_egress_port_tx_util.egress_port_tx_util = 0xffffffff;
+    }
+
+    action int_set_header_0003_i0() {
+    }
+    action int_set_header_0003_i1() {
+        int_set_header_3();
+    }
+    action int_set_header_0003_i2() {
+        int_set_header_2();
+    }
+    action int_set_header_0003_i3() {
+        int_set_header_3();
+        int_set_header_2();
+    }
+    action int_set_header_0003_i4() {
+        int_set_header_1();
+    }
+    action int_set_header_0003_i5() {
+        int_set_header_3();
+        int_set_header_1();
+    }
+    action int_set_header_0003_i6() {
+        int_set_header_2();
+        int_set_header_1();
+    }
+    action int_set_header_0003_i7() {
+        int_set_header_3();
+        int_set_header_2();
+        int_set_header_1();
+    }
+    action int_set_header_0003_i8() {
+        int_set_header_0();
+    }
+    action int_set_header_0003_i9() {
+        int_set_header_3();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i10() {
+        int_set_header_2();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i11() {
+        int_set_header_3();
+        int_set_header_2();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i12() {
+        int_set_header_1();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i13() {
+        int_set_header_3();
+        int_set_header_1();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i14() {
+        int_set_header_2();
+        int_set_header_1();
+        int_set_header_0();
+    }
+    action int_set_header_0003_i15() {
+        int_set_header_3();
+        int_set_header_2();
+        int_set_header_1();
+        int_set_header_0();
+    }
+
+    table int_inst_0003 {
+        key = {
+            hdr.int_header.instruction_mask_0003 : exact;
+        }
+        actions = {
+            int_set_header_0003_i0;
+            int_set_header_0003_i1;
+            int_set_header_0003_i2;
+            int_set_header_0003_i3;
+            int_set_header_0003_i4;
+            int_set_header_0003_i5;
+            int_set_header_0003_i6;
+            int_set_header_0003_i7;
+            int_set_header_0003_i8;
+            int_set_header_0003_i9;
+            int_set_header_0003_i10;
+            int_set_header_0003_i11;
+            int_set_header_0003_i12;
+            int_set_header_0003_i13;
+            int_set_header_0003_i14;
+            int_set_header_0003_i15;
+        }
+        default_action = int_set_header_0003_i0();
+        size = 17;
+    }
+
+    action int_set_header_0407_i0() {
+    }
+    action int_set_header_0407_i1() {
+        int_set_header_7();
+    }
+    action int_set_header_0407_i2() {
+        int_set_header_6();
+    }
+    action int_set_header_0407_i3() {
+        int_set_header_7();
+        int_set_header_6();
+    }
+    action int_set_header_0407_i4() {
+        int_set_header_5();
+    }
+    action int_set_header_0407_i5() {
+        int_set_header_7();
+        int_set_header_5();
+    }
+    action int_set_header_0407_i6() {
+        int_set_header_6();
+        int_set_header_5();
+    }
+    action int_set_header_0407_i7() {
+        int_set_header_7();
+        int_set_header_6();
+        int_set_header_5();
+    }
+    action int_set_header_0407_i8() {
+        int_set_header_4();
+    }
+    action int_set_header_0407_i9() {
+        int_set_header_7();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i10() {
+        int_set_header_6();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i11() {
+        int_set_header_7();
+        int_set_header_6();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i12() {
+        int_set_header_5();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i13() {
+        int_set_header_7();
+        int_set_header_5();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i14() {
+        int_set_header_6();
+        int_set_header_5();
+        int_set_header_4();
+    }
+    action int_set_header_0407_i15() {
+        int_set_header_7();
+        int_set_header_6();
+        int_set_header_5();
+        int_set_header_4();
+    }
+
+    table int_inst_0407 {
+        key = {
+            hdr.int_header.instruction_mask_0407 : exact;
+        }
+        actions = {
+            int_set_header_0407_i0;
+            int_set_header_0407_i1;
+            int_set_header_0407_i2;
+            int_set_header_0407_i3;
+            int_set_header_0407_i4;
+            int_set_header_0407_i5;
+            int_set_header_0407_i6;
+            int_set_header_0407_i7;
+            int_set_header_0407_i8;
+            int_set_header_0407_i9;
+            int_set_header_0407_i10;
+            int_set_header_0407_i11;
+            int_set_header_0407_i12;
+            int_set_header_0407_i13;
+            int_set_header_0407_i14;
+            int_set_header_0407_i15;
+        }
+        default_action = int_set_header_0407_i0();
+        size = 17;
+    }
+
+    apply {
+        int_inst_0003.apply();
+        int_inst_0407.apply();
+    }
+}
+
+control int_outer_encap(inout parsed_headers_t hdr,
+                        in int_metadata_t int_metadata) {
+    action int_update_ipv4() {
+        hdr.ipv4.total_len = hdr.ipv4.total_len + int_metadata.insert_byte_cnt;
+    }
+    action int_update_udp() {
+        hdr.udp.len = hdr.udp.len + int_metadata.insert_byte_cnt;
+        hdr.udp.checksum = 0;
+    }
+    action int_update_shim() {
+        hdr.intl4_shim.len = hdr.intl4_shim.len + int_metadata.int_hdr_word_len;
+    }
+
+    apply{
+        if (hdr.ipv4.isValid()) {
+            int_update_ipv4();
+        }
+        if (hdr.udp.isValid()) {
+            int_update_udp();
+        }
+        if (hdr.intl4_shim.isValid()) {
+            int_update_shim();
+        }
+    }
+}
+
+control int_egress(inout parsed_headers_t hdr,
+                   inout int_metadata_t int_metadata,
+                   inout standard_metadata_t standard_metadata) {
+    action int_transit(bit<32> switch_id) {
+        int_metadata.switch_id = switch_id;
+        int_metadata.insert_byte_cnt = (bit<16>) (hdr.int_header.ins_cnt << 2);
+        int_metadata.int_hdr_word_len = (bit<8>) int_metadata.ins_cnt_tmp;
+    }
+    table int_prep {
+        key = {}
+        actions = {int_transit;}
+    }
+
+    action int_hop_cnt_increment() {
+        hdr.int_header.total_hop_cnt = hdr.int_header.total_hop_cnt + 1;
+    }
+    action int_hop_cnt_exceeded() {
+        hdr.int_header.e = 1;
+    }
+
+    apply{
+        if(hdr.int_header.isValid()) {
+            if(hdr.int_header.total_hop_cnt != hdr.int_header.max_hop_cnt &&
+               hdr.int_header.e == 0) {
+                int_hop_cnt_increment();
+                int_prep.apply();
+                int_metadata_insert.apply(hdr, int_metadata, standard_metadata);
+                int_outer_encap.apply(hdr, int_metadata);
+            } else {
+                int_hop_cnt_exceeded();
+            }
+        }
+    }
+}
diff --git a/pipelines/fabric/src/main/resources/include/parser.p4 b/pipelines/fabric/src/main/resources/include/parser.p4
index 8b03da1..2920a15 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);
+        last_ipv4_dscp = hdr.ipv4.dscp;
         fabric_metadata.ip_proto = hdr.ipv4.protocol;
         //Need header verification?
         transition select(hdr.ipv4.protocol) {
@@ -121,14 +124,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;
-        }
-#else
-        transition accept;
 #endif // WITH_SPGW
+#ifdef WITH_INT_TRANSIT
+            default: parse_int;
+#else
+            default: accept;
+#endif // WITH_INT_TRANSIT
+        }
     }
 
     state parse_icmp {
@@ -144,6 +149,7 @@
 
     state parse_ipv4_inner {
         packet.extract(hdr.gtpu_ipv4);
+        last_ipv4_dscp = hdr.gtpu_ipv4.dscp;
         transition select(hdr.gtpu_ipv4.protocol) {
             PROTO_TCP: parse_tcp;
             PROTO_UDP: parse_udp_inner;
@@ -156,9 +162,33 @@
         packet.extract(hdr.gtpu_udp);
         fabric_metadata.l4_src_port = hdr.gtpu_udp.src_port;
         fabric_metadata.l4_dst_port = hdr.gtpu_udp.dst_port;
+#ifdef WITH_INT_TRANSIT
+        transition parse_int;
+#else
         transition accept;
+#endif // WITH_INT_TRANSIT
     }
 #endif // WITH_SPGW
+
+#ifdef WITH_INT_TRANSIT
+    state parse_int {
+        transition select(last_ipv4_dscp) {
+            DSCP_INT &&& DSCP_INT: 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);
+        fabric_metadata.int_metadata.ins_cnt_tmp = hdr.int_header.ins_cnt;
+        transition accept;
+    }
+#endif // WITH_INT_TRANSIT
 }
 
 control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
@@ -180,6 +210,18 @@
         packet.emit(hdr.tcp);
         packet.emit(hdr.udp);
         packet.emit(hdr.icmp);
+#ifdef WITH_INT_TRANSIT
+        packet.emit(hdr.intl4_shim);
+        packet.emit(hdr.int_header);
+        packet.emit(hdr.int_switch_id);
+        packet.emit(hdr.int_port_ids);
+        packet.emit(hdr.int_hop_latency);
+        packet.emit(hdr.int_q_occupancy);
+        packet.emit(hdr.int_ingress_tstamp);
+        packet.emit(hdr.int_egress_tstamp);
+        packet.emit(hdr.int_q_congestion);
+        packet.emit(hdr.int_egress_port_tx_util);
+#endif // WITH_INT_TRANSIT
     }
 }
 
diff --git a/pipelines/fabric/src/main/resources/include/spgw.p4 b/pipelines/fabric/src/main/resources/include/spgw.p4
index 87839f6..c724530 100644
--- a/pipelines/fabric/src/main/resources/include/spgw.p4
+++ b/pipelines/fabric/src/main/resources/include/spgw.p4
@@ -143,7 +143,7 @@
     }
 
     apply {
-        spgw_meta.do_spgw = false;
+        spgw_meta.do_spgw = 1w0;
         if (gtpu.isValid()) {
             // If here, the parsed ipv4 header is the outer GTP one, but
             // fabric needs to forward on the inner one, i.e. this.
@@ -156,15 +156,15 @@
 
             if (s1u_filter_table.apply().hit) {
                 // TODO: check also that gtpu.msgtype == GTP_GPDU
-                spgw_meta.do_spgw = true;
+                spgw_meta.do_spgw = 1w1;
                 spgw_meta.direction = DIR_UPLINK;
             }
         } else if (ue_filter_table.apply().hit) {
-            spgw_meta.do_spgw = true;
+            spgw_meta.do_spgw = 1w1;
             spgw_meta.direction = DIR_DOWNLINK;
         }
 
-        if (!spgw_meta.do_spgw) {
+        if (spgw_meta.do_spgw == 1w0) {
             // Exit this control block.
             return;
         }
@@ -214,7 +214,8 @@
         gtpu_ipv4.setValid();
         gtpu_ipv4.version = IP_VERSION_4;
         gtpu_ipv4.ihl = IPV4_MIN_IHL;
-        gtpu_ipv4.diffserv = 0;
+        gtpu_ipv4.dscp = 0;
+        gtpu_ipv4.ecn = 0;
         gtpu_ipv4.total_len = spgw_meta.ipv4_len
                 + (IPV4_HDR_SIZE + UDP_HDR_SIZE + GTP_HDR_SIZE);
         gtpu_ipv4.identification = 0x1513; /* From NGIC */
@@ -246,7 +247,7 @@
     }
 
     apply {
-        if (spgw_meta.do_spgw && spgw_meta.direction == DIR_DOWNLINK) {
+        if (spgw_meta.do_spgw == 1w1 && spgw_meta.direction == DIR_DOWNLINK) {
             gtpu_encap();
         }
     }
@@ -297,7 +298,8 @@
             {
                 gtpu_ipv4.version,
                 gtpu_ipv4.ihl,
-                gtpu_ipv4.diffserv,
+                gtpu_ipv4.dscp,
+                gtpu_ipv4.ecn,
                 gtpu_ipv4.total_len,
                 gtpu_ipv4.identification,
                 gtpu_ipv4.flags,