[SEBA-34] Operational Status 802.1x Authenticator

Cherry-picked from aaa-1.10

Change-Id: I7a7da5a03d0b5c6cac8eb6c4edf027b1d02e26e8
diff --git a/api/src/main/java/org/opencord/aaa/AaaStatistics.java b/api/src/main/java/org/opencord/aaa/AaaStatistics.java
index e345a68..db21c02 100644
--- a/api/src/main/java/org/opencord/aaa/AaaStatistics.java
+++ b/api/src/main/java/org/opencord/aaa/AaaStatistics.java
@@ -70,6 +70,22 @@
     private AtomicLong eapolAttrIdentity = new AtomicLong();
     //Number of authenticating transitions due to EAP response or identity message
     private AtomicLong eapolResIdentityMsgTrans = new AtomicLong();
+    //Current number of EAPOL frames transmitted
+    private AtomicLong eapolFramesTx = new AtomicLong();
+    //Authenticator state when idle
+    private AtomicLong authStateIdle = new AtomicLong();
+    //Number of request ID EAP frames transmitted
+    private AtomicLong requestIdFramesTx = new AtomicLong();
+    //Current number of request EAP frames transmitted
+    private AtomicLong reqEapFramesTx = new AtomicLong();
+    //Number of EAPOL frames received with invalid packet type
+    private AtomicLong invalidPktType = new AtomicLong();
+    //Number of EAPOL frames received with invalid body length
+    private AtomicLong invalidBodyLength = new AtomicLong();
+    //number of valid EAPOL frames received
+    private AtomicLong validEapolFramesRx = new AtomicLong();
+    //Number of request pending response from supplicant
+    private AtomicLong pendingResSupp = new AtomicLong();
 
     public Long getEapolResIdentityMsgTrans() {
         return eapolResIdentityMsgTrans.get();
@@ -113,6 +129,38 @@
 
     private LinkedList<Long> packetRoundTripTimeList = new LinkedList<Long>();
 
+    public Long getPendingResSupp() {
+        return pendingResSupp.get();
+    }
+
+    public Long getValidEapolFramesRx() {
+        return validEapolFramesRx.get();
+    }
+
+    public Long getInvalidBodyLength() {
+        return invalidBodyLength.get();
+    }
+
+    public Long getInvalidPktType() {
+        return invalidPktType.get();
+    }
+
+    public Long getRequestIdFramesTx() {
+        return requestIdFramesTx.get();
+    }
+
+    public Long getReqEapFramesTx() {
+        return reqEapFramesTx.get();
+    }
+
+    public Long getAuthStateIdle() {
+        return authStateIdle.get();
+    }
+
+    public Long getEapolFramesTx() {
+        return eapolFramesTx.get();
+    }
+
     public LinkedList<Long> getPacketRoundTripTimeList() {
         return packetRoundTripTimeList;
     }
@@ -205,6 +253,10 @@
         requestReTx.incrementAndGet();
     }
 
