From 326ad2dd292c0a570be4a06e48ae8be8dca3a00e Mon Sep 17 00:00:00 2001 From: Carmelo Cascone Date: Tue, 28 Nov 2017 18:09:13 -0800 Subject: [PATCH] ONOS-7050 Refactored PI translation service and store The translation store is now able to maintain mappings between translated entities and specific instances of a PI entry in the network (i.e. applied to a device). The translation service has been refactored to allow users to learn and forget translated entities. The refactoring of the P4Runtime driver using this service will be submitted separatelly. Change-Id: Iaafd87d90232514853ca0dea0115dbae4f6e7886 --- .../java/org/onosproject/net/group/Group.java | 3 +- .../net/pi/runtime/PiActionGroupHandle.java | 66 ++++++ .../onosproject/net/pi/runtime/PiHandle.java | 74 +++++++ .../net/pi/runtime/PiTableEntryHandle.java | 77 +++++++ .../service/PiFlowRuleTranslationStore.java | 30 +++ .../net/pi/service/PiFlowRuleTranslator.java | 29 +++ .../pi/service/PiGroupTranslationStore.java | 30 +++ .../net/pi/service/PiGroupTranslator.java | 29 +++ .../net/pi/service/PiTranslatedEntity.java | 43 ++-- .../net/pi/service/PiTranslationEvent.java | 7 +- .../pi/service/PiTranslationException.java | 35 ++++ .../net/pi/service/PiTranslationService.java | 69 +------ .../net/pi/service/PiTranslationStore.java | 53 ++--- .../service/PiTranslationStoreDelegate.java | 9 +- .../net/pi/service/PiTranslator.java | 75 +++++++ .../net/pi/impl/AbstractPiTranslatorImpl.java | 58 ++++++ .../pi/impl/CriterionTranslatorHelper.java | 2 +- ...tor.java => PiFlowRuleTranslatorImpl.java} | 8 +- ...slator.java => PiGroupTranslatorImpl.java} | 8 +- .../net/pi/impl/PiTranslationServiceImpl.java | 90 +++++---- .../org/onosproject/net/pi/impl/PiUtils.java | 10 +- .../net/pi/impl/PiTranslatorServiceTest.java | 12 +- ...AbstractDistributedPiTranslationStore.java | 143 +++++++++++++ ...DistributedPiFlowRuleTranslationStore.java | 40 ++++ .../DistributedPiGroupTranslationStore.java | 40 ++++ .../impl/DistributedPiTranslationStore.java | 189 ------------------ ...ributedDevicePipeconfMappingStoreTest.java | 2 +- .../DistributedPiTranslationStoreTest.java | 153 ++++++++++++++ .../store/serializers/KryoNamespaces.java | 6 + .../P4RuntimeFlowRuleProgrammable.java | 6 +- .../p4runtime/P4RuntimeGroupProgrammable.java | 6 +- 31 files changed, 1029 insertions(+), 373 deletions(-) create mode 100644 core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java create mode 100644 core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java create mode 100644 core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java rename core/net/src/main/java/org/onosproject/net/pi/impl/{PiFlowRuleTranslator.java => PiFlowRuleTranslatorImpl.java} (99%) rename core/net/src/main/java/org/onosproject/net/pi/impl/{PiGroupTranslator.java => PiGroupTranslatorImpl.java} (95%) create mode 100644 core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java create mode 100644 core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java create mode 100644 core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java delete mode 100644 core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java create mode 100644 core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java diff --git a/core/api/src/main/java/org/onosproject/net/group/Group.java b/core/api/src/main/java/org/onosproject/net/group/Group.java index 3e2494ca01..39c6a3d208 100644 --- a/core/api/src/main/java/org/onosproject/net/group/Group.java +++ b/core/api/src/main/java/org/onosproject/net/group/Group.java @@ -16,11 +16,12 @@ package org.onosproject.net.group; import org.onosproject.core.GroupId; +import org.onosproject.net.pi.service.PiTranslatable; /** * ONOS representation of group that is stored in the system. */ -public interface Group extends GroupDescription { +public interface Group extends GroupDescription, PiTranslatable { /** * State of the group object in ONOS. */ diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java new file mode 100644 index 0000000000..6c464de61d --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroupHandle.java @@ -0,0 +1,66 @@ +/* + * Copyright 2017-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.net.pi.runtime; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import org.onosproject.net.DeviceId; + +/** + * Global identifier of a PI action group applied to a device, uniquely defined + * by a device ID, action profile ID and group ID. + */ +@Beta +public final class PiActionGroupHandle extends PiHandle { + + + private PiActionGroupHandle(DeviceId deviceId, PiActionGroup actionGroup) { + super(deviceId, actionGroup); + } + + @Override + public int hashCode() { + return Objects.hashCode(deviceId(), + piEntity().actionProfileId(), + piEntity().id()); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + PiActionGroupHandle that = (PiActionGroupHandle) o; + return Objects.equal(deviceId(), that.deviceId()) && + Objects.equal(piEntity().actionProfileId(), + that.piEntity().actionProfileId()) && + Objects.equal(piEntity().id(), piEntity().id()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("deviceId", deviceId()) + .add("actionProfileId", piEntity().actionProfileId()) + .add("groupId", piEntity().id()) + .toString(); + } +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java new file mode 100644 index 0000000000..e8e70d10ae --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiHandle.java @@ -0,0 +1,74 @@ +/* + * Copyright 2017-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.net.pi.runtime; + +import com.google.common.annotations.Beta; +import org.onosproject.net.DeviceId; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Global identifier of a PI entity applied to a device, unique in the scope of + * the whole network. + */ +@Beta +public abstract class PiHandle { + + private final DeviceId deviceId; + private final E piEntity; + + protected PiHandle(DeviceId deviceId, E piEntity) { + this.deviceId = checkNotNull(deviceId); + this.piEntity = checkNotNull(piEntity); + } + + /** + * Returns the device ID of this handle. + * + * @return device ID + */ + public final DeviceId deviceId() { + return deviceId; + } + + /** + * Returns the type of entity identified by this handle. + * + * @return PI entity type + */ + public final PiEntityType entityType() { + return piEntity.piEntityType(); + } + + /** + * The entity to which this handle is associated. + * + * @return PI entity + */ + public final E piEntity() { + return piEntity; + } + + @Override + public abstract int hashCode(); + + @Override + public abstract boolean equals(Object obj); + + @Override + public abstract String toString(); +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java new file mode 100644 index 0000000000..7eeb7f68f1 --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntryHandle.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017-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.net.pi.runtime; + +import com.google.common.annotations.Beta; +import com.google.common.base.MoreObjects; +import com.google.common.base.Objects; +import org.onosproject.net.DeviceId; + +/** + * Global identifier of a PI table entry applied on a device, uniquely defined + * by a device ID, table ID and match key. + */ +@Beta +public final class PiTableEntryHandle extends PiHandle { + + private PiTableEntryHandle(DeviceId deviceId, PiTableEntry entry) { + super(deviceId, entry); + } + + /** + * Creates a new handle for the given PI table entry and device ID. + * + * @param deviceId device ID + * @param entry PI table entry + * @return PI table entry handle + */ + public static PiTableEntryHandle of(DeviceId deviceId, PiTableEntry entry) { + return new PiTableEntryHandle(deviceId, entry); + } + + @Override + public int hashCode() { + return Objects.hashCode(deviceId(), + piEntity().table(), + piEntity().matchKey()); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + final PiTableEntryHandle other = (PiTableEntryHandle) obj; + return Objects.equal(this.deviceId(), other.deviceId()) + && Objects.equal(this.piEntity().table(), + other.piEntity().table()) + && Objects.equal(this.piEntity().matchKey(), + other.piEntity().matchKey()); + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(this) + .add("deviceId", deviceId()) + .add("tableId", piEntity().table()) + .add("matchKey", piEntity().matchKey()) + .toString(); + } +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java new file mode 100644 index 0000000000..a80de10c3f --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslationStore.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.pi.runtime.PiTableEntry; + +/** + * A PI translation store that keeps track of which flow rules have been + * translated to which PI table entries. + */ +@Beta +public interface PiFlowRuleTranslationStore + extends PiTranslationStore { +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java new file mode 100644 index 0000000000..cc82f73350 --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiFlowRuleTranslator.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.pi.runtime.PiTableEntry; + +/** + * A translator of flow rules to PI table entries. + */ +@Beta +public interface PiFlowRuleTranslator + extends PiTranslator { +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java new file mode 100644 index 0000000000..4fe526a35f --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslationStore.java @@ -0,0 +1,30 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; +import org.onosproject.net.group.Group; +import org.onosproject.net.pi.runtime.PiActionGroup; + +/** + * A PI translation store that keeps track of which groups have been + * translated to which PI action groups. + */ +@Beta +public interface PiGroupTranslationStore + extends PiTranslationStore { +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java new file mode 100644 index 0000000000..d5eb5af7c2 --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiGroupTranslator.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; +import org.onosproject.net.group.Group; +import org.onosproject.net.pi.runtime.PiActionGroup; + +/** + * A translator of groups to PI action groups. + */ +@Beta +public interface PiGroupTranslator + extends PiTranslator { +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java index 8914eeeb0f..4ca094bec5 100644 --- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslatedEntity.java @@ -17,29 +17,34 @@ package org.onosproject.net.pi.service; import com.google.common.annotations.Beta; -import org.onosproject.net.pi.model.PiPipeconfId; import org.onosproject.net.pi.runtime.PiEntity; import org.onosproject.net.pi.runtime.PiEntityType; +import org.onosproject.net.pi.runtime.PiHandle; import static com.google.common.base.Preconditions.checkNotNull; /** - * Representation of the result of a PD-to-PI translation. + * Representation of the result of a PD-to-PI translation associated to a PI + * entity handle. */ @Beta -public final class PiTranslatedEntity { +public final class PiTranslatedEntity { - private final PiTranslatable original; - private final PiEntity translated; - private final PiPipeconfId pipeconfId; - private final PiEntityType type; + private final T original; + private final E translated; + private final PiHandle handle; - public PiTranslatedEntity(PiTranslatable original, PiEntity translated, - PiPipeconfId pipeconfId) { + /** + * Creates a new translated entity. + * + * @param original PD entity + * @param translated PI entity + * @param handle PI entity handle + */ + public PiTranslatedEntity(T original, E translated, PiHandle handle) { this.original = checkNotNull(original); this.translated = checkNotNull(translated); - this.pipeconfId = checkNotNull(pipeconfId); - this.type = checkNotNull(translated.piEntityType()); + this.handle = checkNotNull(handle); } /** @@ -48,7 +53,7 @@ public final class PiTranslatedEntity { * @return type of the translated entity */ public final PiEntityType entityType() { - return type; + return translated.piEntityType(); } /** @@ -56,7 +61,7 @@ public final class PiTranslatedEntity { * * @return instance of PI translatable entity */ - public final PiTranslatable original() { + public final T original() { return original; } @@ -65,18 +70,16 @@ public final class PiTranslatedEntity { * * @return PI entity */ - public final PiEntity translated() { + public final E translated() { return translated; } /** - * The ID of the pipeconf for which this translation is valid. In other - * words, the PI entity is guaranteed to be functionally equivalent to the - * PD one when applied to a device configured with such pipeconf. + * Returns the PI entity handle. * - * @return PI pipeconf ID + * @return PI entity handle */ - public final PiPipeconfId pipeconfId() { - return pipeconfId; + public final PiHandle handle() { + return handle; } } diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java index 4f590793f7..9e2411d88d 100644 --- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationEvent.java @@ -18,14 +18,15 @@ package org.onosproject.net.pi.service; import com.google.common.annotations.Beta; import org.onosproject.event.AbstractEvent; +import org.onosproject.net.pi.runtime.PiEntity; /** * Signals an event related to the translation of a protocol-dependent (PD) * entity to a protocol-independent (PI) one. */ @Beta -public final class PiTranslationEvent - extends AbstractEvent { +public final class PiTranslationEvent + extends AbstractEvent> { /** * Type of event. @@ -50,7 +51,7 @@ public final class PiTranslationEvent * @param type type of event * @param subject subject of event */ - public PiTranslationEvent(Type type, PiTranslatedEntity subject) { + public PiTranslationEvent(Type type, PiTranslatedEntity subject) { super(type, subject); } } diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java new file mode 100644 index 0000000000..d8a6c63706 --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; + +/** + * Signals that an error was encountered while translating an entity. + */ +@Beta +public final class PiTranslationException extends Exception { + + /** + * Creates a new exception with the given message. + * + * @param message a message + */ + public PiTranslationException(String message) { + super(message); + } +} diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java index 6af3e8371a..c7a95c37cc 100644 --- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationService.java @@ -17,14 +17,6 @@ package org.onosproject.net.pi.service; import com.google.common.annotations.Beta; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.group.Group; -import org.onosproject.net.pi.model.PiPipeconf; -import org.onosproject.net.pi.model.PiPipeconfId; -import org.onosproject.net.pi.runtime.PiActionGroup; -import org.onosproject.net.pi.runtime.PiTableEntry; - -import java.util.Optional; /** * A service to translate protocol-dependent (PD) entities to @@ -34,65 +26,16 @@ import java.util.Optional; public interface PiTranslationService { /** - * Returns a PI table entry equivalent to the given flow rule for the given - * protocol-independent pipeline configuration. + * Returns a flow rule translator. * - * @param rule a flow rule - * @param pipeconf a pipeline configuration - * @return a table entry - * @throws PiTranslationException if the flow rule cannot be translated + * @return flow rule translator */ - PiTableEntry translate(FlowRule rule, PiPipeconf pipeconf) - throws PiTranslationException; + PiFlowRuleTranslator flowRuleTranslator(); /** - * Returns a PI action group equivalent to the given group for the given - * protocol-independent pipeline configuration. + * Returns a group translator. * - * @param group a group - * @param pipeconf a pipeline configuration - * @return a PI action group - * @throws PiTranslationException if the group cannot be translated + * @return group translator */ - PiActionGroup translate(Group group, PiPipeconf pipeconf) - throws PiTranslationException; - - /** - * Returns a flow rule previously translated to the given PI table entry, - * for the given pipeconf ID, if present. If not present it means that such - * flow rule was never translated in the first place. - * - * @param piTableEntry PI table entry - * @param pipeconfId pipeconf ID - * @return optional flow rule - */ - Optional lookup(PiTableEntry piTableEntry, - PiPipeconfId pipeconfId); - - /** - * Returns a group previously translated to the given PI action group, for - * the given pipeconf ID, if present. If not present it means that such - * group was never translated in the first place. - * - * @param piActionGroup PI action group - * @param pipeconfId pipeconf ID - * @return optional group - */ - Optional lookup(PiActionGroup piActionGroup, - PiPipeconfId pipeconfId); - - /** - * Signals that an error was encountered while translating an entity. - */ - class PiTranslationException extends Exception { - - /** - * Creates a new exception with the given message. - * - * @param message a message - */ - public PiTranslationException(String message) { - super(message); - } - } + PiGroupTranslator groupTranslator(); } diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java index 6e0dec7db4..6274debbe9 100644 --- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStore.java @@ -17,55 +17,44 @@ package org.onosproject.net.pi.service; import com.google.common.annotations.Beta; -import org.onosproject.net.pi.model.PiPipeconfId; import org.onosproject.net.pi.runtime.PiEntity; +import org.onosproject.net.pi.runtime.PiHandle; import org.onosproject.store.Store; /** - * PI translation service store abstraction that acts as a multi-language - * dictionary. For each pipeconf ID (language) it maintains a mapping between a - * protocol-dependent (PD) entity and an equivalent protocol-independent (PI) - * one. + * PI translation store abstraction that maintains a mapping between a PI entity + * handle and a translated entity. + * + * @param PD entity class (translatable to PI) + * @param PI entity class */ @Beta -public interface PiTranslationStore - extends Store { +public interface PiTranslationStore + extends Store, PiTranslationStoreDelegate> { /** - * Adds or update a mapping between the given PD entity (original) and the - * translated PI counterpart, for the given pipeconf ID. + * Adds or update a mapping between the given PI entity handle and + * translated entity. * - * @param original PD entity - * @param translated PI entity - * @param pipeconfId pipeconf ID + * @param handle PI entity handle + * @param entity PI translated entity */ - void addOrUpdate(PiTranslatable original, PiEntity translated, - PiPipeconfId pipeconfId); + void addOrUpdate(PiHandle handle, PiTranslatedEntity entity); /** - * Removes a previously added mapping for the given PI entity and pipeconf + * Returns a PI translated entity for the given handle. Returns null if this + * store does not contain a mapping between the two for the given pipeconf * ID. * - * @param piEntity PI entity - * @param pipeconfId pipeconf ID + * @param handle PI entity handle + * @return PI translated entity */ - void remove(PiEntity piEntity, PiPipeconfId pipeconfId); + PiTranslatedEntity get(PiHandle handle); /** - * Removes all previously learned mappings for the given pipeconf ID. + * Removes a previously added mapping for the given PI entity handle. * - * @param pipeconfId pipeconf ID + * @param handle PI entity handle */ - void removeAll(PiPipeconfId pipeconfId); - - /** - * Returns a PD entity for the given PI one and pipeconf ID. Returns null if - * this store does not contain a mapping between the two for the given - * pipeconf ID. - * - * @param piEntity PI entity - * @param pipeconfId pipeconf ID - * @return PD entity or null - */ - PiTranslatable lookup(PiEntity piEntity, PiPipeconfId pipeconfId); + void remove(PiHandle handle); } diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java index 0fe5c75ed1..2a8d16f42b 100644 --- a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslationStoreDelegate.java @@ -17,12 +17,17 @@ package org.onosproject.net.pi.service; import com.google.common.annotations.Beta; +import org.onosproject.net.pi.runtime.PiEntity; import org.onosproject.store.StoreDelegate; /** - * PI translation service store delegate abstraction. + * PI translation store delegate abstraction. + * + * @param PD entity class (translatable to PI) + * @param PI entity class */ @Beta public interface PiTranslationStoreDelegate - extends StoreDelegate { + + extends StoreDelegate> { } diff --git a/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java new file mode 100644 index 0000000000..202636abe6 --- /dev/null +++ b/core/api/src/main/java/org/onosproject/net/pi/service/PiTranslator.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017-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.net.pi.service; + +import com.google.common.annotations.Beta; +import org.onosproject.net.pi.model.PiPipeconf; +import org.onosproject.net.pi.runtime.PiEntity; +import org.onosproject.net.pi.runtime.PiHandle; + +import java.util.Optional; + +/** + * A translator of PI entities to equivalent PD ones which offer means to learn + * translated entities for later use. + * + * @param PD entity class (translatable to PI) + * @param PI entity class + */ +@Beta +public interface PiTranslator { + + /** + * Translate the given PD entity (original) and returns a PI entity that is + * equivalent to he PD one for the given pipeconf. + * + * @param original PD entity + * @param pipeconf pipeconf + * @return PI entity + * @throws PiTranslationException if a translation is not possible (see + * message for an explanation) + */ + E translate(T original, PiPipeconf pipeconf) + throws PiTranslationException; + + /** + * Stores a mapping between the given translated entity and handle. + * + * @param handle PI entity handle + * @param entity PI translated entity + */ + void learn(PiHandle handle, PiTranslatedEntity entity); + + /** + * Returns a PI translated entity that was previously associated with the + * given handle, if present. If not present, it means a mapping between the + * two has not been learned by the system (via {@link #learn(PiHandle, + * PiTranslatedEntity)}) or that it has been removed (via {@link + * #forget(PiHandle)}). the + * + * @param handle PI entity handle + * @return optional PI translated entity + */ + Optional> lookup(PiHandle handle); + + /** + * Removes any mapping for the given PI entity handle. + * + * @param handle PI entity handle. + */ + void forget(PiHandle handle); +} diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java new file mode 100644 index 0000000000..5d7178c645 --- /dev/null +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/AbstractPiTranslatorImpl.java @@ -0,0 +1,58 @@ +/* + * Copyright 2017-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.net.pi.impl; + +import org.onosproject.net.pi.runtime.PiEntity; +import org.onosproject.net.pi.runtime.PiHandle; +import org.onosproject.net.pi.service.PiTranslatable; +import org.onosproject.net.pi.service.PiTranslatedEntity; +import org.onosproject.net.pi.service.PiTranslationStore; +import org.onosproject.net.pi.service.PiTranslator; + +import java.util.Optional; + +/** + * Abstract implementation of a PI translator backed by a PI translation store. + * + * @param PD entity class + * @param PI entity class + */ +public abstract class AbstractPiTranslatorImpl + + implements PiTranslator { + + private final PiTranslationStore store; + + AbstractPiTranslatorImpl(PiTranslationStore store) { + this.store = store; + } + + @Override + public void learn(PiHandle handle, PiTranslatedEntity entity) { + store.addOrUpdate(handle, entity); + } + + @Override + public Optional> lookup(PiHandle handle) { + return Optional.ofNullable(store.get(handle)); + } + + @Override + public void forget(PiHandle handle) { + store.remove(handle); + } +} diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java index 22d53fd3ef..7f43e2247d 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/CriterionTranslatorHelper.java @@ -86,13 +86,13 @@ import org.onosproject.net.pi.runtime.PiExactFieldMatch; import org.onosproject.net.pi.runtime.PiFieldMatch; import org.onosproject.net.pi.runtime.PiLpmFieldMatch; import org.onosproject.net.pi.runtime.PiTernaryFieldMatch; +import org.onosproject.net.pi.service.PiTranslationException; import java.util.Map; import static java.lang.String.format; import static org.onlab.util.ImmutableByteSequence.ByteSequenceTrimException; import static org.onosproject.net.pi.impl.CriterionTranslator.CriterionTranslatorException; -import static org.onosproject.net.pi.service.PiTranslationService.PiTranslationException; /** * Helper class to translate criterion instances to PI field matches. diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java similarity index 99% rename from core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java rename to core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java index d856fd3bfb..f04e7b0be3 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java @@ -46,6 +46,7 @@ import org.onosproject.net.pi.runtime.PiRangeFieldMatch; import org.onosproject.net.pi.runtime.PiTableAction; import org.onosproject.net.pi.runtime.PiTableEntry; import org.onosproject.net.pi.runtime.PiTernaryFieldMatch; +import org.onosproject.net.pi.service.PiTranslationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,17 +63,16 @@ import static org.onosproject.net.flow.criteria.Criterion.Type.PROTOCOL_INDEPEND import static org.onosproject.net.pi.impl.CriterionTranslatorHelper.translateCriterion; import static org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull; import static org.onosproject.net.pi.impl.PiUtils.translateTableId; -import static org.onosproject.net.pi.service.PiTranslationService.PiTranslationException; /** * Implementation of flow rule translation logic. */ -final class PiFlowRuleTranslator { +final class PiFlowRuleTranslatorImpl { public static final int MAX_PI_PRIORITY = (int) Math.pow(2, 24); - private static final Logger log = LoggerFactory.getLogger(PiFlowRuleTranslator.class); + private static final Logger log = LoggerFactory.getLogger(PiFlowRuleTranslatorImpl.class); - private PiFlowRuleTranslator() { + private PiFlowRuleTranslatorImpl() { // Hide constructor. } diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java similarity index 95% rename from core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java rename to core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java index 255ccb90ad..eeabebce75 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslator.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiGroupTranslatorImpl.java @@ -29,21 +29,21 @@ import org.onosproject.net.pi.runtime.PiActionGroupMember; import org.onosproject.net.pi.runtime.PiActionGroupMemberId; import org.onosproject.net.pi.runtime.PiGroupKey; import org.onosproject.net.pi.runtime.PiTableAction; -import org.onosproject.net.pi.service.PiTranslationService.PiTranslationException; +import org.onosproject.net.pi.service.PiTranslationException; import java.nio.ByteBuffer; import static java.lang.String.format; -import static org.onosproject.net.pi.impl.PiFlowRuleTranslator.translateTreatment; +import static org.onosproject.net.pi.impl.PiFlowRuleTranslatorImpl.translateTreatment; import static org.onosproject.net.pi.impl.PiUtils.getInterpreterOrNull; import static org.onosproject.net.pi.runtime.PiTableAction.Type.ACTION; /** * Implementation of group translation logic. */ -final class PiGroupTranslator { +final class PiGroupTranslatorImpl { - private PiGroupTranslator() { + private PiGroupTranslatorImpl() { // Hides constructor. } diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java index b6d90f0d46..9780fac2fd 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiTranslationServiceImpl.java @@ -28,19 +28,19 @@ import org.onosproject.net.device.DeviceService; import org.onosproject.net.flow.FlowRule; import org.onosproject.net.group.Group; import org.onosproject.net.pi.model.PiPipeconf; -import org.onosproject.net.pi.model.PiPipeconfId; import org.onosproject.net.pi.runtime.PiActionGroup; import org.onosproject.net.pi.runtime.PiTableEntry; -import org.onosproject.net.pi.service.PiTranslatable; +import org.onosproject.net.pi.service.PiFlowRuleTranslationStore; +import org.onosproject.net.pi.service.PiFlowRuleTranslator; +import org.onosproject.net.pi.service.PiGroupTranslationStore; +import org.onosproject.net.pi.service.PiGroupTranslator; +import org.onosproject.net.pi.service.PiTranslationException; import org.onosproject.net.pi.service.PiTranslationService; -import org.onosproject.net.pi.service.PiTranslationStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Optional; - /** - * Implementation of the protocol-independent translation service. + * Implementation of the PI translation service. */ @Component(immediate = true) @Service @@ -54,58 +54,76 @@ public class PiTranslationServiceImpl implements PiTranslationService { protected DeviceService deviceService; @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - private PiTranslationStore translationStore; + private PiFlowRuleTranslationStore flowRuleTranslationStore; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + private PiGroupTranslationStore groupTranslationStore; + + private PiFlowRuleTranslator flowRuleTranslator; + private PiGroupTranslator groupTranslator; @Activate public void activate() { + flowRuleTranslator = new InternalFlowRuleTranslator(flowRuleTranslationStore); + groupTranslator = new InternalGroupTranslator(groupTranslationStore); log.info("Started"); } @Deactivate public void deactivate() { + flowRuleTranslator = null; + groupTranslator = null; log.info("Stopped"); } @Override - public PiTableEntry translate(FlowRule rule, PiPipeconf pipeconf) - throws PiTranslationException { - final PiTableEntry piTableEntry = PiFlowRuleTranslator - .translate(rule, pipeconf, getDevice(rule.deviceId())); - translationStore.addOrUpdate(rule, piTableEntry, pipeconf.id()); - return piTableEntry; + public PiFlowRuleTranslator flowRuleTranslator() { + return flowRuleTranslator; } @Override - public Optional lookup(PiTableEntry piTableEntry, - PiPipeconfId pipeconfId) { - final PiTranslatable original = translationStore - .lookup(piTableEntry, pipeconfId); - return original == null - ? Optional.empty() - : Optional.of((FlowRule) original); - } - - @Override - public PiActionGroup translate(Group group, PiPipeconf pipeconf) - throws PiTranslationException { - return PiGroupTranslator.translate(group, pipeconf, - getDevice(group.deviceId())); - } - - @Override - public Optional lookup(PiActionGroup piActionGroup, - PiPipeconfId pipeconfId) { - // TODO: implement learning and lookup of groups - return Optional.empty(); + public PiGroupTranslator groupTranslator() { + return groupTranslator; } private Device getDevice(DeviceId deviceId) throws PiTranslationException { final Device device = deviceService.getDevice(deviceId); if (device == null) { - throw new PiTranslationException( - "Unable to get device " + deviceId); + throw new PiTranslationException("Unable to get device " + deviceId); } return device; } + + private final class InternalFlowRuleTranslator + extends AbstractPiTranslatorImpl + implements PiFlowRuleTranslator { + + private InternalFlowRuleTranslator(PiFlowRuleTranslationStore store) { + super(store); + } + + @Override + public PiTableEntry translate(FlowRule original, PiPipeconf pipeconf) + throws PiTranslationException { + return PiFlowRuleTranslatorImpl + .translate(original, pipeconf, getDevice(original.deviceId())); + } + } + + private final class InternalGroupTranslator + extends AbstractPiTranslatorImpl + implements PiGroupTranslator { + + private InternalGroupTranslator(PiGroupTranslationStore store) { + super(store); + } + + @Override + public PiActionGroup translate(Group original, PiPipeconf pipeconf) + throws PiTranslationException { + return PiGroupTranslatorImpl + .translate(original, pipeconf, getDevice(original.deviceId())); + } + } } diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java index 6e93d67cb1..78bca5fb41 100644 --- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java +++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiUtils.java @@ -22,7 +22,7 @@ import org.onosproject.net.flow.TableId; import org.onosproject.net.pi.model.PiPipeconf; import org.onosproject.net.pi.model.PiPipelineInterpreter; import org.onosproject.net.pi.model.PiTableId; -import org.onosproject.net.pi.service.PiTranslationService; +import org.onosproject.net.pi.service.PiTranslationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -60,23 +60,23 @@ final class PiUtils { } static PiTableId translateTableId(TableId tableId, PiPipelineInterpreter interpreter) - throws PiTranslationService.PiTranslationException { + throws PiTranslationException { switch (tableId.type()) { case PIPELINE_INDEPENDENT: return (PiTableId) tableId; case INDEX: IndexTableId indexId = (IndexTableId) tableId; if (interpreter == null) { - throw new PiTranslationService.PiTranslationException(format( + throw new PiTranslationException(format( "Unable to map table ID '%d' from index to PI: missing interpreter", indexId.id())); } else if (!interpreter.mapFlowRuleTableId(indexId.id()).isPresent()) { - throw new PiTranslationService.PiTranslationException(format( + throw new PiTranslationException(format( "Unable to map table ID '%d' from index to PI: missing ID in interpreter", indexId.id())); } else { return interpreter.mapFlowRuleTableId(indexId.id()).get(); } default: - throw new PiTranslationService.PiTranslationException(format( + throw new PiTranslationException(format( "Unrecognized table ID type %s", tableId.type().name())); } } diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java index d13def7cc3..9a80e9f2eb 100644 --- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java +++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java @@ -67,7 +67,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.onlab.util.ImmutableByteSequence.copyFrom; import static org.onlab.util.ImmutableByteSequence.fit; import static org.onosproject.net.group.GroupDescription.Type.SELECT; -import static org.onosproject.net.pi.impl.PiFlowRuleTranslator.MAX_PI_PRIORITY; +import static org.onosproject.net.pi.impl.PiFlowRuleTranslatorImpl.MAX_PI_PRIORITY; import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRF_WCMP_SELECTOR_ID; import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRM_PORT_ID; import static org.onosproject.pipelines.basic.BasicConstants.ACT_SET_EGRESS_PORT_ID; @@ -80,7 +80,7 @@ import static org.onosproject.pipelines.basic.BasicConstants.TBL_TABLE0_ID; import static org.onosproject.pipelines.basic.BasicConstants.TBL_WCMP_TABLE_ID; /** - * Tests for {@link PiFlowRuleTranslator}. + * Tests for {@link PiFlowRuleTranslatorImpl}. */ @SuppressWarnings("ConstantConditions") public class PiTranslatorServiceTest { @@ -161,8 +161,8 @@ public class PiTranslatorServiceTest { .withPriority(priority) .build(); - PiTableEntry entry1 = PiFlowRuleTranslator.translate(rule1, pipeconf, null); - PiTableEntry entry2 = PiFlowRuleTranslator.translate(rule1, pipeconf, null); + PiTableEntry entry1 = PiFlowRuleTranslatorImpl.translate(rule1, pipeconf, null); + PiTableEntry entry2 = PiFlowRuleTranslatorImpl.translate(rule1, pipeconf, null); // check equality, i.e. same rules must produce same entries new EqualsTester() @@ -236,8 +236,8 @@ public class PiTranslatorServiceTest { @Test public void testTranslateGroups() throws Exception { - PiActionGroup piGroup1 = PiGroupTranslator.translate(GROUP, pipeconf, null); - PiActionGroup piGroup2 = PiGroupTranslator.translate(GROUP, pipeconf, null); + PiActionGroup piGroup1 = PiGroupTranslatorImpl.translate(GROUP, pipeconf, null); + PiActionGroup piGroup2 = PiGroupTranslatorImpl.translate(GROUP, pipeconf, null); new EqualsTester() .addEqualityGroup(piGroup1, piGroup2) diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java new file mode 100644 index 0000000000..9df6a86b61 --- /dev/null +++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/AbstractDistributedPiTranslationStore.java @@ -0,0 +1,143 @@ +/* + * Copyright 2017-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.store.pi.impl; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onosproject.net.pi.runtime.PiEntity; +import org.onosproject.net.pi.runtime.PiHandle; +import org.onosproject.net.pi.service.PiTranslatable; +import org.onosproject.net.pi.service.PiTranslatedEntity; +import org.onosproject.net.pi.service.PiTranslationEvent; +import org.onosproject.net.pi.service.PiTranslationStore; +import org.onosproject.net.pi.service.PiTranslationStoreDelegate; +import org.onosproject.store.AbstractStore; +import org.onosproject.store.serializers.KryoNamespaces; +import org.onosproject.store.service.EventuallyConsistentMap; +import org.onosproject.store.service.EventuallyConsistentMapEvent; +import org.onosproject.store.service.EventuallyConsistentMapListener; +import org.onosproject.store.service.StorageService; +import org.onosproject.store.service.WallClockTimestamp; +import org.slf4j.Logger; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Distributed implementation of PiTranslationStore. + */ +@Component(immediate = true) +public abstract class AbstractDistributedPiTranslationStore + + extends AbstractStore, PiTranslationStoreDelegate> + implements PiTranslationStore { + + private static final String MAP_NAME_TEMPLATE = "onos-pi-translated-%s-map"; + + private final Logger log = getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + private EventuallyConsistentMap, PiTranslatedEntity> + translatedEntities; + + private final EventuallyConsistentMapListener + , PiTranslatedEntity> entityMapListener = + new InternalEntityMapListener(); + + /** + * Returns a string that identifies the map maintained by this store among + * others that uses this abstract class. + * + * @return string + */ + protected abstract String mapSimpleName(); + + @Activate + public void activate() { + final String fullMapName = format(MAP_NAME_TEMPLATE, mapSimpleName()); + translatedEntities = storageService + ., PiTranslatedEntity>eventuallyConsistentMapBuilder() + .withName(fullMapName) + .withSerializer(KryoNamespaces.API) + .withTimestampProvider((k, v) -> new WallClockTimestamp()) + .build(); + translatedEntities.addListener(entityMapListener); + log.info("Started"); + } + + @Deactivate + public void deactivate() { + translatedEntities.removeListener(entityMapListener); + translatedEntities = null; + log.info("Stopped"); + } + + @Override + public void addOrUpdate(PiHandle handle, PiTranslatedEntity entity) { + checkNotNull(handle); + checkNotNull(entity); + checkArgument(handle.entityType().equals(entity.entityType()), + "Entity type must be the same for handle and translated entity"); + translatedEntities.put(handle, entity); + } + + @Override + public void remove(PiHandle handle) { + checkNotNull(handle); + translatedEntities.remove(handle); + } + + @Override + public PiTranslatedEntity get(PiHandle handle) { + checkNotNull(handle); + return translatedEntities.get(handle); + } + + public Iterable> getAll() { + return translatedEntities.values(); + } + + private class InternalEntityMapListener + implements EventuallyConsistentMapListener + , PiTranslatedEntity> { + + @Override + public void event(EventuallyConsistentMapEvent, + PiTranslatedEntity> event) { + final PiTranslationEvent.Type type; + switch (event.type()) { + case PUT: + type = PiTranslationEvent.Type.LEARNED; + break; + case REMOVE: + type = PiTranslationEvent.Type.FORGOT; + break; + default: + throw new IllegalArgumentException( + "Unknown event type " + event.type().name()); + } + notifyDelegate(new PiTranslationEvent<>(type, event.value())); + } + } +} diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java new file mode 100644 index 0000000000..c123ec5efc --- /dev/null +++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiFlowRuleTranslationStore.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017-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.store.pi.impl; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.net.flow.FlowRule; +import org.onosproject.net.pi.runtime.PiTableEntry; +import org.onosproject.net.pi.service.PiFlowRuleTranslationStore; + +/** + * Distributed implementation of a PI translation store for flow rules. + */ +@Component(immediate = true) +@Service +public class DistributedPiFlowRuleTranslationStore + extends AbstractDistributedPiTranslationStore + implements PiFlowRuleTranslationStore { + + private static final String MAP_SIMPLE_NAME = "flowrule"; + + @Override + protected String mapSimpleName() { + return MAP_SIMPLE_NAME; + } +} diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java new file mode 100644 index 0000000000..fa62ef1cea --- /dev/null +++ b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiGroupTranslationStore.java @@ -0,0 +1,40 @@ +/* + * Copyright 2017-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.store.pi.impl; + +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.net.group.Group; +import org.onosproject.net.pi.runtime.PiActionGroup; +import org.onosproject.net.pi.service.PiGroupTranslationStore; + +/** + * Distributed implementation of a PI translation store for groups. + */ +@Component(immediate = true) +@Service +public class DistributedPiGroupTranslationStore + extends AbstractDistributedPiTranslationStore + implements PiGroupTranslationStore { + + private static final String MAP_SIMPLE_NAME = "group"; + + @Override + protected String mapSimpleName() { + return MAP_SIMPLE_NAME; + } +} diff --git a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java b/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java deleted file mode 100644 index f19c746d21..0000000000 --- a/core/store/dist/src/main/java/org/onosproject/store/pi/impl/DistributedPiTranslationStore.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2017-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.store.pi.impl; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.pi.model.PiPipeconfId; -import org.onosproject.net.pi.runtime.PiEntity; -import org.onosproject.net.pi.service.PiTranslatable; -import org.onosproject.net.pi.service.PiTranslatedEntity; -import org.onosproject.net.pi.service.PiTranslationEvent; -import org.onosproject.net.pi.service.PiTranslationStore; -import org.onosproject.net.pi.service.PiTranslationStoreDelegate; -import org.onosproject.store.AbstractStore; -import org.onosproject.store.serializers.KryoNamespaces; -import org.onosproject.store.service.EventuallyConsistentMap; -import org.onosproject.store.service.EventuallyConsistentMapEvent; -import org.onosproject.store.service.EventuallyConsistentMapListener; -import org.onosproject.store.service.StorageService; -import org.onosproject.store.service.WallClockTimestamp; -import org.slf4j.Logger; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Distributed implementation of PiTranslationStore. - */ -@Component(immediate = true) -@Service -public class DistributedPiTranslationStore - extends AbstractStore - implements PiTranslationStore { - - private static final String DIST_MAP_NAME = "onos-pi-translated-entities-map"; - private final Logger log = getLogger(getClass()); - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected StorageService storageService; - - private EventuallyConsistentMap - translatedEntities; - - private final EventuallyConsistentMapListener entityMapListener = new InternalEntityMapListener(); - - @Activate - public void activate() { - translatedEntities = storageService - .eventuallyConsistentMapBuilder() - .withName(DIST_MAP_NAME) - .withSerializer(KryoNamespace.newBuilder() - .register(KryoNamespaces.API) - .register(PiTranslatedEntityKey.class) - .build()) - .withTimestampProvider((k, v) -> new WallClockTimestamp()) - .build(); - translatedEntities.addListener(entityMapListener); - log.info("Started"); - } - - @Deactivate - public void deactivate() { - translatedEntities.removeListener(entityMapListener); - translatedEntities = null; - log.info("Stopped"); - } - - @Override - public void addOrUpdate(PiTranslatable original, PiEntity translated, - PiPipeconfId pipeconfId) { - translatedEntities.put(PiTranslatedEntityKey.of(pipeconfId, translated), - new PiTranslatedEntity(original, translated, pipeconfId)); - } - - @Override - public void remove(PiEntity piEntity, PiPipeconfId pipeconfId) { - translatedEntities.remove( - PiTranslatedEntityKey.of(pipeconfId, piEntity)); - } - - @Override - public void removeAll(PiPipeconfId pipeconfId) { - // FIXME: this can be heavy, but we assume it won't be called that often - // How often we expect a pipeconf to be removed from the device/system? - final Set keysToRemove = translatedEntities - .keySet().parallelStream() - .filter(k -> k.pipeconfId.equals(pipeconfId)) - .collect(Collectors.toSet()); - keysToRemove.forEach(translatedEntities::remove); - } - - @Override - public PiTranslatable lookup(PiEntity piEntity, PiPipeconfId pipeconfId) { - PiTranslatedEntity translatedEntity = translatedEntities - .get(PiTranslatedEntityKey.of(pipeconfId, piEntity)); - return translatedEntity == null ? null : translatedEntity.original(); - } - - - private class InternalEntityMapListener - implements EventuallyConsistentMapListener - { - - @Override - public void event(EventuallyConsistentMapEvent event) { - final PiTranslationEvent.Type type; - switch (event.type()) { - case PUT: - type = PiTranslationEvent.Type.LEARNED; - break; - case REMOVE: - type = PiTranslationEvent.Type.FORGOT; - break; - default: - throw new IllegalArgumentException( - "Unknown event type " + event.type().name()); - } - notifyDelegate(new PiTranslationEvent(type, event.value())); - } - } - - /** - * Internal representation of a key that uniquely identifies a translated - * entity. - */ - private static final class PiTranslatedEntityKey { - - private final PiPipeconfId pipeconfId; - private final PiEntity piEntity; - - private PiTranslatedEntityKey(PiPipeconfId pipeconfId, - PiEntity piEntity) { - this.pipeconfId = pipeconfId; - this.piEntity = piEntity; - } - - public static PiTranslatedEntityKey of(PiPipeconfId pipeconfId, - PiEntity piEntity) { - return new PiTranslatedEntityKey(pipeconfId, piEntity); - } - - public static PiTranslatedEntityKey of(PiTranslatedEntity entity) { - return new PiTranslatedEntityKey(entity.pipeconfId(), - entity.translated()); - } - - @Override - public int hashCode() { - return Objects.hash(pipeconfId, piEntity); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final PiTranslatedEntityKey other = (PiTranslatedEntityKey) obj; - return Objects.equals(this.pipeconfId, other.pipeconfId) - && Objects.equals(this.piEntity, other.piEntity); - } - } -} diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java index 83b997d794..9a31b0c32f 100644 --- a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java +++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedDevicePipeconfMappingStoreTest.java @@ -119,4 +119,4 @@ public class DistributedDevicePipeconfMappingStoreTest { store.deviceToPipeconf.clear(); } -} \ No newline at end of file +} diff --git a/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java new file mode 100644 index 0000000000..2ba52a26df --- /dev/null +++ b/core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java @@ -0,0 +1,153 @@ +/* + * Copyright 2017-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.store.pi.impl; + +import com.google.common.collect.Lists; +import org.apache.commons.lang3.RandomUtils; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.net.DeviceId; +import org.onosproject.net.pi.runtime.PiEntity; +import org.onosproject.net.pi.runtime.PiEntityType; +import org.onosproject.net.pi.runtime.PiHandle; +import org.onosproject.net.pi.service.PiTranslatable; +import org.onosproject.net.pi.service.PiTranslatedEntity; +import org.onosproject.store.service.TestStorageService; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Test for {@link AbstractDistributedPiTranslationStore}. + */ +public class DistributedPiTranslationStoreTest { + + private AbstractDistributedPiTranslationStore store; + + private static final int HANDLE_HASH = RandomUtils.nextInt(); + private static final PiTranslatable PI_TRANSLATABLE = + new PiTranslatable() { + }; + private static final PiEntity PI_ENTITY = () -> PiEntityType.TABLE_ENTRY; + private static final PiHandle PI_HANDLE = + new PiHandle(DeviceId.NONE, PI_ENTITY) { + @Override + public int hashCode() { + return HANDLE_HASH; + } + + @Override + public boolean equals(Object other) { + return other instanceof PiHandle && other.hashCode() == hashCode(); + } + + @Override + public String toString() { + return String.valueOf(HANDLE_HASH); + } + }; + private static final PiTranslatedEntity TRANSLATED_ENTITY = + new PiTranslatedEntity<>(PI_TRANSLATABLE, PI_ENTITY, PI_HANDLE); + + /** + * Sets up the store and the storage service test harness. + */ + @Before + public void setUp() { + store = new AbstractDistributedPiTranslationStore() { + @Override + protected String mapSimpleName() { + return "test"; + } + }; + store.storageService = new TestStorageService(); + store.setDelegate(event -> { + }); + store.activate(); + } + + /** + * Tests equality of key and value used in other tests. + */ + @Test + public void testEquality() { + assertEquals(PI_HANDLE, PI_HANDLE); + assertEquals(TRANSLATED_ENTITY, TRANSLATED_ENTITY); + } + + /** + * Test for activate. + */ + @Test + public void activate() { + assertNotNull(store.storageService); + assertTrue("Store must have delegate", + store.hasDelegate()); + assertTrue("No value should be in the map", + Lists.newArrayList(store.getAll()).isEmpty()); + } + + /** + * Test for deactivate. + */ + @Test(expected = NullPointerException.class) + public void deactivate() { + store.deactivate(); + store.getAll(); + } + + /** + * Test of value add or update. + */ + @Test + public void addOrUpdate() { + store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY); + assertTrue("Value should be in the map", + store.get(PI_HANDLE) != null); + assertTrue("Exactly 1 value should be in the map", + Lists.newArrayList(store.getAll()).size() == 1); + + // Add again, expect 1 value. + store.addOrUpdate(PI_HANDLE, TRANSLATED_ENTITY); + assertTrue("Exactly 1 value should be in the map", + Lists.newArrayList(store.getAll()).size() == 1); + } + + /** + * Test of value lookup. + */ + @Test + public void lookup() throws Exception { + clear(); + addOrUpdate(); + assertEquals("Wrong value in the map", + store.get(PI_HANDLE), TRANSLATED_ENTITY); + } + + /** + * Test of value removal. + */ + @Test + public void clear() { + store.remove(PI_HANDLE); + assertTrue("Value should NOT be in the map", + store.get(PI_HANDLE) == null); + assertTrue("No value should be in the map", + Lists.newArrayList(store.getAll()).isEmpty()); + } +} diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java index 9c5cb82585..6a03032bf2 100644 --- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java +++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java @@ -220,6 +220,7 @@ import org.onosproject.net.pi.model.PiTableId; import org.onosproject.net.pi.model.PiTableType; import org.onosproject.net.pi.runtime.PiAction; import org.onosproject.net.pi.runtime.PiActionGroup; +import org.onosproject.net.pi.runtime.PiActionGroupHandle; import org.onosproject.net.pi.runtime.PiActionGroupId; import org.onosproject.net.pi.runtime.PiActionGroupMember; import org.onosproject.net.pi.runtime.PiActionGroupMemberId; @@ -232,6 +233,7 @@ import org.onosproject.net.pi.runtime.PiEntityType; import org.onosproject.net.pi.runtime.PiExactFieldMatch; import org.onosproject.net.pi.runtime.PiFieldMatch; import org.onosproject.net.pi.runtime.PiGroupKey; +import org.onosproject.net.pi.runtime.PiHandle; import org.onosproject.net.pi.runtime.PiLpmFieldMatch; import org.onosproject.net.pi.runtime.PiMatchKey; import org.onosproject.net.pi.runtime.PiPacketOperation; @@ -241,6 +243,7 @@ import org.onosproject.net.pi.runtime.PiTableAction; import org.onosproject.net.pi.runtime.PiTableEntry; import org.onosproject.net.pi.runtime.PiTernaryFieldMatch; import org.onosproject.net.pi.runtime.PiValidFieldMatch; +import org.onosproject.net.pi.runtime.PiTableEntryHandle; import org.onosproject.net.pi.service.PiTranslatable; import org.onosproject.net.pi.service.PiTranslatedEntity; import org.onosproject.net.provider.ProviderId; @@ -634,6 +637,7 @@ public final class KryoNamespaces { // PI Runtime PiAction.class, PiActionGroup.class, + PiActionGroupHandle.class, PiActionGroupId.class, PiActionGroupMember.class, PiActionGroupMemberId.class, @@ -646,6 +650,7 @@ public final class KryoNamespaces { PiExactFieldMatch.class, PiFieldMatch.class, PiGroupKey.class, + PiHandle.class, PiLpmFieldMatch.class, PiMatchKey.class, PiPacketOperation.class, @@ -656,6 +661,7 @@ public final class KryoNamespaces { PiTernaryFieldMatch.class, PiValidFieldMatch.class, // PI service + PiTableEntryHandle.class, PiTranslatedEntity.class, PiTranslatable.class, // Other 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 b216fcf51a..053dd7c98d 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 @@ -32,7 +32,7 @@ import org.onosproject.net.pi.model.PiTableModel; import org.onosproject.net.pi.runtime.PiCounterCellData; import org.onosproject.net.pi.runtime.PiCounterCellId; import org.onosproject.net.pi.runtime.PiTableEntry; -import org.onosproject.net.pi.service.PiTranslationService; +import org.onosproject.net.pi.service.PiTranslationException; import org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType; import org.onosproject.p4runtime.api.P4RuntimeFlowRuleWrapper; import org.onosproject.p4runtime.api.P4RuntimeTableEntryReference; @@ -242,8 +242,8 @@ public class P4RuntimeFlowRuleProgrammable extends AbstractP4RuntimeHandlerBehav PiTableEntry piTableEntry; try { - piTableEntry = piTranslationService.translate(rule, pipeconf); - } catch (PiTranslationService.PiTranslationException e) { + piTableEntry = piTranslationService.flowRuleTranslator().translate(rule, pipeconf); + } catch (PiTranslationException e) { log.warn("Unable to translate flow rule: {} - {}", e.getMessage(), rule); continue; // next rule } 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 a3139bc4cd..3cba2d5100 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 @@ -30,7 +30,7 @@ import org.onosproject.net.group.GroupStore; import org.onosproject.net.pi.model.PiActionProfileId; import org.onosproject.net.pi.runtime.PiActionGroup; import org.onosproject.net.pi.runtime.PiActionGroupId; -import org.onosproject.net.pi.service.PiTranslationService; +import org.onosproject.net.pi.service.PiTranslationException; import org.onosproject.p4runtime.api.P4RuntimeClient; import org.onosproject.p4runtime.api.P4RuntimeGroupReference; import org.onosproject.p4runtime.api.P4RuntimeGroupWrapper; @@ -103,8 +103,8 @@ public class P4RuntimeGroupProgrammable extends AbstractP4RuntimeHandlerBehaviou PiActionGroup piActionGroup; try { - piActionGroup = piTranslationService.translate(group, pipeconf); - } catch (PiTranslationService.PiTranslationException e) { + piActionGroup = piTranslationService.groupTranslator().translate(group, pipeconf); + } catch (PiTranslationException e) { log.warn("Unable translate group, aborting group operation {}: {}", groupOp.opType(), e.getMessage()); return; }