예제 #1
0
void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP)  //, int calibration_flag) {
{

  unsigned int nprb[MAX_NUM_CCs];
  unsigned int nCCE[MAX_NUM_CCs];
  int mbsfn_status[MAX_NUM_CCs];
  uint32_t RBalloc[MAX_NUM_CCs];
  protocol_ctxt_t   ctxt;
#ifdef EXMIMO
  int ret;
#endif
#if defined(ENABLE_ITTI)
  MessageDef   *msg_p;
  const char   *msg_name;
  instance_t    instance;
  int           result;
#endif
  DCI_PDU *DCI_pdu[MAX_NUM_CCs];
  int CC_id,i,next_i;
  UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list;
  rnti_t rnti;

  LOG_D(MAC,"[eNB %d] Frame %d, Subframe %d, entering MAC scheduler (UE_list->head %d)\n",module_idP, frameP, subframeP,UE_list->head);

  start_meas(&eNB_mac_inst[module_idP].eNB_scheduler);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    DCI_pdu[CC_id] = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu;
    nCCE[CC_id]=0;
    nprb[CC_id]=0;
    RBalloc[CC_id]=0;
    mbsfn_status[CC_id]=0;
  }

  // refresh UE list based on UEs dropped by PHY in previous subframe
  i = UE_list->head;

  while (i>=0) {
    rnti = UE_RNTI(module_idP, i);
    CC_id = UE_PCCID(module_idP, i);
    LOG_D(MAC,"UE %d: rnti %x (%p)\n", i, rnti,
          mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti));
    next_i= UE_list->next[i];

    if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
      mac_remove_ue(module_idP, i, frameP, subframeP);
    }
    i = next_i;
  }

#if defined(ENABLE_ITTI)

  do {
    // Checks if a message has been sent to MAC sub-task
    itti_poll_msg (TASK_MAC_ENB, &msg_p);

    if (msg_p != NULL) {
      msg_name = ITTI_MSG_NAME (msg_p);
      instance = ITTI_MSG_INSTANCE (msg_p);

      switch (ITTI_MSG_ID(msg_p)) {
      case MESSAGE_TEST:
        LOG_D(MAC, "Received %s\n", ITTI_MSG_NAME(msg_p));
        break;

      case RRC_MAC_BCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_BCCH_DATA_REQ (msg_p).frame, RRC_MAC_BCCH_DATA_REQ (msg_p).enb_index);

        // TODO process BCCH data req.
        break;

      case RRC_MAC_CCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_CCCH_DATA_REQ (msg_p).frame, RRC_MAC_CCCH_DATA_REQ (msg_p).enb_index);

        // TODO process CCCH data req.
        break;

#ifdef Rel10

      case RRC_MAC_MCCH_DATA_REQ:
        LOG_D(MAC, "Received %s from %s: instance %d, frameP %d, eNB_index %d, mbsfn_sync_area %d\n",
              msg_name, ITTI_MSG_ORIGIN_NAME(msg_p), instance,
              RRC_MAC_MCCH_DATA_REQ (msg_p).frame, RRC_MAC_MCCH_DATA_REQ (msg_p).enb_index, RRC_MAC_MCCH_DATA_REQ (msg_p).mbsfn_sync_area);

        // TODO process MCCH data req.
        break;
#endif

      default:
        LOG_E(MAC, "Received unexpected message %s\n", msg_name);
        break;
      }

      result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
      AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
    }
  } while(msg_p != NULL);

#endif

  // clear DCI and BCCH contents before scheduling
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    DCI_pdu[CC_id]->Num_common_dci  = 0;
    DCI_pdu[CC_id]->Num_ue_spec_dci = 0;
    eNB_mac_inst[module_idP].common_channels[CC_id].bcch_active = 0;

#ifdef Rel10
    eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0;
#endif

    eNB_mac_inst[module_idP].frame    = frameP;
    eNB_mac_inst[module_idP].subframe = subframeP;
  }

  //if (subframeP%5 == 0)
  //#ifdef EXMIMO
  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frameP, 0,module_idP);
  pdcp_run(&ctxt);
  //#endif

  // check HO
  rrc_rx_tx(&ctxt,
            0, // eNB index, unused in eNB
            CC_id);

#ifdef Rel10

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (eNB_mac_inst[module_idP].common_channels[CC_id].MBMS_flag >0) {
      start_meas(&eNB_mac_inst[module_idP].schedule_mch);
      mbsfn_status[CC_id] = schedule_MBMS(module_idP,CC_id,frameP,subframeP);
      stop_meas(&eNB_mac_inst[module_idP].schedule_mch);
    }
  }

