[AETHER-1248] Reset default entries
A default entry according to the P4RT spec should be reset to its original value
and not removed. The client can send a specially crafted write request with action field
unset to reset default actions to the original value
Change-Id: I451a3be395b212e14ae8eaf060cc048500705091
(cherry picked from commit 91217e420118075fc8b4f88341b08a127bec9595)
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..3d06c2e 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
@@ -156,23 +156,52 @@
}
}
- if (!inconsistentEntries.isEmpty()) {
- // Trigger clean up of inconsistent entries.
- log.warn("Found {} inconsistent table entries on {}, removing them...",
- inconsistentEntries.size(), deviceId);
- // Submit delete request and update mirror when done.
- client.write(p4DeviceId, pipeconf)
- .entities(inconsistentEntries, DELETE)
- .submit().whenComplete((response, ex) -> {
+ // Default entries need to be treated in a different way according to the spec:
+ // the client can modify (reset or update) them but cannot remove the entries
+ List<PiTableEntry> inconsistentDefaultEntries = Lists.newArrayList();
+ List<PiTableEntry> tempDefaultEntries = inconsistentEntries.stream()
+ .filter(PiTableEntry::isDefaultAction)
+ .collect(Collectors.toList());
+ inconsistentEntries.removeAll(tempDefaultEntries);
+ // Once we have removed the default entry from inconsistentEntries we need to
+ // craft for each default entry a copy without the action field. According to
+ // the spec leaving the action field unset will reset the original default entry.
+ tempDefaultEntries.forEach(piTableEntry -> {
+ PiTableEntry resetEntry = PiTableEntry.builder()
+ .forTable(piTableEntry.table()).build();
+ inconsistentDefaultEntries.add(resetEntry);
+ });
+
+ // Clean up of inconsistent entries.
+ if (!inconsistentEntries.isEmpty() || !inconsistentDefaultEntries.isEmpty()) {
+ WriteRequest writeRequest = client.write(p4DeviceId, pipeconf);
+ // Trigger remove of inconsistent entries.
+ if (!inconsistentEntries.isEmpty()) {
+ log.warn("Found {} inconsistent table entries on {}, removing them...",
+ inconsistentEntries.size(), deviceId);
+ writeRequest = writeRequest.entities(inconsistentEntries, DELETE);
+ }
+
+ // Trigger reset of inconsistent default entries.
+ if (!inconsistentDefaultEntries.isEmpty()) {
+ log.warn("Found {} inconsistent default table entries on {}, resetting them...",
+ inconsistentDefaultEntries.size(), deviceId);
+ writeRequest = writeRequest.entities(inconsistentDefaultEntries, MODIFY);
+ }
+
+ // Submit delete request for non-default entries and modify request
+ // for default entries. Updates mirror when done.
+ writeRequest.submit().whenComplete((response, ex) -> {
if (ex != null) {
log.error("Exception removing inconsistent table entries", ex);
} else {
log.debug("Successfully removed {} out of {} inconsistent entries",
- response.success().size(), response.all().size());
+ response.success().size(), response.all().size());
}
- tableMirror.applyWriteResponse(response);
+ // We can use the entity as the handle does not contain the action field
+ // so the key will be removed even if the table entry is different
+ response.success().forEach(entity -> tableMirror.remove((PiTableEntryHandle) entity.handle()));
});
-
}
return result.build();