Add support for all tables wildcard read in P4Runtime
This is required for targets that are not P4RT-compliant
and do not support table-specific wildcard reads.
The all tables wildcard read are activated via
tableWildcardReads driver property.
Change-Id: I675e6f876648ad7634ea0a13ecf44aa366739d3f
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverProperties.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverProperties.java
index ebc6eda..224e065 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverProperties.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeDriverProperties.java
@@ -51,4 +51,9 @@
// True if target supports reading and writing table entries.
public static final String SUPPORT_DEFAULT_TABLE_ENTRY = "supportDefaultTableEntry";
public static final boolean DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY = true;
+
+ // If true we read table entries from all tables with a single wildcard read.
+ // Otherwise, we submit a read request with wildcard read on a table basis.
+ public static final String TABLE_WILCARD_READS = "tableWildcardReads";
+ public static final boolean DEFAULT_TABLE_WILCARD_READS = false;
}
\ No newline at end of file
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 e8204a6..2cb5b68 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,17 +58,20 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_DELETE_BEFORE_UPDATE;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_READ_FROM_MIRROR;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_SUPPORT_TABLE_COUNTERS;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DEFAULT_TABLE_WILCARD_READS;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.DELETE_BEFORE_UPDATE;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.READ_COUNTERS_WITH_TABLE_ENTRIES;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.READ_FROM_MIRROR;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.SUPPORT_DEFAULT_TABLE_ENTRY;
import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.SUPPORT_TABLE_COUNTERS;
+import static org.onosproject.drivers.p4runtime.P4RuntimeDriverProperties.TABLE_WILCARD_READS;
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;
@@ -181,28 +184,51 @@
private Collection<PiTableEntry> getAllTableEntriesFromDevice() {
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())
- .forEach(t -> {
- request.tableEntries(t.id());
- if (driverBoolProperty(SUPPORT_DEFAULT_TABLE_ENTRY,
- DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY) &&
- t.constDefaultAction().isEmpty()) {
- request.defaultTableEntry(t.id());
- }
- });
+ final boolean supportDefaultTableEntry = driverBoolProperty(
+ SUPPORT_DEFAULT_TABLE_ENTRY, DEFAULT_SUPPORT_DEFAULT_TABLE_ENTRY);
+ final boolean tableWildcardReads = driverBoolProperty(
+ TABLE_WILCARD_READS, DEFAULT_TABLE_WILCARD_READS);
+ if (!tableWildcardReads) {
+ // Read entries from all non-constant tables, including default ones.
+ pipelineModel.tables().stream()
+ .filter(t -> !t.isConstantTable())
+ .forEach(t -> {
+ request.tableEntries(t.id());
+ if (supportDefaultTableEntry && t.constDefaultAction().isEmpty()) {
+ request.defaultTableEntry(t.id());
+ }
+ });
+ } else {
+ request.allTableEntries();
+ if (supportDefaultTableEntry) {
+ request.allDefaultTableEntries();
+ }
+ }
final P4RuntimeReadClient.ReadResponse response = request.submitSync();
if (!response.isSuccess()) {
return null;
}
- return response.all(PiTableEntry.class).stream()
+ Stream<PiTableEntry> piTableEntries = response.all(PiTableEntry.class).stream()
// Device implementation might return duplicate entries. For
// example if reading only default ones is not supported and
// non-default entries are returned, by using distinct() we
// are robust against that possibility.
- .distinct()
- .collect(Collectors.toList());
+ .distinct();
+ if (tableWildcardReads) {
+ // When doing a wildcard read on all tables, the device might
+ // return table entries of tables not present in the pipeline
+ // model or constant (default) entries that are filtered out.
+ piTableEntries = piTableEntries.filter(te -> {
+ var piTableModel = pipelineModel.table(te.table());
+ if (piTableModel.isEmpty() ||
+ piTableModel.get().isConstantTable() ||
+ (supportDefaultTableEntry && piTableModel.get().constDefaultAction().isPresent())) {
+ return false;
+ }
+ return true;
+ });
+ }
+ return piTableEntries.collect(Collectors.toList());
}
@Override
diff --git a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeReadClient.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeReadClient.java
index b99aef3..dc1380c 100644
--- a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeReadClient.java
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeReadClient.java
@@ -99,6 +99,20 @@
ReadRequest defaultTableEntry(Iterable<PiTableId> tableIds);
/**
+ * Requests to read all table entries from all tables.
+ *
+ * @return this
+ */
+ ReadRequest allTableEntries();
+
+ /**
+ * Requests to read all default table entries from all tables.
+ *
+ * @return this
+ */
+ ReadRequest allDefaultTableEntries();
+
+ /**
* Requests to read all action profile groups from the given action
* profile.
*
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/client/ReadRequestImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/client/ReadRequestImpl.java
index 6858800..9ca268c 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/client/ReadRequestImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/client/ReadRequestImpl.java
@@ -157,6 +157,28 @@
}
@Override
+ public P4RuntimeReadClient.ReadRequest allTableEntries() {
+ try {
+ doTableEntry(null, false);
+ } catch (InternalRequestException e) {
+ log.warn("Unable to read entries for all tables from {}: {}",
+ client.deviceId(), e.getMessage());
+ }
+ return this;
+ }
+
+ @Override
+ public P4RuntimeReadClient.ReadRequest allDefaultTableEntries() {
+ try {
+ doTableEntry(null, true);
+ } catch (InternalRequestException e) {
+ log.warn("Unable to read default entries for all tables from {}: {}",
+ client.deviceId(), e.getMessage());
+ }
+ return this;
+ }
+
+ @Override
public P4RuntimeReadClient.ReadRequest actionProfileGroups(PiActionProfileId actionProfileId) {
try {
requestMsg.addEntities(
@@ -270,10 +292,16 @@
private void doTableEntry(PiTableId piTableId, boolean defaultEntries)
throws InternalRequestException {
- checkNotNull(piTableId);
- final var builder = P4RuntimeOuterClass.TableEntry.newBuilder()
- .setTableId(p4TableId(piTableId))
- .setIsDefaultAction(defaultEntries);
+
+ final var builder = P4RuntimeOuterClass.TableEntry.newBuilder();
+
+ builder.setIsDefaultAction(defaultEntries);
+ if (piTableId == null) {
+ builder.setCounterData(P4RuntimeOuterClass.CounterData.getDefaultInstance());
+ builder.setMeterConfig(P4RuntimeOuterClass.MeterConfig.getDefaultInstance());
+ } else {
+ builder.setTableId(p4TableId(piTableId));
+ }
if (tableHasCounters(piTableId)) {
builder.setCounterData(P4RuntimeOuterClass.CounterData
.getDefaultInstance());