Yafit Hadar
Committed by Gerrit Code Review

[Emu] Open Flow Optical Port Description

Change-Id: I8da4d7a1e1dea18d56cba9673f70b1ec69a5adcf
/*
* Copyright 2014 Open Networking Laboratory
* 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.
......@@ -22,8 +22,12 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onlab.util.Frequency;
import org.onosproject.cli.Comparators;
import org.onosproject.net.Device;
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.DeviceService;
......@@ -41,7 +45,10 @@ import static org.onosproject.net.DeviceId.deviceId;
description = "Lists all ports or all ports of a device")
public class DevicePortsListCommand extends DevicesListCommand {
private static final String FMT = " port=%s, state=%s, type=%s, speed=%s%s";
private static final String FMT = " port=%s, state=%s, type=%s, speed=%s %s";
private static final String FMT_OCH = " port=%s, state=%s, type=%s, signalType=%s, isTunable=%s %s";
private static final String FMT_ODUCLT = " port=%s, state=%s, type=%s, signalType=%s %s";
private static final String FMT_OMS = " port=%s, state=%s, type=%s, Freqs= %s / %s / %s GHz, totalChannels=%s %s";
@Option(name = "-e", aliases = "--enabled", description = "Show only enabled ports",
required = false, multiValued = false)
......@@ -137,13 +144,34 @@ public class DevicePortsListCommand extends DevicesListCommand {
List<Port> ports = new ArrayList<>(service.getPorts(device.id()));
Collections.sort(ports, Comparators.PORT_COMPARATOR);
for (Port port : ports) {
if (isIncluded(port)) {
print(FMT, portName(port.number()),
port.isEnabled() ? "enabled" : "disabled",
port.type().toString().toLowerCase(), port.portSpeed(),
annotations(port.annotations()));
if (!isIncluded(port)) {
continue;
}
String portName = portName(port.number());
Object portIsEnabled = port.isEnabled() ? "enabled" : "disabled";
String portType = port.type().toString().toLowerCase();
String annotations = annotations(port.annotations());
switch (port.type()) {
case OCH:
print(FMT_OCH, portName, portIsEnabled, portType,
((OchPort) port).signalType().toString(),
((OchPort) port).isTunable() ? "yes" : "no", annotations);
break;
case ODUCLT:
print(FMT_ODUCLT, portName, portIsEnabled, portType,
((OduCltPort) port).signalType().toString(), annotations);
break;
case OMS:
print(FMT_OMS, portName, portIsEnabled, portType,
((OmsPort) port).minFrequency().asHz() / Frequency.ofGHz(1).asHz(),
((OmsPort) port).maxFrequency().asHz() / Frequency.ofGHz(1).asHz(),
((OmsPort) port).grid().asHz() / Frequency.ofGHz(1).asHz(),
((OmsPort) port).totalChannels(), annotations);
break;
default:
print(FMT, portName, portIsEnabled, portType, port.portSpeed(), annotations);
break;
}
}
}
}
......
......@@ -15,8 +15,26 @@
*/
package org.onosproject.net.device.impl;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.Futures;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.MastershipRole.MASTER;
import static org.onosproject.net.MastershipRole.NONE;
import static org.onosproject.net.MastershipRole.STANDBY;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.DEVICE_READ;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
......@@ -26,12 +44,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.NodeId;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.basics.OpticalPortConfig;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
......@@ -44,6 +56,11 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.config.basics.OpticalPortConfig;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceAdminService;
......@@ -58,27 +75,11 @@ import org.onosproject.net.device.DeviceStore;
import org.onosproject.net.device.DeviceStoreDelegate;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.device.PortStatistics;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
import org.slf4j.Logger;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.MastershipRole.*;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
import com.google.common.util.concurrent.Futures;
/**
* Provides implementation of the device SB &amp; NB APIs.
......@@ -347,11 +348,15 @@ public class DeviceManager
log.info("Device {} disconnected from this node", deviceId);
List<Port> ports = store.getPorts(deviceId);
List<PortDescription> descs = Lists.newArrayList();
ports.forEach(port ->
descs.add(new DefaultPortDescription(port.number(),
false, port.type(),
port.portSpeed())));
final Device device = getDevice(deviceId);
List<PortDescription> descs = ports.stream().map(
port -> (!(Device.Type.ROADM.equals(device.type()))) ?
new DefaultPortDescription(port.number(), false,
port.type(), port.portSpeed()) :
OpticalPortOperator.descriptionOf(port, false)
).collect(Collectors.toList());
store.updatePorts(this.provider().id(), deviceId, descs);
try {
if (mastershipService.isLocalMaster(deviceId)) {
......@@ -430,6 +435,12 @@ public class DeviceManager
portDescription);
return;
}
final Device device = getDevice(deviceId);
if ((Device.Type.ROADM.equals(device.type()))) {
Port port = getPort(deviceId, portDescription.portNumber());
portDescription = OpticalPortOperator.descriptionOf(port, portDescription.isEnabled());
}
portDescription = consolidate(deviceId, portDescription);
final DeviceEvent event = store.updatePortStatus(this.provider().id(),
deviceId, portDescription);
......
......@@ -151,8 +151,25 @@ public final class OpticalPortOperator implements ConfigOperator {
*/
public static PortDescription descriptionOf(Port port) {
checkNotNull(port, "Must supply non-null Port");
final boolean isUp = port.isEnabled();
return descriptionOfPort(port, isUp);
}
/**
* Returns a description built from an existing port and reported status.
*
* @param port
* @param isEnabled
* @return a PortDescription based on the port
*/
static PortDescription descriptionOf(Port port, boolean isEnabled) {
checkNotNull(port, "Must supply non-null Port");
final boolean isup = isEnabled;
return descriptionOfPort(port, isup);
}
private static PortDescription descriptionOfPort(Port port, final boolean isup) {
final PortNumber ptn = port.number();
final boolean isup = port.isEnabled();
final SparseAnnotations an = (SparseAnnotations) port.annotations();
switch (port.type()) {
case OMS:
......
/*
* 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.driver.handshaker;
import org.projectfloodlight.openflow.protocol.OFExpPort;
import org.projectfloodlight.openflow.protocol.OFExpPortDescReply;
import org.projectfloodlight.openflow.protocol.OFExpPortDescRequest;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
import org.projectfloodlight.openflow.protocol.OFStatsType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import org.onosproject.net.Device;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
import org.projectfloodlight.openflow.protocol.OFObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
* Open Flow Optical Switch handshaker - for Open Flow 13.
*/
public class OFOpticalSwitch13 extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private List<OFExpPort> expPortDes = new ArrayList<>();
@Override
public Boolean supportNxRole() {
return false;
}
@Override
public void startDriverHandshake() {
log.info("Starting driver handshake for sw {}", getStringId());
if (startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeAlreadyStarted();
}
startDriverHandshakeCalled = true;
log.debug("sendHandshakeOFExperimenterPortDescRequest for sw {}", getStringId());
try {
sendHandshakeOFExperimenterPortDescRequest();
} catch (IOException e) {
log.error("Failed to send handshaker message OFExperimenterPortDescRequestfor sw {}, {}",
getStringId(), e.getMessage());
e.printStackTrace();
}
}
@Override
public void processDriverHandshakeMessage(OFMessage m) {
if (!startDriverHandshakeCalled) {
throw new SwitchDriverSubHandshakeNotStarted();
}
if (driverHandshakeComplete.get()) {
throw new SwitchDriverSubHandshakeCompleted(m);
}
log.debug("processDriverHandshakeMessage for sw {}", getStringId());
switch (m.getType()) {
case STATS_REPLY: // multipart message is reported as STAT
processOFMultipartReply((OFStatsReply) m);
break;
default:
log.warn("Received message {} during switch-driver " +
"subhandshake " + "from switch {} ... " +
"Ignoring message", m,
getStringId());
}
}
private void processOFMultipartReply(OFStatsReply stats) {
log.debug("Received message {} during switch-driver " +
"subhandshake " + "from switch {} ... " +
stats,
getStringId());
if (stats.getStatsType() == OFStatsType.EXPERIMENTER) {
try {
OFExpPortDescReply expPortDescReply = (OFExpPortDescReply) stats;
expPortDes.addAll(expPortDescReply.getEntries());
if (!expPortDescReply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) {
driverHandshakeComplete.set(true);
return;
}
} catch (ClassCastException e) {
log.error("Unexspected Experimenter Multipart message type {} "
, stats.getClass().getName());
}
}
}
@Override
public boolean isDriverHandshakeComplete() {
return driverHandshakeComplete.get();
}
private void sendHandshakeOFExperimenterPortDescRequest() throws
IOException {
OFExpPortDescRequest preq = factory()
.buildExpPortDescRequest()
.setXid(getNextTransactionId())
.build();
log.debug("Sending experimented port description " +
"message " +
"{}",
preq.toString());
this.sendHandshakeMessage(preq);
}
@Override
public Device.Type deviceType() {
return Device.Type.ROADM;
}
/*
* OduClt ports are reported as regular ETH ports.
*/
@Override
public List<OFPortDesc> getPorts() {
return ImmutableList.copyOf(
ports.stream().flatMap(p -> p.getEntries().stream())
.collect(Collectors.toList()));
}
@Override
public List<? extends OFObject> getPortsOf(PortDescPropertyType type) {
return ImmutableList.copyOf(expPortDes);
}
@Override
public Set<PortDescPropertyType> getPortTypes() {
return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
}
}
......@@ -120,5 +120,10 @@
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OpenVSwitchPipeline"/>
</driver>
<driver name="eci" extends="default"
manufacturer="ECI Telecom" hwVersion="optical" swVersion="V_1_0">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OFOpticalSwitch13"/>
</driver>
</drivers>
......
/*
* 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<OduSignalType, Byte> 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 <I> type of input value
* @param <O> type of output value
* @return the corresponding value stored in the specified map
*/
private static <I, O> O lookup(BiMap<I, O> map, I input, Class<O> 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);
}
}