Linc-OE ports now identifiable as Och and OMS ports.
Reference: ONOS-1803
Conflicts:
utils/misc/src/main/java/org/onlab/util/Frequency.java
Change-Id: Ie2bdf74f8198afbd58a4762ff97bff6f4e9010df
diff --git a/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java b/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java
index 24c21d0..fd7fcd8 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/device/impl/DeviceDescriptions.java
@@ -28,6 +28,9 @@
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
+import org.onosproject.net.device.OchPortDescription;
+import org.onosproject.net.device.OduCltPortDescription;
+import org.onosproject.net.device.OmsPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.store.Timestamp;
import org.onosproject.store.impl.Timestamped;
@@ -97,9 +100,34 @@
if (oldOne != null) {
SparseAnnotations merged = union(oldOne.value().annotations(),
newDesc.value().annotations());
- newOne = new Timestamped<PortDescription>(
- new DefaultPortDescription(newDesc.value(), merged),
- newDesc.timestamp());
+ newOne = null;
+ switch (newDesc.value().type()) {
+ case OMS:
+ OmsPortDescription omsDesc = (OmsPortDescription) (newDesc.value());
+ newOne = new Timestamped<PortDescription>(
+ new OmsPortDescription(
+ omsDesc, omsDesc.minFrequency(), omsDesc.maxFrequency(), omsDesc.grid(), merged),
+ newDesc.timestamp());
+ break;
+ case OCH:
+ OchPortDescription ochDesc = (OchPortDescription) (newDesc.value());
+ newOne = new Timestamped<PortDescription>(
+ new OchPortDescription(
+ ochDesc, ochDesc.signalType(), ochDesc.isTunable(), ochDesc.lambda(), merged),
+ newDesc.timestamp());
+ break;
+ case ODUCLT:
+ OduCltPortDescription ocDesc = (OduCltPortDescription) (newDesc.value());
+ newOne = new Timestamped<PortDescription>(
+ new OduCltPortDescription(
+ ocDesc, ocDesc.signalType(), merged),
+ newDesc.timestamp());
+ break;
+ default:
+ newOne = new Timestamped<PortDescription>(
+ new DefaultPortDescription(newDesc.value(), merged),
+ newDesc.timestamp());
+ }
}
portDescs.put(newOne.value().portNumber(), newOne);
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
index 8852c49..f7f459c 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
@@ -717,7 +717,6 @@
public synchronized DeviceEvent updatePortStatus(ProviderId providerId,
DeviceId deviceId,
PortDescription portDescription) {
-
final Timestamp newTimestamp;
try {
newTimestamp = deviceClockService.getTimestamp(deviceId);
@@ -1000,13 +999,14 @@
// if no primary, assume not enabled
boolean isEnabled = false;
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
-
+ Timestamp newest = null;
final Timestamped<PortDescription> portDesc = primDescs.getPortDesc(number);
if (portDesc != null) {
isEnabled = portDesc.value().isEnabled();
annotations = merge(annotations, portDesc.value().annotations());
+ newest = portDesc.timestamp();
}
-
+ Port updated = null;
for (Entry<ProviderId, DeviceDescriptions> e : descsMap.entrySet()) {
if (e.getKey().equals(primary)) {
continue;
@@ -1019,30 +1019,35 @@
// annotation merging. not so efficient, should revisit later
final Timestamped<PortDescription> otherPortDesc = e.getValue().getPortDesc(number);
if (otherPortDesc != null) {
+ if (newest != null && newest.isNewerThan(otherPortDesc.timestamp())) {
+ continue;
+ }
annotations = merge(annotations, otherPortDesc.value().annotations());
+ switch (otherPortDesc.value().type()) {
+ case OMS:
+ OmsPortDescription omsPortDesc = (OmsPortDescription) otherPortDesc.value();
+ updated = new OmsPort(device, number, isEnabled, omsPortDesc.minFrequency(),
+ omsPortDesc.maxFrequency(), omsPortDesc.grid());
+ break;
+ case OCH:
+ OchPortDescription ochPortDesc = (OchPortDescription) otherPortDesc.value();
+ updated = new OchPort(device, number, isEnabled, ochPortDesc.signalType(),
+ ochPortDesc.isTunable(), ochPortDesc.lambda(), annotations);
+ break;
+ case ODUCLT:
+ OduCltPortDescription oduCltPortDesc = (OduCltPortDescription) otherPortDesc.value();
+ updated = new OduCltPort(device, number, isEnabled, oduCltPortDesc.signalType(), annotations);
+ break;
+ default:
+ updated = new DefaultPort(device, number, isEnabled, annotations);
+ }
+ newest = otherPortDesc.timestamp();
}
}
-
if (portDesc == null) {
- return new DefaultPort(device, number, false, annotations);
+ return updated == null ? new DefaultPort(device, number, false, annotations) : updated;
}
-
- switch (portDesc.value().type()) {
- case OMS:
- OmsPortDescription omsPortDesc = (OmsPortDescription) portDesc.value();
- return new OmsPort(device, number, isEnabled, omsPortDesc.minFrequency(),
- omsPortDesc.maxFrequency(), omsPortDesc.grid());
- case OCH:
- OchPortDescription ochPortDesc = (OchPortDescription) portDesc.value();
- return new OchPort(device, number, isEnabled, ochPortDesc.signalType(),
- ochPortDesc.isTunable(), ochPortDesc.lambda(), annotations);
- case ODUCLT:
- OduCltPortDescription oduCltPortDesc = (OduCltPortDescription) portDesc.value();
- return new OduCltPort(device, number, isEnabled, oduCltPortDesc.signalType(), annotations);
- default:
- return new DefaultPort(device, number, isEnabled, portDesc.value().type(),
- portDesc.value().portSpeed(), annotations);
- }
+ return updated == null ? new DefaultPort(device, number, isEnabled, annotations) : updated;
}
/**
diff --git a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
index c0dc9f8..2d9f4bb 100644
--- a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -342,7 +342,7 @@
if (sw.isOptical()) {
OpenFlowOpticalSwitch opsw = (OpenFlowOpticalSwitch) sw;
opsw.getPortTypes().forEach(type -> {
- LOG.info("ports: {}", opsw.getPortsOf(type));
+ LOG.debug("ports: {}", opsw.getPortsOf(type));
opsw.getPortsOf(type).forEach(
op -> {
portDescs.add(buildPortDescription(type, (OFPortOptical) op));
@@ -406,10 +406,10 @@
if (port.getVersion() == OFVersion.OF_13
&& ptype == PortDescPropertyType.OPTICAL_TRANSPORT) {
// At this point, not much is carried in the optical port message.
- LOG.info("Optical transport port message {}", port.toString());
+ LOG.debug("Optical transport port message {}", port.toString());
} else {
// removable once 1.4+ support complete.
- LOG.warn("Unsupported optical port properties");
+ LOG.debug("Unsupported optical port properties");
}
return new DefaultPortDescription(portNo, enabled, type, 0, annotations);
}
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/ConfigProvider.java b/web/api/src/main/java/org/onosproject/rest/resources/ConfigProvider.java
index f25531b..edbe310 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/ConfigProvider.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/ConfigProvider.java
@@ -17,19 +17,28 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.Lists;
+
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.util.Frequency;
+import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.GridType;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
import org.onosproject.net.Link;
import org.onosproject.net.MastershipRole;
+import org.onosproject.net.OchPort;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OduSignalType;
+import org.onosproject.net.OmsPort;
import org.onosproject.net.Port;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DefaultDeviceDescription;
@@ -41,6 +50,9 @@
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.OchPortDescription;
+import org.onosproject.net.device.OduCltPortDescription;
+import org.onosproject.net.device.OmsPortDescription;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.host.DefaultHostDescription;
import org.onosproject.net.host.HostProvider;
@@ -82,6 +94,10 @@
private static final String UNKNOWN = "unknown";
+ private static final Frequency CENTER = Frequency.ofTHz(193.1);
+ // C-band has 4.4 THz (4,400 GHz) total bandwidth
+ private static final Frequency TOTAL = Frequency.ofTHz(4.4);
+
private CountDownLatch deviceLatch;
private final JsonNode cfg;
@@ -200,6 +216,21 @@
// Parses the given node with port information.
private PortDescription parsePort(JsonNode node) {
Port.Type type = Port.Type.valueOf(node.path("type").asText("COPPER"));
+ switch (type) {
+ case COPPER:
+ return new DefaultPortDescription(portNumber(node.path("port").asLong(0)),
+ node.path("enabled").asBoolean(true),
+ type, node.path("speed").asLong(1_000));
+ case FIBER:
+ // Currently, assume OMS when FIBER. Provide sane defaults.
+ return new OmsPortDescription(portNumber(node.path("port").asLong(0)),
+ node.path("enabled").asBoolean(true),
+ CENTER,
+ CENTER.add(TOTAL),
+ Frequency.ofGHz(100));
+ default:
+ log.warn("{}: Unsupported Port Type");
+ }
return new DefaultPortDescription(portNumber(node.path("port").asLong(0)),
node.path("enabled").asBoolean(true),
type, node.path("speed").asLong(1_000));
@@ -224,7 +255,8 @@
ConnectPoint dst = connectPoint(get(node, "dst"));
Link.Type type = Link.Type.valueOf(get(node, "type", "DIRECT"));
SparseAnnotations annotations = annotations(node.get("annotations"));
-
+ // take annotations to update optical ports with correct attributes.
+ updatePorts(src, dst, annotations);
DefaultLinkDescription desc = reverse ?
new DefaultLinkDescription(dst, src, type, annotations) :
new DefaultLinkDescription(src, dst, type, annotations);
@@ -234,6 +266,98 @@
connectPoints.add(dst);
}
+ private void updatePorts(ConnectPoint src, ConnectPoint dst, SparseAnnotations annotations) {
+ DeviceId srcId = src.deviceId();
+ DeviceId dstId = dst.deviceId();
+ Port srcPort = deviceService.getPort(srcId, src.port());
+ Port dstPort = deviceService.getPort(dstId, dst.port());
+
+ final String linkType = annotations.value("optical.type");
+ if ("cross-connect".equals(linkType)) {
+ String value = annotations.value("bandwidth").trim();
+ try {
+ double bw = Double.parseDouble(value);
+ updateOchPort(bw, srcPort, dstPort, srcId, dstId);
+ } catch (NumberFormatException e) {
+ log.warn("Invalid bandwidth ({}), can't configure port(s)", value);
+ return;
+ }
+ } else if ("WDM".equals(linkType)) {
+ String value = annotations.value("optical.waves").trim();
+ try {
+ int numChls = Integer.parseInt(value);
+ updateOMSPorts(numChls, srcPort, dstPort, srcId, dstId);
+ } catch (NumberFormatException e) {
+ log.warn("Invalid channel ({}), can't configure port(s)", value);
+ return;
+ }
+ }
+ }
+
+ // uses 'bandwidth' annotation to determine the channel spacing.
+ private void updateOchPort(double bw, Port srcPort, Port dstPort, DeviceId srcId, DeviceId dstId) {
+ Device src = deviceService.getDevice(srcId);
+ Device dst = deviceService.getDevice(dstId);
+ // bandwidth in MHz (assuming Hz - linc is not clear if Hz or b).
+ Frequency spacing = Frequency.ofMHz(bw);
+ // channel bandwidth is smaller than smallest standard channel spacing.
+ ChannelSpacing chsp = null;
+ if (spacing.compareTo(ChannelSpacing.CHL_6P25GHZ.frequency()) <= 0) {
+ chsp = ChannelSpacing.CHL_6P25GHZ;
+ }
+ for (int i = 1; i < ChannelSpacing.values().length; i++) {
+ Frequency val = ChannelSpacing.values()[i].frequency();
+ // pick the next highest or equal channel interval.
+ if (val.isLessThan(spacing)) {
+ chsp = ChannelSpacing.values()[i - 1];
+ break;
+ }
+ }
+ if (chsp == null) {
+ log.warn("Invalid channel spacing ({}), can't configure port(s)", spacing);
+ return;
+ }
+ OchSignal signal = new OchSignal(GridType.DWDM, chsp, 1, 1);
+ if (src.type() == Device.Type.ROADM) {
+ PortDescription portDesc = new OchPortDescription(srcPort.number(), srcPort.isEnabled(),
+ OduSignalType.ODU4, true, signal);
+ deviceProviderService.portStatusChanged(srcId, portDesc);
+ }
+ if (dst.type() == Device.Type.ROADM) {
+ PortDescription portDesc = new OchPortDescription(dstPort.number(), dstPort.isEnabled(),
+ OduSignalType.ODU4, true, signal);
+ deviceProviderService.portStatusChanged(dstId, portDesc);
+ }
+ }
+
+ private void updateOMSPorts(int numChls, Port srcPort, Port dstPort, DeviceId srcId, DeviceId dstId) {
+ // round down to largest slot that allows numChl channels to fit into C
+ // band range
+ ChannelSpacing chl = null;
+ Frequency perChl = TOTAL.floorDivision(numChls);
+ for (int i = 0; i < ChannelSpacing.values().length; i++) {
+ Frequency val = ChannelSpacing.values()[i].frequency();
+ if (val.isLessThan(perChl)) {
+ chl = ChannelSpacing.values()[i];
+ break;
+ }
+ }
+ if (chl == null) {
+ chl = ChannelSpacing.CHL_6P25GHZ;
+ }
+
+ // if true, there was less channels than can be tightly packed.
+ Frequency grid = (chl == null) ? Frequency.ofGHz(100) : chl.frequency();
+ // say Linc's 1st slot starts at CENTER and goes up from there.
+ Frequency min = CENTER.add(grid);
+ Frequency max = CENTER.add(grid.multiply(numChls));
+
+ PortDescription srcPortDesc = new OmsPortDescription(srcPort.number(), srcPort.isEnabled(), min, max, grid);
+ PortDescription dstPortDesc = new OmsPortDescription(dstPort.number(), dstPort.isEnabled(), min, max, grid);
+ deviceProviderService.portStatusChanged(srcId, srcPortDesc);
+ deviceProviderService.portStatusChanged(dstId, dstPortDesc);
+ }
+
// Parses the given JSON and provides hosts as configured.
private void parseHosts() {
try {
@@ -298,15 +422,33 @@
// Creates a port description from the specified port.
private PortDescription description(Port p) {
- return new DefaultPortDescription(p.number(), p.isEnabled(), p.type(), p.portSpeed());
+ switch (p.type()) {
+ case OMS:
+ OmsPort op = (OmsPort) p;
+ return new OmsPortDescription(
+ op.number(), op.isEnabled(), op.minFrequency(), op.maxFrequency(), op.grid());
+ case OCH:
+ OchPort ochp = (OchPort) p;
+ return new OchPortDescription(
+ ochp.number(), ochp.isEnabled(), ochp.signalType(), ochp.isTunable(), ochp.lambda());
+ case ODUCLT:
+ OduCltPort odup = (OduCltPort) p;
+ return new OduCltPortDescription(
+ odup.number(), odup.isEnabled(), odup.signalType());
+ default:
+ return new DefaultPortDescription(p.number(), p.isEnabled(), p.type(), p.portSpeed());
+ }
}
// Creates a port description from the specified connection point.
private PortDescription description(ConnectPoint cp) {
- return new DefaultPortDescription(cp.port(), true);
+ Port p = deviceService.getPort(cp.deviceId(), cp.port());
+ if (p == null) {
+ return new DefaultPortDescription(cp.port(), true);
+ }
+ return description(p);
}
-
// Produces set of annotations from the given JSON node.
private SparseAnnotations annotations(JsonNode node) {
if (node == null) {