Client steering notes, docs, fixes (#128)

Signed-off-by: Jeffrey Han <39203126+elludraon@users.noreply.github.com>
This commit is contained in:
Jeffrey Han
2022-11-14 12:55:43 -08:00
committed by GitHub
parent ea3a13e98c
commit ac5a1c8887
8 changed files with 445 additions and 26 deletions

View File

@@ -69,6 +69,24 @@ public abstract class IEUtils {
return element.getAsInt();
}
/**
* Try to get a json object as a int
*
* @param contents the JSON object to try to parse
* @param fieldName the field name
* @return the field as a int (0 if key not present)
*/
public static Integer parseIntField(
JsonObject contents,
String fieldName
) {
JsonElement element = contents.get(fieldName);
if (element == null) {
return 0;
}
return element.getAsInt();
}
/**
* Try to get a json object as a string
*
@@ -86,4 +104,22 @@ public abstract class IEUtils {
}
return element.getAsString();
}
/**
* Try to get a json object as a boolean when represented as a number (0, 1)
*
* @param contents the JSON object to try to parse
* @param fieldName the field name
* @return the field as a boolean (false if key not present)
*/
public static boolean parseBooleanNumberField(
JsonObject contents,
String fieldName
) {
JsonElement element = contents.get(fieldName);
if (element == null) {
return false;
}
return element.getAsInt() > 0;
}
}

View File

@@ -13,38 +13,42 @@ import java.util.Objects;
import com.facebook.openwifi.cloudsdk.ies.Country;
import com.facebook.openwifi.cloudsdk.ies.LocalPowerConstraint;
import com.facebook.openwifi.cloudsdk.ies.QbssLoad;
import com.facebook.openwifi.cloudsdk.ies.RMEnabledCapabilities;
import com.facebook.openwifi.cloudsdk.ies.TxPwrInfo;
/** Wrapper class containing information elements */
public final class InformationElements {
public Country country;
public QbssLoad qbssLoad;
public LocalPowerConstraint localPowerConstraint;
public TxPwrInfo txPwrInfo;
public RMEnabledCapabilities rmEnabledCapabilities;
@Override
public int hashCode() {
return Objects.hash(country, localPowerConstraint, qbssLoad, txPwrInfo);
return Objects.hash(
country,
localPowerConstraint,
qbssLoad,
rmEnabledCapabilities,
txPwrInfo
);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
if (this == obj)
return true;
}
if (obj == null) {
if (obj == null)
return false;
}
if (getClass() != obj.getClass()) {
if (getClass() != obj.getClass())
return false;
}
InformationElements other = (InformationElements) obj;
return Objects.equals(country, other.country) && Objects.equals(
localPowerConstraint,
other.localPowerConstraint
) && Objects.equals(qbssLoad, other.qbssLoad) &&
return Objects.equals(country, other.country) &&
Objects.equals(localPowerConstraint, other.localPowerConstraint) &&
Objects.equals(qbssLoad, other.qbssLoad) &&
Objects
.equals(rmEnabledCapabilities, other.rmEnabledCapabilities) &&
Objects.equals(txPwrInfo, other.txPwrInfo);
}
}

View File

