Esempio n. 1
0
//-----------------------------------------------------------------------------
void
rlc_am_configure(
                const protocol_ctxt_t* const  ctxt_pP,
                rlc_am_entity_t *const        rlc_pP,
                const uint16_t                max_retx_thresholdP,
                const uint16_t                poll_pduP,
                const uint16_t                poll_byteP,
                const uint32_t                t_poll_retransmitP,
                const uint32_t                t_reorderingP,
                const uint32_t                t_status_prohibitP)
//-----------------------------------------------------------------------------
{
  if (rlc_pP->configured == TRUE) {
      LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB AM %u][RECONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          rlc_pP->rb_id,
          max_retx_thresholdP,
          poll_pduP,
          poll_byteP,
          t_poll_retransmitP,
          t_reorderingP,
          t_status_prohibitP);

      rlc_pP->max_retx_threshold = max_retx_thresholdP;
      rlc_pP->poll_pdu           = poll_pduP;
      rlc_pP->poll_byte          = poll_byteP;
      rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;

      rlc_pP->t_poll_retransmit.time_out   = t_poll_retransmitP;
      rlc_pP->t_reordering.time_out        = t_reorderingP;
      rlc_pP->t_status_prohibit.time_out   = t_status_prohibitP;
  } else {
      LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB AM %u][CONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rlc_pP->rb_id,
            max_retx_thresholdP,
            poll_pduP,
            poll_byteP,
            t_poll_retransmitP,
            t_reorderingP,
            t_status_prohibitP);

      rlc_pP->max_retx_threshold = max_retx_thresholdP;
      rlc_pP->poll_pdu           = poll_pduP;
      rlc_pP->poll_byte          = poll_byteP;
      rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;


      rlc_am_init_timer_poll_retransmit(ctxt_pP, rlc_pP, t_poll_retransmitP);
      rlc_am_init_timer_reordering     (ctxt_pP, rlc_pP, t_reorderingP);
      rlc_am_init_timer_status_prohibit(ctxt_pP, rlc_pP, t_status_prohibitP);

      rlc_pP->configured = TRUE;
  }

}
Esempio n. 2
0
//-----------------------------------------------------------------------------
void
rlc_am_init(
                const protocol_ctxt_t* const  ctxt_pP,
                rlc_am_entity_t *const        rlc_pP)
//-----------------------------------------------------------------------------
{
    if (rlc_pP->initialized == TRUE) {
        LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] INITIALIZATION ALREADY DONE, DOING NOTHING\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP));
    } else {
        LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] INITIALIZATION: STATE VARIABLES, BUFFERS, LISTS\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP));
        memset(rlc_pP, 0, sizeof(rlc_am_entity_t));

        list2_init(&rlc_pP->receiver_buffer,      "RX BUFFER");
        list_init(&rlc_pP->pdus_to_mac_layer,     "PDUS TO MAC");
        list_init(&rlc_pP->control_pdu_list,      "CONTROL PDU LIST");
        list_init(&rlc_pP->segmentation_pdu_list, "SEGMENTATION PDU LIST");
        //LOG_D(RLC,"RLC_AM_SDU_CONTROL_BUFFER_SIZE %d sizeof(rlc_am_tx_sdu_management_t) %d \n",  RLC_AM_SDU_CONTROL_BUFFER_SIZE, sizeof(rlc_am_tx_sdu_management_t));

        pthread_mutex_init(&rlc_pP->lock_input_sdus, NULL);
        rlc_pP->input_sdus               = calloc(1, RLC_AM_SDU_CONTROL_BUFFER_SIZE*sizeof(rlc_am_tx_sdu_management_t));
#warning "cast the rlc retrans buffer to uint32"
	//        rlc_pP->pdu_retrans_buffer       = calloc(1, (uint16_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
        rlc_pP->pdu_retrans_buffer       = calloc(1, (uint32_t)((unsigned int)RLC_AM_PDU_RETRANSMISSION_BUFFER_SIZE*(unsigned int)sizeof(rlc_am_tx_data_pdu_management_t)));
        LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] input_sdus[] = %p  element size=%d\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              rlc_pP->input_sdus,
              sizeof(rlc_am_tx_sdu_management_t));
        LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM INIT] pdu_retrans_buffer[] = %p element size=%d\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              rlc_pP->pdu_retrans_buffer,
              sizeof(rlc_am_tx_data_pdu_management_t));

        // TX state variables
        //rlc_pP->vt_a    = 0;
        rlc_pP->vt_ms   = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
        //rlc_pP->vt_s    = 0;
        //rlc_pP->poll_sn = 0;
        // TX counters
        //rlc_pP->c_pdu_without_poll  = 0;
        //rlc_pP->c_byte_without_poll = 0;
        // RX state variables
        //rlc_pP->vr_r    = 0;
        rlc_pP->vr_mr   = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
        //rlc_pP->vr_x    = 0;
        //rlc_pP->vr_ms   = 0;
        //rlc_pP->vr_h    = 0;

        rlc_pP->last_frame_status_indication = 123456; // any value > 1
        rlc_pP->first_retrans_pdu_sn         = -1;

        rlc_pP->initialized                  = TRUE;
    }
}
Esempio n. 3
0
//-----------------------------------------------------------------------------
void
rlc_am_reestablish(
                const protocol_ctxt_t* const  ctxt_pP,
                rlc_am_entity_t* const        rlc_pP)
