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