Update INT version to 1.0

Change-Id: I898501780cad9c1ad725ee624aa0cd4617ad2559
diff --git a/pipelines/basic/src/main/resources/include/actions.p4 b/pipelines/basic/src/main/resources/include/actions.p4
index 9504879..9f8bd4f 100644
--- a/pipelines/basic/src/main/resources/include/actions.p4
+++ b/pipelines/basic/src/main/resources/include/actions.p4
@@ -24,6 +24,8 @@
     mark_to_drop();
 }
 
-
+action nop() {
+    NoAction();
+}
 
 #endif
diff --git a/pipelines/basic/src/main/resources/include/defines.p4 b/pipelines/basic/src/main/resources/include/defines.p4
index 4933ec2..d2683bf 100644
--- a/pipelines/basic/src/main/resources/include/defines.p4
+++ b/pipelines/basic/src/main/resources/include/defines.p4
@@ -24,6 +24,15 @@
 #define IPV4_IHL_MIN 4w5
 #define MAX_PORTS 511
 
+#ifndef _BOOL
+#define _BOOL bool
+#endif
+#ifndef _TRUE
+#define _TRUE true
+#endif
+#ifndef _FALSE
+#define _FALSE false
+#endif
 
 typedef bit<48> mac_t;
 typedef bit<32> ip_address_t;
@@ -38,13 +47,4 @@
 const MeterColor MeterColor_YELLOW = 8w1;
 const MeterColor MeterColor_RED = 8w2;
 
-// FIXME: this works only on BMv2
-#define PKT_INSTANCE_TYPE_NORMAL 0
-#define PKT_INSTANCE_TYPE_INGRESS_CLONE 1
-#define PKT_INSTANCE_TYPE_EGRESS_CLONE 2
-#define PKT_INSTANCE_TYPE_COALESCED 3
-#define PKT_INSTANCE_TYPE_INGRESS_RECIRC 4
-#define PKT_INSTANCE_TYPE_REPLICATION 5
-#define PKT_INSTANCE_TYPE_RESUBMIT 6
-
 #endif
diff --git a/pipelines/basic/src/main/resources/include/int_definitions.p4 b/pipelines/basic/src/main/resources/include/int_definitions.p4
index 17fd69e..8672499 100644
--- a/pipelines/basic/src/main/resources/include/int_definitions.p4
+++ b/pipelines/basic/src/main/resources/include/int_definitions.p4
@@ -20,17 +20,44 @@
 
 #include "defines.p4"
 
-/* indicate INT at LSB of DSCP */
-const bit<6> INT_DSCP = 0x1;
+/* indicate INT by DSCP value */
+const bit<6> DSCP_INT = 0x17;
+const bit<6> DSCP_MASK = 0x3F;
 
 typedef bit<48> timestamp_t;
 typedef bit<32> switch_id_t;
 
-const bit<8> INT_HEADER_LEN_WORD = 4;
+const bit<8> INT_HEADER_LEN_WORD = 3;
+const bit<16> INT_HEADER_SIZE = 8;
+const bit<16> INT_SHIM_HEADER_SIZE = 4;
 
 const bit<8> CPU_MIRROR_SESSION_ID = 250;
 const bit<32> REPORT_MIRROR_SESSION_ID = 500;
 const bit<6> HW_ID = 1;
 const bit<8> REPORT_HDR_TTL = 64;
 
+#ifdef TARGET_BMV2
+// These definitions are from:
+// https://github.com/jafingerhut/p4-guide/blob/master/v1model-special-ops/v1model-special-ops.p4
+
+// These definitions are derived from the numerical values of the enum
+// named "PktInstanceType" in the p4lang/behavioral-model source file
+// targets/simple_switch/simple_switch.h
+// https://github.com/p4lang/behavioral-model/blob/master/targets/simple_switch/simple_switch.h#L126-L134
+
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_NORMAL        = 0;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_INGRESS_CLONE = 1;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_EGRESS_CLONE  = 2;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_COALESCED     = 3;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_RECIRC        = 4;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_REPLICATION   = 5;
+const bit<32> BMV2_V1MODEL_INSTANCE_TYPE_RESUBMIT      = 6;
+
+#define IS_RESUBMITTED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_RESUBMIT)
+#define IS_RECIRCULATED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_RECIRC)
+#define IS_I2E_CLONE(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_INGRESS_CLONE)
+#define IS_E2E_CLONE(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_EGRESS_CLONE)
+#define IS_REPLICATED(smeta) (smeta.instance_type == BMV2_V1MODEL_INSTANCE_TYPE_REPLICATION)
+#endif // TARGET__BMV2
+
 #endif
