From 6a07d2d622eaa06953f3353e39c080984076e8de Mon Sep 17 00:00:00 2001 From: Ashlee Young Date: Fri, 9 Oct 2015 18:32:44 -0700 Subject: Updated master to commit id 6ee8aa3e67ce89908a8c93aa9445c6f71a18f986 Change-Id: I94b055ee2f298daf71e2ec794fd0f2495bd8081f --- .../of/device/impl/OpenFlowDeviceProvider.java | 227 ++++++++++++++++----- .../of/device/impl/OpenFlowDeviceValueMapper.java | 73 +++++++ .../of/device/impl/OpenFlowDeviceProviderTest.java | 3 +- 3 files changed, 253 insertions(+), 50 deletions(-) create mode 100644 framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceValueMapper.java (limited to 'framework/src/onos/providers/openflow/device') diff --git a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java index cb19dc52..4fa961f8 100644 --- a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java +++ b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java @@ -15,10 +15,24 @@ */ package org.onosproject.provider.of.device.impl; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Strings.isNullOrEmpty; +import static org.onlab.util.Tools.get; +import static org.onosproject.net.DeviceId.deviceId; +import static org.onosproject.net.Port.Type.COPPER; +import static org.onosproject.net.Port.Type.FIBER; +import static org.onosproject.openflow.controller.Dpid.dpid; +import static org.onosproject.openflow.controller.Dpid.uri; +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + import org.apache.felix.scr.annotations.Activate; import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Deactivate; @@ -28,15 +42,17 @@ import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.ReferenceCardinality; import org.onlab.packet.ChassisId; import org.onlab.util.Frequency; -import org.onosproject.cfg.ComponentConfigService; import org.onlab.util.Spectrum; +import org.onosproject.cfg.ComponentConfigService; import org.onosproject.net.AnnotationKeys; import org.onosproject.net.ChannelSpacing; import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.Device; import org.onosproject.net.DeviceId; import org.onosproject.net.GridType; import org.onosproject.net.MastershipRole; import org.onosproject.net.OchSignal; +import org.onosproject.net.OduCltPort; import org.onosproject.net.OduSignalType; import org.onosproject.net.Port; import org.onosproject.net.PortNumber; @@ -49,6 +65,7 @@ import org.onosproject.net.device.DeviceProvider; import org.onosproject.net.device.DeviceProviderRegistry; import org.onosproject.net.device.DeviceProviderService; 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.device.PortStatistics; @@ -64,13 +81,19 @@ import org.onosproject.openflow.controller.PortDescPropertyType; import org.onosproject.openflow.controller.RoleState; import org.osgi.service.component.ComponentContext; import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsEntry; +import org.projectfloodlight.openflow.protocol.OFExpPort; +import org.projectfloodlight.openflow.protocol.OFExpPortDescPropOpticalTransport; +import org.projectfloodlight.openflow.protocol.OFExpPortOpticalTransportLayerEntry; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFObject; import org.projectfloodlight.openflow.protocol.OFPortConfig; import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport; import org.projectfloodlight.openflow.protocol.OFPortFeatures; import org.projectfloodlight.openflow.protocol.OFPortOptical; +import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportLayerClass; +import org.projectfloodlight.openflow.protocol.OFPortOpticalTransportSignalType; import org.projectfloodlight.openflow.protocol.OFPortReason; import org.projectfloodlight.openflow.protocol.OFPortState; import org.projectfloodlight.openflow.protocol.OFPortStatsEntry; @@ -83,23 +106,10 @@ import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.PortSpeed; import org.slf4j.Logger; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Dictionary; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Strings.isNullOrEmpty; -import static org.onlab.util.Tools.get; -import static org.onosproject.net.DeviceId.deviceId; -import static org.onosproject.net.Port.Type.COPPER; -import static org.onosproject.net.Port.Type.FIBER; -import static org.onosproject.openflow.controller.Dpid.dpid; -import static org.onosproject.openflow.controller.Dpid.uri; -import static org.slf4j.LoggerFactory.getLogger; +import com.google.common.base.Strings; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; /** * Provider which uses an OpenFlow controller to detect network @@ -109,7 +119,11 @@ import static org.slf4j.LoggerFactory.getLogger; public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider { private static final Logger LOG = getLogger(OpenFlowDeviceProvider.class); + private static final long MBPS = 1_000 * 1_000; + private static final Frequency FREQ100 = Frequency.ofGHz(100); + private static final Frequency FREQ193_1 = Frequency.ofTHz(193.1); + private static final Frequency FREQ4_4 = Frequency.ofTHz(4.4); @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) protected DeviceProviderRegistry providerRegistry; @@ -145,27 +159,16 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr providerService = providerRegistry.register(this); controller.addListener(listener); controller.addEventListener(listener); - for (OpenFlowSwitch sw : controller.getSwitches()) { - try { - listener.switchAdded(new Dpid(sw.getId())); - } catch (Exception e) { - LOG.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage()); - LOG.debug("Error details:", e); - // disconnect to trigger switch-add later - sw.disconnectSwitch(); - } - PortStatsCollector psc = new PortStatsCollector(sw, portStatsPollFrequency); - psc.start(); - collectors.put(new Dpid(sw.getId()), psc); - } + connectInitialDevices(); LOG.info("Started"); } @Deactivate public void deactivate(ComponentContext context) { cfgService.unregisterProperties(getClass(), false); - providerRegistry.unregister(this); controller.removeListener(listener); + disconnectDevices(); + providerRegistry.unregister(this); collectors.values().forEach(PortStatsCollector::stop); providerService = null; LOG.info("Stopped"); @@ -191,13 +194,31 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr LOG.info("Settings: portStatsPollFrequency={}", portStatsPollFrequency); } + private void connectInitialDevices() { + for (OpenFlowSwitch sw : controller.getSwitches()) { + try { + listener.switchAdded(new Dpid(sw.getId())); + } catch (Exception e) { + LOG.warn("Failed initially adding {} : {}", sw.getStringId(), e.getMessage()); + LOG.debug("Error details:", e); + // disconnect to trigger switch-add later + sw.disconnectSwitch(); + } + PortStatsCollector psc = new PortStatsCollector(sw, portStatsPollFrequency); + psc.start(); + collectors.put(new Dpid(sw.getId()), psc); + } + } + + private void disconnectDevices() { + // Only disconnect the devices for which we are currently master. + controller.getMasterSwitches().forEach(sw -> listener.switchRemoved(new Dpid(sw.getId()))); + } + @Override public boolean isReachable(DeviceId deviceId) { OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri())); - if (sw == null || !sw.isConnected()) { - return false; - } - return true; + return sw != null && sw.isConnected(); } @Override @@ -302,8 +323,9 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr ChassisId cId = new ChassisId(dpid.value()); SparseAnnotations annotations = DefaultAnnotations.builder() - .set("protocol", sw.factory().getVersion().toString()) - .set("channelId", sw.channelId()) + .set(AnnotationKeys.PROTOCOL, sw.factory().getVersion().toString()) + .set(AnnotationKeys.CHANNEL_ID, sw.channelId()) + .set(AnnotationKeys.MANAGEMENT_ADDRESS, sw.channelId().split(":")[0]) .build(); DeviceDescription description = @@ -386,18 +408,27 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr */ private List buildPortDescriptions(OpenFlowSwitch sw) { final List portDescs = new ArrayList<>(sw.getPorts().size()); - sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port))); + if (!(Device.Type.ROADM.equals(sw.deviceType()))) { + sw.getPorts().forEach(port -> portDescs.add(buildPortDescription(port))); + } OpenFlowOpticalSwitch opsw; switch (sw.deviceType()) { case ROADM: opsw = (OpenFlowOpticalSwitch) sw; + List ports = opsw.getPorts(); + LOG.debug("SW ID {} , ETH- ODU CLT Ports {}", opsw.getId(), ports); + // ODU client ports are reported as ETH + ports.forEach(port -> portDescs.add(buildOduCltPortDescription(port))); + opsw.getPortTypes().forEach(type -> { - opsw.getPortsOf(type).forEach( - op -> { - portDescs.add(buildPortDescription(type, (OFPortOptical) op)); - } - ); + List portsOf = opsw.getPortsOf(type); + LOG.debug("Ports Of{}", portsOf); + portsOf.forEach( + op -> { + portDescs.add(buildPortDescription(type, (OFObject) op)); + } + ); }); break; case FIBER_SWITCH: @@ -417,6 +448,105 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr return portDescs; } + private PortDescription buildOduCltPortDescription(OFPortDesc port) { + PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); + boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) && + !port.getConfig().contains(OFPortConfig.PORT_DOWN); + Long portSpeed = portSpeed(port); + OduCltPort.SignalType sigType = null; + + switch (portSpeed.toString()) { + case "1": + sigType = OduCltPort.SignalType.CLT_1GBE; + break; + case "10": + sigType = OduCltPort.SignalType.CLT_10GBE; + break; + case "40": + sigType = OduCltPort.SignalType.CLT_40GBE; + break; + case "100": + sigType = OduCltPort.SignalType.CLT_100GBE; + break; + default: + throw new RuntimeException("Un recognize OduClt speed: " + portSpeed.toString()); + } + + SparseAnnotations annotations = buildOduCltAnnotation(port); + return new OduCltPortDescription(portNo, enabled, sigType, annotations); + } + + private SparseAnnotations buildOduCltAnnotation(OFPortDesc port) { + SparseAnnotations annotations = null; + String portName = Strings.emptyToNull(port.getName()); + if (portName != null) { + annotations = DefaultAnnotations.builder() + .set(AnnotationKeys.PORT_NAME, portName) + .set(AnnotationKeys.STATIC_PORT, Boolean.TRUE.toString()).build(); + } + return annotations; + } + + private PortDescription buildPortDescription(PortDescPropertyType ptype, OFObject port) { + if (port instanceof OFPortOptical) { + return buildPortDescription(ptype, (OFPortOptical) port); + } + return buildPortDescription(ptype, (OFExpPort) port); + } + + /** + * Build a portDescription from a given a port description describing some + * Optical port. + * + * @param ptype description property type. + * @param port the port to build from. + * @return portDescription for the port. + */ + private PortDescription buildPortDescription(PortDescPropertyType ptype, OFExpPort port) { + PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber()); + boolean enabled = !port.getState().contains(OFPortState.LINK_DOWN) + && !port.getConfig().contains(OFPortConfig.PORT_DOWN); + SparseAnnotations annotations = makePortNameAnnotation(port.getName()); + + OFExpPortDescPropOpticalTransport firstProp = port.getProperties().get(0); + OFPortOpticalTransportSignalType sigType = firstProp.getPortSignalType(); + + DefaultPortDescription portDes = null; + switch (sigType) { + case OMSN: + portDes = new OmsPortDescription(portNo, enabled, FREQ193_1, FREQ193_1.add(FREQ4_4), + FREQ100, annotations); + break; + case OCH: + OFExpPortOpticalTransportLayerEntry entry = firstProp.getFeatures().get(0).getValue().get(0); + OFPortOpticalTransportLayerClass layerClass = entry.getLayerClass(); + if (!OFPortOpticalTransportLayerClass.ODU.equals(layerClass)) { + LOG.error("Unsupported layer Class {} ", layerClass); + return null; + } + + // convert to ONOS OduSignalType + OduSignalType oduSignalType = OpenFlowDeviceValueMapper. + lookupOduSignalType((byte) entry.getSignalType()); + //OchSignal is needed for OchPortDescription constructor, + //yet not relevant for tunable OCH port, creating with default parameters + OchSignal signalId = new OchSignal(GridType.DWDM, ChannelSpacing.CHL_50GHZ, 1, 1); + + portDes = new OchPortDescription(portNo, enabled, + oduSignalType, true, signalId, annotations); + + break; + case OTU2: + case OTU4: + LOG.error("Signal tpye OTU2/4 not supported yet ", port.toString()); + break; + default: + break; + } + + return portDes; + } + /** * Creates an annotation for the port name if one is available. * @@ -565,5 +695,4 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr } } } - } diff --git a/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceValueMapper.java b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceValueMapper.java new file mode 100644 index 00000000..7bdf06fd --- /dev/null +++ b/framework/src/onos/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceValueMapper.java @@ -0,0 +1,73 @@ +/* + * 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.provider.of.device.impl; + +import org.onosproject.net.OduSignalType; + +import com.google.common.collect.BiMap; +import com.google.common.collect.EnumHashBiMap; + +/** + * Collection of helper methods to convert protocol agnostic models to values used in OpenFlow spec. + */ +final class OpenFlowDeviceValueMapper { + + // prohibit instantiation + private OpenFlowDeviceValueMapper() {} + + private static final BiMap ODU_SIGNAL_TYPES = EnumHashBiMap.create(OduSignalType.class); + static { + // See ONF "Optical Transport Protocol Extensions Version 1.0" for the following values + ODU_SIGNAL_TYPES.put(OduSignalType.ODU1, (byte) 1); // OFPODUT_ODU1 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU2, (byte) 2); // OFPODUT_ODU2 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU3, (byte) 3); // OFPODUT_ODU3 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU4, (byte) 4); // OFPODUT_ODU4 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU0, (byte) 10); // OFPODUT_ODU0 of enum ofp_odu_signal_type + ODU_SIGNAL_TYPES.put(OduSignalType.ODU2e, (byte) 11); // OFPODUT_ODU2E of enum ofp_odu_signal_type + } + + /** + * Looks up the specified input value to the corresponding value with the specified map. + * + * @param map bidirectional mapping + * @param input input value + * @param cls class of output value + * @param type of input value + * @param type of output value + * @return the corresponding value stored in the specified map + */ + private static O lookup(BiMap map, I input, Class cls) { + if (!map.containsKey(input)) { + throw new RuntimeException( + String.format("No mapping found for %s when converting to %s", input, cls.getName())); + } + + return map.get(input); + } + + /** + * Looks up the the corresponding {@link OduSignalType} instance + * from the specified byte value for ODU signal type defined in + * ONF "Optical Transport Protocol Extensions Version 1.0". + * + * @param signalType byte value as ODU (Optical channel Data Unit) signal type defined the spec + * @return the corresponding OchSignalType instance + */ + static OduSignalType lookupOduSignalType(byte signalType) { + return lookup(ODU_SIGNAL_TYPES.inverse(), signalType, OduSignalType.class); + } + +} diff --git a/framework/src/onos/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java b/framework/src/onos/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java index 7b4d7922..d0838bb8 100644 --- a/framework/src/onos/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java +++ b/framework/src/onos/providers/openflow/device/src/test/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProviderTest.java @@ -16,6 +16,7 @@ package org.onosproject.provider.of.device.impl; import com.google.common.collect.HashMultimap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Multimap; @@ -236,7 +237,7 @@ public class OpenFlowDeviceProviderTest { @Override public Iterable getMasterSwitches() { - return null; + return ImmutableSet.of(); } @Override -- cgit 1.2.3-korg