package org.opendaylight.openflowplugin.api;
import java.util.List;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowCookie;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
public static final short OFPP_LOCAL = (short)0xfffe;
/** openflow protocol 1.0 - version identifier. */
- public static final Uint8 OFP_VERSION_1_0 = Uint8.ONE;
+ public static final @NonNull Uint8 OFP_VERSION_1_0 = Uint8.ONE;
/** openflow protocol 1.3 - version identifier. */
- public static final Uint8 OFP_VERSION_1_3 = Uint8.valueOf(0x04);
+ public static final @NonNull Uint8 OFP_VERSION_1_3 = Uint8.valueOf(0x04);
public static final String OF_URI_PREFIX = "openflow:";
import static java.util.Objects.requireNonNull;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import java.util.Arrays;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yangtools.yang.common.Uint8;
/**
* Note: If you add a version here, make sure to update
* org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil as well.
*/
-// FIXME: enum in api is not something what we would like to see in case it is evolving.
+// FIXME: enum in api is not something what we would like to see in case it is evolving. On the other hand we have
+// static constants for well-known versions, so this is not *that* bad.
+@NonNullByDefault
public enum OpenflowVersion {
- OF10(Uint8.ONE),
- OF13(Uint8.valueOf(4)),
+ OF10(OFConstants.OFP_VERSION_1_0),
+ OF13(OFConstants.OFP_VERSION_1_3),
UNSUPPORTED(Uint8.ZERO);
- private static final ImmutableMap<Uint8, OpenflowVersion> VERSIONS = Maps.uniqueIndex(Arrays.asList(values()),
- OpenflowVersion::getVersion);
-
- private Uint8 version;
+ private final Uint8 version;
OpenflowVersion(final Uint8 version) {
this.version = requireNonNull(version);
}
+ @Deprecated
public static OpenflowVersion get(final Uint8 version) {
- final OpenflowVersion ver = VERSIONS.get(version);
- return ver != null ? ver : UNSUPPORTED;
+ return ofVersion(version);
+ }
+
+ public static OpenflowVersion ofVersion(final Uint8 version) {
+ if (OFConstants.OFP_VERSION_1_3.equals(version)) {
+ return OF13;
+ } else if (OFConstants.OFP_VERSION_1_0.equals(version)) {
+ return OF10;
+ } else {
+ return UNSUPPORTED;
+ }
}
/**
import org.opendaylight.openflowplugin.api.openflow.registry.CommonDeviceRegistry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
import org.opendaylight.yangtools.yang.common.Uint8;
/**
*/
public interface DeviceFlowRegistry extends CommonDeviceRegistry<FlowRegistryKey> {
+ @NonNull FlowRegistryKey createKey(@NonNull Flow flow);
+
ListenableFuture<List<Optional<FlowCapableNode>>> fill();
void storeDescriptor(@NonNull FlowRegistryKey flowRegistryKey, @NonNull FlowDescriptor flowDescriptor);
- @Nullable
- FlowDescriptor retrieveDescriptor(@NonNull FlowRegistryKey flowRegistryKey);
+ @Nullable FlowDescriptor retrieveDescriptor(@NonNull FlowRegistryKey flowRegistryKey);
void clearFlowRegistry();
provider.register(MultipartType.OFPMPQUEUE, new QueueStatsMultipartWriter(deviceContext,
instanceIdentifier, deviceContext.getPrimaryConnectionContext().getFeatures()));
provider.register(MultipartType.OFPMPFLOW, new FlowStatsMultipartWriter(deviceContext, instanceIdentifier,
- deviceContext, deviceContext.getDeviceInfo().getVersion()));
+ deviceContext));
provider.register(MultipartType.OFPMPGROUPDESC, new GroupDescMultipartWriter(deviceContext,
instanceIdentifier, deviceContext));
provider.register(MultipartType.OFPMPMETERCONFIG, new MeterConfigMultipartWriter(deviceContext,
*/
package org.opendaylight.openflowplugin.impl.datastore.multipart;
-import static java.util.Objects.requireNonNull;
-
import org.opendaylight.openflowplugin.api.openflow.device.DeviceRegistry;
import org.opendaylight.openflowplugin.api.openflow.device.TxFacade;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.flow.statistics.FlowStatisticsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.Uint8;
public class FlowStatsMultipartWriter extends AbstractMultipartWriter<FlowAndStatisticsMapList> {
private final DeviceRegistry registry;
- private final Uint8 version;
public FlowStatsMultipartWriter(final TxFacade txFacade,
final InstanceIdentifier<Node> instanceIdentifier,
- final DeviceRegistry registry,
- final Uint8 version) {
+ final DeviceRegistry registry) {
super(txFacade, instanceIdentifier);
this.registry = registry;
- this.version = requireNonNull(version);
}
@Override
public void storeStatistics(final FlowAndStatisticsMapList statistics, final boolean withParents) {
statistics.nonnullFlowAndStatisticsMapList()
.forEach(stat -> {
- final FlowBuilder flow = new FlowBuilder(stat)
+ final var flowBuilder = new FlowBuilder(stat)
.withKey(FlowRegistryKeyFactory.DUMMY_FLOW_KEY)
.addAugmentation(new FlowStatisticsDataBuilder()
.setFlowStatistics(new FlowStatisticsBuilder(stat).build())
.build());
- final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(version, flow.build());
- registry.getDeviceFlowRegistry().store(flowRegistryKey);
-
- final FlowDescriptor flowDescriptor = registry
- .getDeviceFlowRegistry()
- .retrieveDescriptor(flowRegistryKey);
+ final var flowRegistry = registry.getDeviceFlowRegistry();
+ final var flowRegistryKey = flowRegistry.createKey(flowBuilder.build());
+ flowRegistry.store(flowRegistryKey);
+ final var flowDescriptor = flowRegistry.retrieveDescriptor(flowRegistryKey);
if (flowDescriptor != null) {
final FlowKey key = new FlowKey(flowDescriptor.getFlowId());
.augmentation(FlowCapableNode.class)
.child(Table.class, new TableKey(stat.getTableId()))
.child(Flow.class, key),
- flow
+ flowBuilder
.setId(key.getId())
.withKey(key)
.build(),
import org.opendaylight.openflowplugin.impl.device.history.FlowGroupInfoHistoryAppender;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
private final BiMap<FlowRegistryKey, FlowDescriptor> flowRegistry = Maps.synchronizedBiMap(HashBiMap.create());
private final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier;
private final FlowGroupInfoHistoryAppender history;
- private final Consumer<Flow> flowConsumer;
+ private final FlowRegistryKeyFactory keyFactory;
private final DataBroker dataBroker;
public DeviceFlowRegistryImpl(final Uint8 version, final DataBroker dataBroker,
this.dataBroker = requireNonNull(dataBroker);
this.instanceIdentifier = requireNonNull(instanceIdentifier);
this.history = requireNonNull(history);
+ keyFactory = FlowRegistryKeyFactory.ofVersion(version);
+ }
- // Specifies what to do with flow read from data store
- flowConsumer = flow -> {
- final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(version, flow);
-
- if (getExistingKey(flowRegistryKey) == null) {
- // Now, we will update the registry
- storeDescriptor(flowRegistryKey, FlowDescriptorFactory.create(flow.getTableId(), flow.getId()));
- }
- };
+ @Override
+ public FlowRegistryKey createKey(
+ final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow flow) {
+ return keyFactory.create(flow);
}
@Override
public void onSuccess(final Optional<FlowCapableNode> result) {
result.ifPresent(flowCapableNode -> {
flowCapableNode.nonnullTable().values().stream()
- .filter(Objects::nonNull)
- .flatMap(table -> table.nonnullFlow().values().stream())
- .filter(Objects::nonNull)
- .filter(flow -> flow.getId() != null)
- .forEach(flowConsumer);
+ .filter(Objects::nonNull)
+ .flatMap(table -> table.nonnullFlow().values().stream())
+ .filter(Objects::nonNull)
+ .filter(flow -> flow.getId() != null)
+ .forEach(flow -> {
+ final var flowRegistryKey = createKey(flow);
+ if (getExistingKey(flowRegistryKey) == null) {
+ // Now, we will update the registry
+ storeDescriptor(flowRegistryKey, FlowDescriptorFactory.create(flow.getTableId(),
+ flow.getId()));
+ }
+ });
});
}
/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
*/
package org.opendaylight.openflowplugin.impl.registry.flow;
-import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElse;
-import java.util.Objects;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.Flow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
-import org.opendaylight.yangtools.yang.common.Uint16;
-import org.opendaylight.yangtools.yang.common.Uint64;
import org.opendaylight.yangtools.yang.common.Uint8;
public final class FlowRegistryKeyFactory {
// ... so we set a dummy value and overwrite it afterwards.
public static final FlowKey DUMMY_FLOW_KEY = new FlowKey(new FlowId("__DUMMY_ID_FOR_ALIEN__"));
- private FlowRegistryKeyFactory() {
- // Hide implicit constructor
- }
-
- public static @NonNull FlowRegistryKey create(final Uint8 version, final @NonNull Flow flow) {
- //TODO: mandatory flow input values (or default values) should be specified via yang model
- final Uint8 tableId = requireNonNull(flow.getTableId(), "flow tableId must not be null");
- final Uint16 priority = requireNonNullElse(flow.getPriority(), OFConstants.DEFAULT_FLOW_PRIORITY);
- final Uint64 cookie = requireNonNullElse(flow.getCookie(), OFConstants.DEFAULT_FLOW_COOKIE).getValue();
- Match match = MatchNormalizationUtil.normalizeMatch(
- requireNonNullElse(flow.getMatch(), OFConstants.EMPTY_MATCH), version);
- return new FlowRegistryKeyDto(tableId.toJava(), priority.toJava(), cookie, match);
- }
-
- private static final class FlowRegistryKeyDto implements FlowRegistryKey {
- private final short tableId;
- private final int priority;
- private final Uint64 cookie;
- private final Match match;
-
- private FlowRegistryKeyDto(final short tableId, final int priority, final @NonNull Uint64 cookie,
- final @NonNull Match match) {
- this.tableId = tableId;
- this.priority = priority;
- this.cookie = cookie;
- this.match = match;
- }
-
- @Override
- public boolean equals(final Object obj) {
- return this == obj || obj instanceof FlowRegistryKey that
- && priority == that.getPriority() && tableId == that.getTableId() && cookie.equals(that.getCookie())
- && equalMatch(that.getMatch());
- }
-
- private boolean equalMatch(final Match input) {
- GeneralAugMatchNodesNodeTableFlow thisAug = match.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
- GeneralAugMatchNodesNodeTableFlow inputAug = input.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
- if (thisAug != inputAug) {
- if (thisAug != null) {
- if (inputAug == null) {
- return false;
- }
- if (!Objects.equals(match.getEthernetMatch(), input.getEthernetMatch())) {
- return false;
- }
- if (!Objects.equals(match.getIcmpv4Match(), input.getIcmpv4Match())) {
- return false;
- }
- if (!Objects.equals(match.getIcmpv6Match(), input.getIcmpv6Match())) {
- return false;
- }
- if (!Objects.equals(match.getInPhyPort(), input.getInPhyPort())) {
- return false;
- }
- if (!Objects.equals(match.getInPort(), input.getInPort())) {
- return false;
- }
- if (!Objects.equals(match.getIpMatch(), input.getIpMatch())) {
- return false;
- }
- if (!Objects.equals(match.getLayer3Match(), input.getLayer3Match())) {
- return false;
- }
- if (!Objects.equals(match.getLayer4Match(), input.getLayer4Match())) {
- return false;
- }
- if (!Objects.equals(match.getMetadata(), input.getMetadata())) {
- return false;
- }
- if (!Objects.equals(match.getProtocolMatchFields(), input.getProtocolMatchFields())) {
- return false;
- }
- if (!Objects.equals(match.getTcpFlagsMatch(), input.getTcpFlagsMatch())) {
- return false;
- }
- if (!Objects.equals(match.getTunnel(), input.getTunnel())) {
- return false;
- }
- if (!Objects.equals(match.getVlanMatch(), input.getVlanMatch())) {
- return false;
- }
- for (var inputExtensionList : inputAug.nonnullExtensionList().values()) {
- if (!thisAug.nonnullExtensionList().containsValue(inputExtensionList)) {
- return false;
- }
- }
- }
- } else {
- return getMatch().equals(input);
+ public static final @NonNull FlowRegistryKeyFactory VERSION_1_0 =
+ new FlowRegistryKeyFactory(OFConstants.OFP_VERSION_1_0);
+ public static final @NonNull FlowRegistryKeyFactory VERSION_1_3 =
+ new FlowRegistryKeyFactory(OFConstants.OFP_VERSION_1_3);
+ private static final LoadingCache<Uint8, @NonNull FlowRegistryKeyFactory> CACHE = CacheBuilder.newBuilder()
+ .weakValues().build(new CacheLoader<>() {
+ @Override
+ public FlowRegistryKeyFactory load(final Uint8 key) {
+ return new FlowRegistryKeyFactory(key);
}
- return true;
- }
+ });
- @Override
- public int hashCode() {
- int result = tableId;
- result = 31 * result + priority;
- result = 31 * result + cookie.hashCode();
- result = 31 * result + match.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return "FlowRegistryKeyDto{"
- + "tableId=" + tableId
- + ", priority=" + priority
- + ", cookie=" + cookie
- + ", match=" + match
- + '}';
- }
-
- @Override
- public short getTableId() {
- return tableId;
- }
+ private final MatchNormalizationUtil matchNormalizer;
- @Override
- public int getPriority() {
- return priority;
- }
+ private FlowRegistryKeyFactory(final Uint8 version) {
+ matchNormalizer = MatchNormalizationUtil.ofVersion(version);
+ }
- @Override
- public Uint64 getCookie() {
- return cookie;
+ public static @NonNull FlowRegistryKeyFactory ofVersion(final Uint8 version) {
+ if (OFConstants.OFP_VERSION_1_3.equals(version)) {
+ return VERSION_1_3;
+ } else if (OFConstants.OFP_VERSION_1_0.equals(version)) {
+ return VERSION_1_0;
+ } else {
+ return CACHE.getUnchecked(version);
}
+ }
- @Override
- public Match getMatch() {
- return match;
- }
+ public @NonNull FlowRegistryKey create(final @NonNull Flow flow) {
+ // FIXME: mandatory flow input values (or default values) should be specified via YANG model
+ final var priority = requireNonNullElse(flow.getPriority(), OFConstants.DEFAULT_FLOW_PRIORITY);
+ final var cookie = requireNonNullElse(flow.getCookie(), OFConstants.DEFAULT_FLOW_COOKIE).getValue();
+ return new FlowRegistryKeyImpl(flow.requireTableId().toJava(), priority.toJava(), cookie,
+ matchNormalizer.normalizeMatch(requireNonNullElse(flow.getMatch(), OFConstants.EMPTY_MATCH)));
}
}
--- /dev/null
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.openflowplugin.impl.registry.flow;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Objects;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNodesNodeTableFlow;
+import org.opendaylight.yangtools.yang.common.Uint64;
+
+record FlowRegistryKeyImpl(
+ short tableId,
+ int priority,
+ @NonNull Uint64 cookie,
+ @NonNull Match match) implements FlowRegistryKey {
+
+ FlowRegistryKeyImpl {
+ requireNonNull(cookie);
+ requireNonNull(match);
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ return this == obj || obj instanceof FlowRegistryKey that
+ && priority == that.getPriority() && tableId == that.getTableId() && cookie.equals(that.getCookie())
+ && equalMatch(that.getMatch());
+ }
+
+ private boolean equalMatch(final Match input) {
+ GeneralAugMatchNodesNodeTableFlow thisAug = match.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
+ GeneralAugMatchNodesNodeTableFlow inputAug = input.augmentation(GeneralAugMatchNodesNodeTableFlow.class);
+ if (thisAug != inputAug) {
+ if (thisAug != null) {
+ if (inputAug == null) {
+ return false;
+ }
+ if (!Objects.equals(match.getEthernetMatch(), input.getEthernetMatch())) {
+ return false;
+ }
+ if (!Objects.equals(match.getIcmpv4Match(), input.getIcmpv4Match())) {
+ return false;
+ }
+ if (!Objects.equals(match.getIcmpv6Match(), input.getIcmpv6Match())) {
+ return false;
+ }
+ if (!Objects.equals(match.getInPhyPort(), input.getInPhyPort())) {
+ return false;
+ }
+ if (!Objects.equals(match.getInPort(), input.getInPort())) {
+ return false;
+ }
+ if (!Objects.equals(match.getIpMatch(), input.getIpMatch())) {
+ return false;
+ }
+ if (!Objects.equals(match.getLayer3Match(), input.getLayer3Match())) {
+ return false;
+ }
+ if (!Objects.equals(match.getLayer4Match(), input.getLayer4Match())) {
+ return false;
+ }
+ if (!Objects.equals(match.getMetadata(), input.getMetadata())) {
+ return false;
+ }
+ if (!Objects.equals(match.getProtocolMatchFields(), input.getProtocolMatchFields())) {
+ return false;
+ }
+ if (!Objects.equals(match.getTcpFlagsMatch(), input.getTcpFlagsMatch())) {
+ return false;
+ }
+ if (!Objects.equals(match.getTunnel(), input.getTunnel())) {
+ return false;
+ }
+ if (!Objects.equals(match.getVlanMatch(), input.getVlanMatch())) {
+ return false;
+ }
+ for (var inputExtensionList : inputAug.nonnullExtensionList().values()) {
+ if (!thisAug.nonnullExtensionList().containsValue(inputExtensionList)) {
+ return false;
+ }
+ }
+ }
+ } else {
+ return getMatch().equals(input);
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = tableId;
+ result = 31 * result + priority;
+ result = 31 * result + cookie.hashCode();
+ result = 31 * result + match.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "FlowRegistryKeyDto{"
+ + "tableId=" + tableId
+ + ", priority=" + priority
+ + ", cookie=" + cookie
+ + ", match=" + match
+ + '}';
+ }
+
+ @Override
+ public short getTableId() {
+ return tableId;
+ }
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ @Override
+ public Uint64 getCookie() {
+ return cookie;
+ }
+
+ @Override
+ public Match getMatch() {
+ return match;
+ }
+}
import com.google.common.util.concurrent.MoreExecutors;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput;
@Override
public final ListenableFuture<RpcResult<AddFlowOutput>> invoke(final AddFlowInput input) {
- final var flowRegistryKey = FlowRegistryKeyFactory.create(version(), input);
+ final var flowRegistry = flowRegistry();
+ final var flowRegistryKey = flowRegistry.createKey(input);
final var future = invokeImpl(input);
- Futures.addCallback(future, new AddFlowCallback(input, flowRegistry(), flowRegistryKey),
+ Futures.addCallback(future, new AddFlowCallback(input, flowRegistry, flowRegistryKey),
MoreExecutors.directExecutor());
return future;
}
@Override
public final ListenableFuture<RpcResult<RemoveFlowOutput>> invoke(final RemoveFlowInput input) {
final var future = invokeImpl(input);
- Futures.addCallback(future, new RemoveFlowCallback(input, flowRegistry(), version()),
- MoreExecutors.directExecutor());
+ Futures.addCallback(future, new RemoveFlowCallback(input, flowRegistry()), MoreExecutors.directExecutor());
return future;
}
@Override
public final ListenableFuture<RpcResult<UpdateFlowOutput>> invoke(final UpdateFlowInput input) {
final var future = invokeImpl(input);
- Futures.addCallback(future, new UpdateFlowCallback(input, flowRegistry(), version()),
- MoreExecutors.directExecutor());
+ Futures.addCallback(future, new UpdateFlowCallback(input, flowRegistry()), MoreExecutors.directExecutor());
return future;
}
import com.google.common.util.concurrent.FutureCallback;
import org.opendaylight.openflowplugin.api.openflow.FlowGroupStatus;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.openflowplugin.impl.util.ErrorUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
private final RemoveFlowInput input;
private final DeviceFlowRegistry flowRegistry;
- private final Uint8 version;
- RemoveFlowCallback(final RemoveFlowInput input, final DeviceFlowRegistry flowRegistry, final Uint8 version) {
+ RemoveFlowCallback(final RemoveFlowInput input, final DeviceFlowRegistry flowRegistry) {
this.input = requireNonNull(input);
this.flowRegistry = requireNonNull(flowRegistry);
- this.version = requireNonNull(version);
}
@Override
LOG.debug("Flow remove finished without error for flow={}", input);
}
if (input.getTableId() != null && !input.getTableId().equals(OFPTT_ALL)) {
- var flowRegistryKey = FlowRegistryKeyFactory.create(version, input);
+ var flowRegistryKey = flowRegistry.createKey(input);
flowRegistry.addMark(flowRegistryKey);
final FlowRef flowRef = input.getFlowRef();
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowDescriptorFactory;
-import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput;
private final UpdateFlowInput input;
private final DeviceFlowRegistry flowRegistry;
- private final Uint8 version;
- UpdateFlowCallback(final UpdateFlowInput input, final DeviceFlowRegistry flowRegistry, final Uint8 version) {
+ UpdateFlowCallback(final UpdateFlowInput input, final DeviceFlowRegistry flowRegistry) {
this.input = requireNonNull(input);
this.flowRegistry = requireNonNull(flowRegistry);
- this.version = requireNonNull(version);
}
@Override
public void onSuccess(final RpcResult<UpdateFlowOutput> updateFlowOutputRpcResult) {
final UpdatedFlow updated = input.getUpdatedFlow();
final OriginalFlow original = input.getOriginalFlow();
- final FlowRegistryKey origFlowRegistryKey = FlowRegistryKeyFactory.create(version, original);
- final FlowRegistryKey updatedFlowRegistryKey = FlowRegistryKeyFactory.create(version, updated);
+ final FlowRegistryKey origFlowRegistryKey = flowRegistry.createKey(original);
+ final FlowRegistryKey updatedFlowRegistryKey = flowRegistry.createKey(updated);
final FlowDescriptor origFlowDescriptor = flowRegistry.retrieveDescriptor(origFlowRegistryKey);
final boolean isUpdate = origFlowDescriptor != null;
extends AbstractMultipartService<I, T> {
private final MultipartType multipartType;
- private final OpenflowVersion ofVersion = OpenflowVersion.get(getVersion());
+ private final OpenflowVersion ofVersion = OpenflowVersion.ofVersion(getVersion());
private final ConvertorExecutor convertorExecutor;
private final MultipartWriterProvider multipartWriterProvider;
import com.google.common.util.concurrent.ListenableFuture;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.impl.datastore.MultipartWriterProvider;
import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
* @return generated flow ID
*/
protected FlowId generateFlowId(final FlowAndStatisticsMapList flowStatistics) {
- final FlowStatisticsDataBuilder flowStatisticsDataBld = new FlowStatisticsDataBuilder()
- .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build());
-
- final FlowBuilder flowBuilder = new FlowBuilder(flowStatistics)
+ final var flowRegistry = getDeviceRegistry().getDeviceFlowRegistry();
+ final var flowRegistryKey = flowRegistry.createKey(new FlowBuilder(flowStatistics)
.withKey(FlowRegistryKeyFactory.DUMMY_FLOW_KEY)
- .addAugmentation(flowStatisticsDataBld.build());
-
- final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(getVersion(), flowBuilder.build());
-
- getDeviceRegistry().getDeviceFlowRegistry().store(flowRegistryKey);
- return getDeviceRegistry().getDeviceFlowRegistry().retrieveDescriptor(flowRegistryKey).getFlowId();
+ .addAugmentation(new FlowStatisticsDataBuilder()
+ .setFlowStatistics(new FlowStatisticsBuilder(flowStatistics).build())
+ .build())
+ .build());
+ flowRegistry.store(flowRegistryKey);
+ return flowRegistry.retrieveDescriptor(flowRegistryKey).getFlowId();
}
}
*/
package org.opendaylight.openflowplugin.impl.util;
+import static java.util.Objects.requireNonNull;
+
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Locale;
+import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
-import org.opendaylight.yangtools.yang.common.Uint32;
-import org.opendaylight.yangtools.yang.common.Uint8;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Utility class used for converting OpenFlow port numbers, Ipv4 and Ipv6 addresses to normalized format.
*/
-public final class AddressNormalizationUtil {
+public enum AddressNormalizationUtil {
+ VERSION_1_0(OpenflowVersion.OF10),
+ VERSION_1_3(OpenflowVersion.OF13),
+ UNSUPPORTED(OpenflowVersion.UNSUPPORTED);
+
private static final Logger LOG = LoggerFactory.getLogger(AddressNormalizationUtil.class);
private static final String NO_ETH_MASK = "ff:ff:ff:ff:ff:ff";
private static final String PREFIX_SEPARATOR = "/";
- private AddressNormalizationUtil() {
+ private final OpenflowVersion version;
+
+ AddressNormalizationUtil(final OpenflowVersion version) {
+ this.version = requireNonNull(version);
+ }
+
+ public static @NonNull AddressNormalizationUtil ofVersion(final OpenflowVersion version) {
+ return switch (version) {
+ case OF10 -> VERSION_1_0;
+ case OF13 -> VERSION_1_3;
+ case UNSUPPORTED -> UNSUPPORTED;
+ };
}
/**
* Extract port number from URI and convert it to OpenFlow specific textual representation.
*
* @param port the OpenFlow port
- * @param protocolVersion the OpenFLow protocol version
* @return normalized uri
*/
- public static @Nullable Uri normalizeProtocolAgnosticPort(@Nullable final Uri port, final Uint8 protocolVersion) {
- if (port == null) {
- return null;
+ public @Nullable Uri normalizeProtocolAgnosticPort(final @Nullable Uri port) {
+ if (port != null) {
+ final var portValue = InventoryDataServiceUtil.portNumberfromNodeConnectorId(version, port.getValue());
+ if (portValue != null) {
+ return OpenflowPortsUtil.getProtocolAgnosticPortUri(version.getVersion(), portValue);
+ }
}
-
- Uint32 portValue = InventoryDataServiceUtil
- .portNumberfromNodeConnectorId(OpenflowVersion.get(protocolVersion), port.getValue());
-
- return portValue == null ? null : OpenflowPortsUtil.getProtocolAgnosticPortUri(protocolVersion, portValue);
+ return null;
}
/**
FlowConvertor.DEFAULT_OFPFF_FLOW_REM);
private FlowCreatorUtil() {
- // Hidden on purpose
+ // FIXME: turn this into a full class with Uint8 version captured
}
public static void setWildcardedFlowMatch(final Uint8 version, final MultipartRequestFlowBuilder flowBuilder) {
/*
* Copyright (c) 2017 Pantheon Technologies s.r.o. and others. All rights reserved.
+ * Copyright (c) 2024 PANTHEON.tech, s.r.o.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeIpv6Prefix;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddress;
import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeMacAddressMask;
-import static org.opendaylight.openflowplugin.impl.util.AddressNormalizationUtil.normalizeProtocolAgnosticPort;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import java.util.function.Function;
-import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
/**
* Utility class for match normalization.
*/
+// FIXME: rename to MatchNormalizer, move to FlowRegistryKeyFactory's package and hide
public final class MatchNormalizationUtil {
- // Cache normalizers for common OpenFlow versions
- private static final ImmutableMap<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>> COMMON_NORMALIZERS =
- ImmutableMap.<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>>builder()
- .put(OFConstants.OFP_VERSION_1_0,
- createNormalizers(OFConstants.OFP_VERSION_1_0).collect(ImmutableSet.toImmutableSet()))
- .put(OFConstants.OFP_VERSION_1_3,
- createNormalizers(OFConstants.OFP_VERSION_1_3).collect(ImmutableSet.toImmutableSet()))
- .build();
- private static final LoadingCache<Uint8, ImmutableSet<Function<MatchBuilder, MatchBuilder>>> UNCOMMON_NORMALIZERS =
- CacheBuilder.newBuilder().weakValues().build(new CacheLoader<>() {
+ public static final @NonNull MatchNormalizationUtil VERSION_1_0 =
+ new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_0);
+ public static final @NonNull MatchNormalizationUtil VERSION_1_3 =
+ new MatchNormalizationUtil(OFConstants.OFP_VERSION_1_3);
+ private static final LoadingCache<Uint8, @NonNull MatchNormalizationUtil> CACHE = CacheBuilder.newBuilder()
+ .weakValues().build(new CacheLoader<>() {
@Override
- public ImmutableSet<Function<MatchBuilder, MatchBuilder>> load(final Uint8 key) {
- return createNormalizers(key).collect(ImmutableSet.toImmutableSet());
+ public MatchNormalizationUtil load(final Uint8 key) {
+ return new MatchNormalizationUtil(key);
}
});
- private MatchNormalizationUtil() {
- // Hidden on purpose
+ private final AddressNormalizationUtil addressNormalizer;
+
+ private MatchNormalizationUtil(final Uint8 version) {
+ addressNormalizer = AddressNormalizationUtil.ofVersion(OpenflowVersion.ofVersion(version));
+ }
+
+ public static @NonNull MatchNormalizationUtil ofVersion(final Uint8 version) {
+ if (OFConstants.OFP_VERSION_1_3.equals(version)) {
+ return VERSION_1_3;
+ } else if (OFConstants.OFP_VERSION_1_0.equals(version)) {
+ return VERSION_1_0;
+ } else {
+ return CACHE.getUnchecked(version);
+ }
}
/**
* Normalize match.
*
* @param match the OpenFlow match
- * @param version the OpenFlow version
* @return normalized OpenFlow match
*/
- public static @NonNull Match normalizeMatch(@NonNull final Match match, final Uint8 version) {
- final var matchBuilder = new MatchBuilder(match);
-
- var normalizers = COMMON_NORMALIZERS.get(version);
- if (normalizers == null) {
- normalizers = UNCOMMON_NORMALIZERS.getUnchecked(version);
- }
- normalizers.forEach(normalizer -> normalizer.apply(matchBuilder));
-
- return matchBuilder.build();
- }
-
- private static @NonNull Stream<Function<MatchBuilder, MatchBuilder>> createNormalizers(final Uint8 version) {
- return Stream.of(
- MatchNormalizationUtil::normalizeExtensionMatch,
- MatchNormalizationUtil::normalizeEthernetMatch,
- MatchNormalizationUtil::normalizeArpMatch,
- MatchNormalizationUtil::normalizeTunnelIpv4Match,
- MatchNormalizationUtil::normalizeIpv4Match,
- MatchNormalizationUtil::normalizeIpv4MatchArbitraryBitMask,
- MatchNormalizationUtil::normalizeIpv6Match,
- MatchNormalizationUtil::normalizeIpv6MatchArbitraryBitMask,
- match -> normalizeInPortMatch(match, version),
- match -> normalizeInPhyPortMatch(match, version));
- }
-
- private static @NonNull MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
- return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
+ public @NonNull Match normalizeMatch(@NonNull final Match match) {
+ var builder = new MatchBuilder(match);
+ builder = normalizeExtensionMatch(builder);
+ builder = normalizeEthernetMatch(builder);
+ builder = normalizeArpMatch(builder);
+ builder = normalizeTunnelIpv4Match(builder);
+ builder = normalizeIpv4Match(builder);
+ builder = normalizeIpv4MatchArbitraryBitMask(builder);
+ builder = normalizeIpv6Match(builder);
+ builder = normalizeIpv6MatchArbitraryBitMask(builder);
+ builder = normalizeInPortMatch(builder);
+ builder = normalizeInPhyPortMatch(builder);
+ return builder.build();
}
@VisibleForTesting
- static @NonNull MatchBuilder normalizeInPortMatch(final @NonNull MatchBuilder match, final Uint8 version) {
+ @NonNull MatchBuilder normalizeInPortMatch(final @NonNull MatchBuilder match) {
final var inPort = match.getInPort();
if (inPort != null) {
- final var inPortUri = normalizeProtocolAgnosticPort(inPort, version);
+ final var inPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPort);
if (inPortUri != null) {
match.setInPort(new NodeConnectorId(inPortUri));
}
}
@VisibleForTesting
- static @NonNull MatchBuilder normalizeInPhyPortMatch(final @NonNull MatchBuilder match, final Uint8 version) {
+ @NonNull MatchBuilder normalizeInPhyPortMatch(final @NonNull MatchBuilder match) {
final var inPhyPort = match.getInPhyPort();
if (inPhyPort != null) {
- final var inPhyPortUri = normalizeProtocolAgnosticPort(inPhyPort, version);
+ final var inPhyPortUri = addressNormalizer.normalizeProtocolAgnosticPort(inPhyPort);
if (inPhyPortUri != null) {
match.setInPhyPort(new NodeConnectorId(inPhyPortUri));
}
}
return match;
}
+
+ private static @NonNull MatchBuilder normalizeExtensionMatch(@NonNull final MatchBuilder match) {
+ return new MatchBuilder(MatchUtil.transformMatch(match.build(), Match.class));
+ }
}
FlowRemoved.class.getName())))).thenReturn(messageTranslatorFlowRemoved);
final java.util.Optional<AbstractDeviceInitializer> deviceInitializer = java.util.Optional
- .of(this.abstractDeviceInitializer);
+ .of(abstractDeviceInitializer);
Mockito.lenient().when(deviceInitializerProvider.lookup(OFConstants.OFP_VERSION_1_3))
.thenReturn(deviceInitializer);
public void testGetReadTransaction() {
readTx = deviceContext.getReadTransaction();
assertNotNull(readTx);
- assertEquals(this.readTx, readTx);
+ assertEquals(readTx, readTx);
}
@Test
.thenReturn(flowRemovedMdsalBld.build());
// insert flow+flowId into local registry
- final FlowRegistryKey flowRegKey =
- FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowRemovedMdsalBld.build());
+ final FlowRegistryKey flowRegKey = FlowRegistryKeyFactory.VERSION_1_3.create(flowRemovedMdsalBld.build());
final FlowDescriptor flowDescriptor = FlowDescriptorFactory.create(Uint8.ZERO, new FlowId("ut-ofp:f456"));
deviceContext.getDeviceFlowRegistry().storeDescriptor(flowRegKey, flowDescriptor);
deviceFlowRegistry = new DeviceFlowRegistryImpl(OFConstants.OFP_VERSION_1_3, dataBroker, nodeInstanceIdentifier,
history);
final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(1).build();
- key = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flowStats);
+ key = FlowRegistryKeyFactory.VERSION_1_3.create(flowStats);
descriptor = FlowDescriptorFactory.create(Uint8.valueOf(key.getTableId()), new FlowId("ut:1"));
Assert.assertEquals(0, deviceFlowRegistry.getAllFlowDescriptors().size());
.build();
final Map<FlowRegistryKey, FlowDescriptor> allFlowDescriptors = fillRegistry(path, flowCapableNode);
- key = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flow);
+ key = FlowRegistryKeyFactory.VERSION_1_3.create(flow);
InOrder order = inOrder(dataBroker, readOnlyTransaction);
order.verify(dataBroker).newReadOnlyTransaction();
// store new key with old value
final FlowAndStatisticsMapList flowStats = TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build();
- final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3, flowStats);
+ final FlowRegistryKey key2 = FlowRegistryKeyFactory.VERSION_1_3.create(flowStats);
deviceFlowRegistry.storeDescriptor(key2, descriptor);
Assert.assertEquals(2, deviceFlowRegistry.getAllFlowDescriptors().size());
Assert.assertEquals("ut:1", deviceFlowRegistry.retrieveDescriptor(key2).getFlowId().getValue());
//store new key
final String alienPrefix = "#UF$TABLE*2-";
- final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(OFConstants.OFP_VERSION_1_3,
+ final FlowRegistryKey key2 = FlowRegistryKeyFactory.VERSION_1_3.create(
TestFlowHelper.createFlowAndStatisticsMapListBuilder(2).build());
deviceFlowRegistry.store(key2);
newFlowId = deviceFlowRegistry.retrieveDescriptor(key2).getFlowId();
package org.opendaylight.openflowplugin.impl.registry.flow;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertThrows;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.List;
-import org.junit.Assert;
+import java.util.NoSuchElementException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
@RunWith(MockitoJUnitRunner.class)
public class FlowRegistryKeyFactoryTest {
-
private static final Logger LOG = LoggerFactory.getLogger(FlowRegistryKeyFactoryTest.class);
-
-
private static final FlowsStatisticsUpdateBuilder FLOWS_STATISTICS_UPDATE_BUILDER =
new FlowsStatisticsUpdateBuilder();
@Mock
@Mock
private DeviceInfo deviceInfo;
-
@Before
public void setup() {
- List<FlowAndStatisticsMapList> flowAndStatisticsMapListList = new ArrayList<>();
+ var flowAndStatisticsMapListList = new ArrayList<FlowAndStatisticsMapList>();
for (int i = 1; i < 4; i++) {
flowAndStatisticsMapListList.add(TestFlowHelper.createFlowAndStatisticsMapListBuilder(i).build());
}
FLOWS_STATISTICS_UPDATE_BUILDER.setFlowAndStatisticsMapList(flowAndStatisticsMapListList);
- Mockito.when(deviceInfo.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
}
@Test
HashSet<FlowRegistryKey> flowRegistryKeys = new HashSet<>();
for (FlowAndStatisticsMapList item : flowStats.nonnullFlowAndStatisticsMapList()) {
- final FlowRegistryKey key1 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), item);
- final FlowRegistryKey key2 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), item);
+ final FlowRegistryKey key1 = FlowRegistryKeyFactory.VERSION_1_3.create(item);
+ final FlowRegistryKey key2 = FlowRegistryKeyFactory.VERSION_1_3.create(item);
flowRegistryKeys.add(key1);
flowRegistryKeys.add(key1);
flowRegistryKeys.add(key2);
@Test
public void testEqualsNegative() {
+ final var keyFactory = FlowRegistryKeyFactory.VERSION_1_3;
+
final FlowAndStatisticsMapList flowStatisticsMapList1 =
TestFlowHelper.createFlowAndStatisticsMapListBuilder(1).build();
- final FlowRegistryKey key1 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowStatisticsMapList1);
+ final FlowRegistryKey key1 = keyFactory.create(flowStatisticsMapList1);
FlowRegistryKey key2;
FlowAndStatisticsMapListBuilder flowStatisticsMapListBld2;
// different priority
flowStatisticsMapListBld2 = new FlowAndStatisticsMapListBuilder(flowStatisticsMapList1);
flowStatisticsMapListBld2.setPriority(Uint16.valueOf(flowStatisticsMapListBld2.getPriority().toJava() + 1));
- key2 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowStatisticsMapListBld2.build());
- Assert.assertFalse(key1.equals(key2));
+ key2 = keyFactory.create(flowStatisticsMapListBld2.build());
+ assertFalse(key1.equals(key2));
// different match
flowStatisticsMapListBld2 = new FlowAndStatisticsMapListBuilder(flowStatisticsMapList1);
flowStatisticsMapListBld2.setMatch(new MatchBuilder().build());
- key2 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowStatisticsMapListBld2.build());
- Assert.assertFalse(key1.equals(key2));
+ key2 = keyFactory.create(flowStatisticsMapListBld2.build());
+ assertFalse(key1.equals(key2));
// different tableId
flowStatisticsMapListBld2 = new FlowAndStatisticsMapListBuilder(flowStatisticsMapList1);
flowStatisticsMapListBld2.setTableId(Uint8.valueOf(flowStatisticsMapListBld2.getTableId().toJava() + 1));
- key2 = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flowStatisticsMapListBld2.build());
- Assert.assertFalse(key1.equals(key2));
+ key2 = keyFactory.create(flowStatisticsMapListBld2.build());
+ assertFalse(key1.equals(key2));
- Assert.assertFalse(key1.equals(null));
+ assertFalse(key1.equals(null));
}
@Test
.setPriority(Uint16.TWO)
.setTableId(Uint8.ZERO);
- FlowRegistryKey flow1Hash = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flow1Builder.build());
+ FlowRegistryKey flow1Hash = FlowRegistryKeyFactory.VERSION_1_3.create(flow1Builder.build());
LOG.info("flowHash1: {}", flow1Hash.hashCode());
.setCookie(new FlowCookie(Uint64.valueOf(148)))
.setMatch(match2Builder.build());
- FlowRegistryKey flow2Hash = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), flow2Builder.build());
+ FlowRegistryKey flow2Hash = FlowRegistryKeyFactory.VERSION_1_3.create(flow2Builder.build());
LOG.info("flowHash2: {}", flow2Hash.hashCode());
- Assert.assertNotSame(flow1Hash, flow2Hash);
+ assertNotSame(flow1Hash, flow2Hash);
}
@Test
FlowBuilder fb1 = new FlowBuilder(flow1Builder.build());
fb1.setTableId((Uint8) null);
- try {
- FlowRegistryKeyFactory.create(deviceInfo.getVersion(), fb1.build());
- Assert.fail("hash creation should have failed because of NPE");
- } catch (NullPointerException e) {
- // expected
- Assert.assertEquals("flow tableId must not be null", e.getMessage());
- }
+
+ var ex = assertThrows(NoSuchElementException.class,
+ () -> FlowRegistryKeyFactory.VERSION_1_3.create(fb1.build()));
+ assertEquals("Value of tableid is not present", ex.getMessage());
FlowBuilder fb2 = new FlowBuilder(flow1Builder.build());
fb2.setPriority((Uint16) null);
- try {
- FlowRegistryKeyFactory.create(deviceInfo.getVersion(), fb2.build());
- } catch (NullPointerException e) {
- // not expected
- Assert.fail("no exception was expected while hash was creating.");
- }
+
+ assertNotNull(FlowRegistryKeyFactory.VERSION_1_3.create(fb2.build()));
FlowBuilder fb3 = new FlowBuilder(flow1Builder.build());
fb3.setCookie(null);
- FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), fb3.build());
- Assert.assertNotNull(flowRegistryKey.getCookie());
- Assert.assertEquals(OFConstants.DEFAULT_COOKIE, flowRegistryKey.getCookie());
+ FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.VERSION_1_3.create(fb3.build());
+ assertNotNull(flowRegistryKey.getCookie());
+ assertEquals(OFConstants.DEFAULT_COOKIE, flowRegistryKey.getCookie());
}
@Test
FlowsStatisticsUpdate flowStats = FLOWS_STATISTICS_UPDATE_BUILDER.build();
for (FlowAndStatisticsMapList item : flowStats.nonnullFlowAndStatisticsMapList()) {
- FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(deviceInfo.getVersion(), item);
+ FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.VERSION_1_3.create(item);
FlowRegistryKey lastHash = null;
if (null != lastHash) {
assertNotEquals(lastHash, flowRegistryKey);
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import java.util.Collections;
import java.util.List;
-import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.opendaylight.mdsal.binding.api.ReadTransaction;
import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
import org.opendaylight.openflowplugin.impl.services.multilayer.MultiLayerFlowMultipartRequestOnTheFlyCallback;
import org.opendaylight.openflowplugin.impl.statistics.ofpspecific.MessageIntelligenceAgencyImpl;
-import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManager;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorManagerFactory;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder;
@Mock
private DeviceFlowRegistry mockedFlowRegistry;
@Mock
+ private FlowRegistryKey mockedFlowKey;
+ @Mock
private FlowDescriptor mockedFlowDescriptor;
@Mock
private ReadTransaction mockedReadOnlyTx;
when(mockedDeviceContext.getDeviceInfo()).thenReturn(mockedDeviceInfo);
when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(mockedFlowRegistry);
+ when(mockedFlowRegistry.createKey(any())).thenReturn(mockedFlowKey);
when(mockedFlowRegistry.retrieveDescriptor(any(FlowRegistryKey.class)))
.thenReturn(mockedFlowDescriptor);
- final InstanceIdentifier<FlowCapableNode> nodePath =
- mockedDeviceInfo.getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
- final FlowCapableNodeBuilder flowNodeBuilder = new FlowCapableNodeBuilder();
- flowNodeBuilder.setTable(Collections.emptyMap());
- final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
dummyRequestContext = new AbstractRequestContext<>(DUMMY_XID) {
-
@Override
public void close() {
//NOOP
}
};
- final ConvertorManager convertorManager = ConvertorManagerFactory.createDefaultManager();
multipartRequestOnTheFlyCallback = new MultiLayerFlowMultipartRequestOnTheFlyCallback<>(
dummyRequestContext,
String.class,
mockedDeviceContext,
dummyEventIdentifier,
MultipartWriterProviderFactory.createDefaultProvider(mockedDeviceContext),
- convertorManager);
+ ConvertorManagerFactory.createDefaultManager());
}
@Test
public void testOnSuccessWithNull() throws Exception {
multipartRequestOnTheFlyCallback.onSuccess(null);
- final RpcResult<List<MultipartReply>> expectedRpcResult =
- RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build();
- final RpcResult<List<MultipartReply>> actualResult = dummyRequestContext.getFuture().get();
+ final var expectedRpcResult = RpcResultBuilder.<List<MultipartReply>>success(List.of()).build();
+ final var actualResult = dummyRequestContext.getFuture().get();
assertEquals(expectedRpcResult.getErrors(), actualResult.getErrors());
assertEquals(expectedRpcResult.getResult(), actualResult.getResult());
assertEquals(expectedRpcResult.isSuccessful(), actualResult.isSuccessful());
assertEquals(expectedRpcResult.getResult(), actualResult.getResult());
assertEquals(expectedRpcResult.isSuccessful(), actualResult.isSuccessful());
- Mockito.verify(mockedDeviceContext, Mockito.never())
- .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
- ArgumentMatchers.<InstanceIdentifier>any(), ArgumentMatchers.any());
- Mockito.verify(mockedDeviceContext).submitTransaction();
+ verify(mockedDeviceContext, never())
+ .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
+ verify(mockedDeviceContext).submitTransaction();
}
/**
@Test
public void testOnSuccessWithValidMultipart1() {
final MatchBuilder matchBuilder = new MatchBuilder()
- .setMatchEntry(Collections.emptyList());
+ .setMatchEntry(List.of());
final FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder()
.setTableId(tableId)
.setPriority(Uint16.TWO)
.setMatch(matchBuilder.build())
.setFlags(new FlowModFlags(true, false, false, false, false));
final MultipartReplyFlowBuilder multipartReplyFlowBuilder = new MultipartReplyFlowBuilder()
- .setFlowStats(Collections.singletonList(flowStatsBuilder.build()));
+ .setFlowStats(List.of(flowStatsBuilder.build()));
final MultipartReplyFlowCaseBuilder multipartReplyFlowCaseBuilder = new MultipartReplyFlowCaseBuilder()
.setMultipartReplyFlow(multipartReplyFlowBuilder.build());
final MultipartReplyMessageBuilder mpReplyMessage = new MultipartReplyMessageBuilder()
final TableBuilder tableDataBld = new TableBuilder();
tableDataBld.setId(tableId);
flowNodeBuilder.setTable(BindingMap.of(tableDataBld.build()));
- final Optional<FlowCapableNode> flowNodeOpt = Optional.of(flowNodeBuilder.build());
multipartRequestOnTheFlyCallback.onSuccess(mpReplyMessage.build());
- verify(mockedReadOnlyTx, times(0)).read(LogicalDatastoreType.OPERATIONAL, nodePath);
- verify(mockedReadOnlyTx, times(0)).close();
- verify(mockedDeviceContext, times(1)).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
- any(), any());
+ verify(mockedReadOnlyTx, never()).read(LogicalDatastoreType.OPERATIONAL, nodePath);
+ verify(mockedReadOnlyTx, never()).close();
+ verify(mockedDeviceContext, times(1)).writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
}
/**
// Nothing else than flow is supported by on the fly callback
assertNotNull(actualResult.getErrors());
assertFalse(actualResult.getErrors().isEmpty());
- Mockito.verify(mockedFlowRegistry, Mockito.never()).store(any());
- Mockito.verify(mockedDeviceContext, Mockito.never())
- .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL),
- ArgumentMatchers.<InstanceIdentifier>any(), ArgumentMatchers.any());
+ verify(mockedFlowRegistry, never()).store(any());
+ verify(mockedDeviceContext, never())
+ .writeToTransaction(eq(LogicalDatastoreType.OPERATIONAL), any(), any());
}
}
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
-import java.util.concurrent.ExecutionException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
import org.opendaylight.openflowplugin.api.openflow.device.Xid;
import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
+import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowRegistryKey;
import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
import org.opendaylight.openflowplugin.impl.services.multilayer.MultiAddFlow;
import org.opendaylight.openflowplugin.impl.services.multilayer.MultiRemoveFlow;
@Mock
private DeviceFlowRegistry deviceFlowRegistry;
@Mock
+ private FlowRegistryKey flowKey;
+ @Mock
private GetFeaturesOutput mockedFeaturesOutput;
@Before
@Test
public void testAddFlow() throws Exception {
+ when(deviceFlowRegistry.createKey(any())).thenReturn(flowKey);
addFlow(OFConstants.OFP_VERSION_1_0);
addFlow(OFConstants.OFP_VERSION_1_3);
}
addFlowFailCallback(OFConstants.OFP_VERSION_1_3);
}
- private void addFlowFailCallback(final Uint8 version) throws InterruptedException, ExecutionException {
+ private void addFlowFailCallback(final Uint8 version) throws Exception {
AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
.setMatch(match)
.setTableId(Uint8.ONE)
doReturn(Futures.<RequestContext<Object>>immediateFailedFuture(new Exception("ut-failed-response")))
.when(requestContext).getFuture();
+ when(deviceFlowRegistry.createKey(any())).thenReturn(flowKey);
final var rpcResultFuture = mockAddFlow(version).invoke(mockedAddFlowInput);
removeFlowFailCallback(OFConstants.OFP_VERSION_1_3);
}
- private void removeFlowFailCallback(final Uint8 version) throws InterruptedException, ExecutionException {
+ private void removeFlowFailCallback(final Uint8 version) throws Exception {
RemoveFlowInput mockedRemoveFlowInput = new RemoveFlowInputBuilder()
.setTableId(Uint8.ONE)
.setMatch(match)
@Test
public void testAddFlowWithItemLifecycle() throws Exception {
+ when(deviceFlowRegistry.createKey(any())).thenReturn(flowKey);
addFlow(OFConstants.OFP_VERSION_1_0);
addFlow(OFConstants.OFP_VERSION_1_3);
}
- private void addFlow(final Uint8 version) throws ExecutionException, InterruptedException {
+ private void addFlow(final Uint8 version) throws Exception {
+
AddFlowInput mockedAddFlowInput = new AddFlowInputBuilder()
.setMatch(match)
.setTableId(Uint8.ONE)
}
private static <T extends DataObject> void verifyOutput(final ListenableFuture<RpcResult<T>> rpcResultFuture)
- throws ExecutionException, InterruptedException {
+ throws Exception {
assertNotNull(rpcResultFuture);
final var addFlowOutputRpcResult = rpcResultFuture.get();
assertNotNull(addFlowOutputRpcResult);
@Mock
private FlowDescriptor flowDescriptor;
@Mock
+ private FlowRegistryKey flowRegistryKey;
+ @Mock
private FlowId flowId;
@Mock
private GetFeaturesOutput features;
when(deviceContext.getDeviceFlowRegistry()).thenReturn(deviceFlowRegistry);
when(deviceContext.getDeviceGroupRegistry()).thenReturn(deviceGroupRegistry);
when(deviceContext.getDeviceMeterRegistry()).thenReturn(deviceMeterRegistry);
- when(deviceFlowRegistry.retrieveDescriptor(any(FlowRegistryKey.class))).thenReturn(flowDescriptor);
+ when(deviceFlowRegistry.createKey(any())).thenReturn(flowRegistryKey);
+ when(deviceFlowRegistry.retrieveDescriptor(any())).thenReturn(flowDescriptor);
when(flowDescriptor.getFlowId()).thenReturn(new FlowId("MOCK_FLOW"));
when(deviceContext.getReadTransaction()).thenReturn(readTx);
when(deviceContext.getReadTransaction()).thenReturn(readTx);
Assert.assertEquals(42, flow.getValue().getTableId().intValue());
}
- private static Iterable<FlowsStatisticsUpdate> prepareFlowStatisticsData() {
+ private static List<FlowsStatisticsUpdate> prepareFlowStatisticsData() {
final FlowAndStatisticsMapListBuilder flowAndStatsMapListBld = new FlowAndStatisticsMapListBuilder();
flowAndStatsMapListBld.setTableId(Uint8.valueOf(42));
flowAndStatsMapListBld.setMatch(new MatchBuilder().build());
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
-
package org.opendaylight.openflowplugin.impl.util;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
-import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask;
public class AddressNormalizationUtilTest {
-
@Test
public void normalizeProtocolAgnosticPortOF10() {
final Uri left = new Uri("openflow:1:INPORT");
final Uri right = new Uri("IN_PORT");
- assertEquals(
- right,
- AddressNormalizationUtil.normalizeProtocolAgnosticPort(left, OFConstants.OFP_VERSION_1_0)
- );
+ assertEquals(right, AddressNormalizationUtil.VERSION_1_0.normalizeProtocolAgnosticPort(left));
}
@Test
final Uri left = new Uri("openflow:1:ANY");
final Uri right = new Uri("ANY");
- assertEquals(
- right,
- AddressNormalizationUtil.normalizeProtocolAgnosticPort(left, OFConstants.OFP_VERSION_1_3)
- );
+ assertEquals(right, AddressNormalizationUtil.VERSION_1_3.normalizeProtocolAgnosticPort(left));
}
@Test
import static org.junit.Assert.assertNull;
import org.junit.Test;
-import org.opendaylight.openflowjava.protocol.api.util.EncodeConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
public void normalizeInPortMatch() {
final long port = 10;
- final MatchBuilder matchBuilder = MatchNormalizationUtil.normalizeInPortMatch(new MatchBuilder()
- .setInPort(new NodeConnectorId("openflow:1:" + port)), EncodeConstants.OF_VERSION_1_3);
+ final MatchBuilder matchBuilder = MatchNormalizationUtil.VERSION_1_3.normalizeInPortMatch(new MatchBuilder()
+ .setInPort(new NodeConnectorId("openflow:1:" + port)));
assertEquals(String.valueOf(port), matchBuilder.getInPort().getValue());
}
public void normalizeInPhyPortMatch() {
final long port = 10;
- final MatchBuilder matchBuilder = MatchNormalizationUtil.normalizeInPhyPortMatch(new MatchBuilder()
- .setInPhyPort(new NodeConnectorId("openflow:1:" + port)), EncodeConstants.OF_VERSION_1_3);
+ final MatchBuilder matchBuilder = MatchNormalizationUtil.VERSION_1_3.normalizeInPhyPortMatch(new MatchBuilder()
+ .setInPhyPort(new NodeConnectorId("openflow:1:" + port)));
assertEquals(String.valueOf(port), matchBuilder.getInPhyPort().getValue());
}