wifi: Add Association Manager base class and default subclass

This commit is contained in:
Stefano Avallone
2022-06-12 15:51:12 +02:00
parent 8b57c8a5e5
commit 384b506ed9
6 changed files with 608 additions and 0 deletions

View File

@@ -111,7 +111,9 @@ set(source_files
model/vht/vht-ppdu.cc
model/wifi-ack-manager.cc
model/wifi-acknowledgment.cc
model/wifi-assoc-manager.cc
model/wifi-default-ack-manager.cc
model/wifi-default-assoc-manager.cc
model/wifi-default-protection-manager.cc
model/wifi-information-element-vector.cc
model/wifi-information-element.cc
@@ -252,7 +254,9 @@ set(header_files
model/vht/vht-ppdu.h
model/wifi-ack-manager.h
model/wifi-acknowledgment.h
model/wifi-assoc-manager.h
model/wifi-default-ack-manager.h
model/wifi-default-assoc-manager.h
model/wifi-default-protection-manager.h
model/wifi-information-element-vector.h
model/wifi-information-element.h

View File

@@ -921,7 +921,9 @@ WifiHelper::EnableLogComponents (void)
LogComponentEnable ("VhtPhy", LOG_LEVEL_ALL);
LogComponentEnable ("VhtPpdu", LOG_LEVEL_ALL);
LogComponentEnable ("WifiAckManager", LOG_LEVEL_ALL);
LogComponentEnable ("WifiAssocManager", LOG_LEVEL_ALL);
LogComponentEnable ("WifiDefaultAckManager", LOG_LEVEL_ALL);
LogComponentEnable ("WifiDefaultAssocManager", LOG_LEVEL_ALL);
LogComponentEnable ("WifiDefaultProtectionManager", LOG_LEVEL_ALL);
LogComponentEnable ("WifiMac", LOG_LEVEL_ALL);
LogComponentEnable ("WifiMacQueue", LOG_LEVEL_ALL);

View File

@@ -0,0 +1,240 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefano Avallone <stavallo@unina.it>
*/
#include <algorithm>
#include "ns3/log.h"
#include "sta-wifi-mac.h"
#include "wifi-assoc-manager.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("WifiAssocManager");
NS_OBJECT_ENSURE_REGISTERED (WifiAssocManager);
WifiAssocManager::ApInfoCompare::ApInfoCompare (const WifiAssocManager& manager)
: m_manager (manager)
{
}
bool
WifiAssocManager::ApInfoCompare::operator() (const StaWifiMac::ApInfo& lhs,
const StaWifiMac::ApInfo& rhs) const
{
NS_ASSERT_MSG (lhs.m_bssid != rhs.m_bssid,
"Comparing two ApInfo objects with the same BSSID: " << lhs.m_bssid);
bool lhsBefore = m_manager.Compare (lhs, rhs);
if (lhsBefore)
{
return true;
}
// the Compare method implemented by subclass may be such that the two ApInfo objects
// compare equal; in such a case, use the BSSID as tie breaker
bool rhsBefore = m_manager.Compare (rhs, lhs);
if (rhsBefore)
{
return false;
}
WifiAddressHash hash;
return hash (lhs.m_bssid) > hash (rhs.m_bssid);
}
TypeId
WifiAssocManager::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::WifiAssocManager")
.SetParent<Object> ()
.SetGroupName ("Wifi")
;
return tid;
}
WifiAssocManager::WifiAssocManager ()
: m_scanParams (), // zero-initialization
m_apList (ApInfoCompare (*this))
{
}
WifiAssocManager::~WifiAssocManager ()
{
NS_LOG_FUNCTION (this);
}
void
WifiAssocManager::DoDispose (void)
{
NS_LOG_FUNCTION (this);
m_mac = nullptr;
}
void
WifiAssocManager::SetStaWifiMac (Ptr<StaWifiMac> mac)
{
NS_LOG_FUNCTION (this << mac);
m_mac = mac;
}
const WifiAssocManager::SortedList&
WifiAssocManager::GetSortedList (void) const
{
return m_apList;
}
const WifiScanParams&
WifiAssocManager::GetScanParams (void) const
{
return m_scanParams;
}
bool
WifiAssocManager::MatchScanParams (const StaWifiMac::ApInfo& apInfo) const
{
NS_LOG_FUNCTION (this);
if (!m_scanParams.ssid.IsBroadcast ())
{
// we need to check if AP's advertised SSID matches the requested SSID
Ssid apSsid;
if (auto beacon = std::get_if<MgtBeaconHeader> (&apInfo.m_frame); beacon)
{
apSsid = beacon->GetSsid ();
}
else
{
auto probeResp = std::get_if<MgtProbeResponseHeader> (&apInfo.m_frame);
NS_ASSERT (probeResp);
apSsid = probeResp->GetSsid ();
}
if (!apSsid.IsEqual (m_scanParams.ssid))
{
NS_LOG_DEBUG ("AP " << apInfo.m_bssid << " does not advertise our SSID "
<< apSsid << " " << m_scanParams.ssid);
return false;
}
}
// we need to check if the AP is operating on a requested channel
auto channelMatch =
[&apInfo](auto&& channel)
{
if (channel.number != 0 && channel.number != apInfo.m_channel.number)
{
return false;
}
if (channel.band != WIFI_PHY_BAND_UNSPECIFIED && channel.band != apInfo.m_channel.band)
{
return false;
}
return true;
};
NS_ASSERT (apInfo.m_linkId < m_scanParams.channelList.size ());
if (std::find_if (m_scanParams.channelList[apInfo.m_linkId].cbegin (),
m_scanParams.channelList[apInfo.m_linkId].cend (),
channelMatch)
== m_scanParams.channelList[apInfo.m_linkId].cend ())
{
NS_LOG_DEBUG ("AP " << apInfo.m_bssid << " is not operating on a requested channel");
return false;
}
return true;
}
void
WifiAssocManager::StartScanning (WifiScanParams&& scanParams)
{
NS_LOG_FUNCTION (this);
m_scanParams = std::move (scanParams);
// remove stored AP information not matching the scanning parameters
for (auto ap = m_apList.begin (); ap != m_apList.end (); )
{
if (!MatchScanParams (*ap))
{
// remove AP info from list
m_apListIt.erase (ap->m_bssid);
ap = m_apList.erase (ap);
}
else
{
++ap;
}
}
DoStartScanning ();
}
void
WifiAssocManager::NotifyApInfo (const StaWifiMac::ApInfo&& apInfo)
{
NS_LOG_FUNCTION (this << apInfo.m_apAddr << apInfo.m_bssid << +apInfo.m_linkId);
if (!CanBeInserted (apInfo) || !MatchScanParams (apInfo))
{
return;
}
// check if an ApInfo object with the same BSSID is already present in the
// sorted list of ApInfo objects. This is done by trying to insert the BSSID
// in the hash table (insertion fails if the BSSID is already present)
auto [hashIt, hashInserted] = m_apListIt.insert ({apInfo.m_bssid, {}});
if (!hashInserted)
{
// an element with the searched BSSID is already present in the hash table.
// Remove the corresponding ApInfo object from the sorted list.
m_apList.erase (hashIt->second);
}
// insert the ApInfo object
auto [listIt, listInserted] = m_apList.insert (std::move (apInfo));
// update the hash table entry
NS_ASSERT_MSG (listInserted,
"An entry (" << listIt->m_apAddr << ", " << listIt->m_bssid << ", "
<< +listIt->m_linkId << ") prevented insertion of given ApInfo object");
hashIt->second = listIt;
}
void
WifiAssocManager::ScanningTimeout (void)
{
NS_LOG_FUNCTION (this);
StaWifiMac::ApInfo bestAp;
do
{
if (m_apList.empty ())
{
m_mac->ScanningTimeout (/*std::nullopt*/);
return;
}
bestAp = std::move (m_apList.extract (m_apList.begin ()).value ());
m_apListIt.erase (bestAp.m_bssid);
} while (!CanBeReturned (bestAp));
m_mac->ScanningTimeout (/*std::move (bestAp)*/);
}
} //namespace ns3

