[ONOS-6933] Support packet request for different device scheme

Change-Id: If9658838c35b4d425f414c6d5c275c364e15e1a6
diff --git a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
index 919010a..8197c90 100644
--- a/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
+++ b/core/api/src/main/java/org/onosproject/net/driver/DefaultDriver.java
@@ -89,7 +89,13 @@
 
         // Merge the properties.
         ImmutableMap.Builder<String, String> properties = ImmutableMap.builder();
-        properties.putAll(this.properties).putAll(other.properties());
+        properties.putAll(other.properties());
+
+        // remove duplicated properties from this driver and merge
+        this.properties().entrySet().stream()
+                .filter(e -> !other.properties().containsKey(e.getKey()))
+                .forEach(properties::put);
+
         List<Driver> completeParents = new ArrayList<>();
 
         if (parents != null) {
diff --git a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
index 490e0d5..ec783f0 100644
--- a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
+++ b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
@@ -16,7 +16,6 @@
 package org.onosproject.net.packet.impl;
 
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
@@ -33,6 +32,8 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverService;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.TrafficTreatment;
@@ -62,7 +63,6 @@
 
 import java.util.List;
 import java.util.Optional;
-import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -89,6 +89,7 @@
     private static final String ERROR_NULL_SELECTOR = "Selector cannot be null";
     private static final String ERROR_NULL_APP_ID = "Application ID cannot be null";
     private static final String ERROR_NULL_DEVICE_ID = "Device ID cannot be null";
+    private static final String SUPPORT_PACKET_REQUEST_PROPERTY = "supportPacketRequest";
 
     private final PacketStoreDelegate delegate = new InternalStoreDelegate();
 
@@ -102,6 +103,9 @@
     protected DeviceService deviceService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected DriverService driverService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected PacketStore store;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -259,11 +263,6 @@
     }
 
     /**
-     * Set of DeviceId scheme which supports packet requests.
-     */
-    private static final Set<String> SUPPORTED = ImmutableSet.of("of");
-
-    /**
      * Pushes a packet request flow rule to all devices.
      *
      * @param request the packet request
@@ -271,8 +270,9 @@
     private void pushToAllDevices(PacketRequest request) {
         log.debug("Pushing packet request {} to all devices", request);
         for (Device device : deviceService.getDevices()) {
-            // TODO properly test capability via driver, defining behaviour
-            if (SUPPORTED.contains(device.id().uri().getScheme())) {
+            Driver driver = driverService.getDriver(device.id());
+            if (driver != null &&
+                    Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
                 pushRule(device, request);
             }
         }
@@ -446,12 +446,20 @@
             eventHandlingExecutor.execute(() -> {
                 try {
                     Device device = event.subject();
+                    Driver driver = driverService.getDriver(device.id());
+                    if (driver == null) {
+                        return;
+                    }
+                    if (!Boolean.parseBoolean(driver.getProperty(SUPPORT_PACKET_REQUEST_PROPERTY))) {
+                        return;
+                    }
+                    if (!deviceService.isAvailable(event.subject().id())) {
+                        return;
+                    }
                     switch (event.type()) {
                         case DEVICE_ADDED:
                         case DEVICE_AVAILABILITY_CHANGED:
-                            if (deviceService.isAvailable(event.subject().id())) {
-                                pushRulesToDevice(device);
-                            }
+                            pushRulesToDevice(device);
                             break;
                         default:
                             break;
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index 2f646d5..4fce46f 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -21,6 +21,7 @@
                    impl="org.onosproject.driver.pipeline.DefaultSingleTablePipeline"/>
         <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
                    impl="org.onosproject.driver.handshaker.DefaultSwitchHandshaker"/>
+        <property name="supportPacketRequest">true</property>
     </driver>
     <driver name="ovs" extends="default"
             manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
diff --git a/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml b/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml
index 9457cac..3f00bde 100644
--- a/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml
+++ b/drivers/p4runtime/src/main/resources/p4runtime-drivers.xml
@@ -24,6 +24,7 @@
                    impl="org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable"/>
         <behaviour api="org.onosproject.net.group.GroupProgrammable"
                    impl="org.onosproject.drivers.p4runtime.P4RuntimeGroupProgrammable"/>
+        <property name="supportPacketRequest">true</property>
     </driver>
 </drivers>