Added tor.p4 to p4src

Change-Id: I8c3a02dee76cbe45e0f9a4f7ca1f93a6f1d8a016
diff --git a/tools/test/p4src/tor/punt.p4 b/tools/test/p4src/tor/punt.p4
new file mode 100644
index 0000000..2bdd45a
--- /dev/null
+++ b/tools/test/p4src/tor/punt.p4
@@ -0,0 +1,98 @@
+// Copyright (c) 2017, Google Inc.
+//
+// P4_16 specification for packet punting behavior.
+// Note: This code has not been tested and is expected to contain bugs.
+
+#ifndef P4_SPEC_PUNT_P4_
+#define P4_SPEC_PUNT_P4_
+
+#include "headers.p4"
+#include "parser.p4"
+
+//------------------------------------------------------------------------------
+// Global defines
+//------------------------------------------------------------------------------
+
+#define CPU_MIRROR_SESSION_ID 1023
+// TODO(samarabdi): Make sure this is also the behavior of the v1model extern
+#define METER_GREEN 0
+
+//------------------------------------------------------------------------------
+// Control Pipelines
+//------------------------------------------------------------------------------
+
+control punt(inout parsed_packet_t hdr,
+             inout local_metadata_t local_metadata,
+             inout standard_metadata_t standard_metadata) {
+
+  @proto_package("punt")
+  direct_meter<bit<2>>(MeterType.bytes) ingress_port_meter;
+
+  @proto_package("punt")
+  direct_counter(CounterType.packets) punt_packet_counter;
+
+  @proto_package("punt")
+  action set_queue_and_clone_to_cpu(@proto_tag(1) bit<5> queue_id) {
+    local_metadata.cpu_cos_queue_id = queue_id;
+    local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
+    clone3<tuple<bit<9>>>(CloneType.I2E, CPU_MIRROR_SESSION_ID,
+                          {standard_metadata.ingress_port});
+    ingress_port_meter.read(local_metadata.color);
+    punt_packet_counter.count();
+  }
+
+  @proto_package("punt")
+  action set_queue_and_send_to_cpu(@proto_tag(1) bit<5> queue_id) {
+    local_metadata.cpu_cos_queue_id = queue_id;
+    local_metadata.egress_spec_at_punt_match = standard_metadata.egress_spec;
+    standard_metadata.egress_spec = CPU_PORT;
+    ingress_port_meter.read(local_metadata.color);
+    punt_packet_counter.count();
+  }
+
+  // Combined punt table.
+  @proto_package("punt")
+  table punt_table {
+    key = {
+      standard_metadata.ingress_port: ternary @proto_tag(1);
+      standard_metadata.egress_spec: ternary @proto_tag(2);
+
+      hdr.ethernet.ether_type: ternary @proto_tag(3);
+
+      hdr.ipv4_base.diffserv: ternary @proto_tag(4);
+      hdr.ipv6_base.traffic_class: ternary @proto_tag(5);
+      hdr.ipv4_base.ttl: ternary @proto_tag(6);
+      hdr.ipv6_base.hop_limit: ternary @proto_tag(7);
+      hdr.ipv4_base.src_addr: ternary @proto_tag(8);
+      hdr.ipv4_base.dst_addr: ternary @proto_tag(9);
+      hdr.ipv6_base.src_addr: ternary @proto_tag(10);
+      hdr.ipv6_base.dst_addr: ternary @proto_tag(11);
+      hdr.ipv4_base.protocol: ternary @proto_tag(12);
+      hdr.ipv6_base.next_header: ternary @proto_tag(13);
+
+      hdr.arp.target_proto_addr: ternary @proto_tag(14);
+      local_metadata.icmp_code: ternary @proto_tag(15);
+
+      hdr.vlan_tag[0].vid: ternary @proto_tag(16);
+      hdr.vlan_tag[0].pcp: ternary @proto_tag(17);
+
+      local_metadata.class_id: ternary @proto_tag(18);
+      local_metadata.vrf_id: ternary @proto_tag(19);
+    }
+    actions = {
+      @proto_tag(1) set_queue_and_clone_to_cpu;
+      @proto_tag(2) set_queue_and_send_to_cpu;
+    }
+    meters = ingress_port_meter;
+    counters = punt_packet_counter;
+  }
+
+  apply {
+    punt_table.apply();
+    if(local_metadata.color != METER_GREEN) {
+      mark_to_drop();
+    }
+  }
+} // end punt
+
+#endif // P4_SPEC_PUNT_P4_