View File

@@ -0,0 +1,185 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefano Avallone <stavallo@unina.it>
*/
#ifndef WIFI_ASSOC_MANAGER_H
#define WIFI_ASSOC_MANAGER_H
#include "qos-utils.h"
#include "sta-wifi-mac.h"
#include <set>
#include <unordered_map>
namespace ns3 {
/**
* \ingroup wifi
*
* Abstract base class for the Association Manager, which manages
* scanning and association for single link devices and ML discovery
* and setup for multi-link devices.
*/
class WifiAssocManager : public Object
{
/**
* Struct providing a function call operator to compare two ApInfo objects.
* This struct is used as the Compare template type parameter of the set of
* ApInfo objects maintained by the Association Manager.
*/
struct ApInfoCompare
{
/**
* Constructor.
*
* \param manager a pointer to the Association Manager
*/
ApInfoCompare (const WifiAssocManager& manager);
/**
* Function call operator. Calls the Compare method of the Association Manager.
*
* \param lhs left hand side ApInfo object
* \param rhs right hand side ApInfo object
* \return true if the left hand side ApInfo object should be placed before the
* right hand side ApInfo object in the sorted list maintained by the
* Association Manager, false otherwise
*/
bool operator()(const StaWifiMac::ApInfo& lhs, const StaWifiMac::ApInfo& rhs) const;
private:
const WifiAssocManager& m_manager; ///< Association Manager
};
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
virtual ~WifiAssocManager ();
/**
* Set the pointer to the STA wifi MAC.
*
* \param mac the pointer to the STA wifi MAC
*/
void SetStaWifiMac (Ptr<StaWifiMac> mac);
/**
* Request the Association Manager to start a scanning procedure according to
* the given scanning parameters. At subclass' discretion, stored information
* about APs matching the given scanning parameters may be used and scanning
* not performed.
*
* \param scanParams the scanning parameters
*/
void StartScanning (WifiScanParams&& scanParams);
/**
* STA wifi MAC received a Beacon frame or Probe Response frame while scanning
* and notifies us the AP information contained in the received frame.
*
* Note that the given ApInfo object is moved to the sorted list of ApInfo objects.
*
* \param apInfo the AP information contained in the received frame
*/
virtual void NotifyApInfo (const StaWifiMac::ApInfo&& apInfo);
/**
* Compare two ApInfo objects for the purpose of keeping a sorted list of
* ApInfo objects.
*
* \param lhs left hand side ApInfo object
* \param rhs right hand side ApInfo object
* \return true if the left hand side ApInfo object should be placed before the
* right hand side ApInfo object in the sorted list of ApInfo objects,
* false otherwise
*/
virtual bool Compare (const StaWifiMac::ApInfo& lhs, const StaWifiMac::ApInfo& rhs) const = 0;
protected:
/**
* Constructor (protected as this is an abstract base class)
*/
WifiAssocManager ();
void DoDispose (void) override;
/// typedef for the sorted list of ApInfo objects
using SortedList = std::set<StaWifiMac::ApInfo, ApInfoCompare>;
/**
* \return a const reference to the sorted list of ApInfo objects.
*/
const SortedList& GetSortedList (void) const;
/**
* \return the scanning parameters.
*/
const WifiScanParams& GetScanParams (void) const;
/**
* Check whether the given AP information match the current scanning parameters.
*
* \param apInfo the given AP information
* \return whether the given AP information match the current scanning parameters
*/
bool MatchScanParams (const StaWifiMac::ApInfo& apInfo) const;
/**
* Allow subclasses to choose whether the given ApInfo shall be considered
* and hence inserted in the sorted list of ApInfo objects.
*
* \param apInfo the apInfo object to insert
* \return true if the apInfo object can be inserted, false otherwise
*/
virtual bool CanBeInserted (const StaWifiMac::ApInfo& apInfo) const = 0;
/**
* Allow subclasses to choose whether the given ApInfo shall be returned or
* discarded when the STA wifi MAC requests information on the best AP.
*
* \param apInfo the apInfo object to return
* \return true if the apInfo object can be returned, false otherwise
*/
virtual bool CanBeReturned (const StaWifiMac::ApInfo& apInfo) const = 0;
/**
* Extract the best AP to associate with from the sorted list and return
* it, if any, to the STA wifi MAC along with the notification that scanning
* is completed.
*/
void ScanningTimeout (void);
Ptr<StaWifiMac> m_mac; ///< pointer to the STA wifi MAC
private:
/**
* Start a scanning procedure. This method needs to schedule a call to
* ScanningTimeout when the scanning procedure is completed.
*/
virtual void DoStartScanning (void) = 0;
WifiScanParams m_scanParams; ///< scanning parameters
SortedList m_apList; ///< sorted list of candidate APs
/// hash table to help locate ApInfo objects in the sorted list based on the BSSID
std::unordered_map<Mac48Address, SortedList::const_iterator, WifiAddressHash> m_apListIt;
};
} //namespace ns3
#endif /* WIFI_ASSOC_MANAGER_H */

