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