Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
//


#include <algorithm>

#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h"
#include "inet/linklayer/ieee80211/mgmt/Ieee80211HtMgmtElements.h"

Expand Down Expand Up @@ -495,14 +497,20 @@ void Ieee80211MgmtSta::sendScanConfirm()
{
EV << "Scanning complete, found " << apList.size() << " APs, sending confirmation to agent\n";

// copy apList contents into a ScanConfirm primitive and send it back
int n = apList.size();
// copy matching apList contents into a ScanConfirm primitive and send it back
// IEEE Std 802.11-2024, 6.5.3.2.2: BSSID and SSID identify specific or wildcard scan targets.
auto matchesScanRequest = [this](const ApInfo& ap) {
return (scanning.bssid == MacAddress::BROADCAST_ADDRESS || ap.address == scanning.bssid)
&& (scanning.ssid.empty() || ap.ssid == scanning.ssid);
};
int n = std::count_if(apList.begin(), apList.end(), matchesScanRequest);
Ieee80211Prim_ScanConfirm *confirm = new Ieee80211Prim_ScanConfirm();
confirm->setBssListArraySize(n);
auto it = apList.begin();
// TODO filter for req'd bssid and ssid
for (int i = 0; i < n; i++, it++) {
for (int i = 0; it != apList.end(); it++) {
ApInfo *ap = &(*it);
if (!matchesScanRequest(*ap))
continue;
Ieee80211Prim_BssDescription& bss = confirm->getBssListForUpdate(i);
bss.setChannelNumber(ap->channel);
bss.setBSSID(ap->address);
Expand All @@ -512,6 +520,7 @@ void Ieee80211MgmtSta::sendScanConfirm()
bss.setExtendedSupportedRates(ap->extendedSupportedRates);
bss.setBeaconInterval(ap->beaconInterval);
bss.setRxPower(ap->rxPower);
i++;
}
sendConfirm(confirm, PRC_SUCCESS);
}
Expand Down
77 changes: 77 additions & 0 deletions tests/unit/Ieee80211ScanConfirmFilters_1.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
%description:
Exercise the production scan-confirm construction with discovered BSSs that
share an SSID, unrelated beacons, exact filters and wildcards. Filtering must
not destroy the discovery cache used by subsequent management operations.

%includes:
#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h"

using namespace inet;
using namespace inet::ieee80211;

%global:
class ScanConfirmStation : public Ieee80211MgmtSta
{
public:
std::vector<MacAddress> results;
int confirmations = 0;

void addBss(const char *address, const char *ssid)
{
apList.emplace_back();
auto& ap = apList.back();
ap.address = MacAddress(address);
ap.ssid = ssid;
ap.channel = 1;
ap.supportedRates.numRates = 0;
ap.extendedSupportedRates.numRates = 0;
}

void confirm(const MacAddress& bssid, const char *ssid, bool active)
{
scanning = ScanningInfo();
scanning.bssid = bssid;
scanning.ssid = ssid;
scanning.activeScan = active;
results.clear();
sendScanConfirm();
ASSERT(apList.size() == 3);
}

protected:
virtual void sendConfirm(Ieee80211PrimConfirm *message, Ieee80211PrimResultCode code) override
{
ASSERT(code == PRC_SUCCESS);
auto confirm = check_and_cast<Ieee80211Prim_ScanConfirm *>(message);
confirmations++;
for (size_t i = 0; i < confirm->getBssListArraySize(); i++)
results.push_back(confirm->getBssList(i).getBSSID());
delete confirm;
}
};

%activity:
ScanConfirmStation station;
const MacAddress a("02:00:00:00:00:01"), b("02:00:00:00:00:02"), c("02:00:00:00:00:03");
station.addBss("02:00:00:00:00:01", "requested");
station.addBss("02:00:00:00:00:02", "requested");
station.addBss("02:00:00:00:00:03", "unrelated");
for (bool active : {false, true}) {
station.confirm(MacAddress::BROADCAST_ADDRESS, "", active);
ASSERT(station.results == std::vector<MacAddress>({a, b, c}));
station.confirm(MacAddress::BROADCAST_ADDRESS, "requested", active);
ASSERT(station.results == std::vector<MacAddress>({a, b}));
station.confirm(b, "", active);
ASSERT(station.results == std::vector<MacAddress>({b}));
station.confirm(b, "requested", active);
ASSERT(station.results == std::vector<MacAddress>({b}));
station.confirm(b, "unrelated", active);
ASSERT(station.results.empty());
station.confirm(MacAddress::BROADCAST_ADDRESS, "absent", active);
ASSERT(station.results.empty());
}
ASSERT(station.confirmations == 12);
EV << "Scan confirms honor both filters and preserve discovery cache.\n";

%contains: stdout
Scan confirms honor both filters and preserve discovery cache.