#endif
  // refresh UE list based on UEs dropped by PHY in previous subframe
  /*
  i=UE_list->head;
  while (i>=0) {
    next_i = UE_list->next[i];
    LOG_T(MAC,"UE %d : rnti %x, stats %p\n",i,UE_RNTI(module_idP,i),mac_xface->get_eNB_UE_stats(module_idP,0,UE_RNTI(module_idP,i)));
    if (mac_xface->get_eNB_UE_stats(module_idP,0,UE_RNTI(module_idP,i))==NULL) {
      mac_remove_ue(module_idP,i,frameP);
    }
    i=next_i;
  }
  */

  switch (subframeP) {
  case 0:

    // FDD/TDD Schedule Downlink RA transmissions (RA response, Msg4 Contention resolution)
    // Schedule ULSCH for FDD or subframeP 4 (TDD config 0,3,6)
    // Schedule Normal DLSCH

    schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE);

    if (mac_xface->lte_frame_parms->frame_type == FDD) {  //FDD
      schedule_ulsch(module_idP,frameP,cooperation_flag,0,4,nCCE);//,calibration_flag);
    } else if  ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD
                (mac_xface->lte_frame_parms->tdd_config == 3) ||
                (mac_xface->lte_frame_parms->tdd_config == 6)) {
      //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE);//,calibration_flag);
    }

    // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);

    fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);

    break;

  case 1:

    // TDD, schedule UL for subframeP 7 (TDD config 0,1) / subframeP 8 (TDD Config 6)
    // FDD, schedule normal UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 0:
      case 1:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      case 6:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
      schedule_ulsch(module_idP,frameP,cooperation_flag,1,5,nCCE);
    }

    break;

  case 2:

    // TDD, nothing
    // FDD, normal UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == FDD) {  //FDD
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
      schedule_ulsch(module_idP,frameP,cooperation_flag,2,6,nCCE);
    }

    break;

  case 3:

    // TDD Config 2, ULSCH for subframeP 7
    // TDD Config 2/5 normal DLSCH
    // FDD, normal UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == TDD) {
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 2:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE);

        // no break here!
      case 5:
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
      schedule_ulsch(module_idP,frameP,cooperation_flag,3,7,nCCE);

    }

    break;

  case 4:

    // TDD Config 1, ULSCH for subframeP 8
    // TDD Config 1/2/4/5 DLSCH
    // FDD UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 1:
        //        schedule_RA(module_idP,frameP,subframeP,nprb,nCCE);
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE);

        // no break here!
      case 2:

        // no break here!
      case 4:

        // no break here!
      case 5:
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);
        break;

      default:
        break;
      }
    } else {
      if (mac_xface->lte_frame_parms->frame_type == FDD) {  //FDD
	//        schedule_RA(module_idP,frameP, subframeP, 0, nprb, nCCE);
        //  schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8, nCCE);
        schedule_ue_spec(module_idP, frameP, subframeP, nprb, nCCE, mbsfn_status);
        fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, 1, mbsfn_status);

      }
    }

    break;

  case 5:
    // TDD/FDD Schedule SI
    // TDD Config 0,6 ULSCH for subframes 9,3 resp.
    // TDD normal DLSCH
    // FDD normal UL/DLSCH
    schedule_SI(module_idP,frameP,nprb,nCCE);

    //schedule_RA(module_idP,frameP,subframeP,5,nprb,nCCE);
    if (mac_xface->lte_frame_parms->frame_type == FDD) {
      schedule_RA(module_idP,frameP,subframeP,1,nprb,nCCE);
      //      schedule_ulsch(module_idP,frameP,cooperation_flag,5,9,nCCE);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);

    } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0
               (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6
      //schedule_ulsch(module_idP,cooperation_flag,subframeP,nCCE);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    } else {
      //schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    }

    break;

  case 6:

    // TDD Config 0,1,6 ULSCH for subframes 2,3
    // TDD Config 3,4,5 Normal DLSCH
    // FDD normal ULSCH/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 0:
        break;

      case 1:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE);
        //  schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      case 6:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE);
        //  schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      case 5:
        schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE);
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);
        break;

      case 3:
      case 4:
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      //      schedule_ulsch(module_idP,frameP,cooperation_flag,6,0,nCCE);
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    }

    break;

  case 7:

    // TDD Config 3,4,5 Normal DLSCH
    // FDD Normal UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 3:
      case 4:
        schedule_RA(module_idP,frameP,subframeP,3,nprb,nCCE);  // 3 = Msg3 subframeP, not
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);
        break;

      case 5:
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1,nCCE);
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    }

    break;

  case 8:

    // TDD Config 2,3,4,5 ULSCH for subframeP 2
    //
    // FDD Normal UL/DLSCH
    if (mac_xface->lte_frame_parms->frame_type == TDD) { // TDD
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 2:
      case 3:
      case 4:
      case 5:

        //  schedule_RA(module_idP,subframeP,nprb,nCCE);
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE);
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2,nCCE);
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    }

    break;

  case 9:

    // TDD Config 1,3,4,6 ULSCH for subframes 3,3,3,4
    if (mac_xface->lte_frame_parms->frame_type == TDD) {
      switch (mac_xface->lte_frame_parms->tdd_config) {
      case 1:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE);
        schedule_RA(module_idP,frameP,subframeP,7,nprb,nCCE);  // 7 = Msg3 subframeP, not
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status);
        break;

      case 3:
      case 4:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE);
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      case 6:
        schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE);
        //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE);
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      case 2:
      case 5:
        //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE);
        schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
        fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
        break;

      default:
        break;
      }
    } else { //FDD
      //     schedule_ulsch(module_idP,frameP,cooperation_flag,9,3,nCCE);
      schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status);
      fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status);
    }

    break;

  }

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    DCI_pdu[CC_id]->nCCE = nCCE[CC_id];
  }

  LOG_D(MAC,"frameP %d, subframeP %d nCCE %d\n",frameP,subframeP,nCCE[0]);

  stop_meas(&eNB_mac_inst[module_idP].eNB_scheduler);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT);

}
예제 #2
0
//-----------------------------------------------------------------------------
void mac_rlc_data_ind     (
  const module_id_t         module_idP,
  const rnti_t              rntiP,
  const module_id_t         eNB_index,
  const frame_t             frameP,
  const eNB_flag_t          enb_flagP,
  const MBMS_flag_t         MBMS_flagP,
  const logical_chan_id_t   channel_idP,
  char                     *buffer_pP,
  const tb_size_t           tb_sizeP,
  num_tb_t                  num_tbP,
  crc_t                    *crcs_pP)
{
  //-----------------------------------------------------------------------------
  rb_id_t                rb_id      = 0;
  rlc_mode_t             rlc_mode   = RLC_MODE_NONE;
  rlc_mbms_id_t         *mbms_id_p  = NULL;
  rlc_union_t           *rlc_union_p     = NULL;
  hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
  srb_flag_t             srb_flag        = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
  protocol_ctxt_t     ctxt;

  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_IND,VCD_FUNCTION_IN);
#ifdef DEBUG_MAC_INTERFACE

  if (num_tbP) {
    LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, Num_tb %d\n",
          PROTOCOL_CTXT_ARGS(&ctxt),
          channel_idP,
          RLC_MAX_LC,
          NB_RB_MAX,
          num_tbP);
  }

#endif // DEBUG_MAC_INTERFACE
#ifdef OAI_EMU

  if (MBMS_flagP)
    AssertFatal (channel_idP < RLC_MAX_MBMS_LC,  "channel id is too high (%u/%d)!\n",
                 channel_idP, RLC_MAX_MBMS_LC);
  else
    AssertFatal (channel_idP < NB_RB_MAX,        "channel id is too high (%u/%d)!\n",
                 channel_idP, NB_RB_MAX);

  CHECK_CTXT_ARGS(&ctxt);

#endif


  if (MBMS_flagP) {
    if (BOOL_NOT(enb_flagP)) {
      mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[module_idP][channel_idP];
      key = RLC_COLL_KEY_MBMS_VALUE(module_idP, rntiP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
    } else {
      return;
    }
  } else {
    if (channel_idP > 2) {
      rb_id = channel_idP - 2;
    } else {
      rb_id = channel_idP;
    }

    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
  }

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);

  if (h_rc == HASH_TABLE_OK) {
    rlc_mode = rlc_union_p->mode;
  } else {
    rlc_mode = RLC_MODE_NONE;
    //AssertFatal (0 , "%s RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
  }

  struct mac_data_ind data_ind = mac_rlc_deserialize_tb(buffer_pP, tb_sizeP, num_tbP, crcs_pP);

  switch (rlc_mode) {
  case RLC_MODE_NONE:
    //handle_event(WARNING,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no radio bearer configured :%d\n", __FILE__, __LINE__, channel_idP);
    break;

  case RLC_MODE_AM:
    rlc_am_mac_data_indication(&ctxt, &rlc_union_p->rlc.am, data_ind);
    break;

  case RLC_MODE_UM:
    rlc_um_mac_data_indication(&ctxt, &rlc_union_p->rlc.um, data_ind);
    break;

  case RLC_MODE_TM:
    rlc_tm_mac_data_indication(&ctxt, &rlc_union_p->rlc.tm, data_ind);
    break;
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_IND,VCD_FUNCTION_OUT);

}
예제 #3
0
//-----------------------------------------------------------------------------
mac_rlc_status_resp_t mac_rlc_status_ind(
  const module_id_t       module_idP,
  const rnti_t            rntiP,
  const eNB_index_t       eNB_index,
  const frame_t           frameP,
  const eNB_flag_t        enb_flagP,
  const MBMS_flag_t       MBMS_flagP,
  const logical_chan_id_t channel_idP,
  const tb_size_t         tb_sizeP)
{
  //-----------------------------------------------------------------------------
  mac_rlc_status_resp_t  mac_rlc_status_resp;
  struct mac_status_ind  tx_status;
  struct mac_status_resp status_resp;
  rb_id_t                rb_id       = 0;
  rlc_mode_t             rlc_mode    = RLC_MODE_NONE;
  rlc_mbms_id_t         *mbms_id_p   = NULL;
  rlc_union_t           *rlc_union_p = NULL;
  hash_key_t             key         = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
  srb_flag_t             srb_flag    = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
  protocol_ctxt_t     ctxt;

  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_STATUS_IND,VCD_FUNCTION_IN);
  memset (&mac_rlc_status_resp, 0, sizeof(mac_rlc_status_resp_t));
  memset (&tx_status          , 0, sizeof(struct mac_status_ind));

