wifi: EMLSR test uses BA agreement notification instead of fixed delay

This commit is contained in:
Stefano Avallone
2025-01-17 18:49:08 +01:00
parent ebf7585c3d
commit fb6eaeb648
2 changed files with 160 additions and 44 deletions

View File

@@ -486,8 +486,18 @@ EmlsrOperationsTestBase::DoSetup()
}
// schedule ML setup for one station at a time
m_apMac->TraceConnectWithoutContext("AssociatedSta",
MakeCallback(&EmlsrOperationsTestBase::SetSsid, this));
m_apMac->TraceConnectWithoutContext(
"AssociatedSta",
MakeCallback(&EmlsrOperationsTestBase::StaAssociated, this));
m_apMac->GetQosTxop(AC_BE)->TraceConnectWithoutContext(
"BaEstablished",
MakeCallback(&EmlsrOperationsTestBase::BaEstablishedDl, this));
for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
{
m_staMacs[id]->GetQosTxop(AC_BE)->TraceConnectWithoutContext(
"BaEstablished",
MakeCallback(&EmlsrOperationsTestBase::BaEstablishedUl, this).Bind(id));
}
Simulator::Schedule(Seconds(0), [&]() { m_staMacs[0]->SetSsid(Ssid("ns-3-ssid")); });
}
@@ -495,12 +505,14 @@ Ptr<PacketSocketClient>
EmlsrOperationsTestBase::GetApplication(TrafficDirection dir,
std::size_t staId,
std::size_t count,
std::size_t pktSize) const
std::size_t pktSize,
uint8_t priority) const
{
auto client = CreateObject<PacketSocketClient>();
client->SetAttribute("PacketSize", UintegerValue(pktSize));
client->SetAttribute("MaxPackets", UintegerValue(count));
client->SetAttribute("Interval", TimeValue(MicroSeconds(0)));
client->SetAttribute("Priority", UintegerValue(priority));
client->SetRemote(dir == DOWNLINK ? m_dlSockets.at(staId) : m_ulSockets.at(staId));
client->SetStartTime(Seconds(0)); // now
client->SetStopTime(m_duration - Simulator::Now());
@@ -509,7 +521,7 @@ EmlsrOperationsTestBase::GetApplication(TrafficDirection dir,
}
void
EmlsrOperationsTestBase::SetSsid(uint16_t aid, Mac48Address /* addr */)
EmlsrOperationsTestBase::StaAssociated(uint16_t aid, Mac48Address /* addr */)
{
if (m_lastAid == aid)
{
@@ -519,42 +531,115 @@ EmlsrOperationsTestBase::SetSsid(uint16_t aid, Mac48Address /* addr */)
m_lastAid = aid;
// wait some time (5ms) to allow the completion of association
auto delay = MilliSeconds(5);
const auto delay = MilliSeconds(5);
if (m_establishBaDl)
if (!m_establishBaDl.empty())
{
// trigger establishment of BA agreement with AP as originator
Simulator::Schedule(delay, [=, this]() {
m_apMac->GetDevice()->GetNode()->AddApplication(
GetApplication(DOWNLINK, aid - 1, 4, 1000));
GetApplication(DOWNLINK, aid - 1, 4, 1000, m_establishBaDl.front()));
});
delay += MilliSeconds(5);
}
if (m_establishBaUl)
else if (!m_establishBaUl.empty())
{
// trigger establishment of BA agreement with AP as recipient
Simulator::Schedule(delay, [=, this]() {
m_staMacs[aid - 1]->GetDevice()->GetNode()->AddApplication(
GetApplication(UPLINK, aid - 1, 4, 1000));
GetApplication(UPLINK, aid - 1, 4, 1000, m_establishBaUl.front()));
});
delay += MilliSeconds(5);
}
else
{
Simulator::Schedule(delay, [=, this]() { SetSsid(aid); });
}
}
Simulator::Schedule(delay, [=, this]() {
if (aid < m_nEmlsrStations + m_nNonEmlsrStations)
{
// make the next STA start ML discovery & setup
m_staMacs[aid]->SetSsid(Ssid("ns-3-ssid"));
return;
}
// all stations associated; start traffic if needed
StartTraffic();
// stop generation of beacon frames in order to avoid interference
m_apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
});
void
EmlsrOperationsTestBase::BaEstablishedDl(Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> /* gcrGroup */)
{
// wait some time (5ms) to allow the exchange of the data frame that triggered the Block Ack
const auto delay = MilliSeconds(5);
auto linkId = m_apMac->IsAssociated(recipient);
NS_TEST_ASSERT_MSG_EQ(linkId.has_value(), true, "No link for association of " << recipient);
auto aid = m_apMac->GetWifiRemoteStationManager(*linkId)->GetAssociationId(recipient);
if (auto it = std::find(m_establishBaDl.cbegin(), m_establishBaDl.cend(), tid);
it != m_establishBaDl.cend() && std::next(it) != m_establishBaDl.cend())
{
// trigger establishment of BA agreement with AP as originator
Simulator::Schedule(delay, [=, this]() {
m_apMac->GetDevice()->GetNode()->AddApplication(
GetApplication(DOWNLINK, aid - 1, 4, 1000, *std::next(it)));
});
}
else if (!m_establishBaUl.empty())
{
// trigger establishment of BA agreement with AP as recipient
Simulator::Schedule(delay, [=, this]() {
m_staMacs[aid - 1]->GetDevice()->GetNode()->AddApplication(
GetApplication(UPLINK, aid - 1, 4, 1000, m_establishBaUl.front()));
});
}
else
{
Simulator::Schedule(delay, [=, this]() { SetSsid(aid - 1 + 1); });
}
}
void
EmlsrOperationsTestBase::BaEstablishedUl(std::size_t index,
Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> /* gcrGroup */)
{
// wait some time (5ms) to allow the exchange of the data frame that triggered the Block Ack
const auto delay = MilliSeconds(5);
if (auto it = std::find(m_establishBaUl.cbegin(), m_establishBaUl.cend(), tid);
it != m_establishBaUl.cend() && std::next(it) != m_establishBaUl.cend())
{
// trigger establishment of BA agreement with AP as recipient
Simulator::Schedule(delay, [=, this]() {
m_staMacs[index]->GetDevice()->GetNode()->AddApplication(
GetApplication(UPLINK, index, 4, 1000, *std::next(it)));
});
}
else
{
Simulator::Schedule(delay, [=, this]() { SetSsid(index + 1); });
}
}
void
EmlsrOperationsTestBase::SetSsid(std::size_t count)
{
if (count < m_nEmlsrStations + m_nNonEmlsrStations)
{
// make the next STA start ML discovery & setup
m_staMacs[count]->SetSsid(Ssid("ns-3-ssid"));
return;
}
// all stations associated; start traffic if needed
StartTraffic();
// stop generation of beacon frames in order to avoid interference
m_apMac->SetAttribute("BeaconGeneration", BooleanValue(false));
// disconnect callbacks
m_apMac->TraceDisconnectWithoutContext(
"AssociatedSta",
MakeCallback(&EmlsrOperationsTestBase::StaAssociated, this));
m_apMac->GetQosTxop(AC_BE)->TraceDisconnectWithoutContext(
"BaEstablished",
MakeCallback(&EmlsrOperationsTestBase::BaEstablishedDl, this));
for (std::size_t id = 0; id < m_nEmlsrStations + m_nNonEmlsrStations; ++id)
{
m_staMacs[id]->GetQosTxop(AC_BE)->TraceDisconnectWithoutContext(
"BaEstablished",
MakeCallback(&EmlsrOperationsTestBase::BaEstablishedUl, this).Bind(id));
}
}
void
@@ -889,7 +974,7 @@ EmlsrDlTxopTest::EmlsrDlTxopTest(const Params& params)
m_paddingDelay = params.paddingDelay;
m_transitionDelay = params.transitionDelay;
m_transitionTimeout = params.transitionTimeout;
m_establishBaDl = true;
m_establishBaDl = {0};
m_putAuxPhyToSleep = params.putAuxPhyToSleep;
m_duration = Seconds(1.5);
@@ -2622,8 +2707,8 @@ EmlsrUlTxopTest::EmlsrUlTxopTest(const Params& params)
// when aux PHYs do not switch link, the main PHY switches back to its previous link after
// a TXOP, hence the transition delay must exceed the channel switch delay (default: 250us)
m_transitionDelay = {MicroSeconds(256)};
m_establishBaDl = true;
m_establishBaUl = true;
m_establishBaDl = {0};
m_establishBaUl = {0};
m_putAuxPhyToSleep = params.putAuxPhyToSleep;
m_duration = Seconds(1);
@@ -3841,8 +3926,8 @@ EmlsrUlOfdmaTest::EmlsrUlOfdmaTest(bool enableBsrp)
m_linksToEnableEmlsrOn = {0, 1, 2};
m_nEmlsrStations = 1;
m_nNonEmlsrStations = 1;
m_establishBaDl = false;
m_establishBaUl = true;
m_establishBaDl = {};
m_establishBaUl = {0};
m_mainPhyId = 1;
m_duration = Seconds(1);
}
@@ -4165,7 +4250,7 @@ EmlsrLinkSwitchTest::EmlsrLinkSwitchTest(const Params& params)
m_nNonEmlsrStations = 0;
m_linksToEnableEmlsrOn = {0, 1, 2}; // enable EMLSR on all links right after association
m_mainPhyId = 1;
m_establishBaDl = true;
m_establishBaDl = {0};
m_duration = Seconds(1);
// when aux PHYs do not switch link, the main PHY switches back to its previous link after
// a TXOP, hence the transition delay must exceed the channel switch delay (default: 250us)
@@ -4770,7 +4855,7 @@ EmlsrCcaBusyTest::EmlsrCcaBusyTest(MHz_u auxPhyMaxChWidth)
m_nNonEmlsrStations = 1;
m_linksToEnableEmlsrOn = {0, 1, 2}; // enable EMLSR on all links right after association
m_mainPhyId = 1;
m_establishBaUl = true;
m_establishBaUl = {0};
m_duration = Seconds(1);
m_transitionDelay = {MicroSeconds(128)};
}
@@ -4991,8 +5076,8 @@ SingleLinkEmlsrTest::SingleLinkEmlsrTest(bool switchAuxPhy, bool auxPhyTxCapable
// channel switch delay will be also set to 64 us
m_paddingDelay = {MicroSeconds(64)};
m_transitionDelay = {MicroSeconds(64)};
m_establishBaDl = true;
m_establishBaUl = true;
m_establishBaDl = {0};
m_establishBaUl = {0};
m_duration = Seconds(0.5);
}

