Generic ROADM port models and descriptions

Change-Id: I053d61c7a057d6298b7990373448df28b3aaa5a5
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java b/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
index 4cf92ba..13e74b8 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultAnnotations.java
@@ -38,6 +38,26 @@
         this.map = null;
     }
 
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        DefaultAnnotations that = (DefaultAnnotations) o;
+
+        return Objects.equals(this.map, that.map);
+
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(this.map);
+    }
+
     /**
      * Creates a new set of annotations using clone of the specified hash map.
      *
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultDevice.java b/core/api/src/main/java/org/onosproject/net/DefaultDevice.java
index 800eb9a..f3f0fe7 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultDevice.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultDevice.java
@@ -54,8 +54,8 @@
      * @param hwVersion    device HW version
      * @param swVersion    device SW version
      * @param serialNumber device serial number
-     * @param chassisId    chasis id
-     * @param annotations optional key/value annotations
+     * @param chassisId    chassis id
+     * @param annotations  optional key/value annotations
      */
     public DefaultDevice(ProviderId providerId, DeviceId id, Type type,
                          String manufacturer, String hwVersion, String swVersion,
diff --git a/core/api/src/main/java/org/onosproject/net/DefaultPort.java b/core/api/src/main/java/org/onosproject/net/DefaultPort.java
index 35c02d3..a6b8441 100644
--- a/core/api/src/main/java/org/onosproject/net/DefaultPort.java
+++ b/core/api/src/main/java/org/onosproject/net/DefaultPort.java
@@ -64,7 +64,6 @@
         this.isEnabled = isEnabled;
         this.type = type;
         this.portSpeed = portSpeed;
-
     }
 
     @Override
@@ -94,7 +93,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(number, isEnabled, type, portSpeed);
+        return Objects.hash(number, isEnabled, type, portSpeed, annotations());
     }
 
     @Override
@@ -108,7 +107,8 @@
                     Objects.equals(this.number, other.number) &&
                     Objects.equals(this.isEnabled, other.isEnabled) &&
                     Objects.equals(this.type, other.type) &&
-                    Objects.equals(this.portSpeed, other.portSpeed);
+                    Objects.equals(this.portSpeed, other.portSpeed) &&
+                    Objects.equals(this.annotations(), other.annotations());
         }
         return false;
     }
