2 * Copyright 2015 Open Networking Laboratory
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org.onosproject.driver.handshaker;
18 import org.onosproject.net.Device;
19 import com.google.common.collect.ImmutableSet;
20 import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
21 import org.onosproject.openflow.controller.PortDescPropertyType;
22 import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
23 import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted;
24 import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted;
25 import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted;
26 import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus;
27 import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply;
28 import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest;
29 import org.projectfloodlight.openflow.protocol.OFMessage;
30 import org.projectfloodlight.openflow.protocol.OFObject;
31 import org.projectfloodlight.openflow.protocol.OFPortDesc;
32 import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport;
33 import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
34 import org.projectfloodlight.openflow.protocol.OFPortOptical;
35 import org.projectfloodlight.openflow.protocol.OFStatsReply;
36 import org.projectfloodlight.openflow.protocol.OFStatsType;
37 import org.projectfloodlight.openflow.types.OFPort;
39 import java.io.IOException;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.List;
44 import java.util.concurrent.atomic.AtomicBoolean;
47 * LINC-OE Optical Emulator switch class.
49 * The LINC ROADM emulator exposes two types of ports: OCh ports connect to ports in the packet layer,
50 * while OMS ports connect to an OMS port on a neighbouring ROADM.
52 * LINC sends the tap ports (OCh for our purposes) in the regular port desc stats reply,
53 * while it sends *all* ports (both tap and WDM ports, i.e., OCh and OMS) in the experimenter port desc stats reply.
56 public class OFOpticalSwitchImplLINC13
57 extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
59 private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
60 private long barrierXidToWaitFor = -1;
62 private List<OFPortOptical> opticalPorts;
65 public void startDriverHandshake() {
66 log.warn("Starting driver handshake for sw {}", getStringId());
67 if (startDriverHandshakeCalled) {
68 throw new SwitchDriverSubHandshakeAlreadyStarted();
70 startDriverHandshakeCalled = true;
72 sendHandshakeOFExperimenterPortDescRequest();
73 } catch (IOException e) {
74 log.error("LINC-OE exception while sending experimenter port desc:",
81 public boolean isDriverHandshakeComplete() {
82 return driverHandshakeComplete.get();
86 public void processDriverHandshakeMessage(OFMessage m) {
87 if (!startDriverHandshakeCalled) {
88 throw new SwitchDriverSubHandshakeNotStarted();
90 if (driverHandshakeComplete.get()) {
91 throw new SwitchDriverSubHandshakeCompleted(m);
94 switch (m.getType()) {
96 if (m.getXid() == barrierXidToWaitFor) {
97 log.debug("LINC-OE Received barrier response");
101 log.error("Switch {} Error {}", getStringId(), m);
107 case GET_ASYNC_REPLY:
112 log.warn("****LINC-OE Port Status {} {}", getStringId(), m);
113 processOFPortStatus((OFCircuitPortStatus) m);
115 case QUEUE_GET_CONFIG_REPLY:
120 OFStatsReply stats = (OFStatsReply) m;
121 if (stats.getStatsType() == OFStatsType.EXPERIMENTER) {
122 log.warn("LINC-OE : Received stats reply message {}", m);
123 createOpticalPortList((OFCircuitPortsReply) m);
124 driverHandshakeComplete.set(true);
128 log.warn("Received message {} during switch-driver " +
129 "subhandshake " + "from switch {} ... " +
130 "Ignoring message", m,
136 public void processOFPortStatus(OFCircuitPortStatus ps) {
137 log.debug("LINC-OE ..OF Port Status :", ps);
140 private void sendHandshakeOFExperimenterPortDescRequest() throws
142 // send multi part message for port description for optical switches
143 OFCircuitPortsRequest circuitPortsRequest = factory()
144 .buildCircuitPortsRequest().setXid(getNextTransactionId())
146 log.warn("LINC-OE : Sending experimented circuit port stats " +
149 circuitPortsRequest.toString());
150 this.sendHandshakeMessage(circuitPortsRequest);
155 * Returns a list of standard (Ethernet) ports.
157 * @return List of ports
159 public List<OFPortDesc> getPorts() {
160 return Collections.EMPTY_LIST;
165 public Boolean supportNxRole() {
170 public Device.Type deviceType() {
171 return Device.Type.ROADM;
175 * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port.
177 * @param port given OF port
178 * @return true if the port is a tap (OCh), false otherwise (OMS port)
180 private boolean hasPort(OFPort port) {
181 for (OFPortDescStatsReply reply : this.ports) {
182 for (OFPortDesc p : reply.getEntries()) {
183 if (p.getPortNo().equals(port)) {
193 * Creates an OpenFlow optical port based on the given port and transport type.
195 * @param port OpenFlow optical port
196 * @param type transport type
197 * @return OpenFlow optical port
199 private OFPortOptical createOpticalPort(OFPortOptical port, short type) {
200 List<OFPortDescPropOpticalTransport> descList = new ArrayList<>(port.getDesc().size());
202 for (OFPortDescPropOpticalTransport desc : port.getDesc()) {
203 OFPortDescPropOpticalTransport newDesc = desc.createBuilder()
204 .setType(desc.getType())
205 .setPortSignalType(type)
206 .setPortType(desc.getPortType())
207 .setReserved(desc.getReserved())
209 descList.add(newDesc);
212 OFPortOptical newPort = port.createBuilder()
213 .setConfig(port.getConfig())
215 .setHwAddr(port.getHwAddr())
216 .setName(port.getName())
217 .setPortNo(port.getPortNo())
218 .setState(port.getState())
225 * Builds list of OFPortOptical ports based on the multi-part circuit ports reply.
227 * Ensure the optical transport port's signal type is configured correctly.
229 * @param wPorts OF reply with circuit ports
231 private void createOpticalPortList(OFCircuitPortsReply wPorts) {
232 opticalPorts = new ArrayList<>(wPorts.getEntries().size());
234 for (OFPortOptical p : wPorts.getEntries()) {
237 // FIXME: use constants once loxi has full optical extensions
238 if (hasPort(p.getPortNo())) {
239 signalType = 5; // OCH port
241 signalType = 2; // OMS port
244 opticalPorts.add(createOpticalPort(p, signalType));
249 public List<? extends OFObject> getPortsOf(PortDescPropertyType type) {
250 if (!type.equals(PortDescPropertyType.OPTICAL_TRANSPORT)) {
251 return Collections.EMPTY_LIST;
258 public Set<PortDescPropertyType> getPortTypes() {
259 return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);