BUG-1953: fix SAL compatility layer
[controller.git] / opendaylight / md-sal / compatibility / sal-compatibility / src / main / java / org / opendaylight / controller / sal / compatibility / FromSalConversionsUtils.java
1 /*
2  * Copyright (c) 2014 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.controller.sal.compatibility;
9
10 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.CRUDP;
11 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.ETHERNET_ARP;
12 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.TCP;
13 import static org.opendaylight.controller.sal.compatibility.ProtocolConstants.UDP;
14 import static org.opendaylight.controller.sal.match.MatchType.DL_DST;
15 import static org.opendaylight.controller.sal.match.MatchType.DL_SRC;
16 import static org.opendaylight.controller.sal.match.MatchType.DL_TYPE;
17
18 import java.net.Inet4Address;
19 import java.net.Inet6Address;
20 import java.net.InetAddress;
21
22 import org.opendaylight.controller.sal.core.NodeConnector;
23 import org.opendaylight.controller.sal.match.Match;
24 import org.opendaylight.controller.sal.match.MatchField;
25 import org.opendaylight.controller.sal.match.MatchType;
26 import org.opendaylight.controller.sal.utils.NetUtils;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Dscp;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
30 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.Address;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv4Builder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.address.address.Ipv6Builder;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.EtherType;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanPcp;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddressBuilder;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetDestinationBuilder;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetSourceBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.ethernet.match.fields.EthernetTypeBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatchBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatch;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.IpMatchBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatch;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.VlanMatchBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatchBuilder;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.SctpMatchBuilder;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatchBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatchBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.vlan.match.fields.VlanIdBuilder;
61
62 import com.google.common.net.InetAddresses;
63
64 /**
65  * MD-SAL to AD-SAL conversions collection
66  */
67 public final class FromSalConversionsUtils {
68
69     /** http://en.wikipedia.org/wiki/IPv4#Packet_structure (end of octet number 1, bit 14.+15.) */
70     public static final int ENC_FIELD_BIT_SIZE = 2;
71
72     private FromSalConversionsUtils() {
73         throw new IllegalAccessError("forcing no instance for factory");
74     }
75
76     @SuppressWarnings("unused")
77     private static Address addressFromAction(InetAddress inetAddress) {
78         String strInetAddresss = InetAddresses.toAddrString(inetAddress);
79         if (inetAddress instanceof Inet4Address) {
80             Ipv4Builder ipv4Builder = new Ipv4Builder();
81             ipv4Builder.setIpv4Address(new Ipv4Prefix(strInetAddresss));
82             return ipv4Builder.build();
83         } else if (inetAddress instanceof Inet6Address) {
84             Ipv6Builder ipv6Builder = new Ipv6Builder();
85             ipv6Builder.setIpv6Address(new Ipv6Prefix(strInetAddresss));
86             return ipv6Builder.build();
87         }
88         return null;
89     }
90
91     public static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match toMatch(
92             Match sourceMatch) {
93         if (sourceMatch != null) {
94             MatchBuilder targetBuilder = new MatchBuilder();
95
96             targetBuilder.setEthernetMatch(ethernetMatch(sourceMatch));
97             targetBuilder.setIpMatch(ipMatch(sourceMatch));
98             targetBuilder.setVlanMatch(vlanMatch(sourceMatch));
99             targetBuilder.setLayer3Match(layer3Match(sourceMatch));
100             targetBuilder.setLayer4Match(layer4Match(sourceMatch));
101             targetBuilder.setInPort(inPortMatch(sourceMatch));
102
103             return targetBuilder.build();
104         }
105         return null;
106
107     }
108
109     private static NodeConnectorId inPortMatch(Match sourceMatch) {
110         MatchField inPort = sourceMatch.getField(MatchType.IN_PORT);
111         if(inPort != null && inPort.getValue() != null && (inPort.getValue() instanceof NodeConnector)) {
112             NodeConnector port = (NodeConnector)inPort.getValue();
113             return (NodeConnectorId)MDFlowMapping.toUri(port);
114         }
115         return null;
116     }
117
118     private static Layer4Match layer4Match(final Match sourceMatch) {
119         MatchField nwProto = sourceMatch.getField(MatchType.NW_PROTO);
120         Short nwProtocolSource = null;
121         if (nwProto != null && nwProto.getValue() != null) {
122             nwProtocolSource = (short) ((byte) nwProto.getValue());
123             switch (nwProtocolSource) {
124             case TCP:
125                 return Layer4MatchAsTcp(sourceMatch);
126             case UDP:
127                 return Layer4MatchAsUdp(sourceMatch);
128             case CRUDP:
129                 return Layer4MatchAsSctp(sourceMatch);
130             }
131         }
132         return null;
133     }
134
135     private static Layer4Match Layer4MatchAsSctp(final Match sourceMatch) {
136         SctpMatchBuilder sctpMatchBuilder = new SctpMatchBuilder();
137
138         Integer sourcePort = transportPort(sourceMatch, MatchType.TP_SRC);
139         Integer destinationPort = transportPort(sourceMatch,
140                 MatchType.TP_DST);
141
142         if (sourcePort != null) {
143             sctpMatchBuilder.setSctpSourcePort(new PortNumber(sourcePort));
144         }
145         if (destinationPort != null) {
146             sctpMatchBuilder.setSctpDestinationPort(new PortNumber(
147                     destinationPort));
148         }
149         if(sourcePort != null || destinationPort != null) {
150             return sctpMatchBuilder.build();
151         }
152         return null;
153     }
154
155     private static Layer4Match Layer4MatchAsUdp(final Match sourceMatch) {
156         UdpMatchBuilder udpMatchBuilder = new UdpMatchBuilder();
157
158         Integer sourcePort = transportPort(sourceMatch, MatchType.TP_SRC);
159         Integer destinationPort = transportPort(sourceMatch,
160                 MatchType.TP_DST);
161
162         if (sourcePort != null) {
163             udpMatchBuilder.setUdpSourcePort(new PortNumber(sourcePort));
164         }
165
166         if (destinationPort != null) {
167             udpMatchBuilder.setUdpDestinationPort(new PortNumber(
168                     destinationPort));
169         }
170         if(sourcePort != null || destinationPort != null) {
171             return udpMatchBuilder.build();
172         }
173         return null;
174     }
175
176     private static Layer4Match Layer4MatchAsTcp(final Match sourceMatch) {
177         TcpMatchBuilder tcpMatchBuilder = new TcpMatchBuilder();
178
179         Integer sourcePort = transportPort(sourceMatch, MatchType.TP_SRC);
180         Integer destinationPort = transportPort(sourceMatch,
181                 MatchType.TP_DST);
182
183         if (sourcePort != null) {
184             tcpMatchBuilder.setTcpSourcePort(new PortNumber(sourcePort));
185         }
186         if (destinationPort != null) {
187             tcpMatchBuilder.setTcpDestinationPort(new PortNumber(
188                     destinationPort));
189         }
190         if(sourcePort != null || destinationPort != null) {
191             return tcpMatchBuilder.build();
192         }
193         return null;
194     }
195
196     private static Integer transportPort(final Match sourceMatch,
197             final MatchType matchType) {
198         MatchField transportPort = sourceMatch.getField(matchType);
199         if (transportPort != null && transportPort.getValue() != null
200                 && transportPort.getValue().getClass().equals(Short.class)) {
201             return new Integer(NetUtils.getUnsignedShort((short) transportPort
202                     .getValue()));
203         }
204         return null;
205     }
206
207     private static VlanMatch vlanMatch(final Match sourceMatch) {
208         VlanMatchBuilder vlanMatchBuild = new VlanMatchBuilder();
209
210         MatchField vlan = sourceMatch.getField(MatchType.DL_VLAN);
211         if (vlan != null && vlan.getValue() != null) {
212             VlanIdBuilder vlanIDBuilder = new VlanIdBuilder();
213             short vid = (short)vlan.getValue();
214             boolean present = (vid != MatchType.DL_VLAN_NONE);
215             vlanIDBuilder.setVlanId(new VlanId((NetUtils
216                     .getUnsignedShort(vid))));
217             vlanIDBuilder.setVlanIdPresent(present);
218             vlanMatchBuild.setVlanId(vlanIDBuilder.build());
219         }
220
221         MatchField vlanPriority = sourceMatch.getField(MatchType.DL_VLAN_PR);
222         if (vlanPriority != null && vlanPriority.getValue() != null) {
223             vlanMatchBuild.setVlanPcp(new VlanPcp((short) ((byte) vlanPriority
224                     .getValue())));
225         }
226         if((vlan != null && vlan.getValue() != null) || (vlanPriority != null && vlanPriority.getValue() != null)) {
227             return vlanMatchBuild.build();
228         }
229         return null;
230     }
231
232     private static IpMatch ipMatch(final Match sourceMatch) {
233         IpMatchBuilder targetIpMatchBuild = new IpMatchBuilder();
234         MatchField networkTos = sourceMatch.getField(MatchType.NW_TOS);
235         if (networkTos != null && networkTos.getValue() != null) {
236             Dscp dscp = new Dscp(
237                     (short) (NetUtils.getUnsignedByte((Byte) networkTos
238                             .getValue())));
239             targetIpMatchBuild.setIpDscp(dscp);
240         }
241
242         MatchField protocol = sourceMatch.getField(MatchType.NW_PROTO);
243         if (protocol != null && protocol.getValue() != null) {
244             targetIpMatchBuild.setIpProtocol((short) ((byte) protocol
245                     .getValue()));
246         }
247         if((networkTos != null && networkTos.getValue() != null) || (protocol != null && protocol.getValue() != null)) {
248             return targetIpMatchBuild.build();
249         }
250         return null;
251     }
252
253     private static EthernetMatch ethernetMatch(final Match sourceMatch) {
254         final EthernetMatchBuilder targetEthMatchBuild = new EthernetMatchBuilder();
255         if(sourceMatch.getField(DL_SRC) != null && sourceMatch.getField(DL_SRC).getValue() != null) {
256             EthernetSourceBuilder ethSourBuild = new EthernetSourceBuilder()
257                     .setAddress(ethernetSourceAddress(sourceMatch));
258             targetEthMatchBuild.setEthernetSource(ethSourBuild.build());
259         }
260         if(sourceMatch.getField(DL_DST) != null && sourceMatch.getField(DL_DST).getValue() != null) {
261             EthernetDestinationBuilder ethDestBuild = new EthernetDestinationBuilder()
262                     .setAddress(ethernetDestAddress(sourceMatch));
263             targetEthMatchBuild.setEthernetDestination(ethDestBuild.build());
264         }
265
266         final MatchField dataLinkType = sourceMatch.getField(MatchType.DL_TYPE);
267         if (dataLinkType != null && dataLinkType.getValue() != null) {
268             EtherType etherType = new EtherType(new Long(
269                     NetUtils.getUnsignedShort((Short) dataLinkType.getValue())));
270             EthernetTypeBuilder ethType = new EthernetTypeBuilder()
271                     .setType(etherType);
272             targetEthMatchBuild.setEthernetType(ethType.build());
273         }
274         if((sourceMatch.getField(DL_SRC) != null && sourceMatch.getField(DL_SRC).getValue() != null) ||
275                 (sourceMatch.getField(DL_DST) != null && sourceMatch.getField(DL_DST).getValue() != null)||
276                 dataLinkType != null ) {
277             return targetEthMatchBuild.build();
278         }
279         return null;
280     }
281
282     private static MacAddress ethernetSourceAddress(final Match sourceMatch) {
283         final MatchField dataLinkSource = sourceMatch.getField(DL_SRC);
284         if (dataLinkSource != null && dataLinkSource.getValue() != null) {
285             return MDFlowMapping.toMacAddress((byte[])dataLinkSource.getValue());
286         }
287         return null;
288
289     }
290
291     private static Layer3Match layer3Match(final Match sourceMatch) {
292         InetAddress inetSourceAddress = null;
293         MatchField netSource = sourceMatch.getField(MatchType.NW_SRC);
294         if (netSource != null && netSource.getValue() != null) {
295             inetSourceAddress = (InetAddress) (netSource.getValue());
296         }
297
298         InetAddress inetDestAddress = null;
299         MatchField netDest = sourceMatch.getField(MatchType.NW_DST);
300         if (netDest != null && netDest.getValue() != null) {
301             inetDestAddress = (InetAddress) (netDest.getValue());
302         }
303
304         if ((inetSourceAddress instanceof Inet4Address)
305                 || (inetDestAddress instanceof Inet4Address)) {
306             MatchField dataLinkType = sourceMatch.getField(DL_TYPE);
307             Short dLType = null;
308             if (dataLinkType != null && dataLinkType.getValue() != null) {
309                 dLType = (Short) (dataLinkType.getValue());
310             }
311             if (dLType != null && dLType.equals(ETHERNET_ARP)) {
312                 return setLayer3MatchAsArp(sourceMatch,
313                         (Inet4Address) inetSourceAddress,
314                         (Inet4Address) inetDestAddress);
315             } else {
316                 return setLayer3MatchAsIpv4((Inet4Address) inetSourceAddress,
317                         (Inet4Address) inetDestAddress);
318             }
319         } else if ((inetSourceAddress instanceof Inet6Address)
320                 || (inetDestAddress instanceof Inet6Address)) {
321             return setLayer3MatchAsIpv6((Inet6Address) inetSourceAddress,
322                     (Inet6Address) inetDestAddress);
323         }
324
325         return null;
326
327     }
328
329     private static Layer3Match setLayer3MatchAsArp(final Match sourceMatch,
330             final Inet4Address inetSourceAddress,
331             final Inet4Address inetDestAddress) {
332         String inetSourceAddressStr = InetAddresses
333                 .toAddrString(inetSourceAddress);
334         Ipv4Prefix ipv4SourcePrefix = new Ipv4Prefix(inetSourceAddressStr + "/32");
335
336         String inetDestAddressValue = InetAddresses
337                 .toAddrString(inetDestAddress);
338         Ipv4Prefix ipv4DestPrefix = new Ipv4Prefix(inetDestAddressValue + "/32");
339
340         ArpMatchBuilder arpMatchBuilder = new ArpMatchBuilder();
341
342         arpMatchBuilder.setArpSourceTransportAddress(ipv4SourcePrefix);
343         arpMatchBuilder.setArpTargetTransportAddress(ipv4DestPrefix);
344
345         ArpSourceHardwareAddressBuilder arpSourceHardwareAddressBuilder = new ArpSourceHardwareAddressBuilder();
346         arpSourceHardwareAddressBuilder
347                 .setAddress(ethernetSourceAddress(sourceMatch));
348         arpMatchBuilder
349                 .setArpSourceHardwareAddress(arpSourceHardwareAddressBuilder
350                         .build());
351
352         ArpTargetHardwareAddressBuilder arpTargetHardwareAddressBuilder = new ArpTargetHardwareAddressBuilder();
353         arpTargetHardwareAddressBuilder
354                 .setAddress(ethernetDestAddress(sourceMatch));
355         arpMatchBuilder
356                 .setArpTargetHardwareAddress(arpTargetHardwareAddressBuilder
357                         .build());
358
359         return arpMatchBuilder.build();
360
361     }
362
363     private static MacAddress ethernetDestAddress(final Match sourceMatch) {
364         final MatchField dataLinkDest = sourceMatch.getField(DL_DST);
365         if (dataLinkDest != null && dataLinkDest.getValue() != null) {
366             return MDFlowMapping.toMacAddress((byte[]) dataLinkDest.getValue());
367         }
368         return null;
369     }
370
371     private static Layer3Match setLayer3MatchAsIpv4(
372             final Inet4Address inetSourceAddress,
373             final Inet4Address inetDestAddress) {
374         Ipv4MatchBuilder layer4MatchBuild = new Ipv4MatchBuilder();
375         if(inetSourceAddress != null) {
376             String inetSrcAddressString = InetAddresses
377                     .toAddrString(inetSourceAddress);
378             layer4MatchBuild.setIpv4Source(new Ipv4Prefix(inetSrcAddressString + "/32"));
379         }
380         if(inetDestAddress != null) {
381             String inetDstAddressString = InetAddresses
382                     .toAddrString(inetDestAddress);
383             layer4MatchBuild
384             .setIpv4Destination(new Ipv4Prefix(inetDstAddressString + "/32"));
385         }
386         return layer4MatchBuild.build();
387
388     }
389
390     private static Layer3Match setLayer3MatchAsIpv6(
391             final Inet6Address inetSourceAddress,
392             final Inet6Address inetDestAddress) {
393         Ipv6MatchBuilder layer6MatchBuild = new Ipv6MatchBuilder();
394         if(inetSourceAddress != null) {
395             String inetSrcAddressString = InetAddresses
396                     .toAddrString(inetSourceAddress);
397             layer6MatchBuild.setIpv6Source(new Ipv6Prefix(inetSrcAddressString + "/128"));
398         }
399         if(inetDestAddress != null) {
400             String inetDstAddressString = InetAddresses
401                     .toAddrString(inetDestAddress);
402             layer6MatchBuild
403                     .setIpv6Destination(new Ipv6Prefix(inetDstAddressString + "/128"));
404         }
405         return layer6MatchBuild.build();
406     }
407
408     public static boolean flowEquals(Flow statsFlow, Flow storedFlow) {
409         if (statsFlow.getClass() != storedFlow.getClass()) {
410             return false;
411         }
412         if (statsFlow.getBufferId()== null) {
413             if (storedFlow.getBufferId() != null) {
414                 return false;
415             }
416         } else if(!statsFlow.getBufferId().equals(storedFlow.getBufferId())) {
417             return false;
418         }
419         if (statsFlow.getContainerName()== null) {
420             if (storedFlow.getContainerName()!= null) {
421                 return false;
422             }
423         } else if(!statsFlow.getContainerName().equals(storedFlow.getContainerName())) {
424             return false;
425         }
426         if (statsFlow.getCookie()== null) {
427             if (storedFlow.getCookie()!= null) {
428                 return false;
429             }
430         } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
431             return false;
432         }
433         if (statsFlow.getMatch()== null) {
434             if (storedFlow.getMatch() != null) {
435                 return false;
436             }
437         } else if(!statsFlow.getMatch().equals(storedFlow.getMatch())) {
438             return false;
439         }
440         if (statsFlow.getCookie()== null) {
441             if (storedFlow.getCookie()!= null) {
442                 return false;
443             }
444         } else if(!statsFlow.getCookie().equals(storedFlow.getCookie())) {
445             return false;
446         }
447         if (statsFlow.getHardTimeout() == null) {
448             if (storedFlow.getHardTimeout() != null) {
449                 return false;
450             }
451         } else if(!statsFlow.getHardTimeout().equals(storedFlow.getHardTimeout() )) {
452             return false;
453         }
454         if (statsFlow.getIdleTimeout()== null) {
455             if (storedFlow.getIdleTimeout() != null) {
456                 return false;
457             }
458         } else if(!statsFlow.getIdleTimeout().equals(storedFlow.getIdleTimeout())) {
459             return false;
460         }
461         if (statsFlow.getPriority() == null) {
462             if (storedFlow.getPriority() != null) {
463                 return false;
464             }
465         } else if(!statsFlow.getPriority().equals(storedFlow.getPriority())) {
466             return false;
467         }
468         if (statsFlow.getTableId() == null) {
469             if (storedFlow.getTableId() != null) {
470                 return false;
471             }
472         } else if(!statsFlow.getTableId().equals(storedFlow.getTableId())) {
473             return false;
474         }
475         return true;
476     }
477
478     /**
479      * @param nwDscp NW-DSCP
480      * @return shifted to NW-TOS (with empty ECN part)
481      */
482     public static int dscpToTos(int nwDscp) {
483         return (short) (nwDscp << ENC_FIELD_BIT_SIZE);
484     }
485
486 }