//------------------------------------------------------------------------------
int s1ap_eNB_handle_nas_downlink(const uint32_t               assoc_id,
                                 const uint32_t               stream,
                                 struct s1ap_message_s* message_p)
//------------------------------------------------------------------------------
{
  const S1ap_DownlinkNASTransportIEs_t *downlink_NAS_transport_p = NULL;

  s1ap_eNB_mme_data_t   *mme_desc_p                        = NULL;
  s1ap_eNB_ue_context_t *ue_desc_p                         = NULL;
  s1ap_eNB_instance_t   *s1ap_eNB_instance                 = NULL;

  DevAssert(message_p != NULL);

  downlink_NAS_transport_p = &message_p->msg.s1ap_DownlinkNASTransportIEs;

  /* UE-related procedure -> stream != 0 */
  if (stream == 0) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream == 0\n",
               assoc_id);
    return -1;
  }

  if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) {
    S1AP_ERROR(
      "[SCTP %d] Received NAS downlink message for non existing MME context\n",
      assoc_id);
    return -1;
  }

  s1ap_eNB_instance = mme_desc_p->s1ap_eNB_instance;

  if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
                   downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL) {
    MSC_LOG_RX_DISCARDED_MESSAGE(
      MSC_S1AP_ENB,
      MSC_S1AP_MME,
      (const char *)downlink_NAS_transport_p,
      sizeof(S1ap_DownlinkNASTransportIEs_t),
      MSC_AS_TIME_FMT" downlinkNASTransport  eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
      0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
      downlink_NAS_transport_p->eNB_UE_S1AP_ID,
      downlink_NAS_transport_p->mme_ue_s1ap_id);

    S1AP_ERROR("[SCTP %d] Received NAS downlink message for non existing UE context eNB_UE_S1AP_ID: 0x%"PRIx32" %u\n",
               assoc_id,
               downlink_NAS_transport_p->eNB_UE_S1AP_ID,
               downlink_NAS_transport_p->eNB_UE_S1AP_ID);
    return -1;
  }

  if (0 == ue_desc_p->rx_stream) {
	ue_desc_p->rx_stream = stream;
  } else if (stream != ue_desc_p->rx_stream) {
    S1AP_ERROR("[SCTP %d] Received UE-related procedure on stream %u, expecting %u\n",
               assoc_id, stream, ue_desc_p->rx_stream);
    return -1;
  }

  /* Is it the first outcome of the MME for this UE ? If so store the mme
   * UE s1ap id.
   */
  if (ue_desc_p->mme_ue_s1ap_id == 0) {
    ue_desc_p->mme_ue_s1ap_id = downlink_NAS_transport_p->mme_ue_s1ap_id;
  } else {
    /* We already have a mme ue s1ap id check the received is the same */
    if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) {
      S1AP_ERROR("[SCTP %d] Mismatch in MME UE S1AP ID (0x%"PRIx32" != 0x%"PRIx32")\n",
                 assoc_id,
                 downlink_NAS_transport_p->mme_ue_s1ap_id,
                 ue_desc_p->mme_ue_s1ap_id
                );
      return -1;
    }
  }

  MSC_LOG_RX_MESSAGE(
    MSC_S1AP_ENB,
    MSC_S1AP_MME,
    (const char *)downlink_NAS_transport_p,
    sizeof(S1ap_DownlinkNASTransportIEs_t),
    MSC_AS_TIME_FMT" downlinkNASTransport  eNB_ue_s1ap_id %u mme_ue_s1ap_id %u",
    0,0,//MSC_AS_TIME_ARGS(ctxt_pP),
    downlink_NAS_transport_p->eNB_UE_S1AP_ID,
    downlink_NAS_transport_p->mme_ue_s1ap_id);

  /* Forward the NAS PDU to RRC */
  s1ap_eNB_itti_send_nas_downlink_ind(s1ap_eNB_instance->instance,
                                      ue_desc_p->ue_initial_id,
                                      ue_desc_p->eNB_ue_s1ap_id,
                                      downlink_NAS_transport_p->nas_pdu.buf,
                                      downlink_NAS_transport_p->nas_pdu.size);

  // LG: Why set to 0 ??
  //ue_desc_p->ue_initial_id = 0;

  return 0;
}
예제 #2
0
void config_req_rlc_um_asn1 (
  const protocol_ctxt_t* const ctxt_pP,
  const srb_flag_t          srb_flagP,
  const MBMS_flag_t         mbms_flagP,
  const mbms_session_id_t   mbms_session_idP,
  const mbms_service_id_t   mbms_service_idP,
  const UL_UM_RLC_t       * const ul_rlc_pP,
  const DL_UM_RLC_t       * const dl_rlc_pP,
  const rb_id_t             rb_idP)
{
  uint32_t         ul_sn_FieldLength   = 0;
  uint32_t         dl_sn_FieldLength   = 0;
  uint32_t         t_Reordering        = 0;
  rlc_union_t     *rlc_union_p         = NULL;
  rlc_um_entity_t *rlc_p               = NULL;
  hash_key_t       key                 = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
  hashtable_rc_t   h_rc;

#if Rel10

  if (mbms_flagP) {
    AssertFatal(dl_rlc_pP, "No RLC UM DL config");
    AssertFatal(ul_rlc_pP == NULL, "RLC UM UL config present");
    key = RLC_COLL_KEY_MBMS_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, mbms_service_idP, mbms_session_idP);
    h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
    AssertFatal (h_rc == HASH_TABLE_OK, "RLC NOT FOUND enb id %u rnti %i enb flag %u service id %u, session id %u",
                 ctxt_pP->module_id,
                 ctxt_pP->rnti,
                 ctxt_pP->enb_flag,
                 mbms_service_idP,
                 mbms_session_idP);
    rlc_p = &rlc_union_p->rlc.um;
  } 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);
    AssertFatal (h_rc == HASH_TABLE_OK, "RLC NOT FOUND enb id %u ue id %i enb flag %u rb id %u, srb flag %u",
                 ctxt_pP->module_id,
                 ctxt_pP->rnti,
                 ctxt_pP->enb_flag,
                 rb_idP,
                 srb_flagP);
    rlc_p = &rlc_union_p->rlc.um;
  }

  //-----------------------------------------------------------------------------
  LOG_D(RLC, PROTOCOL_RLC_UM_CTXT_FMT"  CONFIG_REQ timer_reordering=%dms sn_field_length=   RB %u \n",
        PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
        (dl_rlc_pP && dl_rlc_pP->t_Reordering<31)?t_Reordering_tab[dl_rlc_pP->t_Reordering]:-1,
        rb_idP);

  rlc_um_init(ctxt_pP, rlc_p);


  if (rlc_um_fsm_notify_event (ctxt_pP, rlc_p, RLC_UM_RECEIVE_CRLC_CONFIG_REQ_ENTER_DATA_TRANSFER_READY_STATE_EVENT)) {
    rlc_um_set_debug_infos(ctxt_pP,rlc_p, srb_flagP, rb_idP);

    if (ul_rlc_pP != NULL) {
      switch (ul_rlc_pP->sn_FieldLength) {
      case SN_FieldLength_size5:
        ul_sn_FieldLength = 5;
        break;

      case SN_FieldLength_size10:
        ul_sn_FieldLength = 10;
        break;

      default:
        LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID UL sn_FieldLength %d, RLC NOT CONFIGURED\n",
              PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
              rlc_p->rb_id,
              ul_rlc_pP->sn_FieldLength);
        MSC_LOG_RX_DISCARDED_MESSAGE(
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
      	    NULL,
      	    0,
      	    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ UL sn_FieldLength %u",
      	    MSC_AS_TIME_ARGS(ctxt_pP),
      	    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc_p),
      	    ul_rlc_pP->sn_FieldLength);
        return;
      }
    }

    if (dl_rlc_pP != NULL) {
      switch (dl_rlc_pP->sn_FieldLength) {
      case SN_FieldLength_size5:
        dl_sn_FieldLength = 5;
        break;

      case SN_FieldLength_size10:
        dl_sn_FieldLength = 10;
        break;

      default:
        LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID DL sn_FieldLength %d, RLC NOT CONFIGURED\n",
              PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
              rlc_p->rb_id,
              dl_rlc_pP->sn_FieldLength);
        MSC_LOG_RX_DISCARDED_MESSAGE(
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
      	    NULL,
      	    0,
      	    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ DL sn_FieldLength %u",
      	    MSC_AS_TIME_ARGS(ctxt_pP),
      	    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc_p),
      	    dl_rlc_pP->sn_FieldLength);
        return;
      }

      if (dl_rlc_pP->t_Reordering<T_Reordering_spare1) {
        t_Reordering = t_Reordering_tab[dl_rlc_pP->t_Reordering];
      } else {
        LOG_E(RLC,PROTOCOL_RLC_UM_CTXT_FMT" [CONFIGURE] RB %u INVALID T_Reordering %d, RLC NOT CONFIGURED\n",
              PROTOCOL_RLC_UM_CTXT_ARGS(ctxt_pP,rlc_p),
              rlc_p->rb_id,
              dl_rlc_pP->t_Reordering);

        MSC_LOG_RX_DISCARDED_MESSAGE(
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
      	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
      	    NULL,
      	    0,
      	    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ t_Reord %u",
      	    MSC_AS_TIME_ARGS(ctxt_pP),
      	    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc_p),
      	    dl_rlc_pP->t_Reordering);
        return;
      }
    }

    if (ctxt_pP->enb_flag > 0) {
      rlc_um_configure(ctxt_pP,rlc_p,
                       t_Reordering,
                       ul_sn_FieldLength,
                       dl_sn_FieldLength,
                       mbms_flagP);
      MSC_LOG_RX_MESSAGE(
    	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
    	    NULL,
    	    0,
    	    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ t_Reord %u rx snfl %u tx snfl %u",
    	    MSC_AS_TIME_ARGS(ctxt_pP),
    	    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc_p),
    	    t_Reordering,
    	    ul_sn_FieldLength,
    	    dl_sn_FieldLength);
    } else {

      rlc_um_configure(ctxt_pP,rlc_p,
                       t_Reordering,
                       dl_sn_FieldLength,
                       ul_sn_FieldLength,
                       mbms_flagP);
      MSC_LOG_RX_MESSAGE(
    	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
    	    (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RRC_ENB:MSC_RRC_UE,
    	    NULL,
    	    0,
    	    MSC_AS_TIME_FMT" "PROTOCOL_RLC_AM_MSC_FMT" CONFIG-REQ t_Reord %u rx snfl %u tx snfl %u",
    	    MSC_AS_TIME_ARGS(ctxt_pP),
    	    PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, rlc_p),
    	    t_Reordering,
    	    dl_sn_FieldLength,
    	    ul_sn_FieldLength);
    }
  }
}
예제 #3
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
}
static NwGtpv1uRcT
nwGtpv1uProcessGpdu( NwGtpv1uStackT *thiz,
                     NW_IN uint8_t *gpdu,
                     NW_IN uint32_t gpduLen,
                     NW_IN uint32_t peerIp)

