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
45 changes: 34 additions & 11 deletions src/inet/linklayer/ieee80211/mac/Ieee80211MacHeaderSerializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,23 @@ void copyBlockAckFrameFields(const Ptr<ieee80211::Ieee80211BlockAck> to, const P
to->setReserved(from->getReserved());
}

uint16_t packSequenceControl(uint8_t fragmentNumber, uint16_t sequenceNumber)
{
return (fragmentNumber & 0xF) | ((sequenceNumber & 0xFFF) << 4);
}

void writeSequenceControl(MemoryOutputStream& stream, uint8_t fragmentNumber, uint16_t sequenceNumber)
{
stream.writeUint16Le(packSequenceControl(fragmentNumber, sequenceNumber));
}

void readSequenceControl(MemoryInputStream& stream, int& fragmentNumber, ieee80211::SequenceNumberCyclic& sequenceNumber)
{
auto sequenceControl = stream.readUint16Le();
fragmentNumber = sequenceControl & 0xF;
sequenceNumber = ieee80211::SequenceNumberCyclic((sequenceControl >> 4) & 0xFFF);
}

} // namespace

namespace ieee80211 {
Expand Down Expand Up @@ -162,8 +179,7 @@ void Ieee80211MacHeaderSerializer::serialize(MemoryOutputStream& stream, const P
stream.writeMacAddress(mgmtHeader->getReceiverAddress());
stream.writeMacAddress(mgmtHeader->getTransmitterAddress());
stream.writeMacAddress(mgmtHeader->getAddress3());
stream.writeUint4(mgmtHeader->getFragmentNumber());
stream.writeNBitsOfUint64Be(mgmtHeader->getSequenceNumber().get(), 12);
writeSequenceControl(stream, mgmtHeader->getFragmentNumber(), mgmtHeader->getSequenceNumber().get());
if (mgmtHeader->getOrder())
stream.writeUint32Be(0);
if (type == ST_ACTION) {
Expand Down Expand Up @@ -325,8 +341,7 @@ void Ieee80211MacHeaderSerializer::serialize(MemoryOutputStream& stream, const P
stream.writeMacAddress(dataHeader->getReceiverAddress());
stream.writeMacAddress(dataHeader->getTransmitterAddress());
stream.writeMacAddress(dataHeader->getAddress3());
stream.writeUint4(dataHeader->getFragmentNumber());
stream.writeNBitsOfUint64Be(dataHeader->getSequenceNumber().get(), 12);
writeSequenceControl(stream, dataHeader->getFragmentNumber(), dataHeader->getSequenceNumber().get());
if (dataHeader->getFromDS() && dataHeader->getToDS())
stream.writeMacAddress(dataHeader->getAddress4());
if (type == ST_DATA_WITH_QOS) {
Expand Down Expand Up @@ -385,8 +400,11 @@ const Ptr<Chunk> Ieee80211MacHeaderSerializer::deserialize(MemoryInputStream& st
mgmtHeader->setReceiverAddress(stream.readMacAddress());
mgmtHeader->setTransmitterAddress(stream.readMacAddress());
mgmtHeader->setAddress3(stream.readMacAddress());
mgmtHeader->setFragmentNumber(stream.readUint4());
mgmtHeader->setSequenceNumber(SequenceNumberCyclic(stream.readNBitsToUint64Be(12)));
int fragmentNumber;
SequenceNumberCyclic sequenceNumber;
readSequenceControl(stream, fragmentNumber, sequenceNumber);
mgmtHeader->setFragmentNumber(fragmentNumber);
mgmtHeader->setSequenceNumber(sequenceNumber);
if (order)
stream.readUint32Be();
return mgmtHeader;
Expand All @@ -398,8 +416,11 @@ const Ptr<Chunk> Ieee80211MacHeaderSerializer::deserialize(MemoryInputStream& st
actionFrame->setReceiverAddress(stream.readMacAddress());
actionFrame->setTransmitterAddress(stream.readMacAddress());
actionFrame->setAddress3(stream.readMacAddress());
actionFrame->setFragmentNumber(stream.readUint4());
actionFrame->setSequenceNumber(SequenceNumberCyclic(stream.readNBitsToUint64Be(12)));
int fragmentNumber;
SequenceNumberCyclic sequenceNumber;
readSequenceControl(stream, fragmentNumber, sequenceNumber);
actionFrame->setFragmentNumber(fragmentNumber);
actionFrame->setSequenceNumber(sequenceNumber);
if (order)
stream.readUint32Be();
actionFrame->setCategory(stream.readByte());
Expand Down Expand Up @@ -572,8 +593,11 @@ const Ptr<Chunk> Ieee80211MacHeaderSerializer::deserialize(MemoryInputStream& st
dataHeader->setReceiverAddress(stream.readMacAddress());
dataHeader->setTransmitterAddress(stream.readMacAddress());
dataHeader->setAddress3(stream.readMacAddress());
dataHeader->setFragmentNumber(stream.readUint4());
dataHeader->setSequenceNumber(SequenceNumberCyclic(stream.readNBitsToUint64Be(12)));
int fragmentNumber;
SequenceNumberCyclic sequenceNumber;
readSequenceControl(stream, fragmentNumber, sequenceNumber);
dataHeader->setFragmentNumber(fragmentNumber);
dataHeader->setSequenceNumber(sequenceNumber);
if (dataHeader->getFromDS() && dataHeader->getToDS())
dataHeader->setAddress4(stream.readMacAddress());
if (type == ST_DATA_WITH_QOS) {
Expand Down Expand Up @@ -618,4 +642,3 @@ const Ptr<Chunk> Ieee80211MacTrailerSerializer::deserialize(MemoryInputStream& s
} // namespace ieee80211

} // namespace inet

63 changes: 47 additions & 16 deletions src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚩 Reassociation handler missing sendAssocNotification unlike association handler

In handleAssociationRequestFrame (Ieee80211MgmtAp.cc:233), when a STA transitions to ASSOCIATED, sendAssocNotification is called. However, handleReassociationRequestFrame (Ieee80211MgmtAp.cc:268-269) sets the station to ASSOCIATED without calling sendAssocNotification. This is a pre-existing inconsistency not introduced by this PR, but since the PR touched this function to add allocateAssociationId, it may be worth addressing in the same change for completeness.

(Refers to lines 268-269)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solved in the last commit added to the PR

Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@
#include "inet/common/ModuleAccess.h"
#include "inet/common/Simsignals.h"
#include "inet/linklayer/common/MacAddressTag_m.h"

#ifdef INET_WITH_ETHERNET
#include "inet/linklayer/ethernet/common/EthernetMacHeader_m.h"
#endif // ifdef INET_WITH_ETHERNET

#include "inet/linklayer/ieee80211/mac/contract/IFrameSequenceHandler.h"
#include "inet/linklayer/ieee80211/mac/framesequence/FrameSequenceContext.h"
#include "inet/linklayer/ieee80211/mac/Ieee80211Frame_m.h"
#include "inet/linklayer/ieee80211/mac/Ieee80211SubtypeTag_m.h"
#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.h"
#include "inet/networklayer/common/NetworkInterface.h"
#include "inet/physicallayer/wireless/ieee80211/packetlevel/Ieee80211Radio.h"

namespace inet {
Expand Down Expand Up @@ -61,6 +63,7 @@ void Ieee80211MgmtAp::initialize(int stage)
// subscribe for notifications
cModule *radioModule = getModuleFromPar<cModule>(par("radioModule"), this);
radioModule->subscribe(Ieee80211Radio::radioChannelChangedSignal, this);
getContainingNicModule(this)->subscribe(IFrameSequenceHandler::frameSequenceFinishedSignal, this);

// start beacon timer (randomize startup time)
beaconTimer = new cMessage("beaconTimer");
Expand Down Expand Up @@ -93,6 +96,34 @@ void Ieee80211MgmtAp::receiveSignal(cComponent *source, simsignal_t signalID, in
}
}

void Ieee80211MgmtAp::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details)
{
Enter_Method("%s", cComponent::getSignalName(signalID));

if (signalID == IFrameSequenceHandler::frameSequenceFinishedSignal) {
auto context = check_and_cast<FrameSequenceContext *>(obj);
if (context->getNumSteps() >= 2) {
auto transmitStep = dynamic_cast<ITransmitStep *>(context->getStepBeforeLast());
auto receiveStep = dynamic_cast<IReceiveStep *>(context->getLastStep());
if (transmitStep && receiveStep &&
transmitStep->getCompletion() == IFrameSequenceStep::Completion::ACCEPTED &&
receiveStep->getCompletion() == IFrameSequenceStep::Completion::ACCEPTED) {
auto responseHeader = dynamicPtrCast<const Ieee80211MgmtHeader>(transmitStep->getFrameToTransmit()->peekAtFront<Ieee80211MacHeader>());
if (responseHeader != nullptr && (responseHeader->getType() == ST_ASSOCIATIONRESPONSE || responseHeader->getType() == ST_REASSOCIATIONRESPONSE)) {
auto ackHeader = receiveStep->getReceivedFrame()->peekAtFront<Ieee80211MacHeader>();
if (ackHeader->getType() == ST_ACK) {
if (responseHeader->getType() == ST_ASSOCIATIONRESPONSE && mib->bssAccessPointData.stations[responseHeader->getReceiverAddress()] != Ieee80211Mib::ASSOCIATED)
sendAssocNotification(responseHeader->getReceiverAddress());
mib->bssAccessPointData.stations[responseHeader->getReceiverAddress()] = Ieee80211Mib::ASSOCIATED;
}
}
}
}
}
else
Ieee80211MgmtApBase::receiveSignal(source, signalID, obj, details);
}

Ieee80211MgmtAp::StaInfo *Ieee80211MgmtAp::lookupSenderSTA(const Ptr<const Ieee80211MgmtHeader>& header)
{
auto it = staList.find(header->getTransmitterAddress());
Expand Down Expand Up @@ -144,8 +175,10 @@ void Ieee80211MgmtAp::handleAuthenticationFrame(Packet *packet, const Ptr<const
// receives authentication frame number 1 from STA, which will cause the AP to return an Auth-Error
// making the MN STA to start the handover process all over again.
if (frameAuthSeq == 1) {
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED)
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED) {
sendDisAssocNotification(sta->address);
mib->releaseAssociationId(sta->address);
}
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::NOT_AUTHENTICATED;
sta->authSeqExpected = 1;
}
Expand Down Expand Up @@ -179,8 +212,10 @@ void Ieee80211MgmtAp::handleAuthenticationFrame(Packet *packet, const Ptr<const

// update status
if (isLast) {
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED)
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED) {
sendDisAssocNotification(sta->address);
mib->releaseAssociationId(sta->address);
}
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::AUTHENTICATED; // TODO only when ACK of this frame arrives
EV << "STA authenticated\n";
}
Expand All @@ -199,8 +234,10 @@ void Ieee80211MgmtAp::handleDeauthenticationFrame(Packet *packet, const Ptr<cons

if (sta) {
// mark STA as not authenticated; alternatively, it could also be removed from staList
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED)
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED) {
sendDisAssocNotification(sta->address);
mib->releaseAssociationId(sta->address);
}
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::NOT_AUTHENTICATED;
sta->authSeqExpected = 1;
}
Expand All @@ -223,15 +260,10 @@ void Ieee80211MgmtAp::handleAssociationRequestFrame(Packet *packet, const Ptr<co

delete packet;

// mark STA as associated
if (mib->bssAccessPointData.stations[sta->address] != Ieee80211Mib::ASSOCIATED)
sendAssocNotification(sta->address);
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::ASSOCIATED; // TODO this should only take place when MAC receives the ACK for the response

// send OK response
const auto& body = makeShared<Ieee80211AssociationResponseFrame>();
body->setStatusCode(SC_SUCCESSFUL);
body->setAid(0); // TODO
body->setAid(mib->allocateAssociationId(sta->address));
body->setSupportedRates(supportedRates);
body->setChunkLength(B(2 + 2 + 2 + body->getSupportedRates().numRates + 2));
sendManagementFrame("AssocResp-OK", body, ST_ASSOCIATIONRESPONSE, sta->address);
Expand Down Expand Up @@ -259,13 +291,10 @@ void Ieee80211MgmtAp::handleReassociationRequestFrame(Packet *packet, const Ptr<

delete packet;

// mark STA as associated
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::ASSOCIATED; // TODO this should only take place when MAC receives the ACK for the response

// send OK response
const auto& body = makeShared<Ieee80211ReassociationResponseFrame>();
body->setStatusCode(SC_SUCCESSFUL);
body->setAid(0); // TODO
body->setAid(mib->allocateAssociationId(sta->address));
body->setSupportedRates(supportedRates);
body->setChunkLength(B(2 + (2 + ssid.length()) + (2 + supportedRates.numRates) + 6));
sendManagementFrame("ReassocResp-OK", body, ST_REASSOCIATIONRESPONSE, sta->address);
Expand All @@ -282,8 +311,10 @@ void Ieee80211MgmtAp::handleDisassociationFrame(Packet *packet, const Ptr<const
delete packet;

if (sta) {
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED)
if (mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED) {
sendDisAssocNotification(sta->address);
mib->releaseAssociationId(sta->address);
}
mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::AUTHENTICATED;
}
}
Expand Down Expand Up @@ -348,10 +379,10 @@ void Ieee80211MgmtAp::stop()
{
cancelEvent(beaconTimer);
staList.clear();
mib->bssAccessPointData.associationIds.clear();
Ieee80211MgmtApBase::stop();
}

} // namespace ieee80211

} // namespace inet

2 changes: 1 addition & 1 deletion src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class INET_API Ieee80211MgmtAp : public Ieee80211MgmtApBase

/** Called by the signal handler whenever a change occurs we're interested in */
virtual void receiveSignal(cComponent *source, simsignal_t signalID, intval_t value, cObject *details) override;
virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override;

/** Utility function: return sender STA's entry from our STA list, or nullptr if not in there */
virtual StaInfo *lookupSenderSTA(const Ptr<const Ieee80211MgmtHeader>& header);
Expand Down Expand Up @@ -117,4 +118,3 @@ class INET_API Ieee80211MgmtAp : public Ieee80211MgmtApBase
} // namespace inet

#endif

27 changes: 26 additions & 1 deletion src/inet/linklayer/ieee80211/mib/Ieee80211Mib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ void Ieee80211Mib::initialize(int stage)
WATCH(bssStationData.stationType);
WATCH(bssStationData.isAssociated);
WATCH(bssAccessPointData.stations);
WATCH(bssAccessPointData.associationIds);
WATCH_EXPR("modeStr", getModeStr(mode));
WATCH_EXPR("stationTypeStr", getStationTypeStr(bssStationData.stationType));
WATCH_EXPR("qosStr", qos ? ", QoS" : ", Non-QoS");
Expand Down Expand Up @@ -58,7 +59,31 @@ const char *Ieee80211Mib::getStationTypeStr(Ieee80211Mib::BssStationType station
}
}

short Ieee80211Mib::allocateAssociationId(const MacAddress& address)
{
auto existing = bssAccessPointData.associationIds.find(address);
if (existing != bssAccessPointData.associationIds.end())
return existing->second;
for (short aid = 1; aid <= 2007; aid++) {
bool used = false;
for (const auto& entry : bssAccessPointData.associationIds)
if (entry.second == aid) {
used = true;
break;
}
if (!used) {
bssAccessPointData.associationIds[address] = aid;
return aid;
}
}
throw cRuntimeError("No IEEE 802.11 association ID is available");
}

void Ieee80211Mib::releaseAssociationId(const MacAddress& address)
{
bssAccessPointData.associationIds.erase(address);
}

} // namespace ieee80211

} // namespace inet

