* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / lib / src / xran_cp_proc.c
index e40ce72..789c6fd 100644 (file)
@@ -46,6 +46,7 @@
 #include <rte_memzone.h>
 #include <rte_mbuf.h>
 #include <rte_ring.h>
+#include <rte_malloc.h>
 
 #include "xran_fh_o_du.h"
 
@@ -60,7 +61,6 @@
 #include "xran_dev.h"
 #include "xran_frame_struct.h"
 #include "xran_printf.h"
-#include "xran_app_frag.h"
 #include "xran_cp_proc.h"
 #include "xran_tx_proc.h"
 
@@ -76,9 +76,11 @@ struct xran_recv_packet_info parse_recv[XRAN_PORTS_NUM];
 
 //////////////////////////////////////////
 // For RU emulation
-struct xran_section_recv_info *recvSections[XRAN_PORTS_NUM] = {NULL,NULL,NULL,NULL};
+struct xran_section_recv_info *recvSections[XRAN_PORTS_NUM] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 struct xran_cp_recv_params recvCpInfo[XRAN_PORTS_NUM];
 
+extern int32_t first_call;
+
 static void
 extbuf_free_callback(void *addr __rte_unused, void *opaque __rte_unused)
 {
@@ -141,14 +143,14 @@ xran_init_seqid(void *pHandle)
 int32_t
 process_cplane(struct rte_mbuf *pkt, void* handle)
 {
+    uint32_t mb_free = MBUF_FREE;
     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)handle;
 
-    if(p_xran_dev_ctx) {
+    if(p_xran_dev_ctx && xran_if_current_state == XRAN_RUNNING) {
         if(xran_dev_get_ctx_by_id(0)->fh_cfg.debugStop) /* check CP with standard tests only */
-            xran_parse_cp_pkt(pkt, &recvCpInfo[p_xran_dev_ctx->xran_port_id], &parse_recv[p_xran_dev_ctx->xran_port_id]);
+            xran_parse_cp_pkt(pkt, &recvCpInfo[p_xran_dev_ctx->xran_port_id], &parse_recv[p_xran_dev_ctx->xran_port_id],(void*)p_xran_dev_ctx, &mb_free);
     }
-
-    return (MBUF_FREE);
+    return (mb_free);
 }
 
 int32_t
@@ -188,23 +190,21 @@ xran_check_symbolrange(int symbol_type, uint32_t PortId, int cc_id, int tti,
 }
 
 struct rte_mbuf *
-xran_attach_cp_ext_buf(uint16_t vf_id, int8_t* p_ext_buff_start, int8_t* p_ext_buff, uint16_t ext_buff_len,
+xran_attach_cp_ext_buf(uint16_t vf_id, int8_t* p_ext_buff_start/*ext_start*/, int8_t* p_ext_buff/*ext-section*/, uint16_t ext_buff_len,
                 struct rte_mbuf_ext_shared_info * p_share_data)
 {
     struct rte_mbuf *mb_oran_hdr_ext = NULL;
-    struct rte_mbuf *tmp             = NULL;
+    //struct rte_mbuf *tmp             = NULL;
     int8_t          *ext_buff        = NULL;
     rte_iova_t ext_buff_iova         = 0;
 
     ext_buff  = p_ext_buff - (RTE_PKTMBUF_HEADROOM +
                 sizeof(struct xran_ecpri_hdr) +
-                sizeof(struct xran_cp_radioapp_section1_header) +
-                sizeof(struct xran_cp_radioapp_section1));
+                sizeof(struct xran_cp_radioapp_section1_header));
 
     ext_buff_len += (RTE_PKTMBUF_HEADROOM +
                 sizeof(struct xran_ecpri_hdr) +
-                sizeof(struct xran_cp_radioapp_section1_header) +
-                sizeof(struct xran_cp_radioapp_section1)) + 18;
+                sizeof(struct xran_cp_radioapp_section1_header) + 18);
 
 //    mb_oran_hdr_ext =  rte_pktmbuf_alloc(_eth_mbuf_pool_small);
     mb_oran_hdr_ext = xran_ethdi_mbuf_indir_alloc();
@@ -237,59 +237,154 @@ xran_attach_cp_ext_buf(uint16_t vf_id, int8_t* p_ext_buff_start, int8_t* p_ext_b
     return mb_oran_hdr_ext;
 }
 
+/* TO DO: __thread is slow. We should allocate global 2D array and index it using current core index
+ * for better performance.
+ */
+__thread struct xran_section_gen_info sect_geninfo[XRAN_MAX_SECTIONS_PER_SLOT];
+
 int32_t
 xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int tti, int cc_id,
-        struct xran_prb_map *prbMap, enum xran_category category,  uint8_t ctx_id)
+        struct xran_prb_map *prbMap, struct xran_prb_elm_proc_info_t *prbElmProcInfo, enum xran_category category,  uint8_t ctx_id)
 {
     int32_t ret = 0;
     struct xran_device_ctx *p_x_ctx   = (struct xran_device_ctx *)pHandle;
     struct xran_common_counters *pCnt = &p_x_ctx->fh_counters;
     struct xran_cp_gen_params params;
-    struct xran_section_gen_info sect_geninfo[1];
     struct rte_mbuf *mbuf;
     uint32_t interval = p_x_ctx->interval_us_local;
     uint8_t PortId = p_x_ctx->xran_port_id;
+    int16_t numCPSections=0, ext_offset=0, start_sect_id=0;
 
-
-    uint32_t i, j, loc_sym;
+    uint32_t i, j, loc_sym,idx;
     uint32_t nsection = 0;
     struct xran_prb_elm *pPrbMapElem = NULL;
-    struct xran_prb_elm *pPrbMapElemPrev = NULL;
+    // struct xran_prb_elm *pPrbMapElemPrev = NULL;
     uint32_t slot_id     = XranGetSlotNum(tti, SLOTNUM_PER_SUBFRAME(interval));
     uint32_t subframe_id = XranGetSubFrameNum(tti,SLOTNUM_PER_SUBFRAME(interval),  SUBFRAMES_PER_SYSTEMFRAME);
     uint32_t frame_id    = XranGetFrameNum(tti,xran_getSfnSecStart(),SUBFRAMES_PER_SYSTEMFRAME, SLOTNUM_PER_SUBFRAME(interval));
 
     uint8_t seq_id = 0;
-    uint16_t vf_id = 0;
+    uint16_t vf_id = 0 , curr_sec_id = 0 , prb_per_section, start_Prb;
+    int32_t startSym = 0, numSyms = 0;
 
-    int next;
+    int next=0;
     struct xran_sectionext1_info ext1;
     struct xran_sectionext4_info ext4 = {0};
+    struct xran_sectionext9_info ext9;
     struct xran_sectionext11_info ext11;
 
-    //frame_id = (frame_id & 0xff); /* ORAN frameId, 8 bits, [0, 255] */
-    frame_id = ((frame_id + ((0 == tti)?NUM_OF_FRAMES_PER_SECOND:0)) & 0xff); /* ORAN frameId, 8 bits, [0, 255] */
+    frame_id = (frame_id & 0xff); /* ORAN frameId, 8 bits, [0, 255] */
 
+    if(unlikely((category != XRAN_CATEGORY_A) && (category != XRAN_CATEGORY_B)))
+    {
+        print_err("Unsupported Category %d\n", category);
+        return (-1);
+    }
+
+    /* Generate a C-Plane message per each section,
+     * not a C-Plane message with multi sections */
+    if(0 == p_x_ctx->RunSlotPrbMapBySymbolEnable)
+    {
     if(prbMap) {
+
+            nsection = prbMap->nPrbElm;
+            i=0;
+            if(XRAN_DIR_DL == dir)
+            {
+                if(0 == p_x_ctx->numSymsForDlCP)
+                {
+                    print_dbg("No symbol available for DL CP transmission\n");
+                    return (-1);
+                }
+
+                if(prbMap->nPrbElm == prbElmProcInfo->nPrbElmProcessed && 0 != prbElmProcInfo->numSymsRemaining)
+                {
+                    prbElmProcInfo->numSymsRemaining--;
+                    print_dbg("All sections already processed\n");
+                    return (-1);
+                }
+
+                if(0== prbElmProcInfo->numSymsRemaining)
+                { /* new slot */
+                    prbElmProcInfo->numSymsRemaining = p_x_ctx->numSymsForDlCP;
+                    prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm/p_x_ctx->numSymsForDlCP;
+                    prbElmProcInfo->nPrbElmProcessed = 0;
+                }
+
+                if(1 == prbElmProcInfo->numSymsRemaining)
+                {/* last symbol:: send all remaining */
         nsection = prbMap->nPrbElm;
+                }
+                else
+                {
+                    if(0 == prbElmProcInfo->nPrbElmPerSym)
+                        nsection=prbElmProcInfo->nPrbElmProcessed + 1;
+                    else
+                        nsection = prbElmProcInfo->nPrbElmProcessed + prbElmProcInfo->nPrbElmPerSym;
+                }
+
+                i=prbElmProcInfo->nPrbElmProcessed;
+                prbElmProcInfo->numSymsRemaining--;
+
+            } //dir = DL
+            else
+            {
+                nsection = prbMap->nPrbElm;
+                i=0;
+            } //dir = UL
+
         pPrbMapElem = &prbMap->prbMap[0];
-    } else {
+        }
+        else
+        {
         print_err("prbMap is NULL\n");
         return (-1);
     }
 
+
+        curr_sec_id = 0;
+        if(pPrbMapElem->bf_weight.extType == 1)
+        {
+            for(j=0;j<i;j++)
+                curr_sec_id += prbMap->prbMap[j].bf_weight.numSetBFWs;
+        }
+        else
+            curr_sec_id = i;
+
+        // start_id=curr_sec_id;
+        uint8_t generateCpPkt=0;
+        uint8_t replacePrbStartNSize=0; /* In case of application fragmentation, we send 1 cplane packets for multiple
+                                           uplane packets i.e. 1 cp packet for multiple PRBs. This flag is used to
+                                           achieve that by setting different values for cp packet preparation and for
+                                           cp-up database update */
+
     /* Generate a C-Plane message per each section,
      * not a C-Plane message with multi sections */
-    for (i = 0; i < nsection; i++) {
+        for (; i < nsection; i++) {
         int startSym, numSyms;
 
         pPrbMapElem                 = &prbMap->prbMap[i];
+            prb_per_section = pPrbMapElem->bf_weight.numBundPrb;
+            start_Prb       = pPrbMapElem->nRBStart;
+
+            if((pPrbMapElem->bf_weight.extType == 1) &&
+                    (((i+1)<nsection && prbMap->prbMap[i+1].IsNewSect==1) ||
+                    (i+1) == nsection))
+            { /*ext1*/
+                generateCpPkt=1;
+            }
+            else if(pPrbMapElem->IsNewSect)
+                generateCpPkt=1;
+            else
+                generateCpPkt=0;
+
 
        /* For Special Subframe,
         * Check validity of given symbol range with slot configuration
         * and adjust symbol range accordingly. */
         if(xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_FDD) != 1
-            && xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_SP) == 1) {
+                && xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_SP) == 1)
+            {
             /* This function cannot handle two or more groups of consecutive same type of symbol.
                 * If there are two or more, then it might cause an error */
             startSym = xran_check_symbolrange(
@@ -297,7 +392,8 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
                                 PortId, cc_id, tti,
                                 pPrbMapElem->nStartSymb,
                                 pPrbMapElem->numSymb, &numSyms);
-            if(startSym < 0 || numSyms == 0) {
+                if(startSym < 0 || numSyms == 0)
+                {
                 /* if start symbol is not valid, then skip this section */
                 print_err("Skip section %d due to invalid symbol range - [%d:%d], [%d:%d]",
                             i,
@@ -305,7 +401,9 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
                             startSym, numSyms);
                 continue;
             }
-        } else {
+            }
+            else
+            {
             startSym    = pPrbMapElem->nStartSymb;
             numSyms     = pPrbMapElem->numSymb;
         }
@@ -324,135 +422,189 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
         print_dbg("cp[%d:%d:%d] ru_port_id %d dir=%d\n",
                                frame_id, subframe_id, slot_id, ru_port_id, dir);
 
-        seq_id = xran_get_cp_seqid(pHandle, XRAN_DIR_DL, cc_id, ru_port_id);
-
-        sect_geninfo[0].info.type        = params.sectionType;
-        sect_geninfo[0].info.startSymId  = params.hdr.startSymId;
-        sect_geninfo[0].info.iqWidth     = params.hdr.iqWidth;
-        sect_geninfo[0].info.compMeth    = params.hdr.compMeth;
-
-        sect_geninfo[0].info.id          = i; /* do not revert 'i' to
-                                                xran_alloc_sectionid(pHandle, dir, cc_id, ru_port_id, slot_id); */
-
-        if(sect_geninfo[0].info.id > XRAN_MAX_SECTIONS_PER_SLOT)
-            print_err("sectinfo->id %d\n", sect_geninfo[0].info.id);
-#if 0
-        if (dir == XRAN_DIR_UL) {
-            for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) {
-                int32_t sec_desc_idx = pPrbMapElem->nSecDesc[loc_sym];
-                struct xran_section_desc *p_sec_desc =  pPrbMapElem->p_sec_desc[loc_sym][0];
-                if(p_sec_desc) {
-                    p_sec_desc->section_id   = sect_geninfo[0].info.id;
-                    if(p_sec_desc->pCtrl) {
-                        rte_pktmbuf_free(p_sec_desc->pCtrl);
-                        p_sec_desc->pCtrl = NULL;
-                        p_sec_desc->pData = NULL;
+            if(pPrbMapElem->bf_weight.extType == 1)
+            {
+                /* Send multiple CP sections per prbElement for ext-1 */
+                numCPSections   = pPrbMapElem->bf_weight.numSetBFWs;
+            }
+            else
+            {
+                numCPSections   = 1;
+                replacePrbStartNSize = 1;   /* in case of no app fragmentation, UP_nRBSize will be same as nRBSize. So,
+                                                always replacing the elements when ext1 is not in use */
+            }
+
+            /** Prepare section info for multiple sections in a PRB element */
+            for(idx=0; idx < numCPSections; idx++) {
+
+                sect_geninfo[curr_sec_id].exDataSize=0;
+                sect_geninfo[curr_sec_id].info = xran_cp_get_section_info_ptr(pHandle, dir, cc_id, ru_port_id, ctx_id);
+                if(unlikely(sect_geninfo[curr_sec_id].info == NULL))
+                {
+                    rte_panic("xran_cp_get_section_info_ptr failed\n");
                     }
+
+                struct xran_section_info *info = sect_geninfo[curr_sec_id].info;
+                info->prbElemBegin  = (idx == 0 ) ?  1 : 0;
+                info->prbElemEnd    = (idx + 1 == numCPSections) ?  1 : 0;
+                info->ef            = 0;
+                info->freqOffset    = 0;
+                info->ueId          = 0;
+                info->regFactor     = 0;
+
+                if((idx+1)*prb_per_section > pPrbMapElem->nRBSize){
+                    prb_per_section = pPrbMapElem->nRBSize - idx*prb_per_section;
                 }
-                else {
-                    print_err("section desc is NULL\n");
+
+                if(numCPSections == 1)
+                {
+                    info->startPrbc = pPrbMapElem->nRBStart;
+                    info->numPrbc   = pPrbMapElem->nRBSize;
                 }
-                sec_desc_idx--;
-                pPrbMapElem->nSecDesc[loc_sym] = 0;
+                else
+                {
+                    info->startPrbc = start_Prb;
+                    info->numPrbc   = prb_per_section;
+                    start_Prb       += prb_per_section;
             }
+
+                info->type        = params.sectionType;
+                info->startSymId  = params.hdr.startSymId;
+                info->iqWidth     = params.hdr.iqWidth;
+                info->compMeth    = params.hdr.compMeth;
+                info->id          = curr_sec_id;
+
+                if(info->prbElemBegin && pPrbMapElem->IsNewSect==1)
+                {
+                    start_sect_id = info->id;
         }
-#endif
 
-        sect_geninfo[0].info.rb          = XRAN_RBIND_EVERY;
-        sect_geninfo[0].info.startPrbc   = pPrbMapElem->nRBStart;
-        sect_geninfo[0].info.numPrbc     = pPrbMapElem->nRBSize;
-        sect_geninfo[0].info.numSymbol   = numSyms;
-        sect_geninfo[0].info.reMask      = 0xfff;
-        sect_geninfo[0].info.beamId      = pPrbMapElem->nBeamIndex;
-        sect_geninfo[0].info.symInc      = XRAN_SYMBOLNUMBER_NOTINC;
-
-        for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) {
-            struct xran_section_desc *p_sec_desc =  pPrbMapElem->p_sec_desc[loc_sym][0];
-            if(p_sec_desc) {
-                p_sec_desc->section_id   = sect_geninfo[0].info.id;
-
-                sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;
-                sect_geninfo[0].info.sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;
-            } else {
-                print_err("section desc is NULL\n");
+                if(unlikely(info->id > XRAN_MAX_SECTIONS_PER_SLOT))
+                    print_err("sectinfo->id %d\n", info->id);
+
+                info->rb          = XRAN_RBIND_EVERY;
+                info->numSymbol   = numSyms;
+                info->reMask      = 0xfff;
+                info->beamId      = pPrbMapElem->nBeamIndex;
+                info->symInc      = XRAN_SYMBOLNUMBER_NOTINC;
+
+                for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
+                {
+                    struct xran_section_desc *p_sec_desc =  &pPrbMapElem->sec_desc[loc_sym][0];
+
+                    if(p_sec_desc)
+                    {
+                        info->sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;
+                        info->sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;
+
+                        p_sec_desc->section_id   = info->id;
             }
+                    else
+                    {
+                        print_err("section desc is NULL\n");
         }
 
-        if(unlikely((category != XRAN_CATEGORY_A) && (category != XRAN_CATEGORY_B))) {
-            print_err("Unsupported Category %d\n", category);
-            return (-1);
-        }
+                } /* for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++) */
 
         /* Add extentions if required */
+                if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
+                {
+                    if(pPrbMapElem->bf_weight.extType == 1) /* Prepare section data for ext-1 */
+                    {
         next = 0;
-        sect_geninfo[0].exDataSize       = 0;
+                        sect_geninfo[curr_sec_id].exDataSize  = 0;
 
+                        memset(&ext1, 0, sizeof (struct xran_sectionext1_info));
+                        ext1.bfwNumber      = pPrbMapElem->bf_weight.nAntElmTRx;
+                        ext1.bfwIqWidth     = pPrbMapElem->iqWidth;
+                        ext1.bfwCompMeth    = pPrbMapElem->compMethod;
+                        /* ext-1 buffer contains CP sections */
+                        ext1.bfwIQ_sz       = ONE_EXT_LEN(pPrbMapElem); //76
+
+                        ext_offset          = (idx*ONE_CPSEC_EXT_LEN(pPrbMapElem)) + sizeof(struct xran_cp_radioapp_section1);
+                        ext1.p_bfwIQ        = (int8_t*)(pPrbMapElem->bf_weight.p_ext_section + ext_offset);
+
+                        sect_geninfo[curr_sec_id].exData[next].type   = XRAN_CP_SECTIONEXTCMD_1;
+                        sect_geninfo[curr_sec_id].exData[next].len    = sizeof(ext1);
+                        sect_geninfo[curr_sec_id].exData[next].data   = &ext1;
+
+                        info->ef = 1;
+                        sect_geninfo[curr_sec_id].exDataSize++;
+                        next++;
+                    }
+                    else
+                    {
+                        /*ext-11*/
+                    }
+
+                } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
+
+                curr_sec_id++;
+            } /* for(idx=0; idx < numCPSections;idx++) */
+
+            if (dir==XRAN_DIR_UL || generateCpPkt) //only send actual new CP section
+            {
         /* Extension 4 for modulation compression */
-        if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION) {
+                if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
+                {
             mbuf = xran_ethdi_mbuf_alloc();
 
             ext4.csf                            = 0;  //no shift for now only
             ext4.modCompScaler                  = pPrbMapElem->ScaleFactor;
+                    /* TO DO: Should this be the current section id? */
             sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_4;
             sect_geninfo[0].exData[next].len    = sizeof(ext4);
             sect_geninfo[0].exData[next].data   = &ext4;
 
-            sect_geninfo[0].info.ef             = 1;
+                    sect_geninfo[0].info->ef             = 1;
             sect_geninfo[0].exDataSize++;
             next++;
         }
 
         /* Extension 1 or 11 for Beam forming weights */
-        if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) {
-            /* add extantion section for BF Weights if update is needed */
-            if(pPrbMapElem->bf_weight.numBundPrb == 0) {
-                /* No bundled PRBs, using Extension 1 */
-                struct rte_mbuf_ext_shared_info * p_share_data = &p_x_ctx->cp_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info.id];
-
-                /*add extention section for BF Weights if update is needed */
-                if(pPrbMapElem->bf_weight.p_ext_start) {
+                /* add section extention for BF Weights if update is needed */
+                if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
+                {
+                    if(pPrbMapElem->bf_weight.extType == 1) /* Using Extension 1 */
+                    {
+                        //TODO: Should this change ?
+                        struct rte_mbuf_ext_shared_info * p_share_data =
+                        &p_x_ctx->cp_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info->id];
+
+                        if(pPrbMapElem->bf_weight.p_ext_start)
+                        {
                     /* use buffer with BF Weights for mbuf */
                     mbuf = xran_attach_cp_ext_buf(vf_id, pPrbMapElem->bf_weight.p_ext_start,
                                                 pPrbMapElem->bf_weight.p_ext_section,
                                                 pPrbMapElem->bf_weight.ext_section_sz, p_share_data);
-                } else {
+                        }
+                        else
+                        {
                     print_err("p %d cc %d dir %d Alloc fail!\n", PortId, cc_id, dir);
-                    return (-1);
+                            ret=-1;
+                            goto _create_and_send_section_error;
                 }
-
-                memset(&ext1, 0, sizeof (struct xran_sectionext1_info));
-                ext1.bfwNumber      = pPrbMapElem->bf_weight.nAntElmTRx;
-                ext1.bfwIqWidth     = pPrbMapElem->iqWidth;
-                ext1.bfwCompMeth    = pPrbMapElem->compMethod;
-                ext1.p_bfwIQ        = (int16_t*)pPrbMapElem->bf_weight.p_ext_section;
-                ext1.bfwIQ_sz       = pPrbMapElem->bf_weight.ext_section_sz;
-
-                sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_1;
-                sect_geninfo[0].exData[next].len    = sizeof(ext1);
-                sect_geninfo[0].exData[next].data   = &ext1;
-
-                sect_geninfo[0].info.ef       = 1;
-                sect_geninfo[0].exDataSize++;
-                next++;
-            } else { /* if(pPrbMapElem->bf_weight.numBundPrb == 0) */
+                    } /* if(pPrbMapElem->bf_weight.extType == 1) */
+                    else
+                    {
                 /* Using Extension 11 */
                 struct rte_mbuf_ext_shared_info *shared_info;
+                        next = 0;
 
-                shared_info = &p_x_ctx->bfw_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info.id];
-
-
+                        shared_info = &p_x_ctx->bfw_share_data.sh_data[tti % XRAN_N_FE_BUF_LEN][cc_id][ru_port_id][sect_geninfo[0].info->id];
                 shared_info->free_cb     = NULL;
                 shared_info->fcb_opaque  = NULL;
 
                 mbuf = xran_ethdi_mbuf_indir_alloc();
                 if(unlikely(mbuf == NULL)) {
                     rte_panic("Alloc fail!\n");
-                    return (-1);
                 }
                 //mbuf = rte_pktmbuf_alloc(_eth_mbuf_pool_vf_small[vf_id]);
-                if(xran_cp_attach_ext_buf(mbuf, (uint8_t *)pPrbMapElem->bf_weight.p_ext_start, pPrbMapElem->bf_weight.maxExtBufSize, shared_info) < 0) {
+                        if(xran_cp_attach_ext_buf(mbuf, (uint8_t *)pPrbMapElem->bf_weight.p_ext_start, pPrbMapElem->bf_weight.maxExtBufSize, shared_info) < 0)
+                        {
                     rte_pktmbuf_free(mbuf);
-                    return (-1);
+                            ret=-1;
+                            goto _create_and_send_section_error;
                 }
 
                 rte_mbuf_ext_refcnt_update(shared_info, 0);
@@ -476,29 +628,64 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
                 sect_geninfo[0].exData[next].len    = sizeof(ext11);
                 sect_geninfo[0].exData[next].data   = &ext11;
 
-                sect_geninfo[0].info.ef       = 1;
+                        sect_geninfo[0].info->ef       = 1;
                 sect_geninfo[0].exDataSize++;
                 next++;
             }
-        } else { /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
+                } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
+                else
+                {
             mbuf = xran_ethdi_mbuf_alloc();
-            sect_geninfo[0].info.ef          = 0;
+
+                    sect_geninfo[0].info->ef          = 0;
             sect_geninfo[0].exDataSize       = 0;
+
+                    if(p_x_ctx->dssEnable == 1) {
+                        uint8_t dssSlot = 0;
+                        dssSlot = tti % (p_x_ctx->dssPeriod);
+
+                        ext9.technology = p_x_ctx->technology[dssSlot];
+                        ext9.reserved = 0;
+
+                        sect_geninfo[0].exData[next].type   = XRAN_CP_SECTIONEXTCMD_9;
+                        sect_geninfo[0].exData[next].len    = sizeof(ext9);
+                        sect_geninfo[0].exData[next].data   = &ext9;
+
+                        sect_geninfo[0].info->ef       = 1;
+                        sect_geninfo[0].exDataSize++;
+                        next++;
+                    }
         }
 
-        if(unlikely(mbuf == NULL)) {
+                if(unlikely(mbuf == NULL))
+                {
             print_err("Alloc fail!\n");
-            return (-1);
+                    ret=-1;
+                    goto _create_and_send_section_error;
         }
 
-        params.numSections          = 1;//nsection;
+                params.numSections          = numCPSections;
         params.sections             = sect_geninfo;
 
-        ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id);
-        if(ret < 0) {
+                seq_id = xran_get_cp_seqid(pHandle, ((XRAN_DIR_DL == dir)? XRAN_DIR_DL : XRAN_DIR_UL), cc_id, ru_port_id);
+                ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id,start_sect_id);
+            } /* if (dir==XRAN_DIR_UL || generateCpPkt) */
+
+            if(replacePrbStartNSize && XRAN_DIR_DL == dir)
+            {
+                sect_geninfo[curr_sec_id-1].info->startPrbc = pPrbMapElem->UP_nRBStart;
+                sect_geninfo[curr_sec_id-1].info->numPrbc   = pPrbMapElem->UP_nRBSize;
+            }
+
+            if(ret < 0)
+            {
             print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
                         frame_id, subframe_id, slot_id, dir);
-        } else {
+            }
+            else
+            {
+                if((dir==XRAN_DIR_UL) || generateCpPkt) //only send actual new CP section
+                {
             int32_t cp_sent = 0;
             int32_t pkt_len = 0;
             /* add in the ethernet header */
@@ -508,14 +695,255 @@ xran_cp_create_and_send_section(void *pHandle, uint8_t ru_port_id, int dir, int
             pCnt->tx_bytes_counter += pkt_len; //rte_pktmbuf_pkt_len(mbuf);
             if(pkt_len > p_x_ctx->fh_init.mtu)
                 rte_panic("section %d: pkt_len = %d maxExtBufSize %d\n", i, pkt_len, pPrbMapElem->bf_weight.maxExtBufSize);
-            //rte_mbuf_sanity_check(mbuf, 0);
+
             cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
-            if(cp_sent != 1) {
+                    if(cp_sent != 1)
+                    {
                 rte_pktmbuf_free(mbuf);
             }
-            xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id, &sect_geninfo[0].info);
+                }
         }
     } /* for (i=0; i<nsection; i++) */
+    }
+#if 1
+    else
+    {
+        /* Generate a C-Plane message with multi sections,
+        * a C-Plane message for each section*/
+        if(prbMap)
+        {
+            if(0 == prbMap->nPrbElm)
+            {
+                print_dbg("prbMap->nPrbElm is %d\n",prbMap->nPrbElm);
+                return 0;
+            }
+
+            nsection = prbMap->nPrbElm;
+            i=0;
+            if(XRAN_DIR_DL == dir)
+            {
+                prbElmProcInfo->numSymsRemaining = 0;
+                prbElmProcInfo->nPrbElmProcessed = 0;
+                prbElmProcInfo->nPrbElmPerSym = prbMap->nPrbElm;
+                nsection = prbMap->nPrbElm;
+            } //dir = DL
+            else
+            {
+                nsection = prbMap->nPrbElm;
+            } //dir = UL
+        }
+        else
+        {
+            print_err("prbMap is NULL\n");
+            return (-1);
+        }
+
+        pPrbMapElem = &prbMap->prbMap[0];
+
+        if(xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_FDD) != 1
+            && xran_fs_get_slot_type(PortId, cc_id, tti, XRAN_SLOT_TYPE_SP) == 1)
+        {
+            startSym = xran_check_symbolrange(
+                                ((dir==XRAN_DIR_DL)?XRAN_SYMBOL_TYPE_DL:XRAN_SYMBOL_TYPE_UL),
+                                PortId, cc_id, tti,
+                                pPrbMapElem->nStartSymb,
+                                pPrbMapElem->numSymb, &numSyms);
+
+            if(startSym < 0 || numSyms == 0)
+            {
+                /* if start symbol is not valid, then skip this section */
+                print_err("Skip section %d due to invalid symbol range - [%d:%d], [%d:%d]",
+                            i,
+                            pPrbMapElem->nStartSymb, pPrbMapElem->numSymb,
+                            startSym, numSyms);
+            }
+        }
+        else
+        {
+            startSym    = pPrbMapElem->nStartSymb;
+            numSyms     = pPrbMapElem->numSymb;
+        }
+
+        vf_id  = xran_map_ecpriRtcid_to_vf(p_x_ctx, dir, cc_id, ru_port_id);
+        params.dir                  = dir;
+        params.sectionType          = XRAN_CP_SECTIONTYPE_1;
+        params.hdr.filterIdx        = XRAN_FILTERINDEX_STANDARD;
+        params.hdr.frameId          = frame_id;
+        params.hdr.subframeId       = subframe_id;
+        params.hdr.slotId           = slot_id;
+        params.hdr.startSymId       = startSym;
+        params.hdr.iqWidth          = pPrbMapElem->iqWidth;
+        params.hdr.compMeth         = pPrbMapElem->compMethod;
+        params.sections             = sect_geninfo;
+
+        for (i = 0, j = 0; j < nsection; j++)
+        {
+            sect_geninfo[i].exDataSize=0;
+            sect_geninfo[i].info = xran_cp_get_section_info_ptr(pHandle, dir, cc_id, ru_port_id, ctx_id);
+            sect_geninfo[i].info->prbElemBegin = ((j == 0 ) ?  1 : 0);
+            sect_geninfo[i].info->prbElemEnd   = ((j + 1 == nsection) ?  1 : 0);
+            if(sect_geninfo[i].info == NULL)
+            {
+                rte_panic("xran_cp_get_section_info_ptr failed\n");
+            }
+            pPrbMapElem = &prbMap->prbMap[j];
+
+            sect_geninfo[i].info->type        = XRAN_CP_SECTIONTYPE_1;
+            sect_geninfo[i].info->startSymId  = pPrbMapElem->nStartSymb;
+            sect_geninfo[i].info->iqWidth     = params.hdr.iqWidth;
+            sect_geninfo[i].info->compMeth    = params.hdr.compMeth;
+            sect_geninfo[i].info->id          = pPrbMapElem->nSectId;
+
+            if(sect_geninfo[i].info->id > XRAN_MAX_SECTIONS_PER_SLOT)
+                print_err("sectinfo->id %d\n", sect_geninfo[i].info->id);
+
+            sect_geninfo[i].info->rb          = XRAN_RBIND_EVERY;
+            sect_geninfo[i].info->startPrbc   = pPrbMapElem->UP_nRBStart;
+            sect_geninfo[i].info->numPrbc     = pPrbMapElem->UP_nRBSize;
+            sect_geninfo[i].info->numSymbol   = pPrbMapElem->numSymb;
+            sect_geninfo[i].info->reMask      = 0xfff;
+            sect_geninfo[i].info->beamId      = pPrbMapElem->nBeamIndex;
+
+            if(startSym == pPrbMapElem->nStartSymb)
+                sect_geninfo[i].info->symInc  = XRAN_SYMBOLNUMBER_NOTINC;
+            else
+            {
+                if((startSym + numSyms) == pPrbMapElem->nStartSymb)
+                {
+                    sect_geninfo[i].info->symInc  = XRAN_SYMBOLNUMBER_INC;
+                    startSym  =   pPrbMapElem->nStartSymb;
+                    numSyms   =   pPrbMapElem->numSymb;
+                }
+                else
+                {
+                    sect_geninfo[i].info->startSymId = startSym;
+                    sect_geninfo[i].info->numSymbol  = numSyms;
+                    print_dbg("Last startSym is %d. Last numSyms is %d. But current pPrbMapElem->nStartSymb is %d.\n", startSym, numSyms, pPrbMapElem->nStartSymb);
+                }
+            }
+
+
+            for(loc_sym = 0; loc_sym < XRAN_NUM_OF_SYMBOL_PER_SLOT; loc_sym++)
+            {
+                struct xran_section_desc *p_sec_desc =  &pPrbMapElem->sec_desc[loc_sym][0];
+                if(p_sec_desc)
+                {
+                    p_sec_desc->section_id   = sect_geninfo[i].info->id;
+
+                    sect_geninfo[i].info->sec_desc[loc_sym].iq_buffer_offset = p_sec_desc->iq_buffer_offset;
+                    sect_geninfo[i].info->sec_desc[loc_sym].iq_buffer_len    = p_sec_desc->iq_buffer_len;
+                }
+                else
+                {
+                    print_err("section desc is NULL\n");
+                }
+            }
+
+            next = 0;
+            sect_geninfo[i].exDataSize       = 0;
+
+          /* Extension 4 for modulation compression */
+            if(pPrbMapElem->compMethod == XRAN_COMPMETHOD_MODULATION)
+            {
+                // print_dbg("[%s]:%d Modulation Compression need to verify for this code branch and may not be available\n");
+                print_err("[%s]:%d Modulation Compression need to verify for this code branch and may not be available\n",__FUNCTION__, __LINE__);
+            }
+            /* Extension 1 or 11 for Beam forming weights */
+            /* add section extention for BF Weights if update is needed */
+            if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update))
+            {
+                // print_dbg("[%s]:%d Category B need to verify for this code branch and may not be available\n");
+                print_err("[%s]:%d Category B need to verify for this code branch and may not be available\n",__FUNCTION__, __LINE__);
+            } /* if((category == XRAN_CATEGORY_B) && (pPrbMapElem->bf_weight_update)) */
+            else
+            {
+                sect_geninfo[i].info->ef          = 0;
+                sect_geninfo[i].exDataSize       = 0;
+
+                if(p_x_ctx->dssEnable == 1) {
+                    uint8_t dssSlot = 0;
+                    dssSlot = tti % (p_x_ctx->dssPeriod);
+
+                    ext9.technology = p_x_ctx->technology[dssSlot];
+                    ext9.reserved = 0;
+
+                    sect_geninfo[i].exData[next].type   = XRAN_CP_SECTIONEXTCMD_9;
+                    sect_geninfo[i].exData[next].len    = sizeof(ext9);
+                    sect_geninfo[i].exData[next].data   = &ext9;
+
+                    sect_geninfo[i].info->ef       = 1;
+                    sect_geninfo[i].exDataSize++;
+                    next++;
+                }
+            }
+
+            // xran_cp_add_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id, &sect_geninfo[i].info);
+
+            if(pPrbMapElem->IsNewSect == 1)
+            {
+                sect_geninfo[i].info->startPrbc   = pPrbMapElem->nRBStart;
+                sect_geninfo[i].info->numPrbc     = pPrbMapElem->nRBSize;
+                i++;
+            }
+        }
+
+        params.numSections          = i;
+
+        mbuf = xran_ethdi_mbuf_alloc();
+        if(unlikely(mbuf == NULL))
+        {
+            print_err("Alloc fail!\n");
+            ret=-1;
+            goto _create_and_send_section_error;
+        }
+
+        seq_id = xran_get_cp_seqid(pHandle, ((XRAN_DIR_DL == dir)? XRAN_DIR_DL : XRAN_DIR_UL), cc_id, ru_port_id);
+        ret = xran_prepare_ctrl_pkt(mbuf, &params, cc_id, ru_port_id, seq_id,start_sect_id);
+
+        if(ret < 0)
+        {
+            print_err("Fail to build control plane packet - [%d:%d:%d] dir=%d\n",
+                        frame_id, subframe_id, slot_id, dir);
+        }
+        else
+        {
+
+            int32_t cp_sent = 0;
+            int32_t pkt_len = 0;
+            /* add in the ethernet header */
+            struct rte_ether_hdr *const h = (void *)rte_pktmbuf_prepend(mbuf, sizeof(*h));
+            pkt_len = rte_pktmbuf_pkt_len(mbuf);
+            pCnt->tx_counter++;
+            pCnt->tx_bytes_counter += pkt_len; //rte_pktmbuf_pkt_len(mbuf);
+            if(pkt_len > p_x_ctx->fh_init.mtu)
+                rte_panic("section %d: pkt_len = %d maxExtBufSize %d\n", i, pkt_len, pPrbMapElem->bf_weight.maxExtBufSize);
+
+            cp_sent = p_x_ctx->send_cpmbuf2ring(mbuf, ETHER_TYPE_ECPRI, vf_id);
+            if(cp_sent != 1)
+            {
+                rte_pktmbuf_free(mbuf);
+            }
+        }
+
+        struct xran_section_info *info;
+        for (j = 0; j < nsection; j++)
+        {
+            pPrbMapElem = &prbMap->prbMap[j];
+            info = xran_cp_find_section_info(pHandle, dir, cc_id, ru_port_id, ctx_id,j);
+            if(info == NULL)
+            {
+                rte_panic("xran_cp_get_section_info_ptr failed\n");
+            }
+            info->startPrbc   = pPrbMapElem->UP_nRBStart;
+            info->numPrbc     = pPrbMapElem->UP_nRBSize;
+        }
+    }
+#endif
+_create_and_send_section_error:
+    if(XRAN_DIR_DL == dir)
+    {
+        prbElmProcInfo->nPrbElmProcessed = nsection;
+    }
 
     return ret;
 }
@@ -541,7 +969,7 @@ xran_ruemul_init(void *pHandle)
             }
 
         recvSections[xran_port_id] = malloc(sizeof(struct xran_section_recv_info) * XRAN_MAX_NUM_SECTIONS);
-        if(recvSections == NULL) {
+        if(recvSections[xran_port_id] == NULL) {
             print_err("Fail to allocate memory!");
             return (-1);
             }