X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fprotocol_plugins%2Fopenflow%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fprotocol_plugin%2Fopenflow%2Finternal%2FFlowConverter.java;h=6d1c563aa44729581b5eb46b5e61f8cb0543b47a;hb=c61d22e4dc73fdaba09aa8c0b189ea7459679e03;hp=756a6895dc06e19ef0fbcbd85314c3fb0abdc645;hpb=910fa09609cdbf45e06d4b631079795113af59b3;p=controller.git diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java index 756a6895dc..6d1c563aa4 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java @@ -12,7 +12,9 @@ import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6FlowMod; import org.opendaylight.controller.protocol_plugin.openflow.vendorextension.v6extension.V6Match; @@ -20,6 +22,7 @@ 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.Enqueue; import org.opendaylight.controller.sal.action.Flood; import org.opendaylight.controller.sal.action.FloodAll; import org.opendaylight.controller.sal.action.HwPath; @@ -54,6 +57,7 @@ import org.openflow.protocol.action.OFAction; import org.openflow.protocol.action.OFActionDataLayer; import org.openflow.protocol.action.OFActionDataLayerDestination; import org.openflow.protocol.action.OFActionDataLayerSource; +import org.openflow.protocol.action.OFActionEnqueue; import org.openflow.protocol.action.OFActionNetworkLayerAddress; import org.openflow.protocol.action.OFActionNetworkLayerDestination; import org.openflow.protocol.action.OFActionNetworkLayerSource; @@ -76,6 +80,13 @@ import org.slf4j.LoggerFactory; public class FlowConverter { protected static final Logger logger = LoggerFactory .getLogger(FlowConverter.class); + + /* + * The value 0xffff (OFP_VLAN_NONE) is used to indicate + * that no VLAN ID is set for OF Flow. + */ + private static final short OFP_VLAN_NONE = (short) 0xffff; + 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 @@ -143,6 +154,9 @@ public class FlowConverter { if (match.isPresent(MatchType.DL_VLAN)) { short vlan = (Short) match.getField(MatchType.DL_VLAN) .getValue(); + if (vlan == MatchType.DL_VLAN_NONE) { + vlan = OFP_VLAN_NONE; + } if (!isIPv6) { ofMatch.setDataLayerVirtualLan(vlan); wildcards &= ~OFMatch.OFPFW_DL_VLAN; @@ -267,6 +281,15 @@ public class FlowConverter { actionsLength += OFActionOutput.MINIMUM_LENGTH; continue; } + if (action.getType() == ActionType.ENQUEUE) { + Enqueue a = (Enqueue) action; + OFActionEnqueue ofAction = new OFActionEnqueue(); + ofAction.setPort(PortConverter.toOFPort(a.getPort())); + ofAction.setQueueId(a.getQueue()); + actionsList.add(ofAction); + actionsLength += OFActionEnqueue.MINIMUM_LENGTH; + continue; + } if (action.getType() == ActionType.DROP) { continue; } @@ -400,7 +423,7 @@ public class FlowConverter { continue; } if (action.getType() == ActionType.SET_NEXT_HOP) { - logger.info("Unsupported action: {}", action); + logger.warn("Unsupported action: {}", action); continue; } } @@ -441,13 +464,10 @@ public class FlowConverter { if (port != null) { ((OFFlowMod) fm).setOutPort(port); } - if (command == OFFlowMod.OFPFC_ADD - || command == OFFlowMod.OFPFC_MODIFY + 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); - } + // Instruct switch to let controller know when flow is removed + ((OFFlowMod) fm).setFlags((short) 1); } } else { ((V6FlowMod) fm).setVendor(); @@ -465,13 +485,10 @@ public class FlowConverter { if (port != null) { ((V6FlowMod) fm).setOutPort(port); } - if (command == OFFlowMod.OFPFC_ADD - || command == OFFlowMod.OFPFC_MODIFY + 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); - } + // Instruct switch to let controller know when flow is removed + ((V6FlowMod) fm).setFlags((short) 1); } } logger.trace("Openflow Match: {} Openflow Actions: {}", ofMatch, @@ -514,11 +531,15 @@ public class FlowConverter { salMatch.setField(new MatchField(MatchType.DL_TYPE, ofMatch.getDataLayerType())); } - if (ofMatch.getDataLayerVirtualLan() != 0) { + short vlan = ofMatch.getDataLayerVirtualLan(); + if (vlan != 0) { + if (vlan == OFP_VLAN_NONE) { + vlan = MatchType.DL_VLAN_NONE; + } salMatch.setField(new MatchField(MatchType.DL_VLAN, - ofMatch.getDataLayerVirtualLan())); + vlan)); } - if (ofMatch.getDataLayerVirtualLanPriorityCodePoint() != 0) { + if ((ofMatch.getWildcards() & OFMatch.OFPFW_DL_VLAN_PCP) == 0) { salMatch.setField(MatchType.DL_VLAN_PR, ofMatch .getDataLayerVirtualLanPriorityCodePoint()); } @@ -543,6 +564,7 @@ public class FlowConverter { byte tos = (byte) (dscp >> 2); salMatch.setField(MatchType.NW_TOS, tos); } + //TODO: NW protocol 0 is a valid protocol if (ofMatch.getNetworkProtocol() != 0) { salMatch.setField(MatchType.NW_PROTO, ofMatch.getNetworkProtocol()); @@ -582,11 +604,15 @@ public class FlowConverter { salMatch.setField(new MatchField(MatchType.DL_TYPE, v6Match.getDataLayerType())); } - if (v6Match.getDataLayerVirtualLan() != 0) { + short vlan = v6Match.getDataLayerVirtualLan(); + if (vlan != 0) { + if (vlan == OFP_VLAN_NONE) { + vlan = MatchType.DL_VLAN_NONE; + } salMatch.setField(new MatchField(MatchType.DL_VLAN, - v6Match.getDataLayerVirtualLan())); + vlan)); } - if (v6Match.getDataLayerVirtualLanPriorityCodePoint() != 0) { + if ((v6Match.getWildcards() & OFMatch.OFPFW_DL_VLAN_PCP) == 0) { salMatch.setField(MatchType.DL_VLAN_PR, v6Match .getDataLayerVirtualLanPriorityCodePoint()); } @@ -667,6 +693,10 @@ public class FlowConverter { NodeConnectorCreator.createOFNodeConnector( ofPort, node)); } + } else if (ofAction instanceof OFActionEnqueue) { + salAction = new Enqueue(NodeConnectorCreator.createOFNodeConnector( + ((OFActionEnqueue) ofAction).getPort(), node), + ((OFActionEnqueue) ofAction).getQueueId()); } else if (ofAction instanceof OFActionVirtualLanIdentifier) { salAction = new SetVlanId( ((OFActionVirtualLanIdentifier) ofAction) @@ -734,4 +764,50 @@ public class FlowConverter { return flow; } + private static final Map> actionMap = new HashMap>() { + private static final long serialVersionUID = 1L; + { + put(1 << 0, Output.class); + put(1 << 1, SetVlanId.class); + put(1 << 2, SetVlanPcp.class); + put(1 << 3, PopVlan.class); + put(1 << 4, SetDlSrc.class); + put(1 << 5, SetDlDst.class); + put(1 << 6, SetNwSrc.class); + put(1 << 7, SetNwDst.class); + put(1 << 8, SetNwTos.class); + put(1 << 9, SetTpSrc.class); + put(1 << 10, SetTpDst.class); + put(1 << 11, Enqueue.class); + } + }; + + /** + * Returns the supported flow actions for the netwrok node given the bitmask + * representing the actions the Openflow 1.0 switch supports + * + * @param ofActionBitmask + * OF 1.0 action bitmask + * @return The correspondent list of SAL Action classes + */ + public static List> getFlowActions(int ofActionBitmask) { + List> list = new ArrayList>(); + + for (int i = 0; i < Integer.SIZE; i++) { + int index = 1 << i; + if ((index & ofActionBitmask) > 0) { + if (actionMap.containsKey(index)) { + list.add(actionMap.get(index)); + } + } + } + // Add implicit SAL actions + list.add(Controller.class); + list.add(SwPath.class); + list.add(HwPath.class); + list.add(Drop.class); + + return list; + } + }