// This function assigns pre-available RBS to each UE in specified sub-bands before scheduling is done
void dlsch_scheduler_pre_processor (module_id_t   Mod_id,
                                    frame_t       frameP,
                                    sub_frame_t   subframeP,
                                    uint8_t       dl_pow_off[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
                                    uint16_t      pre_nb_available_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX],
                                    int           N_RBG[MAX_NUM_CCs],
                                    unsigned char rballoc_sub_UE[MAX_NUM_CCs][NUMBER_OF_UE_MAX][N_RBG_MAX],
                                    int           *mbsfn_flag)
{

  unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX],harq_pid=0,harq_pid1=0,harq_pid2=0,round=0,round1=0,round2=0,total_ue_count;
  unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX];
  int                     UE_id, UE_id2, i;
  uint16_t                ii,j;
  uint16_t                nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                nb_rbs_required_remaining_1[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  uint16_t                i1,i2,i3,r1=0;
  uint16_t                average_rbs_per_user[MAX_NUM_CCs] = {0};
  rnti_t             rnti,rnti1,rnti2;
  LTE_eNB_UE_stats  *eNB_UE_stats1 = NULL;
  LTE_eNB_UE_stats  *eNB_UE_stats2 = NULL;
  int                min_rb_unit[MAX_NUM_CCs];

  uint8_t CC_id;
  UE_list_t *UE_list = &eNB_mac_inst[Mod_id].UE_list;
  LTE_DL_FRAME_PARMS   *frame_parms[MAX_NUM_CCs] = {0};
  int rrc_status           = RRC_IDLE;
  int transmission_mode = 0;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

    if (mbsfn_flag[CC_id]>0)  // If this CC is allocated for MBSFN skip it here
      continue;

    frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);


    min_rb_unit[CC_id]=get_min_rb_unit(Mod_id,CC_id);

    for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
      UE_id = i;
      // Initialize scheduling information for all active UEs

      dlsch_scheduler_pre_processor_reset(
        UE_id,
        CC_id,
        N_RBG[CC_id],
        dl_pow_off,
        nb_rbs_required,
        pre_nb_available_rbs,
        nb_rbs_required_remaining,
        rballoc_sub_UE,
        rballoc_sub,
        MIMO_mode_indicator);

    }
  }



  // Store the DLSCH buffer for each logical channel
  store_dlsch_buffer (Mod_id,frameP,subframeP);



  // Calculate the number of RBs required by each UE on the basis of logical channel's buffer
  assign_rbs_required (Mod_id,frameP,subframeP,nb_rbs_required,min_rb_unit);



  // Sorts the user on the basis of dlsch logical channel buffer and CQI
  sort_UEs (Mod_id,frameP,subframeP);



  total_ue_count =0;

  // loop over all active UEs
  for (i=UE_list->head; i>=0; i=UE_list->next[i]) {
    rnti = UE_RNTI(Mod_id,i);

    if(rnti == NOT_A_RNTI)
      continue;

    UE_id = i;

    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
      CC_id = UE_list->ordered_CCids[ii][UE_id];

      average_rbs_per_user[CC_id]=0;

      frame_parms[CC_id] = mac_xface->get_lte_frame_parms(Mod_id,CC_id);

      mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);

      if(round>0) {
        nb_rbs_required[CC_id][UE_id] = UE_list->UE_template[CC_id][UE_id].nb_rb[harq_pid];
      }

      //nb_rbs_required_remaining[UE_id] = nb_rbs_required[UE_id];
      if (nb_rbs_required[CC_id][UE_id] > 0) {
        total_ue_count = total_ue_count + 1;
      }


      // hypotetical assignement
      /*
       * If schedule is enabled and if the priority of the UEs is modified
       * The average rbs per logical channel per user will depend on the level of
       * priority. Concerning the hypothetical assignement, we should assign more
       * rbs to prioritized users. Maybe, we can do a mapping between the
       * average rbs per user and the level of priority or multiply the average rbs
       * per user by a coefficient which represents the degree of priority.
       */

      if (total_ue_count == 0) {
        average_rbs_per_user[CC_id] = 0;
      } else if( (min_rb_unit[CC_id] * total_ue_count) <= (frame_parms[CC_id]->N_RB_DL) ) {
        average_rbs_per_user[CC_id] = (uint16_t) floor(frame_parms[CC_id]->N_RB_DL/total_ue_count);
      } else {
        average_rbs_per_user[CC_id] = min_rb_unit[CC_id]; // consider the total number of use that can be scheduled UE
      }
    }
  }

  // note: nb_rbs_required is assigned according to total_buffer_dl
  // extend nb_rbs_required to capture per LCID RB required
  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
    rnti = UE_RNTI(Mod_id,i);

    for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
      CC_id = UE_list->ordered_CCids[ii][i];

      // control channel
      if (mac_eNB_get_rrc_status(Mod_id,rnti) < RRC_RECONFIGURED) {
        nb_rbs_required_remaining_1[CC_id][i] = nb_rbs_required[CC_id][i];
      } else {
        nb_rbs_required_remaining_1[CC_id][i] = cmin(average_rbs_per_user[CC_id],nb_rbs_required[CC_id][i]);

      }
    }
  }

  //Allocation to UEs is done in 2 rounds,
  // 1st stage: average number of RBs allocated to each UE
  // 2nd stage: remaining RBs are allocated to high priority UEs
  for(r1=0; r1<2; r1++) {

    for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
      for (ii=0; ii<UE_num_active_CC(UE_list,i); ii++) {
        CC_id = UE_list->ordered_CCids[ii][i];

        if(r1 == 0) {
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required_remaining_1[CC_id][i];
        } else { // rb required based only on the buffer - rb allloctaed in the 1st round + extra reaming rb form the 1st round
          nb_rbs_required_remaining[CC_id][i] = nb_rbs_required[CC_id][i]-nb_rbs_required_remaining_1[CC_id][i]+nb_rbs_required_remaining[CC_id][i];
        }

        if (nb_rbs_required[CC_id][i]> 0 )
          LOG_D(MAC,"round %d : nb_rbs_required_remaining[%d][%d]= %d (remaining_1 %d, required %d,  pre_nb_available_rbs %d, N_RBG %d, rb_unit %d)\n",
                r1, CC_id, i,
                nb_rbs_required_remaining[CC_id][i],
                nb_rbs_required_remaining_1[CC_id][i],
                nb_rbs_required[CC_id][i],
                pre_nb_available_rbs[CC_id][i],
                N_RBG[CC_id],
                min_rb_unit[CC_id]);

      }
    }

    if (total_ue_count > 0 ) {
      for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
        UE_id = i;

        for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
          CC_id = UE_list->ordered_CCids[ii][UE_id];

          rnti = UE_RNTI(Mod_id,UE_id);

          // LOG_D(MAC,"UE %d rnti 0x\n", UE_id, rnti );
          if(rnti == NOT_A_RNTI)
            continue;

          transmission_mode = mac_xface->get_transmission_mode(Mod_id,CC_id,rnti);
          mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti,frameP,subframeP,&harq_pid,&round,0);
          rrc_status = mac_eNB_get_rrc_status(Mod_id,rnti);
          /* 1st allocate for the retx */

          // retransmission in data channels
          // control channel in the 1st transmission
          // data channel for all TM
          LOG_T(MAC,"calling dlsch_scheduler_pre_processor_allocate .. \n ");
          dlsch_scheduler_pre_processor_allocate (Mod_id,
                                                  UE_id,
                                                  CC_id,
                                                  N_RBG[CC_id],
                                                  transmission_mode,
                                                  min_rb_unit[CC_id],
                                                  frame_parms[CC_id]->N_RB_DL,
                                                  dl_pow_off,
                                                  nb_rbs_required,
                                                  pre_nb_available_rbs,
                                                  nb_rbs_required_remaining,
                                                  rballoc_sub_UE,
                                                  rballoc_sub,
                                                  MIMO_mode_indicator);

