[ONOS-6463] general device Provider

Change-Id: Ibc045bffe14c24068adc7f0adc96366d0f1807a0
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java b/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java
index 04c4449..7f469b1 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/PortAdmin.java
@@ -15,19 +15,44 @@
  */
 package org.onosproject.net.behaviour;
 
-import org.onosproject.net.device.PortDescription;
+import com.google.common.annotations.Beta;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.driver.HandlerBehaviour;
 
+import java.util.concurrent.CompletableFuture;
+
 /**
- * Means to administratively enable/disable a logical port at the device.
+ * Means to administratively enable,disable and query the state
+ * of a port on a device.
  */
+@Beta
 public interface PortAdmin extends HandlerBehaviour {
 
     /**
-     * Enable/disable administratively a port.
+     * Enable administratively a port.
      *
-     * @param port a port description containing the desired port state
+     * @param number the port to be enabled
+     * @return CompletableFuture with true if the operation was successful
      */
-    void enable(PortDescription port);
+    CompletableFuture<Boolean> enable(PortNumber number);
+
+    /**
+     * Disable administratively a port.
+     *
+     * @param number the port to be disabled
+     * @return CompletableFuture with true if the operation was successful
+     */
+    CompletableFuture<Boolean> disable(PortNumber number);
+
+    /**
+     * Retrieves the information about the administrative state of a port.
+     *
+     * @param number identifier of the port to be queried about its state
+     * @return CompletableFuture containing, when completed, true if the port isEnabled.
+     */
+    CompletableFuture<Boolean> isEnabled(PortNumber number);
+
+    //TODO this behaviour can be augmented or others can be created for
+    // LED and Speed configuration
 
 }
