More robust handling of multicast groups in P4Runtime
Since we cannot read the device state, try to delete and re-insert if
insert or modify operation fails.
Change-Id: I35733c7e0af509317e92f991978c0a4ef36b9bc8
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
index 0dd5f21..1cfe079 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
@@ -265,30 +265,31 @@
PiMulticastGroupEntry groupToApply,
PiMulticastGroupEntry groupOnDevice,
Group pdGroup, GroupOperation.Type opType) {
- if (opType == GroupOperation.Type.DELETE) {
- if (writeMcGroupOnDevice(groupToApply, DELETE)) {
- mcGroupMirror.remove(handle);
- mcGroupTranslator.forget(handle);
- }
- return;
- }
-
- final P4RuntimeClient.WriteOperationType p4OpType =
- opType == GroupOperation.Type.ADD ? INSERT : MODIFY;
-
- if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
- DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
- && p4OpType == MODIFY
- && groupOnDevice != null
- && groupOnDevice.equals(groupToApply)) {
- // Ignore.
- return;
- }
-
- if (writeMcGroupOnDevice(groupToApply, p4OpType)) {
- mcGroupMirror.put(handle, groupToApply);
- mcGroupTranslator.learn(handle, new PiTranslatedEntity<>(
- pdGroup, groupToApply, handle));
+ switch (opType) {
+ case ADD:
+ robustMcGroupAdd(handle, groupToApply, pdGroup);
+ return;
+ case MODIFY:
+ // Since reading multicast groups is not supported yet on
+ // PI/Stratum, we cannot trust groupOnDevic) as we don't have a
+ // mechanism to enforce consistency of the mirror with the
+ // device state.
+ // if (driverBoolProperty(CHECK_MIRROR_BEFORE_UPDATE,
+ // DEFAULT_CHECK_MIRROR_BEFORE_UPDATE)
+ // && p4OpType == MODIFY
+ // && groupOnDevice != null
+ // && groupOnDevice.equals(groupToApply)) {
+ // // Ignore.
+ // return;
+ // }
+ robustMcGroupModify(handle, groupToApply, pdGroup);
+ return;
+ case DELETE:
+ mcGroupApply(handle, groupToApply, pdGroup, DELETE);
+ return;
+ default:
+ log.error("Unknown group operation type {}, " +
+ "cannot process multicast group", opType);
}
}
@@ -299,6 +300,57 @@
"performing multicast group " + opType, false);
}
+ private boolean mcGroupApply(PiMulticastGroupEntryHandle handle,
+ PiMulticastGroupEntry piGroup,
+ Group pdGroup,
+ P4RuntimeClient.WriteOperationType opType) {
+ switch (opType) {
+ case DELETE:
+ if (writeMcGroupOnDevice(piGroup, DELETE)) {
+ mcGroupMirror.remove(handle);
+ mcGroupTranslator.forget(handle);
+ return true;
+ } else {
+ return false;
+ }
+ case INSERT:
+ case MODIFY:
+ if (writeMcGroupOnDevice(piGroup, opType)) {
+ mcGroupMirror.put(handle, piGroup);
+ mcGroupTranslator.learn(handle, new PiTranslatedEntity<>(
+ pdGroup, piGroup, handle));
+ return true;
+ } else {
+ return false;
+ }
+ default:
+ log.warn("Unknown operation type {}, cannot apply group", opType);
+ return false;
+ }
+ }
+
+ private void robustMcGroupAdd(PiMulticastGroupEntryHandle handle,
+ PiMulticastGroupEntry piGroup,
+ Group pdGroup) {
+ if (mcGroupApply(handle, piGroup, pdGroup, INSERT)) {
+ return;
+ }
+ // Try to delete (perhaps it already exists) and re-add...
+ mcGroupApply(handle, piGroup, pdGroup, DELETE);
+ mcGroupApply(handle, piGroup, pdGroup, INSERT);
+ }
+
+ private void robustMcGroupModify(PiMulticastGroupEntryHandle handle,
+ PiMulticastGroupEntry piGroup,
+ Group pdGroup) {
+ if (mcGroupApply(handle, piGroup, pdGroup, MODIFY)) {
+ return;
+ }
+ // Not sure for which reason it cannot be modified, so try to delete and insert instead...
+ mcGroupApply(handle, piGroup, pdGroup, DELETE);
+ mcGroupApply(handle, piGroup, pdGroup, INSERT);
+ }
+
private boolean modifyGroupFromDevice(PiActionGroup groupToApply, PiActionGroup groupOnDevice) {
PiActionProfileId groupProfileId = groupToApply.actionProfileId();
Collection<PiActionGroupMember> membersToRemove = Sets.newHashSet(groupOnDevice.members());