From 5ee6fe727cbc0e97fc24908d9e69062d5432a795 Mon Sep 17 00:00:00 2001
From: Wu Jing <wu.jing@cn.fujitsu.com>
Date: Sat, 8 Jun 2019 13:36:16 +0900
Subject: [PATCH] fix issue that output hoping not to have mis-match between
 CRC ind and RX in VNF-PNF mode

---
 nfapi/oai_integration/nfapi_vnf.c  | 198 ++++++++++++++++++++++++++++-
 openair1/PHY/phy_vars.h            |   1 +
 openair1/SCHED/fapi_l1.c           |   4 +-
 openair2/PHY_INTERFACE/IF_Module.c | 128 ++++++++++++++++++-
 openair2/PHY_INTERFACE/IF_Module.h |  20 +++
 5 files changed, 344 insertions(+), 7 deletions(-)

diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c
index 2752df3435d..40226dfe4ee 100644
--- a/nfapi/oai_integration/nfapi_vnf.c
+++ b/nfapi/oai_integration/nfapi_vnf.c
@@ -42,6 +42,7 @@
 
 #include "common/ran_context.h"
 extern RAN_CONTEXT_t RC;
+extern UL_RCC_IND_t  UL_RCC_INFO;
 
 typedef struct {
   uint8_t enabled;
@@ -424,6 +425,40 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   printf("[VNF] RACH_IND eNB:%p sfn_sf:%d number_of_preambles:%d\n", eNB, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->rach_indication_body.number_of_preambles);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.rach_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_rach_indication : num of rach reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.rach_ind[index] = *ind;
+
+    if (ind->rach_indication_body.number_of_preambles > 0)
+      UL_RCC_INFO.rach_ind[index].rach_indication_body.preamble_list = malloc(sizeof(nfapi_preamble_pdu_t)*ind->rach_indication_body.number_of_preambles );
+
+    for (int i=0; i<ind->rach_indication_body.number_of_preambles; i++) {
+      if (ind->rach_indication_body.preamble_list[i].preamble_rel8.tl.tag == NFAPI_PREAMBLE_REL8_TAG) {
+
+        printf("preamble[%d]: rnti:%02x preamble:%d timing_advance:%d\n",
+              i,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.rnti,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.preamble,
+              ind->rach_indication_body.preamble_list[i].preamble_rel8.timing_advance
+              );
+      }
+      if(ind->rach_indication_body.preamble_list[i].preamble_rel13.tl.tag == NFAPI_PREAMBLE_REL13_TAG) {
+        printf("RACH PREAMBLE REL13 present\n");
+      }
+
+      UL_RCC_INFO.rach_ind[index].rach_indication_body.preamble_list[i] = ind->rach_indication_body.preamble_list[i];
+    }
+  }else{
   eNB->UL_INFO.rach_ind = *ind;
   eNB->UL_INFO.rach_ind.rach_indication_body.preamble_list = eNB->preamble_list;
 
@@ -443,7 +478,7 @@ int phy_rach_indication(struct nfapi_vnf_p7_config *config, nfapi_rach_indicatio
 
     eNB->preamble_list[i] = ind->rach_indication_body.preamble_list[i];
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_rach_ind(p7_vnf->mac, ind);
@@ -454,13 +489,33 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d number_of_harqs:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->harq_indication_body.number_of_harqs);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.harq_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_harq_indication : num of harq reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.harq_ind[index] = *ind;
+
+    if (ind->harq_indication_body.number_of_harqs > 0)
+      UL_RCC_INFO.harq_ind[index].harq_indication_body.harq_pdu_list = malloc(sizeof(nfapi_harq_indication_pdu_t)*ind->harq_indication_body.number_of_harqs );
+    for (int i=0; i<ind->harq_indication_body.number_of_harqs; i++) {
+        memcpy(&UL_RCC_INFO.harq_ind[index].harq_indication_body.harq_pdu_list[i], &ind->harq_indication_body.harq_pdu_list[i], sizeof(nfapi_harq_indication_pdu_t));
+    }
+  }else{
   eNB->UL_INFO.harq_ind = *ind;
   eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list = eNB->harq_pdu_list;
 
   for (int i=0; i<ind->harq_indication_body.number_of_harqs; i++) {
     memcpy(&eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[i], &ind->harq_indication_body.harq_pdu_list[i], sizeof(eNB->UL_INFO.harq_ind.harq_indication_body.harq_pdu_list[i]));
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_harq_ind(p7_vnf->mac, ind);
@@ -470,6 +525,37 @@ int phy_harq_indication(struct nfapi_vnf_p7_config *config, nfapi_harq_indicatio
 int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_t *ind) {
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.crc_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+      }
+      if(UL_RCC_INFO.rx_ind[i].sfn_sf == ind->sfn_sf){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_crc_indication : num of crc reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.crc_ind[index] = *ind;
+
+    if (ind->crc_indication_body.number_of_crcs > 0)
+      UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list = malloc(sizeof(nfapi_crc_indication_pdu_t)*ind->crc_indication_body.number_of_crcs );
+
+    for (int i=0; i<ind->crc_indication_body.number_of_crcs; i++) {
+      memcpy(&UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list[i], &ind->crc_indication_body.crc_pdu_list[i], sizeof(ind->crc_indication_body.crc_pdu_list[0]));
+
+      LOG_D(MAC, "%s() NFAPI SFN/SF:%d CRC_IND:number_of_crcs:%u UL_INFO:crcs:%d PDU[%d] rnti:%04x UL_INFO:rnti:%04x\n",
+          __FUNCTION__,
+          NFAPI_SFNSF2DEC(ind->sfn_sf), ind->crc_indication_body.number_of_crcs, UL_RCC_INFO.crc_ind[index].crc_indication_body.number_of_crcs,
+          i,
+          ind->crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti,
+          UL_RCC_INFO.crc_ind[index].crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti);
+    }
+  }else{
   eNB->UL_INFO.crc_ind = *ind;
   nfapi_crc_indication_t *dest_ind = &eNB->UL_INFO.crc_ind;
   nfapi_crc_indication_pdu_t *dest_pdu_list = eNB->crc_pdu_list;
@@ -489,7 +575,7 @@ int phy_crc_indication(struct nfapi_vnf_p7_config *config, nfapi_crc_indication_
           ind->crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti,
           eNB->UL_INFO.crc_ind.crc_indication_body.crc_pdu_list[i].rx_ue_information.rnti);
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_crc_ind(p7_vnf->mac, ind);
@@ -504,6 +590,52 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t
   }
 
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.rx_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+      }
+      if(UL_RCC_INFO.crc_ind[i].sfn_sf == ind->sfn_sf){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_rx_indication : num of rx reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.rx_ind[index] = *ind;
+
+    if (ind->rx_indication_body.number_of_pdus > 0)
+      UL_RCC_INFO.rx_ind[index].rx_indication_body.rx_pdu_list = malloc(sizeof(nfapi_rx_indication_pdu_t)*ind->rx_indication_body.number_of_pdus );
+
+    for (int i=0; i<ind->rx_indication_body.number_of_pdus; i++) {
+      nfapi_rx_indication_pdu_t *dest_pdu = &UL_RCC_INFO.rx_ind[index].rx_indication_body.rx_pdu_list[i];
+      nfapi_rx_indication_pdu_t *src_pdu = &ind->rx_indication_body.rx_pdu_list[i];
+
+      memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
+      // DJP - TODO FIXME - intentional memory leak
+      if(dest_pdu->rx_indication_rel8.length > 0){
+        dest_pdu->data = malloc(dest_pdu->rx_indication_rel8.length);
+        memcpy(dest_pdu->data, src_pdu->data, dest_pdu->rx_indication_rel8.length);
+      }else{
+        dest_pdu->data = NULL;
+      }
+
+      LOG_D(PHY, "%s() NFAPI SFN/SF:%d PDUs:%d [PDU:%d] handle:%d rnti:%04x length:%d offset:%d ul_cqi:%d ta:%d data:%p\n",
+          __FUNCTION__,
+          NFAPI_SFNSF2DEC(ind->sfn_sf), ind->rx_indication_body.number_of_pdus, i,
+          dest_pdu->rx_ue_information.handle,
+          dest_pdu->rx_ue_information.rnti,
+          dest_pdu->rx_indication_rel8.length,
+          dest_pdu->rx_indication_rel8.offset,
+          dest_pdu->rx_indication_rel8.ul_cqi,
+          dest_pdu->rx_indication_rel8.timing_advance,
+          dest_pdu->data
+          );
+    }
+  }else{
   nfapi_rx_indication_t *dest_ind = &eNB->UL_INFO.rx_ind;
   nfapi_rx_indication_pdu_t *dest_pdu_list = eNB->rx_pdu_list;
   *dest_ind = *ind;
@@ -528,7 +660,7 @@ int phy_rx_indication(struct nfapi_vnf_p7_config *config, nfapi_rx_indication_t
           dest_pdu->data
          );
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_rx_ind(p7_vnf->mac, ind);
@@ -544,6 +676,32 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d srs:%d\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->sr_indication_body.number_of_srs);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.sr_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_sr_indication : num of sr reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.sr_ind[index] = *ind;
+    LOG_D(MAC,"%s() UL_INFO[%d].sr_ind.sr_indication_body.number_of_srs:%d\n", __FUNCTION__, index, eNB->UL_INFO.sr_ind.sr_indication_body.number_of_srs);
+    if (ind->sr_indication_body.number_of_srs > 0)
+      UL_RCC_INFO.sr_ind[index].sr_indication_body.sr_pdu_list = malloc(sizeof(nfapi_sr_indication_pdu_t)*ind->sr_indication_body.number_of_srs );
+
+    for (int i=0; i<ind->sr_indication_body.number_of_srs; i++) {
+        nfapi_sr_indication_pdu_t *dest_pdu = &UL_RCC_INFO.sr_ind[index].sr_indication_body.sr_pdu_list[i];
+        nfapi_sr_indication_pdu_t *src_pdu = &ind->sr_indication_body.sr_pdu_list[i];
+
+        LOG_D(MAC, "SR_IND[PDU:%d %d][rnti:%x cqi:%d channel:%d]\n", index, i, src_pdu->rx_ue_information.rnti, src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
+
+        memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
+    }
+  }else{
   nfapi_sr_indication_t *dest_ind = &eNB->UL_INFO.sr_ind;
   nfapi_sr_indication_pdu_t *dest_pdu_list = eNB->sr_pdu_list;
   *dest_ind = *ind;
@@ -556,7 +714,7 @@ int phy_sr_indication(struct nfapi_vnf_p7_config *config, nfapi_sr_indication_t
     LOG_D(MAC, "SR_IND[PDU:%d][rnti:%x cqi:%d channel:%d]\n", i, src_pdu->rx_ue_information.rnti, src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
     memcpy(dest_pdu, src_pdu, sizeof(*src_pdu));
   }
-
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   // vnf_p7_info* p7_vnf = (vnf_p7_info*)(config->user_data);
   //mac_sr_ind(p7_vnf->mac, ind);
@@ -569,7 +727,36 @@ int phy_cqi_indication(struct nfapi_vnf_p7_config *config, nfapi_cqi_indication_
   struct PHY_VARS_eNB_s *eNB = RC.eNB[0][0];
   LOG_D(MAC, "%s() NFAPI SFN/SF:%d number_of_cqis:%u\n", __FUNCTION__, NFAPI_SFNSF2DEC(ind->sfn_sf), ind->cqi_indication_body.number_of_cqis);
   pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    int8_t index = -1;
+    for(uint8_t i= 0;i< NUM_NFPAI_SUBFRAME;i++){
+      if((UL_RCC_INFO.cqi_ind[i].header.message_id == 0) && (index == -1)){
+        index = i;
+        break;
+      }
+    }
+    if(index == -1){
+      LOG_E(MAC,"phy_cqi_indication : num of cqi reach max \n");
+      return 0;
+    }
+    UL_RCC_INFO.cqi_ind[index] = *ind;
+    if (ind->cqi_indication_body.number_of_cqis > 0){
+      UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_pdu_list = malloc(sizeof(nfapi_cqi_indication_pdu_t)*ind->cqi_indication_body.number_of_cqis );
+      UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_raw_pdu_list = malloc(sizeof(nfapi_cqi_indication_raw_pdu_t)*ind->cqi_indication_body.number_of_cqis );
+    }
+    for (int i=0; i<ind->cqi_indication_body.number_of_cqis; i++) {
+        nfapi_cqi_indication_pdu_t *src_pdu = &ind->cqi_indication_body.cqi_pdu_list[i];
+        LOG_D(MAC, "SR_IND[PDU:%d][rnti:%x cqi:%d channel:%d]\n", i, src_pdu->rx_ue_information.rnti,
+                    src_pdu->ul_cqi_information.ul_cqi, src_pdu->ul_cqi_information.channel);
+        memcpy(&UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_pdu_list[i],
+               src_pdu, sizeof(nfapi_cqi_indication_pdu_t));
+
+        memcpy(&UL_RCC_INFO.cqi_ind[index].cqi_indication_body.cqi_raw_pdu_list[i],
+               &ind->cqi_indication_body.cqi_raw_pdu_list[i], sizeof(nfapi_cqi_indication_raw_pdu_t));
+    }
+  }else{
   eNB->UL_INFO.cqi_ind = ind->cqi_indication_body;
+  }
   pthread_mutex_unlock(&eNB->UL_INFO_mutex);
   return 1;
 }
@@ -947,6 +1134,7 @@ void configure_nfapi_vnf(char *vnf_addr, int vnf_p5_port) {
   config->deallocate_p4_p5_vendor_ext = &vnf_deallocate_p4_p5_vendor_ext;
   config->codec_config.allocate = &vnf_allocate;
   config->codec_config.deallocate = &vnf_deallocate;
+  memset(&UL_RCC_INFO,0,sizeof(UL_RCC_IND_t));
   NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Creating VNF NFAPI start thread %s\n", __FUNCTION__);
   pthread_create(&vnf_start_pthread, NULL, (void *)&vnf_start_thread, config);
   NFAPI_TRACE(NFAPI_TRACE_INFO, "[VNF] Created VNF NFAPI start thread %s\n", __FUNCTION__);
diff --git a/openair1/PHY/phy_vars.h b/openair1/PHY/phy_vars.h
index ea7d2e5033f..272ca0a9ff7 100644
--- a/openair1/PHY/phy_vars.h
+++ b/openair1/PHY/phy_vars.h
@@ -45,6 +45,7 @@ int16_t *primary_synch2_time;
 #ifndef OCP_FRAMEWORK
 PHY_VARS_UE ***PHY_vars_UE_g;
 RAN_CONTEXT_t RC;
+UL_RCC_IND_t  UL_RCC_INFO;
 
 //PHY_VARS_eNB ***PHY_vars_eNB_g;
 //PHY_VARS_RN **PHY_vars_RN_g;
diff --git a/openair1/SCHED/fapi_l1.c b/openair1/SCHED/fapi_l1.c
index 52ca46e6cea..8a43fa260ed 100644
--- a/openair1/SCHED/fapi_l1.c
+++ b/openair1/SCHED/fapi_l1.c
@@ -924,7 +924,9 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) {
   }
 
   if ((NFAPI_MODE!=NFAPI_MONOLITHIC) && do_oai && !dont_send) {
-    oai_nfapi_tx_req(Sched_INFO->TX_req);
+    if(Sched_INFO->TX_req->tx_request_body.number_of_pdus > 0){
+      oai_nfapi_tx_req(Sched_INFO->TX_req);
+    }
     oai_nfapi_dl_config_req(Sched_INFO->DL_req); // DJP - .dl_config_request_body.dl_config_pdu_list[0]); // DJP - FIXME TODO - yuk - only copes with 1 pdu
   }
 
diff --git a/openair2/PHY_INTERFACE/IF_Module.c b/openair2/PHY_INTERFACE/IF_Module.c
index 296d8f92947..b58c96cc13b 100644
--- a/openair2/PHY_INTERFACE/IF_Module.c
+++ b/openair2/PHY_INTERFACE/IF_Module.c
@@ -17,10 +17,34 @@ extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
 extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
 
 extern uint16_t sf_ahead;
+extern UL_RCC_IND_t  UL_RCC_INFO;
+
 uint16_t frame_cnt=0;
 void handle_rach(UL_IND_t *UL_info) {
   int i;
-
+  if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+     if (UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles>0) {
+
+       AssertFatal(UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
+       LOG_D(MAC,"UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:SFN/SF:%d\n",UL_info->frame,UL_info->subframe, NFAPI_SFNSF2DEC(UL_RCC_INFO.rach_ind[j].sfn_sf));
+       initiate_ra_proc(UL_info->module_id,
+                        UL_info->CC_id,
+                        NFAPI_SFNSF2SFN(UL_RCC_INFO.rach_ind[j].sfn_sf),
+                        NFAPI_SFNSF2SF(UL_RCC_INFO.rach_ind[j].sfn_sf),
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.preamble,
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
+                        UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list[0].preamble_rel8.rnti
+#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+                        ,0
+#endif
+       );
+       free(UL_RCC_INFO.rach_ind[j].rach_indication_body.preamble_list);
+       UL_RCC_INFO.rach_ind[j].rach_indication_body.number_of_preambles = 0;
+       UL_RCC_INFO.rach_ind[j].header.message_id = 0;
+     }
+   }
+  }else{
   if (UL_info->rach_ind.rach_indication_body.number_of_preambles>0) {
     AssertFatal(UL_info->rach_ind.rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
     UL_info->rach_ind.rach_indication_body.number_of_preambles=0;
@@ -37,6 +61,7 @@ void handle_rach(UL_IND_t *UL_info) {
 #endif
                     );
   }
+  }
 
 #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
 
@@ -72,6 +97,22 @@ void handle_sr(UL_IND_t *UL_info) {
     if (UL_info->sr_ind.sr_indication_body.number_of_srs>0) {
       oai_nfapi_sr_indication(&UL_info->sr_ind);
     }
+  } else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs > 0){
+        for (i=0;i<UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs;i++){
+          SR_indication(UL_info->module_id,
+              UL_info->CC_id,
+              NFAPI_SFNSF2SFN(UL_RCC_INFO.sr_ind[j].sfn_sf),
+              NFAPI_SFNSF2SF(UL_RCC_INFO.sr_ind[j].sfn_sf),
+              UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list[i].rx_ue_information.rnti,
+              UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list[i].ul_cqi_information.ul_cqi);
+        }
+        free(UL_RCC_INFO.sr_ind[j].sr_indication_body.sr_pdu_list);
+        UL_RCC_INFO.sr_ind[j].sr_indication_body.number_of_srs=0;
+        UL_RCC_INFO.sr_ind[j].header.message_id = 0;
+      }
+    }
   } else {
     for (i=0; i<UL_info->sr_ind.sr_indication_body.number_of_srs; i++)
       SR_indication(UL_info->module_id,
@@ -98,6 +139,26 @@ void handle_cqi(UL_IND_t *UL_info) {
       oai_nfapi_cqi_indication(&ind);
       UL_info->cqi_ind.number_of_cqis=0;
     }
+  } else if (NFAPI_MODE == NFAPI_MODE_VNF) {
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis > 0){
+        for (i=0;i<UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis;i++){
+          cqi_indication(UL_info->module_id,
+                         UL_info->CC_id,
+                         NFAPI_SFNSF2SFN(UL_RCC_INFO.cqi_ind[j].sfn_sf),
+                         NFAPI_SFNSF2SF(UL_RCC_INFO.cqi_ind[j].sfn_sf),
+                         UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].rx_ue_information.rnti,
+                         &UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].cqi_indication_rel9,
+                         UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_raw_pdu_list[i].pdu,
+                         &UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list[i].ul_cqi_information);
+        }
+
+        free(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_pdu_list);
+        free(UL_RCC_INFO.cqi_ind[j].cqi_indication_body.cqi_raw_pdu_list);
+        UL_RCC_INFO.cqi_ind[j].cqi_indication_body.number_of_cqis=0;
+        UL_RCC_INFO.cqi_ind[j].header.message_id = 0;
+      }
+    }
   } else {
     for (i=0; i<UL_info->cqi_ind.number_of_cqis; i++)
       cqi_indication(UL_info->module_id,
@@ -123,7 +184,22 @@ void handle_harq(UL_IND_t *UL_info) {
     }
 
     UL_info->harq_ind.harq_indication_body.number_of_harqs = 0;
+  }else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t j = 0;j < NUM_NFPAI_SUBFRAME;j++){
+      if(UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs > 0){
+        for (int i=0;i<UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs;i++){
+          harq_indication(UL_info->module_id,
+                         UL_info->CC_id,
+                         NFAPI_SFNSF2SFN(UL_RCC_INFO.harq_ind[j].sfn_sf),
+                         NFAPI_SFNSF2SF(UL_RCC_INFO.harq_ind[j].sfn_sf),
+                         &UL_RCC_INFO.harq_ind[j].harq_indication_body.harq_pdu_list[i]);
+        }
 
+        free(UL_RCC_INFO.harq_ind[j].harq_indication_body.harq_pdu_list);
+        UL_RCC_INFO.harq_ind[j].harq_indication_body.number_of_harqs=0;
+        UL_RCC_INFO.harq_ind[j].header.message_id = 0;
+      }
+    }
   } else {
     for (int i=0; i < UL_info->harq_ind.harq_indication_body.number_of_harqs; i++)
       harq_indication(UL_info->module_id,
@@ -151,6 +227,56 @@ void handle_ulsch(UL_IND_t *UL_info) {
       oai_nfapi_rx_ind(&UL_info->rx_ind);
       UL_info->rx_ind.rx_indication_body.number_of_pdus = 0;
     }
+  } else if(NFAPI_MODE == NFAPI_MODE_VNF){
+    for(uint8_t k = 0;k < NUM_NFPAI_SUBFRAME;k++){
+      if((UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus>0) && (UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs>0)){
+        for (i=0;i<UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus;i++) {
+          for (j=0;j<UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs;j++) {
+            // find crc_indication j corresponding rx_indication i
+            LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n",
+                       j,UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti, i,UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti);
+            if (UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti == UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti) {
+              LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n",
+                          j, UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag);
+              if (UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag == 1) { // CRC error indication
+                LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->subframe);
+                  rx_sdu(UL_info->module_id,
+                      UL_info->CC_id,
+                      NFAPI_SFNSF2SFN(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->frame,
+                      NFAPI_SFNSF2SF(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->subframe,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                      (uint8_t *)NULL,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+              }
+              else {
+                  LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->subframe);
+                  rx_sdu(UL_info->module_id,
+                      UL_info->CC_id,
+                      NFAPI_SFNSF2SFN(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->frame,
+                      NFAPI_SFNSF2SF(UL_RCC_INFO.rx_ind[k].sfn_sf), //UL_info->subframe,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                      UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+              }
+              if(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data != NULL){
+                free(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list[i].data);
+              }
+              break;
+            } //if (UL_info->crc_ind.crc_pdu_list[j].rx_ue_information.rnti == UL_info->rx_ind.rx_pdu_list[i].rx_ue_information.rnti)
+          } //    for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++)
+        } //   for (i=0;i<UL_info->rx_ind.number_of_pdus;i++)
+        free(UL_RCC_INFO.crc_ind[k].crc_indication_body.crc_pdu_list);
+        free(UL_RCC_INFO.rx_ind[k].rx_indication_body.rx_pdu_list);
+        UL_RCC_INFO.crc_ind[k].crc_indication_body.number_of_crcs = 0;
+        UL_RCC_INFO.crc_ind[k].header.message_id =0;
+        UL_RCC_INFO.rx_ind[k].rx_indication_body.number_of_pdus = 0;
+        UL_RCC_INFO.rx_ind[k].header.message_id = 0;
+      }
+    }
   } else {
     if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->crc_ind.crc_indication_body.number_of_crcs>0) {
       for (i=0; i<UL_info->rx_ind.rx_indication_body.number_of_pdus; i++) {
diff --git a/openair2/PHY_INTERFACE/IF_Module.h b/openair2/PHY_INTERFACE/IF_Module.h
index b6ede7d598a..11dea21d284 100644
--- a/openair2/PHY_INTERFACE/IF_Module.h
+++ b/openair2/PHY_INTERFACE/IF_Module.h
@@ -90,7 +90,27 @@ typedef struct{
 } UL_IND_t;
 
 // Downlink subframe P7
+#define NUM_NFPAI_SUBFRAME 5
+typedef struct{
+  /// harq indication list
+  nfapi_harq_indication_t harq_ind[NUM_NFPAI_SUBFRAME];
+
+  /// crc indication list
+  nfapi_crc_indication_t crc_ind[NUM_NFPAI_SUBFRAME];
+
+  /// SR indication list
+  nfapi_sr_indication_t sr_ind[NUM_NFPAI_SUBFRAME];
+
+  /// CQI indication list
+  nfapi_cqi_indication_t cqi_ind[NUM_NFPAI_SUBFRAME];
+
+  /// RACH indication list
+  nfapi_rach_indication_t rach_ind[NUM_NFPAI_SUBFRAME];
+
+  /// RX indication
+  nfapi_rx_indication_t rx_ind[NUM_NFPAI_SUBFRAME];
 
+} UL_RCC_IND_t;
 
 typedef struct{
   /// Module ID
-- 
GitLab