#ifdef OAI_EMU

  if (MBMS_flagP)
    AssertFatal (channel_idP < RLC_MAX_MBMS_LC,
                 "%s channel id is too high (%u/%d) enb module id %u ue %u!\n",
                 (enb_flagP) ? "eNB" : "UE",
                 channel_idP,
                 RLC_MAX_MBMS_LC,
                 module_idP,
                 rntiP);
  else
    AssertFatal (channel_idP < NB_RB_MAX,
                 "%s channel id is too high (%u/%d) enb module id %u ue %u!\n",
                 (enb_flagP) ? "eNB" : "UE",
                 channel_idP,
                 NB_RB_MAX,
                 module_idP,
                 rntiP);

  CHECK_CTXT_ARGS(&ctxt);

#endif



  if (MBMS_flagP) {
    if (enb_flagP) {
      mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[module_idP][channel_idP];
    } else {
      mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[module_idP][channel_idP];
    }

    key = RLC_COLL_KEY_MBMS_VALUE(module_idP, rntiP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
  } else {
    if (channel_idP > 2) {
      rb_id = channel_idP - 2;
    } else {
      rb_id = channel_idP;
    }

    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
  }

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);

  if (h_rc == HASH_TABLE_OK) {
    rlc_mode = rlc_union_p->mode;
  } else {
    rlc_mode = RLC_MODE_NONE;
    //LOG_W(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
    //LOG_D(RLC , "[%s] RLC not configured rb id %u lcid %u module %u!\n", __FUNCTION__, rb_id, channel_idP, ue_module_idP);
  }

  switch (rlc_mode) {
  case RLC_MODE_NONE:
    //handle_event(WARNING,"FILE %s FONCTION mac_rlc_data_ind() LINE %s : no radio bearer configured :%d\n", __FILE__, __LINE__, channel_idP);
    mac_rlc_status_resp.bytes_in_buffer                 = 0;
    break;

  case RLC_MODE_AM:
    status_resp = rlc_am_mac_status_indication(&ctxt, &rlc_union_p->rlc.am, tb_sizeP, tx_status);
    mac_rlc_status_resp.bytes_in_buffer                 = status_resp.buffer_occupancy_in_bytes;
    mac_rlc_status_resp.head_sdu_creation_time          = status_resp.head_sdu_creation_time;
    mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send;
    mac_rlc_status_resp.head_sdu_is_segmented           = status_resp.head_sdu_is_segmented;
    //return mac_rlc_status_resp;
    break;

  case RLC_MODE_UM:
    status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status);
    mac_rlc_status_resp.bytes_in_buffer                 = status_resp.buffer_occupancy_in_bytes;
    mac_rlc_status_resp.pdus_in_buffer                  = status_resp.buffer_occupancy_in_pdus;
    mac_rlc_status_resp.head_sdu_creation_time          = status_resp.head_sdu_creation_time;
    mac_rlc_status_resp.head_sdu_remaining_size_to_send = status_resp.head_sdu_remaining_size_to_send;
    mac_rlc_status_resp.head_sdu_is_segmented           = status_resp.head_sdu_is_segmented;
    //   return mac_rlc_status_resp;
    break;

  case RLC_MODE_TM:
    status_resp = rlc_tm_mac_status_indication(&ctxt, &rlc_union_p->rlc.tm, tb_sizeP, tx_status);
    mac_rlc_status_resp.bytes_in_buffer = status_resp.buffer_occupancy_in_bytes;
    mac_rlc_status_resp.pdus_in_buffer  = status_resp.buffer_occupancy_in_pdus;
    // return mac_rlc_status_resp;
    break;

  default:
    mac_rlc_status_resp.bytes_in_buffer                 = 0 ;
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_STATUS_IND,VCD_FUNCTION_OUT);
  return mac_rlc_status_resp;
}
예제 #4
0
//-----------------------------------------------------------------------------
void *gtpv1u_eNB_task(void *args)
{
  int                       rc = 0;
  instance_t                instance;
  //const char               *msg_name_p;

  rc = gtpv1u_eNB_init();
  AssertFatal(rc == 0, "gtpv1u_eNB_init Failed");
  itti_mark_task_ready(TASK_GTPV1_U);
  MSC_START_USE();

  while(1) {
    /* Trying to fetch a message from the message queue.
     * If the queue is empty, this function will block till a
     * message is sent to the task.
     */
    MessageDef *received_message_p = NULL;
    itti_receive_msg(TASK_GTPV1_U, &received_message_p);
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_IN);
    DevAssert(received_message_p != NULL);

    instance = ITTI_MSG_INSTANCE(received_message_p);
    //msg_name_p = ITTI_MSG_NAME(received_message_p);

    switch (ITTI_MSG_ID(received_message_p)) {

    case GTPV1U_ENB_DELETE_TUNNEL_REQ: {
      gtpv1u_delete_s1u_tunnel(instance, &received_message_p->ittiMsg.Gtpv1uDeleteTunnelReq);
    }
    break;

    // DATA COMING FROM UDP
    case UDP_DATA_IND: {
      udp_data_ind_t *udp_data_ind_p;
      udp_data_ind_p = &received_message_p->ittiMsg.udp_data_ind;
      nwGtpv1uProcessUdpReq(gtpv1u_data_g.gtpv1u_stack,
                            udp_data_ind_p->buffer,
                            udp_data_ind_p->buffer_length,
                            udp_data_ind_p->peer_port,
                            udp_data_ind_p->peer_address);
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), udp_data_ind_p->buffer);
    }
    break;

    // DATA TO BE SENT TO UDP
    case GTPV1U_ENB_TUNNEL_DATA_REQ: {
      gtpv1u_enb_tunnel_data_req_t *data_req_p           = NULL;
      NwGtpv1uUlpApiT               stack_req;
      NwGtpv1uRcT                   rc                   = NW_GTPV1U_FAILURE;
      hashtable_rc_t                hash_rc              = HASH_TABLE_KEY_NOT_EXISTS;
      gtpv1u_ue_data_t             *gtpv1u_ue_data_p     = NULL;
      teid_t                        enb_s1u_teid         = 0;
      teid_t                        sgw_s1u_teid         = 0;

      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_IN);
      data_req_p = &GTPV1U_ENB_TUNNEL_DATA_REQ(received_message_p);
      //ipv4_send_data(ipv4_data_p->sd, data_ind_p->buffer, data_ind_p->length);

#if defined(GTP_DUMP_SOCKET) && GTP_DUMP_SOCKET > 0
      gtpv1u_eNB_write_dump_socket(&data_req_p->buffer[data_req_p->offset],data_req_p->length);
