Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 1 | /* |
Brian O'Connor | a09fe5b | 2017-08-03 21:12:30 -0700 | [diff] [blame] | 2 | * Copyright 2016-present Open Networking Foundation |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 3 | * |
Ray Milkey | 8526700 | 2016-11-16 11:06:35 -0800 | [diff] [blame] | 4 | * 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 Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 7 | * |
Ray Milkey | 8526700 | 2016-11-16 11:06:35 -0800 | [diff] [blame] | 8 | * 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 Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 15 | */ |
Andrea Campanella | 238d96e | 2016-01-20 11:52:02 -0800 | [diff] [blame] | 16 | package org.onosproject.drivers.ciena; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 17 | |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 18 | import com.google.common.collect.ImmutableList; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 19 | import com.google.common.collect.Lists; |
| 20 | import org.apache.commons.configuration.HierarchicalConfiguration; |
Fahad Naeem Khan | 752829a | 2017-07-31 11:57:54 -0700 | [diff] [blame] | 21 | import org.onlab.packet.ChassisId; |
Andrea Campanella | 238d96e | 2016-01-20 11:52:02 -0800 | [diff] [blame] | 22 | import org.onosproject.drivers.utilities.XmlConfigParser; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 23 | import org.onosproject.net.AnnotationKeys; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 24 | import org.onosproject.net.ChannelSpacing; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 25 | import org.onosproject.net.CltSignalType; |
| 26 | import org.onosproject.net.DefaultAnnotations; |
Fahad Naeem Khan | 752829a | 2017-07-31 11:57:54 -0700 | [diff] [blame] | 27 | import org.onosproject.net.Device; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 28 | import org.onosproject.net.DeviceId; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 29 | import org.onosproject.net.GridType; |
| 30 | import org.onosproject.net.OchSignal; |
| 31 | import org.onosproject.net.OduSignalType; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 32 | import org.onosproject.net.PortNumber; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 33 | import org.onosproject.net.SparseAnnotations; |
Fahad Naeem Khan | 752829a | 2017-07-31 11:57:54 -0700 | [diff] [blame] | 34 | import org.onosproject.net.device.DefaultDeviceDescription; |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 35 | import org.onosproject.net.device.DeviceDescription; |
| 36 | import org.onosproject.net.device.DeviceDescriptionDiscovery; |
Fahad Naeem Khan | 752829a | 2017-07-31 11:57:54 -0700 | [diff] [blame] | 37 | import org.onosproject.net.device.DeviceService; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 38 | import org.onosproject.net.device.PortDescription; |
| 39 | import org.onosproject.net.driver.AbstractHandlerBehaviour; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 40 | import org.onosproject.protocol.rest.RestSBController; |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 41 | import org.slf4j.Logger; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 42 | |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 43 | import java.util.List; |
| 44 | |
| 45 | import static com.google.common.base.Preconditions.checkNotNull; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 46 | import static org.onosproject.net.optical.device.OchPortHelper.ochPortDescription; |
HIGUCHI Yuta | 4c0ef6b | 2016-05-02 19:45:41 -0700 | [diff] [blame] | 47 | import static org.onosproject.net.optical.device.OduCltPortHelper.oduCltPortDescription; |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 48 | import static org.slf4j.LoggerFactory.getLogger; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 49 | |
| 50 | /** |
| 51 | * Discovers the ports from a Ciena WaveServer Rest device. |
| 52 | */ |
fahadnaeemkhan | 7182724 | 2017-09-21 15:10:07 -0700 | [diff] [blame] | 53 | //TODO: Use CienaRestDevice |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 54 | public class CienaWaveserverDeviceDescription extends AbstractHandlerBehaviour |
| 55 | implements DeviceDescriptionDiscovery { |
| 56 | |
| 57 | private final Logger log = getLogger(getClass()); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 58 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 59 | private static final String PORT_ID = "ptp-index"; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 60 | private static final String XML = "xml"; |
| 61 | private static final String ENABLED = "enabled"; |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 62 | private static final String ADMIN_STATE = "state.admin-state"; |
| 63 | private static final String PORTS = "ws-ptps.ptps"; |
| 64 | private static final String PORT_IN = "properties.line-system.cmd.port-in"; |
| 65 | private static final String PORT_OUT = "properties.line-system.cmd.port-out"; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 66 | |
fahadnaeemkhan | 482951f | 2017-08-24 16:35:17 -0700 | [diff] [blame] | 67 | private static final String CHANNEL_ID = |
| 68 | "properties.transmitter.line-system-channel-number"; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 69 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 70 | private static final String PORT_REQUEST = |
| 71 | "ciena-ws-ptp:ws-ptps?config=true&format=xml&depth=unbounded"; |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 72 | |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 73 | @Override |
| 74 | public DeviceDescription discoverDeviceDetails() { |
Fahad Naeem Khan | 752829a | 2017-07-31 11:57:54 -0700 | [diff] [blame] | 75 | log.debug("getting device description"); |
| 76 | DeviceService deviceService = checkNotNull(handler().get(DeviceService.class)); |
| 77 | DeviceId deviceId = handler().data().deviceId(); |
| 78 | Device device = deviceService.getDevice(deviceId); |
| 79 | |
| 80 | if (device == null) { |
| 81 | return new DefaultDeviceDescription(deviceId.uri(), |
| 82 | Device.Type.OTN, |
| 83 | "Ciena", |
| 84 | "WaveServer", |
| 85 | "Unknown", |
| 86 | "Unknown", |
| 87 | new ChassisId()); |
| 88 | } else { |
| 89 | return new DefaultDeviceDescription(device.id().uri(), |
| 90 | Device.Type.OTN, |
| 91 | device.manufacturer(), |
| 92 | device.hwVersion(), |
| 93 | device.swVersion(), |
| 94 | device.serialNumber(), |
| 95 | device.chassisId()); |
| 96 | } |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 97 | } |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 98 | |
| 99 | @Override |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 100 | public List<PortDescription> discoverPortDetails() { |
| 101 | return getPorts(); |
| 102 | } |
| 103 | |
| 104 | private List<PortDescription> getPorts() { |
fahadnaeemkhan | 482951f | 2017-08-24 16:35:17 -0700 | [diff] [blame] | 105 | /* |
| 106 | * Relationship between ptp-index and port number shown in Ciena Wave Server |
| 107 | * CLI: |
| 108 | * ptp-index = 4 * port_number (without decimal) + decimal |
| 109 | * e.g |
| 110 | * if port_number is 5 then ptp-index = 5 * 4 + 0 = 20 |
| 111 | * if port_number is 5.1 then ptp-index = 5 * 4 + 1 = 21 |
| 112 | * |
| 113 | * Relationship between channelId and in/out port: |
| 114 | * in_port = channelId * 2 |
| 115 | * out_port = channelId * 2 -1 |
| 116 | */ |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 117 | List<PortDescription> ports = Lists.newArrayList(); |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 118 | RestSBController controller = checkNotNull(handler().get(RestSBController.class)); |
| 119 | DeviceId deviceId = handler().data().deviceId(); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 120 | |
| 121 | HierarchicalConfiguration config = XmlConfigParser. |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 122 | loadXml(controller.get(deviceId, PORT_REQUEST, XML)); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 123 | List<HierarchicalConfiguration> portsConfig = |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 124 | parseWaveServerCienaPorts(config); |
Sho SHIMIZU | a09e1bb | 2016-08-01 14:25:25 -0700 | [diff] [blame] | 125 | portsConfig.forEach(sub -> { |
Andrea Campanella | 2947e62 | 2016-01-27 09:23:46 -0800 | [diff] [blame] | 126 | String portId = sub.getString(PORT_ID); |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 127 | DefaultAnnotations.Builder annotations = DefaultAnnotations.builder(); |
fahadnaeemkhan | a62bd2f | 2017-10-11 12:39:55 -0700 | [diff] [blame] | 128 | if (CienaRestDevice.getLinesidePortId().contains(portId)) { |
fahadnaeemkhan | 482951f | 2017-08-24 16:35:17 -0700 | [diff] [blame] | 129 | annotations.set(AnnotationKeys.CHANNEL_ID, sub.getString(CHANNEL_ID)); |
fahadnaeemkhan | 7182724 | 2017-09-21 15:10:07 -0700 | [diff] [blame] | 130 | // TX/OUT and RX/IN ports |
| 131 | annotations.set(AnnotationKeys.PORT_OUT, sub.getString(PORT_OUT)); |
| 132 | annotations.set(AnnotationKeys.PORT_IN, sub.getString(PORT_IN)); |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 133 | ports.add(parseWaveServerCienaOchPorts( |
fahadnaeemkhan | 7182724 | 2017-09-21 15:10:07 -0700 | [diff] [blame] | 134 | Long.valueOf(portId), |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 135 | sub, |
Andrea Campanella | 784ee0f | 2016-02-17 15:50:59 -0800 | [diff] [blame] | 136 | annotations.build())); |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 137 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 138 | } else if (!portId.equals("5") && !portId.equals("49")) { |
| 139 | DefaultAnnotations.builder() |
| 140 | .set(AnnotationKeys.PORT_NAME, portId); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 141 | //FIXME change when all optical types have two way information methods, see jira tickets |
HIGUCHI Yuta | 4c0ef6b | 2016-05-02 19:45:41 -0700 | [diff] [blame] | 142 | ports.add(oduCltPortDescription(PortNumber.portNumber(sub.getLong(PORT_ID)), |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 143 | sub.getString(ADMIN_STATE).equals(ENABLED), |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 144 | CltSignalType.CLT_100GBE, annotations.build())); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 145 | } |
| 146 | }); |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 147 | return ImmutableList.copyOf(ports); |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 148 | } |
| 149 | |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 150 | public static List<HierarchicalConfiguration> parseWaveServerCienaPorts(HierarchicalConfiguration cfg) { |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 151 | return cfg.configurationsAt(PORTS); |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 152 | } |
| 153 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 154 | public static PortDescription parseWaveServerCienaOchPorts(long portNumber, |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 155 | HierarchicalConfiguration config, |
| 156 | SparseAnnotations annotations) { |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 157 | final List<String> tunableType = Lists.newArrayList("performance-optimized", "accelerated"); |
| 158 | final String flexGrid = "flex-grid"; |
| 159 | final String state = "properties.transmitter.state"; |
| 160 | final String tunable = "properties.modem.tx-tuning-mode"; |
| 161 | final String spacing = "properties.line-system.wavelength-spacing"; |
| 162 | final String frequency = "properties.transmitter.frequency.value"; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 163 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 164 | boolean isEnabled = config.getString(state).equals(ENABLED); |
| 165 | boolean isTunable = tunableType.contains(config.getString(tunable)); |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 166 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 167 | GridType gridType = config.getString(spacing).equals(flexGrid) ? GridType.FLEX : null; |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 168 | ChannelSpacing chSpacing = gridType == GridType.FLEX ? ChannelSpacing.CHL_6P25GHZ : null; |
| 169 | |
| 170 | //Working in Ghz //(Nominal central frequency - 193.1)/channelSpacing = spacingMultiplier |
| 171 | final int baseFrequency = 193100; |
Ray Milkey | 74e5913 | 2018-01-17 15:24:52 -0800 | [diff] [blame^] | 172 | long spacingFrequency = chSpacing == null ? baseFrequency : chSpacing.frequency().asHz(); |
fahadnaeemkhan | a62bd2f | 2017-10-11 12:39:55 -0700 | [diff] [blame] | 173 | int spacingMult = ((int) (toGbps(((int) config.getDouble(frequency) - |
Ray Milkey | 74e5913 | 2018-01-17 15:24:52 -0800 | [diff] [blame^] | 174 | baseFrequency)) / toGbpsFromHz(spacingFrequency))); //FIXME is there a better way ? |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 175 | |
Marc De Leenheer | f381876 | 2017-03-20 13:19:55 -0700 | [diff] [blame] | 176 | return ochPortDescription(PortNumber.portNumber(portNumber), isEnabled, OduSignalType.ODU4, isTunable, |
Andrea Campanella | 6c71a05 | 2016-04-22 11:56:31 -0700 | [diff] [blame] | 177 | new OchSignal(gridType, chSpacing, spacingMult, 1), annotations); |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 178 | } |
| 179 | |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 180 | //FIXME remove when all optical types have two way information methods, see jira tickets |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 181 | private static long toGbps(long speed) { |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 182 | return speed * 1000; |
| 183 | } |
Andrea Campanella | 2947e62 | 2016-01-27 09:23:46 -0800 | [diff] [blame] | 184 | |
HIGUCHI Yuta | 9605c78 | 2016-05-16 14:34:05 -0700 | [diff] [blame] | 185 | private static long toGbpsFromHz(long speed) { |
| 186 | return speed / 1000; |
| 187 | } |
Andrea Campanella | d8d92db | 2016-01-14 16:24:41 -0800 | [diff] [blame] | 188 | } |
| 189 | |