| /* |
| * Copyright 2017-present Open Networking Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| package org.opencord.aaa.impl; |
| |
| import static org.slf4j.LoggerFactory.getLogger; |
| |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.onlab.packet.MacAddress; |
| import org.onosproject.net.ConnectPoint; |
| import org.opencord.aaa.AuthenticationEvent; |
| import org.opencord.aaa.StateMachineDelegate; |
| import org.opencord.aaa.AaaSupplicantMachineStats; |
| import org.opencord.aaa.AaaMachineStatisticsEvent; |
| import org.slf4j.Logger; |
| |
| import com.google.common.collect.Maps; |
| |
| /** |
| * AAA Finite State Machine. |
| */ |
| |
| class StateMachine { |
| // INDEX to identify the state in the transition table |
| static final int STATE_IDLE = 0; |
| static final int STATE_STARTED = 1; |
| static final int STATE_PENDING = 2; |
| static final int STATE_AUTHORIZED = 3; |
| static final int STATE_UNAUTHORIZED = 4; |
| |
| // Defining the states where timeout can happen |
| static final Set<Integer> TIMEOUT_ELIGIBLE_STATES = new HashSet(); |
| static { |
| TIMEOUT_ELIGIBLE_STATES.add(STATE_STARTED); |
| TIMEOUT_ELIGIBLE_STATES.add(STATE_PENDING); |
| } |
| // INDEX to identify the transition in the transition table |
| static final int TRANSITION_START = 0; // --> started |
| static final int TRANSITION_REQUEST_ACCESS = 1; |
| static final int TRANSITION_AUTHORIZE_ACCESS = 2; |
| static final int TRANSITION_DENY_ACCESS = 3; |
| static final int TRANSITION_LOGOFF = 4; |
| |
| private static int identifier = 1; |
| private byte challengeIdentifier; |
| private byte[] challengeState; |
| private byte[] username; |
| private byte[] requestAuthenticator; |
| |
| // Supplicant connectivity info |
| private ConnectPoint supplicantConnectpoint; |
| private MacAddress supplicantAddress; |
| private short vlanId; |
| private byte priorityCode; |
| private long sessionStartTime; |
| private String eapolTypeVal; |
| |
| public enum EapolType { |
| EAPOL_PACKET("EAPOL_PACKET"), |
| EAPOL_START("EAPOL_START"), |
| EAPOL_LOGOFF("EAPOL_LOGOFF"), |
| EAPOL_KEY("EAPOL_KEY"), |
| EAPOL_ASF("EAPOL_ASF"); |
| |
| private final String eaptype; |
| |
| private EapolType(String value) { |
| this.eaptype = value; |
| } |
| }; |
| |
| private String sessionTerminateReason; |
| |
| public enum SessionTerminationReasons { |
| SUPPLICANT_LOGOFF("SUPPLICANT_LOGOFF"), |
| TIME_OUT("TIME_OUT"), |
| PORT_REMOVED("PORT_REMOVED"), |
| DEVICE_REMOVED("DEVICE_REMOVED"); |
| |
| private final String reason; |
| |
| private SessionTerminationReasons(String value) { |
| this.reason = value; |
| } |
| |
| public String getReason() { |
| return this.reason; |
| } |
| }; |
| |
| // Supplicant packet count |
| private int totalPacketsSent; |
| private int totalPacketsReceived; |
| private int totalOctetSent; |
| private int totalOctetReceived; |
| |
| // Boolean flag indicating whether response is pending from AAA Server. |
| // Used for counting timeout happening for AAA Sessions due to no response. |
| private boolean waitingForRadiusResponse; |
| |
| private static int cleanupTimerTimeOutInMins; |
| |
| private String sessionId = null; |
| |
| private final Logger log = getLogger(getClass()); |
| |
| private State[] states = {new Idle(), new Started(), new Pending(), new Authorized(), new Unauthorized() }; |
| |
| // Cleanup Timer instance created for this session |
| private java.util.concurrent.ScheduledFuture<?> cleanupTimer = null; |
| |
| // TimeStamp of last EAPOL or RADIUS message received. |
| private long lastPacketReceivedTime = 0; |
| |
| // State transition table |
| /* |
| * |
| * state IDLE | STARTED | PENDING | AUTHORIZED | UNAUTHORIZED //// input |
| * ----------------------------------------------------------------------------- |
| * ----------------------- |
| * |
| * START STARTED | _ | _ | STARTED | STARTED |
| * |
| * REQUEST_ACCESS _ | PENDING | _ | _ | _ |
| * |
| * AUTHORIZE_ACCESS _ | _ | AUTHORIZED | _ | _ |
| * |
| * DENY_ACCESS _ | - | UNAUTHORIZED | _ | _ |
| * |
| * LOGOFF _ | _ | _ | IDLE | IDLE |
| */ |
| |
| private int[] idleTransition = {STATE_STARTED, STATE_IDLE, STATE_IDLE, STATE_IDLE, STATE_IDLE }; |
| private int[] startedTransition = {STATE_STARTED, STATE_PENDING, STATE_STARTED, STATE_STARTED, STATE_STARTED }; |
| private int[] pendingTransition = {STATE_PENDING, STATE_PENDING, STATE_AUTHORIZED, STATE_UNAUTHORIZED, |
| STATE_PENDING }; |
| private int[] authorizedTransition = {STATE_STARTED, STATE_AUTHORIZED, STATE_AUTHORIZED, STATE_AUTHORIZED, |
| STATE_IDLE }; |
| private int[] unauthorizedTransition = {STATE_STARTED, STATE_UNAUTHORIZED, STATE_UNAUTHORIZED, STATE_UNAUTHORIZED, |
| STATE_IDLE }; |
| |
| // THE TRANSITION TABLE |
| private int[][] transition = {idleTransition, startedTransition, pendingTransition, authorizedTransition, |
| unauthorizedTransition }; |
| |
| private int currentState = STATE_IDLE; |
| |
| // Maps of state machines. Each state machine is represented by an |
| // unique identifier on the switch: dpid + port number |
| private static Map<String, StateMachine> sessionIdMap; |
| private static Map<Integer, StateMachine> identifierMap; |
| |
| private static StateMachineDelegate delegate; |
| |
| public static void initializeMaps() { |
| sessionIdMap = Maps.newConcurrentMap(); |
| identifierMap = Maps.newConcurrentMap(); |
| identifier = 1; |
| } |
| |
| public static void destroyMaps() { |
| sessionIdMap = null; |
| identifierMap = null; |
| } |
| |
| public static void setDelegate(StateMachineDelegate delegate) { |
| StateMachine.delegate = delegate; |
| } |
| |
| public static void setcleanupTimerTimeOutInMins(int cleanupTimerTimeoutInMins) { |
| cleanupTimerTimeOutInMins = cleanupTimerTimeoutInMins; |
| } |
| |
| public static void unsetDelegate(StateMachineDelegate delegate) { |
| if (StateMachine.delegate == delegate) { |
| StateMachine.delegate = null; |
| } |
| } |
| |
| public static Map<String, StateMachine> sessionIdMap() { |
| return sessionIdMap; |
| } |
| |
| public static StateMachine lookupStateMachineById(byte identifier) { |
| return identifierMap.get((int) identifier); |
| } |
| |
| public static StateMachine lookupStateMachineBySessionId(String sessionId) { |
| return sessionIdMap.get(sessionId); |
| } |
| |
| public static void deleteStateMachineId(String sessionId) { |
| sessionIdMap.remove(sessionId); |
| } |
| |
| public static void deleteStateMachineMapping(StateMachine machine) { |
| identifierMap.entrySet().removeIf(e -> e.getValue().equals(machine)); |
| if (machine.cleanupTimer != null) { |
| machine.cleanupTimer.cancel(false); |
| machine.cleanupTimer = null; |
| } |
| } |
| |
| public java.util.concurrent.ScheduledFuture<?> getCleanupTimer() { |
| return cleanupTimer; |
| } |
| |
| public boolean isWaitingForRadiusResponse() { |
| return waitingForRadiusResponse; |
| } |
| |
| public void setWaitingForRadiusResponse(boolean waitingForRadiusResponse) { |
| this.waitingForRadiusResponse = waitingForRadiusResponse; |
| } |
| |
| public void setCleanupTimer(java.util.concurrent.ScheduledFuture<?> cleanupTimer) { |
| this.cleanupTimer = cleanupTimer; |
| } |
| |
| /** |
| * Deletes authentication state machine records for a given MAC address. |
| * |
| * @param mac mac address of the suppliant who's state machine should be removed |
| */ |
| public static void deleteByMac(MacAddress mac) { |
| |
| // Walk the map from session IDs to state machines looking for a MAC match |
| for (Map.Entry<String, StateMachine> e : sessionIdMap.entrySet()) { |
| |
| // If a MAC match is found then delete the entry from the session ID |
| // and identifier map as well as call delete identifier to clean up |
| // the identifier bit set. |
| if (e.getValue() != null && e.getValue().supplicantAddress != null |
| && e.getValue().supplicantAddress.equals(mac)) { |
| sessionIdMap.remove(e.getValue().sessionId); |
| if (e.getValue().identifier != 1) { |
| deleteStateMachineMapping(e.getValue()); |
| } |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Creates a new StateMachine with the given session ID. |
| * |
| * @param sessionId session Id represented by the switch dpid + port number |
| */ |
| public StateMachine(String sessionId) { |
| log.info("Creating a new state machine for {}", sessionId); |
| this.sessionId = sessionId; |
| sessionIdMap.put(sessionId, this); |
| } |
| |
| /** |
| * Gets the connect point for the supplicant side. |
| * |
| * @return supplicant connect point |
| */ |
| public ConnectPoint supplicantConnectpoint() { |
| return supplicantConnectpoint; |
| } |
| |
| /** |
| * Sets the supplicant side connect point. |
| * |
| * @param supplicantConnectpoint supplicant select point. |
| */ |
| public void setSupplicantConnectpoint(ConnectPoint supplicantConnectpoint) { |
| this.supplicantConnectpoint = supplicantConnectpoint; |
| } |
| |
| /** |
| * Gets the MAC address of the supplicant. |
| * |
| * @return supplicant MAC address |
| */ |
| public MacAddress supplicantAddress() { |
| return supplicantAddress; |
| } |
| |
| /** |
| * Sets the supplicant MAC address. |
| * |
| * @param supplicantAddress new supplicant MAC address |
| */ |
| public void setSupplicantAddress(MacAddress supplicantAddress) { |
| this.supplicantAddress = supplicantAddress; |
| } |
| |
| /** |
| * Sets the lastPacketReceivedTime. |
| * |
| * @param lastPacketReceivedTime timelastPacket was received |
| */ |
| public void setLastPacketReceivedTime(long lastPacketReceivedTime) { |
| this.lastPacketReceivedTime = lastPacketReceivedTime; |
| } |
| |
| /** |
| * Gets the lastPacketReceivedTime. |
| * |
| * @return lastPacketReceivedTime |
| */ |
| public long getLastPacketReceivedTime() { |
| return lastPacketReceivedTime; |
| } |
| |
| /** |
| * Gets the client's Vlan ID. |
| * |
| * @return client vlan ID |
| */ |
| public short vlanId() { |
| return vlanId; |
| } |
| |
| /** |
| * Sets the client's vlan ID. |
| * |
| * @param vlanId new client vlan ID |
| */ |
| public void setVlanId(short vlanId) { |
| this.vlanId = vlanId; |
| } |
| |
| /** |
| * Gets the client's priority Code. |
| * |
| * @return client Priority code |
| */ |
| public byte priorityCode() { |
| return priorityCode; |
| } |
| |
| /** |
| * Sets the client's priority Code. |
| * |
| * @param priorityCode new client priority Code |
| */ |
| public void setPriorityCode(byte priorityCode) { |
| this.priorityCode = priorityCode; |
| } |
| |
| /** |
| * Gets the session start time. |
| * |
| * @return session start time |
| */ |
| public long sessionStartTime() { |
| return sessionStartTime; |
| } |
| |
| /** |
| * Sets the session start time. |
| * |
| * @param sessionStartTime new session start time |
| */ |
| public void setSessionStartTime(long sessionStartTime) { |
| this.sessionStartTime = sessionStartTime; |
| } |
| |
| /** |
| * returns eapol Type. |
| * |
| * @return eapolTypeVal. |
| */ |
| public String eapolType() { |
| return this.eapolTypeVal; |
| } |
| |
| /** |
| * Sets eapol Type name from eapol value. |
| * |
| * @param value eapol type as byte. |
| */ |
| public void setEapolTypeVal(byte value) { |
| switch (value) { |
| case (byte) 0: this.eapolTypeVal = EapolType.EAPOL_PACKET.eaptype; |
| break; |
| case (byte) 1: this.eapolTypeVal = EapolType.EAPOL_START.eaptype; |
| break; |
| case (byte) 2: this.eapolTypeVal = EapolType.EAPOL_LOGOFF.eaptype; |
| break; |
| case (byte) 3: this.eapolTypeVal = EapolType.EAPOL_KEY.eaptype; |
| break; |
| case (byte) 4: this.eapolTypeVal = EapolType.EAPOL_ASF.eaptype; |
| break; |
| default : this.eapolTypeVal = "INVALID TYPE"; |
| } |
| } |
| |
| public String getSessionTerminateReason() { |
| return sessionTerminateReason; |
| } |
| |
| public void setSessionTerminateReason(String sessionTerminateReason) { |
| this.sessionTerminateReason = sessionTerminateReason; |
| } |
| |
| public int totalPacketsReceived() { |
| return this.totalPacketsReceived; |
| } |
| |
| public void incrementTotalPacketsReceived() { |
| this.totalPacketsReceived = this.totalPacketsReceived + 1; |
| } |
| |
| public int totalPacketsSent() { |
| return this.totalPacketsSent; |
| } |
| |
| public void incrementTotalPacketsSent() { |
| this.totalPacketsSent = this.totalPacketsSent + 1; |
| } |
| |
| public void incrementTotalOctetReceived(short packetLen) { |
| this.totalOctetReceived = this.totalOctetReceived + packetLen; |
| } |
| |
| public void incrementTotalOctetSent(short packetLen) { |
| this.totalOctetSent = this.totalOctetSent + packetLen; |
| } |
| |
| /** |
| * Gets the client id that is requesting for access. |
| * |
| * @return The client id. |
| */ |
| public String sessionId() { |
| return this.sessionId; |
| } |
| |
| /** |
| * Set the challenge identifier and the state issued by the RADIUS. |
| * |
| * @param challengeIdentifier The challenge identifier set into the EAP packet |
| * from the RADIUS message. |
| * @param challengeState The challenge state from the RADIUS. |
| */ |
| protected void setChallengeInfo(byte challengeIdentifier, byte[] challengeState) { |
| this.challengeIdentifier = challengeIdentifier; |
| this.challengeState = challengeState; |
| } |
| |
| /** |
| * Set the challenge identifier issued by the RADIUS on the access challenge |
| * request. |
| * |
| * @param challengeIdentifier The challenge identifier set into the EAP packet |
| * from the RADIUS message. |
| */ |
| protected void setChallengeIdentifier(byte challengeIdentifier) { |
| log.info("Set Challenge Identifier to {}", challengeIdentifier); |
| this.challengeIdentifier = challengeIdentifier; |
| } |
| |
| /** |
| * Gets the challenge EAP identifier set by the RADIUS. |
| * |
| * @return The challenge EAP identifier. |
| */ |
| protected byte challengeIdentifier() { |
| return this.challengeIdentifier; |
| } |
| |
| /** |
| * Set the challenge state info issued by the RADIUS. |
| * |
| * @param challengeState The challenge state from the RADIUS. |
| */ |
| protected void setChallengeState(byte[] challengeState) { |
| log.info("Set Challenge State"); |
| this.challengeState = challengeState; |
| } |
| |
| /** |
| * Gets the challenge state set by the RADIUS. |
| * |
| * @return The challenge state. |
| */ |
| protected byte[] challengeState() { |
| return this.challengeState; |
| } |
| |
| /** |
| * Set the username. |
| * |
| * @param username The username sent to the RADIUS upon access request. |
| */ |
| protected void setUsername(byte[] username) { |
| this.username = username; |
| } |
| |
| /** |
| * Gets the username. |
| * |
| * @return The requestAuthenticator. |
| */ |
| protected byte[] requestAuthenticator() { |
| return this.requestAuthenticator; |
| } |
| |
| /** |
| * Sets the authenticator. |
| * |
| * @param authenticator The username sent to the RADIUS upon access request. |
| */ |
| protected void setRequestAuthenticator(byte[] authenticator) { |
| this.requestAuthenticator = authenticator; |
| } |
| |
| /** |
| * Gets the username. |
| * |
| * @return The username. |
| */ |
| protected byte[] username() { |
| return this.username; |
| } |
| |
| /** |
| * Return the identifier of the state machine. |
| * |
| * @return The state machine identifier. |
| */ |
| public synchronized byte identifier() { |
| //identifier 0 is for statusServerrequest |
| //identifier 1 is for fake accessRequest |
| identifier = (identifier + 1) % 253; |
| identifierMap.put((identifier + 2), this); |
| return (byte) (identifier + 2); |
| } |
| |
| /** |
| * Move to the next state. |
| * |
| * @param msg message |
| */ |
| private void next(int msg) { |
| currentState = transition[currentState][msg]; |
| log.info("Current State " + currentState); |
| } |
| |
| /** |
| * Client has requested the start action to allow network access. |
| * |
| * @throws StateMachineException if authentication protocol is violated |
| */ |
| public void start() throws StateMachineException { |
| states[currentState].start(); |
| |
| delegate.notify(new AuthenticationEvent(AuthenticationEvent.Type.STARTED, supplicantConnectpoint)); |
| |
| // move to the next state |
| next(TRANSITION_START); |
| identifier = this.identifier(); |
| } |
| |
| /** |
| * An Identification information has been sent by the supplicant. Move to the |
| * next state if possible. |
| * |
| * @throws StateMachineException if authentication protocol is violated |
| */ |
| public void requestAccess() throws StateMachineException { |
| states[currentState].requestAccess(); |
| |
| delegate.notify(new AuthenticationEvent(AuthenticationEvent.Type.REQUESTED, supplicantConnectpoint)); |
| |
| // move to the next state |
| next(TRANSITION_REQUEST_ACCESS); |
| } |
| |
| /** |
| * RADIUS has accepted the identification. Move to the next state if possible. |
| * |
| * @throws StateMachineException if authentication protocol is violated |
| */ |
| public void authorizeAccess() throws StateMachineException { |
| states[currentState].radiusAccepted(); |
| // move to the next state |
| next(TRANSITION_AUTHORIZE_ACCESS); |
| |
| delegate.notify(new AuthenticationEvent(AuthenticationEvent.Type.APPROVED, supplicantConnectpoint)); |
| |
| // Clear mapping |
| deleteStateMachineMapping(this); |
| } |
| |
| /** |
| * RADIUS has denied the identification. Move to the next state if possible. |
| * |
| * @throws StateMachineException if authentication protocol is violated |
| */ |
| public void denyAccess() throws StateMachineException { |
| states[currentState].radiusDenied(); |
| // move to the next state |
| next(TRANSITION_DENY_ACCESS); |
| |
| delegate.notify(new AuthenticationEvent(AuthenticationEvent.Type.DENIED, supplicantConnectpoint)); |
| |
| // Clear mappings |
| deleteStateMachineMapping(this); |
| } |
| |
| /** |
| * Logoff request has been requested. Move to the next state if possible. |
| * |
| * @throws StateMachineException if authentication protocol is violated |
| */ |
| public void logoff() throws StateMachineException { |
| states[currentState].logoff(); |
| // move to the next state |
| next(TRANSITION_LOGOFF); |
| } |
| |
| /** |
| * Gets the current state. |
| * |
| * @return The current state. Could be STATE_IDLE, STATE_STARTED, STATE_PENDING, |
| * STATE_AUTHORIZED, STATE_UNAUTHORIZED. |
| */ |
| public int state() { |
| return currentState; |
| } |
| |
| @Override |
| public String toString() { |
| return ("sessionId: " + this.sessionId) + "\t" + ("identifier: " + this.identifier) + "\t" |
| + ("state: " + this.currentState); |
| } |
| |
| abstract class State { |
| private final Logger log = getLogger(getClass()); |
| |
| private String name = "State"; |
| |
| public void start() throws StateMachineInvalidTransitionException { |
| log.warn("START transition from this state is not allowed."); |
| } |
| |
| public void requestAccess() throws StateMachineInvalidTransitionException { |
| log.warn("REQUEST ACCESS transition from this state is not allowed."); |
| } |
| |
| public void radiusAccepted() throws StateMachineInvalidTransitionException { |
| log.warn("AUTHORIZE ACCESS transition from this state is not allowed."); |
| } |
| |
| public void radiusDenied() throws StateMachineInvalidTransitionException { |
| log.warn("DENY ACCESS transition from this state is not allowed."); |
| } |
| |
| public void logoff() throws StateMachineInvalidTransitionException { |
| log.warn("LOGOFF transition from this state is not allowed."); |
| } |
| } |
| |
| /** |
| * Idle state: supplicant is logged of from the network. |
| */ |
| class Idle extends State { |
| private final Logger log = getLogger(getClass()); |
| private String name = "IDLE_STATE"; |
| |
| @Override |
| public void start() { |
| log.info("Moving from IDLE state to STARTED state."); |
| } |
| } |
| |
| /** |
| * Started state: supplicant has entered the network and informed the |
| * authenticator. |
| */ |
| class Started extends State { |
| private final Logger log = getLogger(getClass()); |
| private String name = "STARTED_STATE"; |
| |
| @Override |
| public void requestAccess() { |
| log.info("Moving from STARTED state to PENDING state."); |
| } |
| } |
| |
| /** |
| * Pending state: supplicant has been identified by the authenticator but has |
| * not access yet. |
| */ |
| class Pending extends State { |
| private final Logger log = getLogger(getClass()); |
| private String name = "PENDING_STATE"; |
| |
| @Override |
| public void radiusAccepted() { |
| log.info("Moving from PENDING state to AUTHORIZED state."); |
| } |
| |
| @Override |
| public void radiusDenied() { |
| log.info("Moving from PENDING state to UNAUTHORIZED state."); |
| } |
| } |
| |
| /** |
| * Authorized state: supplicant port has been accepted, access is granted. |
| */ |
| class Authorized extends State { |
| private final Logger log = getLogger(getClass()); |
| private String name = "AUTHORIZED_STATE"; |
| |
| @Override |
| public void start() { |
| log.info("Moving from AUTHORIZED state to STARTED state."); |
| } |
| |
| @Override |
| public void logoff() { |
| |
| log.info("Moving from AUTHORIZED state to IDLE state."); |
| } |
| } |
| |
| /** |
| * Unauthorized state: supplicant port has been rejected, access is denied. |
| */ |
| class Unauthorized extends State { |
| private final Logger log = getLogger(getClass()); |
| private String name = "UNAUTHORIZED_STATE"; |
| |
| @Override |
| public void start() { |
| log.info("Moving from UNAUTHORIZED state to STARTED state."); |
| } |
| |
| @Override |
| public void logoff() { |
| log.info("Moving from UNAUTHORIZED state to IDLE state."); |
| } |
| } |
| |
| /** |
| * Class for cleaning the StateMachine for those session for which no response |
| * is coming--implementing timeout. |
| */ |
| class CleanupTimerTask implements Runnable { |
| private final Logger log = getLogger(getClass()); |
| private String sessionId; |
| private AaaManager aaaManager; |
| |
| CleanupTimerTask(String sessionId, AaaManager aaaManager) { |
| this.sessionId = sessionId; |
| this.aaaManager = aaaManager; |
| } |
| |
| @Override |
| public void run() { |
| StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId); |
| if (null != stateMachine) { |
| // Asserting if last packet received for this stateMachine session was beyond half of timeout period. |
| // StateMachine is considered eligible for cleanup when no packets has been exchanged by it with AAA |
| // Server or RG during a long period (half of timeout period). For example, when cleanup timer has |
| // been configured as 10 minutes, StateMachine would be cleaned up at the end of 10 minutes if |
| // the authentication is still pending and no packet was exchanged for this session during last 5 |
| // minutes. |
| |
| boolean noTrafficWithinThreshold = (System.currentTimeMillis() |
| - stateMachine.getLastPacketReceivedTime()) > ((cleanupTimerTimeOutInMins * 60 * 1000) / 2); |
| |
| if ((TIMEOUT_ELIGIBLE_STATES.contains(stateMachine.state())) && noTrafficWithinThreshold) { |
| log.info("Deleting StateMachineMapping for sessionId: {}", sessionId); |
| cleanupTimer = null; |
| if (stateMachine.state() == STATE_PENDING && stateMachine.isWaitingForRadiusResponse()) { |
| aaaManager.aaaStatisticsManager.getAaaStats().increaseTimedOutPackets(); |
| } |
| //pushing captured machine stats to kafka |
| stateMachine.setSessionTerminateReason("Time out"); |
| AaaSupplicantMachineStats obj = aaaManager.aaaSupplicantStatsManager |
| .getSupplicantStats(stateMachine); |
| aaaManager.aaaSupplicantStatsManager.getMachineStatsDelegate() |
| .notify(new AaaMachineStatisticsEvent( |
| AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj)); |
| |
| deleteStateMachineId(sessionId); |
| deleteStateMachineMapping(stateMachine); |
| |
| // If StateMachine is not eligible for cleanup yet, reschedule cleanupTimer further. |
| } else { |
| aaaManager.scheduleStateMachineCleanupTimer(sessionId, stateMachine); |
| } |
| } else { |
| // This statement should not be logged; cleanupTimer should be cancelled for stateMachine |
| // instances which have been authenticated successfully. |
| log.warn("state-machine not found for sessionId: {}", sessionId); |
| } |
| |
| } |
| } |
| |
| } |