/*
* Copyright (c) 2016 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.sal.convertor.match;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.opendaylight.openflowjava.util.ByteBufUtils;
import org.opendaylight.openflowplugin.api.OFConstants;
import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey;
import org.opendaylight.openflowplugin.extension.api.ConvertorToOFJava;
import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.OFApprovedExperimenterIds;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorProcessor;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfArpMatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchArbitraryBitMaskCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchArbitraryBitMaskCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfSctpMatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTcpMatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTunnelIpv4MatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfUdpMatchCase;
import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFields;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagsMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.Pbb;
import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlags;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlagsContainer;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlagsContainerBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.oxm.container.match.entry.value.experimenter.id._case.TcpFlagsBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.experimenter.id._case.ExperimenterBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthDst;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthSrc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Code;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Type;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Code;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Type;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPhyPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpEcn;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpProto;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Metadata;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsBos;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsLabel;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsTc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OpenflowBasicClass;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.PbbIsid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.TunnelId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.VlanVid;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthDstCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthSrcCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthTypeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4CodeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4TypeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6CodeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6TypeCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPhyPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpEcnCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpProtoCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MetadataCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsBosCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsLabelCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsTcCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.PbbIsidCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.TunnelIdCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.VlanVidCaseBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.dst._case.EthDstBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.src._case.EthSrcBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.type._case.EthTypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.code._case.Icmpv4CodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.type._case.Icmpv4TypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.code._case.Icmpv6CodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.type._case.Icmpv6TypeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.phy.port._case.InPhyPortBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPortBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.ecn._case.IpEcnBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.proto._case.IpProtoBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.bos._case.MplsBosBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.label._case.MplsLabelBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.tc._case.MplsTcBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.pbb.isid._case.PbbIsidBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.tunnel.id._case.TunnelIdBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.vlan.vid._case.VlanVidBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
/**
* Utility class for converting a MD-SAL Flow into the OF flow mod
*/
public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
private static final ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData> LAYER3_PROCESSOR = new ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData>()
.addCase(new SalToOfIpv4MatchArbitraryBitMaskCase())
.addCase(new SalToOfIpv4MatchCase())
.addCase(new SalToOfTunnelIpv4MatchCase())
.addCase(new SalToOfArpMatchCase())
.addCase(new SalToOfIpv6MatchArbitraryBitMaskCase())
.addCase(new SalToOfIpv6MatchCase());
private static final ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData> LAYER4_PROCESSOR = new ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData>()
.addCase(new SalToOfTcpMatchCase())
.addCase(new SalToOfUdpMatchCase())
.addCase(new SalToOfSctpMatchCase());
private static final byte[] VLAN_VID_MASK = new byte[]{16, 0};
private static void layer3Match(final List<MatchEntry> matchEntryList, final Layer3Match layer3Match, ConvertorExecutor convertorExecutor) {
java.util.Optional<List<MatchEntry>> result = LAYER3_PROCESSOR.process(layer3Match, convertorExecutor);
if (result.isPresent()) {
matchEntryList.addAll(result.get());
}
}
private static void layer4Match(final List<MatchEntry> matchEntryList, final Layer4Match layer4Match, ConvertorExecutor convertorExecutor) {
java.util.Optional<List<MatchEntry>> result = LAYER4_PROCESSOR.process(layer4Match, convertorExecutor);
if (result.isPresent()) {
matchEntryList.addAll(result.get());
}
}
private static void inPortMatch(final List<MatchEntry> matchEntryList, NodeConnectorId inPort) {
if (inPort == null) {
return;
}
//TODO: currently this matchconverter is mapped to OF1.3 in MatchReactorMappingFactory. Will need to revisit during 1.4+
final long portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPort);
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(InPort.class);
InPortCaseBuilder caseBuilder = new InPortCaseBuilder();
InPortBuilder portBuilder = new InPortBuilder();
portBuilder.setPortNumber(new PortNumber(portNumber));
caseBuilder.setInPort(portBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
matchEntryList.add(matchEntryBuilder.build());
}
private static void inPhyPortMatch(final List<MatchEntry> matchEntryList, NodeConnectorId inPhyPort) {
if (inPhyPort == null) {
return;
}
//TODO: currently this matchconverter is mapped to OF1.3 in MatchReactorMappingFactory. Will need to revisit during 1.4+
final long portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPhyPort);
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(InPhyPort.class);
InPhyPortCaseBuilder caseBuilder = new InPhyPortCaseBuilder();
InPhyPortBuilder portBuilder = new InPhyPortBuilder();
portBuilder.setPortNumber(new PortNumber(portNumber));
caseBuilder.setInPhyPort(portBuilder.build());
matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
matchEntryList.add(matchEntryBuilder.build());
}
private static void metadataMatch(final List<MatchEntry> matchEntryList,
final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata metadata) {
if (metadata == null) {
return;
}
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
boolean hasmask = metadata.getMetadataMask() != null;
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setOxmMatchField(Metadata.class);
MetadataCaseBuilder metadataCaseBuilder = new MetadataCaseBuilder();
org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.metadata._case.MetadataBuilder metadataBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.metadata._case.MetadataBuilder();
metadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(metadata.getMetadata(), OFConstants.SIZE_OF_LONG_IN_BYTES));
if (hasmask) {
metadataBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(metadata.getMetadataMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
}
metadataCaseBuilder.setMetadata(metadataBuilder.build());
matchEntryBuilder.setMatchEntryValue(metadataCaseBuilder.build());
matchEntryBuilder.setHasMask(hasmask);
matchEntryList.add(matchEntryBuilder.build());
}
private static void tunnelMatch(final List<MatchEntry> matchEntryList,
final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel) {
if (tunnel == null) {
return;
}
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder();
TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder();
boolean hasMask = tunnel.getTunnelMask() != null;
if (hasMask) {
tunnelIdBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
}
tunnelIdBuilder.setTunnelId(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelId(), OFConstants.SIZE_OF_LONG_IN_BYTES));
tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build());
matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build());
matchEntryBuilder.setHasMask(hasMask);
matchEntryBuilder.setOxmMatchField(TunnelId.class);
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryList.add(matchEntryBuilder.build());
}
private static void protocolMatchFields(final List<MatchEntry> matchEntryList,
final ProtocolMatchFields protocolMatchFields) {
if (protocolMatchFields == null) {
return;
}
if (protocolMatchFields.getMplsLabel() != null) {
matchEntryList.add(toOfMplsLabel(protocolMatchFields.getMplsLabel()));
}
if (protocolMatchFields.getMplsBos() != null) {
matchEntryList.add(toOfMplsBos(protocolMatchFields.getMplsBos()));
}
if (protocolMatchFields.getMplsTc() != null) {
matchEntryList.add(toOfMplsTc(protocolMatchFields.getMplsTc()));
}
if (protocolMatchFields.getPbb() != null) {
matchEntryList.add(toOfMplsPbb(protocolMatchFields.getPbb()));
}
}
private static void icmpv6Match(final List<MatchEntry> matchEntryList, final Icmpv6Match icmpv6Match) {
if (icmpv6Match == null) {
return;
}
if (icmpv6Match.getIcmpv6Type() != null) {
matchEntryList.add(toOfIcmpv6Type(icmpv6Match.getIcmpv6Type()));
}
if (icmpv6Match.getIcmpv6Code() != null) {
matchEntryList.add(toOfIcmpv6Code(icmpv6Match.getIcmpv6Code()));
}
}
private static void icmpv4Match(final List<MatchEntry> matchEntryList, final Icmpv4Match icmpv4Match) {
if (icmpv4Match == null) {
return;
}
if (icmpv4Match.getIcmpv4Type() != null) {
matchEntryList.add(toOfIcmpv4Type(icmpv4Match.getIcmpv4Type()));
}
if (icmpv4Match.getIcmpv4Code() != null) {
matchEntryList.add(toOfIcmpv4Code(icmpv4Match.getIcmpv4Code()));
}
}
private static void ipMatch(final List<MatchEntry> matchEntryList, final IpMatch ipMatch) {
if (ipMatch == null) {
return;
}
if (ipMatch.getIpDscp() != null) {
matchEntryList.add(MatchConvertorUtil.toOfIpDscp(ipMatch.getIpDscp()));
}
if (ipMatch.getIpEcn() != null) {
matchEntryList.add(toOfIpEcn(ipMatch.getIpEcn()));
}
if (ipMatch.getIpProtocol() != null) {
matchEntryList.add(toOfIpProto(ipMatch.getIpProtocol()));
}
}
private static void vlanMatch(final List<MatchEntry> matchEntryList, final VlanMatch vlanMatch) {
if (vlanMatch == null) {
return;
}
if (vlanMatch.getVlanId() != null) {
VlanId vlanId = vlanMatch.getVlanId();
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setOxmMatchField(VlanVid.class);
VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
boolean setCfiBit = false;
Integer vidEntryValue = 0;
boolean hasmask = false;
if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) {
setCfiBit = true;
if (vlanId.getVlanId() != null) {
vidEntryValue = vlanId.getVlanId().getValue();
}
hasmask = vidEntryValue == 0;
if (hasmask) {
vlanVidBuilder.setMask(VLAN_VID_MASK);
}
}
vlanVidBuilder.setCfiBit(setCfiBit);
vlanVidBuilder.setVlanVid(vidEntryValue);
vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
matchEntryBuilder.setHasMask(hasmask);
matchEntryList.add(matchEntryBuilder.build());
}
if (vlanMatch.getVlanPcp() != null) {
matchEntryList.add(MatchConvertorUtil.toOfVlanPcp(vlanMatch.getVlanPcp()));
}
}
private static void ethernetMatch(final List<MatchEntry> matchEntryList, final EthernetMatch ethernetMatch) {
if (ethernetMatch == null) {
return;
}
EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
if (ethernetDestination != null) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setOxmMatchField(EthDst.class);
EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder();
EthDstBuilder ethDstBuilder = new EthDstBuilder();
ethDstBuilder.setMacAddress(ethernetDestination.getAddress());
boolean hasMask = ethernetDestination.getMask() != null;
if (hasMask) {
ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetDestination.getMask().getValue()));
}
ethDstCaseBuilder.setEthDst(ethDstBuilder.build());
matchEntryBuilder.setMatchEntryValue(ethDstCaseBuilder.build());
matchEntryBuilder.setHasMask(hasMask);
matchEntryList.add(matchEntryBuilder.build());
}
EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
if (ethernetSource != null) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setOxmMatchField(EthSrc.class);
EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder();
EthSrcBuilder ethDstBuilder = new EthSrcBuilder();
ethDstBuilder.setMacAddress(ethernetSource.getAddress());
boolean hasMask = ethernetSource.getMask() != null;
if (hasMask) {
ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetSource.getMask().getValue()));
}
ethSrcCaseBuilder.setEthSrc(ethDstBuilder.build());
matchEntryBuilder.setMatchEntryValue(ethSrcCaseBuilder.build());
matchEntryBuilder.setHasMask(hasMask);
matchEntryList.add(matchEntryBuilder.build());
}
if (ethernetMatch.getEthernetType() != null) {
matchEntryList.add(toOfEthernetType(ethernetMatch.getEthernetType()));
}
}
private static void tcpFlagsMatch(List<MatchEntry> matchEntryList, TcpFlagsMatch tcpFlagsMatch) {
ExperimenterIdCaseBuilder expIdCaseBuilder = new ExperimenterIdCaseBuilder();
if (tcpFlagsMatch != null) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(ExperimenterClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(TcpFlags.class);
TcpFlagsContainerBuilder tcpFlagsContainerBuilder = new TcpFlagsContainerBuilder();
TcpFlagsBuilder tcpFlagsBuilder = new TcpFlagsBuilder();
tcpFlagsBuilder.setFlags(tcpFlagsMatch.getTcpFlags());
if(tcpFlagsMatch.getTcpFlagsMask() != null) {
matchEntryBuilder.setHasMask(true);
tcpFlagsBuilder.setMask(ByteUtil.unsignedShortToBytes(tcpFlagsMatch.getTcpFlagsMask()));
}
tcpFlagsContainerBuilder.setTcpFlags(tcpFlagsBuilder.build());
//Set experimenter ID.
ExperimenterBuilder experimenterBuilder = new ExperimenterBuilder();
experimenterBuilder.setExperimenter(new ExperimenterId(OFApprovedExperimenterIds.MATCH_TCP_FLAGS_EXP_ID));
expIdCaseBuilder.setExperimenter(experimenterBuilder.build());
expIdCaseBuilder.addAugmentation(TcpFlagsContainer.class, tcpFlagsContainerBuilder.build());
matchEntryBuilder.setMatchEntryValue(expIdCaseBuilder.build());
matchEntryList.add(matchEntryBuilder.build());
}
}
private static MatchEntry toOfMplsPbb(final Pbb pbb) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
boolean hasmask = pbb.getPbbMask() != null;
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setOxmMatchField(PbbIsid.class);
PbbIsidCaseBuilder pbbIsidCaseBuilder = new PbbIsidCaseBuilder();
PbbIsidBuilder pbbIsidBuilder = new PbbIsidBuilder();
pbbIsidBuilder.setIsid(pbb.getPbbIsid());
if (hasmask) {
pbbIsidBuilder.setMask(ByteUtil.unsignedMediumToBytes(pbb.getPbbMask()));
}
pbbIsidCaseBuilder.setPbbIsid(pbbIsidBuilder.build());
matchEntryBuilder.setMatchEntryValue(pbbIsidCaseBuilder.build());
matchEntryBuilder.setHasMask(hasmask);
return matchEntryBuilder.build();
}
private static MatchEntry toOfMplsTc(final Short mplsTc) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(MplsTc.class);
MplsTcCaseBuilder mplsTcCaseBuilder = new MplsTcCaseBuilder();
MplsTcBuilder mplsTcBuilder = new MplsTcBuilder();
mplsTcBuilder.setTc(mplsTc);
mplsTcCaseBuilder.setMplsTc(mplsTcBuilder.build());
matchEntryBuilder.setMatchEntryValue(mplsTcCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfMplsBos(final Short mplsBos) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(MplsBos.class);
MplsBosCaseBuilder mplsBosCaseBuilder = new MplsBosCaseBuilder();
MplsBosBuilder mplsBosBuilder = new MplsBosBuilder();
mplsBosBuilder.setBos(mplsBos != 0);
mplsBosCaseBuilder.setMplsBos(mplsBosBuilder.build());
matchEntryBuilder.setMatchEntryValue(mplsBosCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfMplsLabel(final Long mplsLabel) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(MplsLabel.class);
MplsLabelCaseBuilder mplsLabelCaseBuilder = new MplsLabelCaseBuilder();
MplsLabelBuilder mplsLabelBuilder = new MplsLabelBuilder();
mplsLabelBuilder.setMplsLabel(mplsLabel);
mplsLabelCaseBuilder.setMplsLabel(mplsLabelBuilder.build());
matchEntryBuilder.setMatchEntryValue(mplsLabelCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfEthernetType(final EthernetType ethernetType) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(EthType.class);
EthTypeCaseBuilder ethTypeCaseBuilder = new EthTypeCaseBuilder();
EthTypeBuilder ethTypeBuilder = new EthTypeBuilder();
EtherType etherType = new EtherType(ethernetType.getType().getValue().intValue());
ethTypeBuilder.setEthType(etherType);
ethTypeCaseBuilder.setEthType(ethTypeBuilder.build());
matchEntryBuilder.setMatchEntryValue(ethTypeCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIcmpv4Type(final Short icmpv4Type) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(Icmpv4Type.class);
Icmpv4TypeCaseBuilder icmpv4TypeCaseBuilder = new Icmpv4TypeCaseBuilder();
Icmpv4TypeBuilder icmpv4TypeBuilder = new Icmpv4TypeBuilder();
icmpv4TypeBuilder.setIcmpv4Type(icmpv4Type);
icmpv4TypeCaseBuilder.setIcmpv4Type(icmpv4TypeBuilder.build());
matchEntryBuilder.setMatchEntryValue(icmpv4TypeCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIcmpv4Code(final Short icmpv4Code) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(Icmpv4Code.class);
Icmpv4CodeCaseBuilder icmpv4CodeCaseBuilder = new Icmpv4CodeCaseBuilder();
Icmpv4CodeBuilder icmpv4CodeBuilder = new Icmpv4CodeBuilder();
icmpv4CodeBuilder.setIcmpv4Code(icmpv4Code);
icmpv4CodeCaseBuilder.setIcmpv4Code(icmpv4CodeBuilder.build());
matchEntryBuilder.setMatchEntryValue(icmpv4CodeCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIcmpv6Type(final Short icmpv6Type) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(Icmpv6Type.class);
Icmpv6TypeCaseBuilder icmpv6TypeCaseBuilder = new Icmpv6TypeCaseBuilder();
Icmpv6TypeBuilder icmpv6TypeBuilder = new Icmpv6TypeBuilder();
icmpv6TypeBuilder.setIcmpv6Type(icmpv6Type);
icmpv6TypeCaseBuilder.setIcmpv6Type(icmpv6TypeBuilder.build());
matchEntryBuilder.setMatchEntryValue(icmpv6TypeCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIcmpv6Code(final Short icmpv6Code) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(Icmpv6Code.class);
Icmpv6CodeCaseBuilder icmpv6CodeCaseBuilder = new Icmpv6CodeCaseBuilder();
Icmpv6CodeBuilder icmpv6CodeBuilder = new Icmpv6CodeBuilder();
icmpv6CodeBuilder.setIcmpv6Code(icmpv6Code);
icmpv6CodeCaseBuilder.setIcmpv6Code(icmpv6CodeBuilder.build());
matchEntryBuilder.setMatchEntryValue(icmpv6CodeCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIpProto(final Short ipProtocol) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(IpProto.class);
IpProtoCaseBuilder ipProtoCaseBuilder = new IpProtoCaseBuilder();
IpProtoBuilder ipProtoBuilder = new IpProtoBuilder();
ipProtoBuilder.setProtocolNumber(ipProtocol);
ipProtoCaseBuilder.setIpProto(ipProtoBuilder.build());
matchEntryBuilder.setMatchEntryValue(ipProtoCaseBuilder.build());
return matchEntryBuilder.build();
}
private static MatchEntry toOfIpEcn(final Short ipEcn) {
MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
matchEntryBuilder.setHasMask(false);
matchEntryBuilder.setOxmMatchField(IpEcn.class);
IpEcnCaseBuilder ipEcnCaseBuilder = new IpEcnCaseBuilder();
IpEcnBuilder ipEcnBuilder = new IpEcnBuilder();
ipEcnBuilder.setEcn(ipEcn);
ipEcnCaseBuilder.setIpEcn(ipEcnBuilder.build());
matchEntryBuilder.setMatchEntryValue(ipEcnCaseBuilder.build());
return matchEntryBuilder.build();
}
@Override
public List<MatchEntry> convert(final Match match, ConvertorExecutor convertorExecutor) {
List<MatchEntry> result = new ArrayList<>();
if (match == null) {
return result;
}
inPortMatch(result, match.getInPort());
inPhyPortMatch(result, match.getInPhyPort());
metadataMatch(result, match.getMetadata());
ethernetMatch(result, match.getEthernetMatch());
vlanMatch(result, match.getVlanMatch());
ipMatch(result, match.getIpMatch());
layer4Match(result, match.getLayer4Match(), convertorExecutor);
icmpv4Match(result, match.getIcmpv4Match());
icmpv6Match(result, match.getIcmpv6Match());
layer3Match(result, match.getLayer3Match(), convertorExecutor);
protocolMatchFields(result, match.getProtocolMatchFields());
tunnelMatch(result, match.getTunnel());
tcpFlagsMatch(result, match.getTcpFlagsMatch());
/**
* TODO: EXTENSION PROPOSAL (match, MD-SAL to OFJava)
* - we might need version for conversion and for key
*/
Optional<GeneralExtensionListGrouping> extensionListOpt = ExtensionResolvers.getMatchExtensionResolver().getExtension(match);
if (extensionListOpt.isPresent()) {
List<ExtensionList> extensionListList = extensionListOpt.get().getExtensionList();
for (ExtensionList extensionItem : extensionListList) {
// TODO: get real version
ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
ConvertorToOFJava<MatchEntry> convertor = OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
if (convertor == null) {
throw new IllegalStateException("No converter found for key: " + key.toString());
}
MatchEntry ofMatch = convertor.convert(extensionItem.getExtension());
result.add(ofMatch);
}
}
return result;
}
}