Merge "Revert "Checkstyle enforcer""
[controller.git] / opendaylight / protocol_plugins / openflow / src / main / java / org / opendaylight / controller / protocol_plugin / openflow / internal / FlowConverter.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.controller.protocol_plugin.openflow.internal;
10
11 import java.math.BigInteger;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.List;
16
17 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
18 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
19 import org.opendaylight.controller.sal.action.Action;
20 import org.opendaylight.controller.sal.action.ActionType;
21 import org.opendaylight.controller.sal.action.Controller;
22 import org.opendaylight.controller.sal.action.Drop;
23 import org.opendaylight.controller.sal.action.Flood;
24 import org.opendaylight.controller.sal.action.FloodAll;
25 import org.opendaylight.controller.sal.action.HwPath;
26 import org.opendaylight.controller.sal.action.Loopback;
27 import org.opendaylight.controller.sal.action.Output;
28 import org.opendaylight.controller.sal.action.PopVlan;
29 import org.opendaylight.controller.sal.action.SetDlDst;
30 import org.opendaylight.controller.sal.action.SetDlSrc;
31 import org.opendaylight.controller.sal.action.SetNwDst;
32 import org.opendaylight.controller.sal.action.SetNwSrc;
33 import org.opendaylight.controller.sal.action.SetNwTos;
34 import org.opendaylight.controller.sal.action.SetTpDst;
35 import org.opendaylight.controller.sal.action.SetTpSrc;
36 import org.opendaylight.controller.sal.action.SetVlanId;
37 import org.opendaylight.controller.sal.action.SetVlanPcp;
38 import org.opendaylight.controller.sal.action.SwPath;
39 import org.opendaylight.controller.sal.core.Node;
40 import org.opendaylight.controller.sal.core.NodeConnector;
41 import org.opendaylight.controller.sal.flowprogrammer.Flow;
42 import org.opendaylight.controller.sal.match.Match;
43 import org.opendaylight.controller.sal.match.MatchField;
44 import org.opendaylight.controller.sal.match.MatchType;
45 import org.opendaylight.controller.sal.utils.NetUtils;
46 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
47 import org.openflow.protocol.OFFlowMod;
48 import org.openflow.protocol.OFMatch;
49 import org.openflow.protocol.OFMessage;
50 import org.openflow.protocol.OFPacketOut;
51 import org.openflow.protocol.OFPort;
52 import org.openflow.protocol.OFVendor;
53 import org.openflow.protocol.action.OFAction;
54 import org.openflow.protocol.action.OFActionDataLayerDestination;
55 import org.openflow.protocol.action.OFActionDataLayerSource;
56 import org.openflow.protocol.action.OFActionNetworkLayerAddress;
57 import org.openflow.protocol.action.OFActionNetworkLayerDestination;
58 import org.openflow.protocol.action.OFActionNetworkLayerSource;
59 import org.openflow.protocol.action.OFActionNetworkTypeOfService;
60 import org.openflow.protocol.action.OFActionOutput;
61 import org.openflow.protocol.action.OFActionStripVirtualLan;
62 import org.openflow.protocol.action.OFActionTransportLayer;
63 import org.openflow.protocol.action.OFActionTransportLayerDestination;
64 import org.openflow.protocol.action.OFActionTransportLayerSource;
65 import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
66 import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
67 import org.openflow.util.U16;
68 import org.openflow.util.U32;
69 import org.slf4j.Logger;
70 import org.slf4j.LoggerFactory;
71
72 /**
73  * Utility class for converting a SAL Flow into the OF flow and vice-versa
74  */
75 public class FlowConverter {
76     protected static final Logger logger = LoggerFactory
77             .getLogger(FlowConverter.class);
78     private Flow flow; // SAL Flow
79     private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match
80     private List<OFAction> actionsList; // OF 1.0 actions
81     private int actionsLength;
82     private boolean isIPv6;
83
84     public FlowConverter(OFMatch ofMatch, List<OFAction> actionsList) {
85         this.ofMatch = ofMatch;
86         this.actionsList = actionsList;
87         this.actionsLength = 0;
88         this.flow = null;
89         this.isIPv6 = ofMatch instanceof V6Match;
90     }
91
92     public FlowConverter(Flow flow) {
93         this.ofMatch = null;
94         this.actionsList = null;
95         this.actionsLength = 0;
96         this.flow = flow;
97         this.isIPv6 = flow.isIPv6();
98     }
99
100     /**
101      * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions
102      * form (V6Match)
103      * 
104      * @return
105      */
106     public OFMatch getOFMatch() {
107         if (ofMatch == null) {
108             Match match = flow.getMatch();
109             ofMatch = (isIPv6) ? new V6Match() : new OFMatch();
110
111             int wildcards = OFMatch.OFPFW_ALL;
112             if (match.isPresent(MatchType.IN_PORT)) {
113                 short port = (Short) ((NodeConnector) match.getField(
114                         MatchType.IN_PORT).getValue()).getID();
115                 if (!isIPv6) {
116                     ofMatch.setInputPort(port);
117                     wildcards &= ~OFMatch.OFPFW_IN_PORT;
118                 } else {
119                     ((V6Match) ofMatch).setInputPort(port, (short) 0);
120                 }
121             }
122             if (match.isPresent(MatchType.DL_SRC)) {
123                 byte[] srcMac = (byte[]) match.getField(MatchType.DL_SRC)
124                         .getValue();
125                 if (!isIPv6) {
126                     ofMatch.setDataLayerSource(srcMac.clone());
127                     wildcards &= ~OFMatch.OFPFW_DL_SRC;
128                 } else {
129                     ((V6Match) ofMatch).setDataLayerSource(srcMac, null);
130                 }
131             }
132             if (match.isPresent(MatchType.DL_DST)) {
133                 byte[] dstMac = (byte[]) match.getField(MatchType.DL_DST)
134                         .getValue();
135                 if (!isIPv6) {
136                     ofMatch.setDataLayerDestination(dstMac.clone());
137                     wildcards &= ~OFMatch.OFPFW_DL_DST;
138                 } else {
139                     ((V6Match) ofMatch).setDataLayerDestination(dstMac, null);
140                 }
141             }
142             if (match.isPresent(MatchType.DL_VLAN)) {
143                 short vlan = (Short) match.getField(MatchType.DL_VLAN)
144                         .getValue();
145                 if (!isIPv6) {
146                     ofMatch.setDataLayerVirtualLan(vlan);
147                     wildcards &= ~OFMatch.OFPFW_DL_VLAN;
148                 } else {
149                     ((V6Match) ofMatch).setDataLayerVirtualLan(vlan, (short) 0);
150                 }
151             }
152             if (match.isPresent(MatchType.DL_VLAN_PR)) {
153                 byte vlanPr = (Byte) match.getField(MatchType.DL_VLAN_PR)
154                         .getValue();
155                 if (!isIPv6) {
156                     ofMatch.setDataLayerVirtualLanPriorityCodePoint(vlanPr);
157                     wildcards &= ~OFMatch.OFPFW_DL_VLAN_PCP;
158                 } else {
159                     ((V6Match) ofMatch)
160                             .setDataLayerVirtualLanPriorityCodePoint(vlanPr,
161                                     (byte) 0);
162                 }
163             }
164             if (match.isPresent(MatchType.DL_TYPE)) {
165                 short ethType = (Short) match.getField(MatchType.DL_TYPE)
166                         .getValue();
167                 if (!isIPv6) {
168                     ofMatch.setDataLayerType(ethType);
169                     wildcards &= ~OFMatch.OFPFW_DL_TYPE;
170                 } else {
171                     ((V6Match) ofMatch).setDataLayerType(ethType, (short) 0);
172                 }
173             }
174             if (match.isPresent(MatchType.NW_TOS)) {
175                 /*
176                  * OF 1.0 switch expects the TOS as the 6 msb in the byte. it is
177                  * actually the DSCP field followed by a zero ECN
178                  */
179                 byte tos = (Byte) match.getField(MatchType.NW_TOS).getValue();
180                 byte dscp = (byte) ((int) tos << 2);
181                 if (!isIPv6) {
182                     ofMatch.setNetworkTypeOfService(dscp);
183                     wildcards &= ~OFMatch.OFPFW_NW_TOS;
184                 } else {
185                     ((V6Match) ofMatch).setNetworkTypeOfService(dscp, (byte) 0);
186                 }
187             }
188             if (match.isPresent(MatchType.NW_PROTO)) {
189                 byte proto = (Byte) match.getField(MatchType.NW_PROTO)
190                         .getValue();
191                 if (!isIPv6) {
192                     ofMatch.setNetworkProtocol(proto);
193                     wildcards &= ~OFMatch.OFPFW_NW_PROTO;
194                 } else {
195                     ((V6Match) ofMatch).setNetworkProtocol(proto, (byte) 0);
196                 }
197             }
198             if (match.isPresent(MatchType.NW_SRC)) {
199                 InetAddress address = (InetAddress) match.getField(
200                         MatchType.NW_SRC).getValue();
201                 InetAddress mask = (InetAddress) match.getField(
202                         MatchType.NW_SRC).getMask();
203                 if (!isIPv6) {
204                     ofMatch.setNetworkSource(NetUtils.byteArray4ToInt(address
205                             .getAddress()));
206                     int maskLength = NetUtils
207                             .getSubnetMaskLength((mask == null) ? null : mask
208                                     .getAddress());
209                     wildcards = (wildcards & ~OFMatch.OFPFW_NW_SRC_MASK)
210                             | (maskLength << OFMatch.OFPFW_NW_SRC_SHIFT);
211                 } else {
212                     ((V6Match) ofMatch).setNetworkSource(address, mask);
213                 }
214             }
215             if (match.isPresent(MatchType.NW_DST)) {
216                 InetAddress address = (InetAddress) match.getField(
217                         MatchType.NW_DST).getValue();
218                 InetAddress mask = (InetAddress) match.getField(
219                         MatchType.NW_DST).getMask();
220                 if (!isIPv6) {
221                     ofMatch.setNetworkDestination(NetUtils
222                             .byteArray4ToInt(address.getAddress()));
223                     int maskLength = NetUtils
224                             .getSubnetMaskLength((mask == null) ? null : mask
225                                     .getAddress());
226                     wildcards = (wildcards & ~OFMatch.OFPFW_NW_DST_MASK)
227                             | (maskLength << OFMatch.OFPFW_NW_DST_SHIFT);
228                 } else {
229                     ((V6Match) ofMatch).setNetworkDestination(address, mask);
230                 }
231             }
232             if (match.isPresent(MatchType.TP_SRC)) {
233                 short port = (Short) match.getField(MatchType.TP_SRC)
234                         .getValue();
235                 if (!isIPv6) {
236                     ofMatch.setTransportSource(port);
237                     wildcards &= ~OFMatch.OFPFW_TP_SRC;
238                 } else {
239                     ((V6Match) ofMatch).setTransportSource(port, (short) 0);
240                 }
241             }
242             if (match.isPresent(MatchType.TP_DST)) {
243                 short port = (Short) match.getField(MatchType.TP_DST)
244                         .getValue();
245                 if (!isIPv6) {
246                     ofMatch.setTransportDestination(port);
247                     wildcards &= ~OFMatch.OFPFW_TP_DST;
248                 } else {
249                     ((V6Match) ofMatch)
250                             .setTransportDestination(port, (short) 0);
251                 }
252             }
253
254             if (!isIPv6) {
255                 ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
256             }
257         }
258         logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
259                 ofMatch);
260         return ofMatch;
261     }
262
263     /**
264      * Returns the list of actions in OF 1.0 form
265      * 
266      * @return
267      */
268     public List<OFAction> getOFActions() {
269         if (this.actionsList == null) {
270             actionsList = new ArrayList<OFAction>();
271             for (Action action : flow.getActions()) {
272                 if (action.getType() == ActionType.OUTPUT) {
273                     Output a = (Output) action;
274                     OFActionOutput ofAction = new OFActionOutput();
275                     ofAction.setMaxLength((short) 0xffff);
276                     ofAction.setPort(PortConverter.toOFPort(a.getPort()));
277                     actionsList.add(ofAction);
278                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
279                     continue;
280                 }
281                 if (action.getType() == ActionType.DROP) {
282                     continue;
283                 }
284                 if (action.getType() == ActionType.LOOPBACK) {
285                     OFActionOutput ofAction = new OFActionOutput();
286                     ofAction.setPort(OFPort.OFPP_IN_PORT.getValue());
287                     actionsList.add(ofAction);
288                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
289                     continue;
290                 }
291                 if (action.getType() == ActionType.FLOOD) {
292                     OFActionOutput ofAction = new OFActionOutput();
293                     ofAction.setPort(OFPort.OFPP_FLOOD.getValue());
294                     actionsList.add(ofAction);
295                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
296                     continue;
297                 }
298                 if (action.getType() == ActionType.FLOOD_ALL) {
299                     OFActionOutput ofAction = new OFActionOutput();
300                     ofAction.setPort(OFPort.OFPP_ALL.getValue());
301                     actionsList.add(ofAction);
302                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
303                     continue;
304                 }
305                 if (action.getType() == ActionType.CONTROLLER) {
306                     OFActionOutput ofAction = new OFActionOutput();
307                     ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue());
308                     // We want the whole frame hitting the match be sent to the
309                     // controller
310                     ofAction.setMaxLength((short) 0xffff);
311                     actionsList.add(ofAction);
312                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
313                     continue;
314                 }
315                 if (action.getType() == ActionType.SW_PATH) {
316                     OFActionOutput ofAction = new OFActionOutput();
317                     ofAction.setPort(OFPort.OFPP_LOCAL.getValue());
318                     actionsList.add(ofAction);
319                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
320                     continue;
321                 }
322                 if (action.getType() == ActionType.HW_PATH) {
323                     OFActionOutput ofAction = new OFActionOutput();
324                     ofAction.setPort(OFPort.OFPP_NORMAL.getValue());
325                     actionsList.add(ofAction);
326                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
327                     continue;
328                 }
329                 if (action.getType() == ActionType.SET_VLAN_ID) {
330                     SetVlanId a = (SetVlanId) action;
331                     OFActionVirtualLanIdentifier ofAction = new OFActionVirtualLanIdentifier();
332                     ofAction.setVirtualLanIdentifier((short) a.getVlanId());
333                     actionsList.add(ofAction);
334                     actionsLength += OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
335                     continue;
336                 }
337                 if (action.getType() == ActionType.SET_VLAN_PCP) {
338                     SetVlanPcp a = (SetVlanPcp) action;
339                     OFActionVirtualLanPriorityCodePoint ofAction = new OFActionVirtualLanPriorityCodePoint();
340                     ofAction.setVirtualLanPriorityCodePoint(Integer.valueOf(
341                             a.getPcp()).byteValue());
342                     actionsList.add(ofAction);
343                     actionsLength += OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
344                     continue;
345                 }
346                 if (action.getType() == ActionType.POP_VLAN) {
347                     OFActionStripVirtualLan ofAction = new OFActionStripVirtualLan();
348                     actionsList.add(ofAction);
349                     actionsLength += OFActionStripVirtualLan.MINIMUM_LENGTH;
350                     continue;
351                 }
352                 if (action.getType() == ActionType.SET_DL_SRC) {
353                     SetDlSrc a = (SetDlSrc) action;
354                     OFActionDataLayerSource ofAction = new OFActionDataLayerSource();
355                     ofAction.setDataLayerAddress(a.getDlAddress());
356                     actionsList.add(ofAction);
357                     actionsLength += OFActionDataLayerSource.MINIMUM_LENGTH;
358                     continue;
359                 }
360                 if (action.getType() == ActionType.SET_DL_DST) {
361                     SetDlDst a = (SetDlDst) action;
362                     OFActionDataLayerDestination ofAction = new OFActionDataLayerDestination();
363                     ofAction.setDataLayerAddress(a.getDlAddress());
364                     actionsList.add(ofAction);
365                     actionsLength += OFActionDataLayerDestination.MINIMUM_LENGTH;
366                     continue;
367                 }
368                 if (action.getType() == ActionType.SET_NW_SRC) {
369                     SetNwSrc a = (SetNwSrc) action;
370                     OFActionNetworkLayerSource ofAction = new OFActionNetworkLayerSource();
371                     ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
372                             .getAddress().getAddress()));
373                     actionsList.add(ofAction);
374                     actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
375                     continue;
376                 }
377                 if (action.getType() == ActionType.SET_NW_DST) {
378                     SetNwDst a = (SetNwDst) action;
379                     OFActionNetworkLayerDestination ofAction = new OFActionNetworkLayerDestination();
380                     ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
381                             .getAddress().getAddress()));
382                     actionsList.add(ofAction);
383                     actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
384                     continue;
385                 }
386                 if (action.getType() == ActionType.SET_NW_TOS) {
387                     SetNwTos a = (SetNwTos) action;
388                     OFActionNetworkTypeOfService ofAction = new OFActionNetworkTypeOfService();
389                     ofAction.setNetworkTypeOfService(Integer.valueOf(
390                             a.getNwTos()).byteValue());
391                     actionsList.add(ofAction);
392                     actionsLength += OFActionNetworkTypeOfService.MINIMUM_LENGTH;
393                     continue;
394                 }
395                 if (action.getType() == ActionType.SET_TP_SRC) {
396                     SetTpSrc a = (SetTpSrc) action;
397                     OFActionTransportLayerSource ofAction = new OFActionTransportLayerSource();
398                     ofAction.setTransportPort(Integer.valueOf(a.getPort())
399                             .shortValue());
400                     actionsList.add(ofAction);
401                     actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
402                     continue;
403                 }
404                 if (action.getType() == ActionType.SET_TP_DST) {
405                     SetTpDst a = (SetTpDst) action;
406                     OFActionTransportLayerDestination ofAction = new OFActionTransportLayerDestination();
407                     ofAction.setTransportPort(Integer.valueOf(a.getPort())
408                             .shortValue());
409                     actionsList.add(ofAction);
410                     actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
411                     continue;
412                 }
413                 if (action.getType() == ActionType.SET_NEXT_HOP) {
414                     // TODO
415                     continue;
416                 }
417             }
418         }
419         logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
420                 actionsList);
421         return actionsList;
422     }
423
424     /**
425      * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 +
426      * IPv6 extension (V6FlowMod) Flow modifier Message
427      * 
428      * @param sw
429      * @param command
430      * @param port
431      * @return
432      */
433     public OFMessage getOFFlowMod(short command, OFPort port) {
434         OFMessage fm = (isIPv6) ? new V6FlowMod() : new OFFlowMod();
435         if (this.ofMatch == null) {
436             getOFMatch();
437         }
438         if (this.actionsList == null) {
439             getOFActions();
440         }
441         if (!isIPv6) {
442             ((OFFlowMod) fm).setMatch(this.ofMatch);
443             ((OFFlowMod) fm).setActions(this.actionsList);
444             ((OFFlowMod) fm).setPriority(flow.getPriority());
445             ((OFFlowMod) fm).setCookie(flow.getId());
446             ((OFFlowMod) fm).setBufferId(OFPacketOut.BUFFER_ID_NONE);
447             ((OFFlowMod) fm).setLength(U16.t(OFFlowMod.MINIMUM_LENGTH
448                     + actionsLength));
449             ((OFFlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
450             ((OFFlowMod) fm).setHardTimeout(flow.getHardTimeout());
451             ((OFFlowMod) fm).setCommand(command);
452             if (port != null) {
453                 ((OFFlowMod) fm).setOutPort(port);
454             }
455             if (command == OFFlowMod.OFPFC_ADD
456                     || command == OFFlowMod.OFPFC_MODIFY
457                     || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
458                 if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
459                     // Instruct switch to let controller know when flow expires
460                     ((OFFlowMod) fm).setFlags((short) 1);
461                 }
462             }
463         } else {
464             ((V6FlowMod) fm).setVendor();
465             ((V6FlowMod) fm).setMatch((V6Match) ofMatch);
466             ((V6FlowMod) fm).setActions(this.actionsList);
467             ((V6FlowMod) fm).setPriority(flow.getPriority());
468             ((V6FlowMod) fm).setCookie(flow.getId());
469             ((V6FlowMod) fm).setLength(U16.t(OFVendor.MINIMUM_LENGTH
470                     + ((V6Match) ofMatch).getIPv6ExtMinHdrLen()
471                     + ((V6Match) ofMatch).getIPv6MatchLen()
472                     + ((V6Match) ofMatch).getPadSize() + actionsLength));
473             ((V6FlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
474             ((V6FlowMod) fm).setHardTimeout(flow.getHardTimeout());
475             ((V6FlowMod) fm).setCommand(command);
476             if (port != null) {
477                 ((V6FlowMod) fm).setOutPort(port);
478             }
479             if (command == OFFlowMod.OFPFC_ADD
480                     || command == OFFlowMod.OFPFC_MODIFY
481                     || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
482                 if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
483                     // Instruct switch to let controller know when flow expires
484                     ((V6FlowMod) fm).setFlags((short) 1);
485                 }
486             }
487         }
488         logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
489                 actionsList);
490         logger.trace("Openflow Mod Message: {}", fm);
491         return fm;
492     }
493
494     public Flow getFlow(Node node) {
495         if (this.flow == null) {
496             Match salMatch = new Match();
497
498             /*
499              * Installed flow may not have a Match defined like in case of a
500              * drop all flow
501              */
502             if (ofMatch != null) {
503                 if (!isIPv6) {
504                     // Compute OF1.0 Match
505                     if (ofMatch.getInputPort() != 0) {
506                         salMatch.setField(new MatchField(MatchType.IN_PORT,
507                                 NodeConnectorCreator.createNodeConnector(
508                                         (Short) ofMatch.getInputPort(), node)));
509                     }
510                     if (ofMatch.getDataLayerSource() != null
511                             && !NetUtils
512                                     .isZeroMAC(ofMatch.getDataLayerSource())) {
513                         byte srcMac[] = ofMatch.getDataLayerSource();
514                         salMatch.setField(new MatchField(MatchType.DL_SRC,
515                                 srcMac.clone()));
516                     }
517                     if (ofMatch.getDataLayerDestination() != null
518                             && !NetUtils.isZeroMAC(ofMatch
519                                     .getDataLayerDestination())) {
520                         byte dstMac[] = ofMatch.getDataLayerDestination();
521                         salMatch.setField(new MatchField(MatchType.DL_DST,
522                                 dstMac.clone()));
523                     }
524                     if (ofMatch.getDataLayerType() != 0) {
525                         salMatch.setField(new MatchField(MatchType.DL_TYPE,
526                                 ofMatch.getDataLayerType()));
527                     }
528                     if (ofMatch.getDataLayerVirtualLan() != 0) {
529                         salMatch.setField(new MatchField(MatchType.DL_VLAN,
530                                 ofMatch.getDataLayerVirtualLan()));
531                     }
532                     if (ofMatch.getDataLayerVirtualLanPriorityCodePoint() != 0) {
533                         salMatch.setField(MatchType.DL_VLAN_PR, ofMatch
534                                 .getDataLayerVirtualLanPriorityCodePoint());
535                     }
536                     if (ofMatch.getNetworkSource() != 0) {
537                         salMatch.setField(MatchType.NW_SRC, NetUtils
538                                 .getInetAddress(ofMatch.getNetworkSource()),
539                                 NetUtils.getInetNetworkMask(
540                                         ofMatch.getNetworkSourceMaskLen(),
541                                         false));
542                     }
543                     if (ofMatch.getNetworkDestination() != 0) {
544                         salMatch.setField(MatchType.NW_DST,
545                                 NetUtils.getInetAddress(ofMatch
546                                         .getNetworkDestination()),
547                                 NetUtils.getInetNetworkMask(
548                                         ofMatch.getNetworkDestinationMaskLen(),
549                                         false));
550                     }
551                     if (ofMatch.getNetworkTypeOfService() != 0) {
552                         int dscp = NetUtils.getUnsignedByte(ofMatch
553                                 .getNetworkTypeOfService());
554                         byte tos = (byte) (dscp >> 2);
555                         salMatch.setField(MatchType.NW_TOS, tos);
556                     }
557                     if (ofMatch.getNetworkProtocol() != 0) {
558                         salMatch.setField(MatchType.NW_PROTO,
559                                 ofMatch.getNetworkProtocol());
560                     }
561                     if (ofMatch.getTransportSource() != 0) {
562                         salMatch.setField(MatchType.TP_SRC,
563                                 ((Short) ofMatch.getTransportSource()));
564                     }
565                     if (ofMatch.getTransportDestination() != 0) {
566                         salMatch.setField(MatchType.TP_DST,
567                                 ((Short) ofMatch.getTransportDestination()));
568                     }
569                 } else {
570                     // Compute OF1.0 + IPv6 extensions Match
571                     V6Match v6Match = (V6Match) ofMatch;
572                     if (v6Match.getInputPort() != 0) {
573                         // Mask on input port is not defined
574                         salMatch.setField(new MatchField(MatchType.IN_PORT,
575                                 NodeConnectorCreator.createOFNodeConnector(
576                                         (Short) v6Match.getInputPort(), node)));
577                     }
578                     if (v6Match.getDataLayerSource() != null
579                             && !NetUtils
580                                     .isZeroMAC(ofMatch.getDataLayerSource())) {
581                         byte srcMac[] = v6Match.getDataLayerSource();
582                         salMatch.setField(new MatchField(MatchType.DL_SRC,
583                                 srcMac.clone()));
584                     }
585                     if (v6Match.getDataLayerDestination() != null
586                             && !NetUtils.isZeroMAC(ofMatch
587                                     .getDataLayerDestination())) {
588                         byte dstMac[] = v6Match.getDataLayerDestination();
589                         salMatch.setField(new MatchField(MatchType.DL_DST,
590                                 dstMac.clone()));
591                     }
592                     if (v6Match.getDataLayerType() != 0) {
593                         salMatch.setField(new MatchField(MatchType.DL_TYPE,
594                                 v6Match.getDataLayerType()));
595                     }
596                     if (v6Match.getDataLayerVirtualLan() != 0) {
597                         salMatch.setField(new MatchField(MatchType.DL_VLAN,
598                                 v6Match.getDataLayerVirtualLan()));
599                     }
600                     if (v6Match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
601                         salMatch.setField(MatchType.DL_VLAN_PR, v6Match
602                                 .getDataLayerVirtualLanPriorityCodePoint());
603                     }
604                     if (v6Match.getNetworkSrc() != null) {
605                         salMatch.setField(MatchType.NW_SRC,
606                                 v6Match.getNetworkSrc(),
607                                 v6Match.getNetworkSourceMask());
608                     }
609                     if (v6Match.getNetworkDest() != null) {
610                         salMatch.setField(MatchType.NW_DST,
611                                 v6Match.getNetworkDest(),
612                                 v6Match.getNetworkDestinationMask());
613                     }
614                     if (v6Match.getNetworkTypeOfService() != 0) {
615                         int dscp = NetUtils.getUnsignedByte(v6Match
616                                 .getNetworkTypeOfService());
617                         byte tos = (byte) (dscp >> 2);
618                         salMatch.setField(MatchType.NW_TOS, tos);
619                     }
620                     if (v6Match.getNetworkProtocol() != 0) {
621                         salMatch.setField(MatchType.NW_PROTO,
622                                 v6Match.getNetworkProtocol());
623                     }
624                     if (v6Match.getTransportSource() != 0) {
625                         salMatch.setField(MatchType.TP_SRC,
626                                 ((Short) v6Match.getTransportSource()));
627                     }
628                     if (v6Match.getTransportDestination() != 0) {
629                         salMatch.setField(MatchType.TP_DST,
630                                 ((Short) v6Match.getTransportDestination()));
631                     }
632                 }
633             }
634
635             // Convert actions
636             Action salAction = null;
637             List<Action> salActionList = new ArrayList<Action>();
638             if (actionsList == null) {
639                 salActionList.add(new Drop());
640             } else {
641                 for (OFAction ofAction : actionsList) {
642                     if (ofAction instanceof OFActionOutput) {
643                         short ofPort = ((OFActionOutput) ofAction).getPort();
644                         if (ofPort == OFPort.OFPP_CONTROLLER.getValue()) {
645                             salAction = new Controller();
646                         } else if (ofPort == OFPort.OFPP_NONE.getValue()) {
647                             salAction = new Drop();
648                         } else if (ofPort == OFPort.OFPP_IN_PORT.getValue()) {
649                             salAction = new Loopback();
650                         } else if (ofPort == OFPort.OFPP_FLOOD.getValue()) {
651                             salAction = new Flood();
652                         } else if (ofPort == OFPort.OFPP_ALL.getValue()) {
653                             salAction = new FloodAll();
654                         } else if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
655                             salAction = new SwPath();
656                         } else if (ofPort == OFPort.OFPP_NORMAL.getValue()) {
657                             salAction = new HwPath();
658                         } else if (ofPort == OFPort.OFPP_TABLE.getValue()) {
659                             salAction = new HwPath(); // TODO: we do not handle
660                                                       // table in sal for now
661                         } else {
662                             salAction = new Output(
663                                     NodeConnectorCreator.createOFNodeConnector(
664                                             ofPort, node));
665                         }
666                     } else if (ofAction instanceof OFActionVirtualLanIdentifier) {
667                         salAction = new SetVlanId(
668                                 ((OFActionVirtualLanIdentifier) ofAction)
669                                         .getVirtualLanIdentifier());
670                     } else if (ofAction instanceof OFActionStripVirtualLan) {
671                         salAction = new PopVlan();
672                     } else if (ofAction instanceof OFActionVirtualLanPriorityCodePoint) {
673                         salAction = new SetVlanPcp(
674                                 ((OFActionVirtualLanPriorityCodePoint) ofAction)
675                                         .getVirtualLanPriorityCodePoint());
676                     } else if (ofAction instanceof OFActionDataLayerSource) {
677                         salAction = new SetDlSrc(
678                                 ((OFActionDataLayerSource) ofAction)
679                                         .getDataLayerAddress().clone());
680                     } else if (ofAction instanceof OFActionDataLayerDestination) {
681                         salAction = new SetDlDst(
682                                 ((OFActionDataLayerDestination) ofAction)
683                                         .getDataLayerAddress().clone());
684                     } else if (ofAction instanceof OFActionNetworkLayerSource) {
685                         byte addr[] = BigInteger.valueOf(
686                                 ((OFActionNetworkLayerSource) ofAction)
687                                         .getNetworkAddress()).toByteArray();
688                         InetAddress ip = null;
689                         try {
690                             ip = InetAddress.getByAddress(addr);
691                         } catch (UnknownHostException e) {
692                             logger.error("", e);
693                         }
694                         salAction = new SetNwSrc(ip);
695                     } else if (ofAction instanceof OFActionNetworkLayerDestination) {
696                         byte addr[] = BigInteger.valueOf(
697                                 ((OFActionNetworkLayerDestination) ofAction)
698                                         .getNetworkAddress()).toByteArray();
699                         InetAddress ip = null;
700                         try {
701                             ip = InetAddress.getByAddress(addr);
702                         } catch (UnknownHostException e) {
703                             logger.error("", e);
704                         }
705                         salAction = new SetNwDst(ip);
706                     } else if (ofAction instanceof OFActionNetworkTypeOfService) {
707                         salAction = new SetNwTos(
708                                 ((OFActionNetworkTypeOfService) ofAction)
709                                         .getNetworkTypeOfService());
710                     } else if (ofAction instanceof OFActionTransportLayerSource) {
711                         Short port = ((OFActionTransportLayerSource) ofAction)
712                                 .getTransportPort();
713                         int intPort = NetUtils.getUnsignedShort(port);
714                         salAction = new SetTpSrc(intPort);
715                     } else if (ofAction instanceof OFActionTransportLayerDestination) {
716                         Short port = ((OFActionTransportLayerDestination) ofAction)
717                                 .getTransportPort();
718                         int intPort = NetUtils.getUnsignedShort(port);
719                         salAction = new SetTpDst(intPort);
720                     }
721                     salActionList.add(salAction);
722                 }
723             }
724             // Create Flow
725             flow = new Flow(salMatch, salActionList);
726         }
727         logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
728                 actionsList);
729         logger.trace("SAL Flow: {}", flow);
730         return flow;
731     }
732
733 }