[SEBA-624] Implementation of radius server operational status
Cherry-picked from aaa-1.10
Change-Id: I3b70ddfc45c4b9e57c587df671088580c7426a89
diff --git a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
old mode 100755
new mode 100644
index 55b6726..0e819d9
--- a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
+++ b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
@@ -15,23 +15,8 @@
*/
package org.opencord.aaa.impl;
-import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.util.Map;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Arrays;
-import java.util.List;
-
+import com.google.common.base.Strings;
import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Deactivate;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EAP;
import org.onlab.packet.EAPOL;
@@ -71,31 +56,56 @@
import org.opencord.aaa.AuthenticationStatisticsEvent;
import org.opencord.aaa.AuthenticationStatisticsService;
import org.opencord.aaa.RadiusCommunicator;
+import org.opencord.aaa.RadiusOperationalStatusEvent;
+import org.opencord.aaa.RadiusOperationalStatusService;
+import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
import org.opencord.aaa.StateMachineDelegate;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SadisService;
import org.opencord.sadis.SubscriberAndDeviceInformation;
import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Modified;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
-import com.google.common.base.Strings;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
-import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_EVENT;
-import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_EVENT_DEFAULT;
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_PERIOD;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.STATISTICS_GENERATION_PERIOD_DEFAULT;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE;
+import static org.opencord.aaa.impl.OsgiPropertyConstants.STATUS_SERVER_MODE_DEFAULT;
+import static org.slf4j.LoggerFactory.getLogger;
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
/**
* AAA application for ONOS.
*/
@Component(immediate = true, property = {
- STATISTICS_GENERATION_EVENT + ":Integer=" + STATISTICS_GENERATION_EVENT_DEFAULT,
+ STATISTICS_GENERATION_PERIOD + ":Integer=" + STATISTICS_GENERATION_PERIOD_DEFAULT,
+ OPERATIONAL_STATUS_SERVER_EVENT_GENERATION + ":Integer=" + OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT,
+ OPERATIONAL_STATUS_SERVER_TIMEOUT + ":Integer=" + OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT,
+ STATUS_SERVER_MODE + ":String=" + STATUS_SERVER_MODE_DEFAULT,
})
public class AaaManager
extends AbstractListenerManager<AuthenticationEvent, AuthenticationEventListener>
@@ -129,12 +139,18 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY)
protected ComponentConfigService cfgService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected RadiusOperationalStatusService radiusOperationalStatusService;
+
protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
private final DeviceListener deviceListener = new InternalDeviceListener();
- /** Statistics generation interval. */
- private int statisticsGenerationEvent = STATISTICS_GENERATION_EVENT_DEFAULT;
+ // Properties
+ private int statisticsGenerationPeriodInSeconds = STATISTICS_GENERATION_PERIOD_DEFAULT;
+ private int operationalStatusEventGenerationPeriodInSeconds = OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT;
+ private int operationalStatusServerTimeoutInSeconds = OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT;
+ protected String operationalStatusEvaluationMode = STATUS_SERVER_MODE_DEFAULT;
// NAS IP address
protected InetAddress nasIpAddress;
@@ -181,7 +197,7 @@
AaaConfig newCfg;
ScheduledFuture<?> scheduledFuture;
-
+ ScheduledFuture<?> scheduledStatusServerChecker;
ScheduledExecutorService executor;
String configuredAaaServerAddress;
HashSet<Byte> outPacketSet = new HashSet<Byte>();
@@ -261,11 +277,15 @@
impl.requestIntercepts();
deviceService.addListener(deviceListener);
getConfiguredAaaServerAddress();
+ radiusOperationalStatusService.initialize(nasIpAddress.getAddress(), radiusSecret, impl);
authenticationStatisticsPublisher =
new AuthenticationStatisticsEventPublisher();
- executor = Executors.newScheduledThreadPool(1);
+ executor = Executors.newScheduledThreadPool(3);
+
scheduledFuture = executor.scheduleAtFixedRate(authenticationStatisticsPublisher,
- 0, statisticsGenerationEvent, TimeUnit.SECONDS);
+ 0, statisticsGenerationPeriodInSeconds, TimeUnit.SECONDS);
+ scheduledStatusServerChecker = executor.scheduleAtFixedRate(new ServerStatusChecker(), 0,
+ operationalStatusEventGenerationPeriodInSeconds, TimeUnit.SECONDS);
log.info("Started");
}
@@ -282,16 +302,40 @@
deviceService.removeListener(deviceListener);
eventDispatcher.removeSink(AuthenticationEvent.class);
scheduledFuture.cancel(true);
+ scheduledStatusServerChecker.cancel(true);
executor.shutdown();
log.info("Stopped");
}
-
@Modified
public void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- String s = Tools.get(properties, STATISTICS_GENERATION_EVENT);
- statisticsGenerationEvent = Strings.isNullOrEmpty(s)
- ? STATISTICS_GENERATION_EVENT_DEFAULT : Integer.parseInt(s.trim());
+ Dictionary<String, Object> properties = context.getProperties();
+
+ String s = Tools.get(properties, "statisticsGenerationPeriodInSeconds");
+ statisticsGenerationPeriodInSeconds = Strings.isNullOrEmpty(s) ? STATISTICS_GENERATION_PERIOD_DEFAULT
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
+ operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
+ ? OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
+ operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusEvaluationMode");
+ String newEvaluationModeString = Strings.isNullOrEmpty(s) ? STATUS_SERVER_MODE_DEFAULT : s.trim();
+
+ radiusOperationalStatusService
+ .setOperationalStatusServerTimeoutInMillis(operationalStatusServerTimeoutInSeconds * 1000);
+ RadiusOperationalStatusEvaluationMode newEvaluationMode =
+ RadiusOperationalStatusEvaluationMode.getValue(newEvaluationModeString);
+ if (newEvaluationMode != null) {
+ radiusOperationalStatusService.setRadiusOperationalStatusEvaluationMode(newEvaluationMode);
+ operationalStatusEvaluationMode = newEvaluationModeString;
+ } else {
+ properties.put("operationalStatusEvaluationMode", operationalStatusEvaluationMode);
+ }
}
protected void configureRadiusCommunication() {
@@ -381,6 +425,7 @@
outPacketSet.add(radiusPacket.getIdentifier());
aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
+ aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
impl.sendRadiusPacket(radiusPacket, inPkt);
}
@@ -411,6 +456,10 @@
if (log.isTraceEnabled()) {
log.trace("Received RADIUS packet {}", radiusPacket);
}
+ if (radiusOperationalStatusService.isRadiusResponseForOperationalStatus(radiusPacket.getIdentifier())) {
+ radiusOperationalStatusService.handleRadiusPacketForOperationalStatus(radiusPacket);
+ return;
+ }
StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
if (stateMachine == null) {
log.error("Invalid packet identifier {}, could not find corresponding "
@@ -916,5 +965,20 @@
notify(new AuthenticationStatisticsEvent(AuthenticationStatisticsEvent.Type.STATS_UPDATE,
aaaStatisticsManager.getAaaStats()));
}
+ }
+
+ private class ServerStatusChecker implements Runnable {
+ @Override
+ public void run() {
+ log.info("Notifying RadiusOperationalStatusEvent");
+ radiusOperationalStatusService.checkServerOperationalStatus();
+ log.info("--POSTING--" + radiusOperationalStatusService.getRadiusServerOperationalStatus());
+ radiusOperationalStatusService.getRadiusOprStDelegate()
+ .notify(new RadiusOperationalStatusEvent(
+ RadiusOperationalStatusEvent.Type.RADIUS_OPERATIONAL_STATUS,
+ radiusOperationalStatusService.
+ getRadiusServerOperationalStatus()));
}
-}
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/opencord/aaa/impl/OsgiPropertyConstants.java b/app/src/main/java/org/opencord/aaa/impl/OsgiPropertyConstants.java
index 38f1a32..1c59799 100644
--- a/app/src/main/java/org/opencord/aaa/impl/OsgiPropertyConstants.java
+++ b/app/src/main/java/org/opencord/aaa/impl/OsgiPropertyConstants.java
@@ -24,6 +24,16 @@
private OsgiPropertyConstants() {
}
- public static final String STATISTICS_GENERATION_EVENT = "statisticsGenerationEvent";
- public static final int STATISTICS_GENERATION_EVENT_DEFAULT = 20;
+ public static final String STATISTICS_GENERATION_PERIOD = "statisticsGenerationPeriodInSeconds";
+ public static final int STATISTICS_GENERATION_PERIOD_DEFAULT = 20;
+
+ public static final String OPERATIONAL_STATUS_SERVER_EVENT_GENERATION =
+ "operationalStatusEventGenerationPeriodInSeconds";
+ public static final int OPERATIONAL_STATUS_SERVER_EVENT_GENERATION_DEFAULT = 30;
+
+ public static final String OPERATIONAL_STATUS_SERVER_TIMEOUT = "operationalStatusServerTimeoutInSeconds";
+ public static final int OPERATIONAL_STATUS_SERVER_TIMEOUT_DEFAULT = 10;
+
+ public static final String STATUS_SERVER_MODE = "operationalStatusEvaluationMode";
+ public static final String STATUS_SERVER_MODE_DEFAULT = "AUTO";
}
diff --git a/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java b/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
index 2967a14..ad00b5f 100755
--- a/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
+++ b/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
@@ -15,17 +15,17 @@
*/
package org.opencord.aaa.impl;
+import com.google.common.collect.Maps;
import org.onlab.packet.ARP;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
import org.onlab.packet.RADIUS;
import org.onlab.packet.TpPort;
import org.onlab.packet.UDP;
-
import org.onosproject.core.ApplicationId;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
@@ -43,24 +43,20 @@
import org.onosproject.net.packet.OutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketService;
-
import org.opencord.aaa.AaaConfig;
import org.opencord.aaa.RadiusCommunicator;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SubscriberAndDeviceInformation;
-
import org.slf4j.Logger;
-import com.google.common.collect.Maps;
-
-import static org.onosproject.net.packet.PacketPriority.CONTROL;
-import static org.slf4j.LoggerFactory.getLogger;
-
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Set;
+import static org.onosproject.net.packet.PacketPriority.CONTROL;
+import static org.slf4j.LoggerFactory.getLogger;
+
/**
* Handles communication with the RADIUS server through ports
* of the SDN switches.
@@ -260,13 +256,20 @@
if (deviceInfo == null) {
log.warn("No Device found with SN {}", serialNo);
+ aaaManager.radiusOperationalStatusService.setStatusServerReqSent(false);
return;
}
ipToSnMap.put(deviceInfo.ipAddress(), serialNo);
- aaaManager.aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
+ if (radiusPacket.getIdentifier() == RadiusOperationalStatusManager.AAA_REQUEST_ID_STATUS_REQUEST ||
+ radiusPacket.getIdentifier() == RadiusOperationalStatusManager.AAA_REQUEST_ID_FAKE_ACCESS_REQUEST) {
+ aaaManager.radiusOperationalStatusService.setOutTimeInMillis(radiusPacket.getIdentifier());
+ } else {
+ aaaManager.aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
+ }
// send the message out
sendFromRadiusServerPort(pktCustomizer.
customizeEthernetIPHeaders(ethReply, inPkt));
+ aaaManager.radiusOperationalStatusService.setStatusServerReqSent(true);
}
/**
diff --git a/app/src/main/java/org/opencord/aaa/impl/RadiusOperationalStatusManager.java b/app/src/main/java/org/opencord/aaa/impl/RadiusOperationalStatusManager.java
new file mode 100644
index 0000000..2fe5755
--- /dev/null
+++ b/app/src/main/java/org/opencord/aaa/impl/RadiusOperationalStatusManager.java
@@ -0,0 +1,248 @@
+/*
+ * 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 org.onlab.packet.RADIUS;
+import org.onlab.packet.RADIUSAttribute;
+import org.onosproject.event.AbstractListenerManager;
+import org.opencord.aaa.RadiusCommunicator;
+import org.opencord.aaa.RadiusOperationalStatusEvent;
+import org.opencord.aaa.RadiusOperationalStatusEventDelegate;
+import org.opencord.aaa.RadiusOperationalStatusEventListener;
+import org.opencord.aaa.RadiusOperationalStatusService;
+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 RadiusOperationalStatusManager
+ extends AbstractListenerManager<RadiusOperationalStatusEvent, RadiusOperationalStatusEventListener>
+ implements RadiusOperationalStatusService {
+
+ private byte[] address;
+ private String secret;
+ private RadiusCommunicator impl;
+ private RadiusOperationalStatusEventDelegate radiusOprStDelegate;
+
+ private long operationalStatusServerTimeoutInMillis;
+ private boolean statusServerReqSent;
+ private final Logger log = getLogger(getClass());
+
+ private Boolean fakeAccessRequestPacketRecieved = false;
+ private long fakeAccessRequestOutTimeInMillis;
+
+ private Boolean serverStatusPacketRecieved = false;
+ private long serverStatusOutTimeInMillis;
+
+ private OperationalStatus radiusServerOperationalStatus;
+ public static final byte AAA_REQUEST_ID_STATUS_REQUEST = 0;
+ public static final byte AAA_REQUEST_ID_FAKE_ACCESS_REQUEST = 1;
+
+ private RadiusOperationalStatusEvaluationMode radiusOperationalStatusEvaluationMode;
+
+ private static final String DUMMY_USER = new String("dummy-user");
+ private static final byte RADIUS_CODE_STATUS_REQUEST = (byte) 12;
+ private long lastRadiusPacketInTimeInMillis;
+
+ public void setOperationalStatusServerTimeoutInMillis(long operationalStatusServerTimeoutInMillis) {
+ this.operationalStatusServerTimeoutInMillis = operationalStatusServerTimeoutInMillis;
+ }
+
+ public void setRadiusOperationalStatusEvaluationMode(
+ RadiusOperationalStatusEvaluationMode radiusOperationalStatusEvaluationMode) {
+ this.radiusOperationalStatusEvaluationMode = radiusOperationalStatusEvaluationMode;
+ }
+
+ public RadiusOperationalStatusEventDelegate getRadiusOprStDelegate() {
+ return radiusOprStDelegate;
+ }
+
+ @Override
+ public void setOutTimeInMillis(byte identifier) {
+ if (identifier == AAA_REQUEST_ID_STATUS_REQUEST) {
+ serverStatusOutTimeInMillis = System.currentTimeMillis();
+ } else {
+ fakeAccessRequestOutTimeInMillis = System.currentTimeMillis();
+ }
+ }
+
+ @Override
+ public String getRadiusServerOperationalStatus() {
+ return radiusServerOperationalStatus.toString();
+ }
+
+ @Activate
+ public void activate() {
+ radiusOprStDelegate = new InternalRadiusOperationalStatusDelegate();
+ eventDispatcher.addSink(RadiusOperationalStatusEvent.class, listenerRegistry);
+ radiusServerOperationalStatus = OperationalStatus.UNKNOWN;
+ }
+
+ public void setStatusServerReqSent(boolean statusServerReqSent) {
+ this.statusServerReqSent = statusServerReqSent;
+ }
+
+ @Deactivate
+ public void deactivate() {
+ eventDispatcher.removeSink(RadiusOperationalStatusEvent.class);
+ }
+
+ public void initialize(byte[] address, String secret, RadiusCommunicator impl) {
+ this.address = address;
+ this.secret = secret;
+ this.impl = impl;
+ }
+
+ public boolean isRadiusResponseForOperationalStatus(byte identifier) {
+ if (identifier == AAA_REQUEST_ID_STATUS_REQUEST || identifier == AAA_REQUEST_ID_FAKE_ACCESS_REQUEST) {
+ return true;
+ } else {
+ lastRadiusPacketInTimeInMillis = System.currentTimeMillis();
+ return false;
+ }
+ }
+
+ public void handleRadiusPacketForOperationalStatus(RADIUS radiusPacket) {
+ byte radiusPktIdentifier = radiusPacket.getIdentifier();
+
+ if (radiusPktIdentifier == AAA_REQUEST_ID_STATUS_REQUEST) {
+ long serverStatusRttInMillis = System.currentTimeMillis() - serverStatusOutTimeInMillis;
+ if (serverStatusRttInMillis < operationalStatusServerTimeoutInMillis) {
+ serverStatusPacketRecieved = true;
+ }
+ } else {
+ long fakeAccessRttInMillis = System.currentTimeMillis() - fakeAccessRequestOutTimeInMillis;
+ if (fakeAccessRttInMillis < operationalStatusServerTimeoutInMillis) {
+ fakeAccessRequestPacketRecieved = true;
+ }
+ }
+
+ switch (radiusPacket.getCode()) {
+ case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
+ synchronized (serverStatusPacketRecieved) {
+ serverStatusPacketRecieved.notify();
+ }
+ break;
+ case RADIUS.RADIUS_CODE_ACCESS_REJECT:
+ synchronized (fakeAccessRequestPacketRecieved) {
+ fakeAccessRequestPacketRecieved.notify();
+ }
+ break;
+ default:
+ log.warn("Unexpected Radius message for operational status recieved "
+ + "with code: {}", radiusPacket.getCode());
+ }
+ }
+
+ public void checkServerStatusUsingStatusServerRequest() throws InterruptedException {
+ RADIUS radiusStatusServerRequest;
+ // identifier = 0 for status server
+ radiusStatusServerRequest = new RADIUS(RADIUS_CODE_STATUS_REQUEST, AAA_REQUEST_ID_STATUS_REQUEST);
+
+ radiusStatusServerRequest.setIdentifier(AAA_REQUEST_ID_STATUS_REQUEST);
+ radiusStatusServerRequest.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME, DUMMY_USER.getBytes());
+
+ radiusStatusServerRequest.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP, address);
+ radiusStatusServerRequest.addMessageAuthenticator(secret);
+ setOutTimeInMillis(radiusStatusServerRequest.getIdentifier());
+ impl.sendRadiusPacket(radiusStatusServerRequest, null);
+ synchronized (serverStatusPacketRecieved) {
+ serverStatusPacketRecieved.wait(operationalStatusServerTimeoutInMillis);
+ }
+ }
+
+ public void checkServerStatusUsingFakeAccessRequest() throws InterruptedException {
+ RADIUS radiusDummyAccessRequest;
+ // identifier = 1 for fake accessRequest
+ radiusDummyAccessRequest = new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST, AAA_REQUEST_ID_FAKE_ACCESS_REQUEST);
+
+ radiusDummyAccessRequest.setIdentifier(AAA_REQUEST_ID_FAKE_ACCESS_REQUEST);
+ radiusDummyAccessRequest.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME, DUMMY_USER.getBytes());
+
+ radiusDummyAccessRequest.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP, address);
+ radiusDummyAccessRequest.addMessageAuthenticator(secret);
+ setOutTimeInMillis(radiusDummyAccessRequest.getIdentifier());
+ impl.sendRadiusPacket(radiusDummyAccessRequest, null);
+ synchronized (fakeAccessRequestPacketRecieved) {
+ fakeAccessRequestPacketRecieved.wait(operationalStatusServerTimeoutInMillis);
+ }
+ }
+
+ public void checkStatusServerForAccessRequestMode() throws InterruptedException {
+ long radiusResponseRecievedTimeDifference = System.currentTimeMillis() - lastRadiusPacketInTimeInMillis;
+ if (radiusResponseRecievedTimeDifference > operationalStatusServerTimeoutInMillis) {
+ checkServerStatusUsingFakeAccessRequest();
+ if (statusServerReqSent && fakeAccessRequestPacketRecieved) {
+ radiusServerOperationalStatus = OperationalStatus.IN_USE;
+ } else if (statusServerReqSent && !fakeAccessRequestPacketRecieved) {
+ radiusServerOperationalStatus = OperationalStatus.UNAVAILABLE;
+ } else {
+ radiusServerOperationalStatus = OperationalStatus.UNKNOWN;
+ }
+ } else {
+ radiusServerOperationalStatus = OperationalStatus.IN_USE;
+ }
+ }
+
+ public void checkServerOperationalStatus() {
+
+ try {
+ if (radiusOperationalStatusEvaluationMode == RadiusOperationalStatusEvaluationMode.STATUS_REQUEST) {
+ // determine operational status by statusServerRequest
+ checkServerStatusUsingStatusServerRequest();
+ if (statusServerReqSent && serverStatusPacketRecieved) {
+ // if req sent and response recieved
+ radiusServerOperationalStatus = OperationalStatus.IN_USE;
+ } else if (statusServerReqSent && !serverStatusPacketRecieved) {
+ radiusServerOperationalStatus = OperationalStatus.UNAVAILABLE;
+ } else {
+ radiusServerOperationalStatus = OperationalStatus.UNKNOWN;
+ }
+ } else {
+ if (radiusOperationalStatusEvaluationMode == RadiusOperationalStatusEvaluationMode.AUTO) {
+ checkServerStatusUsingStatusServerRequest();
+ if (statusServerReqSent && serverStatusPacketRecieved) {
+ radiusServerOperationalStatus = OperationalStatus.IN_USE;
+ } else {
+ checkStatusServerForAccessRequestMode();
+ }
+ } else {
+ checkStatusServerForAccessRequestMode();
+ }
+ }
+ fakeAccessRequestPacketRecieved = false;
+ serverStatusPacketRecieved = false;
+ } catch (Exception e) {
+ log.error("Caught exception while checking radius server status::" + e);
+ }
+ }
+
+ /**
+ * Delegate allowing the RadiusOperationalStatus to notify us of events.
+ */
+ private class InternalRadiusOperationalStatusDelegate implements RadiusOperationalStatusEventDelegate {
+ @Override
+ public void notify(RadiusOperationalStatusEvent radiusOperationalStatusEvent) {
+ log.debug("Radius Operational Status event {} for {}", radiusOperationalStatusEvent.type(),
+ radiusOperationalStatusEvent.subject());
+ post(radiusOperationalStatusEvent);
+ }
+ }
+
+}
diff --git a/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java b/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java
index 0324083..d3c49c2 100755
--- a/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java
+++ b/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java
@@ -15,18 +15,7 @@
*/
package org.opencord.aaa.impl;
-import static org.onosproject.net.packet.PacketPriority.CONTROL;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.io.IOException;
-import java.net.DatagramPacket;
-import java.net.DatagramSocket;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.onlab.packet.DeserializationException;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
@@ -41,7 +30,17 @@
import org.opencord.aaa.RadiusCommunicator;
import org.slf4j.Logger;
-import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.UnknownHostException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.onosproject.net.packet.PacketPriority.CONTROL;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Handles Socket based communication with the RADIUS server.
@@ -148,10 +147,11 @@
log.trace("Sending packet {} to Radius Server {}:{} using socket",
radiusPacket, address, radiusServerPort);
}
- aaaManager.aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
socket.send(packet);
+ aaaManager.radiusOperationalStatusService.setStatusServerReqSent(true);
} catch (UnknownHostException uhe) {
log.warn("Unable to resolve host {}", radiusHost);
+ aaaManager.radiusOperationalStatusService.setStatusServerReqSent(false);
}
} catch (IOException e) {
log.info("Cannot send packet to RADIUS server", e);
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 5e9e140..48e4ac0 100644
--- a/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
+++ b/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
@@ -17,19 +17,18 @@
package org.opencord.aaa.impl;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.collect.Maps;
import org.onlab.packet.MacAddress;
import org.onosproject.net.ConnectPoint;
import org.opencord.aaa.AuthenticationEvent;
import org.opencord.aaa.StateMachineDelegate;
import org.slf4j.Logger;
-import com.google.common.collect.Maps;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* AAA Finite State Machine.
@@ -56,7 +55,7 @@
static final int TRANSITION_DENY_ACCESS = 3;
static final int TRANSITION_LOGOFF = 4;
- private static int identifier = -1;
+ private static int identifier = 1;
private byte challengeIdentifier;
private byte[] challengeState;
private byte[] username;
@@ -129,7 +128,7 @@
public static void initializeMaps() {
sessionIdMap = Maps.newConcurrentMap();
identifierMap = Maps.newConcurrentMap();
- identifier = -1;
+ identifier = 1;
}
public static void destroyMaps() {
@@ -207,7 +206,7 @@
if (e.getValue() != null && e.getValue().supplicantAddress != null
&& e.getValue().supplicantAddress.equals(mac)) {
sessionIdMap.remove(e.getValue().sessionId);
- if (e.getValue().identifier != -1) {
+ if (e.getValue().identifier != 1) {
deleteStateMachineMapping(e.getValue());
}
break;
@@ -419,9 +418,11 @@
* @return The state machine identifier.
*/
public synchronized byte identifier() {
- identifier = (identifier + 1) % 255;
- identifierMap.put(identifier, this);
- return (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);
}
/**