4 changes: 3 additions & 1 deletion src/inet/linklayer/ieee80211/mib/Ieee80211Mib.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class INET_API Ieee80211Mib : public SimpleModule
class INET_API BssAccessPointData {
public:
std::map<MacAddress, BssMemberStatus> stations;
std::map<MacAddress, short> associationIds;
};

public:
Expand All @@ -68,11 +69,12 @@ class INET_API Ieee80211Mib : public SimpleModule
static const char *getModeStr(Ieee80211Mib::Mode mode);
static const char *getStationTypeStr(Ieee80211Mib::BssStationType stationType);
std::string getSsidStr() const;
short allocateAssociationId(const MacAddress& address);
void releaseAssociationId(const MacAddress& address);
};

} // namespace ieee80211

} // namespace inet

#endif

Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ const IReceptionResult *Ieee80211LayeredOfdmReceiver::computeReceptionResult(con
if (isCompliant) {
auto packet = signalFieldPacketModel != nullptr ? signalFieldPacketModel->getPacket() : packetModel->getPacket();
const auto& signalFieldBytesChunk = packet->peekAllAsBytes();
uint8_t rate = signalFieldBytesChunk->getByte(0) >> 4;
uint8_t rate = signalFieldBytesChunk->getByte(0) & 0x0F;
mode = Ieee80211OfdmCompliantModes::findCompliantMode(rate, channelSpacing);
if (mode == nullptr)
const_cast<Packet *>(packet)->setBitError(true);
Expand Down Expand Up @@ -492,4 +492,3 @@ Ieee80211LayeredOfdmReceiver::~Ieee80211LayeredOfdmReceiver()

} // namespace physicallayer
} // namespace inet

Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@

