Bug 2442 - UDP matching flow adds a match on dst port=0 (only occurs with OF10)
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchConvertorV10Impl.java
1 /**
2  * Copyright (c) 2013 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 import java.math.BigInteger;
12 import java.util.Iterator;
13
14 import org.opendaylight.openflowplugin.openflow.md.util.ActionUtil;
15 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
16 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.v10.grouping.MatchV10;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev130731.match.v10.grouping.MatchV10Builder;
32
33 /**
34  *
35  */
36 public class MatchConvertorV10Impl implements MatchConvertor<MatchV10> {
37
38     /** default MAC */
39     public static final MacAddress zeroMac = new MacAddress("00:00:00:00:00:00");
40     /** default IPv4 */
41     public static final Ipv4Address zeroIPv4 = new Ipv4Address("0.0.0.0");
42
43     /*
44      * The value 0xffff (OFP_VLAN_NONE) is used to indicate
45      * that no VLAN ID is set for OF Flow.
46      */
47     private static final int OFP_VLAN_NONE = 0xffff;
48
49     /**
50      * Method builds openflow 1.0 specific match (MatchV10) from MD-SAL match.
51      * @param match MD-SAL match
52      * @return OF-API match
53      * @author avishnoi@in.ibm.com
54      */
55     @Override
56     public MatchV10 convert(final Match match,final BigInteger datapathid) {
57         MatchV10Builder matchBuilder = new MatchV10Builder();
58         boolean _dLDST = true;
59         boolean _dLSRC = true;
60         boolean _dLTYPE = true;
61         boolean _dLVLAN = true;
62         boolean _dLVLANPCP = true;
63         boolean _iNPORT = true;
64         boolean _nWPROTO = true;
65         boolean _nWTOS = true;
66         boolean _tPDST = true;
67         boolean _tPSRC = true;
68
69         matchBuilder.setInPort(0);
70         matchBuilder.setDlDst(zeroMac);
71         matchBuilder.setDlSrc(zeroMac);
72         matchBuilder.setDlType(0);
73         matchBuilder.setDlVlan(OFP_VLAN_NONE);
74         matchBuilder.setDlVlanPcp((short) 0);
75         matchBuilder.setNwDst(zeroIPv4);
76         matchBuilder.setNwDstMask((short) 0);
77         matchBuilder.setNwSrc(zeroIPv4);
78         matchBuilder.setNwSrcMask((short) 0);
79         matchBuilder.setNwProto((short) 0);
80         matchBuilder.setNwTos((short) 0);
81         matchBuilder.setTpSrc(0);
82         matchBuilder.setTpDst(0);
83
84         if (match != null) {
85             EthernetMatch ethernetMatch = match.getEthernetMatch();
86             if(ethernetMatch!= null){
87                 _dLDST = convertEthernetDlDst(matchBuilder, ethernetMatch);
88                 _dLSRC = convertEthernetDlSrc(matchBuilder, ethernetMatch);
89                 _dLTYPE = convertEthernetDlType(matchBuilder, ethernetMatch);
90             }
91             VlanMatch vlanMatch = match.getVlanMatch();
92             if(vlanMatch!= null){
93                 _dLVLAN = convertDlVlan(matchBuilder, vlanMatch);
94                 _dLVLANPCP = convertDlVlanPcp(matchBuilder, vlanMatch);
95             }
96             NodeConnectorId inPort = match.getInPort();
97             if(inPort!=null){
98                 _iNPORT = convertInPortMatch(matchBuilder, inPort);
99             }
100             Layer3Match l3Match = match.getLayer3Match();
101             if(l3Match != null){
102                 if(l3Match instanceof Ipv4Match){
103                     Ipv4Match ipv4 = (Ipv4Match)l3Match;
104                     convertL3Ipv4SrcMatch(matchBuilder, ipv4);
105                     convertL3Ipv4DstMatch(matchBuilder, ipv4);
106                 }
107             }
108             IpMatch ipMatch = match.getIpMatch();
109             if(ipMatch!=null){
110                 _nWPROTO = convertNwProto(matchBuilder, ipMatch);
111                 _nWTOS = convertNwTos(matchBuilder, ipMatch);
112             }
113             Layer4Match layer4Match = match.getLayer4Match();
114             if (layer4Match != null) {
115                 if (layer4Match instanceof TcpMatch) {
116                     TcpMatch tcpMatch = (TcpMatch) layer4Match;
117                     _tPSRC = convertL4TpSrcMatch(matchBuilder, tcpMatch);
118                     _tPDST = convertL4TpDstMatch(matchBuilder, tcpMatch);
119                 } else if (layer4Match instanceof UdpMatch) {
120                     UdpMatch udpMatch = (UdpMatch) layer4Match;
121                     _tPSRC = convertL4UdpSrcMatch(matchBuilder, udpMatch);
122                     _tPDST = convertL4UdpDstMatch(matchBuilder, udpMatch);
123                 }
124             }
125         }
126
127         FlowWildcardsV10 wildCards = new FlowWildcardsV10(
128                 _dLDST, _dLSRC, _dLTYPE, _dLVLAN,
129                 _dLVLANPCP, _iNPORT, _nWPROTO, _nWTOS, _tPDST, _tPSRC);
130         matchBuilder.setWildcards(wildCards);
131
132         return matchBuilder.build();
133     }
134
135     /**
136      * @param matchBuilder
137      * @param udpMatch
138      * @return is wildCard
139      */
140     private static boolean convertL4UdpDstMatch(final MatchV10Builder matchBuilder,
141             final UdpMatch udpMatch) {
142         if (udpMatch.getUdpDestinationPort() != null) {
143             matchBuilder.setTpDst(udpMatch.getUdpDestinationPort().getValue());
144             return false;
145         }
146         return true;
147     }
148
149     /**
150      * @param matchBuilder
151      * @param udpMatch
152      * @return is wildCard
153      */
154     private static boolean convertL4UdpSrcMatch(final MatchV10Builder matchBuilder,
155             final UdpMatch udpMatch) {
156         if (udpMatch.getUdpSourcePort() != null) {
157             matchBuilder.setTpSrc(udpMatch.getUdpSourcePort().getValue());
158             return false;
159         }
160         return true;
161     }
162
163     /**
164      * @param matchBuilder
165      * @param tcpMatch
166      * @return is wildCard
167      */
168     private static boolean convertL4TpDstMatch(final MatchV10Builder matchBuilder,
169             final TcpMatch tcpMatch) {
170         if (tcpMatch.getTcpDestinationPort() != null) {
171             matchBuilder.setTpDst(tcpMatch.getTcpDestinationPort().getValue());
172             return false;
173         }
174         return true;
175     }
176
177     /**
178      * @param matchBuilder
179      * @param tcpMatch
180      * @return is wildCard
181      */
182     private static boolean convertL4TpSrcMatch(final MatchV10Builder matchBuilder,
183             final TcpMatch tcpMatch) {
184         if (tcpMatch.getTcpSourcePort() != null) {
185             matchBuilder.setTpSrc(tcpMatch.getTcpSourcePort().getValue());
186             return false;
187         }
188         return true;
189     }
190
191     /**
192      * @param matchBuilder
193      * @param ipMatch
194      * @return is wildCard
195      */
196     private static boolean convertNwTos(final MatchV10Builder matchBuilder,
197             final IpMatch ipMatch) {
198         if (ipMatch.getIpDscp() != null) {
199             matchBuilder.setNwTos(ActionUtil.dscpToTos(ipMatch.getIpDscp().getValue()));
200             return false;
201         }
202         return true;
203     }
204
205     /**
206      * @param matchBuilder
207      * @param ipMatch
208      * @return is wildCard
209      */
210     private static boolean convertNwProto(final MatchV10Builder matchBuilder, final IpMatch ipMatch) {
211         if (ipMatch.getIpProtocol() != null) {
212             matchBuilder.setNwProto(ipMatch.getIpProtocol());
213             return false;
214         }
215         return true;
216     }
217
218     /**
219      * Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
220      * Wildcard value of the IP mask will be determined by Openflow java encoding library.
221      * @param matchBuilder
222      * @param ipv4
223      */
224     private static void convertL3Ipv4DstMatch(final MatchV10Builder matchBuilder,
225             final Ipv4Match ipv4) {
226         if(ipv4.getIpv4Destination()!=null){
227             Iterator<String> addressParts = MatchConvertorImpl.PREFIX_SPLITTER.split(ipv4.getIpv4Destination().getValue()).iterator();
228             Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
229             Integer prefix = buildPrefix(addressParts);
230             matchBuilder.setNwDst(ipv4Address);
231             matchBuilder.setNwDstMask(prefix.shortValue());
232         }
233     }
234
235     /**
236      * Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
237      * Wildcard value of the IP mask will be determined by Openflow java encoding library.
238      * @param matchBuilder
239      * @param ipv4
240      */
241     private static void convertL3Ipv4SrcMatch(final MatchV10Builder matchBuilder,
242             final Ipv4Match ipv4) {
243         if(ipv4.getIpv4Source()!=null){
244             Iterator<String> addressParts = MatchConvertorImpl.PREFIX_SPLITTER.split(ipv4.getIpv4Source().getValue()).iterator();
245             Ipv4Address ipv4Address = new Ipv4Address(addressParts.next());
246             int prefix = buildPrefix(addressParts);
247
248             matchBuilder.setNwSrc(ipv4Address);
249             matchBuilder.setNwSrcMask((short) prefix);
250         }
251     }
252
253     /**
254      * @param addressParts
255      * @return
256      */
257     private static int buildPrefix(final Iterator<String> addressParts) {
258         int prefix = 32;
259         if (addressParts.hasNext()) {
260             prefix = Integer.parseInt(addressParts.next());
261         }
262         return prefix;
263     }
264
265     /**
266      * @param matchBuilder
267      * @param vlanMatch
268      * @return
269      */
270     private static boolean convertDlVlanPcp(final MatchV10Builder matchBuilder,
271             final VlanMatch vlanMatch) {
272         if (vlanMatch.getVlanPcp() != null) {
273             matchBuilder.setDlVlanPcp(vlanMatch.getVlanPcp().getValue());
274             return false;
275         }
276         return true;
277     }
278
279     /**
280      * @param matchBuilder
281      * @param vlanMatch
282      * @return
283      */
284     private static boolean convertDlVlan(final MatchV10Builder matchBuilder, final VlanMatch vlanMatch) {
285         if (vlanMatch.getVlanId() != null) {
286             int vlanId = vlanMatch.getVlanId().getVlanId().getValue();
287             matchBuilder.setDlVlan((vlanId == 0 ? OFP_VLAN_NONE : vlanId));
288             return false;
289         }
290         return true;
291     }
292
293     /**
294      * @param matchBuilder
295      * @param ethernetMatch
296      * @return is wildCard
297      */
298     private static boolean convertEthernetDlType(final MatchV10Builder matchBuilder,
299             final EthernetMatch ethernetMatch) {
300         if (ethernetMatch.getEthernetType() != null) {
301             matchBuilder.setDlType(ethernetMatch.getEthernetType().getType().getValue().intValue());
302             return false;
303         }
304         return true;
305     }
306
307     /**
308      * @param matchBuilder
309      * @param ethernetMatch
310      * @return is wildCard
311      */
312     private static boolean convertEthernetDlSrc(final MatchV10Builder matchBuilder,
313             final EthernetMatch ethernetMatch) {
314         if (ethernetMatch.getEthernetSource() != null) {
315             matchBuilder.setDlSrc(ethernetMatch.getEthernetSource().getAddress());
316             return false;
317         }
318         return true;
319     }
320
321     /**
322      * @param matchBuilder
323      * @param ethernetMatch
324      * @return is wildCard
325      */
326     private static boolean convertEthernetDlDst(final MatchV10Builder matchBuilder,
327             final EthernetMatch ethernetMatch) {
328         if (ethernetMatch.getEthernetDestination() != null) {
329             matchBuilder.setDlDst(ethernetMatch.getEthernetDestination().getAddress());
330             return false;
331         }
332         return true;
333     }
334
335     /**
336      * @param matchBuilder
337      * @param inPort
338      */
339     private static boolean convertInPortMatch(final MatchV10Builder matchBuilder, final NodeConnectorId inPort) {
340         if (inPort != null) {
341             matchBuilder.setInPort(InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF10, inPort).intValue());
342             return false;
343         }
344         return true;
345     }
346
347 }