diff --git a/pipelines/basic/src/main/resources/include/int_headers.p4 b/pipelines/basic/src/main/resources/include/int_headers.p4
index c98ea31..8ea6f0e 100644
--- a/pipelines/basic/src/main/resources/include/int_headers.p4
+++ b/pipelines/basic/src/main/resources/include/int_headers.p4
@@ -22,28 +22,31 @@
 #define __INT_HEADERS__
 #include "telemetry_report_headers.p4"
 
-// INT headers
+// INT version 1.0
+
+// INT header
 header int_header_t {
-    bit<2>  ver;
+    bit<4>  ver;
     bit<2>  rep;
     bit<1>  c;
     bit<1>  e;
-    bit<5>  rsvd1;
-    bit<5>  ins_cnt;
-    bit<8>  max_hop_cnt;
-    bit<8>  total_hop_cnt;
+    bit<1>  m;
+    bit<7>  rsvd1;
+    bit<3>  rsvd2;
+    bit<5>  hop_metadata_len;
+    bit<8>  remaining_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;
+    bit<16> rsvd3;
 }
 
 // INT meta-value headers - different header for each value type
 header int_switch_id_t {
     bit<32> switch_id;
 }
-header int_port_ids_t {
+header int_level1_port_ids_t {
     bit<16> ingress_port_id;
     bit<16> egress_port_id;
 }
@@ -60,9 +63,9 @@
 header int_egress_tstamp_t {
     bit<32> egress_tstamp;
 }
-header int_q_congestion_t {
-    bit<8> q_id;
-    bit<24> q_congestion;
+header int_level2_port_ids_t {
+    bit<32> ingress_port_id;
+    bit<32> egress_port_id;
 }
 header int_egress_port_tx_util_t {
     bit<32> egress_port_tx_util;
@@ -70,8 +73,8 @@
 
 header int_data_t {
     // Maximum int metadata stack size in bits:
-    // (0xFF -4) * 32 (excluding INT shim header, tail header and INT header)
-    varbit<8032> data;
+    // (0x3F - 3) * 4 * 8 (excluding INT shim header and INT header)
+    varbit<1920> data;
 }
 
 // INT shim header for TCP/UDP
@@ -79,23 +82,18 @@
     bit<8> int_type;
     bit<8> rsvd1;
     bit<8> len;
-    bit<8> rsvd2;
-}
-// INT tail header for TCP/UDP
-header intl4_tail_t {
-    bit<8> next_proto;
-    bit<16> dest_port;
-    bit<8> dscp;
+    bit<6> dscp;
+    bit<2> rsvd2;
 }
 
 struct int_metadata_t {
     switch_id_t switch_id;
-    bit<16> insert_byte_cnt;
-    bit<1>  source;
-    bit<1>  sink;
-    bit<8>  mirror_id;
-    bit<16> flow_id;
-    bit<8>  metadata_len;
+    bit<16> new_bytes;
+    bit<8>  new_words;
+    _BOOL  source;
+    _BOOL  sink;
+    _BOOL  transit;
+    bit<8> intl4_shim_len;
 }
 
 struct headers_t {
@@ -118,14 +116,13 @@
     int_header_t int_header;
     int_data_t int_data;
     int_switch_id_t int_switch_id;
-    int_port_ids_t int_port_ids;
+    int_level1_port_ids_t int_level1_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_level2_port_ids_t int_level2_port_ids;
     int_egress_port_tx_util_t int_egress_tx_util;
-    intl4_tail_t intl4_tail;
 }
 
 struct local_metadata_t {
diff --git a/pipelines/basic/src/main/resources/include/int_parser.p4 b/pipelines/basic/src/main/resources/include/int_parser.p4
index 2d03c20..a73e726 100644
--- a/pipelines/basic/src/main/resources/include/int_parser.p4
+++ b/pipelines/basic/src/main/resources/include/int_parser.p4
@@ -56,8 +56,8 @@
         packet.extract(hdr.tcp);
         local_metadata.l4_src_port = hdr.tcp.src_port;
         local_metadata.l4_dst_port = hdr.tcp.dst_port;
-        transition select((hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
-            true: parse_intl4_shim;
+        transition select(hdr.ipv4.dscp) {
+            DSCP_INT &&& DSCP_MASK: parse_intl4_shim;
             default: accept;
         }
     }
@@ -66,37 +66,26 @@
         packet.extract(hdr.udp);
         local_metadata.l4_src_port = hdr.udp.src_port;
         local_metadata.l4_dst_port = hdr.udp.dst_port;
-        transition select((hdr.ipv4.dscp & INT_DSCP) == INT_DSCP) {
-            true: parse_intl4_shim;
+        transition select(hdr.ipv4.dscp) {
+            DSCP_INT &&& DSCP_MASK: parse_intl4_shim;
             default: accept;
         }
     }
 
     state parse_intl4_shim {
         packet.extract(hdr.intl4_shim);
+        local_metadata.int_meta.intl4_shim_len = hdr.intl4_shim.len;
         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.
-        local_metadata.int_meta.metadata_len = hdr.intl4_shim.len - INT_HEADER_LEN_WORD;
-        transition select (local_metadata.int_meta.metadata_len) {
-            0: parse_intl4_tail;
-            default: parse_int_data;
-        }
+        transition 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);
+        // Parse INT metadata stack
+        packet.extract(hdr.int_data, ((bit<32>) (local_metadata.int_meta.intl4_shim_len - INT_HEADER_LEN_WORD)) << 5);
         transition accept;
     }
 }
@@ -117,15 +106,14 @@
         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_level1_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_level2_port_ids);
         packet.emit(hdr.int_egress_tx_util);
         packet.emit(hdr.int_data);
-        packet.emit(hdr.intl4_tail);
     }
 }
 
