diff --git a/examples/complete-network-example.cc b/examples/complete-network-example.cc index 84f9a25a5e..a16dde7e97 100644 --- a/examples/complete-network-example.cc +++ b/examples/complete-network-example.cc @@ -45,6 +45,8 @@ bool realisticChannelModel = false; int appPeriodSeconds = 600; +int numberOfTransmissions = 1; // The maximum number of transmissions allowed, valid is [1:15] + // Output control bool print = true; @@ -87,6 +89,10 @@ main (int argc, char *argv[]) // LogComponentEnable("NetworkStatus", LOG_LEVEL_ALL); // LogComponentEnable("NetworkController", LOG_LEVEL_ALL); + LogComponentEnableAll (LOG_PREFIX_FUNC); + LogComponentEnableAll (LOG_PREFIX_NODE); + LogComponentEnableAll (LOG_PREFIX_TIME); + /*********** * Setup * ***********/ @@ -190,6 +196,10 @@ main (int argc, char *argv[]) Ptr node = *j; Ptr loraNetDevice = node->GetDevice (0)->GetObject (); Ptr phy = loraNetDevice->GetPhy (); + + Ptr edMac = loraNetDevice->GetMac (); + Ptr edLorawanMac = edMac->GetObject (); + edLorawanMac->SetMaxNumberOfTransmissions (numberOfTransmissions); } /********************* diff --git a/helper/lora-packet-tracker.cc b/helper/lora-packet-tracker.cc index 0116e53406..83f88d3698 100644 --- a/helper/lora-packet-tracker.cc +++ b/helper/lora-packet-tracker.cc @@ -137,9 +137,7 @@ LoraPacketTracker::PacketReceptionCallback (Ptr packet, uint32_t g << " was successfully received at gateway " << gwId); - std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); - (*it).second.outcomes.insert (std::pair (gwId, - RECEIVED)); + SetPacketOutcome(packet, std::pair (gwId,RECEIVED)); } } @@ -152,9 +150,7 @@ LoraPacketTracker::InterferenceCallback (Ptr packet, uint32_t gwId << " was interfered at gateway " << gwId); - std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); - (*it).second.outcomes.insert (std::pair (gwId, - INTERFERED)); + SetPacketOutcome(packet, std::pair (gwId,INTERFERED)); } } @@ -166,9 +162,8 @@ LoraPacketTracker::NoMoreReceiversCallback (Ptr packet, uint32_t g NS_LOG_INFO ("PHY packet " << packet << " was lost because no more receivers at gateway " << gwId); - std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); - (*it).second.outcomes.insert (std::pair (gwId, - NO_MORE_RECEIVERS)); + + SetPacketOutcome(packet, std::pair (gwId,NO_MORE_RECEIVERS)); } } @@ -181,9 +176,7 @@ LoraPacketTracker::UnderSensitivityCallback (Ptr packet, uint32_t << " was lost because under sensitivity at gateway " << gwId); - std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); - (*it).second.outcomes.insert (std::pair (gwId, - UNDER_SENSITIVITY)); + SetPacketOutcome(packet, std::pair (gwId,UNDER_SENSITIVITY)); } } @@ -196,12 +189,46 @@ LoraPacketTracker::LostBecauseTxCallback (Ptr packet, uint32_t gwI << " was lost because of GW transmission at gateway " << gwId); - std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); - (*it).second.outcomes.insert (std::pair (gwId, - LOST_BECAUSE_TX)); + SetPacketOutcome(packet, std::pair (gwId, LOST_BECAUSE_TX)); } } +void +LoraPacketTracker::SetPacketOutcome(Ptr packet, std::pair outcome) +{ + NS_LOG_FUNCTION (this); + + uint32_t gwId = outcome.first; + + if(m_packetTracker.count(packet) == 1) //first reception + { + std::map, PacketStatus>::iterator it = m_packetTracker.find (packet); + (*it).second.outcomes.insert (outcome); + } + else + { + std::pair , PacketStatus>::iterator, std::multimap, PacketStatus>::iterator> ret; + ret = m_packetTracker.equal_range(packet); // find all instances of received packet + + int i = 1; + + //loop through all instances and find the one which doesn't yet have an outcome at this gateway + for(std::multimap, PacketStatus>::iterator it=ret.first; it != ret.second; ++it) + { + + if((*it).second.outcomes.find(gwId) == (*it).second.outcomes.end()) + { + NS_LOG_INFO("This is copy " << i <<" of packet "<< packet); + NS_LOG_INFO("This packet was sent at " << (*it).second.sendTime); + NS_LOG_INFO("It was not yet received by GW " << gwId << " logging it now with outcome " << outcome.second); + (*it).second.outcomes.insert(outcome); + } + i++; + } + } + +} + bool LoraPacketTracker::IsUplink (Ptr packet) { @@ -301,6 +328,9 @@ LoraPacketTracker::PrintPhyPacketsPerGw (Time startTime, Time stopTime, NS_LOG_DEBUG ("This packet was received by " << (*itPhy).second.outcomes.size () << " gateways"); + if((*itPhy).second.outcomes.find(gwId) != (*itPhy).second.outcomes.end()) + NS_LOG_DEBUG ("Packet outcome:" << (*itPhy).second.outcomes.at(gwId)); + if ((*itPhy).second.outcomes.count (gwId) > 0) { switch ((*itPhy).second.outcomes.at (gwId)) diff --git a/helper/lora-packet-tracker.h b/helper/lora-packet-tracker.h index ab8c3da450..07db7c6425 100644 --- a/helper/lora-packet-tracker.h +++ b/helper/lora-packet-tracker.h @@ -66,7 +66,7 @@ struct RetransmissionStatus }; typedef std::map, MacPacketStatus> MacPacketData; -typedef std::map, PacketStatus> PhyPacketData; +typedef std::multimap, PacketStatus> PhyPacketData; typedef std::map, RetransmissionStatus> RetransmissionData; @@ -107,6 +107,10 @@ class LoraPacketTracker // macPacketTracker, RetransmissionData reTransmissionTracker, // PhyPacketData packetTracker); + /* + * Sets a packet's outcome at a specified gateway to one of PhyPacketOutcome's values. + */ + void SetPacketOutcome(Ptr packet, std::pair outcome); /** * Count packets to evaluate the performance at PHY level of a specific * gateway. diff --git a/model/class-a-end-device-lorawan-mac.cc b/model/class-a-end-device-lorawan-mac.cc index aacd8acef1..5ce29e669a 100644 --- a/model/class-a-end-device-lorawan-mac.cc +++ b/model/class-a-end-device-lorawan-mac.cc @@ -195,13 +195,18 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) // packet in the second receive window and finding out, after the // fact, that the packet is not for us. In either case, if we no // longer have any retransmissions left, we declare failure. - if (m_retxParams.waitingAck && m_secondReceiveWindow.IsExpired ()) + if (m_secondReceiveWindow.IsExpired ()) { if (m_retxParams.retxLeft == 0) { uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); - m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_DEBUG ("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); + if(m_retxParams.waitingAck) + { + m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); + NS_LOG_DEBUG ("Failure: no more retransmissions left for confirmed packet. Used " << unsigned(txs) << " transmissions."); + } + else if(m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Failure: no more retransmissions left for unconfirmed packet. Used " << unsigned(txs) << " transmissions."); // Reset retransmission parameters resetRetransmissionParameters (); @@ -214,7 +219,7 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) } } } - else if (m_retxParams.waitingAck && m_secondReceiveWindow.IsExpired ()) + else if (m_secondReceiveWindow.IsExpired ()) { NS_LOG_INFO ("The packet we are receiving is in uplink."); if (m_retxParams.retxLeft > 0) @@ -225,8 +230,14 @@ ClassAEndDeviceLorawanMac::Receive (Ptr packet) else { uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); - m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_DEBUG ("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); + if(m_retxParams.waitingAck) + { + + m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); + NS_LOG_DEBUG ("Failure: no more retransmissions left for confirmed packet. Used " << unsigned(txs) << " transmissions."); + } + else if (m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Failure: no more retransmissions left for unconfirmed packet. Used " << unsigned(txs) << " transmissions."); // Reset retransmission parameters resetRetransmissionParameters (); @@ -244,7 +255,7 @@ ClassAEndDeviceLorawanMac::FailedReception (Ptr packet) // Switch to sleep after a failed reception m_phy->GetObject ()->SwitchToSleep (); - if (m_secondReceiveWindow.IsExpired () && m_retxParams.waitingAck) + if (m_secondReceiveWindow.IsExpired ()) { if (m_retxParams.retxLeft > 0) { @@ -254,8 +265,15 @@ ClassAEndDeviceLorawanMac::FailedReception (Ptr packet) else { uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); - m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_DEBUG ("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); + if( m_retxParams.waitingAck) + { + + m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); + NS_LOG_DEBUG ("Failure: no more retransmissions left for confirmed packet. Used " << unsigned(txs) << " transmissions."); + } + else if(m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Failure: no more retransmissions left for unconfirmed packet. Used " << unsigned(txs) << " transmissions."); + // Reset retransmission parameters resetRetransmissionParameters (); @@ -405,40 +423,42 @@ ClassAEndDeviceLorawanMac::CloseSecondReceiveWindow (void) break; } - if (m_retxParams.waitingAck) - { - NS_LOG_DEBUG ("No reception initiated by PHY: rescheduling transmission."); - if (m_retxParams.retxLeft > 0 ) - { - NS_LOG_INFO ("We have " << unsigned(m_retxParams.retxLeft) << " retransmissions left: rescheduling transmission."); - this->Send (m_retxParams.packet); - } - else if (m_retxParams.retxLeft == 0 && m_phy->GetObject ()->GetState () != EndDeviceLoraPhy::RX) - { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); - m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_DEBUG ("Failure: no more retransmissions left. Used " << unsigned(txs) << " transmissions."); - // Reset retransmission parameters - resetRetransmissionParameters (); - } + if (m_retxParams.retxLeft > 0 ) + { + if(m_retxParams.waitingAck) + NS_LOG_DEBUG ("No reception initiated by PHY: rescheduling transmission of confirmed packet."); - else - { - NS_ABORT_MSG ("The number of retransmissions left is negative ! "); - } - } - else - { - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft ); - m_requiredTxCallback (txs, true, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_INFO ("We have " << unsigned(m_retxParams.retxLeft) << - " transmissions left. We were not transmitting confirmed messages."); + if(m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("No reception initiated by PHY: rescheduling transmission of unconfirmed packet."); + + NS_LOG_INFO ("We have " << unsigned(m_retxParams.retxLeft) << " retransmissions left: rescheduling transmission."); - // Reset retransmission parameters - resetRetransmissionParameters (); - } + this->Send (m_retxParams.packet); + } + + else if (m_retxParams.retxLeft == 0 && m_phy->GetObject ()->GetState () != EndDeviceLoraPhy::RX) + { + + uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); + if(m_retxParams.waitingAck) + { + + m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); + NS_LOG_DEBUG ("Failure: no more retransmissions left for confirmed packet. Used " << unsigned(txs) << " transmissions."); + } + else if (m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Finished: no more retransmissions left for unconfirmed packet. Used " << unsigned(txs) << " transmissions."); + + // Reset retransmission parameters + resetRetransmissionParameters (); + } + + else + { + NS_ABORT_MSG ("The number of retransmissions left is negative ! "); + } } ///////////////////////// diff --git a/model/end-device-lorawan-mac.cc b/model/end-device-lorawan-mac.cc index aa06d0f9d6..bb48ff34f9 100644 --- a/model/end-device-lorawan-mac.cc +++ b/model/end-device-lorawan-mac.cc @@ -87,9 +87,9 @@ EndDeviceLorawanMac::GetTypeId (void) "ns3::TracedValueCallback::Double") .AddAttribute ("MaxTransmissions", "Maximum number of transmissions for a packet", - IntegerValue (8), + IntegerValue (1), MakeIntegerAccessor (&EndDeviceLorawanMac::m_maxNumbTx), - MakeIntegerChecker ()) + MakeIntegerChecker (1, 15)) .AddAttribute ("EnableEDDataRateAdaptation", "Whether the End Device should up its Data Rate " "in case it doesn't get a reply from the NS.", @@ -110,7 +110,7 @@ EndDeviceLorawanMac::GetTypeId (void) EndDeviceLorawanMac::EndDeviceLorawanMac () : m_enableDRAdapt (false), - m_maxNumbTx (8), + m_maxNumbTx (1), m_dataRate (0), m_txPower (14), m_codingRate (1), @@ -240,12 +240,17 @@ EndDeviceLorawanMac::DoSend (Ptr packet) // Reset MAC command list m_macCommandList.clear (); + uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); if (m_retxParams.waitingAck) { // Call the callback to notify about the failure - uint8_t txs = m_maxNumbTx - (m_retxParams.retxLeft); m_requiredTxCallback (txs, false, m_retxParams.firstAttempt, m_retxParams.packet); - NS_LOG_DEBUG (" Received new packet from the application layer: stopping retransmission procedure. Used " << + NS_LOG_DEBUG (" Received new packet from the application layer: stopping retransmission procedure of confirmed packet. Used " << + unsigned(txs) << " transmissions out of a maximum of " << unsigned(m_maxNumbTx) << "."); + } + else if (m_retxParams.sendingMultipleUnconfirmed) + { + NS_LOG_DEBUG (" Received new packet from the application layer: stopping retransmission procedure for unconfirmed packet. Used " << unsigned(txs) << " transmissions out of a maximum of " << unsigned(m_maxNumbTx) << "."); } @@ -258,6 +263,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) m_retxParams.packet = packet->Copy (); m_retxParams.retxLeft = m_maxNumbTx; m_retxParams.waitingAck = true; + m_retxParams.sendingMultipleUnconfirmed = false; m_retxParams.firstAttempt = Simulator::Now (); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions @@ -274,8 +280,31 @@ EndDeviceLorawanMac::DoSend (Ptr packet) // static_cast(this)->SendToPhy (m_retxParams.packet); SendToPhy (m_retxParams.packet); } - else - { + else if (m_maxNumbTx > 1) //Unconfirmed packet and NbTrans is configured to be more than 1 + { + m_retxParams.packet = packet->Copy (); + m_retxParams.retxLeft = m_maxNumbTx; + m_retxParams.waitingAck = false; + m_retxParams.sendingMultipleUnconfirmed = true; + m_retxParams.firstAttempt = Simulator::Now (); + m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions + + NS_LOG_DEBUG ("Message type is " << m_mType); + NS_LOG_DEBUG ("It is a unconfirmed packet. Setting retransmission parameters and decreasing the number of transmissions left."); + + NS_LOG_INFO ("Added MAC header of size " << macHdr.GetSerializedSize () << + " bytes."); + + // Sent a new packet + NS_LOG_DEBUG ("Copied packet: " << m_retxParams.packet); + m_sentNewPacket (m_retxParams.packet); + + // static_cast(this)->SendToPhy (m_retxParams.packet); + SendToPhy (m_retxParams.packet); + + } + + else { m_sentNewPacket (packet); // static_cast(this)->SendToPhy (packet); SendToPhy (packet); @@ -285,7 +314,7 @@ EndDeviceLorawanMac::DoSend (Ptr packet) // this is a retransmission else { - if (m_retxParams.waitingAck) + if (m_retxParams.waitingAck or m_retxParams.sendingMultipleUnconfirmed) { // Remove the headers @@ -307,13 +336,16 @@ EndDeviceLorawanMac::DoSend (Ptr packet) ApplyNecessaryOptions (macHdr); packet->AddHeader (macHdr); m_retxParams.retxLeft = m_retxParams.retxLeft - 1; // decreasing the number of retransmissions - NS_LOG_DEBUG ("Retransmitting an old packet."); + + if(m_retxParams.waitingAck) + NS_LOG_DEBUG ("Retransmitting an old confirmed packet."); + else if(m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Retransmitting an old unconfirmed packet."); // static_cast(this)->SendToPhy (m_retxParams.packet); SendToPhy (m_retxParams.packet); } } - } void @@ -358,6 +390,14 @@ EndDeviceLorawanMac::ParseCommands (LoraFrameHeader frameHeader) NS_LOG_ERROR ("Received downlink message not containing an ACK while we were waiting for it!"); } } + else + { + NS_LOG_DEBUG ("Reset retransmission variables to default values."); + if(m_retxParams.sendingMultipleUnconfirmed) + NS_LOG_DEBUG ("Uplink retransmissions will now be cancelled."); + // Reset retransmission parameters + resetRetransmissionParameters (); + } std::list > commands = frameHeader.GetCommands (); std::list >::iterator it; @@ -547,7 +587,7 @@ EndDeviceLorawanMac::GetNextTransmissionDelay (void) waitingTime = std::min (waitingTime, m_channelHelper.GetWaitingTime (logicalChannel)); - NS_LOG_DEBUG ("Waiting time before the next transmission in channel with frequecy " << + NS_LOG_DEBUG ("Waiting time before the next transmission in channel with frequency " << frequency << " is = " << waitingTime.GetSeconds () << "."); } @@ -622,6 +662,7 @@ EndDeviceLorawanMac::Shuffle (std::vector > vector) void EndDeviceLorawanMac::resetRetransmissionParameters () { m_retxParams.waitingAck = false; + m_retxParams.sendingMultipleUnconfirmed = false; m_retxParams.retxLeft = m_maxNumbTx; m_retxParams.packet = 0; m_retxParams.firstAttempt = Seconds (0); @@ -781,6 +822,8 @@ EndDeviceLorawanMac::OnLinkAdrReq (uint8_t dataRate, uint8_t txPower, "DataRateOk: " << dataRateOk << ", " << "txPowerOk: " << txPowerOk); + //TODO: check if repetitions are in valid range [1:15] + // If all checks are successful, set parameters up ////////////////////////////////////////////////// if (channelMaskOk && dataRateOk && txPowerOk) @@ -805,6 +848,8 @@ EndDeviceLorawanMac::OnLinkAdrReq (uint8_t dataRate, uint8_t txPower, // Set the transmission power m_txPower = GetDbmForTxPower (txPower); + + //TODO: also adjust NbTrans. A value of 0 indicates a device should use the default value (1 transmision) } // Craft a LinkAdrAns MAC command as a response diff --git a/model/end-device-lorawan-mac.h b/model/end-device-lorawan-mac.h index a013a6a1a4..0682400561 100644 --- a/model/end-device-lorawan-mac.h +++ b/model/end-device-lorawan-mac.h @@ -341,6 +341,7 @@ class EndDeviceLorawanMac : public LorawanMac Time firstAttempt; Ptr packet = 0; bool waitingAck = false; + bool sendingMultipleUnconfirmed = false; uint8_t retxLeft; };