Uplink scheduler with multiple bearers (LCs) allocates in a Round Robin fashion the active ones
--- a/src/lte/model/lte-enb-phy.cc Mon Nov 28 12:30:41 2011 +0100
+++ b/src/lte/model/lte-enb-phy.cc Mon Nov 28 12:32:08 2011 +0100
@@ -397,8 +397,6 @@
}
// trigger the MAC
- Ptr<LteEnbMac> macEntity = GetDevice ()->GetObject<LteEnbNetDevice> ()->GetMac ();
-
m_enbPhySapUser->SubframeIndication (m_nrFrames, m_nrSubFrames);
--- a/src/lte/model/lte-ue-mac.cc Mon Nov 28 12:30:41 2011 +0100
+++ b/src/lte/model/lte-ue-mac.cc Mon Nov 28 12:32:08 2011 +0100
@@ -31,6 +31,7 @@
#include "lte-mac-tag.h"
#include <ns3/ff-mac-common.h>
#include <ns3/ideal-control-messages.h>
+#include <ns3/simulator.h>
NS_LOG_COMPONENT_DEFINE ("LteUeMac");
@@ -161,7 +162,7 @@
void
UeMemberLteUePhySapUser::SubframeIndication (uint32_t frameNo, uint32_t subframeNo)
{
- NS_LOG_LOGIC (this << " UE-MAC does not yet support this primitive");
+ m_mac->DoSubframeIndication (frameNo, subframeNo);
}
void
@@ -189,6 +190,9 @@
LteUeMac::LteUeMac ()
+ : m_bsrPeriodicity (MilliSeconds (1)), // ideal behavior
+ m_bsrLast (MilliSeconds (0))
+
{
NS_LOG_FUNCTION (this);
m_macSapProvider = new UeMemberLteMacSapProvider (this);
@@ -263,24 +267,51 @@
LteUeMac::DoReportBufferStatus (LteMacSapProvider::ReportBufferStatusParameters params)
{
NS_LOG_FUNCTION (this);
+
+ std::map <uint8_t, long uint>::iterator it;
+
+
+ it = m_ulBsrReceived.find (params.lcid);
+ if (it!=m_ulBsrReceived.end ())
+ {
+ // update entry
+ (*it).second = params.txQueueSize + params.retxQueueSize + params.statusPduSize;
+ }
+ else
+ {
+ m_ulBsrReceived.insert (std::pair<uint8_t, long uint> (params.lcid, params.txQueueSize + params.retxQueueSize + params.statusPduSize));
+ }
+}
+
+
+void
+LteUeMac::SendReportBufferStatus (void)
+{
+ NS_LOG_FUNCTION (this);
MacCeListElement_s bsr;
bsr.m_rnti = m_rnti;
bsr.m_macCeType = MacCeListElement_s::BSR;
- // short BSR
- int queue = params.txQueueSize;
- int index = 0;
- if (BufferSizeLevelBsr[63] < queue)
+ // BSR
+ std::map <uint8_t, long uint>::iterator it;
+ NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
+
+ for (it = m_ulBsrReceived.begin (); it != m_ulBsrReceived.end (); it++)
{
- index = 63;
+ int queue = (*it).second;
+ int index = 0;
+ if (BufferSizeLevelBsr[63] < queue)
+ {
+ index = 63;
+ }
+ else
+ {
+ while (BufferSizeLevelBsr[index] < queue)
+ {
+ index++;
+ }
+ }
+ bsr.m_macCeValue.m_bufferStatus.push_back (index);
}
- else
- {
- while (BufferSizeLevelBsr[index] < queue)
- {
- index++;
- }
- }
- bsr.m_macCeValue.m_bufferStatus.push_back (index);
// create the feedback to eNB
Ptr<BsrIdealControlMessage> msg = Create<BsrIdealControlMessage> ();
@@ -336,9 +367,33 @@
{
Ptr<UlDciIdealControlMessage> msg2 = DynamicCast<UlDciIdealControlMessage> (msg);
UlDciListElement_s dci = msg2->GetDci ();
- std::map <uint8_t, LteMacSapUser*>::iterator it;
- it = m_macSapUserMap.begin (); // use only the first LC --> UE-SCHEDULER??
- (*it).second->NotifyTxOpportunity (dci.m_tbSize);
+ std::map <uint8_t, long uint>::iterator itBsr;
+ NS_ASSERT_MSG (m_ulBsrReceived.size () <=4, " Too many LCs (max is 4)");
+ int activeLcs = 0;
+ for (itBsr = m_ulBsrReceived.begin (); itBsr != m_ulBsrReceived.end (); itBsr++)
+ {
+ if ((*itBsr).second > 0)
+ {
+ activeLcs++;
+ }
+ }
+ if (activeLcs <= 0)
+ {
+ NS_LOG_ERROR (this << " No active flows for this UL-DCI");
+ return;
+ }
+ std::map <uint8_t, LteMacSapUser*>::iterator it;
+ NS_LOG_FUNCTION (this << " UE: UL-CQI notified TxOpportunity of " << dci.m_tbSize);
+ for (it = m_macSapUserMap.begin (); it!=m_macSapUserMap.end (); it++)
+ {
+ itBsr = m_ulBsrReceived.find ((*it).first);
+ if (itBsr!=m_ulBsrReceived.end ())
+ {
+ NS_LOG_FUNCTION (this << "\t" << dci.m_tbSize / m_macSapUserMap.size () << " bytes to LC " << (uint16_t)(*it).first << " queue " << (*itBsr).second);
+ (*it).second->NotifyTxOpportunity (dci.m_tbSize / activeLcs);
+ (*itBsr).second -= dci.m_tbSize / activeLcs;
+ }
+ }
}
else
@@ -348,4 +403,16 @@
}
+void
+LteUeMac::DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo)
+{
+ NS_LOG_FUNCTION (this);
+ if (Simulator::Now () > m_bsrLast + m_bsrPeriodicity)
+ {
+ SendReportBufferStatus ();
+ m_bsrLast = Simulator::Now ();
+ }
+}
+
+
} // namespace ns3
--- a/src/lte/model/lte-ue-mac.h Mon Nov 28 12:30:41 2011 +0100
+++ b/src/lte/model/lte-ue-mac.h Mon Nov 28 12:32:08 2011 +0100
@@ -29,6 +29,7 @@
#include <ns3/lte-mac-sap.h>
#include <ns3/lte-ue-cmac-sap.h>
#include <ns3/lte-ue-phy-sap.h>
+#include <ns3/nstime.h>
namespace ns3 {
@@ -62,6 +63,14 @@
* \param s a pointer to the PHY SAP Provider
*/
void SetLteUePhySapProvider (LteUePhySapProvider* s);
+
+ /**
+ * \brief Forwarded from LteUePhySapUser: trigger the start from a new frame
+ *
+ * \param frameNo frame number
+ * \param subframeNo subframe number
+ */
+ void DoSubframeIndication (uint32_t frameNo, uint32_t subframeNo);
private:
// forwarded from MAC SAP
@@ -76,6 +85,8 @@
// forwarded from PHY SAP
void DoReceivePhyPdu (Ptr<Packet> p);
void DoReceiveIdealControlMessage (Ptr<IdealControlMessage> msg);
+
+ void SendReportBufferStatus (void);
private:
// end of temporary hack
@@ -87,6 +98,11 @@
LteUePhySapProvider* m_uePhySapProvider;
LteUePhySapUser* m_uePhySapUser;
+
+ std::map <uint8_t, long uint> m_ulBsrReceived; // BSR received from RLC (BSR up to now)
+
+ Time m_bsrPeriodicity;
+ Time m_bsrLast;
uint16_t m_rnti;
--- a/src/lte/model/lte-ue-phy.cc Mon Nov 28 12:30:41 2011 +0100
+++ b/src/lte/model/lte-ue-phy.cc Mon Nov 28 12:32:08 2011 +0100
@@ -491,6 +491,9 @@
{
m_uplinkSpectrumPhy->StartTx (pb);
}
+
+ // trigger the MAC
+ m_uePhySapUser->SubframeIndication (frameNo, subframeNo);
}