Allow sharing the same gRPC channel between clients
This change introduces a refactoring of the gRPC protocol subsystem that
allows the creation of a gRPC chanel independently of the client, while
allowing multiple clients to share the same channel (e.g. as in Stratum
where we use 3 clients).
Moreover, we refactor the P4RuntimeClient API to support multiple
P4Runtime-internal device ID using the same client. While before the
client was associated to one of such ID.
Finally, we provide an abstract implementation for gRPC-based driver
behaviors, reducing code duplication in P4Runtime, gNMI and gNOI drivers.
Change-Id: I1a46352bbbef1e0d24042f169ae8ba580202944f
diff --git a/drivers/gnmi/BUILD b/drivers/gnmi/BUILD
index efc3f08..f01a9f3 100644
--- a/drivers/gnmi/BUILD
+++ b/drivers/gnmi/BUILD
@@ -7,7 +7,7 @@
"//protocols/gnmi/stub:onos-protocols-gnmi-stub",
"//protocols/gnmi/api:onos-protocols-gnmi-api",
"//protocols/grpc/api:onos-protocols-grpc-api",
- "//protocols/grpc/proto:onos-protocols-grpc-proto",
+ "//protocols/grpc/utils:onos-protocols-grpc-utils",
]
BUNDLES = [
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/AbstractGnmiHandlerBehaviour.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/AbstractGnmiHandlerBehaviour.java
deleted file mode 100644
index 72233fc..0000000
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/AbstractGnmiHandlerBehaviour.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2018-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.drivers.gnmi;
-
-import com.google.common.base.Strings;
-import org.onosproject.gnmi.api.GnmiClient;
-import org.onosproject.gnmi.api.GnmiClientKey;
-import org.onosproject.gnmi.api.GnmiController;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * Abstract implementation of a behaviour handler for a gNMI device.
- */
-public class AbstractGnmiHandlerBehaviour extends AbstractHandlerBehaviour {
-
- protected final Logger log = LoggerFactory.getLogger(getClass());
- protected DeviceId deviceId;
- protected DeviceService deviceService;
- protected GnmiClient client;
-
- protected boolean setupBehaviour(String opName) {
- deviceId = handler().data().deviceId();
- deviceService = handler().get(DeviceService.class);
- client = getClientByKey();
- if (client == null) {
- log.warn("Missing client for {}, aborting {}", deviceId, opName);
- return false;
- }
-
- return true;
- }
-
- GnmiClient getClientByKey() {
- final GnmiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return null;
- }
- return handler().get(GnmiController.class).getClient(clientKey);
- }
-
- protected GnmiClientKey clientKey() {
- deviceId = handler().data().deviceId();
-
- final BasicDeviceConfig cfg = handler().get(NetworkConfigService.class)
- .getConfig(deviceId, BasicDeviceConfig.class);
- if (cfg == null || Strings.isNullOrEmpty(cfg.managementAddress())) {
- log.error("Missing or invalid config for {}, cannot derive " +
- "gNMI server endpoints", deviceId);
- return null;
- }
-
- try {
- return new GnmiClientKey(
- deviceId, new URI(cfg.managementAddress()));
- } catch (URISyntaxException e) {
- log.error("Management address of {} is not a valid URI: {}",
- deviceId, cfg.managementAddress());
- return null;
- }
- }
-}
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiHandshaker.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiHandshaker.java
index a6d0c04..82fc40c 100644
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiHandshaker.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiHandshaker.java
@@ -17,33 +17,23 @@
package org.onosproject.drivers.gnmi;
import org.onosproject.gnmi.api.GnmiClient;
-import org.onosproject.gnmi.api.GnmiClientKey;
import org.onosproject.gnmi.api.GnmiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandshaker;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceHandshaker;
import java.util.concurrent.CompletableFuture;
-import static java.util.concurrent.CompletableFuture.completedFuture;
-
/**
* Implementation of DeviceHandshaker for gNMI.
*/
-public class GnmiHandshaker extends AbstractGnmiHandlerBehaviour implements DeviceHandshaker {
+public class GnmiHandshaker
+ extends AbstractGrpcHandshaker<GnmiClient, GnmiController>
+ implements DeviceHandshaker {
- @Override
- public boolean isReachable() {
- final GnmiClient client = getClientByKey();
- return client != null && client.isServerReachable();
- }
- @Override
- public CompletableFuture<Boolean> probeReachability() {
- final GnmiClient client = getClientByKey();
- if (client == null) {
- return completedFuture(false);
- }
- return client.probeService();
+ public GnmiHandshaker() {
+ super(GnmiController.class);
}
@Override
@@ -65,33 +55,4 @@
public MastershipRole getRole() {
throw new UnsupportedOperationException("Mastership operation not supported");
}
-
- @Override
- public CompletableFuture<Boolean> connect() {
- return CompletableFuture.supplyAsync(this::createClient);
- }
-
- private boolean createClient() {
- GnmiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return false;
- }
- if (!handler().get(GnmiController.class).createClient(clientKey)) {
- log.warn("Unable to create client for {}",
- handler().data().deviceId());
- return false;
- }
- return true;
- }
-
- @Override
- public boolean isConnected() {
- return getClientByKey() != null;
- }
-
- @Override
- public void disconnect() {
- handler().get(GnmiController.class)
- .removeClient(handler().data().deviceId());
- }
}
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiDeviceDescriptionDiscovery.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiDeviceDescriptionDiscovery.java
index a85cdfb..210a237 100644
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiDeviceDescriptionDiscovery.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiDeviceDescriptionDiscovery.java
@@ -23,6 +23,9 @@
import gnmi.Gnmi.GetRequest;
import gnmi.Gnmi.GetResponse;
import org.onlab.packet.ChassisId;
+import org.onosproject.gnmi.api.GnmiClient;
+import org.onosproject.gnmi.api.GnmiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
@@ -48,7 +51,7 @@
* supports the gNMI protocol and Openconfig models.
*/
public class OpenConfigGnmiDeviceDescriptionDiscovery
- extends AbstractGnmiHandlerBehaviour
+ extends AbstractGrpcHandlerBehaviour<GnmiClient, GnmiController>
implements DeviceDescriptionDiscovery {
private static final Logger log = LoggerFactory
@@ -58,6 +61,10 @@
private static final String UNKNOWN = "unknown";
+ public OpenConfigGnmiDeviceDescriptionDiscovery() {
+ super(GnmiController.class);
+ }
+
@Override
public DeviceDescription discoverDeviceDetails() {
return new DefaultDeviceDescription(
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortAdminBehaviour.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortAdminBehaviour.java
index 4f050b0..666d5b1 100644
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortAdminBehaviour.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortAdminBehaviour.java
@@ -18,6 +18,8 @@
import gnmi.Gnmi;
import org.onosproject.gnmi.api.GnmiClient;
+import org.onosproject.gnmi.api.GnmiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.PortAdmin;
@@ -29,11 +31,18 @@
* Implementation of PortAdmin for gNMI devices with OpenConfig support.
*/
public class OpenConfigGnmiPortAdminBehaviour
- extends AbstractGnmiHandlerBehaviour
+ extends AbstractGrpcHandlerBehaviour<GnmiClient, GnmiController>
implements PortAdmin {
+ public OpenConfigGnmiPortAdminBehaviour() {
+ super(GnmiController.class);
+ }
+
@Override
public CompletableFuture<Boolean> enable(PortNumber number) {
+ if (!setupBehaviour("enable()")) {
+ return completedFuture(false);
+ }
doEnable(number, true);
// Always returning true is OK assuming this is used only by the
// GeneralDeviceProvider, which ignores the return value and instead
@@ -43,6 +52,9 @@
@Override
public CompletableFuture<Boolean> disable(PortNumber number) {
+ if (!setupBehaviour("disable()")) {
+ return completedFuture(false);
+ }
doEnable(number, false);
return completedFuture(true);
}
@@ -58,11 +70,6 @@
portNumber, deviceId);
return;
}
- final GnmiClient client = getClientByKey();
- if (client == null) {
- log.warn("Cannot update ports on {}, missing gNMI client", deviceId);
- return;
- }
final Gnmi.Path path = Gnmi.Path.newBuilder()
.addElem(Gnmi.PathElem.newBuilder().setName("interfaces").build())
.addElem(Gnmi.PathElem.newBuilder().setName("interface")
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
index fa7231f..6e361ff 100644
--- a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/OpenConfigGnmiPortStatisticsDiscovery.java
@@ -23,6 +23,9 @@
import gnmi.Gnmi.GetResponse;
import gnmi.Gnmi.Path;
import org.apache.commons.lang3.tuple.Pair;
+import org.onosproject.gnmi.api.GnmiClient;
+import org.onosproject.gnmi.api.GnmiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
@@ -41,13 +44,18 @@
/**
* Behaviour to get port statistics from device via gNMI.
*/
-public class OpenConfigGnmiPortStatisticsDiscovery extends AbstractGnmiHandlerBehaviour
+public class OpenConfigGnmiPortStatisticsDiscovery
+ extends AbstractGrpcHandlerBehaviour<GnmiClient, GnmiController>
implements PortStatisticsDiscovery {
private static final Map<Pair<DeviceId, PortNumber>, Long> PORT_START_TIMES =
Maps.newConcurrentMap();
private static final String LAST_CHANGE = "last-changed";
+ public OpenConfigGnmiPortStatisticsDiscovery() {
+ super(GnmiController.class);
+ }
+
@Override
public Collection<PortStatistics> discoverPortStatistics() {
if (!setupBehaviour("discoverPortStatistics()")) {
diff --git a/drivers/gnoi/BUILD b/drivers/gnoi/BUILD
index 3a710a8..b5355a9 100644
--- a/drivers/gnoi/BUILD
+++ b/drivers/gnoi/BUILD
@@ -6,6 +6,7 @@
"//protocols/gnoi/stub:onos-protocols-gnoi-stub",
"//protocols/gnoi/api:onos-protocols-gnoi-api",
"//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/grpc/utils:onos-protocols-grpc-utils",
]
BUNDLES = [
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java
deleted file mode 100644
index 84043a8..0000000
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/AbstractGnoiHandlerBehaviour.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2019-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.drivers.gnoi;
-
-import com.google.common.base.Strings;
-import org.onosproject.gnoi.api.GnoiClient;
-import org.onosproject.gnoi.api.GnoiClientKey;
-import org.onosproject.gnoi.api.GnoiController;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-
-/**
- * Abstract implementation of a behaviour handler for a gNOI device.
- */
-public class AbstractGnoiHandlerBehaviour extends AbstractHandlerBehaviour {
-
- protected final Logger log = LoggerFactory.getLogger(getClass());
- protected DeviceId deviceId;
- protected GnoiClient client;
-
- protected boolean setupBehaviour(String opName) {
- deviceId = handler().data().deviceId();
- client = getClientByKey();
-
- if (client == null) {
- log.warn("Missing client for {}, aborting {}", deviceId, opName);
- return false;
- }
-
- return true;
- }
-
- GnoiClient getClientByKey() {
- final GnoiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return null;
- }
- return handler().get(GnoiController.class).getClient(clientKey);
- }
-
- protected GnoiClientKey clientKey() {
- deviceId = handler().data().deviceId();
-
- final BasicDeviceConfig cfg = handler().get(NetworkConfigService.class)
- .getConfig(deviceId, BasicDeviceConfig.class);
- if (cfg == null || Strings.isNullOrEmpty(cfg.managementAddress())) {
- log.error("Missing or invalid config for {}, cannot derive " +
- "gNOI server endpoints", deviceId);
- return null;
- }
-
- try {
- return new GnoiClientKey(
- deviceId, new URI(cfg.managementAddress()));
- } catch (URISyntaxException e) {
- log.error("Management address of {} is not a valid URI: {}",
- deviceId, cfg.managementAddress());
- return null;
- }
- }
-}
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
index b979546..7876886 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiBasicSystemOperationsImpl.java
@@ -19,9 +19,10 @@
import gnoi.system.SystemOuterClass.RebootMethod;
import gnoi.system.SystemOuterClass.RebootRequest;
import gnoi.system.SystemOuterClass.RebootResponse;
+import org.onosproject.gnoi.api.GnoiClient;
+import org.onosproject.gnoi.api.GnoiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.behaviour.BasicSystemOperations;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.concurrent.CompletableFuture;
@@ -30,10 +31,12 @@
* devices.
*/
public class GnoiBasicSystemOperationsImpl
- extends AbstractGnoiHandlerBehaviour implements BasicSystemOperations {
+ extends AbstractGrpcHandlerBehaviour<GnoiClient, GnoiController>
+ implements BasicSystemOperations {
- private static final Logger log = LoggerFactory
- .getLogger(GnoiBasicSystemOperationsImpl.class);
+ public GnoiBasicSystemOperationsImpl() {
+ super(GnoiController.class);
+ }
@Override
public CompletableFuture<Boolean> reboot() {
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
index 3c308d6..2010c53 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiDeviceDescriptionDiscovery.java
@@ -24,6 +24,7 @@
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.PortDescription;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
import java.util.Collections;
import java.util.List;
@@ -32,7 +33,8 @@
* Implementation of DeviceDescriptionDiscovery for gNOI devices.
*/
public class GnoiDeviceDescriptionDiscovery
- extends AbstractGnoiHandlerBehaviour implements DeviceDescriptionDiscovery {
+ extends AbstractHandlerBehaviour
+ implements DeviceDescriptionDiscovery {
private static final String UNKNOWN = "unknown";
diff --git a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
index 36a4971..1668bcc 100644
--- a/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
+++ b/drivers/gnoi/src/main/java/org/onosproject/drivers/gnoi/GnoiHandshaker.java
@@ -17,33 +17,22 @@
package org.onosproject.drivers.gnoi;
import org.onosproject.gnoi.api.GnoiClient;
-import org.onosproject.gnoi.api.GnoiClientKey;
import org.onosproject.gnoi.api.GnoiController;
+import org.onosproject.grpc.utils.AbstractGrpcHandshaker;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceHandshaker;
import java.util.concurrent.CompletableFuture;
-import static java.util.concurrent.CompletableFuture.completedFuture;
-
/**
* Implementation of DeviceHandshaker for gNOI.
*/
-public class GnoiHandshaker extends AbstractGnoiHandlerBehaviour implements DeviceHandshaker {
+public class GnoiHandshaker
+ extends AbstractGrpcHandshaker<GnoiClient, GnoiController>
+ implements DeviceHandshaker {
- @Override
- public boolean isReachable() {
- final GnoiClient client = getClientByKey();
- return client != null && client.isServerReachable();
- }
-
- @Override
- public CompletableFuture<Boolean> probeReachability() {
- final GnoiClient client = getClientByKey();
- if (client == null) {
- return completedFuture(false);
- }
- return client.probeService();
+ public GnoiHandshaker() {
+ super(GnoiController.class);
}
@Override
@@ -65,33 +54,4 @@
public MastershipRole getRole() {
throw new UnsupportedOperationException("Mastership operation not supported");
}
-
- @Override
- public CompletableFuture<Boolean> connect() {
- return CompletableFuture.supplyAsync(this::createClient);
- }
-
- private boolean createClient() {
- GnoiClientKey clientKey = clientKey();
- if (clientKey == null) {
- return false;
- }
- if (!handler().get(GnoiController.class).createClient(clientKey)) {
- log.warn("Unable to create client for {}",
- handler().data().deviceId());
- return false;
- }
- return true;
- }
-
- @Override
- public boolean isConnected() {
- return getClientByKey() != null;
- }
-
- @Override
- public void disconnect() {
- handler().get(GnoiController.class)
- .removeClient(handler().data().deviceId());
- }
}
diff --git a/drivers/p4runtime/BUILD b/drivers/p4runtime/BUILD
index 7f917cd..f97dbd7 100644
--- a/drivers/p4runtime/BUILD
+++ b/drivers/p4runtime/BUILD
@@ -1,5 +1,7 @@
COMPILE_DEPS = CORE_DEPS + KRYO + [
"//core/store/serializers:onos-core-serializers",
+ "//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/grpc/utils:onos-protocols-grpc-utils",
"//protocols/p4runtime/api:onos-protocols-p4runtime-api",
"@io_grpc_grpc_java//core",
]
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimeHandlerBehaviour.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimeHandlerBehaviour.java
index c71907b..7bbc00b 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimeHandlerBehaviour.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimeHandlerBehaviour.java
@@ -16,40 +16,31 @@
package org.onosproject.drivers.p4runtime;
-import com.google.common.base.Strings;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.config.basics.BasicDeviceConfig;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.grpc.utils.AbstractGrpcHandlerBehaviour;
import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.service.PiPipeconfService;
import org.onosproject.net.pi.service.PiTranslationService;
import org.onosproject.p4runtime.api.P4RuntimeClient;
-import org.onosproject.p4runtime.api.P4RuntimeClientKey;
import org.onosproject.p4runtime.api.P4RuntimeController;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.net.URI;
-import java.net.URISyntaxException;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.extractP4DeviceId;
/**
* Abstract implementation of a behaviour handler for a P4Runtime device.
*/
-public class AbstractP4RuntimeHandlerBehaviour extends AbstractHandlerBehaviour {
-
- protected final Logger log = LoggerFactory.getLogger(getClass());
+public abstract class AbstractP4RuntimeHandlerBehaviour
+ extends AbstractGrpcHandlerBehaviour<P4RuntimeClient, P4RuntimeController> {
// Initialized by setupBehaviour()
- protected DeviceId deviceId;
+ protected Long p4DeviceId;
protected PiPipeconf pipeconf;
- protected P4RuntimeClient client;
- protected PiTranslationService translationService;
+ PiTranslationService translationService;
+
+
+ AbstractP4RuntimeHandlerBehaviour() {
+ super(P4RuntimeController.class);
+ }
/**
* Initializes this behaviour attributes. Returns true if the operation was
@@ -59,20 +50,25 @@
* @return true if successful, false otherwise
*/
protected boolean setupBehaviour(String opName) {
- deviceId = handler().data().deviceId();
-
- client = getClientByKey();
- if (client == null) {
- log.warn("Missing client for {}, aborting {}", deviceId, opName);
+ if (!super.setupBehaviour(opName)) {
return false;
}
- PiPipeconfService piPipeconfService = handler().get(PiPipeconfService.class);
- if (!piPipeconfService.getPipeconf(deviceId).isPresent()) {
+ p4DeviceId = extractP4DeviceId(mgmtUriFromNetcfg());
+ if (p4DeviceId == null) {
+ log.warn("Unable to obtain P4Runtime-internal device_id from " +
+ "config of {}, cannot perform {}",
+ deviceId, opName);
+ return false;
+ }
+
+ final PiPipeconfService pipeconfService = handler().get(
+ PiPipeconfService.class);
+ if (!pipeconfService.getPipeconf(deviceId).isPresent()) {
log.warn("Missing pipeconf for {}, cannot perform {}", deviceId, opName);
return false;
}
- pipeconf = piPipeconfService.getPipeconf(deviceId).get();
+ pipeconf = pipeconfService.getPipeconf(deviceId).get();
translationService = handler().get(PiTranslationService.class);
@@ -80,61 +76,6 @@
}
/**
- * Returns an instance of the interpreter implementation for this device,
- * null if an interpreter cannot be retrieved.
- *
- * @return interpreter or null
- */
- PiPipelineInterpreter getInterpreter() {
- final Device device = handler().get(DeviceService.class).getDevice(deviceId);
- if (device == null) {
- log.warn("Unable to find device {}, cannot get interpreter", deviceId);
- return null;
- }
- if (!device.is(PiPipelineInterpreter.class)) {
- log.warn("Unable to get interpreter for {}, missing behaviour",
- deviceId);
- return null;
- }
- return device.as(PiPipelineInterpreter.class);
- }
-
- /**
- * Returns a P4Runtime client previsouly created for this device, null if
- * such client does not exist.
- *
- * @return client or null
- */
- P4RuntimeClient getClientByKey() {
- final P4RuntimeClientKey clientKey = clientKey();
- if (clientKey == null) {
- return null;
- }
- return handler().get(P4RuntimeController.class).getClient(clientKey);
- }
-
- protected P4RuntimeClientKey clientKey() {
- deviceId = handler().data().deviceId();
-
- final BasicDeviceConfig cfg = handler().get(NetworkConfigService.class)
- .getConfig(deviceId, BasicDeviceConfig.class);
- if (cfg == null || Strings.isNullOrEmpty(cfg.managementAddress())) {
- log.error("Missing or invalid config for {}, cannot derive " +
- "P4Runtime server endpoints", deviceId);
- return null;
- }
-
- try {
- return new P4RuntimeClientKey(
- deviceId, new URI(cfg.managementAddress()));
- } catch (URISyntaxException e) {
- log.error("Management address of {} is not a valid URI: {}",
- deviceId, cfg.managementAddress());
- return null;
- }
- }
-
- /**
* Returns the value of the given driver property, if present, otherwise
* returns the given default value.
*
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimePipelineProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimePipelineProgrammable.java
index 916a945..9b700ca 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimePipelineProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/AbstractP4RuntimePipelineProgrammable.java
@@ -16,11 +16,8 @@
package org.onosproject.drivers.p4runtime;
-import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.PiPipelineProgrammable;
import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.p4runtime.api.P4RuntimeClient;
-import org.onosproject.p4runtime.api.P4RuntimeController;
import org.slf4j.Logger;
import java.nio.ByteBuffer;
@@ -49,42 +46,32 @@
@Override
public CompletableFuture<Boolean> setPipeconf(PiPipeconf pipeconf) {
- DeviceId deviceId = handler().data().deviceId();
- P4RuntimeController controller = handler().get(P4RuntimeController.class);
-
- P4RuntimeClient client = controller.getClient(deviceId);
- if (client == null) {
- log.warn("Unable to find client for {}, aborting pipeconf deploy", deviceId);
+ if (!setupBehaviour("setPipeconf()")) {
return completedFuture(false);
}
- ByteBuffer deviceDataBuffer = createDeviceDataBuffer(pipeconf);
+ final ByteBuffer deviceDataBuffer = createDeviceDataBuffer(pipeconf);
if (deviceDataBuffer == null) {
// Hopefully the child class logged the problem.
return completedFuture(false);
}
- return client.setPipelineConfig(pipeconf, deviceDataBuffer);
+ return client.setPipelineConfig(p4DeviceId, pipeconf, deviceDataBuffer);
}
@Override
public CompletableFuture<Boolean> isPipeconfSet(PiPipeconf pipeconf) {
- DeviceId deviceId = handler().data().deviceId();
- P4RuntimeController controller = handler().get(P4RuntimeController.class);
-
- P4RuntimeClient client = controller.getClient(deviceId);
- if (client == null) {
- log.warn("Unable to find client for {}, cannot check if pipeconf is set", deviceId);
+ if (!setupBehaviour("isPipeconfSet()")) {
return completedFuture(false);
}
- ByteBuffer deviceDataBuffer = createDeviceDataBuffer(pipeconf);
+ final ByteBuffer deviceDataBuffer = createDeviceDataBuffer(pipeconf);
if (deviceDataBuffer == null) {
// Hopefully the child class logged the problem.
return completedFuture(false);
}
- return client.isPipelineConfigSet(pipeconf, deviceDataBuffer);
+ return client.isPipelineConfigSet(p4DeviceId, pipeconf, deviceDataBuffer);
}
@Override
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
index d14b917..612394f 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeActionGroupProgrammable.java
@@ -131,7 +131,8 @@
}
// Dump groups and members from device for all action profiles.
- final P4RuntimeReadClient.ReadRequest request = client.read(pipeconf);
+ final P4RuntimeReadClient.ReadRequest request = client.read(
+ p4DeviceId, pipeconf);
pipeconf.pipelineModel().actionProfiles()
.stream().map(PiActionProfileModel::id)
.forEach(id -> request.actionProfileGroups(id)
@@ -184,7 +185,7 @@
log.warn("Cleaning up {} action profile groups and " +
"{} members on {}...",
groupHandlesToRemove.size(), memberHandlesToRemove.size(), deviceId);
- client.write(pipeconf)
+ client.write(p4DeviceId, pipeconf)
.delete(groupHandlesToRemove)
.delete(memberHandlesToRemove)
.submit().whenComplete((r, ex) -> {
@@ -244,7 +245,8 @@
// found on the device.
if (!validateGroupMembers(piGroupFromStore, membersOnDevice)) {
log.warn("Group on device {} refers to members that are different " +
- "than those found in translation store: {}", handle);
+ "than those found in translation store: {}",
+ deviceId, handle);
return null;
}
if (mirrorEntry == null) {
@@ -308,7 +310,7 @@
if (members == null) {
return;
}
- final WriteRequest request = client.write(pipeconf);
+ final WriteRequest request = client.write(p4DeviceId, pipeconf);
WRITE_LOCKS.get(deviceId).lock();
try {
if (operation == Operation.APPLY) {
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDeviceDescriptionDiscovery.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDeviceDescriptionDiscovery.java
index 337ce6a..4b3dba9 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDeviceDescriptionDiscovery.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDeviceDescriptionDiscovery.java
@@ -24,21 +24,25 @@
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceDescriptionDiscovery;
import org.onosproject.net.device.PortDescription;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
import java.util.Collections;
import java.util.List;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.extractP4DeviceId;
+
/**
* Implementation of DeviceDescriptionDiscovery for P4Runtime devices.
*/
public class P4RuntimeDeviceDescriptionDiscovery
- extends AbstractHandlerBehaviour implements DeviceDescriptionDiscovery {
+ extends AbstractP4RuntimeHandlerBehaviour
+ implements DeviceDescriptionDiscovery {
private static final String UNKNOWN = "unknown";
+ private static final String P4_DEVICE_ID = "p4DeviceId";
@Override
public DeviceDescription discoverDeviceDetails() {
+ final Long p4DeviceId = extractP4DeviceId(mgmtUriFromNetcfg());
return new DefaultDeviceDescription(
data().deviceId().uri(),
Device.Type.SWITCH,
@@ -49,6 +53,8 @@
new ChassisId(),
false,
DefaultAnnotations.builder()
+ .set(P4_DEVICE_ID, p4DeviceId == null
+ ? UNKNOWN : String.valueOf(p4DeviceId))
.set(AnnotationKeys.PROTOCOL, "P4Runtime")
.build());
}
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverUtils.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverUtils.java
new file mode 100644
index 0000000..73eed40
--- /dev/null
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverUtils.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019-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.drivers.p4runtime;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.pi.model.PiPipelineInterpreter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URLDecoder;
+
+/**
+ * Utility class for the P4Runtime driver.
+ */
+final class P4RuntimeDriverUtils {
+
+ private static final String DEVICE_ID_PARAM = "device_id=";
+
+ private static final Logger log = LoggerFactory.getLogger(P4RuntimeDriverUtils.class);
+
+ private P4RuntimeDriverUtils() {
+ // Hide constructor.
+ }
+
+ /**
+ * Returns an instance of the interpreter implementation for this device,
+ * null if an interpreter cannot be retrieved.
+ *
+ * @param handler driver handler
+ * @return interpreter or null
+ */
+ static PiPipelineInterpreter getInterpreter(DriverHandler handler) {
+ final DeviceId deviceId = handler.data().deviceId();
+ final Device device = handler.get(DeviceService.class).getDevice(deviceId);
+ if (device == null) {
+ log.warn("Unable to find device {}, cannot get interpreter", deviceId);
+ return null;
+ }
+ if (!device.is(PiPipelineInterpreter.class)) {
+ log.warn("Unable to get interpreter for {}, missing behaviour",
+ deviceId);
+ return null;
+ }
+ return device.as(PiPipelineInterpreter.class);
+ }
+
+ static Long extractP4DeviceId(URI uri) {
+ if (uri == null) {
+ return null;
+ }
+ String[] segments = uri.getRawQuery().split("&");
+ try {
+ for (String s : segments) {
+ if (s.startsWith(DEVICE_ID_PARAM)) {
+ return Long.parseUnsignedLong(
+ URLDecoder.decode(
+ s.substring(DEVICE_ID_PARAM.length()), "utf-8"));
+ }
+ }
+ } catch (UnsupportedEncodingException e) {
+ log.error("Unable to decode P4Runtime-internal device_id from URI {}: {}",
+ uri, e.toString());
+ } catch (NumberFormatException e) {
+ log.error("Invalid P4Runtime-internal device_id in URI {}: {}",
+ uri, e.toString());
+ }
+ log.error("Missing P4Runtime-internal device_id in URI {}", uri);
+ return null;
+ }
+}
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
index d55dd71..7432d2d 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
@@ -58,6 +58,7 @@
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.getInterpreter;
import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.APPLY;
import static org.onosproject.drivers.p4runtime.P4RuntimeFlowRuleProgrammable.Operation.REMOVE;
import static org.onosproject.net.flow.FlowEntry.FlowEntryState.ADDED;
@@ -175,7 +176,7 @@
log.warn("Found {} inconsistent table entries on {}, removing them...",
inconsistentEntries.size(), deviceId);
// Submit delete request and update mirror when done.
- client.write(pipeconf)
+ client.write(p4DeviceId, pipeconf)
.entities(inconsistentEntries, DELETE)
.submit().whenComplete((response, ex) -> {
if (ex != null) {
@@ -193,7 +194,8 @@
}
private Collection<PiTableEntry> getAllTableEntriesFromDevice() {
- final P4RuntimeReadClient.ReadRequest request = client.read(pipeconf);
+ final P4RuntimeReadClient.ReadRequest request = client.read(
+ p4DeviceId, pipeconf);
// Read entries from all non-constant tables, including default ones.
pipelineModel.tables().stream()
.filter(t -> !t.isConstantTable())
@@ -274,7 +276,7 @@
return Collections.emptyList();
}
// Created batched write request.
- final WriteRequest request = client.write(pipeconf);
+ final WriteRequest request = client.write(p4DeviceId, pipeconf);
// For each rule, translate to PI and append to write request.
final Map<PiHandle, FlowRule> handleToRuleMap = Maps.newHashMap();
final List<FlowRule> skippedRules = Lists.newArrayList();
@@ -433,7 +435,7 @@
}
private PiTableEntry getOriginalDefaultEntry(PiTableId tableId) {
- final PiPipelineInterpreter interpreter = getInterpreter();
+ final PiPipelineInterpreter interpreter = getInterpreter(handler());
if (interpreter == null) {
log.warn("Missing interpreter for {}, cannot get default action",
deviceId);
@@ -483,7 +485,7 @@
.map(id -> PiCounterCellHandle.of(deviceId, id))
.collect(Collectors.toSet());
// FIXME: We might be sending a very large read request...
- return client.read(pipeconf)
+ return client.read(p4DeviceId, pipeconf)
.handles(cellHandles)
.submitSync()
.all(PiCounterCell.class).stream()
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
index 64611fe..e689298 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeHandshaker.java
@@ -17,24 +17,27 @@
package org.onosproject.drivers.p4runtime;
import org.onosproject.cluster.ClusterService;
+import org.onosproject.grpc.utils.AbstractGrpcHandshaker;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.device.DeviceAgentListener;
import org.onosproject.net.device.DeviceHandshaker;
import org.onosproject.net.pi.service.PiPipeconfWatchdogService;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.p4runtime.api.P4RuntimeClient;
-import org.onosproject.p4runtime.api.P4RuntimeClientKey;
import org.onosproject.p4runtime.api.P4RuntimeController;
import java.math.BigInteger;
import java.util.concurrent.CompletableFuture;
import static java.util.concurrent.CompletableFuture.completedFuture;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.extractP4DeviceId;
/**
* Implementation of DeviceHandshaker for P4Runtime.
*/
-public class P4RuntimeHandshaker extends AbstractP4RuntimeHandlerBehaviour implements DeviceHandshaker {
+public class P4RuntimeHandshaker
+ extends AbstractGrpcHandshaker<P4RuntimeClient, P4RuntimeController>
+ implements DeviceHandshaker {
// This is needed to compute an election ID based on mastership term and
// preference. At the time of writing the practical maximum cluster size is
@@ -44,60 +47,35 @@
// election IDs (e.g. two nodes seeing different cluster sizes).
private static final int MAX_CLUSTER_SIZE = 20;
- @Override
- public CompletableFuture<Boolean> connect() {
- return CompletableFuture
- .supplyAsync(this::createClient);
+ private Long p4DeviceId;
+
+ public P4RuntimeHandshaker() {
+ super(P4RuntimeController.class);
}
- private boolean createClient() {
- final P4RuntimeClientKey clientKey = clientKey();
- if (clientKey == null) {
+ @Override
+ protected boolean setupBehaviour(String opName) {
+ if (!super.setupBehaviour(opName)) {
return false;
}
- if (!handler().get(P4RuntimeController.class).createClient(clientKey)) {
- log.debug("Unable to create client for {}", data().deviceId());
+
+ p4DeviceId = extractP4DeviceId(mgmtUriFromNetcfg());
+ if (p4DeviceId == null) {
+ log.warn("Unable to obtain the P4Runtime-internal device_id from " +
+ "config of {}, cannot perform {}",
+ deviceId, opName);
return false;
}
return true;
}
@Override
- public boolean isConnected() {
- // This is based on the client key obtained from the current netcfg. If
- // a client already exists for this device, but the netcfg with the
- // server endpoints has changed, this will return false.
- return getClientByKey() != null;
- }
-
- @Override
- public void disconnect() {
- // This removes clients associated with this device ID, even if the
- // netcfg has changed and so the client key for this device.
- handler().get(P4RuntimeController.class).removeClient(data().deviceId());
- }
-
- @Override
- public boolean isReachable() {
- final P4RuntimeClient client = getClientByKey();
- return client != null && client.isServerReachable();
- }
-
- @Override
- public CompletableFuture<Boolean> probeReachability() {
- final P4RuntimeClient client = getClientByKey();
- if (client == null) {
- return completedFuture(false);
- }
- return client.probeService();
- }
-
- @Override
public boolean isAvailable() {
// To be available, we require a session open (for packet in/out) and a
// pipeline config set.
- final P4RuntimeClient client = getClientByKey();
- if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
+ if (!setupBehaviour("isAvailable()") ||
+ !client.isServerReachable() ||
+ !client.isSessionOpen(p4DeviceId)) {
return false;
}
// Since we cannot probe the device, we rely on what's known by the
@@ -111,11 +89,12 @@
public CompletableFuture<Boolean> probeAvailability() {
// To be available, we require a session open (for packet in/out) and a
// pipeline config set.
- final P4RuntimeClient client = getClientByKey();
- if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
+ if (!setupBehaviour("probeAvailability()") ||
+ !client.isServerReachable() ||
+ !client.isSessionOpen(p4DeviceId)) {
return completedFuture(false);
}
- return client.isAnyPipelineConfigSet();
+ return client.isAnyPipelineConfigSet(p4DeviceId);
}
@Override
@@ -125,7 +104,7 @@
}
if (newRole.equals(MastershipRole.NONE)) {
log.info("Notified role NONE, closing session...");
- client.closeSession();
+ client.closeSession(p4DeviceId);
} else {
throw new UnsupportedOperationException(
"Use preference-based way for setting MASTER or STANDBY roles");
@@ -143,19 +122,21 @@
throw new IllegalStateException(
"Cluster too big! Maz size supported is " + MAX_CLUSTER_SIZE);
}
- BigInteger electionId = BigInteger.valueOf(term)
+ final BigInteger electionId = BigInteger.valueOf(term)
.multiply(BigInteger.valueOf(MAX_CLUSTER_SIZE))
.subtract(BigInteger.valueOf(preference));
- client.setMastership(preference == 0, electionId);
+ client.setMastership(p4DeviceId, preference == 0, electionId);
}
@Override
public MastershipRole getRole() {
- final P4RuntimeClient client = getClientByKey();
- if (client == null || !client.isServerReachable() || !client.isSessionOpen()) {
+ if (!setupBehaviour("getRole()") ||
+ !client.isServerReachable() ||
+ !client.isSessionOpen(p4DeviceId)) {
return MastershipRole.NONE;
}
- return client.isMaster() ? MastershipRole.MASTER : MastershipRole.STANDBY;
+ return client.isMaster(p4DeviceId)
+ ? MastershipRole.MASTER : MastershipRole.STANDBY;
}
@Override
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
index 73faf45..796bea6 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMeterProgrammable.java
@@ -105,7 +105,7 @@
final PiMeterCellHandle handle = PiMeterCellHandle.of(deviceId, piMeterCellConfig);
ENTRY_LOCKS.getUnchecked(handle).lock();
- final boolean result = client.write(pipeconf)
+ final boolean result = client.write(p4DeviceId, pipeconf)
.modify(piMeterCellConfig).submitSync().isSuccess();
if (result) {
meterMirror.put(handle, piMeterCellConfig);
@@ -129,7 +129,7 @@
meterIds.add(mode.id());
}
- piMeterCellConfigs = client.read(pipeconf)
+ piMeterCellConfigs = client.read(p4DeviceId, pipeconf)
.meterCells(meterIds).submitSync().all(PiMeterCellConfig.class);
Collection<Meter> meters = piMeterCellConfigs.stream()
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMulticastGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMulticastGroupProgrammable.java
index 80c771e..212ada2 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMulticastGroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeMulticastGroupProgrammable.java
@@ -145,7 +145,7 @@
return;
case MODIFY:
// Since reading multicast groups is not supported yet on
- // PI/Stratum, we cannot trust groupOnDevic) as we don't have a
+ // PI/Stratum, we cannot trust groupOnDevice as we don't have a
// mechanism to enforce consistency of the mirror with the
// device state.
// if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
@@ -169,7 +169,8 @@
private boolean writeMcGroupOnDevice(
PiMulticastGroupEntry group, P4RuntimeClient.UpdateType opType) {
- return client.write(pipeconf).entity(group, opType).submitSync().isSuccess();
+ return client.write(p4DeviceId, pipeconf)
+ .entity(group, opType).submitSync().isSuccess();
}
private boolean mcGroupApply(PiMulticastGroupEntryHandle handle,
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
index 9010c51..8a182a7 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
@@ -23,6 +23,8 @@
import java.util.Collection;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.getInterpreter;
+
/**
* Implementation of PacketProgrammable behaviour for P4Runtime.
*/
@@ -37,7 +39,7 @@
return;
}
- final PiPipelineInterpreter interpreter = getInterpreter();
+ final PiPipelineInterpreter interpreter = getInterpreter(handler());
if (interpreter == null) {
// Error logged by getInterpreter().
return;
@@ -47,7 +49,7 @@
Collection<PiPacketOperation> operations = interpreter.mapOutboundPacket(packet);
operations.forEach(piPacketOperation -> {
log.debug("Doing PiPacketOperation {}", piPacketOperation);
- client.packetOut(piPacketOperation, pipeconf);
+ client.packetOut(p4DeviceId, piPacketOperation, pipeconf);
});
} catch (PiPipelineInterpreter.PiInterpreterException e) {
log.error("Unable to translate outbound packet for {} with pipeconf {}: {}",
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeTableStatisticsDiscovery.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeTableStatisticsDiscovery.java
index 1b390ef..8a32232 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeTableStatisticsDiscovery.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeTableStatisticsDiscovery.java
@@ -36,6 +36,7 @@
import java.util.Map;
import static com.google.common.collect.Lists.newArrayList;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverUtils.getInterpreter;
/**
* Implementation of behaviour TableStatisticsDiscovery for P4Runtime.
@@ -49,7 +50,7 @@
return Collections.emptyList();
}
FlowRuleService flowService = handler().get(FlowRuleService.class);
- PiPipelineInterpreter interpreter = getInterpreter();
+ PiPipelineInterpreter interpreter = getInterpreter(handler());
PiPipelineModel model = pipeconf.pipelineModel();
List<TableStatisticsEntry> tableStatsList;
diff --git a/drivers/stratum/BUILD b/drivers/stratum/BUILD
index 1d19c3c..a87c97e 100644
--- a/drivers/stratum/BUILD
+++ b/drivers/stratum/BUILD
@@ -4,6 +4,8 @@
"//drivers/gnmi:onos-drivers-gnmi",
"//drivers/gnoi:onos-drivers-gnoi",
"//pipelines/basic:onos-pipelines-basic",
+ "//protocols/grpc/api:onos-protocols-grpc-api",
+ "//protocols/grpc/utils:onos-protocols-grpc-utils",
]
osgi_jar(
diff --git a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
index dbcb193..fdf8173 100644
--- a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumDeviceDescriptionDiscovery.java
@@ -63,6 +63,9 @@
// Availability is mandated by P4Runtime.
p4Descr.isDefaultAvailable(),
DefaultAnnotations.builder()
+ .putAll(p4Descr.annotations())
+ .putAll(gnmiDescr.annotations())
+ .putAll(gnoiDescr.annotations())
.set(AnnotationKeys.PROTOCOL, format(
"%s, %s, %s",
p4Descr.annotations().value(AnnotationKeys.PROTOCOL),
diff --git a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
index d512d3b..ac9a534 100644
--- a/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
+++ b/drivers/stratum/src/main/java/org/onosproject/drivers/stratum/StratumHandshaker.java
@@ -38,6 +38,23 @@
}
@Override
+ public boolean connect() {
+ return p4runtime.connect() && gnmi.connect() && gnoi.connect();
+ }
+
+ @Override
+ public boolean hasConnection() {
+ return p4runtime.hasConnection() && gnmi.hasConnection() && gnoi.hasConnection();
+ }
+
+ @Override
+ public void disconnect() {
+ p4runtime.disconnect();
+ gnmi.disconnect();
+ gnoi.disconnect();
+ }
+
+ @Override
public boolean isReachable() {
// Reachability is mainly used for mastership contests and it's a
// prerequisite for availability. We can probably live without gNMI and
@@ -86,23 +103,4 @@
public void removeDeviceAgentListener(ProviderId providerId) {
p4runtime.removeDeviceAgentListener(providerId);
}
-
- @Override
- public CompletableFuture<Boolean> connect() {
- // We should execute connections in parallel.
- return p4runtime.connect().thenCombine(gnmi.connect(), Boolean::logicalAnd)
- .thenCombine(gnoi.connect(), Boolean::logicalAnd);
- }
-
- @Override
- public boolean isConnected() {
- return p4runtime.isConnected() && gnmi.isConnected() && gnoi.isConnected();
- }
-
- @Override
- public void disconnect() {
- p4runtime.disconnect();
- gnmi.disconnect();
- gnoi.disconnect();
- }
}