Adding intitial skeleton of tor app

Change-Id: Ifca304ccdbf8612ce089615a8f98f6f30fea6410
diff --git a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
index 18b6bc6..dcad695 100644
--- a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
+++ b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
@@ -122,7 +122,6 @@
     @Before
     public void setUp() throws Exception {
         controller.grpcController = grpcController;
-        GrpcControllerImpl.enableMessageLog = true;
         grpcController.activate();
     }
 
diff --git a/apps/pi-demo/ecmp/src/main/java/org/onosproject/pi/demo/app/ecmp/EcmpPipeconfFactory.java b/apps/pi-demo/ecmp/src/main/java/org/onosproject/pi/demo/app/ecmp/EcmpPipeconfFactory.java
index a415472..18f33c1 100644
--- a/apps/pi-demo/ecmp/src/main/java/org/onosproject/pi/demo/app/ecmp/EcmpPipeconfFactory.java
+++ b/apps/pi-demo/ecmp/src/main/java/org/onosproject/pi/demo/app/ecmp/EcmpPipeconfFactory.java
@@ -54,6 +54,10 @@
     private static final PiPipeconf MAVERICKS_PIPECONF = buildTofinoPipeconf(MAVERICKS);
     private static final PiPipeconf MONTARA_PIPECONF = buildTofinoPipeconf(MONTARA);
 
+    private EcmpPipeconfFactory() {
+        // Hides constructor.
+    }
+
     static Collection<PiPipeconf> getAll() {
         return Lists.newArrayList(BMV2_PIPECONF, MAVERICKS_PIPECONF, MONTARA_PIPECONF);
     }
