756a6895dc06e19ef0fbcbd85314c3fb0abdc645
[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.OFActionDataLayer;
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) (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(MatchType.NW_SRC).getValue();
201                 InetAddress mask = (InetAddress) match.getField(MatchType.NW_SRC).getMask();
202                 if (!isIPv6) {
203                     ofMatch.setNetworkSource(NetUtils.byteArray4ToInt(address.getAddress()));
204                     int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
205                     wildcards = (wildcards & ~OFMatch.OFPFW_NW_SRC_MASK) | ((32 - 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(MatchType.NW_DST).getValue();
212                 InetAddress mask = (InetAddress) match.getField(MatchType.NW_DST).getMask();
213                 if (!isIPv6) {
214                     ofMatch.setNetworkDestination(NetUtils.byteArray4ToInt(address.getAddress()));
215                     int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
216                     wildcards = (wildcards & ~OFMatch.OFPFW_NW_DST_MASK) | ((32 - maskLength) << OFMatch.OFPFW_NW_DST_SHIFT);
217                 } else {
218                     ((V6Match) ofMatch).setNetworkDestination(address, mask);
219                 }
220             }
221             if (match.isPresent(MatchType.TP_SRC)) {
222                 short port = (Short) match.getField(MatchType.TP_SRC)
223                         .getValue();
224                 if (!isIPv6) {
225                     ofMatch.setTransportSource(port);
226                     wildcards &= ~OFMatch.OFPFW_TP_SRC;
227                 } else {
228                     ((V6Match) ofMatch).setTransportSource(port, (short) 0);
229                 }
230             }
231             if (match.isPresent(MatchType.TP_DST)) {
232                 short port = (Short) match.getField(MatchType.TP_DST)
233                         .getValue();
234                 if (!isIPv6) {
235                     ofMatch.setTransportDestination(port);
236                     wildcards &= ~OFMatch.OFPFW_TP_DST;
237                 } else {
238                     ((V6Match) ofMatch)
239                             .setTransportDestination(port, (short) 0);
240                 }
241             }
242
243             if (!isIPv6) {
244                 ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
245             }
246         }
247         logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
248                 ofMatch);
249         return ofMatch;
250     }
251
252     /**
253      * Returns the list of actions in OF 1.0 form
254      *
255      * @return
256      */
257     public List<OFAction> getOFActions() {
258         if (this.actionsList == null) {
259             actionsList = new ArrayList<OFAction>();
260             for (Action action : flow.getActions()) {
261                 if (action.getType() == ActionType.OUTPUT) {
262                     Output a = (Output) action;
263                     OFActionOutput ofAction = new OFActionOutput();
264                     ofAction.setMaxLength((short) 0xffff);
265                     ofAction.setPort(PortConverter.toOFPort(a.getPort()));
266                     actionsList.add(ofAction);
267                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
268                     continue;
269                 }
270                 if (action.getType() == ActionType.DROP) {
271                     continue;
272                 }
273                 if (action.getType() == ActionType.LOOPBACK) {
274                     OFActionOutput ofAction = new OFActionOutput();
275                     ofAction.setPort(OFPort.OFPP_IN_PORT.getValue());
276                     actionsList.add(ofAction);
277                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
278                     continue;
279                 }
280                 if (action.getType() == ActionType.FLOOD) {
281                     OFActionOutput ofAction = new OFActionOutput();
282                     ofAction.setPort(OFPort.OFPP_FLOOD.getValue());
283                     actionsList.add(ofAction);
284                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
285                     continue;
286                 }
287                 if (action.getType() == ActionType.FLOOD_ALL) {
288                     OFActionOutput ofAction = new OFActionOutput();
289                     ofAction.setPort(OFPort.OFPP_ALL.getValue());
290                     actionsList.add(ofAction);
291                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
292                     continue;
293                 }
294                 if (action.getType() == ActionType.CONTROLLER) {
295                     OFActionOutput ofAction = new OFActionOutput();
296                     ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue());
297                     // We want the whole frame hitting the match be sent to the
298                     // controller
299                     ofAction.setMaxLength((short) 0xffff);
300                     actionsList.add(ofAction);
301                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
302                     continue;
303                 }
304                 if (action.getType() == ActionType.SW_PATH) {
305                     OFActionOutput ofAction = new OFActionOutput();
306                     ofAction.setPort(OFPort.OFPP_LOCAL.getValue());
307                     actionsList.add(ofAction);
308                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
309                     continue;
310                 }
311                 if (action.getType() == ActionType.HW_PATH) {
312                     OFActionOutput ofAction = new OFActionOutput();
313                     ofAction.setPort(OFPort.OFPP_NORMAL.getValue());
314                     actionsList.add(ofAction);
315                     actionsLength += OFActionOutput.MINIMUM_LENGTH;
316                     continue;
317                 }
318                 if (action.getType() == ActionType.SET_VLAN_ID) {
319                     SetVlanId a = (SetVlanId) action;
320                     OFActionVirtualLanIdentifier ofAction = new OFActionVirtualLanIdentifier();
321                     ofAction.setVirtualLanIdentifier((short) a.getVlanId());
322                     actionsList.add(ofAction);
323                     actionsLength += OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
324                     continue;
325                 }
326                 if (action.getType() == ActionType.SET_VLAN_PCP) {
327                     SetVlanPcp a = (SetVlanPcp) action;
328                     OFActionVirtualLanPriorityCodePoint ofAction = new OFActionVirtualLanPriorityCodePoint();
329                     ofAction.setVirtualLanPriorityCodePoint(Integer.valueOf(
330                             a.getPcp()).byteValue());
331                     actionsList.add(ofAction);
332                     actionsLength += OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
333                     continue;
334                 }
335                 if (action.getType() == ActionType.POP_VLAN) {
336                     OFActionStripVirtualLan ofAction = new OFActionStripVirtualLan();
337                     actionsList.add(ofAction);
338                     actionsLength += OFActionStripVirtualLan.MINIMUM_LENGTH;
339                     continue;
340                 }
341                 if (action.getType() == ActionType.SET_DL_SRC) {
342                     SetDlSrc a = (SetDlSrc) action;
343                     OFActionDataLayerSource ofAction = new OFActionDataLayerSource();
344                     ofAction.setDataLayerAddress(a.getDlAddress());
345                     actionsList.add(ofAction);
346                     actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
347                     continue;
348                 }
349                 if (action.getType() == ActionType.SET_DL_DST) {
350                     SetDlDst a = (SetDlDst) action;
351                     OFActionDataLayerDestination ofAction = new OFActionDataLayerDestination();
352                     ofAction.setDataLayerAddress(a.getDlAddress());
353                     actionsList.add(ofAction);
354                     actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
355                     continue;
356                 }
357                 if (action.getType() == ActionType.SET_NW_SRC) {
358                     SetNwSrc a = (SetNwSrc) action;
359                     OFActionNetworkLayerSource ofAction = new OFActionNetworkLayerSource();
360                     ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
361                             .getAddress().getAddress()));
362                     actionsList.add(ofAction);
363                     actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
364                     continue;
365                 }
366                 if (action.getType() == ActionType.SET_NW_DST) {
367                     SetNwDst a = (SetNwDst) action;
368                     OFActionNetworkLayerDestination ofAction = new OFActionNetworkLayerDestination();
369                     ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
370                             .getAddress().getAddress()));
371                     actionsList.add(ofAction);
372                     actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
373                     continue;
374                 }
375                 if (action.getType() == ActionType.SET_NW_TOS) {
376                     SetNwTos a = (SetNwTos) action;
377                     OFActionNetworkTypeOfService ofAction = new OFActionNetworkTypeOfService();
378                     ofAction.setNetworkTypeOfService(Integer.valueOf(
379                             a.getNwTos()).byteValue());
380                     actionsList.add(ofAction);
381                     actionsLength += OFActionNetworkTypeOfService.MINIMUM_LENGTH;
382                     continue;
383                 }
384                 if (action.getType() == ActionType.SET_TP_SRC) {
385                     SetTpSrc a = (SetTpSrc) action;
386                     OFActionTransportLayerSource ofAction = new OFActionTransportLayerSource();
387                     ofAction.setTransportPort(Integer.valueOf(a.getPort())
388                             .shortValue());
389                     actionsList.add(ofAction);
390                     actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
391                     continue;
392                 }
393                 if (action.getType() == ActionType.SET_TP_DST) {
394                     SetTpDst a = (SetTpDst) action;
395                     OFActionTransportLayerDestination ofAction = new OFActionTransportLayerDestination();
396                     ofAction.setTransportPort(Integer.valueOf(a.getPort())
397                             .shortValue());
398                     actionsList.add(ofAction);
399                     actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
400                     continue;
401                 }
402                 if (action.getType() == ActionType.SET_NEXT_HOP) {
403                     logger.info("Unsupported action: {}", action);
404                     continue;
405                 }
406             }
407         }
408         logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
409                 actionsList);
410         return actionsList;
411     }
412
413     /**
414      * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 +
415      * IPv6 extension (V6FlowMod) Flow modifier Message
416      *
417      * @param sw
418      * @param command
419      * @param port
420      * @return
421      */
422     public OFMessage getOFFlowMod(short command, OFPort port) {
423         OFMessage fm = (isIPv6) ? new V6FlowMod() : new OFFlowMod();
424         if (this.ofMatch == null) {
425             getOFMatch();
426         }
427         if (this.actionsList == null) {
428             getOFActions();
429         }
430         if (!isIPv6) {
431             ((OFFlowMod) fm).setMatch(this.ofMatch);
432             ((OFFlowMod) fm).setActions(this.actionsList);
433             ((OFFlowMod) fm).setPriority(flow.getPriority());
434             ((OFFlowMod) fm).setCookie(flow.getId());
435             ((OFFlowMod) fm).setBufferId(OFPacketOut.BUFFER_ID_NONE);
436             ((OFFlowMod) fm).setLength(U16.t(OFFlowMod.MINIMUM_LENGTH
437                     + actionsLength));
438             ((OFFlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
439             ((OFFlowMod) fm).setHardTimeout(flow.getHardTimeout());
440             ((OFFlowMod) fm).setCommand(command);
441             if (port != null) {
442                 ((OFFlowMod) fm).setOutPort(port);
443             }
444             if (command == OFFlowMod.OFPFC_ADD
445                     || command == OFFlowMod.OFPFC_MODIFY
446                     || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
447                 if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
448                     // Instruct switch to let controller know when flow expires
449                     ((OFFlowMod) fm).setFlags((short) 1);
450                 }
451             }
452         } else {
453             ((V6FlowMod) fm).setVendor();
454             ((V6FlowMod) fm).setMatch((V6Match) ofMatch);
455             ((V6FlowMod) fm).setActions(this.actionsList);
456             ((V6FlowMod) fm).setPriority(flow.getPriority());
457             ((V6FlowMod) fm).setCookie(flow.getId());
458             ((V6FlowMod) fm).setLength(U16.t(OFVendor.MINIMUM_LENGTH
459                     + ((V6Match) ofMatch).getIPv6ExtMinHdrLen()
460                     + ((V6Match) ofMatch).getIPv6MatchLen()
461                     + ((V6Match) ofMatch).getPadSize() + actionsLength));
462             ((V6FlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
463             ((V6FlowMod) fm).setHardTimeout(flow.getHardTimeout());
464             ((V6FlowMod) fm).setCommand(command);
465             if (port != null) {
466                 ((V6FlowMod) fm).setOutPort(port);
467             }
468             if (command == OFFlowMod.OFPFC_ADD
469                     || command == OFFlowMod.OFPFC_MODIFY
470                     || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
471                 if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) {
472                     // Instruct switch to let controller know when flow expires
473                     ((V6FlowMod) fm).setFlags((short) 1);
474                 }
475             }
476         }
477         logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
478                 actionsList);
479         logger.trace("Openflow Mod Message: {}", fm);
480         return fm;
481     }
482
483     public Flow getFlow(Node node) {
484         if (this.flow == null) {
485             Match salMatch = new Match();
486
487             /*
488              * Installed flow may not have a Match defined like in case of a
489              * drop all flow
490              */
491             if (ofMatch != null) {
492                 if (!isIPv6) {
493                     // Compute OF1.0 Match
494                     if (ofMatch.getInputPort() != 0 && ofMatch.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
495                         salMatch.setField(new MatchField(MatchType.IN_PORT,
496                                 NodeConnectorCreator.createNodeConnector(
497                                         ofMatch.getInputPort(), node)));
498                     }
499                     if (ofMatch.getDataLayerSource() != null
500                             && !NetUtils
501                                     .isZeroMAC(ofMatch.getDataLayerSource())) {
502                         byte srcMac[] = ofMatch.getDataLayerSource();
503                         salMatch.setField(new MatchField(MatchType.DL_SRC,
504                                 srcMac.clone()));
505                     }
506                     if (ofMatch.getDataLayerDestination() != null
507                             && !NetUtils.isZeroMAC(ofMatch
508                                     .getDataLayerDestination())) {
509                         byte dstMac[] = ofMatch.getDataLayerDestination();
510                         salMatch.setField(new MatchField(MatchType.DL_DST,
511                                 dstMac.clone()));
512                     }
513                     if (ofMatch.getDataLayerType() != 0) {
514                         salMatch.setField(new MatchField(MatchType.DL_TYPE,
515                                 ofMatch.getDataLayerType()));
516                     }
517                     if (ofMatch.getDataLayerVirtualLan() != 0) {
518                         salMatch.setField(new MatchField(MatchType.DL_VLAN,
519                                 ofMatch.getDataLayerVirtualLan()));
520                     }
521                     if (ofMatch.getDataLayerVirtualLanPriorityCodePoint() != 0) {
522                         salMatch.setField(MatchType.DL_VLAN_PR, ofMatch
523                                 .getDataLayerVirtualLanPriorityCodePoint());
524                     }
525                     if (ofMatch.getNetworkSource() != 0) {
526                         salMatch.setField(MatchType.NW_SRC, NetUtils
527                                 .getInetAddress(ofMatch.getNetworkSource()),
528                                 NetUtils.getInetNetworkMask(
529                                         ofMatch.getNetworkSourceMaskLen(),
530                                         false));
531                     }
532                     if (ofMatch.getNetworkDestination() != 0) {
533                         salMatch.setField(MatchType.NW_DST,
534                                 NetUtils.getInetAddress(ofMatch
535                                         .getNetworkDestination()),
536                                 NetUtils.getInetNetworkMask(
537                                         ofMatch.getNetworkDestinationMaskLen(),
538                                         false));
539                     }
540                     if (ofMatch.getNetworkTypeOfService() != 0) {
541                         int dscp = NetUtils.getUnsignedByte(ofMatch
542                                 .getNetworkTypeOfService());
543                         byte tos = (byte) (dscp >> 2);
544                         salMatch.setField(MatchType.NW_TOS, tos);
545                     }
546                     if (ofMatch.getNetworkProtocol() != 0) {
547                         salMatch.setField(MatchType.NW_PROTO,
548                                 ofMatch.getNetworkProtocol());
549                     }
550                     if (ofMatch.getTransportSource() != 0) {
551                         salMatch.setField(MatchType.TP_SRC,
552                                 ofMatch.getTransportSource());
553                     }
554                     if (ofMatch.getTransportDestination() != 0) {
555                         salMatch.setField(MatchType.TP_DST,
556                                 ofMatch.getTransportDestination());
557                     }
558                 } else {
559                     // Compute OF1.0 + IPv6 extensions Match
560                     V6Match v6Match = (V6Match) ofMatch;
561                     if (v6Match.getInputPort() != 0 && v6Match.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
562                         // Mask on input port is not defined
563                         salMatch.setField(new MatchField(MatchType.IN_PORT,
564                                 NodeConnectorCreator.createOFNodeConnector(
565                                         v6Match.getInputPort(), node)));
566                     }
567                     if (v6Match.getDataLayerSource() != null
568                             && !NetUtils
569                                     .isZeroMAC(ofMatch.getDataLayerSource())) {
570                         byte srcMac[] = v6Match.getDataLayerSource();
571                         salMatch.setField(new MatchField(MatchType.DL_SRC,
572                                 srcMac.clone()));
573                     }
574                     if (v6Match.getDataLayerDestination() != null
575                             && !NetUtils.isZeroMAC(ofMatch
576                                     .getDataLayerDestination())) {
577                         byte dstMac[] = v6Match.getDataLayerDestination();
578                         salMatch.setField(new MatchField(MatchType.DL_DST,
579                                 dstMac.clone()));
580                     }
581                     if (v6Match.getDataLayerType() != 0) {
582                         salMatch.setField(new MatchField(MatchType.DL_TYPE,
583                                 v6Match.getDataLayerType()));
584                     }
585                     if (v6Match.getDataLayerVirtualLan() != 0) {
586                         salMatch.setField(new MatchField(MatchType.DL_VLAN,
587                                 v6Match.getDataLayerVirtualLan()));
588                     }
589                     if (v6Match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
590                         salMatch.setField(MatchType.DL_VLAN_PR, v6Match
591                                 .getDataLayerVirtualLanPriorityCodePoint());
592                     }
593                     // V6Match may carry IPv4 address
594                     if (v6Match.getNetworkSrc() != null) {
595                         salMatch.setField(MatchType.NW_SRC,
596                                 v6Match.getNetworkSrc(),
597                                 v6Match.getNetworkSourceMask());
598                     } else if (v6Match.getNetworkSource() != 0) {
599                         salMatch.setField(MatchType.NW_SRC, NetUtils
600                                 .getInetAddress(v6Match.getNetworkSource()),
601                                 NetUtils.getInetNetworkMask(
602                                         v6Match.getNetworkSourceMaskLen(),
603                                         false));
604                     }
605                     // V6Match may carry IPv4 address
606                     if (v6Match.getNetworkDest() != null) {
607                         salMatch.setField(MatchType.NW_DST,
608                                 v6Match.getNetworkDest(),
609                                 v6Match.getNetworkDestinationMask());
610                     } else if (v6Match.getNetworkDestination() != 0) {
611                         salMatch.setField(MatchType.NW_DST,
612                                 NetUtils.getInetAddress(v6Match
613                                         .getNetworkDestination()),
614                                 NetUtils.getInetNetworkMask(
615                                         v6Match.getNetworkDestinationMaskLen(),
616                                         false));
617                     }
618                     if (v6Match.getNetworkTypeOfService() != 0) {
619                         int dscp = NetUtils.getUnsignedByte(v6Match
620                                 .getNetworkTypeOfService());
621                         byte tos = (byte) (dscp >> 2);
622                         salMatch.setField(MatchType.NW_TOS, tos);
623                     }
624                     if (v6Match.getNetworkProtocol() != 0) {
625                         salMatch.setField(MatchType.NW_PROTO,
626                                 v6Match.getNetworkProtocol());
627                     }
628                     if (v6Match.getTransportSource() != 0) {
629                         salMatch.setField(MatchType.TP_SRC,
630                                 (v6Match.getTransportSource()));
631                     }
632                     if (v6Match.getTransportDestination() != 0) {
633                         salMatch.setField(MatchType.TP_DST,
634                                 (v6Match.getTransportDestination()));
635                     }
636                 }
637             }
638
639             // Convert actions
640             Action salAction = null;
641             List<Action> salActionList = new ArrayList<Action>();
642             if (actionsList == null) {
643                 salActionList.add(new Drop());
644             } else {
645                 for (OFAction ofAction : actionsList) {
646                     if (ofAction instanceof OFActionOutput) {
647                         short ofPort = ((OFActionOutput) ofAction).getPort();
648                         if (ofPort == OFPort.OFPP_CONTROLLER.getValue()) {
649                             salAction = new Controller();
650                         } else if (ofPort == OFPort.OFPP_NONE.getValue()) {
651                             salAction = new Drop();
652                         } else if (ofPort == OFPort.OFPP_IN_PORT.getValue()) {
653                             salAction = new Loopback();
654                         } else if (ofPort == OFPort.OFPP_FLOOD.getValue()) {
655                             salAction = new Flood();
656                         } else if (ofPort == OFPort.OFPP_ALL.getValue()) {
657                             salAction = new FloodAll();
658                         } else if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
659                             salAction = new SwPath();
660                         } else if (ofPort == OFPort.OFPP_NORMAL.getValue()) {
661                             salAction = new HwPath();
662                         } else if (ofPort == OFPort.OFPP_TABLE.getValue()) {
663                             salAction = new HwPath(); // TODO: we do not handle
664                                                       // table in sal for now
665                         } else {
666                             salAction = new Output(
667                                     NodeConnectorCreator.createOFNodeConnector(
668                                             ofPort, node));
669                         }
670                     } else if (ofAction instanceof OFActionVirtualLanIdentifier) {
671                         salAction = new SetVlanId(
672                                 ((OFActionVirtualLanIdentifier) ofAction)
673                                         .getVirtualLanIdentifier());
674                     } else if (ofAction instanceof OFActionStripVirtualLan) {
675                         salAction = new PopVlan();
676                     } else if (ofAction instanceof OFActionVirtualLanPriorityCodePoint) {
677                         salAction = new SetVlanPcp(
678                                 ((OFActionVirtualLanPriorityCodePoint) ofAction)
679                                         .getVirtualLanPriorityCodePoint());
680                     } else if (ofAction instanceof OFActionDataLayerSource) {
681                         salAction = new SetDlSrc(
682                                 ((OFActionDataLayerSource) ofAction)
683                                         .getDataLayerAddress().clone());
684                     } else if (ofAction instanceof OFActionDataLayerDestination) {
685                         salAction = new SetDlDst(
686                                 ((OFActionDataLayerDestination) ofAction)
687                                         .getDataLayerAddress().clone());
688                     } else if (ofAction instanceof OFActionNetworkLayerSource) {
689                         byte addr[] = BigInteger.valueOf(
690                                 ((OFActionNetworkLayerSource) ofAction)
691                                         .getNetworkAddress()).toByteArray();
692                         InetAddress ip = null;
693                         try {
694                             ip = InetAddress.getByAddress(addr);
695                         } catch (UnknownHostException e) {
696                             logger.error("", e);
697                         }
698                         salAction = new SetNwSrc(ip);
699                     } else if (ofAction instanceof OFActionNetworkLayerDestination) {
700                         byte addr[] = BigInteger.valueOf(
701                                 ((OFActionNetworkLayerDestination) ofAction)
702                                         .getNetworkAddress()).toByteArray();
703                         InetAddress ip = null;
704                         try {
705                             ip = InetAddress.getByAddress(addr);
706                         } catch (UnknownHostException e) {
707                             logger.error("", e);
708                         }
709                         salAction = new SetNwDst(ip);
710                     } else if (ofAction instanceof OFActionNetworkTypeOfService) {
711                         salAction = new SetNwTos(
712                                 ((OFActionNetworkTypeOfService) ofAction)
713                                         .getNetworkTypeOfService());
714                     } else if (ofAction instanceof OFActionTransportLayerSource) {
715                         Short port = ((OFActionTransportLayerSource) ofAction)
716                                 .getTransportPort();
717                         int intPort = NetUtils.getUnsignedShort(port);
718                         salAction = new SetTpSrc(intPort);
719                     } else if (ofAction instanceof OFActionTransportLayerDestination) {
720                         Short port = ((OFActionTransportLayerDestination) ofAction)
721                                 .getTransportPort();
722                         int intPort = NetUtils.getUnsignedShort(port);
723                         salAction = new SetTpDst(intPort);
724                     }
725                     salActionList.add(salAction);
726                 }
727             }
728             // Create Flow
729             flow = new Flow(salMatch, salActionList);
730         }
731         logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
732                 actionsList);
733         logger.trace("SAL Flow: {}", flow);
734         return flow;
735     }
736
737 }