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