blob: 92aa0f56a5e2545493ef3c6103142a74e150b82c [file] [log] [blame]
Andrea Campanellad8d92db2016-01-14 16:24:41 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Andrea Campanellad8d92db2016-01-14 16:24:41 -08003 *
Ray Milkey85267002016-11-16 11:06:35 -08004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Andrea Campanellad8d92db2016-01-14 16:24:41 -08007 *
Ray Milkey85267002016-11-16 11:06:35 -08008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Andrea Campanellad8d92db2016-01-14 16:24:41 -080015 */
Andrea Campanella238d96e2016-01-20 11:52:02 -080016package org.onosproject.drivers.ciena;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080017
Andrea Campanella6c71a052016-04-22 11:56:31 -070018import com.google.common.collect.ImmutableList;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080019import com.google.common.collect.Lists;
20import org.apache.commons.configuration.HierarchicalConfiguration;
Fahad Naeem Khan752829a2017-07-31 11:57:54 -070021import org.onlab.packet.ChassisId;
Andrea Campanella238d96e2016-01-20 11:52:02 -080022import org.onosproject.drivers.utilities.XmlConfigParser;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080023import org.onosproject.net.AnnotationKeys;
HIGUCHI Yuta9605c782016-05-16 14:34:05 -070024import org.onosproject.net.ChannelSpacing;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080025import org.onosproject.net.CltSignalType;
26import org.onosproject.net.DefaultAnnotations;
Fahad Naeem Khan752829a2017-07-31 11:57:54 -070027import org.onosproject.net.Device;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080028import org.onosproject.net.DeviceId;
HIGUCHI Yuta9605c782016-05-16 14:34:05 -070029import org.onosproject.net.GridType;
30import org.onosproject.net.OchSignal;
31import org.onosproject.net.OduSignalType;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080032import org.onosproject.net.PortNumber;
HIGUCHI Yuta9605c782016-05-16 14:34:05 -070033import org.onosproject.net.SparseAnnotations;
Fahad Naeem Khan752829a2017-07-31 11:57:54 -070034import org.onosproject.net.device.DefaultDeviceDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070035import org.onosproject.net.device.DeviceDescription;
36import org.onosproject.net.device.DeviceDescriptionDiscovery;
Fahad Naeem Khan752829a2017-07-31 11:57:54 -070037import org.onosproject.net.device.DeviceService;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080038import org.onosproject.net.device.PortDescription;
39import org.onosproject.net.driver.AbstractHandlerBehaviour;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080040import org.onosproject.protocol.rest.RestSBController;
Andrea Campanella6c71a052016-04-22 11:56:31 -070041import org.slf4j.Logger;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080042
Andrea Campanellad8d92db2016-01-14 16:24:41 -080043import java.util.List;
fahadnaeemkhan482951f2017-08-24 16:35:17 -070044import java.util.ArrayList;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080045
46import static com.google.common.base.Preconditions.checkNotNull;
HIGUCHI Yuta9605c782016-05-16 14:34:05 -070047import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription;
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -070048import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription;
Andrea Campanella6c71a052016-04-22 11:56:31 -070049import static org.slf4j.LoggerFactory.getLogger;
Andrea Campanellad8d92db2016-01-14 16:24:41 -080050
51/**
52 * Discovers the ports from a Ciena WaveServer Rest device.
53 */
fahadnaeemkhan71827242017-09-21 15:10:07 -070054//TODO: Use CienaRestDevice
Andrea Campanella6c71a052016-04-22 11:56:31 -070055public class CienaWaveserverDeviceDescription extends AbstractHandlerBehaviour
56 implements DeviceDescriptionDiscovery {
57
58 private final Logger log = getLogger(getClass());
Andrea Campanellad8d92db2016-01-14 16:24:41 -080059
Marc De Leenheerf3818762017-03-20 13:19:55 -070060 private static final String PORT_ID = "ptp-index";
Andrea Campanellad8d92db2016-01-14 16:24:41 -080061 private static final String XML = "xml";
62 private static final String ENABLED = "enabled";
Marc De Leenheerf3818762017-03-20 13:19:55 -070063 private static final String ADMIN_STATE = "state.admin-state";
64 private static final String PORTS = "ws-ptps.ptps";
65 private static final String PORT_IN = "properties.line-system.cmd.port-in";
66 private static final String PORT_OUT = "properties.line-system.cmd.port-out";
Andrea Campanellad8d92db2016-01-14 16:24:41 -080067
fahadnaeemkhan482951f2017-08-24 16:35:17 -070068 private static final String CHANNEL_ID =
69 "properties.transmitter.line-system-channel-number";
Andrea Campanellad8d92db2016-01-14 16:24:41 -080070
Marc De Leenheerf3818762017-03-20 13:19:55 -070071 private static final String PORT_REQUEST =
72 "ciena-ws-ptp:ws-ptps?config=true&format=xml&depth=unbounded";
fahadnaeemkhan482951f2017-08-24 16:35:17 -070073 private static final ArrayList<String> LINESIDE_PORT_ID = Lists.newArrayList(
74 "4", "48");
Andrea Campanellad8d92db2016-01-14 16:24:41 -080075
Andrea Campanella6c71a052016-04-22 11:56:31 -070076 @Override
77 public DeviceDescription discoverDeviceDetails() {
Fahad Naeem Khan752829a2017-07-31 11:57:54 -070078 log.debug("getting device description");
79 DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
80 DeviceId deviceId = handler().data().deviceId();
81 Device device = deviceService.getDevice(deviceId);
82
83 if (device == null) {
84 return new DefaultDeviceDescription(deviceId.uri(),
85 Device.Type.OTN,
86 "Ciena",
87 "WaveServer",
88 "Unknown",
89 "Unknown",
90 new ChassisId());
91 } else {
92 return new DefaultDeviceDescription(device.id().uri(),
93 Device.Type.OTN,
94 device.manufacturer(),
95 device.hwVersion(),
96 device.swVersion(),
97 device.serialNumber(),
98 device.chassisId());
99 }
Andrea Campanella6c71a052016-04-22 11:56:31 -0700100 }
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800101
102 @Override
Andrea Campanella6c71a052016-04-22 11:56:31 -0700103 public List<PortDescription> discoverPortDetails() {
104 return getPorts();
105 }
106
107 private List<PortDescription> getPorts() {
fahadnaeemkhan482951f2017-08-24 16:35:17 -0700108 /*
109 * Relationship between ptp-index and port number shown in Ciena Wave Server
110 * CLI:
111 * ptp-index = 4 * port_number (without decimal) + decimal
112 * e.g
113 * if port_number is 5 then ptp-index = 5 * 4 + 0 = 20
114 * if port_number is 5.1 then ptp-index = 5 * 4 + 1 = 21
115 *
116 * Relationship between channelId and in/out port:
117 * in_port = channelId * 2
118 * out_port = channelId * 2 -1
119 */
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800120 List<PortDescription> ports = Lists.newArrayList();
Marc De Leenheerf3818762017-03-20 13:19:55 -0700121 RestSBController controller = checkNotNull(handler().get(RestSBController.class));
122 DeviceId deviceId = handler().data().deviceId();
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800123
124 HierarchicalConfiguration config = XmlConfigParser.
Marc De Leenheerf3818762017-03-20 13:19:55 -0700125 loadXml(controller.get(deviceId, PORT_REQUEST, XML));
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800126 List<HierarchicalConfiguration> portsConfig =
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700127 parseWaveServerCienaPorts(config);
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700128 portsConfig.forEach(sub -> {
Andrea Campanella2947e622016-01-27 09:23:46 -0800129 String portId = sub.getString(PORT_ID);
Marc De Leenheerf3818762017-03-20 13:19:55 -0700130 DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
Andrea Campanella2947e622016-01-27 09:23:46 -0800131 if (LINESIDE_PORT_ID.contains(portId)) {
fahadnaeemkhan482951f2017-08-24 16:35:17 -0700132 annotations.set(AnnotationKeys.CHANNEL_ID, sub.getString(CHANNEL_ID));
fahadnaeemkhan71827242017-09-21 15:10:07 -0700133 // TX/OUT and RX/IN ports
134 annotations.set(AnnotationKeys.PORT_OUT, sub.getString(PORT_OUT));
135 annotations.set(AnnotationKeys.PORT_IN, sub.getString(PORT_IN));
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700136 ports.add(parseWaveServerCienaOchPorts(
fahadnaeemkhan71827242017-09-21 15:10:07 -0700137 Long.valueOf(portId),
Marc De Leenheerf3818762017-03-20 13:19:55 -0700138 sub,
Andrea Campanella784ee0f2016-02-17 15:50:59 -0800139 annotations.build()));
Marc De Leenheerf3818762017-03-20 13:19:55 -0700140
Marc De Leenheerf3818762017-03-20 13:19:55 -0700141 } else if (!portId.equals("5") && !portId.equals("49")) {
142 DefaultAnnotations.builder()
143 .set(AnnotationKeys.PORT_NAME, portId);
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800144 //FIXME change when all optical types have two way information methods, see jira tickets
HIGUCHI Yuta4c0ef6b2016-05-02 19:45:41 -0700145 ports.add(oduCltPortDescription(PortNumber.portNumber(sub.getLong(PORT_ID)),
Andrea Campanella6c71a052016-04-22 11:56:31 -0700146 sub.getString(ADMIN_STATE).equals(ENABLED),
Marc De Leenheerf3818762017-03-20 13:19:55 -0700147 CltSignalType.CLT_100GBE, annotations.build()));
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800148 }
149 });
Andrea Campanella6c71a052016-04-22 11:56:31 -0700150 return ImmutableList.copyOf(ports);
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800151 }
152
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700153 public static List<HierarchicalConfiguration> parseWaveServerCienaPorts(HierarchicalConfiguration cfg) {
Marc De Leenheerf3818762017-03-20 13:19:55 -0700154 return cfg.configurationsAt(PORTS);
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700155 }
156
Marc De Leenheerf3818762017-03-20 13:19:55 -0700157 public static PortDescription parseWaveServerCienaOchPorts(long portNumber,
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700158 HierarchicalConfiguration config,
159 SparseAnnotations annotations) {
Marc De Leenheerf3818762017-03-20 13:19:55 -0700160 final List<String> tunableType = Lists.newArrayList("performance-optimized", "accelerated");
161 final String flexGrid = "flex-grid";
162 final String state = "properties.transmitter.state";
163 final String tunable = "properties.modem.tx-tuning-mode";
164 final String spacing = "properties.line-system.wavelength-spacing";
165 final String frequency = "properties.transmitter.frequency.value";
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700166
Marc De Leenheerf3818762017-03-20 13:19:55 -0700167 boolean isEnabled = config.getString(state).equals(ENABLED);
168 boolean isTunable = tunableType.contains(config.getString(tunable));
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700169
Marc De Leenheerf3818762017-03-20 13:19:55 -0700170 GridType gridType = config.getString(spacing).equals(flexGrid) ? GridType.FLEX : null;
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700171 ChannelSpacing chSpacing = gridType == GridType.FLEX ? ChannelSpacing.CHL_6P25GHZ : null;
172
173 //Working in Ghz //(Nominal central frequency - 193.1)/channelSpacing = spacingMultiplier
174 final int baseFrequency = 193100;
Marc De Leenheerf3818762017-03-20 13:19:55 -0700175 int spacingMult = (int) (toGbps(((int) config.getDouble(frequency) -
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700176 baseFrequency)) / toGbpsFromHz(chSpacing.frequency().asHz())); //FIXME is there a better way ?
177
Marc De Leenheerf3818762017-03-20 13:19:55 -0700178 return ochPortDescription(PortNumber.portNumber(portNumber), isEnabled, OduSignalType.ODU4, isTunable,
Andrea Campanella6c71a052016-04-22 11:56:31 -0700179 new OchSignal(gridType, chSpacing, spacingMult, 1), annotations);
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700180 }
181
fahadnaeemkhan71827242017-09-21 15:10:07 -0700182 public static ArrayList<String> getLinesidePortId() {
183 return LINESIDE_PORT_ID;
184 }
185
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800186 //FIXME remove when all optical types have two way information methods, see jira tickets
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700187 private static long toGbps(long speed) {
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800188 return speed * 1000;
189 }
Andrea Campanella2947e622016-01-27 09:23:46 -0800190
HIGUCHI Yuta9605c782016-05-16 14:34:05 -0700191 private static long toGbpsFromHz(long speed) {
192 return speed / 1000;
193 }
Andrea Campanellad8d92db2016-01-14 16:24:41 -0800194}
195