Created LinkService and added unit tests.

Change-Id: I1f2104c873e5a9e2df34074d36cddc823e3b3ec5
diff --git a/incubator/protobuf/models/BUCK b/incubator/protobuf/models/BUCK
index 6bfac3d..99619ed 100644
--- a/incubator/protobuf/models/BUCK
+++ b/incubator/protobuf/models/BUCK
@@ -3,13 +3,15 @@
     '//lib:CORE_DEPS',
     ':onos-incubator-protobuf-models-proto',
     '//lib:protobuf-java-3.2.0',
-    '//lib:GRPC_1.3'
+    '//lib:GRPC_1.3',
+    '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0'
 ]
 
 GRPC_DEPS = [
     '//lib:GRPC_1.3',
     '//lib:protobuf-java-3.2.0',
-    '//lib:guava'
+    '//lib:guava',
+    '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0'
 ]
 
 BUNDLES = [
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/GrpcNbDeviceServiceUtil.java
similarity index 99%
rename from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java
rename to incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/GrpcNbDeviceServiceUtil.java
index 0ad1b3f..4b84a1a 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/GrpcNbDeviceServiceUtil.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/GrpcNbDeviceServiceUtil.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.grpc.nb.utils;
+package org.onosproject.incubator.protobuf.models;
 
 import org.onlab.packet.ChassisId;
 import org.onosproject.grpc.net.device.models.DeviceDescriptionProtoOuterClass;
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/ProtobufUtils.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/ProtobufUtils.java
index adfa496..14df91c 100644
--- a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/ProtobufUtils.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/ProtobufUtils.java
@@ -57,7 +57,7 @@
      * Translates gRPC enum MastershipRoleProto to ONOS enum.
      *
      * @param role mastership role in gRPC enum
-     * @return equivalent in ONOS enum
+     * @return equivalent ONOS enum
      */
     public static MastershipRole translate(MastershipRoleProto role) {
         switch (role) {
@@ -79,7 +79,7 @@
      * Translates ONOS enum MastershipRole to gRPC enum.
      *
      * @param newRole ONOS' mastership role
-     * @return equivalent in gRPC message enum
+     * @return equivalent gRPC message enum
      */
     public static MastershipRoleProto translate(MastershipRole newRole) {
         switch (newRole) {
@@ -93,7 +93,6 @@
         }
     }
 
-
     /**
      * Translates gRPC DeviceDescriptionProto to {@link DeviceDescription}.
      *
@@ -139,7 +138,6 @@
                 .build();
     }
 
-
     /**
      * Translates gRPC DeviceTypeProto to {@link Device.Type}.
      *
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java
new file mode 100644
index 0000000..c0177fe
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ConnectPointProtoTranslator.java
@@ -0,0 +1,94 @@
+/*
+ * 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.incubator.protobuf.models.net;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.grpc.net.models.ConnectPointProtoOuterClass;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.IpElementId;
+import org.onosproject.net.PortNumber;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+/**
+ * gRPC ConnectPoint message to org.onosproject.net.ConnectPoint conversion related utilities.
+ */
+public final class ConnectPointProtoTranslator {
+
+    private static final Logger log = LoggerFactory.getLogger(ConnectPointProtoTranslator.class);
+
+    /**
+     * Translates gRPC ConnectPoint message to Optional of {@link org.onosproject.net.ConnectPoint}.
+     *
+     * @param connectPoint gRPC message
+     * @return Optional of equivalent {@link org.onosproject.net.ConnectPoint} or empty if ElementId is not recognized
+     */
+    public static Optional<ConnectPoint> translate(ConnectPointProtoOuterClass.ConnectPointProto connectPoint) {
+        switch (connectPoint.getElementIdCase()) {
+            case DEVICE_ID:
+                return Optional.of(new ConnectPoint(DeviceId.deviceId(connectPoint.getDeviceId()),
+                                                    PortNumber.portNumber(connectPoint.getPortNumber())));
+            case HOST_ID:
+                return Optional.of(new ConnectPoint(HostId.hostId(connectPoint.getHostId()),
+                                                    PortNumber.portNumber(connectPoint.getPortNumber())));
+            case IP_ELEMENT_ID:
+                return Optional.of(new ConnectPoint(IpElementId.ipElement(IpAddress
+                                                                                  .valueOf(connectPoint
+                                                                                                   .getIpElementId()
+                                                                                  )),
+                                                    PortNumber.portNumber(connectPoint.getPortNumber())));
+            default:
+                return Optional.empty();
+        }
+    }
+
+    /**
+     * Translates {@link org.onosproject.net.ConnectPoint} to gRPC ConnectPoint message.
+     *
+     * @param connectPoint {@link org.onosproject.net.ConnectPoint}
+     * @return gRPC ConnectPoint message
+     */
+    public static ConnectPointProtoOuterClass.ConnectPointProto translate(ConnectPoint connectPoint) {
+        if (connectPoint.elementId() instanceof DeviceId) {
+            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
+                    .setDeviceId(connectPoint.deviceId().toString())
+                    .setPortNumber(connectPoint.port().toString())
+                    .build();
+        } else if (connectPoint.elementId() instanceof HostId) {
+            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
+                    .setHostId(connectPoint.hostId().toString())
+                    .setPortNumber(connectPoint.port().toString())
+                    .build();
+        } else if (connectPoint.ipElementId() instanceof IpElementId) {
+            return ConnectPointProtoOuterClass.ConnectPointProto.newBuilder()
+                    .setIpElementId(connectPoint.ipElementId().toString())
+                    .setPortNumber(connectPoint.port().toString())
+                    .build();
+        } else {
+            log.warn("Unrecognized ElementId", connectPoint);
+            throw new IllegalArgumentException("Unrecognized ElementId");
+        }
+    }
+
+
+    // Utility class not intended for instantiation.
+    private ConnectPointProtoTranslator() {}
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/LinkProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/LinkProtoTranslator.java
new file mode 100644
index 0000000..56804c7
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/LinkProtoTranslator.java
@@ -0,0 +1,84 @@
+/*
+ * 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.incubator.protobuf.models.net;
+
+import org.onosproject.grpc.net.models.LinkProtoOuterClass;
+import org.onosproject.incubator.protobuf.models.ProtobufUtils;
+import org.onosproject.incubator.protobuf.models.net.link.LinkEnumsProtoTranslator;
+import org.onosproject.net.Annotations;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Link;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * gRPC LinkProto message to equivalent ONOS Link conversion related utilities.
+ */
+public final class LinkProtoTranslator {
+
+    /**
+     * Translates gRPC LinkCore message to {@link org.onosproject.net.Link}.
+     *
+     * @param link gRPC message
+     * @return {@link org.onosproject.net.Link} null if link is a default instance
+     */
+    public static Link translate(LinkProtoOuterClass.LinkProto link) {
+        if (link.equals(LinkProtoOuterClass.LinkProto.getDefaultInstance())) {
+            return null;
+        }
+        ProviderId providerId = ProviderIdProtoTranslator.translate(link.getProviderId());
+        Link.State state = LinkEnumsProtoTranslator.translate(link.getState()).get();
+        ConnectPoint src = ConnectPointProtoTranslator.translate(link.getSrc()).get();
+        ConnectPoint dst = ConnectPointProtoTranslator.translate(link.getDst()).get();
+        Link.Type type = LinkEnumsProtoTranslator.translate(link.getType()).get();
+        Annotations annots = ProtobufUtils.asAnnotations(link.getAnnotations());
+        Boolean isExpected = link.getIsExpected();
+        return DefaultLink.builder().state(state)
+                .annotations(annots)
+                .providerId(providerId)
+                .src(src)
+                .dst(dst)
+                .type(type)
+                .isExpected(isExpected)
+                .build();
+    }
+
+
+    /**
+     * Translates {@link org.onosproject.net.Link} to gRPC LinkCore message.
+     *
+     * @param link {@link org.onosproject.net.Link}
+     * @return gRPC LinkCore message
+     */
+    public static LinkProtoOuterClass.LinkProto translate(Link link) {
+        if (link == null) {
+            return LinkProtoOuterClass.LinkProto.getDefaultInstance();
+        }
+        return LinkProtoOuterClass.LinkProto.newBuilder()
+                .setProviderId(ProviderIdProtoTranslator.translate(link.providerId()))
+                .setState(LinkEnumsProtoTranslator.translate(link.state()))
+                .setSrc(ConnectPointProtoTranslator.translate(link.src()))
+                .setDst(ConnectPointProtoTranslator.translate(link.dst()))
+                .setType(LinkEnumsProtoTranslator.translate(link.type()))
+                .setIsExpected(link.isExpected())
+                .build();
+    }
+
+    // Utility class not intended for instantiation.
+    private LinkProtoTranslator() {}
+
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ProviderIdProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ProviderIdProtoTranslator.java
new file mode 100644
index 0000000..8ee4fe5
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/ProviderIdProtoTranslator.java
@@ -0,0 +1,61 @@
+/*
+ * 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.incubator.protobuf.models.net;
+
+import org.onosproject.grpc.net.models.ProviderIdProtoOuterClass;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * gRPC ProviderId message to org.onosproject.net.provider.ProviderId conversion related utilities.
+ */
+public final class ProviderIdProtoTranslator {
+
+    /**
+     * Translates gRPC ProviderId message to {@link org.onosproject.net.provider.ProviderId}.
+     *
+     * @param providerId gRPC ProviderId message
+     * @return {@link org.onosproject.net.provider.ProviderId} or null if providerId is a default instance
+     */
+    public static ProviderId translate(ProviderIdProtoOuterClass.ProviderIdProto providerId) {
+        if (providerId.equals(ProviderIdProtoOuterClass.ProviderIdProto.getDefaultInstance())) {
+            return null;
+        }
+        return new ProviderId(providerId.getScheme(), providerId.getId(), providerId.getAncillary());
+    }
+
+    /**
+     * Translates {@link org.onosproject.net.provider.ProviderId} to gRPC ProviderId message.
+     *
+     * @param providerId {@link org.onosproject.net.provider.ProviderId}
+     * @return gRPC ProviderId message
+     */
+    public static ProviderIdProtoOuterClass.ProviderIdProto translate(ProviderId providerId) {
+        if (providerId == null) {
+            return ProviderIdProtoOuterClass.ProviderIdProto.getDefaultInstance();
+        }
+        return ProviderIdProtoOuterClass.ProviderIdProto.newBuilder()
+                .setScheme(providerId.scheme())
+                .setId(providerId.id())
+                .setAncillary(providerId.isAncillary())
+                .build();
+    }
+
+
+    // Utility class not intended for instantiation.
+    private ProviderIdProtoTranslator() {}
+
+}
+
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/LinkEnumsProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/LinkEnumsProtoTranslator.java
new file mode 100644
index 0000000..bc87984
--- /dev/null
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/LinkEnumsProtoTranslator.java
@@ -0,0 +1,125 @@
+/*
+ * 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.incubator.protobuf.models.net.link;
+
+import org.onosproject.grpc.net.link.models.LinkEnumsProto;
+import org.onosproject.net.Link;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+/**
+ * gRPC LinkType and LinkState message to equivalent ONOS enum conversion related utilities.
+ */
+public final class LinkEnumsProtoTranslator {
+
+    private static final Logger log = LoggerFactory.getLogger(LinkEnumsProtoTranslator.class);
+
+    /**
+     * Translates gRPC enum LinkType to Optional of ONOS enum.
+     *
+     * @param type linktype type in gRPC enum
+     * @return Optional of equivalent ONOS enum or empty if not recognized
+     */
+    public static Optional<Link.Type> translate(LinkEnumsProto.LinkTypeProto type) {
+        switch (type) {
+            case DIRECT:
+                return Optional.of(Link.Type.DIRECT);
+            case INDIRECT:
+                return Optional.of(Link.Type.INDIRECT);
+            case EDGE:
+                return Optional.of(Link.Type.EDGE);
+            case TUNNEL:
+                return Optional.of(Link.Type.TUNNEL);
+            case OPTICAL:
+                return Optional.of(Link.Type.OPTICAL);
+            case VIRTUAL:
+                return Optional.of(Link.Type.VIRTUAL);
+            default:
+                log.warn("Unrecognized Type gRPC message: {}", type);
+                return Optional.empty();
+        }
+    }
+
+    /**
+     * Translates ONOS enum Type to gRPC enum.
+     *
+     * @param type ONOS' Type type
+     * @return equivalent gRPC message enum
+     */
+    public static LinkEnumsProto.LinkTypeProto translate(Link.Type type) {
+        switch (type) {
+            case DIRECT:
+                return LinkEnumsProto.LinkTypeProto.DIRECT;
+            case INDIRECT:
+                return LinkEnumsProto.LinkTypeProto.INDIRECT;
+            case EDGE:
+                return LinkEnumsProto.LinkTypeProto.EDGE;
+            case TUNNEL:
+                return LinkEnumsProto.LinkTypeProto.TUNNEL;
+            case OPTICAL:
+                return LinkEnumsProto.LinkTypeProto.OPTICAL;
+            case VIRTUAL:
+                return LinkEnumsProto.LinkTypeProto.VIRTUAL;
+            default:
+                log.warn("Unrecognized type", type);
+                throw new IllegalArgumentException("Unrecognized Type");
+        }
+    }
+
+    /**
+     * Translates gRPC enum LinkState to Optional of ONOS enum.
+     *
+     * @param state linkstate state in gRPC enum
+     * @return Optional of equivalent ONOS enum or empty if not recognized
+     */
+    public static Optional<Link.State> translate(LinkEnumsProto.LinkStateProto state) {
+        switch (state) {
+            case ACTIVE:
+                return Optional.of(Link.State.ACTIVE);
+            case INACTIVE:
+                return Optional.of(Link.State.INACTIVE);
+            default:
+                log.warn("Unrecognized State gRPC message: {}", state);
+                return Optional.empty();
+        }
+    }
+
+    /**
+     * Translates ONOS enum State to gRPC enum.
+     *
+     * @param state ONOS' state state
+     * @return equivalent gRPC message enum
+     */
+    public static LinkEnumsProto.LinkStateProto translate(Link.State state) {
+        switch (state) {
+            case ACTIVE:
+                return LinkEnumsProto.LinkStateProto.ACTIVE;
+            case INACTIVE:
+                return LinkEnumsProto.LinkStateProto.INACTIVE;
+            default:
+                log.warn("Unrecognized State", state);
+                throw new IllegalArgumentException("Unrecognized State");
+        }
+    }
+
+
+    // Utility class not intended for instantiation.
+    private LinkEnumsProtoTranslator() {}
+
+}
+
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/package-info.java
similarity index 83%
copy from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
copy to incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/package-info.java
index 0814b10..1392669 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/link/package-info.java
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 /**
- * gRPC server implementations for northbound services.
+ * Utilities to handle ProtoBuf version of ONOS link models.
  */
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.models.net.link;
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/package-info.java
similarity index 83%
copy from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
copy to incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/package-info.java
index 0814b10..e393681 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/net/package-info.java
@@ -14,6 +14,6 @@
  * limitations under the License.
  */
 /**
- * gRPC server implementations for northbound services.
+ * Utilities to handle ProtoBuf version of ONOS network models.
  */
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.models.net;
diff --git a/incubator/protobuf/models/src/main/proto/net/ConnectPointProto.proto b/incubator/protobuf/models/src/main/proto/net/ConnectPointProto.proto
index 3749b6f..e0444b4 100644
--- a/incubator/protobuf/models/src/main/proto/net/ConnectPointProto.proto
+++ b/incubator/protobuf/models/src/main/proto/net/ConnectPointProto.proto
@@ -7,8 +7,8 @@
     oneof element_id {
         // DeviceID as String DeviceId#toString
         string device_id = 1;
-
-        // TODO add support to other element_id if required
+        string host_id = 3;
+        string ip_element_id = 4;
     }
     // PortNumber as String PortNumber#toString
     string port_number = 2;
diff --git a/incubator/protobuf/models/src/main/proto/net/LinkProto.proto b/incubator/protobuf/models/src/main/proto/net/LinkProto.proto
index 77bb32b..9b41dc4 100644
--- a/incubator/protobuf/models/src/main/proto/net/LinkProto.proto
+++ b/incubator/protobuf/models/src/main/proto/net/LinkProto.proto
@@ -5,6 +5,7 @@
 
 import "net/link/LinkEnumsProto.proto";
 import "net/ConnectPointProto.proto";
+import "net/ProviderIdProto.proto";
 
 // Corresponds to org.onosproject.net.Link.
 message LinkProto {
@@ -13,6 +14,6 @@
     net.ConnectPointProto dst = 3;
     net.link.LinkTypeProto type = 4;
     map<string, string> annotations = 5;
-}
-
-
+    net.ProviderIdProto provider_id = 6;
+    bool isExpected = 7;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/models/src/main/proto/net/ProviderIdProto.proto b/incubator/protobuf/models/src/main/proto/net/ProviderIdProto.proto
new file mode 100644
index 0000000..3e470c7
--- /dev/null
+++ b/incubator/protobuf/models/src/main/proto/net/ProviderIdProto.proto
@@ -0,0 +1,11 @@
+syntax = "proto3";
+option java_package = "org.onosproject.grpc.net.models";
+
+package net;
+
+// Corresponds to org.onosproject.net.provider.ProviderId
+message ProviderIdProto {
+    string scheme = 1;
+    string id = 2;
+    bool ancillary = 3;
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/BUCK b/incubator/protobuf/services/nb/BUCK
index 4d9c789..6f582e0 100644
--- a/incubator/protobuf/services/nb/BUCK
+++ b/incubator/protobuf/services/nb/BUCK
@@ -5,11 +5,14 @@
     '//incubator/protobuf/models:onos-incubator-protobuf-models-proto',
     '//incubator/protobuf/models:onos-incubator-protobuf-models',
     '//lib:protobuf-java-3.2.0',
-    '//lib:GRPC_1.3'
+    '//lib:GRPC_1.3',
+    '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
+    '//lib:grpc-protobuf-lite-1.3.0'
 ]
 
 GRPC_DEPS = [
     '//lib:GRPC_1.3',
+    '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
     '//incubator/protobuf/models:onos-incubator-protobuf-models-proto',
     '//lib:protobuf-java-3.2.0',
     '//lib:guava'
@@ -23,6 +26,7 @@
     '//lib:protobuf-java-3.2.0',
     '//lib:guava',
     '//lib:grpc-core-1.3.0',
+    '//incubator/grpc-dependencies:grpc-core-repkg-1.3.0',
     '//lib:grpc-protobuf-1.3.0',
     '//lib:grpc-stub-1.3.0',
     '//lib:grpc-netty-1.3.0',
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
deleted file mode 100644
index 341744c..0000000
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/utils/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * A package contains a set of utilities that are used to convert gRPC model
- * object to ONOS data model object.
- */
-package org.onosproject.grpc.nb.utils;
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
similarity index 99%
rename from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
rename to incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
index 1e1bdc9..df85f18 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/GrpcNbDeviceService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
@@ -33,7 +33,7 @@
 import org.onosproject.net.MastershipRole;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DeviceService;
-import org.onosproject.grpc.nb.utils.GrpcNbDeviceServiceUtil;
+import org.onosproject.incubator.protobuf.models.GrpcNbDeviceServiceUtil;
 
 import static org.onosproject.grpc.nb.net.device.DeviceServiceNb.*;
 
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java
new file mode 100644
index 0000000..d6d7d61
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkService.java
@@ -0,0 +1,216 @@
+/*
+* 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.incubator.protobuf.services.nb;
+import org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.LinkProtoTranslator;
+
+import com.google.common.annotations.Beta;
+import io.grpc.Server;
+import io.grpc.ServerBuilder;
+import io.grpc.stub.StreamObserver;
+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.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onosproject.grpc.nb.net.link.LinkServiceGrpc.LinkServiceImplBase;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.link.LinkService;
+
+import java.io.IOException;
+
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkCountRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkCountReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinkReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getActiveLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getActiveLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceEgressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceEgressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceIngressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getDeviceIngressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getEgressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getEgressLinksReply;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getIngressLinksRequest;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb.getIngressLinksReply;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A server that provides access to the methods exposed by {@link org.onosproject.net.link.LinkService}.
+ */
+@Beta
+@Component(immediate = true)
+public class GrpcNbLinkService {
+
+    private static final Logger log = LoggerFactory.getLogger(GrpcNbLinkService.class);
+
+
+    private Server server;
+    private LinkServiceNBServerInternal innerClassInstance = null;
+
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected LinkService linkService;
+
+    @Activate
+    public void activate() {
+        server = ServerBuilder.forPort(64000).addService(getInnerClassInstance()).build();
+        try {
+            server.start();
+        } catch (IOException e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    @Deactivate
+    public void deactivate() {
+        server.shutdown();
+    }
+
+    public class LinkServiceNBServerInternal extends LinkServiceImplBase {
+
+        public LinkServiceNBServerInternal() {
+            super();
+        }
+
+        @Override
+        public void getLinkCount(getLinkCountRequest request,
+                                 StreamObserver<getLinkCountReply> responseObserver) {
+            responseObserver
+                    .onNext(getLinkCountReply
+                                    .newBuilder()
+                                    .setLinkCount(linkService.getLinkCount())
+                                    .build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getLink(getLinkRequest request,
+                            StreamObserver<getLinkReply> responseObserver) {
+            ConnectPoint src = ConnectPointProtoTranslator.translate(request.getSrc()).get();
+            ConnectPoint dst = ConnectPointProtoTranslator.translate(request.getDst()).get();
+
+            org.onosproject.net.Link link = linkService.getLink(src, dst);
+            getLinkReply reply = getLinkReply.newBuilder()
+                    .setLink(LinkProtoTranslator.translate(link)).build();
+
+            responseObserver.onNext(reply);
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getActiveLinks(getActiveLinksRequest request,
+                                   StreamObserver<getActiveLinksReply> responseObserver) {
+            getActiveLinksReply.Builder builder = getActiveLinksReply.newBuilder();
+            linkService.getActiveLinks().forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getDeviceLinks(getDeviceLinksRequest request,
+                                   StreamObserver<getDeviceLinksReply> responseObserver) {
+            DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+            getDeviceLinksReply.Builder builder = getDeviceLinksReply.newBuilder();
+            linkService.getDeviceLinks(deviceId).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getDeviceEgressLinks(getDeviceEgressLinksRequest request,
+                                         StreamObserver<getDeviceEgressLinksReply> responseObserver) {
+            DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+            getDeviceEgressLinksReply.Builder builder = getDeviceEgressLinksReply.newBuilder();
+            linkService.getDeviceEgressLinks(deviceId).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getDeviceIngressLinks(getDeviceIngressLinksRequest request,
+                                          StreamObserver<getDeviceIngressLinksReply> responseObserver) {
+            DeviceId deviceId = DeviceId.deviceId(request.getDeviceId());
+            getDeviceIngressLinksReply.Builder builder = getDeviceIngressLinksReply.newBuilder();
+            linkService.getDeviceIngressLinks(deviceId).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getEgressLinks(getEgressLinksRequest request,
+                                   StreamObserver<getEgressLinksReply> responseObserver) {
+            ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+            getEgressLinksReply.Builder builder = getEgressLinksReply.newBuilder();
+            linkService.getEgressLinks(connectPoint).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getIngressLinks(getIngressLinksRequest request,
+                                    StreamObserver<getIngressLinksReply> responseObserver) {
+            ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+
+            getIngressLinksReply.Builder builder = getIngressLinksReply.newBuilder();
+            linkService.getIngressLinks(connectPoint).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+
+        @Override
+        public void getLinks(getLinksRequest request,
+                             StreamObserver<getLinksReply> responseObserver) {
+            ConnectPoint connectPoint = ConnectPointProtoTranslator.translate(request.getConnectPoint()).get();
+
+            getLinksReply.Builder builder = getLinksReply.newBuilder();
+            linkService.getLinks(connectPoint).forEach(l -> {
+                builder.addLink(LinkProtoTranslator.translate(l));
+            });
+            responseObserver.onNext(builder.build());
+            responseObserver.onCompleted();
+        }
+    }
+
+    public LinkServiceNBServerInternal getInnerClassInstance() {
+        if (innerClassInstance == null) {
+            innerClassInstance = new LinkServiceNBServerInternal();
+        }
+        return innerClassInstance;
+    }
+}
+
+
+
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
similarity index 92%
rename from incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
rename to incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
index 0814b10..51cb983 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/grpc/nb/net/device/package-info.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/package-info.java
@@ -16,4 +16,4 @@
 /**
  * gRPC server implementations for northbound services.
  */
-package org.onosproject.grpc.nb.net.device;
+package org.onosproject.incubator.protobuf.services.nb;
diff --git a/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto b/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto
new file mode 100644
index 0000000..7a267b7
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/main/proto/net/link/LinkServiceNb.proto
@@ -0,0 +1,90 @@
+syntax="proto3";
+option java_package = "org.onosproject.grpc.nb.net.link";
+
+package nb.net.link;
+
+import "net/LinkProto.proto";
+import "net/ConnectPointProto.proto";
+
+message getLinkCountRequest {
+}
+
+message getLinkCountReply {
+    int32 link_count = 1;
+}
+
+message getActiveLinksRequest {
+}
+
+message getActiveLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getDeviceLinksRequest {
+    string device_id = 1;
+}
+
+message getDeviceLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getDeviceEgressLinksRequest {
+    string device_id = 1;
+}
+
+message getDeviceEgressLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getDeviceIngressLinksRequest {
+    string device_id = 1;
+}
+
+message getDeviceIngressLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getLinksRequest {
+    .net.ConnectPointProto connect_point = 1;
+}
+
+message getLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getEgressLinksRequest {
+    .net.ConnectPointProto connect_point = 1;
+}
+
+message getEgressLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getIngressLinksRequest {
+    .net.ConnectPointProto connect_point = 1;
+}
+
+message getIngressLinksReply {
+    repeated .net.LinkProto link = 1;
+}
+
+message getLinkRequest {
+    .net.ConnectPointProto src = 1;
+    .net.ConnectPointProto dst = 2;
+}
+
+message getLinkReply {
+    .net.LinkProto link = 1;
+}
+
+service LinkService {
+    rpc getLinkCount(getLinkCountRequest) returns(getLinkCountReply) {}
+    rpc getLinks(getLinksRequest) returns(getLinksReply) {}
+    rpc getActiveLinks(getActiveLinksRequest) returns(getActiveLinksReply) {}
+    rpc getDeviceLinks(getDeviceLinksRequest) returns(getDeviceLinksReply) {}
+    rpc getDeviceEgressLinks(getDeviceEgressLinksRequest) returns(getDeviceEgressLinksReply) {}
+    rpc getDeviceIngressLinks(getDeviceIngressLinksRequest) returns(getDeviceIngressLinksReply) {}
+    rpc getEgressLinks(getEgressLinksRequest) returns(getEgressLinksReply) {}
+    rpc getIngressLinks(getIngressLinksRequest) returns(getIngressLinksReply) {}
+    rpc getLink(getLinkRequest) returns(getLinkReply) {}
+}
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java
new file mode 100644
index 0000000..d734e50
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbLinkServiceTest.java
@@ -0,0 +1,452 @@
+/*
+* 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.incubator.protobuf.services.nb;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.grpc.net.models.LinkProtoOuterClass;
+
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.net.DeviceId.deviceId;
+import static org.onosproject.net.PortNumber.portNumber;
+
+import io.grpc.ManagedChannel;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import org.onosproject.incubator.protobuf.models.net.ConnectPointProtoTranslator;
+import org.onosproject.incubator.protobuf.models.net.LinkProtoTranslator;
+import org.onosproject.net.ConnectPoint;
+
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DeviceId;
+
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.net.provider.ProviderId;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import org.onosproject.grpc.nb.net.link.LinkServiceGrpc;
+import org.onosproject.grpc.nb.net.link.LinkServiceGrpc.LinkServiceBlockingStub;
+import org.onosproject.grpc.nb.net.link.LinkServiceNb;
+import org.onosproject.incubator.protobuf.services.nb.GrpcNbLinkService.LinkServiceNBServerInternal;
+
+public class GrpcNbLinkServiceTest {
+    private static InProcessServer<LinkServiceNBServerInternal> inprocessServer;
+    private static ManagedChannel channel;
+    private static LinkServiceBlockingStub blockingStub;
+
+    private static final String D1 = "d1";
+    private static final String D2 = "d2";
+    private static final String D3 = "d3";
+    private static final String D4 = "d4";
+    private static final String D5 = "d5";
+    private static final String D6 = "d6";
+    private static final String D7 = "d7";
+    private static final String D8 = "d8";
+    private static final String D9 = "d9";
+
+    private static final String[][] LINK_CONNECT_DATA = {
+            {D1, "12", D2, "21"},
+            {D2, "23", D3, "32"},
+            {D4, "41", D1, "14"},
+            {D5, "51", D1, "15"},
+            {D6, "61", D1, "16"},
+            {D7, "73", D3, "37"},
+            {D8, "83", D3, "38"},
+            {D9, "93", D3, "39"},
+    };
+
+    private static final DeviceId DEVID_1 = deviceId(D1);
+    private static final PortNumber PORT_14 = portNumber("14");
+
+    private static final DeviceId DEVID_4 = deviceId(D4);
+    private static final PortNumber PORT_41 = portNumber("41");
+
+    private static final DeviceId DEVID_3 = deviceId(D3);
+    private static final PortNumber PORT_32 = portNumber("32");
+
+    private static final ConnectPoint DEVID_1_14 = new ConnectPoint(DEVID_1, PORT_14);
+    private static final ConnectPoint DEVID_4_41 = new ConnectPoint(DEVID_4, PORT_41);
+
+    private static final ProviderId PID = new ProviderId("Test", "Test");
+
+    private static List<Link> allLinks = new ArrayList<Link>();
+
+    private static final LinkService MOCK_LINK = new MockLinkService();
+
+    /**
+     * Creates a list of links.
+     *
+     */
+    private static void populateLinks() {
+        for (String[] linkPair : LINK_CONNECT_DATA) {
+            allLinks.addAll(makeLinkPair(linkPair));
+        }
+    }
+
+    /**
+     * Synthesizes a pair of unidirectional links between two devices. The
+     * string array should be of the form:
+     * <pre>
+     *     { "device-A-id", "device-A-port", "device-B-id", "device-B-port" }
+     * </pre>
+     *
+     * @param linkPairData device ids and ports
+     * @return pair of synthesized links
+     */
+    private static List<Link> makeLinkPair(String[] linkPairData) {
+        DeviceId devA = deviceId(linkPairData[0]);
+        PortNumber portA = portNumber(linkPairData[1]);
+
+        DeviceId devB = deviceId(linkPairData[2]);
+        PortNumber portB = portNumber(linkPairData[3]);
+
+        Link linkA = DefaultLink.builder()
+                .providerId(PID)
+                .type(Link.Type.DIRECT)
+                .src(new ConnectPoint(devA, portA))
+                .dst(new ConnectPoint(devB, portB))
+                .build();
+
+        Link linkB = DefaultLink.builder()
+                .providerId(PID)
+                .type(Link.Type.DIRECT)
+                .src(new ConnectPoint(devB, portB))
+                .dst(new ConnectPoint(devA, portA))
+                .build();
+
+        return ImmutableList.of(linkA, linkB);
+    }
+
+    public GrpcNbLinkServiceTest() {
+    }
+
+    @Test
+    public void testGetLinkCount() throws InterruptedException {
+        LinkServiceNb.getLinkCountRequest request = LinkServiceNb.getLinkCountRequest.getDefaultInstance();
+        LinkServiceNb.getLinkCountReply response;
+
+        try {
+            response = blockingStub.getLinkCount(request);
+            int linkCount = response.getLinkCount();
+            assertTrue(allLinks.size() == linkCount);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetLink() throws InterruptedException {
+        LinkServiceNb.getLinkRequest request = LinkServiceNb.getLinkRequest.newBuilder()
+                .setSrc(ConnectPointProtoTranslator.translate(DEVID_1_14))
+                .setDst(ConnectPointProtoTranslator.translate(DEVID_4_41))
+                .build();
+        LinkServiceNb.getLinkReply response;
+
+        try {
+            response = blockingStub.getLink(request);
+            LinkProtoOuterClass.LinkProto link = response.getLink();
+            assertTrue(LinkProtoTranslator.translate(allLinks.get(5)).equals(link));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetLinks() throws InterruptedException {
+        LinkServiceNb.getLinksRequest request = LinkServiceNb.getLinksRequest.newBuilder()
+                .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+                .build();
+        LinkServiceNb.getLinksReply response;
+
+        try {
+            response = blockingStub.getLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(4));
+            expectedLinks.add(allLinks.get(5));
+
+            assertTrue(expectedLinks.equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetActiveLinks() throws InterruptedException {
+        LinkServiceNb.getActiveLinksRequest request = LinkServiceNb.getActiveLinksRequest.getDefaultInstance();
+        LinkServiceNb.getActiveLinksReply response;
+
+        try {
+            response = blockingStub.getActiveLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+
+            Set<Link> expectedLinks = new HashSet<Link>(allLinks);
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetDeviceLinks() throws InterruptedException {
+        LinkServiceNb.getDeviceLinksRequest request = LinkServiceNb.getDeviceLinksRequest.newBuilder()
+                .setDeviceId(D1)
+                .build();
+        LinkServiceNb.getDeviceLinksReply response;
+
+        try {
+            response = blockingStub.getDeviceLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(4));
+            expectedLinks.add(allLinks.get(5));
+            expectedLinks.add(allLinks.get(6));
+            expectedLinks.add(allLinks.get(7));
+            expectedLinks.add(allLinks.get(8));
+            expectedLinks.add(allLinks.get(9));
+            expectedLinks.add(allLinks.get(0));
+            expectedLinks.add(allLinks.get(1));
+
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetDeviceEgressLinks() throws InterruptedException {
+        LinkServiceNb.getDeviceEgressLinksRequest request = LinkServiceNb.getDeviceEgressLinksRequest.newBuilder()
+                .setDeviceId(D1)
+                .build();
+        LinkServiceNb.getDeviceEgressLinksReply response;
+
+        try {
+            response = blockingStub.getDeviceEgressLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(0));
+            expectedLinks.add(allLinks.get(5));
+            expectedLinks.add(allLinks.get(7));
+            expectedLinks.add(allLinks.get(9));
+
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetDeviceIngressLinks() throws InterruptedException {
+        LinkServiceNb.getDeviceIngressLinksRequest request = LinkServiceNb.getDeviceIngressLinksRequest.newBuilder()
+                .setDeviceId(D1)
+                .build();
+        LinkServiceNb.getDeviceIngressLinksReply response;
+
+        try {
+            response = blockingStub.getDeviceIngressLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(1));
+            expectedLinks.add(allLinks.get(4));
+            expectedLinks.add(allLinks.get(6));
+            expectedLinks.add(allLinks.get(8));
+
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetEgressLinks() throws InterruptedException {
+        LinkServiceNb.getEgressLinksRequest request = LinkServiceNb.getEgressLinksRequest.newBuilder()
+                .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+                .build();
+        LinkServiceNb.getEgressLinksReply response;
+
+        try {
+            response = blockingStub.getEgressLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(5));
+
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Test
+    public void testGetIngressLinks() throws InterruptedException {
+        LinkServiceNb.getIngressLinksRequest request = LinkServiceNb.getIngressLinksRequest.newBuilder()
+                .setConnectPoint(ConnectPointProtoTranslator.translate(DEVID_1_14))
+                .build();
+        LinkServiceNb.getIngressLinksReply response;
+
+        try {
+            response = blockingStub.getIngressLinks(request);
+
+            Set<Link> actualLinks = new HashSet<Link>();
+            for (LinkProtoOuterClass.LinkProto link : response.getLinkList()) {
+                actualLinks.add(LinkProtoTranslator.translate(link));
+            }
+            Set<Link> expectedLinks = new HashSet<Link>();
+            expectedLinks.add(allLinks.get(4));
+
+            assertTrue((expectedLinks).equals(actualLinks));
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    @BeforeClass
+    public static void beforeClass() throws InstantiationException, IllegalAccessException, IOException {
+        inprocessServer = new InProcessServer<LinkServiceNBServerInternal>(LinkServiceNBServerInternal.class);
+
+        GrpcNbLinkService outer = new GrpcNbLinkService();
+        GrpcNbLinkService.LinkServiceNBServerInternal inner = outer.getInnerClassInstance();
+        outer.linkService = MOCK_LINK;
+        inprocessServer.addServiceToBind(inner);
+
+        inprocessServer.start();
+        channel = InProcessChannelBuilder.forName("test").directExecutor()
+                // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
+                // needing certificates.
+                .usePlaintext(true).build();
+        blockingStub = LinkServiceGrpc.newBlockingStub(channel);
+
+        populateLinks();
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        channel.shutdownNow();
+
+        inprocessServer.stop();
+    }
+
+    private static class MockLinkService implements LinkService {
+        MockLinkService() {
+        }
+
+        @Override
+        public int getLinkCount() {
+            return allLinks.size();
+        }
+
+        @Override
+        public Iterable<Link> getLinks() {
+            return ImmutableSet.copyOf(allLinks);
+        }
+
+        @Override
+        public Iterable<Link> getActiveLinks() {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> input.state() == Link.State.ACTIVE);
+        }
+
+        @Override
+        public Set<Link> getDeviceLinks(DeviceId deviceId) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.src().deviceId().equals(deviceId)) ||
+                            (input.dst().deviceId().equals(deviceId))).toSet();
+        }
+
+        @Override
+        public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.src().deviceId().equals(deviceId))).toSet();
+        }
+
+        @Override
+        public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.dst().deviceId().equals(deviceId))).toSet();
+        }
+
+        @Override
+        public Set<Link> getLinks(ConnectPoint connectPoint) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.src().equals(connectPoint)) || (input.dst().equals(connectPoint))).toSet();
+        }
+
+        @Override
+        public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.src().equals(connectPoint))).toSet();
+        }
+
+        @Override
+        public Set<Link> getIngressLinks(ConnectPoint connectPoint) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.dst().equals(connectPoint))).toSet();
+        }
+
+        @Override
+        public Link getLink(ConnectPoint src, ConnectPoint dst) {
+            return FluentIterable.from(getLinks())
+                    .filter(input -> (input.src().equals(src)) && (input.dst().equals(dst)))
+                    .first().get();
+        }
+
+        @Override
+        public void addListener(org.onosproject.net.link.LinkListener listener) {
+        }
+
+        @Override
+        public void removeListener(org.onosproject.net.link.LinkListener listener) {
+        }
+    }
+}
\ No newline at end of file
diff --git a/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java
new file mode 100644
index 0000000..6caa9d9
--- /dev/null
+++ b/incubator/protobuf/services/nb/src/test/java/org/onosproject/incubator/protobuf/services/nb/InProcessServer.java
@@ -0,0 +1,78 @@
+/*
+* 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.incubator.protobuf.services.nb;
+
+import com.google.common.collect.Sets;
+import io.grpc.Server;
+import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.internal.AbstractServerImplBuilder;
+
+import java.io.IOException;
+import java.util.Set;
+/**
+ * InProcessServer that manages startup/shutdown of a service within the same process
+ * as the client is running. Used for unit testing purposes.
+ */
+public class InProcessServer<T extends io.grpc.BindableService> {
+    private Server server;
+
+    Set<T> services = Sets.newHashSet();
+
+    private Class<T> clazz;
+
+    public InProcessServer(Class<T> clazz) {
+        this.clazz = clazz;
+    }
+
+    public void addServiceToBind(T service) {
+        if (service != null) {
+            services.add(service);
+        }
+    }
+
+    public void start() throws IOException, InstantiationException, IllegalAccessException {
+
+        AbstractServerImplBuilder builder = InProcessServerBuilder.forName("test").directExecutor();
+        services.forEach(service -> builder.addService(service));
+        server = builder.build().start();
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                // Use stderr here since the logger may have been reset by its JVM shutdown hook.
+                System.err.println("*** shutting down gRPC server since JVM is shutting down");
+                InProcessServer.this.stop();
+                System.err.println("*** server shut down");
+            }
+        });
+    }
+
+    void stop() {
+        if (server != null) {
+            server.shutdown();
+        }
+    }
+
+    /**
+     * Await termination on the main thread since the grpc library uses daemon threads.
+     * @throws InterruptedException if there is an issue
+     */
+    public void blockUntilShutdown() throws InterruptedException {
+        if (server != null) {
+            server.awaitTermination();
+        }
+    }
+}
\ No newline at end of file
diff --git a/lib/BUCK b/lib/BUCK
index 8a9d663..6db1b6b 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -111,7 +111,6 @@
   name = 'GRPC_1.3',
   visibility = ['PUBLIC'],
   exported_deps = [
-    ':grpc-core-1.3.0',
     ':grpc-protobuf-1.3.0',
     ':grpc-stub-1.3.0',
     ':grpc-netty-1.3.0',
diff --git a/lib/deps.json b/lib/deps.json
index 6ff4604..82992bd 100644
--- a/lib/deps.json
+++ b/lib/deps.json
@@ -70,7 +70,7 @@
       "netty-common"
     ],
     "GRPC_1.3": [
-      "grpc-core-1.3.0",
+//      "grpc-core-1.3.0",
       "grpc-protobuf-1.3.0",
       "grpc-stub-1.3.0",
       "grpc-netty-1.3.0",