rrc_UE.c 94.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23 24 25 26 27 28 29 30
/* \file rrc_UE.c
 * \brief RRC procedures
 * \author R. Knopp, K.H. HSU
 * \date 2018
 * \version 0.1
 * \company Eurecom / NTUST
 * \email: knopp@eurecom.fr, kai-hsiang.hsu@eurecom.fr
 * \note
 * \warning
31 32 33 34 35
 */

#define RRC_UE
#define RRC_UE_C

36 37 38 39 40 41
#include "NR_DL-DCCH-Message.h"        //asn_DEF_NR_DL_DCCH_Message
#include "NR_DL-CCCH-Message.h"        //asn_DEF_NR_DL_CCCH_Message
#include "NR_BCCH-BCH-Message.h"       //asn_DEF_NR_BCCH_BCH_Message
#include "NR_BCCH-DL-SCH-Message.h"    //asn_DEF_NR_BCCH_DL_SCH_Message
#include "NR_CellGroupConfig.h"        //asn_DEF_NR_CellGroupConfig
#include "NR_BWP-Downlink.h"           //asn_DEF_NR_BWP_Downlink
42 43
#include "NR_RRCReconfiguration.h"
#include "NR_MeasConfig.h"
Xue Song's avatar
Xue Song committed
44
#include "NR_UL-DCCH-Message.h"
45 46
#include "uper_encoder.h"
#include "uper_decoder.h"
47

48 49
#include "rrc_defs.h"
#include "rrc_proto.h"
50
#include "LAYER2/NR_MAC_UE/mac_proto.h"
51

52 53
#include "intertask_interface.h"

54
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
55
#include "nr-uesoftmodem.h"
yaojie's avatar
yaojie committed
56
#include "plmn_data.h"
57
#include "nr_pdcp/nr_pdcp_oai_api.h"
mir's avatar
mir committed
58 59 60
#include "openair3/SECU/secu_defs.h"
#include "openair3/SECU/key_nas_deriver.h"

yaojie's avatar
yaojie committed
61 62
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
Xue Song's avatar
Xue Song committed
63

yaojie's avatar
yaojie committed
64 65 66 67 68 69 70 71
#ifndef CELLULAR
  #include "RRC/NR/MESSAGES/asn1_msg.h"
#endif

#include "RRC/NAS/nas_config.h"
#include "RRC/NAS/rb_config.h"
#include "SIMULATION/TOOLS/sim.h" // for taus

72
#include "nr_nas_msg_sim.h"
73
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
74

Laurent THOMAS's avatar
Laurent THOMAS committed
75
static NR_UE_RRC_INST_t *NR_UE_rrc_inst;
yaojie's avatar
yaojie committed
76
/* NAS Attach request with IMSI */
Laurent THOMAS's avatar
Laurent THOMAS committed
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
static const char nr_nas_attach_req_imsi_dummy_NSA_case[] = {
    0x07,
    0x41,
    /* EPS Mobile identity = IMSI */
    0x71,
    0x08,
    0x29,
    0x80,
    0x43,
    0x21,
    0x43,
    0x65,
    0x87,
    0xF9,
    /* End of EPS Mobile Identity */
    0x02,
    0xE0,
    0xE0,
    0x00,
    0x20,
    0x02,
    0x03,
    0xD0,
    0x11,
    0x27,
    0x1A,
    0x80,
    0x80,
    0x21,
    0x10,
    0x01,
    0x00,
    0x00,
    0x10,
    0x81,
    0x06,
    0x00,
    0x00,
    0x00,
    0x00,
    0x83,
    0x06,
    0x00,
    0x00,
    0x00,
    0x00,
    0x00,
    0x0D,
    0x00,
    0x00,
    0x0A,
    0x00,
    0x52,
    0x12,
    0xF2,
    0x01,
    0x27,
    0x11,
yaojie's avatar
yaojie committed
135 136
};

137 138
static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
                                      const NR_CellGroupConfig_t *cellGroupConfig);
Laurent THOMAS's avatar
Laurent THOMAS committed
139 140 141

static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
                                                NR_RadioBearerConfig_t *const radioBearerConfig);
142
static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc, const NR_RRCReestablishment_t *rrcReestablishment);
Laurent THOMAS's avatar
Laurent THOMAS committed
143
static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len);
144
static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
145 146 147 148
                                                 int gNB_index,
                                                 NR_RRCReconfiguration_t *rrcReconfiguration);

static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry);
149
static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
150 151 152
                                              OCTET_STRING_t *masterCellGroup,
                                              long *fullConfig);

153
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers);
154

155 156 157 158 159 160 161 162 163 164 165 166
static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id)
{
  AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
  return rrc->status_DRBs[drb_id - 1];
}

static void set_DRB_status(NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id, NR_RB_status_t status)
{
  AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
  rrc->status_DRBs[drb_id - 1] = status;
}

167
static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
168 169
                                                 int gNB_index,
                                                 NR_RRCReconfiguration_t *rrcReconfiguration)
170
{
171
  rrcPerNB_t *rrcNB = rrc->perNB + gNB_index;
Laurent THOMAS's avatar
Laurent THOMAS committed
172 173 174 175 176 177 178

  switch (rrcReconfiguration->criticalExtensions.present) {
    case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: {
      NR_RRCReconfiguration_IEs_t *ie = rrcReconfiguration->criticalExtensions.choice.rrcReconfiguration;

      if (ie->radioBearerConfig != NULL) {
        LOG_I(NR_RRC, "radio Bearer Configuration is present\n");
179
        nr_rrc_ue_process_RadioBearerConfig(rrc, ie->radioBearerConfig);
Laurent THOMAS's avatar
Laurent THOMAS committed
180 181 182 183 184 185 186
        if (LOG_DEBUGFLAG(DEBUG_ASN1))
          xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)ie->radioBearerConfig);
      }

      if (ie->nonCriticalExtension) {
        NR_RRCReconfiguration_v1530_IEs_t *ext = ie->nonCriticalExtension;
        if (ext->masterCellGroup)
187
          nr_rrc_ue_process_masterCellGroup(rrc, ext->masterCellGroup, ext->fullConfig);
Laurent THOMAS's avatar
Laurent THOMAS committed
188 189 190 191 192 193 194 195 196
        /* Check if there is dedicated NAS information to forward to NAS */
        if (ie->nonCriticalExtension->dedicatedNAS_MessageList) {
          struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *tmp = ext->dedicatedNAS_MessageList;
          for (int i = 0; i < tmp->list.count; i++) {
            MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_CONN_ESTABLI_CNF);
            NasConnEstabCnf *msg = &NAS_CONN_ESTABLI_CNF(ittiMsg);
            msg->errCode = AS_SUCCESS;
            msg->nasMsg.length = tmp->list.array[i]->size;
            msg->nasMsg.data = tmp->list.array[i]->buf;
197
            itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg);
198
          }
Laurent THOMAS's avatar
Laurent THOMAS committed
199
          tmp->list.count = 0; // to prevent the automatic free by ASN1_FREE
200 201
        }
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
202 203

      if (ie->secondaryCellGroup != NULL) {
204
        NR_CellGroupConfig_t *cellGroupConfig = NULL;
Laurent THOMAS's avatar
Laurent THOMAS committed
205 206
        asn_dec_rval_t dec_rval = uper_decode(NULL,
                                              &asn_DEF_NR_CellGroupConfig, // might be added prefix later
207
                                              (void **)&cellGroupConfig,
Laurent THOMAS's avatar
Laurent THOMAS committed
208 209 210 211
                                              (uint8_t *)ie->secondaryCellGroup->buf,
                                              ie->secondaryCellGroup->size,
                                              0,
                                              0);
212
        if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
Laurent THOMAS's avatar
Laurent THOMAS committed
213
          uint8_t *buffer = ie->secondaryCellGroup->buf;
214
          LOG_E(NR_RRC, "NR_CellGroupConfig decode error\n");
Laurent THOMAS's avatar
Laurent THOMAS committed
215
          for (int i = 0; i < ie->secondaryCellGroup->size; i++)
216 217 218
            LOG_E(NR_RRC, "%02x ", buffer[i]);
          LOG_E(NR_RRC, "\n");
          // free the memory
219
          SEQUENCE_free(&asn_DEF_NR_CellGroupConfig, (void *)cellGroupConfig, 1);
220
        }
221

Laurent THOMAS's avatar
Laurent THOMAS committed
222
        if (LOG_DEBUGFLAG(DEBUG_ASN1))
223
          xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig);
224

225
        nr_rrc_cellgroup_configuration(rrc, cellGroupConfig);
226

227
        AssertFatal(!get_softmodem_params()->sa, "secondaryCellGroup only used in NSA for now\n");
228
        nr_rrc_mac_config_req_cg(0, 0, cellGroupConfig, rrc->UECap.UE_NR_Capability);
229
        asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, cellGroupConfig);
230
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
231 232
      if (ie->measConfig != NULL) {
        LOG_I(NR_RRC, "Measurement Configuration is present\n");
233
        nr_rrc_ue_process_measConfig(rrcNB, ie->measConfig, &rrc->timers_and_constants);
234
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
235
      if (ie->lateNonCriticalExtension != NULL) {
236 237
        //  unuse now
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
238 239
    } break;

240 241 242 243 244
    case NR_RRCReconfiguration__criticalExtensions_PR_NOTHING:
    case NR_RRCReconfiguration__criticalExtensions_PR_criticalExtensionsFuture:
    default:
      break;
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
245
  return;
246 247
}

248
void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len)
249
{
250
  switch (nsa_message_type) {
francescomani's avatar
francescomani committed
251 252 253 254 255 256 257 258 259 260 261 262
    case nr_SecondaryCellGroupConfig_r15: {
      NR_RRCReconfiguration_t *RRCReconfiguration=NULL;
      asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                     &asn_DEF_NR_RRCReconfiguration,
                                                     (void **)&RRCReconfiguration,
                                                     (uint8_t *)message,
                                                     msg_len);
      if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
        LOG_E(NR_RRC, "NR_RRCReconfiguration decode error\n");
        // free the memory
        SEQUENCE_free( &asn_DEF_NR_RRCReconfiguration, RRCReconfiguration, 1 );
        return;
263
      }
francescomani's avatar
francescomani committed
264 265 266 267
      nr_rrc_ue_process_rrcReconfiguration(rrc, 0, RRCReconfiguration);
      ASN_STRUCT_FREE(asn_DEF_NR_RRCReconfiguration, RRCReconfiguration);
    }
    break;
rmagueta's avatar
rmagueta committed
268
    
francescomani's avatar
francescomani committed
269 270 271 272 273 274 275 276 277 278 279 280
    case nr_RadioBearerConfigX_r15: {
      NR_RadioBearerConfig_t *RadioBearerConfig=NULL;
      asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                     &asn_DEF_NR_RadioBearerConfig,
                                                     (void **)&RadioBearerConfig,
                                                     (uint8_t *)message,
                                                     msg_len);
      if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
        LOG_E(NR_RRC, "NR_RadioBearerConfig decode error\n");
        // free the memory
        SEQUENCE_free( &asn_DEF_NR_RadioBearerConfig, RadioBearerConfig, 1 );
        return;
281
      }
francescomani's avatar
francescomani committed
282 283 284 285 286 287 288 289 290 291 292
      LOG_D(NR_RRC, "Calling nr_rrc_ue_process_RadioBearerConfig()with: e_rab_id = %ld, drbID = %ld, cipher_algo = %ld, key = %ld \n",
            RadioBearerConfig->drb_ToAddModList->list.array[0]->cnAssociation->choice.eps_BearerIdentity,
            RadioBearerConfig->drb_ToAddModList->list.array[0]->drb_Identity,
            RadioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm,
            *RadioBearerConfig->securityConfig->keyToUse);
      nr_rrc_ue_process_RadioBearerConfig(rrc, RadioBearerConfig);
      if (LOG_DEBUGFLAG(DEBUG_ASN1))
        xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)RadioBearerConfig);
      ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, RadioBearerConfig);
    }
    break;
rmagueta's avatar
rmagueta committed
293
    
294 295 296 297 298 299
    default:
      AssertFatal(1==0,"Unknown message %d\n",nsa_message_type);
      break;
  }
}

300
NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst)
301
{
302 303 304 305 306 307 308 309
  NR_UE_rrc_inst = (NR_UE_RRC_INST_t *)calloc(nb_inst, sizeof(NR_UE_RRC_INST_t));
  AssertFatal(NR_UE_rrc_inst, "Couldn't allocate %d instances of RRC module\n", nb_inst);

  for(int nr_ue = 0; nr_ue < nb_inst; nr_ue++) {
    NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[nr_ue];
    rrc->ue_id = nr_ue;
    // fill UE-NR-Capability @ UE-CapabilityRAT-Container here.
    rrc->selected_plmn_identity = 1;
310
    rrc->ra_trigger = RA_NOT_RUNNING;
311 312 313
    rrc->dl_bwp_id = 0;
    rrc->ul_bwp_id = 0;
    rrc->as_security_activated = false;
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

    FILE *f = NULL;
    if (uecap_file)
      f = fopen(uecap_file, "r");
    if(f) {
      char UE_NR_Capability_xer[65536];
      size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f);
      if (size == 0 || size == sizeof UE_NR_Capability_xer) {
        LOG_E(NR_RRC, "UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size);
      }
      else {
        asn_dec_rval_t dec_rval =
            xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&rrc->UECap.UE_NR_Capability, UE_NR_Capability_xer, size);
        assert(dec_rval.code == RC_OK);
      }
    }
330

331
    memset(&rrc->timers_and_constants, 0, sizeof(rrc->timers_and_constants));
332
    set_default_timers_and_constants(&rrc->timers_and_constants);
333

334 335
    for (int j = 0; j < NR_NUM_SRB; j++)
      rrc->Srb[j] = RB_NOT_PRESENT;
336 337
    for (int j = 1; j <= MAX_DRBS_PER_UE; j++)
      set_DRB_status(rrc, j, RB_NOT_PRESENT);
338 339 340 341 342
    // SRB0 activated by default
    rrc->Srb[0] = RB_ESTABLISHED;
    for (int j = 0; j < NR_MAX_NUM_LCID; j++)
      rrc->active_RLC_entity[j] = false;

343 344 345
    for (int i = 0; i < NB_CNX_UE; i++) {
      rrcPerNB_t *ptr = &rrc->perNB[i];
      ptr->SInfo = (NR_UE_RRC_SI_INFO){0};
346
      init_SI_timers(&ptr->SInfo);
347
    }
348

349
    init_sidelink(rrc);
350
  }
351

352
  return NR_UE_rrc_inst;
353 354
}