#ifdef TM5

          // data chanel TM5: to be revisted
          if ((round == 0 )  &&
              (transmission_mode == 5)  &&
              (dl_pow_off[CC_id][UE_id] != 1)) {

            for(j=0; j<N_RBG[CC_id]; j+=2) {

              if( (((j == (N_RBG[CC_id]-1))&& (rballoc_sub[CC_id][j] == 0) && (rballoc_sub_UE[CC_id][UE_id][j] == 0))  ||
                   ((j < (N_RBG[CC_id]-1)) && (rballoc_sub[CC_id][j+1] == 0) && (rballoc_sub_UE[CC_id][UE_id][j+1] == 0)) ) &&
                  (nb_rbs_required_remaining[CC_id][UE_id]>0)) {

                for (ii = UE_list->next[i+1]; ii >=0; ii=UE_list->next[ii]) {

                  UE_id2 = ii;
                  rnti2 = UE_RNTI(Mod_id,UE_id2);

                  if(rnti2 == NOT_A_RNTI)
                    continue;

                  eNB_UE_stats2 = mac_xface->get_eNB_UE_stats(Mod_id,CC_id,rnti2);
                  mac_xface->get_ue_active_harq_pid(Mod_id,CC_id,rnti2,frameP,subframeP,&harq_pid2,&round2,0);

                  if ((mac_eNB_get_rrc_status(Mod_id,rnti2) >= RRC_RECONFIGURED) &&
                      (round2==0) &&
                      (mac_xface->get_transmission_mode(Mod_id,CC_id,rnti2)==5) &&
                      (dl_pow_off[CC_id][UE_id2] != 1)) {

                    if( (((j == (N_RBG[CC_id]-1)) && (rballoc_sub_UE[CC_id][UE_id2][j] == 0)) ||
                         ((j < (N_RBG[CC_id]-1)) && (rballoc_sub_UE[CC_id][UE_id2][j+1] == 0))  ) &&
                        (nb_rbs_required_remaining[CC_id][UE_id2]>0)) {

                      if((((eNB_UE_stats2->DL_pmi_single^eNB_UE_stats1->DL_pmi_single)<<(14-j))&0xc000)== 0x4000) { //MU-MIMO only for 25 RBs configuration

                        rballoc_sub[CC_id][j] = 1;
                        rballoc_sub_UE[CC_id][UE_id][j] = 1;
                        rballoc_sub_UE[CC_id][UE_id2][j] = 1;
                        MIMO_mode_indicator[CC_id][j] = 0;

                        if (j< N_RBG[CC_id]-1) {
                          rballoc_sub[CC_id][j+1] = 1;
                          rballoc_sub_UE[CC_id][UE_id][j+1] = 1;
                          rballoc_sub_UE[CC_id][UE_id2][j+1] = 1;
                          MIMO_mode_indicator[CC_id][j+1] = 0;
                        }

                        dl_pow_off[CC_id][UE_id] = 0;
                        dl_pow_off[CC_id][UE_id2] = 0;


                        if ((j == N_RBG[CC_id]-1) &&
                            ((PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 25) ||
                             (PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms.N_RB_DL == 50))) {
			  
                          nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - min_rb_unit[CC_id]+1;
                          pre_nb_available_rbs[CC_id][UE_id] = pre_nb_available_rbs[CC_id][UE_id] + min_rb_unit[CC_id]-1;
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - min_rb_unit[CC_id]+1;
                          pre_nb_available_rbs[CC_id][UE_id2] = pre_nb_available_rbs[CC_id][UE_id2] + min_rb_unit[CC_id]-1;
                        } else {
                          
			  nb_rbs_required_remaining[CC_id][UE_id] = nb_rbs_required_remaining[CC_id][UE_id] - 4;
                          pre_nb_available_rbs[CC_id][UE_id] = pre_nb_available_rbs[CC_id][UE_id] + 4;
                          nb_rbs_required_remaining[CC_id][UE_id2] = nb_rbs_required_remaining[CC_id][UE_id2] - 4;
                          pre_nb_available_rbs[CC_id][UE_id2] = pre_nb_available_rbs[CC_id][UE_id2] + 4;
                        }

                        break;
                      }
                    }
                  }
                }
              }
            }
          }

