Merge "Technical debt MeterUtil, GroupUtil, FlowUtil"
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchConvertorImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match;
10
11
12 import com.google.common.base.Optional;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.openflowjava.util.ByteBufUtils;
16 import org.opendaylight.openflowplugin.api.OFConstants;
17 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
18 import org.opendaylight.openflowplugin.extension.api.ConverterExtensionKey;
19 import org.opendaylight.openflowplugin.extension.api.ConvertorToOFJava;
20 import org.opendaylight.openflowplugin.openflow.md.core.extension.ExtensionResolvers;
21 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.OFApprovedExperimenterIds;
22 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.ConvertorExecutor;
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.match.cases.SalToOfArpMatchCase;
26 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchArbitraryBitMaskCase;
27 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv4MatchCase;
28 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchArbitraryBitMaskCase;
29 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfIpv6MatchCase;
30 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfSctpMatchCase;
31 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTcpMatchCase;
32 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfTunnelIpv4MatchCase;
33 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match.cases.SalToOfUdpMatchCase;
34 import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
35 import org.opendaylight.openflowplugin.openflow.md.util.ByteUtil;
36 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestination;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSource;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetType;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv6Match;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.ProtocolMatchFields;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.TcpFlagsMatch;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.protocol.match.fields.Pbb;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanId;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlags;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlagsContainer;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.TcpFlagsContainerBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.approved.extensions.rev160802.oxm.container.match.entry.value.experimenter.id._case.TcpFlagsBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.ExperimenterIdCaseBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.augments.rev150225.oxm.container.match.entry.value.experimenter.id._case.ExperimenterBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.EtherType;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.ExperimenterId;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumber;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthDst;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthSrc;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.EthType;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.ExperimenterClass;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Code;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv4Type;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Code;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Icmpv6Type;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPhyPort;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.InPort;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpEcn;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.IpProto;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.Metadata;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsBos;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsLabel;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.MplsTc;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.OpenflowBasicClass;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.PbbIsid;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.TunnelId;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.VlanVid;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entries.grouping.MatchEntryBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthDstCaseBuilder;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthSrcCaseBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.EthTypeCaseBuilder;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4CodeCaseBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv4TypeCaseBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6CodeCaseBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.Icmpv6TypeCaseBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPhyPortCaseBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.InPortCaseBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpEcnCaseBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.IpProtoCaseBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MetadataCaseBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsBosCaseBuilder;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsLabelCaseBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.MplsTcCaseBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.PbbIsidCaseBuilder;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.TunnelIdCaseBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.VlanVidCaseBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.dst._case.EthDstBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.src._case.EthSrcBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.eth.type._case.EthTypeBuilder;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.code._case.Icmpv4CodeBuilder;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv4.type._case.Icmpv4TypeBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.code._case.Icmpv6CodeBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.icmpv6.type._case.Icmpv6TypeBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.phy.port._case.InPhyPortBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.in.port._case.InPortBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.ecn._case.IpEcnBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.ip.proto._case.IpProtoBuilder;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.bos._case.MplsBosBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.label._case.MplsLabelBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.mpls.tc._case.MplsTcBuilder;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.pbb.isid._case.PbbIsidBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.tunnel.id._case.TunnelIdBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.entry.value.grouping.match.entry.value.vlan.vid._case.VlanVidBuilder;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.ExtensionKey;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.GeneralExtensionListGrouping;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowplugin.extension.general.rev140714.general.extension.list.grouping.ExtensionList;
122
123 /**
124  * Utility class for converting a MD-SAL Flow into the OF flow mod
125  */
126 public class MatchConvertorImpl implements MatchConvertor<List<MatchEntry>> {
127     private static final ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData> LAYER3_PROCESSOR = new ConvertorProcessor<Layer3Match, List<MatchEntry>, VersionConvertorData>()
128             .addCase(new SalToOfIpv4MatchArbitraryBitMaskCase())
129             .addCase(new SalToOfIpv4MatchCase())
130             .addCase(new SalToOfTunnelIpv4MatchCase())
131             .addCase(new SalToOfArpMatchCase())
132             .addCase(new SalToOfIpv6MatchArbitraryBitMaskCase())
133             .addCase(new SalToOfIpv6MatchCase());
134
135     private static final ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData> LAYER4_PROCESSOR = new ConvertorProcessor<Layer4Match, List<MatchEntry>, VersionConvertorData>()
136             .addCase(new SalToOfTcpMatchCase())
137             .addCase(new SalToOfUdpMatchCase())
138             .addCase(new SalToOfSctpMatchCase());
139
140     private static final byte[] VLAN_VID_MASK = new byte[]{16, 0};
141
142     private static void layer3Match(final List<MatchEntry> matchEntryList, final Layer3Match layer3Match, ConvertorExecutor convertorExecutor) {
143         java.util.Optional<List<MatchEntry>> result = LAYER3_PROCESSOR.process(layer3Match, convertorExecutor);
144
145         if (result.isPresent()) {
146             matchEntryList.addAll(result.get());
147         }
148     }
149
150     private static void layer4Match(final List<MatchEntry> matchEntryList, final Layer4Match layer4Match, ConvertorExecutor convertorExecutor) {
151         java.util.Optional<List<MatchEntry>> result = LAYER4_PROCESSOR.process(layer4Match, convertorExecutor);
152
153         if (result.isPresent()) {
154             matchEntryList.addAll(result.get());
155         }
156     }
157
158     private static void inPortMatch(final List<MatchEntry> matchEntryList, NodeConnectorId inPort) {
159         if (inPort == null) {
160             return;
161         }
162
163         //TODO: currently this matchconverter is mapped to OF1.3 in MatchReactorMappingFactory. Will need to revisit during 1.4+
164         final long portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPort);
165         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
166         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
167         matchEntryBuilder.setHasMask(false);
168         matchEntryBuilder.setOxmMatchField(InPort.class);
169         InPortCaseBuilder caseBuilder = new InPortCaseBuilder();
170         InPortBuilder portBuilder = new InPortBuilder();
171         portBuilder.setPortNumber(new PortNumber(portNumber));
172         caseBuilder.setInPort(portBuilder.build());
173         matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
174         matchEntryList.add(matchEntryBuilder.build());
175     }
176
177     private static void inPhyPortMatch(final List<MatchEntry> matchEntryList, NodeConnectorId inPhyPort) {
178         if (inPhyPort == null) {
179             return;
180         }
181
182         //TODO: currently this matchconverter is mapped to OF1.3 in MatchReactorMappingFactory. Will need to revisit during 1.4+
183         final long portNumber = InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF13, inPhyPort);
184         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
185         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
186         matchEntryBuilder.setHasMask(false);
187         matchEntryBuilder.setOxmMatchField(InPhyPort.class);
188         InPhyPortCaseBuilder caseBuilder = new InPhyPortCaseBuilder();
189         InPhyPortBuilder portBuilder = new InPhyPortBuilder();
190         portBuilder.setPortNumber(new PortNumber(portNumber));
191         caseBuilder.setInPhyPort(portBuilder.build());
192         matchEntryBuilder.setMatchEntryValue(caseBuilder.build());
193         matchEntryList.add(matchEntryBuilder.build());
194     }
195
196     private static void metadataMatch(final List<MatchEntry> matchEntryList,
197                                       final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Metadata metadata) {
198         if (metadata == null) {
199             return;
200         }
201
202         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
203         boolean hasmask = metadata.getMetadataMask() != null;
204         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
205         matchEntryBuilder.setOxmMatchField(Metadata.class);
206         MetadataCaseBuilder metadataCaseBuilder = new MetadataCaseBuilder();
207         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();
208         metadataBuilder.setMetadata(ByteUtil.convertBigIntegerToNBytes(metadata.getMetadata(), OFConstants.SIZE_OF_LONG_IN_BYTES));
209
210         if (hasmask) {
211             metadataBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(metadata.getMetadataMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
212         }
213
214         metadataCaseBuilder.setMetadata(metadataBuilder.build());
215         matchEntryBuilder.setMatchEntryValue(metadataCaseBuilder.build());
216         matchEntryBuilder.setHasMask(hasmask);
217         matchEntryList.add(matchEntryBuilder.build());
218     }
219
220     private static void tunnelMatch(final List<MatchEntry> matchEntryList,
221                                     final org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Tunnel tunnel) {
222         if (tunnel == null) {
223             return;
224         }
225
226         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
227         TunnelIdCaseBuilder tunnelIdCaseBuilder = new TunnelIdCaseBuilder();
228         TunnelIdBuilder tunnelIdBuilder = new TunnelIdBuilder();
229         boolean hasMask = tunnel.getTunnelMask() != null;
230
231         if (hasMask) {
232             tunnelIdBuilder.setMask(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelMask(), OFConstants.SIZE_OF_LONG_IN_BYTES));
233         }
234
235         tunnelIdBuilder.setTunnelId(ByteUtil.convertBigIntegerToNBytes(tunnel.getTunnelId(), OFConstants.SIZE_OF_LONG_IN_BYTES));
236         tunnelIdCaseBuilder.setTunnelId(tunnelIdBuilder.build());
237         matchEntryBuilder.setMatchEntryValue(tunnelIdCaseBuilder.build());
238         matchEntryBuilder.setHasMask(hasMask);
239         matchEntryBuilder.setOxmMatchField(TunnelId.class);
240         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
241         matchEntryList.add(matchEntryBuilder.build());
242     }
243
244     private static void protocolMatchFields(final List<MatchEntry> matchEntryList,
245                                             final ProtocolMatchFields protocolMatchFields) {
246         if (protocolMatchFields == null) {
247             return;
248         }
249
250         if (protocolMatchFields.getMplsLabel() != null) {
251             matchEntryList.add(toOfMplsLabel(protocolMatchFields.getMplsLabel()));
252         }
253
254         if (protocolMatchFields.getMplsBos() != null) {
255             matchEntryList.add(toOfMplsBos(protocolMatchFields.getMplsBos()));
256         }
257
258         if (protocolMatchFields.getMplsTc() != null) {
259             matchEntryList.add(toOfMplsTc(protocolMatchFields.getMplsTc()));
260         }
261
262         if (protocolMatchFields.getPbb() != null) {
263             matchEntryList.add(toOfMplsPbb(protocolMatchFields.getPbb()));
264         }
265     }
266
267     private static void icmpv6Match(final List<MatchEntry> matchEntryList, final Icmpv6Match icmpv6Match) {
268         if (icmpv6Match == null) {
269             return;
270         }
271
272         if (icmpv6Match.getIcmpv6Type() != null) {
273             matchEntryList.add(toOfIcmpv6Type(icmpv6Match.getIcmpv6Type()));
274         }
275
276         if (icmpv6Match.getIcmpv6Code() != null) {
277             matchEntryList.add(toOfIcmpv6Code(icmpv6Match.getIcmpv6Code()));
278         }
279     }
280
281     private static void icmpv4Match(final List<MatchEntry> matchEntryList, final Icmpv4Match icmpv4Match) {
282         if (icmpv4Match == null) {
283             return;
284         }
285
286         if (icmpv4Match.getIcmpv4Type() != null) {
287             matchEntryList.add(toOfIcmpv4Type(icmpv4Match.getIcmpv4Type()));
288         }
289
290         if (icmpv4Match.getIcmpv4Code() != null) {
291             matchEntryList.add(toOfIcmpv4Code(icmpv4Match.getIcmpv4Code()));
292         }
293     }
294
295     private static void ipMatch(final List<MatchEntry> matchEntryList, final IpMatch ipMatch) {
296         if (ipMatch == null) {
297             return;
298         }
299
300         if (ipMatch.getIpDscp() != null) {
301             matchEntryList.add(MatchConvertorUtil.toOfIpDscp(ipMatch.getIpDscp()));
302         }
303
304         if (ipMatch.getIpEcn() != null) {
305             matchEntryList.add(toOfIpEcn(ipMatch.getIpEcn()));
306         }
307
308         if (ipMatch.getIpProtocol() != null) {
309             matchEntryList.add(toOfIpProto(ipMatch.getIpProtocol()));
310         }
311     }
312
313     private static void vlanMatch(final List<MatchEntry> matchEntryList, final VlanMatch vlanMatch) {
314         if (vlanMatch == null) {
315             return;
316         }
317
318         if (vlanMatch.getVlanId() != null) {
319             VlanId vlanId = vlanMatch.getVlanId();
320             MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
321             matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
322             matchEntryBuilder.setOxmMatchField(VlanVid.class);
323             VlanVidCaseBuilder vlanVidCaseBuilder = new VlanVidCaseBuilder();
324             VlanVidBuilder vlanVidBuilder = new VlanVidBuilder();
325             boolean setCfiBit = false;
326             Integer vidEntryValue = 0;
327             boolean hasmask = false;
328
329             if (Boolean.TRUE.equals(vlanId.isVlanIdPresent())) {
330                 setCfiBit = true;
331                 if (vlanId.getVlanId() != null) {
332                     vidEntryValue = vlanId.getVlanId().getValue();
333                 }
334
335                 hasmask = (vidEntryValue == 0);
336                 if (hasmask) {
337                     vlanVidBuilder.setMask(VLAN_VID_MASK);
338                 }
339             }
340
341             vlanVidBuilder.setCfiBit(setCfiBit);
342             vlanVidBuilder.setVlanVid(vidEntryValue);
343             vlanVidCaseBuilder.setVlanVid(vlanVidBuilder.build());
344             matchEntryBuilder.setMatchEntryValue(vlanVidCaseBuilder.build());
345             matchEntryBuilder.setHasMask(hasmask);
346             matchEntryList.add(matchEntryBuilder.build());
347         }
348
349         if (vlanMatch.getVlanPcp() != null) {
350             matchEntryList.add(MatchConvertorUtil.toOfVlanPcp(vlanMatch.getVlanPcp()));
351         }
352     }
353
354     private static void ethernetMatch(final List<MatchEntry> matchEntryList, final EthernetMatch ethernetMatch) {
355         if (ethernetMatch == null) {
356             return;
357         }
358
359         EthernetDestination ethernetDestination = ethernetMatch.getEthernetDestination();
360         if (ethernetDestination != null) {
361             MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
362             matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
363             matchEntryBuilder.setOxmMatchField(EthDst.class);
364             EthDstCaseBuilder ethDstCaseBuilder = new EthDstCaseBuilder();
365             EthDstBuilder ethDstBuilder = new EthDstBuilder();
366             ethDstBuilder.setMacAddress(ethernetDestination.getAddress());
367             boolean hasMask = ethernetDestination.getMask() != null;
368
369             if (hasMask) {
370                 ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetDestination.getMask().getValue()));
371             }
372
373             ethDstCaseBuilder.setEthDst(ethDstBuilder.build());
374             matchEntryBuilder.setMatchEntryValue(ethDstCaseBuilder.build());
375             matchEntryBuilder.setHasMask(hasMask);
376             matchEntryList.add(matchEntryBuilder.build());
377         }
378
379         EthernetSource ethernetSource = ethernetMatch.getEthernetSource();
380         if (ethernetSource != null) {
381             MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
382             matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
383             matchEntryBuilder.setOxmMatchField(EthSrc.class);
384             EthSrcCaseBuilder ethSrcCaseBuilder = new EthSrcCaseBuilder();
385             EthSrcBuilder ethDstBuilder = new EthSrcBuilder();
386             ethDstBuilder.setMacAddress(ethernetSource.getAddress());
387             boolean hasMask = ethernetSource.getMask() != null;
388
389             if (hasMask) {
390                 ethDstBuilder.setMask(ByteBufUtils.macAddressToBytes(ethernetSource.getMask().getValue()));
391             }
392
393             ethSrcCaseBuilder.setEthSrc(ethDstBuilder.build());
394             matchEntryBuilder.setMatchEntryValue(ethSrcCaseBuilder.build());
395             matchEntryBuilder.setHasMask(hasMask);
396             matchEntryList.add(matchEntryBuilder.build());
397         }
398
399         if (ethernetMatch.getEthernetType() != null) {
400             matchEntryList.add(toOfEthernetType(ethernetMatch.getEthernetType()));
401         }
402     }
403
404     private static void tcpFlagsMatch(List<MatchEntry> matchEntryList, TcpFlagsMatch tcpFlagsMatch) {
405         ExperimenterIdCaseBuilder expIdCaseBuilder = new ExperimenterIdCaseBuilder();
406         if (tcpFlagsMatch != null) {
407             MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
408             matchEntryBuilder.setOxmClass(ExperimenterClass.class);
409             matchEntryBuilder.setHasMask(false);
410             matchEntryBuilder.setOxmMatchField(TcpFlags.class);
411
412             TcpFlagsContainerBuilder tcpFlagsContainerBuilder = new TcpFlagsContainerBuilder();
413             TcpFlagsBuilder tcpFlagsBuilder = new TcpFlagsBuilder();
414             tcpFlagsBuilder.setFlags(tcpFlagsMatch.getTcpFlags());
415             if(tcpFlagsMatch.getTcpFlagsMask() != null) {
416                 matchEntryBuilder.setHasMask(true);
417                 tcpFlagsBuilder.setMask(ByteUtil.unsignedShortToBytes(tcpFlagsMatch.getTcpFlagsMask()));
418             }
419             tcpFlagsContainerBuilder.setTcpFlags(tcpFlagsBuilder.build());
420
421             //Set experimenter ID.
422             ExperimenterBuilder experimenterBuilder = new ExperimenterBuilder();
423             experimenterBuilder.setExperimenter(new ExperimenterId(OFApprovedExperimenterIds.MATCH_TCP_FLAGS_EXP_ID));
424             expIdCaseBuilder.setExperimenter(experimenterBuilder.build());
425
426             expIdCaseBuilder.addAugmentation(TcpFlagsContainer.class, tcpFlagsContainerBuilder.build());
427             matchEntryBuilder.setMatchEntryValue(expIdCaseBuilder.build());
428             matchEntryList.add(matchEntryBuilder.build());
429         }
430     }
431
432     private static MatchEntry toOfMplsPbb(final Pbb pbb) {
433         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
434         boolean hasmask = pbb.getPbbMask() != null;
435         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
436         matchEntryBuilder.setOxmMatchField(PbbIsid.class);
437         PbbIsidCaseBuilder pbbIsidCaseBuilder = new PbbIsidCaseBuilder();
438         PbbIsidBuilder pbbIsidBuilder = new PbbIsidBuilder();
439         pbbIsidBuilder.setIsid(pbb.getPbbIsid());
440
441         if (hasmask) {
442             pbbIsidBuilder.setMask(ByteUtil.unsignedMediumToBytes(pbb.getPbbMask()));
443         }
444
445         pbbIsidCaseBuilder.setPbbIsid(pbbIsidBuilder.build());
446         matchEntryBuilder.setMatchEntryValue(pbbIsidCaseBuilder.build());
447         matchEntryBuilder.setHasMask(hasmask);
448         return matchEntryBuilder.build();
449     }
450
451     private static MatchEntry toOfMplsTc(final Short mplsTc) {
452         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
453         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
454         matchEntryBuilder.setHasMask(false);
455         matchEntryBuilder.setOxmMatchField(MplsTc.class);
456         MplsTcCaseBuilder mplsTcCaseBuilder = new MplsTcCaseBuilder();
457         MplsTcBuilder mplsTcBuilder = new MplsTcBuilder();
458         mplsTcBuilder.setTc(mplsTc);
459         mplsTcCaseBuilder.setMplsTc(mplsTcBuilder.build());
460         matchEntryBuilder.setMatchEntryValue(mplsTcCaseBuilder.build());
461         return matchEntryBuilder.build();
462     }
463
464     private static MatchEntry toOfMplsBos(final Short mplsBos) {
465         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
466         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
467         matchEntryBuilder.setHasMask(false);
468         matchEntryBuilder.setOxmMatchField(MplsBos.class);
469         MplsBosCaseBuilder mplsBosCaseBuilder = new MplsBosCaseBuilder();
470         MplsBosBuilder mplsBosBuilder = new MplsBosBuilder();
471         mplsBosBuilder.setBos(mplsBos != 0);
472         mplsBosCaseBuilder.setMplsBos(mplsBosBuilder.build());
473         matchEntryBuilder.setMatchEntryValue(mplsBosCaseBuilder.build());
474         return matchEntryBuilder.build();
475     }
476
477     private static MatchEntry toOfMplsLabel(final Long mplsLabel) {
478         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
479         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
480         matchEntryBuilder.setHasMask(false);
481         matchEntryBuilder.setOxmMatchField(MplsLabel.class);
482         MplsLabelCaseBuilder mplsLabelCaseBuilder = new MplsLabelCaseBuilder();
483         MplsLabelBuilder mplsLabelBuilder = new MplsLabelBuilder();
484         mplsLabelBuilder.setMplsLabel(mplsLabel);
485         mplsLabelCaseBuilder.setMplsLabel(mplsLabelBuilder.build());
486         matchEntryBuilder.setMatchEntryValue(mplsLabelCaseBuilder.build());
487         return matchEntryBuilder.build();
488     }
489
490     private static MatchEntry toOfEthernetType(final EthernetType ethernetType) {
491         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
492         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
493         matchEntryBuilder.setHasMask(false);
494         matchEntryBuilder.setOxmMatchField(EthType.class);
495         EthTypeCaseBuilder ethTypeCaseBuilder = new EthTypeCaseBuilder();
496         EthTypeBuilder ethTypeBuilder = new EthTypeBuilder();
497         EtherType etherType = new EtherType(ethernetType.getType().getValue().intValue());
498         ethTypeBuilder.setEthType(etherType);
499         ethTypeCaseBuilder.setEthType(ethTypeBuilder.build());
500         matchEntryBuilder.setMatchEntryValue(ethTypeCaseBuilder.build());
501         return matchEntryBuilder.build();
502     }
503
504     private static MatchEntry toOfIcmpv4Type(final Short icmpv4Type) {
505         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
506         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
507         matchEntryBuilder.setHasMask(false);
508         matchEntryBuilder.setOxmMatchField(Icmpv4Type.class);
509         Icmpv4TypeCaseBuilder icmpv4TypeCaseBuilder = new Icmpv4TypeCaseBuilder();
510         Icmpv4TypeBuilder icmpv4TypeBuilder = new Icmpv4TypeBuilder();
511         icmpv4TypeBuilder.setIcmpv4Type(icmpv4Type);
512         icmpv4TypeCaseBuilder.setIcmpv4Type(icmpv4TypeBuilder.build());
513         matchEntryBuilder.setMatchEntryValue(icmpv4TypeCaseBuilder.build());
514         return matchEntryBuilder.build();
515     }
516
517     private static MatchEntry toOfIcmpv4Code(final Short icmpv4Code) {
518         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
519         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
520         matchEntryBuilder.setHasMask(false);
521         matchEntryBuilder.setOxmMatchField(Icmpv4Code.class);
522         Icmpv4CodeCaseBuilder icmpv4CodeCaseBuilder = new Icmpv4CodeCaseBuilder();
523         Icmpv4CodeBuilder icmpv4CodeBuilder = new Icmpv4CodeBuilder();
524         icmpv4CodeBuilder.setIcmpv4Code(icmpv4Code);
525         icmpv4CodeCaseBuilder.setIcmpv4Code(icmpv4CodeBuilder.build());
526         matchEntryBuilder.setMatchEntryValue(icmpv4CodeCaseBuilder.build());
527         return matchEntryBuilder.build();
528     }
529
530     private static MatchEntry toOfIcmpv6Type(final Short icmpv6Type) {
531         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
532         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
533         matchEntryBuilder.setHasMask(false);
534         matchEntryBuilder.setOxmMatchField(Icmpv6Type.class);
535         Icmpv6TypeCaseBuilder icmpv6TypeCaseBuilder = new Icmpv6TypeCaseBuilder();
536         Icmpv6TypeBuilder icmpv6TypeBuilder = new Icmpv6TypeBuilder();
537         icmpv6TypeBuilder.setIcmpv6Type(icmpv6Type);
538         icmpv6TypeCaseBuilder.setIcmpv6Type(icmpv6TypeBuilder.build());
539         matchEntryBuilder.setMatchEntryValue(icmpv6TypeCaseBuilder.build());
540         return matchEntryBuilder.build();
541     }
542
543     private static MatchEntry toOfIcmpv6Code(final Short icmpv6Code) {
544         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
545         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
546         matchEntryBuilder.setHasMask(false);
547         matchEntryBuilder.setOxmMatchField(Icmpv6Code.class);
548         Icmpv6CodeCaseBuilder icmpv6CodeCaseBuilder = new Icmpv6CodeCaseBuilder();
549         Icmpv6CodeBuilder icmpv6CodeBuilder = new Icmpv6CodeBuilder();
550         icmpv6CodeBuilder.setIcmpv6Code(icmpv6Code);
551         icmpv6CodeCaseBuilder.setIcmpv6Code(icmpv6CodeBuilder.build());
552         matchEntryBuilder.setMatchEntryValue(icmpv6CodeCaseBuilder.build());
553         return matchEntryBuilder.build();
554     }
555
556     private static MatchEntry toOfIpProto(final Short ipProtocol) {
557         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
558         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
559         matchEntryBuilder.setHasMask(false);
560         matchEntryBuilder.setOxmMatchField(IpProto.class);
561         IpProtoCaseBuilder ipProtoCaseBuilder = new IpProtoCaseBuilder();
562         IpProtoBuilder ipProtoBuilder = new IpProtoBuilder();
563         ipProtoBuilder.setProtocolNumber(ipProtocol);
564         ipProtoCaseBuilder.setIpProto(ipProtoBuilder.build());
565         matchEntryBuilder.setMatchEntryValue(ipProtoCaseBuilder.build());
566         return matchEntryBuilder.build();
567     }
568
569     private static MatchEntry toOfIpEcn(final Short ipEcn) {
570         MatchEntryBuilder matchEntryBuilder = new MatchEntryBuilder();
571         matchEntryBuilder.setOxmClass(OpenflowBasicClass.class);
572         matchEntryBuilder.setHasMask(false);
573         matchEntryBuilder.setOxmMatchField(IpEcn.class);
574         IpEcnCaseBuilder ipEcnCaseBuilder = new IpEcnCaseBuilder();
575         IpEcnBuilder ipEcnBuilder = new IpEcnBuilder();
576         ipEcnBuilder.setEcn(ipEcn);
577         ipEcnCaseBuilder.setIpEcn(ipEcnBuilder.build());
578         matchEntryBuilder.setMatchEntryValue(ipEcnCaseBuilder.build());
579         return matchEntryBuilder.build();
580     }
581
582     @Override
583     public List<MatchEntry> convert(final Match match, ConvertorExecutor convertorExecutor) {
584         List<MatchEntry> result = new ArrayList<>();
585
586         if (match == null) {
587             return result;
588         }
589
590         inPortMatch(result, match.getInPort());
591         inPhyPortMatch(result, match.getInPhyPort());
592         metadataMatch(result, match.getMetadata());
593         ethernetMatch(result, match.getEthernetMatch());
594         vlanMatch(result, match.getVlanMatch());
595         ipMatch(result, match.getIpMatch());
596         layer4Match(result, match.getLayer4Match(), convertorExecutor);
597         icmpv4Match(result, match.getIcmpv4Match());
598         icmpv6Match(result, match.getIcmpv6Match());
599         layer3Match(result, match.getLayer3Match(), convertorExecutor);
600         protocolMatchFields(result, match.getProtocolMatchFields());
601         tunnelMatch(result, match.getTunnel());
602         tcpFlagsMatch(result, match.getTcpFlagsMatch());
603
604         /**
605          * TODO: EXTENSION PROPOSAL (match, MD-SAL to OFJava)
606          * - we might need version for conversion and for key
607          * - sanitize NPE
608          */
609         Optional<GeneralExtensionListGrouping> extensionListOpt = ExtensionResolvers.getMatchExtensionResolver().getExtension(match);
610         if (extensionListOpt.isPresent()) {
611             for (ExtensionList extensionItem : extensionListOpt.get().getExtensionList()) {
612                 // TODO: get real version
613                 ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(extensionItem.getExtensionKey(), OFConstants.OFP_VERSION_1_3);
614                 ConvertorToOFJava<MatchEntry> convertor = OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
615                 MatchEntry ofMatch = convertor.convert(extensionItem.getExtension());
616                 result.add(ofMatch);
617             }
618         }
619
620         return result;
621     }
622 }