--- a/src/lte/model/lte-enb-mac.cc Fri Aug 31 16:49:46 2012 +0200
+++ b/src/lte/model/lte-enb-mac.cc Mon Oct 08 17:18:22 2012 +0200
@@ -234,6 +234,8 @@
virtual void SubframeIndication (uint32_t frameNo, uint32_t subframeNo);
virtual void ReceiveLteControlMessage (Ptr<LteControlMessage> msg);
virtual void UlCqiReport (FfMacSchedSapProvider::SchedUlCqiInfoReqParameters ulcqi);
+ virtual void UlInfoListElementHarqFeeback (UlInfoListElement_s params);
+ virtual void DlInfoListElementHarqFeeback (DlInfoListElement_s params);
private:
LteEnbMac* m_mac;
@@ -268,6 +270,18 @@
m_mac->DoUlCqiReport (ulcqi);
}
+void
+EnbMacMemberLteEnbPhySapUser::UlInfoListElementHarqFeeback (UlInfoListElement_s params)
+{
+ m_mac->DoUlInfoListElementHarqFeeback (params);
+}
+
+void
+EnbMacMemberLteEnbPhySapUser::DlInfoListElementHarqFeeback (DlInfoListElement_s params)
+{
+ m_mac->DoDlInfoListElementHarqFeeback (params);
+}
+
// //////////////////////////////////////
// generic LteEnbMac methods
@@ -312,6 +326,12 @@
LteEnbMac::DoDispose ()
{
NS_LOG_FUNCTION (this);
+ m_dlCqiReceived.clear ();
+ m_ulCqiReceived.clear ();
+ m_ulCeReceived.clear ();
+ m_dlInfoListReceived.clear ();
+ m_ulInfoListReceived.clear ();
+m_miDlHarqProcessesPackets.clear ();
delete m_macSapProvider;
delete m_cmacSapProvider;
delete m_schedSapUser;
@@ -412,7 +432,6 @@
m_schedSapProvider->SchedDlCqiInfoReq (dlcqiInfoReq);
}
-
// Get downlink transmission opportunities
uint32_t dlSchedFrameNo = m_frameNo;
uint32_t dlSchedSubframeNo = m_subframeNo;
@@ -426,9 +445,18 @@
{
dlSchedSubframeNo = dlSchedSubframeNo + m_macChTtiDelay;
}
- FfMacSchedSapProvider::SchedDlTriggerReqParameters params; // to be filled
- params.m_sfnSf = ((0x3FF & dlSchedFrameNo) << 4) | (0xF & dlSchedSubframeNo);
- m_schedSapProvider->SchedDlTriggerReq (params);
+ FfMacSchedSapProvider::SchedDlTriggerReqParameters dlparams;
+ dlparams.m_sfnSf = ((0x3FF & dlSchedFrameNo) << 4) | (0xF & dlSchedSubframeNo);
+
+ // Forward DL HARQ feebacks collected during last TTI
+ if (m_dlInfoListReceived.size () > 0)
+ {
+ dlparams.m_dlInfoList = m_dlInfoListReceived;
+ // empty local buffer
+ m_dlInfoListReceived.clear ();
+ }
+
+ m_schedSapProvider->SchedDlTriggerReq (dlparams);
// --- UPLINK ---
@@ -475,26 +503,34 @@
FfMacSchedSapProvider::SchedUlTriggerReqParameters ulparams;
ulparams.m_sfnSf = ((0x3FF & ulSchedFrameNo) << 4) | (0xF & ulSchedSubframeNo);
- std::map <uint16_t,UlInfoListElement_s>::iterator it;
- for (it = m_ulInfoListElements.begin (); it != m_ulInfoListElements.end (); it++)
+ // Forward DL HARQ feebacks collected during last TTI
+ if (m_ulInfoListReceived.size () > 0)
{
- ulparams.m_ulInfoList.push_back ((*it).second);
+ ulparams.m_ulInfoList = m_ulInfoListReceived;
+ // empty local buffer
+ m_ulInfoListReceived.clear ();
}
+
+// std::map <uint16_t,UlInfoListElement_s>::iterator it;
+// for (it = m_ulInfoListElements.begin (); it != m_ulInfoListElements.end (); it++)
+// {
+// ulparams.m_ulInfoList.push_back ((*it).second);
+// }
m_schedSapProvider->SchedUlTriggerReq (ulparams);
// reset UL info
- for (it = m_ulInfoListElements.begin (); it != m_ulInfoListElements.end (); it++)
- {
- for (uint16_t i = 0; i < (*it).second.m_ulReception.size (); i++)
- {
- (*it).second.m_ulReception.at (i) = 0;
- }
- (*it).second.m_receptionStatus = UlInfoListElement_s::Ok;
- (*it).second.m_tpc = 0;
- }
+// for (it = m_ulInfoListElements.begin (); it != m_ulInfoListElements.end (); it++)
+// {
+// for (uint16_t i = 0; i < (*it).second.m_ulReception.size (); i++)
+// {
+// (*it).second.m_ulReception.at (i) = 0;
+// }
+// (*it).second.m_receptionStatus = UlInfoListElement_s::Ok;
+// (*it).second.m_tpc = 0;
+// }
}
void
@@ -511,6 +547,11 @@
Ptr<BsrLteControlMessage> bsr = DynamicCast<BsrLteControlMessage> (msg);
ReceiveBsrMessage (bsr->GetBsr ());
}
+ else if (msg->GetMessageType () == LteControlMessage::DL_HARQ)
+ {
+ Ptr<DlHarqFeedbackLteControlMessage> dlharq = DynamicCast<DlHarqFeedbackLteControlMessage> (msg);
+ DoDlInfoListElementHarqFeeback (dlharq->GetDlHarqFeedback ());
+ }
else
{
NS_LOG_LOGIC (this << " LteControlMessage not recognized");
@@ -525,7 +566,6 @@
{
NS_LOG_DEBUG (this << " eNB rxed an PUSCH UL-CQI");
}
- // TODO store UL-CQI to send them to scheduler
m_ulCqiReceived.push_back (ulcqi);
}
@@ -561,33 +601,33 @@
// store info of the packet received
- std::map <uint16_t,UlInfoListElement_s>::iterator it;
+// std::map <uint16_t,UlInfoListElement_s>::iterator it;
// u_int rnti = tag.GetRnti ();
// u_int lcid = tag.GetLcid ();
- it = m_ulInfoListElements.find (tag.GetRnti ());
- if (it == m_ulInfoListElements.end ())
- {
- // new RNTI
- UlInfoListElement_s ulinfonew;
- ulinfonew.m_rnti = tag.GetRnti ();
- // always allocate full size of ulReception vector, initializing all elements to 0
- ulinfonew.m_ulReception.assign (MAX_LC_LIST+1, 0);
- // set the element for the current LCID
- ulinfonew.m_ulReception.at (tag.GetLcid ()) = p->GetSize ();
- ulinfonew.m_receptionStatus = UlInfoListElement_s::Ok;
- ulinfonew.m_tpc = 0; // Tx power control not implemented at this stage
- m_ulInfoListElements.insert (std::pair<uint16_t, UlInfoListElement_s > (tag.GetRnti (), ulinfonew));
-
- }
- else
- {
- // existing RNTI: we just set the value for the current
- // LCID. Note that the corresponding element had already been
- // allocated previously.
- NS_ASSERT_MSG ((*it).second.m_ulReception.at (tag.GetLcid ()) == 0, "would overwrite previously written ulReception element");
- (*it).second.m_ulReception.at (tag.GetLcid ()) = p->GetSize ();
- (*it).second.m_receptionStatus = UlInfoListElement_s::Ok;
- }
+// it = m_ulInfoListElements.find (tag.GetRnti ());
+// if (it == m_ulInfoListElements.end ())
+// {
+// // new RNTI
+// UlInfoListElement_s ulinfonew;
+// ulinfonew.m_rnti = tag.GetRnti ();
+// // always allocate full size of ulReception vector, initializing all elements to 0
+// ulinfonew.m_ulReception.assign (MAX_LC_LIST+1, 0);
+// // set the element for the current LCID
+// ulinfonew.m_ulReception.at (tag.GetLcid ()) = p->GetSize ();
+// ulinfonew.m_receptionStatus = UlInfoListElement_s::Ok;
+// ulinfonew.m_tpc = 0; // Tx power control not implemented at this stage
+// m_ulInfoListElements.insert (std::pair<uint16_t, UlInfoListElement_s > (tag.GetRnti (), ulinfonew));
+//
+// }
+// else
+// {
+// // existing RNTI: we just set the value for the current
+// // LCID. Note that the corresponding element had already been
+// // allocated previously.
+// NS_ASSERT_MSG ((*it).second.m_ulReception.at (tag.GetLcid ()) == 0, "would overwrite previously written ulReception element");
+// (*it).second.m_ulReception.at (tag.GetLcid ()) = p->GetSize ();
+// (*it).second.m_receptionStatus = UlInfoListElement_s::Ok;
+// }
@@ -629,6 +669,16 @@
params.m_rnti = rnti;
params.m_transmissionMode = 0; // set to default value (SISO) for avoiding random initialization (valgrind error)
m_cschedSapProvider->CschedUeConfigReq (params);
+
+ // Create DL trasmission HARQ buffers
+ std::vector < Ptr<Packet> > dlHarqLayer0pkt;
+ dlHarqLayer0pkt.resize (8);
+ std::vector < Ptr<Packet> > dlHarqLayer1pkt;
+ dlHarqLayer1pkt.resize (8);
+ DlHarqProcessesBuffer_t buf;
+ buf.push_back (dlHarqLayer0pkt);
+ buf.push_back (dlHarqLayer1pkt);
+ m_miDlHarqProcessesPackets.insert (std::pair <uint16_t, DlHarqProcessesBuffer_t> (rnti, buf));
}
void
@@ -703,9 +753,12 @@
NS_LOG_FUNCTION (this);
LteRadioBearerTag tag (params.rnti, params.lcid, params.layer);
params.pdu->AddPacketTag (tag);
-// Ptr<PacketBurst> pb = CreateObject<PacketBurst> ();
-// pb->AddPacket (params.pdu);
-
+ // Store pkt in HARQ buffer
+ std::map <uint16_t, DlHarqProcessesBuffer_t>::iterator it = m_miDlHarqProcessesPackets.find (params.rnti);
+ NS_ASSERT (it!=m_miDlHarqProcessesPackets.end ());
+ NS_LOG_DEBUG (this << " LAYER " <<(uint16_t)tag.GetLayer () << " HARQ ID " << (uint16_t)params.harqProcessId);
+// NS_ASSERT ((*it).second.at (params.layer).at (params.harqProcessId) == 0);
+ (*it).second.at (params.layer).at (params.harqProcessId) = params.pdu;//->Copy ();
m_enbPhySapProvider->SendMacPdu (params.pdu);
}
@@ -746,12 +799,30 @@
{
for (uint16_t k = 0; k < ind.m_buildDataList.at (i).m_rlcPduList.at (j).size (); k++)
{
- LteFlowId_t flow (ind.m_buildDataList.at (i).m_rnti,
- ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_logicalChannelIdentity);
- it = m_rlcAttached.find (flow);
- NS_ASSERT_MSG (it != m_rlcAttached.end (), "rnti=" << flow.m_rnti << " lcid=" << (uint32_t) flow.m_lcId);
- NS_LOG_DEBUG (this << " rnti= " << flow.m_rnti << " lcid= " << (uint32_t) flow.m_lcId << " layer= " << k);
- (*it).second->NotifyTxOpportunity (ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_size, k);
+// NS_ASSERT_MSG (ind.m_buildDataList.at (i).m_dci.m_ndi.size ()<=1, " NOT MIMO, layer " << k);
+// NS_ASSERT_MSG (ind.m_buildDataList.size ()>i, " I " << i);
+// NS_ASSERT_MSG (ind.m_buildDataList.at (i).m_dci.m_ndi.size ()>k, " k " << ind.m_buildDataList.at (i).m_rlcPduList.at (j).size ());
+ if (ind.m_buildDataList.at (i).m_dci.m_ndi.at (k) == 1)
+ {
+ // New Data -> retrieve it from RLC
+ LteFlowId_t flow (ind.m_buildDataList.at (i).m_rnti,
+ ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_logicalChannelIdentity);
+ it = m_rlcAttached.find (flow);
+ NS_ASSERT_MSG (it != m_rlcAttached.end (), "rnti=" << flow.m_rnti << " lcid=" << (uint32_t) flow.m_lcId);
+ NS_LOG_DEBUG (this << " rnti= " << flow.m_rnti << " lcid= " << (uint32_t) flow.m_lcId << " layer= " << k);
+ (*it).second->NotifyTxOpportunity (ind.m_buildDataList.at (i).m_rlcPduList.at (j).at (k).m_size, k, ind.m_buildDataList.at (i).m_dci.m_harqProcess);
+ }
+ else
+ {
+ if (ind.m_buildDataList.at (i).m_dci.m_tbsSize.at (k)>0)
+ {
+ // HARQ retransmission -> retrieve TB from HARQ buffer
+ std::map <uint16_t, DlHarqProcessesBuffer_t>::iterator it = m_miDlHarqProcessesPackets.find (ind.m_buildDataList.at (i).m_rnti);
+ NS_ASSERT(it!=m_miDlHarqProcessesPackets.end());
+ Ptr<Packet> pkt = (*it).second.at (k).at ( ind.m_buildDataList.at (i).m_dci.m_harqProcess)->Copy ();
+ m_enbPhySapProvider->SendMacPdu (pkt);
+ }
+ }
}
}
// send the relative DCI
@@ -884,5 +955,39 @@
NS_LOG_FUNCTION (this);
}
+void
+LteEnbMac::DoUlInfoListElementHarqFeeback (UlInfoListElement_s params)
+{
+ NS_LOG_FUNCTION (this);
+ m_ulInfoListReceived.push_back (params);
+}
+
+void
+LteEnbMac::DoDlInfoListElementHarqFeeback (DlInfoListElement_s params)
+{
+ NS_LOG_FUNCTION (this);
+ // Update HARQ buffer
+ std::map <uint16_t, DlHarqProcessesBuffer_t>::iterator it = m_miDlHarqProcessesPackets.find (params.m_rnti);
+ NS_ASSERT (it!=m_miDlHarqProcessesPackets.end ());
+ for (uint8_t layer = 0; layer < params.m_harqStatus.size (); layer++)
+ {
+ if (params.m_harqStatus.at (layer)==DlInfoListElement_s::ACK)
+ {
+ // discard buffer
+ (*it).second.at (layer).at (params.m_harqProcessId) = 0;
+ NS_LOG_DEBUG (this << " HARQ-ACK UE " << params.m_rnti << " harqId " << (uint16_t)params.m_harqProcessId << " layer " << (uint16_t)layer);
+ }
+ else if (params.m_harqStatus.at (layer)==DlInfoListElement_s::NACK)
+ {
+ NS_LOG_DEBUG (this << " HARQ-NACK UE " << params.m_rnti << " harqId " << (uint16_t)params.m_harqProcessId << " layer " << (uint16_t)layer);
+ }
+ else
+ {
+ NS_FATAL_ERROR (" HARQ functionality not implemented");
+ }
+ }
+ m_dlInfoListReceived.push_back (params);
+}
+
} // namespace ns3