@LogMessageDoc(level="WARN", message="Failed to authenticate connection from {remote}: {message}", explanation="Challenge/Response authentication failed", recommendation="Check the included error message, and " + "verify the shared secret is correctly-configured") protected void handshake(HelloMessage request, Channel channel) { try { switch (getAuthScheme()) { case CHALLENGE_RESPONSE: handshakeChallengeResponse(request, channel); break; case NO_AUTH: // shouldn't get here break; } } catch (AuthException e) { logger.warn("[{}->{}] Failed to authenticate connection: {}", new Object[]{getLocalNodeIdString(), getRemoteNodeIdString(), e.getMessage()}); channel.write(getError(request.getHeader().getTransactionId(), e, MessageType.HELLO)); channel.close(); } }
/** * Add a key/value to the hint store for the given store * @param storeName the name of the store for the keyed value * @param key the key * @param value the value */ @LogMessageDoc(level="ERROR", message="Failed to queue hint for store {storeName}", explanation="There was an error synchronizing data to " + "remote nodes", recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public void queueHint(String storeName, ByteArray key, Versioned<byte[]> value) { try { HintKey hk = new HintKey(storeName,key); hintLock.lock(); try { boolean needed = !hints.containsKey(hk); needed &= hints.doput(hk, value); if (needed) { hintQueue.add(hk); hintsAvailable.signal(); } } finally { hintLock.unlock(); } } catch (SyncException e) { logger.error("Failed to queue hint for store " + storeName, e); } }
@Override @LogMessageDoc(level="INFO", message="Cluster not yet configured; using fallback " + "local configuration", explanation="No other nodes are known") public ClusterConfig getConfig() throws SyncException { if (!warned) { logger.info("Cluster not yet configured; using fallback local " + "configuration"); warned = true; } return new ClusterConfig(Collections. singletonList(new Node("localhost", syncPort, Short.MAX_VALUE, Short.MAX_VALUE)), Short.MAX_VALUE, "localhost", authScheme, keyStorePath, keyStorePassword); }
@LogMessageDoc(level="WARN", message="Unexpected sync message reply type={type} id={id}", explanation="An error occurred in the sync protocol", recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public void dispatchReply(int xid, SyncReply reply) { RemoteSyncFuture future = futureMap.get(Integer.valueOf(xid)); if (future == null) { logger.warn("Unexpected sync message replyid={}", xid); return; } futureMap.remove(Integer.valueOf(xid)); future.setReply(reply); synchronized (futureNotify) { futureNotify.notify(); } }
@Override @LogMessageDoc(level="WARN", message="Time to process packet-in exceeded threshold: {}", explanation="Time to process packet-in exceeded the configured " + "performance threshold", recommendation=LogMessageDoc.CHECK_CONTROLLER) public void recordEndTimePktIn(IOFSwitch sw, OFMessage m, FloodlightContext cntx) { if (isEnabled()) { long procTimeNs = System.nanoTime() - startTimePktNs; ctb.updatePerPacketCounters(procTimeNs); if (ptWarningThresholdInNano > 0 && procTimeNs > ptWarningThresholdInNano) { logger.warn("Time to process packet-in exceeded threshold: {}", procTimeNs/1000); } } }
@Override @LogMessageDoc(level="INFO", message="Packet processing time threshold for warning" + " set to {time} ms.", explanation="Performance monitoring will log a warning if " + "packet processing time exceeds the configured threshold") public void startUp(FloodlightModuleContext context) { // Add our REST API restApi.addRestletRoutable(new PerfWebRoutable()); // TODO - Alex - change this to a config option ptWarningThresholdInNano = Long.parseLong(System.getProperty( "net.floodlightcontroller.core.PTWarningThresholdInMilli", "0")) * 1000000; if (ptWarningThresholdInNano > 0) { logger.info("Packet processing time threshold for warning" + " set to {} ms.", ptWarningThresholdInNano/1000000); } }
@Post @LogMessageDoc(level="ERROR", message="Error deleting flow mod request: {request}", explanation="An invalid delete request was sent to static flow pusher", recommendation="Fix the format of the static flow mod request") public String del(String fmJson) { IStorageSourceService storageSource = (IStorageSourceService)getContext().getAttributes(). get(IStorageSourceService.class.getCanonicalName()); String fmName = null; if (fmJson == null) { return "{\"status\" : \"Error! No data posted.\"}"; } try { fmName = StaticFlowEntries.getEntryNameFromJson(fmJson); if (fmName == null) { return "{\"status\" : \"Error deleting entry, no name provided\"}"; } } catch (IOException e) { log.error("Error deleting flow mod request: " + fmJson, e); return "{\"status\" : \"Error deleting entry, see log for details\"}"; } storageSource.deleteRowAsync(StaticFlowEntryPusher.TABLE_NAME, fmName); return "{\"status\" : \"Entry " + fmName + " deleted\"}"; }
@Delete @LogMessageDoc(level="ERROR", message="Error deleting flow mod request: {request}", explanation="An invalid delete request was sent to static flow pusher", recommendation="Fix the format of the static flow mod request") public String del(String fmJson) { IStorageSourceService storageSource = (IStorageSourceService)getContext().getAttributes(). get(IStorageSourceService.class.getCanonicalName()); String fmName = null; if (fmJson == null) { return "{\"status\" : \"Error! No data posted.\"}"; } try { fmName = StaticFlowEntries.getEntryNameFromJson(fmJson); if (fmName == null) { return "{\"status\" : \"Error deleting entry, no name provided\"}"; } } catch (IOException e) { log.error("Error deleting flow mod request: " + fmJson, e); return "{\"status\" : \"Error deleting entry, see log for details\"}"; } storageSource.deleteRowAsync(StaticFlowEntryPusher.TABLE_NAME, fmName); return "{\"status\" : \"Entry " + fmName + " deleted\"}"; }
/** * Read entries from storageSource, and store them in a hash * * @return */ @LogMessageDoc(level="ERROR", message="failed to access storage: {reason}", explanation="Could not retrieve static flows from the system " + "database", recommendation=LogMessageDoc.CHECK_CONTROLLER) private Map<String, Map<String, OFFlowMod>> readEntriesFromStorage() { Map<String, Map<String, OFFlowMod>> entries = new ConcurrentHashMap<String, Map<String, OFFlowMod>>(); try { Map<String, Object> row; // null1=no predicate, null2=no ordering IResultSet resultSet = storageSourceService.executeQuery(TABLE_NAME, ColumnNames, null, null); for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) { row = it.next().getRow(); parseRow(row, entries); } } catch (StorageException e) { log.error("failed to access storage: {}", e.getMessage()); // if the table doesn't exist, then wait to populate later via // setStorageSource() } return entries; }
/** * Writes a list of OFMessages to a switch * @param dpid The datapath ID of the switch to write to * @param messages The list of OFMessages to write. */ @LogMessageDoc(level="ERROR", message="Tried to write to switch {switch} but got {error}", explanation="An I/O error occured while trying to write a " + "static flow to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) private void writeOFMessagesToSwitch(DatapathId dpid, List<OFMessage> messages) { IOFSwitch ofswitch = switchService.getSwitch(dpid); if (ofswitch != null) { // is the switch connected if (log.isDebugEnabled()) { log.debug("Sending {} new entries to {}", messages.size(), dpid); } ofswitch.write(messages); ofswitch.flush(); } }
@Override @LogMessageDoc(level="WARN", message="Switch {switch} flow table is full", explanation="The controller received flow table full " + "message from the switch, could be caused by increased " + "traffic pattern", recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public void setTableFull(boolean isFull) { if (isFull && !flowTableFull) { switchManager.addSwitchEvent(this.datapathId, "SWITCH_FLOW_TABLE_FULL " + "Table full error from switch", false); log.warn("Switch {} flow table is full", datapathId.toString()); } flowTableFull = isFull; }
@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(Iterable<OFMessage> msglist) { if (!isConnected()) { if (logger.isDebugEnabled()) logger.debug(this.toString() + " : not connected - dropping {} element msglist {} ", Iterables.size(msglist), String.valueOf(msglist).substring(0, 80)); return; } for (OFMessage m : msglist) { if (logger.isTraceEnabled()) logger.trace("{}: send {}", this, m); counters.updateWriteStats(m); } this.channel.write(msglist); }
/** * Log an OpenFlow error message from a switch * @param error The error message */ @LogMessageDoc(level="ERROR", message="Error {error type} {error code} from {switch} " + "in state {state}", explanation="The switch responded with an unexpected error" + "to an OpenFlow message from the controller", recommendation="This could indicate improper network operation. " + "If the problem persists restarting the switch and " + "controller may help." ) protected void logError(OFErrorMsg error) { log.error("{} from switch {} in state {}", new Object[] { error.toString(), getSwitchInfoString(), this.toString()}); }
@Override @LogMessageDoc(level="WARN", message="Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", explanation="The switch has receive a PacketIn despite being " + "in slave role indicating inconsistent controller roles", recommendation="This situation can occurs transiently during role" + " changes. If, however, the condition persists or happens" + " frequently this indicates a role inconsistency. " + LogMessageDoc.CHECK_CONTROLLER ) void processOFPacketIn(OFPacketIn m) { // we don't expect packetIn while slave, reassert we are slave switchManagerCounters.packetInWhileSwitchIsSlave.increment(); log.warn("Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", sw); reassertRole(OFControllerRole.ROLE_SLAVE); }
@LogMessageDocs({ @LogMessageDoc(message="Controller role set to {role}", explanation="Setting the initial HA role to "), @LogMessageDoc(level="ERROR", message="Invalid current role value: {role}", explanation="An invalid HA role value was read from the " + "properties file", recommendation=LogMessageDoc.CHECK_CONTROLLER) }) protected HARole getInitialRole(Map<String, String> configParams) { HARole role = HARole.STANDBY; String roleString = configParams.get("role"); if (roleString != null) { try { role = HARole.valueOfBackwardsCompatible(roleString); } catch (IllegalArgumentException exc) { log.error("Invalid current role value: {}", roleString); } } log.info("Controller role set to {}", role); return role; }
/** * Log an OpenFlow error message from a switch * @param sw The switch that sent the error * @param error The error message */ @LogMessageDoc(level="ERROR", message="Error {error type} {error code} from {switch} " + "in state {state}", explanation="The switch responded with an unexpected error" + "to an OpenFlow message from the controller", recommendation="This could indicate improper network operation. " + "If the problem persists restarting the switch and " + "controller may help." ) protected void logError(OFErrorMsg error) { log.error("{} from switch {} in state {}", new Object[] { error.toString(), getConnectionInfoString(), this.toString()}); }
@Override @LogMessageDocs({ @LogMessageDoc(level="WARN", message="Error parsing flow idle timeout, " + "using default of {number} seconds", explanation="The properties file contains an invalid " + "flow idle timeout", recommendation="Correct the idle timeout in the " + "properties file."), @LogMessageDoc(level="WARN", message="Error parsing flow hard timeout, " + "using default of {number} seconds", explanation="The properties file contains an invalid " + "flow hard timeout", recommendation="Correct the hard timeout in the " + "properties file.") }) public void init(FloodlightModuleContext context) throws FloodlightModuleException { super.init(); this.floodlightProvider = context.getServiceImpl(IFloodlightProviderService.class); this.deviceManager = context.getServiceImpl(IDeviceService.class); this.routingEngine = context.getServiceImpl(IRoutingService.class); this.topology = context.getServiceImpl(ITopologyService.class); this.counterStore = context.getServiceImpl(ICounterStoreService.class); }
/** * Read entries from storageSource, and store them in a hash * * @return */ @LogMessageDoc(level="ERROR", message="failed to access storage: {reason}", explanation="Could not retrieve static flows from the system " + "database", recommendation=LogMessageDoc.CHECK_CONTROLLER) private Map<String, Map<String, OFFlowMod>> readEntriesFromStorage() { Map<String, Map<String, OFFlowMod>> entries = new ConcurrentHashMap<String, Map<String, OFFlowMod>>(); try { Map<String, Object> row; // null1=no predicate, null2=no ordering IResultSet resultSet = storageSource.executeQuery(TABLE_NAME, ColumnNames, null, null); for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) { row = it.next().getRow(); parseRow(row, entries); } } catch (StorageException e) { log.error("failed to access storage: {}", e.getMessage()); // if the table doesn't exist, then wait to populate later via // setStorageSource() } return entries; }
/** * Writes a list of OFMessages to a switch * @param dpid The datapath ID of the switch to write to * @param messages The list of OFMessages to write. */ @LogMessageDoc(level="ERROR", message="Tried to write to switch {switch} but got {error}", explanation="An I/O error occured while trying to write a " + "static flow to a switch", recommendation=LogMessageDoc.CHECK_SWITCH) private void writeOFMessagesToSwitch(long dpid, List<OFMessage> messages) { IOFSwitch ofswitch = floodlightProvider.getSwitch(dpid); if (ofswitch != null) { // is the switch connected try { if (log.isDebugEnabled()) { log.debug("Sending {} new entries to {}", messages.size(), dpid); } ofswitch.write(messages, null); ofswitch.flush(); } catch (IOException e) { log.error("Tried to write to switch {} but got {}", dpid, e.getMessage()); } } }
@LogMessageDoc(level="INFO", message="Switch {switch} flow cleared", explanation="The switch flow table has been cleared, " + "this normally happens on switch connection") @Override public void clearAllFlowMods() { if (channel == null || !isConnected()) return; // Delete all pre-existing flows log.info("Clearing all flows on switch {}", this); 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 = floodlightProvider.getOFMessageFactory().getMessage( OFType.BARRIER_REQUEST); barrierMsg.setXid(getNextTransactionId()); List<OFMessage> msglist = new ArrayList<OFMessage>(2); msglist.add(fm); msglist.add(barrierMsg); channel.write(msglist); }
@Override @JsonIgnore @LogMessageDoc(level="WARN", message="Switch {switch} flow table is full", explanation="The controller received flow table full " + "message from the switch, could be caused by increased " + "traffic pattern", recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG) public void setTableFull(boolean isFull) { if (isFull && !flowTableFull) { floodlightProvider.addSwitchEvent(this.datapathId, "SWITCH_FLOW_TABLE_FULL " + "Table full error from switch", false); log.warn("Switch {} flow table is full", stringId); } flowTableFull = isFull; }
@LogMessageDoc(level="ERROR", message="Error while terminating packet " + "filter session", explanation="An unknown error occurred while terminating " + "a packet filter session.", recommendation=LogMessageDoc.GENERIC_ACTION) protected String deleteFilter(String sessionId) { if (filterMap.containsKey(sessionId)) { filterMap.remove(sessionId); try { if (packetClient != null) packetClient.terminateSession(sessionId); } catch (TException e) { log.error("Error while terminating packet " + "filter session", e); } log.debug("Deleted Filter {}. # of filters" + " remaining: {}", sessionId, filterMap.size()); return SUCCESS; } else return FILTER_SESSION_ID_NOT_FOUND; }
@LogMessageDoc(level="WARN", message=FLOW_PRIORITY_CHANGED_AFTER_STARTUP, explanation="A user has changed the priority with which access " + "and core flows are installed after controller startup. " + "Changing this setting will only take affect after a " + "controller restart", recommendation="Restart controller") @Override public void rowsModified(String tableName, Set<Object> rowKeys) { if (tableName.equals(CONTROLLER_INTERFACE_TABLE_NAME)) { handleControllerNodeIPChanges(); } else if (tableName.equals(FLOW_PRIORITY_TABLE_NAME)) { log.warn(FLOW_PRIORITY_CHANGED_AFTER_STARTUP); } }
@Override @LogMessageDoc(level="WARN", message="Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", explanation="The switch has receive a PacketIn despite being " + "in slave role indicating inconsistent controller roles", recommendation="This situation can occurs transiently during role" + " changes. If, however, the condition persists or happens" + " frequently this indicates a role inconsistency. " + LogMessageDoc.CHECK_CONTROLLER ) void processOFPacketIn(OFChannelHandler h, OFPacketIn m) throws IOException { // we don't expect packetIn while slave, reassert we are slave h.counters.packetInWhileSwitchIsSlave.updateCounterNoFlush(); log.warn("Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", h.sw); h.controller.reassertRole(h, Role.SLAVE); }
/** * Log an OpenFlow error message from a switch * @param sw The switch that sent the error * @param error The error message */ @LogMessageDoc(level="ERROR", message="Error {error type} {error code} from {switch} " + "in state {state}", explanation="The switch responded with an unexpected error" + "to an OpenFlow message from the controller", recommendation="This could indicate improper network operation. " + "If the problem persists restarting the switch and " + "controller may help." ) protected void logError(OFChannelHandler h, OFError error) { log.error("{} from switch {} in state {}", new Object[] { getErrorString(error), h.getSwitchInfoString(), this.toString()}); }
@Override @LogMessageDoc(message="Disconnected switch {switch information}", explanation="The specified switch has disconnected.") public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception { controller.removeSwitchChannel(this); if (this.sw != null) { // TODO: switchDisconnected() will check if we've previously // activated the switch. Nevertheless, we might want to check // here as well. controller.switchDisconnected(this.sw); this.sw.setConnected(false); } log.info("Disconnected switch {}", getSwitchInfoString()); }