//-----------------------------------------------------------------------------
{
    /*
     * RLC re-establishment is performed upon request by RRC, and the function
     * is applicable for AM, UM and TM RLC entities.
     * When RRC indicates that an RLC entity should be re-established, the RLC entity shall:
     * - if it is an AM RLC entity:
     *    - when possible, reassemble RLC SDUs from any byte segments of AMD PDUs with SN < VR(MR) in the
     *       receiving side, remove RLC headers when doing so and deliver all reassembled RLC SDUs to upper layer in
     *        ascending order of the RLC SN, if not delivered before;
     *    - discard the remaining AMD PDUs and byte segments of AMD PDUs in the receiving side;
     *    - discard all RLC SDUs and AMD PDUs in the transmitting side;
     *    - discard all RLC control PDUs.
     *    - stop and reset all timers;
     *    - reset all state variables to their initial values.
     */
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[AM REESTABLISH] RE-INIT STATE VARIABLES, BUFFERS, LISTS\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP));

#warning TODO when possible reassemble RLC SDUs from any byte segments of AMD PDUs with SN inf VR(MR)
    list2_free(&rlc_pP->receiver_buffer);

    list_free(&rlc_pP->pdus_to_mac_layer);
    list_free(&rlc_pP->control_pdu_list);
    list_free(&rlc_pP->segmentation_pdu_list);


    // TX state variables
    rlc_pP->vt_a    = 0;
    rlc_pP->vt_ms   = rlc_pP->vt_a + RLC_AM_WINDOW_SIZE;
    rlc_pP->vt_s    = 0;
    rlc_pP->poll_sn = 0;

    // TX counters
    rlc_pP->c_pdu_without_poll  = 0;
    rlc_pP->c_byte_without_poll = 0;

    // RX state variables
    rlc_pP->vr_r    = 0;
    rlc_pP->vr_mr   = rlc_pP->vr_r + RLC_AM_WINDOW_SIZE;
    rlc_pP->vr_x    = 0;
    rlc_pP->vr_ms   = 0;
    rlc_pP->vr_h    = 0;

    rlc_pP->last_frame_status_indication = 123456; // any value > 1
    rlc_pP->first_retrans_pdu_sn         = -1;

    rlc_pP->initialized                  = TRUE;

}
Esempio n. 4
0
//-----------------------------------------------------------------------------
void
rlc_am_set_debug_infos(
                const protocol_ctxt_t* const  ctxt_pP,
                rlc_am_entity_t *const        rlc_pP,
                const srb_flag_t              srb_flagP,
                const rb_id_t                 rb_idP)
//-----------------------------------------------------------------------------
{

    rlc_pP->rb_id         = rb_idP;
    if (srb_flagP) {
      rlc_pP->is_data_plane = 0;
    } else {
      rlc_pP->is_data_plane = 1;
    }
    LOG_D(RLC, PROTOCOL_CTXT_FMT RB_AM_FMT "[SET DEBUG INFOS]\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          RB_AM_ARGS(rlc_pP));

}
Esempio n. 5
0
//-----------------------------------------------------------------------------
int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
{
#ifdef PDCP_USE_NETLINK
  protocol_ctxt_t                ctxt_cpy = *ctxt_pP;
  protocol_ctxt_t                ctxt;
  hash_key_t                     key       = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t                 h_rc;
  struct pdcp_netlink_element_s* data_p    = NULL;
  module_id_t                    ue_id     = 0;
  pdcp_t*                        pdcp_p    = NULL;
# if defined(PDCP_USE_NETLINK_QUEUES)
  rb_id_t                        rab_id    = 0;

  pdcp_transmission_mode_t       pdcp_mode = PDCP_TRANSMISSION_MODE_UNKNOWN;


  while (pdcp_netlink_dequeue_element(ctxt_pP, &data_p) != 0) {
    DevAssert(data_p != NULL);
    rab_id = data_p->pdcp_read_header.rb_id % maxDRB;
    // ctxt_pP->rnti is NOT_A_RNTI
    ctxt_cpy.rnti = pdcp_module_id_to_rnti[ctxt_cpy.module_id][data_p->pdcp_read_header.inst];
    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_cpy.rnti, ctxt_pP->enb_flag, rab_id, SRB_FLAG_NO);
    h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

    if (h_rc != HASH_TABLE_OK) {
      LOG_W(PDCP, PROTOCOL_CTXT_FMT" Dropped IP PACKET cause no PDCP instanciated\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP));
      free(data_p->data);
      free(data_p);
      data_p = NULL;
      continue;
    }

    CHECK_CTXT_ARGS(&ctxt_cpy);

    AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);

    if (rab_id != 0) {
        LOG_D(PDCP, "[FRAME %05d][%s][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ "
            "/ %d Bytes --->][PDCP][MOD %u][RB %u]\n",
              ctxt_cpy.frame,
              (ctxt_cpy.enb_flag) ? "eNB" : "UE",
            data_p->pdcp_read_header.inst,
            data_p->pdcp_read_header.rb_id,
            data_p->pdcp_read_header.data_size,
            ctxt_cpy.module_id,
              rab_id);
#ifdef  OAI_NW_DRIVER_TYPE_ETHERNET

      if ((data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV6_TYPE_MULTICAST) /*TRAFFIC_IPV6_TYPE_MULTICAST */ ||
          (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_MULTICAST) /*TRAFFIC_IPV4_TYPE_MULTICAST */ ||
          (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_BROADCAST) /*TRAFFIC_IPV4_TYPE_BROADCAST */ ) {
#if defined (Rel10)
          PDCP_TRANSMISSION_MODE_TRANSPARENT;
#else
          pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
#endif
      } else if ((data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV6_TYPE_UNICAST) /* TRAFFIC_IPV6_TYPE_UNICAST */ ||
                 (data_p->pdcp_read_header.traffic_type == TRAFFIC_IPV4_TYPE_UNICAST) /*TRAFFIC_IPV4_TYPE_UNICAST*/ ) {
          pdcp_mode=  PDCP_TRANSMISSION_MODE_DATA;
        } else {
          pdcp_mode= PDCP_TRANSMISSION_MODE_DATA;
          LOG_W(PDCP,"unknown IP traffic type \n");
        }

#else // OAI_NW_DRIVER_TYPE_ETHERNET NASMESH driver does not curreenlty support multicast traffic
        pdcp_mode = PDCP_TRANSMISSION_MODE_DATA;
#endif
      pdcp_data_req(&ctxt_cpy,
                      SRB_FLAG_NO,
                      rab_id % maxDRB,
                      RLC_MUI_UNDEFINED,
                      RLC_SDU_CONFIRM_NO,
                    data_p->pdcp_read_header.data_size,
                    data_p->data,
                      pdcp_mode);
    } else if (ctxt_cpy.enb_flag) {
      /* rb_id = 0, thus interpreated as broadcast and transported as
       * multiple unicast is a broadcast packet, we have to send this
       * packet on all default RABS of all connected UEs
       */
      LOG_D(PDCP, "eNB Try Forcing send on DEFAULT_RAB_ID first_ue_local %u nb_ue_local %u\n", oai_emulation.info.first_ue_local, oai_emulation.info.nb_ue_local);

      for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) {
        if (pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
          LOG_D(PDCP, "eNB Try Forcing send on DEFAULT_RAB_ID UE %d\n", ue_id);
          ctxt.module_id     = ctxt_cpy.module_id;
          ctxt.rnti          = ctxt_cpy.pdcp_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
          ctxt.frame         = ctxt_cpy.frame;
          ctxt.enb_flag      = ctxt_cpy.enb_flag;

          pdcp_data_req(
            &ctxt,
            SRB_FLAG_NO,
            DEFAULT_RAB_ID,
            RLC_MUI_UNDEFINED,
            RLC_SDU_CONFIRM_NO,
            data_p->pdcp_read_header.data_size,
            data_p->data,
            PDCP_TRANSMISSION_MODE_DATA);
        }
      }
    } else {
      LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
      pdcp_data_req(
        &ctxt_cpy,
        SRB_FLAG_NO,
        DEFAULT_RAB_ID,
        RLC_MUI_UNDEFINED,
        RLC_SDU_CONFIRM_NO,
        data_p->pdcp_read_header.data_size,
        data_p->data,
        PDCP_TRANSMISSION_MODE_DATA);
    }

    free(data_p->data);
    free(data_p);
    data_p = NULL;
  }

  return 0;
