+ struct xran_cp_radioapp_section_ext2 *ext2;
+ uint8_t *data;
+ int total_len;
+ int parm_size;
+ uint32_t val, shift_val;
+ int val_size, pad_size;
+
+
+ total_len = 0;
+
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext2);
+ ext2 = (struct xran_cp_radioapp_section_ext2 *)rte_pktmbuf_append(mbuf, parm_size);
+ if(ext2 == NULL) {
+ print_err("Fail to allocate the space for section extension 2");
+ return (XRAN_STATUS_RESOURCE);
+ }
+ total_len += parm_size;
+
+ ext2->extType = XRAN_CP_SECTIONEXTCMD_2;
+ ext2->ef = last_flag;
+ ext2->bfZe3ddWidth = params->bfZe3ddWidth;
+ ext2->bfAz3ddWidth = params->bfAz3ddWidth;
+ ext2->bfZePtWidth = params->bfZePtWidth;
+ ext2->bfAzPtWidth = params->bfAzPtWidth;
+ ext2->bfaCompResv0 = 0;
+ ext2->bfaCompResv1 = 0;
+
+ val = 0;
+ shift_val = 0;
+ if(params->bfAzPtWidth) {
+ val += params->bfAzPt & bitmask[params->bfAzPtWidth];
+ shift_val += 8 - (params->bfAzPtWidth+1);
+ }
+ else
+ shift_val += 8;
+
+ if(params->bfZePtWidth) {
+ val = val << (params->bfZePtWidth+1);
+ val += params->bfZePt & bitmask[params->bfZePtWidth];
+ shift_val += 8 - (params->bfZePtWidth+1);
+ }
+ else
+ shift_val += 8;
+
+ if(params->bfAz3ddWidth) {
+ val = val << (params->bfAz3ddWidth+1);
+ val += params->bfAz3dd & bitmask[params->bfAz3ddWidth];
+ shift_val += 8 - (params->bfAz3ddWidth+1);
+ }
+ else
+ shift_val += 8;
+
+ if(params->bfZe3ddWidth) {
+ val = val << (params->bfZe3ddWidth+1);
+ val += params->bfZe3dd & bitmask[params->bfZe3ddWidth];
+ shift_val += 8 - (params->bfZe3ddWidth+1);
+ }
+ else
+ shift_val += 8;
+
+ if(val) {
+ val = val << shift_val;
+ val = rte_cpu_to_be_32(val);
+ }
+
+ val_size = 4 - (shift_val/8); /* ceil(total bit/8) */
+ parm_size = val_size + 1; /* additional 1 byte for bfxxSI */
+
+ // alignment
+ total_len += parm_size;
+ pad_size = total_len % XRAN_SECTIONEXT_ALIGN;
+ if(pad_size) {
+ pad_size = XRAN_SECTIONEXT_ALIGN - pad_size;
+ parm_size += pad_size;
+ total_len += pad_size;
+ }
+
+ data = (uint8_t *)rte_pktmbuf_append(mbuf, parm_size);
+ if(data == NULL) {
+ print_err("Fail to allocate the space for section extension 2");
+ return (XRAN_STATUS_RESOURCE);
+ }
+
+ rte_memcpy(data, &val, val_size);
+ data += val_size;
+ *data = ((params->bfAzSI) << 3) + (params->bfZeSI);
+ data++;
+ rte_memcpy(data, zeropad, pad_size);
+
+ ext2->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
+ *(uint32_t *)ext2 = rte_cpu_to_be_32(*(uint32_t *)ext2);
+
+ return (total_len);
+}
+
+static int xran_prepare_sectionext_4(struct rte_mbuf *mbuf,
+ struct xran_sectionext4_info *params, int last_flag)
+{
+ struct xran_cp_radioapp_section_ext4 *ext4;
+ int parm_size;
+ int total_len;
+ int ret;
+
+
+ total_len = 0;
+
+ parm_size = sizeof(struct xran_cp_radioapp_section_ext4);
+ ext4 = (struct xran_cp_radioapp_section_ext4 *)rte_pktmbuf_append(mbuf, parm_size);
+ if(ext4 == NULL) {
+ print_err("Fail to allocate the space for section extension 4");
+ return(XRAN_STATUS_RESOURCE);
+ }
+ else {
+ total_len += parm_size;
+
+ ext4->extType = XRAN_CP_SECTIONEXTCMD_4;
+ ext4->ef = last_flag;
+ ext4->modCompScaler = params->modCompScaler;
+ ext4->csf = params->csf?1:0;
+ ext4->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
+
+ *(uint32_t *)ext4 = rte_cpu_to_be_32(*(uint32_t*)ext4);
+ }
+
+ return (total_len);
+}
+
+static int xran_prepare_sectionext_5(struct rte_mbuf *mbuf,
+ struct xran_sectionext5_info *params, int last_flag)
+{
+ struct xran_cp_radioapp_section_ext_hdr *ext_hdr;
+ struct xran_cp_radioapp_section_ext5 ext5;
+ int padding;
+ int total_len;
+ uint8_t *data;
+ int i;
+
+
+ if(params->num_sets > XRAN_MAX_MODCOMP_ADDPARMS) {
+ print_err("Exceeds maximum number of parameters(%d). Skipping.", params->num_sets);
+ return (0);
+ }
+
+ total_len = sizeof(struct xran_cp_radioapp_section_ext_hdr)
+ + (sizeof(struct xran_cp_radioapp_section_ext5)*params->num_sets)/2
+ - (params->num_sets>>1); // 8bits are added by every two sets, so needs to adjust
+
+ /* for alignment */
+ padding = total_len % XRAN_SECTIONEXT_ALIGN;
+ if(padding) {
+ padding = XRAN_SECTIONEXT_ALIGN - padding;
+ total_len += padding;
+ }
+
+ ext_hdr = (struct xran_cp_radioapp_section_ext_hdr *)rte_pktmbuf_append(mbuf, total_len);
+ if(ext_hdr == NULL) {
+ print_err("Fail to allocate the space for section extension 5");
+ return (XRAN_STATUS_RESOURCE);
+ }
+
+ ext_hdr->extType = XRAN_CP_SECTIONEXTCMD_5;
+ ext_hdr->ef = last_flag;
+ ext_hdr->extLen = total_len / XRAN_SECTIONEXT_ALIGN;
+
+ *(uint16_t *)ext_hdr = rte_cpu_to_be_16(*((uint16_t *)ext_hdr));
+
+ data = (uint8_t *)(ext_hdr + 1);
+ i = 0;
+ while(i < params->num_sets) {
+ if(i%2) { // odd index
+ ext5.mcScaleOffset2 = params->mc[i].mcScaleOffset;
+ ext5.csf2 = params->mc[i].csf;
+ ext5.mcScaleReMask2 = params->mc[i].mcScaleReMask;
+ ext5.reserved0 = 0;
+ i++;
+
+ // adding two sets at once (due to the definition of structure)
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
+ rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5));
+ data += sizeof(struct xran_cp_radioapp_section_ext5);
+ }
+ else { // even index
+ ext5.mcScaleOffset1 = params->mc[i].mcScaleOffset;
+ ext5.csf1 = params->mc[i].csf;
+ ext5.mcScaleReMask1 = params->mc[i].mcScaleReMask;
+ ext5.mcScaleReMask2 = 0;
+ i++;
+
+ if(i == params->num_sets) { // adding last even index
+ *((uint64_t *)&ext5) = rte_cpu_to_be_64(*((uint64_t *)&ext5));
+ rte_memcpy(data, &ext5, sizeof(struct xran_cp_radioapp_section_ext5)/2);
+ data += sizeof(struct xran_cp_radioapp_section_ext5)/2;
+ break;
+ }
+ }
+ }
+
+ /* zero padding */
+ if(padding)
+ rte_memcpy(data, zeropad, padding);
+
+ return (total_len);
+}
+
+/**
+ * @brief add section extension to C-Plane packet
+ *
+ * @param mbuf
+ * A pointer to the packet buffer
+ * @param params
+ * A porinter to the information to generate a C-Plane packet
+ * @return
+ * XRAN_STATUS_SUCCESS on success
+ * XRAN_STATUS_INVALID_PARM
+ * XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
+ */
+int xran_append_section_extensions(struct rte_mbuf *mbuf, struct xran_section_gen_info *params)
+{
+ int i, ret;
+ uint32_t totalen;
+ int last_flag;
+ int ext_size;
+
+ if(unlikely(params->exDataSize > XRAN_MAX_NUM_EXTENSIONS)) {
+ print_err("Invalid total number of extensions - %d", params->exDataSize);
+ return (XRAN_STATUS_INVALID_PARAM);
+ }
+
+ totalen = 0;
+
+ ret = XRAN_STATUS_SUCCESS;
+
+ print_dbg("params->exDataSize %d\n", params->exDataSize);
+ for(i=0; i < params->exDataSize; i++) {
+ if(params->exData[i].data == NULL) {
+ print_err("Invalid parameter - extension data %d is NULL", i);
+ ret = XRAN_STATUS_INVALID_PARAM;
+ continue;
+ }
+
+ last_flag = (params->exDataSize == (i+1))?0:1;
+
+ switch(params->exData[i].type) {
+ case XRAN_CP_SECTIONEXTCMD_1:
+ ext_size = xran_copy_sectionext_1(mbuf, params->exData[i].data, last_flag);
+ //xran_prepare_sectionext_1(mbuf, params->exData[i].data, last_flag);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_2:
+ ext_size = xran_prepare_sectionext_2(mbuf, params->exData[i].data, last_flag);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_4:
+ ext_size = xran_prepare_sectionext_4(mbuf, params->exData[i].data, last_flag);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_5:
+ ext_size = xran_prepare_sectionext_5(mbuf, params->exData[i].data, last_flag);
+ break;
+ case XRAN_CP_SECTIONEXTCMD_0:
+ case XRAN_CP_SECTIONEXTCMD_3:
+ default:
+ print_err("Extension Type %d is not supported!", params->exData[i].type);
+ ret = XRAN_STATUS_INVALID_PARAM;
+ ext_size = 0;
+ }
+
+ if(ext_size == XRAN_STATUS_RESOURCE) {
+ break;
+ }
+
+ totalen += ext_size;
+ }
+
+ return (totalen);