View File

@@ -111,13 +111,15 @@ class EmlsrOperationsTestBase : public TestCase
* @param staId the index (starting at 0) of the non-AP MLD generating/receiving packets
* @param count the number of packets to generate
* @param pktSize the size of the packets to generate
* @param priority user priority for generated packets
* @return an application generating the given number packets of the given size from/to the
* AP MLD to/from the given non-AP MLD
*/
Ptr<PacketSocketClient> GetApplication(TrafficDirection dir,
std::size_t staId,
std::size_t count,
std::size_t pktSize) const;
std::size_t pktSize,
uint8_t priority = 0) const;
/**
* Check whether QoS data unicast transmissions addressed to the given destination on the
@@ -219,11 +221,11 @@ class EmlsrOperationsTestBase : public TestCase
std::vector<Time> m_paddingDelay{
{MicroSeconds(32)}}; ///< Padding Delay advertised by the non-AP MLD
std::vector<Time> m_transitionDelay{
{MicroSeconds(16)}}; ///< Transition Delay advertised by the non-AP MLD
bool m_establishBaDl{false}; /**< whether BA needs to be established (for TID 0)
with the AP as originator */
bool m_establishBaUl{false}; /**< whether BA needs to be established (for TID 0)
with the AP as recipient */
{MicroSeconds(16)}}; ///< Transition Delay advertised by the non-AP MLD
std::vector<uint8_t> m_establishBaDl{}; /**< the TIDs for which BA needs to be established
with the AP as originator */
std::vector<uint8_t> m_establishBaUl{}; /**< the TIDs for which BA needs to be established
with the AP as recipient */
bool m_putAuxPhyToSleep{false}; //!< whether aux PHYs are put to sleep during DL/UL TXOPs
std::vector<FrameInfo> m_txPsdus; ///< transmitted PSDUs
Ptr<ApWifiMac> m_apMac; ///< AP wifi MAC
@@ -237,13 +239,42 @@ class EmlsrOperationsTestBase : public TestCase
private:
/**
* Set the SSID on the next station that needs to start the association procedure.
* This method is connected to the ApWifiMac's AssociatedSta trace source.
* Callback connected to the ApWifiMac's AssociatedSta trace source.
* Start generating traffic (if needed) when all stations are associated.
*
* @param aid the AID assigned to the previous associated STA
*/
void SetSsid(uint16_t aid, Mac48Address /* addr */);
void StaAssociated(uint16_t aid, Mac48Address /* addr */);
/**
* Callback connected to the QosTxop's BaEstablished trace source of the AP's BE AC.
*
* @param recipient the recipient of the established Block Ack agreement
* @param tid the TID
*/
void BaEstablishedDl(Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> /* gcrGroup */);
/**
* Callback connected to the QosTxop's BaEstablished trace source of a STA's BE AC.
*
* @param index the index of the STA which the callback is connected to
* @param recipient the recipient of the established Block Ack agreement
* @param tid the TID
*/
void BaEstablishedUl(std::size_t index,
Mac48Address recipient,
uint8_t tid,
std::optional<Mac48Address> /* gcrGroup */);
/**
* Set the SSID on the next station that needs to start the association procedure, or start
* traffic if no other station left.
*
* @param count the number of STAs that completed the association procedure
*/
void SetSsid(std::size_t count);
/**
* Start the generation of traffic (needs to be overridden)