diff --git a/pipelines/basic/src/main/resources/include/int_report.p4 b/pipelines/basic/src/main/resources/include/int_report.p4
index b7ca357..bf2a4e5 100644
--- a/pipelines/basic/src/main/resources/include/int_report.p4
+++ b/pipelines/basic/src/main/resources/include/int_report.p4
@@ -30,15 +30,18 @@
          * we'll not use local_report_header for this purpose.
          */
         hdr.report_fixed_header.setValid();
-        hdr.report_fixed_header.ver = 0;
+        hdr.report_fixed_header.ver = 1;
+        hdr.report_fixed_header.len = 4;
         /* only support for flow_watchlist */
         hdr.report_fixed_header.nproto = NPROTO_ETHERNET;
+        hdr.report_fixed_header.rep_md_bits = 0;
         hdr.report_fixed_header.d = 0;
         hdr.report_fixed_header.q = 0;
         hdr.report_fixed_header.f = 1;
         hdr.report_fixed_header.rsvd = 0;
         //TODO how to get information specific to the switch
         hdr.report_fixed_header.hw_id = HW_ID;
+        hdr.report_fixed_header.sw_id = local_metadata.int_meta.switch_id;
         // TODO how save a variable and increment
         hdr.report_fixed_header.seq_no = 0;
         //TODO how to get timestamp from ingress ns
@@ -61,8 +64,8 @@
         hdr.report_ipv4.dscp = 6w0;
         hdr.report_ipv4.ecn = 2w0;
         /* Total Len is report_ipv4_len + report_udp_len + report_fixed_hdr_len + ethernet_len + ipv4_totalLen */