355 356 357 358
bool check_si_validity(NR_UE_RRC_SI_INFO *SI_info, int si_type)
{
  switch (si_type) {
    case NR_SIB_TypeInfo__type_sibType2:
359
      if (!SI_info->sib2)
360
        return false;
francescomani's avatar
francescomani committed
361
      break;
362
    case NR_SIB_TypeInfo__type_sibType3:
363
      if (!SI_info->sib3)
364
        return false;
francescomani's avatar
francescomani committed
365
      break;
366
    case NR_SIB_TypeInfo__type_sibType4:
367
      if (!SI_info->sib4)
368
        return false;
francescomani's avatar
francescomani committed
369
      break;
370
    case NR_SIB_TypeInfo__type_sibType5:
371
      if (!SI_info->sib5)
372
        return false;
francescomani's avatar
francescomani committed
373
      break;
374
    case NR_SIB_TypeInfo__type_sibType6:
375
      if (!SI_info->sib6)
376
        return false;
francescomani's avatar
francescomani committed
377
      break;
378
    case NR_SIB_TypeInfo__type_sibType7:
379
      if (!SI_info->sib7)
380
        return false;
francescomani's avatar
francescomani committed
381
      break;
382
    case NR_SIB_TypeInfo__type_sibType8:
383
      if (!SI_info->sib8)
384
        return false;
francescomani's avatar
francescomani committed
385
      break;
386
    case NR_SIB_TypeInfo__type_sibType9:
387
      if (!SI_info->sib9)
388
        return false;
francescomani's avatar
francescomani committed
389
      break;
390
    case NR_SIB_TypeInfo__type_sibType10_v1610:
391
      if (!SI_info->sib10)
392
        return false;
francescomani's avatar
francescomani committed
393
      break;
394
    case NR_SIB_TypeInfo__type_sibType11_v1610:
395
      if (!SI_info->sib11)
396
        return false;
francescomani's avatar
francescomani committed
397
      break;
398
    case NR_SIB_TypeInfo__type_sibType12_v1610:
399
      if (!SI_info->sib12)
400
        return false;
francescomani's avatar
francescomani committed
401
      break;
402
    case NR_SIB_TypeInfo__type_sibType13_v1610:
403
      if (!SI_info->sib13)
404
        return false;
francescomani's avatar
francescomani committed
405
      break;
406
    case NR_SIB_TypeInfo__type_sibType14_v1610:
407
      if (!SI_info->sib14)
408
        return false;
francescomani's avatar
francescomani committed
409
      break;
410 411 412 413 414 415
    default :
      AssertFatal(false, "Invalid SIB type %d\n", si_type);
  }
  return true;
}

416 417
int check_si_status(NR_UE_RRC_SI_INFO *SI_info)
{
418
  // schedule reception of SIB1 if RRC doesn't have it
419
  if (!SI_info->sib1)
420 421
    return 1;
  else {
422 423 424 425 426 427 428 429 430 431 432 433 434 435
    if (SI_info->sib1->si_SchedulingInfo) {
      // Check if RRC has configured default SI
      // from SIB2 to SIB14 as current ASN1 version
      // TODO can be used for on demand SI when (if) implemented
      for (int i = 2; i < 15; i++) {
        int si_index = i - 2;
        if ((SI_info->default_otherSI_map >> si_index) & 0x01) {
          // if RRC has no valid version of one of the default configured SI
          // Then schedule reception of otherSI
          if (!check_si_validity(SI_info, si_index))
            return 2;
        }
      }
    }
436 437 438 439
  }
  return 0;
}

440
/*brief decode BCCH-BCH (MIB) message*/
441
static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
442
                                                 const uint8_t gNB_index,
443
                                                 const uint32_t phycellid,
444
                                                 const long ssb_arfcn,
Laurent THOMAS's avatar
Laurent THOMAS committed
445 446
                                                 uint8_t *const bufferP,
                                                 const uint8_t buffer_len)
Sakthivel Velumani's avatar
Sakthivel Velumani committed
447
{
448
  NR_BCCH_BCH_Message_t *bcch_message = NULL;
449
  rrc->phyCellID = phycellid;
450
  rrc->arfcn_ssb = ssb_arfcn;
451

452 453 454 455 456
  asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                 &asn_DEF_NR_BCCH_BCH_Message,
                                                 (void **)&bcch_message,
                                                 (const void *)bufferP,
                                                 buffer_len);
457 458

  if ((dec_rval.code != RC_OK) || (dec_rval.consumed == 0)) {
Sakthivel Velumani's avatar
Sakthivel Velumani committed
459
    LOG_E(NR_RRC, "NR_BCCH_BCH decode error\n");
Laurent THOMAS's avatar
Laurent THOMAS committed
460 461 462
    return;
  }

463 464 465 466 467 468
  // Actions following cell selection while T311 is running
  NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
  if (is_nr_timer_active(timers->T311)) {
    nr_timer_stop(&timers->T311);
    rrc->ra_trigger = RRC_CONNECTION_REESTABLISHMENT;

469 470 471 472 473 474 475 476 477
    // preparing MSG3 for re-establishment in advance
    uint8_t buffer[1024];
    int buf_size = do_RRCReestablishmentRequest(buffer,
                                                rrc->reestablishment_cause,
                                                rrc->phyCellID,
                                                rrc->rnti); // old rnti

    nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buffer, buf_size);

478 479 480 481 482 483 484
    // apply the default MAC Cell Group configuration
    // (done at MAC by calling nr_ue_mac_default_configs)

    // apply the timeAlignmentTimerCommon included in SIB1
    // not used
  }

Laurent THOMAS's avatar
Laurent THOMAS committed
485
  int get_sib = 0;
486 487
  if (get_softmodem_params()->sa &&
      bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred &&
488 489
      rrc->nrRrcState != RRC_STATE_DETACH_NR) {
    NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo;
Laurent THOMAS's avatar
Laurent THOMAS committed
490 491
    // to schedule MAC to get SI if required
    get_sib = check_si_status(SI_info);
492
  }
493
  nr_rrc_mac_config_req_mib(rrc->ue_id, 0, bcch_message->message.choice.mib, get_sib);
494
  ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, bcch_message);
Laurent THOMAS's avatar
Laurent THOMAS committed
495
  return;
496 497
}

Laurent THOMAS's avatar
Laurent THOMAS committed
498
static int nr_decode_SI(NR_UE_RRC_SI_INFO *SI_info, NR_SystemInformation_t *si)
499
{
yaojie's avatar
yaojie committed
500 501 502
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_IN );

  // Dump contents
503 504 505 506
  if (si->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_systemInformation ||
      si->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_criticalExtensionsFuture_r16) {
    LOG_D( RRC, "[UE] si->criticalExtensions.choice.NR_SystemInformation_t->sib_TypeAndInfo.list.count %d\n",
           si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count );
yaojie's avatar
yaojie committed
507 508 509 510 511
  } else {
    LOG_D( RRC, "[UE] Unknown criticalExtension version (not Rel16)\n" );
    return -1;
  }

512
  for (int i = 0; i < si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) {
yaojie's avatar
yaojie committed
513
    SystemInformation_IEs__sib_TypeAndInfo__Member *typeandinfo;
514
    typeandinfo = si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i];
Laurent THOMAS's avatar
Laurent THOMAS committed
515
    LOG_I(RRC, "Found SIB%d\n", typeandinfo->present + 1);
yaojie's avatar
yaojie committed
516 517
    switch(typeandinfo->present) {
      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2:
518 519 520
        if(!SI_info->sib2)
          SI_info->sib2 = calloc(1, sizeof(*SI_info->sib2));
        memcpy(SI_info->sib2, typeandinfo->choice.sib2, sizeof(NR_SIB2_t));
521
        nr_timer_start(&SI_info->sib2_timer);
Laurent THOMAS's avatar
Laurent THOMAS committed
522
        break;
yaojie's avatar
yaojie committed
523 524

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3:
525 526 527
        if(!SI_info->sib3)
          SI_info->sib3 = calloc(1, sizeof(*SI_info->sib3));
        memcpy(SI_info->sib3, typeandinfo->choice.sib3, sizeof(NR_SIB3_t));
528
        nr_timer_start(&SI_info->sib3_timer);
yaojie's avatar
yaojie committed
529 530 531
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4:
532 533
        if(!SI_info->sib4)
          SI_info->sib4 = calloc(1, sizeof(*SI_info->sib4));
534
        memcpy(SI_info->sib4, typeandinfo->choice.sib4, sizeof(NR_SIB4_t));
535
        nr_timer_start(&SI_info->sib4_timer);
yaojie's avatar
yaojie committed
536 537 538
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5:
539 540
        if(!SI_info->sib5)
          SI_info->sib5 = calloc(1, sizeof(*SI_info->sib5));
541
        memcpy(SI_info->sib5, typeandinfo->choice.sib5, sizeof(NR_SIB5_t));
542
        nr_timer_start(&SI_info->sib5_timer);
yaojie's avatar
yaojie committed
543 544 545
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6:
546 547
        if(!SI_info->sib6)
          SI_info->sib6 = calloc(1, sizeof(*SI_info->sib6));
548
        memcpy(SI_info->sib6, typeandinfo->choice.sib6, sizeof(NR_SIB6_t));
549
        nr_timer_start(&SI_info->sib6_timer);
yaojie's avatar
yaojie committed
550 551 552
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7:
553 554
        if(!SI_info->sib7)
          SI_info->sib7 = calloc(1, sizeof(*SI_info->sib7));
555
        memcpy(SI_info->sib7, typeandinfo->choice.sib7, sizeof(NR_SIB7_t));
556
        nr_timer_start(&SI_info->sib7_timer);
yaojie's avatar
yaojie committed
557 558 559
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8:
560 561
        if(!SI_info->sib8)
          SI_info->sib8 = calloc(1, sizeof(*SI_info->sib8));
562
        memcpy(SI_info->sib8, typeandinfo->choice.sib8, sizeof(NR_SIB8_t));
563
        nr_timer_start(&SI_info->sib8_timer);
yaojie's avatar
yaojie committed
564 565 566
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9:
567 568
        if(!SI_info->sib9)
          SI_info->sib9 = calloc(1, sizeof(*SI_info->sib9));
569
        memcpy(SI_info->sib9, typeandinfo->choice.sib9, sizeof(NR_SIB9_t));
570
        nr_timer_start(&SI_info->sib9_timer);
yaojie's avatar
yaojie committed
571 572 573
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610:
574 575
        if(!SI_info->sib10)
          SI_info->sib10 = calloc(1, sizeof(*SI_info->sib10));
576
        memcpy(SI_info->sib10, typeandinfo->choice.sib10_v1610, sizeof(NR_SIB10_r16_t));
577
        nr_timer_start(&SI_info->sib10_timer);
yaojie's avatar
yaojie committed
578 579 580
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610:
581 582
        if(!SI_info->sib11)
          SI_info->sib11 = calloc(1, sizeof(*SI_info->sib11));
583
        memcpy(SI_info->sib11, typeandinfo->choice.sib11_v1610, sizeof(NR_SIB11_r16_t));
584
        nr_timer_start(&SI_info->sib11_timer);
yaojie's avatar
yaojie committed
585 586 587
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610:
588 589
        if(!SI_info->sib12)
          SI_info->sib12 = calloc(1, sizeof(*SI_info->sib12));
590
        memcpy(SI_info->sib12, typeandinfo->choice.sib12_v1610, sizeof(NR_SIB12_r16_t));
591
        nr_timer_start(&SI_info->sib12_timer);
yaojie's avatar
yaojie committed
592 593 594
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610:
595 596
        if(!SI_info->sib13)
          SI_info->sib13 = calloc(1, sizeof(*SI_info->sib13));
597
        memcpy(SI_info->sib13, typeandinfo->choice.sib13_v1610, sizeof(NR_SIB13_r16_t));
598
        nr_timer_start(&SI_info->sib13_timer);
yaojie's avatar
yaojie committed
599 600 601
        break;

      case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610:
602 603 604
        if(!SI_info->sib14)
          SI_info->sib14 = calloc(1, sizeof(*SI_info->sib14));
        memcpy(SI_info->sib12, typeandinfo->choice.sib14_v1610, sizeof(NR_SIB14_r16_t));
605
        nr_timer_start(&SI_info->sib14_timer);
Laurent THOMAS's avatar
Laurent THOMAS committed
606
        break;
yaojie's avatar
yaojie committed
607 608 609 610 611
      default:
        break;
    }
  }
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_UE_DECODE_SI, VCD_FUNCTION_OUT);
612 613 614
  return 0;
}

615
static void nr_rrc_handle_msg3_indication(NR_UE_RRC_INST_t *rrc, rnti_t rnti)
francescomani's avatar
francescomani committed
616
{
617
  NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
618
  switch (rrc->ra_trigger) {
619
    case RRC_CONNECTION_SETUP:
620
      // After SIB1 is received, prepare RRCConnectionRequest
621
      rrc->rnti = rnti;
622
      // start timer T300
623
      nr_timer_start(&tac->T300);
624 625
      break;
    case RRC_CONNECTION_REESTABLISHMENT:
626 627 628 629 630 631 632 633 634 635
      rrc->rnti = rnti;
      nr_timer_start(&tac->T301);
      int srb_id = 1;
      // re-establish PDCP for SRB1
      nr_pdcp_reestablishment(rrc->ue_id, srb_id, true);
      // re-establish RLC for SRB1
      int lc_id = nr_rlc_get_lcid_from_rb(rrc->ue_id, true, 1);
      nr_rlc_reestablish_entity(rrc->ue_id, lc_id);
      // apply the specified configuration defined in 9.2.1 for SRB1
      nr_rlc_reconfigure_entity(rrc->ue_id, lc_id, NULL);
636 637
      // suspend integrity protection and ciphering for SRB1
      nr_pdcp_config_set_security(rrc->ue_id, srb_id, 0, NULL, NULL, NULL);
638 639
      // resume SRB1
      rrc->Srb[srb_id] = RB_ESTABLISHED;
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
      break;
    case DURING_HANDOVER:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    case NON_SYNCHRONISED:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    case TRANSITION_FROM_RRC_INACTIVE:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    case TO_ESTABLISH_TA:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    case REQUEST_FOR_OTHER_SI:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    case BEAM_FAILURE_RECOVERY:
      AssertFatal(1==0, "ra_trigger not implemented yet!\n");
      break;
    default:
      AssertFatal(1==0, "Invalid ra_trigger value!\n");
      break;
yaojie's avatar
yaojie committed
662
  }
francescomani's avatar
francescomani committed
663
}
yaojie's avatar
yaojie committed
664

665
static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc)
francescomani's avatar
francescomani committed
666
{
francescomani's avatar
francescomani committed
667
  LOG_D(NR_RRC, "Generation of RRCSetupRequest\n");
francescomani's avatar
francescomani committed
668 669 670 671 672 673 674 675 676 677 678 679 680
  uint8_t rv[6];
  // Get RRCConnectionRequest, fill random for now
  // Generate random byte stream for contention resolution
  for (int i = 0; i < 6; i++) {
#ifdef SMBV
    // if SMBV is configured the contention resolution needs to be fix for the connection procedure to succeed
    rv[i] = i;
#else
    rv[i] = taus() & 0xff;
#endif
  }

  uint8_t buf[1024];
Laurent THOMAS's avatar
Laurent THOMAS committed
681
  int len = do_RRCSetupRequest(buf, sizeof(buf), rv);
francescomani's avatar
francescomani committed
682

683
  nr_rlc_srb_recv_sdu(rrc->ue_id, 0, buf, len);
684
}
685

686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info,
                                 NR_SIB1_t *sib1)
{
  struct NR_SI_SchedulingInfo *si_SchedulingInfo = sib1->si_SchedulingInfo;
  if (!si_SchedulingInfo)
    return;
  SI_info->default_otherSI_map = 0;
  for (int i = 0; i < si_SchedulingInfo->schedulingInfoList.list.count; i++) {
    struct NR_SchedulingInfo *schedulingInfo = si_SchedulingInfo->schedulingInfoList.list.array[i];
    for (int j = 0; j < schedulingInfo->sib_MappingInfo.list.count; j++) {
      struct NR_SIB_TypeInfo *sib_Type = schedulingInfo->sib_MappingInfo.list.array[j];
      SI_info->default_otherSI_map |= 1 << sib_Type->type;
    }
  }
}

