use of org.onosproject.net.pi.runtime.PiActionProfileGroupHandle in project onos by opennetworkinglab.
the class P4RuntimeActionGroupProgrammable method checkAndForgeGroupEntry.
private Group checkAndForgeGroupEntry(PiActionProfileGroup piGroupOnDevice, Map<PiActionProfileMemberHandle, PiActionProfileMember> membersOnDevice) {
final PiActionProfileGroupHandle handle = PiActionProfileGroupHandle.of(deviceId, piGroupOnDevice);
final Optional<PiTranslatedEntity<Group, PiActionProfileGroup>> translatedEntity = groupTranslator.lookup(handle);
final TimedEntry<PiActionProfileGroup> mirrorEntry = groupMirror.get(handle);
// by the translation store.
if (!translatedEntity.isPresent()) {
log.warn("Group not found in translation store: {}", handle);
return null;
}
final PiActionProfileGroup piGroupFromStore = translatedEntity.get().translated();
if (!piGroupFromStore.equals(piGroupOnDevice)) {
log.warn("Group on device {} is different from the one in " + "translation store: {} [device={}, store={}]", deviceId, handle, piGroupOnDevice, piGroupFromStore);
return null;
}
// 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: {}", deviceId, handle);
return null;
}
if (mirrorEntry == null) {
log.warn("Group handle not found in device mirror: {}", handle);
return null;
}
// Check that members from device are the same as in the translated group.
return addedGroup(translatedEntity.get().original(), mirrorEntry.lifeSec());
}
use of org.onosproject.net.pi.runtime.PiActionProfileGroupHandle in project onos by opennetworkinglab.
the class P4RuntimeActionGroupProgrammable method getGroups.
@Override
public Collection<Group> getGroups() {
if (!setupBehaviour("getGroups()")) {
return Collections.emptyList();
}
if (driverBoolProperty(READ_ACTION_GROUPS_FROM_MIRROR, DEFAULT_READ_ACTION_GROUPS_FROM_MIRROR)) {
return getGroupsFromMirror();
}
// Dump groups and members from device for all action profiles.
final P4RuntimeReadClient.ReadRequest request = client.read(p4DeviceId, pipeconf);
pipeconf.pipelineModel().actionProfiles().stream().filter(piActionProfileModel -> piActionProfileModel.tables().stream().map(tableId -> pipeconf.pipelineModel().table(tableId)).allMatch(piTableModel -> piTableModel.isPresent() && !piTableModel.get().oneShotOnly())).map(PiActionProfileModel::id).forEach(id -> request.actionProfileGroups(id).actionProfileMembers(id));
final P4RuntimeReadClient.ReadResponse response = request.submitSync();
if (!response.isSuccess()) {
// Error at client level.
return Collections.emptyList();
}
final Collection<PiActionProfileGroup> groupsOnDevice = response.all(PiActionProfileGroup.class);
final Map<PiActionProfileMemberHandle, PiActionProfileMember> membersOnDevice = response.all(PiActionProfileMember.class).stream().collect(toMap(m -> m.handle(deviceId), m -> m));
// Sync mirrors.
groupMirror.sync(deviceId, groupsOnDevice);
memberMirror.sync(deviceId, membersOnDevice.values());
// Retrieve the original PD group before translation.
final List<Group> result = Lists.newArrayList();
final List<PiActionProfileGroup> groupsToRemove = Lists.newArrayList();
final Set<PiActionProfileMemberHandle> memberHandlesToKeep = Sets.newHashSet();
for (PiActionProfileGroup piGroup : groupsOnDevice) {
final Group pdGroup = checkAndForgeGroupEntry(piGroup, membersOnDevice);
if (pdGroup == null) {
// Entry is on device but is inconsistent with controller state.
// Mark for removal.
groupsToRemove.add(piGroup);
} else {
result.add(pdGroup);
// Keep track of member handles used in groups.
piGroup.members().stream().map(m -> PiActionProfileMemberHandle.of(deviceId, piGroup.actionProfile(), m.id())).forEach(memberHandlesToKeep::add);
}
}
// Trigger clean up of inconsistent groups and members (if any). Also
// take care of removing any orphan member, e.g. from a
// partial/unsuccessful group insertion.
final Set<PiActionProfileMemberHandle> memberHandlesToRemove = Sets.difference(membersOnDevice.keySet(), memberHandlesToKeep);
final Set<PiActionProfileGroupHandle> groupHandlesToRemove = groupsToRemove.stream().map(g -> g.handle(deviceId)).collect(toSet());
if (groupHandlesToRemove.size() + memberHandlesToRemove.size() > 0) {
log.warn("Cleaning up {} action profile groups and " + "{} members on {}...", groupHandlesToRemove.size(), memberHandlesToRemove.size(), deviceId);
client.write(p4DeviceId, pipeconf).delete(groupHandlesToRemove).delete(memberHandlesToRemove).submit().whenComplete((r, ex) -> {
if (ex != null) {
log.error("Exception removing inconsistent group/members", ex);
} else {
log.debug("Completed removal of inconsistent " + "groups/members ({} of {} updates succeeded)", r.success().size(), r.all().size());
groupMirror.applyWriteResponse(r);
memberMirror.applyWriteResponse(r);
}
});
}
// Done.
return result;
}
use of org.onosproject.net.pi.runtime.PiActionProfileGroupHandle in project onos by opennetworkinglab.
the class P4RuntimeActionGroupProgrammable method processPdGroup.
private void processPdGroup(Group pdGroup, GroupOperation.Type opType) {
// Translate.
final PiActionProfileGroup piGroup;
try {
piGroup = groupTranslator.translate(pdGroup, pipeconf);
} catch (PiTranslationException e) {
log.warn("Unable to translate group, aborting {} operation: {} [{}]", opType, e.getMessage(), pdGroup);
return;
}
final Operation operation = opType.equals(GroupOperation.Type.DELETE) ? Operation.REMOVE : Operation.APPLY;
final PiActionProfileGroupHandle handle = piGroup.handle(deviceId);
// Update translation store.
if (operation.equals(Operation.APPLY)) {
groupTranslator.learn(handle, new PiTranslatedEntity<>(pdGroup, piGroup, handle));
} else {
groupTranslator.forget(handle);
}
// Submit write and forget about it.
asyncWritePiGroup(piGroup, handle, operation);
}
Aggregations