Merge remote-tracking branch 'liblldp/master'
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / core / sal / convertor / match / MatchV10ResponseConvertor.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 import java.math.BigInteger;
12 import java.util.Collection;
13 import java.util.Collections;
14 import java.util.Set;
15 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
16 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.common.Convertor;
17 import org.opendaylight.openflowplugin.openflow.md.core.sal.convertor.data.VersionDatapathIdConvertorData;
18 import org.opendaylight.openflowplugin.openflow.md.util.ActionUtil;
19 import org.opendaylight.openflowplugin.openflow.md.util.InventoryDataServiceUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Icmpv4MatchBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.oxm.rev150225.match.v10.grouping.MatchV10;
36 import org.opendaylight.yangtools.yang.binding.DataContainer;
37
38 /**
39  * Converts Openflow 1.0 specific flow match to MD-SAL format flow
40  * match
41  *
42  * Example usage:
43  * <pre>
44  * {@code
45  * VersionDatapathIdConvertorData data = new VersionDatapathIdConvertorData(version);
46  * data.setDatapathId(datapathId);
47  * Optional<MatchBuilder> salMatch = convertorManager.convert(ofMatchV10, data);
48  * }
49  * </pre>
50  */
51 public class MatchV10ResponseConvertor extends Convertor<MatchV10, MatchBuilder, VersionDatapathIdConvertorData> {
52     private static final short PROTO_TCP = 6;
53     private static final short PROTO_UDP = 17;
54     private static final short PROTO_ICMPV4 = 1;
55     private static final String NO_IP = "0.0.0.0/0";
56     private static final Set<Class<?>> TYPES = Collections.singleton(MatchV10.class);
57
58     @Override
59     public Collection<Class<?>> getTypes() {
60         return TYPES;
61     }
62
63     @Override
64     public MatchBuilder convert(MatchV10 source, VersionDatapathIdConvertorData datapathIdConvertorData) {
65         MatchBuilder matchBuilder = new MatchBuilder();
66         EthernetMatchBuilder ethMatchBuilder = new EthernetMatchBuilder();
67         VlanMatchBuilder vlanMatchBuilder = new VlanMatchBuilder();
68         Ipv4MatchBuilder ipv4MatchBuilder = new Ipv4MatchBuilder();
69         IpMatchBuilder ipMatchBuilder = new IpMatchBuilder();
70         OpenflowVersion ofVersion = OpenflowVersion.get(datapathIdConvertorData.getVersion());
71         BigInteger datapathid = datapathIdConvertorData.getDatapathId();
72
73         if (!source.getWildcards().isINPORT() && source.getInPort() != null) {
74             matchBuilder.setInPort(InventoryDataServiceUtil.nodeConnectorIdfromDatapathPortNo(datapathid,
75                     (long) source.getInPort(), ofVersion));
76         }
77
78         if (!source.getWildcards().isDLSRC() && source.getDlSrc() != null) {
79             EthernetSourceBuilder ethSrcBuilder = new EthernetSourceBuilder();
80             ethSrcBuilder.setAddress(source.getDlSrc());
81             ethMatchBuilder.setEthernetSource(ethSrcBuilder.build());
82             matchBuilder.setEthernetMatch(ethMatchBuilder.build());
83         }
84         if (!source.getWildcards().isDLDST() && source.getDlDst() != null) {
85             EthernetDestinationBuilder ethDstBuilder = new EthernetDestinationBuilder();
86             ethDstBuilder.setAddress(source.getDlDst());
87             ethMatchBuilder.setEthernetDestination(ethDstBuilder.build());
88             matchBuilder.setEthernetMatch(ethMatchBuilder.build());
89         }
90         if (!source.getWildcards().isDLTYPE() && source.getDlType() != null) {
91             EthernetTypeBuilder ethTypeBuilder = new EthernetTypeBuilder();
92             ethTypeBuilder.setType(new org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType(
93                     (long) source.getDlType()));
94             ethMatchBuilder.setEthernetType(ethTypeBuilder.build());
95             matchBuilder.setEthernetMatch(ethMatchBuilder.build());
96         }
97         if (!source.getWildcards().isDLVLAN() && source.getDlVlan() != null) {
98             VlanIdBuilder vlanIdBuilder = new VlanIdBuilder();
99             int vlanId = (source.getDlVlan() == (0xffff)) ? 0 : source.getDlVlan();
100             vlanIdBuilder.setVlanId(new org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId(vlanId));
101             vlanIdBuilder.setVlanIdPresent(vlanId != 0);
102             vlanMatchBuilder.setVlanId(vlanIdBuilder.build());
103             matchBuilder.setVlanMatch(vlanMatchBuilder.build());
104         }
105         if (!source.getWildcards().isDLVLANPCP() && source.getDlVlanPcp() != null) {
106             vlanMatchBuilder.setVlanPcp(new org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp(
107                     source.getDlVlanPcp()));
108             matchBuilder.setVlanMatch(vlanMatchBuilder.build());
109         }
110         if (!source.getWildcards().isDLTYPE() && source.getNwSrc() != null) {
111             final Ipv4Prefix prefix;
112             if (source.getNwSrcMask() != null) {
113                 prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(source.getNwSrc(), source.getNwSrcMask());
114             } else {
115                 //Openflow Spec : 1.3.2
116                 //An all-one-bits oxm_mask is equivalent to specifying 0 for oxm_hasmask and omitting oxm_mask.
117                 // So when user specify 32 as a mast, switch omit that mast and we get null as a mask in flow
118                 // statistics response.
119                 prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(source.getNwSrc());
120             }
121             if (!NO_IP.equals(prefix.getValue())) {
122                 ipv4MatchBuilder.setIpv4Source(prefix);
123                 matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
124             }
125         }
126         if (!source.getWildcards().isDLTYPE() && source.getNwDst() != null) {
127             final Ipv4Prefix prefix;
128             if (source.getNwDstMask() != null) {
129                 prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(source.getNwDst(), source.getNwDstMask());
130             } else {
131                 //Openflow Spec : 1.3.2
132                 //An all-one-bits oxm_mask is equivalent to specifying 0 for oxm_hasmask and omitting oxm_mask.
133                 // So when user specify 32 as a mast, switch omit that mast and we get null as a mask in flow
134                 // statistics response.
135                 prefix = IetfInetUtil.INSTANCE.ipv4PrefixFor(source.getNwDst());
136             }
137             if (!NO_IP.equals(prefix.getValue())) {
138                 ipv4MatchBuilder.setIpv4Destination(prefix);
139                 matchBuilder.setLayer3Match(ipv4MatchBuilder.build());
140             }
141         }
142         if (!source.getWildcards().isNWPROTO() && source.getNwProto() != null) {
143             Short nwProto = source.getNwProto();
144             ipMatchBuilder.setIpProtocol(nwProto);
145             matchBuilder.setIpMatch(ipMatchBuilder.build());
146
147             int proto = nwProto.intValue();
148             if (proto == PROTO_TCP) {
149                 TcpMatchBuilder tcpMatchBuilder = new TcpMatchBuilder();
150                 boolean hasTcp = false;
151                 if (!source.getWildcards().isTPSRC() && source.getTpSrc() != null) {
152                     tcpMatchBuilder
153                             .setTcpSourcePort(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber(
154                                     source.getTpSrc()));
155                     hasTcp = true;
156                 }
157                 if (!source.getWildcards().isTPDST() && source.getTpDst() != null) {
158                     tcpMatchBuilder
159                             .setTcpDestinationPort(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber(
160                                     source.getTpDst()));
161                     hasTcp = true;
162                 }
163
164                 if (hasTcp) {
165                     matchBuilder.setLayer4Match(tcpMatchBuilder.build());
166                 }
167             } else if (proto == PROTO_UDP) {
168                 UdpMatchBuilder udpMatchBuilder = new UdpMatchBuilder();
169                 boolean hasUdp = false;
170                 if (!source.getWildcards().isTPSRC() && source.getTpSrc() != null) {
171                     udpMatchBuilder
172                             .setUdpSourcePort(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber(
173                                     source.getTpSrc()));
174                     hasUdp = true;
175                 }
176                 if (!source.getWildcards().isTPDST() && source.getTpDst() != null) {
177                     udpMatchBuilder
178                             .setUdpDestinationPort(new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber(
179                                     source.getTpDst()));
180                     hasUdp = true;
181                 }
182
183                 if (hasUdp) {
184                     matchBuilder.setLayer4Match(udpMatchBuilder.build());
185                 }
186             } else if (proto == PROTO_ICMPV4) {
187                 Icmpv4MatchBuilder icmpv4MatchBuilder = new Icmpv4MatchBuilder();
188                 boolean hasIcmpv4 = false;
189                 if (!source.getWildcards().isTPSRC()) {
190                     Integer type = source.getTpSrc();
191                     if (type != null) {
192                         icmpv4MatchBuilder.setIcmpv4Type(type.shortValue());
193                         hasIcmpv4 = true;
194                     }
195                 }
196                 if (!source.getWildcards().isTPDST()) {
197                     Integer code = source.getTpDst();
198                     if (code != null) {
199                         icmpv4MatchBuilder.setIcmpv4Code(code.shortValue());
200                         hasIcmpv4 = true;
201                     }
202                 }
203
204                 if (hasIcmpv4) {
205                     matchBuilder.setIcmpv4Match(icmpv4MatchBuilder.build());
206                 }
207             }
208         }
209         if (!source.getWildcards().isNWTOS() && source.getNwTos() != null) {
210             Short dscp = ActionUtil.tosToDscp(source.getNwTos());
211             ipMatchBuilder.setIpDscp(new Dscp(dscp));
212             matchBuilder.setIpMatch(ipMatchBuilder.build());
213         }
214
215         return matchBuilder;
216     }
217 }