# else /* PDCP_USE_NETLINK_QUEUES*/
  int              len = 1;
  rb_id_t          rab_id  = 0;

  while (len > 0) {
    len = recvmsg(nas_sock_fd, &nas_msg_rx, 0);

    if (len<=0) {
      // nothing in pdcp NAS socket
      //LOG_D(PDCP, "[PDCP][NETLINK] Nothing in socket, length %d \n", len);
    } else {
      for (nas_nlh_rx = (struct nlmsghdr *) nl_rx_buf;
           NLMSG_OK (nas_nlh_rx, len);
           nas_nlh_rx = NLMSG_NEXT (nas_nlh_rx, len)) {

        if (nas_nlh_rx->nlmsg_type == NLMSG_DONE) {
          LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_DONE\n");
          //return;
        }

        if (nas_nlh_rx->nlmsg_type == NLMSG_ERROR) {
          LOG_D(PDCP, "[PDCP][NETLINK] RX NLMSG_ERROR\n");
        }

        if (pdcp_read_state_g == 0) {
          if (nas_nlh_rx->nlmsg_len == sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)) {
            pdcp_read_state_g = 1;  //get
            memcpy((void *)&pdcp_read_header_g, (void *)NLMSG_DATA(nas_nlh_rx), sizeof(pdcp_data_req_header_t));
            LOG_D(PDCP, "[PDCP][NETLINK] RX pdcp_data_req_header_t inst %u, rb_id %u data_size %d\n",
                  pdcp_read_header_g.inst, pdcp_read_header_g.rb_id, pdcp_read_header_g.data_size);
          } else {
            LOG_E(PDCP, "[PDCP][NETLINK] WRONG size %d should be sizeof (pdcp_data_req_header_t) + sizeof(struct nlmsghdr)\n",
                  nas_nlh_rx->nlmsg_len);
          }
        } else {
          pdcp_read_state_g = 0;
          // print_active_requests()
#ifdef PDCP_DEBUG
          LOG_D(PDCP, "[PDCP][NETLINK] Something in socket, length %d \n",
                nas_nlh_rx->nlmsg_len - sizeof(struct nlmsghdr));
#endif

#ifdef OAI_EMU

          // overwrite function input parameters, because only one netlink socket for all instances
          if (pdcp_read_header_g.inst < oai_emulation.info.nb_enb_local) {
            ctxt.frame         = ctxt_cpy.frame;
            ctxt.enb_flag      = ENB_FLAG_YES;
            ctxt.module_id     = pdcp_read_header_g.inst  +  oai_emulation.info.first_enb_local;
            ctxt.rnti          = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt.module_id ][pdcp_read_header_g.rb_id / maxDRB + oai_emulation.info.first_ue_local];
            rab_id    = pdcp_read_header_g.rb_id % maxDRB;
          } else {
            ctxt.frame         = ctxt_cpy.frame;
            ctxt.enb_flag      = ENB_FLAG_NO;
            ctxt.module_id     = pdcp_read_header_g.inst - oai_emulation.info.nb_enb_local + oai_emulation.info.first_ue_local;
            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
            rab_id    = pdcp_read_header_g.rb_id;
          }

          CHECK_CTXT_ARGS(&ctxt);
          AssertFatal (rab_id    < maxDRB,                       "RB id is too high (%u/%d)!\n", rab_id, maxDRB);
          /*LGpdcp_read_header.inst = (pdcp_read_header_g.inst >= oai_emulation.info.nb_enb_local) ? \
                  pdcp_read_header_g.inst - oai_emulation.info.nb_enb_local+ NB_eNB_INST + oai_emulation.info.first_ue_local :
                  pdcp_read_header_g.inst +  oai_emulation.info.first_enb_local;*/
#else // OAI_EMU
          pdcp_read_header_g.inst = 0;
#warning "TO DO CORRCT VALUES FOR ue mod id, enb mod id"
          ctxt.frame         = ctxt_cpy.frame;
          ctxt.enb_flag      = ctxt_cpy.enb_flag;

          if (ctxt_cpy.enb_flag) {
            ctxt.module_id = 0;
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
            ctxt.rnti          = pdcp_eNB_UE_instance_to_rnti[pdcp_eNB_UE_instance_to_rnti_index];
          } else {
            ctxt.module_id = 0;
            rab_id      = pdcp_read_header_g.rb_id % maxDRB;
            ctxt.rnti          = pdcp_UE_UE_module_id_to_rnti[ctxt.module_id];
          }


#endif

          if (ctxt.enb_flag) {
            if (rab_id != 0) {
              rab_id = rab_id % maxDRB;
              key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
              h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

              if (h_rc == HASH_TABLE_OK) {
#ifdef PDCP_DEBUG
                LOG_D(PDCP, "[FRAME %5u][eNB][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      len,
                      nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                      pdcp_read_header_g.rb_id);
#endif

          	    MSC_LOG_RX_MESSAGE(
          	      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
          	      NULL,
          	      0,
          	      MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
          	      MSC_AS_TIME_ARGS(ctxt_pP),
                  pdcp_read_header_g.inst,
          	      pdcp_read_header_g.rb_id,
          	      rab_id,
          	      pdcp_read_header_g.data_size);
                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u]UE %u][RB %u]\n",
                      ctxt_cpy.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
                      ctxt.module_id,
                      ctxt.rnti,
                      rab_id);

                pdcp_data_req(&ctxt,
                              SRB_FLAG_NO,
                              rab_id,
                              RLC_MUI_UNDEFINED,
                              RLC_SDU_CONFIRM_NO,
                              pdcp_read_header_g.data_size,
                              (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                              PDCP_TRANSMISSION_MODE_DATA);
              } else {
                LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE, DROPPED\n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
                      ctxt.module_id,
                      ctxt.rnti,
                      rab_id);
              }
            } else  { // rb_id =0, thus interpreated as broadcast and transported as multiple unicast
              // is a broadcast packet, we have to send this packet on all default RABS of all connected UEs
#warning CODE TO BE REVIEWED, ONLY WORK FOR SIMPLE TOPOLOGY CASES
              for (ue_id = 0; ue_id < NB_UE_INST; ue_id++) {
                if (oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id] != NOT_A_RNTI) {
                  ctxt.rnti = oai_emulation.info.eNB_ue_module_id_to_rnti[ctxt_cpy.module_id][ue_id];
                  LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
                        ctxt.frame,
                        pdcp_read_header_g.inst,
                        pdcp_read_header_g.rb_id,
                        pdcp_read_header_g.data_size,
                        ctxt.module_id,
                        ctxt.rnti,
                        DEFAULT_RAB_ID);
                  pdcp_data_req (
                    &ctxt,
                    SRB_FLAG_NO,
                    DEFAULT_RAB_ID,
                    RLC_MUI_UNDEFINED,
                    RLC_SDU_CONFIRM_NO,
                    pdcp_read_header_g.data_size,
                    (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                    PDCP_TRANSMISSION_MODE_DATA);
                }
              }
            }
          } else { // enb_flag
            if (rab_id != 0) {
              rab_id = rab_id % maxDRB;
              key = PDCP_COLL_KEY_VALUE(ctxt.module_id, ctxt.rnti, ctxt.enb_flag, rab_id, SRB_FLAG_NO);
              h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);

              if (h_rc == HASH_TABLE_OK) {
#ifdef PDCP_DEBUG
                LOG_D(PDCP, "[FRAME %5u][UE][NETLINK][IP->PDCP] INST %d: Received socket with length %d (nlmsg_len = %d) on Rab %d \n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      len,
                      nas_nlh_rx->nlmsg_len-sizeof(struct nlmsghdr),
                      pdcp_read_header_g.rb_id);

                LOG_D(PDCP, "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB %u]\n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
                      ctxt.module_id,
                      ctxt.rnti,
                      rab_id);
#endif
          	    MSC_LOG_RX_MESSAGE(
          	      (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
          	      NULL,
          	      0,
          	      MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
          	      MSC_AS_TIME_ARGS(ctxt_pP),
                  pdcp_read_header_g.inst,
          	      pdcp_read_header_g.rb_id,
          	      rab_id,
          	      pdcp_read_header_g.data_size);

                pdcp_data_req(
                  &ctxt,
                  SRB_FLAG_NO,
                  rab_id,
                  RLC_MUI_UNDEFINED,
                  RLC_SDU_CONFIRM_NO,
                  pdcp_read_header_g.data_size,
                  (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                  PDCP_TRANSMISSION_MODE_DATA);
              } else {
            	MSC_LOG_RX_DISCARDED_MESSAGE(
                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                  (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                  NULL,
                  0,
                  MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u rab %u size %u",
                  MSC_AS_TIME_ARGS(ctxt_pP),
                  pdcp_read_header_g.inst,
                  pdcp_read_header_g.rb_id,
                  rab_id,
                  pdcp_read_header_g.data_size);
                LOG_D(PDCP,
                      "[FRAME %5u][UE][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes ---X][PDCP][MOD %u][UE %u][RB %u] NON INSTANCIATED INSTANCE key 0x%"PRIx64", DROPPED\n",
                      ctxt.frame,
                      pdcp_read_header_g.inst,
                      pdcp_read_header_g.rb_id,
                      pdcp_read_header_g.data_size,
                      ctxt.module_id,
                      ctxt.rnti,
                      rab_id,
                      key);
              }
            }  else {
              LOG_D(PDCP, "Forcing send on DEFAULT_RAB_ID\n");
              LOG_D(PDCP, "[FRAME %5u][eNB][IP][INSTANCE %u][RB %u][--- PDCP_DATA_REQ / %d Bytes --->][PDCP][MOD %u][UE %u][RB DEFAULT_RAB_ID %u]\n",
                    ctxt.frame,
                    pdcp_read_header_g.inst,
                    pdcp_read_header_g.rb_id,
                    pdcp_read_header_g.data_size,
                    ctxt.module_id,
                    ctxt.rnti,
                    DEFAULT_RAB_ID);
          	  MSC_LOG_RX_MESSAGE(
                (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_PDCP_ENB:MSC_PDCP_UE,
                (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_IP_ENB:MSC_IP_UE,
                NULL,0,
                MSC_AS_TIME_FMT" DATA-REQ inst %u rb %u default rab %u size %u",
                MSC_AS_TIME_ARGS(ctxt_pP),
                pdcp_read_header_g.inst,
                pdcp_read_header_g.rb_id,
                DEFAULT_RAB_ID,
                pdcp_read_header_g.data_size);

              pdcp_data_req (
                &ctxt,
                SRB_FLAG_NO,
                DEFAULT_RAB_ID,
                RLC_MUI_UNDEFINED,
                RLC_SDU_CONFIRM_NO,
                pdcp_read_header_g.data_size,
                (unsigned char *)NLMSG_DATA(nas_nlh_rx),
                PDCP_TRANSMISSION_MODE_DATA);
            }
          }

        }
      }
    }
  }

  return len;
