60f8f9ae8626c7ab2f5732577cc2e6fff8c38b6c
[openflowplugin.git] / openflowplugin / src / main / java / org / opendaylight / openflowplugin / openflow / md / util / OpenflowPortsUtil.java
1 /*
2  * Copyright (c) 2013, 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.openflow.md.util;
10
11 import com.google.common.collect.ImmutableBiMap;
12 import org.opendaylight.openflowjava.protocol.api.util.BinContent;
13 import org.opendaylight.openflowplugin.api.openflow.md.util.OpenflowVersion;
14 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortNumberUni;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumberValues;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.PortNumberValuesV10;
18
19 /**
20  * Class which integrates the port constants defined and used by MDSAL and the ports defined in openflow java
21  * This class is responsible for converting MDSAL given logical names to port numbers and back.
22  * Any newer version of openflow can have a similar mapping or can/should be extended.
23  *
24  * @author Kamal Rameshan on 5/2/14.
25  */
26 public class OpenflowPortsUtil {
27
28     static ImmutableBiMap<OpenflowVersion, ImmutableBiMap<String, Long>> versionPortMap;
29
30     static final String MAX = "MAX";
31
32     // the init gets called from MDController at the start
33     public static void init() {
34
35         // v1.0 ports
36         final ImmutableBiMap<String, Long> OFv10 = new ImmutableBiMap.Builder<String, Long>()
37                 .put(OutputPortValues.MAX.toString(), Long.valueOf(PortNumberValuesV10.MAX.getIntValue())) //0xff00
38                 .put(OutputPortValues.INPORT.toString(), Long.valueOf(PortNumberValuesV10.INPORT.getIntValue())) //0xfff8
39                 .put(OutputPortValues.TABLE.toString(), Long.valueOf(PortNumberValuesV10.TABLE.getIntValue())) //0xfff9
40                 .put(OutputPortValues.NORMAL.toString(), Long.valueOf(PortNumberValuesV10.NORMAL.getIntValue())) //0xfffa
41                 .put(OutputPortValues.FLOOD.toString(), Long.valueOf(PortNumberValuesV10.FLOOD.getIntValue())) //0xfffb
42                 .put(OutputPortValues.ALL.toString(), Long.valueOf(PortNumberValuesV10.ALL.getIntValue())) //0xfffc
43                 .put(OutputPortValues.CONTROLLER.toString(), Long.valueOf(PortNumberValuesV10.CONTROLLER.getIntValue())) //0xfffd
44                 .put(OutputPortValues.LOCAL.toString(), Long.valueOf(PortNumberValuesV10.LOCAL.getIntValue())) //0xfffe
45                 .put(OutputPortValues.NONE.toString(), Long.valueOf(PortNumberValuesV10.NONE.getIntValue())) //0xffff
46                 .build();
47
48         // openflow 1.3 reserved ports.
49         // PortNumberValues are defined in OFJava yang. And yang maps an int to all enums. Hence we need to create longs from (-ve) ints
50         // TODO: do we need to define these ports in yang?
51         final ImmutableBiMap<String, Long> OFv13 = new ImmutableBiMap.Builder<String, Long>()
52                 .put(OutputPortValues.MAX.toString(), BinContent.intToUnsignedLong(PortNumberValues.MAX.getIntValue())) //0xffffff00
53                 .put(OutputPortValues.INPORT.toString(), BinContent.intToUnsignedLong(PortNumberValues.INPORT.getIntValue())) //0xfffffff8
54                 .put(OutputPortValues.TABLE.toString(), BinContent.intToUnsignedLong(PortNumberValues.TABLE.getIntValue())) //0xfffffff9
55                 .put(OutputPortValues.NORMAL.toString(), BinContent.intToUnsignedLong(PortNumberValues.NORMAL.getIntValue())) //0xfffffffa
56                 .put(OutputPortValues.FLOOD.toString(), BinContent.intToUnsignedLong(PortNumberValues.FLOOD.getIntValue())) //0xfffffffb
57                 .put(OutputPortValues.ALL.toString(), BinContent.intToUnsignedLong(PortNumberValues.ALL.getIntValue())) //0xfffffffc
58                 .put(OutputPortValues.CONTROLLER.toString(), BinContent.intToUnsignedLong(PortNumberValues.CONTROLLER.getIntValue())) //0xfffffffd
59                 .put(OutputPortValues.LOCAL.toString(), BinContent.intToUnsignedLong(PortNumberValues.LOCAL.getIntValue())) //0xfffffffe
60                 .put(OutputPortValues.ANY.toString(), BinContent.intToUnsignedLong(PortNumberValues.ANY.getIntValue())) //0xffffffff
61                 .build();
62
63         versionPortMap = new ImmutableBiMap.Builder<OpenflowVersion, ImmutableBiMap<String, Long>>()
64                 .put(OpenflowVersion.OF10, OFv10)
65                 .put(OpenflowVersion.OF13, OFv13)
66                 .build();
67
68     }
69
70     public static void close() {
71         versionPortMap = null;
72     }
73
74     public static String getPortLogicalName(final short ofVersion, final long portNumber) {
75         return versionPortMap.get(OpenflowVersion.get(ofVersion)).inverse().get(portNumber);
76     }
77
78     public static String getPortLogicalName(final OpenflowVersion ofVersion, final Long portNumber) {
79         if (ofVersion.equals(OpenflowVersion.UNSUPPORTED)) {
80             return null;
81         }
82         return versionPortMap.get(ofVersion).inverse().get(portNumber);
83     }
84
85     public static Long getPortFromLogicalName(final OpenflowVersion ofVersion, final String logicalNameOrPort) {
86         Long port = versionPortMap.get(ofVersion).get(logicalNameOrPort);
87         if (port == null) {
88             try {
89                 port = Long.decode(logicalNameOrPort);
90             } catch (final NumberFormatException ne) {
91                 //ignore, sent null back.
92                 if (logicalNameOrPort.contains(":")) {
93                     port = Long.parseLong(logicalNameOrPort.substring(logicalNameOrPort.lastIndexOf(":") + 1));
94                 }
95             }
96         }
97         return port;
98     }
99
100     public static PortNumberUni getProtocolAgnosticPort(final OpenflowVersion ofVersion, final Long portNumber) {
101         final String reservedPortLogicalName = getPortLogicalName(ofVersion, portNumber);
102         return (reservedPortLogicalName == null ? new PortNumberUni(portNumber) :
103                 new PortNumberUni(reservedPortLogicalName));
104     }
105
106     public static Long getProtocolPortNumber(final OpenflowVersion ofVersion, final PortNumberUni port) {
107         final String portLogicalName = port.getString();
108
109         if (portLogicalName != null) {
110             return versionPortMap.get(ofVersion).get(portLogicalName);
111         } else {
112             return port.getUint32();
113         }
114     }
115
116     public static Long getMaxPortForVersion(final OpenflowVersion ofVersion) {
117         return getPortFromLogicalName(ofVersion, MAX);
118     }
119
120     public static boolean isPortReserved(final OpenflowVersion ofVersion, final Long portNumber) {
121         return versionPortMap.get(ofVersion).inverse().containsKey(portNumber);
122     }
123
124     /**
125      * @param ofVersion OpenFlow version of the switch
126      * @param portNumber port number
127      * @return true if port number is valid for given protocol version
128      */
129     public static boolean checkPortValidity(final OpenflowVersion ofVersion, final Long portNumber) {
130         boolean portIsValid = true;
131         if (portNumber == null) {
132             portIsValid = false;
133         } else if (portNumber < 0) {
134             portIsValid = false;
135         } else if (portNumber > OpenflowPortsUtil.getMaxPortForVersion(ofVersion)) {
136             if (!OpenflowPortsUtil.isPortReserved(ofVersion, portNumber)) {
137                 portIsValid = false;
138             }
139         }
140         return portIsValid;
141     }
142
143     /**
144      * @param portNumber port number
145      * @return string containing number or logical name
146      */
147     public static String portNumberToString(final PortNumberUni portNumber) {
148         String result = null;
149         if (portNumber.getUint32() != null) {
150             result = String.valueOf(portNumber.getUint32());
151         } else if (portNumber.getString() != null) {
152             result = portNumber.getString();
153         }
154         return result;
155     }
156 }