Added tor.p4 to p4src

Change-Id: I8c3a02dee76cbe45e0f9a4f7ca1f93a6f1d8a016
diff --git a/tools/test/p4src/tor/l3_fwd.p4 b/tools/test/p4src/tor/l3_fwd.p4
new file mode 100644
index 0000000..b5b8aa6
--- /dev/null
+++ b/tools/test/p4src/tor/l3_fwd.p4
@@ -0,0 +1,194 @@
+// Copyright (c) 2017, Google Inc.
+//
+// P4_16 specification for a L3 forwarding app.
+// Note: This code has not been tested and is expected to contain bugs.
+
+#ifndef P4_SPEC_L3_FWD_P4_
+#define P4_SPEC_L3_FWD_P4_
+
+#include "headers.p4"
+#include "parser.p4"
+
+#ifdef P4_EXPLICIT_LAG
+#include "lag.p4"
+#endif
+
+//------------------------------------------------------------------------------
+// IPv4/v6 L3 Forwarding
+//------------------------------------------------------------------------------
+
+control l3_fwd(inout parsed_packet_t hdr,
+               inout local_metadata_t local_metadata,
+               inout standard_metadata_t standard_metadata) {
+
+
+  @proto_package("l3_fwd")
+  action set_nexthop(@proto_tag(1) PortNum port,
+                     @proto_tag(2) EthernetAddress smac,
+                     @proto_tag(3) EthernetAddress dmac) {
+    standard_metadata.egress_spec = port;
+    hdr.ethernet.src_addr = smac;
+    hdr.ethernet.dst_addr = dmac;
+    // if (hdr.ipv4_base.isValid()) {
+      hdr.ipv4_base.ttl = hdr.ipv4_base.ttl - 1;
+    // } else if (hdr.ipv6_base.isValid()) {
+    //   hdr.ipv6_base.hop_limit = hdr.ipv6_base.hop_limit - 1;
+    // }
+  }
+
+  // Hit implies that the packet needs to be L3 forwarded.
+  // Equivalent of BCM MY_STATION table
+  @proto_package("l3_fwd")
+  table l3_routing_classifier_table {
+    key = {
+      hdr.ethernet.dst_addr : exact @proto_tag(1);
+    }
+    actions = {
+      @proto_tag(1) NoAction;
+    }
+    const default_action = NoAction();
+  }
+
+  action_selector(HashAlgorithm.crc16, 32w1024, 32w14) wcmp_action_profile;
+
+  // LPM forwarding tables for IPV4 packets.
+  @proto_package("l3_fwd")
+  table l3_ipv4_override_table {
+    key = {
+      hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
+
+      hdr.ipv4_base.dst_addr : selector @proto_tag(2);
+      hdr.ipv4_base.src_addr : selector @proto_tag(3);
+      hdr.ipv4_base.protocol : selector @proto_tag(4);
+      local_metadata.l4_src_port : selector @proto_tag(5);
+      local_metadata.l4_dst_port : selector @proto_tag(6);
+    }
+    actions = {
+      @proto_tag(1) set_nexthop;
+      @proto_tag(2) NoAction;
+    }
+    const default_action = NoAction();
+    // TODO(samarabdi): do we need to specify selector size?
+    implementation = wcmp_action_profile;
+  }
+
+  @proto_package("l3_fwd")
+  table l3_ipv4_vrf_table {
+    key = {
+      local_metadata.vrf_id: exact @proto_tag(1);
+      hdr.ipv4_base.dst_addr : lpm @proto_tag(2);
+      hdr.ipv4_base.dst_addr : selector @proto_tag(3);
+      hdr.ipv4_base.src_addr : selector @proto_tag(4);
+      hdr.ipv4_base.protocol : selector @proto_tag(5);
+      local_metadata.l4_src_port : selector @proto_tag(6);
+      local_metadata.l4_dst_port : selector @proto_tag(7);
+    }
+    actions = {
+      @proto_tag(1) set_nexthop;
+      @proto_tag(2) NoAction;
+    }
+    const default_action = NoAction();
+    implementation = wcmp_action_profile;
+  }
+
+  @proto_package("l3_fwd")
+  table l3_ipv4_fallback_table {
+    key = {
+      hdr.ipv4_base.dst_addr : lpm @proto_tag(1);
+      hdr.ipv4_base.dst_addr : selector @proto_tag(2);
+      hdr.ipv4_base.src_addr : selector @proto_tag(3);
+      hdr.ipv4_base.protocol : selector @proto_tag(4);
+      local_metadata.l4_src_port : selector @proto_tag(5);
+      local_metadata.l4_dst_port : selector @proto_tag(6);
+    }
+    actions = {
+      @proto_tag(1) set_nexthop;
+      @proto_tag(2) NoAction;
+    }
+    const default_action = NoAction();
+    implementation = wcmp_action_profile;
+  }
+
+  // LPM forwarding tables for IPV6 packets.
+
+  // @proto_package("l3_fwd")
+  // table l3_ipv6_override_table {
+  //   key = {
+  //     hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
+  //     hdr.ipv6_base.dst_addr : selector @proto_tag(2);
+  //     hdr.ipv6_base.src_addr : selector @proto_tag(3);
+  //     hdr.ipv6_base.flow_label : selector @proto_tag(4);
+  //     local_metadata.l4_src_port : selector @proto_tag(5);
+  //     local_metadata.l4_dst_port : selector @proto_tag(6);
+  //   }
+  //   actions = {
+  //     @proto_tag(1) set_nexthop;
+  //   }
+  //   implementation = wcmp_action_profile;
+  // }
+
+  // @proto_package("l3_fwd")
+  // table l3_ipv6_vrf_table {
+  //   key = {
+  //     local_metadata.vrf_id: exact @proto_tag(1);
+  //     hdr.ipv6_base.dst_addr : lpm @proto_tag(2);
+  //     hdr.ipv6_base.dst_addr : selector @proto_tag(3);
+  //     hdr.ipv6_base.src_addr : selector @proto_tag(4);
+  //     hdr.ipv6_base.flow_label : selector @proto_tag(5);
+  //     local_metadata.l4_src_port : selector @proto_tag(6);
+  //     local_metadata.l4_dst_port : selector @proto_tag(7);
+  //   }
+  //   actions = {
+  //     @proto_tag(1) set_nexthop;
+  //   }
+  //   implementation = wcmp_action_profile;
+  // }
+
+  // @proto_package("l3_fwd")
+  // table l3_ipv6_fallback_table {
+  //   key = {
+  //     hdr.ipv6_base.dst_addr : lpm @proto_tag(1);
+  //     hdr.ipv6_base.dst_addr : selector @proto_tag(2);
+  //     hdr.ipv6_base.src_addr : selector @proto_tag(3);
+  //     hdr.ipv6_base.flow_label : selector @proto_tag(4);
+  //     local_metadata.l4_src_port : selector @proto_tag(5);
+  //     local_metadata.l4_dst_port : selector @proto_tag(6);
+  //   }
+  //   actions = {
+  //     @proto_tag(1) set_nexthop;
+  //   }
+  //   implementation = wcmp_action_profile;
+  // }
+
+  apply {
+    if(l3_routing_classifier_table.apply().hit) {
+      if (hdr.ipv4_base.isValid()) {
+        if(!l3_ipv4_override_table.apply().hit) {
+          if(!l3_ipv4_vrf_table.apply().hit) {
+            l3_ipv4_fallback_table.apply();
+          }
+        }
+        if(hdr.ipv4_base.ttl == 0) {
+          mark_to_drop();
+          return;
+        }
+      }//  else if (hdr.ipv6_base.isValid()) {
+      //   if(!l3_ipv6_override_table.apply().hit) {
+      //     if(!l3_ipv6_vrf_table.apply().hit) {
+      //       l3_ipv6_fallback_table.apply();
+      //     }
+      //   }
+      //   if(hdr.ipv6_base.hop_limit == 0) {
+      //     mark_to_drop();
+      //     return;
+      //   }
+      // }
+    }
+  }
+#ifdef P4_EXPLICIT_LAG
+  lag_handling() lag;
+  lag(hdr, local_metadata, standard_metadata);
+#endif
+} // end l3_fwd
+
+#endif // P4_SPEC_L3_FWD_P4_