Praseed Balakrishnan | e48aa68 | 2014-10-08 17:31:37 -0700 | [diff] [blame] | 1 | package org.onlab.onos.openflow.drivers.impl; |
| 2 | |
| 3 | import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted; |
| 4 | import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeCompleted; |
| 5 | import org.onlab.onos.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; |
| 6 | import org.onlab.onos.openflow.controller.Dpid; |
| 7 | import org.onlab.onos.openflow.controller.driver.AbstractOpenFlowSwitch; |
| 8 | import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply; |
| 9 | import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest; |
| 10 | import org.projectfloodlight.openflow.protocol.OFDescStatsReply; |
| 11 | import org.projectfloodlight.openflow.protocol.OFErrorMsg; |
| 12 | import org.projectfloodlight.openflow.protocol.OFMatchV3; |
| 13 | import org.projectfloodlight.openflow.protocol.OFMessage; |
| 14 | import org.projectfloodlight.openflow.protocol.OFOxmList; |
| 15 | import org.projectfloodlight.openflow.protocol.OFPortDesc; |
| 16 | import org.projectfloodlight.openflow.protocol.OFPortOptical; |
| 17 | import org.projectfloodlight.openflow.protocol.action.OFAction; |
| 18 | import org.projectfloodlight.openflow.protocol.action.OFActionCircuit; |
| 19 | import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; |
| 20 | import org.projectfloodlight.openflow.protocol.oxm.OFOxmInPort; |
| 21 | import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigid; |
| 22 | import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic; |
| 23 | import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtype; |
| 24 | import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigtypeBasic; |
| 25 | import org.projectfloodlight.openflow.types.CircuitSignalID; |
| 26 | import org.projectfloodlight.openflow.types.OFPort; |
| 27 | import org.projectfloodlight.openflow.types.U8; |
| 28 | import org.slf4j.Logger; |
| 29 | import org.slf4j.LoggerFactory; |
| 30 | |
| 31 | import java.io.IOException; |
| 32 | import java.util.ArrayList; |
| 33 | import java.util.Collection; |
| 34 | import java.util.Collections; |
| 35 | import java.util.List; |
| 36 | import java.util.concurrent.atomic.AtomicBoolean; |
| 37 | |
| 38 | /** |
| 39 | * LINC-OE Optical Emulator switch class. |
| 40 | */ |
| 41 | public class OFOpticalSwitchImplLINC13 extends AbstractOpenFlowSwitch { |
| 42 | |
| 43 | private final AtomicBoolean driverHandshakeComplete; |
| 44 | private long barrierXidToWaitFor = -1; |
| 45 | |
| 46 | private final Logger log = |
| 47 | LoggerFactory.getLogger(OFOpticalSwitchImplLINC13.class); |
| 48 | |
Yuta HIGUCHI | bccb6be | 2014-10-09 17:20:29 -0700 | [diff] [blame] | 49 | OFOpticalSwitchImplLINC13(Dpid dpid, OFDescStatsReply desc) { |
Praseed Balakrishnan | e48aa68 | 2014-10-08 17:31:37 -0700 | [diff] [blame] | 50 | super(dpid); |
| 51 | //setAttribute("optical", "true"); |
| 52 | driverHandshakeComplete = new AtomicBoolean(false); |
| 53 | setSwitchDescription(desc); |
| 54 | } |
| 55 | |
| 56 | @Override |
| 57 | public String toString() { |
| 58 | return "OFOpticalSwitchImplLINC13 [" + ((channel != null) |
| 59 | ? channel.getRemoteAddress() : "?") |
| 60 | + " DPID[" + ((getStringId() != null) ? getStringId() : "?") + "]]"; |
| 61 | } |
| 62 | |
| 63 | @Override |
| 64 | public void startDriverHandshake() { |
| 65 | log.debug("Starting driver handshake for sw {}", getStringId()); |
| 66 | if (startDriverHandshakeCalled) { |
| 67 | throw new SwitchDriverSubHandshakeAlreadyStarted(); |
| 68 | } |
| 69 | startDriverHandshakeCalled = true; |
| 70 | try { |
| 71 | sendHandshakeOFExperimenterPortDescRequest(); |
| 72 | } catch (IOException e) { |
| 73 | e.printStackTrace(); |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | @Override |
| 78 | public boolean isDriverHandshakeComplete() { |
| 79 | if (!startDriverHandshakeCalled) { |
| 80 | throw new SwitchDriverSubHandshakeNotStarted(); |
| 81 | } |
| 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(), (OFErrorMsg) 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 | break; |
| 113 | case QUEUE_GET_CONFIG_REPLY: |
| 114 | break; |
| 115 | case ROLE_REPLY: |
| 116 | break; |
| 117 | case STATS_REPLY: |
| 118 | log.debug("LINC-OE : Received stats reply message {}", m); |
| 119 | processHandshakeOFExperimenterPortDescRequest( |
| 120 | (OFCircuitPortsReply) m); |
| 121 | driverHandshakeComplete.set(true); |
| 122 | /* try { |
| 123 | testMA(); |
| 124 | } catch (IOException e) { |
| 125 | e.printStackTrace(); |
| 126 | }*/ |
| 127 | break; |
| 128 | default: |
| 129 | log.debug("Received message {} during switch-driver " + |
| 130 | "subhandshake " + "from switch {} ... " + |
| 131 | "Ignoring message", m, |
| 132 | getStringId()); |
| 133 | |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | |
| 138 | private void processHandshakeOFExperimenterPortDescRequest( |
| 139 | OFCircuitPortsReply sr) { |
| 140 | Collection<OFPortOptical> entries = sr.getEntries(); |
| 141 | List<OFPortDesc> ofPortDescList = new ArrayList<>(entries.size()); |
| 142 | for (OFPortOptical entry : entries) { |
| 143 | ofPortDescList.add(factory().buildPortDesc(). |
| 144 | setPortNo(entry.getPortNo()) |
| 145 | .setConfig(entry.getConfig()) |
| 146 | .setState(entry.getState()) |
| 147 | .setHwAddr(entry.getHwAddr()) |
| 148 | .setName(entry.getName()) |
| 149 | .build()); |
| 150 | } |
| 151 | setPortDescReply(factory().buildPortDescStatsReply(). |
| 152 | setEntries(ofPortDescList).build()); |
| 153 | } |
| 154 | |
| 155 | |
| 156 | private void sendHandshakeOFExperimenterPortDescRequest() throws |
| 157 | IOException { |
| 158 | // send multi part message for port description for optical switches |
| 159 | OFCircuitPortsRequest circuitPortsRequest = factory() |
| 160 | .buildCircuitPortsRequest().setXid(getNextTransactionId()) |
| 161 | .build(); |
| 162 | log.debug("LINC-OE : Sending experimented circuit port stats " + |
| 163 | "message " + |
| 164 | "{}", |
| 165 | circuitPortsRequest.toString()); |
| 166 | channel.write(Collections.singletonList(circuitPortsRequest)); |
| 167 | } |
| 168 | |
| 169 | |
| 170 | |
| 171 | //todo for testing |
| 172 | public static final U8 SIGNAL_TYPE = U8.of((short) 1); |
| 173 | private void testMA() throws IOException { |
| 174 | log.debug("LINC OE *** Testing MA "); |
| 175 | short lambda = 100; |
| 176 | if (getId() == 0x0000ffffffffff02L) { |
| 177 | final int inport = 10; |
| 178 | final int outport = 20; |
| 179 | //Circuit signal id |
| 180 | CircuitSignalID sigID = getSignalID(lambda); |
| 181 | |
| 182 | OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID); |
| 183 | OFOxmOchSigtype fieldSigType = factory() |
| 184 | .oxms() |
| 185 | .ochSigtype(SIGNAL_TYPE); |
| 186 | |
| 187 | OFOxmOchSigidBasic ofOxmOchSigidBasic = |
| 188 | factory().oxms().ochSigidBasic(sigID); |
| 189 | |
| 190 | OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic = |
| 191 | factory().oxms().ochSigtypeBasic(SIGNAL_TYPE); |
| 192 | |
| 193 | //Match Port |
| 194 | OFOxmInPort fieldPort = factory().oxms() |
| 195 | .inPort(OFPort.of(inport)); |
| 196 | OFMatchV3 matchPort = |
| 197 | factory() |
| 198 | .buildMatchV3(). |
| 199 | setOxmList(OFOxmList.of(fieldPort, |
| 200 | fieldSigType, |
| 201 | fieldSigIDMatch)).build(); |
| 202 | |
| 203 | |
| 204 | // Set Action outport ,sigType and sigID |
| 205 | List<OFAction> actionList = new ArrayList<>(); |
| 206 | OFAction actionOutPort = |
| 207 | factory().actions().output(OFPort.of(outport), |
| 208 | Short.MAX_VALUE); |
| 209 | |
| 210 | OFActionCircuit actionCircuit = factory() |
| 211 | .actions() |
| 212 | .circuit(ofOxmOchSigidBasic); |
| 213 | OFActionCircuit setActionSigType = factory() |
| 214 | .actions() |
| 215 | .circuit(ofOxmOchSigtypeBasic); |
| 216 | |
| 217 | actionList.add(actionOutPort); |
| 218 | actionList.add(setActionSigType); |
| 219 | actionList.add(actionCircuit); |
| 220 | |
| 221 | OFInstruction instructionAction = |
| 222 | factory().instructions().buildApplyActions() |
| 223 | .setActions(actionList) |
| 224 | .build(); |
| 225 | List<OFInstruction> instructions = |
| 226 | Collections.singletonList(instructionAction); |
| 227 | |
| 228 | OFMessage opticalFlowEntry = |
| 229 | factory().buildFlowAdd() |
| 230 | .setMatch(matchPort) |
| 231 | .setInstructions(instructions) |
| 232 | .setXid(getNextTransactionId()) |
| 233 | .build(); |
| 234 | log.debug("Adding optical flow in sw {}", getStringId()); |
| 235 | List<OFMessage> msglist = new ArrayList<>(1); |
| 236 | msglist.add(opticalFlowEntry); |
| 237 | write(msglist); |
| 238 | } else if (getId() == 0x0000ffffffffff03L) { |
| 239 | final int inport = 21; |
| 240 | final int outport = 22; |
| 241 | //Circuit signal id |
| 242 | CircuitSignalID sigID = getSignalID(lambda); |
| 243 | |
| 244 | OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID); |
| 245 | OFOxmOchSigtype fieldSigType = factory() |
| 246 | .oxms() |
| 247 | .ochSigtype(SIGNAL_TYPE); |
| 248 | |
| 249 | OFOxmOchSigidBasic ofOxmOchSigidBasic = |
| 250 | factory().oxms().ochSigidBasic(sigID); |
| 251 | |
| 252 | OFOxmOchSigtypeBasic ofOxmOchSigtypeBasic = |
| 253 | factory().oxms().ochSigtypeBasic(SIGNAL_TYPE); |
| 254 | |
| 255 | //Match Port,SigType,SigID |
| 256 | OFOxmInPort fieldPort = factory() |
| 257 | .oxms() |
| 258 | .inPort(OFPort.of(inport)); |
| 259 | OFMatchV3 matchPort = factory() |
| 260 | .buildMatchV3() |
| 261 | .setOxmList(OFOxmList.of(fieldPort, |
| 262 | fieldSigType, |
| 263 | fieldSigIDMatch)) |
| 264 | .build(); |
| 265 | |
| 266 | // Set Action outport ,SigType, sigID |
| 267 | List<OFAction> actionList = new ArrayList<>(); |
| 268 | OFAction actionOutPort = |
| 269 | factory().actions().output(OFPort.of(outport), |
| 270 | Short.MAX_VALUE); |
| 271 | |
| 272 | OFActionCircuit setActionSigType = factory() |
| 273 | .actions() |
| 274 | .circuit(ofOxmOchSigtypeBasic); |
| 275 | OFActionCircuit actionCircuit = factory() |
| 276 | .actions() |
| 277 | .circuit(ofOxmOchSigidBasic); |
| 278 | |
| 279 | |
| 280 | actionList.add(actionOutPort); |
| 281 | actionList.add(setActionSigType); |
| 282 | actionList.add(actionCircuit); |
| 283 | |
| 284 | OFInstruction instructionAction = |
| 285 | factory().instructions().buildApplyActions() |
| 286 | .setActions(actionList) |
| 287 | .build(); |
| 288 | List<OFInstruction> instructions = |
| 289 | Collections.singletonList(instructionAction); |
| 290 | |
| 291 | OFMessage opticalFlowEntry = |
| 292 | factory().buildFlowAdd() |
| 293 | .setMatch(matchPort) |
| 294 | .setInstructions(instructions) |
| 295 | .setXid(getNextTransactionId()) |
| 296 | .build(); |
| 297 | log.debug("Adding optical flow in sw {}", getStringId()); |
| 298 | List<OFMessage> msglist = new ArrayList<>(1); |
| 299 | msglist.add(opticalFlowEntry); |
| 300 | write(msglist); |
| 301 | |
| 302 | } else if (getId() == 0x0000ffffffffff04L) { |
| 303 | final int inport = 23; |
| 304 | final int outport = 11; |
| 305 | //Circuit signal id |
| 306 | CircuitSignalID sigID = getSignalID(lambda); |
| 307 | |
| 308 | OFOxmOchSigid fieldSigIDMatch = factory().oxms().ochSigid(sigID); |
| 309 | OFOxmOchSigtype fieldSigType = factory() |
| 310 | .oxms() |
| 311 | .ochSigtype(SIGNAL_TYPE); |
| 312 | |
| 313 | |
| 314 | //Match Port, sig type and sig id |
| 315 | OFOxmInPort fieldPort = factory() |
| 316 | .oxms() |
| 317 | .inPort(OFPort.of(inport)); |
| 318 | OFMatchV3 matchPort = |
| 319 | factory().buildMatchV3() |
| 320 | .setOxmList(OFOxmList.of(fieldPort, |
| 321 | fieldSigType, |
| 322 | fieldSigIDMatch)) |
| 323 | .build(); |
| 324 | |
| 325 | // Set Action outport |
| 326 | List<OFAction> actionList = new ArrayList<>(); |
| 327 | OFAction actionOutPort = |
| 328 | factory().actions().output(OFPort.of(outport), |
| 329 | Short.MAX_VALUE); |
| 330 | |
| 331 | actionList.add(actionOutPort); |
| 332 | |
| 333 | OFInstruction instructionAction = |
| 334 | factory().instructions().buildApplyActions() |
| 335 | .setActions(actionList) |
| 336 | .build(); |
| 337 | List<OFInstruction> instructions = |
| 338 | Collections.singletonList(instructionAction); |
| 339 | |
| 340 | OFMessage opticalFlowEntry = |
| 341 | factory().buildFlowAdd() |
| 342 | .setMatch(matchPort) |
| 343 | .setInstructions(instructions) |
| 344 | .setXid(getNextTransactionId()) |
| 345 | .build(); |
| 346 | log.debug("Adding optical flow in sw {}", getStringId()); |
| 347 | List<OFMessage> msglist = new ArrayList<>(1); |
| 348 | msglist.add(opticalFlowEntry); |
| 349 | write(msglist); |
| 350 | } |
| 351 | |
| 352 | } |
| 353 | |
| 354 | // Todo remove - for testing purpose only |
| 355 | private static CircuitSignalID getSignalID(short lambda) { |
| 356 | byte myGrid = 1; |
| 357 | byte myCs = 2; |
| 358 | short myCn = lambda; |
| 359 | short mySw = 1; |
| 360 | |
| 361 | CircuitSignalID signalID = new CircuitSignalID(myGrid, |
| 362 | myCs, |
| 363 | myCn, |
| 364 | mySw); |
| 365 | return signalID; |
| 366 | } |
| 367 | |
| 368 | @Override |
| 369 | public void write(OFMessage msg) { |
| 370 | this.channel.write(msg); |
| 371 | } |
| 372 | |
| 373 | @Override |
| 374 | public void write(List<OFMessage> msgs) { |
| 375 | this.channel.write(msgs); |
| 376 | } |
| 377 | |
| 378 | @Override |
| 379 | public Boolean supportNxRole() { |
| 380 | return false; |
| 381 | } |
| 382 | |
| 383 | } |