View File

@@ -0,0 +1,114 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefano Avallone <stavallo@unina.it>
*/
#include "ns3/log.h"
#include "ns3/simulator.h"
#include "sta-wifi-mac.h"
#include "wifi-default-assoc-manager.h"
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("WifiDefaultAssocManager");
NS_OBJECT_ENSURE_REGISTERED (WifiDefaultAssocManager);
TypeId
WifiDefaultAssocManager::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::WifiDefaultAssocManager")
.SetParent<WifiAssocManager> ()
.AddConstructor<WifiDefaultAssocManager> ()
.SetGroupName ("Wifi")
;
return tid;
}
WifiDefaultAssocManager::WifiDefaultAssocManager ()
{
NS_LOG_FUNCTION (this);
}
WifiDefaultAssocManager::~WifiDefaultAssocManager ()
{
NS_LOG_FUNCTION (this);
}
void
WifiDefaultAssocManager::DoDispose (void)
{
NS_LOG_FUNCTION (this);
m_probeRequestEvent.Cancel ();
m_waitBeaconEvent.Cancel ();
WifiAssocManager::DoDispose();
}
bool
WifiDefaultAssocManager::Compare (const StaWifiMac::ApInfo& lhs,
const StaWifiMac::ApInfo& rhs) const
{
return lhs.m_snr > rhs.m_snr;
}
void
WifiDefaultAssocManager::DoStartScanning (void)
{
NS_LOG_FUNCTION (this);
// if there are entries in the sorted list of AP information, reuse them and
// do not perform scanning
if (!GetSortedList ().empty ())
{
Simulator::ScheduleNow (&WifiDefaultAssocManager::ScanningTimeout, this);
return;
}
m_probeRequestEvent.Cancel ();
m_waitBeaconEvent.Cancel ();
if (GetScanParams ().type == WifiScanParams::ACTIVE)
{
Simulator::Schedule (GetScanParams ().probeDelay, &StaWifiMac::SendProbeRequest, m_mac);
m_probeRequestEvent = Simulator::Schedule (GetScanParams ().probeDelay
+ GetScanParams().maxChannelTime,
&WifiDefaultAssocManager::ScanningTimeout,
this);
}
else
{
m_waitBeaconEvent = Simulator::Schedule (GetScanParams ().maxChannelTime,
&WifiDefaultAssocManager::ScanningTimeout,
this);
}
}
bool
WifiDefaultAssocManager::CanBeInserted (const StaWifiMac::ApInfo& apInfo) const
{
return (m_waitBeaconEvent.IsRunning () || m_probeRequestEvent.IsRunning ());
}
bool
WifiDefaultAssocManager::CanBeReturned (const StaWifiMac::ApInfo& apInfo) const
{
return true;
}
} //namespace ns3