702
static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc,
laurent's avatar
laurent committed
703 704 705 706 707 708
                                                      const uint8_t gNB_index,
                                                      uint8_t *const Sdu,
                                                      const uint8_t Sdu_len,
                                                      const uint8_t rsrq,
                                                      const uint8_t rsrp)
{
709
  NR_BCCH_DL_SCH_Message_t *bcch_message = NULL;
710

Laurent THOMAS's avatar
Laurent THOMAS committed
711
  NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo;
712
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_IN);
713

714 715 716 717 718
  asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                 &asn_DEF_NR_BCCH_DL_SCH_Message,
                                                 (void **)&bcch_message,
                                                 (const void *)Sdu,
                                                 Sdu_len);
719

720 721
  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
    xer_fprint(stdout, &asn_DEF_NR_BCCH_DL_SCH_Message,(void *)bcch_message);
722 723
  }

724
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
725
    LOG_E(NR_RRC, "[UE %ld] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n", rrc->ue_id, dec_rval.consumed);
726
    log_dump(NR_RRC, Sdu, Sdu_len, LOG_DUMP_CHAR,"   Received bytes:\n");
727
    // free the memory
728
    SEQUENCE_free(&asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1);
729 730 731 732 733 734 735
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
    return -1;
  }

  if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) {
    switch (bcch_message->message.choice.c1->present) {
      case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
736
        LOG_D(NR_RRC, "[UE %ld] Decoding SIB1\n", rrc->ue_id);
737
        asn1cFreeStruc(asn_DEF_NR_SIB1, SI_info->sib1);
738
        NR_SIB1_t *sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
francescomani's avatar
francescomani committed
739 740 741
        if(!SI_info->sib1)
          SI_info->sib1 = calloc(1, sizeof(*SI_info->sib1));
        memcpy(SI_info->sib1, sib1, sizeof(NR_SIB1_t));
742 743 744
        if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG)
          xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) SI_info->sib1);
        LOG_A(NR_RRC, "SIB1 decoded\n");
745
        nr_timer_start(&SI_info->sib1_timer);
Laurent THOMAS's avatar
Laurent THOMAS committed
746
        if (rrc->nrRrcState == RRC_STATE_IDLE_NR) {
747
          rrc->ra_trigger = RRC_CONNECTION_SETUP;
748 749
          // preparing RRC setup request payload in advance
          nr_rrc_ue_prepare_RRCSetupRequest(rrc);
750
        }
751 752
        // configure default SI
        nr_rrc_configure_default_SI(SI_info, sib1);
753
        // configure timers and constant
754
        nr_rrc_set_sib1_timers_and_constants(&rrc->timers_and_constants, sib1);
755
        nr_rrc_mac_config_req_sib1(rrc->ue_id, 0, sib1->si_SchedulingInfo, sib1->servingCellConfigCommon);
756
        break;
757
      case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
758
        LOG_I(NR_RRC, "[UE %ld] Decoding SI\n", rrc->ue_id);
759
        NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation;
760
        nr_decode_SI(SI_info, si);
761
        SEQUENCE_free(&asn_DEF_NR_BCCH_DL_SCH_Message, (void *)bcch_message, 1);
762 763 764 765 766 767 768 769 770
        break;
      case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
      default:
        break;
    }
  }
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT );
  return 0;
}
771

772 773
static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
                                      const NR_CellGroupConfig_t *cellGroupConfig)
774
{
francescomani's avatar
francescomani committed
775
  if (cellGroupConfig->rlc_BearerToReleaseList != NULL) {
776 777 778
    for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) {
      NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i];
      AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n");
779
      nr_rlc_release_entity(rrc->ue_id, *lcid);
780
    }
781 782
  }

francescomani's avatar
francescomani committed
783
  if (cellGroupConfig->rlc_BearerToAddModList != NULL) {
784 785 786
    for (int i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) {
      NR_RLC_BearerConfig_t *rlc_bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[i];
      NR_LogicalChannelIdentity_t lcid = rlc_bearer->logicalChannelIdentity;
787
      if (rrc->active_RLC_entity[lcid]) {
788
        if (rlc_bearer->reestablishRLC)
789
          nr_rlc_reestablish_entity(rrc->ue_id, lcid);
790 791
        if (rlc_bearer->rlc_Config)
          nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config);
francescomani's avatar
francescomani committed
792
      } else {
793
        rrc->active_RLC_entity[lcid] = true;
794 795 796 797 798
        AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n");
        AssertFatal(rlc_bearer->servedRadioBearer->present != NR_RLC_BearerConfig__servedRadioBearer_PR_NOTHING,
                    "Invalid RB for RLC configuration\n");
        if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) {
          NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity;
799
          nr_rlc_add_srb(rrc->ue_id, srb_id, rlc_bearer);
francescomani's avatar
francescomani committed
800
        } else { // DRB
801
          NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity;
802
          nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer);
803 804 805 806 807
        }
      }
    }
  }
}
808

809
void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig)
810 811 812 813 814 815 816
{
  NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;

  NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig;
  if(spCellConfig != NULL) {
    if (spCellConfig->reconfigurationWithSync != NULL) {
      NR_ReconfigurationWithSync_t *reconfigurationWithSync = spCellConfig->reconfigurationWithSync;
817 818 819 820 821
      if (reconfigurationWithSync->spCellConfigCommon &&
          reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon &&
          reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL &&
          reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB)
        rrc->arfcn_ssb = *reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB;
822 823 824 825 826 827
      // perform Reconfiguration with sync according to 5.3.5.5.2
      if (!rrc->as_security_activated && rrc->nrRrcState != RRC_STATE_IDLE_NR) {
        // perform the actions upon going to RRC_IDLE as specified in 5.3.11
        // with the release cause 'other' upon which the procedure ends
        // TODO
      }
828 829 830 831
      nr_timer_stop(&tac->T310);
      int t304_value = nr_rrc_get_T304(reconfigurationWithSync->t304);
      nr_timer_setup(&tac->T304, t304_value, 10); // 10ms step
      nr_timer_start(&tac->T304);
832 833 834
      rrc->rnti = reconfigurationWithSync->newUE_Identity;
      // resume suspended radio bearers
      for (int i = 0; i < NR_NUM_SRB; i++) {
835 836
        if (rrc->Srb[i] == RB_SUSPENDED)
          rrc->Srb[i] = RB_ESTABLISHED;
837
      }
838 839 840
      for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
        if (get_DRB_status(rrc, i) == RB_SUSPENDED)
          set_DRB_status(rrc, i, RB_ESTABLISHED);
841 842 843 844 845 846 847 848 849 850 851 852 853
      }
      // TODO reset MAC
    }
    nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(rrc, spCellConfig->rlf_TimersAndConstants);
    if (spCellConfig->spCellConfigDedicated) {
      if (spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id)
        rrc->dl_bwp_id = *spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id;
      if (spCellConfig->spCellConfigDedicated->uplinkConfig &&
          spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id)
        rrc->dl_bwp_id = *spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id;
    }
  }

854
  nr_rrc_manage_rlc_bearers(rrc, cellGroupConfig);
855 856 857 858 859 860 861 862 863

  AssertFatal(cellGroupConfig->sCellToReleaseList == NULL,
              "Secondary serving cell release not implemented\n");

  AssertFatal(cellGroupConfig->sCellToAddModList == NULL,
              "Secondary serving cell addition not implemented\n");
}


864
static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
865 866
                                              OCTET_STRING_t *masterCellGroup,
                                              long *fullConfig)
yaojie's avatar
yaojie committed
867
{
868
  AssertFatal(!fullConfig, "fullConfig not supported yet\n");
869
  NR_CellGroupConfig_t *cellGroupConfig = NULL;
870
  uper_decode(NULL,
rmagueta's avatar
rmagueta committed
871 872 873 874
              &asn_DEF_NR_CellGroupConfig,   //might be added prefix later
              (void **)&cellGroupConfig,
              (uint8_t *)masterCellGroup->buf,
              masterCellGroup->size, 0, 0);
rmagueta's avatar
rmagueta committed
875

876
  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
rmagueta's avatar
rmagueta committed
877 878
    xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig);
  }
rmagueta's avatar
rmagueta committed
879

880
  nr_rrc_cellgroup_configuration(rrc, cellGroupConfig);
yaojie's avatar
yaojie committed
881

882
  LOG_D(RRC,"Sending CellGroupConfig to MAC\n");
883
  nr_rrc_mac_config_req_cg(rrc->ue_id, 0, cellGroupConfig, rrc->UECap.UE_NR_Capability);
884
  asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, cellGroupConfig);
885 886
}

887
static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id)
888
{
889 890 891 892
  uint8_t buffer[100];
  uint8_t size;
  const char *nas_msg;
  int   nas_msg_length;
893

894 895
  if (get_softmodem_params()->sa) {
    as_nas_info_t initialNasMsg;
896
    nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id);
897
    generateRegistrationRequest(&initialNasMsg, nas);
898 899
    nas_msg = (char*)initialNasMsg.data;
    nas_msg_length = initialNasMsg.length;
900
  } else {
Laurent THOMAS's avatar
Laurent THOMAS committed
901 902
    nas_msg = nr_nas_attach_req_imsi_dummy_NSA_case;
    nas_msg_length = sizeof(nr_nas_attach_req_imsi_dummy_NSA_case);
903
  }
904

905 906
  size = do_RRCSetupComplete(buffer, sizeof(buffer), Transaction_id, rrc->selected_plmn_identity, nas_msg_length, nas_msg);
  LOG_I(NR_RRC, "[UE %ld][RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCSetupComplete (bytes%d)\n", rrc->ue_id, size);
907
  int srb_id = 1; // RRC setup complete on SRB1
908
  LOG_D(NR_RRC, "[RRC_UE %ld] PDCP_DATA_REQ/%d Bytes RRCSetupComplete ---> %d\n", rrc->ue_id, size, srb_id);
909

910
  nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
911 912
}

913
static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc,
914 915 916 917 918
                                    const NR_RRCSetup_t *rrcSetup)
{
  // if the RRCSetup is received in response to an RRCReestablishmentRequest
  // or RRCResumeRequest or RRCResumeRequest1
  // TODO none of the procedures implemented yet
919 920 921 922 923
  if (rrc->ra_trigger == RRC_CONNECTION_REESTABLISHMENT) {
    LOG_E(NR_RRC, "Handling of RRCSetup in response of RRCReestablishment not implemented yet. Going back to IDLE.\n");
    nr_rrc_going_to_IDLE(rrc, OTHER, NULL);
    return;
  }
924 925

  // perform the cell group configuration procedure in accordance with the received masterCellGroup
926
  nr_rrc_ue_process_masterCellGroup(rrc,
927 928 929 930 931 932 933 934 935
                                    &rrcSetup->criticalExtensions.choice.rrcSetup->masterCellGroup,
                                    NULL);
  // perform the radio bearer configuration procedure in accordance with the received radioBearerConfig
  nr_rrc_ue_process_RadioBearerConfig(rrc,
                                      &rrcSetup->criticalExtensions.choice.rrcSetup->radioBearerConfig);

  // TODO (not handled) if stored, discard the cell reselection priority information provided by
  // the cellReselectionPriorities or inherited from another RAT

936
  // stop timer T300, T301, T319, T320 if running;
937
  NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
938 939 940 941
  nr_timer_stop(&timers->T300);
  nr_timer_stop(&timers->T301);
  nr_timer_stop(&timers->T319);
  nr_timer_stop(&timers->T320);
942 943 944 945 946 947 948 949 950

  // TODO if T390 and T302 are running (not implemented)

  // if the RRCSetup is received in response to an RRCResumeRequest, RRCResumeRequest1 or RRCSetupRequest
  // enter RRC_CONNECTED
  rrc->nrRrcState = RRC_STATE_CONNECTED_NR;

  // set the content of RRCSetupComplete message
  // TODO procedues described in 5.3.3.4 seems more complex than what we actualy do
951
  rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier);
952 953
}

954
static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc,
955
                                    const NRRrcMacCcchDataInd *ind)
956
{
957
  NR_DL_CCCH_Message_t *dl_ccch_msg = NULL;
958 959 960
  asn_dec_rval_t dec_rval;
  int rval=0;
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_IN);
961
  LOG_D(RRC, "[NR UE%ld] Decoding DL-CCCH message (%d bytes), State %d\n", rrc->ue_id, ind->sdu_size, rrc->nrRrcState);
francescomani's avatar
francescomani committed
962

Laurent THOMAS's avatar
Laurent THOMAS committed
963
  dec_rval = uper_decode(NULL, &asn_DEF_NR_DL_CCCH_Message, (void **)&dl_ccch_msg, ind->sdu, ind->sdu_size, 0, 0);
francescomani's avatar
francescomani committed
964 965 966 967

  if (LOG_DEBUGFLAG(DEBUG_ASN1))
    xer_fprint(stdout, &asn_DEF_NR_DL_CCCH_Message, (void *)dl_ccch_msg);

Laurent THOMAS's avatar
Laurent THOMAS committed
968
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
969
    LOG_E(RRC, "[UE %ld] Failed to decode DL-CCCH-Message (%zu bytes)\n", rrc->ue_id, dec_rval.consumed);
francescomani's avatar
francescomani committed
970 971
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT);
    return -1;
972
   }
973

974
   if (dl_ccch_msg->message.present == NR_DL_CCCH_MessageType_PR_c1) {
975
     switch (dl_ccch_msg->message.choice.c1->present) {
976
       case NR_DL_CCCH_MessageType__c1_PR_NOTHING:
977
         LOG_I(NR_RRC, "[UE%ld] Received PR_NOTHING on DL-CCCH-Message\n", rrc->ue_id);
Laurent THOMAS's avatar
Laurent THOMAS committed
978 979
         rval = 0;
         break;
980 981

       case NR_DL_CCCH_MessageType__c1_PR_rrcReject:
982
         LOG_I(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id);
Laurent THOMAS's avatar
Laurent THOMAS committed
983 984
         rval = 0;
         break;
985 986

       case NR_DL_CCCH_MessageType__c1_PR_rrcSetup:
987
         LOG_I(NR_RRC, "[UE%ld][RAPROC] Logical Channel DL-CCCH (SRB0), Received NR_RRCSetup\n", rrc->ue_id);
988
         nr_rrc_process_rrcsetup(rrc, dl_ccch_msg->message.choice.c1->choice.rrcSetup);
989 990
         rval = 0;
         break;
991 992

       default:
993
         LOG_E(NR_RRC, "[UE%ld] Unknown message\n", rrc->ue_id);
Laurent THOMAS's avatar
Laurent THOMAS committed
994 995
         rval = -1;
         break;
996 997
     }
   }
998

999
   ASN_STRUCT_FREE(asn_DEF_NR_DL_CCCH_Message, dl_ccch_msg);
1000 1001
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_CCCH, VCD_FUNCTION_OUT);
   return rval;
Laurent THOMAS's avatar
Laurent THOMAS committed
1002
}
1003

Laurent THOMAS's avatar
Laurent THOMAS committed
1004
static void nr_rrc_ue_process_securityModeCommand(NR_UE_RRC_INST_t *ue_rrc,
1005
                                                  NR_SecurityModeCommand_t *const securityModeCommand)