+    public void incrementInvalidPktType() {
+        invalidPktType.incrementAndGet();
+    }
+
     public void increaseOrDecreasePendingRequests(boolean isIncrement) {
         if (isIncrement) {
             pendingRequests.incrementAndGet();
@@ -261,6 +313,34 @@
         eapolTlsRespChall.incrementAndGet();
     }
 
+    public void incrementEapolFramesTx() {
+        eapolFramesTx.incrementAndGet();
+    }
+
+    public void incrementAuthStateIdle() {
+        authStateIdle.incrementAndGet();
+    }
+
+    public void incrementRequestIdFramesTx() {
+        requestIdFramesTx.incrementAndGet();
+    }
+
+    public void incrementInvalidBodyLength() {
+        invalidBodyLength.incrementAndGet();
+    }
+
+    public void incrementValidEapolFramesRx() {
+        validEapolFramesRx.incrementAndGet();
+    }
+
+    public void incrementPendingResSupp() {
+        pendingResSupp.incrementAndGet();
+    }
+
+    public void decrementPendingResSupp() {
+        pendingResSupp.decrementAndGet();
+    }
+
     public void countDroppedResponsesRx() {
         long numberOfDroppedPackets = invalidValidatorsRx.get();
         numberOfDroppedPackets += unknownTypeRx.get();
@@ -269,6 +349,12 @@
         this.droppedResponsesRx = new AtomicLong(numberOfDroppedPackets);
     }
 
+    public void countReqEapFramesTx() {
+        long noReqEapFramesTx = requestIdFramesTx.get();
+        noReqEapFramesTx += challengeResponsesRx.get();
+        this.reqEapFramesTx = new AtomicLong(noReqEapFramesTx);
+    }
+
     public void resetAllCounters() {
         clearPacketRoundTripTimeList();
 
@@ -291,7 +377,14 @@
         eapolTransRespNotNak.set(0);
         eapPktTxauthChooseEap.set(0);
         eapolResIdentityMsgTrans.set(0);
-
+        eapolFramesTx.set(0);
+        authStateIdle.set(0);
+        requestIdFramesTx.set(0);
+        reqEapFramesTx.set(0);
+        invalidPktType.set(0);
+        invalidBodyLength.set(0);
+        validEapolFramesRx.set(0);
+        pendingResSupp.set(0);
     }
     public void countTransRespNotNak() {
         long eapolTransactionNotNak = eapolMd5RspChall.get();
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 1323e5f..55b6726 100755
--- a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
+++ b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
@@ -25,6 +25,7 @@
 import java.util.Dictionary;
 import java.util.HashSet;
 import java.util.Arrays;
+import java.util.List;
 
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.osgi.service.component.annotations.Component;
@@ -184,6 +185,9 @@
     ScheduledExecutorService executor;
     String configuredAaaServerAddress;
     HashSet<Byte> outPacketSet = new HashSet<Byte>();
+    HashSet<Byte> outPacketSupp = new HashSet<Byte>();
+    static final List<Byte> VALID_EAPOL_TYPE = Arrays.asList(EAPOL.EAPOL_START, EAPOL.EAPOL_LOGOFF, EAPOL.EAPOL_PACKET);
+    static final int HEADER_LENGTH = 4;
     // Configuration properties factory
     private final ConfigFactory factory =
             new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
@@ -440,6 +444,8 @@
                 log.debug("Send EAP challenge response to supplicant {}", stateMachine.supplicantAddress().toString());
                 sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), true);
                 aaaStatisticsManager.getAaaStats().increaseChallengeResponsesRx();
+                outPacketSupp.add(eapPayload.getIdentifier());
+                aaaStatisticsManager.getAaaStats().incrementPendingResSupp();
                 break;
             case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
                 log.debug("RADIUS packet: RADIUS_CODE_ACCESS_ACCEPT");
@@ -514,6 +520,8 @@
         if (isChallengeResponse) {
             aaaStatisticsManager.getAaaStats().incrementEapPktTxauthEap();
         }
+        aaaStatisticsManager.getAaaStats().incrementEapolFramesTx();
+        aaaStatisticsManager.getAaaStats().countReqEapFramesTx();
     }
 
     @Override
@@ -599,6 +607,20 @@
                           portNumber);
             }
 