View File

@@ -0,0 +1,63 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2022 Universita' degli Studi di Napoli Federico II
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Stefano Avallone <stavallo@unina.it>
*/
#ifndef WIFI_DEFAULT_ASSOC_MANAGER_H
#define WIFI_DEFAULT_ASSOC_MANAGER_H
#include "wifi-assoc-manager.h"
namespace ns3 {
class StaWifiMac;
/**
* \ingroup wifi
*
* Default wifi Association Manager.
*/
class WifiDefaultAssocManager : public WifiAssocManager
{
public:
/**
* \brief Get the type ID.
* \return the object TypeId
*/
static TypeId GetTypeId (void);
WifiDefaultAssocManager ();
virtual ~WifiDefaultAssocManager ();
bool Compare (const StaWifiMac::ApInfo& lhs, const StaWifiMac::ApInfo& rhs) const override;
protected:
void DoDispose (void) override;
bool CanBeInserted (const StaWifiMac::ApInfo& apInfo) const override;
bool CanBeReturned (const StaWifiMac::ApInfo& apInfo) const override;
private:
void DoStartScanning (void) override;
EventId m_waitBeaconEvent; ///< wait beacon event
EventId m_probeRequestEvent; ///< probe request event
};
} //namespace ns3
#endif /* WIFI_DEFAULT_ASSOC_MANAGER_H */