diff --git a/core/api/src/main/java/org/onosproject/net/OchPort.java b/core/api/src/main/java/org/onosproject/net/OchPort.java
new file mode 100644
index 0000000..cdf0dd3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/OchPort.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.util.Frequency;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of OCh port (Optical Channel).
+ * Also referred to as a line side port (L-port) or narrow band port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ */
+public class OchPort extends DefaultPort {
+
+    public static final Frequency CENTER_FREQUENCY = Frequency.ofTHz(193.1);
+    public static final Frequency FLEX_GRID_SLOT = Frequency.ofGHz(12.5);
+
+    public enum SignalType {
+        ODU0,
+        ODU1,
+        ODU2,
+        ODU2e,
+        ODU3,
+        ODU4
+    }
+
+    public enum GridType {
+        RES,                // ??
+        DWDM,               // Dense Wavelength Division Multiplexing
+        CWDM,               // Coarse WDM
+        FLEX                // Flex Grid
+    }
+
+    public enum ChannelSpacing {
+        CHL_100GHZ(100),        // 100 GHz
+        CHL_50GHZ(50),          // 50 GHz
+        CHL_25GHZ(25),          // 25 GHz
+        CHL_12P5GHZ(12.5),      // 12.5 GHz
+        CHL_6P25GHZ(6.5);       // 6.25 GHz
+
+        private final Frequency frequency;
+
+        ChannelSpacing(double value) {
+            this.frequency = Frequency.ofGHz(value);
+        }
+
+        public Frequency frequency() {
+            return frequency;
+        }
+    }
+
+    private final SignalType signalType;
+    private final boolean isTunable;
+    private final GridType gridType;
+    private final ChannelSpacing channelSpacing;
+    // Frequency = 193.1 THz + spacingMultiplier * channelSpacing
+    private final int spacingMultiplier;
+    // Slot width = slotGranularity * 12.5 GHz
+    private final int slotGranularity;
+
+
+    /**
+     * Creates an OCh port in the specified network element.
+     *
+     * @param element               parent network element
+     * @param number                port number
+     * @param isEnabled             port enabled state
+     * @param signalType            ODU signal type
+     * @param isTunable             maximum frequency in MHz
+     * @param gridType              grid type
+     * @param channelSpacing        channel spacing
+     * @param spacingMultiplier     channel spacing multiplier
+     * @param slotGranularity       slot width granularity
+     * @param annotations           optional key/value annotations
+     */
+    public OchPort(Element element, PortNumber number, boolean isEnabled, SignalType signalType,
+                   boolean isTunable, GridType gridType, ChannelSpacing channelSpacing,
+                   int spacingMultiplier, int slotGranularity, Annotations... annotations) {
+        super(element, number, isEnabled, Type.OCH, 0, annotations);
+        this.signalType = signalType;
+        this.isTunable = isTunable;
+        this.gridType = gridType;
+        this.channelSpacing = channelSpacing;
+        this.spacingMultiplier = spacingMultiplier;
+        this.slotGranularity = slotGranularity;
+    }
+
+    /**
+     * Returns ODU signal type.
+     *
+     * @return ODU signal type
+     */
+    public SignalType signalType() {
+        return signalType;
+    }
+
+    /**
+     * Returns true if port is wavelength tunable.
+     *
+     * @return tunable wavelength capability
+     */
+    public boolean isTunable() {
+        return isTunable;
+    }
+
+    /**
+     * Returns grid type.
+     *
+     * @return grid type
+     */
+    public GridType gridType() {
+        return gridType;
+    }
+
+    /**
+     * Returns channel spacing.
+     *
+     * @return channel spacing
+     */
+    public ChannelSpacing channelSpacing() {
+        return channelSpacing;
+    }
+
+    /**
+     * Returns spacing multiplier.
+     *
+     * @return spacing multiplier
+     */
+    public int spacingMultiplier() {
+        return spacingMultiplier;
+    }
+
+    /**
+     * Returns slow width granularity.
+     *
+     * @return slow width granularity
+     */
+    public int slotGranularity() {
+        return slotGranularity;
+    }
+
+    /**
+     * Returns central frequency in MHz.
+     *
+     * @return frequency in MHz
+     */
+    public Frequency centralFrequency() {
+        return CENTER_FREQUENCY.add(channelSpacing().frequency().multiply(spacingMultiplier));
+    }
+
+    /**
+     * Returns slot width.
+     *
+     * @return slot width
+     */
+    public Frequency slotWidth() {
+        return FLEX_GRID_SLOT.multiply(slotGranularity);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(number(), isEnabled(), type(), signalType, isTunable,
+                gridType, channelSpacing, spacingMultiplier, slotGranularity, annotations());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof OchPort) {
+            final OchPort other = (OchPort) obj;
+            return Objects.equals(this.element().id(), other.element().id()) &&
+                    Objects.equals(this.number(), other.number()) &&
+                    Objects.equals(this.isEnabled(), other.isEnabled()) &&
+                    Objects.equals(this.signalType, other.signalType) &&
+                    Objects.equals(this.isTunable, other.isTunable) &&
+                    Objects.equals(this.gridType, other.gridType) &&
+                    Objects.equals(this.channelSpacing, other.channelSpacing) &&
+                    Objects.equals(this.spacingMultiplier, other.spacingMultiplier) &&
+                    Objects.equals(this.slotGranularity, other.slotGranularity) &&
+                    Objects.equals(this.annotations(), other.annotations());
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("element", element().id())
+                .add("number", number())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("signalType", signalType)
+                .add("isTunable", isTunable)
+                .add("gridType", gridType)
+                .add("channelSpacing", channelSpacing)
+                .add("spacingMultiplier", spacingMultiplier)
+                .add("slotGranularity", slotGranularity)
+                .toString();
+    }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/OduCltPort.java b/core/api/src/main/java/org/onosproject/net/OduCltPort.java
new file mode 100644
index 0000000..e5602f3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/OduCltPort.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of ODU client port (Optical channel Data Unit).
+ * Also referred to as a T-port or wide band port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ */
+
+public class OduCltPort extends DefaultPort {
+
+    public enum SignalType {
+        CLT_1GBE,
+        CLT_10GBE,
+        CLT_40GBE,
+        CLT_100GBE
+    }
+
+    private final SignalType signalType;
+
+
+    /**
+     * Creates an ODU client port in the specified network element.
+     *
+     * @param element           parent network element
+     * @param number            port number
+     * @param isEnabled         port enabled state
+     * @param signalType        ODU client signal type
+     * @param annotations       optional key/value annotations
+     */
+    public OduCltPort(Element element, PortNumber number, boolean isEnabled,
+                      SignalType signalType, Annotations... annotations) {
+        super(element, number, isEnabled, Type.ODUCLT, 0, annotations);
+        this.signalType = signalType;
+    }
+
+    /**
+     * Returns ODU client signal type.
+     *
+     * @return ODU client signal type
+     */
+    public SignalType signalType() {
+        return signalType;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(number(), isEnabled(), type(), signalType, annotations());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof OduCltPort) {
+            final OduCltPort other = (OduCltPort) obj;
+            return Objects.equals(this.element().id(), other.element().id()) &&
+                    Objects.equals(this.number(), other.number()) &&
+                    Objects.equals(this.isEnabled(), other.isEnabled()) &&
+                    Objects.equals(this.signalType, other.signalType) &&
+                    Objects.equals(this.annotations(), other.annotations());
+        }
+        return false;
+    }
+
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("element", element().id())
+                .add("number", number())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("signalType", signalType)
+                .toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/OmsPort.java b/core/api/src/main/java/org/onosproject/net/OmsPort.java
new file mode 100644
index 0000000..753834b
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/OmsPort.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net;
+
+import org.onlab.util.Frequency;
+
+import java.util.Objects;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * Implementation of OMS port (Optical Multiplexing Section).
+ * Also referred to as a WDM port or W-port.
+ * See ITU G.709 "Interfaces for the Optical Transport Network (OTN)"
+ *
+ * Assumes we only support fixed grid for now.
+ */
+public class OmsPort extends DefaultPort {
+
+    private final Frequency minFrequency;     // Minimum frequency
+    private final Frequency maxFrequency;     // Maximum frequency
+    private final Frequency grid;             // Grid spacing frequency
+
+
+    /**
+     * Creates an OMS port in the specified network element.
+     *
+     * @param element       parent network element
+     * @param number        port number
+     * @param isEnabled     port enabled state
+     * @param minFrequency  minimum frequency
+     * @param maxFrequency  maximum frequency
+     * @param grid          grid spacing frequency
+     * @param annotations   optional key/value annotations
+     */
+    public OmsPort(Element element, PortNumber number, boolean isEnabled,
+                   Frequency minFrequency, Frequency maxFrequency, Frequency grid, Annotations... annotations) {
+        super(element, number, isEnabled, Type.OMS, 0, annotations);
+        this.minFrequency = minFrequency;
+        this.maxFrequency = maxFrequency;
+        this.grid = grid;
+    }
+
+    /**
+     * Returns the total number of channels on the port.
+     *
+     * @return total number of channels
+     */
+    public short totalChannels() {
+        Frequency diff = maxFrequency.subtract(minFrequency);
+        return (short) (diff.asHz() / (grid.asHz() + 1));
+    }
+
+    /**
+     * Returns the minimum frequency.
+     *
+     * @return minimum frequency
+     */
+    public Frequency minFrequency() {
+        return minFrequency;
+    }
+
+    /**
+     * Returns the maximum frequency.
+     *
+     * @return maximum frequency
+     */
+    public Frequency maxFrequency() {
+        return maxFrequency;
+    }
+
+    /**
+     * Returns the grid spacing frequency.
+     *
+     * @return grid spacing frequency
+     */
+    public Frequency grid() {
+        return grid;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(number(), isEnabled(), type(),
+                minFrequency, maxFrequency, grid, annotations());
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj instanceof OmsPort) {
+            final OmsPort other = (OmsPort) obj;
+            return Objects.equals(this.element().id(), other.element().id()) &&
+                    Objects.equals(this.number(), other.number()) &&
+                    Objects.equals(this.isEnabled(), other.isEnabled()) &&
+                    Objects.equals(this.minFrequency, other.minFrequency) &&
+                    Objects.equals(this.maxFrequency, other.maxFrequency) &&
+                    Objects.equals(this.grid, other.grid) &&
+                    Objects.equals(this.annotations(), other.annotations());
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        return toStringHelper(this)
+                .add("element", element().id())
+                .add("number", number())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("minFrequency", minFrequency)
+                .add("maxFrequency", maxFrequency)
+                .add("grid", grid)
+                .toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/Port.java b/core/api/src/main/java/org/onosproject/net/Port.java
index dd51448..70b05d7 100644
--- a/core/api/src/main/java/org/onosproject/net/Port.java
+++ b/core/api/src/main/java/org/onosproject/net/Port.java
@@ -54,7 +54,6 @@
          * Optical Multiplexing Section (See ITU G.709).
          */
         OMS
-
     }
 
     /**
diff --git a/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java b/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java
index a615456..e86b50c 100644
--- a/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java
+++ b/core/api/src/main/java/org/onosproject/net/SparseAnnotations.java
@@ -34,7 +34,7 @@
 
     /**
      * Indicates whether the specified key has been tagged as removed. This is
-     * used to for merging sparse annotation sets.
+     * used for merging sparse annotation sets.
      *
      * @param key annotation key
      * @return true if the previous annotation has been tagged for removal
diff --git a/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java b/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java
new file mode 100644
index 0000000..c13a004
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/device/OchPortDescription.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable OCh port description.
+ */
+public class OchPortDescription extends DefaultPortDescription {
+
+    private final OchPort.SignalType signalType;
+    private final boolean isTunable;
+    private final OchPort.GridType gridType;
+    private final OchPort.ChannelSpacing channelSpacing;
+    // Frequency = 193.1 THz + spacingMultiplier * channelSpacing
+    private final int spacingMultiplier;
+    // Slot width = slotGranularity * 12.5 GHz
+    private final int slotGranularity;
+
+    /**
+     * Creates OCH port description based on the supplied information.
+     *
+     * @param number            port number
+     * @param isEnabled         port enabled state
+     * @param signalType        ODU signal type
+     * @param isTunable         tunable wavelength capability
+     * @param gridType          grid type
+     * @param channelSpacing    channel spacing
+     * @param spacingMultiplier channel spacing multiplier
+     * @param slotGranularity   slow width granularity
+     * @param annotations       optional key/value annotations map
+     */
+    public OchPortDescription(PortNumber number, boolean isEnabled, OchPort.SignalType signalType,
+                              boolean isTunable, OchPort.GridType gridType,
+                              OchPort.ChannelSpacing channelSpacing,
+                              int spacingMultiplier, int slotGranularity, SparseAnnotations... annotations) {
+        super(number, isEnabled, Port.Type.OCH, 0, annotations);
+        this.signalType = signalType;
+        this.isTunable = isTunable;
+        this.gridType = gridType;
+        this.channelSpacing = channelSpacing;
+        this.spacingMultiplier = spacingMultiplier;
+        this.slotGranularity = slotGranularity;
+    }
+
+    /**
+     * Creates OCH port description based on the supplied information.
+     *
+     * @param base              PortDescription to get basic information from
+     * @param signalType        ODU signal type
+     * @param isTunable         tunable wavelength capability
+     * @param gridType          grid type
+     * @param channelSpacing    channel spacing
+     * @param spacingMultiplier channel spacing multiplier
+     * @param slotGranularity   slot width granularity
+     * @param annotations       optional key/value annotations map
+     */
+    public OchPortDescription(PortDescription base, OchPort.SignalType signalType, boolean isTunable,
+                              OchPort.GridType gridType, OchPort.ChannelSpacing channelSpacing,
+                              int spacingMultiplier, int slotGranularity, SparseAnnotations annotations) {
+        super(base, annotations);
+        this.signalType = signalType;
+        this.isTunable = isTunable;
+        this.gridType = gridType;
+        this.channelSpacing = channelSpacing;
+        this.spacingMultiplier = spacingMultiplier;
+        this.slotGranularity = slotGranularity;
+    }
+
+    /**
+     * Returns ODU signal type.
+     *
+     * @return ODU signal type
+     */
+    public OchPort.SignalType signalType() {
+        return signalType;
+    }
+
+    /**
+     * Returns true if port is wavelength tunable.
+     *
+     * @return tunable wavelength capability
+     */
+    public boolean isTunable() {
+        return isTunable;
+    }
+
+    /**
+     * Returns grid type.
+     *
+     * @return grid type
+     */
+    public OchPort.GridType gridType() {
+        return gridType;
+    }
+
+    /**
+     * Returns channel spacing.
+     *
+     * @return channel spacing
+     */
+    public OchPort.ChannelSpacing channelSpacing() {
+        return channelSpacing;
+    }
+
+    /**
+     * Returns channel spacing multiplier.
+     *
+     * @return channel spacing multiplier
+     */
+    public int spacingMultiplier() {
+        return spacingMultiplier;
+    }
+
+    /**
+     * Returns slot width granularity.
+     *
+     * @return slot width granularity
+     */
+    public int slotGranularity() {
+        return slotGranularity;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("number", portNumber())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("signalType", signalType)
+                .add("isTunable", isTunable)
+                .add("gridType", gridType)
+                .add("channelSpacing", channelSpacing)
+                .add("spacingMultiplier", spacingMultiplier)
+                .add("slotGranularity", slotGranularity)
+                .add("annotations", annotations())
+                .toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java b/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java
new file mode 100644
index 0000000..eee7de2
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/device/OduCltPortDescription.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable ODU client port description.
+ */
+public class OduCltPortDescription extends DefaultPortDescription {
+
+    private final OduCltPort.SignalType signalType;
+
+    /**
+     * Creates ODU client port description based on the supplied information.
+     *
+     * @param number        port number
+     * @param isEnabled     port enabled state
+     * @param signalType    ODU client signal type
+     * @param annotations   optional key/value annotations map
+     */
+    public OduCltPortDescription(PortNumber number, boolean isEnabled, OduCltPort.SignalType signalType,
+                                 SparseAnnotations... annotations) {
+        super(number, isEnabled, Port.Type.ODUCLT, 0, annotations);
+        this.signalType = signalType;
+    }
+
+    /**
+     * Creates ODU client port description based on the supplied information.
+     *
+     * @param base          PortDescription to get basic information from
+     * @param signalType    ODU client signal type
+     * @param annotations   optional key/value annotations map
+     */
+    public OduCltPortDescription(PortDescription base, OduCltPort.SignalType signalType,
+                                 SparseAnnotations annotations) {
+        super(base, annotations);
+        this.signalType = signalType;
+    }
+
+    /**
+     * Returns ODU client signal type.
+     *
+     * @return ODU client signal type
+     */
+    public OduCltPort.SignalType signalType() {
+        return signalType;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("number", portNumber())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("signalType", signalType)
+                .toString();
+    }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java b/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java
new file mode 100644
index 0000000..131314a
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/device/OmsPortDescription.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.device;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Frequency;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+
+/**
+ * Default implementation of immutable OMS port description.
+ */
+public class OmsPortDescription extends DefaultPortDescription {
+
+    private final Frequency minFrequency;
+    private final Frequency maxFrequency;
+    private final Frequency grid;
+
+    /**
+     * Creates OMS port description based on the supplied information.
+     *
+     * @param number        port number
+     * @param isEnabled     port enabled state
+     * @param minFrequency  minimum frequency
+     * @param maxFrequency  maximum frequency
+     * @param grid          grid spacing frequency
+     * @param annotations   optional key/value annotations map
+     */
+    public OmsPortDescription(PortNumber number, boolean isEnabled, Frequency minFrequency, Frequency maxFrequency,
+                              Frequency grid, SparseAnnotations... annotations) {
+        super(number, isEnabled, Port.Type.OMS, 0, annotations);
+        this.minFrequency = minFrequency;
+        this.maxFrequency = maxFrequency;
+        this.grid = grid;
+    }
+
+    /**
+     * Creates OMS port description based on the supplied information.
+     *
+     * @param base          PortDescription to get basic information from
+     * @param minFrequency  minimum frequency
+     * @param maxFrequency  maximum frequency
+     * @param grid          grid spacing frequency
+     * @param annotations   optional key/value annotations map
+     */
+    public OmsPortDescription(PortDescription base, Frequency minFrequency, Frequency maxFrequency,
+                              Frequency grid, SparseAnnotations annotations) {
+        super(base, annotations);
+        this.minFrequency = minFrequency;
+        this.maxFrequency = maxFrequency;
+        this.grid = grid;
+    }
+
+    /**
+     * Returns minimum frequency.
+     *
+     * @return minimum frequency
+     */
+    public Frequency minFrequency() {
+        return minFrequency;
+    }
+
+    /**
+     * Returns maximum frequency.
+     *
+     * @return maximum frequency
+     */
+    public Frequency maxFrequency() {
+        return maxFrequency;
+    }
+
+    /**
+     * Returns grid spacing frequency.
+     *
+     * @return grid spacing frequency
+     */
+    public Frequency grid() {
+        return grid;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("number", portNumber())
+                .add("isEnabled", isEnabled())
+                .add("type", type())
+                .add("minFrequency", minFrequency)
+                .add("maxFrequency", maxFrequency)
+                .add("grid", grid)
+                .add("annotations", annotations())
+                .toString();
+    }
+
+}
+
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java
index 5d5a463..60d09fb 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/DefaultPortSerializer.java
@@ -15,8 +15,10 @@
  */
 package org.onosproject.store.serializers;
 
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DefaultPort;
 import org.onosproject.net.Element;
+import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 
 import com.esotericsoftware.kryo.Kryo;
@@ -43,15 +45,21 @@
         kryo.writeClassAndObject(output, object.element());
         kryo.writeObject(output, object.number());
         output.writeBoolean(object.isEnabled());
+        kryo.writeObject(output, object.type());
+        output.writeLong(object.portSpeed());
+        kryo.writeClassAndObject(output, object.annotations());
     }
 
     @Override
-    public DefaultPort read(Kryo kryo, Input input,
-            Class<DefaultPort> type) {
+    public DefaultPort read(Kryo kryo, Input input, Class<DefaultPort> aClass) {
         Element element = (Element) kryo.readClassAndObject(input);
         PortNumber number = kryo.readObject(input, PortNumber.class);
         boolean isEnabled = input.readBoolean();
+        Port.Type type = kryo.readObject(input, Port.Type.class);
+        long portSpeed = input.readLong();
+        Annotations annotations = (Annotations) kryo.readClassAndObject(input);
 
-        return new DefaultPort(element, number, isEnabled);
+        return new DefaultPort(element, number, isEnabled, type, portSpeed, annotations);
     }
+
 }
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 17eb374..a918e2d 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -28,6 +28,7 @@
 import org.onlab.packet.IpPrefix;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
+import org.onlab.util.Frequency;
 import org.onlab.util.KryoNamespace;
 import org.onosproject.app.ApplicationState;
 import org.onosproject.cluster.ControllerNode;
@@ -41,6 +42,7 @@
 import org.onosproject.core.DefaultGroupId;
 import org.onosproject.core.Version;
 import org.onosproject.mastership.MastershipTerm;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.DefaultDevice;
@@ -55,6 +57,9 @@
 import org.onosproject.net.HostLocation;
 import org.onosproject.net.Link;
 import org.onosproject.net.LinkKey;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OmsPort;
 import org.onosproject.net.Port;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.device.DefaultDeviceDescription;
@@ -348,8 +353,10 @@
                     AnnotationConstraint.class,
                     BooleanConstraint.class,
                     IntentOperation.class,
-                    FlowRuleExtPayLoad.class
-                    )
+                    FlowRuleExtPayLoad.class,
+                    Frequency.class,
+                    DefaultAnnotations.class
+            )
             .register(new DefaultApplicationIdSerializer(), DefaultApplicationId.class)
             .register(new URISerializer(), URI.class)
             .register(new NodeIdSerializer(), NodeId.class)
@@ -365,6 +372,14 @@
             .register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class)
             .register(Versioned.class)
             .register(DefaultGroupId.class)
+            .register(Annotations.class)
+            .register(OmsPort.class)
+            .register(OchPort.class)
+            .register(OchPort.SignalType.class)
+            .register(OchPort.GridType.class)
+            .register(OchPort.ChannelSpacing.class)
+            .register(OduCltPort.class)
+            .register(OduCltPort.SignalType.class)
             .register(
                     MplsIntent.class,
                     MplsPathIntent.class,
@@ -373,7 +388,7 @@
                     MplsLabel.class,
                     org.onlab.packet.MplsLabel.class,
                     org.onlab.packet.MPLS.class
-                    )
+            )
 
             .build();
 