#endif
      memset(&stack_req, 0, sizeof(NwGtpv1uUlpApiT));

      hash_rc = hashtable_get(gtpv1u_data_g.ue_mapping, (uint64_t)data_req_p->rnti, (void**)&gtpv1u_ue_data_p);

      if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
        LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: while getting ue rnti %x in hashtable ue_mapping\n", data_req_p->rnti);
      } else {
        if ((data_req_p->rab_id >= GTPV1U_BEARER_OFFSET) && (data_req_p->rab_id <= max_val_DRB_Identity)) {
          enb_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_eNB;
          sgw_s1u_teid                        = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].teid_sgw;
          stack_req.apiType                   = NW_GTPV1U_ULP_API_SEND_TPDU;
          stack_req.apiInfo.sendtoInfo.teid   = sgw_s1u_teid;
          stack_req.apiInfo.sendtoInfo.ipAddr = gtpv1u_ue_data_p->bearers[data_req_p->rab_id - GTPV1U_BEARER_OFFSET].sgw_ip_addr;

          rc = nwGtpv1uGpduMsgNew(
                 gtpv1u_data_g.gtpv1u_stack,
                 sgw_s1u_teid,
                 NW_FALSE,
                 gtpv1u_data_g.seq_num++,
                 data_req_p->buffer,
                 data_req_p->length,
                 data_req_p->offset,
                 &(stack_req.apiInfo.sendtoInfo.hMsg));

          if (rc != NW_GTPV1U_OK) {
            LOG_E(GTPU, "nwGtpv1uGpduMsgNew failed: 0x%x\n", rc);
            MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
            		enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
            (void)enb_s1u_teid; /* avoid gcc warning "set but not used" */
          } else {
            rc = nwGtpv1uProcessUlpReq(gtpv1u_data_g.gtpv1u_stack, &stack_req);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uProcessUlpReq failed: 0x%x\n", rc);
              MSC_LOG_EVENT(MSC_GTPU_ENB,"0 Failed send G-PDU ltid %u rtid %u size %u",
              		enb_s1u_teid,sgw_s1u_teid,data_req_p->length);
            } else {
            	  MSC_LOG_TX_MESSAGE(
            			  MSC_GTPU_ENB,
            			  MSC_GTPU_SGW,
            			  NULL,
            			  0,
            			  MSC_AS_TIME_FMT" G-PDU ltid %u rtid %u size %u",
            			  0,0,
            			  enb_s1u_teid,
            			  sgw_s1u_teid,
            			  data_req_p->length);

            }

            rc = nwGtpv1uMsgDelete(gtpv1u_data_g.gtpv1u_stack,
                                   stack_req.apiInfo.sendtoInfo.hMsg);

            if (rc != NW_GTPV1U_OK) {
              LOG_E(GTPU, "nwGtpv1uMsgDelete failed: 0x%x\n", rc);
            }
          }
        }
      }

      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_TUNNEL_DATA_REQ, VCD_FUNCTION_OUT);
      /* Buffer still needed, do not free it */
      //itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), data_req_p->buffer);
    }
    break;

    case TERMINATE_MESSAGE: {
      if (gtpv1u_data_g.ue_mapping != NULL) {
        hashtable_destroy (gtpv1u_data_g.ue_mapping);
      }

      if (gtpv1u_data_g.teid_mapping != NULL) {
        hashtable_destroy (gtpv1u_data_g.teid_mapping);
      }

      itti_exit_task();
    }
    break;

    case TIMER_HAS_EXPIRED:
      nwGtpv1uProcessTimeout(&received_message_p->ittiMsg.timer_has_expired.arg);
      break;

    default: {
      LOG_E(GTPU, "Unkwnon message ID %d:%s\n",
            ITTI_MSG_ID(received_message_p),
            ITTI_MSG_NAME(received_message_p));
    }
    break;
    }

    rc = itti_free(ITTI_MSG_ORIGIN_ID(received_message_p), received_message_p);
    AssertFatal(rc == EXIT_SUCCESS, "Failed to free memory (%d)!\n", rc);
    received_message_p = NULL;
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_ENB_TASK, VCD_FUNCTION_OUT);
  }

  return NULL;
}
예제 #5
0
//-----------------------------------------------------------------------------
tbs_size_t mac_rlc_data_req(
  const module_id_t       module_idP,
  const rnti_t            rntiP,
  const eNB_index_t       eNB_index,
  const frame_t           frameP,
  const eNB_flag_t        enb_flagP,
  const MBMS_flag_t       MBMS_flagP,
  const logical_chan_id_t channel_idP,
  char             *buffer_pP)
{
  //-----------------------------------------------------------------------------
  struct mac_data_req    data_request;
  rb_id_t                rb_id           = 0;
  rlc_mode_t             rlc_mode        = RLC_MODE_NONE;
  rlc_mbms_id_t         *mbms_id_p       = NULL;
  rlc_union_t           *rlc_union_p     = NULL;
  hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
  srb_flag_t             srb_flag        = (channel_idP <= 2) ? SRB_FLAG_YES : SRB_FLAG_NO;
  tbs_size_t             ret_tb_size         = 0;
  protocol_ctxt_t     ctxt;

  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0,eNB_index);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,VCD_FUNCTION_IN);
#ifdef DEBUG_MAC_INTERFACE
  LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_REQ channel %d (%d) MAX RB %d, Num_tb %d\n",
        PROTOCOL_CTXT_ARGS((&ctxt)),
        channel_idP,
        RLC_MAX_LC,
        NB_RB_MAX);

#endif // DEBUG_MAC_INTERFACE

  if (MBMS_flagP) {
    AssertFatal (channel_idP < RLC_MAX_MBMS_LC,        "channel id is too high (%u/%d)!\n",     channel_idP, RLC_MAX_MBMS_LC);
  } else {
    AssertFatal (channel_idP < NB_RB_MAX,        "channel id is too high (%u/%d)!\n",     channel_idP, NB_RB_MAX);
  }

#ifdef OAI_EMU
  CHECK_CTXT_ARGS(&ctxt);
  //printf("MBMS_flagP %d, MBMS_FLAG_NO %d \n",MBMS_flagP, MBMS_FLAG_NO);
  //  AssertFatal (MBMS_flagP == MBMS_FLAG_NO ," MBMS FLAG SHOULD NOT BE SET IN mac_rlc_data_req in UE\n");

