@Override @LogMessageDoc( level = "ERROR", message = "Failed to clear all flows on switch {switch}", explanation = "An I/O error occured while trying to clear " + "flows on the switch.", recommendation = LogMessageDoc.CHECK_SWITCH) public void clearAllFlowMods() { // Delete all pre-existing flows OFMatch match = new OFMatch().setWildcards(OFMatch.OFPFW_ALL); OFMessage fm = ((OFFlowMod) floodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD)) .setMatch(match) .setCommand(OFFlowMod.OFPFC_DELETE) .setOutPort(OFPort.OFPP_NONE) .setLength(U16.t(OFFlowMod.MINIMUM_LENGTH)); fm.setXid(getNextTransactionId()); OFMessage barrierMsg = (OFBarrierRequest) floodlightProvider.getOFMessageFactory().getMessage(OFType.BARRIER_REQUEST); barrierMsg.setXid(getNextTransactionId()); try { List<OFMessage> msglist = new ArrayList<OFMessage>(1); msglist.add(fm); write(msglist); msglist = new ArrayList<OFMessage>(1); msglist.add(barrierMsg); write(msglist); } catch (Exception e) { log.error("Failed to clear all flows on switch " + this, e); } }
@Override @LogMessageDoc( level = "WARN", message = "Sending OF message that modifies switch " + "state while in the slave role: {switch}", explanation = "An application has sent a message to a switch " + "that is not valid when the switch is in a slave role", recommendation = LogMessageDoc.REPORT_CONTROLLER_BUG) public void write(List<OFMessage> msglist, FloodlightContext bc) throws IOException { for (OFMessage m : msglist) { if (role == Role.SLAVE) { switch (m.getType()) { case PACKET_OUT: case FLOW_MOD: case PORT_MOD: log.warn( "Sending OF message that modifies switch " + "state while in the slave role: {}", m.getType().name()); break; default: break; } } this.floodlightProvider.handleOutgoingMessage(this, m, bc); } this.write(msglist); }
@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 net.floodlightcontroller.core.IListener.Command receive( IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { if (msg.getType() == OFType.PACKET_IN) { OFPacketIn pi = (OFPacketIn) msg; Ethernet eth = IFloodlightProviderService.bcStore.get( cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD); Short type = eth.getEtherType(); if (type == Ethernet.TYPE_IPv4) { IPv4 ippacket = (IPv4) eth.getPayload(); log.info("New IPv4 message found. \n {} \n", eth.toString()); // For debugging purposes in mininet only if (ippacket.getProtocol() == IPv4.PROTOCOL_ICMP) { // ICMP icmp = (ICMP)ippacket.getPayload(); log.info("New ICMP message found. \n {} \n", ippacket.toString()); // TODO: Call doForwardFlow with the calculated weights // change doForwardFlow args... // doForwardFlow(sw, pi, cntx); } } } return Command.CONTINUE; }
protected List<ICounter> getPktRemoteFMCounters(IOFSwitch sw, OFMessage m) { /* If possible, find and return counters for this tuple */ String countersKey = this.getCountersKey(sw, m, null); List<ICounter> counters = this.pktremoteCounters.get(countersKey); if (counters != null) { return counters; } /* * Create the required counters */ counters = new ArrayList<ICounter>(); /* String values for names */ String switchIdHex = sw.getStringId(); String packetName = m.getType().toClass().getName(); packetName = packetName.substring(packetName.lastIndexOf('.') + 1); String controllerFMCounterName = CounterStore.createCounterName(CONTROLLER_NAME, -1, packetName); counters.add(createCounter(controllerFMCounterName, CounterValue.CounterType.LONG)); String switchFMCounterName = CounterStore.createCounterName(switchIdHex, -1, packetName); counters.add(createCounter(switchFMCounterName, CounterValue.CounterType.LONG)); /* Add to map and return */ this.pktremoteCounters.putIfAbsent(countersKey, counters); return this.pktremoteCounters.get(countersKey); }
@Override public void write(OFMessage m, FloodlightContext bc) throws IOException { Map<IOFSwitch, List<OFMessage>> msg_buffer_map = local_msg_buffer.get(); List<OFMessage> msg_buffer = msg_buffer_map.get(this); if (msg_buffer == null) { msg_buffer = new ArrayList<OFMessage>(); msg_buffer_map.put(this, msg_buffer); } this.floodlightProvider.handleOutgoingMessage(this, m, bc); msg_buffer.add(m); if ((msg_buffer.size() >= Controller.BATCH_MAX_SIZE) || ((m.getType() != OFType.PACKET_OUT) && (m.getType() != OFType.FLOW_MOD))) { this.write(msg_buffer); msg_buffer.clear(); } }
@Override public void run() { while (true) { try { SwitchEvent ev = switchEvents.take(); SwitchEvent.SwitchEventType eType = ev.getEventType(); ISwitch sw = ev.getSwitch(); switch (eType) { case SWITCH_ADD: Long sid = sw.getId(); ISwitch existingSwitch = switches.get(sid); if (existingSwitch != null) { logger.info("Replacing existing {} with New {}", existingSwitch, sw); disconnectSwitch(existingSwitch); } switches.put(sid, sw); notifySwitchAdded(sw); break; case SWITCH_DELETE: disconnectSwitch(sw); break; case SWITCH_ERROR: disconnectSwitch(sw); break; case SWITCH_MESSAGE: OFMessage msg = ev.getMsg(); if (msg != null) { IMessageListener listener = messageListeners.get(msg.getType()); if (listener != null) { listener.receive(sw, msg); } } break; default: logger.error("Unknown switch event {}", eType.ordinal()); } } catch (InterruptedException e) { switchEvents.clear(); return; } } }
@Override public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: return this.processPacketInMessage(sw, (OFPacketIn) msg, cntx); default: break; } return Command.CONTINUE; }
@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); }
@Override public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) { switch (msg.getType()) { case PACKET_IN: IRoutingDecision decision = null; if (cntx != null) decision = IRoutingDecision.rtStore.get(cntx, IRoutingDecision.CONTEXT_DECISION); return this.processPacketInMessage(sw, (OFPacketIn) msg, decision, cntx); default: break; } return Command.CONTINUE; }
protected String getCountersKey(IOFSwitch sw, OFMessage m, Ethernet eth) { byte mtype = m.getType().getTypeValue(); // long swid = sw.getId(); String swsid = sw.getStringId(); short port = 0; short l3type = 0; byte l4type = 0; if (eth != null) { // Packet in counters // Need port and protocol level differentiation OFPacketIn packet = (OFPacketIn) m; port = packet.getInPort(); l3type = eth.getEtherType(); if (l3type == (short) 0x0800) { IPv4 ipV4 = (IPv4) eth.getPayload(); l4type = ipV4.getProtocol(); } } /* If possible, find and return counters for this tuple * * NOTE: this can be converted to a tuple for better performance, * for now we are using a string representation as a the key */ String countersKey = Byte.toString(mtype) + "-" + swsid + "-" + Short.toString(port) + "-" + Short.toString(l3type) + "-" + Byte.toString(l4type); return countersKey; }
/** * 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()) } }
private void handleIOEvent(FVIOEvent e) { if (!this.isConnected) { try { if (!this.sock.finishConnect()) return; // not done yet } catch (IOException e1) { FVLog.log( LogLevel.DEBUG, this, "retrying connection in ", this.reconnectSeconds, " seconds; got: ", e1); this.reconnectLater(); return; } FVLog.log(LogLevel.DEBUG, this, "connected"); this.isConnected = true; this.connectCount++; HashMap<String, Object> info = this.getStatusInfo(); TopologyController tc = TopologyController.getRunningInstance(); if (tc != null) tc.sliceConnectionJustChanged(info, TopologyCallback.EventType.SLICE_CONNECTED); this.reconnectSeconds = 0; try { msgStream = new FVMessageAsyncStream(this.sock, new FVMessageFactory(), this, this.stats); } catch (IOException e1) { FVLog.log( LogLevel.WARN, this, "Trying again later; while creating OFMessageAsyncStream, got: ", e1); this.reconnectLater(); return; } sendMsg(new OFHello(), this); // send initial handshake } try { if (msgStream.needsFlush()) // flush any pending messages msgStream.flush(); List<OFMessage> msgs = this.msgStream.read(); // .read(FVSlicer.MessagesPerRead); // read any new // messages if (msgs == null) throw new IOException("got null from read()"); for (OFMessage msg : msgs) { FVLog.log(LogLevel.DEBUG, this, "recv from controller: ", msg); this.stats.increment(FVStatsType.SEND, this, msg); if ((msg instanceof SanityCheckable) && (!((SanityCheckable) msg).isSane())) { FVLog.log(LogLevel.CRIT, this, "msg failed sanity check; dropping: " + msg); continue; } if (msg instanceof Slicable) { // mark this channel as still alive this.keepAlive.registerPong(); if (msg.getType() != OFType.HELLO && !fvClassifier.isRateLimited(this.getSliceName())) { FVLog.log( LogLevel.WARN, this, "dropping msg because slice", this.getSliceName(), " is rate limited: ", msg); this.sendMsg(FVMessageUtil.makeErrorMsg(OFBadRequestCode.OFPBRC_EPERM, msg), this); continue; } ((Slicable) msg).sliceFromController(fvClassifier, this); } else FVLog.log(LogLevel.CRIT, this, "dropping msg that doesn't implement classify: ", msg); } } catch (IOException e1) { FVLog.log(LogLevel.WARN, this, "got i/o error; tearing down and reconnecting: ", e1); reconnect(); } catch (Exception e2) { e2.printStackTrace(); FVLog.log(LogLevel.ALERT, this, "got unknown error; tearing down and reconnecting: ", e2); reconnect(); } // no need to setup for next select; done in eventloop }
public void takeSwitchEventMsg(ISwitch sw, OFMessage msg) { if (messageListeners.get(msg.getType()) != null) { SwitchEvent ev = new SwitchEvent(SwitchEvent.SwitchEventType.SWITCH_MESSAGE, sw, msg); addSwitchEvent(ev); } }
protected List<ICounter> getPacketInCounters(IOFSwitch sw, OFMessage m, Ethernet eth) { /* If possible, find and return counters for this tuple */ String countersKey = this.getCountersKey(sw, m, eth); List<ICounter> counters = this.pktinCounters.get(countersKey); if (counters != null) { return counters; } /* * Create the required counters */ counters = new ArrayList<ICounter>(); /* values for names */ short port = ((OFPacketIn) m).getInPort(); short l3type = eth.getEtherType(); String switchIdHex = sw.getStringId(); String etherType = String.format("%04x", eth.getEtherType()); String packetName = m.getType().toClass().getName(); packetName = packetName.substring(packetName.lastIndexOf('.') + 1); // L2 Type String l2Type = null; if (eth.isBroadcast()) { l2Type = BROADCAST; } else if (eth.isMulticast()) { l2Type = MULTICAST; } else { l2Type = UNICAST; } /* * Use alias for L3 type * Valid EtherType must be greater than or equal to 0x0600 * It is V1 Ethernet Frame if EtherType < 0x0600 */ if (l3type < 0x0600) { etherType = "0599"; } if (TypeAliases.l3TypeAliasMap != null && TypeAliases.l3TypeAliasMap.containsKey(etherType)) { etherType = TypeAliases.l3TypeAliasMap.get(etherType); } else { etherType = "L3_" + etherType; } // overall controller packet counter names String controllerCounterName = CounterStore.createCounterName(CONTROLLER_NAME, -1, packetName); counters.add(createCounter(controllerCounterName, CounterType.LONG)); String switchCounterName = CounterStore.createCounterName(switchIdHex, -1, packetName); counters.add(createCounter(switchCounterName, CounterType.LONG)); String portCounterName = CounterStore.createCounterName(switchIdHex, port, packetName); counters.add(createCounter(portCounterName, CounterType.LONG)); // L2 counter names String controllerL2CategoryCounterName = CounterStore.createCounterName(CONTROLLER_NAME, -1, packetName, l2Type, NetworkLayer.L2); counters.add(createCounter(controllerL2CategoryCounterName, CounterType.LONG)); String switchL2CategoryCounterName = CounterStore.createCounterName(switchIdHex, -1, packetName, l2Type, NetworkLayer.L2); counters.add(createCounter(switchL2CategoryCounterName, CounterType.LONG)); String portL2CategoryCounterName = CounterStore.createCounterName(switchIdHex, port, packetName, l2Type, NetworkLayer.L2); counters.add(createCounter(portL2CategoryCounterName, CounterType.LONG)); // L3 counter names String controllerL3CategoryCounterName = CounterStore.createCounterName(CONTROLLER_NAME, -1, packetName, etherType, NetworkLayer.L3); counters.add(createCounter(controllerL3CategoryCounterName, CounterType.LONG)); String switchL3CategoryCounterName = CounterStore.createCounterName(switchIdHex, -1, packetName, etherType, NetworkLayer.L3); counters.add(createCounter(switchL3CategoryCounterName, CounterType.LONG)); String portL3CategoryCounterName = CounterStore.createCounterName(switchIdHex, port, packetName, etherType, NetworkLayer.L3); counters.add(createCounter(portL3CategoryCounterName, CounterType.LONG)); // L4 counters if (l3type == (short) 0x0800) { // resolve protocol alias IPv4 ipV4 = (IPv4) eth.getPayload(); String l4name = String.format("%02x", ipV4.getProtocol()); if (TypeAliases.l4TypeAliasMap != null && TypeAliases.l4TypeAliasMap.containsKey(l4name)) { l4name = TypeAliases.l4TypeAliasMap.get(l4name); } else { l4name = "L4_" + l4name; } // create counters String controllerL4CategoryCounterName = CounterStore.createCounterName(CONTROLLER_NAME, -1, packetName, l4name, NetworkLayer.L4); counters.add(createCounter(controllerL4CategoryCounterName, CounterType.LONG)); String switchL4CategoryCounterName = CounterStore.createCounterName(switchIdHex, -1, packetName, l4name, NetworkLayer.L4); counters.add(createCounter(switchL4CategoryCounterName, CounterType.LONG)); String portL4CategoryCounterName = CounterStore.createCounterName(switchIdHex, port, packetName, l4name, NetworkLayer.L4); counters.add(createCounter(portL4CategoryCounterName, CounterType.LONG)); } /* Add to map and return */ this.pktinCounters.putIfAbsent(countersKey, counters); return this.pktinCounters.get(countersKey); }