[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
diff --git a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
index 9f83df5..a98b252 100644
--- a/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
+++ b/apps/roadm/src/main/java/org/onosproject/roadm/RoadmManager.java
@@ -593,11 +593,12 @@
}
// 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();
diff --git a/drivers/lumentum/BUILD b/drivers/lumentum/BUILD
index b8f8156..2f991cc 100644
--- a/drivers/lumentum/BUILD
+++ b/drivers/lumentum/BUILD
@@ -5,6 +5,7 @@
"//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 @@
"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",
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumConnection.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumConnection.java
deleted file mode 100644
index 58c5b78..0000000
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumConnection.java
+++ /dev/null
@@ -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;
- }
-
-}
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumFlowRule.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumFlowRule.java
index 9489ff1..fe26d72 100644
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumFlowRule.java
+++ b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumFlowRule.java
@@ -44,6 +44,9 @@
}
public Type type;
+ private String connectionName;
+ private int connectionId;
+ private int connectionModule;
private PortNumber addDrop;
private PortNumber inputPort;
@@ -52,6 +55,12 @@
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 @@
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 @@
addDrop = outInstruction.port();
isAddRule = false;
}
+
+ connectionName = "inPort" + inputPort.toString() + "-ochSig-" + ochSignal.centralFrequency().toString();
}
public PortNumber addDrop() {
@@ -158,4 +170,36 @@
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;
+ }
}
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmDiscovery.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmDiscovery.java
index eea8b59..df656c9 100644
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmDiscovery.java
+++ b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmDiscovery.java
@@ -45,7 +45,6 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
//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 @@
@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 @@
}
NetconfSession session = getNetconfSession();
-
if (session == null) {
log.error("Lumentum NETCONF - session not found for {}", deviceId);
return ImmutableList.of();
@@ -195,6 +196,7 @@
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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
}
}
+ /**
+ * 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();
}
}
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmFlowRuleProgrammable.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmFlowRuleProgrammable.java
index 13f82eb..57cc025 100644
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmFlowRuleProgrammable.java
+++ b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumNetconfRoadmFlowRuleProgrammable.java
@@ -21,27 +21,23 @@
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.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 @@
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 @@
*/
@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 @@
*/
@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 @@
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 @@
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 @@
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 @@
double inputPower = state.getDouble(CHANNEL_INPUT_POWER);
double outputPower = state.getDouble(CHANNEL_OUTPUT_POWER);
- if (pair == null) {
- return null;
- }
+ PortNumber portNumber = getPortNumber(moduleId, inputPortReference, outputPortReference);
- PortNumber portNumber = getPortNumber(pair.getLeft(), 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 @@
*/
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- 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 @@
*
* 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();
+ }
}
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumPowerConfig.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumPowerConfig.java
index 16000bd..7bc44c6 100644
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumPowerConfig.java
+++ b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumPowerConfig.java
@@ -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.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 @@
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 @@
//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 @@
}
//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 @@
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();
}
}
\ No newline at end of file
diff --git a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumRoadmLambdaQuery.java b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumRoadmLambdaQuery.java
index cfd54c8..53fdc63 100644
--- a/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumRoadmLambdaQuery.java
+++ b/drivers/lumentum/src/main/java/org/onosproject/drivers/lumentum/LumentumRoadmLambdaQuery.java
@@ -17,17 +17,19 @@
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 @@
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 @@
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();
+ }
}
}