#endif

  if (MBMS_flagP) {
    if (enb_flagP) {
      mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[module_idP][channel_idP];
      key = RLC_COLL_KEY_MBMS_VALUE(module_idP, rntiP, enb_flagP, mbms_id_p->service_id, mbms_id_p->session_id);
    } else {
      return (tbs_size_t)0;
    }
  } else {
    if (channel_idP > 2) {
      rb_id = channel_idP - 2;
    } else {
      rb_id = channel_idP;
    }

    key = RLC_COLL_KEY_VALUE(module_idP, rntiP, enb_flagP, rb_id, srb_flag);
  }

  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);

  if (h_rc == HASH_TABLE_OK) {
    rlc_mode = rlc_union_p->mode;
  } else {
    rlc_mode = RLC_MODE_NONE;
    AssertFatal (0 , "RLC not configured rb id %u lcid %u RNTI %x!\n", rb_id, channel_idP, rntiP);
  }

  switch (rlc_mode) {
  case RLC_MODE_NONE:
    ret_tb_size =0;
    break;

  case RLC_MODE_AM:
    data_request = rlc_am_mac_data_request(&ctxt, &rlc_union_p->rlc.am);
    ret_tb_size =mac_rlc_serialize_tb(buffer_pP, data_request.data);
    break;

  case RLC_MODE_UM:
    data_request = rlc_um_mac_data_request(&ctxt, &rlc_union_p->rlc.um);
    ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data);
    break;

  case RLC_MODE_TM:
    data_request = rlc_tm_mac_data_request(&ctxt, &rlc_union_p->rlc.tm);
    ret_tb_size = mac_rlc_serialize_tb(buffer_pP, data_request.data);
    break;

  default:
    ;
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,VCD_FUNCTION_OUT);
  return ret_tb_size;
}
예제 #6
0
//-----------------------------------------------------------------------------
int
pdcp_validate_security(
  const protocol_ctxt_t* const ctxt_pP,
  pdcp_t         * const pdcp_pP,
  const srb_flag_t     srb_flagP,
  const rb_id_t        rb_id,
  const uint8_t        pdcp_header_len,
  const uint16_t       current_sn,
  uint8_t       *const pdcp_pdu_buffer,
  const uint16_t       sdu_buffer_size
)
{
  uint8_t *buffer_decrypted = NULL;
  stream_cipher_t decrypt_params;

  DevAssert(pdcp_pP != NULL);

  DevAssert(pdcp_pdu_buffer != NULL);
  DevCheck(rb_id < NB_RB_MAX && rb_id >= 0, rb_id, NB_RB_MAX, 0);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_IN);

  buffer_decrypted = (uint8_t*)&pdcp_pdu_buffer[pdcp_header_len];

  decrypt_params.direction  = (pdcp_pP->is_ue == 1) ? SECU_DIRECTION_DOWNLINK : SECU_DIRECTION_UPLINK ;
  decrypt_params.bearer     = rb_id - 1;
  decrypt_params.count      = pdcp_get_next_count_rx(pdcp_pP, srb_flagP, current_sn);
  decrypt_params.message    = &pdcp_pdu_buffer[pdcp_header_len];
  decrypt_params.blength    = (sdu_buffer_size - pdcp_header_len) << 3;
  decrypt_params.key_length = 16;

  if (srb_flagP) {
    LOG_D(PDCP, "[OSA][RB %d] %s Validating control-plane security\n",
          rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
    decrypt_params.key = pdcp_pP->kRRCenc;// + 128;
  } else {
    LOG_D(PDCP, "[OSA][RB %d] %s Validating user-plane security\n",
          rb_id, (pdcp_pP->is_ue != 0) ? "eNB -> UE" : "UE -> eNB");
    decrypt_params.key = pdcp_pP->kUPenc;// + 128;
  }

  /* Uncipher the block */
  stream_decrypt(pdcp_pP->cipheringAlgorithm,
                 &decrypt_params,
                 &buffer_decrypted);

  if (srb_flagP) {
    /* Now check the integrity of the complete PDU */
    decrypt_params.message    = pdcp_pdu_buffer;
    decrypt_params.blength    = sdu_buffer_size << 3;
    decrypt_params.key        = pdcp_pP->kRRCint + 16;// 128;

    if (stream_check_integrity(pdcp_pP->integrityProtAlgorithm,
                               &decrypt_params,
                               &pdcp_pdu_buffer[sdu_buffer_size]) != 0) {
      MSC_LOG_EVENT(
    	  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
    	  " Security: failed MAC-I Algo %X UE %"PRIx16" ",
    	  pdcp_pP->integrityProtAlgorithm,
    	  ctxt_pP->rnti);
      LOG_E(PDCP, "[OSA][RB %d] %s failed to validate MAC-I of incoming PDU\n",
            rb_id, (pdcp_pP->is_ue != 0) ? "UE" : "eNB");
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);
      return -1;
    }
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_VALIDATE_SECURITY, VCD_FUNCTION_OUT);

  return 0;
}
예제 #7
0
int dlsch_encoding(unsigned char *a,
                   LTE_DL_FRAME_PARMS *frame_parms,
                   uint8_t num_pdcch_symbols,
                   LTE_eNB_DLSCH_t *dlsch,
                   int frame,
                   uint8_t subframe,
                   time_stats_t *rm_stats,
                   time_stats_t *te_stats,
                   time_stats_t *i_stats)
{

  unsigned int G;
  unsigned int crc=1;
  unsigned short iind;

  unsigned char harq_pid = dlsch->current_harq_pid;
  unsigned short nb_rb = dlsch->harq_processes[harq_pid]->nb_rb;
  unsigned int A;
  unsigned char mod_order;
  unsigned int Kr=0,Kr_bytes,r,r_offset=0;
  unsigned short m=dlsch->harq_processes[harq_pid]->mcs;

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_IN);

  A = dlsch->harq_processes[harq_pid]->TBS; //6228
  // printf("Encoder: A: %d\n",A);
  mod_order = get_Qm(dlsch->harq_processes[harq_pid]->mcs);

  G = get_G(frame_parms,nb_rb,dlsch->harq_processes[harq_pid]->rb_alloc,mod_order,dlsch->harq_processes[harq_pid]->Nl,num_pdcch_symbols,frame,subframe);


  //  if (dlsch->harq_processes[harq_pid]->Ndi == 1) {  // this is a new packet
  if (dlsch->harq_processes[harq_pid]->round == 0) {  // this is a new packet

    /*
    int i;
    printf("dlsch (tx): \n");
    for (i=0;i<(A>>3);i++)
      printf("%02x.",a[i]);
    printf("\n");
    */
    // Add 24-bit crc (polynomial A) to payload
    crc = crc24a(a,
                 A)>>8;
    a[A>>3] = ((uint8_t*)&crc)[2];
    a[1+(A>>3)] = ((uint8_t*)&crc)[1];
    a[2+(A>>3)] = ((uint8_t*)&crc)[0];
    //    printf("CRC %x (A %d)\n",crc,A);

    dlsch->harq_processes[harq_pid]->B = A+24;
    //    dlsch->harq_processes[harq_pid]->b = a;
    memcpy(dlsch->harq_processes[harq_pid]->b,a,(A/8)+4);

    if (lte_segmentation(dlsch->harq_processes[harq_pid]->b,
                         dlsch->harq_processes[harq_pid]->c,
                         dlsch->harq_processes[harq_pid]->B,
                         &dlsch->harq_processes[harq_pid]->C,
                         &dlsch->harq_processes[harq_pid]->Cplus,
                         &dlsch->harq_processes[harq_pid]->Cminus,
                         &dlsch->harq_processes[harq_pid]->Kplus,
                         &dlsch->harq_processes[harq_pid]->Kminus,
                         &dlsch->harq_processes[harq_pid]->F)<0)
      return(-1);

    for (r=0; r<dlsch->harq_processes[harq_pid]->C; r++) {
      if (r<dlsch->harq_processes[harq_pid]->Cminus)
        Kr = dlsch->harq_processes[harq_pid]->Kminus;
      else
        Kr = dlsch->harq_processes[harq_pid]->Kplus;

      Kr_bytes = Kr>>3;

      // get interleaver index for Turbo code (lookup in Table 5.1.3-3 36-212, V8.6 2009-03, p. 13-14)
      if (Kr_bytes<=64)
        iind = (Kr_bytes-5);
      else if (Kr_bytes <=128)
        iind = 59 + ((Kr_bytes-64)>>1);
      else if (Kr_bytes <= 256)
        iind = 91 + ((Kr_bytes-128)>>2);
      else if (Kr_bytes <= 768)
예제 #8
0
//-----------------------------------------------------------------------------
int
pdcp_apply_security(
  const protocol_ctxt_t* const ctxt_pP,
  pdcp_t        *const pdcp_pP,
  const srb_flag_t     srb_flagP,
  const rb_id_t        rb_id,
  const uint8_t        pdcp_header_len,
  const uint16_t       current_sn,
  uint8_t       * const pdcp_pdu_buffer,
  const uint16_t      sdu_buffer_size
)
{
  uint8_t *buffer_encrypted = NULL;
  stream_cipher_t encrypt_params;

  DevAssert(pdcp_pP != NULL);
  DevAssert(pdcp_pdu_buffer != NULL);
  DevCheck(rb_id < NB_RB_MAX && rb_id >= 0, rb_id, NB_RB_MAX, 0);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_IN);

  encrypt_params.direction  = (pdcp_pP->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK;
  encrypt_params.bearer     = rb_id - 1;
  encrypt_params.count      = pdcp_get_next_count_tx(pdcp_pP, srb_flagP, current_sn);
  encrypt_params.key_length = 16;

  if (srb_flagP) {
    /* SRBs */
    uint8_t *mac_i;

    LOG_D(PDCP, "[OSA][RB %d] %s Applying control-plane security %d \n",
          rb_id, (pdcp_pP->is_ue != 0) ? "UE -> eNB" : "eNB -> UE", pdcp_pP->integrityProtAlgorithm);

    encrypt_params.message    = pdcp_pdu_buffer;
    encrypt_params.blength    = (pdcp_header_len + sdu_buffer_size) << 3;
    encrypt_params.key        = pdcp_pP->kRRCint + 16; // + 128;

    mac_i = &pdcp_pdu_buffer[pdcp_header_len + sdu_buffer_size];

    /* Both header and data parts are integrity protected for
     * control-plane PDUs */
    stream_compute_integrity(pdcp_pP->integrityProtAlgorithm,
                             &encrypt_params,
                             mac_i);

    encrypt_params.key = pdcp_pP->kRRCenc;  // + 128  // bit key
  } else {
    LOG_D(PDCP, "[OSA][RB %d] %s Applying user-plane security\n",
          rb_id, (pdcp_pP->is_ue != 0) ? "UE -> eNB" : "eNB -> UE");

    encrypt_params.key = pdcp_pP->kUPenc;//  + 128;
  }

  encrypt_params.message    = &pdcp_pdu_buffer[pdcp_header_len];
  encrypt_params.blength    = sdu_buffer_size << 3;

  buffer_encrypted = &pdcp_pdu_buffer[pdcp_header_len];

  /* Apply ciphering if any requested */
  stream_encrypt(pdcp_pP->cipheringAlgorithm,
                 &encrypt_params,
                 &buffer_encrypted);

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_APPLY_SECURITY, VCD_FUNCTION_OUT);

  return 0;
}
예제 #9
0
//log record, format, and print:  executed in the main thread (mt)
void logRecord_mt(const char *file, const char *func, int line, int comp,
                  int level, const char *format, ...)
{
  int len = 0;
  va_list args;
  log_component_t *c;
  char *log_start;
  char *log_end;
  /* The main difference with the version above is the use of this local log_buffer.
   * The other difference is the return value of snprintf which was not used
   * correctly. It was not a big problem because in practice MAX_LOG_TOTAL is
   * big enough so that the buffer is never full.
   */
  char log_buffer[MAX_LOG_TOTAL];

  /* for no gcc warnings */
  (void)log_start;
  (void)log_end;

  c = &g_log->log_component[comp];

  // do not apply filtering for LOG_F
  // only log messages which are enabled and are below the global log level and component's level threshold
  if ((level != LOG_FILE) && ((level > c->level) || (level > g_log->level))) {
    /* if ((level != LOG_FILE) &&
          ((level > c->level) ||
           (level > g_log->level) ||
           ( c->level > g_log->level))) {
    */
    return;
  }

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
                                          VCD_FUNCTION_IN);

  va_start(args, format);

  // adjust syslog level for TRACE messages
  if (g_log->syslog) {
    if (g_log->level > LOG_DEBUG) {
      g_log->level = LOG_DEBUG;
    }
  }

  // make sure that for log trace the extra info is only printed once, reset when the level changes
  if ((level == LOG_FILE) || (c->flag == LOG_NONE) || (level == LOG_TRACE)) {
    log_start = log_buffer;
    len = vsnprintf(log_buffer, MAX_LOG_TOTAL, format, args);
    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    log_end = log_buffer + len;
  } else {
    if ( (g_log->flag & FLAG_COLOR) || (c->flag & FLAG_COLOR) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
                      log_level_highlight_start[level]);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }

    log_start = log_buffer + len;

    if ( (g_log->flag & FLAG_COMP) || (c->flag & FLAG_COMP) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]",
                      g_log->log_component[comp].name);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }

    if ( (g_log->flag & FLAG_LEVEL) || (c->flag & FLAG_LEVEL) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]",
                      g_log->level2string[level]);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }

    if ( (g_log->flag & FLAG_THREAD) || (c->flag & FLAG_THREAD) ) {
#     define THREAD_NAME_LEN 128
      char threadname[THREAD_NAME_LEN];
      if (pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN) != 0)
      {
        perror("pthread_getname_np : ");
      } else {
        len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s]", threadname);
        if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
      }
