/* * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.controller.protocol_plugin.openflow.internal; import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match; import org.opendaylight.controller.sal.action.Action; import org.opendaylight.controller.sal.action.ActionType; import org.opendaylight.controller.sal.action.Controller; import org.opendaylight.controller.sal.action.Drop; import org.opendaylight.controller.sal.action.Flood; import org.opendaylight.controller.sal.action.FloodAll; import org.opendaylight.controller.sal.action.HwPath; import org.opendaylight.controller.sal.action.Loopback; import org.opendaylight.controller.sal.action.Output; import org.opendaylight.controller.sal.action.PopVlan; import org.opendaylight.controller.sal.action.SetDlDst; import org.opendaylight.controller.sal.action.SetDlSrc; import org.opendaylight.controller.sal.action.SetNwDst; import org.opendaylight.controller.sal.action.SetNwSrc; import org.opendaylight.controller.sal.action.SetNwTos; import org.opendaylight.controller.sal.action.SetTpDst; import org.opendaylight.controller.sal.action.SetTpSrc; import org.opendaylight.controller.sal.action.SetVlanId; import org.opendaylight.controller.sal.action.SetVlanPcp; import org.opendaylight.controller.sal.action.SwPath; import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.flowprogrammer.Flow; import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.match.MatchField; import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.NetUtils; import org.opendaylight.controller.sal.utils.NodeConnectorCreator; import org.openflow.protocol.OFFlowMod; import org.openflow.protocol.OFMatch; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketOut; import org.openflow.protocol.OFPort; import org.openflow.protocol.OFVendor; import org.openflow.protocol.action.OFAction; import org.openflow.protocol.action.OFActionDataLayerDestination; import org.openflow.protocol.action.OFActionDataLayerSource; import org.openflow.protocol.action.OFActionNetworkLayerAddress; import org.openflow.protocol.action.OFActionNetworkLayerDestination; import org.openflow.protocol.action.OFActionNetworkLayerSource; import org.openflow.protocol.action.OFActionNetworkTypeOfService; import org.openflow.protocol.action.OFActionOutput; import org.openflow.protocol.action.OFActionStripVirtualLan; import org.openflow.protocol.action.OFActionTransportLayer; import org.openflow.protocol.action.OFActionTransportLayerDestination; import org.openflow.protocol.action.OFActionTransportLayerSource; import org.openflow.protocol.action.OFActionVirtualLanIdentifier; import org.openflow.protocol.action.OFActionVirtualLanPriorityCodePoint; import org.openflow.util.U16; import org.openflow.util.U32; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility class for converting a SAL Flow into the OF flow and vice-versa */ public class FlowConverter { protected static final Logger logger = LoggerFactory .getLogger(FlowConverter.class); private Flow flow; // SAL Flow private OFMatch ofMatch; // OF 1.0 match or OF 1.0 + IPv6 extension match private List actionsList; // OF 1.0 actions private int actionsLength; private boolean isIPv6; public FlowConverter(OFMatch ofMatch, List actionsList) { this.ofMatch = ofMatch; this.actionsList = actionsList; this.actionsLength = 0; this.flow = null; this.isIPv6 = ofMatch instanceof V6Match; } public FlowConverter(Flow flow) { this.ofMatch = null; this.actionsList = null; this.actionsLength = 0; this.flow = flow; this.isIPv6 = flow.isIPv6(); } /** * Returns the match in OF 1.0 (OFMatch) form or OF 1.0 + IPv6 extensions * form (V6Match) * * @return */ public OFMatch getOFMatch() { if (ofMatch == null) { Match match = flow.getMatch(); ofMatch = (isIPv6) ? new V6Match() : new OFMatch(); int wildcards = OFMatch.OFPFW_ALL; if (match.isPresent(MatchType.IN_PORT)) { short port = (Short) ((NodeConnector) match.getField( MatchType.IN_PORT).getValue()).getID(); if (!isIPv6) { ofMatch.setInputPort(port); wildcards &= ~OFMatch.OFPFW_IN_PORT; } else { ((V6Match) ofMatch).setInputPort(port, (short) 0); } } if (match.isPresent(MatchType.DL_SRC)) { byte[] srcMac = (byte[]) match.getField(MatchType.DL_SRC) .getValue(); if (!isIPv6) { ofMatch.setDataLayerSource(srcMac.clone()); wildcards &= ~OFMatch.OFPFW_DL_SRC; } else { ((V6Match) ofMatch).setDataLayerSource(srcMac, null); } } if (match.isPresent(MatchType.DL_DST)) { byte[] dstMac = (byte[]) match.getField(MatchType.DL_DST) .getValue(); if (!isIPv6) { ofMatch.setDataLayerDestination(dstMac.clone()); wildcards &= ~OFMatch.OFPFW_DL_DST; } else { ((V6Match) ofMatch).setDataLayerDestination(dstMac, null); } } if (match.isPresent(MatchType.DL_VLAN)) { short vlan = (Short) match.getField(MatchType.DL_VLAN) .getValue(); if (!isIPv6) { ofMatch.setDataLayerVirtualLan(vlan); wildcards &= ~OFMatch.OFPFW_DL_VLAN; } else { ((V6Match) ofMatch).setDataLayerVirtualLan(vlan, (short) 0); } } if (match.isPresent(MatchType.DL_VLAN_PR)) { byte vlanPr = (Byte) match.getField(MatchType.DL_VLAN_PR) .getValue(); if (!isIPv6) { ofMatch.setDataLayerVirtualLanPriorityCodePoint(vlanPr); wildcards &= ~OFMatch.OFPFW_DL_VLAN_PCP; } else { ((V6Match) ofMatch) .setDataLayerVirtualLanPriorityCodePoint(vlanPr, (byte) 0); } } if (match.isPresent(MatchType.DL_TYPE)) { short ethType = (Short) match.getField(MatchType.DL_TYPE) .getValue(); if (!isIPv6) { ofMatch.setDataLayerType(ethType); wildcards &= ~OFMatch.OFPFW_DL_TYPE; } else { ((V6Match) ofMatch).setDataLayerType(ethType, (short) 0); } } if (match.isPresent(MatchType.NW_TOS)) { /* * OF 1.0 switch expects the TOS as the 6 msb in the byte. it is * actually the DSCP field followed by a zero ECN */ byte tos = (Byte) match.getField(MatchType.NW_TOS).getValue(); byte dscp = (byte) ((int) tos << 2); if (!isIPv6) { ofMatch.setNetworkTypeOfService(dscp); wildcards &= ~OFMatch.OFPFW_NW_TOS; } else { ((V6Match) ofMatch).setNetworkTypeOfService(dscp, (byte) 0); } } if (match.isPresent(MatchType.NW_PROTO)) { byte proto = (Byte) match.getField(MatchType.NW_PROTO) .getValue(); if (!isIPv6) { ofMatch.setNetworkProtocol(proto); wildcards &= ~OFMatch.OFPFW_NW_PROTO; } else { ((V6Match) ofMatch).setNetworkProtocol(proto, (byte) 0); } } if (match.isPresent(MatchType.NW_SRC)) { InetAddress address = (InetAddress) match.getField( MatchType.NW_SRC).getValue(); InetAddress mask = (InetAddress) match.getField( MatchType.NW_SRC).getMask(); if (!isIPv6) { ofMatch.setNetworkSource(NetUtils.byteArray4ToInt(address .getAddress())); int maskLength = NetUtils .getSubnetMaskLength((mask == null) ? null : mask .getAddress()); wildcards = (wildcards & ~OFMatch.OFPFW_NW_SRC_MASK) | (maskLength << OFMatch.OFPFW_NW_SRC_SHIFT); } else { ((V6Match) ofMatch).setNetworkSource(address, mask); } } if (match.isPresent(MatchType.NW_DST)) { InetAddress address = (InetAddress) match.getField( MatchType.NW_DST).getValue(); InetAddress mask = (InetAddress) match.getField( MatchType.NW_DST).getMask(); if (!isIPv6) { ofMatch.setNetworkDestination(NetUtils .byteArray4ToInt(address.getAddress())); int maskLength = NetUtils .getSubnetMaskLength((mask == null) ? null : mask .getAddress()); wildcards = (wildcards & ~OFMatch.OFPFW_NW_DST_MASK) | (maskLength << OFMatch.OFPFW_NW_DST_SHIFT); } else { ((V6Match) ofMatch).setNetworkDestination(address, mask); } } if (match.isPresent(MatchType.TP_SRC)) { short port = (Short) match.getField(MatchType.TP_SRC) .getValue(); if (!isIPv6) { ofMatch.setTransportSource(port); wildcards &= ~OFMatch.OFPFW_TP_SRC; } else { ((V6Match) ofMatch).setTransportSource(port, (short) 0); } } if (match.isPresent(MatchType.TP_DST)) { short port = (Short) match.getField(MatchType.TP_DST) .getValue(); if (!isIPv6) { ofMatch.setTransportDestination(port); wildcards &= ~OFMatch.OFPFW_TP_DST; } else { ((V6Match) ofMatch) .setTransportDestination(port, (short) 0); } } if (!isIPv6) { ofMatch.setWildcards(U32.t(Long.valueOf(wildcards))); } } logger.trace("SAL Match: {} Openflow Match: {}", flow.getMatch(), ofMatch); return ofMatch; } /** * Returns the list of actions in OF 1.0 form * * @return */ public List getOFActions() { if (this.actionsList == null) { actionsList = new ArrayList(); for (Action action : flow.getActions()) { if (action.getType() == ActionType.OUTPUT) { Output a = (Output) action; OFActionOutput ofAction = new OFActionOutput(); ofAction.setMaxLength((short) 0xffff); ofAction.setPort(PortConverter.toOFPort(a.getPort())); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.DROP) { continue; } if (action.getType() == ActionType.LOOPBACK) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_IN_PORT.getValue()); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.FLOOD) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_FLOOD.getValue()); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.FLOOD_ALL) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_ALL.getValue()); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.CONTROLLER) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_CONTROLLER.getValue()); // We want the whole frame hitting the match be sent to the // controller ofAction.setMaxLength((short) 0xffff); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SW_PATH) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_LOCAL.getValue()); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.HW_PATH) { OFActionOutput ofAction = new OFActionOutput(); ofAction.setPort(OFPort.OFPP_NORMAL.getValue()); actionsList.add(ofAction); actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_VLAN_ID) { SetVlanId a = (SetVlanId) action; OFActionVirtualLanIdentifier ofAction = new OFActionVirtualLanIdentifier(); ofAction.setVirtualLanIdentifier((short) a.getVlanId()); actionsList.add(ofAction); actionsLength += OFActionVirtualLanIdentifier.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_VLAN_PCP) { SetVlanPcp a = (SetVlanPcp) action; OFActionVirtualLanPriorityCodePoint ofAction = new OFActionVirtualLanPriorityCodePoint(); ofAction.setVirtualLanPriorityCodePoint(Integer.valueOf( a.getPcp()).byteValue()); actionsList.add(ofAction); actionsLength += OFActionVirtualLanPriorityCodePoint.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.POP_VLAN) { OFActionStripVirtualLan ofAction = new OFActionStripVirtualLan(); actionsList.add(ofAction); actionsLength += OFActionStripVirtualLan.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_DL_SRC) { SetDlSrc a = (SetDlSrc) action; OFActionDataLayerSource ofAction = new OFActionDataLayerSource(); ofAction.setDataLayerAddress(a.getDlAddress()); actionsList.add(ofAction); actionsLength += OFActionDataLayerSource.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_DL_DST) { SetDlDst a = (SetDlDst) action; OFActionDataLayerDestination ofAction = new OFActionDataLayerDestination(); ofAction.setDataLayerAddress(a.getDlAddress()); actionsList.add(ofAction); actionsLength += OFActionDataLayerDestination.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_NW_SRC) { SetNwSrc a = (SetNwSrc) action; OFActionNetworkLayerSource ofAction = new OFActionNetworkLayerSource(); ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a .getAddress().getAddress())); actionsList.add(ofAction); actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_NW_DST) { SetNwDst a = (SetNwDst) action; OFActionNetworkLayerDestination ofAction = new OFActionNetworkLayerDestination(); ofAction.setNetworkAddress(NetUtils.byteArray4ToInt(a .getAddress().getAddress())); actionsList.add(ofAction); actionsLength += OFActionNetworkLayerAddress.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_NW_TOS) { SetNwTos a = (SetNwTos) action; OFActionNetworkTypeOfService ofAction = new OFActionNetworkTypeOfService(); ofAction.setNetworkTypeOfService(Integer.valueOf( a.getNwTos()).byteValue()); actionsList.add(ofAction); actionsLength += OFActionNetworkTypeOfService.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_TP_SRC) { SetTpSrc a = (SetTpSrc) action; OFActionTransportLayerSource ofAction = new OFActionTransportLayerSource(); ofAction.setTransportPort(Integer.valueOf(a.getPort()) .shortValue()); actionsList.add(ofAction); actionsLength += OFActionTransportLayer.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_TP_DST) { SetTpDst a = (SetTpDst) action; OFActionTransportLayerDestination ofAction = new OFActionTransportLayerDestination(); ofAction.setTransportPort(Integer.valueOf(a.getPort()) .shortValue()); actionsList.add(ofAction); actionsLength += OFActionTransportLayer.MINIMUM_LENGTH; continue; } if (action.getType() == ActionType.SET_NEXT_HOP) { // TODO continue; } } } logger.trace("SAL Actions: {} Openflow Actions: {}", flow.getActions(), actionsList); return actionsList; } /** * Utility to convert a SAL flow to an OF 1.0 (OFFlowMod) or to an OF 1.0 + * IPv6 extension (V6FlowMod) Flow modifier Message * * @param sw * @param command * @param port * @return */ public OFMessage getOFFlowMod(short command, OFPort port) { OFMessage fm = (isIPv6) ? new V6FlowMod() : new OFFlowMod(); if (this.ofMatch == null) { getOFMatch(); } if (this.actionsList == null) { getOFActions(); } if (!isIPv6) { ((OFFlowMod) fm).setMatch(this.ofMatch); ((OFFlowMod) fm).setActions(this.actionsList); ((OFFlowMod) fm).setPriority(flow.getPriority()); ((OFFlowMod) fm).setCookie(flow.getId()); ((OFFlowMod) fm).setBufferId(OFPacketOut.BUFFER_ID_NONE); ((OFFlowMod) fm).setLength(U16.t(OFFlowMod.MINIMUM_LENGTH + actionsLength)); ((OFFlowMod) fm).setIdleTimeout(flow.getIdleTimeout()); ((OFFlowMod) fm).setHardTimeout(flow.getHardTimeout()); ((OFFlowMod) fm).setCommand(command); if (port != null) { ((OFFlowMod) fm).setOutPort(port); } if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY || command == OFFlowMod.OFPFC_MODIFY_STRICT) { if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) { // Instruct switch to let controller know when flow expires ((OFFlowMod) fm).setFlags((short) 1); } } } else { ((V6FlowMod) fm).setVendor(); ((V6FlowMod) fm).setMatch((V6Match) ofMatch); ((V6FlowMod) fm).setActions(this.actionsList); ((V6FlowMod) fm).setPriority(flow.getPriority()); ((V6FlowMod) fm).setCookie(flow.getId()); ((V6FlowMod) fm).setLength(U16.t(OFVendor.MINIMUM_LENGTH + ((V6Match) ofMatch).getIPv6ExtMinHdrLen() + ((V6Match) ofMatch).getIPv6MatchLen() + ((V6Match) ofMatch).getPadSize() + actionsLength)); ((V6FlowMod) fm).setIdleTimeout(flow.getIdleTimeout()); ((V6FlowMod) fm).setHardTimeout(flow.getHardTimeout()); ((V6FlowMod) fm).setCommand(command); if (port != null) { ((V6FlowMod) fm).setOutPort(port); } if (command == OFFlowMod.OFPFC_ADD || command == OFFlowMod.OFPFC_MODIFY || command == OFFlowMod.OFPFC_MODIFY_STRICT) { if (flow.getIdleTimeout() != 0 || flow.getHardTimeout() != 0) { // Instruct switch to let controller know when flow expires ((V6FlowMod) fm).setFlags((short) 1); } } } logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch, actionsList); logger.trace("Openflow Mod Message: {}", fm); return fm; } public Flow getFlow(Node node) { if (this.flow == null) { Match salMatch = new Match(); /* * Installed flow may not have a Match defined like in case of a * drop all flow */ if (ofMatch != null) { if (!isIPv6) { // Compute OF1.0 Match if (ofMatch.getInputPort() != 0) { salMatch.setField(new MatchField(MatchType.IN_PORT, NodeConnectorCreator.createNodeConnector( (Short) ofMatch.getInputPort(), node))); } if (ofMatch.getDataLayerSource() != null && !NetUtils .isZeroMAC(ofMatch.getDataLayerSource())) { byte srcMac[] = ofMatch.getDataLayerSource(); salMatch.setField(new MatchField(MatchType.DL_SRC, srcMac.clone())); } if (ofMatch.getDataLayerDestination() != null && !NetUtils.isZeroMAC(ofMatch .getDataLayerDestination())) { byte dstMac[] = ofMatch.getDataLayerDestination(); salMatch.setField(new MatchField(MatchType.DL_DST, dstMac.clone())); } if (ofMatch.getDataLayerType() != 0) { salMatch.setField(new MatchField(MatchType.DL_TYPE, ofMatch.getDataLayerType())); } if (ofMatch.getDataLayerVirtualLan() != 0) { salMatch.setField(new MatchField(MatchType.DL_VLAN, ofMatch.getDataLayerVirtualLan())); } if (ofMatch.getDataLayerVirtualLanPriorityCodePoint() != 0) { salMatch.setField(MatchType.DL_VLAN_PR, ofMatch .getDataLayerVirtualLanPriorityCodePoint()); } if (ofMatch.getNetworkSource() != 0) { salMatch.setField(MatchType.NW_SRC, NetUtils .getInetAddress(ofMatch.getNetworkSource()), NetUtils.getInetNetworkMask( ofMatch.getNetworkSourceMaskLen(), false)); } if (ofMatch.getNetworkDestination() != 0) { salMatch.setField(MatchType.NW_DST, NetUtils.getInetAddress(ofMatch .getNetworkDestination()), NetUtils.getInetNetworkMask( ofMatch.getNetworkDestinationMaskLen(), false)); } if (ofMatch.getNetworkTypeOfService() != 0) { int dscp = NetUtils.getUnsignedByte(ofMatch .getNetworkTypeOfService()); byte tos = (byte) (dscp >> 2); salMatch.setField(MatchType.NW_TOS, tos); } if (ofMatch.getNetworkProtocol() != 0) { salMatch.setField(MatchType.NW_PROTO, ofMatch.getNetworkProtocol()); } if (ofMatch.getTransportSource() != 0) { salMatch.setField(MatchType.TP_SRC, ((Short) ofMatch.getTransportSource())); } if (ofMatch.getTransportDestination() != 0) { salMatch.setField(MatchType.TP_DST, ((Short) ofMatch.getTransportDestination())); } } else { // Compute OF1.0 + IPv6 extensions Match V6Match v6Match = (V6Match) ofMatch; if (v6Match.getInputPort() != 0) { // Mask on input port is not defined salMatch.setField(new MatchField(MatchType.IN_PORT, NodeConnectorCreator.createOFNodeConnector( (Short) v6Match.getInputPort(), node))); } if (v6Match.getDataLayerSource() != null && !NetUtils .isZeroMAC(ofMatch.getDataLayerSource())) { byte srcMac[] = v6Match.getDataLayerSource(); salMatch.setField(new MatchField(MatchType.DL_SRC, srcMac.clone())); } if (v6Match.getDataLayerDestination() != null && !NetUtils.isZeroMAC(ofMatch .getDataLayerDestination())) { byte dstMac[] = v6Match.getDataLayerDestination(); salMatch.setField(new MatchField(MatchType.DL_DST, dstMac.clone())); } if (v6Match.getDataLayerType() != 0) { salMatch.setField(new MatchField(MatchType.DL_TYPE, v6Match.getDataLayerType())); } if (v6Match.getDataLayerVirtualLan() != 0) { salMatch.setField(new MatchField(MatchType.DL_VLAN, v6Match.getDataLayerVirtualLan())); } if (v6Match.getDataLayerVirtualLanPriorityCodePoint() != 0) { salMatch.setField(MatchType.DL_VLAN_PR, v6Match .getDataLayerVirtualLanPriorityCodePoint()); } if (v6Match.getNetworkSrc() != null) { salMatch.setField(MatchType.NW_SRC, v6Match.getNetworkSrc(), v6Match.getNetworkSourceMask()); } if (v6Match.getNetworkDest() != null) { salMatch.setField(MatchType.NW_DST, v6Match.getNetworkDest(), v6Match.getNetworkDestinationMask()); } if (v6Match.getNetworkTypeOfService() != 0) { int dscp = NetUtils.getUnsignedByte(v6Match .getNetworkTypeOfService()); byte tos = (byte) (dscp >> 2); salMatch.setField(MatchType.NW_TOS, tos); } if (v6Match.getNetworkProtocol() != 0) { salMatch.setField(MatchType.NW_PROTO, v6Match.getNetworkProtocol()); } if (v6Match.getTransportSource() != 0) { salMatch.setField(MatchType.TP_SRC, ((Short) v6Match.getTransportSource())); } if (v6Match.getTransportDestination() != 0) { salMatch.setField(MatchType.TP_DST, ((Short) v6Match.getTransportDestination())); } } } // Convert actions Action salAction = null; List salActionList = new ArrayList(); if (actionsList == null) { salActionList.add(new Drop()); } else { for (OFAction ofAction : actionsList) { if (ofAction instanceof OFActionOutput) { short ofPort = ((OFActionOutput) ofAction).getPort(); if (ofPort == OFPort.OFPP_CONTROLLER.getValue()) { salAction = new Controller(); } else if (ofPort == OFPort.OFPP_NONE.getValue()) { salAction = new Drop(); } else if (ofPort == OFPort.OFPP_IN_PORT.getValue()) { salAction = new Loopback(); } else if (ofPort == OFPort.OFPP_FLOOD.getValue()) { salAction = new Flood(); } else if (ofPort == OFPort.OFPP_ALL.getValue()) { salAction = new FloodAll(); } else if (ofPort == OFPort.OFPP_LOCAL.getValue()) { salAction = new SwPath(); } else if (ofPort == OFPort.OFPP_NORMAL.getValue()) { salAction = new HwPath(); } else if (ofPort == OFPort.OFPP_TABLE.getValue()) { salAction = new HwPath(); // TODO: we do not handle // table in sal for now } else { salAction = new Output( NodeConnectorCreator.createOFNodeConnector( ofPort, node)); } } else if (ofAction instanceof OFActionVirtualLanIdentifier) { salAction = new SetVlanId( ((OFActionVirtualLanIdentifier) ofAction) .getVirtualLanIdentifier()); } else if (ofAction instanceof OFActionStripVirtualLan) { salAction = new PopVlan(); } else if (ofAction instanceof OFActionVirtualLanPriorityCodePoint) { salAction = new SetVlanPcp( ((OFActionVirtualLanPriorityCodePoint) ofAction) .getVirtualLanPriorityCodePoint()); } else if (ofAction instanceof OFActionDataLayerSource) { salAction = new SetDlSrc( ((OFActionDataLayerSource) ofAction) .getDataLayerAddress().clone()); } else if (ofAction instanceof OFActionDataLayerDestination) { salAction = new SetDlDst( ((OFActionDataLayerDestination) ofAction) .getDataLayerAddress().clone()); } else if (ofAction instanceof OFActionNetworkLayerSource) { byte addr[] = BigInteger.valueOf( ((OFActionNetworkLayerSource) ofAction) .getNetworkAddress()).toByteArray(); InetAddress ip = null; try { ip = InetAddress.getByAddress(addr); } catch (UnknownHostException e) { logger.error("", e); } salAction = new SetNwSrc(ip); } else if (ofAction instanceof OFActionNetworkLayerDestination) { byte addr[] = BigInteger.valueOf( ((OFActionNetworkLayerDestination) ofAction) .getNetworkAddress()).toByteArray(); InetAddress ip = null; try { ip = InetAddress.getByAddress(addr); } catch (UnknownHostException e) { logger.error("", e); } salAction = new SetNwDst(ip); } else if (ofAction instanceof OFActionNetworkTypeOfService) { salAction = new SetNwTos( ((OFActionNetworkTypeOfService) ofAction) .getNetworkTypeOfService()); } else if (ofAction instanceof OFActionTransportLayerSource) { Short port = ((OFActionTransportLayerSource) ofAction) .getTransportPort(); int intPort = NetUtils.getUnsignedShort(port); salAction = new SetTpSrc(intPort); } else if (ofAction instanceof OFActionTransportLayerDestination) { Short port = ((OFActionTransportLayerDestination) ofAction) .getTransportPort(); int intPort = NetUtils.getUnsignedShort(port); salAction = new SetTpDst(intPort); } salActionList.add(salAction); } } // Create Flow flow = new Flow(salMatch, salActionList); } logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch, actionsList); logger.trace("SAL Flow: {}", flow); return flow; } }