Implementation of L-MAC (Lightweight Medium Access Protocol for Wireless Sensor Networks [van Hoesel 04] ). More...
#include <LMacLayer.h>
Inherits BaseMacLayer.
Public Member Functions | |
virtual | ~LMacLayer () |
Clean up messges. | |
virtual void | initialize (int) |
Initialization of the module and some variables. | |
virtual void | finish () |
Delete all dynamically allocated objects of the module. | |
virtual void | handleLowerMsg (cMessage *) |
Handle messages from lower layer. | |
virtual void | handleUpperMsg (cMessage *) |
Handle messages from upper layer. | |
virtual void | handleSelfMsg (cMessage *) |
Handle self messages such as timers. | |
virtual void | handleLowerControl (cMessage *msg) |
Handle control messages from lower layer. | |
virtual MacPkt * | encapsMsg (cMessage *) |
Encapsulate the NetwPkt into an MacPkt. | |
Protected Types | |
enum | States { INIT, SLEEP, CCA, WAIT_CONTROL, WAIT_DATA, SEND_CONTROL, SEND_DATA } |
MAC states. More... | |
enum | TYPES { LMAC_CONTROL = 167, LMAC_TIMEOUT = 168, LMAC_WAKEUP = 169, LMAC_SEND_DATA = 170, LMAC_SETUP_PHASE_END = 171, LMAC_CHECK_CHANNEL = 172, LMAC_SOMEBODY = 173, LMAC_DATA = 174, LMAC_START_LMAC = 175, LMAC_SEND_CONTROL = 176 } |
typedef std::list< LMacPkt * > | MacQueue |
Protected Member Functions | |
void | findNewSlot () |
find a new slot | |
void | attachSignal (MacPkt *macPkt) |
Internal function to attach a signal to the packet. | |
Protected Attributes | |
bool | SETUP_PHASE |
the setup phase is the beginning of the simulation, where only control packets at very small slot durations are exchanged. | |
cOutVector * | slotChange |
indicate how often the node needs to change its slot because of collisions | |
States | macState |
keep track of MAC state | |
Radio::RadioState | radioState |
Current state of active channel (radio), set using radio, updated via BB. | |
int | catRadioState |
category number given by bb for RadioState | |
int | catIndication |
track and publish current occupation state of medium | |
double | slotDuration |
Duration of a slot. | |
double | controlDuration |
Duration of teh control time in each slot. | |
int | mySlot |
my slot ID | |
int | numSlots |
how many slots are there | |
int | currSlot |
The current slot of the simulation. | |
short | occSlotsDirect [64] |
Occupied slots from nodes, from which I hear directly. | |
short | occSlotsAway [64] |
Occupied slots of two-hop neighbors. | |
int | reservedMobileSlots |
The first couple of slots are reserved for nodes with special needs to avoid changing slots for them (mobile nodes). | |
MacQueue | macQueue |
A queue to store packets from upper layer in case another packet is still waiting for transmission.. | |
unsigned | queueLength |
length of the queue | |
cMessage * | wakeup |
cMessage * | timeout |
cMessage * | sendData |
cMessage * | initChecker |
cMessage * | checkChannel |
cMessage * | start_lmac |
cMessage * | send_control |
double | bitrate |
the bit rate at which we transmit | |
DroppedPacket | droppedPacket |
Inspect reasons for dropped packets. | |
int | catDroppedPacket |
plus category from BB | |
int | nicId |
publish dropped packets nic wide | |
double | txPower |
Transmission power of the node. | |
Static Protected Attributes | |
static const int | LMAC_NO_RECEIVER |
dummy receiver address to indicate no pending packets in the control packet |
Implementation of L-MAC (Lightweight Medium Access Protocol for Wireless Sensor Networks [van Hoesel 04] ).
Each node has its own unique timeslot. Nodes can use their timeslots to transfer data without having to contend for the medium or having to deal with energy wasting collisions or retransmissions.
During the first 5 full frames nodes will be waking up every controlDuration to setup the network first by assigning a different timeslot to each node. Normal packets will be queued, but will be send only after the setup phase.
During its timeslot a node wakes up, checks the channel for a short random period (CCA) to check for possible collision in the slot and, if the channel is free, sends a control packet. If there is a collision it tries to change its timeslot to an empty one. After the transmission of the control packet it checks its packet queue and if its non-empty it sends a data packet.
During a foreign timeslot a node wakes up, checks the channel for 2*controlDuration period for an incoming control packet and if there in nothing it goes back to sleep and conserves energy for the rest of the timeslot. If it receives a control packet addressed for itself it stays awake for the rest of the timeslot to receive the incoming data packet.
The finite state machine of the protocol is given in the below figure:
State chart for LMAC layer
A paper describing the protocol is:
L. van Hoesel and P. Havinga. A lightweight medium access protocol (LMAC) for wireless sensor networks. In Proceedings of the 3rd International Symposium on Information Processing in Sensor Networks (IPSN), pages 55-60, Berkeley, CA, February 2004. April.
Definition at line 66 of file LMacLayer.h.
enum LMacLayer::States [protected] |
MAC states.
The MAC states help to keep track what the MAC is actually trying to do -- this is esp. useful when radio switching takes some time. SLEEP -- the node sleeps but accepts packets from the network layer RX -- MAC accepts packets from PHY layer TX -- MAC transmits a packet CCA -- Clear Channel Assessment - MAC checks whether medium is busy
Definition at line 109 of file LMacLayer.h.
{ INIT, SLEEP, CCA, WAIT_CONTROL, WAIT_DATA, SEND_CONTROL, SEND_DATA };
MacPkt * LMacLayer::encapsMsg | ( | cMessage * | msg | ) | [virtual] |
Encapsulate the NetwPkt into an MacPkt.
Encapsulates the received network-layer packet into a MacPkt and set all needed header fields.
Definition at line 676 of file LMacLayer.cc.
References NetwToMacControlInfo::getNextHopMac(), BaseMacLayer::headerLength, and BaseMacLayer::myMacAddr.
Referenced by handleUpperMsg().
{ LMacPkt *pkt = new LMacPkt(msg->getName(), msg->getKind()); pkt->setBitLength(headerLength); // copy dest address from the Control Info attached to the network // mesage by the network layer NetwToMacControlInfo* cInfo = static_cast<NetwToMacControlInfo*>(msg->removeControlInfo()); debugEV <<"CInfo removed, mac addr="<< cInfo->getNextHopMac()<<endl; pkt->setDestAddr(cInfo->getNextHopMac()); //delete the control info delete cInfo; //set the src address to own mac address (nic module getId()) pkt->setSrcAddr(myMacAddr); //encapsulate the network packet pkt->encapsulate(check_and_cast<cPacket *>(msg)); debugEV <<"pkt encapsulated\n"; return pkt; }
void LMacLayer::findNewSlot | ( | ) | [protected] |
find a new slot
Try to find a new slot after collision. If not possible, set own slot to -1 (not able to send anything)
Definition at line 645 of file LMacLayer.cc.
References mySlot, numSlots, occSlotsAway, reservedMobileSlots, and slotChange.
Referenced by handleSelfMsg().
{ // pick a random slot at the beginning and schedule the next wakeup // free the old one first int counter = 0; mySlot = intrand((numSlots - reservedMobileSlots)); while ((occSlotsAway[mySlot] != -1) && (counter < (numSlots - reservedMobileSlots))) { counter++; mySlot--; if (mySlot < 0) mySlot = (numSlots - reservedMobileSlots)-1; } if (occSlotsAway[mySlot] != -1) { EV << "ERROR: I cannot find a free slot. Cannot send data.\n"; mySlot = -1; } else { EV << "ERROR: My new slot is : " << mySlot << endl; } EV << "ERROR: I needed to find new slot\n"; slotChange->recordWithTimestamp(simTime(), getParentModule()->getParentModule()->getId()-4); }
void LMacLayer::handleLowerControl | ( | cMessage * | msg | ) | [virtual] |
Handle control messages from lower layer.
Handle transmission over messages: send the data packet or don;t do anyhting.
Reimplemented from BaseMacLayer.
Definition at line 602 of file LMacLayer.cc.
References MacToPhyInterface::getRadioState(), macState, BaseMacLayer::phy, MacToPhyInterface::setRadioState(), and Radio::SLEEP.
{ if(msg->getKind() == MacToPhyInterface::TX_OVER) { // if data is scheduled for transfer, don;t do anything. if (sendData->isScheduled()) { debugEV << " transmission of control packet over. data transfer will start soon." << endl; delete msg; return; } else { debugEV << " transmission over. nothing else is scheduled, get back to sleep." << endl; macState = SLEEP; debugEV << "Old state: ?, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); if (timeout->isScheduled()) cancelEvent(timeout); } } else if(msg->getKind() == MacToPhyInterface::RADIO_SWITCHING_OVER) { // we just switched to TX after CCA, so simply send the first sendPremable self message if ((macState == SEND_CONTROL) && (phy->getRadioState() == Radio::TX)) { scheduleAt(simTime(), send_control); } } else { EV << "control message with wrong kind -- deleting\n"; } delete msg; }
void LMacLayer::handleLowerMsg | ( | cMessage * | msg | ) | [virtual] |
Handle messages from lower layer.
Handle LMAC control packets and data packets. Recognize collisions, change own slot if necessary and remember who is using which slot.
Reimplemented from BaseMacLayer.
Definition at line 592 of file LMacLayer.cc.
References handleSelfMsg().
{ // simply pass the massage as self message, to be processed by the FSM. handleSelfMsg(msg); }
void LMacLayer::handleSelfMsg | ( | cMessage * | msg | ) | [virtual] |
Handle self messages such as timers.
Handle self messages: LMAC_SETUP_PHASE_END: end of setup phase. Change slot duration to normal and start sending data packets. The slots of the nodes should be stable now. LMAC_SEND_DATA: send the data packet. LMAC_CHECK_CHANNEL: check the channel in own slot. If busy, change the slot. If not, send a control packet. LMAC_WAKEUP: wake up the node and either check the channel before sending a control packet or wait for control packets. LMAC_TIMEOUT: go back to sleep after nothing happened.
Reimplemented from BaseMacLayer.
Definition at line 153 of file LMacLayer.cc.
References attachSignal(), controlDuration, currSlot, BaseMacLayer::decapsMsg(), findNewSlot(), BaseMacLayer::headerLength, LMAC_NO_RECEIVER, macQueue, macState, BaseMacLayer::myMacAddr, mySlot, numSlots, occSlotsAway, occSlotsDirect, BaseMacLayer::phy, reservedMobileSlots, Radio::RX, BaseLayer::sendDown(), BaseLayer::sendUp(), MacToPhyInterface::setRadioState(), SETUP_PHASE, Radio::SLEEP, slotDuration, and Radio::TX.
Referenced by handleLowerMsg().
{ switch (macState) { case INIT: if (msg->getKind() == LMAC_START_LMAC) { // the first 5 full slots we will be waking up every controlDuration to setup the network first // normal packets will be queued, but will be send only after the setup phase scheduleAt(slotDuration*5*numSlots, initChecker); coreEV << "Startup time =" << slotDuration*5*numSlots << endl; debugEV << "Scheduling the first wakeup at : " << slotDuration << endl; scheduleAt(slotDuration, wakeup); for (int i = 0; i < numSlots; i++) { occSlotsDirect[i] = -1; occSlotsAway[i] = -1; } if (myId >= reservedMobileSlots) mySlot = ((int) getParentModule()->getParentModule()->getId() )% (numSlots - reservedMobileSlots); else mySlot = myId; //occSlotsDirect[mySlot] = myMacAddr; //occSlotsAway[mySlot] = myMacAddr; currSlot = 0; debugEV << "ID: " << getParentModule()->getParentModule()->getId() << ". Picked random slot: " << mySlot << endl; macState=SLEEP; debugEV << "Old state: INIT, New state: SLEEP" << endl; SETUP_PHASE = true; } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case SLEEP: if(msg->getKind() == LMAC_WAKEUP) { currSlot++; currSlot %= numSlots; debugEV << "New slot starting - No. " << currSlot << ", my slot is " << mySlot << endl; if (mySlot == currSlot) { debugEV << "Waking up in my slot. Switch to RECV first to check the channel.\n"; phy->setRadioState(Radio::RX); macState = CCA; debugEV << "Old state: SLEEP, New state: CCA" << endl; double small_delay = controlDuration*dblrand(); scheduleAt(simTime()+small_delay, checkChannel); debugEV << "Checking for channel for " << small_delay << " time.\n"; } else { debugEV << "Waking up in a foreign slot. Ready to receive control packet.\n"; phy->setRadioState(Radio::RX); macState = WAIT_CONTROL; debugEV << "Old state: SLEEP, New state: WAIT_CONTROL" << endl; if (!SETUP_PHASE) //in setup phase do not sleep scheduleAt(simTime()+2.f*controlDuration, timeout); } if (SETUP_PHASE) { scheduleAt(simTime()+2.f*controlDuration, wakeup); debugEV << "setup phase slot duration:" << 2.f*controlDuration << "while controlduration is" << controlDuration << endl; } else scheduleAt(simTime()+slotDuration, wakeup); } else if(msg->getKind() == LMAC_SETUP_PHASE_END) { debugEV << "Setup phase end. Start normal work at the next slot.\n"; if (wakeup->isScheduled()) cancelEvent(wakeup); scheduleAt(simTime()+slotDuration, wakeup); SETUP_PHASE = false; } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case CCA: if(msg->getKind() == LMAC_CHECK_CHANNEL) { // if the channel is clear, get ready for sending the control packet coreEV << "Channel is free, so let's prepare for sending.\n"; phy->setRadioState(Radio::TX); macState = SEND_CONTROL; debugEV << "Old state: CCA, New state: SEND_CONTROL" << endl; } else if(msg->getKind() == LMAC_CONTROL) { LMacPkt *mac = static_cast<LMacPkt *>(msg); int dest = mac->getDestAddr(); debugEV << " I have received a control packet from src " << mac->getSrcAddr() << " and dest " << dest << ".\n"; bool collision = false; // if we are listening to the channel and receive anything, there is a collision in the slot. if (checkChannel->isScheduled()) { cancelEvent(checkChannel); collision = true; } for (int s = 0; s < numSlots; s++) { occSlotsAway[s] = mac->getOccupiedSlots(s); debugEV << "Occupied slot " << s << ": " << occSlotsAway[s] << endl; debugEV << "Occupied direct slot " << s << ": " << occSlotsDirect[s] << endl; } if (mac->getMySlot() >-1) { // check first whether this address didn't have another occupied slot and free it again for (int i=0; i < numSlots; i++) { if (occSlotsDirect[i] == mac->getSrcAddr()) occSlotsDirect[i] = -1; if (occSlotsAway[i] == mac->getSrcAddr()) occSlotsAway[i] = -1; } occSlotsAway[mac->getMySlot()] = mac->getSrcAddr(); occSlotsDirect[mac->getMySlot()] = mac->getSrcAddr(); } collision = collision || (mac->getMySlot() == mySlot); if (((mySlot > -1) && (mac->getOccupiedSlots(mySlot) > -1) && (mac->getOccupiedSlots(mySlot) != myMacAddr)) || collision) { debugEV << "My slot is taken by " << mac->getOccupiedSlots(mySlot) << ". I need to change it.\n"; findNewSlot(); debugEV << "My new slot is " << mySlot << endl; } if (mySlot < 0) { debugEV << "I don;t have a slot - try to find one.\n"; findNewSlot(); } if(dest == myMacAddr || dest == L2BROADCAST) { debugEV << "I need to stay awake.\n"; if (timeout->isScheduled()) cancelEvent(timeout); macState=WAIT_DATA; debugEV << "Old state: CCA, New state: WAIT_DATA" << endl; } else { debugEV << "Incoming data packet not for me. Going back to sleep.\n"; macState = SLEEP; debugEV << "Old state: CCA, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); if (timeout->isScheduled()) cancelEvent(timeout); } delete mac; } //probably it never happens else if(msg->getKind() == LMAC_DATA) { LMacPkt *mac = static_cast<LMacPkt *>(msg); int dest = mac->getDestAddr(); bool collision = false; // if we are listening to the channel and receive anything, there is a collision in the slot. if (checkChannel->isScheduled()) { cancelEvent(checkChannel); collision = true; } debugEV << " I have received a data packet.\n"; if(dest == myMacAddr || dest == L2BROADCAST) { debugEV << "sending pkt to upper...\n"; sendUp(decapsMsg(mac)); } else { debugEV << "packet not for me, deleting...\n"; delete mac; } // in any case, go back to sleep macState = SLEEP; debugEV << "Old state: CCA, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); } else if(msg->getKind() == LMAC_SETUP_PHASE_END) { debugEV << "Setup phase end. Start normal work at the next slot.\n"; if (wakeup->isScheduled()) cancelEvent(wakeup); scheduleAt(simTime()+slotDuration, wakeup); SETUP_PHASE = false; } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case WAIT_CONTROL: if(msg->getKind() == LMAC_TIMEOUT) { debugEV << "Control timeout. Go back to sleep.\n"; macState = SLEEP; debugEV << "Old state: WAIT_CONTROL, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); } else if(msg->getKind() == LMAC_CONTROL) { LMacPkt *mac = static_cast<LMacPkt *>(msg); int dest = mac->getDestAddr(); debugEV << " I have received a control packet from src " << mac->getSrcAddr() << " and dest " << dest << ".\n"; bool collision = false; // check first the slot assignment // copy the current slot assignment for (int s = 0; s < numSlots; s++) { occSlotsAway[s] = mac->getOccupiedSlots(s); debugEV << "Occupied slot " << s << ": " << occSlotsAway[s] << endl; debugEV << "Occupied direct slot " << s << ": " << occSlotsDirect[s] << endl; } if (mac->getMySlot() >-1) { // check first whether this address didn't have another occupied slot and free it again for (int i=0; i < numSlots; i++) { if (occSlotsDirect[i] == mac->getSrcAddr()) occSlotsDirect[i] = -1; if (occSlotsAway[i] == mac->getSrcAddr()) occSlotsAway[i] = -1; } occSlotsAway[mac->getMySlot()] = mac->getSrcAddr(); occSlotsDirect[mac->getMySlot()] = mac->getSrcAddr(); } collision = collision || (mac->getMySlot() == mySlot); if (((mySlot > -1) && (mac->getOccupiedSlots(mySlot) > -1) && (mac->getOccupiedSlots(mySlot) != myMacAddr)) || collision) { debugEV << "My slot is taken by " << mac->getOccupiedSlots(mySlot) << ". I need to change it.\n"; findNewSlot(); debugEV << "My new slot is " << mySlot << endl; } if (mySlot < 0) { debugEV << "I don;t have a slot - try to find one.\n"; findNewSlot(); } if(dest == myMacAddr || dest == L2BROADCAST) { debugEV << "I need to stay awake.\n"; macState=WAIT_DATA; debugEV << "Old state: WAIT_CONTROL, New state: WAIT_DATA" << endl; if (timeout->isScheduled()) cancelEvent(timeout); } else { debugEV << "Incoming data packet not for me. Going back to sleep.\n"; macState = SLEEP; debugEV << "Old state: WAIT_CONTROL, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); if (timeout->isScheduled()) cancelEvent(timeout); } delete mac; } else if ((msg->getKind() == LMAC_WAKEUP)) { if (SETUP_PHASE == true) debugEV << "End of setup-phase slot" << endl; else debugEV << "Very unlikely transition"; macState = SLEEP; debugEV << "Old state: WAIT_DATA, New state: SLEEP" << endl; scheduleAt(simTime(), wakeup); } else if (msg->getKind() == LMAC_SETUP_PHASE_END) { debugEV << "Setup phase end. Start normal work at the next slot.\n"; if (wakeup->isScheduled()) cancelEvent(wakeup); scheduleAt(simTime()+slotDuration, wakeup); SETUP_PHASE = false; } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case SEND_CONTROL: if(msg->getKind() == LMAC_SEND_CONTROL) { // send first a control message, so that non-receiving nodes can switch off. coreEV << "Sending a control packet.\n"; LMacPkt* control = new LMacPkt(); control->setKind(LMAC_CONTROL); if ((macQueue.size() > 0) && !SETUP_PHASE) control->setDestAddr((macQueue.front())->getDestAddr()); else control->setDestAddr(LMAC_NO_RECEIVER); control->setSrcAddr(myMacAddr); control->setMySlot(mySlot); control->setBitLength(headerLength + numSlots); control->setOccupiedSlotsArraySize(numSlots); for (int i = 0; i < numSlots; i++) control->setOccupiedSlots(i, occSlotsDirect[i]); attachSignal(control); sendDown(control); if ((macQueue.size() > 0) && (!SETUP_PHASE)) scheduleAt(simTime()+controlDuration, sendData); } else if(msg->getKind() == LMAC_SEND_DATA) { // we should be in our own slot and the control packet should be already sent. receiving neighbors should wait for the data now. if (currSlot != mySlot) { debugEV << "ERROR: Send data message received, but we are not in our slot!!! Repair.\n"; phy->setRadioState(Radio::SLEEP); if (timeout->isScheduled()) cancelEvent(timeout); return; } LMacPkt* data = macQueue.front()->dup(); data->setKind(LMAC_DATA); data->setMySlot(mySlot); data->setOccupiedSlotsArraySize(numSlots); for (int i = 0; i < numSlots; i++) data->setOccupiedSlots(i, occSlotsDirect[i]); attachSignal(data); coreEV << "Sending down data packet\n"; sendDown(data); delete macQueue.front(); macQueue.pop_front(); macState = SEND_DATA; debugEV << "Old state: SEND_CONTROL, New state: SEND_DATA" << endl; } else if(msg->getKind() == LMAC_SETUP_PHASE_END) { debugEV << "Setup phase end. Start normal work at the next slot.\n"; if (wakeup->isScheduled()) cancelEvent(wakeup); scheduleAt(simTime()+slotDuration, wakeup); SETUP_PHASE = false; } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case SEND_DATA: if(msg->getKind() == LMAC_WAKEUP) { error("I am still sending a message, while a new slot is starting!\n"); } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; case WAIT_DATA: if(msg->getKind() == LMAC_DATA) { LMacPkt *mac = static_cast<LMacPkt *>(msg); int dest = mac->getDestAddr(); debugEV << " I have received a data packet.\n"; if(dest == myMacAddr || dest == L2BROADCAST) { debugEV << "sending pkt to upper...\n"; sendUp(decapsMsg(mac)); } else { debugEV << "packet not for me, deleting...\n"; delete mac; } // in any case, go back to sleep macState = SLEEP; debugEV << "Old state: WAIT_DATA, New state: SLEEP" << endl; phy->setRadioState(Radio::SLEEP); if (timeout->isScheduled()) cancelEvent(timeout); } else if(msg->getKind() == LMAC_WAKEUP) { macState = SLEEP; debugEV << "Unlikely transition. Old state: WAIT_DATA, New state: SLEEP" << endl; scheduleAt(simTime(), wakeup); } else { EV << "Unknown packet" << msg->getKind() << "in state" << macState << endl; delete msg; } break; default: opp_error("Unknown mac state: %d", macState); } }
void LMacLayer::handleUpperMsg | ( | cMessage * | msg | ) | [virtual] |
Handle messages from upper layer.
Check whether the queue is not full: if yes, print a warning and drop the packet. Sending of messages is automatic.
Reimplemented from BaseMacLayer.
Definition at line 120 of file LMacLayer.cc.
References catDroppedPacket, currSlot, droppedPacket, encapsMsg(), macQueue, macState, mySlot, nicId, BaseMacLayer::PACKET_DROPPED, Blackboard::publishBBItem(), queueLength, BaseLayer::sendControlUp(), DroppedPacket::setReason(), and BaseModule::utility.
{ LMacPkt *mac = static_cast<LMacPkt *>(encapsMsg(msg)); // message has to be queued if another message is waiting to be send // or if we are already trying to send another message if (macQueue.size() <= queueLength) { macQueue.push_back(mac); debugEV << "packet put in queue\n queue size: " << macQueue.size() << " macState: " << macState << "; mySlot is " << mySlot << "; current slot is " << currSlot << endl;; } else { // queue is full, message has to be deleted debugEV << "New packet arrived, but queue is FULL, so new packet is deleted\n"; mac->setName("MAC ERROR"); mac->setKind(PACKET_DROPPED); sendControlUp(mac); droppedPacket.setReason(DroppedPacket::QUEUE); utility->publishBBItem(catDroppedPacket, &droppedPacket, nicId); debugEV << "ERROR: Queue is full, forced to delete.\n"; } }