mirror of
https://github.com/Telecominfraproject/wlan-cloud-rrm.git
synced 2025-10-30 18:17:58 +00:00
Use ht operation element class decoder (#41)
This commit is contained in:
@@ -10,7 +10,6 @@ package com.facebook.openwifirrm.optimizers.channel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -26,6 +25,8 @@ import com.facebook.openwifirrm.modules.Modeler.DataModel;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralConstants;
|
||||
import com.facebook.openwifirrm.ucentral.UCentralUtils.WifiScanEntry;
|
||||
import com.facebook.openwifirrm.ucentral.models.State;
|
||||
import com.facebook.openwifirrm.ucentral.operationelement.HTOperationElement;
|
||||
import com.facebook.openwifirrm.ucentral.operationelement.VHTOperationElement;
|
||||
|
||||
/**
|
||||
* Channel optimizer base class.
|
||||
@@ -179,15 +180,6 @@ public abstract class ChannelOptimizer {
|
||||
}
|
||||
}
|
||||
|
||||
/** Convert the input string into a byte array. */
|
||||
private static byte[] decodeBase64(String s) {
|
||||
try {
|
||||
return Base64.getDecoder().decode(s);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the channel width based on the HT operation and VHT operation in wifi scan.
|
||||
* @param channel the current channel (from the scan result)
|
||||
@@ -209,76 +201,33 @@ public abstract class ChannelOptimizer {
|
||||
return MIN_CHANNEL_WIDTH;
|
||||
}
|
||||
|
||||
// Decode HT operation information element
|
||||
byte[] htOperDecode = decodeBase64(htOper);
|
||||
if (htOperDecode == null) {
|
||||
return MIN_CHANNEL_WIDTH;
|
||||
}
|
||||
// The second byte of HT operation contains the channel width information.
|
||||
// The third bit (so we & 4 = 100 below) in the second byte is STA channel width.
|
||||
// 0 for a 20 MHz channel width, 1 for any other channel widths.
|
||||
int htChannelWidth = htOperDecode[1] & 4;
|
||||
|
||||
HTOperationElement htOperObj = new HTOperationElement(htOper);
|
||||
if (vhtOper == null) {
|
||||
// HT mode, it only supports 20/40 MHz
|
||||
// Therefore, htChannelWidth > 0 means 40 MHz, htChannelWidth = 0 means 20 MHz.
|
||||
if (htChannelWidth == 0) {
|
||||
return 20;
|
||||
// HT mode only supports 20/40 MHz
|
||||
return htOperObj.staChannelWidth ? 40 : 20;
|
||||
} else {
|
||||
return 40;
|
||||
}
|
||||
} else {
|
||||
// VHT/HE mode, it supports 20/40/160/8080 MHz
|
||||
|
||||
// Decode VHT operation information element
|
||||
byte[] vhtOperDecode = decodeBase64(vhtOper);
|
||||
if (vhtOperDecode == null) {
|
||||
return MIN_CHANNEL_WIDTH;
|
||||
}
|
||||
// The first byte of VHT operation is channel width, which takes values 0-3.
|
||||
// 0 for 20 MHz or 40 MHz
|
||||
// 1 for 80 MHz, 160 MHz , or 80+80 MHz BSS bandwidth
|
||||
// 2 and 3 are deprecated
|
||||
int vhtChannelWidth = vhtOperDecode[0] & 255;
|
||||
// The second byte of VHT operation is channel center frequency segment 0.
|
||||
// For 80 MHz BSS bandwidth, indicates the channel center frequency index
|
||||
// for the 80 MHz channel on which the VHT BSS operates.
|
||||
// For 160 MHz or 80+80 MHz BSS bandwidth, it contains the channel center
|
||||
// frequency index for the first 80 MHz channel.
|
||||
int channelOffset1 = vhtOperDecode[1] & 255;
|
||||
// The third byte of VHT operation is channel center frequency segment 1.
|
||||
// For a 20, 40, or 80 MHz BSS bandwidth, this subfield is set to 0.
|
||||
// For 160 MHz or 80+80 MHz BSS bandwidth, it contains the channel center
|
||||
// frequency index for the second 80 MHz channel.
|
||||
int channelOffset2 = vhtOperDecode[2] & 255;
|
||||
|
||||
if (htChannelWidth == 0 && vhtChannelWidth == 0) {
|
||||
// VHT/HE mode supports 20/40/160/80+80 MHz
|
||||
VHTOperationElement vhtOperObj = new VHTOperationElement(vhtOper);
|
||||
if (!htOperObj.staChannelWidth && vhtOperObj.channelWidth == 0) {
|
||||
return 20;
|
||||
} else if (htChannelWidth > 0 && vhtChannelWidth == 0) {
|
||||
} else if (htOperObj.staChannelWidth && vhtOperObj.channelWidth == 0) {
|
||||
return 40;
|
||||
} else if (
|
||||
htChannelWidth > 0 &&
|
||||
vhtChannelWidth == 1 &&
|
||||
channelOffset2 == 0
|
||||
) {
|
||||
} else if (htOperObj.staChannelWidth && vhtOperObj.channelWidth == 1 && vhtOperObj.channel2 == 0) {
|
||||
return 80;
|
||||
} else if (
|
||||
htChannelWidth > 0 &&
|
||||
vhtChannelWidth == 1 &&
|
||||
channelOffset2 != 0
|
||||
htOperObj.staChannelWidth
|
||||
&& vhtOperObj.channelWidth == 1
|
||||
&& vhtOperObj.channel2 != 0
|
||||
) {
|
||||
// if it is 160 MHz, it use two consecutive 80 MHz bands
|
||||
// the difference of 8 means it is consecutive
|
||||
if (Math.abs(channelOffset1 - channelOffset2) == 8) {
|
||||
return 160;
|
||||
} else {
|
||||
return 8080;
|
||||
}
|
||||
int channelDiff = Math.abs(vhtOperObj.channel1 - vhtOperObj.channel2);
|
||||
// the "8080" below does not mean 8080 MHz wide, it refers to 80+80 MHz channel
|
||||
return channelDiff == 8 ? 160 : 8080;
|
||||
} else {
|
||||
return MIN_CHANNEL_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,7 +20,7 @@ import org.apache.commons.codec.binary.Base64;
|
||||
public class HTOperationElement {
|
||||
|
||||
/** Channel number of the primary channel. */
|
||||
private final byte primaryChannel;
|
||||
public final byte primaryChannel;
|
||||
/**
|
||||
* Indicates the offset of the secondary channel relative to the primary
|
||||
* channel. A 1 indicates that the secondary channel is above the primary
|
||||
@@ -28,48 +28,48 @@ public class HTOperationElement {
|
||||
* channel. A 0 indicates that there is no secondary channel present. The value
|
||||
* 2 is reserved.
|
||||
*/
|
||||
private final byte secondaryChannelOffset;
|
||||
public final byte secondaryChannelOffset;
|
||||
/**
|
||||
* Defines the channel widths that can be used to transmit to the STA. With
|
||||
* exceptions, false allows a 20 MHz channel width. True allows use of any
|
||||
* channel width in the supported channel width set. See 802.11 for exceptions.
|
||||
*/
|
||||
private final boolean staChannelWidth;
|
||||
public final boolean staChannelWidth;
|
||||
/** True if RIFS is permitted; false otherwise. */
|
||||
private final boolean rifsMode;
|
||||
public final boolean rifsMode;
|
||||
/**
|
||||
* A 0 indicates no protection mode. A 1 indicates nonmember protection mode. A
|
||||
* 2 indicates 20 MHz protection mode. A 3 indicates non-HT mixed mode.
|
||||
*/
|
||||
private final byte htProtection;
|
||||
public final byte htProtection;
|
||||
/**
|
||||
* False if all HT STAs that are associated are HT-greenfield capable or all HT
|
||||
* peer mesh STAs are HT-greenfield capable; true otherwise.
|
||||
*/
|
||||
private final boolean nongreenfieldHtStasPresent;
|
||||
public final boolean nongreenfieldHtStasPresent;
|
||||
/**
|
||||
* Indicates if the use of protection for non-HT STAs by overlapping BSSs is
|
||||
* determined to be desirable. See 802.11 for details.
|
||||
*/
|
||||
private final boolean obssNonHtStasPresent;
|
||||
public final boolean obssNonHtStasPresent;
|
||||
/**
|
||||
* Defines the channel center frequency for a 160 or 80+80 MHz BSS bandwidth
|
||||
* with NSS support less than Max VHT NSS. This is 0 for non-VHT STAs. See
|
||||
* 802.11 for details.
|
||||
*/
|
||||
private final byte channelCenterFrequencySegment2;
|
||||
public final byte channelCenterFrequencySegment2;
|
||||
/** False if no STBC beacon is transmitted; true otherwise. */
|
||||
private final boolean dualBeacon;
|
||||
public final boolean dualBeacon;
|
||||
/** False if dual CTS protection is not required; true otherwise. */
|
||||
private final boolean dualCtsProtection;
|
||||
public final boolean dualCtsProtection;
|
||||
/** False in a primary beacon. True in an STBC beacon. */
|
||||
private final boolean stbcBeacon;
|
||||
public final boolean stbcBeacon;
|
||||
/**
|
||||
* Indicates the HT-MCS values that are supported by all HT STAs in the BSS. A
|
||||
* bitmap where a bit is set to 1 to indicate support for that MCS and 0
|
||||
* otherwise, where bit 0 corresponds to MCS 0.
|
||||
*/
|
||||
private final byte[] basicHtMcsSet;
|
||||
public final byte[] basicHtMcsSet;
|
||||
|
||||
/**
|
||||
* Constructs an {@code HTOperationElement} using the given field values. See
|
||||
|
||||
@@ -19,8 +19,11 @@ import org.apache.commons.codec.binary.Base64;
|
||||
*/
|
||||
public class VHTOperationElement {
|
||||
|
||||
/** False if the channel width is 20 MHz or 40 MHz; true otherwise. */
|
||||
private final boolean channelWidthIndicator;
|
||||
/**
|
||||
* This field is 0 if the channel width is 20 MHz or 40 MHz, and 1 otherwise.
|
||||
* Values of 2 and 3 are deprecated.
|
||||
*/
|
||||
public final byte channelWidth;
|
||||
/**
|
||||
* If the channel is 20 MHz, 40 MHz, or 80 MHz wide, this parameter is the
|
||||
* channel number. E.g., the channel centered at 5180 MHz is channel 36. For a
|
||||
@@ -28,14 +31,14 @@ public class VHTOperationElement {
|
||||
* channel that contains the primary channel. For a 80+80 MHz wide channel, this
|
||||
* parameter is the channel number of the primary channel.
|
||||
*/
|
||||
private final byte channel1;
|
||||
public final byte channel1;
|
||||
/**
|
||||
* This should be zero unless the channel is 160MHz or 80+80 MHz wide. If the
|
||||
* channel is 160 MHz wide, this parameter is the channel number of the 160 MHz
|
||||
* wide channel. If the channel is 80+80 MHz wide, this parameter is the channel
|
||||
* index of the secondary 80 MHz wide channel.
|
||||
*/
|
||||
private final byte channel2;
|
||||
public final byte channel2;
|
||||
/**
|
||||
* An 8-element array where each element is between 0 and 4 inclusive. MCS means
|
||||
* Modulation and Coding Scheme. NSS means Number of Spatial Streams. There can
|
||||
@@ -46,7 +49,7 @@ public class VHTOperationElement {
|
||||
* VHT-MCS is supported for that NSS. For the specifics of what each VHT-MCS is,
|
||||
* see IEEE 802.11-2020, Table "21-29" through Table "21-60".
|
||||
*/
|
||||
private final byte[] vhtMcsForNss;
|
||||
public final byte[] vhtMcsForNss;
|
||||
|
||||
/**
|
||||
* Constructs a {@code VHTOperationElement} by decoding {@code vhtOper}.
|
||||
@@ -56,7 +59,7 @@ public class VHTOperationElement {
|
||||
*/
|
||||
public VHTOperationElement(String vhtOper) {
|
||||
byte[] bytes = Base64.decodeBase64(vhtOper);
|
||||
this.channelWidthIndicator = bytes[0] == 1;
|
||||
this.channelWidth = bytes[0];
|
||||
this.channel1 = bytes[1];
|
||||
this.channel2 = bytes[2];
|
||||
byte[] vhtMcsForNss = new byte[8];
|
||||
@@ -78,13 +81,13 @@ public class VHTOperationElement {
|
||||
* For details about the parameters, see the javadocs for the corresponding
|
||||
* member variables.
|
||||
*/
|
||||
public VHTOperationElement(boolean channelWidthIndicator, byte channel1, byte channel2, byte[] vhtMcsForNss) {
|
||||
public VHTOperationElement(byte channelWidth, byte channel1, byte channel2, byte[] vhtMcsForNss) {
|
||||
/*
|
||||
* XXX some combinations of channelWidth, channel, channel2, and vhtMcsAtNss are
|
||||
* invalid, but this is not checked here. If fidelity to 802.11 is required, the
|
||||
* caller of this method must make sure to pass in valid parameters.
|
||||
*/
|
||||
this.channelWidthIndicator = channelWidthIndicator;
|
||||
this.channelWidth = channelWidth;
|
||||
this.channel1 = channel1;
|
||||
this.channel2 = channel2;
|
||||
this.vhtMcsForNss = vhtMcsForNss;
|
||||
@@ -101,7 +104,7 @@ public class VHTOperationElement {
|
||||
public boolean matchesForAggregation(VHTOperationElement other) {
|
||||
// check everything except vhtMcsForNss
|
||||
return other != null && channel1 == other.channel1 && channel2 == other.channel2
|
||||
&& channelWidthIndicator == other.channelWidthIndicator;
|
||||
&& channelWidth == other.channelWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +136,7 @@ public class VHTOperationElement {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(vhtMcsForNss);
|
||||
result = prime * result + Objects.hash(channel1, channel2, channelWidthIndicator);
|
||||
result = prime * result + Objects.hash(channel1, channel2, channelWidth);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -150,7 +153,7 @@ public class VHTOperationElement {
|
||||
}
|
||||
VHTOperationElement other = (VHTOperationElement) obj;
|
||||
return channel1 == other.channel1 && channel2 == other.channel2
|
||||
&& channelWidthIndicator == other.channelWidthIndicator
|
||||
&& channelWidth == other.channelWidth
|
||||
&& Arrays.equals(vhtMcsForNss, other.vhtMcsForNss);
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ public class VHTOperationElementTest {
|
||||
void testGetVhtOper() {
|
||||
String vhtOper = "ACQAAAA=";
|
||||
VHTOperationElement vhtOperObj = new VHTOperationElement(vhtOper);
|
||||
boolean expectedChannelWidthIndicator = false; // 20 MHz channel width
|
||||
byte expectedChannelWidthIndicator = 0; // 20 MHz channel width
|
||||
byte expectedChannel1 = 36;
|
||||
byte expectedChannel2 = 0;
|
||||
byte[] expectedVhtMcsForNss = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
@@ -27,7 +27,7 @@ public class VHTOperationElementTest {
|
||||
|
||||
vhtOper = "AToAUAE=";
|
||||
vhtOperObj = new VHTOperationElement(vhtOper);
|
||||
expectedChannelWidthIndicator = true; // 80 MHz channel width
|
||||
expectedChannelWidthIndicator = 1; // 80 MHz channel width
|
||||
expectedChannel1 = 58;
|
||||
// same channel2
|
||||
expectedVhtMcsForNss = new byte[] { 1, 1, 0, 0, 0, 0, 0, 1 };
|
||||
|
||||
Reference in New Issue
Block a user