diff --git a/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java b/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java
new file mode 100644
index 0000000..abfb237
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/device/DeviceHandshaker.java
@@ -0,0 +1,49 @@
+/*
+ * 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.net.device;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.driver.DeviceConnect;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Behavior to test device's reachability and change the mastership role on that
+ * device.
+ */
+@Beta
+public interface DeviceHandshaker extends DeviceConnect {
+
+    /**
+     * Checks the reachability (connectivity) of a device.
+     * Reachability, unlike availability, denotes whether THIS particular node
+     * can send messages and receive replies from the specified device.
+     *
+     * @return CompletableFuture eventually true if reachable, false otherwise
+     */
+    CompletableFuture<Boolean> isReachable();
+
+    /**
+     * Applies on the device a mastership role change as decided by the core.
+     *
+     * @param newRole newly determined mastership role
+     * @return CompletableFuture with the mastership role accepted from the device
+     */
+    CompletableFuture<MastershipRole> roleChanged(MastershipRole newRole);
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DeviceConnect.java b/core/api/src/main/java/org/onosproject/net/driver/DeviceConnect.java
new file mode 100644
index 0000000..7b28f0b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/driver/DeviceConnect.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015-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.net.driver;
+
+import com.google.common.annotations.Beta;
+
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Abstraction of handler behaviour used to set-up and tear-down
+ * connection with a device.
+ */
+@Beta
+public interface DeviceConnect extends HandlerBehaviour {
+
+    /**
+     * Connects to the device.
+     * It's supposed to initiate the transport sessions, channel and also,
+     * if applicable, store them in the proper protocol specific
+     * controller (e.g. GrpcController).
+     *
+     * @return CompletableFuture with true if the operation was successful
+     */
+    CompletableFuture<Boolean> connect();
+
+    /**
+     * Disconnects from the device.
+     * It's supposed to destroy the transport sessions and channel and also,
+     * if applicable, remove them in the proper protocol specific
+     * controller (e.g. GrpcController).
+     *
+     * @return CompletableFuture with true if the operation was successful
+     */
+    CompletableFuture<Boolean> disconnect();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java b/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java
deleted file mode 100644
index 34a91ea..0000000
--- a/core/api/src/main/java/org/onosproject/net/driver/DriverConnect.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2015-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.net.driver;
-
-/**
- * Abstraction of handler behaviour used to set-up and tear-down driver
- * connection with a device.
- */
-public interface DriverConnect extends HandlerBehaviour {
-
-    /**
-     * Connects to the device.
-     *
-     * @param credentials optional login credentials in string form
-     */
-    void connect(String... credentials);
-
-    /**
-     * Disconnects from the device.
-     */
-    void disconnect();
-
-}
diff --git a/drivers/bmv2/BUCK b/drivers/bmv2/BUCK
new file mode 100644
index 0000000..95b2d44
--- /dev/null
+++ b/drivers/bmv2/BUCK
@@ -0,0 +1,29 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+    '//core/api:onos-api-tests',
+]
+
+BUNDLES = [
+    ':onos-drivers-bmv2',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+    resources_root = 'src/main/resources',
+    resources = glob(['src/main/resources/**']),
+)
+
+onos_app (
+    app_name = 'org.onosproject.drivers.bmv2',
+    title = 'bmv2 Device Drivers',
+    category = 'Drivers',
+    url = 'http://onosproject.org',
+    description = 'ONOS BMv2 Device Drivers application.',
+    included_bundles = BUNDLES,
+    required_apps = [ 'org.onosproject.generaldeviceprovider' ],
+)
diff --git a/drivers/bmv2/features.xml b/drivers/bmv2/features.xml
new file mode 100644
index 0000000..1741897
--- /dev/null
+++ b/drivers/bmv2/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+        <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+
+    </feature>
+</features>
diff --git a/drivers/bmv2/pom.xml b/drivers/bmv2/pom.xml
new file mode 100644
index 0000000..f99f555
--- /dev/null
+++ b/drivers/bmv2/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+
+<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-drivers-general</artifactId>
+        <groupId>org.onosproject</groupId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>onos-drivers-bmv2</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>BMv2 device drivers</description>
+
+    <properties>
+        <onos.app.name>org.onosproject.drivers.bmv2</onos.app.name>
+        <onos.app.origin>ON.Lab</onos.app.origin>
+        <onos.app.title>BMv2 Device Drivers</onos.app.title>
+        <onos.app.category>Drivers</onos.app.category>
+        <onos.app.url>http://onosproject.org</onos.app.url>
+        <onos.app.requires>
+            org.onosproject.generaldeviceprovider
+        </onos.app.requires>
+    </properties>
+
+</project>
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DriversLoader.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DriversLoader.java
new file mode 100644
index 0000000..45fb749
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DriversLoader.java
@@ -0,0 +1,31 @@
+/*
+ * 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 org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for P4Runtime device drivers.
+ */
+@Component(immediate = true)
+public class Bmv2DriversLoader extends AbstractDriverLoader {
+
+    public Bmv2DriversLoader() {
+        super("/bmv2-drivers.xml");
+    }
+}
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
new file mode 100644
index 0000000..06f9c9e
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2Handshaker.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.drivers.bmv2;
+
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.device.DeviceHandshaker;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.key.DeviceKeyId;
+import org.onosproject.net.key.DeviceKeyService;
+import org.slf4j.Logger;
+
+import java.util.concurrent.CompletableFuture;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * 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.
+//FIXME fill method bodies, used for testing.
+public class Bmv2Handshaker extends AbstractHandlerBehaviour
+        implements DeviceHandshaker {
+
+    private final Logger log = getLogger(getClass());
+
+    @Override
+    public CompletableFuture<Boolean> connect() {
+        CompletableFuture<Boolean> result = new CompletableFuture<>();
+        DeviceKeyService deviceKeyService = handler().get(DeviceKeyService.class);
+        DriverData data = data();
+        //Retrieving information from the driver data.
+        log.info("protocol bmv2, ip {}, port {}, key {}", data.value("p4runtime_ip"),
+                data.value("p4runtime_port"),
+                deviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(data.value("p4runtime_key")))
+                        .asUsernamePassword().username());
+
+        log.info("protocol gnmi, ip {}, port {}, key {}", data.value("gnmi_ip"), data.value("gnmi_port"),
+                deviceKeyService.getDeviceKey(DeviceKeyId.deviceKeyId(data.value("gnmi_key")))
+                        .asUsernamePassword().username());
+        result.complete(true);
+        return result;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> disconnect() {
+        CompletableFuture<Boolean> result = new CompletableFuture<>();
+        result.complete(true);
+        return result;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> isReachable() {
+        CompletableFuture<Boolean> result = new CompletableFuture<>();
+        result.complete(true);
+        return result;
+    }
+
+    @Override
+    public CompletableFuture<MastershipRole> roleChanged(MastershipRole newRole) {
+        CompletableFuture<MastershipRole> result = new CompletableFuture<>();
+        result.complete(MastershipRole.MASTER);
+        return result;
+    }
+
+}
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/package-info.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/package-info.java
new file mode 100644
index 0000000..e76790e
--- /dev/null
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/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 bmv2 device drivers.
+ */
+package org.onosproject.drivers.bmv2;
\ No newline at end of file
diff --git a/drivers/bmv2/src/main/resources/bmv2-drivers.xml b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
new file mode 100644
index 0000000..7f0d3f2
--- /dev/null
+++ b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<drivers>
+    <driver name="bmv2" manufacturer="barefoot" hwVersion="1.0.0" swVersion="1.0.0">
+        <behaviour api="org.onosproject.net.device.DeviceHandshaker"
+                   impl="org.onosproject.drivers.bmv2.Bmv2Handshaker"/>
+    </driver>
+</drivers>
+
diff --git a/drivers/pom.xml b/drivers/pom.xml
index 99016d9..72fa76f 100644
--- a/drivers/pom.xml
+++ b/drivers/pom.xml
@@ -49,6 +49,7 @@
         <module>flowspec</module>
         <module>microsemi</module>
         <module>oplink</module>
+        <module>bmv2</module>
     </modules>
 
     <!--<properties>
diff --git a/modules.defs b/modules.defs
index cbada41..df4530a 100644
--- a/modules.defs
+++ b/modules.defs
@@ -75,6 +75,7 @@
     '//providers/isis/topology:onos-providers-isis-topology',
     '//providers/lisp/device:onos-providers-lisp-device',
     '//providers/tl1/device:onos-providers-tl1-device',
+    '//providers/general/device:onos-providers-general-device',
 
     '//web/api:onos-rest',
     '//web/gui:onos-gui',
@@ -102,6 +103,7 @@
 #   Removed until we can handle v1.12 of onos-yang-tools - in the mean time build manually with Maven
 #   '//drivers/microsemi/ea1000driver:onos-drivers-microsemi-ea1000driver-oar',
     '//drivers/oplink:onos-drivers-oplink-oar',
+    '//drivers/bmv2:onos-drivers-bmv2-oar',
 ]
 
 ONOS_PROVIDERS = [
@@ -127,6 +129,7 @@
     '//providers/link:onos-providers-link-oar',
     '//providers/lisp:onos-providers-lisp-oar',
     '//providers/tl1:onos-providers-tl1-oar',
+    '//providers/general:onos-providers-general-oar',
 #    '//providers/ietfte:onos-providers-ietfte-oar',
 ]
 
diff --git a/providers/general/BUCK b/providers/general/BUCK
new file mode 100644
index 0000000..5d4973e
--- /dev/null
+++ b/providers/general/BUCK
@@ -0,0 +1,15 @@
+BUNDLES = [
+    '//providers/general/device:onos-providers-general-device',
+]
+
+onos_app (
+    app_name = "org.onosproject.generaldeviceprovider",
+    title = 'General Device Provider',
+    category = 'Provider',
+    url = 'http://onosproject.org',
+    included_bundles = BUNDLES,
+    description = 'General device southbound providers.',
+    required_apps = [],
+)
+
+
diff --git a/providers/general/app/app.xml b/providers/general/app/app.xml
new file mode 100644
index 0000000..eeaba0c
--- /dev/null
+++ b/providers/general/app/app.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<app name="org.onosproject.generaldeviceprovider" origin="ON.Lab" version="${project.version}"
+     category="Provider" url="https://wiki.onosproject.org/" title="General Device Provider"
+     featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+     features="${project.artifactId}">
+    <description>${project.description}</description>
+
+    <artifact>mvn:${project.groupId}/onos-general-provider-device/${project.version}</artifact>
+
+</app>
diff --git a/providers/general/app/features.xml b/providers/general/app/features.xml
new file mode 100644
index 0000000..f147e61
--- /dev/null
+++ b/providers/general/app/features.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+  ~ 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.
+  -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+    <feature name="${project.artifactId}" version="${project.version}"
+             description="${project.description}">
+        <feature>onos-api</feature>
+
+        <bundle>mvn:${project.groupId}/onos-general-provider-device/${project.version}</bundle>
+    </feature>
+</features>
+
diff --git a/providers/general/app/pom.xml b/providers/general/app/pom.xml
new file mode 100644
index 0000000..da2bf99
--- /dev/null
+++ b/providers/general/app/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<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/maven-4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-general-providers</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-general-provider-app</artifactId>
+    <packaging>bundle</packaging>
+
+    <properties>
+        <onos.app.name>org.onosproject.generaldriverprovider</onos.app.name>
+        <onos.app.title>General Device Provider</onos.app.title>
+        <onos.app.category>Provider</onos.app.category>
+        <onos.app.requires>
+        </onos.app.requires>
+        <onos.app.url>
+        </onos.app.url>
+    </properties>
+
+    <description>General Device Provider that uses drivers as means of device discovery</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-general-provider-device</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- Add other dependencies here as more bundles are added to the app -->
+
+    </dependencies>
+
+</project>
diff --git a/providers/general/device/BUCK b/providers/general/device/BUCK
new file mode 100644
index 0000000..770f6ca
--- /dev/null
+++ b/providers/general/device/BUCK
@@ -0,0 +1,12 @@
+COMPILE_DEPS = [
+    '//lib:CORE_DEPS',
+]
+
+TEST_DEPS = [
+    '//lib:TEST_ADAPTERS',
+]
+
+osgi_jar_with_tests (
+    deps = COMPILE_DEPS,
+    test_deps = TEST_DEPS,
+)
diff --git a/providers/general/device/pom.xml b/providers/general/device/pom.xml
new file mode 100644
index 0000000..1c7bb14
--- /dev/null
+++ b/providers/general/device/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+ -->
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-general-providers</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-general-provider-device</artifactId>
+    <packaging>bundle</packaging>
+
+    <description>ONOS general device provider that uses drivers as a mean of
+    discovery and handshake. </description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onlab-junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>5.0.0</version>
+            <scope>provided</scope>
+        </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>
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/DeviceInfoConfig.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/DeviceInfoConfig.java
new file mode 100644
index 0000000..f8660af
--- /dev/null
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/DeviceInfoConfig.java
@@ -0,0 +1,57 @@
+/*
+ * 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.provider.general.device.api;
+
+import com.google.common.annotations.Beta;
+
+import java.util.Map;
+
+/**
+ * Protocol specific configuration for the general device provider.
+ */
+@Beta
+public final class DeviceInfoConfig {
+
+    private final Map<String, String> configValues;
+    private final String deviceKeyId;
+
+
+    public DeviceInfoConfig(Map<String, String> configValues, String deviceKeyId) {
+        this.configValues = configValues;
+        this.deviceKeyId = deviceKeyId;
+    }
+
+    /**
+     * Gets the configValues contained in the json sent via net-cfg.
+     *
+     * @return configValues in key-value pairs.
+     */
+    public Map<String, String> configValues() {
+        return configValues;
+    }
+
+    /**
+     * Gets the device key id of the device.
+     * This key should be pre-existing in ONOS.
+     *
+     * @return device key id
+     */
+    public String deviceKeyId() {
+        return deviceKeyId;
+    }
+
+}
\ No newline at end of file
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/GeneralProviderDeviceConfig.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/GeneralProviderDeviceConfig.java
new file mode 100644
index 0000000..de3d8d9
--- /dev/null
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/GeneralProviderDeviceConfig.java
@@ -0,0 +1,68 @@
+/*
+ * 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.provider.general.device.api;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.annotations.Beta;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.config.Config;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Configuration for General device provider.
+ */
+@Beta
+public class GeneralProviderDeviceConfig extends Config<DeviceId> {
+
+    private static final String DEVICEKEYID = "deviceKeyId";
+
+
+    @Override
+    public boolean isValid() {
+        return true;
+    }
+
+    /**
+     * Gets the information of all protocols associated to the device.
+     *
+     * @return map of protocol name and relative information
+     */
+    public Map<String, DeviceInfoConfig> protocolsInfo() {
+        return getProtocolInfoMap();
+    }
+
+    private Map<String, DeviceInfoConfig> getProtocolInfoMap() {
+        Map<String, DeviceInfoConfig> deviceMap = new HashMap<>();
+        node.fieldNames().forEachRemaining(name -> {
+
+            Map<String, String> configMap = new HashMap<>();
+            JsonNode protocol = node.get(name);
+            protocol.fieldNames().forEachRemaining(info -> configMap.put(info, protocol.get(info).asText()));
+
+            String deviceKeyId = "";
+            if (protocol.has(DEVICEKEYID)) {
+                deviceKeyId = protocol.get(DEVICEKEYID).asText("");
+            }
+
+            deviceMap.put(name, new DeviceInfoConfig(configMap, deviceKeyId));
+        });
+        return deviceMap;
+    }
+
+}
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/package-info.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/package-info.java
new file mode 100644
index 0000000..fb23954
--- /dev/null
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/api/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.
+ */
+
+/**
+ * APIs for General Provider that uses drivers as a means of infrastructure device discovery.
+ */
+package org.onosproject.provider.general.device.api;
\ No newline at end of file
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
new file mode 100644
index 0000000..8909591
--- /dev/null
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
@@ -0,0 +1,446 @@
+/*
+ * 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.provider.general.device.impl;
+
+import com.google.common.annotations.Beta;
+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.onlab.packet.ChassisId;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.behaviour.PortAdmin;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DefaultDeviceDescription;
+import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.DeviceDescriptionDiscovery;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceHandshaker;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceProvider;
+import org.onosproject.net.device.DeviceProviderRegistry;
+import org.onosproject.net.device.DeviceProviderService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.device.PortStatisticsDiscovery;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.key.DeviceKeyAdminService;
+import org.onosproject.net.provider.AbstractProvider;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.provider.general.device.api.GeneralProviderDeviceConfig;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.device.DeviceEvent.Type;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provider which uses drivers to detect device and do initial handshake
+ * and channel establishment with devices. Any other provider specific operation
+ * is also delegated to the DeviceHandshaker driver.
+ */
+@Beta
+@Component(immediate = true)
+public class GeneralDeviceProvider extends AbstractProvider
+        implements DeviceProvider {
+    private final Logger log = getLogger(getClass());
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceProviderRegistry providerRegistry;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected NetworkConfigRegistry cfgService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceService deviceService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DeviceKeyAdminService deviceKeyAdminService;
+
+    protected static final String APP_NAME = "org.onosproject.generaldeviceprovider";
+    protected static final String URI_SCHEME = "device";
+    protected static final String CFG_SCHEME = "generalprovider";
+    private static final String DEVICE_PROVIDER_PACKAGE = "org.onosproject.general.provider.device";
+    private static final int CORE_POOL_SIZE = 10;
+    private static final String UNKNOWN = "unknown";
+    private static final int PORT_STATS_PERIOD_SECONDS = 10;
+
+
+    protected ScheduledExecutorService connectionExecutor
+            = newScheduledThreadPool(CORE_POOL_SIZE,
+            groupedThreads("onos/generaldeviceprovider-device",
+                    "connection-executor-%d", log));
+    protected ScheduledExecutorService portStatsExecutor
+            = newScheduledThreadPool(CORE_POOL_SIZE,
+            groupedThreads("onos/generaldeviceprovider-port-stats",
+                    "port-stats-executor-%d", log));
+
+    protected DeviceProviderService providerService;
+    private InternalDeviceListener deviceListener = new InternalDeviceListener();
+
+    protected final ConfigFactory factory =
+            new ConfigFactory<DeviceId, GeneralProviderDeviceConfig>(
+                    SubjectFactories.DEVICE_SUBJECT_FACTORY,
+                    GeneralProviderDeviceConfig.class, CFG_SCHEME) {
+                @Override
+                public GeneralProviderDeviceConfig createConfig() {
+                    return new GeneralProviderDeviceConfig();
+                }
+            };
+
+    protected final NetworkConfigListener cfgListener = new InternalNetworkConfigListener();
+
+
+    @Activate
+    public void activate() {
+        providerService = providerRegistry.register(this);
+        coreService.registerApplication(APP_NAME);
+        cfgService.registerConfigFactory(factory);
+        cfgService.addListener(cfgListener);
+        deviceService.addListener(deviceListener);
+        //This will fail if ONOS has CFG and drivers which depend on this provider
+        // are activated, failing due to not finding the driver.
+        cfgService.getSubjects(DeviceId.class, GeneralProviderDeviceConfig.class)
+                .forEach(did -> connectionExecutor.execute(() -> connectDevice(did)));
+        log.info("Started");
+    }
+
+
+    @Deactivate
+    public void deactivate() {
+        portStatsExecutor.shutdown();
+        cfgService.removeListener(cfgListener);
+        //Not Removing the device so they can still be used from other driver providers
+        //cfgService.getSubjects(DeviceId.class, GeneralProviderDeviceConfig.class)
+        //          .forEach(did -> connectionExecutor.execute(() -> disconnectDevice(did)));
+        connectionExecutor.shutdown();
+        deviceService.removeListener(deviceListener);
+        providerRegistry.unregister(this);
+        providerService = null;
+        cfgService.unregisterConfigFactory(factory);
+        log.info("Stopped");
+    }
+
+    public GeneralDeviceProvider() {
+        super(new ProviderId(URI_SCHEME, DEVICE_PROVIDER_PACKAGE));
+    }
+
+
+    @Override
+    public void triggerProbe(DeviceId deviceId) {
+        //TODO Really don't see the point of this in non OF Context,
+        // for now testing reachability, can be moved to no-op
+        log.debug("Triggering probe equals testing reachability on device {}", deviceId);
+        isReachable(deviceId);
+    }
+
+    @Override
+    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
+        log.debug("Received role {} for device {}", newRole, deviceId);
+        CompletableFuture<MastershipRole> roleReply = getHandshaker(deviceId).roleChanged(newRole);
+        roleReply.thenAcceptAsync(mastership -> providerService.receivedRoleReply(deviceId, newRole, mastership));
+    }
+
+    @Override
+    public boolean isReachable(DeviceId deviceId) {
+        log.debug("Testing rechability for device {}", deviceId);
+        CompletableFuture<Boolean> reachable = getHandshaker(deviceId).isReachable();
+        try {
+            return reachable.get(10, TimeUnit.SECONDS);
+        } catch (InterruptedException | ExecutionException | TimeoutException e) {
+            log.error("Device {} is not reachable", deviceId, e);
+            return false;
+        }
+    }
+
+    @Override
+    public void changePortState(DeviceId deviceId, PortNumber portNumber,
+                                boolean enable) {
+        if (deviceService.getDevice(deviceId).is(PortAdmin.class)) {
+
+            PortAdmin portAdmin = getPortAdmin(deviceId);
+            CompletableFuture<Boolean> modified;
+            if (enable) {
+                modified = portAdmin.enable(portNumber);
+            } else {
+                modified = portAdmin.disable(portNumber);
+            }
+            modified.thenAcceptAsync(result -> {
+                if (!result) {
+                    log.warn("Your device {} port {} status can't be changed to {}",
+                            deviceId, portNumber, enable);
+                }
+            });
+
+        } else {
+            log.warn("Device {} does not support PortAdmin behaviour", deviceId);
+        }
+    }
+
+    private DeviceHandshaker getHandshaker(DeviceId deviceId) {
+        Driver driver = getDriver(deviceId);
+        return getBehaviour(driver, DeviceHandshaker.class,
+                new DefaultDriverData(driver, deviceId));
+    }
+
+    private PortAdmin getPortAdmin(DeviceId deviceId) {
+        Driver driver = getDriver(deviceId);
+        return getBehaviour(driver, PortAdmin.class,
+                new DefaultDriverData(driver, deviceId));
+
+    }
+
+    private Driver getDriver(DeviceId deviceId) {
+        Driver driver;
+        try {
+            driver = driverService.getDriver(deviceId);
+        } catch (ItemNotFoundException e) {
+            log.debug("Falling back to configuration to fetch driver " +
+                    "for device {}", deviceId);
+            driver = driverService.getDriver(
+                    cfgService.getConfig(deviceId, BasicDeviceConfig.class).driver());
+        }
+        return driver;
+    }
+
+    //needed since the device manager will not return the driver through implementation()
+    // method since the device is not pushed to the core so for the connectDevice
+    // we need to work around that in order to test before calling
+    // store.createOrUpdateDevice
+    private <T extends Behaviour> T getBehaviour(Driver driver, Class<T> type,
+                                                 DriverData data) {
+        if (driver.hasBehaviour(type)) {
+            DefaultDriverHandler handler = new DefaultDriverHandler(data);
+            return driver.createBehaviour(handler, type);
+        } else {
+            return null;
+        }
+    }
+
+    //Connects a general device
+    private void connectDevice(DeviceId deviceId) {
+        //retrieve the configuration
+        GeneralProviderDeviceConfig providerConfig =
+                cfgService.getConfig(deviceId, GeneralProviderDeviceConfig.class);
+        BasicDeviceConfig basicDeviceConfig =
+                cfgService.getConfig(deviceId, BasicDeviceConfig.class);
+
+        if (providerConfig == null || basicDeviceConfig == null) {
+            log.error("Configuration is NULL: basic config {}, general provider " +
+                    "config {}", basicDeviceConfig, providerConfig);
+        } else {
+            log.info("Connecting to device {}", deviceId);
+
+            Driver driver = driverService.getDriver(basicDeviceConfig.driver());
+            DriverData driverData = new DefaultDriverData(driver, deviceId);
+
+            DeviceHandshaker handshaker =
+                    getBehaviour(driver, DeviceHandshaker.class, driverData);
+
+            if (handshaker != null) {
+
+                //Storing deviceKeyId and all other config values
+                // as data in the driver with protocol_<info>
+                // name as the key. e.g protocol_ip
+                providerConfig.protocolsInfo()
+                        .forEach((protocol, deviceInfoConfig) -> {
+                            deviceInfoConfig.configValues()
+                                    .forEach((k, v) -> driverData.set(protocol + "_" + k, v));
+                            driverData.set(protocol + "_key", deviceInfoConfig.deviceKeyId());
+                        });
+
+                //Connecting to the device
+                CompletableFuture<Boolean> connected = handshaker.connect();
+
+                connected.thenAcceptAsync(result -> {
+                    if (result) {
+
+                        //Populated with the default values obtained by the driver
+                        ChassisId cid = new ChassisId();
+                        SparseAnnotations annotations = DefaultAnnotations.builder()
+                                .set(AnnotationKeys.PROTOCOL,
+                                        providerConfig.protocolsInfo().keySet().toString())
+                                .build();
+                        DeviceDescription description =
+                                new DefaultDeviceDescription(deviceId.uri(), Device.Type.SWITCH,
+                                        driver.manufacturer(), driver.hwVersion(),
+                                        driver.swVersion(), UNKNOWN,
+                                        cid, false, annotations);
+                        //Empty list of ports
+                        List<PortDescription> ports = new ArrayList<>();
+
+                        if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
+                            DeviceDescriptionDiscovery deviceDiscovery = driver
+                                    .createBehaviour(driverData, DeviceDescriptionDiscovery.class);
+
+                            DeviceDescription newdescription = deviceDiscovery.discoverDeviceDetails();
+                            if (newdescription != null) {
+                                description = newdescription;
+                            }
+                            ports = deviceDiscovery.discoverPortDetails();
+                        }
+                        providerService.deviceConnected(deviceId, description);
+                        providerService.updatePorts(deviceId, ports);
+
+                    } else {
+                        log.warn("Can't connect to device {}", deviceId);
+                    }
+                });
+            } else {
+                log.error("Device {}, with driver {} does not support DeviceHandshaker " +
+                        "behaviour, {}", deviceId, driver.name(), driver.behaviours());
+            }
+        }
+    }
+
+    private void disconnectDevice(DeviceId deviceId) {
+        log.info("Disconnecting for device {}", deviceId);
+        DeviceHandshaker handshaker = getHandshaker(deviceId);
+        if (handshaker != null) {
+            CompletableFuture<Boolean> disconnect = handshaker.disconnect();
+
+            disconnect.thenAcceptAsync(result -> {
+                if (result) {
+                    log.info("Disconnected device {}", deviceId);
+                    providerService.deviceDisconnected(deviceId);
+                } else {
+                    log.warn("Device {} was unable to disconnect", deviceId);
+                }
+            });
+        } else {
+            //gracefully ignoring.
+            log.info("No DeviceHandshaker for device {}", deviceId);
+        }
+    }
+
+    //Needed to catch the exception in the executors since are not rethrown otherwise.
+    private Runnable exceptionSafe(Runnable runnable) {
+        return () -> {
+            try {
+                runnable.run();
+            } catch (Exception e) {
+                log.error("Unhandled Exception", e);
+            }
+        };
+    }
+
+    private void updatePortStatistics(DeviceId deviceId) {
+        Collection<PortStatistics> statistics = deviceService.getDevice(deviceId)
+                .as(PortStatisticsDiscovery.class)
+                .discoverPortStatistics();
+        providerService.updatePortStatistics(deviceId, statistics);
+    }
+
+    /**
+     * Listener for configuration events.
+     */
+    private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+
+        @Override
+        public void event(NetworkConfigEvent event) {
+            DeviceId deviceId = (DeviceId) event.subject();
+            //Assuming that the deviceId comes with uri 'device:'
+            if (!deviceId.uri().getScheme().equals(URI_SCHEME)) {
+                // not under my scheme, skipping
+                log.debug("{} is not my scheme, skipping", deviceId);
+                return;
+            }
+            if (deviceService.getDevice(deviceId) == null || !deviceService.isAvailable(deviceId)) {
+                connectionExecutor.submit(exceptionSafe(() -> connectDevice(deviceId)));
+            } else {
+                log.info("Device {} is already connected to ONOS and is available", deviceId);
+            }
+        }
+
+        @Override
+        public boolean isRelevant(NetworkConfigEvent event) {
+            return event.configClass().equals(GeneralProviderDeviceConfig.class) &&
+                    (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
+                            event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
+        }
+    }
+
+    /**
+     * Listener for core device events.
+     */
+    private class InternalDeviceListener implements DeviceListener {
+        @Override
+        public void event(DeviceEvent event) {
+            Type type = event.type();
+
+            if (type.equals((Type.DEVICE_ADDED))) {
+
+                //For now this is scheduled periodically, when streaming API will
+                // be available we check and base it on the streaming API (e.g. gNMI)
+                if (deviceService.getDevice(event.subject().id()).
+                        is(PortStatisticsDiscovery.class)) {
+                    portStatsExecutor.scheduleAtFixedRate(exceptionSafe(() ->
+                                    updatePortStatistics(event.subject().id())),
+                            0, PORT_STATS_PERIOD_SECONDS, TimeUnit.SECONDS);
+                    updatePortStatistics(event.subject().id());
+                }
+
+            } else if (type.equals(Type.DEVICE_REMOVED)) {
+                connectionExecutor.submit(exceptionSafe(() ->
+                        disconnectDevice(event.subject().id())));
+            }
+        }
+
+        @Override
+        public boolean isRelevant(DeviceEvent event) {
+            return URI_SCHEME.toUpperCase()
+                    .equals(event.subject().id().uri().toString());
+        }
+    }
+}
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/package-info.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/package-info.java
new file mode 100644
index 0000000..aa4b93db
--- /dev/null
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/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.
+ */
+
+/**
+ * Provider that uses drivers as a means of infrastructure device discovery.
+ */
+package org.onosproject.provider.general.device.impl;
\ No newline at end of file
diff --git a/providers/general/device/src/test/resources/device.json b/providers/general/device/src/test/resources/device.json
new file mode 100644
index 0000000..f11a264
--- /dev/null
+++ b/providers/general/device/src/test/resources/device.json
@@ -0,0 +1,6 @@
+{
+  "ip":"1.1.1.1",
+  "port":830,
+  "username":"test",
+  "password":"test"
+}
diff --git a/providers/general/device/src/test/resources/deviceSshKey.json b/providers/general/device/src/test/resources/deviceSshKey.json
new file mode 100644
index 0000000..c799935
--- /dev/null
+++ b/providers/general/device/src/test/resources/deviceSshKey.json
@@ -0,0 +1,7 @@
+{
+  "ip":"1.1.1.1",
+  "port":830,
+  "username":"test",
+  "password":"test",
+  "sshkey":"test"
+}
diff --git a/providers/general/pom.xml b/providers/general/pom.xml
new file mode 100644
index 0000000..f09a78c
--- /dev/null
+++ b/providers/general/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<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/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.onosproject</groupId>
+        <artifactId>onos-providers</artifactId>
+        <version>1.11.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>onos-general-providers</artifactId>
+    <packaging>pom</packaging>
+
+    <description>ONOS general device provider</description>
+
+    <modules>
+        <module>device</module>
+        <module>app</module>
+    </modules>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-api</artifactId>
+            <classifier>tests</classifier>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/providers/pom.xml b/providers/pom.xml
index ea91290..27f10a4 100644
--- a/providers/pom.xml
+++ b/providers/pom.xml
@@ -53,6 +53,7 @@
         <module>ietfte</module>
         -->
         <module>tl1</module>
