From bd30471076e9624c9c3041fb138fba87e9f8248e Mon Sep 17 00:00:00 2001
From: gabrielC <couturier.gabriel@gmail.com>
Date: Thu, 8 Dec 2016 11:07:38 +0100
Subject: [PATCH]   [OAI-UE] merge com4Innov branch to integration branch

---
 cmake_targets/CMakeLists.txt                  |  4 +-
 openair1/PHY/defs.h                           |  2 +-
 openair2/COMMON/commonDef.h                   |  2 +-
 openair2/LAYER2/MAC/ue_procedures.c           |  2 +-
 openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c      |  2 +-
 openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c        | 18 +++++-
 openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h        |  2 +-
 openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c   |  8 +--
 openair2/LAYER2/RLC/rlc_mac.c                 |  2 +-
 openair2/NETWORK_DRIVER/UE_IP/common.c        |  5 +-
 openair3/NAS/COMMON/EMM/MSG/AttachAccept.c    |  3 +-
 .../COMMON/EMM/MSG/AuthenticationRequest.c    |  2 +-
 .../NAS/COMMON/EMM/MSG/SecurityModeCommand.c  |  2 +
 .../NAS/COMMON/EMM/MSG/SecurityModeComplete.c |  5 +-
 openair3/NAS/COMMON/IES/EmergencyNumberList.c | 54 ++++++++++++++----
 openair3/NAS/COMMON/IES/EmergencyNumberList.h | 10 +++-
 openair3/NAS/COMMON/IES/MobileIdentity.c      | 15 +++--
 openair3/NAS/COMMON/IES/MobileIdentity.h      | 57 ++++++++++++++++++-
 openair3/NAS/UE/EMM/SAP/emm_asDef.h           |  1 +
 openair3/NAS/UE/EMM/SAP/emm_recv.c            |  4 +-
 openair3/NAS/UE/EMM/SAP/emm_send.c            | 29 ++++++++++
 openair3/NAS/UE/EMM/SecurityModeControl.c     |  3 +-
 openair3/NAS/UE/EMM/emm_proc.h                |  2 +-
 targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c    |  4 +-
 24 files changed, 194 insertions(+), 44 deletions(-)

diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 07d92a1b0..891001ecb 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -644,7 +644,7 @@ add_boolean_option(ENABLE_USE_CPU_EXECUTION_TIME True "Add data in vcd traces: d
 add_boolean_option(ENABLE_VCD              True  "always true now, time measurements of proc calls and var displays")
 add_boolean_option(ENABLE_VCD_FIFO         True  "time measurements of proc calls and var displays sent to FIFO (one more thread)")
 add_boolean_option(HARD_RT                 False "???")
-add_boolean_option(LINUX                   False "used in weird memcpy() in pdcp.c ???")
+add_boolean_option(LINUX                   True "used in weird memcpy() in pdcp.c ???")
 add_boolean_option(LINUX_LIST              False "used only in lists.c: either use OAI implementation of lists or Linux one (should be True, but it is False")
 add_boolean_option(LOG_NO_THREAD           True  "Disable thread for log, seems always set to true")
 add_boolean_option(OPENAIR_LTE             True "Seems legacy: keep it to true")
@@ -727,7 +727,7 @@ add_boolean_option(TRACE_RLC_UM_TX_STATUS  False "TRACE for RLC UM, TO BE CHANGE
 ##########################
 # PDCP LAYER OPTIONS
 ##########################
-add_boolean_option(PDCP_USE_NETLINK            False "For eNB, PDCP communicate with a NETLINK socket if connected to network driver, else could use a RT-FIFO")
+add_boolean_option(PDCP_USE_NETLINK            True "For eNB, PDCP communicate with a NETLINK socket if connected to network driver, else could use a RT-FIFO")
 add_boolean_option(PDCP_USE_NETLINK_QUEUES     False "When PDCP_USE_NETLINK is true, incoming IP packets are stored in queues")
 add_boolean_option(LINK_ENB_PDCP_TO_IP_DRIVER  False "For eNB, PDCP communicate with a IP driver")
 add_boolean_option(LINK_ENB_PDCP_TO_GTPV1U     True  "For eNB, PDCP communicate with GTP-U protocol (eNB<->S-GW)")
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 375efa5fe..0e69265d2 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -656,7 +656,7 @@ typedef struct {
   /// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime)
   uint32_t rx_gain_byp[4];
   /// \brief Current transmit power
-  int8_t tx_power_dBm[10];
+  int16_t tx_power_dBm[10];
   /// \brief Total number of REs in current transmission
   int tx_total_RE[10];
   /// \brief Maximum transmit power
diff --git a/openair2/COMMON/commonDef.h b/openair2/COMMON/commonDef.h
index cfd5d68e4..ae1bdaf99 100644
--- a/openair2/COMMON/commonDef.h
+++ b/openair2/COMMON/commonDef.h
@@ -119,7 +119,7 @@ typedef struct {
       Byte_t digit14:4;
       Byte_t digit13:4;
 #define EVEN_PARITY 0
-#define ODD_PARITY  1
+#define ODD_PARITY  0xf
       Byte_t parity:4;
       Byte_t digit15:4;
     } num;
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index 886ccff23..642475a06 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -1356,7 +1356,7 @@ void ue_get_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subf
         // Trigger BSR Periodic
       UE_mac_inst[module_idP].BSR_reporting_active |= BSR_TRIGGER_PERIODIC;
 
-      LOG_I(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
+      LOG_D(MAC,"[UE %d] MAC BSR Triggered PeriodicBSR Timer expiry at frame%d subframe %d TBS=%d\n",
                        module_idP, frameP, subframe, buflen);
 
     }
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
index 17808c03f..fedef42b6 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c
@@ -493,7 +493,7 @@ int pdcp_fifo_read_input_sdus (const protocol_ctxt_t* const  ctxt_pP)
           ctxt.enb_flag      = ctxt_cpy.enb_flag;
 
 #ifdef PDCP_DEBUG
-          LOG_I(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d\n", pdcp_read_header_g.rb_id);
+          LOG_D(PDCP, "[PDCP][NETLINK] pdcp_read_header_g.rb_id = %d\n", pdcp_read_header_g.rb_id);
 #endif
 
           if (ctxt_cpy.enb_flag) {
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
index 3232399d1..51440d0bf 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.c
@@ -426,7 +426,7 @@ rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, void *argP, struct mac_data_ind
 
 //-----------------------------------------------------------------------------
 struct mac_status_resp
-rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP)
+rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP,const eNB_flag_t enb_flagP)
 {
   struct mac_status_resp status_resp;
   uint16_t  sdu_size = 0;
@@ -434,6 +434,7 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
   int32_t diff_time=0;
   rlc_um_entity_t   *rlc_p = NULL;
   mem_block_t       *mb_p = NULL;
+  unsigned int       max_li_overhead = 0;
 
   status_resp.buffer_occupancy_in_pdus         = 0;
   status_resp.buffer_occupancy_in_bytes        = 0;
@@ -453,7 +454,20 @@ rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, void *rlc_pP
 
     if ((status_resp.buffer_occupancy_in_bytes > 0) && ((mb_p = list_get_head(&rlc_p->input_sdus)) != NULL)) {
 
-      status_resp.buffer_occupancy_in_bytes += rlc_p->tx_header_min_length_in_bytes;
+        //Fix on full Header size
+        if (enb_flagP == ENB_FLAG_NO)
+        {
+            // compute Length Indicator overhead to inform MAC of maximum full RLC PDU size according to stored SDUs
+            // For UE scheduler
+            // Could be useful for eNB: to be checked
+            if (rlc_p->input_sdus.nb_elements <= 1) {
+                max_li_overhead = 0;
+            } else {
+                unsigned int       num_li = rlc_p->input_sdus.nb_elements - 1;
+                max_li_overhead = num_li + (num_li >> 1) + (num_li & 1);
+            }
+        }
+      status_resp.buffer_occupancy_in_bytes += (rlc_p->tx_header_min_length_in_bytes + max_li_overhead);
       status_resp.buffer_occupancy_in_pdus = rlc_p->input_sdus.nb_elements;
 
       diff_time =   ctxt_pP->frame - ((struct rlc_um_tx_sdu_management *)mb_p->data)->sdu_creation_time;
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
index d87f1e29d..5951eaf14 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um.h
@@ -186,7 +186,7 @@ protected_rlc_um( void     rlc_um_rx (const protocol_ctxt_t* const ctxt_pP, rlc_
 * \param[in]  tx_statusP                Transmission status given by MAC on previous MAC transmission of the PDU.
 * \return     The maximum number of bytes that can be served by RLC instance to MAC.
 */
-public_rlc_um(    struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP);)
+public_rlc_um(    struct mac_status_resp rlc_um_mac_status_indication (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP, uint16_t tbs_sizeP, struct mac_status_ind tx_statusP, const eNB_flag_t enb_flagP);)
 
 /*! \fn struct mac_data_req rlc_um_mac_data_request (const protocol_ctxt_t* const ctxt_pP, rlc_um_entity_t * const rlc_pP)
 * \brief    Gives PDUs to lower layer MAC.
diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
index c9a82e12f..92f18e72d 100644
--- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
+++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_test.c
@@ -471,9 +471,9 @@ void rlc_um_v9_3_0_test_exchange_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP, g_frame);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP, g_frame);
 
 
@@ -517,9 +517,9 @@ void rlc_um_v9_3_0_test_exchange_delayed_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, g_frame, 1, bytes_txP, tx_status,ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP, g_frame);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, g_frame, 0, bytes_rxP, tx_status,ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP, g_frame);
 
 
diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c
index 6462bb9ab..d59b187dc 100644
--- a/openair2/LAYER2/RLC/rlc_mac.c
+++ b/openair2/LAYER2/RLC/rlc_mac.c
@@ -406,7 +406,7 @@ mac_rlc_status_resp_t mac_rlc_status_ind(
     break;
 
   case RLC_MODE_UM:
-    status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status);
+    status_resp = rlc_um_mac_status_indication(&ctxt, &rlc_union_p->rlc.um, tb_sizeP, tx_status, enb_flagP);
     mac_rlc_status_resp.bytes_in_buffer                 = status_resp.buffer_occupancy_in_bytes;
     mac_rlc_status_resp.pdus_in_buffer                  = status_resp.buffer_occupancy_in_pdus;
     mac_rlc_status_resp.head_sdu_creation_time          = status_resp.head_sdu_creation_time;
diff --git a/openair2/NETWORK_DRIVER/UE_IP/common.c b/openair2/NETWORK_DRIVER/UE_IP/common.c
index 6bef269de..869680159 100644
--- a/openair2/NETWORK_DRIVER/UE_IP/common.c
+++ b/openair2/NETWORK_DRIVER/UE_IP/common.c
@@ -99,7 +99,8 @@ ue_ip_common_class_wireless2ip(
   hard_header_len = ue_ip_dev[instP]->hard_header_len;
 
   skb_set_mac_header(skb_p, 0);
-
+  skb_set_network_header(skb_p, hard_header_len);
+skb_p->mark = rb_idP;
   //printk("[NAC_COMMIN_RECEIVE]: Packet Type %d (%d,%d)",skb_p->pkt_type,PACKET_HOST,PACKET_BROADCAST);
   skb_p->pkt_type = PACKET_HOST;
 
@@ -344,7 +345,7 @@ void ue_ip_common_wireless2ip(struct nlmsghdr *nlh_pP)
 
   ue_ip_common_class_wireless2ip(pdcph_p->data_size,
                                  (unsigned char *)NLMSG_DATA(nlh_pP) + UE_IP_PDCPH_SIZE,
-                                 pdcph_p->inst,
+                                 1, //pdcph_p->inst,
                                  pdcph_p->rb_id);
 
 }
diff --git a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
index cec2d1697..248540dff 100644
--- a/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
+++ b/openair3/NAS/COMMON/EMM/MSG/AttachAccept.c
@@ -188,10 +188,11 @@ int decode_attach_accept(attach_accept_msg *attach_accept, uint8_t *buffer, uint
 
     default:
       errorCodeDecoder = TLV_DECODE_UNEXPECTED_IEI;
+      LOG_TRACE(WARNING, "DECODE_UNEXPECTED_IEI %x (4 bits)", ieiDecoded);
       return TLV_DECODE_UNEXPECTED_IEI;
     }
   }
-
+  LOG_TRACE(WARNING, "DECODED %d\n", decoded);
   return decoded;
 }
 
diff --git a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
index fac93c5df..3e0bffde2 100644
--- a/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
+++ b/openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c
@@ -38,7 +38,7 @@ int decode_authentication_request(authentication_request_msg *authentication_req
   CHECK_PDU_POINTER_AND_LENGTH_DECODER(buffer, AUTHENTICATION_REQUEST_MINIMUM_LENGTH, len);
 
   /* Decoding mandatory fields */
-  if ((decoded_result = decode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded) >> 4, len - decoded)) < 0)
+  if ((decoded_result = decode_u8_nas_key_set_identifier(&authentication_request->naskeysetidentifierasme, 0, *(buffer + decoded), len - decoded)) < 0)
     return decoded_result;
 
   decoded++;
diff --git a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
index aeec3d402..c89a9f5bb 100644
--- a/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
+++ b/openair3/NAS/COMMON/EMM/MSG/SecurityModeCommand.c
@@ -72,6 +72,8 @@ int decode_security_mode_command(security_mode_command_msg *security_mode_comman
       decoded += decoded_result;
       /* Set corresponding mask to 1 in presencemask */
       security_mode_command->presencemask |= SECURITY_MODE_COMMAND_IMEISV_REQUEST_PRESENT;
+      LOG_I(NAS," SECURITY MODE COMMAND: IMEISV_REQUEST: %d \n",security_mode_command->imeisvrequest);
+
       break;
 
     case SECURITY_MODE_COMMAND_REPLAYED_NONCEUE_IEI:
diff --git a/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c b/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
index f10401d09..80ceeb34d 100644
--- a/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
+++ b/openair3/NAS/COMMON/EMM/MSG/SecurityModeComplete.c
@@ -76,8 +76,11 @@ int encode_security_mode_complete(security_mode_complete_msg *security_mode_comp
   /* Checking IEI and pointer */
   CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, SECURITY_MODE_COMPLETE_MINIMUM_LENGTH, len);
 
+  LOG_I(NAS,"SECURITY MODE COMMAND COMPLETE:  presencemask: %d \n",security_mode_complete->presencemask);
+
   if ((security_mode_complete->presencemask & SECURITY_MODE_COMPLETE_IMEISV_PRESENT)
       == SECURITY_MODE_COMPLETE_IMEISV_PRESENT) {
+	  LOG_I(NAS,"SECURITY MODE COMMAND COMPLETE: encode imeisv \n");
     if ((encode_result =
            encode_mobile_identity(&security_mode_complete->imeisv,
                                   SECURITY_MODE_COMPLETE_IMEISV_IEI, buffer + encoded, len -
@@ -87,7 +90,7 @@ int encode_security_mode_complete(security_mode_complete_msg *security_mode_comp
     else
       encoded += encode_result;
   }
-
+  LOG_I(NAS,"SECURITY MODE COMMAND COMPLETE done !!! \n");
   return encoded;
 }
 
diff --git a/openair3/NAS/COMMON/IES/EmergencyNumberList.c b/openair3/NAS/COMMON/IES/EmergencyNumberList.c
index 39b59ef0c..9330fdc31 100644
--- a/openair3/NAS/COMMON/IES/EmergencyNumberList.c
+++ b/openair3/NAS/COMMON/IES/EmergencyNumberList.c
@@ -41,10 +41,24 @@ int decode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8
   ielen = *(buffer + decoded);
   decoded++;
   CHECK_LENGTH_DECODER(len - decoded, ielen);
-  emergencynumberlist->lengthofemergency = *(buffer + decoded);
-  decoded++;
-  emergencynumberlist->emergencyservicecategoryvalue = *(buffer + decoded) & 0x1f;
-  decoded++;
+  int information_element_index = 0;
+  while ((decoded < ielen) && (information_element_index < EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION)) {
+    emergencynumberlist->emergency_number_information[information_element_index].lengthofemergency = *(buffer + decoded);
+    decoded++;
+    emergencynumberlist->emergency_number_information[information_element_index].emergencyservicecategoryvalue = *(buffer + decoded) & 0x1f;
+    decoded++;
+    int remaining_len = emergencynumberlist->emergency_number_information[information_element_index].lengthofemergency - 1;
+    int digit_index = 0;
+    while (remaining_len > 0) {
+    	emergencynumberlist->emergency_number_information[information_element_index].bcd_digits[digit_index++] = *(buffer + decoded);
+        decoded++;
+        remaining_len --;
+    }
+    while (digit_index < EMERGENCY_NUMBER_LIST_MAX_2DIGITS) {
+    	emergencynumberlist->emergency_number_information[information_element_index].bcd_digits[digit_index++] = 0xFF;
+    }
+    information_element_index++;
+  }
 #if defined (NAS_DEBUG)
   dump_emergency_number_list_xml(emergencynumberlist, iei);
 #endif
@@ -67,11 +81,16 @@ int encode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8
 
   lenPtr  = (buffer + encoded);
   encoded ++;
-  *(buffer + encoded) = emergencynumberlist->lengthofemergency;
-  encoded++;
-  *(buffer + encoded) = 0x00 |
-                        (emergencynumberlist->emergencyservicecategoryvalue & 0x1f);
-  encoded++;
+  for (  int ie_index = 0; ie_index < emergencynumberlist->num_emergency_elements; ie_index++) {
+	  *(buffer + encoded) = emergencynumberlist->emergency_number_information[ie_index].lengthofemergency;
+	  encoded++;
+	  *(buffer + encoded) = 0x00 |
+	                        (emergencynumberlist->emergency_number_information[ie_index].emergencyservicecategoryvalue & 0x1f);
+	  encoded++;
+	  for (int bcd2_index = 0; bcd2_index < (emergencynumberlist->emergency_number_information[ie_index].lengthofemergency - 1); bcd2_index++) {
+		  *(buffer + encoded) = emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index];
+	  }
+  }
   *lenPtr = encoded - 1 - ((iei > 0) ? 1 : 0);
   return encoded;
 }
@@ -83,9 +102,20 @@ void dump_emergency_number_list_xml(EmergencyNumberList *emergencynumberlist, ui
   if (iei > 0)
     /* Don't display IEI if = 0 */
     printf("    <IEI>0x%X</IEI>\n", iei);
-
-  printf("    <Length of emergency>%u</Length of emergency>\n", emergencynumberlist->lengthofemergency);
-  printf("    <Emergency service category value>%u</Emergency service category value>\n", emergencynumberlist->emergencyservicecategoryvalue);
+  for (  int ie_index = 0; ie_index < emergencynumberlist->num_emergency_elements; ie_index++) {
+	  printf("    <Length of emergency>%u</Length of emergency>\n", emergencynumberlist->emergency_number_information[ie_index].lengthofemergency);
+	  printf("    <Emergency service category value>%u</Emergency service category value>\n", emergencynumberlist->emergency_number_information[ie_index].emergencyservicecategoryvalue);
+	  for (int bcd2_index = 0; bcd2_index < (emergencynumberlist->emergency_number_information[ie_index].lengthofemergency - 1); bcd2_index++) {
+		  uint8_t bcd1 = emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index] & 0x0f;
+		  uint8_t bcd2 = (emergencynumberlist->emergency_number_information[ie_index].bcd_digits[bcd2_index] & 0xf0) >> 4;
+		  if (bcd1 < 10) {
+		    printf("    <BCD Digit%u>%u</BCD Digit%u>\n", (bcd2_index*2)+1, bcd1, (bcd2_index*2)+1);
+		    if (bcd2 < 10) {
+		    	printf("    <BCD Digit%u>%u</BCD Digit%u>\n", (bcd2_index*2)+2, bcd2, (bcd2_index*2)+2);
+		    }
+		  }
+	  }
+  }
   printf("</Emergency Number List>\n");
 }
 
diff --git a/openair3/NAS/COMMON/IES/EmergencyNumberList.h b/openair3/NAS/COMMON/IES/EmergencyNumberList.h
index d2fd149dc..ab47c1ff0 100644
--- a/openair3/NAS/COMMON/IES/EmergencyNumberList.h
+++ b/openair3/NAS/COMMON/IES/EmergencyNumberList.h
@@ -32,8 +32,14 @@
 #define EMERGENCY_NUMBER_LIST_MAXIMUM_LENGTH 50
 
 typedef struct EmergencyNumberList_tag {
-  uint8_t  lengthofemergency;
-  uint8_t  emergencyservicecategoryvalue:5;
+  uint8_t  num_emergency_elements;
+  struct {
+    uint8_t  lengthofemergency;
+    uint8_t  emergencyservicecategoryvalue:5;
+#define EMERGENCY_NUMBER_LIST_MAX_2DIGITS 6
+    uint8_t  bcd_digits[EMERGENCY_NUMBER_LIST_MAX_2DIGITS]; // length to be fixed
+#define EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION 2
+  } emergency_number_information[EMERGENCY_NUMBER_LIST_MAX_NUMBER_INFORMATION];
 } EmergencyNumberList;
 
 int encode_emergency_number_list(EmergencyNumberList *emergencynumberlist, uint8_t iei, uint8_t *buffer, uint32_t len);
diff --git a/openair3/NAS/COMMON/IES/MobileIdentity.c b/openair3/NAS/COMMON/IES/MobileIdentity.c
index 7ab30011c..59cf4dc44 100644
--- a/openair3/NAS/COMMON/IES/MobileIdentity.c
+++ b/openair3/NAS/COMMON/IES/MobileIdentity.c
@@ -575,6 +575,8 @@ static int encode_imei_mobile_identity(ImeiMobileIdentity_t *imei, uint8_t *buff
 static int encode_imeisv_mobile_identity(ImeisvMobileIdentity_t *imeisv, uint8_t *buffer)
 {
   uint32_t encoded = 0;
+  LOG_I(NAS,"SECURITY MODE COMMAND COMPLETE: encode_imeisv_mobile_identity \n");
+
   *(buffer + encoded) = 0x00 | (imeisv->digit1 << 4) | (imeisv->oddeven << 3) |
                         (imeisv->typeofidentity);
   encoded++;
@@ -590,12 +592,15 @@ static int encode_imeisv_mobile_identity(ImeisvMobileIdentity_t *imeisv, uint8_t
   encoded++;
   *(buffer + encoded) = 0x00 | (imeisv->digit13 << 4) | imeisv->digit12;
   encoded++;
+  *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
+  encoded++;
+  *(buffer + encoded) = 0x00 | (imeisv->parity << 4) | imeisv->digit16;
 
-  if (imeisv->oddeven != MOBILE_IDENTITY_EVEN) {
-    *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
-  } else {
-    *(buffer + encoded) = 0xf0 | imeisv->digit14;
-  }
+  //if (imeisv->oddeven != MOBILE_IDENTITY_EVEN) {
+  //  *(buffer + encoded) = 0x00 | (imeisv->digit15 << 4) | imeisv->digit14;
+  //} else {
+  //  *(buffer + encoded) = 0xf0 | imeisv->digit14;
+  //}
 
   encoded++;
   return encoded;
diff --git a/openair3/NAS/COMMON/IES/MobileIdentity.h b/openair3/NAS/COMMON/IES/MobileIdentity.h
index 8d1c5cdbe..9c082c12d 100644
--- a/openair3/NAS/COMMON/IES/MobileIdentity.h
+++ b/openair3/NAS/COMMON/IES/MobileIdentity.h
@@ -73,8 +73,63 @@ typedef struct {
   uint8_t  mbmssessionid;
 } TmgiMobileIdentity_t;
 
+typedef struct imeisv_s{
+  uint8_t  digit1:4;
+  uint8_t  oddeven:1;
+  uint8_t  typeofidentity:3;
+  uint8_t  digit2:4;
+  uint8_t  digit3:4;
+  uint8_t  digit4:4;
+  uint8_t  digit5:4;
+  uint8_t  digit6:4;
+  uint8_t  digit7:4;
+  uint8_t  digit8:4;
+  uint8_t  digit9:4;
+  uint8_t  digit10:4;
+  uint8_t  digit11:4;
+  uint8_t  digit12:4;
+  uint8_t  digit13:4;
+  uint8_t  digit14:4;
+  uint8_t  digit15:4;
+  uint8_t  digit16:4;
+#define EVEN_PARITY 0
+#define ODD_PARITY  1
+       uint8_t parity:4;
+} imeisv_t;
+
+#if 0
+typedef struct imeisv_s {
+   uint8_t length;
+   union {
+     struct {
+       uint8_t tac2:4;
+       uint8_t tac1:4;
+       uint8_t tac4:4;
+       uint8_t tac3:4;
+       uint8_t tac6:4;
+       uint8_t tac5:4;
+       uint8_t tac8:4;
+       uint8_t tac7:4;
+       uint8_t snr2:4;
+       uint8_t snr1:4;
+       uint8_t snr4:4;
+       uint8_t snr3:4;
+       uint8_t snr6:4;
+       uint8_t snr5:4;
+       uint8_t svn2:4;
+       uint8_t svn1:4;
+#define EVEN_PARITY 0
+#define ODD_PARITY  1
+       uint8_t parity:4;
+     } num;
+#define IMEISV_BCD8_SIZE   9
+     uint8_t value[IMEISV_BCD8_SIZE];
+   } u;
+} imeisv_t;
+#endif
+
 typedef ImsiMobileIdentity_t ImeiMobileIdentity_t;
-typedef ImsiMobileIdentity_t ImeisvMobileIdentity_t;
+typedef imeisv_t             ImeisvMobileIdentity_t;
 typedef ImsiMobileIdentity_t TmsiMobileIdentity_t;
 typedef ImsiMobileIdentity_t NoMobileIdentity_t;
 
diff --git a/openair3/NAS/UE/EMM/SAP/emm_asDef.h b/openair3/NAS/UE/EMM/SAP/emm_asDef.h
index bf0e6f6c3..69ea979b6 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_asDef.h
+++ b/openair3/NAS/UE/EMM/SAP/emm_asDef.h
@@ -120,6 +120,7 @@ typedef struct emm_as_security_s {
   uint8_t ucs2;
   uint8_t uia;        /* Replayed UMTS integrity algorithms   */
   uint8_t gea;        /* Replayed GPRS encryption algorithms   */
+  uint8_t imeisv_request;
   uint8_t umts_present;
   uint8_t gprs_present;
 
diff --git a/openair3/NAS/UE/EMM/SAP/emm_recv.c b/openair3/NAS/UE/EMM/SAP/emm_recv.c
index a79a14d9c..60b504f1c 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_recv.c
+++ b/openair3/NAS/UE/EMM/SAP/emm_recv.c
@@ -472,13 +472,15 @@ int emm_recv_security_mode_command(security_mode_command_msg *msg,
    * Message processing
    */
   /* Execute the security mode control procedure initiated by the network */
+  LOG_I(NAS,"Execute the security mode control procedure initiated by the network:  imeisvrequest %d\n",msg->imeisvrequest);
   rc = emm_proc_security_mode_command(
          msg->naskeysetidentifier.tsc != NAS_KEY_SET_IDENTIFIER_MAPPED,
          msg->naskeysetidentifier.naskeysetidentifier,
          msg->selectednassecurityalgorithms.typeofcipheringalgorithm,
          msg->selectednassecurityalgorithms.typeofintegrityalgorithm,
          msg->replayeduesecuritycapabilities.eea,
-         msg->replayeduesecuritycapabilities.eia);
+         msg->replayeduesecuritycapabilities.eia,
+		 msg->imeisvrequest & 0x7);
 
   LOG_FUNC_RETURN (rc);
 }
diff --git a/openair3/NAS/UE/EMM/SAP/emm_send.c b/openair3/NAS/UE/EMM/SAP/emm_send.c
index 7e13d03c7..e960b8584 100644
--- a/openair3/NAS/UE/EMM/SAP/emm_send.c
+++ b/openair3/NAS/UE/EMM/SAP/emm_send.c
@@ -855,6 +855,35 @@ int emm_send_security_mode_complete(const emm_as_security_t *msg,
   /* Mandatory - Message type */
   emm_msg->messagetype = SECURITY_MODE_COMPLETE;
 
+  if(msg->imeisv_request)
+  {
+	  // configure imeisv param
+	  emm_msg->presencemask |= SECURITY_MODE_COMPLETE_IMEISV_PRESENT;
+
+	  // 33 85 76 02 05 26 84 01 F1
+	  emm_msg->imeisv.imeisv;
+	  emm_msg->imeisv.imeisv.digit1         = 0x3;
+	  emm_msg->imeisv.imeisv.oddeven        = 0x0;
+	  emm_msg->imeisv.imeisv.typeofidentity = 0x3;
+	  emm_msg->imeisv.imeisv.digit2         = 0x5;
+	  emm_msg->imeisv.imeisv.digit3         = 0x7;
+	  emm_msg->imeisv.imeisv.digit4         = 0x4;
+	  emm_msg->imeisv.imeisv.digit5         = 0x7;
+	  emm_msg->imeisv.imeisv.digit6         = 0x3;
+	  emm_msg->imeisv.imeisv.digit7         = 0x0;
+	  emm_msg->imeisv.imeisv.digit8         = 0x4;
+	  emm_msg->imeisv.imeisv.digit9         = 0x0;
+	  emm_msg->imeisv.imeisv.digit10        = 0x0;
+	  emm_msg->imeisv.imeisv.digit11        = 0x7;
+	  emm_msg->imeisv.imeisv.digit12        = 0x0;
+	  emm_msg->imeisv.imeisv.digit13        = 0x5;
+	  emm_msg->imeisv.imeisv.digit14        = 0x3;
+	  emm_msg->imeisv.imeisv.digit15        = 0x0;
+	  emm_msg->imeisv.imeisv.digit16        = 0x0;
+	  emm_msg->imeisv.imeisv.parity         = ODD_PARITY;
+
+	  size += SECURITY_MODE_COMPLETE_MAXIMUM_LENGTH;
+  }
   LOG_FUNC_RETURN (size);
 }
 
diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c
index 7d1980848..f27eb7b4a 100644
--- a/openair3/NAS/UE/EMM/SecurityModeControl.c
+++ b/openair3/NAS/UE/EMM/SecurityModeControl.c
@@ -146,7 +146,7 @@ static void _security_release(emm_security_context_t *ctx);
  **                                                                        **
  ***************************************************************************/
 int emm_proc_security_mode_command(int native_ksi, int ksi,
-                                   int seea, int seia, int reea, int reia)
+                                   int seea, int seia, int reea, int reia, int imeisv_request)
 {
   LOG_FUNC_IN;
 
@@ -329,6 +329,7 @@ int emm_proc_security_mode_command(int native_ksi, int ksi,
   emm_sap.u.emm_as.u.security.guti = _emm_data.guti;
   emm_sap.u.emm_as.u.security.ueid = 0;
   emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_SMC;
+  emm_sap.u.emm_as.u.security.imeisv_request = imeisv_request;
   emm_sap.u.emm_as.u.security.emm_cause = emm_cause;
   /* Setup EPS NAS security data */
   emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx,
diff --git a/openair3/NAS/UE/EMM/emm_proc.h b/openair3/NAS/UE/EMM/emm_proc.h
index e6a3ae0cd..60f71f11c 100644
--- a/openair3/NAS/UE/EMM/emm_proc.h
+++ b/openair3/NAS/UE/EMM/emm_proc.h
@@ -174,7 +174,7 @@ int emm_proc_authentication_delete(void);
  * --------------------------------------------------------------------------
  */
 int emm_proc_security_mode_command(int native_ksi, int ksi, int seea, int seia,
-                                   int reea, int reia);
+                                   int reea, int reia,int imeisv_request);
 
 /*
  *---------------------------------------------------------------------------
diff --git a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
index 0c1500fd5..dc395281d 100644
--- a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
+++ b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c
@@ -188,9 +188,9 @@ void pdcp_rlc_test_exchange_pdus(rlc_um_entity_t *um_txP,
   memset(&mac_rlc_status_resp_tx, 0, sizeof(struct mac_status_resp));
   memset(&mac_rlc_status_resp_rx, 0, sizeof(struct mac_status_resp));
 
-  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, bytes_txP, tx_status);
+  mac_rlc_status_resp_tx = rlc_um_mac_status_indication(um_txP, bytes_txP, tx_status, ENB_FLAG_YES);
   data_request_tx        = rlc_um_mac_data_request(um_txP);
-  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, bytes_rxP, tx_status);
+  mac_rlc_status_resp_rx = rlc_um_mac_status_indication(um_rxP, bytes_rxP, tx_status, ENB_FLAG_YES);
   data_request_rx        = rlc_um_mac_data_request(um_rxP);
 
 
-- 
GitLab