#include "inet/common/ProtocolTag_m.h"
#include "inet/common/packet/chunk/BitCountChunk.h"
#include "inet/common/packet/chunk/BytesChunk.h"
#include "inet/physicallayer/wireless/ieee80211/bitlevel/Ieee80211LayeredOfdmReceiver.h"
#include "inet/physicallayer/wireless/ieee80211/bitlevel/Ieee80211LayeredOfdmTransmitter.h"
#include "inet/physicallayer/wireless/ieee80211/packetlevel/Ieee80211OfdmSignalField.h"
#include "inet/physicallayer/wireless/ieee80211/packetlevel/Ieee80211PhyHeader_m.h"
#include "inet/physicallayer/wireless/ieee80211/packetlevel/Ieee80211Tag_m.h"

Expand Down Expand Up @@ -43,17 +45,28 @@ void Ieee80211OfdmRadio::decapsulate(Packet *packet) const
{
if (!packet->hasBitError()) {
auto ofdmReceiver = check_and_cast<const Ieee80211LayeredOfdmReceiver *>(receiver);
const auto& phyHeader = packet->popAtFront<Ieee80211OfdmPhyHeader>();
const auto& phyHeaderBytes = packet->peekDataAt<BytesChunk>(b(0), B(5), Chunk::PF_ALLOW_IMPROPERLY_REPRESENTED);
auto signalField = unpackIeee80211OfdmSignalField(phyHeaderBytes->getByte(0), phyHeaderBytes->getByte(1), phyHeaderBytes->getByte(2));
const auto& phyHeader = makeShared<Ieee80211OfdmPhyHeader>();
phyHeader->setRate(signalField.rate);
phyHeader->setReserved(signalField.reserved);
phyHeader->setLengthField(B(signalField.length));
phyHeader->setParity(signalField.parity);
phyHeader->setTail(signalField.tail);
phyHeader->setService(phyHeaderBytes->getByte(3) | (phyHeaderBytes->getByte(4) << 8));
packet->eraseAtFront(B(5));
auto mode = ofdmReceiver->getMode(packet);
auto dataLength = B(phyHeader->getLengthField());
auto paddingLength = mode->getDataMode()->getPaddingLength(dataLength);
packet->popAtBack(std::min(paddingLength + b(6), packet->getDataLength()));
packet->setBitError(packet->getDataLength() != dataLength);
auto trailerLength = std::min(paddingLength + b(6), packet->getDataLength());
if (trailerLength > b(0))
packet->popAtBack(trailerLength,
Chunk::PF_ALLOW_INCORRECT | Chunk::PF_ALLOW_INCOMPLETE | Chunk::PF_ALLOW_IMPROPERLY_REPRESENTED);
packet->setBitError(packet->hasBitError() || packet->getDataLength() != dataLength);
packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::ieee80211Mac);
}
}

} // namespace physicallayer

} // namespace inet

Loading
Loading