Skip to content
Draft
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
16 changes: 16 additions & 0 deletions src/inet/linklayer/ieee80211/mac/Ieee80211BssidReq.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later
//

import inet.common.INETDefs;
import inet.common.TagBase;
import inet.linklayer.common.MacAddress;

namespace inet;

// The management procedure's BSSID for Address3 of an outgoing management frame.
// It is independent of the receiver address and survives queuing/state changes.
class Ieee80211BssidReq extends TagBase
{
MacAddress bssid;
}
46 changes: 41 additions & 5 deletions src/inet/linklayer/ieee80211/mac/Ieee80211Mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@


#include "inet/linklayer/ieee80211/mac/Ieee80211Mac.h"
#include "inet/linklayer/ieee80211/mac/Ieee80211BssidReq_m.h"

#include <algorithm>

Expand Down Expand Up @@ -46,8 +47,8 @@ Ieee80211Mac::Ieee80211Mac()

Ieee80211Mac::~Ieee80211Mac()
{
if (pendingRadioConfigMsg)
delete pendingRadioConfigMsg;
cancelAndDelete(radioConfigRetry);
delete pendingRadioConfigMsg;
}

void Ieee80211Mac::initialize(int stage)
Expand Down Expand Up @@ -156,15 +157,46 @@ void Ieee80211Mac::handleMessageWhenUp(cMessage *message)

void Ieee80211Mac::handleSelfMessage(cMessage *msg)
{
ASSERT(false);
if (msg == radioConfigRetry) {
// Retry after delivered receptions and exchange callbacks have reserved any SIFS response.
if (pendingRadioConfigMsg && rx->isMediumFree() && !tx->isTransmissionPending() &&
!(mib->qos ? hcf->isFrameSequenceRunning() : dcf->isFrameSequenceRunning()))
sendDownPendingRadioConfigMsg();
}
else
ASSERT(false);
}

void Ieee80211Mac::scheduleRadioConfigRetry()
{
Enter_Method("scheduleRadioConfigRetry");
if (pendingRadioConfigMsg) {
if (!radioConfigRetry)
radioConfigRetry = new cMessage("radioConfigRetry");
if (!radioConfigRetry->isScheduled())
scheduleAt(simTime(), radioConfigRetry);
}
}


void Ieee80211Mac::clearPendingRadioConfig()
{
if (radioConfigRetry)
cancelEvent(radioConfigRetry);
delete pendingRadioConfigMsg;
pendingRadioConfigMsg = nullptr;
}


void Ieee80211Mac::handleMgmtPacket(Packet *packet)
{
const auto& header = makeShared<Ieee80211MgmtHeader>();
header->setType((Ieee80211FrameType)packet->getTag<Ieee80211SubtypeReq>()->getSubtype());
header->setReceiverAddress(packet->getTag<MacAddressReq>()->getDestAddress());
if (mib->mode == Ieee80211Mib::INFRASTRUCTURE && mib->bssStationData.stationType == Ieee80211Mib::ACCESS_POINT)
// IEEE Std 802.11-2024, 9.3.3.1: management supplies its intended BSSID.
if (auto bssid = packet->findTag<Ieee80211BssidReq>())
header->setAddress3(bssid->getBssid());
else if (mib->mode == Ieee80211Mib::INFRASTRUCTURE && mib->bssStationData.stationType == Ieee80211Mib::ACCESS_POINT)
header->setAddress3(mib->bssData.bssid);
packet->insertAtFront(header);
packet->insertAtBack(makeShared<Ieee80211MacTrailer>());
Expand Down Expand Up @@ -239,9 +271,9 @@ void Ieee80211Mac::handleUpperCommand(cMessage *msg)
sendDown(msg);
}
else {
// TODO waiting potentially indefinitely?! wtf?!
EV_DEBUG << "Delaying " << msg->getName() << " until next IDLE or DEFER state\n";
pendingRadioConfigMsg = msg;
scheduleRadioConfigRetry();
}
}
else {
Expand Down Expand Up @@ -340,6 +372,8 @@ void Ieee80211Mac::receiveSignal(cComponent *source, simsignal_t signalID, intva
configureRadioMode(IRadio::RADIO_MODE_RECEIVER); // FIXME this is in a very wrong place!!! should be done explicitly from coordination function!
}
rx->transmissionStateChanged(transmissionState);
if (transmissionFinished)
scheduleRadioConfigRetry();
}
else if (signalID == IRadio::receivedSignalPartChangedSignal) {
rx->receivedSignalPartChanged(static_cast<IRadioSignal::SignalPart>(value));
Expand Down Expand Up @@ -428,11 +462,13 @@ void Ieee80211Mac::handleStartOperation(LifecycleOperation *operation)
// FIXME
void Ieee80211Mac::handleStopOperation(LifecycleOperation *operation)
{
clearPendingRadioConfig();
}

// FIXME
void Ieee80211Mac::handleCrashOperation(LifecycleOperation *operation)
{
clearPendingRadioConfig();
}

} // namespace ieee80211
Expand Down
3 changes: 3 additions & 0 deletions src/inet/linklayer/ieee80211/mac/Ieee80211Mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class INET_API Ieee80211Mac : public MacProtocolBase

