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
8 package org.opendaylight.openflowplugin.openflow.md.util;
10 import com.google.common.collect.ImmutableBiMap;
11 import com.google.common.collect.Maps;
12 import java.util.Objects;
13 import org.eclipse.jdt.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.opendaylight.yangtools.yang.common.Uint32;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
27 * Class which integrates the port constants defined and used by MDSAL and the ports defined in openflow java
28 * This class is responsible for converting MDSAL given logical names to port numbers and back.
29 * Any newer version of openflow can have a similar mapping or can/should be extended.
31 public final class OpenflowPortsUtil {
32 private OpenflowPortsUtil() {
35 private static final Logger LOG = LoggerFactory.getLogger(OpenflowPortsUtil.class);
37 // TODO: deprecate this
38 private static final ImmutableBiMap<Short, ImmutableBiMap<Long, String>> VERSION_INVERSE_PORT_MAP;
40 private static final ImmutableBiMap<Short, ImmutableBiMap<String, Uint32>> VERSION_PORT_MAP_UINT;
41 private static final ImmutableBiMap<Short, ImmutableBiMap<Uint32, String>> VERSION_INVERSE_PORT_MAP_UINT;
43 private static boolean inportWarnignAlreadyFired = false;
47 final ImmutableBiMap<String, Long> ofv10ports = new ImmutableBiMap.Builder<String, Long>()
48 .put(OutputPortValues.MAX.getName(), (long) PortNumberValuesV10.MAX.getIntValue()) //0xff00
49 .put(OutputPortValues.INPORT.getName(), (long) PortNumberValuesV10.INPORT.getIntValue()) //0xfff8
50 .put(OutputPortValues.TABLE.getName(), (long) PortNumberValuesV10.TABLE.getIntValue()) //0xfff9
51 .put(OutputPortValues.NORMAL.getName(), (long) PortNumberValuesV10.NORMAL.getIntValue()) //0xfffa
52 .put(OutputPortValues.FLOOD.getName(), (long) PortNumberValuesV10.FLOOD.getIntValue()) //0xfffb
53 .put(OutputPortValues.ALL.getName(), (long) PortNumberValuesV10.ALL.getIntValue()) //0xfffc
54 .put(OutputPortValues.CONTROLLER.getName(),
55 (long) PortNumberValuesV10.CONTROLLER.getIntValue()) //0xfffd
56 .put(OutputPortValues.LOCAL.getName(), (long) PortNumberValuesV10.LOCAL.getIntValue()) //0xfffe
57 .put(OutputPortValues.NONE.getName(), (long) PortNumberValuesV10.NONE.getIntValue()) //0xffff
60 // openflow 1.3 reserved ports.
61 // PortNumberValues are defined in OFJava yang. And yang maps an int to all enums. Hence we need to create
62 // longs from (-ve) ints
63 // TODO: do we need to define these ports in yang?
64 final ImmutableBiMap<String, Long> ofv13ports = new ImmutableBiMap.Builder<String, Long>()
65 .put(OutputPortValues.MAX.getName(),
66 BinContent.intToUnsignedLong(PortNumberValues.MAX.getIntValue())) // 0xffffff00
67 .put(OutputPortValues.INPORT.getName(),
68 BinContent.intToUnsignedLong(PortNumberValues.INPORT.getIntValue())) // 0xfffffff8
69 .put(OutputPortValues.TABLE.getName(),
70 BinContent.intToUnsignedLong(PortNumberValues.TABLE.getIntValue())) // 0xfffffff9
71 .put(OutputPortValues.NORMAL.getName(),
72 BinContent.intToUnsignedLong(PortNumberValues.NORMAL.getIntValue())) // 0xfffffffa
73 .put(OutputPortValues.FLOOD.getName(),
74 BinContent.intToUnsignedLong(PortNumberValues.FLOOD.getIntValue())) // 0xfffffffb
75 .put(OutputPortValues.ALL.getName(),
76 BinContent.intToUnsignedLong(PortNumberValues.ALL.getIntValue())) // 0xfffffffc
77 .put(OutputPortValues.CONTROLLER.getName(),
78 BinContent.intToUnsignedLong(PortNumberValues.CONTROLLER.getIntValue())) // 0xfffffffd
79 .put(OutputPortValues.LOCAL.getName(),
80 BinContent.intToUnsignedLong(PortNumberValues.LOCAL.getIntValue())) // 0xfffffffe
81 .put(OutputPortValues.ANY.getName(),
82 BinContent.intToUnsignedLong(PortNumberValues.ANY.getIntValue())) // 0xffffffff
85 VERSION_INVERSE_PORT_MAP = new ImmutableBiMap.Builder<Short, ImmutableBiMap<Long, String>>()
86 .put(OFConstants.OFP_VERSION_1_0, ofv10ports.inverse())
87 .put(OFConstants.OFP_VERSION_1_3, ofv13ports.inverse())
90 final ImmutableBiMap<String, Uint32> ofv10portsUint = ImmutableBiMap.copyOf(Maps.transformValues(ofv10ports,
91 l -> Uint32.valueOf(l).intern()));
92 final ImmutableBiMap<String, Uint32> ofv13portsUint = ImmutableBiMap.copyOf(Maps.transformValues(ofv13ports,
93 l -> Uint32.valueOf(l).intern()));
95 VERSION_PORT_MAP_UINT = new ImmutableBiMap.Builder<Short, ImmutableBiMap<String, Uint32>>()
96 .put(OFConstants.OFP_VERSION_1_0, ofv10portsUint)
97 .put(OFConstants.OFP_VERSION_1_3, ofv13portsUint)
100 VERSION_INVERSE_PORT_MAP_UINT = new ImmutableBiMap.Builder<Short, ImmutableBiMap<Uint32, String>>()
101 .put(OFConstants.OFP_VERSION_1_0, ofv10portsUint.inverse())
102 .put(OFConstants.OFP_VERSION_1_3, ofv13portsUint.inverse())
106 // TODO: deprecate and migrate
107 public static String getPortLogicalName(final short ofVersion, final Long portNumber) {
108 return VERSION_INVERSE_PORT_MAP.get(ofVersion).get(portNumber);
111 public static String getPortLogicalName(final short ofVersion, final Uint32 portNumber) {
112 return VERSION_INVERSE_PORT_MAP_UINT.get(ofVersion).get(portNumber);
115 // TODO: deprecate and migrate
116 public static String getPortLogicalName(final OpenflowVersion ofVersion, final Long portNumber) {
117 return ofVersion.equals(OpenflowVersion.UNSUPPORTED)
119 : getPortLogicalName(ofVersion.getVersion(), portNumber);
122 public static String getPortLogicalName(final OpenflowVersion ofVersion, final Uint32 portNumber) {
123 return ofVersion.equals(OpenflowVersion.UNSUPPORTED)
125 : getPortLogicalName(ofVersion.getVersion(), portNumber);
129 static Uint32 getPortFromLogicalName(final OpenflowVersion ofVersion, final String logicalNameOrPort) {
131 //The correct keyword defined in openflow specification in IN_PORT so we need to allow to use it
132 //for legacy reasons we can't just simply drop the misspelled INPORT
133 //TODO: Consider to remove 'INPORT' keyword
135 if (Objects.equals(logicalNameOrPort, "INPORT")) {
136 if (!inportWarnignAlreadyFired) {
137 LOG.warn("Using '{}' in port field is not recommended use 'IN_PORT' instead", logicalNameOrPort);
138 inportWarnignAlreadyFired = true;
140 port = VERSION_PORT_MAP_UINT.get(ofVersion.getVersion()).get(OutputPortValues.INPORT.getName());
142 port = VERSION_PORT_MAP_UINT.get(ofVersion.getVersion()).get(logicalNameOrPort);
146 port = Uint32.valueOf(Long.decode(logicalNameOrPort));
147 } catch (final IllegalArgumentException ne) {
148 //ignore, sent null back.
149 final int lastColon = logicalNameOrPort.lastIndexOf(':');
150 if (lastColon != -1) {
151 port = Uint32.valueOf(logicalNameOrPort.substring(lastColon + 1));
158 public static PortNumberUni getProtocolAgnosticPort(final OpenflowVersion ofVersion, final Long portNumber) {
159 final String reservedPortLogicalName = getPortLogicalName(ofVersion, portNumber);
161 return reservedPortLogicalName == null
162 ? new PortNumberUni(portNumber == null ? (Uint32) null : Uint32.valueOf(portNumber))
163 : new PortNumberUni(reservedPortLogicalName);
166 // TODO: deprecate and migrate
167 public static PortNumberUni getProtocolAgnosticPort(final OpenflowVersion ofVersion, final Uint32 portNumber) {
168 final String reservedPortLogicalName = getPortLogicalName(ofVersion, portNumber);
170 return reservedPortLogicalName == null
171 ? new PortNumberUni(portNumber)
172 : new PortNumberUni(reservedPortLogicalName);
176 public static Uint32 getProtocolPortNumber(final OpenflowVersion ofVersion, final PortNumberUni port) {
177 final String portLogicalName = port.getString();
179 return portLogicalName != null
180 ? VERSION_PORT_MAP_UINT.get(ofVersion.getVersion()).get(portLogicalName)
184 public static Uint32 getMaxPortForVersion(final OpenflowVersion ofVersion) {
185 return getPortFromLogicalName(ofVersion, OutputPortValues.MAX.getName());
188 public static boolean isPortReserved(final OpenflowVersion ofVersion, final Uint32 portNumber) {
189 return VERSION_INVERSE_PORT_MAP_UINT.get(ofVersion.getVersion()).containsKey(portNumber);
193 * Checks port validity.
195 * @param ofVersion OpenFlow version of the switch
196 * @param portNumber port number
197 * @return true if port number is valid for given protocol version
199 public static boolean checkPortValidity(final OpenflowVersion ofVersion, final Uint32 portNumber) {
200 boolean portIsValid = true;
201 if (portNumber == null) {
203 } else if (portNumber.compareTo(getMaxPortForVersion(ofVersion)) > 0) {
204 if (!isPortReserved(ofVersion, portNumber)) {
212 * Converts a port number to a string.
214 * @param portNumber port number
215 * @return string containing number or logical name
217 public static String portNumberToString(final PortNumberUni portNumber) {
218 String result = null;
219 if (portNumber.getUint32() != null) {
220 result = String.valueOf(portNumber.getUint32());
221 } else if (portNumber.getString() != null) {
222 result = portNumber.getString();
228 * Converts port number to Uri.
230 * @param version openflow version
231 * @param portNumber port number
232 * @return port number uri
234 // TODO: deprecate and migrate
235 public static Uri getProtocolAgnosticPortUri(final short version, final long portNumber) {
236 return new Uri(portNumberToString(getProtocolAgnosticPort(OpenflowVersion.get(version), portNumber)));
240 * Converts port number to Uri.
242 * @param version openflow version
243 * @param portNumber port number
244 * @return port number uri
246 public static Uri getProtocolAgnosticPortUri(final short version, final Uint32 portNumber) {
247 return new Uri(portNumberToString(getProtocolAgnosticPort(OpenflowVersion.get(version), portNumber)));