[ONOS-6465] gRPC Protocol and controller

Change-Id: I0ae997f234ce95a78db2db1917f2cbbe3696ccfd
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java
index 06f9c9e..8774c09 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.java
@@ -16,6 +16,11 @@
 
 package org.onosproject.drivers.bmv2;
 
+import org.onosproject.grpc.api.GrpcChannelId;
+import org.onosproject.grpc.api.GrpcController;
+import org.onosproject.grpc.api.GrpcServiceId;
+import org.onosproject.grpc.api.GrpcStreamObserverId;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.device.DeviceHandshaker;
 import org.onosproject.net.driver.AbstractHandlerBehaviour;
@@ -29,7 +34,7 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
- * Implementation of the DeviceHandshaker for the bmv2 softswitch.
+ * Implementation of the DeviceHandshaker for the BMv2 softswitch.
  */
 //TODO consider abstract class with empty connect method and
 //the implementation into a protected one for reusability.
@@ -41,6 +46,9 @@
 
     @Override
     public CompletableFuture<Boolean> connect() {
+        GrpcController controller = handler().get(GrpcController.class);
+        DeviceId deviceId = handler().data().deviceId();
+
         CompletableFuture<Boolean> result = new CompletableFuture<>();
         DeviceKeyService deviceKeyService = handler().get(DeviceKeyService.class);
         DriverData data = data();
@@ -54,6 +62,13 @@
                 deviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(data.value("gnmi_key")))
                         .asUsernamePassword().username());
         result.complete(true);
+
+        //we know we need packet in so we register the observer.
+        GrpcChannelId channelId = GrpcChannelId.of(deviceId, "bmv2");
+        GrpcServiceId serviceId = GrpcServiceId.of(channelId, "p4runtime");
+        GrpcStreamObserverId observerId = GrpcStreamObserverId.of(serviceId,
+                Bmv2PacketProgrammable.class.getSimpleName());
+        controller.addObserver(observerId, new Bmv2PacketInObserverHandler());
         return result;
     }
 
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketInObserverHandler.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketInObserverHandler.java
new file mode 100644
index 0000000..3b9e145
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketInObserverHandler.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.drivers.bmv2;
+
+import io.grpc.ManagedChannel;
+import io.grpc.stub.StreamObserver;
+import org.onosproject.grpc.api.GrpcObserverHandler;
+import org.slf4j.Logger;
+
+import java.util.Optional;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Sample Implementation of a PacketInObserverHandler.
+ * TODO refactor and actually use.
+ */
+public class Bmv2PacketInObserverHandler implements GrpcObserverHandler {
+
+    private final Logger log = getLogger(getClass());
+
+    //private final AbstractStub asyncStub;
+
+    //FIXME put at object due to p4Runtime compilation problems to be fixed.
+    private StreamObserver<Object> requestStreamObserver;
+
+    @Override
+    public void bindObserver(ManagedChannel channel) {
+
+        //asyncStub = ProtoGeneratedClass.newStub(channel);
+
+        //reqeustStreamObserver = asyncStub.MethodName(new PacketInObserver());
+
+    }
+
+    @Override
+    public Optional<StreamObserver> requestStreamObserver() {
+        return Optional.of(requestStreamObserver);
+    }
+
+    @Override
+    public void removeObserver() {
+        //this should complete the two way streaming
+        requestStreamObserver.onCompleted();
+    }
+
+    private class PacketInObserver implements StreamObserver<Object> {
+
+        @Override
+        public void onNext(Object o) {
+            log.info("onNext: {}", o.toString());
+
+        }
+
+        @Override
+        public void onError(Throwable throwable) {
+
+        }
+
+        @Override
+        public void onCompleted() {
+
+        }
+    }
+}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
new file mode 100644
index 0000000..4b76067
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2PacketProgrammable.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * 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.drivers.bmv2;
+
+import io.grpc.stub.StreamObserver;
+import org.onosproject.grpc.api.GrpcChannelId;
+import org.onosproject.grpc.api.GrpcController;
+import org.onosproject.grpc.api.GrpcObserverHandler;
+import org.onosproject.grpc.api.GrpcServiceId;
+import org.onosproject.grpc.api.GrpcStreamObserverId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketProgrammable;
+
+import java.util.Optional;
+
+/**
+ * Packet Programmable behaviour for BMv2 devices.
+ */
+public class Bmv2PacketProgrammable extends AbstractHandlerBehaviour implements PacketProgrammable {
+    @Override
+    public void emit(OutboundPacket packet) {
+        DriverHandler handler = handler();
+        GrpcController controller = handler.get(GrpcController.class);
+        DeviceId deviceId = handler.data().deviceId();
+        GrpcChannelId channelId = GrpcChannelId.of(deviceId, "bmv2");
+        GrpcServiceId serviceId = GrpcServiceId.of(channelId, "p4runtime");
+        GrpcStreamObserverId observerId = GrpcStreamObserverId.of(serviceId,
+                this.getClass().getSimpleName());
+        Optional<GrpcObserverHandler> manager = controller.getObserverManager(observerId);
+        if (!manager.isPresent()) {
+            //this is the first time the behaviour is called
+            controller.addObserver(observerId, new Bmv2PacketInObserverHandler());
+        }
+        //other already registered the observer for us.
+        Optional<StreamObserver> observer = manager.get().requestStreamObserver();
+        observer.ifPresent(objectStreamObserver -> objectStreamObserver.onNext(packet));
+    }
+}
diff --git a/drivers/bmv2/src/main/resources/bmv2-drivers.xml b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
index 7f0d3f2..bc343e0 100644
--- a/drivers/bmv2/src/main/resources/bmv2-drivers.xml
+++ b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
@@ -15,9 +15,11 @@
   ~ limitations under the License.
   -->
 <drivers>
-    <driver name="bmv2" manufacturer="barefoot" hwVersion="1.0.0" swVersion="1.0.0">
+    <driver name="bmv2" manufacturer="p4.org" hwVersion="master" swVersion="master">
         <behaviour api="org.onosproject.net.device.DeviceHandshaker"
                    impl="org.onosproject.drivers.bmv2.Bmv2Handshaker"/>
+        <behaviour api="org.onosproject.net.packet.PacketProgrammable"
+                   impl="org.onosproject.drivers.bmv2.Bmv2PacketProgrammable"/>
     </driver>
 </drivers>