EPONImplementationforOMNet++
0.8Beta
|
EPON_mac class is actually the EtherMAC2 class modified. More...
#include <EPON_mac.h>
Public Member Functions | |
EPON_mac () | |
virtual | ~EPON_mac () |
Protected Member Functions | |
virtual void | initialize () |
virtual void | finalize () |
virtual void | initializeTxrate () |
virtual void | handleMessage (cMessage *msg) |
virtual void | startFrameTransmission () |
When Tx starts we have already added Logical Link Identifier. | |
virtual void | processFrameFromUpperLayer (EtherFrame *frame) |
virtual void | processMsgFromNetwork (cPacket *msg) |
virtual void | handleEndIFGPeriod () |
virtual void | handleEndTxPeriod () |
virtual void | updateHasSubcribers () |
void | scheduleEndTxPeriod (cPacket *frame) |
Protected Attributes | |
cOutVector | TxRateVector |
EPON_mac class is actually the EtherMAC2 class modified.
From the INET framework documentation:
"A simplified version of EtherMAC. Since modern Ethernets typically operate over duplex links where's no contention, the original CSMA/CD algorithm is no longer needed. This simplified implementation doesn't contain CSMA/CD, frames are just simply queued and sent out one by one."
We use this class for some basic operations. The first one (and most important) is to change the way the frame is transmitted. On EPON network the Ethernet pre-amble includes the LLID (Logical Link ID). This LLID is carried, from the higher layers, inside the cMessage ControInfo. Thus what we do here is too remove the ControlInfo and use them in EtherFrameWithLLID. The original message is encapsulated inside this frame. Finally the preamble is added (-2 Bytes cause they are already in the EtherFrameWithLLID) and the SFD. For incoming frame from the network we do the opposite process (decapsulate the frame and add ControlInfo)
The second usage of this module is to handle the IFG times that, based on the drafts, should be there.
Finally note here that the basic control of the transmission times is located in the MacCtl modules (ONUMacCtl & OLTMacCtl), thus most of the times the queue this module has is not used at all.
{ }
EPON_mac::~EPON_mac | ( | ) | [virtual] |
{ for (int i=0; i<txQueue.length(); i++) delete txQueue.pop(); }
void EPON_mac::finalize | ( | ) | [protected, virtual] |
{ // Do logging if (!disabled) { simtime_t t = simTime(); if (t>0) { // recordScalar("frames/sec sent", TxRateVector); } } }
void EPON_mac::handleEndIFGPeriod | ( | ) | [protected, virtual] |
void EPON_mac::handleEndTxPeriod | ( | ) | [protected, virtual] |
{ if (hasSubscribers) { // fire notification notifDetails.setPacket((cPacket *)txQueue.front()); nb->fireChangeNotification(NF_PP_TX_END, ¬ifDetails); } if (checkAndScheduleEndPausePeriod()) return; // Deletes the frame... and log stats EtherMACBase::handleEndTxPeriod(); beginSendFrames(); }
void EPON_mac::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
{ if (!connected) processMessageWhenNotConnected(msg); else if (disabled) processMessageWhenDisabled(msg); else if (msg->isSelfMessage()) { EV << "Self-message " << msg << " received\n"; if (msg == endTxMsg) handleEndTxPeriod(); else if (msg == endIFGMsg) handleEndIFGPeriod(); else if (msg == endPauseMsg) handleEndPausePeriod(); else error("Unknown self message received!"); } else { if (msg->getArrivalGate() == gate("upperLayerIn")) processFrameFromUpperLayer(check_and_cast<EtherFrame *>(msg)); else if (msg->getArrivalGate() == gate("phys$i") || msg->getArrivalGate() == gate("direct")) { processMsgFromNetwork(check_and_cast<cPacket *>(msg)); }else error("Message received from unknown gate!"); } if (ev.isGUI()) updateDisplayString(); }
void EPON_mac::initialize | ( | ) | [protected, virtual] |
{ EtherMACBase::initialize(); duplexMode = true; calculateParameters(); beginSendFrames(); }
void EPON_mac::initializeTxrate | ( | ) | [protected, virtual] |
{ // if we're connected, find the gate with transmission rate txrate = 0; if (connected) { // obtain txrate from channel. As a side effect, this also asserts // that the other end is an EPON_mac, since normal EtherMAC // insists that the connection has *no* datarate set. // if we're connected, get the gate with transmission rate cChannel *datarateChannel = physOutGate->getTransmissionChannel(); txrate = datarateChannel->par("datarate").doubleValue(); } }
void EPON_mac::processFrameFromUpperLayer | ( | EtherFrame * | frame | ) | [protected, virtual] |
{ EV << "Received frame from upper layer: " << frame << endl; if (frame->getDest().equals(address)) { error("logic error: frame %s from higher layer has local MAC address as dest (%s)", frame->getFullName(), frame->getDest().str().c_str()); } if (frame->getByteLength() > MAX_ETHERNET_FRAME_D1Q) error("packet from higher layer (%d bytes) exceeds maximum Ethernet frame size (%d)", frame->getByteLength(), MAX_ETHERNET_FRAME_D1Q); // must be EtherFrame (or EtherPauseFrame) from upper layer bool isPauseFrame = (dynamic_cast<EtherPauseFrame*>(frame)!=NULL); if (!isPauseFrame) { numFramesFromHL++; if (txQueueLimit && txQueue.length()>txQueueLimit) error("txQueue length exceeds %d -- this is probably due to " "a bogus app model generating excessive traffic " "(or if this is normal, increase txQueueLimit!)", txQueueLimit); // fill in src address if not set if (frame->getSrc().isUnspecified()) frame->setSrc(address); // Note: take the control from the origial frame. Dup() does not clone it. EPON_LLidCtrlInfo *nfo=dynamic_cast<EPON_LLidCtrlInfo *>(frame->getControlInfo()); EtherFrameWithLLID * llid_eth = new EtherFrameWithLLID(); llid_eth->setName(frame->getName()); if (nfo != NULL){ EV << "Control Info FOUND"<<endl; // Convert to EtherFrameWithLLID uint16_t tmpLlid = nfo->llid; // Relay didn't knew the llid... if (tmpLlid == -1) tmpLlid=LLID_EPON_BC; llid_eth->setLlid(tmpLlid); }else{ // MPCP Frames may not have LLIDs // Encapsulate BC uint16_t tmpLlid = LLID_EPON_BC; llid_eth->setLlid(tmpLlid); } /* * YOU HAVE TO MANUALLY SET THE BYTE LENGTH... */ llid_eth->addByteLength(2); // add for the 2 bytes in the preamble frame->addByteLength(EPON_PREAMBLE_BYTES+SFD_BYTES); // add the rest llid_eth->encapsulate(frame); //frame=NULL; // store frame and possibly begin transmitting EV << "Packet " << llid_eth << " arrived from higher layers, enqueueing\n"; EV << "After enc Size " << llid_eth->getByteLength()<< " \n"; EV << "Orig. Size " << frame->getByteLength()<< " \n"; txQueue.insert(llid_eth); } else { EV << "PAUSE received from higher layer\n"; // PAUSE frames enjoy priority -- they're transmitted before all other frames queued up if (!txQueue.empty()) txQueue.insertBefore(txQueue.front(), frame); // front() frame is probably being transmitted else txQueue.insert(frame); } // In any case, wait for IFG before transmitting if (transmitState == TX_IDLE_STATE) scheduleEndIFGPeriod(); }
void EPON_mac::processMsgFromNetwork | ( | cPacket * | msg | ) | [protected, virtual] |
{ //EtherMACBase::processMsgFromNetwork(msg); // the original ^ checks for frame type and for cable length... // both not applicable here... EtherFrame *ethframe = dynamic_cast<EtherFrame *>(msg); EtherFrameWithLLID * ethllid= dynamic_cast<EtherFrameWithLLID *>(msg); if ( ethframe== NULL && ethllid== NULL){ error("EPON_mac: Unrecognized Frame... Shit happens"); } // IF we have EPON frame with LLID de-capsulate if (ethllid){ ethframe = check_and_cast<EtherFrame *>(ethllid->decapsulate()); delete ethllid->decapsulate(); // Add Control Information to it EV << "IT HAD LLID INFO ... : "<<ethllid->getLlid()<<endl; if (ethframe->getControlInfo()==NULL) ethframe->setControlInfo(new EPON_LLidCtrlInfo(ethllid->getLlid()) ); // Add original pre-amble.. to be used from the base class... ethframe->addByteLength(-EPON_PREAMBLE_BYTES); ethframe->addByteLength(PREAMBLE_BYTES); // Get rid of the original delete msg; } if (hasSubscribers) { // fire notification notifDetails.setPacket(ethframe); nb->fireChangeNotification(NF_PP_RX_END, ¬ifDetails); } if (checkDestinationAddress(ethframe)) frameReceptionComplete(ethframe); }
void EPON_mac::scheduleEndTxPeriod | ( | cPacket * | frame | ) | [protected] |
{ EtherMACBase::scheduleEndTxPeriod(frame); }
void EPON_mac::startFrameTransmission | ( | ) | [protected, virtual] |
When Tx starts we have already added Logical Link Identifier.
{ EtherFrameWithLLID *origFrame = (EtherFrameWithLLID *)txQueue.front(); EV << "Transmitting a copy of frame " << origFrame << endl; EtherFrameWithLLID *frame = (EtherFrameWithLLID *) origFrame->dup(); if (hasSubscribers) { // fire notification notifDetails.setPacket(frame); nb->fireChangeNotification(NF_PP_TX_BEGIN, ¬ifDetails); } // fill in src address if not set // if (frame->getSrc().isUnspecified()) // frame->setSrc(address); // send EV << "Starting transmission of " << frame << endl; send(frame, physOutGate); scheduleEndTxPeriod(frame); // update burst variables if (frameBursting) { bytesSentInBurst = frame->getByteLength(); framesSentInBurst++; } }
void EPON_mac::updateHasSubcribers | ( | ) | [protected, virtual] |
{ hasSubscribers = nb->hasSubscribers(NF_PP_TX_BEGIN) || nb->hasSubscribers(NF_PP_TX_END) || nb->hasSubscribers(NF_PP_RX_END); }
cOutVector EPON_mac::TxRateVector [protected] |