/**
* Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
*
* 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.openflow.md.core.extension;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.opendaylight.openflowjava.protocol.api.keys.MatchEntrySerializerKey;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.extension.api.AugmentTuple;
import org.opendaylight.openflowplugin.extension.api.ConvertorFromOFJava;
import org.opendaylight.openflowplugin.extension.api.ExtensionAugment;
import org.opendaylight.openflowplugin.extension.api.path.MatchPath;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MatchField;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OxmClassBase;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketIn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifPacketInBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifSwitchFlowRemovedBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchNotifUpdateFlowStatsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcOutputFlowStats;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralAugMatchRpcOutputFlowStatsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.Extension;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.grouping.ExtensionBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionListBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received.Match;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
*/
public final class MatchExtensionHelper {
private static final Logger LOG = LoggerFactory
.getLogger(MatchExtensionHelper.class);
private MatchExtensionHelper() {
throw new IllegalAccessError("singleton enforcement");
}
/**
* @param matchEntry match entry
* @param ofVersion openflow version
* @param matchPath match path
*/
public static <T> void injectExtension(
final short ofVersion,
final MatchEntry matchEntry,
final T matchBuilder,
final MatchPath matchPath) {
final ExtensionListBuilder extBuilder = processExtension(matchEntry, ofVersion, matchPath);
if (Objects.isNull(extBuilder)) {
LOG.warn("Convertor for {} for version {} with match path {} not found.",
matchEntry.toString(),
ofVersion,
matchPath.name());
}
switch (matchPath) {
case FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH: {
final MatchBuilder augMatchBuilder = MatchBuilder.class.cast(matchBuilder);
final GeneralAugMatchNotifUpdateFlowStatsBuilder builder = Optional
.ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifUpdateFlowStats.class))
.map(aug -> new GeneralAugMatchNotifUpdateFlowStatsBuilder(aug))
.orElse(new GeneralAugMatchNotifUpdateFlowStatsBuilder().setExtensionList(new ArrayList<>()));
builder.getExtensionList().add(extBuilder.build());
break;
}
case PACKETRECEIVED_MATCH: {
final org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received
.MatchBuilder augMatchBuilder = org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received
.MatchBuilder.class.cast(matchBuilder);
final GeneralAugMatchNotifPacketInBuilder builder = Optional
.ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifPacketIn.class))
.map(aug -> new GeneralAugMatchNotifPacketInBuilder(aug))
.orElse(new GeneralAugMatchNotifPacketInBuilder().setExtensionList(new ArrayList<>()));
builder.getExtensionList().add(extBuilder.build());
break;
}
case SWITCHFLOWREMOVED_MATCH: {
final org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed
.MatchBuilder augMatchBuilder = org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed
.MatchBuilder.class.cast(matchBuilder);
final GeneralAugMatchNotifSwitchFlowRemovedBuilder builder = Optional
.ofNullable(augMatchBuilder.getAugmentation(GeneralAugMatchNotifSwitchFlowRemoved.class))
.map(aug -> new GeneralAugMatchNotifSwitchFlowRemovedBuilder(aug))
.orElse(new GeneralAugMatchNotifSwitchFlowRemovedBuilder().setExtensionList(new ArrayList<>()));
builder.getExtensionList().add(extBuilder.build());
break;
}
default:
LOG.warn("Match path {} not supported.", matchPath.name());
}
}
/**
* @param matchEntries match entries
* @param ofVersion openflow version
* @param matchPath match path
* @param <EXT_POINT> extension point
* @return augmentation wrapper containing augmentation depending on matchPath
*/
@SuppressWarnings("unchecked")
public static <EXT_POINT extends Augmentable<EXT_POINT>>
AugmentTuple<EXT_POINT> processAllExtensions(Collection<MatchEntry> matchEntries,
OpenflowVersion ofVersion, MatchPath matchPath) {
List<ExtensionList> extensionsList = new ArrayList<>();
for (MatchEntry matchEntry : matchEntries) {
ExtensionListBuilder extensionListBld = processExtension(matchEntry, ofVersion.getVersion(), matchPath);
if (extensionListBld == null) {
continue;
}
extensionsList.add(extensionListBld.build());
}
AugmentTuple<EXT_POINT> augmentTuple = null;
if (!extensionsList.isEmpty()) {
switch (matchPath) {
case FLOWSSTATISTICSUPDATE_FLOWANDSTATISTICSMAPLIST_MATCH:
GeneralAugMatchNotifUpdateFlowStatsBuilder generalExtMatchAugBld1 = new GeneralAugMatchNotifUpdateFlowStatsBuilder();
generalExtMatchAugBld1.setExtensionList(extensionsList);
augmentTuple = (AugmentTuple<EXT_POINT>)
new AugmentTuple<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match>(
GeneralAugMatchNotifUpdateFlowStats.class, generalExtMatchAugBld1.build());
break;
case PACKETRECEIVED_MATCH:
GeneralAugMatchNotifPacketInBuilder generalExtMatchAugBld2 = new GeneralAugMatchNotifPacketInBuilder();
generalExtMatchAugBld2.setExtensionList(extensionsList);
augmentTuple = (AugmentTuple<EXT_POINT>)
new AugmentTuple<Match>(GeneralAugMatchNotifPacketIn.class, generalExtMatchAugBld2.build());
break;
case SWITCHFLOWREMOVED_MATCH:
GeneralAugMatchNotifSwitchFlowRemovedBuilder generalExtMatchAugBld3 = new GeneralAugMatchNotifSwitchFlowRemovedBuilder();
generalExtMatchAugBld3.setExtensionList(extensionsList);
augmentTuple = (AugmentTuple<EXT_POINT>)
new AugmentTuple<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed.Match>(
GeneralAugMatchNotifSwitchFlowRemoved.class, generalExtMatchAugBld3.build());
break;
case RPCFLOWSSTATISTICS_FLOWANDSTATISTICSMAPLIST_MATCH:
GeneralAugMatchRpcOutputFlowStatsBuilder generalExtMatchAugBld4 = new GeneralAugMatchRpcOutputFlowStatsBuilder();
generalExtMatchAugBld4.setExtensionList(extensionsList);
augmentTuple = (AugmentTuple<EXT_POINT>)
new AugmentTuple<org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match>(
GeneralAugMatchRpcOutputFlowStats.class, generalExtMatchAugBld4.build());
break;
default:
LOG.warn("matchPath not supported: {}", matchPath);
}
}
return augmentTuple;
}
/**
* @param ofVersion
* @param matchPath
* @param matchEntry
* @return
*/
private static ExtensionListBuilder processExtension(MatchEntry matchEntry, short ofVersion, MatchPath matchPath) {
ExtensionListBuilder extListBld = null;
/** TODO: EXTENSION PROPOSAL (match, OFJava to MD-SAL) */
MatchEntrySerializerKey<? extends OxmClassBase, ? extends MatchField> key = new MatchEntrySerializerKey<>(
ofVersion, matchEntry.getOxmClass(), matchEntry.getOxmMatchField());
if (null != OFSessionUtil.getExtensionConvertorProvider()) {
ConvertorFromOFJava<MatchEntry, MatchPath> convertor = OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
if (convertor != null) {
ExtensionAugment<? extends Augmentation<Extension>> extensionMatch =
convertor.convert(matchEntry, matchPath);
ExtensionBuilder extBld = new ExtensionBuilder();
extBld.addAugmentation(extensionMatch.getAugmentationClass(), extensionMatch.getAugmentationObject());
extListBld = new ExtensionListBuilder();
extListBld.setExtension(extBld.build());
extListBld.setExtensionKey(extensionMatch.getKey());
}
}
return extListBld;
}
}