[SEBA-624] Implementation of radius server operational status
Change-Id: I2881ffc80e224589ae042db1e0b7471e72c64ec3
diff --git a/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEvent.java b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEvent.java
new file mode 100644
index 0000000..7ba9534
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEvent.java
@@ -0,0 +1,32 @@
+/*
+ * 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;
+
+public class RadiusOperationalStatusEvent extends
+ AbstractEvent<RadiusOperationalStatusEvent.Type, String> {
+
+ public RadiusOperationalStatusEvent(Type type, String subject) {
+ super(type, subject);
+ }
+
+ public enum Type {
+ RADIUS_OPERATIONAL_STATUS
+ }
+
+}
diff --git a/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventDelegate.java b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventDelegate.java
new file mode 100644
index 0000000..f4d5d5d
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+public interface RadiusOperationalStatusEventDelegate
+ extends StoreDelegate<RadiusOperationalStatusEvent> {
+
+}
diff --git a/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventListener.java b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventListener.java
new file mode 100644
index 0000000..defffcc
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+public interface RadiusOperationalStatusEventListener extends
+ EventListener<RadiusOperationalStatusEvent> {
+
+}
diff --git a/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusService.java b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusService.java
new file mode 100644
index 0000000..10c5d8b
--- /dev/null
+++ b/api/src/main/java/org/opencord/aaa/RadiusOperationalStatusService.java
@@ -0,0 +1,121 @@
+/*
+ * 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.onlab.packet.RADIUS;
+import org.onosproject.event.ListenerService;
+
+/**
+ * Service for interacting with operational status module.
+ */
+
+public interface RadiusOperationalStatusService extends
+ ListenerService<RadiusOperationalStatusEvent, RadiusOperationalStatusEventListener> {
+ /**
+ * Return RadiusOperationalStatusEventDelegate object.
+ *
+ * @return RadiusOperationalStatusEventDelegate
+ */
+ RadiusOperationalStatusEventDelegate getRadiusOprStDelegate();
+
+ /**
+ * Return String object.
+ *
+ * @return String
+ */
+ String getRadiusServerOperationalStatus();
+
+ /**
+ * Set the value of statusServerReqSent flag.
+ *
+ * @param statusServerReqSent statusServerReqSent flag
+ */
+ void setStatusServerReqSent(boolean statusServerReqSent);
+
+ /**
+ * Set the value of radiusOperationalStatus Evaluation Mode.
+ *
+ * @param radiusOperationalStatusEvaluationMode radiusOperationalStatusEvaluationMode value
+ */
+ void setRadiusOperationalStatusEvaluationMode(
+ RadiusOperationalStatusEvaluationMode radiusOperationalStatusEvaluationMode);
+
+ /**
+ * Set the value of Operational Status Server Timeout In Milliseconds.
+ *
+ * @param operationalStatusServerTimeoutInMillis operationalStatusServerTimeoutInMillis
+ */
+ void setOperationalStatusServerTimeoutInMillis(long operationalStatusServerTimeoutInMillis);
+
+ /**
+ * Determine the operational status of server.
+ */
+ void checkServerOperationalStatus();
+
+ /**
+ * Check if radius response is for operational status.
+ *
+ * @param identifier identifier value of radius packet
+ * @return boolean
+ */
+ boolean isRadiusResponseForOperationalStatus(byte identifier);
+
+ /**
+ * handle incoming radius packet for operational status.
+ *
+ * @param radiusPacket radiusPacket of incoming operational status
+ */
+ void handleRadiusPacketForOperationalStatus(RADIUS radiusPacket);
+
+ /**
+ * initialize radiusOperationalStatusService.
+ *
+ * @param address address of radius server
+ * @param secret secret key for radius server
+ * @param impl impl of RadiusCommunicator
+ */
+ void initialize(byte[] address, String secret, RadiusCommunicator impl);
+
+ /**
+ * set packet outgoing time in milliseconds.
+ *
+ * @param identifier identifier of outgoing packet
+ */
+ void setOutTimeInMillis(byte identifier);
+
+ enum OperationalStatus {
+ UNAVAILABLE,
+ UNKNOWN,
+ IN_USE,
+ }
+
+ enum RadiusOperationalStatusEvaluationMode {
+
+ STATUS_REQUEST, ACCESS_REQUEST, AUTO;
+
+ public static RadiusOperationalStatusEvaluationMode getValue(String value) {
+
+ for (RadiusOperationalStatusEvaluationMode mode: RadiusOperationalStatusEvaluationMode.values()) {
+ if (mode.toString().equalsIgnoreCase(value)) {
+ return mode;
+ }
+ }
+ return null;
+ }
+ }
+
+}
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 ff3c812..8e1f5c1
--- a/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
+++ b/app/src/main/java/org/opencord/aaa/impl/AaaManager.java
@@ -73,7 +73,10 @@
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.StateMachineDelegate;
+import org.opencord.aaa.RadiusOperationalStatusService.RadiusOperationalStatusEvaluationMode;
import org.opencord.sadis.BaseInformationService;
import org.opencord.sadis.SadisService;
import org.opencord.sadis.SubscriberAndDeviceInformation;
@@ -127,14 +130,35 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService cfgService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RadiusOperationalStatusService radiusOperationalStatusService;
+
protected AuthenticationStatisticsEventPublisher authenticationStatisticsPublisher;
protected BaseInformationService<SubscriberAndDeviceInformation> subsService;
private final DeviceListener deviceListener = new InternalDeviceListener();
private static final int DEFAULT_REPEAT_DELAY = 20;
- @Property(name = "statisticsGenerationEvent", intValue = DEFAULT_REPEAT_DELAY,
- label = "statisticsGenerationEvent")
- private int statisticsGenerationEvent = DEFAULT_REPEAT_DELAY;
+ @Property(name = "statisticsGenerationPeriodInSeconds", intValue = DEFAULT_REPEAT_DELAY,
+ label = "AAA Statistics generation frequency in seconds")
+ private int statisticsGenerationPeriodInSeconds = DEFAULT_REPEAT_DELAY;
+
+ private static final int DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION = 30;
+ @Property(name = "operationalStatusEventGenerationPeriodInSeconds",
+ intValue = DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION, label = "AAA Radius Server Operational "
+ + "Status Frequency in seconds")
+ private int operationalStatusEventGenerationPeriodInSeconds = DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION;
+
+ private static final int DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT = 10;
+ @Property(name = "operationalStatusServerTimeoutInSeconds",
+ intValue = DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT, label = "Maximum period(in Seconds) to "
+ + "wait for Status response from AAA Server ")
+ private int operationalStatusServerTimeoutInSeconds = DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT;
+
+ private static final String DEFAULT_STATUS_SERVER_MODE = "AUTO";
+ @Property(name = "operationalStatusEvaluationMode", value = DEFAULT_STATUS_SERVER_MODE,
+ label = "Evaluation mode for determining the Operational Status of Radius Server. Valid values are AUTO "
+ + "(default), STATUS_REQUEST and ACCESS_REQUEST")
+ protected String operationalStatusEvaluationMode = DEFAULT_STATUS_SERVER_MODE;
// NAS IP address
protected InetAddress nasIpAddress;
@@ -181,7 +205,7 @@
AaaConfig newCfg;
ScheduledFuture<?> scheduledFuture;
-
+ ScheduledFuture<?> scheduledStatusServerChecker;
ScheduledExecutorService executor;
String configuredAaaServerAddress;
HashSet<Byte> outPacketSet = new HashSet<Byte>();
@@ -261,11 +285,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,15 +310,39 @@
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, "statisticsGenerationEvent");
- statisticsGenerationEvent = Strings.isNullOrEmpty(s) ? DEFAULT_REPEAT_DELAY : Integer.parseInt(s.trim());
+ Dictionary<String, Object> properties = context.getProperties();
+ String s = Tools.get(properties, "statisticsGenerationPeriodInSeconds");
+ statisticsGenerationPeriodInSeconds = Strings.isNullOrEmpty(s) ? DEFAULT_REPEAT_DELAY
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusEventGenerationPeriodInSeconds");
+ operationalStatusEventGenerationPeriodInSeconds = Strings.isNullOrEmpty(s)
+ ? DEFAULT_OPERATIONAL_STATUS_SERVER_EVENT_GENERATION
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusServerTimeoutInSeconds");
+ operationalStatusServerTimeoutInSeconds = Strings.isNullOrEmpty(s) ? DEFAULT_OPERATIONAL_STATUS_SERVER_TIMEOUT
+ : Integer.parseInt(s.trim());
+
+ s = Tools.get(properties, "operationalStatusEvaluationMode");
+ String newEvaluationModeString = Strings.isNullOrEmpty(s) ? DEFAULT_STATUS_SERVER_MODE : 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() {
@@ -380,6 +432,7 @@
outPacketSet.add(radiusPacket.getIdentifier());
aaaStatisticsManager.getAaaStats().increaseOrDecreasePendingRequests(true);
aaaStatisticsManager.getAaaStats().increaseAccessRequestsTx();
+ aaaStatisticsManager.putOutgoingIdentifierToMap(radiusPacket.getIdentifier());
impl.sendRadiusPacket(radiusPacket, inPkt);
}
@@ -410,6 +463,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 "
@@ -915,5 +972,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/PortBasedRadiusCommunicator.java b/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
index 2967a14..92fea87 100755
--- a/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
+++ b/app/src/main/java/org/opencord/aaa/impl/PortBasedRadiusCommunicator.java
@@ -260,13 +260,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..448cbce
--- /dev/null
+++ b/app/src/main/java/org/opencord/aaa/impl/RadiusOperationalStatusManager.java
@@ -0,0 +1,250 @@
+/*
+ * 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 org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.RADIUS;
+import org.onlab.packet.RADIUSAttribute;
+import org.onosproject.event.AbstractListenerManager;
+import org.opencord.aaa.RadiusOperationalStatusService;
+import org.opencord.aaa.RadiusCommunicator;
+import org.opencord.aaa.RadiusOperationalStatusEvent;
+import org.opencord.aaa.RadiusOperationalStatusEventDelegate;
+import org.opencord.aaa.RadiusOperationalStatusEventListener;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.slf4j.Logger;
+
+@Service
+@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..32d4f21 100755
--- a/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java
+++ b/app/src/main/java/org/opencord/aaa/impl/SocketBasedRadiusCommunicator.java
@@ -148,10 +148,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 5994a28..7635d86 100644
--- a/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
+++ b/app/src/main/java/org/opencord/aaa/impl/StateMachine.java
@@ -56,7 +56,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 +129,7 @@
public static void initializeMaps() {
sessionIdMap = Maps.newConcurrentMap();
identifierMap = Maps.newConcurrentMap();
- identifier = -1;
+ identifier = 1;
}
public static void destroyMaps() {
@@ -207,7 +207,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 +419,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);
}
/**
diff --git a/app/src/test/java/org/opencord/aaa/impl/AaaManagerTest.java b/app/src/test/java/org/opencord/aaa/impl/AaaManagerTest.java
index 7303257..1b4257d 100644
--- a/app/src/test/java/org/opencord/aaa/impl/AaaManagerTest.java
+++ b/app/src/test/java/org/opencord/aaa/impl/AaaManagerTest.java
@@ -122,13 +122,13 @@
String challenge = "12345678901234567";
- EAP eap = new EAP(challengeType, (byte) 1, challengeType,
+ EAP eap = new EAP(challengeType, (byte) 4, challengeType,
challenge.getBytes(Charsets.US_ASCII));
- eap.setIdentifier((byte) 1);
+ eap.setIdentifier((byte) 4);
RADIUS radius = new RADIUS();
radius.setCode(challengeCode);
-
+ radius.setIdentifier((byte) 4);
radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
challenge.getBytes(Charsets.US_ASCII));
@@ -167,6 +167,7 @@
aaaManager.sadisService = new MockSadisService();
aaaManager.cfgService = new MockCfgService();
aaaStatisticsManager = new AaaStatisticsManager();
+ aaaManager.radiusOperationalStatusService = new RadiusOperationalStatusManager();
TestUtils.setField(aaaStatisticsManager, "eventDispatcher", new TestEventDispatcher());
aaaStatisticsManager.activate();
aaaManager.aaaStatisticsManager = this.aaaStatisticsManager;
@@ -228,7 +229,7 @@
// (2) Supplicant identify
- Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
+ Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 3, null);
sendPacket(identifyPacket);
RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
@@ -273,7 +274,7 @@
RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
- assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 3));
+ assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 9));
assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
// State machine should be in pending state
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 e4718b7..8627d3c 100644
--- a/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java
+++ b/app/src/test/java/org/opencord/aaa/impl/AaaStatisticsTest.java
@@ -138,20 +138,24 @@
*/
private RADIUS constructRadiusCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
- String challenge = "12345678901234567";
- EAP eap = new EAP(challengeType, (byte) 1, challengeType, challenge.getBytes(Charsets.US_ASCII));
- eap.setIdentifier((byte) 1);
+ String challenge = "12345678901234567";
- RADIUS radius = new RADIUS();
- radius.setCode(challengeCode);
+ EAP eap = new EAP(challengeType, (byte) 4, challengeType,
+ challenge.getBytes(Charsets.US_ASCII));
+ eap.setIdentifier((byte) 4);
- radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE, challenge.getBytes(Charsets.US_ASCII));
+ RADIUS radius = new RADIUS();
+ radius.setCode(challengeCode);
+ radius.setIdentifier((byte) 4);
+ radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
+ challenge.getBytes(Charsets.US_ASCII));
- radius.setPayload(eap);
- radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE, eap.serialize());
- radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH, aaaManager.radiusSecret.getBytes());
- return radius;
-
+ radius.setPayload(eap);
+ radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
+ eap.serialize());
+ radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_MESSAGE_AUTH,
+ aaaManager.radiusSecret.getBytes());
+ return radius;
}
public static void injectEventDispatcher(Object manager, EventDeliveryService svc) {
@@ -174,6 +178,7 @@
@Before
public void setUp() {
aaaManager = new AaaManagerWithoutRadiusServer();
+ aaaManager.radiusOperationalStatusService = new RadiusOperationalStatusManager();
aaaManager.netCfgService = new TestNetworkConfigRegistry();
aaaManager.coreService = new CoreServiceAdapter();
aaaManager.packetService = new MockPacketService();
@@ -278,7 +283,7 @@
RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
- assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 3));
+ assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 9));
assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
// State machine should be in pending state
diff --git a/app/src/test/java/org/opencord/aaa/impl/AaaTestBase.java b/app/src/test/java/org/opencord/aaa/impl/AaaTestBase.java
index 4912e4e..8f48ce4 100644
--- a/app/src/test/java/org/opencord/aaa/impl/AaaTestBase.java
+++ b/app/src/test/java/org/opencord/aaa/impl/AaaTestBase.java
@@ -411,7 +411,7 @@
eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
eth.setVlanID((short) 2);
- EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null);
+ EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 3, EAPOL.EAPOL_START, null);
// eapol header
EAPOL eapol = new EAPOL();