[ONOS-6465] gRPC Protocol and controller

Change-Id: I0ae997f234ce95a78db2db1917f2cbbe3696ccfd
diff --git a/protocols/grpc/api/BUCK b/protocols/grpc/api/BUCK
new file mode 100644
index 0000000..66efde3
--- /dev/null
+++ b/protocols/grpc/api/BUCK
@@ -0,0 +1,12 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//lib:grpc-core-1.3.0',
+    '//lib:grpc-protobuf-1.3.0',
+    '//lib:grpc-stub-1.3.0',
+    '//lib:grpc-netty-1.3.0',
+    '//lib:grpc-auth-1.3.0',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+)
diff --git a/protocols/grpc/api/pom.xml b/protocols/grpc/api/pom.xml
new file mode 100644
index 0000000..4841ca3
--- /dev/null
+++ b/protocols/grpc/api/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>onos-grpc-protocol</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <packaging>bundle</packaging>
+
+    <artifactId>onos-grpc-protocol-api</artifactId>
+
+   <dependencies>
+       <dependency>
+           <groupId>org.onosproject</groupId>
+           <artifactId>onos-api</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.apache.felix</groupId>
+           <artifactId>org.apache.felix.scr.annotations</artifactId>
+       </dependency>
+       <dependency>
+           <groupId>org.onosproject</groupId>
+           <artifactId>onos-core-serializers</artifactId>
+           <version>${project.version}</version>
+       </dependency>
+       <dependency>
+           <groupId>io.grpc</groupId>
+           <artifactId>grpc-stub</artifactId>
+           <version>1.3.0</version>
+       </dependency>
+   </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcChannelId.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcChannelId.java
new file mode 100644
index 0000000..c1fdbf1
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcChannelId.java
@@ -0,0 +1,81 @@
+/*
+ * 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.grpc.api;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * gRPCChannel identifier suitable as an external key.
+ * <p>
+ * This class is immutable.</p>
+ */
+@Beta
+public final class GrpcChannelId extends Identifier<String> {
+
+    private final DeviceId deviceId;
+
+    private final String channelName;
+
+    /**
+     * Instantiates a new GrpcChannel id.
+     *
+     * @param deviceId    the device id
+     * @param channelName the name of the channel
+     */
+    private GrpcChannelId(DeviceId deviceId, String channelName) {
+        super(deviceId.toString() + ":" + channelName);
+        checkNotNull(deviceId, "device id must not be null");
+        checkNotNull(channelName, "channel name must not be null");
+        checkArgument(!channelName.isEmpty(), "channel name must not be empty");
+        this.deviceId = deviceId;
+        this.channelName = channelName;
+    }
+
+    /**
+     * Returns the deviceId of the device that uses this channel.
+     *
+     * @return the device Id
+     */
+    public DeviceId deviceId() {
+        return deviceId;
+    }
+
+    /**
+     * Returns the channel name.
+     *
+     * @return the channel name
+     */
+    public String channelName() {
+        return channelName;
+    }
+
+    /**
+     * Creates a grpc channel identifier from the specified device id and name provided.
+     *
+     * @param id          device id
+     * @param channelName name of the channel
+     * @return channel name
+     */
+    public static GrpcChannelId of(DeviceId id, String channelName) {
+        return new GrpcChannelId(id, channelName);
+    }
+}
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcController.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcController.java
new file mode 100644
index 0000000..f1e279a
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcController.java
@@ -0,0 +1,102 @@
+/*
+ * 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.grpc.api;
+
+import com.google.common.annotations.Beta;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import org.onosproject.net.DeviceId;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Abstraction of a gRPC controller. Serves as a one stop shop for obtaining
+ * gRCP ManagedChannels to interact with devices and (un)register observers on event streams from the device.
+ */
+@Beta
+public interface GrpcController {
+
+    /**
+     * Adds a StreamObserver on a channel specific for a device.
+     *
+     * @param observerId          the id of the observer
+     * @param grpcObserverHandler the manager for the stream.
+     */
+    void addObserver(GrpcStreamObserverId observerId, GrpcObserverHandler grpcObserverHandler);
+
+    /**
+     * Removes the StreamObserver on a channel specific for a device.
+     *
+     * @param observerId the id of the observer
+     */
+    void removeObserver(GrpcStreamObserverId observerId);
+
+    /**
+     * If present returns the stream observer manager previously added for the given device.
+     *
+     * @param observerId the id of the observer.
+     * @return the ObserverManager
+     */
+    Optional<GrpcObserverHandler> getObserverManager(GrpcStreamObserverId observerId);
+
+    /**
+     * Tries to connect to a specific gRPC device, if the connection is successful
+     * returns the ManagedChannel. This method blocks until the channel is setup or a timeout expires.
+     * By default the timeout is 20 seconds. If the timeout expires and thus the channel can't be set up
+     * a IOException is thrown.
+     *
+     * @param channelId      the id of the channel
+     * @param channelBuilder the builder for the managed channel.
+     * @return the ManagedChannel created.
+     * @throws IOException if channel can't be setup.
+     */
+    ManagedChannel connectChannel(GrpcChannelId channelId, ManagedChannelBuilder<?> channelBuilder) throws IOException;
+
+    /**
+     * Disconnects a gRPC device by removing it's ManagedChannel from this controller.
+     *
+     * @param channelId id of the service to remove
+     */
+    void disconnectChannel(GrpcChannelId channelId);
+
+    /**
+     * Gets all ManagedChannels for the gRPC devices.
+     *
+     * @return Map of all the ManagedChannels with their identifier saved in this controller
+     */
+    Map<GrpcChannelId, ManagedChannel> getChannels();
+
+    /**
+     * Returns all ManagedChannels associated to the given device identifier.
+     *
+     * @param deviceId the device for which we are interested.
+     * @return collection of all the ManagedChannels saved in this controller
+     */
+    Collection<ManagedChannel> getChannels(DeviceId deviceId);
+
+    /**
+     * If present, returns the managed channel associated with the given identifier.
+     *
+     * @param channelId the id of the channel
+     * @return the ManagedChannel of the device.
+     */
+    Optional<ManagedChannel> getChannel(GrpcChannelId channelId);
+
+}
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcObserverHandler.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcObserverHandler.java
new file mode 100644
index 0000000..46a3967
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcObserverHandler.java
@@ -0,0 +1,53 @@
+/*
+ * 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.grpc.api;
+
+import com.google.common.annotations.Beta;
+import io.grpc.ManagedChannel;
+import io.grpc.stub.StreamObserver;
+
+import java.util.Optional;
+
+/**
+ * Implementation to add or remove an observer to the managed channel.
+ *
+ */
+@Beta
+public interface GrpcObserverHandler {
+    /**
+     * The implementation of this method adds an
+     * observer on a stub generated on the specific channel.
+     * This method will be called by the gRPC controller.
+     *
+     * @param channel the channel from which to derive the stub.
+     */
+    void bindObserver(ManagedChannel channel);
+
+    /**
+     * The implementation of this method returns the request stream
+     * observer, if any, on a stub generated on the specific channel.
+     *
+     * @return the observer on the stub, empty if observer is server-side unidirectional.
+     */
+    Optional<StreamObserver> requestStreamObserver();
+
+    /**
+     * The implementation of this method removes an
+     * observer on a stub generated on the specific channel.
+     * This method will be called by the gRPC controller.
+     */
+    void removeObserver();
+}
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcServiceId.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcServiceId.java
new file mode 100644
index 0000000..203ade6
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcServiceId.java
@@ -0,0 +1,81 @@
+/*
+ * 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.grpc.api;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * gRPCService identifier suitable as an external key.
+ * <p>
+ * This class is immutable.</p>
+ */
+@Beta
+public final class GrpcServiceId extends Identifier<String> {
+
+    private final GrpcChannelId channelId;
+
+    private final String serviceName;
+
+    /**
+     * Instantiates a new gRPC Service id.
+     *
+     * @param channelId   the channel id
+     * @param serviceName the name of the service on that channel
+     */
+    private GrpcServiceId(GrpcChannelId channelId, String serviceName) {
+        super(channelId.toString() + ":" + serviceName);
+        checkNotNull(channelId, "channel id must not be null");
+        checkNotNull(serviceName, "service name must not be null");
+        checkArgument(!serviceName.isEmpty(), "service name must not be empty");
+        this.channelId = channelId;
+        this.serviceName = serviceName;
+    }
+
+    /**
+     * Returns the id of the channel that this service uses.
+     *
+     * @return the channel Id
+     */
+    public GrpcChannelId channelId() {
+        return channelId;
+    }
+
+    /**
+     * Returns the name of this service.
+     *
+     * @return the service name
+     */
+    public String serviceName() {
+        return serviceName;
+    }
+
+    /**
+     * Creates a gRPC Service identifier from the specified device id and
+     * service name provided.
+     *
+     * @param id          channel id
+     * @param serviceName name of the service
+     * @return service name
+     */
+    public static GrpcServiceId of(GrpcChannelId id, String serviceName) {
+        return new GrpcServiceId(id, serviceName);
+    }
+}
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcStreamObserverId.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcStreamObserverId.java
new file mode 100644
index 0000000..911705a
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/GrpcStreamObserverId.java
@@ -0,0 +1,80 @@
+/*
+ * 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.grpc.api;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * GrpcStreamObserver identifier suitable as an external key.
+ * <p>
+ * This class is immutable.</p>
+ */
+@Beta
+public final class GrpcStreamObserverId extends Identifier<String> {
+
+    private GrpcServiceId serviceId;
+    private String streamName;
+
+    /**
+     * Instantiates a new GrpcStreamObserver id.
+     *
+     * @param serviceId  the service id
+     * @param streamName the name of the stream on that device
+     */
+    private GrpcStreamObserverId(GrpcServiceId serviceId, String streamName) {
+        super(serviceId.toString() + ":" + streamName);
+        checkNotNull(serviceId, "service id must not be null");
+        checkNotNull(streamName, "stream name must not be null");
+        checkArgument(!streamName.isEmpty(), "stream name must not be empty");
+        this.serviceId = serviceId;
+        this.streamName = streamName;
+    }
+
+    /**
+     * Returns the id of the service that this stream observer uses.
+     *
+     * @return the service Id
+     */
+    public GrpcServiceId serviceId() {
+        return serviceId;
+    }
+
+    /**
+     * Returns the name of this stream.
+     *
+     * @return the stream name
+     */
+    public String streamName() {
+        return streamName;
+    }
+
+    /**
+     * Creates a gRPC Stream Observer identifier from the specified service id and
+     * stream name provided.
+     *
+     * @param id         service id
+     * @param streamName stream name
+     * @return stream name
+     */
+    public static GrpcStreamObserverId of(GrpcServiceId id, String streamName) {
+        return new GrpcStreamObserverId(id, streamName);
+    }
+}
diff --git a/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/package-info.java b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/package-info.java
new file mode 100644
index 0000000..c3251db
--- /dev/null
+++ b/protocols/grpc/api/src/main/java/org/onosproject/grpc/api/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-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.
+ */
+
+/**
+ * gRPC protocol API.
+ */
+package org.onosproject.grpc.api;
\ No newline at end of file
diff --git a/protocols/grpc/ctl/BUCK b/protocols/grpc/ctl/BUCK
new file mode 100644
index 0000000..764d980
--- /dev/null
+++ b/protocols/grpc/ctl/BUCK
@@ -0,0 +1,20 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+    '//protocols/grpc/api:onos-protocols-grpc-api',
+    '//lib:grpc-core-1.3.0',
+    '//lib:grpc-protobuf-1.3.0',
+    '//lib:grpc-stub-1.3.0',
+    '//lib:grpc-netty-1.3.0',
+    '//lib:grpc-auth-1.3.0',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//utils/osgi:onlab-osgi-tests',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+)
+
diff --git a/protocols/grpc/ctl/pom.xml b/protocols/grpc/ctl/pom.xml
new file mode 100644
index 0000000..eb327f9
--- /dev/null
+++ b/protocols/grpc/ctl/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>onos-grpc-protocol</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>onos-grpc-protocol-ctl</artifactId>
+
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-grpc-protocol-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.onosproject</groupId>
+                <artifactId>onos-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+    
+</project>
\ No newline at end of file
diff --git a/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/GrpcControllerImpl.java b/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/GrpcControllerImpl.java
new file mode 100644
index 0000000..4ce097d
--- /dev/null
+++ b/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/GrpcControllerImpl.java
@@ -0,0 +1,127 @@
+/*
+ * 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.grpc.ctl;
+
+import com.google.common.collect.ImmutableSet;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.grpc.api.GrpcChannelId;
+import org.onosproject.grpc.api.GrpcController;
+import org.onosproject.grpc.api.GrpcObserverHandler;
+import org.onosproject.grpc.api.GrpcStreamObserverId;
+import org.onosproject.net.DeviceId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Default implementation of the GrpcController.
+ */
+@Component(immediate = true)
+@Service
+public class GrpcControllerImpl implements GrpcController {
+
+    public static final Logger log = LoggerFactory
+            .getLogger(GrpcControllerImpl.class);
+
+    private Map<GrpcStreamObserverId, GrpcObserverHandler> observers;
+    private Map<GrpcChannelId, ManagedChannel> channels;
+    private Map<GrpcChannelId, ManagedChannelBuilder<?>> channelBuilders;
+
+    @Activate
+    public void activate() {
+        observers = new ConcurrentHashMap<>();
+        channels = new ConcurrentHashMap<>();
+        channelBuilders = new ConcurrentHashMap<>();
+        log.info("Started");
+    }
+
+    @Deactivate
+    public void deactivate() {
+        channels.values().forEach(ManagedChannel::shutdown);
+        observers.clear();
+        channels.clear();
+        channelBuilders.clear();
+        log.info("Stopped");
+    }
+
+    @Override
+    public void addObserver(GrpcStreamObserverId observerId, GrpcObserverHandler grpcObserverHandler) {
+        grpcObserverHandler.bindObserver(channels.get(observerId.serviceId().channelId()));
+        observers.put(observerId, grpcObserverHandler);
+    }
+
+    @Override
+    public void removeObserver(GrpcStreamObserverId observerId) {
+        observers.get(observerId).removeObserver();
+        observers.remove(observerId);
+    }
+
+    @Override
+    public Optional<GrpcObserverHandler> getObserverManager(GrpcStreamObserverId observerId) {
+        return Optional.ofNullable(observers.get(observerId));
+    }
+
+    @Override
+    public ManagedChannel connectChannel(GrpcChannelId channelId, ManagedChannelBuilder<?> channelBuilder) {
+        ManagedChannel channel = channelBuilder.build();
+
+        channel.getState(true);
+        channelBuilders.put(channelId, channelBuilder);
+        channels.put(channelId, channel);
+        return channel;
+    }
+
+    @Override
+    public void disconnectChannel(GrpcChannelId channelId) {
+        channels.get(channelId).shutdown();
+        channels.remove(channelId);
+        channelBuilders.remove(channelId);
+    }
+
+    @Override
+    public Map<GrpcChannelId, ManagedChannel> getChannels() {
+        return channels;
+    }
+
+    @Override
+    public Collection<ManagedChannel> getChannels(final DeviceId deviceId) {
+        final Set<ManagedChannel> deviceChannels = new HashSet<>();
+        channels.forEach((k, v) -> {
+            if (k.deviceId().equals(deviceId)) {
+                deviceChannels.add(v);
+            }
+        });
+
+        return ImmutableSet.copyOf(deviceChannels);
+    }
+
+    @Override
+    public Optional<ManagedChannel> getChannel(GrpcChannelId channelId) {
+        return Optional.ofNullable(channels.get(channelId));
+    }
+}
diff --git a/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/package-info.java b/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/package-info.java
new file mode 100644
index 0000000..c29204a
--- /dev/null
+++ b/protocols/grpc/ctl/src/main/java/org/onosproject/grpc/ctl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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 for gRPC protocol implementations.
+ */
+package org.onosproject.grpc.ctl;
\ No newline at end of file
diff --git a/protocols/grpc/pom.xml b/protocols/grpc/pom.xml
new file mode 100644
index 0000000..eca6143
--- /dev/null
+++ b/protocols/grpc/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2016-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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>onos-protocols</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>onos-grpc-protocol</artifactId>
+
+    <modules>
+        <module>api</module>
+        <module>ctl</module>
+    </modules>
+
+    <packaging>pom</packaging>
+
+    <description>gRPC protocol subsystem</description>
+
+</project>
\ No newline at end of file
diff --git a/protocols/pom.xml b/protocols/pom.xml
index b823f9c..23b428b 100644
--- a/protocols/pom.xml
+++ b/protocols/pom.xml
@@ -43,6 +43,7 @@
         <module>lisp</module>
         <module>restconf</module>
         <module>tl1</module>
+        <module>grpc</module>
     </modules>
 
     <dependencies>