+            short pktlen = eapol.getPacketLength();
+            byte[] eapPayLoadBuffer = eapol.serialize();
+            int len = eapPayLoadBuffer.length;
+            if (len != (HEADER_LENGTH + pktlen)) {
+                aaaStatisticsManager.getAaaStats().incrementInvalidBodyLength();
+                return;
+            }
+            if (!VALID_EAPOL_TYPE.contains(eapol.getEapolType())) {
+                aaaStatisticsManager.getAaaStats().incrementInvalidPktType();
+                return;
+            }
+            if (pktlen >= 0 && ethPkt.getEtherType() == EthType.EtherType.EAPOL.ethType().toShort()) {
+                aaaStatisticsManager.getAaaStats().incrementValidEapolFramesRx();
+            }
             StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
             if (stateMachine == null) {
                 log.debug("Creating new state machine for sessionId: {} for "
@@ -630,6 +652,7 @@
                     stateMachine.setVlanId(ethPkt.getVlanID());
                     log.debug("Getting EAP identity from supplicant {}", stateMachine.supplicantAddress().toString());
                     sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint(), false);
+                    aaaStatisticsManager.getAaaStats().incrementRequestIdFramesTx();
 
                     break;
                 case EAPOL.EAPOL_LOGOFF:
@@ -638,12 +661,16 @@
                         stateMachine.logoff();
                         aaaStatisticsManager.getAaaStats().incrementEapolLogoffRx();
                     }
+                    if (stateMachine.state() == StateMachine.STATE_IDLE) {
+                        aaaStatisticsManager.getAaaStats().incrementAuthStateIdle();
+                    }
 
                     break;
                 case EAPOL.EAPOL_PACKET:
                     RADIUS radiusPayload;
                     // check if this is a Response/Identify or  a Response/TLS
                     EAP eapPacket = (EAP) eapol.getPayload();
+                    Byte identifier = new Byte(eapPacket.getIdentifier());
 
                     byte dataType = eapPacket.getDataType();
                     switch (dataType) {
@@ -689,6 +716,10 @@
                                             stateMachine.challengeState());
                                 }
                                 radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
+                                if (outPacketSupp.contains(eapPacket.getIdentifier())) {
+                                    aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
+                                    outPacketSupp.remove(identifier);
+                                }
                                 sendRadiusPacket(radiusPayload, inPacket);
                                 stateMachine.setWaitingForRadiusResponse(true);
                                 aaaStatisticsManager.getAaaStats().incrementEapolMd5RspChall();
@@ -707,6 +738,10 @@
                             stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
 
                             radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
+                            if (outPacketSupp.contains(eapPacket.getIdentifier())) {
+                                aaaStatisticsManager.getAaaStats().decrementPendingResSupp();
+                                outPacketSupp.remove(identifier);
+                            }
                             sendRadiusPacket(radiusPayload, inPacket);
                             stateMachine.setWaitingForRadiusResponse(true);
                             aaaStatisticsManager.getAaaStats().incrementEapolTlsRespChall();
@@ -868,6 +903,15 @@
             aaaStatisticsManager.getAaaStats().getEapPktTxauthChooseEap());
             log.debug("EapolResIdentityMsgTrans---" +
             aaaStatisticsManager.getAaaStats().getEapolResIdentityMsgTrans());
+            log.debug("EapolFramesTx---" + aaaStatisticsManager.getAaaStats().getEapolFramesTx());
+            log.debug("AuthStateIdle---" + aaaStatisticsManager.getAaaStats().getAuthStateIdle());
+            log.debug("RequestIdFramesTx---" + aaaStatisticsManager.getAaaStats().getRequestIdFramesTx());
+            log.debug("ReqEapFramesTx---" + aaaStatisticsManager.getAaaStats().getReqEapFramesTx());
+            log.debug("InvalidPktType---" + aaaStatisticsManager.getAaaStats().getInvalidPktType());
+            log.debug("InvalidBodyLength---" + aaaStatisticsManager.getAaaStats().getInvalidBodyLength());
+            log.debug("ValidEapolFramesRx---" + aaaStatisticsManager.getAaaStats().getValidEapolFramesRx());
+            log.debug("PendingResSupp---" + aaaStatisticsManager.getAaaStats().getPendingResSupp());
+            log.debug("ResIdEapFramesRx---" + aaaStatisticsManager.getAaaStats().getEapolattrIdentity());
             aaaStatisticsManager.getStatsDelegate().
                 notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
                     aaaStatisticsManager.getAaaStats()));