mirror of
https://github.com/opennetworkinglab/onos.git
synced 2026-05-05 04:06:49 +02:00
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
This commit is contained in:
parent
e2a1500ce0
commit
326ad2dd29
@ -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.
|
||||
*/
|
||||
|
||||
@ -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<PiActionGroup> {
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -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<E extends PiEntity> {
|
||||
|
||||
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();
|
||||
}
|
||||
@ -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<PiTableEntry> {
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -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<FlowRule, PiTableEntry> {
|
||||
}
|
||||
@ -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<FlowRule, PiTableEntry> {
|
||||
}
|
||||
@ -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<Group, PiActionGroup> {
|
||||
}
|
||||
@ -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<Group, PiActionGroup> {
|
||||
}
|
||||
@ -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<T extends PiTranslatable, E extends PiEntity> {
|
||||
|
||||
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<E> 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<E> 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<E> handle() {
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<PiTranslationEvent.Type, PiTranslatedEntity> {
|
||||
public final class PiTranslationEvent<T extends PiTranslatable, E extends PiEntity>
|
||||
extends AbstractEvent<PiTranslationEvent.Type, PiTranslatedEntity<T, E>> {
|
||||
|
||||
/**
|
||||
* 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<T, E> subject) {
|
||||
super(type, subject);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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<FlowRule> 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<Group> 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();
|
||||
}
|
||||
|
||||
@ -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 <T> PD entity class (translatable to PI)
|
||||
* @param <E> PI entity class
|
||||
*/
|
||||
@Beta
|
||||
public interface PiTranslationStore
|
||||
extends Store<PiTranslationEvent, PiTranslationStoreDelegate> {
|
||||
public interface PiTranslationStore<T extends PiTranslatable, E extends PiEntity>
|
||||
extends Store<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>> {
|
||||
|
||||
/**
|
||||
* 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<E> handle, PiTranslatedEntity<T, E> 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<T, E> get(PiHandle<E> 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<E> handle);
|
||||
}
|
||||
|
||||
@ -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 <T> PD entity class (translatable to PI)
|
||||
* @param <E> PI entity class
|
||||
*/
|
||||
@Beta
|
||||
public interface PiTranslationStoreDelegate
|
||||
extends StoreDelegate<PiTranslationEvent> {
|
||||
<T extends PiTranslatable, E extends PiEntity>
|
||||
extends StoreDelegate<PiTranslationEvent<T, E>> {
|
||||
}
|
||||
|
||||
@ -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 <T> PD entity class (translatable to PI)
|
||||
* @param <E> PI entity class
|
||||
*/
|
||||
@Beta
|
||||
public interface PiTranslator<T extends PiTranslatable, E extends PiEntity> {
|
||||
|
||||
/**
|
||||
* 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<E> handle, PiTranslatedEntity<T, E> 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<PiTranslatedEntity<T, E>> lookup(PiHandle<E> handle);
|
||||
|
||||
/**
|
||||
* Removes any mapping for the given PI entity handle.
|
||||
*
|
||||
* @param handle PI entity handle.
|
||||
*/
|
||||
void forget(PiHandle<E> handle);
|
||||
}
|
||||
@ -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 <T> PD entity class
|
||||
* @param <E> PI entity class
|
||||
*/
|
||||
public abstract class AbstractPiTranslatorImpl
|
||||
<T extends PiTranslatable, E extends PiEntity>
|
||||
implements PiTranslator<T, E> {
|
||||
|
||||
private final PiTranslationStore<T, E> store;
|
||||
|
||||
AbstractPiTranslatorImpl(PiTranslationStore<T, E> store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void learn(PiHandle<E> handle, PiTranslatedEntity<T, E> entity) {
|
||||
store.addOrUpdate(handle, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<PiTranslatedEntity<T, E>> lookup(PiHandle<E> handle) {
|
||||
return Optional.ofNullable(store.get(handle));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forget(PiHandle<E> handle) {
|
||||
store.remove(handle);
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
}
|
||||
|
||||
@ -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.
|
||||
}
|
||||
|
||||
@ -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<FlowRule> 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<Group> 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<FlowRule, PiTableEntry>
|
||||
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<Group, PiActionGroup>
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
<T extends PiTranslatable, E extends PiEntity>
|
||||
extends AbstractStore<PiTranslationEvent<T, E>, PiTranslationStoreDelegate<T, E>>
|
||||
implements PiTranslationStore<T, E> {
|
||||
|
||||
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<PiHandle<E>, PiTranslatedEntity<T, E>>
|
||||
translatedEntities;
|
||||
|
||||
private final EventuallyConsistentMapListener
|
||||
<PiHandle<E>, PiTranslatedEntity<T, E>> 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
|
||||
.<PiHandle<E>, PiTranslatedEntity<T, E>>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<E> handle, PiTranslatedEntity<T, E> 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<E> handle) {
|
||||
checkNotNull(handle);
|
||||
translatedEntities.remove(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PiTranslatedEntity<T, E> get(PiHandle<E> handle) {
|
||||
checkNotNull(handle);
|
||||
return translatedEntities.get(handle);
|
||||
}
|
||||
|
||||
public Iterable<PiTranslatedEntity<T, E>> getAll() {
|
||||
return translatedEntities.values();
|
||||
}
|
||||
|
||||
private class InternalEntityMapListener
|
||||
implements EventuallyConsistentMapListener
|
||||
<PiHandle<E>, PiTranslatedEntity<T, E>> {
|
||||
|
||||
@Override
|
||||
public void event(EventuallyConsistentMapEvent<PiHandle<E>,
|
||||
PiTranslatedEntity<T, E>> 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<FlowRule, PiTableEntry>
|
||||
implements PiFlowRuleTranslationStore {
|
||||
|
||||
private static final String MAP_SIMPLE_NAME = "flowrule";
|
||||
|
||||
@Override
|
||||
protected String mapSimpleName() {
|
||||
return MAP_SIMPLE_NAME;
|
||||
}
|
||||
}
|
||||
@ -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<Group, PiActionGroup>
|
||||
implements PiGroupTranslationStore {
|
||||
|
||||
private static final String MAP_SIMPLE_NAME = "group";
|
||||
|
||||
@Override
|
||||
protected String mapSimpleName() {
|
||||
return MAP_SIMPLE_NAME;
|
||||
}
|
||||
}
|
||||
@ -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<PiTranslationEvent, PiTranslationStoreDelegate>
|
||||
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<PiTranslatedEntityKey, PiTranslatedEntity>
|
||||
translatedEntities;
|
||||
|
||||
private final EventuallyConsistentMapListener<PiTranslatedEntityKey,
|
||||
PiTranslatedEntity> entityMapListener = new InternalEntityMapListener();
|
||||
|
||||
@Activate
|
||||
public void activate() {
|
||||
translatedEntities = storageService
|
||||
.<PiTranslatedEntityKey, PiTranslatedEntity>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<PiTranslatedEntityKey> 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
|
||||
<PiTranslatedEntityKey, PiTranslatedEntity> {
|
||||
|
||||
@Override
|
||||
public void event(EventuallyConsistentMapEvent<PiTranslatedEntityKey,
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -119,4 +119,4 @@ public class DistributedDevicePipeconfMappingStoreTest {
|
||||
store.deviceToPipeconf.clear();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
153
core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
vendored
Normal file
153
core/store/dist/src/test/java/org/onosproject/store/pi/impl/DistributedPiTranslationStoreTest.java
vendored
Normal file
@ -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<PiTranslatable, PiEntity> 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<PiEntity> PI_HANDLE =
|
||||
new PiHandle<PiEntity>(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<PiTranslatable, PiEntity> 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<PiTranslatable, PiEntity>() {
|
||||
@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());
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user