[SEBA-36] Operational Status 802.1x Session

Cherry-picked from aaa-1.10

Change-Id: I6b90ec939c1f70b259fc96aedb34d2ab7e6b5812
diff --git a/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsDelegate.java b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsDelegate.java
new file mode 100644
index 0000000..a402419
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsDelegate.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018-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;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Delegate for Authentication Statistics.
+ */
+public interface AaaMachineStatisticsDelegate extends StoreDelegate<AaaMachineStatisticsEvent> {
+
+}
diff --git a/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEvent.java b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEvent.java
new file mode 100644
index 0000000..1c130dc
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEvent.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2018-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;
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Event indicating the Accounting Data of AAA.
+ */
+public class AaaMachineStatisticsEvent extends
+        AbstractEvent<AaaMachineStatisticsEvent.Type, AaaSupplicantMachineStats> {
+/**
+ * Accounting data.
+ * Machine Statistic event type.
+ */
+    public enum Type {
+        /**
+         * signifies that the Machine Statistics Event stats has been updated.
+         */
+        STATS_UPDATE
+    }
+    public AaaMachineStatisticsEvent(Type type, AaaSupplicantMachineStats stats) {
+        super(type, stats);
+    }
+}
\ No newline at end of file
diff --git a/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEventListener.java b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEventListener.java
new file mode 100644
index 0000000..28681eb
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsEventListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018-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;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Listener for accounting events.
+ */
+public interface AaaMachineStatisticsEventListener extends
+EventListener<AaaMachineStatisticsEvent> {
+}
diff --git a/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsService.java b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsService.java
new file mode 100644
index 0000000..11095b3
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/AaaMachineStatisticsService.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018-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;
+
+import org.onosproject.event.ListenerService;
+
+/**
+ * Service for interacting with authentication module.
+ */
+public interface AaaMachineStatisticsService
+        extends ListenerService<AaaMachineStatisticsEvent, AaaMachineStatisticsEventListener> {
+    /**
+     * To get Supplicant machine stat.
+     *
+     * @param obj State Machine instance.
+     * @return supplicant stats.
+     */
+    public AaaSupplicantMachineStats getSupplicantStats(Object obj);
+
+    /**
+     * Returns AaaMachineStatisticsDelegate object.
+     *
+     * @return AaaMachineStatisticsDelegate.
+     */
+    public AaaMachineStatisticsDelegate getMachineStatsDelegate();
+
+    /**
+     * Log the Machine stats.
+     *
+     * @param obj of AaaSupplicantMachineStats.
+     */
+    void logAaaSupplicantMachineStats(AaaSupplicantMachineStats obj);
+
+}
diff --git a/api/src/main/java/org/opencord/aaa/AaaSupplicantMachineStats.java b/api/src/main/java/org/opencord/aaa/AaaSupplicantMachineStats.java
new file mode 100644
index 0000000..87fa2f5
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/AaaSupplicantMachineStats.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018-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;
+
+public class AaaSupplicantMachineStats {
+
+        private String sessionId;
+
+        private String sessionName;
+
+        private long sessionDuration;
+
+        private long totalFramesReceived;
+
+        private long totalFramesSent;
+
+        private long totalPacketsRecieved;
+
+        private long totalPacketsSent;
+
+        private long totalOctetRecieved;
+
+        private long totalOctetSent;
+
+        private String eapolType;
+
+        private String srcMacAddress;
+
+        private String sessionTerminateReason;
+
+        public String getSessionId() {
+                return sessionId;
+        }
+
+        public void setSessionId(String sessionId) {
+                this.sessionId = sessionId;
+        }
+
+        public String getSessionName() {
+                return sessionName;
+        }
+
+        public void setSessionName(String sessionName) {
+                this.sessionName = sessionName;
+        }
+
+        public long getSessionDuration() {
+                return sessionDuration;
+        }
+
+        public void setSessionDuration(long sessionDuration) {
+                this.sessionDuration = sessionDuration;
+        }
+
+        public long getTotalFramesReceived() {
+                return totalFramesReceived;
+        }
+
+        public void setTotalFramesReceived(long totalFramesReceived) {
+                this.totalFramesReceived = totalFramesReceived;
+        }
+
+        public String getEapolType() {
+                return eapolType;
+        }
+
+        public void setEapolType(String eapolType) {
+                this.eapolType = eapolType;
+        }
+
+        public String getSrcMacAddress() {
+                return srcMacAddress;
+        }
+
+        public void setSrcMacAddress(String srcMacAddress) {
+                this.srcMacAddress = srcMacAddress;
+        }
+
+        public long getTotalFramesSent() {
+                return totalFramesSent;
+        }
+
+        public void setTotalFramesSent(long totalFramesSent) {
+                this.totalFramesSent = totalFramesSent;
+        }
+
+        public long getTotalPacketsRecieved() {
+                return totalPacketsRecieved;
+        }
+
+        public void setTotalPacketsRecieved(long totalPacketsRecieved) {
+                this.totalPacketsRecieved = totalPacketsRecieved;
+        }
+
+        public long getTotalPacketsSent() {
+                return totalPacketsSent;
+        }
+
+        public void setTotalPacketsSent(long totalPacketsSent) {
+                this.totalPacketsSent = totalPacketsSent;
+        }
+
+        public long getTotalOctetRecieved() {
+                return totalOctetRecieved;
+        }
+
+        public void setTotalOctetRecieved(long totalOctetRecieved) {
+                this.totalOctetRecieved = totalOctetRecieved;
+        }
+
+        public long getTotalOctetSent() {
+                return totalOctetSent;
+        }
+
+        public void setTotalOctetSent(long totalOctetSent) {
+                this.totalOctetSent = totalOctetSent;
+        }
+
+        public String getSessionTerminateReason() {
+                return sessionTerminateReason;
+        }
+
+        public void setSessionTerminateReason(String sessionTerminateReason) {
+                this.sessionTerminateReason = sessionTerminateReason;
+        }
+
+}
diff --git a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
index 0e819d9..09fe8ae 100644
--- a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
+++ b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
@@ -50,6 +50,9 @@
 import org.onosproject.net.packet.PacketProcessor;
 import org.onosproject.net.packet.PacketService;
 import org.opencord.aaa.AaaConfig;