francescomani's avatar
francescomani committed
1006
{
Laurent THOMAS's avatar
Laurent THOMAS committed
1007
  int securityMode = 0;
1008
  LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing securityModeCommand\n");
francescomani's avatar
francescomani committed
1009

Laurent THOMAS's avatar
Laurent THOMAS committed
1010 1011
  NR_SecurityConfigSMC_t *securityConfigSMC =
      &securityModeCommand->criticalExtensions.choice.securityModeCommand->securityConfigSMC;
francescomani's avatar
francescomani committed
1012 1013 1014 1015 1016

  switch (securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm) {
    case NR_CipheringAlgorithm_nea0:
    case NR_CipheringAlgorithm_nea1:
    case NR_CipheringAlgorithm_nea2:
Laurent THOMAS's avatar
Laurent THOMAS committed
1017 1018
      LOG_I(NR_RRC, "Security algorithm is set to nea%d\n", securityMode);
      securityMode = securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm;
francescomani's avatar
francescomani committed
1019 1020
      break;
    default:
Laurent THOMAS's avatar
Laurent THOMAS committed
1021
      LOG_W(NR_RRC, "Security algorithm is set to none\n");
francescomani's avatar
francescomani committed
1022 1023 1024 1025
      securityMode = NR_CipheringAlgorithm_spare1;
      break;
  }
  ue_rrc->cipheringAlgorithm = securityConfigSMC->securityAlgorithmConfig.cipheringAlgorithm;
1026

francescomani's avatar
francescomani committed
1027 1028 1029
  if (securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm != NULL) {
    switch (*securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm) {
      case NR_IntegrityProtAlgorithm_nia1:
Laurent THOMAS's avatar
Laurent THOMAS committed
1030
        LOG_I(NR_RRC, "Integrity protection algorithm is set to nia1\n");
francescomani's avatar
francescomani committed
1031 1032
        securityMode |= 1 << 5;
        break;
1033

francescomani's avatar
francescomani committed
1034
      case NR_IntegrityProtAlgorithm_nia2:
Laurent THOMAS's avatar
Laurent THOMAS committed
1035
        LOG_I(NR_RRC, "Integrity protection algorithm is set to nia2\n");
francescomani's avatar
francescomani committed
1036 1037
        securityMode |= 1 << 6;
        break;
1038

francescomani's avatar
francescomani committed
1039
      default:
Laurent THOMAS's avatar
Laurent THOMAS committed
1040 1041
        LOG_I(NR_RRC, "Integrity protection algorithm is set to none\n");
        securityMode |= 0x70;
francescomani's avatar
francescomani committed
1042 1043
        break;
    }
1044

francescomani's avatar
francescomani committed
1045 1046
    ue_rrc->integrityProtAlgorithm = *securityConfigSMC->securityAlgorithmConfig.integrityProtAlgorithm;
  }
1047

Laurent THOMAS's avatar
Laurent THOMAS committed
1048 1049 1050 1051
  LOG_D(NR_RRC, "security mode is %x \n", securityMode);
  NR_UL_DCCH_Message_t ul_dcch_msg = {0};

  // memset((void *)&SecurityModeCommand,0,sizeof(SecurityModeCommand_t));
francescomani's avatar
francescomani committed
1052
  ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
Laurent THOMAS's avatar
Laurent THOMAS committed
1053
  asn1cCalloc(ul_dcch_msg.message.choice.c1, c1);
1054

francescomani's avatar
francescomani committed
1055 1056
  if (securityMode >= NO_SECURITY_MODE) {
    LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode complete case \n");
Laurent THOMAS's avatar
Laurent THOMAS committed
1057
    c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
francescomani's avatar
francescomani committed
1058 1059
  } else {
    LOG_I(NR_RRC, "rrc_ue_process_securityModeCommand, security mode failure case \n");
Laurent THOMAS's avatar
Laurent THOMAS committed
1060 1061
    c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeFailure;
    c1->present = NR_UL_DCCH_MessageType__c1_PR_securityModeComplete;
francescomani's avatar
francescomani committed
1062 1063
  }

1064 1065 1066
  uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
  uint8_t  kUPenc[NR_K_KEY_SIZE] = {0};
  uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
Laurent THOMAS's avatar
Laurent THOMAS committed
1067 1068 1069
  nr_derive_key(UP_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kUPenc);
  nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc);
  nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint);
francescomani's avatar
francescomani committed
1070

Laurent THOMAS's avatar
Laurent THOMAS committed
1071
  log_dump(NR_RRC, ue_rrc->kgnb, 32, LOG_DUMP_CHAR, "driving kRRCenc, kRRCint and kUPenc from KgNB=");
francescomani's avatar
francescomani committed
1072 1073 1074

  if (securityMode != 0xff) {
    uint8_t security_mode = ue_rrc->cipheringAlgorithm | (ue_rrc->integrityProtAlgorithm << 4);
1075 1076
    // configure lower layers to apply SRB integrity protection and ciphering
    for (int i = 1; i < NR_NUM_SRB; i++) {
1077
      if (ue_rrc->Srb[i] == RB_ESTABLISHED)
1078
        nr_pdcp_config_set_security(ue_rrc->ue_id, i, security_mode, kRRCenc, kRRCint, kUPenc);
1079
    }
francescomani's avatar
francescomani committed
1080 1081 1082
  } else {
    LOG_I(NR_RRC, "skipped pdcp_config_set_security() as securityMode == 0x%02x", securityMode);
  }
Xue Song's avatar
Xue Song committed
1083

francescomani's avatar
francescomani committed
1084
  if (securityModeCommand->criticalExtensions.present == NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1085 1086 1087 1088 1089 1090
    asn1cCalloc(c1->choice.securityModeComplete, modeComplete);
    modeComplete->rrc_TransactionIdentifier = securityModeCommand->rrc_TransactionIdentifier;
    modeComplete->criticalExtensions.present = NR_SecurityModeComplete__criticalExtensions_PR_securityModeComplete;
    asn1cCalloc(modeComplete->criticalExtensions.choice.securityModeComplete, ext);
    ext->nonCriticalExtension = NULL;
    LOG_I(NR_RRC,
1091
          "Receiving from SRB1 (DL-DCCH), encoding securityModeComplete, rrc_TransactionIdentifier: %ld\n",
Laurent THOMAS's avatar
Laurent THOMAS committed
1092 1093 1094 1095 1096
          securityModeCommand->rrc_TransactionIdentifier);
    uint8_t buffer[200];
    asn_enc_rval_t enc_rval =
        uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, sizeof(buffer));
    AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded);
francescomani's avatar
francescomani committed
1097 1098

    if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
1099
      xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
Xue Song's avatar
Xue Song committed
1100
    }
francescomani's avatar
francescomani committed
1101
    log_dump(NR_RRC, buffer, 16, LOG_DUMP_CHAR, "securityModeComplete payload: ");
Laurent THOMAS's avatar
Laurent THOMAS committed
1102 1103
    LOG_D(NR_RRC, "securityModeComplete Encoded %zd bits (%zd bytes)\n", enc_rval.encoded, (enc_rval.encoded + 7) / 8);
    ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NR_UL_DCCH_Message, &ul_dcch_msg);
1104

1105
    for (int i = 0; i < (enc_rval.encoded + 7) / 8; i++) {
francescomani's avatar
francescomani committed
1106 1107 1108
      LOG_T(NR_RRC, "%02x.", buffer[i]);
    }
    LOG_T(NR_RRC, "\n");
1109

Laurent THOMAS's avatar
Laurent THOMAS committed
1110 1111
    // TODO the SecurityModeCommand message needs to pass the integrity protection check
    //  for the UE to declare AS security to be activated
1112
    ue_rrc->as_security_activated = true;
1113
    int srb_id = 1; // SecurityModeComplete in SRB1
1114
    nr_pdcp_data_req_srb(ue_rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
francescomani's avatar
francescomani committed
1115
  } else
Laurent THOMAS's avatar
Laurent THOMAS committed
1116 1117 1118
    LOG_W(NR_RRC,
          "securityModeCommand->criticalExtensions.present (%d) != "
          "NR_SecurityModeCommand__criticalExtensions_PR_securityModeCommand\n",
francescomani's avatar
francescomani committed
1119 1120
          securityModeCommand->criticalExtensions.present);
}
Xue Song's avatar
Xue Song committed
1121

1122
static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers)
Laurent THOMAS's avatar
Laurent THOMAS committed
1123
{
1124 1125 1126 1127 1128 1129
  // remove the measurement reporting entry for this measId if included
  asn1cFreeStruc(asn_DEF_NR_VarMeasReport, rrc->MeasReport[id]);
  // TODO stop the periodical reporting timer or timer T321, whichever is running,
  // and reset the associated information (e.g. timeToTrigger) for this measId
  nr_timer_stop(&timers->T321);
}
1130

1131
static void handle_measobj_remove(rrcPerNB_t *rrc, struct NR_MeasObjectToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers)
Laurent THOMAS's avatar
Laurent THOMAS committed
1132
{
1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
  // section 5.5.2.4 in 38.331
  for (int i = 0; i < remove_list->list.count; i++) {
    // for each measObjectId included in the received measObjectToRemoveList
    // that is part of measObjectList in the configuration
    NR_MeasObjectId_t id = *remove_list->list.array[i];
    if (rrc->MeasObj[id - 1]) {
      // remove the entry with the matching measObjectId from the measObjectList
      asn1cFreeStruc(asn_DEF_NR_MeasObjectToAddMod, rrc->MeasObj[id - 1]);
      // remove all measId associated with this measObjectId from the measIdList
      for (int j = 0; j < MAX_MEAS_ID; j++) {
        if (rrc->MeasId[j] && rrc->MeasId[j]->measObjectId == id) {
          asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]);
1145
          handle_meas_reporting_remove(rrc, j, timers);
Laurent THOMAS's avatar
Laurent THOMAS committed
1146 1147 1148 1149
        }
      }
    }
  }
1150
}
1151

1152 1153 1154 1155 1156 1157 1158 1159
static void update_ssb_configmob(NR_SSB_ConfigMobility_t *source, NR_SSB_ConfigMobility_t *target)
{
  if (source->ssb_ToMeasure)
    HANDLE_SETUPRELEASE_IE(target->ssb_ToMeasure, source->ssb_ToMeasure, NR_SSB_ToMeasure_t, asn_DEF_NR_SSB_ToMeasure);
  target->deriveSSB_IndexFromCell = source->deriveSSB_IndexFromCell;
  if (source->ss_RSSI_Measurement)
    UPDATE_IE(target->ss_RSSI_Measurement, source->ss_RSSI_Measurement, NR_SS_RSSI_Measurement_t);
}
1160

1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
static void update_nr_measobj(NR_MeasObjectNR_t *source, NR_MeasObjectNR_t *target)
{
  UPDATE_IE(target->ssbFrequency, source->ssbFrequency, NR_ARFCN_ValueNR_t);
  UPDATE_IE(target->ssbSubcarrierSpacing, source->ssbSubcarrierSpacing, NR_SubcarrierSpacing_t);
  UPDATE_IE(target->smtc1, source->smtc1, NR_SSB_MTC_t);
  if (source->smtc2) {
    target->smtc2->periodicity = source->smtc2->periodicity;
    if (source->smtc2->pci_List)
      UPDATE_IE(target->smtc2->pci_List, source->smtc2->pci_List, struct NR_SSB_MTC2__pci_List);
  }
  else
    asn1cFreeStruc(asn_DEF_NR_SSB_MTC2, target->smtc2);
  UPDATE_IE(target->refFreqCSI_RS, source->refFreqCSI_RS, NR_ARFCN_ValueNR_t);
  if (source->referenceSignalConfig.ssb_ConfigMobility)
    update_ssb_configmob(source->referenceSignalConfig.ssb_ConfigMobility, target->referenceSignalConfig.ssb_ConfigMobility);
  UPDATE_IE(target->absThreshSS_BlocksConsolidation, source->absThreshSS_BlocksConsolidation, NR_ThresholdNR_t);
  UPDATE_IE(target->absThreshCSI_RS_Consolidation, source->absThreshCSI_RS_Consolidation, NR_ThresholdNR_t);
  UPDATE_IE(target->nrofSS_BlocksToAverage, source->nrofSS_BlocksToAverage, long);
  UPDATE_IE(target->nrofCSI_RS_ResourcesToAverage, source->nrofCSI_RS_ResourcesToAverage, long);
  target->quantityConfigIndex = source->quantityConfigIndex;
  target->offsetMO = source->offsetMO;
  if (source->cellsToRemoveList) {
    RELEASE_IE_FROMLIST(source->cellsToRemoveList, target->cellsToAddModList, physCellId);
Laurent THOMAS's avatar
Laurent THOMAS committed
1184
  }
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
  if (source->cellsToAddModList) {
    if (!target->cellsToAddModList)
      target->cellsToAddModList = calloc(1, sizeof(*target->cellsToAddModList));
    ADDMOD_IE_FROMLIST(source->cellsToAddModList, target->cellsToAddModList, physCellId, NR_CellsToAddMod_t);
  }
  if (source->excludedCellsToRemoveList) {
    RELEASE_IE_FROMLIST(source->excludedCellsToRemoveList, target->excludedCellsToAddModList, pci_RangeIndex);
  }
  if (source->excludedCellsToAddModList) {
    if (!target->excludedCellsToAddModList)
      target->excludedCellsToAddModList = calloc(1, sizeof(*target->excludedCellsToAddModList));
    ADDMOD_IE_FROMLIST(source->excludedCellsToAddModList, target->excludedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t);
  }
  if (source->allowedCellsToRemoveList) {
    RELEASE_IE_FROMLIST(source->allowedCellsToRemoveList, target->allowedCellsToAddModList, pci_RangeIndex);
  }
  if (source->allowedCellsToAddModList) {
    if (!target->allowedCellsToAddModList)
      target->allowedCellsToAddModList = calloc(1, sizeof(*target->allowedCellsToAddModList));
    ADDMOD_IE_FROMLIST(source->allowedCellsToAddModList, target->allowedCellsToAddModList, pci_RangeIndex, NR_PCI_RangeElement_t);
  }
  if (source->ext1) {
    UPDATE_IE(target->ext1->freqBandIndicatorNR, source->ext1->freqBandIndicatorNR, NR_FreqBandIndicatorNR_t);
    UPDATE_IE(target->ext1->measCycleSCell, source->ext1->measCycleSCell, long);
  }
}
1211

1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
static void handle_measobj_addmod(rrcPerNB_t *rrc, struct NR_MeasObjectToAddModList *addmod_list)
{
  // section 5.5.2.5 in 38.331
  for (int i = 0; i < addmod_list->list.count; i++) {
    NR_MeasObjectToAddMod_t *measObj = addmod_list->list.array[i];
    if (measObj->measObject.present != NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
      LOG_E(NR_RRC, "Cannot handle MeasObjt other than NR\n");
      continue;
    }
    NR_MeasObjectId_t id = measObj->measObjectId;
    if (rrc->MeasObj[id]) {
      update_nr_measobj(measObj->measObject.choice.measObjectNR, rrc->MeasObj[id]->measObject.choice.measObjectNR);
    }
    else {
      // add a new entry for the received measObject to the measObjectList
      UPDATE_IE(rrc->MeasObj[id], addmod_list->list.array[i], NR_MeasObjectToAddMod_t);
Laurent THOMAS's avatar
Laurent THOMAS committed
1228 1229
    }
  }
1230
}
1231

1232 1233 1234
static void handle_reportconfig_remove(rrcPerNB_t *rrc,
                                       struct NR_ReportConfigToRemoveList *remove_list,
                                       NR_UE_Timers_Constants_t *timers)
1235 1236 1237 1238 1239 1240 1241 1242 1243
{
  for (int i = 0; i < remove_list->list.count; i++) {
    NR_ReportConfigId_t id = *remove_list->list.array[i];
    // remove the entry with the matching reportConfigId from the reportConfigList
    asn1cFreeStruc(asn_DEF_NR_ReportConfigToAddMod, rrc->ReportConfig[id]);
    for (int j = 0; j < MAX_MEAS_ID; j++) {
      if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id) {
        // remove all measId associated with the reportConfigId from the measIdList
        asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[j]);
1244
        handle_meas_reporting_remove(rrc, j, timers);
Laurent THOMAS's avatar
Laurent THOMAS committed
1245 1246 1247
      }
    }
  }