# endif
#else // neither PDCP_USE_NETLINK nor PDCP_USE_RT_FIFO
  return 0;
#endif // PDCP_USE_NETLINK
}
//-----------------------------------------------------------------------------
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);

}
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_config_req   (
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t      srb_flagP,
  const MBMS_flag_t     mbms_flagP,
  const config_action_t actionP,
  const rb_id_t         rb_idP,
  const rlc_info_t      rlc_infoP)
{
  //-----------------------------------------------------------------------------
  rlc_op_status_t status;

  LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG_REQ for RAB %u\n",
        PROTOCOL_CTXT_ARGS(ctxt_pP),
        rb_idP);

#ifdef OAI_EMU

  CHECK_CTXT_ARGS(ctxt_pP)

#endif
  AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);

  switch (actionP) {

  case CONFIG_ACTION_ADD:
    if (rrc_rlc_add_rlc(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, rb_idP, rlc_infoP.rlc_mode) != NULL) {
      return RLC_OP_STATUS_INTERNAL_ERROR;
    }

    // no break, fall to next case
  case CONFIG_ACTION_MODIFY:
    switch (rlc_infoP.rlc_mode) {
    case RLC_MODE_AM:
      LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB AM\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);

      config_req_rlc_am(
        ctxt_pP,
        srb_flagP,
        &rlc_infoP.rlc.rlc_am_info,
        rb_idP);
      break;

    case RLC_MODE_UM:
      LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB UM\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
      config_req_rlc_um(
        ctxt_pP,
        srb_flagP,
        &rlc_infoP.rlc.rlc_um_info,
        rb_idP);
      break;

    case RLC_MODE_TM:
      LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB TM\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            rb_idP);
      config_req_rlc_tm(
        ctxt_pP,
        srb_flagP,
        &rlc_infoP.rlc.rlc_tm_info,
        rb_idP);
      break;

    default:
      return RLC_OP_STATUS_BAD_PARAMETER;
    }

    break;

  case CONFIG_ACTION_REMOVE:
    return rrc_rlc_remove_rlc(ctxt_pP, srb_flagP, mbms_flagP, rb_idP);
    break;

  default:
    return RLC_OP_STATUS_BAD_PARAMETER;
  }

  return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_config_asn1_req (const protocol_ctxt_t   * const ctxt_pP,
    const SRB_ToAddModList_t   * const srb2add_listP,
    const DRB_ToAddModList_t   * const drb2add_listP,
    const DRB_ToReleaseList_t  * const drb2release_listP
#if defined(Rel10)
    ,const PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP
#endif
                                        )
{
  //-----------------------------------------------------------------------------
  rb_id_t                rb_id           = 0;
  logical_chan_id_t      lc_id           = 0;
  DRB_Identity_t         drb_id          = 0;
  DRB_Identity_t*        pdrb_id         = NULL;
  long int               cnt             = 0;
  const SRB_ToAddMod_t  *srb_toaddmod_p  = NULL;
  const DRB_ToAddMod_t  *drb_toaddmod_p  = NULL;
  rlc_union_t           *rlc_union_p     = NULL;
  hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
#if defined(Rel10)
  int                        i, j;
  MBMS_SessionInfoList_r9_t *mbms_SessionInfoList_r9_p = NULL;
  MBMS_SessionInfo_r9_t     *MBMS_SessionInfo_p        = NULL;
  mbms_session_id_t          mbms_session_id;
  mbms_service_id_t          mbms_service_id;
  DL_UM_RLC_t                dl_um_rlc;


#endif

  LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ ASN1 \n",
        PROTOCOL_CTXT_ARGS(ctxt_pP));