{
  NwGtpv1uRcT              rc                = NW_GTPV1U_FAILURE;
  NwGtpv1uMsgHeaderT      *msgHdr            = NULL;
  NwGtpv1uTunnelEndPointT *pTunnelEndPoint   = NULL;
  NwGtpv1uTunnelEndPointT  tunnelEndPointKey;
  //    uint16_t                   hdr_len           = 0;

#if defined(LOG_GTPU) && LOG_GTPU > 0
  NW_ENTER(thiz);
#endif

  // no buffer offset
  msgHdr = (NwGtpv1uMsgHeaderT *) gpdu;

  tunnelEndPointKey.teid = ntohl(msgHdr->teid);

  pTunnelEndPoint = RB_FIND(NwGtpv1uTunnelEndPointIdentifierMap,
                            &(thiz->teidMap), &tunnelEndPointKey);

  if(pTunnelEndPoint) {
    NwGtpv1uMsgHandleT hMsg;

    rc = nwGtpv1uMsgFromBufferNew( (NwGtpv1uStackHandleT)thiz,
                                   (uint8_t *)gpdu,
                                   gpduLen,
                                   &hMsg);

    /*
      uint8_t*        msgBuf;
      uint32_t        msgBufLen;
      uint32_t        msgBufOffset;
     */
    if(NW_GTPV1U_OK == rc) {
      NwGtpv1uMsgT *pMsg = (NwGtpv1uMsgT *) hMsg;
#if defined(LOG_GTPU) && LOG_GTPU > 0
      GTPU_DEBUG("Received T-PDU over tunnel end-point '%x' of size %u (%u) (decapsulated %u)from "NW_IPV4_ADDR"\n",
                 ntohl(msgHdr->teid), gpduLen, pMsg->msgLen, pMsg->msgBufLen, NW_IPV4_ADDR_FORMAT((peerIp)));
#endif
      MSC_LOG_RX_MESSAGE(
        (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_ENB:MSC_GTPU_SGW,
        (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_SGW:MSC_GTPU_ENB,
        NULL,
        0,
        " G-PDU ltid %u size %u",
        tunnelEndPointKey.teid,
        gpduLen);

      rc = nwGtpSessionSendMsgApiToUlpEntity(pTunnelEndPoint, pMsg);
    }
  } else {
    MSC_LOG_RX_DISCARDED_MESSAGE(
      (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_ENB:MSC_GTPU_SGW,
      (thiz->stackType == GTPU_STACK_ENB) ? MSC_GTPU_SGW:MSC_GTPU_ENB,
      NULL,
      0,
      " G-PDU ltid %u size %u",
      tunnelEndPointKey.teid,
      gpduLen);
    GTPU_ERROR("Received T-PDU over non-existent tunnel end-point '%x' from "NW_IPV4_ADDR"\n",
               ntohl(msgHdr->teid), NW_IPV4_ADDR_FORMAT((peerIp)));
  }

#if defined(LOG_GTPU) && LOG_GTPU > 0
  NW_LEAVE(thiz);
#endif
  return rc;
}