1248
}
1249

1250 1251 1252
static void handle_reportconfig_addmod(rrcPerNB_t *rrc,
                                       struct NR_ReportConfigToAddModList *addmod_list,
                                       NR_UE_Timers_Constants_t *timers)
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263
{
  for (int i = 0; i < addmod_list->list.count; i++) {
    NR_ReportConfigToAddMod_t *rep = addmod_list->list.array[i];
    if (rep->reportConfig.present != NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR) {
      LOG_E(NR_RRC, "Cannot handle reportConfig type other than NR\n");
      continue;
    }
    NR_ReportConfigId_t id = rep->reportConfigId;
    if (rrc->ReportConfig[id]) {
      for (int j = 0; j < MAX_MEAS_ID; j++) {
        // for each measId associated with this reportConfigId included in the measIdList
1264 1265
        if (rrc->MeasId[j] && rrc->MeasId[j]->reportConfigId == id)
          handle_meas_reporting_remove(rrc, j, timers);
1266
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
1267
    }
1268
    UPDATE_IE(rrc->ReportConfig[id], addmod_list->list.array[i], NR_ReportConfigToAddMod_t);
Laurent THOMAS's avatar
Laurent THOMAS committed
1269
  }
1270
}
yaojie's avatar
yaojie committed
1271

1272
static void handle_quantityconfig(rrcPerNB_t *rrc, NR_QuantityConfig_t *quantityConfig, NR_UE_Timers_Constants_t *timers)
1273 1274 1275 1276 1277 1278 1279 1280 1281
{
  if (quantityConfig->quantityConfigNR_List) {
    for (int i = 0; i < quantityConfig->quantityConfigNR_List->list.count; i++) {
      NR_QuantityConfigNR_t *quantityNR = quantityConfig->quantityConfigNR_List->list.array[i];
      if (!rrc->QuantityConfig[i])
        rrc->QuantityConfig[i] = calloc(1, sizeof(*rrc->QuantityConfig[i]));
      rrc->QuantityConfig[i]->quantityConfigCell = quantityNR->quantityConfigCell;
      if (quantityNR->quantityConfigRS_Index)
        UPDATE_IE(rrc->QuantityConfig[i]->quantityConfigRS_Index, quantityNR->quantityConfigRS_Index, struct NR_QuantityConfigRS);
Laurent THOMAS's avatar
Laurent THOMAS committed
1282 1283
    }
  }
1284 1285
  for (int j = 0; j < MAX_MEAS_ID; j++) {
    // for each measId included in the measIdList
1286 1287 1288 1289
    if (rrc->MeasId[j])
      handle_meas_reporting_remove(rrc, j, timers);
  }
}
1290

1291 1292 1293 1294 1295 1296 1297
static void handle_measid_remove(rrcPerNB_t *rrc, struct NR_MeasIdToRemoveList *remove_list, NR_UE_Timers_Constants_t *timers)
{
  for (int i = 0; i < remove_list->list.count; i++) {
    NR_MeasId_t id = *remove_list->list.array[i];
    if (rrc->MeasId[id]) {
      asn1cFreeStruc(asn_DEF_NR_MeasIdToAddMod, rrc->MeasId[id]);
      handle_meas_reporting_remove(rrc, id, timers);
Laurent THOMAS's avatar
Laurent THOMAS committed
1298 1299
    }
  }
1300
}
1301

1302
static void handle_measid_addmod(rrcPerNB_t *rrc, struct NR_MeasIdToAddModList *addmod_list, NR_UE_Timers_Constants_t *timers)
1303
{
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335
  for (int i = 0; i < addmod_list->list.count; i++) {
    NR_MeasId_t id = addmod_list->list.array[i]->measId;
    NR_ReportConfigId_t reportId = addmod_list->list.array[i]->reportConfigId;
    NR_MeasObjectId_t measObjectId = addmod_list->list.array[i]->measObjectId;
    UPDATE_IE(rrc->MeasId[id], addmod_list->list.array[i], NR_MeasIdToAddMod_t);
    handle_meas_reporting_remove(rrc, id, timers);
    if (rrc->ReportConfig[reportId]) {
      NR_ReportConfigToAddMod_t *report = rrc->ReportConfig[reportId];
      AssertFatal(report->reportConfig.present == NR_ReportConfigToAddMod__reportConfig_PR_reportConfigNR,
                  "Only NR config report is supported\n");
      NR_ReportConfigNR_t *reportNR = report->reportConfig.choice.reportConfigNR;
      // if the reportType is set to reportCGI in the reportConfig associated with this measId
      if (reportNR->reportType.present == NR_ReportConfigNR__reportType_PR_reportCGI) {
        if (rrc->MeasObj[measObjectId]) {
          if (rrc->MeasObj[measObjectId]->measObject.present == NR_MeasObjectToAddMod__measObject_PR_measObjectNR) {
            NR_MeasObjectNR_t *obj_nr = rrc->MeasObj[measObjectId]->measObject.choice.measObjectNR;
            NR_ARFCN_ValueNR_t freq = 0;
            if (obj_nr->ssbFrequency)
              freq = *obj_nr->ssbFrequency;
            else if (obj_nr->refFreqCSI_RS)
              freq = *obj_nr->refFreqCSI_RS;
            AssertFatal(freq > 0, "Invalid ARFCN frequency for this measurement object\n");
            if (freq > 2016666)
              nr_timer_setup(&timers->T321, 16000, 10); // 16 seconds for FR2
            else
              nr_timer_setup(&timers->T321, 2000, 10); // 2 seconds for FR1
          }
          else // EUTRA
            nr_timer_setup(&timers->T321, 1000, 10); // 1 second for EUTRA
          nr_timer_start(&timers->T321);
        }
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
1336 1337
    }
  }
1338
}
1339

1340 1341
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers)
{
1342
  if (measConfig->measObjectToRemoveList)
1343
    handle_measobj_remove(rrc, measConfig->measObjectToRemoveList, timers);
1344 1345 1346

  if (measConfig->measObjectToAddModList)
    handle_measobj_addmod(rrc, measConfig->measObjectToAddModList);
1347

1348
  if (measConfig->reportConfigToRemoveList)
1349
    handle_reportconfig_remove(rrc, measConfig->reportConfigToRemoveList, timers);
1350

1351
  if (measConfig->reportConfigToAddModList)
1352
    handle_reportconfig_addmod(rrc, measConfig->reportConfigToAddModList, timers);
1353

1354
  if (measConfig->quantityConfig)
1355
    handle_quantityconfig(rrc, measConfig->quantityConfig, timers);
yaojie's avatar
yaojie committed
1356

1357 1358
  if (measConfig->measIdToRemoveList)
    handle_measid_remove(rrc, measConfig->measIdToRemoveList, timers);
1359

1360 1361
  if (measConfig->measIdToAddModList)
    handle_measid_addmod(rrc, measConfig->measIdToAddModList, timers);
1362

1363 1364
  AssertFatal(!measConfig->measGapConfig, "Measurement gaps not yet supported\n");
  AssertFatal(!measConfig->measGapSharingConfig, "Measurement gaps not yet supported\n");
francescomani's avatar
francescomani committed
1365

Laurent THOMAS's avatar
Laurent THOMAS committed
1366 1367 1368 1369 1370 1371 1372 1373
  if (measConfig->s_MeasureConfig) {
    if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_ssb_RSRP) {
      rrc->s_measure = measConfig->s_MeasureConfig->choice.ssb_RSRP;
    } else if (measConfig->s_MeasureConfig->present == NR_MeasConfig__s_MeasureConfig_PR_csi_RSRP) {
      rrc->s_measure = measConfig->s_MeasureConfig->choice.csi_RSRP;
    }
  }
}
1374

1375 1376 1377 1378
/**
 * @brief add, modify and release SRBs and/or DRBs
 * @ref   3GPP TS 38.331
 */
Laurent THOMAS's avatar
Laurent THOMAS committed
1379 1380 1381 1382 1383
static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc,
                                                NR_RadioBearerConfig_t *const radioBearerConfig)
{
  if (LOG_DEBUGFLAG(DEBUG_ASN1))
    xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void *)radioBearerConfig);
1384

1385
  if (radioBearerConfig->srb3_ToRelease) {
1386
    nr_pdcp_release_srb(ue_rrc->ue_id, 3);
1387 1388
    ue_rrc->Srb[3] = RB_NOT_PRESENT;
  }
1389

1390 1391
  uint8_t kRRCenc[NR_K_KEY_SIZE] = {0};
  uint8_t kRRCint[NR_K_KEY_SIZE] = {0};
Laurent THOMAS's avatar
Laurent THOMAS committed
1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408
  if (ue_rrc->as_security_activated) {
    if (radioBearerConfig->securityConfig != NULL) {
      // When the field is not included, continue to use the currently configured keyToUse
      if (radioBearerConfig->securityConfig->keyToUse) {
        AssertFatal(*radioBearerConfig->securityConfig->keyToUse == NR_SecurityConfig__keyToUse_master,
                    "Secondary key usage seems not to be implemented\n");
        ue_rrc->keyToUse = *radioBearerConfig->securityConfig->keyToUse;
      }
      // When the field is not included, continue to use the currently configured security algorithm
      if (radioBearerConfig->securityConfig->securityAlgorithmConfig) {
        ue_rrc->cipheringAlgorithm = radioBearerConfig->securityConfig->securityAlgorithmConfig->cipheringAlgorithm;
        ue_rrc->integrityProtAlgorithm = *radioBearerConfig->securityConfig->securityAlgorithmConfig->integrityProtAlgorithm;
      }
    }
    nr_derive_key(RRC_ENC_ALG, ue_rrc->cipheringAlgorithm, ue_rrc->kgnb, kRRCenc);
    nr_derive_key(RRC_INT_ALG, ue_rrc->integrityProtAlgorithm, ue_rrc->kgnb, kRRCint);
  }
1409

Laurent THOMAS's avatar
Laurent THOMAS committed
1410 1411 1412
  if (radioBearerConfig->srb_ToAddModList != NULL) {
    for (int cnt = 0; cnt < radioBearerConfig->srb_ToAddModList->list.count; cnt++) {
      struct NR_SRB_ToAddMod *srb = radioBearerConfig->srb_ToAddModList->list.array[cnt];
1413 1414
      if (ue_rrc->Srb[srb->srb_Identity] == RB_NOT_PRESENT) {
        ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED;
Laurent THOMAS's avatar
Laurent THOMAS committed
1415
        add_srb(false,
1416
                ue_rrc->ue_id,
Laurent THOMAS's avatar
Laurent THOMAS committed
1417 1418 1419 1420 1421
                radioBearerConfig->srb_ToAddModList->list.array[cnt],
                ue_rrc->cipheringAlgorithm,
                ue_rrc->integrityProtAlgorithm,
                kRRCenc,
                kRRCint);
1422
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
1423 1424
      else {
        AssertFatal(srb->discardOnPDCP == NULL, "discardOnPDCP not yet implemented\n");
1425 1426 1427 1428 1429 1430
        if (srb->reestablishPDCP) {
          ue_rrc->Srb[srb->srb_Identity] = RB_ESTABLISHED;
          nr_pdcp_reestablishment(ue_rrc->ue_id, srb->srb_Identity, true);
          // TODO configure the PDCP entity to apply the integrity protection algorithm
          // TODO configure the PDCP entity to apply the ciphering algorithm
        }
Laurent THOMAS's avatar
Laurent THOMAS committed
1431
        if (srb->pdcp_Config && srb->pdcp_Config->t_Reordering)
1432
          nr_pdcp_reconfigure_srb(ue_rrc->ue_id, srb->srb_Identity, *srb->pdcp_Config->t_Reordering);
Laurent THOMAS's avatar
Laurent THOMAS committed
1433 1434 1435
      }
    }
  }
1436

Laurent THOMAS's avatar
Laurent THOMAS committed
1437 1438 1439
  if (radioBearerConfig->drb_ToReleaseList) {
    for (int cnt = 0; cnt < radioBearerConfig->drb_ToReleaseList->list.count; cnt++) {
      NR_DRB_Identity_t *DRB_id = radioBearerConfig->drb_ToReleaseList->list.array[cnt];
1440
      if (DRB_id) {
1441
        nr_pdcp_release_drb(ue_rrc->ue_id, *DRB_id);
1442 1443
        set_DRB_status(ue_rrc, *DRB_id, RB_NOT_PRESENT);
      }
Laurent THOMAS's avatar
Laurent THOMAS committed
1444 1445
    }
  }
heshanyun's avatar
heshanyun committed
1446

1447 1448 1449 1450
  /**
   * Establish/reconfig DRBs if DRB-ToAddMod is present
   * according to 3GPP TS 38.331 clause 5.3.5.6.5 DRB addition/modification
   */
Laurent THOMAS's avatar
Laurent THOMAS committed
1451 1452 1453 1454
  if (radioBearerConfig->drb_ToAddModList != NULL) {
    for (int cnt = 0; cnt < radioBearerConfig->drb_ToAddModList->list.count; cnt++) {
      struct NR_DRB_ToAddMod *drb = radioBearerConfig->drb_ToAddModList->list.array[cnt];
      int DRB_id = drb->drb_Identity;
1455 1456 1457 1458 1459 1460 1461
      if (get_DRB_status(ue_rrc, DRB_id) != RB_NOT_PRESENT) {
        if (drb->reestablishPDCP) {
          set_DRB_status(ue_rrc, DRB_id, RB_ESTABLISHED);
          nr_pdcp_reestablishment(ue_rrc->ue_id, DRB_id, false);
          // TODO configure the PDCP entity to apply the integrity protection algorithm
          // TODO configure the PDCP entity to apply the ciphering algorithm
        }
Laurent THOMAS's avatar
Laurent THOMAS committed
1462
        AssertFatal(drb->recoverPDCP == NULL, "recoverPDCP not yet implemented\n");
1463
        /* sdap-Config is included (SA mode) */
francescomani's avatar
francescomani committed
1464
        NR_SDAP_Config_t *sdap_Config = drb->cnAssociation ? drb->cnAssociation->choice.sdap_Config : NULL;
1465 1466 1467 1468 1469 1470
        /* PDCP reconfiguration */
        if (drb->pdcp_Config)
          nr_pdcp_reconfigure_drb(ue_rrc->ue_id, DRB_id, drb->pdcp_Config);
        /* SDAP entity reconfiguration */
        if (sdap_Config)
          nr_reconfigure_sdap_entity(sdap_Config, ue_rrc->ue_id, sdap_Config->pdu_Session, DRB_id);
Laurent THOMAS's avatar
Laurent THOMAS committed
1471
      } else {
1472
        set_DRB_status(ue_rrc ,DRB_id, RB_ESTABLISHED);
Laurent THOMAS's avatar
Laurent THOMAS committed
1473
        add_drb(false,
1474
                ue_rrc->ue_id,
Laurent THOMAS's avatar
Laurent THOMAS committed
1475 1476 1477 1478 1479 1480 1481 1482
                radioBearerConfig->drb_ToAddModList->list.array[cnt],
                ue_rrc->cipheringAlgorithm,
                ue_rrc->integrityProtAlgorithm,
                kRRCenc,
                kRRCint);
      }
    }
  } // drb_ToAddModList //
1483

Laurent THOMAS's avatar
Laurent THOMAS committed
1484 1485 1486
  ue_rrc->nrRrcState = RRC_STATE_CONNECTED_NR;
  LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n");
}
Sakthivel Velumani's avatar
Sakthivel Velumani committed
1487

1488
static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, const int srb_id, const uint8_t Transaction_id)
Laurent THOMAS's avatar
Laurent THOMAS committed
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
{
  uint8_t buffer[32], size;
  size = do_NR_RRCReconfigurationComplete(buffer, sizeof(buffer), Transaction_id);
  LOG_I(NR_RRC, " Logical Channel UL-DCCH (SRB1), Generating RRCReconfigurationComplete (bytes %d)\n", size);
  AssertFatal(srb_id == 1 || srb_id == 3, "Invalid SRB ID %d\n", srb_id);
  LOG_D(RLC,
        "PDCP_DATA_REQ/%d Bytes (RRCReconfigurationComplete) "
        "--->][PDCP][RB %02d]\n",
        size,
        srb_id);
1499
  nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
Laurent THOMAS's avatar
Laurent THOMAS committed
1500
}
1501

1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512
static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
                                                 const int gNB_index,
                                                 const NR_RRCReestablishment_t *rrcReestablishment)
{
  // implementign procedues as described in 38.331 section 5.3.7.5
  // stop timer T301
  NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
  nr_timer_stop(&timers->T301);
  // store the nextHopChainingCount value
  NR_RRCReestablishment_IEs_t *ies = rrcReestablishment->criticalExtensions.choice.rrcReestablishment;
  AssertFatal(ies, "Not expecting RRCReestablishment_IEs to be NULL\n");
1513 1514 1515 1516
  // TODO need to understand how to use nextHopChainingCount
  // int nh = rrcReestablishment->criticalExtensions.choice.rrcReestablishment->nextHopChainingCount;

  // update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value
1517
  nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb);
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530

  // derive the K RRCenc and K UPenc keys associated with the previously configured cipheringAlgorithm
  // derive the K RRCint and K UPint keys associated with the previously configured integrityProtAlgorithm
  uint8_t kRRCenc[16] = {0};
  uint8_t kRRCint[16] = {0};
  uint8_t kUPenc[16] = {0};
  uint8_t kUPint[16] = {0};

  nr_derive_key(UP_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kUPenc);
  nr_derive_key(UP_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kUPint);
  nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, kRRCenc);
  nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, kRRCint);

1531 1532
  // TODO request lower layers to verify the integrity protection of the RRCReestablishment message
  // TODO if the integrity protection check of the RRCReestablishment message fails -> go to IDLE
1533 1534 1535 1536 1537 1538 1539 1540

  // configure lower layers to resume integrity protection for SRB1
  // configure lower layers to resume ciphering for SRB1
  int srb_id = 1;
  int security_mode = (rrc->integrityProtAlgorithm << 4)
                      | rrc->cipheringAlgorithm;
  nr_pdcp_config_set_security(rrc->ue_id, srb_id, security_mode, kRRCenc, kRRCint, kUPenc);

1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551
  // release the measurement gap configuration indicated by the measGapConfig, if configured
  rrcPerNB_t *rrcNB = rrc->perNB + gNB_index;
  asn1cFreeStruc(asn_DEF_NR_MeasGapConfig, rrcNB->measGapConfig);

  // resetting the RA trigger state after receiving MSG4 with RRCReestablishment
  rrc->ra_trigger = RA_NOT_RUNNING;

  // submit the RRCReestablishmentComplete message to lower layers for transmission
  nr_rrc_ue_generate_rrcReestablishmentComplete(rrc, rrcReestablishment);
}

1552
static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
1553 1554 1555 1556
                                 const srb_id_t Srb_id,
                                 const uint8_t *const Buffer,
                                 size_t Buffer_size,
                                 const uint8_t gNB_indexP)
1557

Laurent THOMAS's avatar
Laurent THOMAS committed
1558 1559 1560 1561 1562
{
  NR_DL_DCCH_Message_t *dl_dcch_msg = NULL;
  if (Srb_id != 1 && Srb_id != 2) {
    LOG_E(NR_RRC, "Received message on DL-DCCH (SRB%ld), should not have ...\n", Srb_id);
  }
1563

Laurent THOMAS's avatar
Laurent THOMAS committed
1564 1565
  LOG_D(NR_RRC, "Decoding DL-DCCH Message\n");
  asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_DL_DCCH_Message, (void **)&dl_dcch_msg, Buffer, Buffer_size, 0, 0);
1566

Laurent THOMAS's avatar
Laurent THOMAS committed
1567 1568 1569 1570 1571
  if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
    LOG_E(NR_RRC, "Failed to decode DL-DCCH (%zu bytes)\n", dec_rval.consumed);
    ASN_STRUCT_FREE(asn_DEF_NR_DL_DCCH_Message, dl_dcch_msg);
    return -1;
  }
1572

Laurent THOMAS's avatar
Laurent THOMAS committed
1573 1574 1575
  if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
    xer_fprint(stdout, &asn_DEF_NR_DL_DCCH_Message, (void *)dl_dcch_msg);
  }
1576

Laurent THOMAS's avatar
Laurent THOMAS committed
1577 1578 1579 1580 1581 1582 1583
  switch (dl_dcch_msg->message.present) {
    case NR_DL_DCCH_MessageType_PR_c1: {
      struct NR_DL_DCCH_MessageType__c1 *c1 = dl_dcch_msg->message.choice.c1;
      switch (c1->present) {
        case NR_DL_DCCH_MessageType__c1_PR_NOTHING:
          LOG_I(NR_RRC, "Received PR_NOTHING on DL-DCCH-Message\n");
          break;
heshanyun's avatar
heshanyun committed
1584

Laurent THOMAS's avatar
Laurent THOMAS committed
1585
        case NR_DL_DCCH_MessageType__c1_PR_rrcReconfiguration: {
1586 1587
          nr_rrc_ue_process_rrcReconfiguration(rrc, gNB_indexP, c1->choice.rrcReconfiguration);
          nr_rrc_ue_generate_RRCReconfigurationComplete(rrc, Srb_id, c1->choice.rrcReconfiguration->rrc_TransactionIdentifier);
Laurent THOMAS's avatar
Laurent THOMAS committed
1588 1589 1590 1591 1592
        } break;

        case NR_DL_DCCH_MessageType__c1_PR_rrcResume:
          LOG_I(NR_RRC, "Received rrcResume on DL-DCCH-Message\n");
          break;
1593
        case NR_DL_DCCH_MessageType__c1_PR_rrcRelease:
1594
          LOG_I(NR_RRC, "[UE %ld] Received RRC Release (gNB %d)\n", rrc->ue_id, gNB_indexP);
1595 1596
          // TODO properly implement procedures in 5.3.8.3 of 38.331
          NR_Release_Cause_t cause = OTHER;
1597
          nr_rrc_going_to_IDLE(rrc, cause, dl_dcch_msg->message.choice.c1->choice.rrcRelease);
1598
          break;
Laurent THOMAS's avatar
Laurent THOMAS committed
1599 1600 1601 1602 1603 1604 1605 1606

        case NR_DL_DCCH_MessageType__c1_PR_ueCapabilityEnquiry:
          LOG_I(NR_RRC, "Received Capability Enquiry (gNB %d)\n", gNB_indexP);
          nr_rrc_ue_process_ueCapabilityEnquiry(rrc, c1->choice.ueCapabilityEnquiry);
          break;

        case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment:
          LOG_I(NR_RRC, "Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n");
1607
          nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment);
Laurent THOMAS's avatar
Laurent THOMAS committed
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620
          break;

        case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: {
          NR_DLInformationTransfer_t *dlInformationTransfer = c1->choice.dlInformationTransfer;

          if (dlInformationTransfer->criticalExtensions.present
              == NR_DLInformationTransfer__criticalExtensions_PR_dlInformationTransfer) {
            /* This message hold a dedicated info NAS payload, forward it to NAS */
            NR_DedicatedNAS_Message_t *dedicatedNAS_Message =
                dlInformationTransfer->criticalExtensions.choice.dlInformationTransfer->dedicatedNAS_Message;

            MessageDef *ittiMsg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NAS_DOWNLINK_DATA_IND);
            NasDlDataInd *msg = &NAS_DOWNLINK_DATA_IND(ittiMsg);
1621
            msg->UEid = rrc->ue_id;
Laurent THOMAS's avatar
Laurent THOMAS committed
1622 1623
            msg->nasMsg.length = dedicatedNAS_Message->size;
            msg->nasMsg.data = dedicatedNAS_Message->buf;
1624
            itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, ittiMsg);
Laurent THOMAS's avatar
Laurent THOMAS committed
1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639
            dedicatedNAS_Message->buf = NULL; // to keep the buffer, up to NAS to free it
          }
        } break;
        case NR_DL_DCCH_MessageType__c1_PR_mobilityFromNRCommand:
        case NR_DL_DCCH_MessageType__c1_PR_dlDedicatedMessageSegment_r16:
        case NR_DL_DCCH_MessageType__c1_PR_ueInformationRequest_r16:
        case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransferMRDC_r16:
        case NR_DL_DCCH_MessageType__c1_PR_loggedMeasurementConfiguration_r16:
        case NR_DL_DCCH_MessageType__c1_PR_spare3:
        case NR_DL_DCCH_MessageType__c1_PR_spare2:
        case NR_DL_DCCH_MessageType__c1_PR_spare1:
        case NR_DL_DCCH_MessageType__c1_PR_counterCheck:
          break;
        case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand:
          LOG_I(NR_RRC, "Received securityModeCommand (gNB %d)\n", gNB_indexP);
1640
          nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand);
Laurent THOMAS's avatar
Laurent THOMAS committed
1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652
          break;
      }
    } break;
    default:
      break;
  }
  //  release memory allocation
  SEQUENCE_free(&asn_DEF_NR_DL_DCCH_Message, (void *)dl_dcch_msg, 1);
  return 0;
}

void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded)
1653
{
Laurent THOMAS's avatar
Laurent THOMAS committed
1654
  NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
1655
  if (ra_succeeded && is_nr_timer_active(timers->T304)) {
1656
    // successful Random Access procedure triggered by reconfigurationWithSync
1657
    nr_timer_stop(&timers->T304);
1658 1659 1660 1661
    // TODO handle the rest of procedures as described in 5.3.5.3 for when
    // reconfigurationWithSync is included in spCellConfig
  }
}
francescomani's avatar
francescomani committed
1662

francescomani's avatar
francescomani committed
1663 1664
void *rrc_nrue_task(void *args_p)
{
1665 1666 1667 1668 1669
  itti_mark_task_ready(TASK_RRC_NRUE);
  while (1) {
    rrc_nrue(NULL);
  }
}
Xue Song's avatar
Xue Song committed
1670

1671 1672 1673 1674 1675
void *rrc_nrue(void *notUsed)
{
  MessageDef *msg_p = NULL;
  itti_receive_msg(TASK_RRC_NRUE, &msg_p);
  instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
Laurent THOMAS's avatar
Laurent THOMAS committed
1676
  LOG_D(NR_RRC, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p));
1677

1678 1679 1680
  NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance];
  AssertFatal(instance == rrc->ue_id, "Instance %ld received from ITTI doesn't matach with UE-ID %ld\n", instance, rrc->ue_id);

1681
  switch (ITTI_MSG_ID(msg_p)) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1682 1683 1684 1685
  case TERMINATE_MESSAGE:
    LOG_W(NR_RRC, " *** Exiting RRC thread\n");
    itti_exit_task();
    break;
1686

Laurent THOMAS's avatar
Laurent THOMAS committed
1687 1688
  case MESSAGE_TEST:
    break;
1689

Laurent THOMAS's avatar
Laurent THOMAS committed
1690 1691 1692 1693 1694
  case NR_RRC_MAC_SYNC_IND: {
    nr_sync_msg_t sync_msg = NR_RRC_MAC_SYNC_IND(msg_p).in_sync ? IN_SYNC : OUT_OF_SYNC;
    NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
    handle_rlf_sync(tac, sync_msg);
  } break;
1695

Laurent THOMAS's avatar
Laurent THOMAS committed
1696 1697 1698
  case NRRRC_FRAME_PROCESS:
    LOG_D(NR_RRC, "Received %s: frame %d\n", ITTI_MSG_NAME(msg_p), NRRRC_FRAME_PROCESS(msg_p).frame);
    // increase the timers every 10ms (every new frame)
1699 1700
    nr_rrc_handle_timers(rrc);
    NR_UE_RRC_SI_INFO *SInfo = &rrc->perNB[NRRRC_FRAME_PROCESS(msg_p).gnb_id].SInfo;
Laurent THOMAS's avatar
Laurent THOMAS committed
1701 1702
    nr_rrc_SI_timers(SInfo);
    break;
1703

Laurent THOMAS's avatar
Laurent THOMAS committed
1704
  case NR_RRC_MAC_MSG3_IND:
1705
    nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti);
Laurent THOMAS's avatar
Laurent THOMAS committed
1706
    break;
1707

Laurent THOMAS's avatar
Laurent THOMAS committed
1708 1709 1710
  case NR_RRC_MAC_RA_IND:
    LOG_D(NR_RRC,
	  "[UE %ld] Received %s: frame %d RA %s\n",
1711
	  rrc->ue_id,
Laurent THOMAS's avatar
Laurent THOMAS committed
1712 1713 1714 1715 1716
	  ITTI_MSG_NAME(msg_p),
	  NR_RRC_MAC_RA_IND(msg_p).frame,
	  NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed");
    nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded);
    break;
1717

Laurent THOMAS's avatar
Laurent THOMAS committed
1718
  case NR_RRC_MAC_BCCH_DATA_IND:
1719
    LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", rrc->ue_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_BCCH_DATA_IND(msg_p).gnb_index);
Laurent THOMAS's avatar
Laurent THOMAS committed
1720 1721
    NRRrcMacBcchDataInd *bcch = &NR_RRC_MAC_BCCH_DATA_IND(msg_p);
    if (bcch->is_bch)
1722
      nr_rrc_ue_decode_NR_BCCH_BCH_Message(rrc, bcch->gnb_index, bcch->phycellid, bcch->ssb_arfcn, bcch->sdu, bcch->sdu_size);
Laurent THOMAS's avatar
Laurent THOMAS committed
1723
    else
1724
      nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(rrc, bcch->gnb_index, bcch->sdu, bcch->sdu_size, bcch->rsrq, bcch->rsrp);
Laurent THOMAS's avatar
Laurent THOMAS committed
1725
    break;
1726

1727 1728 1729 1730 1731 1732 1733 1734
  case NR_RRC_MAC_SBCCH_DATA_IND:
    LOG_D(NR_RRC, "[UE %ld] Received %s: gNB %d\n", instance, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_SBCCH_DATA_IND(msg_p).gnb_index);
    NRRrcMacSBcchDataInd *sbcch = &NR_RRC_MAC_SBCCH_DATA_IND(msg_p);
    
    nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(rrc, sbcch->gnb_index,sbcch->frame, sbcch->slot, sbcch->sdu,
                                             sbcch->sdu_size, sbcch->rx_slss_id);
    break;

Laurent THOMAS's avatar
Laurent THOMAS committed
1735 1736
  case NR_RRC_MAC_CCCH_DATA_IND: {
    NRRrcMacCcchDataInd *ind = &NR_RRC_MAC_CCCH_DATA_IND(msg_p);
1737
    nr_rrc_ue_decode_ccch(rrc, ind);
Laurent THOMAS's avatar
Laurent THOMAS committed
1738
  } break;
1739

