Public Member Functions | Protected Types | Protected Member Functions | Protected Attributes | Static Protected Attributes

LMacLayer Class Reference
[macLayer - MAC layer modules]

Implementation of L-MAC (Lightweight Medium Access Protocol for Wireless Sensor Networks [van Hoesel 04] ). More...

#include <LMacLayer.h>

Inherits BaseMacLayer.

Collaboration diagram for LMacLayer:
Collaboration graph
[legend]

List of all members.

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

Detailed Description

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:

LMACFSM.jpg

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.


Member Enumeration Documentation

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
    };


Member Function Documentation

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";
    }
}


The documentation for this class was generated from the following files: