diff --git a/nfapi/oai_integration/aerial/fapi_nvIPC.c b/nfapi/oai_integration/aerial/fapi_nvIPC.c index bbb0d66900..53717ffdaf 100644 --- a/nfapi/oai_integration/aerial/fapi_nvIPC.c +++ b/nfapi/oai_integration/aerial/fapi_nvIPC.c @@ -355,7 +355,7 @@ void *epoll_recv_task(void *arg) void create_recv_thread(int8_t affinity) { pthread_t thread_id; - threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT); + threadCreate(&thread_id, epoll_recv_task, NULL, "vnf_nvipc_aerial", affinity, OAI_PRIORITY_RT_MAX); } int load_hard_code_config(nv_ipc_config_t *config, int module_type, nv_ipc_transport_t _transport) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 2c3ee539fc..d60fd6bfd3 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3898,6 +3898,8 @@ static int nr_ue_validate_successrar(uint8_t *pduP, int32_t pdu_len, NR_UE_MAC_I return n; } +#define MAX_NUM_DATA_IND 1024 + /////////////////////////////////// // brief: nr_ue_process_mac_pdu // function: parsing DL PDU header @@ -3962,6 +3964,9 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ pdu_len -= n; } + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; + while (!done && pdu_len > 0){ uint16_t mac_len = 0x0000; uint16_t mac_subheader_len = 0x0001; // default to fixed-length subheader = 1-oct @@ -3992,7 +3997,9 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ if (mac_len > 0) { LOG_DDUMP(NR_MAC, (void *)pduP, mac_subheader_len + mac_len, LOG_DUMP_CHAR, "DL_SCH_LCID_CCCH (e.g. RRCSetup) payload: "); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } break; case DL_SCH_LCID_TCI_STATE_ACT_UE_SPEC_PDSCH: @@ -4104,15 +4111,20 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ // MAC SDU // From values 1 to 32 it equals to the identity of the logical channel case 1 ... 32: - if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) - return; + if (!get_mac_len(pduP, pdu_len, &mac_len, &mac_subheader_len)) { + LOG_E(MAC, "get_mac_len(): invalid pdu_len %d (mac_len %d mac_subheader_len %d)\n", pdu_len, mac_len, mac_subheader_len); + done = 1; + break; + } // discard the received subPDU if RB is suspended if (is_lcid_suspended(mac, rx_lcid)) { LOG_W(NR_MAC, "Received PDU for a suspended RB, corresponding to LCID %d. Dropping it.\n", rx_lcid); break; } LOG_D(NR_MAC, "%4d.%2d : DLSCH -> LCID %d %d bytes\n", frameP, slot, rx_lcid, mac_len); - nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = rx_lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); break; default: LOG_W(MAC, "unknown lcid %02x\n", rx_lcid); @@ -4120,9 +4132,13 @@ static void nr_ue_process_mac_pdu(NR_UE_MAC_INST_t *mac, nr_downlink_indication_ } pduP += (mac_subheader_len + mac_len); pdu_len -= (mac_subheader_len + mac_len); - if (pdu_len < 0) + if (pdu_len < 0) { LOG_E(MAC, "[UE %d][%d.%d] nr_ue_process_mac_pdu, residual mac pdu length %d < 0!\n", mac->ue_id, frameP, slot, pdu_len); + done = 1; + } } + + nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, data_ind, num_data_ind); } /** diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index cc933b50e4..071514cbaa 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1461,23 +1461,24 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent) static void nr_update_rlc_buffers_status(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP) { + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; for (int i = 0; i < mac->lc_ordered_list.count; i++) { nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i]; if (lc_info->rb_suspended) continue; - int lcid = lc_info->lcid; + ch[n++] = lc_info->lcid; + } + + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(mac->ue_id, frameP, n, ch, ret); + for (int i = 0; i < n; ++i) { + const logical_chan_id_t lcid = ch[i]; + const rlc_buffer_occupancy_t b = ret[i].bytes_in_buffer; NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lcid); - mac_rlc_status_resp_t rlc_status = nr_mac_rlc_status_ind(mac->ue_id, frameP, lcid); - if (rlc_status.bytes_in_buffer > 0) { - LOG_D(NR_MAC, - "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", - mac->ue_id, - lcid, - rlc_status.bytes_in_buffer, - frameP, - slotP); - } - lc_sched_info->LCID_buffer_remain = rlc_status.bytes_in_buffer; + if (b > 0) + LOG_D(NR_MAC, "[UE %d] LCID %d has %d bytes to transmit at sfn %d.%d\n", mac->ue_id, lcid, b, frameP, slotP); + lc_sched_info->LCID_buffer_remain = b; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 44fd2546cb..fc563b56b9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1699,21 +1699,23 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int current_harq_pid = sched_ctrl->retrans_dl_harq.head; - logical_chan_id_t lcid = DL_SCH_LCID_CCCH; + logical_chan_id_t lcid = 0; if (current_harq_pid < 0) { - // Check for data on SRB0 (RRCSetup) - mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + const logical_chan_id_t lcid_l[2] = {DL_SCH_LCID_CCCH, DL_SCH_LCID_DCCH}; + mac_rlc_status_resp_t stat[2]; + nr_mac_rlc_status_ind(UE->rnti, frameP, 2, lcid_l, stat); - if (srb_status.bytes_in_buffer == 0) { - lcid = DL_SCH_LCID_DCCH; - // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) - srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); + if (stat[0].bytes_in_buffer > 0) { + // some data in SRB0 (likely RRCSetup) + mac_sdu_length = stat[0].bytes_in_buffer; + lcid = lcid_l[0]; + } else if (stat[1].bytes_in_buffer > 0) { + // some data in SRB1 (likely RRCReestablishmnt/RRCReconfiguration) + mac_sdu_length = stat[1].bytes_in_buffer; + lcid = lcid_l[1]; + } else { + return; // no data to forward } - - // Need to wait until data for Msg4 is ready - if (srb_status.bytes_in_buffer == 0) - return; - mac_sdu_length = srb_status.bytes_in_buffer; } const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 8ad9d4f6bc..dbf285e931 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -50,6 +50,8 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) +#define MAX_NUM_DATA_REQ 1024 + int get_dl_tda(const gNB_MAC_INST *nrmac, int slot) { /* we assume that this function is mutex-protected from outside */ @@ -326,31 +328,38 @@ static uint32_t update_dlsch_buffer(frame_t frame, slot_t slot, NR_UE_info_t *UE sched_ctrl->num_total_bytes = 0; sched_ctrl->dl_pdus_total = 0; + logical_chan_id_t ch[NR_MAX_NUM_LCID] = {0}; + int n = 0; /* loop over all activated logical channels */ - for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { - const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); - const int lcid = c->lcid; - const uint16_t rnti = UE->rnti; - LOG_D(NR_MAC, "UE %x: LCID %d\n", rnti, lcid); - memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); - if (c->suspended) + FOR_EACH_SEQ_ARR(const nr_lc_config_t *, c, &sched_ctrl->lc_config ) { + logical_chan_id_t lcid = c->lcid; + if (c->suspended || (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt))) { + memset(&sched_ctrl->rlc_status[lcid], 0, sizeof(sched_ctrl->rlc_status[lcid])); continue; - if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt)) - continue; - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + } + ch[n++] = lcid; + } - if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) + mac_rlc_status_resp_t ret[NR_MAX_NUM_LCID] = {0}; + nr_mac_rlc_status_ind(UE->rnti, frame, n, ch, ret); + + for (int i = 0; i < n; ++i) { + logical_chan_id_t lcid = ch[i]; + + if (ret[i].bytes_in_buffer == 0) continue; + sched_ctrl->rlc_status[lcid] = ret[i]; sched_ctrl->dl_pdus_total += sched_ctrl->rlc_status[lcid].pdus_in_buffer; sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; LOG_D(MAC, - "%4d.%2d UE %04x LCID %d status: %d bytes, total buffer %d bytes %d PDUs\n", + "%4d.%2d UE %04x LCID %d status: %d bytes, %d PDUs, total buffer %d bytes %d PDUs\n", frame, slot, UE->rnti, lcid, - sched_ctrl->rlc_status[lcid].bytes_in_buffer, + ret[i].bytes_in_buffer, + ret[i].pdus_in_buffer, sched_ctrl->num_total_bytes, sched_ctrl->dl_pdus_total); } @@ -1289,47 +1298,25 @@ void post_process_dlsch(gNB_MAC_INST *nr_mac, post_process_pdsch_t *pdsch, NR_UE if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) continue; // no data for this LC tbs_size_t len = 0; - int lcid_bytes=0; - while (bufEnd-buf > sizeof(NR_MAC_SUBHEADER_LONG) + 1 ) { - // we do not know how much data we will get from RLC, i.e., whether it - // will be longer than 256B or not. Therefore, reserve space for long header, then - // fetch data, then fill real length + + tb_size_t pdu_siz[MAX_NUM_DATA_REQ]; + int num = nr_mac_rlc_multi_data_req(module_id, rnti, true, lcid, bufEnd - buf, (char *)buf, pdu_siz, sizeofArray(pdu_siz)); + DevAssert(num <= sizeofArray(pdu_siz)); + + sdus += num; + int lcid_bytes = 0; + for (int j = 0; j < num; ++j) { NR_MAC_SUBHEADER_LONG *header = (NR_MAC_SUBHEADER_LONG *) buf; - /* limit requested number of bytes to what preprocessor specified, or - * such that TBS is full */ - const rlc_buffer_occupancy_t ndata = min(sched_ctrl->rlc_status[lcid].bytes_in_buffer, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - tbs_size_t len = nr_mac_rlc_data_req(module_id, - rnti, - true, - lcid, - ndata, - (char *)buf+sizeof(NR_MAC_SUBHEADER_LONG)); - LOG_D(NR_MAC, - "%4d.%2d RNTI %04x: %d bytes from %s %d (ndata %d, remaining size %ld)\n", - frame, - slot, - rnti, - len, - lcid < 4 ? "DCCH" : "DTCH", - lcid, - ndata, - bufEnd-buf-sizeof(NR_MAC_SUBHEADER_LONG)); - - if (len == 0) - break; - - T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(len * 8), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); header->R = 0; header->F = 1; header->LCID = lcid; - header->L = htons(len); - buf += len+sizeof(NR_MAC_SUBHEADER_LONG); - dlsch_total_bytes += len; - lcid_bytes += len; - sdus += 1; + header->L = htons(pdu_siz[j]); + buf += pdu_siz[j] + sizeof(NR_MAC_SUBHEADER_LONG); + dlsch_total_bytes += pdu_siz[j]; + lcid_bytes += pdu_siz[j]; } + T(T_GNB_MAC_LCID_DL, T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(lcid), T_INT(lcid_bytes), T_INT(nr_rlc_tx_list_occupancy(rnti, lcid))); UE->mac_stats.dl.lc_bytes[lcid] += lcid_bytes; } } else if (get_softmodem_params()->phy_test || get_softmodem_params()->do_ra) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index fdec1d0c6f..08b8f6edc0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -144,11 +144,11 @@ void nr_preprocessor_phytest(gNB_MAC_INST *mac, post_process_pdsch_t *pp_pdsch) sched_ctrl->num_total_bytes = 0; DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1); const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0); - const int lcid = c->lcid; + const logical_chan_id_t lcid = c->lcid; const uint16_t rnti = UE->rnti; /* update sched_ctrl->num_total_bytes so that postprocessor schedules data, * if available */ - sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(rnti, frame, lcid); + nr_mac_rlc_status_ind(rnti, frame, 1, &lcid, &sched_ctrl->rlc_status[lcid]); sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer; int CCEIndex = get_cce_index(mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 481c0ea9f8..0998eb463b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -37,6 +37,7 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" //#define SRS_IND_DEBUG +#define MAX_NUM_DATA_IND 1024 /* \brief Get the number of UL TDAs that could be used in slot, reachable * via specific k2. The output parameter first_idx is a pointer to the first @@ -395,6 +396,8 @@ static int nr_process_mac_pdu(instance_t module_idP, log_dump(NR_MAC, pduP, pdu_len, LOG_DUMP_CHAR, "\n"); #endif + nr_rlc_data_ind_t data_ind[MAX_NUM_DATA_IND] = {0}; + int num_data_ind = 0; while (pdu_len > 0) { uint16_t mac_len = 0; uint8_t lcid = 0; @@ -416,7 +419,7 @@ static int nr_process_mac_pdu(instance_t module_idP, for (int i = 0; i < print_len; i++) printf("%02x ", pduP[i]); printf("\n"); - return 0; + break; } LOG_D(NR_MAC, @@ -456,7 +459,9 @@ static int nr_process_mac_pdu(instance_t module_idP, } if (prepare_initial_ul_rrc_message(RC.nrmac[module_idP], UE)) { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, 0, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = 0, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); } else { LOG_E(NR_MAC, "prepare_initial_ul_rrc_message() returned false, cannot forward CCCH message\n"); } @@ -475,7 +480,9 @@ static int nr_process_mac_pdu(instance_t module_idP, if (!srbc || srbc->suspended) { LOG_I(NR_MAC, "RNTI %04x LCID %d: ignoring %d bytes\n", UE->rnti, lcid, mac_len); } else { - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); UE->mac_stats.ul.total_sdu_bytes += mac_len; UE->mac_stats.ul.lc_bytes[lcid] += mac_len; @@ -499,7 +506,9 @@ static int nr_process_mac_pdu(instance_t module_idP, } else { UE->mac_stats.ul.lc_bytes[lcid] += mac_len; - nr_mac_rlc_data_ind(module_idP, UE->rnti, true, lcid, (char *)(pduP + mac_subheader_len), mac_len); + nr_rlc_data_ind_t ind = {.ch = lcid, .buf = pduP + mac_subheader_len, .len = mac_len}; + data_ind[num_data_ind++] = ind; + DevAssert(num_data_ind < MAX_NUM_DATA_IND); sdus += 1; /* Updated estimated buffer when receiving data */ @@ -530,7 +539,7 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_SINGLE_ENTRY_PHR: if (harq_pid < 0) { LOG_E(NR_MAC, "Invalid HARQ PID %d\n", harq_pid); - return 0; + continue; } NR_sched_pusch_t *sched_pusch = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch; @@ -605,14 +614,18 @@ static int nr_process_mac_pdu(instance_t module_idP, case UL_SCH_LCID_PADDING: // End of MAC PDU, can ignore the rest. - return 0; + // 38.321 Sec 6.1.5: "Presence and length of padding is implicit based + // on TB size, size of MAC subPDU(s)." + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 + break; default: LOG_E(NR_MAC, "RNTI %0x [%d.%d], received unknown MAC header (LCID = 0x%02x)\n", UE->rnti, frameP, slot, lcid); - return -1; + mac_len = pdu_len - mac_subheader_len; // will make pdu_len go to 0 break; } + #ifdef ENABLE_MAC_PAYLOAD_DEBUG if (lcid < 45 || lcid == 52 || lcid == 63) { LOG_I(NR_MAC, "In %s: dumping UL MAC SDU sub-header with length %d (LCID = 0x%02x):\n", __func__, mac_subheader_len, lcid); @@ -629,6 +642,8 @@ static int nr_process_mac_pdu(instance_t module_idP, pdu_len -= (mac_subheader_len + mac_len); } + nr_mac_rlc_data_ind(module_idP, UE->rnti, true, data_ind, num_data_ind); + UE->mac_stats.ul.num_mac_sdu += sdus; return 0; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 133aea8d15..9789e85a84 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -163,12 +163,12 @@ void nr_rlc_release_entity(int ue_id, logical_chan_id_t channel_id) void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP) + const nr_rlc_data_ind_t *data, + int num_data) { if (gnb_flagP) - T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(channel_idP), T_INT(tb_sizeP)); + for (int i = 0; i < num_data; ++i) + T(T_ENB_RLC_MAC_UL, T_INT(module_idP), T_INT(ue_id), T_INT(data[i].ch), T_INT(data[i].len)); nr_rlc_manager_lock(nr_rlc_ue_manager); nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); @@ -176,20 +176,65 @@ void nr_mac_rlc_data_ind(const module_id_t module_idP, if(ue == NULL) LOG_I(RLC, "RLC instance for the given UE was not found \n"); - nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); - - if (rb != NULL) { - LOG_D(RLC, "RB found! (channel ID %d) \n", channel_idP); - rb->set_time(rb, get_nr_rlc_current_time()); - rb->recv_pdu(rb, buffer_pP, tb_sizeP); - } else { - LOG_E(RLC, "Fatal: no RB found (channel ID %d UE ID %d)\n", channel_idP, ue_id); - // exit(1); + for (int i = 0; i < num_data; ++i) { + logical_chan_id_t ch = data[i].ch; + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, ch); + if (rb != NULL) { + LOG_D(RLC, "RB found! (channel ID %d) \n", ch); + rb->set_time(rb, get_nr_rlc_current_time()); + rb->recv_pdu(rb, (char *)data[i].buf, data[i].len); + } else { + LOG_W(RLC, "no RB found (channel ID %d UE ID %d)\n", ch, ue_id); + } } nr_rlc_manager_unlock(nr_rlc_ue_manager); } +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len) +{ + int ret = 0; + + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); + + if (rb != NULL) { + rb->set_time(rb, get_nr_rlc_current_time()); + while (tb_sizeP - 3 > 0 && pdu_siz_len > 0) { + // fill PDU in buffer, store size of PDU + pdu_siz[0] = rb->generate_pdu(rb, buffer_pP + 3, tb_sizeP - 3); + if (pdu_siz[0] == 0) + break; + LOG_D(RLC, "MAC PDU created: channel_idP %d len %d\n", channel_idP, pdu_siz[0]); + // reserve header + tb_sizeP -= 3 + pdu_siz[0]; + buffer_pP += 3 + pdu_siz[0]; + pdu_siz++; + pdu_siz_len--; + ret++; + } + } else { + LOG_D(RLC, "MAC PDU failed to get created for channel_idP:%d \n", channel_idP); + ret = 0; + } + + nr_rlc_manager_unlock(nr_rlc_ue_manager); + + if (gnb_flagP) + T(T_ENB_RLC_MAC_DL, T_INT(module_idP), T_INT(ue_id), + T_INT(channel_idP), T_INT(ret)); + + return ret; +} + tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, @@ -223,12 +268,10 @@ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, return ret; } -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP) +static mac_rlc_status_resp_t _nr_rlc_status_ind(nr_rlc_ue_t *ue, frame_t frame, logical_chan_id_t channel_idP) { mac_rlc_status_resp_t ret; - nr_rlc_manager_lock(nr_rlc_ue_manager); - nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, channel_idP); if (rb != NULL) { @@ -243,12 +286,10 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t ret.bytes_in_buffer = buf_stat.status_size + buf_stat.retx_size + buf_stat.tx_size; } else { if (!(frame % 128) || channel_idP == 0) //to suppress this warning message - LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue_id); + LOG_W(RLC, "Radio Bearer (channel ID %d) is NULL for UE %d\n", channel_idP, ue->ue_id); ret.bytes_in_buffer = 0; } - nr_rlc_manager_unlock(nr_rlc_ue_manager); - ret.pdus_in_buffer = 0; /* TODO: creation time may be important (unit: frame, as it seems) */ ret.head_sdu_creation_time = 0; @@ -257,6 +298,16 @@ mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t return ret; } +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret) +{ + nr_rlc_manager_lock(nr_rlc_ue_manager); + nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id); + for (int i = 0; i < n_ch; ++i) { + ret[i] = _nr_rlc_status_ind(ue, frame, ch[i]); + } + nr_rlc_manager_unlock(nr_rlc_ue_manager); +} + rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_idP, @@ -1022,7 +1073,7 @@ bool nr_rlc_get_statistics(int ue_id, int srb_flag, int rb_id, nr_rlc_statistics // Patch buffer status using OAI results (no need to change anything in the RB) // rb->set_time(rb, get_nr_rlc_current_time()); - nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 1000*1000); + nr_rlc_entity_buffer_status_t oai_stat = rb->buffer_status(rb, 256 * 1000); out->rxbuf_occ_bytes = oai_stat.status_size; out->txbuf_occ_bytes = oai_stat.tx_size + oai_stat.retx_size; } else { diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h index 454a59b928..cf5d088834 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h @@ -41,12 +41,32 @@ struct NR_RLC_Config; struct NR_LogicalChannelConfig; int nr_rlc_module_init(nr_rlc_op_mode_t mode); +typedef struct nr_rlc_data_ind { + logical_chan_id_t ch; + uint8_t *buf; + tb_size_t len; +} nr_rlc_data_ind_t; void nr_mac_rlc_data_ind(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, - const logical_chan_id_t channel_idP, - char *buffer_pP, - const tb_size_t tb_sizeP); + const nr_rlc_data_ind_t *data, + int num_data); +/* \brief Fill up to pdu_siz_len RLC PDUs into buffer pointed to by buffer_pP, + * or until tb_sizeP is reached. Each PDU is preceded by 3 bytes (nothing is + * written) that have to be filled by the consumer (with a MAC sub-PDU + * subheader). This function fills up to an entire TB in a single call, unlike + * nr_mac_rlc_data_req() that fills only one RLC PDU in one step. */ +int nr_mac_rlc_multi_data_req(const module_id_t module_idP, + const uint16_t ue_id, + const bool gnb_flagP, + const logical_chan_id_t channel_idP, + const tb_size_t tb_sizeP, + char *buffer_pP, + tb_size_t *pdu_siz, + int pdu_siz_len); +/* \brief Fill one RLC PDU into buffer pointed to by buffer_pP, or until + * tb_sizeP is reached. Note that NO header is prepended (for a MAC sub-PDU + * subheader), and the user of the API has to fill the necessary data. */ tbs_size_t nr_mac_rlc_data_req(const module_id_t module_idP, const uint16_t ue_id, const bool gnb_flagP, @@ -59,7 +79,7 @@ rlc_op_status_t nr_rlc_data_req(const protocol_ctxt_t *const ctxt_pP, const mui_t muiP, sdu_size_t sdu_sizeP, uint8_t *sdu_pP); -mac_rlc_status_resp_t nr_mac_rlc_status_ind(const uint16_t ue_id, const frame_t frame, const logical_chan_id_t channel_idP); +void nr_mac_rlc_status_ind(uint16_t ue_id, frame_t frame, int n_ch, const logical_chan_id_t *ch, mac_rlc_status_resp_t *ret); void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig); void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);