#ifdef OAI_EMU

  CHECK_CTXT_ARGS(ctxt_pP)

#endif

  if (srb2add_listP != NULL) {
    for (cnt=0; cnt<srb2add_listP->list.count; cnt++) {
      rb_id = srb2add_listP->list.array[cnt]->srb_Identity;
      lc_id  = rb_id + 2;

      LOG_D(RLC, "Adding SRB %d, rb_id %d\n",srb2add_listP->list.array[cnt]->srb_Identity,rb_id);
      srb_toaddmod_p = srb2add_listP->list.array[cnt];

      if (srb_toaddmod_p->rlc_Config) {
        switch (srb_toaddmod_p->rlc_Config->present) {
        case SRB_ToAddMod__rlc_Config_PR_NOTHING:
          break;

        case SRB_ToAddMod__rlc_Config_PR_explicitValue:
          switch (srb_toaddmod_p->rlc_Config->choice.explicitValue.present) {
          case RLC_Config_PR_NOTHING:
            break;

          case RLC_Config_PR_am:
            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_AM) != NULL) {
              config_req_rlc_am_asn1 (
                ctxt_pP,
                SRB_FLAG_YES,
                &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.am,
                rb_id);
            } else {
              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                    PROTOCOL_CTXT_ARGS(ctxt_pP),
                    rb_id);
            }

            break;

          case RLC_Config_PR_um_Bi_Directional:
            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
              config_req_rlc_um_asn1(
                ctxt_pP,
                SRB_FLAG_YES,
                MBMS_FLAG_NO,
                UNUSED_PARAM_MBMS_SESSION_ID,
                UNUSED_PARAM_MBMS_SERVICE_ID,
                &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.ul_UM_RLC,
                &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Bi_Directional.dl_UM_RLC,
                rb_id);
            } else {
              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                    PROTOCOL_CTXT_ARGS(ctxt_pP),
                    rb_id);
            }

            break;

          case RLC_Config_PR_um_Uni_Directional_UL:
            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
              config_req_rlc_um_asn1(
                ctxt_pP,
                SRB_FLAG_YES,
                MBMS_FLAG_NO,
                UNUSED_PARAM_MBMS_SESSION_ID,
                UNUSED_PARAM_MBMS_SERVICE_ID,
                &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_UL.ul_UM_RLC,
                NULL,
                rb_id);
            } else {
              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                    PROTOCOL_CTXT_ARGS(ctxt_pP),
                    rb_id);
            }

            break;

          case RLC_Config_PR_um_Uni_Directional_DL:
            if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
              config_req_rlc_um_asn1(
                ctxt_pP,
                SRB_FLAG_YES,
                MBMS_FLAG_NO,
                UNUSED_PARAM_MBMS_SESSION_ID,
                UNUSED_PARAM_MBMS_SERVICE_ID,
                NULL,
                &srb_toaddmod_p->rlc_Config->choice.explicitValue.choice.um_Uni_Directional_DL.dl_UM_RLC,
                rb_id);
            } else {
              LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                    PROTOCOL_CTXT_ARGS(ctxt_pP),
                    rb_id);
            }

            break;

          default:
            LOG_E(RLC, PROTOCOL_CTXT_FMT" UNKNOWN RLC CONFIG %d \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
                  srb_toaddmod_p->rlc_Config->choice.explicitValue.present);
            break;
          }

          break;

        case SRB_ToAddMod__rlc_Config_PR_defaultValue:
#warning TO DO SRB_ToAddMod__rlc_Config_PR_defaultValue
          if (rrc_rlc_add_rlc   (ctxt_pP, SRB_FLAG_YES, MBMS_FLAG_NO, rb_id, lc_id, RLC_MODE_UM) != NULL) {
            config_req_rlc_um_asn1(
              ctxt_pP,
              SRB_FLAG_YES,
              MBMS_FLAG_NO,
              UNUSED_PARAM_MBMS_SESSION_ID,
              UNUSED_PARAM_MBMS_SERVICE_ID,
              NULL, // TO DO DEFAULT CONFIG
              NULL, // TO DO DEFAULT CONFIG
              rb_id);
          } else {
            LOG_D(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                  PROTOCOL_CTXT_ARGS(ctxt_pP),
                  rb_id);
          }

          break;

        default:
          ;
        }
      }
    }
  }

  if (drb2add_listP != NULL) {
    for (cnt=0; cnt<drb2add_listP->list.count; cnt++) {
      drb_toaddmod_p = drb2add_listP->list.array[cnt];

      drb_id = drb_toaddmod_p->drb_Identity;
      lc_id  = drb_id + 2;

      LOG_D(RLC, "Adding DRB %d, lc_id %d\n",drb_id,lc_id);


      if (drb_toaddmod_p->rlc_Config) {

        switch (drb_toaddmod_p->rlc_Config->present) {
        case RLC_Config_PR_NOTHING:
          break;

        case RLC_Config_PR_am:
          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_AM) != NULL) {
            config_req_rlc_am_asn1 (
              ctxt_pP,
              SRB_FLAG_NO,
              &drb_toaddmod_p->rlc_Config->choice.am,
              drb_id);
          }

          break;

        case RLC_Config_PR_um_Bi_Directional:
          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
            config_req_rlc_um_asn1(
              ctxt_pP,
              SRB_FLAG_NO,
              MBMS_FLAG_NO,
              UNUSED_PARAM_MBMS_SESSION_ID,
              UNUSED_PARAM_MBMS_SERVICE_ID,
              &drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.ul_UM_RLC,
              &drb_toaddmod_p->rlc_Config->choice.um_Bi_Directional.dl_UM_RLC,
              drb_id);
          }

          break;

        case RLC_Config_PR_um_Uni_Directional_UL:
          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
            config_req_rlc_um_asn1(
              ctxt_pP,
              SRB_FLAG_NO,
              MBMS_FLAG_NO,
              UNUSED_PARAM_MBMS_SESSION_ID,
              UNUSED_PARAM_MBMS_SERVICE_ID,
              &drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_UL.ul_UM_RLC,
              NULL,
              drb_id);
          }

          break;

        case RLC_Config_PR_um_Uni_Directional_DL:
          if (rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, MBMS_FLAG_NO, drb_id, lc_id, RLC_MODE_UM) != NULL) {
            config_req_rlc_um_asn1(
              ctxt_pP,
              SRB_FLAG_NO,
              MBMS_FLAG_NO,
              UNUSED_PARAM_MBMS_SESSION_ID,
              UNUSED_PARAM_MBMS_SERVICE_ID,
              NULL,
              &drb_toaddmod_p->rlc_Config->choice.um_Uni_Directional_DL.dl_UM_RLC,
              drb_id);
          }

          break;

        default:
          LOG_W(RLC, PROTOCOL_CTXT_FMT"[RB %u] unknown drb_toaddmod_p->rlc_Config->present \n",
                PROTOCOL_CTXT_ARGS(ctxt_pP),
                drb_id);
        }
      }
    }
  }

  if (drb2release_listP != NULL) {
    for (cnt=0; cnt<drb2release_listP->list.count; cnt++) {
      pdrb_id = drb2release_listP->list.array[cnt];
      rrc_rlc_remove_rlc(
        ctxt_pP,
        SRB_FLAG_NO,
        MBMS_FLAG_NO,
        *pdrb_id);
    }
  }

