rfid_reader_mac.cpp

00001 
00002 #include "rfid_reader_mac.hpp"
00003 #include "packet.hpp"
00004 #include "rfid_tag_mac.hpp"
00005 #include "rfid_reader_app.hpp"
00006 #include "log_stream_manager.hpp"
00007 
00008 const double RfidReaderMac::m_READER_IFS = 10e-6;
00009 const t_uint RfidReaderMac::m_DEFAULT_NUMBER_OF_SLOTS = 10;
00010 const double RfidReaderMac::m_DEFAULT_CYCLE_TIME = 5.25;
00011 const t_uint RfidReaderMac::m_MISSED_READ_THRESHOLD = 3;
00012 
00013 const string RfidReaderMac::m_MISSED_READ_TOTAL_STRING = "missedReadTotal";
00014 const string RfidReaderMac::m_MISSED_READ_SLOT_AVG_STRING = "missedReadSlotAvg";
00015 const string RfidReaderMac::m_WINNING_SLOT_AVG_STRING = "winningSlotAvg";
00016 
00017 RfidReaderMac::RfidReaderMac(NodePtr node, RfidReaderAppPtr readerApp)
00018    : SlottedMac(node), 
00019    m_doResetSlot(false), m_resetSlotNumber(0),
00020    m_doEntireReadCycle(false), m_missedReadCount(0),
00021    m_nextCycleNumberOfSlots(m_DEFAULT_NUMBER_OF_SLOTS),
00022    m_nextCycleTime(m_DEFAULT_CYCLE_TIME), m_readerApp(readerApp)
00023 {
00024    setSlotTime(SimTime(m_DEFAULT_SLOT_TIME));
00025 }
00026 
00027 RfidReaderMac::~RfidReaderMac()
00028 {
00029 
00030 }
00031 
00032 void RfidReaderMac::simulationEndHandler()
00033 {
00034    t_uint missedReadSlotSum = 0;
00035    for(t_uint i = 0; i < m_missedReads.size(); ++i) {
00036       missedReadSlotSum += m_missedReads[i];
00037    }
00038    double missedReadSlotAvg = 0.0;
00039    if(m_missedReads.size() > 0)
00040       missedReadSlotAvg = static_cast<double>(missedReadSlotSum) / 
00041          m_missedReads.size();
00042 
00043    ostringstream missedReadTotalStream;
00044    missedReadTotalStream << m_missedReads.size();
00045    LogStreamManager::instance()->logStatsItem(getNode()->getNodeId(),
00046       m_MISSED_READ_TOTAL_STRING, missedReadTotalStream.str());
00047 
00048    ostringstream missedReadSlotAvgStream;
00049    missedReadSlotAvgStream << missedReadSlotAvg;
00050    LogStreamManager::instance()->logStatsItem(getNode()->getNodeId(),
00051       m_MISSED_READ_SLOT_AVG_STRING, missedReadSlotAvgStream.str());
00052 
00053    t_uint winningSlotSum = 0;
00054    for(t_uint i = 0; i < m_winningSlotNumbers.size(); ++i) {
00055       winningSlotSum += m_winningSlotNumbers[i].second;
00056    }
00057    double winningSlotAvg = 0.0;
00058    if(m_winningSlotNumbers.size() > 0)
00059       winningSlotAvg = static_cast<double>(winningSlotSum) / 
00060          m_winningSlotNumbers.size();
00061 
00062    ostringstream winningSlotAvgStream;
00063    winningSlotAvgStream << winningSlotAvg;
00064    LogStreamManager::instance()->logStatsItem(getNode()->getNodeId(),
00065       m_WINNING_SLOT_AVG_STRING, winningSlotAvgStream.str());
00066 
00067 }
00068 
00069 bool RfidReaderMac::isEnoughTimeForContentionCycle() const
00070 {
00071    // We need one extra slot be cycle to send the REQUEST
00072    // packet.
00073    double nextContentionCycleTime = 
00074    (m_nextCycleNumberOfSlots + 1) * m_DEFAULT_SLOT_TIME;
00075 
00076    if(m_DEBUG_CONTENTION_CYCLE_TIME) {
00077       SimTime timeRemaining = m_cycleTimer->timeRemaining();
00078       if(timeRemaining > 0.0) {
00079          ostringstream debugStream;
00080          debugStream << __PRETTY_FUNCTION__ <<
00081          " nextCycleTime=" << nextContentionCycleTime <<
00082          ", readCycleRemaining=" << timeRemaining;
00083          LogStreamManager::instance()->logDebugItem(
00084             debugStream.str());
00085       }
00086    }
00087 
00088    return (SimTime(nextContentionCycleTime) < 
00089          m_cycleTimer->timeRemaining());
00090 }
00091 
00092 void RfidReaderMac::beginSlotEvent()
00093 {
00094    // Check for a transmission slot before checking for the end
00095    // slot.  This lets us transmit on the next slot after calling
00096    // stopContentionCycle() without triggering the actions
00097    // for the end slot.
00098 
00099    if(m_currentSlotNumber == m_txSlotNumber) {
00100       if(m_packetToTransmit.get() != 0) {
00101          if(m_DEBUG) {
00102             ostringstream debugStream;
00103             debugStream << __PRETTY_FUNCTION__ <<
00104             " is enough time, txSlot=" << m_txSlotNumber <<
00105             ", currentSlot=" << m_currentSlotNumber;
00106             LogStreamManager::instance()->logDebugItem(
00107                debugStream.str());
00108          }
00109 
00110          startSendTimer(CommunicationLayer::Directions_Lower, 
00111             m_packetToTransmit, m_READER_IFS);
00112          m_packetToTransmit.reset();
00113       }
00114    } else if(m_numberOfSlots == 0 ||
00115          m_currentSlotNumber >= m_numberOfSlots ||
00116          (m_doResetSlot && m_currentSlotNumber == m_resetSlotNumber)) {
00117       // Send another request if there is sufficient time in
00118       // the current cycle.  Note that this occurs when
00119       // no tags were read in a contention cycle.  There is a one
00120       // slot delay between the last slot of the previous contention
00121       // cycle and when the next REQUEST packet gets sent.  This
00122       // is needed to avoid stopping the contention cycle when
00123       // a tag is transmitting data in the last slot of the
00124       // contention cycle.
00125       assert(m_packetToTransmit.get() == 0);
00126 
00127       ostringstream debugStream;
00128       debugStream << __PRETTY_FUNCTION__ << 
00129          " currentSlot: " << m_currentSlotNumber << " resetSlot: " <<
00130          m_resetSlotNumber << " numSlots: " << m_numberOfSlots <<
00131          " missedReadCount: " << m_missedReadCount <<
00132          boolalpha << " doReset: " << m_doResetSlot <<
00133          " isEnoughCycleTime: " << isEnoughTimeForContentionCycle();
00134       LogStreamManager::instance()->logDebugItem(
00135          debugStream.str());
00136 
00137       // We were unable to successfully read a packet
00138       // in the given interval.  We only do this if we
00139       // are currently in a read interval (i.e., the timer
00140       // is running).
00141       if(!m_doEntireReadCycle && m_cycleTimer->isRunning()) {
00142          m_missedReads.push_back(m_currentSlotNumber);
00143          m_missedReadCount++;
00144       } else
00145          m_missedReadCount = 0;
00146 
00147       m_doResetSlot = false;
00148       //cout << "stopCycle1" << endl;
00149       stopContentionCycle();
00150 
00151       if(!m_doEntireReadCycle &&
00152             m_missedReadCount == m_MISSED_READ_THRESHOLD) {
00153          // The timer should be running since, otherwise,
00154          // the missedReadCount was reset to zero above.
00155          assert(m_cycleTimer->isRunning());
00156          // If we have missed too many consecutive reads, then
00157          // we will force the current read cycle to stop.
00158          m_cycleTimer->stop();
00159          endRequestCycleEvent();
00160       } else {
00161          if(isEnoughTimeForContentionCycle()) {
00162             m_packetToTransmit = createRequestPacket();
00163             // Have to set this for the next slot number since
00164             // currentSlotNumber is incremented at the end of this
00165             // function.
00166             m_txSlotNumber = m_currentSlotNumber + 1;
00167          } else if(!m_cycleTimer->isRunning()) {
00168             assert(!getQueueIsBlocked());
00169          }
00170       }
00171    }
00172 
00173    m_currentSlotNumber++;
00174    assert(m_slotTimer.get() != 0);
00175    m_slotTimer->reschedule(getSlotTime());
00176 }
00177 
00178 void RfidReaderMac::endRequestCycleEvent()
00179 {
00180    assert(!inContentionCycle());
00181    m_currentAppReadPacket.reset();
00182    unblockUpperQueues();
00183    m_readerApp->signalReadEnd();
00184 }
00185 
00186 void RfidReaderMac::handleChannelBusy(PacketPtr packet)
00187 {
00188    // For now, we will just silently drop the packet
00189    // rather than implement a retransmission scheme.
00190    if(!isPacketType(packet, RfidReaderMacData::Types_Request) && 
00191          !isPacketType(packet, RfidReaderMacData::Types_Select)) {
00192       unblockUpperQueues();
00193    }
00194 }
00195 
00196 void RfidReaderMac::handlePacketSent(PacketPtr packet)
00197 {
00198    if(isPacketType(packet, RfidReaderMacData::Types_Request)) {
00199       // Start a cycle
00200       m_currentSlotNumber = 0;
00201       RfidReaderMacDataPtr macData =
00202          boost::dynamic_pointer_cast<RfidReaderMacData>
00203          (packet->getData(Packet::DataTypes_Link));
00204       assert(macData.get() != 0);
00205       m_numberOfSlots = macData->getNumberOfSlots();
00206    } else if(isPacketType(packet, RfidReaderMacData::Types_Select)) {
00207       m_doResetSlot = true;
00208       // m_currentSlotNumber is already set to slot i+1, so
00209       // the resetSlotNumber should be slot i+2.  Thus, we
00210       // add one to currentSlotNumber.
00211       m_resetSlotNumber = m_currentSlotNumber + 1;
00212       /*
00213       cout << "slot: " << m_currentSlotNumber << " resetSlot: " <<
00214          m_resetSlotNumber << endl;
00215       */
00216    } else if(isPacketType(packet, RfidReaderMacData::Types_Ack)) {
00217       if(isEnoughTimeForContentionCycle()) {
00218          startNextContentionCycle();
00219       }
00220    } else {
00221       unblockUpperQueues();
00222    }
00223 }
00224 
00225 bool RfidReaderMac::isPacketType(PacketPtr packet, 
00226    RfidReaderMacData::Types type) const
00227 {
00228    bool isType = false;
00229    RfidReaderMacDataPtr macData =
00230       boost::dynamic_pointer_cast<RfidReaderMacData>
00231       (packet->getData(Packet::DataTypes_Link));
00232    if(macData.get() != 0 && macData->getType() == type) {
00233       isType = true;
00234    }
00235    return isType;
00236 }
00237 
00238 bool RfidReaderMac::packetIsForMe(RfidTagMacDataPtr macData) const
00239 {
00240    return (macData->getReceiverId() == getNode()->getNodeId() ||
00241       macData->getReceiverId() == NodeId::broadcastDestination());
00242 }
00243 
00244 void RfidReaderMac::startNextContentionCycle()
00245 {
00246    // TODO: Remove this before the assertion.
00247    if(m_packetToTransmit.get() != 0) {
00248       ostringstream debugStream;
00249       debugStream << __PRETTY_FUNCTION__ << *m_packetToTransmit <<
00250          " curSlot: " << m_currentSlotNumber << ", numSlots: " <<
00251          m_numberOfSlots;
00252       LogStreamManager::instance()->logDebugItem(
00253          debugStream.str());
00254    }
00255    assert(m_packetToTransmit.get() == 0);
00256    m_packetToTransmit = createRequestPacket();
00257    m_missedReadCount = 0;
00258    m_doResetSlot = false;
00259    //cout << "stopCycle2" << endl;
00260    stopContentionCycle();
00261    m_txSlotNumber = m_currentSlotNumber;
00262 }
00263 
00264 bool RfidReaderMac::handleRecvdMacPacket(PacketPtr packet, 
00265    t_uint sendingLayerIdx)
00266 {
00267    RfidTagMacDataPtr macData =
00268       boost::dynamic_pointer_cast<RfidTagMacData>
00269       (packet->getData(Packet::DataTypes_Link));
00270 
00271    bool wasSuccessful = true;
00272 
00273    // For now, we'll only handle MAC packets from tags.
00274    if(macData.get() != 0) {
00275       if(packetIsForMe(macData)) {
00276          switch(macData->getType()) {
00277          case RfidTagMacData::Types_Reply:
00278             // If we ended the cycle early due to too many
00279             // consecutive missed reads, then the timer will
00280             // be stopped and we shouldn't handle anymore
00281             // REPLY packets.
00282             if(m_cycleTimer->isRunning()) {
00283                // It could be the case that this reply is received
00284                // in a contention cycle after the a SELECT packet
00285                // was lost.  In response to the SELECT packet being
00286                // lost in slot i, the reader will reset in
00287                // slot i+2 and send a REQUEST in slot i+3.
00288                // If this reply is received in slot i+2, we should
00289                // ignore it since m_packetToTransmit already
00290                // has a REQUEST packet pending.
00291                if(m_packetToTransmit.get() == 0) {
00292                   assert(m_currentAppReadPacket.get() != 0);
00293                   // Send SELECT message header on the original
00294                   // app packet.
00295                   addSelectHeader(m_currentAppReadPacket, 
00296                      macData->getSenderId());
00297                   m_packetToTransmit = m_currentAppReadPacket;
00298                   m_txSlotNumber = m_currentSlotNumber;
00299                   assert(m_slotTimer.get() != 0 && 
00300                      m_slotTimer->isRunning());
00301                }
00302             }
00303             break;
00304          case RfidTagMacData::Types_Generic:
00305             // Subtract three from the winning slot number for:
00306             // 1. The current slot number was incremented
00307             // at the beginning of the slot.
00308             // 2. The REPLY was sent two slots prior
00309             // to this packet being received (the SELECT
00310             // packet was sent one slot prior).
00311             m_winningSlotNumbers.push_back(
00312                make_pair(macData->getSenderId(), 
00313                (m_currentSlotNumber - 3)));
00314             // Just pass the packet to upper layers.
00315             wasSuccessful = sendToLinkLayer(
00316                CommunicationLayer::Directions_Upper, packet);
00317             m_packetToTransmit = createAckPacket(macData->getSenderId());
00318             m_txSlotNumber = m_currentSlotNumber;
00319             assert(m_slotTimer.get() != 0 && 
00320                m_slotTimer->isRunning());
00321             break;
00322          default:
00323             wasSuccessful = false;
00324          }
00325       }
00326    }
00327 
00328    return wasSuccessful;
00329 }
00330 
00331 PacketPtr RfidReaderMac::createRequestPacket() const
00332 {
00333    RfidReaderMacDataPtr macData = RfidReaderMacData::create();
00334    macData->setType(RfidReaderMacData::Types_Request);
00335    macData->setSenderId(getNode()->getNodeId());
00336    macData->setReceiverId(NodeId::broadcastDestination());
00337    // We must have at least: (1) a contention slot,
00338    // (2) a slot for the SELECT to be sent by the ready,
00339    // (3) a slot for the tag to reply with an app packet,
00340    // (4) a slot for the reader to reply with an ACK.
00341    assert(m_nextCycleNumberOfSlots >= 4);
00342    macData->setNumberOfSlots(m_nextCycleNumberOfSlots);
00343    PacketPtr packet = Packet::create();
00344    assert(m_currentAppReadPacket.get() != 0);
00345    packet->setTxPower(m_currentAppReadPacket->getTxPower());
00346    packet->addData(Packet::DataTypes_Link, *macData);
00347    return packet;
00348 }
00349 
00350 PacketPtr RfidReaderMac::createAckPacket(NodeId destination) const
00351 {
00352    RfidReaderMacDataPtr macData = RfidReaderMacData::create();
00353    macData->setType(RfidReaderMacData::Types_Ack);
00354    macData->setSenderId(getNode()->getNodeId());
00355    macData->setReceiverId(destination);
00356 
00357    PacketPtr packet = Packet::create();
00358    packet->setDoMaxTxPower(true);
00359    packet->addData(Packet::DataTypes_Link, *macData);
00360    return packet;
00361 }
00362 
00363 void RfidReaderMac::addGenericHeader(PacketPtr packet, 
00364    NodeId receiverId) const
00365 {
00366    RfidReaderMacDataPtr macData = RfidReaderMacData::create();
00367    macData->setType(RfidReaderMacData::Types_Generic);
00368    macData->setSenderId(getNode()->getNodeId());
00369    macData->setReceiverId(receiverId);
00370    packet->addData(Packet::DataTypes_Link, *macData);
00371 }
00372 
00373 void RfidReaderMac::addSelectHeader(PacketPtr packet, 
00374    NodeId receiverId) const
00375 {
00376    RfidReaderMacDataPtr macData = RfidReaderMacData::create();
00377    macData->setType(RfidReaderMacData::Types_Select);
00378    macData->setSenderId(getNode()->getNodeId());
00379    macData->setReceiverId(receiverId);
00380    packet->setDoMaxTxPower(true);
00381    packet->addData(Packet::DataTypes_Link, *macData);
00382 }
00383 
00384 bool RfidReaderMac::handleRecvdUpperLayerPacket(PacketPtr packet,
00385    t_uint sendingLayerIdx)
00386 {
00387    RfidReaderAppDataPtr appData =
00388       boost::dynamic_pointer_cast<RfidReaderAppData>
00389       (packet->getData(Packet::DataTypes_Application));
00390 
00391    bool wasSuccessful = false;
00392 
00393    if(m_DEBUG) {
00394       ostringstream debugStream;
00395       debugStream << __PRETTY_FUNCTION__;
00396       LogStreamManager::instance()->logDebugItem(
00397          debugStream.str());
00398    }
00399 
00400    // For now, we only handle application packets.
00401    if(appData.get() != 0) {
00402       switch(appData->getType()) {
00403       case RfidReaderAppData::Types_Read:
00404          // We'll only handle one packet at a time
00405          blockUpperQueues();
00406 
00407          assert(m_currentAppReadPacket.get() == 0);
00408          m_currentAppReadPacket = packet;
00409          m_doEntireReadCycle = appData->getDoEntireReadCycle();
00410          // Start cycle timer
00411          assert(m_cycleTimer.get() != 0);
00412          m_cycleTimer->start(m_nextCycleTime);
00413          if(isEnoughTimeForContentionCycle()) {
00414             startNextContentionCycle();
00415          }
00416          wasSuccessful = true;
00417          break;
00418       case RfidReaderAppData::Types_Reset:
00419          // We'll only handle one packet at a time
00420          blockUpperQueues();
00421 
00422          assert(m_packetToTransmit == 0);
00423          addGenericHeader(packet, NodeId::broadcastDestination());
00424          m_packetToTransmit = packet;
00425          m_txSlotNumber = m_currentSlotNumber;
00426          wasSuccessful = true;
00427          break;
00428       default:
00429          wasSuccessful = false;
00430       }
00431       assert(m_slotTimer.get() != 0 && m_slotTimer->isRunning());
00432    }
00433 
00434    return wasSuccessful;
00435 }
00436 
00438 // RfidReaderMacData functions
00440 
00441 RfidReaderMacData::RfidReaderMacData()
00442    : m_numberOfSlots(0), m_type(RfidReaderMacData::Types_Generic)
00443 {
00444    fill(m_senderId, &m_senderId[m_senderIdBytes], 0);
00445    fill(m_receiverId, &m_receiverId[m_receiverIdBytes], 0);
00446 }
00447 
00448 RfidReaderMacData::RfidReaderMacData(const RfidReaderMacData& rhs)
00449    : PacketData(rhs), m_numberOfSlots(rhs.m_numberOfSlots), 
00450    m_type(rhs.m_type)
00451 {
00452    copy(rhs.m_senderId, &rhs.m_senderId[m_senderIdBytes], m_senderId);
00453    copy(rhs.m_receiverId, &rhs.m_receiverId[m_receiverIdBytes], 
00454       m_receiverId);
00455 }
00456 
00457 PacketDataPtr RfidReaderMacData::clone() const
00458 {
00459     PacketDataPtr p(new RfidReaderMacData(*this));
00460     return p;
00461 }
00462 
00463 void RfidReaderMacData::setSenderId(const NodeId& nodeId)
00464 {
00465    nodeId.writeToByteArray(m_senderId, m_senderIdBytes);
00466 }
00467 
00468 NodeId RfidReaderMacData::getSenderId() const
00469 {
00470    NodeId nodeId(m_senderId, m_senderIdBytes);
00471    return nodeId;
00472 }
00473 
00474 void RfidReaderMacData::setReceiverId(const NodeId& nodeId)
00475 {
00476    nodeId.writeToByteArray(m_receiverId, m_receiverIdBytes);
00477 }
00478 
00479 NodeId RfidReaderMacData::getReceiverId() const
00480 {
00481    NodeId nodeId(m_receiverId, m_receiverIdBytes);
00482    return nodeId;
00483 }
00484 
00485 

Generated on Tue Dec 12 17:04:38 2006 for rfidsim by  doxygen 1.4.7