Laurent THOMAS's avatar
Laurent THOMAS committed
1740
  case NR_RRC_DCCH_DATA_IND:
1741
    nr_rrc_ue_decode_dcch(rrc,
Laurent THOMAS's avatar
Laurent THOMAS committed
1742 1743 1744 1745 1746
			  NR_RRC_DCCH_DATA_IND(msg_p).dcch_index,
			  NR_RRC_DCCH_DATA_IND(msg_p).sdu_p,
			  NR_RRC_DCCH_DATA_IND(msg_p).sdu_size,
			  NR_RRC_DCCH_DATA_IND(msg_p).gNB_index);
    break;
1747

Laurent THOMAS's avatar
Laurent THOMAS committed
1748 1749 1750
  case NAS_KENB_REFRESH_REQ:
    memcpy(rrc->kgnb, NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(rrc->kgnb));
    break;
1751 1752 1753 1754 1755

  case NAS_DETACH_REQ:
    if (!NAS_DETACH_REQ(msg_p).wait_release) {
      rrc->nrRrcState = RRC_STATE_DETACH_NR;
      NR_Release_Cause_t release_cause = OTHER;
1756
      nr_rrc_going_to_IDLE(rrc, release_cause, NULL);
1757 1758 1759
    }
    break;

Laurent THOMAS's avatar
Laurent THOMAS committed
1760 1761 1762 1763 1764 1765 1766 1767 1768
  case NAS_UPLINK_DATA_REQ: {
    uint32_t length;
    uint8_t *buffer;
    NasUlDataReq *req = &NAS_UPLINK_DATA_REQ(msg_p);
    /* Create message for PDCP (ULInformationTransfer_t) */
    length = do_NR_ULInformationTransfer(&buffer, req->nasMsg.length, req->nasMsg.data);
    /* Transfer data to PDCP */
    // check if SRB2 is created, if yes request data_req on SRB2
    // error: the remote gNB is hardcoded here
1769
    rb_id_t srb_id = rrc->Srb[2] == RB_ESTABLISHED ? 2 : 1;
1770
    nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, length, buffer, deliver_pdu_srb_rlc, NULL);
Laurent THOMAS's avatar
Laurent THOMAS committed
1771
    break;
heshanyun's avatar
heshanyun committed
1772
  }
1773

Laurent THOMAS's avatar
Laurent THOMAS committed
1774
  default:
1775
    LOG_E(NR_RRC, "[UE %ld] Received unexpected message %s\n", rrc->ue_id, ITTI_MSG_NAME(msg_p));
Laurent THOMAS's avatar
Laurent THOMAS committed
1776 1777
    break;
  }
1778
  LOG_D(NR_RRC, "[UE %ld] RRC Status %d\n", rrc->ue_id, rrc->nrRrcState);
1779 1780 1781
  int result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
  AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  return NULL;
heshanyun's avatar
heshanyun committed
1782
}
1783

1784
void nr_rrc_ue_process_sidelink_radioResourceConfig(NR_SetupRelease_SL_ConfigDedicatedNR_r16_t *sl_ConfigDedicatedNR)
yincong's avatar
yincong committed
1785 1786 1787
{
  //process sl_CommConfig, configure MAC/PHY for transmitting SL communication (RRC_CONNECTED)
  if (sl_ConfigDedicatedNR != NULL) {
1788
    switch (sl_ConfigDedicatedNR->present){
yincong's avatar
yincong committed
1789
      case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_setup:
1790 1791
        //TODO
        break;
yincong's avatar
yincong committed
1792
      case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_release:
1793
        break;
yincong's avatar
yincong committed
1794
      case NR_SetupRelease_SL_ConfigDedicatedNR_r16_PR_NOTHING:
1795
        break;
yincong's avatar
yincong committed
1796
      default:
1797 1798
        break;
    }
yincong's avatar
yincong committed
1799 1800
  }
}
zhanghuiqin's avatar
zhanghuiqin committed
1801

Laurent THOMAS's avatar
Laurent THOMAS committed
1802
static void nr_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc, NR_UECapabilityEnquiry_t *UECapabilityEnquiry)
zhanghuiqin's avatar
zhanghuiqin committed
1803
{
Laurent THOMAS's avatar
Laurent THOMAS committed
1804 1805 1806 1807
  NR_UL_DCCH_Message_t ul_dcch_msg = {0};
  //
  LOG_I(NR_RRC, "Receiving from SRB1 (DL-DCCH), Processing UECapabilityEnquiry\n");

1808
  ul_dcch_msg.message.present = NR_UL_DCCH_MessageType_PR_c1;
Laurent THOMAS's avatar
Laurent THOMAS committed
1809 1810 1811 1812 1813
  asn1cCalloc(ul_dcch_msg.message.choice.c1, c1);
  c1->present = NR_UL_DCCH_MessageType__c1_PR_ueCapabilityInformation;
  asn1cCalloc(c1->choice.ueCapabilityInformation, info);
  info->rrc_TransactionIdentifier = UECapabilityEnquiry->rrc_TransactionIdentifier;
  NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container = {.rat_Type = NR_RAT_Type_nr};
1814

1815
  if (!rrc->UECap.UE_NR_Capability) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1816 1817
    rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t));
    asn1cSequenceAdd(rrc->UECap.UE_NR_Capability->rf_Parameters.supportedBandListNR.list, NR_BandNR_t, nr_bandnr);
1818 1819
    nr_bandnr->bandNR = 1;
  }
Laurent THOMAS's avatar
Laurent THOMAS committed
1820
  xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, (void *)rrc->UECap.UE_NR_Capability);
1821

Laurent THOMAS's avatar
Laurent THOMAS committed
1822 1823 1824 1825 1826
  asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability,
                                                  NULL,
                                                  (void *)rrc->UECap.UE_NR_Capability,
                                                  &rrc->UECap.sdu[0],
                                                  MAX_UE_NR_CAPABILITY_SIZE);
1827 1828
  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
               enc_rval.failed_type->name, enc_rval.encoded);
Laurent THOMAS's avatar
Laurent THOMAS committed
1829 1830
  rrc->UECap.sdu_size = (enc_rval.encoded + 7) / 8;
  LOG_I(PHY, "[RRC]UE NR Capability encoded, %d bytes (%zd bits)\n", rrc->UECap.sdu_size, enc_rval.encoded + 7);
1831

Laurent THOMAS's avatar
Laurent THOMAS committed
1832
  OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container, (const char *)rrc->UECap.sdu, rrc->UECap.sdu_size);
David Kim's avatar
David Kim committed
1833

1834
  NR_UECapabilityEnquiry_IEs_t *ueCapabilityEnquiry_ie = UECapabilityEnquiry->criticalExtensions.choice.ueCapabilityEnquiry;
David Kim's avatar
David Kim committed
1835
  if (get_softmodem_params()->nsa == 1) {
francescomani's avatar
francescomani committed
1836
    OCTET_STRING_t *requestedFreqBandsNR = ueCapabilityEnquiry_ie->ue_CapabilityEnquiryExt;
David Kim's avatar
David Kim committed
1837 1838
    nsa_sendmsg_to_lte_ue(requestedFreqBandsNR->buf, requestedFreqBandsNR->size, UE_CAPABILITY_INFO);
  }
zhanghuiqin's avatar
zhanghuiqin committed
1839 1840 1841 1842 1843 1844
  //  ue_CapabilityRAT_Container.ueCapabilityRAT_Container.buf  = UE_rrc_inst[ue_mod_idP].UECapability;
  // ue_CapabilityRAT_Container.ueCapabilityRAT_Container.size = UE_rrc_inst[ue_mod_idP].UECapability_size;
  AssertFatal(UECapabilityEnquiry->criticalExtensions.present == NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry,
              "UECapabilityEnquiry->criticalExtensions.present (%d) != UECapabilityEnquiry__criticalExtensions_PR_c1 (%d)\n",
              UECapabilityEnquiry->criticalExtensions.present,NR_UECapabilityEnquiry__criticalExtensions_PR_ueCapabilityEnquiry);

1845 1846
  NR_UECapabilityInformation_t *ueCapabilityInformation = ul_dcch_msg.message.choice.c1->choice.ueCapabilityInformation;
  ueCapabilityInformation->criticalExtensions.present = NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation;
Laurent THOMAS's avatar
Laurent THOMAS committed
1847 1848 1849
  asn1cCalloc(ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation, infoIE);
  asn1cCalloc(infoIE->ue_CapabilityRAT_ContainerList, UEcapList);
  UEcapList->list.count = 0;
1850 1851 1852

  for (int i = 0; i < ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.count; i++) {
    if (ueCapabilityEnquiry_ie->ue_CapabilityRAT_RequestList.list.array[i]->rat_Type == NR_RAT_Type_nr) {
Laurent THOMAS's avatar
Laurent THOMAS committed
1853 1854 1855
      asn1cSeqAdd(&UEcapList->list, &ue_CapabilityRAT_Container);
      uint8_t buffer[500];
      asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UL_DCCH_Message, NULL, (void *)&ul_dcch_msg, buffer, 500);
zhanghuiqin's avatar
zhanghuiqin committed
1856 1857 1858
      AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
                   enc_rval.failed_type->name, enc_rval.encoded);

1859
      if (LOG_DEBUGFLAG(DEBUG_ASN1)) {
zhanghuiqin's avatar
zhanghuiqin committed
1860
        xer_fprint(stdout, &asn_DEF_NR_UL_DCCH_Message, (void *)&ul_dcch_msg);
Xue Song's avatar
Xue Song committed
1861
      }
1862
      LOG_I(NR_RRC, "UECapabilityInformation Encoded %zd bits (%zd bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
francescomani's avatar
francescomani committed
1863
      int srb_id = 1; // UECapabilityInformation on SRB1
1864
      nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, (enc_rval.encoded + 7) / 8, buffer, deliver_pdu_srb_rlc, NULL);
zhanghuiqin's avatar
zhanghuiqin committed
1865 1866
    }
  }
1867
}
1868

francescomani's avatar
francescomani committed
1869
void nr_rrc_initiate_rrcReestablishment(NR_UE_RRC_INST_t *rrc,
1870
                                        NR_ReestablishmentCause_t cause,
francescomani's avatar
francescomani committed
1871 1872
                                        const int gnb_id)
{
1873 1874
  rrc->reestablishment_cause = cause;

francescomani's avatar
francescomani committed
1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909
  NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
  rrcPerNB_t *rrcNB = rrc->perNB + gnb_id;

  // reset timers to SIB1 as part of release of spCellConfig
  // it needs to be done before handling timers
  set_rlf_sib1_timers_and_constants(timers, rrcNB->SInfo.sib1);

  // stop timer T310, if running
  nr_timer_stop(&timers->T310);
  // stop timer T304, if running
  nr_timer_stop(&timers->T304);
  // start timer T311
  nr_timer_start(&timers->T311);
  // suspend all RBs, except SRB0
  for (int i = 1; i < 4; i++) {
    if (rrc->Srb[i] == RB_ESTABLISHED) {
      rrc->Srb[i] = RB_SUSPENDED;
      nr_pdcp_suspend_srb(rrc->ue_id, i);
    }
  }
  for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
    if (get_DRB_status(rrc, i) == RB_ESTABLISHED) {
      set_DRB_status(rrc, i, RB_SUSPENDED);
      nr_pdcp_suspend_drb(rrc->ue_id, i);
    }
  }
  // release the MCG SCell(s), if configured
  // no SCell configured in our implementation

  // reset MAC
  // release spCellConfig, if configured
  // perform cell selection in accordance with the cell selection process
  nr_rrc_mac_config_req_reset(rrc->ue_id, RE_ESTABLISHMENT);
}

1910 1911
static void nr_rrc_ue_generate_rrcReestablishmentComplete(const NR_UE_RRC_INST_t *rrc,
                                                          const NR_RRCReestablishment_t *rrcReestablishment)
1912
{
francescomani's avatar
francescomani committed
1913 1914
  uint8_t buffer[RRC_BUFFER_SIZE] = {0};
  int size = do_RRCReestablishmentComplete(buffer, RRC_BUFFER_SIZE,
1915
                                           rrcReestablishment->rrc_TransactionIdentifier);
francescomani's avatar
francescomani committed
1916
  LOG_I(NR_RRC, "[RAPROC] Logical Channel UL-DCCH (SRB1), Generating RRCReestablishmentComplete (bytes %d)\n", size);
1917 1918
  int srb_id = 1; // RRC re-establishment complete on SRB1
  nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL);
1919
}
1920 1921 1922

void *recv_msgs_from_lte_ue(void *args_p)
{
francescomani's avatar
francescomani committed
1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934
  itti_mark_task_ready (TASK_RRC_NSA_NRUE);
  int from_lte_ue_fd = get_from_lte_ue_fd();
  for (;;) {
    nsa_msg_t msg;
    int recvLen = recvfrom(from_lte_ue_fd, &msg, sizeof(msg), MSG_WAITALL | MSG_TRUNC, NULL, NULL);
    if (recvLen == -1) {
      LOG_E(NR_RRC, "%s: recvfrom: %s\n", __func__, strerror(errno));
      continue;
    }
    if (recvLen > sizeof(msg)) {
      LOG_E(NR_RRC, "%s: Received truncated message %d\n", __func__, recvLen);
      continue;
1935
    }
francescomani's avatar
francescomani committed
1936 1937 1938
    process_lte_nsa_msg(NR_UE_rrc_inst, &msg, recvLen);
  }
  return NULL;
1939
}
1940

1941
static void nsa_rrc_ue_process_ueCapabilityEnquiry(NR_UE_RRC_INST_t *rrc)
1942
{
1943
  NR_UE_NR_Capability_t *UE_Capability_nr = rrc->UECap.UE_NR_Capability = CALLOC(1, sizeof(NR_UE_NR_Capability_t));
1944 1945
  NR_BandNR_t *nr_bandnr = CALLOC(1, sizeof(NR_BandNR_t));
  nr_bandnr->bandNR = 78;
1946
  asn1cSeqAdd(&UE_Capability_nr->rf_Parameters.supportedBandListNR.list, nr_bandnr);
1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957
  OAI_NR_UECapability_t *UECap = CALLOC(1, sizeof(OAI_NR_UECapability_t));
  UECap->UE_NR_Capability = UE_Capability_nr;

  asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_NR_Capability,
                                   NULL,
                                   (void *)UE_Capability_nr,
                                   &UECap->sdu[0],
                                   MAX_UE_NR_CAPABILITY_SIZE);
  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
               enc_rval.failed_type->name, enc_rval.encoded);
  UECap->sdu_size = (enc_rval.encoded + 7) / 8;
1958
  LOG_A(NR_RRC, "[NR_RRC] NRUE Capability encoded, %d bytes (%zd bits)\n",
1959
        UECap->sdu_size, enc_rval.encoded + 7);
Melissa Elkadi's avatar
Melissa Elkadi committed
1960

1961 1962 1963 1964
  NR_UE_CapabilityRAT_Container_t ue_CapabilityRAT_Container;
  memset(&ue_CapabilityRAT_Container, 0, sizeof(NR_UE_CapabilityRAT_Container_t));
  ue_CapabilityRAT_Container.rat_Type = NR_RAT_Type_nr;
  OCTET_STRING_fromBuf(&ue_CapabilityRAT_Container.ue_CapabilityRAT_Container,
1965 1966
                       (const char *)rrc->UECap.sdu,
                       rrc->UECap.sdu_size);
1967

1968 1969
  nsa_sendmsg_to_lte_ue(ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.buf,
                        ue_CapabilityRAT_Container.ue_CapabilityRAT_Container.size,
1970
                        NRUE_CAPABILITY_INFO);
