7faee37416ee32cf98e0a9e308d757d34d3fe963
[onosfw.git] /
1 /*
2  * Copyright 2015 Open Networking Laboratory
3  *
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  */
16 package org.onosproject.driver.handshaker;
17
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;
38
39 import java.io.IOException;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.List;
43 import java.util.Set;
44 import java.util.concurrent.atomic.AtomicBoolean;
45
46 /**
47  * LINC-OE Optical Emulator switch class.
48  *
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.
51  *
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.
54  *
55  */
56 public class OFOpticalSwitchImplLINC13
57  extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
58
59     private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
60     private long barrierXidToWaitFor = -1;
61
62     private List<OFPortOptical> opticalPorts;
63
64     @Override
65     public void startDriverHandshake() {
66         log.warn("Starting driver handshake for sw {}", getStringId());
67         if (startDriverHandshakeCalled) {
68             throw new SwitchDriverSubHandshakeAlreadyStarted();
69         }
70         startDriverHandshakeCalled = true;
71         try {
72             sendHandshakeOFExperimenterPortDescRequest();
73         } catch (IOException e) {
74             log.error("LINC-OE exception while sending experimenter port desc:",
75                      e.getMessage());
76             e.printStackTrace();
77         }
78     }
79
80     @Override
81     public boolean isDriverHandshakeComplete() {
82         return driverHandshakeComplete.get();
83     }
84
85     @Override
86     public void processDriverHandshakeMessage(OFMessage m) {
87         if (!startDriverHandshakeCalled) {
88             throw new SwitchDriverSubHandshakeNotStarted();
89         }
90         if (driverHandshakeComplete.get()) {
91             throw new SwitchDriverSubHandshakeCompleted(m);
92         }
93
94         switch (m.getType()) {
95             case BARRIER_REPLY:
96                 if (m.getXid() == barrierXidToWaitFor) {
97                     log.debug("LINC-OE Received barrier response");
98                 }
99                 break;
100             case ERROR:
101                 log.error("Switch {} Error {}", getStringId(), m);
102                 break;
103             case FEATURES_REPLY:
104                 break;
105             case FLOW_REMOVED:
106                 break;
107             case GET_ASYNC_REPLY:
108                 break;
109             case PACKET_IN:
110                 break;
111             case PORT_STATUS:
112                 log.warn("****LINC-OE Port Status {} {}", getStringId(), m);
113                 processOFPortStatus((OFCircuitPortStatus) m);
114                 break;
115             case QUEUE_GET_CONFIG_REPLY:
116                 break;
117             case ROLE_REPLY:
118                 break;
119             case STATS_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);
125                 }
126                 break;
127             default:
128                 log.warn("Received message {} during switch-driver " +
129                                  "subhandshake " + "from switch {} ... " +
130                                  "Ignoring message", m,
131                          getStringId());
132
133         }
134     }
135
136     public void processOFPortStatus(OFCircuitPortStatus ps) {
137         log.debug("LINC-OE ..OF Port Status :", ps);
138     }
139
140     private void sendHandshakeOFExperimenterPortDescRequest() throws
141             IOException {
142         // send multi part message for port description for optical switches
143         OFCircuitPortsRequest circuitPortsRequest = factory()
144                 .buildCircuitPortsRequest().setXid(getNextTransactionId())
145                 .build();
146         log.warn("LINC-OE : Sending experimented circuit port stats " +
147                          "message " +
148                          "{}",
149                  circuitPortsRequest.toString());
150         this.sendHandshakeMessage(circuitPortsRequest);
151     }
152
153     @Override
154     /**
155      * Returns a list of standard (Ethernet) ports.
156      *
157      * @return List of ports
158      */
159     public List<OFPortDesc> getPorts() {
160         return Collections.EMPTY_LIST;
161     }
162
163
164     @Override
165     public Boolean supportNxRole() {
166         return false;
167     }
168
169     @Override
170     public Device.Type deviceType() {
171         return Device.Type.ROADM;
172     }
173
174     /**
175      * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port.
176      *
177      * @param port given OF port
178      * @return true if the port is a tap (OCh), false otherwise (OMS port)
179      */
180     private boolean hasPort(OFPort port) {
181         for (OFPortDescStatsReply reply : this.ports) {
182             for (OFPortDesc p : reply.getEntries()) {
183                 if (p.getPortNo().equals(port)) {
184                     return true;
185                 }
186             }
187         }
188
189         return false;
190     }
191
192     /**
193      * Creates an OpenFlow optical port based on the given port and transport type.
194      *
195      * @param port OpenFlow optical port
196      * @param type transport type
197      * @return OpenFlow optical port
198      */
199     private OFPortOptical createOpticalPort(OFPortOptical port, short type) {
200         List<OFPortDescPropOpticalTransport> descList = new ArrayList<>(port.getDesc().size());
201
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())
208                     .build();
209             descList.add(newDesc);
210         }
211
212         OFPortOptical newPort = port.createBuilder()
213                 .setConfig(port.getConfig())
214                 .setDesc(descList)
215                 .setHwAddr(port.getHwAddr())
216                 .setName(port.getName())
217                 .setPortNo(port.getPortNo())
218                 .setState(port.getState())
219                 .build();
220
221         return newPort;
222     }
223
224     /**
225      * Builds list of OFPortOptical ports based on the multi-part circuit ports reply.
226      *
227      * Ensure the optical transport port's signal type is configured correctly.
228      *
229      * @param wPorts OF reply with circuit ports
230      */
231     private void createOpticalPortList(OFCircuitPortsReply wPorts) {
232         opticalPorts = new ArrayList<>(wPorts.getEntries().size());
233
234         for (OFPortOptical p : wPorts.getEntries()) {
235             short signalType;
236
237             // FIXME: use constants once loxi has full optical extensions
238             if (hasPort(p.getPortNo())) {
239                 signalType = 5;      // OCH port
240             } else {
241                 signalType = 2;      // OMS port
242             }
243
244             opticalPorts.add(createOpticalPort(p, signalType));
245         }
246     }
247
248     @Override
249     public List<? extends OFObject> getPortsOf(PortDescPropertyType type) {
250         if (!type.equals(PortDescPropertyType.OPTICAL_TRANSPORT)) {
251             return Collections.EMPTY_LIST;
252         }
253
254         return opticalPorts;
255     }
256
257     @Override
258     public Set<PortDescPropertyType> getPortTypes() {
259         return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
260     }
261 }