Bump upstreams
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchV10Convertor.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 package org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.match;
9
10 import java.util.Collection;
11 import java.util.Iterator;
12 import java.util.List;
13 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
14 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
15 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.IpConversionUtil;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionConvertorData;
17 import org.opendaylight.openflowplugin.openflow.md.util.ActionUtil;
18 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
19 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.set.field._case.SetField;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.Match;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4Match;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.FlowWildcardsV10;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10Builder;
37 import org.opendaylight.yangtools.yang.common.Uint16;
38 import org.opendaylight.yangtools.yang.common.Uint8;
39
40 /**
41  * The type Match converter v 10.
42  */
43 public class MatchV10Convertor extends Convertor<Match, MatchV10, VersionConvertorData> {
44
45     private static final List<Class<?>> TYPES = List.of(
46             Match.class,
47             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match.class,
48             org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.mod.removed.Match.class,
49             org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.received.Match.class,
50             org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.packet.in.message.Match.class,
51             org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.feature.prop.type.table.feature
52                 .prop.type.Match.class,
53             SetField.class);
54
55     /**
56      * default MAC.
57      */
58     private static final MacAddress ZERO_MAC = new MacAddress("00:00:00:00:00:00");
59
60     /**
61      * default IPv4.
62      */
63     private static final Ipv4Address ZERO_IPV4 = new Ipv4Address("0.0.0.0");
64
65     private static final Uint8 DEFAULT_PREFIX = Uint8.valueOf(32);
66
67     /*
68      * The value 0xffff (OFP_VLAN_NONE) is used to indicate
69      * that no VLAN ID is set for OF Flow.
70      */
71     private static final Uint16 OFP_VLAN_NONE = Uint16.MAX_VALUE;
72
73     private static boolean convertL4UdpDstMatch(final MatchV10Builder matchBuilder, final UdpMatch udpMatch) {
74         final var port = udpMatch.getUdpDestinationPort();
75         if (port != null) {
76             matchBuilder.setTpDst(port.getValue());
77             return false;
78         }
79         return true;
80     }
81
82     private static boolean convertL4UdpSrcMatch(final MatchV10Builder matchBuilder, final UdpMatch udpMatch) {
83         final var port = udpMatch.getUdpSourcePort();
84         if (port != null) {
85             matchBuilder.setTpSrc(port.getValue());
86             return false;
87         }
88         return true;
89     }
90
91     private static boolean convertL4TpDstMatch(final MatchV10Builder matchBuilder, final TcpMatch tcpMatch) {
92         final var port = tcpMatch.getTcpDestinationPort();
93         if (port != null) {
94             matchBuilder.setTpDst(tcpMatch.getTcpDestinationPort().getValue());
95             return false;
96         }
97         return true;
98     }
99
100     private static boolean convertL4TpSrcMatch(final MatchV10Builder matchBuilder, final TcpMatch tcpMatch) {
101         final var port = tcpMatch.getTcpSourcePort();
102         if (port != null) {
103             matchBuilder.setTpSrc(port.getValue());
104             return false;
105         }
106         return true;
107     }
108
109     private static boolean convertNwTos(final MatchV10Builder matchBuilder, final IpMatch ipMatch) {
110         final var ipDscp = ipMatch.getIpDscp();
111         if (ipDscp != null) {
112             matchBuilder.setNwTos(ActionUtil.dscpToTos(ipDscp.getValue().toJava()));
113             return false;
114         }
115         return true;
116     }
117
118     private static boolean convertNwProto(final MatchV10Builder matchBuilder, final IpMatch ipMatch) {
119         if (ipMatch.getIpProtocol() != null) {
120             matchBuilder.setNwProto(ipMatch.getIpProtocol());
121             return false;
122         }
123         return true;
124     }
125
126     /**
127      * Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
128      * Wildcard value of the IP mask will be determined by Openflow java encoding library.
129      *
130      * @param matchBuilder match builder
131      * @param ipv4         ip v4 match
132      */
133     private static void convertL3Ipv4DstMatch(final MatchV10Builder matchBuilder, final Ipv4Match ipv4) {
134         final Ipv4Prefix destination = ipv4.getIpv4Destination();
135         if (destination != null) {
136             // TODO: consider using IetfInetUtil
137             Iterator<String> addressParts = IpConversionUtil.PREFIX_SPLITTER.split(destination.getValue()).iterator();
138             matchBuilder.setNwDst(new Ipv4Address(addressParts.next()));
139             matchBuilder.setNwDstMask(buildPrefix(addressParts));
140         }
141     }
142
143     /**
144      * Method splits the IP address and its mask and set their respective values in MatchV10Builder instance.
145      * Wildcard value of the IP mask will be determined by Openflow java encoding library.
146      *
147      * @param matchBuilder match builder
148      * @param ipv4         ip v4 match
149      */
150     private static void convertL3Ipv4SrcMatch(final MatchV10Builder matchBuilder, final Ipv4Match ipv4) {
151         final Ipv4Prefix source = ipv4.getIpv4Source();
152         if (source != null) {
153             // TODO: consider IetfInetUtil
154             Iterator<String> addressParts = IpConversionUtil.PREFIX_SPLITTER.split(source.getValue()).iterator();
155             matchBuilder.setNwSrc(new Ipv4Address(addressParts.next()));
156             matchBuilder.setNwSrcMask(buildPrefix(addressParts));
157         }
158     }
159
160     private static Uint8 buildPrefix(final Iterator<String> addressParts) {
161         return addressParts.hasNext() ? Uint8.valueOf(addressParts.next()) : DEFAULT_PREFIX;
162     }
163
164     private static boolean convertDlVlanPcp(final MatchV10Builder matchBuilder, final VlanMatch vlanMatch) {
165         final var vlanPcp = vlanMatch.getVlanPcp();
166         if (vlanPcp != null) {
167             matchBuilder.setDlVlanPcp(vlanPcp.getValue());
168             return false;
169         }
170         return true;
171     }
172
173     private static boolean convertDlVlan(final MatchV10Builder matchBuilder, final VlanMatch vlanMatch) {
174         final var id = vlanMatch.getVlanId();
175         if (id != null) {
176             final Uint16 vlanId = id.getVlanId().getValue();
177             matchBuilder.setDlVlan(Uint16.ZERO.equals(vlanId) ? OFP_VLAN_NONE : vlanId);
178             return false;
179         }
180         return true;
181     }
182
183     private static boolean convertEthernetDlType(final MatchV10Builder matchBuilder,
184             final EthernetMatch ethernetMatch) {
185         final var ethType = ethernetMatch.getEthernetType();
186         if (ethType != null) {
187             matchBuilder.setDlType(Uint16.valueOf(ethType.getType().getValue().intValue()));
188             return false;
189         }
190         return true;
191     }
192
193     private static boolean convertEthernetDlSrc(final MatchV10Builder matchBuilder,
194                                                 final EthernetMatch ethernetMatch) {
195         final var ethSource = ethernetMatch.getEthernetSource();
196         if (ethSource != null) {
197             matchBuilder.setDlSrc(ethSource.getAddress());
198             return false;
199         }
200         return true;
201     }
202
203     private static boolean convertEthernetDlDst(final MatchV10Builder matchBuilder,
204                                                 final EthernetMatch ethernetMatch) {
205         if (ethernetMatch.getEthernetDestination() != null) {
206             matchBuilder.setDlDst(ethernetMatch.getEthernetDestination().getAddress());
207             return false;
208         }
209         return true;
210     }
211
212     private static boolean convertInPortMatch(final MatchV10Builder matchBuilder, final NodeConnectorId inPort) {
213         if (inPort != null) {
214             matchBuilder.setInPort(Uint16.valueOf(
215                 InventoryDataServiceUtil.portNumberfromNodeConnectorId(OpenflowVersion.OF10, inPort).intValue()));
216             return false;
217         }
218         return true;
219     }
220
221     /**
222      * Create default empty match v10
223      * Use this method, if result from converter is empty.
224      */
225     public static MatchV10 defaultResult() {
226         return new MatchV10Builder().build();
227     }
228
229     @Override
230     public Collection<Class<?>> getTypes() {
231         return TYPES;
232     }
233
234     @Override
235     public MatchV10 convert(final Match source, final VersionConvertorData data) {
236         MatchV10Builder matchBuilder = new MatchV10Builder()
237                 .setInPort(Uint16.ZERO)
238                 .setDlDst(ZERO_MAC)
239                 .setDlSrc(ZERO_MAC)
240                 .setDlType(Uint16.ZERO)
241                 .setDlVlan(OFP_VLAN_NONE)
242                 .setDlVlanPcp(Uint8.ZERO)
243                 .setNwDst(ZERO_IPV4)
244                 .setNwDstMask(Uint8.ZERO)
245                 .setNwSrc(ZERO_IPV4)
246                 .setNwSrcMask(Uint8.ZERO)
247                 .setNwProto(Uint8.ZERO)
248                 .setNwTos(Uint8.ZERO)
249                 .setTpSrc(Uint16.ZERO)
250                 .setTpDst(Uint16.ZERO);
251
252         boolean dlDst = true;
253         boolean dlSsc = true;
254         boolean dlType = true;
255         boolean dlVlan = true;
256         boolean dlVlanPcp = true;
257         boolean ipPort = true;
258         boolean nwProto = true;
259         boolean nwTos = true;
260         boolean tpDst = true;
261         boolean tpSrc = true;
262
263         if (source != null) {
264             EthernetMatch ethernetMatch = source.getEthernetMatch();
265             if (ethernetMatch != null) {
266                 dlDst = convertEthernetDlDst(matchBuilder, ethernetMatch);
267                 dlSsc = convertEthernetDlSrc(matchBuilder, ethernetMatch);
268                 dlType = convertEthernetDlType(matchBuilder, ethernetMatch);
269             }
270             VlanMatch vlanMatch = source.getVlanMatch();
271             if (vlanMatch != null) {
272                 dlVlan = convertDlVlan(matchBuilder, vlanMatch);
273                 dlVlanPcp = convertDlVlanPcp(matchBuilder, vlanMatch);
274             }
275             NodeConnectorId inPort = source.getInPort();
276             if (inPort != null) {
277                 ipPort = convertInPortMatch(matchBuilder, inPort);
278             }
279             Layer3Match l3Match = source.getLayer3Match();
280             if (l3Match != null) {
281                 if (l3Match instanceof Ipv4Match) {
282                     Ipv4Match ipv4 = (Ipv4Match) l3Match;
283                     convertL3Ipv4SrcMatch(matchBuilder, ipv4);
284                     convertL3Ipv4DstMatch(matchBuilder, ipv4);
285                 }
286             }
287             IpMatch ipMatch = source.getIpMatch();
288             if (ipMatch != null) {
289                 nwProto = convertNwProto(matchBuilder, ipMatch);
290                 nwTos = convertNwTos(matchBuilder, ipMatch);
291             }
292             Layer4Match layer4Match = source.getLayer4Match();
293             if (layer4Match != null) {
294                 if (layer4Match instanceof TcpMatch) {
295                     TcpMatch tcpMatch = (TcpMatch) layer4Match;
296                     tpSrc = convertL4TpSrcMatch(matchBuilder, tcpMatch);
297                     tpDst = convertL4TpDstMatch(matchBuilder, tcpMatch);
298                 } else if (layer4Match instanceof UdpMatch) {
299                     UdpMatch udpMatch = (UdpMatch) layer4Match;
300                     tpSrc = convertL4UdpSrcMatch(matchBuilder, udpMatch);
301                     tpDst = convertL4UdpDstMatch(matchBuilder, udpMatch);
302                 }
303             } else {
304                 Icmpv4Match icmpv4Match = source.getIcmpv4Match();
305                 if (icmpv4Match != null) {
306                     Uint8 type = icmpv4Match.getIcmpv4Type();
307                     if (type != null) {
308                         matchBuilder.setTpSrc(Uint16.valueOf(type));
309                         tpSrc = false;
310                     }
311                     Uint8 code = icmpv4Match.getIcmpv4Code();
312                     if (code != null) {
313                         matchBuilder.setTpDst(Uint16.valueOf(code));
314                         tpDst = false;
315                     }
316                 }
317             }
318         }
319
320         return matchBuilder
321             .setWildcards(new FlowWildcardsV10(
322                 dlDst, dlSsc, dlType, dlVlan, dlVlanPcp, ipPort, nwProto, nwTos, tpDst, tpSrc))
323             .build();
324     }
325 }