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