// The last change channel message received and not yet sent to the physical layer, or nullptr.
cMessage *pendingRadioConfigMsg = nullptr;
cMessage *radioConfigRetry = nullptr;

protected:
virtual int numInitStages() const override { return NUM_INIT_STAGES; }
Expand All @@ -79,6 +80,7 @@ class INET_API Ieee80211Mac : public MacProtocolBase

/** @brief Handle timer self messages */
virtual void handleSelfMessage(cMessage *msg) override;
void clearPendingRadioConfig();

/** @brief Handle packets from management */
virtual void handleMgmtPacket(Packet *packet);
Expand Down Expand Up @@ -106,6 +108,7 @@ class INET_API Ieee80211Mac : public MacProtocolBase
virtual void sendUpFrame(Packet *frame);
virtual void sendDownFrame(Packet *frame);
virtual void sendDownPendingRadioConfigMsg();
virtual void scheduleRadioConfigRetry();

virtual void processUpperFrame(Packet *packet, const Ptr<const Ieee80211DataOrMgmtHeader>& header);
virtual void processLowerFrame(Packet *packet, const Ptr<const Ieee80211MacHeader>& header);
Expand Down
1 change: 1 addition & 0 deletions src/inet/linklayer/ieee80211/mac/Tx.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class INET_API Tx : public SimpleModule, public ITx
virtual void transmitFrame(Packet *packet, const Ptr<const Ieee80211MacHeader>& header, ITx::ICallback *txCallback) override;
virtual void transmitFrame(Packet *packet, const Ptr<const Ieee80211MacHeader>& header, simtime_t ifs, ITx::ICallback *txCallback) override;
virtual void radioTransmissionFinished() override;
virtual bool isTransmissionPending() const override { return frame != nullptr; }
};

} // namespace ieee80211
Expand Down
3 changes: 3 additions & 0 deletions src/inet/linklayer/ieee80211/mac/contention/Contention.cc
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ void Contention::mediumStateChanged(bool mediumFree)
this->mediumFree = mediumFree;
lastChannelBusyTime = simTime();
handleWithFSM(MEDIUM_STATE_CHANGED);
// An idle contender otherwise has no transition that applies a deferred channel change.
if (mediumFree)
mac->scheduleRadioConfigRetry();
}

void Contention::handleMessage(cMessage *msg)
Expand Down
3 changes: 3 additions & 0 deletions src/inet/linklayer/ieee80211/mac/contract/ITx.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class INET_API ITx
virtual void transmitFrame(Packet *packet, const Ptr<const Ieee80211MacHeader>& header, ICallback *callback) = 0;
virtual void transmitFrame(Packet *packet, const Ptr<const Ieee80211MacHeader>& header, simtime_t ifs, ICallback *callback) = 0;
virtual void radioTransmissionFinished() = 0;

// Includes a frame waiting for its inter-frame space, as well as on-air transmission.
virtual bool isTransmissionPending() const = 0;
};

} // namespace ieee80211
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class INET_API Dcf : public ICoordinationFunction, public IFrameSequenceHandler:

public:
virtual ~Dcf();
virtual bool isFrameSequenceRunning() const { return frameSequenceHandler->isSequenceRunning(); }

// ICoordinationFunction
virtual void processUpperFrame(Packet *packet, const Ptr<const Ieee80211DataOrMgmtHeader>& header) override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ class INET_API Hcf : public ICoordinationFunction, public IFrameSequenceHandler:

public:
virtual ~Hcf();
virtual bool isFrameSequenceRunning() const { return frameSequenceHandler->isSequenceRunning(); }

// ICoordinationFunction
virtual void processUpperFrame(Packet *packet, const Ptr<const Ieee80211DataOrMgmtHeader>& header) override;
Expand Down
Loading
Loading