%description: Test 802.11 frame sequences %includes: #include #include "inet/linklayer/common/MACAddress.h" #include "inet/linklayer/ieee80211/mac/contract/IFrameSequence.h" #include "inet/linklayer/ieee80211/mac/framesequence/FrameSequenceContext.h" #include "inet/linklayer/ieee80211/mac/framesequence/FrameSequenceStep.h" #include "inet/linklayer/ieee80211/mac/framesequence/GenericFrameSequences.h" %inifile: omnetpp.ini #debug-on-errors = true #debugger-attach-on-error = true %global: using namespace inet; using namespace inet::ieee80211; enum Role { ORIGINATOR, RECIPIENT, }; FrameSequenceContext *originatorContext = new FrameSequenceContext(MACAddress(), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); FrameSequenceContext *recipientContext = new FrameSequenceContext(MACAddress(), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); class DataFs : public IFrameSequence { protected: int firstStep = -1; int step = -1; public: virtual void startSequence(FrameSequenceContext *context, int firstStep) override { this->firstStep = firstStep; step = 0; } virtual IFrameSequenceStep *prepareStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: { Ieee80211Frame *frame = new Ieee80211Frame("DATA"); frame->setType(ST_DATA); return new TransmitStep(frame, 0); } case 1: return nullptr; default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: return new ReceiveStep(); case 1: return nullptr; default: throw cRuntimeError("Unknown step"); } } } virtual bool completeStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: step++; return true; default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: { IReceiveStep *receiveStep = check_and_cast(context->getStep(firstStep + step)); step++; return receiveStep->getReceivedFrame()->getType() == ST_DATA; } default: throw cRuntimeError("Unknown step"); } } } virtual std::string getHistory() override { return ""; } }; class INET_API AckFs : public IFrameSequence { protected: int firstStep = -1; int step = -1; public: virtual void startSequence(FrameSequenceContext *context, int firstStep) override { this->firstStep = firstStep; step = 0; } virtual IFrameSequenceStep *prepareStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: return new ReceiveStep(); case 1: return nullptr; default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: { Ieee80211Frame *frame = new Ieee80211Frame("ACK"); frame->setType(ST_ACK); return new TransmitStep(frame, 0); } case 1: return nullptr; default: throw cRuntimeError("Unknown step"); } } } virtual bool completeStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: { IReceiveStep *receiveStep = check_and_cast(context->getStep(firstStep + step)); step++; return receiveStep->getReceivedFrame()->getType() == ST_ACK; } default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: step++; return true; default: throw cRuntimeError("Unknown step"); } } } virtual std::string getHistory() override { return ""; } }; class RtsCtsFs : public IFrameSequence { protected: int firstStep = -1; int step = -1; public: RtsCtsFs() { } virtual void startSequence(FrameSequenceContext *context, int firstStep) override { step = 0; this->firstStep = firstStep; } IFrameSequenceStep *prepareStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: { Ieee80211Frame *frame = new Ieee80211Frame("RTS"); frame->setType(ST_RTS); return new TransmitStep(frame, 0); } case 1: return new ReceiveStep(); case 2: return nullptr; default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: return new ReceiveStep(); case 1: { Ieee80211Frame *frame = new Ieee80211Frame("CTS"); frame->setType(ST_CTS); return new TransmitStep(frame, 0); } case 2: return nullptr; default: throw cRuntimeError("Unknown step"); } } } bool completeStep(FrameSequenceContext *context) override { if (context == originatorContext) { switch (step) { case 0: step++; return true; case 1: { IReceiveStep *receiveStep = check_and_cast(context->getStep(firstStep + step)); step++; return receiveStep->getReceivedFrame()->getType() == ST_CTS; } default: throw cRuntimeError("Unknown step"); } } else { switch (step) { case 0: { IReceiveStep *receiveStep = check_and_cast(context->getStep(firstStep + step)); step++; return receiveStep->getReceivedFrame()->getType() == ST_RTS; } case 1: step++; return true; default: throw cRuntimeError("Unknown step"); } } } virtual std::string getHistory() override { return ""; } }; static void runFrameSequence(IFrameSequence *originatorFrameSequence, IFrameSequence *recipientFrameSequence) { // prepare originator bool isOriginatorRunning = true; IFrameSequenceStep *originatorStep = nullptr; Ieee80211Frame *originatorFrame = nullptr; originatorContext = new FrameSequenceContext(MACAddress(ORIGINATOR), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); originatorFrameSequence->startSequence(originatorContext, 0); // prepare recipient bool isRecipientRunning = true; IFrameSequenceStep *recipientStep = nullptr; Ieee80211Frame *recipientFrame = nullptr; recipientContext = new FrameSequenceContext(MACAddress(RECIPIENT), nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); recipientFrameSequence->startSequence(recipientContext, 0); // run frame sequence while (isOriginatorRunning || isRecipientRunning) { if (isOriginatorRunning) { // advance originator originatorStep = originatorFrameSequence->prepareStep(originatorContext); if (originatorStep == nullptr) { EV_INFO << "originator complete\n"; isOriginatorRunning = false; } else originatorContext->addStep(originatorStep); } if (isRecipientRunning) { // advance recipient recipientStep = recipientFrameSequence->prepareStep(recipientContext); if (recipientStep == nullptr) { EV_INFO << "recipient complete\n"; isRecipientRunning = false; } else recipientContext->addStep(recipientStep); } // handle originator transmit if (isOriginatorRunning) { if (originatorStep->getType() == IFrameSequenceStep::Type::TRANSMIT) { ITransmitStep *transmitStep = check_and_cast(originatorStep); originatorFrame = transmitStep->getFrameToTransmit(); EV_INFO << "originator transmit: " << originatorFrame->getName() << "\n"; } } // handle recipient transmit if (isRecipientRunning) { if (recipientStep->getType() == IFrameSequenceStep::Type::TRANSMIT) { ITransmitStep *transmitStep = check_and_cast(recipientStep); recipientFrame = transmitStep->getFrameToTransmit(); EV_INFO << "recipient transmit: " << recipientFrame->getName() << "\n"; } } // handle originator receive if (isOriginatorRunning) { if (originatorStep->getType() == IFrameSequenceStep::Type::RECEIVE) { IReceiveStep *receiveStep = check_and_cast(originatorStep); ASSERT(recipientFrame); receiveStep->setFrameToReceive(recipientFrame); EV_INFO << "originator receive: " << recipientFrame->getName() << "\n"; } } // handle recipient receive if (isRecipientRunning) { if (recipientStep->getType() == IFrameSequenceStep::Type::RECEIVE) { IReceiveStep *receiveStep = check_and_cast(recipientStep); ASSERT(originatorFrame); receiveStep->setFrameToReceive(originatorFrame); EV_INFO << "recipient receive: " << originatorFrame->getName() << "\n"; } } // complete originator if (isOriginatorRunning) { bool originatorStepCompletion = originatorFrameSequence->completeStep(originatorContext); if (!originatorStepCompletion) { EV_INFO << "originator abort\n"; isOriginatorRunning = false; } } // complete recipient if (isRecipientRunning) { bool recipientStepCompletion = recipientFrameSequence->completeStep(recipientContext); if (!recipientStepCompletion) { EV_INFO << "recipient abort\n"; isRecipientRunning = false; } } delete originatorFrame; delete recipientFrame; originatorFrame = nullptr; recipientFrame = nullptr; } delete originatorFrameSequence; delete recipientFrameSequence; } bool applyOptional(OptionalFs *frameSequence, FrameSequenceContext *context) { return true; } bool skipOptional(OptionalFs *frameSequence, FrameSequenceContext *context) { return false; } bool skipRepeated(RepeatingFs *frameSequence, FrameSequenceContext *context) { return false; } bool applyRepeatedOneTime(RepeatingFs *frameSequence, FrameSequenceContext *context) { return frameSequence->getCount() <= 0; } bool applyRepeatedTwoTimes(RepeatingFs *frameSequence, FrameSequenceContext *context) { return frameSequence->getCount() <= 1; } int selectFirstAlternative(AlternativesFs *frameSequence, FrameSequenceContext *context) { return 0; } int selectSecondAlternative(AlternativesFs *frameSequences, FrameSequenceContext *context) { return 1; } int selectSubsequentAlternativeCounter = 0; int selectSubsequentAlternative(AlternativesFs *frameSequences, FrameSequenceContext *context) { if (context == originatorContext) return selectSubsequentAlternativeCounter++ / 2; else { selectSubsequentAlternativeCounter++; if (selectSubsequentAlternativeCounter < 2) return -1; else return selectSubsequentAlternativeCounter / 2; } } %activity: EV_INFO << "\nTesting DATA frame sequence\n"; runFrameSequence(new DataFs(), new DataFs()); EV_INFO << "\nTesting sequential frame sequence\n"; runFrameSequence(new SequentialFs({new DataFs(), new DataFs()}), new SequentialFs({new DataFs(), new DataFs()})); EV_INFO << "\nTesting applied optional frame sequence\n"; runFrameSequence(new OptionalFs(new DataFs(), applyOptional), new OptionalFs(new DataFs(), applyOptional)); EV_INFO << "\nTesting skipped optional frame sequence\n"; runFrameSequence(new OptionalFs(new DataFs(), skipOptional), new OptionalFs(new DataFs(), skipOptional)); EV_INFO << "\nTesting skipped repeated frame sequence\n"; runFrameSequence(new RepeatingFs(new DataFs(), skipRepeated), new RepeatingFs(new DataFs(), skipRepeated)); EV_INFO << "\nTesting one time applied repeated frame sequence\n"; runFrameSequence(new RepeatingFs(new DataFs(), applyRepeatedOneTime), new RepeatingFs(new DataFs(), applyRepeatedOneTime)); EV_INFO << "\nTesting alternative frame sequence\n"; runFrameSequence(new AlternativesFs({new DataFs()}, selectFirstAlternative), new AlternativesFs({new DataFs()}, selectFirstAlternative)); EV_INFO << "\nTesting DATA ACK frame sequence\n"; runFrameSequence(new SequentialFs({new DataFs(), new AckFs()}), new SequentialFs({new DataFs(), new AckFs()})); EV_INFO << "\nTesting skipped [RTS CTS] DATA ACK frame sequence\n"; runFrameSequence(new SequentialFs({new OptionalFs(new RtsCtsFs(), skipOptional), new DataFs(), new AckFs()}), new SequentialFs({new OptionalFs(new RtsCtsFs(), skipOptional), new DataFs(), new AckFs()})); EV_INFO << "\nTesting applied [RTS CTS] DATA ACK frame sequence\n"; runFrameSequence(new SequentialFs({new OptionalFs(new RtsCtsFs(), applyOptional), new DataFs(), new AckFs()}), new SequentialFs({new OptionalFs(new RtsCtsFs(), applyOptional), new DataFs(), new AckFs()})); %contains: stdout Testing DATA frame sequence originator transmit: DATA recipient receive: DATA originator complete recipient complete Testing sequential frame sequence originator transmit: DATA recipient receive: DATA originator transmit: DATA recipient receive: DATA originator complete recipient complete Testing applied optional frame sequence originator transmit: DATA recipient receive: DATA originator complete recipient complete Testing skipped optional frame sequence originator complete recipient complete Testing skipped repeated frame sequence originator complete recipient complete Testing one time applied repeated frame sequence originator transmit: DATA recipient receive: DATA originator complete recipient complete Testing alternative frame sequence originator transmit: DATA recipient receive: DATA originator complete recipient complete Testing DATA ACK frame sequence originator transmit: DATA recipient receive: DATA recipient transmit: ACK originator receive: ACK originator complete recipient complete Testing skipped [RTS CTS] DATA ACK frame sequence originator transmit: DATA recipient receive: DATA recipient transmit: ACK originator receive: ACK originator complete recipient complete Testing applied [RTS CTS] DATA ACK frame sequence originator transmit: RTS recipient receive: RTS recipient transmit: CTS originator receive: CTS originator transmit: DATA recipient receive: DATA recipient transmit: ACK originator receive: ACK originator complete recipient complete