2 * Copyright (c) 2013, 2015 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.openflowplugin.openflow.md.util;
11 import com.google.common.collect.ImmutableBiMap;
12 import java.util.Objects;
13 import javax.annotation.Nullable;
14 import org.opendaylight.openflowjava.protocol.api.util.BinContent;
15 import org.opendaylight.openflowplugin.api.OFConstants;
16 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumberValues;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumberValuesV10;
22 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory;
26 * Class which integrates the port constants defined and used by MDSAL and the ports defined in openflow java
27 * This class is responsible for converting MDSAL given logical names to port numbers and back.
28 * Any newer version of openflow can have a similar mapping or can/should be extended.
30 public class OpenflowPortsUtil {
32 private static final Logger LOG = LoggerFactory.getLogger(OpenflowPortsUtil.class);
33 private static final ImmutableBiMap<Short, ImmutableBiMap<String, Long>> versionPortMap;
34 private static final ImmutableBiMap<Short, ImmutableBiMap<Long, String>> versionInversePortMap;
36 private static boolean inportWarnignAlreadyFired = false;
40 final ImmutableBiMap<String, Long> ofv10ports = new ImmutableBiMap.Builder<String, Long>()
41 .put(OutputPortValues.MAX.getName(), (long) PortNumberValuesV10.MAX.getIntValue()) //0xff00
42 .put(OutputPortValues.INPORT.getName(), (long) PortNumberValuesV10.INPORT.getIntValue()) //0xfff8
43 .put(OutputPortValues.TABLE.getName(), (long) PortNumberValuesV10.TABLE.getIntValue()) //0xfff9
44 .put(OutputPortValues.NORMAL.getName(), (long) PortNumberValuesV10.NORMAL.getIntValue()) //0xfffa
45 .put(OutputPortValues.FLOOD.getName(), (long) PortNumberValuesV10.FLOOD.getIntValue()) //0xfffb
46 .put(OutputPortValues.ALL.getName(), (long) PortNumberValuesV10.ALL.getIntValue()) //0xfffc
47 .put(OutputPortValues.CONTROLLER.getName(), (long) PortNumberValuesV10.CONTROLLER.getIntValue()) //0xfffd
48 .put(OutputPortValues.LOCAL.getName(), (long) PortNumberValuesV10.LOCAL.getIntValue()) //0xfffe
49 .put(OutputPortValues.NONE.getName(), (long) PortNumberValuesV10.NONE.getIntValue()) //0xffff
52 // openflow 1.3 reserved ports.
53 // PortNumberValues are defined in OFJava yang. And yang maps an int to all enums. Hence we need to create longs from (-ve) ints
54 // TODO: do we need to define these ports in yang?
55 final ImmutableBiMap<String, Long> ofv13ports = new ImmutableBiMap.Builder<String, Long>()
56 .put(OutputPortValues.MAX.getName(), BinContent.intToUnsignedLong(PortNumberValues.MAX.getIntValue())) //0xffffff00
57 .put(OutputPortValues.INPORT.getName(), BinContent.intToUnsignedLong(PortNumberValues.INPORT.getIntValue())) //0xfffffff8
58 .put(OutputPortValues.TABLE.getName(), BinContent.intToUnsignedLong(PortNumberValues.TABLE.getIntValue())) //0xfffffff9
59 .put(OutputPortValues.NORMAL.getName(), BinContent.intToUnsignedLong(PortNumberValues.NORMAL.getIntValue())) //0xfffffffa
60 .put(OutputPortValues.FLOOD.getName(), BinContent.intToUnsignedLong(PortNumberValues.FLOOD.getIntValue())) //0xfffffffb
61 .put(OutputPortValues.ALL.getName(), BinContent.intToUnsignedLong(PortNumberValues.ALL.getIntValue())) //0xfffffffc
62 .put(OutputPortValues.CONTROLLER.getName(), BinContent.intToUnsignedLong(PortNumberValues.CONTROLLER.getIntValue())) //0xfffffffd
63 .put(OutputPortValues.LOCAL.getName(), BinContent.intToUnsignedLong(PortNumberValues.LOCAL.getIntValue())) //0xfffffffe
64 .put(OutputPortValues.ANY.getName(), BinContent.intToUnsignedLong(PortNumberValues.ANY.getIntValue())) //0xffffffff
67 versionPortMap = new ImmutableBiMap.Builder<Short, ImmutableBiMap<String, Long>>()
68 .put(OFConstants.OFP_VERSION_1_0, ofv10ports)
69 .put(OFConstants.OFP_VERSION_1_3, ofv13ports)
72 versionInversePortMap = new ImmutableBiMap.Builder<Short, ImmutableBiMap<Long, String>>()
73 .put(OFConstants.OFP_VERSION_1_0, ofv10ports.inverse())
74 .put(OFConstants.OFP_VERSION_1_3, ofv13ports.inverse())
78 public static String getPortLogicalName(final short ofVersion, final Long portNumber) {
79 return versionInversePortMap.get(ofVersion).get(portNumber);
82 public static String getPortLogicalName(final OpenflowVersion ofVersion, final Long portNumber) {
83 return ofVersion.equals(OpenflowVersion.UNSUPPORTED)
85 : getPortLogicalName(ofVersion.getVersion(), portNumber);
89 static Long getPortFromLogicalName(final OpenflowVersion ofVersion, final String logicalNameOrPort) {
91 //The correct keyword defined in openflow specification in IN_PORT so we need to allow to use it
92 //for legacy reasons we can't just simply drop the misspelled INPORT
93 //TODO: Consider to remove 'INPORT' keyword
95 if (Objects.equals(logicalNameOrPort, "INPORT")) {
96 if (!inportWarnignAlreadyFired) {
97 LOG.warn("Using '{}' in port field is not recommended use 'IN_PORT' instead", logicalNameOrPort);
98 inportWarnignAlreadyFired = true;
100 port = versionPortMap.get(ofVersion.getVersion()).get(OutputPortValues.INPORT.getName());
102 port = versionPortMap.get(ofVersion.getVersion()).get(logicalNameOrPort);
106 port = Long.decode(logicalNameOrPort);
107 } catch (final NumberFormatException ne) {
108 //ignore, sent null back.
109 if (logicalNameOrPort.contains(":")) {
110 port = Long.parseLong(logicalNameOrPort.substring(logicalNameOrPort.lastIndexOf(":") + 1));
117 public static PortNumberUni getProtocolAgnosticPort(final OpenflowVersion ofVersion, final Long portNumber) {
118 final String reservedPortLogicalName = getPortLogicalName(ofVersion, portNumber);
120 return reservedPortLogicalName == null
121 ? new PortNumberUni(portNumber)
122 : new PortNumberUni(reservedPortLogicalName);
125 public static Long getProtocolPortNumber(final OpenflowVersion ofVersion, final PortNumberUni port) {
126 final String portLogicalName = port.getString();
128 return portLogicalName != null
129 ? versionPortMap.get(ofVersion.getVersion()).get(portLogicalName)
133 public static Long getMaxPortForVersion(final OpenflowVersion ofVersion) {
134 return getPortFromLogicalName(ofVersion, OutputPortValues.MAX.getName());
137 public static boolean isPortReserved(final OpenflowVersion ofVersion, final Long portNumber) {
138 return versionInversePortMap.get(ofVersion.getVersion()).containsKey(portNumber);
142 * @param ofVersion OpenFlow version of the switch
143 * @param portNumber port number
144 * @return true if port number is valid for given protocol version
146 public static boolean checkPortValidity(final OpenflowVersion ofVersion, final Long portNumber) {
147 boolean portIsValid = true;
148 if (portNumber == null) {
150 } else if (portNumber < 0) {
152 } else if (portNumber > getMaxPortForVersion(ofVersion)) {
153 if (!isPortReserved(ofVersion, portNumber)) {
161 * @param portNumber port number
162 * @return string containing number or logical name
164 public static String portNumberToString(final PortNumberUni portNumber) {
165 String result = null;
166 if (portNumber.getUint32() != null) {
167 result = String.valueOf(portNumber.getUint32());
168 } else if (portNumber.getString() != null) {
169 result = portNumber.getString();
175 * Converts port number to Uri
176 * @param version openflow version
177 * @param portNumber port number
178 * @return port number uri
180 public static Uri getProtocolAgnosticPortUri(final short version, final long portNumber) {
181 return new Uri(portNumberToString(getProtocolAgnosticPort(OpenflowVersion.get(version), portNumber)));