-        hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN +
-                                (bit<16>) REPORT_FIXED_HEADER_LEN +  (bit<16>) ETH_HEADER_LEN + hdr.ipv4.len;
+        hdr.report_ipv4.len = (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN +
+                              (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN + (((bit<16>) hdr.intl4_shim.len)<< 2);
         /* Dont Fragment bit should be set */
         hdr.report_ipv4.identification = 0;
         hdr.report_ipv4.flags = 0;
@@ -76,23 +79,28 @@
         hdr.report_udp.setValid();
         hdr.report_udp.src_port = 0;
         hdr.report_udp.dst_port = mon_port;
-        hdr.report_udp.length_ =  (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN +
-                                    (bit<16>) ETH_HEADER_LEN + hdr.ipv4.len;
+        hdr.report_udp.length_ = (bit<16>) UDP_HEADER_LEN + (bit<16>) REPORT_FIXED_HEADER_LEN +
+                                 (bit<16>) ETH_HEADER_LEN + (bit<16>) IPV4_MIN_HEAD_LEN + (bit<16>) UDP_HEADER_LEN +
+                                 (((bit<16>) hdr.intl4_shim.len)<< 2);
 
         local_metadata.compute_checksum = true;
         add_report_fixed_header();
+
+        truncate((bit<32>)hdr.report_ipv4.len + (bit<32>) ETH_HEADER_LEN);
     }
 
-    /* Cloned packet instance_type is PKT_INSTANCE_TYPE_INGRESS_CLONE=1
-     * Packet is forwarded according to the mirroring_add command
-     */
+    // Cloned packet is forwarded according to the mirroring_add command
     table tb_generate_report {
+        // We don't really need a key here, however we add a dummy one as a
+        // workaround to ONOS inability to properly support default actions.
         key = {
-            standard_metadata.instance_type: exact;
+            hdr.int_header.isValid(): exact @name("int_is_valid");
         }
         actions = {
             do_report_encapsulation;
+            @defaultonly nop();
         }
+        default_action = nop;
     }
 
     apply {
diff --git a/pipelines/basic/src/main/resources/include/int_sink.p4 b/pipelines/basic/src/main/resources/include/int_sink.p4
index 7023671..549ae97 100644
--- a/pipelines/basic/src/main/resources/include/int_sink.p4
+++ b/pipelines/basic/src/main/resources/include/int_sink.p4
@@ -22,27 +22,28 @@
     inout headers_t hdr,
     inout local_metadata_t local_metadata,
     inout standard_metadata_t standard_metadata) {
+    @hidden
     action restore_header () {
-        hdr.udp.dst_port = hdr.intl4_tail.dest_port;
-        hdr.ipv4.dscp = (bit<6>)hdr.intl4_tail.dscp;
+        hdr.ipv4.dscp = hdr.intl4_shim.dscp;
+        // restore length fields of IPv4 header and UDP header
+        bit<16> len_bytes = ((bit<16>)hdr.intl4_shim.len) << 2;
+        hdr.ipv4.len = hdr.ipv4.len - len_bytes;
+        hdr.udp.length_ = hdr.udp.length_ - len_bytes;
     }
 
+    @hidden
     action int_sink() {
-        // restore length fields of IPv4 header and UDP header
-        hdr.ipv4.len = hdr.ipv4.len - (bit<16>)((hdr.intl4_shim.len - (bit<8>)hdr.int_header.ins_cnt) << 2);
-        hdr.udp.length_ = hdr.udp.length_ - (bit<16>)((hdr.intl4_shim.len - (bit<8>)hdr.int_header.ins_cnt) << 2);
         // remove all the INT information from the packet
         hdr.int_header.setInvalid();
         hdr.int_data.setInvalid();
         hdr.intl4_shim.setInvalid();
-        hdr.intl4_tail.setInvalid();
         hdr.int_switch_id.setInvalid();
-        hdr.int_port_ids.setInvalid();
+        hdr.int_level1_port_ids.setInvalid();
         hdr.int_hop_latency.setInvalid();
         hdr.int_q_occupancy.setInvalid();
         hdr.int_ingress_tstamp.setInvalid();
         hdr.int_egress_tstamp.setInvalid();
-        hdr.int_q_congestion.setInvalid();
+        hdr.int_level2_port_ids.setInvalid();
         hdr.int_egress_tx_util.setInvalid();
     }
 
diff --git a/pipelines/basic/src/main/resources/include/int_source.p4 b/pipelines/basic/src/main/resources/include/int_source.p4
index 6fd2730..b7c5046 100644
--- a/pipelines/basic/src/main/resources/include/int_source.p4
+++ b/pipelines/basic/src/main/resources/include/int_source.p4
@@ -26,12 +26,13 @@
 
     direct_counter(CounterType.packets_and_bytes) counter_int_source;
 
-    action int_source(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
+    action int_source(bit<5> hop_metadata_len, bit<8> remaining_hop_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
         // insert INT shim header
         hdr.intl4_shim.setValid();
         // int_type: Hop-by-hop type (1) , destination type (2)
         hdr.intl4_shim.int_type = 1;
         hdr.intl4_shim.len = INT_HEADER_LEN_WORD;
+        hdr.intl4_shim.dscp = hdr.ipv4.dscp;
 
         // insert INT header
         hdr.int_header.setValid();
@@ -39,28 +40,24 @@
         hdr.int_header.rep = 0;
         hdr.int_header.c = 0;
         hdr.int_header.e = 0;
+        hdr.int_header.m = 0;
         hdr.int_header.rsvd1 = 0;
-        hdr.int_header.ins_cnt = ins_cnt;
-        hdr.int_header.max_hop_cnt = max_hop;
-        hdr.int_header.total_hop_cnt = 0;
+        hdr.int_header.rsvd2 = 0;
+        hdr.int_header.hop_metadata_len = hop_metadata_len;
+        hdr.int_header.remaining_hop_cnt = remaining_hop_cnt;
         hdr.int_header.instruction_mask_0003 = ins_mask0003;
         hdr.int_header.instruction_mask_0407 = ins_mask0407;
         hdr.int_header.instruction_mask_0811 = 0; // not supported
         hdr.int_header.instruction_mask_1215 = 0; // not supported
 
-        // insert INT tail header
-        hdr.intl4_tail.setValid();
-        hdr.intl4_tail.next_proto = hdr.ipv4.protocol;
-        hdr.intl4_tail.dest_port = local_metadata.l4_dst_port;
-        hdr.intl4_tail.dscp = (bit<8>) hdr.ipv4.dscp;
-
-        // add the header len (8 bytes) to total len
-        hdr.ipv4.len = hdr.ipv4.len + 16;
-        hdr.udp.length_ = hdr.udp.length_ + 16;
+        // add the header len (3 words) to total len
+        hdr.ipv4.len = hdr.ipv4.len + INT_HEADER_SIZE + INT_SHIM_HEADER_SIZE;
+        hdr.udp.length_ = hdr.udp.length_ + INT_HEADER_SIZE + INT_SHIM_HEADER_SIZE;
     }
-    action int_source_dscp(bit<8> max_hop, bit<5> ins_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
-        int_source(max_hop, ins_cnt, ins_mask0003, ins_mask0407);
-        hdr.ipv4.dscp = INT_DSCP;
+    action int_source_dscp(bit<5> hop_metadata_len, bit<8> remaining_hop_cnt, bit<4> ins_mask0003, bit<4> ins_mask0407) {
+        int_source(hop_metadata_len, remaining_hop_cnt, ins_mask0003, ins_mask0407);
+        hdr.ipv4.dscp = DSCP_INT;
+        counter_int_source.count();
     }
 
     table tb_int_source {
@@ -72,9 +69,10 @@
         }
         actions = {
             int_source_dscp;
+            @defaultonly nop();
         }
         counters = counter_int_source;
-        size = 1024;
+        const default_action = nop();
     }
 
     apply {
@@ -82,7 +80,7 @@
     }
 }
 
-control process_set_source_sink (
+control process_int_source_sink (
     inout headers_t hdr,
     inout local_metadata_t local_metadata,
     inout standard_metadata_t standard_metadata) {
@@ -91,11 +89,13 @@
     direct_counter(CounterType.packets_and_bytes) counter_set_sink;
 
     action int_set_source () {
-        local_metadata.int_meta.source = 1;
+        local_metadata.int_meta.source = _TRUE;
+        counter_set_source.count();
     }
 
     action int_set_sink () {
-        local_metadata.int_meta.sink = 1;
+        local_metadata.int_meta.sink = _TRUE;
+        counter_set_sink.count();
     }
 
     table tb_set_source {
@@ -104,9 +104,11 @@
         }
         actions = {
             int_set_source;
+            @defaultonly nop();
         }
         counters = counter_set_source;
-        size = 256;
+        const default_action = nop();
+        size = MAX_PORTS;
     }
     table tb_set_sink {
         key = {
@@ -114,9 +116,11 @@
         }
         actions = {
             int_set_sink;
+            @defaultonly nop();
         }
         counters = counter_set_sink;
-        size = 256;
+        const default_action = nop();
+        size = MAX_PORTS;
     }
 
     apply {
diff --git a/pipelines/basic/src/main/resources/include/int_transit.p4 b/pipelines/basic/src/main/resources/include/int_transit.p4
index 658edfe..ad7d8d3 100644
--- a/pipelines/basic/src/main/resources/include/int_transit.p4
+++ b/pipelines/basic/src/main/resources/include/int_transit.p4
@@ -22,36 +22,28 @@
     inout local_metadata_t local_metadata,
     inout standard_metadata_t standard_metadata) {
 
-    direct_counter(CounterType.packets_and_bytes) counter_int_insert;
-    direct_counter(CounterType.packets_and_bytes) counter_int_inst_0003;
-    direct_counter(CounterType.packets_and_bytes) counter_int_inst_0407;
-
-    action int_update_total_hop_cnt() {
-        hdr.int_header.total_hop_cnt = hdr.int_header.total_hop_cnt + 1;
-    }
-
-    action int_transit(switch_id_t switch_id) {
+    action init_metadata(switch_id_t switch_id) {
+        local_metadata.int_meta.transit = _TRUE;
         local_metadata.int_meta.switch_id = switch_id;
-        local_metadata.int_meta.insert_byte_cnt = (bit<16>) hdr.int_header.ins_cnt << 2;
     }
 
-    /* Instr Bit 0 */
+    @hidden
     action int_set_header_0() { //switch_id
         hdr.int_switch_id.setValid();
         hdr.int_switch_id.switch_id = local_metadata.int_meta.switch_id;
     }
-    action int_set_header_1() { //port_ids
-        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;
+    @hidden
+    action int_set_header_1() { //level1_port_id
+        hdr.int_level1_port_ids.setValid();
+        hdr.int_level1_port_ids.ingress_port_id = (bit<16>) standard_metadata.ingress_port;
+        hdr.int_level1_port_ids.egress_port_id = (bit<16>) standard_metadata.egress_port;
     }
+    @hidden
     action int_set_header_2() { //hop_latency
         hdr.int_hop_latency.setValid();
-        hdr.int_hop_latency.hop_latency =
-        (bit<32>) standard_metadata.deq_timedelta;
+        hdr.int_hop_latency.hop_latency = (bit<32>) standard_metadata.egress_global_timestamp - (bit<32>) standard_metadata.ingress_global_timestamp;
     }
+    @hidden
     action int_set_header_3() { //q_occupancy
         // TODO: Support egress queue ID
         hdr.int_q_occupancy.setValid();
@@ -61,28 +53,26 @@
         hdr.int_q_occupancy.q_occupancy =
         (bit<24>) standard_metadata.deq_qdepth;
     }
+    @hidden
     action int_set_header_4() { //ingress_tstamp
         hdr.int_ingress_tstamp.setValid();
         hdr.int_ingress_tstamp.ingress_tstamp =
-        (bit<32>) standard_metadata.enq_timestamp;
+        (bit<32>) standard_metadata.ingress_global_timestamp;
     }
+    @hidden
     action int_set_header_5() { //egress_timestamp
         hdr.int_egress_tstamp.setValid();
         hdr.int_egress_tstamp.egress_tstamp =
-        (bit<32>) standard_metadata.enq_timestamp +
-        (bit<32>) standard_metadata.deq_timedelta;
+        (bit<32>) standard_metadata.egress_global_timestamp;
     }
-    action int_set_header_6() { //q_congestion
-        // TODO: implement queue congestion support in BMv2
-        // TODO: update egress queue ID
-        hdr.int_q_congestion.setValid();
-        hdr.int_q_congestion.q_id =
-        0;
-        // (bit<8>) standard_metadata.egress_qid;
-        hdr.int_q_congestion.q_congestion =
-        // (bit<24>) queueing_metadata.deq_congestion;
-        0;
-    }
+    @hidden
+    action int_set_header_6() { //level2_port_id
+        hdr.int_level2_port_ids.setValid();
+        // level2_port_id indicates Logical port ID
+        hdr.int_level2_port_ids.ingress_port_id = (bit<32>) standard_metadata.ingress_port;
+        hdr.int_level2_port_ids.egress_port_id = (bit<32>) standard_metadata.egress_port;
+     }
+    @hidden
     action int_set_header_7() { //egress_port_tx_utilization
         // TODO: implement tx utilization support in BMv2
         hdr.int_egress_tx_util.setValid();
@@ -91,149 +81,249 @@
         0;
     }
 
-    /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */
-    /* Each bit set indicates that corresponding INT header should be added */
-    action int_set_header_0003_i0() {
+    // Actions to keep track of the new metadata added.
+    @hidden
+    action add_1() {
+        local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 1;
+        local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 4;
     }
-    action int_set_header_0003_i1() {
+
+    @hidden
+    action add_2() {
+        local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 2;
+        local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 8;
+    }
+
+    @hidden
+    action add_3() {
+        local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 3;
+        local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 12;
+    }
+
+    @hidden
+    action add_4() {
+        local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 4;
+       local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 16;
+    }
+
+    @hidden
+    action add_5() {
+        local_metadata.int_meta.new_words = local_metadata.int_meta.new_words + 5;
+        local_metadata.int_meta.new_bytes = local_metadata.int_meta.new_bytes + 20;
+    }
+
+     /* action function for bits 0-3 combinations, 0 is msb, 3 is lsb */
+     /* Each bit set indicates that corresponding INT header should be added */
+    @hidden
+     action int_set_header_0003_i0() {
+     }
+    @hidden
+     action int_set_header_0003_i1() {
         int_set_header_3();
+        add_1();
     }
+    @hidden
     action int_set_header_0003_i2() {
         int_set_header_2();
+        add_1();
     }
+    @hidden
     action int_set_header_0003_i3() {
         int_set_header_3();
         int_set_header_2();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i4() {
         int_set_header_1();
+        add_1();
     }
+    @hidden
     action int_set_header_0003_i5() {
         int_set_header_3();
         int_set_header_1();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i6() {
         int_set_header_2();
         int_set_header_1();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i7() {
         int_set_header_3();
         int_set_header_2();
         int_set_header_1();
+        add_3();
     }
+    @hidden
     action int_set_header_0003_i8() {
         int_set_header_0();
+        add_1();
     }
+    @hidden
     action int_set_header_0003_i9() {
         int_set_header_3();
         int_set_header_0();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i10() {
         int_set_header_2();
         int_set_header_0();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i11() {
         int_set_header_3();
         int_set_header_2();
         int_set_header_0();
+        add_3();
     }
+    @hidden
     action int_set_header_0003_i12() {
         int_set_header_1();
         int_set_header_0();
+        add_2();
     }
+    @hidden
     action int_set_header_0003_i13() {
         int_set_header_3();
         int_set_header_1();
         int_set_header_0();
+        add_3();
     }
+    @hidden
     action int_set_header_0003_i14() {
         int_set_header_2();
         int_set_header_1();
         int_set_header_0();
+        add_3();
     }
+    @hidden
     action int_set_header_0003_i15() {
         int_set_header_3();
         int_set_header_2();
         int_set_header_1();
         int_set_header_0();
+        add_4();
     }
 
-    /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */
+     /* action function for bits 4-7 combinations, 4 is msb, 7 is lsb */
+    @hidden
     action int_set_header_0407_i0() {
     }
+    @hidden
     action int_set_header_0407_i1() {
         int_set_header_7();
+        add_1();
     }
+    @hidden
     action int_set_header_0407_i2() {
         int_set_header_6();
+        add_2();
     }
+    @hidden
     action int_set_header_0407_i3() {
         int_set_header_7();
         int_set_header_6();
+        add_3();
     }
+    @hidden
     action int_set_header_0407_i4() {
         int_set_header_5();
+        add_1();
     }
+    @hidden
     action int_set_header_0407_i5() {
         int_set_header_7();
         int_set_header_5();
+        add_2();
     }
+    @hidden
     action int_set_header_0407_i6() {
         int_set_header_6();
         int_set_header_5();
+        add_3();
     }
+    @hidden
     action int_set_header_0407_i7() {
         int_set_header_7();
         int_set_header_6();
         int_set_header_5();
+        add_4();
     }
+    @hidden
     action int_set_header_0407_i8() {
         int_set_header_4();
+        add_1();
     }
+    @hidden
     action int_set_header_0407_i9() {
         int_set_header_7();
         int_set_header_4();
+        add_2();
     }
+    @hidden
     action int_set_header_0407_i10() {
         int_set_header_6();
         int_set_header_4();
+        add_3();
     }
+    @hidden
     action int_set_header_0407_i11() {
         int_set_header_7();
         int_set_header_6();
         int_set_header_4();
+        add_4();
     }
+    @hidden
     action int_set_header_0407_i12() {
         int_set_header_5();
         int_set_header_4();
+        add_2();
     }
+    @hidden
     action int_set_header_0407_i13() {
         int_set_header_7();
         int_set_header_5();
         int_set_header_4();
+        add_3();
     }
+    @hidden
     action int_set_header_0407_i14() {
         int_set_header_6();
         int_set_header_5();
         int_set_header_4();
+        add_4();
     }
+    @hidden
     action int_set_header_0407_i15() {
         int_set_header_7();
         int_set_header_6();
         int_set_header_5();
         int_set_header_4();
+        add_5();
     }
 
+    // Default action used to set switch ID.
     table tb_int_insert {
-        key = {}
-        actions = {
-            int_transit;
+        // We don't really need a key here, however we add a dummy one as a
+        // workaround to ONOS inability to properly support default actions.
+        key = {
+            hdr.int_header.isValid(): exact @name("int_is_valid");
         }
-        counters = counter_int_insert;
-        size = 2;
+        actions = {
+            init_metadata;
+            @defaultonly nop;
+        }
+        const default_action = nop();
+        size = 1;
     }
 
     /* Table to process instruction bits 0-3 */
+    @hidden
     table tb_int_inst_0003 {
         key = {
             hdr.int_header.instruction_mask_0003 : exact;
@@ -256,11 +346,28 @@
             int_set_header_0003_i14;
             int_set_header_0003_i15;
         }
-        counters = counter_int_inst_0003;
-        size = 16;
+        const entries = {
+            (0x0) : int_set_header_0003_i0();
+            (0x1) : int_set_header_0003_i1();
+            (0x2) : int_set_header_0003_i2();
+            (0x3) : int_set_header_0003_i3();
+            (0x4) : int_set_header_0003_i4();
+            (0x5) : int_set_header_0003_i5();
+            (0x6) : int_set_header_0003_i6();
+            (0x7) : int_set_header_0003_i7();
+            (0x8) : int_set_header_0003_i8();
+            (0x9) : int_set_header_0003_i9();
+            (0xA) : int_set_header_0003_i10();
+            (0xB) : int_set_header_0003_i11();
+            (0xC) : int_set_header_0003_i12();
+            (0xD) : int_set_header_0003_i13();
+            (0xE) : int_set_header_0003_i14();
+            (0xF) : int_set_header_0003_i15();
+        }
     }
 
     /* Table to process instruction bits 4-7 */
+    @hidden
     table tb_int_inst_0407 {
         key = {
             hdr.int_header.instruction_mask_0407 : exact;
@@ -283,42 +390,46 @@
             int_set_header_0407_i14;
             int_set_header_0407_i15;
         }
-        counters = counter_int_inst_0407;
-        size = 16;
+        const entries = {
+            (0x0) : int_set_header_0407_i0();
+            (0x1) : int_set_header_0407_i1();
+            (0x2) : int_set_header_0407_i2();
+            (0x3) : int_set_header_0407_i3();
+            (0x4) : int_set_header_0407_i4();
+            (0x5) : int_set_header_0407_i5();
+            (0x6) : int_set_header_0407_i6();
+            (0x7) : int_set_header_0407_i7();
+            (0x8) : int_set_header_0407_i8();
+            (0x9) : int_set_header_0407_i9();
+            (0xA) : int_set_header_0407_i10();
+            (0xB) : int_set_header_0407_i11();
+            (0xC) : int_set_header_0407_i12();
+            (0xD) : int_set_header_0407_i13();
+            (0xE) : int_set_header_0407_i14();
+            (0xF) : int_set_header_0407_i15();
+        }
     }
 
     apply {
         tb_int_insert.apply();
+        if (local_metadata.int_meta.transit == _FALSE) {
+            return;
+        }
         tb_int_inst_0003.apply();
         tb_int_inst_0407.apply();
-        int_update_total_hop_cnt();
-    }
-}
 
-control process_int_outer_encap (
-    inout headers_t hdr,
-    inout local_metadata_t local_metadata,
-    inout standard_metadata_t standard_metadata) {
+        // Decrement remaining hop cnt
+        hdr.int_header.remaining_hop_cnt = hdr.int_header.remaining_hop_cnt - 1;
 
-    action int_update_ipv4() {
-        hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.insert_byte_cnt;
-    }
-    action int_update_udp() {
-        hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.insert_byte_cnt;
-    }
-    action int_update_shim() {
-        hdr.intl4_shim.len = hdr.intl4_shim.len + (bit<8>)hdr.int_header.ins_cnt;
-    }
-
-    apply {
+        // Update headers lengths.
         if (hdr.ipv4.isValid()) {
-            int_update_ipv4();
+            hdr.ipv4.len = hdr.ipv4.len + local_metadata.int_meta.new_bytes;
         }
         if (hdr.udp.isValid()) {
-            int_update_udp();
+            hdr.udp.length_ = hdr.udp.length_ + local_metadata.int_meta.new_bytes;
         }
         if (hdr.intl4_shim.isValid()) {
-            int_update_shim();
+            hdr.intl4_shim.len = hdr.intl4_shim.len + local_metadata.int_meta.new_words;
         }
     }
 }
diff --git a/pipelines/basic/src/main/resources/include/telemetry_report_headers.p4 b/pipelines/basic/src/main/resources/include/telemetry_report_headers.p4
index bf0f6f7..73a56ec 100644
--- a/pipelines/basic/src/main/resources/include/telemetry_report_headers.p4
+++ b/pipelines/basic/src/main/resources/include/telemetry_report_headers.p4
@@ -18,24 +18,27 @@
 #ifndef __TELEMETRY_REPORT_HEADERS__
 #define __TELEMETRY_REPORT_HEADERS__
 
-const bit<4> NPROTO_ETHERNET = 0;
-const bit<4> NPROTO_TELEMETRY_DROP_HEADER = 1;
-const bit<4> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2;
+const bit<3> NPROTO_ETHERNET = 0;
+const bit<3> NPROTO_TELEMETRY_DROP_HEADER = 1;
+const bit<3> NPROTO_TELEMETRY_SWITCH_LOCAL_HEADER = 2;
 
 
 // Report Telemetry Headers
 header report_fixed_header_t {
     bit<4>  ver;
-    bit<4>  nproto;
+    bit<4>  len;
+    bit<3>  nproto;
+    bit<6>  rep_md_bits;
     bit<1>  d;
     bit<1>  q;
     bit<1>  f;
-    bit<15> rsvd;
+    bit<6>  rsvd;
     bit<6>  hw_id;
+    bit<32> sw_id;
     bit<32> seq_no;
     bit<32> ingress_tstamp;
 }
-const bit<8> REPORT_FIXED_HEADER_LEN = 12;
+const bit<8> REPORT_FIXED_HEADER_LEN = 16;
 
 // Telemetry drop report header
 header drop_report_header_t {