From e5216cdba321e48fffab178458f6e7c4a1e27c2d Mon Sep 17 00:00:00 2001
From: Xue Song <xuesong@cn.fujitsu.com>
Date: Thu, 17 Sep 2020 07:55:05 +0000
Subject: [PATCH] Handle NGAP Initial Context Setup Request message from NGAP
 task

---
 openair2/RRC/NR/nr_rrc_defs.h  |   2 +
 openair2/RRC/NR/nr_rrc_proto.h |   6 +-
 openair2/RRC/NR/rrc_gNB_NGAP.c | 109 ++++++++++++++++++++++++++++++++-
 openair2/RRC/NR/rrc_gNB_NGAP.h |   7 +++
 4 files changed, 122 insertions(+), 2 deletions(-)

diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index 9590989f41..372d7b66ef 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -314,6 +314,8 @@ typedef struct gNB_RRC_UE_s {
 
   /* Information from S1AP initial_context_setup_req */
   uint32_t                           gNB_ue_s1ap_id :24;
+  uint32_t                           gNB_ue_ngap_id;
+  uint64_t                           amf_ue_ngap_id:40;
   nr_rrc_guami_t                     ue_guami;
 
   security_capabilities_t            security_capabilities;
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 317282c814..2f6da02776 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -91,7 +91,11 @@ int generate_CG_Config(gNB_RRC_INST *rrc,
 
 int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m);
 
-
+void
+rrc_gNB_generate_SecurityModeCommand(
+  const protocol_ctxt_t *const ctxt_pP,
+  rrc_gNB_ue_context_t          *const ue_context_pP
+);
 
 /**\brief RRC eNB task.
    \param void *args_p Pointer on arguments to start the task. */
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c
index 51956f6a6e..15ed5982b2 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.c
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.c
@@ -67,6 +67,45 @@ get_next_ue_initial_id(
     return ue_initial_id[mod_id];
 }
 
+//------------------------------------------------------------------------------
+/*
+* Get the UE NG struct containing hashtables NG_id/UE_id.
+* Is also used to set the NG_id of the UE, depending on inputs.
+*/
+struct rrc_ue_ngap_ids_s *
+rrc_gNB_NGAP_get_ue_ids(
+    gNB_RRC_INST   *const rrc_instance_pP,
+    const uint16_t ue_initial_id,
+    const uint32_t gNB_ue_ngap_idP
+)
+//------------------------------------------------------------------------------
+{
+    rrc_ue_ngap_ids_t *result = NULL;
+
+    /* TODO */
+
+    return result;
+}
+
+//------------------------------------------------------------------------------
+static struct rrc_gNB_ue_context_s *
+rrc_gNB_get_ue_context_from_ngap_ids(
+    const instance_t  instanceP,
+    const uint16_t    ue_initial_idP,
+    const uint32_t    gNB_ue_ngap_idP
+) 
+//------------------------------------------------------------------------------
+{
+    rrc_ue_ngap_ids_t *temp = NULL;
+    temp = rrc_gNB_NGAP_get_ue_ids(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instanceP)], ue_initial_idP, gNB_ue_ngap_idP);
+
+    if (temp != NULL) {
+        return rrc_gNB_get_ue_context(RC.nrrrc[GNB_INSTANCE_TO_MODULE_ID(instanceP)], temp->ue_rnti);
+    }
+
+    return NULL;
+}
+
 //------------------------------------------------------------------------------
 /*
 * Initial UE NAS message on S1AP.
@@ -184,4 +223,72 @@ rrc_gNB_send_NGAP_NAS_FIRST_REQ(
     }
 
     itti_send_msg_to_task (TASK_NGAP, ctxt_pP->instance, message_p);
-}
\ No newline at end of file
+}
+
+//------------------------------------------------------------------------------
+int
+rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(
+    MessageDef *msg_p,
+    const char *msg_name,
+    instance_t instance
+)
+//------------------------------------------------------------------------------
+{
+    uint16_t                        ue_initial_id;
+    uint32_t                        gNB_ue_ngap_id;
+    rrc_gNB_ue_context_t            *ue_context_p = NULL;
+    protocol_ctxt_t                 ctxt;
+
+    ue_initial_id  = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).ue_initial_id;
+    gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ(msg_p).gNB_ue_ngap_id;
+
+    ue_context_p   = rrc_gNB_get_ue_context_from_ngap_ids(instance, ue_initial_id, gNB_ue_ngap_id);
+    LOG_I(NR_RRC, "[gNB %d] Received %s: ue_initial_id %d, gNB_ue_ngap_id %d \n",
+        instance, msg_name, ue_initial_id, gNB_ue_ngap_id);
+
+    if (ue_context_p == NULL) {
+        /* Can not associate this message to an UE index, send a failure to NGAP and discard it! */
+        MessageDef *msg_fail_p = NULL;
+        LOG_W(NR_RRC, "[gNB %d] In NGAP_INITIAL_CONTEXT_SETUP_REQ: unknown UE from S1AP ids (%d, %d)\n", instance, ue_initial_id, gNB_ue_ngap_id);
+        msg_fail_p = itti_alloc_new_message (TASK_RRC_GNB, NGAP_INITIAL_CONTEXT_SETUP_FAIL);
+        NGAP_INITIAL_CONTEXT_SETUP_FAIL (msg_fail_p).gNB_ue_ngap_id = gNB_ue_ngap_id;
+        // TODO add failure cause when defined!
+        itti_send_msg_to_task (TASK_NGAP, instance, msg_fail_p);
+        return (-1);
+    } else {
+        PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_YES, ue_context_p->ue_context.rnti, 0, 0);
+        ue_context_p->ue_context.gNB_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).gNB_ue_ngap_id;
+        ue_context_p->ue_context.amf_ue_ngap_id = NGAP_INITIAL_CONTEXT_SETUP_REQ (msg_p).amf_ue_ngap_id;
+        
+        /* TODO security */
+        uint8_t send_security_mode_command = TRUE;
+
+        /* TODO rrc_pdcp_config_security */
+        // rrc_pdcp_config_security(
+        //     &ctxt,
+        //     ue_context_p,
+        //     send_security_mode_command);
+
+        if (send_security_mode_command) {
+            rrc_gNB_generate_SecurityModeCommand (&ctxt, ue_context_p);
+            send_security_mode_command = FALSE;
+
+            /* TODO rrc_pdcp_config_security */
+            // rrc_pdcp_config_security(
+            //     &ctxt,
+            //     ue_context_p,
+            //     send_security_mode_command);
+        } else {
+            /* TODO rrc_gNB_generate_UECapabilityEnquiry */
+            // rrc_gNB_generate_UECapabilityEnquiry (&ctxt, ue_context_p);
+        }
+
+        // in case, send the S1SP initial context response if it is not sent with the attach complete message
+        if (ue_context_p->ue_context.Status == NR_RRC_RECONFIGURED) {
+            LOG_I(NR_RRC, "Sending rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP, cause %ld\n", ue_context_p->ue_context.reestablishment_cause);
+            // rrc_gNB_send_NGAP_INITIAL_CONTEXT_SETUP_RESP(&ctxt,ue_context_p);
+        }
+
+        return 0;
+    }
+}
diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h
index 21f9fcb3ee..50b588f01d 100644
--- a/openair2/RRC/NR/rrc_gNB_NGAP.h
+++ b/openair2/RRC/NR/rrc_gNB_NGAP.h
@@ -48,4 +48,11 @@ rrc_gNB_send_NGAP_NAS_FIRST_REQ(
     NR_RRCSetupComplete_IEs_t *rrcSetupComplete
 );
 
+int
+rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(
+    MessageDef *msg_p,
+    const char *msg_name,
+    instance_t instance
+);
+
 #endif
-- 
2.26.2