+import org.opencord.aaa.AaaMachineStatisticsEvent;
+import org.opencord.aaa.AaaMachineStatisticsService;
+import org.opencord.aaa.AaaSupplicantMachineStats;
 import org.opencord.aaa.AuthenticationEvent;
 import org.opencord.aaa.AuthenticationEventListener;
 import org.opencord.aaa.AuthenticationService;
@@ -137,6 +140,9 @@
     protected AuthenticationStatisticsService aaaStatisticsManager;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected AaaMachineStatisticsService aaaSupplicantStatsManager;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ComponentConfigService cfgService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -468,9 +474,18 @@
             aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
             return;
         }
+
+        //instance of StateMachine using the sessionId for updating machine stats
+        StateMachine machineStats = StateMachine.lookupStateMachineBySessionId(stateMachine.sessionId());
+
         EAP eapPayload;
         Ethernet eth;
         checkReceivedPacketForValidValidator(radiusPacket, stateMachine.requestAuthenticator());
+
+        //increasing packets and octets received from server
+        machineStats.incrementTotalPacketsReceived();
+        machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
+
         if (outPacketSet.contains(radiusPacket.getIdentifier())) {
             aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(false);
             outPacketSet.remove(new Byte(radiusPacket.getIdentifier()));
@@ -495,6 +510,9 @@
                 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
                 outPacketSupp.add(eapPayload.getIdentifier());
                 aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
+                //increasing packets send to server
+                machineStats.incrementTotalPacketsSent();
+                machineStats.incrementTotalOctetSent(eapPayload.getLength());
                 break;
             case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
                 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
@@ -514,6 +532,9 @@
 
                 stateMachine.authorizeAccess();
                 aaaStatisticsManager.getAaaStats().increaseAcceptResponsesRx();
+                //increasing packets send to server
+                machineStats.incrementTotalPacketsSent();
+                machineStats.incrementTotalOctetSent(eapPayload.getLength());
                 break;
             case RADIUS.RADIUS_CODE_ACCESS_REJECT:
                 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_REJECT");
@@ -541,10 +562,20 @@
 
                 stateMachine.denyAccess();
                 aaaStatisticsManager.getAaaStats().increaseRejectResponsesRx();
+                //increasing packets send to server
+                machineStats.incrementTotalPacketsSent();
+                machineStats.incrementTotalOctetSent(eapPayload.getLength());
+                //pushing machine stats to kafka
+                AaaSupplicantMachineStats machineObj = aaaSupplicantStatsManager.getSupplicantStats(machineStats);
+                aaaSupplicantStatsManager.getMachineStatsDelegate()
+                        .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, machineObj));
                 break;
             default:
                 log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
                 aaaStatisticsManager.getAaaStats().increaseUnknownTypeRx();
