+int32_t
+xran_parse_section_ext1(void *ext, struct xran_sectionext1_info *extinfo)
+{
+ int32_t len;
+ int32_t total_len;
+ struct xran_cp_radioapp_section_ext1 *ext1;
+ uint8_t *data;
+ int32_t parm_size = 0, iq_size, iq_size_bytes;
+ int32_t N;
+ void *pHandle;
+
+ pHandle = NULL;
+ N = xran_get_conf_num_bfweights(pHandle);
+ extinfo->bfwNumber = N;
+
+ ext1 = (struct xran_cp_radioapp_section_ext1 *)ext;
+ data = (uint8_t *)ext;
+
+ len = 0;
+ total_len = ext1->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->bfwCompMeth = ext1->bfwCompMeth;
+ extinfo->bfwIqWidth = (ext1->bfwIqWidth==0)?16:ext1->bfwIqWidth;
+
+ len += sizeof(struct xran_cp_radioapp_section_ext1);
+ data += sizeof(struct xran_cp_radioapp_section_ext1);
+ extinfo->p_bfwIQ = (int8_t*)(data);
+
+ switch(ext1->bfwCompMeth) {
+ case XRAN_BFWCOMPMETHOD_NONE:
+ parm_size = 0;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:
+ parm_size = 1;
+ extinfo->bfwCompParam.exponent = *data & 0x0f;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:
+ parm_size = 1;
+ extinfo->bfwCompParam.blockScaler = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_ULAW:
+ parm_size = 1;
+ extinfo->bfwCompParam.compBitWidthShift = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:
+ parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
+ memcpy(data, extinfo->bfwCompParam.activeBeamspaceCoeffMask, parm_size);
+ break;
+
+ default:
+ print_err("Invalid BfComp method - %d", ext1->bfwCompMeth);
+ parm_size = 0;
+ }
+
+ len += parm_size;
+ data += parm_size;
+ iq_size_bytes = parm_size;
+
+ /* Get BF weights */
+ iq_size = N * extinfo->bfwIqWidth * 2; // total in bits
+ parm_size = iq_size>>3; // total in bytes (/8)
+ if(iq_size%8) parm_size++; // round up
+ iq_size_bytes += parm_size;
+
+ //memcpy(data, extinfo->p_bfwIQ, parm_size);
+ extinfo->bfwIQ_sz = iq_size_bytes;
+
+ len += parm_size;
+
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;
+ if(parm_size)
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);
+
+ if(len != total_len) {
+ print_err("The size of extension 1 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext2(void *ext, struct xran_sectionext2_info *extinfo)
+{
+ int32_t len;
+ int32_t total_len;
+ struct xran_cp_radioapp_section_ext2 *ext2;
+ uint8_t *data;
+ int32_t parm_size;
+ uint32_t val;
+ int32_t val_size;
+
+ ext2 = (struct xran_cp_radioapp_section_ext2 *)ext;
+ data = (uint8_t *)ext;
+ *(uint32_t *)ext2 = rte_be_to_cpu_32(*(uint32_t *)ext2);
+
+ len = 0;
+ total_len = ext2->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
+
+ extinfo->bfAzPtWidth = ext2->bfAzPtWidth;
+ extinfo->bfZePtWidth = ext2->bfZePtWidth;
+ extinfo->bfAz3ddWidth = ext2->bfAz3ddWidth;
+ extinfo->bfZe3ddWidth = ext2->bfZe3ddWidth;
+
+ if(ext2->bfaCompResv0 || ext2->bfaCompResv1)
+ print_err("Incorrect reserved field - %d, %d", ext2->bfaCompResv0, ext2->bfaCompResv1);
+
+ data += parm_size;
+ len += parm_size;
+
+ val_size = (extinfo->bfAzPtWidth ? extinfo->bfAzPtWidth+1 : 0)
+ + (extinfo->bfZePtWidth ? extinfo->bfZePtWidth+1 : 0)
+ + (extinfo->bfAz3ddWidth ? extinfo->bfAz3ddWidth+1 : 0)
+ + (extinfo->bfZe3ddWidth ? extinfo->bfZe3ddWidth+ 1: 0);
+ if(val_size) {
+ val = rte_be_to_cpu_32(*(uint32_t *)data);
+ val >>= (32 - val_size);
+
+ if(extinfo->bfZe3ddWidth) {
+ extinfo->bfZe3dd = val & bitmask[extinfo->bfZe3ddWidth];
+ val >>= (extinfo->bfZe3ddWidth + 1);
+ }
+ if(extinfo->bfAz3ddWidth) {
+ extinfo->bfAz3dd = val & bitmask[extinfo->bfAz3ddWidth];
+ val >>= (extinfo->bfAz3ddWidth + 1);
+ }
+ if(extinfo->bfZePtWidth) {
+ extinfo->bfZePt = val & bitmask[extinfo->bfZePtWidth];
+ val >>= (extinfo->bfZePtWidth + 1);
+ }
+ if(extinfo->bfAzPtWidth) {
+ extinfo->bfAzPt = val & bitmask[extinfo->bfAzPtWidth];
+ val >>= (extinfo->bfAzPtWidth + 1);
+ }
+ }
+
+ parm_size = val_size/8;
+ if(val_size%8) parm_size += 1;
+
+ data += parm_size;
+ len += parm_size;
+
+ extinfo->bfAzSI = (*data >> 3) & 0x07;
+ extinfo->bfZeSI = *data & 0x07;
+
+ data++;
+ len++;
+
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;
+ if(parm_size)
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);
+
+ if(len != total_len) {
+ print_err("The size of extension 2 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+
+}
+
+int32_t
+xran_parse_section_ext3(void *ext, struct xran_sectionext3_info *extinfo)
+{
+ int32_t len;
+ int32_t total_len;
+
+ total_len = 0;
+ len = *((uint8_t *)ext + 1);
+
+ switch(len) {
+ case 1: /* non-first data layer */
+ {
+ union xran_cp_radioapp_section_ext3_non_first *ext3_nf;
+
+ ext3_nf = (union xran_cp_radioapp_section_ext3_non_first *)ext;
+ *(uint32_t *)ext3_nf = rte_be_to_cpu_32(*(uint32_t *)ext3_nf);
+
+ total_len = ext3_nf->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->codebookIdx= ext3_nf->all_bits.codebookIndex;
+ extinfo->layerId = ext3_nf->all_bits.layerId;
+ extinfo->numLayers = ext3_nf->all_bits.numLayers;
+ }
+ break;
+
+ case 3: /* first data layer with two antenna */
+ case 4: /* first data layer with four antenna */
+ {
+ union xran_cp_radioapp_section_ext3_first *ext3_f;
+ uint16_t *beamid;
+
+ ext3_f = (union xran_cp_radioapp_section_ext3_first *)ext;
+ *(uint64_t *)ext3_f = rte_be_to_cpu_64(*(uint64_t *)ext3_f);
+
+ total_len = ext3_f->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->codebookIdx= ext3_f->all_bits.codebookIndex;
+ extinfo->layerId = ext3_f->all_bits.layerId;
+ extinfo->numLayers = ext3_f->all_bits.numLayers;
+ extinfo->txScheme = ext3_f->all_bits.txScheme;
+ extinfo->crsReMask = ext3_f->all_bits.crsReMask;
+ extinfo->crsShift = ext3_f->all_bits.crsShift;
+ extinfo->crsSymNum = ext3_f->all_bits.crsSymNum;
+
+ /* beam IDs are stored from 10th octet */
+ beamid = (uint16_t *)((uint8_t *)ext + 10);
+
+ extinfo->beamIdAP1 = rte_be_to_cpu_16(*beamid++);
+ if(len == 4) {
+ extinfo->beamIdAP2 = rte_be_to_cpu_16(*beamid++);
+ extinfo->beamIdAP3 = rte_be_to_cpu_16(*beamid);
+ extinfo->numAntPort = 4;
+ }
+ else {
+ extinfo->numAntPort = 2;
+ }
+ }
+ break;
+
+ default:
+ print_err("Invalid length of extension 3 - %d", len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext4(void *ext, struct xran_sectionext4_info *extinfo)
+{
+ int32_t len;
+ struct xran_cp_radioapp_section_ext4 *ext4;
+ int32_t total_len;
+
+ ext4 = (struct xran_cp_radioapp_section_ext4 *)ext;
+
+ *(uint32_t *)ext4 = rte_be_to_cpu_32(*(uint32_t *)ext4);
+
+ len = 0;
+ total_len = ext4->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->modCompScaler = ext4->modCompScaler;
+ extinfo->csf = ext4->csf;
+
+ len += sizeof(struct xran_cp_radioapp_section_ext4);
+ if(len != total_len) {
+ print_err("The size of extension 4 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext5(void *ext,
+ struct xran_sectionext5_info *extinfo)
+{
+ struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
+ struct xran_cp_radioapp_section_ext5 ext5;
+ int32_t parm_size;
+ int32_t total_len;
+ uint8_t *data;
+ uint16_t i;
+
+ ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)ext;
+ *(uint16_t *)ext_hdr = rte_be_to_cpu_16(*(uint16_t *)ext_hdr);
+
+ total_len = ext_hdr->extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ /* one set has 3.5 bytes, so enforcing double to do integer calculation */
+ parm_size = ((total_len-sizeof(struct xran_cp_radioapp_section_ext_hdr))*2) / 7;
+
+ if(parm_size > XRAN_MAX_MODCOMP_ADDPARMS) {
+ print_err("Exceeds maximum number of parameters - %d", parm_size);
+ parm_size = XRAN_MAX_MODCOMP_ADDPARMS;
+ }
+
+ data = (uint8_t *)(ext_hdr + 1);
+
+ i = 0;
+ while(i < parm_size) {
+ // For odd number set, more data can be copied
+ *((uint64_t *)&ext5) = rte_be_to_cpu_64(*((uint64_t *)data));
+
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset1;
+ extinfo->mc[i].csf = ext5.csf1;
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask1;
+ i++;
+
+ extinfo->mc[i].mcScaleOffset = ext5.mcScaleOffset2;
+ extinfo->mc[i].csf = ext5.csf2;
+ extinfo->mc[i].mcScaleReMask = ext5.mcScaleReMask2;
+ i++;
+
+ data += sizeof(struct xran_cp_radioapp_section_ext5);
+ }
+
+ /* check the values of last set
+ * due to alignment, it cannot be identified by the length that 3 or 4, 11 or 12 and etc
+ * don't check mcScaleOffset might not be zero (some part is out of zero-padding) */
+ i--;
+ if(i < XRAN_MAX_MODCOMP_ADDPARMS) {
+ if(extinfo->mc[i].csf == 0 && extinfo->mc[i].mcScaleReMask == 0)
+ extinfo->num_sets = i;
+ else
+ extinfo->num_sets = i+1;
+ }else {
+ print_err("Maximum total number %d is not correct!", i);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext6(void *ext,
+ struct xran_sectionext6_info *extinfo)
+{
+ int32_t len;
+ union xran_cp_radioapp_section_ext6 *ext6;
+ int32_t total_len;
+
+ ext6 = (union xran_cp_radioapp_section_ext6 *)ext;
+ *(uint64_t *)ext6 = rte_be_to_cpu_64(*(uint64_t *)ext6);
+
+ total_len = ext6->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->rbgSize = ext6->all_bits.rbgSize;
+ extinfo->rbgMask = ext6->all_bits.rbgMask;
+ extinfo->symbolMask = ext6->all_bits.symbolMask;
+
+ len = sizeof(union xran_cp_radioapp_section_ext6);
+ if(len != total_len) {
+ print_err("The size of extension 6 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext9(void *ext,
+ struct xran_sectionext9_info *extinfo, struct xran_cp_recv_params *result)
+{
+ int32_t len = 0;
+ int32_t total_len;
+ int8_t dssSlot = 0;
+ int8_t presumed_technology = -1;
+ struct xran_cp_radioapp_section_ext9 *ext9;
+
+ ext9 = (struct xran_cp_radioapp_section_ext9 *)ext;
+ *(uint32_t *)ext9 = rte_be_to_cpu_32(*(uint32_t *)ext9);
+
+ total_len = ext9->extLen * XRAN_SECTIONEXT_ALIGN;
+
+ if(result) {
+ dssSlot = result->tti % result->dssPeriod;
+ presumed_technology = result->technology_arr[dssSlot];
+ } else {
+ print_err("\nTechnology verification parameters not received");
+ // return (-1);
+ }
+
+ if(presumed_technology != ext9->technology) {
+ print_err("\nWrong technology recieved! [%d,%d]", presumed_technology, ext9->technology);
+ // return (-1);
+ }
+
+ extinfo->technology = ext9->technology;
+ extinfo->reserved = ext9->reserved;
+
+ len += sizeof(struct xran_cp_radioapp_section_ext9);
+ if(len != total_len) {
+ print_err("\nThe size of extension 9 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+
+int32_t
+xran_parse_section_ext10(void *ext,
+ struct xran_sectionext10_info *extinfo)
+{
+ int32_t len, padding;
+ int32_t i;
+ union xran_cp_radioapp_section_ext10 *ext10;
+ int32_t total_len;
+ uint16_t *ptr;
+
+ ext10 = (union xran_cp_radioapp_section_ext10 *)ext;
+
+ total_len = ext10->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->numPortc = ext10->all_bits.numPortc;
+ extinfo->beamGrpType= ext10->all_bits.beamGroupType;
+
+ len = sizeof(union xran_cp_radioapp_section_ext10);
+ if(ext10->all_bits.beamGroupType == XRAN_BEAMGT_VECTORLIST) {
+ len += extinfo->numPortc * 2 - 1;
+ padding = len % XRAN_SECTIONEXT_ALIGN;
+ if(padding) {
+ padding = XRAN_SECTIONEXT_ALIGN - padding;
+ len += padding;
+ }
+
+ ptr = (uint16_t *)&ext10->all_bits.reserved;
+ for(i=0; i < extinfo->numPortc; i++)
+ extinfo->beamID[i] = rte_be_to_cpu_16(ptr[i]);
+ }
+
+ if(len != total_len) {
+ print_err("The size of extension 10 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_ext11(void *ext,
+ struct xran_sectionext11_recv_info *extinfo)
+{
+ int32_t len;
+ int32_t total_len;
+ union xran_cp_radioapp_section_ext11 *ext11;
+ uint8_t *data;
+ int32_t parm_size, iq_size;
+ int32_t N;
+ void *pHandle;
+
+ pHandle = NULL;
+ N = xran_get_conf_num_bfweights(pHandle);
+
+ ext11 = (union xran_cp_radioapp_section_ext11 *)ext;
+ data = (uint8_t *)ext;
+
+ *(uint32_t *)ext11 = rte_cpu_to_be_32(*(uint32_t*)ext11);
+ total_len = ext11->all_bits.extLen * XRAN_SECTIONEXT_ALIGN; /* from word to byte */
+
+ extinfo->RAD = ext11->all_bits.RAD;
+ extinfo->disableBFWs = ext11->all_bits.disableBFWs;
+ extinfo->numBundPrb = ext11->all_bits.numBundPrb;
+ extinfo->bfwCompMeth = ext11->all_bits.bfwCompMeth;
+ extinfo->bfwIqWidth = (ext11->all_bits.bfwIqWidth==0)?16:ext11->all_bits.bfwIqWidth;
+
+ len = sizeof(union xran_cp_radioapp_section_ext11);
+ data += sizeof(union xran_cp_radioapp_section_ext11);
+
+ extinfo->numSetBFWs = 0;
+ while((len+4) < total_len) { /* adding 4 is to consider zero pads */
+ /* Get bfwCompParam */
+ switch(ext11->all_bits.bfwCompMeth) {
+ case XRAN_BFWCOMPMETHOD_NONE:
+ parm_size = 0;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BLKFLOAT:
+ parm_size = 1;
+ extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.exponent = *data & 0x0f;
+ break;
+#if 0 /* Not supported */
+ case XRAN_BFWCOMPMETHOD_BLKSCALE:
+ parm_size = 1;
+ extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.blockScaler = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_ULAW:
+ parm_size = 1;
+ extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.compBitWidthShift = *data;
+ break;
+
+ case XRAN_BFWCOMPMETHOD_BEAMSPACE:
+ parm_size = N>>3; if(N%8) parm_size++; parm_size *= 8;
+ memcpy(data, extinfo->bundInfo[extinfo->numSetBFWs].bfwCompParam.activeBeamspaceCoeffMask, parm_size);
+ break;
+#endif
+ default:
+ print_err("Invalid BfComp method - %d", ext11->all_bits.bfwCompMeth);
+ parm_size = 0;
+ }
+ len += parm_size;
+ data += parm_size;
+
+ /* Get beam ID */
+ extinfo->bundInfo[extinfo->numSetBFWs].beamId = rte_be_to_cpu_16(*((int16_t *)data));
+ len += sizeof(int16_t);
+ data += sizeof(int16_t);
+
+ /* Get BF weights */
+ iq_size = N * extinfo->bfwIqWidth * 2; // total in bits
+ parm_size = iq_size>>3; // total in bytes (/8)
+ if(iq_size%8) parm_size++; // round up
+
+ if(extinfo->bundInfo[extinfo->numSetBFWs].pBFWs) {
+ memcpy(extinfo->bundInfo[extinfo->numSetBFWs].pBFWs, data, parm_size);
+ }
+ extinfo->bundInfo[extinfo->numSetBFWs].BFWSize = parm_size;
+
+ len += parm_size;
+ data += parm_size;
+ extinfo->numSetBFWs++;
+ }
+
+ parm_size = len % XRAN_SECTIONEXT_ALIGN;
+ if(parm_size)
+ len += (XRAN_SECTIONEXT_ALIGN - parm_size);
+
+ if(len != total_len) {
+ //print_err("The size of extension 11 is not correct! [%d:%d]", len, total_len);
+ }
+
+ return (total_len);
+}
+
+int32_t
+xran_parse_section_extension(struct rte_mbuf *mbuf,
+ void *ext, struct xran_cp_recv_params *result,
+ int32_t section_idx)
+{
+ struct xran_section_recv_info *section = &result->sections[section_idx];
+ int32_t total_len, len, numext;
+ uint8_t *ptr;
+ int32_t flag_last;
+ int32_t ext_type;
+ int32_t i;
+
+ total_len = 0;
+ ptr = (uint8_t *)ext;
+
+ numext = 0;
+
+ flag_last = 1;
+ i = 0;
+ while(flag_last) {
+ /* check ef */
+ flag_last = (*ptr & 0x80);
+
+ ext_type = *ptr & 0x7f;
+ section->exts[numext].type = ext_type;
+ switch(ext_type) {
+ case XRAN_CP_SECTIONEXTCMD_1:
+ result->ext1count++;
+ len = xran_parse_section_ext1(ptr, §ion->exts[numext].u.ext1);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_2:
+ len = xran_parse_section_ext2(ptr, §ion->exts[numext].u.ext2);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_3:
+ len = xran_parse_section_ext3(ptr, §ion->exts[numext].u.ext3);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_4:
+ len = xran_parse_section_ext4(ptr, §ion->exts[numext].u.ext4);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_5:
+ len = xran_parse_section_ext5(ptr, §ion->exts[numext].u.ext5);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_6:
+ len = xran_parse_section_ext6(ptr, §ion->exts[numext].u.ext6);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_9:
+ len = xran_parse_section_ext9(ptr, §ion->exts[numext].u.ext9, result);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_10:
+ len = xran_parse_section_ext10(ptr, §ion->exts[numext].u.ext10);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_11:
+ len = xran_parse_section_ext11(ptr, §ion->exts[numext].u.ext11);
+ break;
+
+ default:
+ print_err("Extension %d is not supported!", ext_type);
+ len = 0;
+ }
+
+ section->exts[numext].size = len;
+ ptr += len; total_len += len;
+
+ i++;
+ if(++numext < XRAN_MAX_NUM_EXTENSIONS) continue;
+
+ /* exceeds maximum number of extensions */
+ break;
+ }
+
+ section->numExts = numext;
+
+ return (total_len);
+}
+