blob: cf1a179923a652081a38031648528310432fce12 [file] [log] [blame]
Jimmy Jinc0198032016-01-04 13:26:10 -08001/*
yjimmyy646aa022016-07-05 12:09:50 -07002 * Copyright 2016 Open Networking Laboratory
Jimmy Jinc0198032016-01-04 13:26:10 -08003 *
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
7 *
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.
15 */
HIGUCHI Yuta07a9e562016-05-23 16:41:17 -070016package org.onosproject.driver.optical.handshaker;
Jimmy Jinc0198032016-01-04 13:26:10 -080017
18import com.google.common.collect.ImmutableList;
19import com.google.common.collect.ImmutableSet;
20
21import java.io.IOException;
22import java.util.ArrayList;
23import java.util.Collections;
24import java.util.List;
25import java.util.Set;
26import java.util.concurrent.atomic.AtomicBoolean;
27
yjimmyy646aa022016-07-05 12:09:50 -070028import org.onosproject.net.AnnotationKeys;
29import org.onosproject.net.DefaultAnnotations;
Jimmy Jinc0198032016-01-04 13:26:10 -080030import org.onosproject.net.Device;
yjimmyy646aa022016-07-05 12:09:50 -070031import org.onosproject.net.Port;
32import org.onosproject.net.PortNumber;
33import org.onosproject.net.device.DefaultPortDescription;
34import org.onosproject.net.device.DeviceService;
35import org.onosproject.net.device.PortDescription;
Jimmy Jinc0198032016-01-04 13:26:10 -080036import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
37import org.onosproject.openflow.controller.PortDescPropertyType;
38import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
39import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
40import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
41import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
42import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
43import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
44import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
45import org.projectfloodlight.openflow.protocol.OFMessage;
46import org.projectfloodlight.openflow.protocol.OFObject;
yjimmyy646aa022016-07-05 12:09:50 -070047import org.projectfloodlight.openflow.protocol.OFOplinkPortPower;
Jimmy Jinc0198032016-01-04 13:26:10 -080048import org.projectfloodlight.openflow.protocol.OFPortDesc;
49import org.projectfloodlight.openflow.protocol.OFPortOptical;
50import org.projectfloodlight.openflow.protocol.OFStatsReply;
yjimmyy646aa022016-07-05 12:09:50 -070051import org.projectfloodlight.openflow.protocol.OFStatsRequest;
Jimmy Jinc0198032016-01-04 13:26:10 -080052import org.projectfloodlight.openflow.protocol.OFStatsType;
yjimmyy646aa022016-07-05 12:09:50 -070053import org.projectfloodlight.openflow.protocol.OFType;
54import org.projectfloodlight.openflow.protocol.OFOplinkPortPowerRequest;
55import org.projectfloodlight.openflow.protocol.OFOplinkPortPowerReply;
56
Jimmy Jinc0198032016-01-04 13:26:10 -080057
58/**
59 * Driver for Oplink single WSS 8D ROADM.
60 *
61 * Driver implements custom handshaker and supports for Optical channel Port based on OpenFlow OTN extension.
62 * The device consists of Och ports, and performances wavelength cross-connect among the ports.
63 */
64public class OplinkRoadmHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
yjimmyy646aa022016-07-05 12:09:50 -070065
Jimmy Jinc0198032016-01-04 13:26:10 -080066 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
67 private List<OFPortOptical> opticalPorts;
68
69 @Override
70 public List<? extends OFObject> getPortsOf(PortDescPropertyType type) {
71 return ImmutableList.copyOf(opticalPorts);
72 }
73
74 @Override
75 /**
76 * Returns a list of standard (Ethernet) ports.
77 *
78 * @return List of ports
79 */
80 public List<OFPortDesc> getPorts() {
81 return Collections.EMPTY_LIST;
82 }
83
84 @Override
85 public Set<PortDescPropertyType> getPortTypes() {
86 return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
87 }
88
89 @Override
90 public Boolean supportNxRole() {
91 return false;
92 }
93
94 @Override
95 public void startDriverHandshake() {
96 log.warn("Starting driver handshake for sw {}", getStringId());
97 if (startDriverHandshakeCalled) {
98 throw new SwitchDriverSubHandshakeAlreadyStarted();
99 }
100 startDriverHandshakeCalled = true;
101 try {
102 sendHandshakeOFExperimenterPortDescRequest();
103 } catch (IOException e) {
104 log.error("OPLK ROADM exception while sending experimenter port desc:", e);
105 }
106 }
107
108 @Override
109 public boolean isDriverHandshakeComplete() {
110 return driverHandshakeComplete.get();
111 }
112
113 @Override
114 public void processDriverHandshakeMessage(OFMessage m) {
115
116 if (!startDriverHandshakeCalled) {
117 throw new SwitchDriverSubHandshakeNotStarted();
118 }
119
120 if (driverHandshakeComplete.get()) {
121 throw new SwitchDriverSubHandshakeCompleted(m);
122 }
123
124 switch (m.getType()) {
125 case BARRIER_REPLY:
126 log.debug("OPLK ROADM Received barrier response");
127 break;
128 case ERROR:
129 log.error("Switch {} Error {}", getStringId(), m);
130 break;
131 case FEATURES_REPLY:
132 break;
133 case FLOW_REMOVED:
134 break;
135 case GET_ASYNC_REPLY:
136 break;
137 case PACKET_IN:
138 break;
139 case PORT_STATUS:
140 processOFPortStatus((OFCircuitPortStatus) m);
141 break;
142 case QUEUE_GET_CONFIG_REPLY:
143 break;
144 case ROLE_REPLY:
145 break;
146 case STATS_REPLY:
147 OFStatsReply stats = (OFStatsReply) m;
148 if (stats.getStatsType() == OFStatsType.EXPERIMENTER) {
149 log.warn("OPLK ROADM : Received multipart (port desc) reply message {}", m);
150 //OTN Optical extension 1.0 port-desc
151 createOpticalPortList((OFCircuitPortsReply) m);
152 driverHandshakeComplete.set(true);
153 }
154 break;
155 default:
156 log.warn("Received message {} during switch-driver " +
157 "subhandshake " + "from switch {} ... " +
158 "Ignoring message", m,
159 getStringId());
160
161 }
162 }
163
164 private void processOFPortStatus(OFCircuitPortStatus ps) {
165 log.debug("OPLK ROADM ..OF Port Status :", ps);
166 }
167
168 @Override
169 public Device.Type deviceType() {
170 return Device.Type.ROADM;
171 }
172
173 @Override
174 public final void sendMsg(OFMessage m) {
175 OFMessage newMsg = m;
yjimmyy646aa022016-07-05 12:09:50 -0700176
177 if (m.getType() == OFType.STATS_REQUEST) {
178 OFStatsRequest sr = (OFStatsRequest) m;
179 log.debug("OPLK ROADM rebuilding stats request type {}", sr.getStatsType());
180 switch (sr.getStatsType()) {
181 case PORT:
182 //replace with Oplink experiment stats message to get the port current power
183 OFOplinkPortPowerRequest pRequest = this.factory().buildOplinkPortPowerRequest()
184 .setXid(sr.getXid())
185 .setFlags(sr.getFlags())
186 .build();
187 newMsg = pRequest;
188 break;
189 default:
190 break;
191 }
192 } else {
193 log.debug("OPLK ROADM sends msg:{}, as is", m.getType());
194 }
195
Jimmy Jinc0198032016-01-04 13:26:10 -0800196 super.sendMsg(newMsg);
197 }
198
199 private void sendHandshakeOFExperimenterPortDescRequest() throws IOException {
200 // send multi part message for port description for optical switches
201 OFCircuitPortsRequest circuitPortsRequest = factory()
202 .buildCircuitPortsRequest().setXid(getNextTransactionId())
203 .build();
204 log.info("OPLK ROADM : Sending experimented circuit port stats " +
205 "message " +
206 "{}",
207 circuitPortsRequest);
208 this.sendHandshakeMessage(circuitPortsRequest);
209 }
210
211 /**
212 * Builds list of OFPortOptical ports based on the multi-part circuit ports reply.
213 * Ensure the optical transport port's signal type is configured correctly.
214 *
215 * @param wPorts OF reply with circuit ports
216 */
217 private void createOpticalPortList(OFCircuitPortsReply wPorts) {
218 opticalPorts = new ArrayList<>();
219 opticalPorts.addAll(wPorts.getEntries());
220 }
yjimmyy646aa022016-07-05 12:09:50 -0700221
222 @Override
223 public List<PortDescription> processExpPortStats(OFMessage msg) {
224 if (msg instanceof OFOplinkPortPowerReply) {
225 return buildPortPowerDescriptions(((OFOplinkPortPowerReply) msg).getEntries());
226 }
227 return Collections.emptyList();
228 }
229
230 private OFOplinkPortPower getPortPower(List<OFOplinkPortPower> portPowers, PortNumber portNum) {
231 for (OFOplinkPortPower power : portPowers) {
232 if (power.getPort() == portNum.toLong()) {
233 return power;
234 }
235 }
236 return null;
237 }
238
239 private List<PortDescription> buildPortPowerDescriptions(List<OFOplinkPortPower> portPowers) {
240 DeviceService deviceService = this.handler().get(DeviceService.class);
241 List<Port> ports = deviceService.getPorts(this.data().deviceId());
242 final List<PortDescription> portDescs = new ArrayList<>();
243 for (Port port : ports) {
244 DefaultAnnotations.Builder builder = DefaultAnnotations.builder();
245 builder.putAll(port.annotations());
246 OFOplinkPortPower power = getPortPower(portPowers, port.number());
247 if (power != null) {
248 builder.set(AnnotationKeys.CURRENT_POWER, Long.toString(power.getPowerValue()));
249 }
250 portDescs.add(new DefaultPortDescription(port.number(), port.isEnabled(),
251 port.type(), port.portSpeed(), builder.build()));
252 }
253 return portDescs;
254 }
Jimmy Jinc0198032016-01-04 13:26:10 -0800255}