PortNumber fixes

- hide new PortNumber(short) and use PortNumber.uint16 instead
- added utility to get PortNumber

Change-Id: Ia39fbe6e7126a3d9465d3035a06850c1d54a7f25
diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
index 23d61bb..dd063a6 100644
--- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java
+++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java
@@ -614,6 +614,7 @@
             FloodlightContext bContext)
             throws IOException {
         Ethernet eth = null;
+        // FIXME losing port number precision here
         short inport = -1;
 
         switch (m.getType()) {
diff --git a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
index 7c229b6..127b2c0 100644
--- a/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
+++ b/src/main/java/net/onrc/onos/apps/forwarding/Forwarding.java
@@ -397,6 +397,7 @@
 
                     boolean isflowEntryForThisSwitch = false;
                     net.onrc.onos.core.intent.Path path = pathIntent.getPath();
+                    // FIXME should switch to PortNumber, etc.
                     long outPort = -1;
 
                     if (spfIntent.getDstSwitchDpid() == sw.getDpid().value()) {
@@ -430,7 +431,7 @@
 
                         log.debug("Sending packet out from sw {}, outport{}", sw.getDpid(), outPort);
                         packetService.sendPacket(eth, new SwitchPort(
-                                sw.getDpid(), new PortNumber((short) outPort)));
+                                sw.getDpid(), PortNumber.uint16((short) outPort)));
                     }
                 } else {
                     // Flow path has not yet been installed to switches so save the
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/Interface.java b/src/main/java/net/onrc/onos/apps/sdnip/Interface.java
index 463cac8..4052e81 100644
--- a/src/main/java/net/onrc/onos/apps/sdnip/Interface.java
+++ b/src/main/java/net/onrc/onos/apps/sdnip/Interface.java
@@ -73,7 +73,7 @@
     public SwitchPort getSwitchPort() {
         //TODO SwitchPort, Dpid and Port are mutable, but they could probably
         //be made immutable which would prevent the need to copy
-        return new SwitchPort(new Dpid(dpid), new PortNumber(port));
+        return new SwitchPort(new Dpid(dpid), PortNumber.uint16(port));
     }
 
     /**
diff --git a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
index e39f404..d6713d5 100644
--- a/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
+++ b/src/main/java/net/onrc/onos/apps/sdnip/SdnIp.java
@@ -203,7 +203,7 @@
 
             bgpdAttachmentPoint = new SwitchPort(
                     new Dpid(config.getBgpdAttachmentDpid()),
-                    new PortNumber(config.getBgpdAttachmentPort()));
+                    PortNumber.uint16(config.getBgpdAttachmentPort()));
 
             bgpdMacAddress = config.getBgpdMacAddress();
             vlan = config.getVlan();
diff --git a/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java b/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
index 9f6373d..a5e3bd9 100644
--- a/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
+++ b/src/main/java/net/onrc/onos/core/hostmanager/HostManager.java
@@ -29,6 +29,7 @@
 import net.onrc.onos.core.topology.Topology;
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.PortNumberUtils;
 
 import org.projectfloodlight.openflow.protocol.OFMessage;
 import org.projectfloodlight.openflow.protocol.OFPacketIn;
@@ -121,11 +122,13 @@
     protected Command processPacketIn(IOFSwitch sw, OFPacketIn pi, Ethernet eth,
             short inport) {
         if (log.isTraceEnabled()) {
-            log.trace("Receive PACKET_IN swId {}, portId {}", sw.getId(), pi.getInPort());
+            log.trace("Receive PACKET_IN swId {}, portId {}", sw.getId(), inport);
         }
 
         final Dpid dpid = new Dpid(sw.getId());
-        final PortNumber portNum = new PortNumber(inport);
+        // FIXME method signature needs to be fixed. losing port number precision
+        final PortNumber portNum = PortNumberUtils
+                            .openFlow(sw.getOFVersion(), inport);
 
         Host srcHost =
                 getSourceHostFromPacket(eth, dpid.value(), portNum.value());
diff --git a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
index 8a9c065..4f96302 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/BroadcastPacketOutNotification.java
@@ -92,7 +92,7 @@
             topology.acquireReadLock();
             try {
                 globalPort = topology.getPort(new Dpid(entry.getKey()),
-                    new PortNumber(entry.getValue()));
+                    PortNumber.uint16(entry.getValue()));
             } finally {
                 topology.releaseReadLock();
             }
diff --git a/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
index 35aca3a..61fa735 100644
--- a/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
+++ b/src/main/java/net/onrc/onos/core/packetservice/PacketModule.java
@@ -157,6 +157,7 @@
 
         Ethernet eth = IFloodlightProviderService.bcStore.
                 get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
+        // FIXME losing port number precision
         short inport = (short) cntx.getStorage()
                 .get(IFloodlightProviderService.CONTEXT_PI_INPORT);
 
@@ -165,7 +166,7 @@
         try {
             topology.acquireReadLock();
             Dpid dpid = new Dpid(sw.getId());
-            PortNumber p = new PortNumber(inport);
+            PortNumber p = PortNumber.uint16(inport);
             topologySwitch = topology.getSwitch(dpid);
             inPort = topology.getPort(dpid, p);
         } finally {
diff --git a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
index 2863523..7675aae 100644
--- a/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
+++ b/src/main/java/net/onrc/onos/core/topology/TopologyPublisher.java
@@ -21,7 +21,6 @@
 import net.floodlightcontroller.core.module.IFloodlightService;
 import net.floodlightcontroller.core.util.SingletonTask;
 import net.floodlightcontroller.threadpool.IThreadPoolService;
-
 import net.onrc.onos.core.datagrid.IDatagridService;
 import net.onrc.onos.core.datagrid.IEventChannel;
 import net.onrc.onos.core.hostmanager.Host;
@@ -35,7 +34,7 @@
 import net.onrc.onos.core.registry.RegistryException;
 import net.onrc.onos.core.util.Dpid;
 import net.onrc.onos.core.util.OnosInstanceId;
-import net.onrc.onos.core.util.PortNumber;
+import net.onrc.onos.core.util.PortNumberUtils;
 import net.onrc.onos.core.util.SwitchPort;
 
 import org.apache.commons.lang3.concurrent.ConcurrentUtils;
@@ -260,7 +259,7 @@
         List<PortEvent> portEvents = new ArrayList<PortEvent>();
         for (OFPortDesc port : sw.getPorts()) {
             PortEvent portEvent = new PortEvent(dpid,
-                    new PortNumber(port.getPortNo().getShortPortNumber()));
+                                                PortNumberUtils.openFlow(port));
             // FIXME should be merging, with existing attrs, etc..
             // TODO define attr name as constant somewhere.
             // TODO populate appropriate attributes.
@@ -349,8 +348,8 @@
      */
     private void switchPortAdded(long switchId, OFPortDesc port) {
         final Dpid dpid = new Dpid(switchId);
-        PortEvent portEvent = new PortEvent(dpid,
-                new PortNumber(port.getPortNo().getShortPortNumber()));
+        final PortEvent portEvent = new PortEvent(dpid,
+                                        PortNumberUtils.openFlow(port));
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
@@ -371,8 +370,8 @@
     private void switchPortRemoved(long switchId, OFPortDesc port) {
         final Dpid dpid = new Dpid(switchId);
 
-        PortEvent portEvent = new PortEvent(dpid, new PortNumber(
-                port.getPortNo().getShortPortNumber()));
+        final PortEvent portEvent = new PortEvent(dpid,
+                                        PortNumberUtils.openFlow(port));
         // FIXME should be merging, with existing attrs, etc..
         // TODO define attr name as constant somewhere.
         // TODO populate appropriate attributes.
diff --git a/src/main/java/net/onrc/onos/core/util/PortNumber.java b/src/main/java/net/onrc/onos/core/util/PortNumber.java
index 0320a42..a9b42b0 100644
--- a/src/main/java/net/onrc/onos/core/util/PortNumber.java
+++ b/src/main/java/net/onrc/onos/core/util/PortNumber.java
@@ -35,7 +35,7 @@
      *
      * @param value the value to use.
      */
-    public PortNumber(short value) {
+    protected PortNumber(short value) {
         this.value = (int) shortToUnsignedLong(value);
     }
 
diff --git a/src/main/java/net/onrc/onos/core/util/PortNumberUtils.java b/src/main/java/net/onrc/onos/core/util/PortNumberUtils.java
new file mode 100644
index 0000000..38051ff
--- /dev/null
+++ b/src/main/java/net/onrc/onos/core/util/PortNumberUtils.java
@@ -0,0 +1,74 @@
+package net.onrc.onos.core.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.OFPort;
+
+/**
+ * {@link PortNumber} related utilities.
+ */
+public final class PortNumberUtils {
+
+    /**
+     * Gets {@link PortNumber} for specified port.
+     *
+     * @param ofVersion OF version to use translating {@code portNumber}
+     * @param portNumber treated as uint16 if {@link OFVersion#OF_10}
+     *                  uint32 otherwise
+     * @return {@link PortNumber}
+     */
+    public static PortNumber openFlow(OFVersion ofVersion, int portNumber) {
+        if (ofVersion == OFVersion.OF_10) {
+            return PortNumber.uint16(toOF10(portNumber));
+        } else {
+            return PortNumber.uint32(portNumber);
+        }
+    }
+
+    /**
+     * Gets {@link PortNumber} for specified port.
+     *
+     * @param desc {@link OFPortDesc}
+     * @return {@link PortNumber}
+     */
+    public static PortNumber openFlow(final OFPortDesc desc) {
+        if (checkNotNull(desc).getVersion() == OFVersion.OF_10) {
+            return PortNumber.uint16(desc.getPortNo().getShortPortNumber());
+        } else {
+            return PortNumber.uint32(desc.getPortNo().getPortNumber());
+        }
+    }
+
+    /**
+     * Validate OF1.0 port number.
+     *
+     * @param of10PortNumber 0F1.0 port number or {@link OFPort#getPortNumber()}
+     * @return OF1.0 port number
+     * @throws IllegalArgumentException if out of valid OF1.0 range
+     */
+    public static short toOF10(final int of10PortNumber) {
+        try {
+            // if the input was from OFPort#getPortNumber()
+            // some named/reserved port number to OF1.0 constants.
+            return OFPort.ofInt(of10PortNumber).getShortPortNumber();
+        } catch (IllegalArgumentException e) {
+            // OFPort#getShortPortNumber will rejects OF1.0 special ports
+            if (0xFFf8 <= of10PortNumber && of10PortNumber <= 0xFFff) {
+                // allow OF1.0 Fake output "ports" to pass
+                return (short) (0xFFFF & of10PortNumber);
+            } else if (0xFF00 == of10PortNumber) {
+                // allow OFPP_MAX
+                return (short) (0xFFFF & of10PortNumber);
+            }
+            throw e;
+        }
+    }
+
+    /**
+     * Avoid instantiation.
+     */
+    private PortNumberUtils() {}
+
+}
diff --git a/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
index 1a40013..ae7b4e3 100644
--- a/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
+++ b/src/test/java/net/onrc/onos/api/flowmanager/SingleDstTreeFlowTest.java
@@ -112,7 +112,7 @@
      */
     private List<Action> outputAction(int outputPort) {
         return Arrays.asList(
-                (Action) new OutputAction(new PortNumber((short) outputPort)));
+                (Action) new OutputAction(PortNumber.uint16((short) outputPort)));
     }
 
     /**
diff --git a/src/test/java/net/onrc/onos/apps/proxyarp/ProxyArpManagerTest.java b/src/test/java/net/onrc/onos/apps/proxyarp/ProxyArpManagerTest.java
index 901a14e..b9285de 100644
--- a/src/test/java/net/onrc/onos/apps/proxyarp/ProxyArpManagerTest.java
+++ b/src/test/java/net/onrc/onos/apps/proxyarp/ProxyArpManagerTest.java
@@ -121,8 +121,8 @@
         cachedIp2 = InetAddress.getByAddress(IPv4.toIPv4AddressBytes(cachedStrIp2));
 
         sw1Dpid = new Dpid(1L);
-        sw1Inport = new PortNumber((short) 1);
-        sw1Outport = new PortNumber((short) 2);
+        sw1Inport = PortNumber.uint16((short) 1);
+        sw1Outport = PortNumber.uint16((short) 2);
         vlanId = 1;
 
         //Made tested packets
diff --git a/src/test/java/net/onrc/onos/core/flowprogrammer/FlowPusherTest.java b/src/test/java/net/onrc/onos/core/flowprogrammer/FlowPusherTest.java
index f84c08f..6ad1e5f 100644
--- a/src/test/java/net/onrc/onos/core/flowprogrammer/FlowPusherTest.java
+++ b/src/test/java/net/onrc/onos/core/flowprogrammer/FlowPusherTest.java
@@ -408,8 +408,8 @@
         /*
         flowEntry1.setDpid(new Dpid(DPID_TO_VERIFY));
         flowEntry1.setFlowId(new FlowId(1));
-        flowEntry1.setInPort(new PortNumber((short) 1));
-        flowEntry1.setOutPort(new PortNumber((short) 11));
+        flowEntry1.setInPort(PortNumber.uint16((short) 1));
+        flowEntry1.setOutPort(PortNumber.uint16((short) 11));
         flowEntry1.setFlowEntryId(new FlowEntryId(1));
         flowEntry1.setFlowEntryMatch(new FlowEntryMatch());
         flowEntry1.setFlowEntryActions(new FlowEntryActions());
diff --git a/src/test/java/net/onrc/onos/core/hostmanager/HostManagerTest.java b/src/test/java/net/onrc/onos/core/hostmanager/HostManagerTest.java
index 1431a24..26ceb59 100644
--- a/src/test/java/net/onrc/onos/core/hostmanager/HostManagerTest.java
+++ b/src/test/java/net/onrc/onos/core/hostmanager/HostManagerTest.java
@@ -92,7 +92,7 @@
 
         expect(datagridService.createChannel("onos.host", Long.class, Host.class))
         .andReturn(eventChannel).once();
-        expect(topology.getOutgoingLink(new Dpid(1L), new PortNumber((short) 100))).andReturn(null).anyTimes();
+        expect(topology.getOutgoingLink(new Dpid(1L), PortNumber.uint16((short) 100))).andReturn(null).anyTimes();
         expect(datagridService.addListener(
                 eq("onos.host"),
                 anyObject(IEventChannelListener.class),
diff --git a/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
index b9d2b07..a0095be 100644
--- a/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/ConstrainedBFSTreeTest.java
@@ -22,13 +22,13 @@
     private static final Dpid DPID_3 = new Dpid(3L);
     private static final Dpid DPID_4 = new Dpid(4L);
 
-    private static final PortNumber PORT_NUMBER_12 = new PortNumber((short) 12);
-    private static final PortNumber PORT_NUMBER_14 = new PortNumber((short) 14);
-    private static final PortNumber PORT_NUMBER_21 = new PortNumber((short) 21);
-    private static final PortNumber PORT_NUMBER_23 = new PortNumber((short) 23);
-    private static final PortNumber PORT_NUMBER_41 = new PortNumber((short) 41);
-    private static final PortNumber PORT_NUMBER_42 = new PortNumber((short) 42);
-    private static final PortNumber PORT_NUMBER_43 = new PortNumber((short) 43);
+    private static final PortNumber PORT_NUMBER_12 = PortNumber.uint16((short) 12);
+    private static final PortNumber PORT_NUMBER_14 = PortNumber.uint16((short) 14);
+    private static final PortNumber PORT_NUMBER_21 = PortNumber.uint16((short) 21);
+    private static final PortNumber PORT_NUMBER_23 = PortNumber.uint16((short) 23);
+    private static final PortNumber PORT_NUMBER_41 = PortNumber.uint16((short) 41);
+    private static final PortNumber PORT_NUMBER_42 = PortNumber.uint16((short) 42);
+    private static final PortNumber PORT_NUMBER_43 = PortNumber.uint16((short) 43);
 
     static final long LOCAL_PORT = 0xFFFEL;
 
diff --git a/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java b/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java
index 1cadfb6..f0d7464 100644
--- a/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/PathIntentMapTest.java
@@ -22,8 +22,8 @@
 import org.junit.Test;
 
 public class PathIntentMapTest {
-    private static final PortNumber PORT_NUMBER_1 = new PortNumber((short) 1);
-    private static final PortNumber PORT_NUMBER_3 = new PortNumber((short) 3);
+    private static final PortNumber PORT_NUMBER_1 = PortNumber.uint16((short) 1);
+    private static final PortNumber PORT_NUMBER_3 = PortNumber.uint16((short) 3);
     private static final Dpid DPID_1 = new Dpid(1L);
     private static final Dpid DPID_2 = new Dpid(2L);
     private static final Dpid DPID_3 = new Dpid(3L);
@@ -55,12 +55,12 @@
         port23 = createMock(Port.class);
         port31 = createMock(Port.class);
         port41 = createMock(Port.class);
-        expect(port11.getNumber()).andReturn(new PortNumber((short) 1)).anyTimes();
-        expect(port22.getNumber()).andReturn(new PortNumber((short) 2)).anyTimes();
-        expect(port21.getNumber()).andReturn(new PortNumber((short) 1)).anyTimes();
-        expect(port23.getNumber()).andReturn(new PortNumber((short) 3)).anyTimes();
-        expect(port31.getNumber()).andReturn(new PortNumber((short) 1)).anyTimes();
-        expect(port41.getNumber()).andReturn(new PortNumber((short) 1)).anyTimes();
+        expect(port11.getNumber()).andReturn(PortNumber.uint16((short) 1)).anyTimes();
+        expect(port22.getNumber()).andReturn(PortNumber.uint16((short) 2)).anyTimes();
+        expect(port21.getNumber()).andReturn(PortNumber.uint16((short) 1)).anyTimes();
+        expect(port23.getNumber()).andReturn(PortNumber.uint16((short) 3)).anyTimes();
+        expect(port31.getNumber()).andReturn(PortNumber.uint16((short) 1)).anyTimes();
+        expect(port41.getNumber()).andReturn(PortNumber.uint16((short) 1)).anyTimes();
         replay(port11);
         replay(port22);
         replay(port21);
diff --git a/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java b/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java
index 3149103..6ffc0f4 100644
--- a/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java
+++ b/src/test/java/net/onrc/onos/core/intent/PathIntentTest.java
@@ -25,8 +25,8 @@
     private static final Dpid DPID_3 = new Dpid(3L);
     private static final Dpid DPID_4 = new Dpid(4L);
 
-    private static final PortNumber PORT_NUMBER_1 = new PortNumber((short) 1);
-    private static final PortNumber PORT_NUMBER_2 = new PortNumber((short) 2);
+    private static final PortNumber PORT_NUMBER_1 = PortNumber.uint16((short) 1);
+    private static final PortNumber PORT_NUMBER_2 = PortNumber.uint16((short) 2);
 
     @Before
     public void setUp() throws Exception {
diff --git a/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentTest.java b/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentTest.java
index c9da728..69c7277 100644
--- a/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentTest.java
+++ b/src/test/java/net/onrc/onos/core/newintent/PathFlowIntentTest.java
@@ -21,7 +21,7 @@
     private final IntentId intentId2 = new IntentId(456);
     private final FlowId flowId1 = new FlowId(1L);
     private final PacketMatch match = new PacketMatchBuilder().build();
-    private final PortNumber port = new PortNumber((short) 1);
+    private final PortNumber port = PortNumber.uint16((short) 1);
 
     /**
      * Creates a PathFlowIntent.
diff --git a/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentTest.java b/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentTest.java
index 3799889..2c4b969 100644
--- a/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentTest.java
+++ b/src/test/java/net/onrc/onos/core/newintent/SingleDstTreeFlowIntentTest.java
@@ -37,7 +37,7 @@
                 match,
                 Arrays.asList(switchPort1, switchPort2),
                 createTree(),
-                Arrays.asList((Action) new OutputAction(new PortNumber(port3))));
+                Arrays.asList((Action) new OutputAction(PortNumber.uint16(port3))));
         return new SingleDstTreeFlowIntent(intentId1, treeFlow);
     }
 
@@ -47,7 +47,7 @@
                 match,
                 Arrays.asList(switchPort1, switchPort3),
                 createTree(),
-                Arrays.asList((Action) new OutputAction(new PortNumber(port2))));
+                Arrays.asList((Action) new OutputAction(PortNumber.uint16(port2))));
         return new SingleDstTreeFlowIntent(intentId2, treeFlow);
     }
 
diff --git a/src/test/java/net/onrc/onos/core/topology/MockPacketOpticalTopology.java b/src/test/java/net/onrc/onos/core/topology/MockPacketOpticalTopology.java
index 79db75c..36b6abf 100644
--- a/src/test/java/net/onrc/onos/core/topology/MockPacketOpticalTopology.java
+++ b/src/test/java/net/onrc/onos/core/topology/MockPacketOpticalTopology.java
@@ -36,8 +36,7 @@
     @Override
     public Port addPort(Switch sw, Long portNumber) {
         PortEvent portEvent = new PortEvent(sw.getDpid(),
-                                            new PortNumber(portNumber
-                                                                   .shortValue()));
+                                    PortNumber.uint16(portNumber.shortValue()));
         portEvent.createStringAttribute(TopologyElement.TYPE,
                                         TopologyElement.TYPE_PACKET_LAYER);
         portEvent.createStringAttribute(TopologyElement.ELEMENT_TYPE,
@@ -85,8 +84,7 @@
     //todo - add t-port specific properties
     public Port addTPort(Switch sw, Long portNumber) {
         PortEvent portEvent = new PortEvent(sw.getDpid(),
-                                            new PortNumber(portNumber
-                                                                   .shortValue()));
+                                    PortNumber.uint16(portNumber.shortValue()));
         portEvent.createStringAttribute(TopologyElement.TYPE,
                                         TopologyElement.TYPE_OPTICAL_LAYER);
         portEvent.createStringAttribute(TopologyElement.ELEMENT_TYPE,
@@ -109,8 +107,7 @@
     //todo - add w-port specific properties
     public Port addWPort(Switch sw, Long portNumber) {
         PortEvent portEvent = new PortEvent(sw.getDpid(),
-                                            new PortNumber(portNumber
-                                                                   .shortValue()));
+                                    PortNumber.uint16(portNumber.shortValue()));
         portEvent.createStringAttribute(TopologyElement.TYPE,
                                         TopologyElement.TYPE_OPTICAL_LAYER);
         portEvent.createStringAttribute(TopologyElement.ELEMENT_TYPE,
@@ -146,8 +143,8 @@
 
         final Dpid srcDpidObj = new Dpid(srcDpid);
         final Dpid dstDpidObj = new Dpid(dstDpid);
-        final PortNumber srcPortNum = new PortNumber(srcPortNo.shortValue());
-        final PortNumber dstPortNum = new PortNumber(dstPortNo.shortValue());
+        final PortNumber srcPortNum = PortNumber.uint16(srcPortNo.shortValue());
+        final PortNumber dstPortNum = PortNumber.uint16(dstPortNo.shortValue());
         LinkEvent linkEvent = new LinkEvent(new SwitchPort(srcDpidObj,
                                                            srcPortNum),
                                             new SwitchPort(dstDpidObj,
diff --git a/src/test/java/net/onrc/onos/core/topology/MockTopology.java b/src/test/java/net/onrc/onos/core/topology/MockTopology.java
index 6afffb6..05660f7 100644
--- a/src/test/java/net/onrc/onos/core/topology/MockTopology.java
+++ b/src/test/java/net/onrc/onos/core/topology/MockTopology.java
@@ -29,7 +29,7 @@
 
     public Port addPort(Switch sw, Long portNumber) {
         PortEvent port = new PortEvent(sw.getDpid(),
-                                new PortNumber(portNumber.shortValue()));
+                                PortNumber.uint16(portNumber.shortValue()));
         ((TopologyImpl) this).putPort(port);
         return this.getPort(port.getSwitchPort());
     }
@@ -149,9 +149,9 @@
     public void removeLink(Long srcDpid, Long srcPortNo, Long dstDpid,
                            Long dstPortNo) {
         this.removeLink(new Dpid(srcDpid),
-                           new PortNumber(srcPortNo.shortValue()),
+                           PortNumber.uint16(srcPortNo.shortValue()),
                            new Dpid(dstDpid),
-                           new PortNumber(dstPortNo.shortValue()));
+                           PortNumber.uint16(dstPortNo.shortValue()));
     }
 
     public void removeLink(Dpid srcDpid, PortNumber srcPortNo,
diff --git a/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java b/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
index 290b136..e281404 100644
--- a/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
+++ b/src/test/java/net/onrc/onos/core/util/LinkTupleTest.java
@@ -11,9 +11,9 @@
 public class LinkTupleTest {
 
     private static final Dpid SRC_DPID = new Dpid(9);
-    private static final PortNumber SRC_PORT_NUM = new PortNumber((short) 56);
+    private static final PortNumber SRC_PORT_NUM = PortNumber.uint16((short) 56);
     private static final Dpid DST_DPID = new Dpid(12);
-    private static final PortNumber DST_PORT_NUM = new PortNumber((short) 81);
+    private static final PortNumber DST_PORT_NUM = PortNumber.uint16((short) 81);
 
     private static final SwitchPort SRC = new SwitchPort(SRC_DPID, SRC_PORT_NUM);
     private static final SwitchPort DST = new SwitchPort(DST_DPID, DST_PORT_NUM);
@@ -21,8 +21,8 @@
 
     private static final LinkTuple L1 = new LinkTuple(SRC, DST);
     private static final LinkTuple L2 = new LinkTuple(
-            new SwitchPort(new Dpid(1), new PortNumber((short) 65535)),
-            new SwitchPort(new Dpid(2), new PortNumber((short) 65534)));
+            new SwitchPort(new Dpid(1), PortNumber.uint16((short) 65535)),
+            new SwitchPort(new Dpid(2), PortNumber.uint16((short) 65534)));
 
     /**
      * Test to confirm class definition is immutable.
diff --git a/src/test/java/net/onrc/onos/core/util/PortNumberTest.java b/src/test/java/net/onrc/onos/core/util/PortNumberTest.java
index d9fbddc..fa16481 100644
--- a/src/test/java/net/onrc/onos/core/util/PortNumberTest.java
+++ b/src/test/java/net/onrc/onos/core/util/PortNumberTest.java
@@ -102,9 +102,9 @@
      */
     @Test
     public void testShortValue() {
-        assertEquals(0L, new PortNumber((short) 0).shortValue());
+        assertEquals(0L, PortNumber.uint16((short) 0).shortValue());
 
-        assertEquals(1L, new PortNumber((short) 1).shortValue());
+        assertEquals(1L, PortNumber.uint16((short) 1).shortValue());
 
         // user of #shortValue() needs to be careful
         // simply widening them will result in negative value
@@ -121,9 +121,9 @@
      */
     @Test
     public void testLongValue() {
-        assertEquals(0L, new PortNumber((short) 0).value());
+        assertEquals(0L, PortNumber.uint16((short) 0).value());
 
-        assertEquals(1L, new PortNumber((short) 1).value());
+        assertEquals(1L, PortNumber.uint16((short) 1).value());
 
         assertEquals(0xffffL, new PortNumber(PORT_NONE).value());
     }
@@ -133,9 +133,9 @@
      */
     @Test
     public void testToString() {
-        assertEquals("0", new PortNumber((short) 0).toString());
+        assertEquals("0", PortNumber.uint16((short) 0).toString());
 
-        assertEquals("1", new PortNumber((short) 1).toString());
+        assertEquals("1", PortNumber.uint16((short) 1).toString());
 
         // 0xffff in decimal
         assertEquals("65535", new PortNumber(PORT_NONE).toString());
@@ -147,11 +147,11 @@
     @Test
     public void testEqualsObject() {
         // Some trivial
-        assertTrue(new PortNumber(PORT_NONE).equals(new PortNumber((short) 0xffff)));
-        assertFalse(new PortNumber((short) 0).equals(new PortNumber((short) 1)));
+        assertTrue(new PortNumber(PORT_NONE).equals(PortNumber.uint16((short) 0xffff)));
+        assertFalse(PortNumber.uint16((short) 0).equals(PortNumber.uint16((short) 1)));
 
         // different type
-        assertFalse(new PortNumber((short) 0).equals(Short.valueOf((short) 0)));
+        assertFalse(PortNumber.uint16((short) 0).equals(Short.valueOf((short) 0)));
 
     }
 
diff --git a/src/test/java/net/onrc/onos/core/util/PortNumberUtilsTest.java b/src/test/java/net/onrc/onos/core/util/PortNumberUtilsTest.java
new file mode 100644
index 0000000..2785c70
--- /dev/null
+++ b/src/test/java/net/onrc/onos/core/util/PortNumberUtilsTest.java
@@ -0,0 +1,100 @@
+package net.onrc.onos.core.util;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.types.OFPort;
+
+/**
+ * Tests for {@link PortNumberUtils}.
+ */
+public class PortNumberUtilsTest {
+
+
+    /**
+     * Tests for {@link PortNumberUtils#of(OFVersion, int))}.
+     */
+    @Test
+    public void testOfOFVersionInt() {
+
+        assertEquals(PortNumber.uint32(0x1ffff),
+                PortNumberUtils.openFlow(OFVersion.OF_13, 0x1FFFF));
+
+        assertEquals(PortNumber.uint16((short) 0xabc),
+                PortNumberUtils.openFlow(OFVersion.OF_10, 0xabc));
+
+        try {
+            PortNumberUtils.openFlow(OFVersion.OF_10, 0x1FFFF);
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) { // CHECKSTYLE IGNORE THIS LINE
+            // should throw
+        }
+    }
+
+    /**
+     * Tests for {@link PortNumberUtils#openFlow(OFPortDesc)}.
+     */
+    @Test
+    public void testOfOFPortDesc() {
+        final OFPortDesc desc10 = OFFactories.getFactory(OFVersion.OF_10)
+                .buildPortDesc()
+                .setPortNo(OFPort.of(123))
+                .build();
+
+        assertEquals(PortNumber.uint16((short) 123),
+                PortNumberUtils.openFlow(desc10));
+
+        final OFPortDesc desc13 = OFFactories.getFactory(OFVersion.OF_13)
+                .buildPortDesc()
+                .setPortNo(OFPort.of(0x1FFFF))
+                .build();
+
+        assertEquals(PortNumber.uint32(0x1FFFF),
+                PortNumberUtils.openFlow(desc13));
+    }
+
+    /**
+     * Tests for {@link PortNumberUtils#toOF10(int)}.
+     */
+    @Test
+    public void testToOF10() {
+        assertEquals((short) 0, PortNumberUtils.toOF10(0));
+        assertEquals((short) 1, PortNumberUtils.toOF10(1));
+        assertEquals((short) 0xFF00, PortNumberUtils.toOF10(0xFF00));
+        for (int i = 0xFF00 + 1; i < 0xFFf8; ++i) {
+            try {
+                PortNumberUtils.toOF10(i);
+                fail("Should have thrown IllegalArgumentException");
+            } catch (IllegalArgumentException e) { // CHECKSTYLE IGNORE THIS LINE
+                // should throw
+            }
+        }
+        assertEquals((short) 0xFFf8, PortNumberUtils.toOF10(0xFFf8));
+        assertEquals((short) 0xFFff, PortNumberUtils.toOF10(0xFFff));
+
+
+        // OFPort#getPortNumber can return int value outside OF1.0
+        // verifty that toOF10 converts them into valid OF1.0 range
+        assertEquals((short) 0xFF00,
+                PortNumberUtils.toOF10(OFPort.MAX.getPortNumber()));
+        assertEquals((short) 0xFFf8,
+                PortNumberUtils.toOF10(OFPort.IN_PORT.getPortNumber()));
+        assertEquals((short) 0xFFf9,
+                PortNumberUtils.toOF10(OFPort.TABLE.getPortNumber()));
+        assertEquals((short) 0xFFfa,
+                PortNumberUtils.toOF10(OFPort.NORMAL.getPortNumber()));
+        assertEquals((short) 0xFFfb,
+                PortNumberUtils.toOF10(OFPort.FLOOD.getPortNumber()));
+        assertEquals((short) 0xFFfc,
+                PortNumberUtils.toOF10(OFPort.ALL.getPortNumber()));
+        assertEquals((short) 0xFFfd,
+                PortNumberUtils.toOF10(OFPort.CONTROLLER.getPortNumber()));
+        assertEquals((short) 0xFFfe,
+                PortNumberUtils.toOF10(OFPort.LOCAL.getPortNumber()));
+        assertEquals((short) 0xFFff, // OFPP_NONE
+                PortNumberUtils.toOF10(OFPort.ANY.getPortNumber()));
+    }
+}
diff --git a/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java b/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
index 2832dc1..af9efad 100644
--- a/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
+++ b/src/test/java/net/onrc/onos/core/util/SwitchPortTest.java
@@ -10,11 +10,11 @@
 public class SwitchPortTest {
 
     private static final Dpid DPID = new Dpid(9);
-    private static final PortNumber PORT_NUM = new PortNumber((short) 56);
+    private static final PortNumber PORT_NUM = PortNumber.uint16((short) 56);
 
     private static final SwitchPort SWP1 = new SwitchPort(DPID, PORT_NUM);
     private static final SwitchPort SWP2 = new SwitchPort(new Dpid(1),
-                                                 new PortNumber((short) 65535));
+                                                 PortNumber.uint16((short) 65535));
 
     /**
      * Tests to confirm 2-arg constructor.
diff --git a/src/test/java/net/onrc/onos/core/util/serializers/KryoFactoryTest.java b/src/test/java/net/onrc/onos/core/util/serializers/KryoFactoryTest.java
index 38a37a0..01b27ea 100644
--- a/src/test/java/net/onrc/onos/core/util/serializers/KryoFactoryTest.java
+++ b/src/test/java/net/onrc/onos/core/util/serializers/KryoFactoryTest.java
@@ -48,8 +48,8 @@
 
     private static final Dpid DPID_A = new Dpid(0x1234L);
     private static final Dpid DPID_B = new Dpid(Long.MAX_VALUE);
-    private static final PortNumber PORT_NO_A = new PortNumber((short) 42);
-    private static final PortNumber PORT_NO_B = new PortNumber((short) 65534);
+    private static final PortNumber PORT_NO_A = PortNumber.uint16((short) 42);
+    private static final PortNumber PORT_NO_B = PortNumber.uint16((short) 65534);
     private static final String ONOS_INSTANCE_NAME = "ONOS-Instance-Test";
 
     private static final double SEC_IN_NANO = 1000 * 1000 * 1000.0;