2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.protocol_plugin.openflow.internal;
11 import java.math.BigInteger;
12 import java.net.InetAddress;
13 import java.net.UnknownHostException;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
19 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod;
20 import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match;
21 import org.opendaylight.controller.sal.action.Action;
22 import org.opendaylight.controller.sal.action.ActionType;
23 import org.opendaylight.controller.sal.action.Controller;
24 import org.opendaylight.controller.sal.action.Drop;
25 import org.opendaylight.controller.sal.action.Enqueue;
26 import org.opendaylight.controller.sal.action.Flood;
27 import org.opendaylight.controller.sal.action.FloodAll;
28 import org.opendaylight.controller.sal.action.HwPath;
29 import org.opendaylight.controller.sal.action.Loopback;
30 import org.opendaylight.controller.sal.action.Output;
31 import org.opendaylight.controller.sal.action.PopVlan;
32 import org.opendaylight.controller.sal.action.SetDlDst;
33 import org.opendaylight.controller.sal.action.SetDlSrc;
34 import org.opendaylight.controller.sal.action.SetNwDst;
35 import org.opendaylight.controller.sal.action.SetNwSrc;
36 import org.opendaylight.controller.sal.action.SetNwTos;
37 import org.opendaylight.controller.sal.action.SetTpDst;
38 import org.opendaylight.controller.sal.action.SetTpSrc;
39 import org.opendaylight.controller.sal.action.SetVlanId;
40 import org.opendaylight.controller.sal.action.SetVlanPcp;
41 import org.opendaylight.controller.sal.action.SwPath;
42 import org.opendaylight.controller.sal.core.Node;
43 import org.opendaylight.controller.sal.core.NodeConnector;
44 import org.opendaylight.controller.sal.flowprogrammer.Flow;
45 import org.opendaylight.controller.sal.match.Match;
46 import org.opendaylight.controller.sal.match.MatchField;
47 import org.opendaylight.controller.sal.match.MatchType;
48 import org.opendaylight.controller.sal.utils.NetUtils;
49 import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
50 import org.openflow.protocol.OFFlowMod;
51 import org.openflow.protocol.OFMatch;
52 import org.openflow.protocol.OFMessage;
53 import org.openflow.protocol.OFPacketOut;
54 import org.openflow.protocol.OFPort;
55 import org.openflow.protocol.OFVendor;
56 import org.openflow.protocol.action.OFAction;
57 import org.openflow.protocol.action.OFActionDataLayer;
58 import org.openflow.protocol.action.OFActionDataLayerDestination;
59 import org.openflow.protocol.action.OFActionDataLayerSource;
60 import org.openflow.protocol.action.OFActionNetworkLayerAddress;
61 import org.openflow.protocol.action.OFActionNetworkLayerDestination;
62 import org.openflow.protocol.action.OFActionNetworkLayerSource;
63 import org.openflow.protocol.action.OFActionNetworkTypeOfService;
64 import org.openflow.protocol.action.OFActionOutput;
65 import org.openflow.protocol.action.OFActionStripVirtualLan;
66 import org.openflow.protocol.action.OFActionTransportLayer;
67 import org.openflow.protocol.action.OFActionTransportLayerDestination;
68 import org.openflow.protocol.action.OFActionTransportLayerSource;
69 import org.openflow.protocol.action.OFActionVirtualLanIdentifier;
70 import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint;
71 import org.openflow.util.U16;
72 import org.openflow.util.U32;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
77 * Utility class for converting a SAL Flow into the OF flow and vice-versa
79 public class FlowConverter {
80 protected static final Logger logger = LoggerFactory
81 .getLogger(FlowConverter.class);
84 * The value 0xffff (OFP_VLAN_NONE) is used to indicate
85 * that no VLAN ID is set for OF Flow.
87 private static final short OFP_VLAN_NONE = (short) 0xffff;
89 private Flow flow; // SAL Flow
90 private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match
91 private List<OFAction> actionsList; // OF 1.0 actions
92 private int actionsLength;
93 private boolean isIPv6;
95 public FlowConverter(OFMatch ofMatch, List<OFAction> actionsList) {
96 this.ofMatch = ofMatch;
97 this.actionsList = actionsList;
98 this.actionsLength = 0;
100 this.isIPv6 = ofMatch instanceof V6Match;
103 public FlowConverter(Flow flow) {
105 this.actionsList = null;
106 this.actionsLength = 0;
108 this.isIPv6 = flow.isIPv6();
112 * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions
117 public OFMatch getOFMatch() {
118 if (ofMatch == null) {
119 Match match = flow.getMatch();
120 ofMatch = (isIPv6) ? new V6Match() : new OFMatch();
122 int wildcards = OFMatch.OFPFW_ALL;
123 if (match.isPresent(MatchType.IN_PORT)) {
124 short port = (Short) ((NodeConnector) match.getField(
125 MatchType.IN_PORT).getValue()).getID();
127 ofMatch.setInputPort(port);
128 wildcards &= ~OFMatch.OFPFW_IN_PORT;
130 ((V6Match) ofMatch).setInputPort(port, (short) 0);
133 if (match.isPresent(MatchType.DL_SRC)) {
134 byte[] srcMac = (byte[]) match.getField(MatchType.DL_SRC)
137 ofMatch.setDataLayerSource(srcMac.clone());
138 wildcards &= ~OFMatch.OFPFW_DL_SRC;
140 ((V6Match) ofMatch).setDataLayerSource(srcMac, null);
143 if (match.isPresent(MatchType.DL_DST)) {
144 byte[] dstMac = (byte[]) match.getField(MatchType.DL_DST)
147 ofMatch.setDataLayerDestination(dstMac.clone());
148 wildcards &= ~OFMatch.OFPFW_DL_DST;
150 ((V6Match) ofMatch).setDataLayerDestination(dstMac, null);
153 if (match.isPresent(MatchType.DL_VLAN)) {
154 short vlan = (Short) match.getField(MatchType.DL_VLAN)
156 if (vlan == MatchType.DL_VLAN_NONE) {
157 vlan = OFP_VLAN_NONE;
160 ofMatch.setDataLayerVirtualLan(vlan);
161 wildcards &= ~OFMatch.OFPFW_DL_VLAN;
163 ((V6Match) ofMatch).setDataLayerVirtualLan(vlan, (short) 0);
166 if (match.isPresent(MatchType.DL_VLAN_PR)) {
167 byte vlanPr = (Byte) match.getField(MatchType.DL_VLAN_PR)
170 ofMatch.setDataLayerVirtualLanPriorityCodePoint(vlanPr);
171 wildcards &= ~OFMatch.OFPFW_DL_VLAN_PCP;
174 .setDataLayerVirtualLanPriorityCodePoint(vlanPr,
178 if (match.isPresent(MatchType.DL_TYPE)) {
179 short ethType = (Short) match.getField(MatchType.DL_TYPE)
182 ofMatch.setDataLayerType(ethType);
183 wildcards &= ~OFMatch.OFPFW_DL_TYPE;
185 ((V6Match) ofMatch).setDataLayerType(ethType, (short) 0);
188 if (match.isPresent(MatchType.NW_TOS)) {
190 * OF 1.0 switch expects the TOS as the 6 msb in the byte. it is
191 * actually the DSCP field followed by a zero ECN
193 byte tos = (Byte) match.getField(MatchType.NW_TOS).getValue();
194 byte dscp = (byte) (tos << 2);
196 ofMatch.setNetworkTypeOfService(dscp);
197 wildcards &= ~OFMatch.OFPFW_NW_TOS;
199 ((V6Match) ofMatch).setNetworkTypeOfService(dscp, (byte) 0);
202 if (match.isPresent(MatchType.NW_PROTO)) {
203 byte proto = (Byte) match.getField(MatchType.NW_PROTO)
206 ofMatch.setNetworkProtocol(proto);
207 wildcards &= ~OFMatch.OFPFW_NW_PROTO;
209 ((V6Match) ofMatch).setNetworkProtocol(proto, (byte) 0);
212 if (match.isPresent(MatchType.NW_SRC)) {
213 InetAddress address = (InetAddress) match.getField(MatchType.NW_SRC).getValue();
214 InetAddress mask = (InetAddress) match.getField(MatchType.NW_SRC).getMask();
216 ofMatch.setNetworkSource(NetUtils.byteArray4ToInt(address.getAddress()));
217 int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
218 wildcards = (wildcards & ~OFMatch.OFPFW_NW_SRC_MASK) | ((32 - maskLength) << OFMatch.OFPFW_NW_SRC_SHIFT);
220 ((V6Match) ofMatch).setNetworkSource(address, mask);
223 if (match.isPresent(MatchType.NW_DST)) {
224 InetAddress address = (InetAddress) match.getField(MatchType.NW_DST).getValue();
225 InetAddress mask = (InetAddress) match.getField(MatchType.NW_DST).getMask();
227 ofMatch.setNetworkDestination(NetUtils.byteArray4ToInt(address.getAddress()));
228 int maskLength = (mask == null) ? 32 : NetUtils.getSubnetMaskLength(mask);
229 wildcards = (wildcards & ~OFMatch.OFPFW_NW_DST_MASK) | ((32 - maskLength) << OFMatch.OFPFW_NW_DST_SHIFT);
231 ((V6Match) ofMatch).setNetworkDestination(address, mask);
234 if (match.isPresent(MatchType.TP_SRC)) {
235 short port = (Short) match.getField(MatchType.TP_SRC)
238 ofMatch.setTransportSource(port);
239 wildcards &= ~OFMatch.OFPFW_TP_SRC;
241 ((V6Match) ofMatch).setTransportSource(port, (short) 0);
244 if (match.isPresent(MatchType.TP_DST)) {
245 short port = (Short) match.getField(MatchType.TP_DST)
248 ofMatch.setTransportDestination(port);
249 wildcards &= ~OFMatch.OFPFW_TP_DST;
252 .setTransportDestination(port, (short) 0);
257 ofMatch.setWildcards(U32.t(Long.valueOf(wildcards)));
260 logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(),
266 * Returns the list of actions in OF 1.0 form
270 public List<OFAction> getOFActions() {
271 if (this.actionsList == null) {
272 actionsList = new ArrayList<OFAction>();
273 for (Action action : flow.getActions()) {
274 if (action.getType() == ActionType.OUTPUT) {
275 Output a = (Output) action;
276 OFActionOutput ofAction = new OFActionOutput();
277 ofAction.setMaxLength((short) 0xffff);
278 ofAction.setPort(PortConverter.toOFPort(a.getPort()));
279 actionsList.add(ofAction);
280 actionsLength += OFActionOutput.MINIMUM_LENGTH;
283 if (action.getType() == ActionType.DROP) {
286 if (action.getType() == ActionType.LOOPBACK) {
287 OFActionOutput ofAction = new OFActionOutput();
288 ofAction.setPort(OFPort.OFPP_IN_PORT.getValue());
289 actionsList.add(ofAction);
290 actionsLength += OFActionOutput.MINIMUM_LENGTH;
293 if (action.getType() == ActionType.FLOOD) {
294 OFActionOutput ofAction = new OFActionOutput();
295 ofAction.setPort(OFPort.OFPP_FLOOD.getValue());
296 actionsList.add(ofAction);
297 actionsLength += OFActionOutput.MINIMUM_LENGTH;
300 if (action.getType() == ActionType.FLOOD_ALL) {
301 OFActionOutput ofAction = new OFActionOutput();
302 ofAction.setPort(OFPort.OFPP_ALL.getValue());
303 actionsList.add(ofAction);
304 actionsLength += OFActionOutput.MINIMUM_LENGTH;
307 if (action.getType() == ActionType.CONTROLLER) {
308 OFActionOutput ofAction = new OFActionOutput();
309 ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue());
310 // We want the whole frame hitting the match be sent to the
312 ofAction.setMaxLength((short) 0xffff);
313 actionsList.add(ofAction);
314 actionsLength += OFActionOutput.MINIMUM_LENGTH;
317 if (action.getType() == ActionType.SW_PATH) {
318 OFActionOutput ofAction = new OFActionOutput();
319 ofAction.setPort(OFPort.OFPP_LOCAL.getValue());
320 actionsList.add(ofAction);
321 actionsLength += OFActionOutput.MINIMUM_LENGTH;
324 if (action.getType() == ActionType.HW_PATH) {
325 OFActionOutput ofAction = new OFActionOutput();
326 ofAction.setPort(OFPort.OFPP_NORMAL.getValue());
327 actionsList.add(ofAction);
328 actionsLength += OFActionOutput.MINIMUM_LENGTH;
331 if (action.getType() == ActionType.SET_VLAN_ID) {
332 SetVlanId a = (SetVlanId) action;
333 OFActionVirtualLanIdentifier ofAction = new OFActionVirtualLanIdentifier();
334 ofAction.setVirtualLanIdentifier((short) a.getVlanId());
335 actionsList.add(ofAction);
336 actionsLength += OFActionVirtualLanIdentifier.MINIMUM_LENGTH;
339 if (action.getType() == ActionType.SET_VLAN_PCP) {
340 SetVlanPcp a = (SetVlanPcp) action;
341 OFActionVirtualLanPriorityCodePoint ofAction = new OFActionVirtualLanPriorityCodePoint();
342 ofAction.setVirtualLanPriorityCodePoint(Integer.valueOf(
343 a.getPcp()).byteValue());
344 actionsList.add(ofAction);
345 actionsLength += OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH;
348 if (action.getType() == ActionType.POP_VLAN) {
349 OFActionStripVirtualLan ofAction = new OFActionStripVirtualLan();
350 actionsList.add(ofAction);
351 actionsLength += OFActionStripVirtualLan.MINIMUM_LENGTH;
354 if (action.getType() == ActionType.SET_DL_SRC) {
355 SetDlSrc a = (SetDlSrc) action;
356 OFActionDataLayerSource ofAction = new OFActionDataLayerSource();
357 ofAction.setDataLayerAddress(a.getDlAddress());
358 actionsList.add(ofAction);
359 actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
362 if (action.getType() == ActionType.SET_DL_DST) {
363 SetDlDst a = (SetDlDst) action;
364 OFActionDataLayerDestination ofAction = new OFActionDataLayerDestination();
365 ofAction.setDataLayerAddress(a.getDlAddress());
366 actionsList.add(ofAction);
367 actionsLength += OFActionDataLayer.MINIMUM_LENGTH;
370 if (action.getType() == ActionType.SET_NW_SRC) {
371 SetNwSrc a = (SetNwSrc) action;
372 OFActionNetworkLayerSource ofAction = new OFActionNetworkLayerSource();
373 ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
374 .getAddress().getAddress()));
375 actionsList.add(ofAction);
376 actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
379 if (action.getType() == ActionType.SET_NW_DST) {
380 SetNwDst a = (SetNwDst) action;
381 OFActionNetworkLayerDestination ofAction = new OFActionNetworkLayerDestination();
382 ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a
383 .getAddress().getAddress()));
384 actionsList.add(ofAction);
385 actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH;
388 if (action.getType() == ActionType.SET_NW_TOS) {
389 SetNwTos a = (SetNwTos) action;
390 OFActionNetworkTypeOfService ofAction = new OFActionNetworkTypeOfService();
391 ofAction.setNetworkTypeOfService(Integer.valueOf(
392 a.getNwTos()).byteValue());
393 actionsList.add(ofAction);
394 actionsLength += OFActionNetworkTypeOfService.MINIMUM_LENGTH;
397 if (action.getType() == ActionType.SET_TP_SRC) {
398 SetTpSrc a = (SetTpSrc) action;
399 OFActionTransportLayerSource ofAction = new OFActionTransportLayerSource();
400 ofAction.setTransportPort(Integer.valueOf(a.getPort())
402 actionsList.add(ofAction);
403 actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
406 if (action.getType() == ActionType.SET_TP_DST) {
407 SetTpDst a = (SetTpDst) action;
408 OFActionTransportLayerDestination ofAction = new OFActionTransportLayerDestination();
409 ofAction.setTransportPort(Integer.valueOf(a.getPort())
411 actionsList.add(ofAction);
412 actionsLength += OFActionTransportLayer.MINIMUM_LENGTH;
415 if (action.getType() == ActionType.SET_NEXT_HOP) {
416 logger.info("Unsupported action: {}", action);
421 logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(),
427 * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 +
428 * IPv6 extension (V6FlowMod) Flow modifier Message
435 public OFMessage getOFFlowMod(short command, OFPort port) {
436 OFMessage fm = (isIPv6) ? new V6FlowMod() : new OFFlowMod();
437 if (this.ofMatch == null) {
440 if (this.actionsList == null) {
444 ((OFFlowMod) fm).setMatch(this.ofMatch);
445 ((OFFlowMod) fm).setActions(this.actionsList);
446 ((OFFlowMod) fm).setPriority(flow.getPriority());
447 ((OFFlowMod) fm).setCookie(flow.getId());
448 ((OFFlowMod) fm).setBufferId(OFPacketOut.BUFFER_ID_NONE);
449 ((OFFlowMod) fm).setLength(U16.t(OFFlowMod.MINIMUM_LENGTH
451 ((OFFlowMod) fm).setIdleTimeout(flow.getIdleTimeout());
452 ((OFFlowMod) fm).setHardTimeout(flow.getHardTimeout());
453 ((OFFlowMod) fm).setCommand(command);
455 ((OFFlowMod) fm).setOutPort(port);
457 if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY
458 || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
459 // Instruct switch to let controller know when flow is removed
460 ((OFFlowMod) fm).setFlags((short) 1);
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);
476 ((V6FlowMod) fm).setOutPort(port);
478 if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY
479 || command == OFFlowMod.OFPFC_MODIFY_STRICT) {
480 // Instruct switch to let controller know when flow is removed
481 ((V6FlowMod) fm).setFlags((short) 1);
484 logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
486 logger.trace("Openflow Mod Message: {}", fm);
490 public Flow getFlow(Node node) {
491 if (this.flow == null) {
492 Match salMatch = new Match();
495 * Installed flow may not have a Match defined like in case of a
498 if (ofMatch != null) {
500 // Compute OF1.0 Match
501 if (ofMatch.getInputPort() != 0 && ofMatch.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
502 salMatch.setField(new MatchField(MatchType.IN_PORT,
503 NodeConnectorCreator.createNodeConnector(
504 ofMatch.getInputPort(), node)));
506 if (ofMatch.getDataLayerSource() != null
508 .isZeroMAC(ofMatch.getDataLayerSource())) {
509 byte srcMac[] = ofMatch.getDataLayerSource();
510 salMatch.setField(new MatchField(MatchType.DL_SRC,
513 if (ofMatch.getDataLayerDestination() != null
514 && !NetUtils.isZeroMAC(ofMatch
515 .getDataLayerDestination())) {
516 byte dstMac[] = ofMatch.getDataLayerDestination();
517 salMatch.setField(new MatchField(MatchType.DL_DST,
520 if (ofMatch.getDataLayerType() != 0) {
521 salMatch.setField(new MatchField(MatchType.DL_TYPE,
522 ofMatch.getDataLayerType()));
524 short vlan = ofMatch.getDataLayerVirtualLan();
526 if (vlan == OFP_VLAN_NONE) {
527 vlan = MatchType.DL_VLAN_NONE;
529 salMatch.setField(new MatchField(MatchType.DL_VLAN,
532 if (ofMatch.getDataLayerVirtualLanPriorityCodePoint() != 0) {
533 salMatch.setField(MatchType.DL_VLAN_PR, ofMatch
534 .getDataLayerVirtualLanPriorityCodePoint());
536 if (ofMatch.getNetworkSource() != 0) {
537 salMatch.setField(MatchType.NW_SRC, NetUtils
538 .getInetAddress(ofMatch.getNetworkSource()),
539 NetUtils.getInetNetworkMask(
540 ofMatch.getNetworkSourceMaskLen(),
543 if (ofMatch.getNetworkDestination() != 0) {
544 salMatch.setField(MatchType.NW_DST,
545 NetUtils.getInetAddress(ofMatch
546 .getNetworkDestination()),
547 NetUtils.getInetNetworkMask(
548 ofMatch.getNetworkDestinationMaskLen(),
551 if (ofMatch.getNetworkTypeOfService() != 0) {
552 int dscp = NetUtils.getUnsignedByte(ofMatch
553 .getNetworkTypeOfService());
554 byte tos = (byte) (dscp >> 2);
555 salMatch.setField(MatchType.NW_TOS, tos);
557 //TODO: NW protocol 0 is a valid protocol
558 if (ofMatch.getNetworkProtocol() != 0) {
559 salMatch.setField(MatchType.NW_PROTO,
560 ofMatch.getNetworkProtocol());
562 if (ofMatch.getTransportSource() != 0) {
563 salMatch.setField(MatchType.TP_SRC,
564 ofMatch.getTransportSource());
566 if (ofMatch.getTransportDestination() != 0) {
567 salMatch.setField(MatchType.TP_DST,
568 ofMatch.getTransportDestination());
571 // Compute OF1.0 + IPv6 extensions Match
572 V6Match v6Match = (V6Match) ofMatch;
573 if (v6Match.getInputPort() != 0 && v6Match.getInputPort() != OFPort.OFPP_LOCAL.getValue()) {
574 // Mask on input port is not defined
575 salMatch.setField(new MatchField(MatchType.IN_PORT,
576 NodeConnectorCreator.createOFNodeConnector(
577 v6Match.getInputPort(), node)));
579 if (v6Match.getDataLayerSource() != null
581 .isZeroMAC(ofMatch.getDataLayerSource())) {
582 byte srcMac[] = v6Match.getDataLayerSource();
583 salMatch.setField(new MatchField(MatchType.DL_SRC,
586 if (v6Match.getDataLayerDestination() != null
587 && !NetUtils.isZeroMAC(ofMatch
588 .getDataLayerDestination())) {
589 byte dstMac[] = v6Match.getDataLayerDestination();
590 salMatch.setField(new MatchField(MatchType.DL_DST,
593 if (v6Match.getDataLayerType() != 0) {
594 salMatch.setField(new MatchField(MatchType.DL_TYPE,
595 v6Match.getDataLayerType()));
597 short vlan = v6Match.getDataLayerVirtualLan();
599 if (vlan == OFP_VLAN_NONE) {
600 vlan = MatchType.DL_VLAN_NONE;
602 salMatch.setField(new MatchField(MatchType.DL_VLAN,
605 if (v6Match.getDataLayerVirtualLanPriorityCodePoint() != 0) {
606 salMatch.setField(MatchType.DL_VLAN_PR, v6Match
607 .getDataLayerVirtualLanPriorityCodePoint());
609 // V6Match may carry IPv4 address
610 if (v6Match.getNetworkSrc() != null) {
611 salMatch.setField(MatchType.NW_SRC,
612 v6Match.getNetworkSrc(),
613 v6Match.getNetworkSourceMask());
614 } else if (v6Match.getNetworkSource() != 0) {
615 salMatch.setField(MatchType.NW_SRC, NetUtils
616 .getInetAddress(v6Match.getNetworkSource()),
617 NetUtils.getInetNetworkMask(
618 v6Match.getNetworkSourceMaskLen(),
621 // V6Match may carry IPv4 address
622 if (v6Match.getNetworkDest() != null) {
623 salMatch.setField(MatchType.NW_DST,
624 v6Match.getNetworkDest(),
625 v6Match.getNetworkDestinationMask());
626 } else if (v6Match.getNetworkDestination() != 0) {
627 salMatch.setField(MatchType.NW_DST,
628 NetUtils.getInetAddress(v6Match
629 .getNetworkDestination()),
630 NetUtils.getInetNetworkMask(
631 v6Match.getNetworkDestinationMaskLen(),
634 if (v6Match.getNetworkTypeOfService() != 0) {
635 int dscp = NetUtils.getUnsignedByte(v6Match
636 .getNetworkTypeOfService());
637 byte tos = (byte) (dscp >> 2);
638 salMatch.setField(MatchType.NW_TOS, tos);
640 if (v6Match.getNetworkProtocol() != 0) {
641 salMatch.setField(MatchType.NW_PROTO,
642 v6Match.getNetworkProtocol());
644 if (v6Match.getTransportSource() != 0) {
645 salMatch.setField(MatchType.TP_SRC,
646 (v6Match.getTransportSource()));
648 if (v6Match.getTransportDestination() != 0) {
649 salMatch.setField(MatchType.TP_DST,
650 (v6Match.getTransportDestination()));
656 Action salAction = null;
657 List<Action> salActionList = new ArrayList<Action>();
658 if (actionsList == null) {
659 salActionList.add(new Drop());
661 for (OFAction ofAction : actionsList) {
662 if (ofAction instanceof OFActionOutput) {
663 short ofPort = ((OFActionOutput) ofAction).getPort();
664 if (ofPort == OFPort.OFPP_CONTROLLER.getValue()) {
665 salAction = new Controller();
666 } else if (ofPort == OFPort.OFPP_NONE.getValue()) {
667 salAction = new Drop();
668 } else if (ofPort == OFPort.OFPP_IN_PORT.getValue()) {
669 salAction = new Loopback();
670 } else if (ofPort == OFPort.OFPP_FLOOD.getValue()) {
671 salAction = new Flood();
672 } else if (ofPort == OFPort.OFPP_ALL.getValue()) {
673 salAction = new FloodAll();
674 } else if (ofPort == OFPort.OFPP_LOCAL.getValue()) {
675 salAction = new SwPath();
676 } else if (ofPort == OFPort.OFPP_NORMAL.getValue()) {
677 salAction = new HwPath();
678 } else if (ofPort == OFPort.OFPP_TABLE.getValue()) {
679 salAction = new HwPath(); // TODO: we do not handle
680 // table in sal for now
682 salAction = new Output(
683 NodeConnectorCreator.createOFNodeConnector(
686 } else if (ofAction instanceof OFActionVirtualLanIdentifier) {
687 salAction = new SetVlanId(
688 ((OFActionVirtualLanIdentifier) ofAction)
689 .getVirtualLanIdentifier());
690 } else if (ofAction instanceof OFActionStripVirtualLan) {
691 salAction = new PopVlan();
692 } else if (ofAction instanceof OFActionVirtualLanPriorityCodePoint) {
693 salAction = new SetVlanPcp(
694 ((OFActionVirtualLanPriorityCodePoint) ofAction)
695 .getVirtualLanPriorityCodePoint());
696 } else if (ofAction instanceof OFActionDataLayerSource) {
697 salAction = new SetDlSrc(
698 ((OFActionDataLayerSource) ofAction)
699 .getDataLayerAddress().clone());
700 } else if (ofAction instanceof OFActionDataLayerDestination) {
701 salAction = new SetDlDst(
702 ((OFActionDataLayerDestination) ofAction)
703 .getDataLayerAddress().clone());
704 } else if (ofAction instanceof OFActionNetworkLayerSource) {
705 byte addr[] = BigInteger.valueOf(
706 ((OFActionNetworkLayerSource) ofAction)
707 .getNetworkAddress()).toByteArray();
708 InetAddress ip = null;
710 ip = InetAddress.getByAddress(addr);
711 } catch (UnknownHostException e) {
714 salAction = new SetNwSrc(ip);
715 } else if (ofAction instanceof OFActionNetworkLayerDestination) {
716 byte addr[] = BigInteger.valueOf(
717 ((OFActionNetworkLayerDestination) ofAction)
718 .getNetworkAddress()).toByteArray();
719 InetAddress ip = null;
721 ip = InetAddress.getByAddress(addr);
722 } catch (UnknownHostException e) {
725 salAction = new SetNwDst(ip);
726 } else if (ofAction instanceof OFActionNetworkTypeOfService) {
727 salAction = new SetNwTos(
728 ((OFActionNetworkTypeOfService) ofAction)
729 .getNetworkTypeOfService());
730 } else if (ofAction instanceof OFActionTransportLayerSource) {
731 Short port = ((OFActionTransportLayerSource) ofAction)
733 int intPort = NetUtils.getUnsignedShort(port);
734 salAction = new SetTpSrc(intPort);
735 } else if (ofAction instanceof OFActionTransportLayerDestination) {
736 Short port = ((OFActionTransportLayerDestination) ofAction)
738 int intPort = NetUtils.getUnsignedShort(port);
739 salAction = new SetTpDst(intPort);
741 salActionList.add(salAction);
745 flow = new Flow(salMatch, salActionList);
747 logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch,
749 logger.trace("SAL Flow: {}", flow);
753 private static final Map<Integer, Class<? extends Action>> actionMap = new HashMap<Integer, Class<? extends Action>>() {
754 private static final long serialVersionUID = 1L;
756 put(1 << 0, Output.class);
757 put(1 << 1, SetVlanId.class);
758 put(1 << 2, SetVlanPcp.class);
759 put(1 << 3, PopVlan.class);
760 put(1 << 4, SetDlSrc.class);
761 put(1 << 5, SetDlDst.class);
762 put(1 << 6, SetNwSrc.class);
763 put(1 << 7, SetNwDst.class);
764 put(1 << 8, SetNwTos.class);
765 put(1 << 9, SetTpSrc.class);
766 put(1 << 10, SetTpDst.class);
767 put(1 << 11, Enqueue.class);
772 * Returns the supported flow actions for the netwrok node given the bitmask
773 * representing the actions the Openflow 1.0 switch supports
775 * @param ofActionBitmask
776 * OF 1.0 action bitmask
777 * @return The correspondent list of SAL Action classes
779 public static List<Class<? extends Action>> getFlowActions(int ofActionBitmask) {
780 List<Class<? extends Action>> list = new ArrayList<Class<? extends Action>>();
782 for (int i = 0; i < Integer.SIZE; i++) {
784 if ((index & ofActionBitmask) > 0) {
785 if (actionMap.containsKey(index)) {
786 list.add(actionMap.get(index));
790 // Add implicit SAL actions
791 list.add(Controller.class);
792 list.add(SwPath.class);
793 list.add(HwPath.class);
794 list.add(Drop.class);