1971 1972
}

Laurent THOMAS's avatar
Laurent THOMAS committed
1973
static void process_lte_nsa_msg(NR_UE_RRC_INST_t *rrc, nsa_msg_t *msg, int msg_len)
1974
{
francescomani's avatar
francescomani committed
1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005
  if (msg_len < sizeof(msg->msg_type)) {
    LOG_E(RRC, "Msg_len = %d\n", msg_len);
    return;
  }
  LOG_D(NR_RRC, "Processing an NSA message\n");
  Rrc_Msg_Type_t msg_type = msg->msg_type;
  uint8_t *const msg_buffer = msg->msg_buffer;
  msg_len -= sizeof(msg->msg_type);
  switch (msg_type) {
    case UE_CAPABILITY_ENQUIRY: {
      LOG_D(NR_RRC, "We are processing a %d message \n", msg_type);
      NR_FreqBandList_t *nr_freq_band_list = NULL;
      asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                     &asn_DEF_NR_FreqBandList,
                                                     (void **)&nr_freq_band_list,
                                                     msg_buffer,
                                                     msg_len);
      if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
        SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING);
        LOG_E(RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed);
        break;
      }
      for (int i = 0; i < nr_freq_band_list->list.count; i++) {
        LOG_D(NR_RRC, "Received NR band information: %ld.\n",
        nr_freq_band_list->list.array[i]->choice.bandInformationNR->bandNR);
      }
      int dummy_msg = 0;// whatever piece of data, it will never be used by sendee
      LOG_D(NR_RRC, "We are calling nsa_sendmsg_to_lte_ue to send a UE_CAPABILITY_DUMMY\n");
      nsa_sendmsg_to_lte_ue(&dummy_msg, sizeof(dummy_msg), UE_CAPABILITY_DUMMY);
      LOG_A(NR_RRC, "Sent initial NRUE Capability response to LTE UE\n");
      break;
2006
    }
2007

francescomani's avatar
francescomani committed
2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
    case NRUE_CAPABILITY_ENQUIRY: {
      LOG_I(NR_RRC, "We are processing a %d message \n", msg_type);
      NR_FreqBandList_t *nr_freq_band_list = NULL;
      asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                     &asn_DEF_NR_FreqBandList,
                                                     (void **)&nr_freq_band_list,
                                                     msg_buffer,
                                                     msg_len);
      if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
        SEQUENCE_free(&asn_DEF_NR_FreqBandList, nr_freq_band_list, ASFM_FREE_EVERYTHING);
        LOG_E(NR_RRC, "Failed to decode UECapabilityInfo (%zu bits)\n", dec_rval.consumed);
        break;
      }
      LOG_I(NR_RRC, "Calling nsa_rrc_ue_process_ueCapabilityEnquiry\n");
      nsa_rrc_ue_process_ueCapabilityEnquiry(rrc);
      break;
    }
2025

francescomani's avatar
francescomani committed
2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045
    case RRC_MEASUREMENT_PROCEDURE: {
      LOG_I(NR_RRC, "We are processing a %d message \n", msg_type);

      LTE_MeasObjectToAddMod_t *nr_meas_obj = NULL;
      asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
                                                     &asn_DEF_NR_MeasObjectToAddMod,
                                                     (void **)&nr_meas_obj,
                                                     msg_buffer,
                                                     msg_len);
      if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
        SEQUENCE_free(&asn_DEF_NR_MeasObjectToAddMod, nr_meas_obj, ASFM_FREE_EVERYTHING);
        LOG_E(RRC, "Failed to decode measurement object (%zu bits) %d\n", dec_rval.consumed, dec_rval.code);
        break;
      }
      LOG_D(NR_RRC, "NR carrierFreq_r15 (ssb): %ld and sub carrier spacing:%ld\n",
            nr_meas_obj->measObject.choice.measObjectNR_r15.carrierFreq_r15,
            nr_meas_obj->measObject.choice.measObjectNR_r15.rs_ConfigSSB_r15.subcarrierSpacingSSB_r15);
      start_oai_nrue_threads();
      break;
    }
2046

francescomani's avatar
francescomani committed
2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081
    case RRC_CONFIG_COMPLETE_REQ: {
      struct msg {
        uint32_t RadioBearer_size;
        uint32_t SecondaryCellGroup_size;
        uint8_t trans_id;
        uint8_t padding[3];
        uint8_t buffer[];
      } hdr;
      AssertFatal(msg_len >= sizeof(hdr), "Bad received msg\n");
      memcpy(&hdr, msg_buffer, sizeof(hdr));
      LOG_I(NR_RRC, "We got an RRC_CONFIG_COMPLETE_REQ\n");
      uint32_t nr_RadioBearer_size = hdr.RadioBearer_size;
      uint32_t nr_SecondaryCellGroup_size = hdr.SecondaryCellGroup_size;
      AssertFatal(sizeof(hdr) + nr_RadioBearer_size + nr_SecondaryCellGroup_size <= msg_len,
                  "nr_RadioBearerConfig1_r15 size %u nr_SecondaryCellGroupConfig_r15 size %u sizeof(hdr) %zu, msg_len = %d\n",
                  nr_RadioBearer_size,
                  nr_SecondaryCellGroup_size,
                  sizeof(hdr),
                  msg_len);
      NR_RRC_TransactionIdentifier_t t_id = hdr.trans_id;
      LOG_I(NR_RRC, "nr_RadioBearerConfig1_r15 size %d nr_SecondaryCellGroupConfig_r15 size %d t_id %ld\n",
            nr_RadioBearer_size,
            nr_SecondaryCellGroup_size,
            t_id);

      uint8_t *nr_RadioBearer_buffer = msg_buffer + offsetof(struct msg, buffer);
      uint8_t *nr_SecondaryCellGroup_buffer = nr_RadioBearer_buffer + nr_RadioBearer_size;
      process_nsa_message(NR_UE_rrc_inst, nr_SecondaryCellGroupConfig_r15, nr_SecondaryCellGroup_buffer, nr_SecondaryCellGroup_size);
      process_nsa_message(NR_UE_rrc_inst, nr_RadioBearerConfigX_r15, nr_RadioBearer_buffer, nr_RadioBearer_size);
      LOG_I(NR_RRC, "Calling do_NR_RRCReconfigurationComplete. t_id %ld \n", t_id);
      uint8_t buffer[RRC_BUF_SIZE];
      size_t size = do_NR_RRCReconfigurationComplete_for_nsa(buffer, sizeof(buffer), t_id);
      nsa_sendmsg_to_lte_ue(buffer, size, NR_RRC_CONFIG_COMPLETE_REQ);
      break;
    }
2082

francescomani's avatar
francescomani committed
2083 2084 2085 2086 2087 2088 2089 2090
    case OAI_TUN_IFACE_NSA: {
      LOG_I(NR_RRC, "We got an OAI_TUN_IFACE_NSA!!\n");
      char cmd_line[RRC_BUF_SIZE];
      memcpy(cmd_line, msg_buffer, sizeof(cmd_line));
      LOG_D(NR_RRC, "Command line: %s\n", cmd_line);
      if (background_system(cmd_line) != 0)
        LOG_E(NR_RRC, "ESM-PROC - failed command '%s'", cmd_line);
      break;
2091
    }
francescomani's avatar
francescomani committed
2092 2093 2094 2095

    default:
      LOG_E(NR_RRC, "No NSA Message Found\n");
  }
2096
}
2097

2098
void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
2099
                          NR_Release_Cause_t release_cause,
francescomani's avatar
francescomani committed
2100 2101 2102
                          NR_RRCRelease_t *RRCRelease)
{
  NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants;
2103

francescomani's avatar
francescomani committed
2104 2105 2106 2107 2108 2109 2110 2111 2112
  // if going to RRC_IDLE was triggered by reception
  // of the RRCRelease message including a waitTime
  NR_RejectWaitTime_t *waitTime = NULL;
  if (RRCRelease) {
    struct NR_RRCRelease_IEs *rrcReleaseIEs = RRCRelease->criticalExtensions.choice.rrcRelease;
    if(rrcReleaseIEs) {
      waitTime = rrcReleaseIEs->nonCriticalExtension ?
                 rrcReleaseIEs->nonCriticalExtension->waitTime : NULL;
      if (waitTime) {
2113
        nr_timer_stop(&tac->T302); // stop 302
francescomani's avatar
francescomani committed
2114
        // start timer T302 with the value set to the waitTime
2115 2116 2117
        int target = *waitTime * 1000; // waitTime is in seconds
        nr_timer_setup(&tac->T302, target, 10);
        nr_timer_start(&tac->T302);
2118
        // TODO inform upper layers that access barring is applicable
francescomani's avatar
francescomani committed
2119 2120 2121 2122 2123 2124
        // for all access categories except categories '0' and '2'.
        LOG_E(NR_RRC,"Go to IDLE. Handling RRCRelease message including a waitTime not implemented\n");
      }
    }
  }
  if (!waitTime) {
2125 2126
    if (is_nr_timer_active(tac->T302)) {
      nr_timer_stop(&tac->T302);
francescomani's avatar
francescomani committed
2127 2128 2129 2130 2131
      // TODO barring alleviation as in 5.3.14.4
      // not implemented
      LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n");
    }
  }
2132 2133
  if (is_nr_timer_active(tac->T390)) {
    nr_timer_stop(&tac->T390);
francescomani's avatar
francescomani committed
2134 2135 2136 2137 2138 2139 2140
    // TODO barring alleviation as in 5.3.14.4
    // not implemented
    LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n");
  }
  if (!RRCRelease && rrc->nrRrcState == RRC_STATE_INACTIVE_NR) {
    // TODO discard the cell reselection priority information provided by the cellReselectionPriorities
    // cell reselection priorities not implemented yet
2141
    nr_timer_stop(&tac->T320);
francescomani's avatar
francescomani committed
2142 2143
  }
  // Stop all the timers except T302, T320 and T325
2144 2145 2146 2147 2148 2149
  nr_timer_stop(&tac->T300);
  nr_timer_stop(&tac->T301);
  nr_timer_stop(&tac->T304);
  nr_timer_stop(&tac->T310);
  nr_timer_stop(&tac->T311);
  nr_timer_stop(&tac->T319);
francescomani's avatar
francescomani committed
2150 2151 2152 2153 2154 2155 2156 2157 2158 2159

  // discard the UE Inactive AS context
  // TODO there is no inactive AS context

  // release the suspendConfig
  // TODO suspendConfig not handled yet

  // discard the keys (only kgnb is stored)
  memset(rrc->kgnb, 0, sizeof(rrc->kgnb));

2160
  // release all radio resources, including release of the RLC entity,
francescomani's avatar
francescomani committed
2161 2162
  // the MAC configuration and the associated PDCP entity
  // and SDAP for all established RBs
2163 2164 2165
  for (int i = 1; i <= MAX_DRBS_PER_UE; i++) {
    if (get_DRB_status(rrc, i) != RB_NOT_PRESENT) {
      set_DRB_status(rrc, i, RB_NOT_PRESENT);
2166
      nr_pdcp_release_drb(rrc->ue_id, i);
2167
    }
2168 2169 2170 2171 2172
  }
  for (int i = 1; i < NR_NUM_SRB; i++) {
    if (rrc->Srb[i] != RB_NOT_PRESENT) {
      rrc->Srb[i] = RB_NOT_PRESENT;
      nr_pdcp_release_srb(rrc->ue_id, i);
2173
    }
2174 2175 2176 2177 2178
  }
  for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
    if (rrc->active_RLC_entity[i]) {
      rrc->active_RLC_entity[i] = false;
      nr_rlc_release_entity(rrc->ue_id, i);
2179 2180
    }
  }
francescomani's avatar
francescomani committed
2181 2182 2183 2184

  for (int i = 0; i < NB_CNX_UE; i++) {
    rrcPerNB_t *nb = &rrc->perNB[i];
    NR_UE_RRC_SI_INFO *SI_info = &nb->SInfo;
2185
    init_SI_timers(SI_info);
2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199
    asn1cFreeStruc(asn_DEF_NR_SIB1, SI_info->sib1);
    asn1cFreeStruc(asn_DEF_NR_SIB2, SI_info->sib2);
    asn1cFreeStruc(asn_DEF_NR_SIB3, SI_info->sib3);
    asn1cFreeStruc(asn_DEF_NR_SIB4, SI_info->sib4);
    asn1cFreeStruc(asn_DEF_NR_SIB5, SI_info->sib5);
    asn1cFreeStruc(asn_DEF_NR_SIB6, SI_info->sib6);
    asn1cFreeStruc(asn_DEF_NR_SIB7, SI_info->sib7);
    asn1cFreeStruc(asn_DEF_NR_SIB8, SI_info->sib8);
    asn1cFreeStruc(asn_DEF_NR_SIB9, SI_info->sib9);
    asn1cFreeStruc(asn_DEF_NR_SIB10_r16, SI_info->sib10);
    asn1cFreeStruc(asn_DEF_NR_SIB11_r16, SI_info->sib11);
    asn1cFreeStruc(asn_DEF_NR_SIB12_r16, SI_info->sib12);
    asn1cFreeStruc(asn_DEF_NR_SIB13_r16, SI_info->sib13);
    asn1cFreeStruc(asn_DEF_NR_SIB14_r16, SI_info->sib14);
francescomani's avatar
francescomani committed
2200 2201
  }

2202 2203 2204
  if (rrc->nrRrcState == RRC_STATE_DETACH_NR)
    asn1cFreeStruc(asn_DEF_NR_UE_NR_Capability, rrc->UECap.UE_NR_Capability);

2205
  // reset MAC
2206
  NR_UE_MAC_reset_cause_t cause = (rrc->nrRrcState == RRC_STATE_DETACH_NR) ? DETACH : GO_TO_IDLE;
2207
  nr_rrc_mac_config_req_reset(rrc->ue_id, cause);
francescomani's avatar
francescomani committed
2208 2209

  // enter RRC_IDLE
2210 2211 2212 2213
  LOG_I(NR_RRC, "RRC moved into IDLE state\n");
  if (rrc->nrRrcState != RRC_STATE_DETACH_NR)
    rrc->nrRrcState = RRC_STATE_IDLE_NR;

francescomani's avatar
francescomani committed
2214
  rrc->rnti = 0;
2215 2216 2217 2218

  // Indicate the release of the RRC connection to upper layers
  MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_NAS_CONN_RELEASE_IND);
  NR_NAS_CONN_RELEASE_IND(msg_p).cause = release_cause;
2219
  itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p);
francescomani's avatar
francescomani committed
2220 2221
}

2222
void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
francescomani's avatar
francescomani committed
2223
{
2224 2225 2226
  rrc->ra_trigger = RRC_CONNECTION_SETUP;
  nr_rrc_ue_prepare_RRCSetupRequest(rrc);

francescomani's avatar
francescomani committed
2227 2228
  // reset MAC, release the MAC configuration
  NR_UE_MAC_reset_cause_t cause = T300_EXPIRY;
2229
  nr_rrc_mac_config_req_reset(rrc->ue_id, cause);
francescomani's avatar
francescomani committed
2230 2231 2232
  // TODO handle connEstFailureControl
  // TODO inform upper layers about the failure to establish the RRC connection
}
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246

//This calls the sidelink preconf message after RRC, MAC instances are created.
void start_sidelink(int instance)
{

  NR_UE_RRC_INST_t *rrc = &NR_UE_rrc_inst[instance];

  if (get_softmodem_params()->sl_mode == 2) {

    //Process the Sidelink Preconfiguration
    rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref);

  }
}