#if defined(Rel10)

  if (pmch_InfoList_r9_pP != NULL) {
    for (i=0; i<pmch_InfoList_r9_pP->list.count; i++) {
      mbms_SessionInfoList_r9_p = &(pmch_InfoList_r9_pP->list.array[i]->mbms_SessionInfoList_r9);

      for (j=0; j<mbms_SessionInfoList_r9_p->list.count; j++) {
        MBMS_SessionInfo_p = mbms_SessionInfoList_r9_p->list.array[j];
        mbms_session_id    = MBMS_SessionInfo_p->sessionId_r9->buf[0];
        lc_id              = mbms_session_id;
        mbms_service_id    = MBMS_SessionInfo_p->tmgi_r9.serviceId_r9.buf[2]; //serviceId is 3-octet string

        // can set the mch_id = i
        if (ctxt_pP->enb_flag) {
          rb_id =  (mbms_service_id * maxSessionPerPMCH ) + mbms_session_id;//+ (maxDRB + 3) * MAX_MOBILES_PER_ENB; // 1
          rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lc_id].service_id                     = mbms_service_id;
          rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lc_id].session_id                     = mbms_session_id;
          rlc_mbms_enb_set_lcid_by_rb_id(ctxt_pP->module_id,rb_id,lc_id);

        } else {
          rb_id =  (mbms_service_id * maxSessionPerPMCH ) + mbms_session_id; // + (maxDRB + 3); // 15
          rlc_mbms_lcid2service_session_id_ue[ctxt_pP->module_id][lc_id].service_id                    = mbms_service_id;
          rlc_mbms_lcid2service_session_id_ue[ctxt_pP->module_id][lc_id].session_id                    = mbms_session_id;
          rlc_mbms_ue_set_lcid_by_rb_id(ctxt_pP->module_id,rb_id,lc_id);
        }

        key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->module_id, ctxt_pP->enb_flag, mbms_service_id, mbms_session_id);

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

        if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
          rlc_union_p = rrc_rlc_add_rlc   (
                          ctxt_pP,
                          SRB_FLAG_NO,
                          MBMS_FLAG_YES,
                          rb_id,
                          lc_id,
                          RLC_MODE_UM);
          AssertFatal(rlc_union_p != NULL, "ADD MBMS RLC UM FAILED");
        }

        LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ MBMS ASN1 LC ID %u RB ID %u SESSION ID %u SERVICE ID %u\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              lc_id,
              rb_id,
              mbms_session_id,
              mbms_service_id
             );
        dl_um_rlc.sn_FieldLength = SN_FieldLength_size5;
        dl_um_rlc.t_Reordering   = T_Reordering_ms0;

        config_req_rlc_um_asn1 (
          ctxt_pP,
          SRB_FLAG_NO,
          MBMS_FLAG_YES,
          mbms_session_id,
          mbms_service_id,
          NULL,
          &dl_um_rlc,
          rb_id);
      }
    }
  }