diff --git a/apps/pi-demo/tor/BUCK b/apps/pi-demo/tor/BUCK
new file mode 100644
index 0000000..58f7277
--- /dev/null
+++ b/apps/pi-demo/tor/BUCK
@@ -0,0 +1,36 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:minimal-json',
+    '//incubator/bmv2/model:onos-incubator-bmv2-model',
+    '//apps/pi-demo/common:onos-apps-pi-demo-common',
+    '//drivers/default:onos-drivers-default',
+    '//drivers/p4runtime:onos-drivers-p4runtime',
+]
+
+osgi_jar (
+    deps = COMPILE_DEPS,
+)
+
+BUNDLES = [
+    '//apps/pi-demo/tor:onos-apps-pi-demo-tor',
+    '//apps/pi-demo/common:onos-apps-pi-demo-common',
+    '//drivers/default:onos-drivers-default',
+    '//incubator/bmv2/model:onos-incubator-bmv2-model',
+]
+
+onos_app (
+    app_name = 'org.onosproject.pi-tor',
+    title = 'PI Demo ECMP Fabric',
+    category = 'Traffic Steering',
+    url = 'http://onosproject.org',
+    description = 'Provides ECMP support for a 2-stage clos fabric topology of PI-enabled devices',
+    included_bundles = BUNDLES,
+    required_apps = [
+        # FIXME: there should be no dependendcy on a driver here.
+        # However, we depend on the DefaultP4Interpreter that currently lives in the p4runtime
+        # driver. Bringing up the whole app avoids to specify all transitive runtime dependencies
+        # as bundles. DefaultP4Interpreter and other pipeconf-related stuff should leave in a
+        # separate location, outside the drivers.
+        'org.onosproject.drivers.p4runtime'
+    ]
+)
diff --git a/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorApp.java b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorApp.java
new file mode 100644
index 0000000..5b1eea3
--- /dev/null
+++ b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorApp.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.pi.demo.app.tor;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.topology.Topology;
+import org.onosproject.pi.demo.app.common.AbstractUpgradableFabricApp;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Implementation of an upgradable fabric app for TOR configuration.
+ */
+//TODO implement
+@Component(immediate = true)
+public class TorApp extends AbstractUpgradableFabricApp {
+
+    private static final String APP_NAME = "org.onosproject.pi-tor";
+
+    private static final Map<DeviceId, Map<Set<PortNumber>, Short>> DEVICE_GROUP_ID_MAP = Maps.newHashMap();
+
+    public TorApp() {
+        super(APP_NAME, TorPipeconfFactory.getAll());
+    }
+
+    @Override
+    public boolean initDevice(DeviceId deviceId) {
+        // Nothing to do.
+        return true;
+    }
+
+    @Override
+    public List<FlowRule> generateLeafRules(DeviceId leaf, Host srcHost, Collection<Host> dstHosts,
+                                            Collection<DeviceId> availableSpines, Topology topo)
+            throws FlowRuleGeneratorException {
+
+        return ImmutableList.of();
+    }
+
+    @Override
+    public List<FlowRule> generateSpineRules(DeviceId deviceId, Collection<Host> dstHosts, Topology topo)
+            throws FlowRuleGeneratorException {
+
+        return ImmutableList.of();
+    }
+
+}
\ No newline at end of file
diff --git a/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorInterpreter.java b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorInterpreter.java
new file mode 100644
index 0000000..e6fc8d9
--- /dev/null
+++ b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorInterpreter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.pi.demo.app.tor;
+
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.pi.model.PiPipelineInterpreter;
+import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiCounterId;
+import org.onosproject.net.pi.runtime.PiHeaderFieldId;
+import org.onosproject.net.pi.runtime.PiPacketOperation;
+import org.onosproject.net.pi.runtime.PiTableId;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * Implementation of a PiPipeline interpreter for TOR configuration.
+ */
+//TODO implement
+public class TorInterpreter extends AbstractHandlerBehaviour implements PiPipelineInterpreter {
+
+
+    @Override
+    public Optional<Integer> mapPiTableId(PiTableId piTableId) {
+        return Optional.empty();
+    }
+
+    @Override
+    public PiAction mapTreatment(TrafficTreatment treatment, PiTableId piTableId) throws PiInterpreterException {
+        return null;
+    }
+
+    @Override
+    public Optional<PiCounterId> mapTableCounter(PiTableId piTableId) {
+        return Optional.empty();
+    }
+
+    @Override
+    public Collection<PiPacketOperation> mapOutboundPacket(OutboundPacket packet) throws PiInterpreterException {
+        return ImmutableList.of();
+    }
+
+    @Override
+    public InboundPacket mapInboundPacket(DeviceId deviceId, PiPacketOperation packetInOperation)
+            throws PiInterpreterException {
+        return null;
+    }
+
+    @Override
+    public Optional<PiHeaderFieldId> mapCriterionType(Criterion.Type type) {
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<Criterion.Type> mapPiHeaderFieldId(PiHeaderFieldId headerFieldId) {
+        return Optional.empty();
+    }
+
+    @Override
+    public Optional<PiTableId> mapFlowRuleTableId(int flowRuleTableId) {
+        return Optional.empty();
+    }
+}
\ No newline at end of file
diff --git a/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorPipeconfFactory.java b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorPipeconfFactory.java
new file mode 100644
index 0000000..e9dbba2
--- /dev/null
+++ b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/TorPipeconfFactory.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.pi.demo.app.tor;
+
+import com.google.common.collect.Lists;
+import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
+import org.onosproject.drivers.p4runtime.DefaultP4PortStatisticsDiscovery;
+import org.onosproject.drivers.p4runtime.NetcfgLinkDiscovery;
+import org.onosproject.net.behaviour.LinkDiscovery;
+import org.onosproject.net.device.PortStatisticsDiscovery;
+import org.onosproject.net.pi.model.DefaultPiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.model.PiPipelineInterpreter;
+
+import java.net.URL;
+import java.util.Collection;
+
+import static java.lang.String.format;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_BIN;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.TOFINO_CONTEXT_JSON;
+
+/**
+ * Pipeconf factory for all tor.p4 based pipeconf, both BMv2 and Tofino
+ */
+final class TorPipeconfFactory {
+
+    private static final String BMV2_PIPECONF_ID = "bmv2-tor";
+    private static final URL BMV2_P4INFO_URL = TorApp.class.getResource("/tor.p4info");
+    private static final URL BMV2_JSON_URL = TorApp.class.getResource("/tor.json");
+
+    private static final String TOFINO_PIPECONF_ID_BASE = "tofino-tor-%s";
+    private static final String TOFINO_JSON_PATH_BASE = "/tor-tofino/%s/tor.json";
+    private static final String TOFINO_P4INFO_PATH_BASE = "/tor-tofino/%s/tor.p4info";
+    private static final String TOFINO_CONTEXT_JSON_PATH_BASE = "/tor-tofino/%s/context/context.json";
+    private static final String TOFINO_BIN_PATH_BASE = "/tor-tofino/%s/tofino.bin";
+
+    private static final String MAVERICKS = "mavericks";
+    private static final String MONTARA = "montara";
+
+    private static final PiPipeconf BMV2_PIPECONF = buildBmv2Pipeconf();
+    private static final PiPipeconf MAVERICKS_PIPECONF = buildTofinoPipeconf(MAVERICKS);
+    private static final PiPipeconf MONTARA_PIPECONF = buildTofinoPipeconf(MONTARA);
+
+    private TorPipeconfFactory() {
+        // Hides constructor.
+    }
+
+    static Collection<PiPipeconf> getAll() {
+        return Lists.newArrayList(BMV2_PIPECONF, MAVERICKS_PIPECONF, MONTARA_PIPECONF);
+    }
+
+    private static PiPipeconf buildTofinoPipeconf(String system) {
+        final URL bmv2JsonUrl = TorPipeconfFactory.class.getResource(format(TOFINO_JSON_PATH_BASE, system));
+        final URL p4InfoUrl = TorPipeconfFactory.class.getResource(format(TOFINO_P4INFO_PATH_BASE, system));
+        final URL tofinoUrl = TorPipeconfFactory.class.getResource(format(TOFINO_BIN_PATH_BASE, system));
+        final URL contextUrl = TorPipeconfFactory.class.getResource(format(TOFINO_CONTEXT_JSON_PATH_BASE, system));
+
+        return DefaultPiPipeconf.builder()
+                .withId(new PiPipeconfId(format(TOFINO_PIPECONF_ID_BASE, system)))
+                .withPipelineModel(Bmv2PipelineModelParser.parse(bmv2JsonUrl))
+                .addBehaviour(PiPipelineInterpreter.class, TorInterpreter.class)
+                //FIXME change underneath to proper TOR implementation
+                //.addBehaviour(Pipeliner.class, DefaultSingleTablePipeline.class)
+                .addBehaviour(PortStatisticsDiscovery.class, DefaultP4PortStatisticsDiscovery.class)
+                // FIXME: can remove if Packet I/O is working
+                .addBehaviour(LinkDiscovery.class, NetcfgLinkDiscovery.class)
+                .addExtension(P4_INFO_TEXT, p4InfoUrl)
+                .addExtension(TOFINO_BIN, tofinoUrl)
+                .addExtension(TOFINO_CONTEXT_JSON, contextUrl)
+                .build();
+    }
+
+    private static PiPipeconf buildBmv2Pipeconf() {
+        return DefaultPiPipeconf.builder()
+                .withId(new PiPipeconfId(BMV2_PIPECONF_ID))
+                .withPipelineModel(Bmv2PipelineModelParser.parse(BMV2_JSON_URL))
+                .addBehaviour(PiPipelineInterpreter.class, TorInterpreter.class)
+                //FIXME change underneath to proper TOR implementation
+                //.addBehaviour(Pipeliner.class, DefaultSingleTablePipeline.class)
+                .addBehaviour(PortStatisticsDiscovery.class, DefaultP4PortStatisticsDiscovery.class)
+                // FIXME: can remove if Packet I/O is working
+                .addBehaviour(LinkDiscovery.class, NetcfgLinkDiscovery.class)
+                .addExtension(P4_INFO_TEXT, BMV2_P4INFO_URL)
+                .addExtension(BMV2_JSON, BMV2_JSON_URL)
+                .build();
+    }
+}
diff --git a/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/package-info.java b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/package-info.java
new file mode 100644
index 0000000..f2779e9
--- /dev/null
+++ b/apps/pi-demo/tor/src/main/java/org/onosproject/pi/demo/app/tor/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * PI TOR demo app.
+ */
+package org.onosproject.pi.demo.app.tor;
\ No newline at end of file
diff --git a/modules.defs b/modules.defs
index 5025038..589b236 100644
--- a/modules.defs
+++ b/modules.defs
@@ -214,6 +214,7 @@
     '//apps/openroadm:onos-apps-openroadm-oar',
     '//apps/artemis:onos-apps-artemis-oar',
     '//apps/pi-demo/ecmp:onos-apps-pi-demo-ecmp-oar',
+    '//apps/pi-demo/tor:onos-apps-pi-demo-tor-oar',
     '//apps/gluon:onos-apps-gluon-oar',
     '//apps/evpnopenflow:onos-apps-evpnopenflow-oar',
     '//apps/route-service:onos-apps-route-service-oar',