网络知识 娱乐 【OpenAirInterface5g】RRC NR解析之RrcSetupRequest

【OpenAirInterface5g】RRC NR解析之RrcSetupRequest

作者:柒号华仔
个人主页:欢迎访问我的主页
个人信条:星光不问赶路人,岁月不负有心人。
个人方向:专注于4G/5G领域,同时兼顾其他网络协议,编解码协议,C/C++,linux等,感兴趣的小伙伴可以关注我,一起交流。


目录

    • 1. RrcSetupRequest介绍
      • 1.1 发起目的
      • 1.2 信令内容抓包
      • 1.3 gNB回复
    • 2. RrcSetupRequest解析处理流程
    • 3. 相关代码

1. RrcSetupRequest介绍

Rrc setup Request消息由UE发起,携带RRC建立原因和UE标识,用于UE向gNB请求建立RRC 连接,传输信道为CCCH。

1.1 发起目的

  • 建立SRB1无线承载
  • 发送NAS消息

1.2 信令内容抓包

在这里插入图片描述

信令抓包
  • ue-Identity为终端标识,类型为randomValue
  • randomValue是长度为39bit的随机值
  • establishmentCause为建立原因mo-Signalling,常见的有mt-Access、mo-Signalling以及mo-Data三种原因。

1.3 gNB回复

gNB进行准入判断,若允许UE接入,回复RRC Connection Setup继续接入流程;若不允许,回复RRC Connection Reject拒绝接入


2. RrcSetupRequest解析处理流程

OAI 调用nr_rrc_gNB_decode_ccch()函数解码CCCH pdu,其解码rrcSetupRequest流程如下:
在这里插入图片描述

rrcSetupRequest处理流程
  1. 对于主函数传过来的buffer,调用uper_decode()进行per解码,获得消息ID为rrcSetupRequest。
  2. 根据rnti查找UE上下文rrc_gNB_get_ue_context(),如果能够找到上下文,说明该rnti已经注册,释放掉该UE上下文rrc_gNB_free_mem_UE_context();一般正常情况UE是初次接入,rnti也是唯一的,在上下文中是无法查找到的。
  3. 对ue_Identity类型进行判断,分三种情况:
  • ue_Identity为NR_InitialUE_Identity_PR_randomValue ,即随机值,长度为39bit;
  • ue_Identity为NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1 ,5G_S_TMSI长度为48bit,Part1为前39bit。
  • 以上两种均不是。
  1. 对于randomValue或者5G_S_TMSI_Part1,将为该UE创建上下文rrc_gNB_get_next_free_ue_context(),然后生成RRCSetup回复UE,调用函数rrc_gNB_generate_RRCSetup()。
  2. 对于无法识别类型的ue_Identity,将为该UE创建上下文rrc_gNB_get_next_free_ue_context(),然后生成RRCReject拒绝该UE接入,调用函数rrc_gNB_generate_RRCReject()。