#     undef THREAD_NAME_LEN
    }

    if ( (g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s] ",
                      func);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }

    if ( (g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "[%s:%d]",
                      file, line);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }

    len += vsnprintf(&log_buffer[len], MAX_LOG_TOTAL - len, format, args);
    if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    log_end = log_buffer + len;

    if ( (g_log->flag & FLAG_COLOR) || (c->flag & FLAG_COLOR) ) {
      len += snprintf(&log_buffer[len], MAX_LOG_TOTAL - len, "%s",
                      log_level_highlight_end[level]);
      if (len > MAX_LOG_TOTAL) len = MAX_LOG_TOTAL;
    }
  }

  va_end(args);

  // OAI printf compatibility
  if ((g_log->onlinelog == 1) && (level != LOG_FILE))
#ifdef RTAI
    if (len > MAX_LOG_TOTAL) {
      rt_printk ("[OPENAIR] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n");
    }

  if (len > 0) {
    rtf_put (FIFO_PRINTF_NO, log_buffer, len);
  }

#else
    fwrite(log_buffer, len, 1, stdout);
#endif

#ifndef RTAI

  if (g_log->syslog) {
    syslog(g_log->level, "%s", log_buffer);
  }

  if (g_log->filelog) {
    if (write(gfd, log_buffer, len) < len) {
      // TODO assert ?
    }
  }

  if ((g_log->log_component[comp].filelog) && (level == LOG_FILE)) {
    if (write(g_log->log_component[comp].fd, log_buffer, len) < len) {
      // TODO assert ?
    }
  }

#else

  // online print messges
  if ((g_log->log_component[comp].filelog) && (level == LOG_FILE)) {
    printf(log_buffer);
  }

#endif