#endif
        }
      }
    } // total_ue_count
  } // end of for for r1 and r2

#ifdef TM5

  // This has to be revisited!!!!
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    i1=0;
    i2=0;
    i3=0;

    for (j=0; j<N_RBG[CC_id]; j++) {
      if(MIMO_mode_indicator[CC_id][j] == 2) {
        i1 = i1+1;
      } else if(MIMO_mode_indicator[CC_id][j] == 1) {
        i2 = i2+1;
      } else if(MIMO_mode_indicator[CC_id][j] == 0) {
        i3 = i3+1;
      }
    }

    if((i1 < N_RBG[CC_id]) && (i2>0) && (i3==0)) {
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_SUMIMO_transmissions + 1;
    }

    if(i3 == N_RBG[CC_id] && i1==0 && i2==0) {
      PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->FULL_MUMIMO_transmissions + 1;
    }

    if((i1 < N_RBG[CC_id]) && (i3 > 0)) {
      PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_MUMIMO_transmissions + 1;
    }

    PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions = PHY_vars_eNB_g[Mod_id][CC_id]->check_for_total_transmissions + 1;

  }

#endif

  for(i=UE_list->head; i>=0; i=UE_list->next[i]) {
    UE_id = i;

    for (ii=0; ii<UE_num_active_CC(UE_list,UE_id); ii++) {
      CC_id = UE_list->ordered_CCids[ii][UE_id];
      //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].dl_pow_off = dl_pow_off[UE_id];

      if (pre_nb_available_rbs[CC_id][UE_id] > 0 ) {
        LOG_D(MAC,"******************DL Scheduling Information for UE%d ************************\n",UE_id);
        LOG_D(MAC,"dl power offset UE%d = %d \n",UE_id,dl_pow_off[CC_id][UE_id]);
        LOG_D(MAC,"***********RB Alloc for every subband for UE%d ***********\n",UE_id);

        for(j=0; j<N_RBG[CC_id]; j++) {
          //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].rballoc_sub[i] = rballoc_sub_UE[CC_id][UE_id][i];
          LOG_D(MAC,"RB Alloc for UE%d and Subband%d = %d\n",UE_id,j,rballoc_sub_UE[CC_id][UE_id][j]);
        }

        //PHY_vars_eNB_g[Mod_id]->mu_mimo_mode[UE_id].pre_nb_available_rbs = pre_nb_available_rbs[CC_id][UE_id];
        LOG_D(MAC,"Total RBs allocated for UE%d = %d\n",UE_id,pre_nb_available_rbs[CC_id][UE_id]);
      }
    }
  }
}
Esempio n. 2
0
void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const  ctxt_pP) {

  unsigned char       *otg_pkt=NULL;
  module_id_t          dst_id; // dst for otg
  rb_id_t              rb_id;
  unsigned int         pkt_size=0;
#if defined(USER_MODE) && defined(OAI_EMU)
  module_id_t          src_id;
  static unsigned int  pkt_cnt_enb=0, pkt_cnt_ue=0;

  Packet_otg_elt_t    *otg_pkt_info=NULL;
  int                  result;
  uint8_t              pdcp_mode, is_ue=0;
#endif
  protocol_ctxt_t      ctxt;
  // we need to add conditions to avoid transmitting data when the UE is not RRC connected.
#if defined(USER_MODE) && defined(OAI_EMU)

  if (oai_emulation.info.otg_enabled ==1 ) {
    // module_id is source id
    while ((otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[ctxt_pP->instance]))) != NULL) {
      LOG_I(OTG,"Mod_id %d Frame %d Got a packet (%p), HEAD of otg_pdcp_buffer[%d] is %p and Nb elements is %d\n",
            ctxt_pP->module_id,
            ctxt_pP->frame,
            otg_pkt_info,
            ctxt_pP->instance,
            pkt_list_get_head(&(otg_pdcp_buffer[ctxt_pP->instance])),
            otg_pdcp_buffer[ctxt_pP->instance].nb_elements);
      //otg_pkt_info = pkt_list_remove_head(&(otg_pdcp_buffer[module_id]));
      dst_id    = (otg_pkt_info->otg_pkt).dst_id; // type is module_id_t
      src_id    = (otg_pkt_info->otg_pkt).module_id; // type is module_id_t
      rb_id     = (otg_pkt_info->otg_pkt).rb_id;
      is_ue     = (otg_pkt_info->otg_pkt).is_ue;
      pdcp_mode = (otg_pkt_info->otg_pkt).mode;
      //    LOG_I(PDCP,"pdcp_fifo, pdcp mode is= %d\n",pdcp_mode);

      // generate traffic if the ue is rrc reconfigured state
      // if (mac_get_rrc_status(module_id, ctxt_pP->enb_flag, dst_id ) > 2 /*RRC_CONNECTED*/) { // not needed: this test is already done in update_otg_enb
      otg_pkt = (unsigned char*) (otg_pkt_info->otg_pkt).sdu_buffer;
      pkt_size = (otg_pkt_info->otg_pkt).sdu_buffer_size;

      if (otg_pkt != NULL) {
        if (is_ue == 0 ) {
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            src_id,
            ENB_FLAG_YES,
            oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id],
            ctxt_pP->frame,
            ctxt_pP->subframe,
	    src_id);

          LOG_D(OTG,"[eNB %d] Frame %d sending packet %d from module %d on rab id %d (src %d, dst %d/%x) pkt size %d for pdcp mode %d\n",
                ctxt.module_id,
                ctxt.frame,
                pkt_cnt_enb++,
                src_id,
                rb_id,
                src_id,
                dst_id,
		oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id],
                pkt_size,
                pdcp_mode);
          result = pdcp_data_req(&ctxt,
                                 SRB_FLAG_NO,
                                 rb_id,
                                 RLC_MUI_UNDEFINED,
                                 RLC_SDU_CONFIRM_NO,
                                 pkt_size,
                                 otg_pkt,
                                 pdcp_mode);
          if (result != TRUE) {
            LOG_W(OTG,"PDCP data request failed!\n");
          }
        } else {
          //rb_id= eNB_index * MAX_NUM_RB + DTCH;


          LOG_D(OTG,"[UE %d] Frame %d: sending packet %d from module %d on rab id %d (src %d/%x, dst %d) pkt size %d\n",
                ctxt_pP->module_id,
                ctxt_pP->frame,
                pkt_cnt_ue++,
                ctxt_pP->module_id,
                rb_id,
                src_id,
		pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id], // [src_id]
                dst_id,
                pkt_size);
          PROTOCOL_CTXT_SET_BY_MODULE_ID(
            &ctxt,
            ctxt_pP->module_id, //src_id,
            ENB_FLAG_NO,
            pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id],// [src_id]
            ctxt_pP->frame,
            ctxt_pP->subframe,
	    dst_id);

          result = pdcp_data_req( &ctxt,
                                  SRB_FLAG_NO,
                                  rb_id,
                                  RLC_MUI_UNDEFINED,
                                  RLC_SDU_CONFIRM_NO,
                                  pkt_size,
                                  otg_pkt,
                                  PDCP_TRANSMISSION_MODE_DATA);
          if (result != TRUE) {
            LOG_W(OTG,"PDCP data request failed!\n");
          }
        }

        free(otg_pkt);
        otg_pkt = NULL;
      }

      // } //else LOG_D(OTG,"ctxt_pP->frame %d enb %d-> ue %d link not yet established state %d  \n", ctxt_pP->frame, eNB_index,dst_id - NB_eNB_INST, mac_get_rrc_status(module_id, ctxt_pP->enb_flag, dst_id - NB_eNB_INST));

    }
  }

