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