+        <module>general</module>
     </modules>
 
     <dependencies>
diff --git a/tools/test/configs/general-provider-cfg.json b/tools/test/configs/general-provider-cfg.json
new file mode 100644
index 0000000..7c4f147
--- /dev/null
+++ b/tools/test/configs/general-provider-cfg.json
@@ -0,0 +1,38 @@
+{
+  "devices": {
+    "device:identifier": {
+      "generalprovider": {
+        "p4runtime": {
+          "ip": "192.168.56.104",
+          "port": 830,
+          "deviceKeyId": "p4runtime:device:identifier"
+        },
+        "gnmi": {
+          "ip": "192.168.56.105",
+          "port": 830,
+          "deviceKeyId": "p4runtime:device:identifier"
+        }
+      },
+      "basic": {
+        "driver": "bmv2"
+      }
+    },
+    "device:identifier2": {
+      "generalprovider": {
+        "p4runtime": {
+          "ip": "192.168.56.106",
+          "port": 830,
+          "deviceKeyId": "p4runtime:device:identifier2"
+        },
+        "gnmi": {
+          "ip": "192.168.56.107",
+          "port": 830,
+          "deviceKeyId": "p4runtime:device:identifier2"
+        }
+      },
+      "basic": {
+        "driver": "bmv2"
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/tools/test/configs/rest-key.json b/tools/test/configs/rest-key.json
new file mode 100644
index 0000000..edac5a3
--- /dev/null
+++ b/tools/test/configs/rest-key.json
@@ -0,0 +1,6 @@
+{
+  "id": "p4runtime:device:identifier",
+  "type": "USERNAME_PASSWORD",
+  "username": "test_username",
+  "password": "test_password"
+}