diff --git a/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java b/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
index 9ac35a3..379249d 100644
--- a/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
+++ b/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
@@ -24,6 +24,7 @@
 import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
+import org.onlab.util.Frequency;
 import org.onosproject.cluster.NodeId;
 import org.onosproject.cluster.RoleInfo;
 import org.onosproject.core.DefaultGroupId;
@@ -40,6 +41,9 @@
 import org.onosproject.net.Link;
 import org.onosproject.net.Link.Type;
 import org.onosproject.net.LinkKey;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OmsPort;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.SparseAnnotations;
 import org.onosproject.net.flow.DefaultFlowRule;
@@ -177,6 +181,28 @@
     }
 
     @Test
+    public void testOmsPort() {
+        testSerializedEquals(new OmsPort(DEV1, P1, true, Frequency.ofGHz(190_100), Frequency.ofGHz(197_300),
+                Frequency.ofGHz(100)));
+        testSerializedEquals(new OmsPort(DEV1, P1, true, Frequency.ofGHz(190_100), Frequency.ofGHz(197_300),
+                Frequency.ofGHz(100), A1_2));
+    }
+
+    @Test
+    public void testOchPort() {
+        testSerializedEquals(new OchPort(DEV1, P1, true, OchPort.SignalType.ODU0, false, OchPort.GridType.DWDM,
+                OchPort.ChannelSpacing.CHL_100GHZ, -8, 4));
+        testSerializedEquals(new OchPort(DEV1, P1, true, OchPort.SignalType.ODU0, false, OchPort.GridType.DWDM,
+                OchPort.ChannelSpacing.CHL_100GHZ, -8, 4, A1_2));
+    }
+
+    @Test
+    public void testOduCltPort() {
+        testSerializedEquals(new OduCltPort(DEV1, P1, true, OduCltPort.SignalType.CLT_10GBE));
+        testSerializedEquals(new OduCltPort(DEV1, P1, true, OduCltPort.SignalType.CLT_10GBE, A1_2));
+    }
+
+    @Test
     public void testDeviceId() {
         testSerializedEquals(DID1);
     }