3. 相关代码

      switch (ul_ccch_msg->message.choice.c1->present) {
      case NR_UL_CCCH_MessageType__c1_PR_rrcSetupRequest:
        LOG_D(NR_RRC, "Received RRCSetupRequest on UL-CCCH-Message (UE rnti %x)n", ctxt_pP->rnti);
        ue_context_p = rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti);
        if (ue_context_p != NULL) {
          rrc_gNB_free_mem_UE_context(ctxt_pP, ue_context_p);
          MSC_LOG_RX_DISCARDED_MESSAGE(
              MSC_RRC_GNB,
              MSC_RRC_UE,
              buffer,
              dec_rval.consumed,
              MSC_AS_TIME_FMT" NR_RRCSetupRequest UE %x size %u (UE already in context)",
              MSC_AS_TIME_ARGS(ctxt_pP),
              ue_context_p->ue_context.rnti,
              dec_rval.consumed);
        } else {
          rrcSetupRequest = &ul_ccch_msg->message.choice.c1->choice.rrcSetupRequest->rrcSetupRequest;
          if (NR_InitialUE_Identity_PR_randomValue == rrcSetupRequest->ue_Identity.present) {
            /* randomValue                         BIT STRING (SIZE (39)) */
            if (rrcSetupRequest->ue_Identity.choice.randomValue.size != 5) { // 39-bit random value
              LOG_E(NR_RRC, "wrong InitialUE-Identity randomValue size, expected 5, provided %lu",
                          (long unsigned int)rrcSetupRequest->ue_Identity.choice.randomValue.size);
              return -1;
            }

            memcpy(((uint8_t *) & random_value) + 3,
                    rrcSetupRequest->ue_Identity.choice.randomValue.buf,
                    rrcSetupRequest->ue_Identity.choice.randomValue.size);

            /* if there is already a registered UE (with another RNTI) with this random_value,
            * the current one must be removed from MAC/PHY (zombie UE)
            */
            if ((ue_context_p = rrc_gNB_ue_context_random_exist(RC.nrrrc[ctxt_pP->module_id], random_value))) {
              LOG_W(NR_RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHYn",
                      ctxt_pP->rnti, ue_context_p->ue_context.rnti, ue_context_p->ue_context.rnti);
              ue_context_p->ue_context.ul_failure_timer = 20000;
            }

            ue_context_p = rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], random_value);
            ue_context_p->ue_context.Srb0.Srb_id = 0;
            ue_context_p->ue_context.Srb0.Active = 1;
            memcpy(ue_context_p->ue_context.Srb0.Rx_buffer.Payload,
                    buffer,
                    buffer_length);
            ue_context_p->ue_context.Srb0.Rx_buffer.payload_size = buffer_length;
          } else if (NR_InitialUE_Identity_PR_ng_5G_S_TMSI_Part1 == rrcSetupRequest->ue_Identity.present) {
            /* TODO */
            /*  =  48-bit */
            /* ng-5G-S-TMSI-Part1                  BIT STRING (SIZE (39)) */
            if (rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.size != 5) {
              LOG_E(NR_RRC, "wrong ng_5G_S_TMSI_Part1 size, expected 5, provided %lu n",
                          (long unsigned int)rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1.size);
              return -1;
            }

            uint64_t s_tmsi_part1 = bitStr_to_uint64(&rrcSetupRequest->ue_Identity.choice.ng_5G_S_TMSI_Part1);
            if ((ue_context_p = rrc_gNB_ue_context_5g_s_tmsi_exist(RC.nrrrc[ctxt_pP->module_id], s_tmsi_part1))) {
              LOG_I(NR_RRC, " 5G-S-TMSI-Part1 exists, ue_context_p %p, old rnti %x => %xn",ue_context_p, ue_context_p->ue_context.rnti, ctxt_pP->rnti);

              nr_rrc_mac_remove_ue(ctxt_pP->module_id, ue_context_p->ue_context.rnti);
              RB_REMOVE(rrc_nr_ue_tree_s, &RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head, ue_context_p);
              /* and insert again, after changing rnti everywhere it has to be changed */
              ue_context_p->ue_id_rnti = ctxt_pP->rnti;
              ue_context_p->ue_context.rnti = ctxt_pP->rnti;
              RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[ctxt_pP->module_id]->rrc_ue_head, ue_context_p);
              /* reset timers */
              ue_context_p->ue_context.ul_failure_timer = 0;
              ue_context_p->ue_context.ue_release_timer = 0;
              ue_context_p->ue_context.ue_reestablishment_timer = 0;
              ue_context_p->ue_context.ue_release_timer_s1 = 0;
              ue_context_p->ue_context.ue_release_timer_rrc = 0;
            } else {
              LOG_I(NR_RRC, " 5G-S-TMSI-Part1 doesn't exist, setting ng_5G_S_TMSI_Part1 to %p => %ldn",
                              ue_context_p, s_tmsi_part1);

              ue_context_p = rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], s_tmsi_part1);

              if (ue_context_p == NULL) {
                  LOG_E(RRC, "%s:%d:%s: rrc_gNB_get_next_free_ue_context returned NULLn", __FILE__, __LINE__, __FUNCTION__);
              }

              if (ue_context_p != NULL) {
                ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence = TRUE;
                ue_context_p->ue_context.ng_5G_S_TMSI_Part1 = s_tmsi_part1;
              }
            }
          } else {
            memcpy(((uint8_t *) & random_value) + 3,
                    rrcSetupRequest->ue_Identity.choice.randomValue.buf,
                    rrcSetupRequest->ue_Identity.choice.randomValue.size);

            rrc_gNB_get_next_free_ue_context(ctxt_pP, RC.nrrrc[ctxt_pP->module_id], random_value);
            LOG_E(NR_RRC,
                    PROTOCOL_NR_RRC_CTXT_UE_FMT" RRCSetupRequest without random UE identity or S-TMSI not supported, let's reject the UEn",
                    PROTOCOL_NR_RRC_CTXT_UE_ARGS(ctxt_pP));
            rrc_gNB_generate_RRCReject(ctxt_pP,
                                       rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti),
                                       CC_id);
            break;
          }

          ue_context_p->ue_context.establishment_cause = rrcSetupRequest->establishmentCause;

          rrc_gNB_generate_RRCSetup(ctxt_pP,
                                    rrc_gNB_get_ue_context(gnb_rrc_inst, ctxt_pP->rnti),
                                    du_to_cu_rrc_container,
                                    gnb_rrc_inst->carrier.servingcellconfigcommon,
                                    CC_id);
        }
        break;
      }