X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=openflowplugin%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fopenflowplugin%2Fopenflow%2Fmd%2Fcore%2Fsal%2Fconvertor%2Fmatch%2FMatchConvertor.java;h=20b111f1da9011437beb64191fc30498c9a3a918;hb=f7b6593eaad290c8c1cbd592e9972729a9a953b8;hp=b4a027329e98b96527fb0957f8a554350ecb553d;hpb=3c34de49abdc57fe13181e370e61e06a1e0ca658;p=openflowplugin.git diff --git a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertor.java b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertor.java index b4a027329e..20b111f1da 100644 --- a/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertor.java +++ b/openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor/match/MatchConvertor.java @@ -5,23 +5,653 @@ * 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.Collection; +import java.util.List; +import java.util.Optional; +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.extension.api.core.extension.ExtensionConverterProvider; +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.common.ConvertReactorConvertor; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.OFApprovedExperimenterIds; +import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor; +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.flow.FlowConvertor; +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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil; +import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField; +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.PacketTypeMatch; +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.TcpFlagsContainerBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.tcp.flags.container.TcpFlagsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.experimenter.id.match.entry.ExperimenterIdCaseBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.experimenter.id.match.entry.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.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.PacketType; +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.PacketTypeCaseBuilder; +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.packet.type._case.PacketTypeBuilder; +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; +import org.opendaylight.yangtools.yang.common.Uint16; +import org.opendaylight.yangtools.yang.common.Uint32; +import org.opendaylight.yangtools.yang.common.Uint8; /** - * converting from MD-SAL match model into appropriate OF-API match model - * - * @param type of converted match + * Utility class for converting a MD-SAL Flow into the OF flow mod. */ -public interface MatchConvertor extends ConvertReactorConvertor { +public class MatchConvertor extends Convertor, VersionConvertorData> { + private static final List> TYPES = List.of( + Match.class, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match.class, + org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed.Match.class, + org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received.Match.class, + org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.in.message.Match.class, + org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature + .prop.type.Match.class, + SetField.class); + + private static final ConvertorProcessor, VersionConvertorData> LAYER3_PROCESSOR = + new ConvertorProcessor, VersionConvertorData>() + .addCase(new SalToOfIpv4MatchArbitraryBitMaskCase()) + .addCase(new SalToOfIpv4MatchCase()) + .addCase(new SalToOfTunnelIpv4MatchCase()) + .addCase(new SalToOfArpMatchCase()) + .addCase(new SalToOfIpv6MatchArbitraryBitMaskCase()) + .addCase(new SalToOfIpv6MatchCase()); + + private static final ConvertorProcessor, VersionConvertorData> LAYER4_PROCESSOR = + new ConvertorProcessor, 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 matchEntryList, final Layer3Match layer3Match, + final ConvertorExecutor converterExecutor, + final ExtensionConverterProvider extensionConvertorProvider) { + LAYER3_PROCESSOR.process(layer3Match, converterExecutor).ifPresent(matchEntryList::addAll); + } + + private static void layer4Match(final List matchEntryList, final Layer4Match layer4Match, + final ConvertorExecutor converterExecutor, final ExtensionConverterProvider extensionConvertorProvider) { + LAYER4_PROCESSOR.process(layer4Match, converterExecutor).ifPresent(matchEntryList::addAll); + } + + private static void inPortMatch(final List matchEntryList, final NodeConnectorId inPort) { + if (inPort == null) { + return; + } + + //TODO: currently this matchconverter is mapped to OF1.3 in MatchInjector. Will need to revisit during 1.4+ + final Uint32 portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPort); + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setHasMask(false); + matchEntryBuilder.setOxmMatchField(InPort.VALUE); + 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 matchEntryList, final NodeConnectorId inPhyPort) { + if (inPhyPort == null) { + return; + } + + //TODO: currently this matchconverter is mapped to OF1.3 in MatchInjector. Will need to revisit during 1.4+ + final Uint32 portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, + inPhyPort); + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setHasMask(false); + matchEntryBuilder.setOxmMatchField(InPhyPort.VALUE); + 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 matchEntryList, + final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata metadata) { + if (metadata == null) { + return; + } + + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + final boolean hasmask = metadata.getMetadataMask() != null; + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setOxmMatchField(Metadata.VALUE); + 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.uint64toBytes(metadata.getMetadata())); + + if (hasmask) { + metadataBuilder.setMask(ByteUtil.uint64toBytes(metadata.getMetadataMask())); + } + + metadataCaseBuilder.setMetadata(metadataBuilder.build()); + matchEntryBuilder.setMatchEntryValue(metadataCaseBuilder.build()); + matchEntryBuilder.setHasMask(hasmask); + matchEntryList.add(matchEntryBuilder.build()); + } + + private static void packetTypeMatch(final List matchEntryList, final PacketTypeMatch packetTypeMatch) { + if (packetTypeMatch == null) { + return; + } + + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setOxmMatchField(PacketType.VALUE); + matchEntryBuilder.setHasMask(false); + PacketTypeCaseBuilder packetTypeCaseBuilder = new PacketTypeCaseBuilder(); + PacketTypeBuilder packetTypeBuilder = new PacketTypeBuilder(); + packetTypeBuilder.setPacketType(packetTypeMatch.getPacketType()); + packetTypeCaseBuilder.setPacketType(packetTypeBuilder.build()); + matchEntryBuilder.setMatchEntryValue(packetTypeCaseBuilder.build()); + matchEntryList.add(matchEntryBuilder.build()); + } + + private static void tunnelMatch(final List matchEntryList, + final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel) { + if (tunnel == null) { + return; + } + + TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder(); + TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder(); + boolean hasMask = tunnel.getTunnelMask() != null; + + if (hasMask) { + tunnelIdBuilder.setMask(ByteUtil.uint64toBytes(tunnel.getTunnelMask())); + } + + tunnelIdBuilder.setTunnelId(ByteUtil.uint64toBytes(tunnel.getTunnelId())); + tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build()); + + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build()); + matchEntryBuilder.setHasMask(hasMask); + matchEntryBuilder.setOxmMatchField(TunnelId.VALUE); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryList.add(matchEntryBuilder.build()); + } + + private static void protocolMatchFields(final List 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 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 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 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 matchEntryList, final VlanMatch vlanMatch) { + if (vlanMatch == null) { + return; + } + + if (vlanMatch.getVlanId() != null) { + VlanId vlanId = vlanMatch.getVlanId(); + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setOxmMatchField(VlanVid.VALUE); + VlanVidBuilder vlanVidBuilder = new VlanVidBuilder(); + boolean setCfiBit = false; + Uint16 vidEntryValue = Uint16.ZERO; + boolean hasmask = false; + + if (Boolean.TRUE.equals(vlanId.getVlanIdPresent())) { + setCfiBit = true; + if (vlanId.getVlanId() != null) { + vidEntryValue = vlanId.getVlanId().getValue(); + } + + hasmask = vidEntryValue.toJava() == 0; + if (hasmask) { + vlanVidBuilder.setMask(VLAN_VID_MASK); + } + } + + vlanVidBuilder.setCfiBit(setCfiBit); + vlanVidBuilder.setVlanVid(vidEntryValue); + VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder(); + 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 matchEntryList, final EthernetMatch ethernetMatch) { + if (ethernetMatch == null) { + return; + } + + EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination(); + if (ethernetDestination != null) { + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setOxmMatchField(EthDst.VALUE); + EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder(); + EthDstBuilder ethDstBuilder = new EthDstBuilder(); + ethDstBuilder.setMacAddress(ethernetDestination.getAddress()); + boolean hasMask = ethernetDestination.getMask() != null; + + if (hasMask) { + ethDstBuilder.setMask(IetfYangUtil.INSTANCE.macAddressBytes(ethernetDestination.getMask())); + } + + 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.VALUE); + matchEntryBuilder.setOxmMatchField(EthSrc.VALUE); + EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder(); + EthSrcBuilder ethDstBuilder = new EthSrcBuilder(); + ethDstBuilder.setMacAddress(ethernetSource.getAddress()); + boolean hasMask = ethernetSource.getMask() != null; + + if (hasMask) { + ethDstBuilder.setMask(IetfYangUtil.INSTANCE.macAddressBytes(ethernetSource.getMask())); + } + + 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(final List matchEntryList, final TcpFlagsMatch tcpFlagsMatch) { + ExperimenterIdCaseBuilder expIdCaseBuilder = new ExperimenterIdCaseBuilder(); + if (tcpFlagsMatch != null) { + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder() + .setOxmClass(ExperimenterClass.VALUE) + .setHasMask(false) + .setOxmMatchField(TcpFlags.VALUE); + + 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. + expIdCaseBuilder.setExperimenter(new ExperimenterBuilder() + .setExperimenter(OFApprovedExperimenterIds.MATCH_TCP_FLAGS_EXP_ID) + .build()); + + expIdCaseBuilder.addAugmentation(tcpFlagsContainerBuilder.build()); + matchEntryBuilder.setMatchEntryValue(expIdCaseBuilder.build()); + matchEntryList.add(matchEntryBuilder.build()); + } + } + + private static MatchEntry toOfMplsPbb(final Pbb pbb) { + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + final boolean hasmask = pbb.getPbbMask() != null; + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setOxmMatchField(PbbIsid.VALUE); + 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 Uint8 mplsTc) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(MplsTc.VALUE) + .setMatchEntryValue(new MplsTcCaseBuilder() + .setMplsTc(new MplsTcBuilder().setTc(mplsTc).build()) + .build()) + .build(); + } + + private static MatchEntry toOfMplsBos(final Uint8 mplsBos) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(MplsBos.VALUE) + .setMatchEntryValue(new MplsBosCaseBuilder() + .setMplsBos(new MplsBosBuilder().setBos(mplsBos.toJava() != 0).build()) + .build()) + .build(); + } + + private static MatchEntry toOfMplsLabel(final Uint32 mplsLabel) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(MplsLabel.VALUE) + .setMatchEntryValue(new MplsLabelCaseBuilder() + .setMplsLabel(new MplsLabelBuilder().setMplsLabel(mplsLabel).build()) + .build()) + .build(); + } + + private static MatchEntry toOfEthernetType(final EthernetType ethernetType) { + MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder(); + matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE); + matchEntryBuilder.setHasMask(false); + matchEntryBuilder.setOxmMatchField(EthType.VALUE); + EthTypeCaseBuilder ethTypeCaseBuilder = new EthTypeCaseBuilder(); + EthTypeBuilder ethTypeBuilder = new EthTypeBuilder(); + EtherType etherType = new EtherType(ethernetType.getType().getValue().toUint16()); + ethTypeBuilder.setEthType(etherType); + ethTypeCaseBuilder.setEthType(ethTypeBuilder.build()); + matchEntryBuilder.setMatchEntryValue(ethTypeCaseBuilder.build()); + return matchEntryBuilder.build(); + } + + private static MatchEntry toOfIcmpv4Type(final Uint8 icmpv4Type) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(Icmpv4Type.VALUE) + .setMatchEntryValue(new Icmpv4TypeCaseBuilder() + .setIcmpv4Type(new Icmpv4TypeBuilder().setIcmpv4Type(icmpv4Type).build()) + .build()) + .build(); + } + + private static MatchEntry toOfIcmpv4Code(final Uint8 icmpv4Code) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(Icmpv4Code.VALUE) + .setMatchEntryValue(new Icmpv4CodeCaseBuilder() + .setIcmpv4Code(new Icmpv4CodeBuilder().setIcmpv4Code(icmpv4Code).build()).build()) + .build(); + } + + private static MatchEntry toOfIcmpv6Type(final Uint8 icmpv6Type) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(Icmpv6Type.VALUE) + .setMatchEntryValue(new Icmpv6TypeCaseBuilder() + .setIcmpv6Type(new Icmpv6TypeBuilder().setIcmpv6Type(icmpv6Type).build()) + .build()) + .build(); + } + + private static MatchEntry toOfIcmpv6Code(final Uint8 icmpv6Code) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(Icmpv6Code.VALUE) + .setMatchEntryValue(new Icmpv6CodeCaseBuilder() + .setIcmpv6Code(new Icmpv6CodeBuilder().setIcmpv6Code(icmpv6Code).build()) + .build()) + .build(); + } + + private static MatchEntry toOfIpProto(final Uint8 ipProtocol) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(IpProto.VALUE) + .setMatchEntryValue(new IpProtoCaseBuilder() + .setIpProto(new IpProtoBuilder().setProtocolNumber(ipProtocol).build()) + .build()) + .build(); + } + + private static MatchEntry toOfIpEcn(final Uint8 ipEcn) { + return new MatchEntryBuilder() + .setOxmClass(OpenflowBasicClass.VALUE) + .setHasMask(Boolean.FALSE) + .setOxmMatchField(IpEcn.VALUE) + .setMatchEntryValue(new IpEcnCaseBuilder().setIpEcn(new IpEcnBuilder().setEcn(ipEcn).build()).build()) + .build(); + } + /** - * @param source match input - * @param convertorExecutor - * @return converted match (into OF-API model) + * Create default empty match entries + * Use this method, if result from converter is empty. */ - E convert(Match source, ConvertorExecutor convertorExecutor); + public static List defaultResult() { + return FlowConvertor.DEFAULT_MATCH_ENTRIES; + } + + @Override + public Collection> getTypes() { + return TYPES; + } + + @Override + public List convert(final Match source, final VersionConvertorData data) { + List result = new ArrayList<>(); + + if (source == null) { + return result; + } + + final ExtensionConverterProvider extensionConvertorProvider = OFSessionUtil.getExtensionConvertorProvider(); + + inPortMatch(result, source.getInPort()); + inPhyPortMatch(result, source.getInPhyPort()); + metadataMatch(result, source.getMetadata()); + packetTypeMatch(result, source.getPacketTypeMatch()); + ethernetMatch(result, source.getEthernetMatch()); + vlanMatch(result, source.getVlanMatch()); + ipMatch(result, source.getIpMatch()); + layer4Match(result, source.getLayer4Match(), getConvertorExecutor(), extensionConvertorProvider); + icmpv4Match(result, source.getIcmpv4Match()); + icmpv6Match(result, source.getIcmpv6Match()); + layer3Match(result, source.getLayer3Match(), getConvertorExecutor(), extensionConvertorProvider); + protocolMatchFields(result, source.getProtocolMatchFields()); + tunnelMatch(result, source.getTunnel()); + tcpFlagsMatch(result, source.getTcpFlagsMatch()); + + /* + * TODO: EXTENSION PROPOSAL (source, MD-SAL to OFJava) + * - we might need version for conversion and for key + */ + Optional extensionListOpt = + ExtensionResolvers.getMatchExtensionResolver().getExtension(source); + if (extensionListOpt.isPresent()) { + for (ExtensionList extensionItem : extensionListOpt.orElseThrow().nonnullExtensionList().values()) { + // TODO: get real version + ConverterExtensionKey key = + new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3); + ConvertorToOFJava convertor = extensionConvertorProvider.getConverter(key); + if (convertor == null) { + throw new IllegalStateException("No converter found for key: " + key.toString()); + } + result.add(convertor.convert(extensionItem.getExtension())); + } + } + + return result; + } } +