#if defined(ENABLE_ITTI)

  if (level <= LOG_DEBUG) {
    task_id_t origin_task_id = TASK_UNKNOWN;
    MessagesIds messages_id;
    MessageDef *message_p;
    size_t      message_string_size;
    char       *message_msg_p;

    message_string_size = log_end - log_start;

#if !defined(DISABLE_ITTI_DETECT_SUB_TASK_ID)

    /* Try to identify sub task ID from log information (comp, log_instance_type) */
    switch (comp) {
    case PHY:
      switch (log_instance_type) {
      case LOG_INSTANCE_ENB:
        origin_task_id = TASK_PHY_ENB;
        break;

      case LOG_INSTANCE_UE:
        origin_task_id = TASK_PHY_UE;
        break;

      default:
        break;
      }

      break;

    case MAC:
      switch (log_instance_type) {
      case LOG_INSTANCE_ENB:
        origin_task_id = TASK_MAC_ENB;
        break;

      case LOG_INSTANCE_UE:
        origin_task_id = TASK_MAC_UE;

      default:
        break;
      }

      break;

    case RLC:
      switch (log_instance_type) {
      case LOG_INSTANCE_ENB:
        origin_task_id = TASK_RLC_ENB;
        break;

      case LOG_INSTANCE_UE:
        origin_task_id = TASK_RLC_UE;

      default:
        break;
      }

      break;

    case PDCP:
      switch (log_instance_type) {
      case LOG_INSTANCE_ENB:
        origin_task_id = TASK_PDCP_ENB;
        break;

      case LOG_INSTANCE_UE:
        origin_task_id = TASK_PDCP_UE;

      default:
        break;
      }

      break;

    default:
      break;
    }

#endif

    switch (level) {
    case LOG_EMERG:
    case LOG_ALERT:
    case LOG_CRIT:
    case LOG_ERR:
      messages_id = ERROR_LOG;
      break;

    case LOG_WARNING:
      messages_id = WARNING_LOG;
      break;

    case LOG_NOTICE:
      messages_id = NOTICE_LOG;
      break;

    case LOG_INFO:
      messages_id = INFO_LOG;
      break;

    default:
      messages_id = DEBUG_LOG;
      break;
    }

    message_p = itti_alloc_new_message_sized(origin_task_id, messages_id, message_string_size);

    switch (level) {
    case LOG_EMERG:
    case LOG_ALERT:
    case LOG_CRIT:
    case LOG_ERR:
      message_msg_p = (char *) &message_p->ittiMsg.error_log;
      break;

    case LOG_WARNING:
      message_msg_p = (char *) &message_p->ittiMsg.warning_log;
      break;

    case LOG_NOTICE:
      message_msg_p = (char *) &message_p->ittiMsg.notice_log;
      break;

    case LOG_INFO:
      message_msg_p = (char *) &message_p->ittiMsg.info_log;
      break;

    default:
      message_msg_p = (char *) &message_p->ittiMsg.debug_log;
      break;
    }

    memcpy(message_msg_p, log_start, message_string_size);

    itti_send_msg_to_task(TASK_UNKNOWN, INSTANCE_DEFAULT, message_p);
  }

#endif

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
                                          VCD_FUNCTION_OUT);
}
예제 #10
0
void logRecord_thread_safe(const char *file, const char *func,
                           int line,  int comp, int level,
                           int len, const char *params_string)
{
  log_component_t *c;
  int total_len = 0;
  char log_buffer[MAX_LOG_TOTAL];

  c = &g_log->log_component[comp];

  // do not apply filtering for LOG_F
  // only log messages which are enabled and are below the global log level and component's level threshold
  if ((level != LOG_FILE) && ((c->level > g_log->level) ||
                              (level > c->level) || (level > g_log->level))) {
    return;
  }


  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
                                          VCD_FUNCTION_IN);

  // adjust syslog level for TRACE messages
  if (g_log->syslog) {
    if (g_log->level > LOG_DEBUG) {
      g_log->level = LOG_DEBUG;
    }
  }

  // make sure that for log trace the extra info is only printed once, reset when the level changes
  if ((level == LOG_FILE) ||  (c->flag == LOG_NONE)  || (level ==LOG_TRACE )) {
    total_len = snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - 1, "%s",
                         params_string);
  } else {
    if ((g_log->flag & FLAG_COLOR) || (c->flag & FLAG_COLOR)) {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "%s",
                            log_level_highlight_start[level]);
    }

    if ((g_log->flag & FLAG_COMP) || (c->flag & FLAG_COMP) ) {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%s]",
                            g_log->log_component[comp].name);
    }

    if ((g_log->flag & FLAG_LEVEL) || (c->flag & FLAG_LEVEL)) {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%s]",
                            g_log->level2string[level]);
    }

    if ((g_log->flag & FLAG_FUNCT) || (c->flag & FLAG_FUNCT)) {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%s] ",
                            func);
    }

    if ((g_log->flag & FLAG_FILE_LINE) || (c->flag & FLAG_FILE_LINE) )  {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "[%s:%d]",
                            file, line);
    }

    len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - len, "%s",
                    params_string);

    if ((g_log->flag & FLAG_COLOR) || (c->flag & FLAG_COLOR)) {
      total_len += snprintf(&log_buffer[total_len], MAX_LOG_TOTAL - total_len, "%s",
                            log_level_highlight_end[level]);
    }
  }

  // OAI printf compatibility
  if ((g_log->onlinelog == 1) && (level != LOG_FILE)) {
#ifdef RTAI

    if (len > MAX_LOG_TOTAL) {
      rt_printk ("[OPENAIR] FIFO_PRINTF WROTE OUTSIDE ITS MEMORY BOUNDARY : ERRORS WILL OCCUR\n");
    }

    if (len > 0) {
      rtf_put (FIFO_PRINTF_NO, log_buffer, len);
    }

#else
    fprintf(stdout, "%s", log_buffer);
#endif
  }

#ifndef RTAI

  if (g_log->syslog) {
    syslog(g_log->level, "%s", log_buffer);
  }

  if (g_log->filelog) {
    if (write(gfd, log_buffer, total_len) < total_len) {
      // TODO assert ?
    }
  }

  if ((g_log->log_component[comp].filelog) && (level == LOG_FILE)) {
    if (write(g_log->log_component[comp].fd, log_buffer, total_len) < total_len) {
      // TODO assert ?
    }
  }

