2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match;
10 import java.util.ArrayList;
11 import java.util.Collection;
12 import java.util.List;
13 import java.util.Optional;
14 import org.opendaylight.openflowplugin.api.OFConstants;
15 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
16 import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey;
17 import org.opendaylight.openflowplugin.extension.api.ConvertorToOFJava;
18 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
19 import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
20 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.OFApprovedExperimenterIds;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
23 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.ConvertorProcessor;
24 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
25 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.flow.FlowConvertor;
26 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfArpMatchCase;
27 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchArbitraryBitMaskCase;
28 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchCase;
29 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchArbitraryBitMaskCase;
30 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchCase;
31 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfSctpMatchCase;
32 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTcpMatchCase;
33 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTunnelIpv4MatchCase;
34 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfUdpMatchCase;
35 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
36 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
37 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
38 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.IetfYangUtil;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6Match;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.PacketTypeMatch;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFields;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagsMatch;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.Pbb;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlags;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlagsContainerBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.tcp.flags.container.TcpFlagsBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.experimenter.id.match.entry.ExperimenterIdCaseBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.experimenter.id.match.entry.experimenter.id._case.ExperimenterBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthDst;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthSrc;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthType;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Code;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Type;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Code;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Type;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPhyPort;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPort;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpEcn;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpProto;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Metadata;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsBos;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsLabel;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsTc;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OpenflowBasicClass;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.PacketType;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.PbbIsid;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.TunnelId;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.VlanVid;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthDstCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthSrcCaseBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthTypeCaseBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4CodeCaseBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4TypeCaseBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6CodeCaseBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6TypeCaseBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPhyPortCaseBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCaseBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpEcnCaseBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpProtoCaseBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MetadataCaseBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsBosCaseBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsLabelCaseBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsTcCaseBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.PacketTypeCaseBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.PbbIsidCaseBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.TunnelIdCaseBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.VlanVidCaseBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.dst._case.EthDstBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.src._case.EthSrcBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.type._case.EthTypeBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.code._case.Icmpv4CodeBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.type._case.Icmpv4TypeBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.code._case.Icmpv6CodeBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.type._case.Icmpv6TypeBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.phy.port._case.InPhyPortBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPortBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.ecn._case.IpEcnBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.proto._case.IpProtoBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.bos._case.MplsBosBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.label._case.MplsLabelBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.tc._case.MplsTcBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.packet.type._case.PacketTypeBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.pbb.isid._case.PbbIsidBuilder;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.tunnel.id._case.TunnelIdBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.vlan.vid._case.VlanVidBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
127 import org.opendaylight.yangtools.yang.common.Uint16;
128 import org.opendaylight.yangtools.yang.common.Uint32;
129 import org.opendaylight.yangtools.yang.common.Uint8;
132 * Utility class for converting a MD-SAL Flow into the OF flow mod.
134 public class MatchConvertor extends Convertor<Match, List<MatchEntry>, VersionConvertorData> {
135 private static final List<Class<?>> TYPES = List.of(
137 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match.class,
138 org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed.Match.class,
139 org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received.Match.class,
140 org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.in.message.Match.class,
141 org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature
142 .prop.type.Match.class,
145 private static final ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData> LAYER3_PROCESSOR =
146 new ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData>()
147 .addCase(new SalToOfIpv4MatchArbitraryBitMaskCase())
148 .addCase(new SalToOfIpv4MatchCase())
149 .addCase(new SalToOfTunnelIpv4MatchCase())
150 .addCase(new SalToOfArpMatchCase())
151 .addCase(new SalToOfIpv6MatchArbitraryBitMaskCase())
152 .addCase(new SalToOfIpv6MatchCase());
154 private static final ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData> LAYER4_PROCESSOR =
155 new ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData>()
156 .addCase(new SalToOfTcpMatchCase())
157 .addCase(new SalToOfUdpMatchCase())
158 .addCase(new SalToOfSctpMatchCase());
160 private static final byte[] VLAN_VID_MASK = new byte[]{16, 0};
162 private static void layer3Match(final List<MatchEntry> matchEntryList, final Layer3Match layer3Match,
163 final ConvertorExecutor converterExecutor,
164 final ExtensionConverterProvider extensionConvertorProvider) {
165 LAYER3_PROCESSOR.process(layer3Match, converterExecutor).ifPresent(matchEntryList::addAll);
168 private static void layer4Match(final List<MatchEntry> matchEntryList, final Layer4Match layer4Match,
169 final ConvertorExecutor converterExecutor, final ExtensionConverterProvider extensionConvertorProvider) {
170 LAYER4_PROCESSOR.process(layer4Match, converterExecutor).ifPresent(matchEntryList::addAll);
173 private static void inPortMatch(final List<MatchEntry> matchEntryList, final NodeConnectorId inPort) {
174 if (inPort == null) {
178 //TODO: currently this matchconverter is mapped to OF1.3 in MatchInjector. Will need to revisit during 1.4+
179 final Uint32 portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPort);
180 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
181 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
182 matchEntryBuilder.setHasMask(false);
183 matchEntryBuilder.setOxmMatchField(InPort.VALUE);
184 InPortCaseBuilder caseBuilder = new InPortCaseBuilder();
185 InPortBuilder portBuilder = new InPortBuilder();
186 portBuilder.setPortNumber(new PortNumber(portNumber));
187 caseBuilder.setInPort(portBuilder.build());
188 matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
189 matchEntryList.add(matchEntryBuilder.build());
192 private static void inPhyPortMatch(final List<MatchEntry> matchEntryList, final NodeConnectorId inPhyPort) {
193 if (inPhyPort == null) {
197 //TODO: currently this matchconverter is mapped to OF1.3 in MatchInjector. Will need to revisit during 1.4+
198 final Uint32 portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13,
200 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
201 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
202 matchEntryBuilder.setHasMask(false);
203 matchEntryBuilder.setOxmMatchField(InPhyPort.VALUE);
204 InPhyPortCaseBuilder caseBuilder = new InPhyPortCaseBuilder();
205 InPhyPortBuilder portBuilder = new InPhyPortBuilder();
206 portBuilder.setPortNumber(new PortNumber(portNumber));
207 caseBuilder.setInPhyPort(portBuilder.build());
208 matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
209 matchEntryList.add(matchEntryBuilder.build());
212 private static void metadataMatch(final List<MatchEntry> matchEntryList,
213 final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata metadata) {
214 if (metadata == null) {
218 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
219 final boolean hasmask = metadata.getMetadataMask() != null;
220 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
221 matchEntryBuilder.setOxmMatchField(Metadata.VALUE);
222 MetadataCaseBuilder metadataCaseBuilder = new MetadataCaseBuilder();
223 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry
224 .value.metadata._case.MetadataBuilder metadataBuilder = new org.opendaylight.yang.gen.v1.urn.opendaylight
225 .openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.metadata._case.MetadataBuilder();
226 metadataBuilder.setMetadata(ByteUtil.uint64toBytes(metadata.getMetadata()));
229 metadataBuilder.setMask(ByteUtil.uint64toBytes(metadata.getMetadataMask()));
232 metadataCaseBuilder.setMetadata(metadataBuilder.build());
233 matchEntryBuilder.setMatchEntryValue(metadataCaseBuilder.build());
234 matchEntryBuilder.setHasMask(hasmask);
235 matchEntryList.add(matchEntryBuilder.build());
238 private static void packetTypeMatch(final List<MatchEntry> matchEntryList, final PacketTypeMatch packetTypeMatch) {
239 if (packetTypeMatch == null) {
243 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
244 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
245 matchEntryBuilder.setOxmMatchField(PacketType.VALUE);
246 matchEntryBuilder.setHasMask(false);
247 PacketTypeCaseBuilder packetTypeCaseBuilder = new PacketTypeCaseBuilder();
248 PacketTypeBuilder packetTypeBuilder = new PacketTypeBuilder();
249 packetTypeBuilder.setPacketType(packetTypeMatch.getPacketType());
250 packetTypeCaseBuilder.setPacketType(packetTypeBuilder.build());
251 matchEntryBuilder.setMatchEntryValue(packetTypeCaseBuilder.build());
252 matchEntryList.add(matchEntryBuilder.build());
255 private static void tunnelMatch(final List<MatchEntry> matchEntryList,
256 final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel) {
257 if (tunnel == null) {
261 TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder();
262 TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder();
263 boolean hasMask = tunnel.getTunnelMask() != null;
266 tunnelIdBuilder.setMask(ByteUtil.uint64toBytes(tunnel.getTunnelMask()));
269 tunnelIdBuilder.setTunnelId(ByteUtil.uint64toBytes(tunnel.getTunnelId()));
270 tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build());
272 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
273 matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build());
274 matchEntryBuilder.setHasMask(hasMask);
275 matchEntryBuilder.setOxmMatchField(TunnelId.VALUE);
276 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
277 matchEntryList.add(matchEntryBuilder.build());
280 private static void protocolMatchFields(final List<MatchEntry> matchEntryList,
281 final ProtocolMatchFields protocolMatchFields) {
282 if (protocolMatchFields == null) {
286 if (protocolMatchFields.getMplsLabel() != null) {
287 matchEntryList.add(toOfMplsLabel(protocolMatchFields.getMplsLabel()));
290 if (protocolMatchFields.getMplsBos() != null) {
291 matchEntryList.add(toOfMplsBos(protocolMatchFields.getMplsBos()));
294 if (protocolMatchFields.getMplsTc() != null) {
295 matchEntryList.add(toOfMplsTc(protocolMatchFields.getMplsTc()));
298 if (protocolMatchFields.getPbb() != null) {
299 matchEntryList.add(toOfMplsPbb(protocolMatchFields.getPbb()));
303 private static void icmpv6Match(final List<MatchEntry> matchEntryList, final Icmpv6Match icmpv6Match) {
304 if (icmpv6Match == null) {
308 if (icmpv6Match.getIcmpv6Type() != null) {
309 matchEntryList.add(toOfIcmpv6Type(icmpv6Match.getIcmpv6Type()));
312 if (icmpv6Match.getIcmpv6Code() != null) {
313 matchEntryList.add(toOfIcmpv6Code(icmpv6Match.getIcmpv6Code()));
317 private static void icmpv4Match(final List<MatchEntry> matchEntryList, final Icmpv4Match icmpv4Match) {
318 if (icmpv4Match == null) {
322 if (icmpv4Match.getIcmpv4Type() != null) {
323 matchEntryList.add(toOfIcmpv4Type(icmpv4Match.getIcmpv4Type()));
326 if (icmpv4Match.getIcmpv4Code() != null) {
327 matchEntryList.add(toOfIcmpv4Code(icmpv4Match.getIcmpv4Code()));
331 private static void ipMatch(final List<MatchEntry> matchEntryList, final IpMatch ipMatch) {
332 if (ipMatch == null) {
336 if (ipMatch.getIpDscp() != null) {
337 matchEntryList.add(MatchConvertorUtil.toOfIpDscp(ipMatch.getIpDscp()));
340 if (ipMatch.getIpEcn() != null) {
341 matchEntryList.add(toOfIpEcn(ipMatch.getIpEcn()));
344 if (ipMatch.getIpProtocol() != null) {
345 matchEntryList.add(toOfIpProto(ipMatch.getIpProtocol()));
349 private static void vlanMatch(final List<MatchEntry> matchEntryList, final VlanMatch vlanMatch) {
350 if (vlanMatch == null) {
354 if (vlanMatch.getVlanId() != null) {
355 VlanId vlanId = vlanMatch.getVlanId();
356 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
357 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
358 matchEntryBuilder.setOxmMatchField(VlanVid.VALUE);
359 VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
360 boolean setCfiBit = false;
361 Uint16 vidEntryValue = Uint16.ZERO;
362 boolean hasmask = false;
364 if (Boolean.TRUE.equals(vlanId.getVlanIdPresent())) {
366 if (vlanId.getVlanId() != null) {
367 vidEntryValue = vlanId.getVlanId().getValue();
370 hasmask = vidEntryValue.toJava() == 0;
372 vlanVidBuilder.setMask(VLAN_VID_MASK);
376 vlanVidBuilder.setCfiBit(setCfiBit);
377 vlanVidBuilder.setVlanVid(vidEntryValue);
378 VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
379 vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
380 matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
381 matchEntryBuilder.setHasMask(hasmask);
382 matchEntryList.add(matchEntryBuilder.build());
385 if (vlanMatch.getVlanPcp() != null) {
386 matchEntryList.add(MatchConvertorUtil.toOfVlanPcp(vlanMatch.getVlanPcp()));
390 private static void ethernetMatch(final List<MatchEntry> matchEntryList, final EthernetMatch ethernetMatch) {
391 if (ethernetMatch == null) {
395 EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
396 if (ethernetDestination != null) {
397 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
398 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
399 matchEntryBuilder.setOxmMatchField(EthDst.VALUE);
400 EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder();
401 EthDstBuilder ethDstBuilder = new EthDstBuilder();
402 ethDstBuilder.setMacAddress(ethernetDestination.getAddress());
403 boolean hasMask = ethernetDestination.getMask() != null;
406 ethDstBuilder.setMask(IetfYangUtil.macAddressBytes(ethernetDestination.getMask()));
409 ethDstCaseBuilder.setEthDst(ethDstBuilder.build());
410 matchEntryBuilder.setMatchEntryValue(ethDstCaseBuilder.build());
411 matchEntryBuilder.setHasMask(hasMask);
412 matchEntryList.add(matchEntryBuilder.build());
415 EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
416 if (ethernetSource != null) {
417 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
418 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
419 matchEntryBuilder.setOxmMatchField(EthSrc.VALUE);
420 EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder();
421 EthSrcBuilder ethDstBuilder = new EthSrcBuilder();
422 ethDstBuilder.setMacAddress(ethernetSource.getAddress());
423 boolean hasMask = ethernetSource.getMask() != null;
426 ethDstBuilder.setMask(IetfYangUtil.macAddressBytes(ethernetSource.getMask()));
429 ethSrcCaseBuilder.setEthSrc(ethDstBuilder.build());
430 matchEntryBuilder.setMatchEntryValue(ethSrcCaseBuilder.build());
431 matchEntryBuilder.setHasMask(hasMask);
432 matchEntryList.add(matchEntryBuilder.build());
435 if (ethernetMatch.getEthernetType() != null) {
436 matchEntryList.add(toOfEthernetType(ethernetMatch.getEthernetType()));
440 private static void tcpFlagsMatch(final List<MatchEntry> matchEntryList, final TcpFlagsMatch tcpFlagsMatch) {
441 ExperimenterIdCaseBuilder expIdCaseBuilder = new ExperimenterIdCaseBuilder();
442 if (tcpFlagsMatch != null) {
443 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder()
444 .setOxmClass(ExperimenterClass.VALUE)
446 .setOxmMatchField(TcpFlags.VALUE);
448 TcpFlagsContainerBuilder tcpFlagsContainerBuilder = new TcpFlagsContainerBuilder();
449 TcpFlagsBuilder tcpFlagsBuilder = new TcpFlagsBuilder();
450 tcpFlagsBuilder.setFlags(tcpFlagsMatch.getTcpFlags());
451 if (tcpFlagsMatch.getTcpFlagsMask() != null) {
452 matchEntryBuilder.setHasMask(true);
453 tcpFlagsBuilder.setMask(ByteUtil.unsignedShortToBytes(tcpFlagsMatch.getTcpFlagsMask()));
455 tcpFlagsContainerBuilder.setTcpFlags(tcpFlagsBuilder.build());
457 //Set experimenter ID.
458 expIdCaseBuilder.setExperimenter(new ExperimenterBuilder()
459 .setExperimenter(OFApprovedExperimenterIds.MATCH_TCP_FLAGS_EXP_ID)
462 expIdCaseBuilder.addAugmentation(tcpFlagsContainerBuilder.build());
463 matchEntryBuilder.setMatchEntryValue(expIdCaseBuilder.build());
464 matchEntryList.add(matchEntryBuilder.build());
468 private static MatchEntry toOfMplsPbb(final Pbb pbb) {
469 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
470 final boolean hasmask = pbb.getPbbMask() != null;
471 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
472 matchEntryBuilder.setOxmMatchField(PbbIsid.VALUE);
473 PbbIsidCaseBuilder pbbIsidCaseBuilder = new PbbIsidCaseBuilder();
474 PbbIsidBuilder pbbIsidBuilder = new PbbIsidBuilder();
475 pbbIsidBuilder.setIsid(pbb.getPbbIsid());
478 pbbIsidBuilder.setMask(ByteUtil.unsignedMediumToBytes(pbb.getPbbMask()));
481 pbbIsidCaseBuilder.setPbbIsid(pbbIsidBuilder.build());
482 matchEntryBuilder.setMatchEntryValue(pbbIsidCaseBuilder.build());
483 matchEntryBuilder.setHasMask(hasmask);
484 return matchEntryBuilder.build();
487 private static MatchEntry toOfMplsTc(final Uint8 mplsTc) {
488 return new MatchEntryBuilder()
489 .setOxmClass(OpenflowBasicClass.VALUE)
490 .setHasMask(Boolean.FALSE)
491 .setOxmMatchField(MplsTc.VALUE)
492 .setMatchEntryValue(new MplsTcCaseBuilder()
493 .setMplsTc(new MplsTcBuilder().setTc(mplsTc).build())
498 private static MatchEntry toOfMplsBos(final Uint8 mplsBos) {
499 return new MatchEntryBuilder()
500 .setOxmClass(OpenflowBasicClass.VALUE)
501 .setHasMask(Boolean.FALSE)
502 .setOxmMatchField(MplsBos.VALUE)
503 .setMatchEntryValue(new MplsBosCaseBuilder()
504 .setMplsBos(new MplsBosBuilder().setBos(mplsBos.toJava() != 0).build())
509 private static MatchEntry toOfMplsLabel(final Uint32 mplsLabel) {
510 return new MatchEntryBuilder()
511 .setOxmClass(OpenflowBasicClass.VALUE)
512 .setHasMask(Boolean.FALSE)
513 .setOxmMatchField(MplsLabel.VALUE)
514 .setMatchEntryValue(new MplsLabelCaseBuilder()
515 .setMplsLabel(new MplsLabelBuilder().setMplsLabel(mplsLabel).build())
520 private static MatchEntry toOfEthernetType(final EthernetType ethernetType) {
521 MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
522 matchEntryBuilder.setOxmClass(OpenflowBasicClass.VALUE);
523 matchEntryBuilder.setHasMask(false);
524 matchEntryBuilder.setOxmMatchField(EthType.VALUE);
525 EthTypeCaseBuilder ethTypeCaseBuilder = new EthTypeCaseBuilder();
526 EthTypeBuilder ethTypeBuilder = new EthTypeBuilder();
527 EtherType etherType = new EtherType(ethernetType.getType().getValue().toUint16());
528 ethTypeBuilder.setEthType(etherType);
529 ethTypeCaseBuilder.setEthType(ethTypeBuilder.build());
530 matchEntryBuilder.setMatchEntryValue(ethTypeCaseBuilder.build());
531 return matchEntryBuilder.build();
534 private static MatchEntry toOfIcmpv4Type(final Uint8 icmpv4Type) {
535 return new MatchEntryBuilder()
536 .setOxmClass(OpenflowBasicClass.VALUE)
537 .setHasMask(Boolean.FALSE)
538 .setOxmMatchField(Icmpv4Type.VALUE)
539 .setMatchEntryValue(new Icmpv4TypeCaseBuilder()
540 .setIcmpv4Type(new Icmpv4TypeBuilder().setIcmpv4Type(icmpv4Type).build())
545 private static MatchEntry toOfIcmpv4Code(final Uint8 icmpv4Code) {
546 return new MatchEntryBuilder()
547 .setOxmClass(OpenflowBasicClass.VALUE)
548 .setHasMask(Boolean.FALSE)
549 .setOxmMatchField(Icmpv4Code.VALUE)
550 .setMatchEntryValue(new Icmpv4CodeCaseBuilder()
551 .setIcmpv4Code(new Icmpv4CodeBuilder().setIcmpv4Code(icmpv4Code).build()).build())
555 private static MatchEntry toOfIcmpv6Type(final Uint8 icmpv6Type) {
556 return new MatchEntryBuilder()
557 .setOxmClass(OpenflowBasicClass.VALUE)
558 .setHasMask(Boolean.FALSE)
559 .setOxmMatchField(Icmpv6Type.VALUE)
560 .setMatchEntryValue(new Icmpv6TypeCaseBuilder()
561 .setIcmpv6Type(new Icmpv6TypeBuilder().setIcmpv6Type(icmpv6Type).build())
566 private static MatchEntry toOfIcmpv6Code(final Uint8 icmpv6Code) {
567 return new MatchEntryBuilder()
568 .setOxmClass(OpenflowBasicClass.VALUE)
569 .setHasMask(Boolean.FALSE)
570 .setOxmMatchField(Icmpv6Code.VALUE)
571 .setMatchEntryValue(new Icmpv6CodeCaseBuilder()
572 .setIcmpv6Code(new Icmpv6CodeBuilder().setIcmpv6Code(icmpv6Code).build())
577 private static MatchEntry toOfIpProto(final Uint8 ipProtocol) {
578 return new MatchEntryBuilder()
579 .setOxmClass(OpenflowBasicClass.VALUE)
580 .setHasMask(Boolean.FALSE)
581 .setOxmMatchField(IpProto.VALUE)
582 .setMatchEntryValue(new IpProtoCaseBuilder()
583 .setIpProto(new IpProtoBuilder().setProtocolNumber(ipProtocol).build())
588 private static MatchEntry toOfIpEcn(final Uint8 ipEcn) {
589 return new MatchEntryBuilder()
590 .setOxmClass(OpenflowBasicClass.VALUE)
591 .setHasMask(Boolean.FALSE)
592 .setOxmMatchField(IpEcn.VALUE)
593 .setMatchEntryValue(new IpEcnCaseBuilder().setIpEcn(new IpEcnBuilder().setEcn(ipEcn).build()).build())
598 * Create default empty match entries
599 * Use this method, if result from converter is empty.
601 public static List<MatchEntry> defaultResult() {
602 return FlowConvertor.DEFAULT_MATCH_ENTRIES;
606 public Collection<Class<?>> getTypes() {
611 public List<MatchEntry> convert(final Match source, final VersionConvertorData data) {
612 List<MatchEntry> result = new ArrayList<>();
614 if (source == null) {
618 final ExtensionConverterProvider extensionConvertorProvider = OFSessionUtil.getExtensionConvertorProvider();
620 inPortMatch(result, source.getInPort());
621 inPhyPortMatch(result, source.getInPhyPort());
622 metadataMatch(result, source.getMetadata());
623 packetTypeMatch(result, source.getPacketTypeMatch());
624 ethernetMatch(result, source.getEthernetMatch());
625 vlanMatch(result, source.getVlanMatch());
626 ipMatch(result, source.getIpMatch());
627 layer4Match(result, source.getLayer4Match(), getConvertorExecutor(), extensionConvertorProvider);
628 icmpv4Match(result, source.getIcmpv4Match());
629 icmpv6Match(result, source.getIcmpv6Match());
630 layer3Match(result, source.getLayer3Match(), getConvertorExecutor(), extensionConvertorProvider);
631 protocolMatchFields(result, source.getProtocolMatchFields());
632 tunnelMatch(result, source.getTunnel());
633 tcpFlagsMatch(result, source.getTcpFlagsMatch());
636 * TODO: EXTENSION PROPOSAL (source, MD-SAL to OFJava)
637 * - we might need version for conversion and for key
639 Optional<GeneralExtensionListGrouping> extensionListOpt =
640 ExtensionResolvers.getMatchExtensionResolver().getExtension(source);
641 if (extensionListOpt.isPresent()) {
642 for (ExtensionList extensionItem : extensionListOpt.orElseThrow().nonnullExtensionList().values()) {
643 // TODO: get real version
644 ConverterExtensionKey<? extends ExtensionKey> key =
645 new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
646 ConvertorToOFJava<MatchEntry> convertor = extensionConvertorProvider.getConverter(key);
647 if (convertor == null) {
648 throw new IllegalStateException("No converter found for key: " + key.toString());
650 result.add(convertor.convert(extensionItem.getExtension()));