#endif

  LOG_D(RLC, PROTOCOL_CTXT_FMT" CONFIG REQ ASN1 END \n",
        PROTOCOL_CTXT_ARGS(ctxt_pP));
  return RLC_OP_STATUS_OK;
}
//-----------------------------------------------------------------------------
rlc_union_t* rrc_rlc_add_rlc   (
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t        srb_flagP,
  const MBMS_flag_t       MBMS_flagP,
  const rb_id_t           rb_idP,
  const logical_chan_id_t chan_idP,
  const rlc_mode_t        rlc_modeP)
{
  //-----------------------------------------------------------------------------
  hash_key_t             key         = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
  rlc_union_t           *rlc_union_p = NULL;
#ifdef Rel10
  rlc_mbms_id_t         *mbms_id_p  = NULL;
  logical_chan_id_t      lcid            = 0;
#endif

#ifdef OAI_EMU

  CHECK_CTXT_ARGS(ctxt_pP)

#endif

  if (MBMS_flagP == FALSE) {
    AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);
    AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC);
  }

#ifdef Rel10

  if (MBMS_flagP == TRUE) {
    if (ctxt_pP->enb_flag) {
      lcid = rlc_mbms_enb_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP);
      mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid];
      //LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].service_id = 0;
      //LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].session_id = 0;
      //LG 2014-04-15rlc_mbms_rbid2lcid_eNB[ctxt_pP->module_id][rb_idP] = RLC_LC_UNALLOCATED;

    } else {
      lcid = rlc_mbms_ue_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP);
      mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[ctxt_pP->module_id][lcid];
      //LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].service_id = 0;
      //LG 2014-04-15rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].session_id = 0;
      //LG 2014-04-15rlc_mbms_rbid2lcid_ue[ctxt_pP->module_id][rb_idP] = RLC_LC_UNALLOCATED;
    }

    key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
  } else
#endif
  {
    key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  }

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

  if (h_rc == HASH_TABLE_OK) {
    LOG_W(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc , already exist %s\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          (srb_flagP) ? "SRB" : "DRB",
          rb_idP,
          (srb_flagP) ? "SRB" : "DRB");
    AssertFatal(rlc_union_p->mode == rlc_modeP, "Error rrc_rlc_add_rlc , already exist but RLC mode differ");
    return rlc_union_p;
  } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
    rlc_union_p = calloc(1, sizeof(rlc_union_t));
    h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p);

    if (h_rc == HASH_TABLE_OK) {
#ifdef Rel10

      if (MBMS_flagP == TRUE) {
        LOG_I(RLC, PROTOCOL_CTXT_FMT" RLC service id %u session id %u rrc_rlc_add_rlc\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              mbms_id_p->service_id,
              mbms_id_p->session_id);
      } else
#endif
      {
        LOG_I(RLC, PROTOCOL_CTXT_FMT" [%s %u] rrc_rlc_add_rlc  %s\n",
              PROTOCOL_CTXT_ARGS(ctxt_pP),
              (srb_flagP) ? "SRB" : "DRB",
              rb_idP,
              (srb_flagP) ? "SRB" : "DRB");
      }

      rlc_union_p->mode = rlc_modeP;
      return rlc_union_p;
    } else {
      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc  FAILED %s\n",
            PROTOCOL_CTXT_ARGS(ctxt_pP),
            (srb_flagP) ? "SRB" : "DRB",
            rb_idP,
            (srb_flagP) ? "SRB" : "DRB");
      free(rlc_union_p);
      rlc_union_p = NULL;
      return NULL;
    }
  } else {
    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_add_rlc , INTERNAL ERROR %s\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          (srb_flagP) ? "SRB" : "DRB",
          rb_idP,
          (srb_flagP) ? "SRB" : "DRB");
  }

  return NULL;
}
//-----------------------------------------------------------------------------
rlc_op_status_t rrc_rlc_remove_rlc   (
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t  srb_flagP,
  const MBMS_flag_t MBMS_flagP,
  const rb_id_t     rb_idP)
{
  //-----------------------------------------------------------------------------
  logical_chan_id_t      lcid            = 0;
  hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
  hashtable_rc_t         h_rc;
  rlc_union_t           *rlc_union_p = NULL;
#ifdef Rel10
  rlc_mbms_id_t         *mbms_id_p  = NULL;
#endif
#ifdef OAI_EMU
  CHECK_CTXT_ARGS(ctxt_pP)

#endif

#ifdef Rel10

  if (MBMS_flagP == TRUE) {
    if (ctxt_pP->enb_flag) {
      lcid = rlc_mbms_enb_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP);
      mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid];
      rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].service_id = 0;
      rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].session_id = 0;
      rlc_mbms_rbid2lcid_ue[ctxt_pP->module_id][rb_idP] = RLC_LC_UNALLOCATED;

    } else {
      lcid = rlc_mbms_ue_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP);
      mbms_id_p = &rlc_mbms_lcid2service_session_id_ue[ctxt_pP->module_id][lcid];
      rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].service_id = 0;
      rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid].session_id = 0;
      rlc_mbms_rbid2lcid_ue[ctxt_pP->module_id][rb_idP] = RLC_LC_UNALLOCATED;
    }

    key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_id_p->service_id, mbms_id_p->session_id);
  } else
#endif
  {
    key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  }


  AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX);

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

  if (h_rc == HASH_TABLE_OK) {
    h_rc = hashtable_remove(rlc_coll_p, key);
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASED %s\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          (srb_flagP) ? "SRB" : "DRB",
          rb_idP,
          (srb_flagP) ? "SRB" : "DRB");
  } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) {
    LOG_D(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : RLC NOT FOUND %s\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          (srb_flagP) ? "SRB" : "DRB",
          rb_idP,
          (srb_flagP) ? "SRB" : "DRB");
  } else {
    LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] RELEASE : INTERNAL ERROR %s\n",
          PROTOCOL_CTXT_ARGS(ctxt_pP),
          (srb_flagP) ? "SRB" : "DRB",
          rb_idP,
          (srb_flagP) ? "SRB" : "DRB");
  }

  return RLC_OP_STATUS_OK;
}