#endif

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LOG_RECORD,
                                          VCD_FUNCTION_OUT);
}
예제 #11
0
NwGtpv1uRcT
nwGtpv1uProcessUdpReq( NW_IN NwGtpv1uStackHandleT hGtpuStackHandle,
                       NW_IN uint8_t *udpData,
                       NW_IN uint32_t udpDataLen,
                       NW_IN uint16_t peerPort,
                       NW_IN uint32_t peerIp)
{
  NwGtpv1uRcT           ret = NW_GTPV1U_FAILURE;
  NwGtpv1uStackT       *thiz;
  uint16_t                msgType;

#if defined(ENB_MODE)
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_UDP_REQ, VCD_FUNCTION_IN);
#endif
  thiz = (NwGtpv1uStackT *) hGtpuStackHandle;

  NW_ASSERT(thiz);

  msgType = *((uint8_t *)(udpData + 1));

  switch(msgType) {
  case NW_GTP_ECHO_REQ:
    GTPU_DEBUG("NW_GTP_ECHO_REQ\n");
    ret = nwGtpv1uHandleEchoReq( thiz, udpData, udpDataLen, peerPort, peerIp);
    break;

  case NW_GTP_ERROR_INDICATION:
    GTPU_DEBUG("NW_GTP_ERROR_INDICATION\n");
    ret = nwGtpv1uSendUlpMessageIndication( thiz,
                                            0,
                                            NW_GTPV1U_ULP_API_RECV_MSG,
                                            msgType,
                                            peerIp,
                                            peerPort,
                                            udpData,
                                            udpDataLen);

    NW_ASSERT(ret == NW_GTPV1U_OK);
    break;

  case NW_GTP_ECHO_RSP:
    GTPU_DEBUG("NW_GTP_ECHO_RSP\n");
    ret = NW_GTPV1U_OK;
    break;

  case NW_GTP_GPDU:
#if defined(LOG_GTPU) && LOG_GTPU > 0
    GTPU_DEBUG("NW_GTP_GPDU: DATA COMING FROM UDP\n");
#endif
    ret = nwGtpv1uProcessGpdu(thiz, udpData, udpDataLen, peerIp);
    break;

  default:
    ret = NW_GTPV1U_FAILURE;
    NW_ASSERT(0);
    break;
  }

#if defined(LOG_GTPU) && LOG_GTPU > 0
  NW_LEAVE(thiz);
#endif
#if defined(ENB_MODE)
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GTPV1U_PROCESS_UDP_REQ, VCD_FUNCTION_OUT);
#endif
  return ret;
}
/** RX_PDSCH Decoding Thread */
static void * rx_pdsch_thread(void *param)
{

  //unsigned long cpuid;
  uint8_t dlsch_thread_index = 0;
  uint8_t pilot2,harq_pid,subframe;
  //  uint8_t last_slot;

  uint8_t dual_stream_UE = 0;
  uint8_t i_mod = 0;


#ifdef RTAI
  RT_TASK *task;
#endif

  int m,eNB_id = 0;
  int eNB_id_i = 1;
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];

#ifdef RTAI
  task = rt_task_init_schmod(nam2num("RX_PDSCH_THREAD"), 0, 0, 0, SCHED_FIFO, 0xF);

  if (task==NULL) {
    LOG_E(PHY,"[SCHED][RX_PDSCH] Problem starting rx_pdsch thread!!!!\n");
    return 0;
  } else {
    LOG_I(PHY,"[SCHED][RX_PDSCH] rx_pdsch_thread started for with id %p\n",task);
  }

#endif

  mlockall(MCL_CURRENT | MCL_FUTURE);

  //rt_set_runnable_on_cpuid(task,1);
  //cpuid = rtai_cpuid();

#ifdef HARD_RT
  rt_make_hard_real_time();
#endif

  if (UE->lte_frame_parms.Ncp == NORMAL) {  // normal prefix
    pilot2 = 7;
  } else { // extended prefix
    pilot2 = 6;
  }


  while (!oai_exit) {
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 0);

    if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) {
      LOG_E(PHY,"[SCHED][RX_PDSCH] error locking mutex.\n");
    } else {
      while (rx_pdsch_instance_cnt < 0) {
        pthread_cond_wait(&rx_pdsch_cond,&rx_pdsch_mutex);
      }

      if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) {
        LOG_E(PHY,"[SCHED][RX_PDSCH] error unlocking mutex.\n");
      }
    }

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 1);

    //      last_slot = rx_pdsch_slot;
    subframe = UE->slot_rx>>1;
    // Important! assumption that PDCCH procedure of next SF is not called yet
    harq_pid = UE->dlsch_ue[eNB_id][0]->current_harq_pid;
    UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&UE->lte_frame_parms,
        UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb,
        UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc,
        get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs),
        UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl,
        UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols,
        UE->frame_rx,subframe);

    if ((UE->transmission_mode[eNB_id] == 5) &&
        (UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) &&
        (openair_daq_vars.use_ia_receiver > 0)) {
      dual_stream_UE = 1;
      eNB_id_i = UE->n_connected_eNB;

      if (openair_daq_vars.use_ia_receiver == 2) {
        i_mod =  get_Qm(((UE->frame_rx%1024)/3)%28);
      } else {
        i_mod =  get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs);
      }
    } else {
      dual_stream_UE = 0;
      eNB_id_i = eNB_id+1;
      i_mod = 0;
    }

    if (oai_exit) break;

    LOG_D(PHY,"[SCHED][RX_PDSCH] Frame %d, slot %d: Calling rx_pdsch_decoding with harq_pid %d\n",UE->frame_rx,UE->slot_rx,harq_pid);


    // Check if we are in even or odd slot
    if (UE->slot_rx%2) { // odd slots

      // measure time
      //time0 = rt_get_time_ns();
      //        rt_printk("[SCHED][RX_PDSCH][before rx_pdsch] Frame %d, slot %d, time %llu\n",UE->frame,last_slot,rt_get_time_ns());
      for (m=pilot2; m<UE->lte_frame_parms.symbols_per_tti; m++) {

        rx_pdsch(UE,
                 PDSCH,
                 eNB_id,
                 eNB_id_i,
                 subframe,
                 m,
                 0,
                 dual_stream_UE,
                 i_mod,
                 harq_pid);

      }

      //        time1 = rt_get_time_ns();
      //        rt_printk("[SCHED][RX_PDSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",UE->frame_rx,last_slot,time0,time1,(time1-time0));

      dlsch_thread_index = harq_pid;

      if (pthread_mutex_lock (&dlsch_mutex[dlsch_thread_index]) != 0) {               // Signal MAC_PHY Scheduler
        LOG_E(PHY,"[UE  %d] ERROR pthread_mutex_lock\n",UE->Mod_id);     // lock before accessing shared resource
        //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
        //return(-1);
      }

      dlsch_instance_cnt[dlsch_thread_index]++;
      dlsch_subframe[dlsch_thread_index] = subframe;
      pthread_mutex_unlock (&dlsch_mutex[dlsch_thread_index]);

      if (dlsch_instance_cnt[dlsch_thread_index] == 0) {
        if (pthread_cond_signal(&dlsch_cond[dlsch_thread_index]) != 0) {
          LOG_E(PHY,"[UE  %d] ERROR pthread_cond_signal for dlsch_cond[%d]\n",UE->Mod_id,dlsch_thread_index);
          //    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
          //return(-1);
        }
      } else {
        LOG_W(PHY,"[UE  %d] DLSCH thread for dlsch_thread_index %d busy!!!\n",UE->Mod_id,dlsch_thread_index);
        //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
        //return(-1);
      }

    } else { // even slots

      for (m=UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols; m<pilot2; m++) {

        rx_pdsch(UE,
                 PDSCH,
                 eNB_id,
                 eNB_id_i,
                 subframe,
                 m,
                 (m==UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0,   // first_symbol_flag
                 dual_stream_UE,
                 i_mod,
                 harq_pid);
      }
    }


    if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) {
      msg("[openair][SCHED][RX_PDSCH] error locking mutex.\n");
    } else {
      rx_pdsch_instance_cnt--;

      if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) {
        msg("[openair][SCHED][RX_PDSCH] error unlocking mutex.\n");
      }
    }

  }

#ifdef HARD_RT
  rt_make_soft_real_time();
#endif

  LOG_D(PHY,"[openair][SCHED][RX_PDSCH] RX_PDSCH thread exiting\n");

  return 0;
}