mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-22 21:01:00 +02:00
[ONOS-7980] Lumentum ROADM-20 driver: aligned to distributed DeviceConnectionCache.
Supports the configuration of attenuation parameter using the ROADM app. Patch 2: fixed a conflict on RoadmManager.java Patch 3: checkstyle Patch 4: addressed comments by Andrea, checkstyle. Patch 5: addressed comments by Ramon, revised logging info. Patch 6: checkstyle. Change-Id: Id848220ef3a2cb5af6940cbca127a62d9afea2e2
This commit is contained in:
parent
9c9b06c3a8
commit
1bf2a63f4b
@ -593,11 +593,12 @@ public class RoadmManager implements RoadmService {
|
||||
}
|
||||
|
||||
// Delay the call to setTargetPower because the flow may not be in the store yet
|
||||
// Tested with Lumentum ROADM-20 1 seconds was not enough, increased to 5 seconds
|
||||
private void delayedSetAttenuation(DeviceId deviceId, PortNumber outPort,
|
||||
OchSignal ochSignal, long attenuation) {
|
||||
Runnable setAtt = () -> {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
TimeUnit.SECONDS.sleep(5);
|
||||
} catch (InterruptedException e) {
|
||||
log.warn("Thread interrupted. Setting attenuation early.");
|
||||
Thread.currentThread().interrupt();
|
||||
|
@ -5,6 +5,7 @@ COMPILE_DEPS = CORE_DEPS + [
|
||||
"//protocols/tl1/api:onos-protocols-tl1-api",
|
||||
"//protocols/netconf/api:onos-protocols-netconf-api",
|
||||
"//apps/optical-model:onos-apps-optical-model",
|
||||
"//drivers/odtn-driver:onos-drivers-odtn-driver",
|
||||
"//drivers/optical:onos-drivers-optical",
|
||||
]
|
||||
|
||||
@ -31,6 +32,8 @@ onos_app(
|
||||
"org.onosproject.optical-model",
|
||||
"org.onosproject.tl1",
|
||||
"org.onosproject.netconf",
|
||||
"org.onosproject.drivers.odtn-driver",
|
||||
"org.onosproject.drivers.netconf",
|
||||
"org.onosproject.drivers.optical",
|
||||
],
|
||||
title = "Lumentum Drivers",
|
||||
|
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017-present Open Networking Foundation
|
||||
*
|
||||
* 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.drivers.lumentum;
|
||||
|
||||
import org.onosproject.net.OchSignal;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Lumentum cross connection abstraction.
|
||||
*
|
||||
* Required to store all information needed by Lumentum device not included in CrossConnectFlowRule.
|
||||
*/
|
||||
public class LumentumConnection {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(LumentumConnection.class);
|
||||
|
||||
protected boolean isAddRule;
|
||||
protected int connectionId;
|
||||
protected int connectionModule;
|
||||
protected int hashCode;
|
||||
protected PortNumber inPortNumber;
|
||||
protected PortNumber outPortNumber;
|
||||
protected OchSignal ochSignal;
|
||||
|
||||
protected double attenuation;
|
||||
protected double targetAttenuation;
|
||||
protected double targetPower;
|
||||
protected double inputPower;
|
||||
protected double outputPower;
|
||||
|
||||
protected LumentumFlowRule rule;
|
||||
|
||||
//TODO: compute target attenuation to obtain the desired targetPower
|
||||
|
||||
/**
|
||||
* Builds a LumentumConnection.
|
||||
*
|
||||
* @param id the id retrieved from the device
|
||||
* @param flowRuleHash the hash code associated to the Flow Rule
|
||||
* @param xc the cross connect flow rule
|
||||
*/
|
||||
public LumentumConnection(Integer id, Integer flowRuleHash, LumentumFlowRule xc) {
|
||||
|
||||
connectionId = id;
|
||||
hashCode = flowRuleHash;
|
||||
|
||||
isAddRule = xc.isAddRule();
|
||||
ochSignal = xc.ochSignal();
|
||||
attenuation = 0.0; //dB
|
||||
inputPower = 0.0; //dBm
|
||||
outputPower = 0.0; //dBm
|
||||
rule = xc;
|
||||
|
||||
if (isAddRule) {
|
||||
outPortNumber = LumentumNetconfRoadmFlowRuleProgrammable.LINE_PORT_NUMBER;
|
||||
inPortNumber = xc.addDrop();
|
||||
} else {
|
||||
outPortNumber = xc.addDrop();
|
||||
inPortNumber = LumentumNetconfRoadmFlowRuleProgrammable.LINE_PORT_NUMBER;
|
||||
}
|
||||
|
||||
log.debug("Lumentum NETCONF inPort {} outPort {} ochSignal {}", inPortNumber, outPortNumber, xc.ochSignal());
|
||||
}
|
||||
|
||||
protected Integer getConnectionId() {
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
protected Integer getHash() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
protected void setAttenuation(double att) {
|
||||
attenuation = att;
|
||||
}
|
||||
|
||||
protected void setInputPower(double power) {
|
||||
inputPower = power;
|
||||
}
|
||||
|
||||
protected void setOutputPower(double power) {
|
||||
outputPower = power;
|
||||
}
|
||||
|
||||
}
|
@ -44,6 +44,9 @@ public class LumentumFlowRule extends DefaultFlowRule {
|
||||
}
|
||||
public Type type;
|
||||
|
||||
private String connectionName;
|
||||
private int connectionId;
|
||||
private int connectionModule;
|
||||
private PortNumber addDrop;
|
||||
|
||||
private PortNumber inputPort;
|
||||
@ -52,6 +55,12 @@ public class LumentumFlowRule extends DefaultFlowRule {
|
||||
private OchSignal ochSignal;
|
||||
private boolean isAddRule;
|
||||
|
||||
protected double attenuation;
|
||||
protected double targetAttenuation;
|
||||
protected double targetPower;
|
||||
protected double inputPower;
|
||||
protected double outputPower;
|
||||
|
||||
//As generated by the OpticalConnectivityIntentCompiler
|
||||
private static final int NUM_CRITERIA_INTENT = 3;
|
||||
private static final int NUM_INSTRUCTIONS_INTENT = 2;
|
||||
@ -60,6 +69,7 @@ public class LumentumFlowRule extends DefaultFlowRule {
|
||||
private static final int NUM_CRITERIA_ROADM = 3;
|
||||
private static final int NUM_INSTRUCTIONS_ROADM = 1;
|
||||
|
||||
|
||||
public LumentumFlowRule(FlowRule rule, List<PortNumber> linePorts) {
|
||||
super(rule);
|
||||
|
||||
@ -137,6 +147,8 @@ public class LumentumFlowRule extends DefaultFlowRule {
|
||||
addDrop = outInstruction.port();
|
||||
isAddRule = false;
|
||||
}
|
||||
|
||||
connectionName = "inPort" + inputPort.toString() + "-ochSig-" + ochSignal.centralFrequency().toString();
|
||||
}
|
||||
|
||||
public PortNumber addDrop() {
|
||||
@ -158,4 +170,36 @@ public class LumentumFlowRule extends DefaultFlowRule {
|
||||
public PortNumber getOutputPort() {
|
||||
return outputPort;
|
||||
}
|
||||
|
||||
public String getConnectionName() {
|
||||
return connectionName;
|
||||
}
|
||||
|
||||
public int getConnectionId() {
|
||||
return connectionId;
|
||||
}
|
||||
|
||||
public int getConnectionModule() {
|
||||
return connectionModule;
|
||||
}
|
||||
|
||||
public void setConnectionId(int id) {
|
||||
connectionId = id;
|
||||
}
|
||||
|
||||
public void setConnectionModule(int id) {
|
||||
connectionModule = id;
|
||||
}
|
||||
|
||||
protected void setAttenuation(double att) {
|
||||
attenuation = att;
|
||||
}
|
||||
|
||||
protected void setInputPower(double power) {
|
||||
inputPower = power;
|
||||
}
|
||||
|
||||
protected void setOutputPower(double power) {
|
||||
outputPower = power;
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ import org.onosproject.net.intent.OpticalPathIntent;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.onosproject.netconf.NetconfDevice;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@ -87,13 +86,17 @@ public class LumentumNetconfRoadmDiscovery
|
||||
private static final int MAX_DEM_PORT = 5220;
|
||||
private static final int DELTA_MUX_DEM_PORT = MIN_DEM_PORT - MIN_MUX_PORT;
|
||||
|
||||
private static final String MUX_PORT_NAME = "Mux Input";
|
||||
private static final String DEMUX_PORT_NAME = "Demux Output";
|
||||
private static final String LINE_PORT_NAME = "Optical Line";
|
||||
|
||||
private final Logger log = getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public DeviceDescription discoverDeviceDetails() {
|
||||
SparseAnnotations annotations = DefaultAnnotations.builder().build();
|
||||
|
||||
log.info("Lumentum NETCONF - starting discoverDeviceDetails");
|
||||
log.debug("Lumentum NETCONF - starting discoverDeviceDetails");
|
||||
|
||||
// Some defaults values
|
||||
String vendor = "Lumentum";
|
||||
@ -106,7 +109,6 @@ public class LumentumNetconfRoadmDiscovery
|
||||
DeviceId deviceId = handler().data().deviceId();
|
||||
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for {}", deviceId);
|
||||
return null;
|
||||
@ -119,7 +121,7 @@ public class LumentumNetconfRoadmDiscovery
|
||||
|
||||
try {
|
||||
String reply = session.get(systemRequestBuilder.toString(), null);
|
||||
log.info("Lumentum NETCONF - session.get reply {}", reply);
|
||||
log.debug("Lumentum NETCONF - session.get reply {}", reply);
|
||||
|
||||
XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(reply);
|
||||
|
||||
@ -136,7 +138,7 @@ public class LumentumNetconfRoadmDiscovery
|
||||
|
||||
try {
|
||||
String reply = session.get(chassisRequestBuilder.toString(), null);
|
||||
log.info("Lumentum NETCONF - session.get reply {}", reply);
|
||||
log.debug("Lumentum NETCONF - session.get reply {}", reply);
|
||||
|
||||
XMLConfiguration xconf = (XMLConfiguration) XmlConfigParser.loadXmlString(reply);
|
||||
|
||||
@ -152,10 +154,11 @@ public class LumentumNetconfRoadmDiscovery
|
||||
}
|
||||
|
||||
//Upon connection of a new devices all pre-configured connections are removed
|
||||
//TODO: do not cancel and import already configured connections
|
||||
//TODO consider a way to keep "external" FlowRules
|
||||
rpcRemoveAllConnections("1");
|
||||
rpcRemoveAllConnections("2");
|
||||
|
||||
log.info("Lumentum ROADM20 - discovered details:");
|
||||
log.info("TYPE {}", Device.Type.ROADM);
|
||||
log.info("VENDOR {}", vendor);
|
||||
log.info("HWVERSION {}", hwVersion);
|
||||
@ -170,7 +173,6 @@ public class LumentumNetconfRoadmDiscovery
|
||||
|
||||
@Override
|
||||
public List<PortDescription> discoverPortDetails() {
|
||||
String reply;
|
||||
DeviceId deviceId = handler().data().deviceId();
|
||||
DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
|
||||
Device device = deviceService.getDevice(deviceId);
|
||||
@ -182,7 +184,6 @@ public class LumentumNetconfRoadmDiscovery
|
||||
}
|
||||
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for {}", deviceId);
|
||||
return ImmutableList.of();
|
||||
@ -195,6 +196,7 @@ public class LumentumNetconfRoadmDiscovery
|
||||
requestBuilder.append("xmlns:loteeth=\"http://www.lumentum.com/lumentum-ote-port-ethernet\">");
|
||||
requestBuilder.append("</physical-ports>");
|
||||
|
||||
String reply;
|
||||
try {
|
||||
reply = session.get(requestBuilder.toString(), null);
|
||||
} catch (NetconfException e) {
|
||||
@ -259,9 +261,6 @@ public class LumentumNetconfRoadmDiscovery
|
||||
log.error("Port Type not correctly loaded");
|
||||
}
|
||||
|
||||
//Store reverse port index in the annotations
|
||||
Long reversePortId;
|
||||
|
||||
/**
|
||||
* Setting the reverse port value for the unidirectional ports.
|
||||
*
|
||||
@ -272,11 +271,11 @@ public class LumentumNetconfRoadmDiscovery
|
||||
* Where port 520x is always the reverse of 410x.
|
||||
*/
|
||||
if ((portNum.toLong() >= MIN_MUX_PORT) && (portNum.toLong() <= MAX_MUX_PORT)) {
|
||||
reversePortId = portNum.toLong() + DELTA_MUX_DEM_PORT;
|
||||
Long reversePortId = portNum.toLong() + DELTA_MUX_DEM_PORT;
|
||||
annotations.set(OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY, reversePortId.toString());
|
||||
}
|
||||
if ((portNum.toLong() >= MIN_DEM_PORT) && (portNum.toLong() <= MAX_DEM_PORT)) {
|
||||
reversePortId = portNum.toLong() - DELTA_MUX_DEM_PORT;
|
||||
Long reversePortId = portNum.toLong() - DELTA_MUX_DEM_PORT;
|
||||
annotations.set(OpticalPathIntent.REVERSE_PORT_ANNOTATION_KEY, reversePortId.toString());
|
||||
}
|
||||
|
||||
@ -305,7 +304,13 @@ public class LumentumNetconfRoadmDiscovery
|
||||
log.debug("Lumentum NETCONF - retrieved port {},{},{},{},{}",
|
||||
portNum, isEnabled, type, speed, annotations.build());
|
||||
|
||||
if (type == Port.Type.FIBER) {
|
||||
|
||||
if ((type == Port.Type.FIBER) &&
|
||||
((annotations.build().value(AnnotationKeys.PORT_NAME)).contains(MUX_PORT_NAME) ||
|
||||
(annotations.build().value(AnnotationKeys.PORT_NAME)).contains(DEMUX_PORT_NAME) ||
|
||||
(annotations.build().value(AnnotationKeys.PORT_NAME)).contains(LINE_PORT_NAME))) {
|
||||
|
||||
//These are the ports supporting OchSignals
|
||||
portDescriptions.add(omsPortDescription(portNum,
|
||||
isEnabled,
|
||||
START_CENTER_FREQ_50,
|
||||
@ -313,6 +318,7 @@ public class LumentumNetconfRoadmDiscovery
|
||||
CHANNEL_SPACING_50.frequency(),
|
||||
annotations.build()));
|
||||
} else {
|
||||
//These are COPPER ports, or FIBER ports not supporting OchSignals
|
||||
DefaultPortDescription.Builder portDescriptionBuilder = DefaultPortDescription.builder();
|
||||
portDescriptionBuilder.withPortNumber(portNum)
|
||||
.isEnabled(isEnabled)
|
||||
@ -342,7 +348,6 @@ public class LumentumNetconfRoadmDiscovery
|
||||
|
||||
private boolean editCrossConnect(String xcString) {
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for {}", handler().data().deviceId());
|
||||
return false;
|
||||
@ -358,15 +363,19 @@ public class LumentumNetconfRoadmDiscovery
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the Netconf session.
|
||||
*/
|
||||
private NetconfSession getNetconfSession() {
|
||||
NetconfController controller = checkNotNull(handler().get(NetconfController.class));
|
||||
NetconfDevice ncDevice = controller.getNetconfDevice(handler().data().deviceId());
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
return controller.getNetconfDevice(did()).getSession();
|
||||
}
|
||||
|
||||
if (ncDevice == null) {
|
||||
log.error("Lumentum NETCONF - device not found for {}", handler().data().deviceId());
|
||||
return null;
|
||||
}
|
||||
|
||||
return ncDevice.getSession();
|
||||
/**
|
||||
* Helper method to get the device id.
|
||||
*/
|
||||
private DeviceId did() {
|
||||
return data().deviceId();
|
||||
}
|
||||
}
|
||||
|
@ -21,27 +21,23 @@ import org.apache.commons.configuration.HierarchicalConfiguration;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.onlab.util.Frequency;
|
||||
import org.onlab.util.Spectrum;
|
||||
import org.onosproject.driver.optical.flowrule.CrossConnectCache;
|
||||
import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
|
||||
import org.onosproject.drivers.utilities.XmlConfigParser;
|
||||
import org.onosproject.net.ChannelSpacing;
|
||||
import org.onosproject.net.GridType;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.OchSignal;
|
||||
import org.onosproject.net.OchSignalType;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.ChannelSpacing;
|
||||
import org.onosproject.net.GridType;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||
import org.onosproject.net.flow.DefaultFlowEntry;
|
||||
import org.onosproject.net.flow.DefaultFlowRule;
|
||||
import org.onosproject.net.flow.DefaultTrafficSelector;
|
||||
import org.onosproject.net.flow.DefaultTrafficTreatment;
|
||||
import org.onosproject.net.flow.FlowEntry;
|
||||
import org.onosproject.net.flow.FlowId;
|
||||
import org.onosproject.net.flow.FlowRule;
|
||||
import org.onosproject.net.flow.FlowRuleProgrammable;
|
||||
import org.onosproject.net.flow.TrafficSelector;
|
||||
import org.onosproject.net.flow.TrafficTreatment;
|
||||
import org.onosproject.net.flow.criteria.Criteria;
|
||||
import org.onosproject.net.flow.instructions.Instructions;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
@ -49,12 +45,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -91,14 +86,7 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
protected static final long MUX_OUT = 4201;
|
||||
protected static final long DEMUX_IN = 5101;
|
||||
protected static final long GHZ = 1_000_000_000L;
|
||||
protected static final int MAX_CONNECTIONS = 100;
|
||||
|
||||
//List of LumentumConnections to associate ConnectionId and other info to the relative hash
|
||||
|
||||
//This is required because CrossConnect, CrossConnect Cache do not include all parameters required by Lumentum
|
||||
//TODO: Use an external cache as CrossConnectCache to avoid problems in case of multiple devices using this driver
|
||||
|
||||
protected static final Set<LumentumConnection> CONNECTION_SET = new HashSet<>();
|
||||
protected static final int LUMENTUM_ROADM20_MAX_CONNECTIONS = 100;
|
||||
|
||||
/**Get the flow entries that are present on the Lumentum device, called by FlowRuleDriverProvider.
|
||||
*
|
||||
@ -109,13 +97,15 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
*/
|
||||
@Override
|
||||
public Collection<FlowEntry> getFlowEntries() {
|
||||
return ImmutableList.copyOf(
|
||||
fetchConnectionsFromDevice().stream()
|
||||
.map(conn -> buildFlowrule(conn))
|
||||
.filter(Objects::nonNull)
|
||||
.map(fr -> new DefaultFlowEntry(
|
||||
fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
|
||||
.collect(Collectors.toList()));
|
||||
Collection<FlowEntry> fetched = fetchConnectionsFromDevice().stream()
|
||||
.map(conn -> buildFlowrule(conn))
|
||||
.map(fr -> new DefaultFlowEntry(fr, FlowEntry.FlowEntryState.ADDED, 0, 0, 0))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
//Print out number of rules actually found on the device that are also included in the cache
|
||||
log.debug("Device {} getFlowEntries fetched connections {}", did(), fetched.size());
|
||||
|
||||
return fetched;
|
||||
}
|
||||
|
||||
/**Apply the flow entries specified in the collection rules.
|
||||
@ -125,40 +115,54 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
*/
|
||||
@Override
|
||||
public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
|
||||
// Apply the rules on the device
|
||||
Collection<FlowRule> added = rules.stream()
|
||||
.map(r -> new LumentumFlowRule(r, getLinePorts()))
|
||||
.filter(xc -> rpcAddConnection(xc))
|
||||
.collect(Collectors.toList());
|
||||
//Check NETCONF session
|
||||
NetconfSession session = getNetconfSession();
|
||||
if (session == null) {
|
||||
log.error("Device {} null session", did());
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
// Cache the cookie/priority
|
||||
CrossConnectCache cache = this.handler().get(CrossConnectCache.class);
|
||||
added.forEach(xc -> cache.set(
|
||||
Objects.hash(data().deviceId(), xc.selector()),
|
||||
xc.id(),
|
||||
xc.priority()));
|
||||
// Apply the rules on the device and add to cache if success
|
||||
Collection<FlowRule> added = new ArrayList<>();
|
||||
for (FlowRule flowRule : rules) {
|
||||
LumentumFlowRule lumFlowRule = new LumentumFlowRule(flowRule, getLinePorts());
|
||||
|
||||
added.forEach(xc -> log.debug("Lumentum build cached FlowRule selector {} treatment {}",
|
||||
xc.selector().toString(), xc.treatment().toString()));
|
||||
if (rpcAddConnection(lumFlowRule)) {
|
||||
added.add(lumFlowRule);
|
||||
getConnectionCache().add(did(), lumFlowRule.getConnectionName(), lumFlowRule);
|
||||
}
|
||||
}
|
||||
|
||||
//Print out number of rules sent to the device (without receiving errors)
|
||||
log.debug("Device {} applyFlowRules added {}", did(), added.size());
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
|
||||
// Remove the valid rules from the device
|
||||
Collection<FlowRule> removed = rules.stream()
|
||||
.map(r -> new LumentumFlowRule(r, getLinePorts()))
|
||||
.filter(xc -> rpcDeleteConnection(xc))
|
||||
.collect(Collectors.toList());
|
||||
NetconfSession session = getNetconfSession();
|
||||
if (session == null) {
|
||||
log.error("Device {} null session", did());
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
// Remove flow rule from cache
|
||||
CrossConnectCache cache = this.handler().get(CrossConnectCache.class);
|
||||
removed.forEach(xc -> cache.remove(
|
||||
Objects.hash(data().deviceId(), xc.selector())));
|
||||
// Remove the rules from the device and from the cache
|
||||
List<FlowRule> removed = new ArrayList<>();
|
||||
for (FlowRule r : rules) {
|
||||
try {
|
||||
LumentumFlowRule flowRule = new LumentumFlowRule(r, getLinePorts());
|
||||
rpcDeleteConnection(flowRule);
|
||||
getConnectionCache().remove(did(), r);
|
||||
removed.add(r);
|
||||
} catch (Exception e) {
|
||||
log.error("Device {} Error {}", did(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
removed.forEach(xc -> log.debug("Lumentum NETCONF - removed cached FlowRule selector {} treatment {}",
|
||||
xc.selector(), xc.treatment()));
|
||||
//Print out number of removed rules from the device (without receiving errors)
|
||||
log.debug("Device {} removeFlowRules removed {}", did(), removed.size());
|
||||
|
||||
return removed;
|
||||
}
|
||||
@ -184,7 +188,6 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
requestBuilder.append("</connections>");
|
||||
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for {}", handler().data().deviceId());
|
||||
return ImmutableList.of();
|
||||
@ -192,7 +195,7 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
|
||||
try {
|
||||
reply = session.get(requestBuilder.toString(), null);
|
||||
log.info("Lumentum NETCONF - fetchConnectionsFromDevice reply {}", reply);
|
||||
log.debug("Lumentum NETCONF - fetchConnectionsFromDevice reply {}", reply);
|
||||
} catch (NetconfException e) {
|
||||
log.error("Failed to retrieve configuration details for device {}",
|
||||
handler().data().deviceId(), e);
|
||||
@ -238,6 +241,15 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
|
||||
String dn = connection.getString(DN);
|
||||
Pair<Short, Short> pair = parseDn(dn);
|
||||
short connId = pair.getRight();
|
||||
short moduleId = pair.getLeft();
|
||||
|
||||
if (pair == null) {
|
||||
log.error("Lumentum NETCONF - device {} error in retrieving DN field", did());
|
||||
return null;
|
||||
}
|
||||
|
||||
log.debug("Lumentum NETCONF - retrieved FlowRule module {} connection {}", moduleId, connId);
|
||||
|
||||
HierarchicalConfiguration config = connection.configurationAt(CONFIG);
|
||||
double startFreq = config.getDouble(START_FREQ);
|
||||
@ -250,65 +262,44 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
double inputPower = state.getDouble(CHANNEL_INPUT_POWER);
|
||||
double outputPower = state.getDouble(CHANNEL_OUTPUT_POWER);
|
||||
|
||||
if (pair == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PortNumber portNumber = getPortNumber(pair.getLeft(), inputPortReference, outputPortReference);
|
||||
PortNumber portNumber = getPortNumber(moduleId, inputPortReference, outputPortReference);
|
||||
|
||||
//If rule is on module 1 it means input port in the Flow rule is contained in portNumber.
|
||||
//Otherwise the input port in the Flow rule must is the line port.
|
||||
TrafficSelector selector = DefaultTrafficSelector.builder()
|
||||
.matchInPort(pair.getLeft() == 1 ? portNumber : LINE_PORT_NUMBER)
|
||||
.matchInPort(moduleId == 1 ? portNumber : LINE_PORT_NUMBER)
|
||||
.add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
|
||||
.add(Criteria.matchLambda(toOchSignal(startFreq, endFreq)))
|
||||
.build();
|
||||
|
||||
log.debug("Lumentum NETCONF - retrieved FlowRule startFreq {} endFreq {}", startFreq, endFreq);
|
||||
|
||||
// Lookup flow ID and priority
|
||||
int hash = Objects.hash(data().deviceId(), selector);
|
||||
CrossConnectCache cache = this.handler().get(CrossConnectCache.class);
|
||||
Pair<FlowId, Integer> lookup = cache.get(hash);
|
||||
|
||||
LumentumConnection conn = CONNECTION_SET.stream()
|
||||
.filter(c -> hash == c.getHash())
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
TrafficTreatment treatment;
|
||||
if (conn.rule.type == LumentumFlowRule.Type.OPTICAL_CONNECTIVITY_INTENT_RULE) {
|
||||
treatment = DefaultTrafficTreatment.builder()
|
||||
.add(Instructions.modL0Lambda(toOchSignal(startFreq, endFreq)))
|
||||
.setOutput(pair.getLeft() == 1 ? LINE_PORT_NUMBER : portNumber)
|
||||
.build();
|
||||
} else { // This is ROADM_APP_RULE
|
||||
treatment = DefaultTrafficTreatment.builder()
|
||||
.setOutput(pair.getLeft() == 1 ? LINE_PORT_NUMBER : portNumber)
|
||||
.build();
|
||||
//Lookup of connection
|
||||
//Retrieved rules, cached rules are considered equal if the selector is equal
|
||||
FlowRule cacheRule = null;
|
||||
if (getConnectionCache().size(did()) != 0) {
|
||||
cacheRule = getConnectionCache().get(did()).stream()
|
||||
.filter(r -> (r.selector().equals(selector)))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
//If the flow entry is not in the cache: return null/publish the flow rule
|
||||
if ((lookup == null) || (conn == null)) {
|
||||
log.error("Lumentum NETCONF connection not in connectionSet {}", pair.getRight());
|
||||
rpcDeleteUnwantedConnection(pair.getRight().toString());
|
||||
return null;
|
||||
|
||||
if (cacheRule == null) {
|
||||
//TODO consider a way to keep "external" FlowRules
|
||||
log.error("Lumentum NETCONF connection not in the cache {}", pair.getRight());
|
||||
rpcDeleteExternalConnection(moduleId, connId);
|
||||
return null;
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF attenuation and parameters set {} for connection id {}",
|
||||
attenuation,
|
||||
conn.getConnectionId());
|
||||
//Update monitored values
|
||||
log.debug("Attenuation retrieved {} dB for connection {}",
|
||||
attenuation, ((LumentumFlowRule) cacheRule).getConnectionId());
|
||||
((LumentumFlowRule) cacheRule).setAttenuation(attenuation);
|
||||
((LumentumFlowRule) cacheRule).setInputPower(inputPower);
|
||||
((LumentumFlowRule) cacheRule).setOutputPower(outputPower);
|
||||
|
||||
conn.setAttenuation(attenuation);
|
||||
conn.setInputPower(inputPower);
|
||||
conn.setOutputPower(outputPower);
|
||||
return cacheRule;
|
||||
}
|
||||
|
||||
return DefaultFlowRule.builder()
|
||||
.forDevice(data().deviceId())
|
||||
.makePermanent()
|
||||
.withSelector(selector)
|
||||
.withTreatment(treatment)
|
||||
.withPriority(lookup.getRight())
|
||||
.withCookie(lookup.getLeft().value())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -339,47 +330,16 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
*/
|
||||
private Pair<Short, Short> setModuleConnection(LumentumFlowRule xc, Integer id) {
|
||||
if (xc.isAddRule()) {
|
||||
xc.setConnectionModule((short) 1);
|
||||
xc.setConnectionId(id.shortValue());
|
||||
return Pair.of((short) 1, id.shortValue());
|
||||
} else {
|
||||
xc.setConnectionModule((short) 2);
|
||||
xc.setConnectionId(id.shortValue());
|
||||
return Pair.of((short) 2, id.shortValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve module and connection from the cache.
|
||||
*
|
||||
* Connection number is incremental within the class and associated to the rule hash.
|
||||
*
|
||||
* @param xc the cross connect flow
|
||||
* @return pair of module (1 for MUX/ADD, 2 for DEMUX/DROP) and connection number
|
||||
*/
|
||||
private Pair<Short, Short> retrieveModuleConnection(LumentumFlowRule xc) {
|
||||
|
||||
int hash = Objects.hash(data().deviceId(), xc.selector());
|
||||
|
||||
LumentumConnection retrievedConnection = CONNECTION_SET.stream()
|
||||
.filter(conn -> conn.getHash() == hash)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (retrievedConnection == null) {
|
||||
log.error("Lumentum connection not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
//Remove connection id from the local cache
|
||||
CONNECTION_SET.remove(retrievedConnection);
|
||||
|
||||
log.debug("Lumentum NETCONF - retrieveModuleConnection {} retrievedConnectionId {} port {}",
|
||||
xc.isAddRule(), retrievedConnection.getConnectionId(), xc.addDrop());
|
||||
|
||||
if (xc.isAddRule()) {
|
||||
return Pair.of((short) 1, retrievedConnection.getConnectionId().shortValue());
|
||||
} else {
|
||||
return Pair.of((short) 2, retrievedConnection.getConnectionId().shortValue());
|
||||
}
|
||||
}
|
||||
|
||||
//Following Lumentum documentation rpc operation to configure a new connection
|
||||
private boolean rpcAddConnection(LumentumFlowRule xc) {
|
||||
|
||||
@ -390,11 +350,6 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
return false;
|
||||
}
|
||||
|
||||
LumentumConnection connection = new LumentumConnection(currentConnectionId,
|
||||
Objects.hash(data().deviceId(), xc.selector()), xc);
|
||||
|
||||
CONNECTION_SET.add(connection);
|
||||
|
||||
Pair<Short, Short> pair = setModuleConnection(xc, currentConnectionId);
|
||||
String module = pair.getLeft().toString();
|
||||
String connectionId = pair.getRight().toString();
|
||||
@ -431,7 +386,8 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
stringBuilder.append("</add-connection>" + "\n");
|
||||
stringBuilder.append("</rpc>" + "\n");
|
||||
|
||||
log.info("Lumentum NETCONF - RPC add-connection {}", stringBuilder);
|
||||
log.info("Lumentum ROADM20 - RPC add-connection sent to device {}", did());
|
||||
log.debug("Lumentum ROADM20 - RPC add-connection sent to device {} {}", did(), stringBuilder);
|
||||
|
||||
return editCrossConnect(stringBuilder.toString());
|
||||
}
|
||||
@ -467,48 +423,59 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
stringBuilder.append("</edit-config>" + "\n");
|
||||
stringBuilder.append("</rpc>" + "\n");
|
||||
|
||||
log.info("Lumentum {} - edit-connection {}", data().deviceId(), stringBuilder);
|
||||
log.info("Lumentum ROADM20 - edit-connection sent to device {}", did());
|
||||
log.debug("Lumentum ROADM20 - edit-connection sent to device {} {}", did(), stringBuilder);
|
||||
|
||||
return editCrossConnect(stringBuilder.toString());
|
||||
}
|
||||
|
||||
//Following Lumentum documentation rpc operation to delete a new connection
|
||||
private boolean rpcDeleteConnection(LumentumFlowRule xc) {
|
||||
Pair<Short, Short> pair = retrieveModuleConnection(xc);
|
||||
|
||||
if (pair == null) {
|
||||
//Look for corresponding rule into the cache
|
||||
FlowRule cacheRule = getConnectionCache().get(did()).stream()
|
||||
.filter(r -> (r.selector().equals(xc.selector()) && r.treatment().equals(xc.treatment())))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (cacheRule == null) {
|
||||
log.error("Lumentum RPC delete-connection, connection not found on the local cache");
|
||||
throw new IllegalStateException("Lumentum RPC delete-connection, connection not found on the local cache");
|
||||
}
|
||||
|
||||
String module = pair.getLeft().toString();
|
||||
String connection = pair.getRight().toString();
|
||||
|
||||
int moduleId = ((LumentumFlowRule) cacheRule).getConnectionModule();
|
||||
int connId = ((LumentumFlowRule) cacheRule).getConnectionId();
|
||||
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" + "\n");
|
||||
stringBuilder.append("<delete-connection xmlns=\"http://www.lumentum.com/lumentum-ote-connection\">" + "\n");
|
||||
stringBuilder.append(
|
||||
"<dn>ne=1;chassis=1;card=1;module=" + module + ";connection=" + connection + "</dn>" + "\n");
|
||||
"<dn>ne=1;chassis=1;card=1;module=" + moduleId + ";connection=" + connId + "</dn>" + "\n");
|
||||
stringBuilder.append("</delete-connection>" + "\n");
|
||||
stringBuilder.append("</rpc>" + " \n");
|
||||
|
||||
log.info("Lumentum RPC delete-connection {}", stringBuilder);
|
||||
log.info("Lumentum ROADM20 - RPC delete-connection sent to device {}", did());
|
||||
log.debug("Lumentum ROADM20 - - RPC delete-connection sent to device {} {}", did(), stringBuilder);
|
||||
|
||||
return editCrossConnect(stringBuilder.toString());
|
||||
}
|
||||
|
||||
//Following Lumentum documentation rpc operation to delete a new connection
|
||||
//Executed if for some reason a connection not in the cache is detected
|
||||
private boolean rpcDeleteUnwantedConnection(String connectionId) {
|
||||
private boolean rpcDeleteExternalConnection(short moduleId, short connectionId) {
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" + "\n");
|
||||
stringBuilder.append("<delete-connection xmlns=\"http://www.lumentum.com/lumentum-ote-connection\">" + "\n");
|
||||
stringBuilder.append("<dn>ne=1;chassis=1;card=1;module=1;connection=" + connectionId + "</dn>" + "\n");
|
||||
stringBuilder.append("<dn>ne=1;chassis=1;card=1;module="
|
||||
+ moduleId + ";connection=" + connectionId + "</dn>" + "\n");
|
||||
stringBuilder.append("</delete-connection>" + "\n");
|
||||
stringBuilder.append("</rpc>" + "\n");
|
||||
|
||||
log.info("Lumentum {} - RPC delete-connection unwanted {}", data().deviceId(), stringBuilder);
|
||||
log.info("Lumentum ROADM20 - RPC delete-external-connection sent to device {}", did());
|
||||
log.debug("Lumentum ROADM20 - - RPC delete-external-connection sent to device {} {}", did(), stringBuilder);
|
||||
|
||||
return editCrossConnect(stringBuilder.toString());
|
||||
}
|
||||
@ -516,7 +483,6 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
|
||||
private boolean editCrossConnect(String xcString) {
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for device {}", handler().data().deviceId());
|
||||
return false;
|
||||
@ -532,20 +498,7 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
}
|
||||
}
|
||||
|
||||
private NetconfSession getNetconfSession() {
|
||||
NetconfController controller = checkNotNull(handler().get(NetconfController.class));
|
||||
|
||||
try {
|
||||
NetconfSession session = checkNotNull(
|
||||
controller.getNetconfDevice(handler().data().deviceId()).getSession());
|
||||
return session;
|
||||
} catch (NullPointerException e) {
|
||||
log.error("Lumentum NETCONF - session not found for {}", handler().data().deviceId());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Convert start and end frequencies to OCh signal.
|
||||
*
|
||||
* FIXME: assumes slots of 12.5 GHz while devices allows granularity 6.25 GHz
|
||||
@ -585,18 +538,43 @@ public class LumentumNetconfRoadmFlowRuleProgrammable extends AbstractHandlerBeh
|
||||
*
|
||||
* Device only supports connection id < 100
|
||||
*/
|
||||
private static Integer generateConnectionId() {
|
||||
private int generateConnectionId() {
|
||||
//LUMENTUM_ROADM20_MAX_CONNECTIONS = 100, device only supports connection id < 100
|
||||
for (int i = 1; i < LUMENTUM_ROADM20_MAX_CONNECTIONS; i++) {
|
||||
Set<FlowRule> rulesForDevice = getConnectionCache().get(did());
|
||||
|
||||
//Device only supports connection id < 100
|
||||
for (int i = 1; i < MAX_CONNECTIONS; i++) {
|
||||
Set<Integer> connIds = CONNECTION_SET.stream()
|
||||
.map(conn -> conn.getConnectionId())
|
||||
.collect(Collectors.toSet());
|
||||
if (rulesForDevice == null) {
|
||||
return 1;
|
||||
} else {
|
||||
Set<Integer> connIds = rulesForDevice.stream()
|
||||
.map(flow -> ((LumentumFlowRule) flow).getConnectionId())
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (!connIds.contains(i)) {
|
||||
return i;
|
||||
if (!connIds.contains(i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private DeviceConnectionCache getConnectionCache() {
|
||||
return DeviceConnectionCache.init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the device id.
|
||||
*/
|
||||
private DeviceId did() {
|
||||
return data().deviceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the Netconf session.
|
||||
*/
|
||||
private NetconfSession getNetconfSession() {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
return controller.getNetconfDevice(did()).getSession();
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,8 @@
|
||||
package org.onosproject.drivers.lumentum;
|
||||
|
||||
import com.google.common.collect.Range;
|
||||
import org.onosproject.drivers.odtn.impl.DeviceConnectionCache;
|
||||
import org.onosproject.net.DeviceId;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.OchSignal;
|
||||
import org.onosproject.net.behaviour.PowerConfig;
|
||||
@ -27,8 +29,13 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.onosproject.net.flow.FlowRule;
|
||||
import org.onosproject.netconf.NetconfController;
|
||||
import org.onosproject.netconf.NetconfException;
|
||||
import org.onosproject.netconf.NetconfSession;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static org.slf4j.LoggerFactory.getLogger;
|
||||
|
||||
public class LumentumPowerConfig<T> extends AbstractHandlerBehaviour
|
||||
@ -43,6 +50,7 @@ public class LumentumPowerConfig<T> extends AbstractHandlerBehaviour
|
||||
return Optional.ofNullable(acquireTargetPower(port, component));
|
||||
}
|
||||
|
||||
//Used by the ROADM app to set the "attenuation" parameter
|
||||
@Override
|
||||
public void setTargetPower(PortNumber port, T component, long power) {
|
||||
if (component instanceof OchSignal) {
|
||||
@ -101,22 +109,33 @@ public class LumentumPowerConfig<T> extends AbstractHandlerBehaviour
|
||||
|
||||
//TODO implement actual get configuration from the device
|
||||
//This is used by ROADM application to retrieve attenuation parameter, with T instanceof OchSignal
|
||||
//The ROADM app expresses the attenuation in 0.01 dB units
|
||||
private Long acquireTargetPower(PortNumber port, T component) {
|
||||
log.debug("Lumentum get port {} target power...", port);
|
||||
|
||||
if (component instanceof OchSignal) {
|
||||
//FIXME include port in the filter
|
||||
LumentumConnection conn = LumentumNetconfRoadmFlowRuleProgrammable.CONNECTION_SET.stream()
|
||||
.filter(c -> c.ochSignal == component)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (conn == null) {
|
||||
log.debug("Lumentum NETCONF fail to retrieve attenuation signal {} port {}", component, port);
|
||||
Set<FlowRule> rules = getConnectionCache().get(did());
|
||||
FlowRule rule;
|
||||
|
||||
if (rules == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve attenuation signal {} port {}", component, port);
|
||||
return 0L;
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF on port {} attenuation {}", port, conn.attenuation);
|
||||
return ((long) (conn.attenuation * 100));
|
||||
rule = rules.stream()
|
||||
.filter(c -> ((LumentumFlowRule) c).getOutputPort() == port)
|
||||
.filter(c -> ((LumentumFlowRule) c).ochSignal() == component)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
if (rule == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve attenuation signal {} port {}", component, port);
|
||||
return 0L;
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF on port {} attenuation {}", port,
|
||||
(((LumentumFlowRule) rule).attenuation * 100));
|
||||
return ((long) (((LumentumFlowRule) rule).attenuation * 100));
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,23 +143,32 @@ public class LumentumPowerConfig<T> extends AbstractHandlerBehaviour
|
||||
}
|
||||
|
||||
//TODO implement actual get configuration from the device
|
||||
//This is used by ROADM application to retrieve attenuation parameter, with T instanceof OchSignal
|
||||
//This is used by ROADM application to retrieve power parameter, with T instanceof OchSignal
|
||||
private Long acquireCurrentPower(PortNumber port, T component) {
|
||||
log.debug("Lumentum get port {} current power...", port);
|
||||
|
||||
if (component instanceof OchSignal) {
|
||||
//FIXME include port in the filter
|
||||
LumentumConnection conn = LumentumNetconfRoadmFlowRuleProgrammable.CONNECTION_SET.stream()
|
||||
.filter(c -> c.ochSignal == component)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (conn == null) {
|
||||
log.debug("Lumentum NETCONF fail to retrieve power signal {} port {}", component, port);
|
||||
Set<FlowRule> rules = getConnectionCache().get(did());
|
||||
FlowRule rule;
|
||||
|
||||
if (rules == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve power signal {} port {}", component, port);
|
||||
return 0L;
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF on port {} power {}", port, conn.inputPower);
|
||||
return ((long) (conn.inputPower * 100));
|
||||
rule = rules.stream()
|
||||
.filter(c -> ((LumentumFlowRule) c).getInputPort() == port)
|
||||
.filter(c -> ((LumentumFlowRule) c).ochSignal() == component)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
if (rule == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve power signal {} port {}", component, port);
|
||||
return 0L;
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF on port {} power {}", port, (((LumentumFlowRule) rule).inputPower));
|
||||
return ((long) (((LumentumFlowRule) rule).inputPower * 100));
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,9 +195,103 @@ public class LumentumPowerConfig<T> extends AbstractHandlerBehaviour
|
||||
log.debug("Set port {} target power {}", port, power);
|
||||
}
|
||||
|
||||
//TODO implement configuration on the device
|
||||
//Nothing to do
|
||||
//Used by the ROADM app to set the "attenuation" parameter
|
||||
private void setConnectionTargetPower(PortNumber port, OchSignal signal, long power) {
|
||||
log.debug("Set connection target power {} ochsignal {} port {}", power, signal, port);
|
||||
|
||||
Set<FlowRule> rules = getConnectionCache().get(did());
|
||||
FlowRule rule = null;
|
||||
|
||||
if (rules == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve power signal {} port {}", signal, port);
|
||||
} else {
|
||||
rule = rules.stream()
|
||||
.filter(c -> ((LumentumFlowRule) c).getOutputPort() == port)
|
||||
.filter(c -> ((LumentumFlowRule) c).ochSignal() == signal)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
if (rule == null) {
|
||||
log.error("Lumentum NETCONF fail to retrieve attenuation signal {} port {}", signal, port);
|
||||
} else {
|
||||
log.debug("Lumentum NETCONF setting attenuation {} on port {} signal {}", power, port, signal);
|
||||
|
||||
int moduleId = ((LumentumFlowRule) rule).getConnectionModule();
|
||||
int connId = ((LumentumFlowRule) rule).getConnectionId();
|
||||
|
||||
editConnection(moduleId, connId, power);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private DeviceConnectionCache getConnectionCache() {
|
||||
return DeviceConnectionCache.init();
|
||||
}
|
||||
|
||||
//Following Lumentum documentation <edit-config> operation to edit connection parameter
|
||||
//Currently only edit the "attenuation" parameter
|
||||
private boolean editConnection(int moduleId, int connectionId, long attenuation) {
|
||||
|
||||
double attenuationDouble = ((double) attenuation);
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
stringBuilder.append("<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">" + "\n");
|
||||
stringBuilder.append("<edit-config>" + "\n");
|
||||
stringBuilder.append("<target>" + "\n");
|
||||
stringBuilder.append("<running/>" + "\n");
|
||||
stringBuilder.append("</target>" + "\n");
|
||||
stringBuilder.append("<config>" + "\n");
|
||||
stringBuilder.append("<connections xmlns=\"http://www.lumentum.com/lumentum-ote-connection\">" + "\n");
|
||||
stringBuilder.append("<connection>" + "\n");
|
||||
stringBuilder.append("" +
|
||||
"<dn>ne=1;chassis=1;card=1;module=" + moduleId + ";connection=" + connectionId + "</dn>" + "\n");
|
||||
stringBuilder.append("<config>" + "\n");
|
||||
stringBuilder.append("<attenuation>" + attenuationDouble + "</attenuation>" + "\n");
|
||||
stringBuilder.append("</config>" + "\n");
|
||||
stringBuilder.append("</connection>" + "\n");
|
||||
stringBuilder.append("</connections>" + "\n");
|
||||
stringBuilder.append("</config>" + "\n");
|
||||
stringBuilder.append("</edit-config>" + "\n");
|
||||
stringBuilder.append("</rpc>" + "\n");
|
||||
|
||||
log.info("Lumentum ROADM20 - edit-connection sent to device {}", did());
|
||||
log.debug("Lumentum ROADM20 - edit-connection sent to device {} {}", did(), stringBuilder);
|
||||
|
||||
return editCrossConnect(stringBuilder.toString());
|
||||
}
|
||||
|
||||
private boolean editCrossConnect(String xcString) {
|
||||
NetconfSession session = getNetconfSession();
|
||||
|
||||
if (session == null) {
|
||||
log.error("Lumentum NETCONF - session not found for device {}", handler().data().deviceId());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
return session.editConfig(xcString);
|
||||
} catch (NetconfException e) {
|
||||
log.error("Failed to edit the CrossConnect edid-cfg for device {}",
|
||||
handler().data().deviceId(), e);
|
||||
log.debug("Failed configuration {}", xcString);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the device id.
|
||||
*/
|
||||
private DeviceId did() {
|
||||
return data().deviceId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get the Netconf session.
|
||||
*/
|
||||
private NetconfSession getNetconfSession() {
|
||||
NetconfController controller =
|
||||
checkNotNull(handler().get(NetconfController.class));
|
||||
return controller.getNetconfDevice(did()).getSession();
|
||||
}
|
||||
}
|
@ -17,17 +17,19 @@ package org.onosproject.drivers.lumentum;
|
||||
|
||||
import org.onlab.util.Frequency;
|
||||
import org.onlab.util.Spectrum;
|
||||
import org.onosproject.net.ChannelSpacing;
|
||||
import org.onosproject.net.GridType;
|
||||
import org.onosproject.net.ChannelSpacing;
|
||||
import org.onosproject.net.OchSignal;
|
||||
import org.onosproject.net.Port;
|
||||
import org.onosproject.net.PortNumber;
|
||||
import org.onosproject.net.behaviour.LambdaQuery;
|
||||
import org.onosproject.net.device.DeviceService;
|
||||
import org.onosproject.net.driver.AbstractHandlerBehaviour;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Collectors;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* Implementation of lambda query interface for Lumentum ROADMs.
|
||||
@ -53,19 +55,23 @@ public class LumentumRoadmLambdaQuery extends AbstractHandlerBehaviour implement
|
||||
private static final int LAMBDA_COUNT_100 = 48;
|
||||
|
||||
@Override
|
||||
public Set<OchSignal> queryLambdas(PortNumber port) {
|
||||
public Set<OchSignal> queryLambdas(PortNumber portNumber) {
|
||||
DeviceService deviceService = this.handler().get(DeviceService.class);
|
||||
Port port = deviceService.getPort(data().deviceId(), portNumber);
|
||||
|
||||
//Complete set of 50GHz OchSignal
|
||||
int startMultiplier50 = (int) (START_CENTER_FREQ_50.subtract(Spectrum.CENTER_FREQUENCY).asHz()
|
||||
/ Frequency.ofGHz(50).asHz());
|
||||
if (port.type() == Port.Type.FIBER) {
|
||||
|
||||
Set<OchSignal> channels50 = IntStream.range(0, LAMBDA_COUNT_50)
|
||||
.mapToObj(x -> new OchSignal(GRID_TYPE, CHANNEL_SPACING_50,
|
||||
startMultiplier50 + x,
|
||||
4))
|
||||
.collect(Collectors.toSet());
|
||||
//Complete set of 50GHz OchSignal
|
||||
int startMultiplier50 = (int) (START_CENTER_FREQ_50.subtract(Spectrum.CENTER_FREQUENCY).asHz()
|
||||
/ Frequency.ofGHz(50).asHz());
|
||||
|
||||
//Complete set of 100GHz OchSignal
|
||||
Set<OchSignal> channels50 = IntStream.range(0, LAMBDA_COUNT_50)
|
||||
.mapToObj(x -> new OchSignal(GRID_TYPE, CHANNEL_SPACING_50,
|
||||
startMultiplier50 + x,
|
||||
4))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
/*//Complete set of 100GHz OchSignal
|
||||
int startMultiplier100 = (int) (START_CENTER_FREQ_100.subtract(Spectrum.CENTER_FREQUENCY).asHz()
|
||||
/ Frequency.ofGHz(100).asHz());
|
||||
|
||||
@ -74,9 +80,12 @@ public class LumentumRoadmLambdaQuery extends AbstractHandlerBehaviour implement
|
||||
CHANNEL_SPACING_100, startMultiplier100 + x, 8))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Set<OchSignal> channels = Sets.union(channels50, channels100);
|
||||
Set<OchSignal> channels = Sets.union(channels50, channels100);*/
|
||||
|
||||
return channels;
|
||||
return channels50;
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user