+                //increasing packets received to server
+                machineStats.incrementTotalPacketsReceived();
+                machineStats.incrementTotalOctetReceived(radiusPacket.decapsulateMessage().getLength());
         }
         aaaStatisticsManager.getAaaStats().countDroppedResponsesRx();
     }
@@ -677,6 +708,7 @@
                 stateMachine = new StateMachine(sessionId);
             } else {
                 log.debug("Using existing state-machine for sessionId: {}", sessionId);
+                stateMachine.setEapolTypeVal(eapol.getEapolType());
             }
 
             switch (eapol.getEapolType()) {
@@ -706,6 +738,15 @@
                     break;
                 case EAPOL.EAPOL_LOGOFF:
                     log.debug("EAP packet: EAPOL_LOGOFF");
+                    //posting the machine stat data for current supplicant device.
+                    if (stateMachine.getSessionTerminateReason() == null ||
+                            stateMachine.getSessionTerminateReason().equals("")) {
+                        stateMachine.setSessionTerminateReason(
+                                StateMachine.SessionTerminationReasons.SUPPLICANT_LOGOFF.getReason());
+                    }
+                    AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
+                    aaaSupplicantStatsManager.getMachineStatsDelegate()
+                            .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
                     if (stateMachine.state() == StateMachine.STATE_AUTHORIZED) {
                         stateMachine.logoff();
                         aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
@@ -743,6 +784,8 @@
                             // change the state to "PENDING"
                             if (stateMachine.state() == StateMachine.STATE_PENDING) {
                                 aaaStatisticsManager.getAaaStats().increaseRequestReTx();
+                                stateMachine.incrementTotalPacketsSent();
+                                stateMachine.incrementTotalOctetSent(eapol.getPacketLength());
                             }
                             stateMachine.requestAccess();
                             break;
@@ -910,6 +953,16 @@
                     PortNumber portNumber = event.port().number();
                     String sessionId = devId.toString() + portNumber.toString();
 
+                    StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
+                    if (stateMachine != null) {
+                        stateMachine.setSessionTerminateReason(
+                                StateMachine.SessionTerminationReasons.PORT_REMOVED.getReason());
+                    }
+                    //pushing captured machine stats to kafka
+                    AaaSupplicantMachineStats obj = aaaSupplicantStatsManager.getSupplicantStats(stateMachine);
+                    aaaSupplicantStatsManager.getMachineStatsDelegate()
+                            .notify(new AaaMachineStatisticsEvent(AaaMachineStatisticsEvent.Type.STATS_UPDATE, obj));
+
                     Map<String, StateMachine> sessionIdMap = StateMachine.sessionIdMap();
                     StateMachine removed = sessionIdMap.remove(sessionId);
                     if (removed != null) {
diff --git a/app/src/main/java/org/opencord/aaa/impl/AaaSupplicantMachineStatsManager.java b/app/src/main/java/org/opencord/aaa/impl/AaaSupplicantMachineStatsManager.java
new file mode 100644
index 0000000..8cee43d
--- /dev/null
+++ b/app/src/main/java/org/opencord/aaa/impl/AaaSupplicantMachineStatsManager.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2018-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 org.onosproject.event.AbstractListenerManager;
+import org.opencord.aaa.AaaMachineStatisticsDelegate;
+import org.opencord.aaa.AaaMachineStatisticsEvent;
+import org.opencord.aaa.AaaMachineStatisticsEventListener;
+import org.opencord.aaa.AaaMachineStatisticsService;
+import org.opencord.aaa.AaaSupplicantMachineStats;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+@Component(immediate = true)
+public class AaaSupplicantMachineStatsManager
+        extends AbstractListenerManager<AaaMachineStatisticsEvent, AaaMachineStatisticsEventListener>
+        implements AaaMachineStatisticsService {
+
+    private final Logger log = getLogger(getClass());
+
+    private AaaMachineStatisticsDelegate machineStatDelegate;
+
+    @Activate
+    public void activate() {
+        log.info("Activate aaaStatisticsManager");
+        machineStatDelegate = new InternalMachineStatDelegate();
+        eventDispatcher.addSink(AaaMachineStatisticsEvent.class, listenerRegistry);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        eventDispatcher.removeSink(AaaMachineStatisticsEvent.class);
+    }
+
+    @Override
+    public AaaSupplicantMachineStats getSupplicantStats(Object obj) {
+        StateMachine stateMachine = null;
+        AaaSupplicantMachineStats stats = new AaaSupplicantMachineStats();
+        try {
+            stateMachine = (StateMachine) obj;
+        } catch (ClassCastException e) {
+            log.debug("casting exception detected for StateMachine.");
+            return null;
+        }
+        log.debug("capturing supplicant machine stat from authentication session");
+        stats.setTotalPacketsSent(stateMachine.totalPacketsSent());
+        stats.setTotalPacketsRecieved(stateMachine.totalPacketsReceived());
+        stats.setTotalFramesSent(stateMachine.totalPacketsSent());
+        stats.setTotalFramesReceived(stateMachine.totalPacketsReceived());
+        stats.setSrcMacAddress(stateMachine.supplicantAddress() == null ? ""
+                : stateMachine.supplicantAddress().toString());
+        stats.setSessionName(stateMachine.username() == null ? ""
+                : new String(stateMachine.username()));
+        stats.setSessionId(stateMachine.sessionId());
+        stats.setSessionDuration(System.currentTimeMillis() - stateMachine.sessionStartTime());
+        stats.setEapolType(stateMachine.eapolType());
+        stats.setSessionTerminateReason(stateMachine.getSessionTerminateReason());
+
+        log.trace("EapolType" + " - " + stats.getEapolType());
+        log.trace("SessionDuration" + " - " + stats.getSessionDuration());
+        log.trace("SessionId" + " - " + stats.getSessionId());
+        log.trace("SessionName" + " - " + stats.getSessionName());
+        log.trace("SessionTerminateReason" + " - " + stats.getSessionTerminateReason());
+        log.trace("SrcMacAddress" + " - " + stats.getSrcMacAddress());
+        log.trace("TotalFramesReceived" + " - " + stats.getTotalFramesReceived());
+        log.trace("TotalFramesSent" + " - " + stats.getTotalFramesSent());
+        log.trace("TotalOctetRecieved" + " - " + stats.getTotalOctetRecieved());
+        log.trace("TotalOctetSent" + " - " + stats.getTotalOctetSent());
+        log.trace("TotalPacketsSent" + " - " + stats.getTotalPacketsSent());
+        log.trace("TotalOctetRecieved" + " - " + stats.getTotalOctetRecieved());
+        return stats;
+    }
+
+    @Override
+    public void logAaaSupplicantMachineStats(AaaSupplicantMachineStats obj) {
+        log.trace("EapolType" + " - " + obj.getEapolType());
+        log.trace("SessionDuration" + " - " + obj.getSessionDuration());
+        log.trace("SessionId" + " - " + obj.getSessionId());
+        log.trace("SessionName" + " - " + obj.getSessionName());
+        log.trace("SessionTerminateReason" + " - " + obj.getSessionTerminateReason());
+        log.trace("SrcMacAddress" + " - " + obj.getSrcMacAddress());
+        log.trace("TotalFramesReceived" + " - " + obj.getTotalFramesReceived());
+        log.trace("TotalFramesSent" + " - " + obj.getTotalFramesSent());
+        log.trace("TotalOctetRecieved" + " - " + obj.getTotalOctetRecieved());
+        log.trace("TotalOctetSent" + " - " + obj.getTotalOctetSent());
+        log.trace("TotalPacketsSent" + " - " + obj.getTotalPacketsSent());
+        log.trace("TotalOctetRecieved" + " - " + obj.getTotalOctetRecieved());
+    }
+
+    @Override
+    public AaaMachineStatisticsDelegate getMachineStatsDelegate() {
+        return machineStatDelegate;
+    }
+
+    private class InternalMachineStatDelegate implements AaaMachineStatisticsDelegate {
+        @Override
+        public void notify(AaaMachineStatisticsEvent aaaMachineStatisticsEvent) {
+            log.debug("Supplicant Statistics event {} for {}", aaaMachineStatisticsEvent.type(),
+                    aaaMachineStatisticsEvent.subject());
+            post(aaaMachineStatisticsEvent);
+        }
+    }
+
+}
diff --git a/app/src/main/java/org/opencord/aaa/impl/StateMachine.java b/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
index 48e4ac0..8d73e15 100644
--- a/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
+++ b/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
@@ -66,6 +66,46 @@
     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");
+
+        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.
@@ -316,6 +356,86 @@
     }
 
     /**
+     * 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.
diff --git a/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java b/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java
index 8627d3c..43e7c4d 100644
--- a/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java
+++ b/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java
@@ -64,6 +64,7 @@
     private final Logger log = getLogger(getClass());
     private AaaManager aaaManager;
     private AaaStatisticsManager aaaStatisticsManager;
+    private AaaSupplicantMachineStatsManager aaaSupplicantStatsManager;
 
     class AaaManagerWithoutRadiusServer extends AaaManager {
        protected void sendRadiusPacket(RADIUS radiusPacket, InboundPacket inPkt) {
@@ -186,9 +187,13 @@
         aaaManager.sadisService = new MockSadisService();
         aaaManager.cfgService = new MockCfgService();
         aaaStatisticsManager = new AaaStatisticsManager();
+        aaaSupplicantStatsManager = new AaaSupplicantMachineStatsManager();
         TestUtils.setField(aaaStatisticsManager, "eventDispatcher", new TestEventDispatcher());
         aaaStatisticsManager.activate();
+        TestUtils.setField(aaaSupplicantStatsManager, "eventDispatcher", new TestEventDispatcher());
+        aaaSupplicantStatsManager.activate();
         aaaManager.aaaStatisticsManager = this.aaaStatisticsManager;
+        aaaManager.aaaSupplicantStatsManager = this.aaaSupplicantStatsManager;
         TestUtils.setField(aaaManager, "eventDispatcher", new TestEventDispatcher());
         aaaManager.activate(new AaaTestBase.MockComponentContext());
     }
@@ -460,4 +465,4 @@
 
     }
 
-}
\ No newline at end of file
+}