#else

  if ((otg_enabled==1) && (ctxt_pP->enb_flag == ENB_FLAG_YES)) { // generate DL traffic
    unsigned int ctime=0;
    ctime = ctxt_pP->frame * 100;

    /*if  ((mac_get_rrc_status(eNB_index, ctxt_pP->enb_flag, 0 ) > 2) &&
    (mac_get_rrc_status(eNB_index, ctxt_pP->enb_flag, 1 ) > 2)) { */
    PROTOCOL_CTXT_SET_BY_MODULE_ID(
      &ctxt,
      ctxt_pP->module_id,
      ctxt_pP->enb_flag,
      NOT_A_RNTI,
      ctxt_pP->frame,
      ctxt_pP->subframe,
      ctxt_pP->module_id);

    for (dst_id = 0; dst_id<NUMBER_OF_UE_MAX; dst_id++) {
      ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id][dst_id];

      if (ctxt.rnti != NOT_A_RNTI) {
        if (mac_eNB_get_rrc_status(ctxt.module_id, ctxt.rnti ) > 2 /*RRC_SI_RECEIVED*/) {
        unsigned int temp = 0;
          otg_pkt=packet_gen(
                    ENB_MODULE_ID_TO_INSTANCE(ctxt.module_id),
                    UE_MODULE_ID_TO_INSTANCE(dst_id),
                    0,
                    ctime,
                    &temp);
        pkt_size = temp;

        if (otg_pkt != NULL) {
          rb_id = dst_id * maxDRB + DTCH;
          pdcp_data_req(&ctxt,
                        SRB_FLAG_NO,
                        rb_id,
                        RLC_MUI_UNDEFINED,
                        RLC_SDU_CONFIRM_NO,
                        pkt_size,
                        otg_pkt,
                        PDCP_TRANSMISSION_MODE_DATA);
            LOG_I(OTG,
                  "send packet from module %d on rab id %d (src %d, dst %d) pkt size %d\n",
                  ctxt_pP->module_id, rb_id, ctxt_pP->module_id, dst_id, pkt_size);
            free(otg_pkt);
          }
        }
      }
    }
  }

#endif
}