@Override public Future<OFFeaturesReply> querySwitchFeaturesReply() throws IOException { OFMessage request = floodlightProvider.getOFMessageFactory().getMessage(OFType.FEATURES_REQUEST); request.setXid(getNextTransactionId()); OFFeaturesReplyFuture future = new OFFeaturesReplyFuture(threadPool, this, request.getXid()); this.featuresFutureMap.put(request.getXid(), future); List<OFMessage> msglist = new ArrayList<OFMessage>(1); msglist.add(request); this.write(msglist); return future; }
@Override public void deliverStatisticsReply(OFMessage reply) { OFStatisticsFuture future = this.statsFutureMap.get(reply.getXid()); if (future != null) { future.deliverFuture(this, reply); // The future will ultimately unregister itself and call // cancelStatisticsReply return; } /* Transaction id was not found in statsFutureMap.check the other map */ IOFMessageListener caller = this.iofMsgListenersMap.get(reply.getXid()); if (caller != null) { caller.receive(this, reply, null); } }
@Override public void deliverOFFeaturesReply(OFMessage reply) { OFFeaturesReplyFuture future = this.featuresFutureMap.get(reply.getXid()); if (future != null) { future.deliverFuture(this, reply); // The future will ultimately unregister itself and call // cancelFeaturesReply return; } log.error("Switch {}: received unexpected featureReply", this); }
/** * Handle replies to certain OFMessages, and pass others off to listeners * * @param sw * @param msgs * @throws IOException */ @SuppressWarnings("unchecked") protected void handleMessages(IOFSwitchExt sw, List<OFMessage> msgs) throws IOException { for (OFMessage m : msgs) { // If we detect a write failure, break early so we can disconnect if (((OFStream) sw.getInputStream()).getWriteFailure()) { break; } // Always handle ECHO REQUESTS, regardless of state switch (m.getType()) { case ECHO_REQUEST: OFMessageInStream in = sw.getInputStream(); OFMessageOutStream out = sw.getOutputStream(); OFEchoReply reply = (OFEchoReply) in.getMessageFactory().getMessage(OFType.ECHO_REPLY); reply.setXid(m.getXid()); out.write(reply); break; case ECHO_REPLY: // *Note, ECHO REPLIES need no handling due to last message timestamp break; case ERROR: logError(sw, (OFError) m); // fall through intentionally so error can be listened for default: switch (sw.getState()) { case DISCONNECTED: log.info("Switch {} in state DISCONNECTED, exiting message processing loop", sw); return; case HELLO_SENT: if (m.getType() == OFType.HELLO) { log.debug("HELLO from {}", sw); sw.transitionToState(OFSwitchState.FEATURES_REQUEST_SENT); // Send initial Features Request sw.getOutputStream().write(factory.getMessage(OFType.FEATURES_REQUEST)); } break; case FEATURES_REQUEST_SENT: if (m.getType() == OFType.FEATURES_REPLY) { log.debug("Features Reply from {}", sw); sw.setFeaturesReply((OFFeaturesReply) m); // Send Description Statistics Request OFStatisticsRequest sr = new OFStatisticsRequest(); sr.setStatisticType(OFStatisticsType.DESC); sw.getOutputStream().write(sr); sw.transitionToState(OFSwitchState.DESCRIPTION_STATISTICS_REQUEST_SENT); } break; case DESCRIPTION_STATISTICS_REQUEST_SENT: if (m.getType() == OFType.STATS_REPLY) { OFStatisticsReply sr = (OFStatisticsReply) m; if (sr.getStatisticType() == OFStatisticsType.DESC && sr.getStatistics().size() > 0) { OFDescriptionStatistics desc = (OFDescriptionStatistics) sr.getStatistics().get(0); sw.setDescriptionStatistics(desc); log.debug("Description Statistics Reply from {}: {}", sw, desc); // Set config and request to receive the config OFSetConfig config = (OFSetConfig) factory.getMessage(OFType.SET_CONFIG); config.setMissSendLength((short) 0xffff).setLengthU(OFSetConfig.MINIMUM_LENGTH); sw.getOutputStream().write(config); sw.getOutputStream().write(factory.getMessage(OFType.BARRIER_REQUEST)); sw.getOutputStream().write(factory.getMessage(OFType.GET_CONFIG_REQUEST)); sw.transitionToState(OFSwitchState.GET_CONFIG_REQUEST_SENT); } } break; case GET_CONFIG_REQUEST_SENT: if (m.getType() == OFType.GET_CONFIG_REPLY) { OFGetConfigReply cr = (OFGetConfigReply) m; if (cr.getMissSendLength() == (short) 0xffff) { log.debug("Config Reply from {} confirms miss length set to 0xffff", sw); sw.transitionToState(OFSwitchState.INITIALIZING); CopyOnWriteArrayList<IOFInitializerListener> initializers = (CopyOnWriteArrayList<IOFInitializerListener>) initializerList.clone(); // Add all existing initializers to the list this.initializerMap.put(sw, initializers); log.debug( "Remaining initializers for switch {}: {}", sw, this.initializerMap.get(sw)); // Delete all pre-existing flows if (deletePreExistingFlows) { OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); OFMessage fm = ((OFFlowMod) sw.getInputStream().getMessageFactory().getMessage(OFType.FLOW_MOD)) .setMatch(match) .setCommand(OFFlowMod.OFPFC_DELETE) .setOutPort(OFPort.OFPP_NONE) .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); sw.getOutputStream().write(fm); sw.getOutputStream().write(factory.getMessage(OFType.BARRIER_REQUEST)); } if (initializers.size() > 0) queueInitializer(sw, initializers.iterator().next()); else advanceInitializers(sw); } else { log.error( "Switch {} refused to set miss send length to 0xffff, disconnecting", sw); disconnectSwitch(((OFStream) sw.getInputStream()).getKey(), sw); return; } } break; case INITIALIZING: CopyOnWriteArrayList<IOFInitializerListener> initializers = initializerMap.get(sw); Iterator<IOFInitializerListener> it = initializers.iterator(); if (it.hasNext()) { IOFInitializerListener listener = it.next(); try { listener.initializerReceive(sw, m); } catch (Exception e) { log.error( "Error calling initializer listener: {} on switch: {} for message: {}, removing listener", new Object[] {listener, sw, m}); advanceInitializers(sw); } } break; case ACTIVE: List<IOFMessageListener> listeners = messageListeners.get(m.getType()); if (listeners != null) { for (IOFMessageListener listener : listeners) { try { if (listener instanceof IOFSwitchFilter) { if (!((IOFSwitchFilter) listener).isInterested(sw)) { continue; } } if (Command.STOP.equals(listener.receive(sw, m))) { break; } } catch (Exception e) { log.error( "Failure calling listener [" + listener.toString() + "] with message [" + m.toString() + "]", e); } } } else { log.debug("Unhandled OF Message: {} from {}", m, sw); } break; } // end switch(sw.getState()) } // end switch(m.getType()) } }