@@ -28,6 +28,7 @@ import org.slf4j.LoggerFactory;
import com.facebook.openwifi.cloudsdk.ies.Country;
import com.facebook.openwifi.cloudsdk.ies.LocalPowerConstraint;
import com.facebook.openwifi.cloudsdk.ies.QbssLoad;
import com.facebook.openwifi.cloudsdk.ies.RMEnabledCapabilities;
import com.facebook.openwifi.cloudsdk.ies.TxPwrInfo;
import com.facebook.openwifi.cloudsdk.models.ap.Capabilities;
import com.facebook.openwifi.cloudsdk.models.ap.State;
@@ -172,6 +173,10 @@ public class UCentralUtils {
case TxPwrInfo.TYPE:
ieContainer.txPwrInfo = TxPwrInfo.parse(contents);
break;
case RMEnabledCapabilities.TYPE:
ieContainer.rmEnabledCapabilities =
RMEnabledCapabilities.parse(contents);
break;
}
} catch (Exception e) {
logger.error(String.format("Skipping invalid IE %s", ie), e);

View File

@@ -0,0 +1,274 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.openwifi.cloudsdk.ies;
import java.util.Objects;
import com.facebook.openwifi.cloudsdk.IEUtils;
import com.google.gson.JsonObject;
/**
* This information element (IE) appears in wifiscan entries. It's called "RM
* Enabled Capabilities" in 802.11 specs (section 9.4.2.45). Refer to the
* specification for more details. Language in javadocs is taken from the
* specification.
*/
public class RMEnabledCapabilities {
/** Defined in 802.11 table 9-92 */
public static final int TYPE = 70;
// Bit fields
// @formatter:off
public final boolean linkMeasurementCapabilityEnabled;
public final boolean neighborReportCapabilityEnabled;
public final boolean parallelMeasurementsCapabilityEnabled;
public final boolean repeatedMeasurementsCapabilityEnabled;
public final boolean beaconPassiveMeasurementCapabilityEnabled;
public final boolean beaconActiveMeasurementCapabilityEnabled;
public final boolean beaconTableMeasurementCapabilityEnabled;
public final boolean beaconMeasurementReportingConditionsCapabilityEnabled;
public final boolean frameMeasurementCapabilityEnabled;
public final boolean channelLoadMeasurementCapabilityEnabled;
public final boolean noiseHistogramMeasurementCapabilityEnabled;
public final boolean statisticsMeasurementCapabilityEnabled;
public final boolean lciMeasurementCapabilityEnabled;
public final boolean lciAzimuthCapabilityEnabled;
public final boolean transmitStreamCategoryMeasurementCapabilityEnabled;
public final boolean triggeredTransmitStreamCategoryMeasurementCapabilityEnabled;
public final boolean apChannelReportCapabilityEnabled;
public final boolean rmMibCapabilityEnabled;
public final int operatingChannelMaxMeasurementDuration;
public final int nonoperatingChannelMaxMeasurementDuration;
public final int measurementPilotCapability;
public final boolean measurementPilotTransmissionInformationCapabilityEnabled;
public final boolean neighborReportTsfOffsetCapabilityEnabled;
public final boolean rcpiMeasurementCapabilityEnabled;
public final boolean rsniMeasurementCapabilityEnabled;
public final boolean bssAverageAccessDelayCapabilityEnabled;
public final boolean bssAvailableAdmissionCapacityCapabilityEnabled;
public final boolean antennaCapabilityEnabled;
public final boolean ftmRangeReportCapabilityEnabled;
public final boolean civicLocationMeasurementCapabilityEnabled;
// @formatter:on
/** Constructor */
public RMEnabledCapabilities(
boolean linkMeasurementCapabilityEnabled,
boolean neighborReportCapabilityEnabled,
boolean parallelMeasurementsCapabilityEnabled,
boolean repeatedMeasurementsCapabilityEnabled,
boolean beaconPassiveMeasurementCapabilityEnabled,
boolean beaconActiveMeasurementCapabilityEnabled,
boolean beaconTableMeasurementCapabilityEnabled,
boolean beaconMeasurementReportingConditionsCapabilityEnabled,
boolean frameMeasurementCapabilityEnabled,
boolean channelLoadMeasurementCapabilityEnabled,
boolean noiseHistogramMeasurementCapabilityEnabled,
boolean statisticsMeasurementCapabilityEnabled,
boolean lciMeasurementCapabilityEnabled,
boolean lciAzimuthCapabilityEnabled,
boolean transmitStreamCategoryMeasurementCapabilityEnabled,
boolean triggeredTransmitStreamCategoryMeasurementCapabilityEnabled,
boolean apChannelReportCapabilityEnabled,
boolean rmMibCapabilityEnabled,
int operatingChannelMaxMeasurementDuration,
int nonoperatingChannelMaxMeasurementDuration,
int measurementPilotCapability,
boolean measurementPilotTransmissionInformationCapabilityEnabled,
boolean neighborReportTsfOffsetCapabilityEnabled,
boolean rcpiMeasurementCapabilityEnabled,
boolean rsniMeasurementCapabilityEnabled,
boolean bssAverageAccessDelayCapabilityEnabled,
boolean bssAvailableAdmissionCapacityCapabilityEnabled,
boolean antennaCapabilityEnabled,
boolean ftmRangeReportCapabilityEnabled,
boolean civicLocationMeasurementCapabilityEnabled
) {
// @formatter:off
this.linkMeasurementCapabilityEnabled = linkMeasurementCapabilityEnabled;
this.neighborReportCapabilityEnabled = neighborReportCapabilityEnabled;
this.parallelMeasurementsCapabilityEnabled = parallelMeasurementsCapabilityEnabled;
this.repeatedMeasurementsCapabilityEnabled = repeatedMeasurementsCapabilityEnabled;
this.beaconPassiveMeasurementCapabilityEnabled = beaconPassiveMeasurementCapabilityEnabled;
this.beaconActiveMeasurementCapabilityEnabled = beaconActiveMeasurementCapabilityEnabled;
this.beaconTableMeasurementCapabilityEnabled = beaconTableMeasurementCapabilityEnabled;
this.beaconMeasurementReportingConditionsCapabilityEnabled = beaconMeasurementReportingConditionsCapabilityEnabled;
this.frameMeasurementCapabilityEnabled = frameMeasurementCapabilityEnabled;
this.channelLoadMeasurementCapabilityEnabled = channelLoadMeasurementCapabilityEnabled;
this.noiseHistogramMeasurementCapabilityEnabled = noiseHistogramMeasurementCapabilityEnabled;
this.statisticsMeasurementCapabilityEnabled = statisticsMeasurementCapabilityEnabled;
this.lciMeasurementCapabilityEnabled = lciMeasurementCapabilityEnabled;
this.lciAzimuthCapabilityEnabled = lciAzimuthCapabilityEnabled;
this.transmitStreamCategoryMeasurementCapabilityEnabled = transmitStreamCategoryMeasurementCapabilityEnabled;
this.triggeredTransmitStreamCategoryMeasurementCapabilityEnabled = triggeredTransmitStreamCategoryMeasurementCapabilityEnabled;
this.apChannelReportCapabilityEnabled = apChannelReportCapabilityEnabled;
this.rmMibCapabilityEnabled = rmMibCapabilityEnabled;
this.operatingChannelMaxMeasurementDuration = operatingChannelMaxMeasurementDuration;
this.nonoperatingChannelMaxMeasurementDuration = nonoperatingChannelMaxMeasurementDuration;
this.measurementPilotCapability = measurementPilotCapability;
this.measurementPilotTransmissionInformationCapabilityEnabled = measurementPilotTransmissionInformationCapabilityEnabled;
this.neighborReportTsfOffsetCapabilityEnabled = neighborReportTsfOffsetCapabilityEnabled;
this.rcpiMeasurementCapabilityEnabled = rcpiMeasurementCapabilityEnabled;
this.rsniMeasurementCapabilityEnabled = rsniMeasurementCapabilityEnabled;
this.bssAverageAccessDelayCapabilityEnabled = bssAverageAccessDelayCapabilityEnabled;
this.bssAvailableAdmissionCapacityCapabilityEnabled = bssAvailableAdmissionCapacityCapabilityEnabled;
this.antennaCapabilityEnabled = antennaCapabilityEnabled;
this.ftmRangeReportCapabilityEnabled = ftmRangeReportCapabilityEnabled;
this.civicLocationMeasurementCapabilityEnabled = civicLocationMeasurementCapabilityEnabled;
// @formatter:on
}
/** Parse RMEnabledCapabilities IE from appropriate Json object. */
public static RMEnabledCapabilities parse(JsonObject contents) {
JsonObject o = contents.get("RM Capabilities").getAsJsonObject();
// @formatter:off
return new RMEnabledCapabilities(
/* bits 0-17 */
IEUtils.parseBooleanNumberField(o, "Link Measurement"),
IEUtils.parseBooleanNumberField(o, "Neighbor Report"),
IEUtils.parseBooleanNumberField(o, "Parallel Measurements"),
IEUtils.parseBooleanNumberField(o, "Repeated Measurements"),
IEUtils.parseBooleanNumberField(o, "Beacon Passive Measurement"),
IEUtils.parseBooleanNumberField(o, "Beacon Active Measurement"),
IEUtils.parseBooleanNumberField(o, "Beacon Table Measurement"),
IEUtils.parseBooleanNumberField(o, "Beacon Measurement Reporting Conditions"),
IEUtils.parseBooleanNumberField(o, "Frame Measurement"),
IEUtils.parseBooleanNumberField(o, "Channel Load Measurement"),
IEUtils.parseBooleanNumberField(o, "Noise Histogram Measurement"),
IEUtils.parseBooleanNumberField(o, "Statistics Measurement"),
IEUtils.parseBooleanNumberField(o, "LCI Measurement"),
IEUtils.parseBooleanNumberField(o, "LCI Azimuth capability"),
IEUtils.parseBooleanNumberField(o, "Transmit Stream/Category Measurement"),
IEUtils.parseBooleanNumberField(o, "Triggered Transmit Stream/Category Measurement"),
IEUtils.parseBooleanNumberField(o, "AP Channel Report capability"),
IEUtils.parseBooleanNumberField(o, "RM MIB capability"),
/* bits 18-20 */
IEUtils.parseIntField(o, "Operating Channel Max Measurement Duration"),
/* bits 21-23 */
IEUtils.parseIntField(o, "Nonoperating Channel Max Measurement Duration"),
/* bits 24-26 */
IEUtils.parseIntField(o, "Measurement Pilotcapability"),
/* bits 27-35 */
false /* TODO "Measurement Pilot Transmission Information Capability" */,
IEUtils.parseBooleanNumberField(o, "Neighbor Report TSF Offset"),
IEUtils.parseBooleanNumberField(o, "RCPI Measurement capability"),
IEUtils.parseBooleanNumberField(o, "RSNI Measurement capability"),
IEUtils.parseBooleanNumberField(o, "BSS Average Access Delay capability"),
IEUtils.parseBooleanNumberField(o, "BSS Available Admission Capacity capability"),
IEUtils.parseBooleanNumberField(o, "Antenna capability"),
false /* TODO "FTM Range Report Capability" */,
false /* TODO "Civic Location Measurement Capability" */
/* bits 36-39 reserved */
);
// @formatter:on
}
@Override
public int hashCode() {
return Objects.hash(
antennaCapabilityEnabled,
apChannelReportCapabilityEnabled,
beaconActiveMeasurementCapabilityEnabled,
beaconMeasurementReportingConditionsCapabilityEnabled,
beaconPassiveMeasurementCapabilityEnabled,
beaconTableMeasurementCapabilityEnabled,
bssAvailableAdmissionCapacityCapabilityEnabled,
bssAverageAccessDelayCapabilityEnabled,
channelLoadMeasurementCapabilityEnabled,
civicLocationMeasurementCapabilityEnabled,
frameMeasurementCapabilityEnabled,
ftmRangeReportCapabilityEnabled,
lciAzimuthCapabilityEnabled,
lciMeasurementCapabilityEnabled,
linkMeasurementCapabilityEnabled,
measurementPilotCapability,
measurementPilotTransmissionInformationCapabilityEnabled,
neighborReportCapabilityEnabled,
neighborReportTsfOffsetCapabilityEnabled,
noiseHistogramMeasurementCapabilityEnabled,
nonoperatingChannelMaxMeasurementDuration,
operatingChannelMaxMeasurementDuration,
parallelMeasurementsCapabilityEnabled,
rcpiMeasurementCapabilityEnabled,
repeatedMeasurementsCapabilityEnabled,
rmMibCapabilityEnabled,
rsniMeasurementCapabilityEnabled,
statisticsMeasurementCapabilityEnabled,
transmitStreamCategoryMeasurementCapabilityEnabled,
triggeredTransmitStreamCategoryMeasurementCapabilityEnabled
);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
RMEnabledCapabilities other = (RMEnabledCapabilities) obj;
return antennaCapabilityEnabled == other.antennaCapabilityEnabled &&
apChannelReportCapabilityEnabled ==
other.apChannelReportCapabilityEnabled &&
beaconActiveMeasurementCapabilityEnabled ==
other.beaconActiveMeasurementCapabilityEnabled &&
beaconMeasurementReportingConditionsCapabilityEnabled ==
other.beaconMeasurementReportingConditionsCapabilityEnabled &&
beaconPassiveMeasurementCapabilityEnabled ==
other.beaconPassiveMeasurementCapabilityEnabled &&
beaconTableMeasurementCapabilityEnabled ==
other.beaconTableMeasurementCapabilityEnabled &&
bssAvailableAdmissionCapacityCapabilityEnabled ==
other.bssAvailableAdmissionCapacityCapabilityEnabled &&
bssAverageAccessDelayCapabilityEnabled ==
other.bssAverageAccessDelayCapabilityEnabled &&
channelLoadMeasurementCapabilityEnabled ==
other.channelLoadMeasurementCapabilityEnabled &&
civicLocationMeasurementCapabilityEnabled ==
other.civicLocationMeasurementCapabilityEnabled &&
frameMeasurementCapabilityEnabled ==
other.frameMeasurementCapabilityEnabled &&
ftmRangeReportCapabilityEnabled ==
other.ftmRangeReportCapabilityEnabled &&
lciAzimuthCapabilityEnabled == other.lciAzimuthCapabilityEnabled &&
lciMeasurementCapabilityEnabled ==
other.lciMeasurementCapabilityEnabled &&
linkMeasurementCapabilityEnabled ==
other.linkMeasurementCapabilityEnabled &&
measurementPilotCapability == other.measurementPilotCapability &&
measurementPilotTransmissionInformationCapabilityEnabled ==
other.measurementPilotTransmissionInformationCapabilityEnabled &&
neighborReportCapabilityEnabled ==
other.neighborReportCapabilityEnabled &&
neighborReportTsfOffsetCapabilityEnabled ==
other.neighborReportTsfOffsetCapabilityEnabled &&
noiseHistogramMeasurementCapabilityEnabled ==
other.noiseHistogramMeasurementCapabilityEnabled &&
nonoperatingChannelMaxMeasurementDuration ==
other.nonoperatingChannelMaxMeasurementDuration &&
operatingChannelMaxMeasurementDuration ==
other.operatingChannelMaxMeasurementDuration &&
parallelMeasurementsCapabilityEnabled ==
other.parallelMeasurementsCapabilityEnabled &&
rcpiMeasurementCapabilityEnabled ==
other.rcpiMeasurementCapabilityEnabled &&
repeatedMeasurementsCapabilityEnabled ==
other.repeatedMeasurementsCapabilityEnabled &&
rmMibCapabilityEnabled == other.rmMibCapabilityEnabled &&
rsniMeasurementCapabilityEnabled ==
other.rsniMeasurementCapabilityEnabled &&
statisticsMeasurementCapabilityEnabled ==
other.statisticsMeasurementCapabilityEnabled &&
transmitStreamCategoryMeasurementCapabilityEnabled ==
other.transmitStreamCategoryMeasurementCapabilityEnabled &&
triggeredTransmitStreamCategoryMeasurementCapabilityEnabled ==
other.triggeredTransmitStreamCategoryMeasurementCapabilityEnabled;
}
}