1 /******************************************************************************
3 * Copyright (c) 2019 Intel.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 *******************************************************************************/
20 * @brief This file provides the implementation of User Plane Messages APIs.
23 * @ingroup group_lte_source_xran
24 * @author Intel Corporation
28 #include <rte_memcpy.h>
30 #include "xran_fh_lls_cu.h"
31 #include "xran_transport.h"
32 #include "xran_up_api.h"
34 #include "mlog_lnx_xRAN.h"
39 extern uint32_t xran_lib_ota_tti;
43 * @brief Builds eCPRI header in xRAN packet
45 * @param mbuf Initialized rte_mbuf packet
46 * @param iq_data_num_bytes Number of bytes in IQ data buffer
47 * @param iq_data_offset Number of elements already sent
48 * @return int int 0 on success, non zero on failure
50 static int build_ecpri_hdr(struct rte_mbuf *mbuf,
51 const uint32_t iq_data_num_bytes,
52 const uint32_t iq_data_offset,
55 struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *)
56 rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr));
58 uint16_t iq_samples_bytes_in_mbuf = rte_pktmbuf_tailroom(mbuf) -
59 sizeof(struct radio_app_common_hdr) - sizeof(struct data_section_hdr);
61 iq_samples_bytes_in_mbuf -= (iq_samples_bytes_in_mbuf % alignment);
63 if (NULL == ecpri_hdr)
66 ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER;
67 ecpri_hdr->ecpri_resv = 0;
68 ecpri_hdr->ecpri_concat = 0;
69 ecpri_hdr->ecpri_mesg_type = ECPRI_IQ_DATA;
71 if (iq_data_offset + iq_samples_bytes_in_mbuf > iq_data_num_bytes) {
72 ecpri_hdr->ecpri_payl_size =
73 rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) +
74 sizeof(struct data_section_hdr) +
75 (iq_data_num_bytes - iq_data_offset));
76 ecpri_hdr->ecpri_seq_id.e_bit = 1; /* last segment */
78 ecpri_hdr->ecpri_payl_size =
79 rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) +
80 sizeof(struct data_section_hdr) +
81 iq_samples_bytes_in_mbuf);
82 ecpri_hdr->ecpri_seq_id.e_bit = 0;
85 // ecpri_hdr->ecpri_xtc_id = 0; /* currently not used */
86 ecpri_hdr->ecpri_seq_id.seq_id = 0;
87 ecpri_hdr->ecpri_seq_id.sub_seq_id = iq_data_offset /
88 iq_samples_bytes_in_mbuf;
94 * @brief Builds eCPRI header in xRAN packet
96 * @param mbuf Initialized rte_mbuf packet
97 * @param ecpri_mesg_type eCPRI message type
98 * @param payl_size the size in bytes of the payload part of eCPRI message
99 * @param CC_ID Component Carrier ID for ecpriRtcid/ecpriPcid
100 * @param Ant_ID Antenna ID for ecpriRtcid/ecpriPcid
101 * @param seq_id Message identifier for eCPRI message
102 * @return int int 0 on success, non zero on failure
104 static int xran_build_ecpri_hdr_ex(struct rte_mbuf *mbuf,
105 uint8_t ecpri_mesg_type,
111 struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *)
112 rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr));
114 if (NULL == ecpri_hdr)
117 ecpri_hdr->ecpri_ver = XRAN_ECPRI_VER;
118 ecpri_hdr->ecpri_resv = 0; // should be zero
119 ecpri_hdr->ecpri_concat = 0;
120 ecpri_hdr->ecpri_mesg_type = ecpri_mesg_type;
121 ecpri_hdr->ecpri_payl_size = rte_cpu_to_be_16(payl_size
122 + sizeof(struct data_section_hdr)+sizeof(struct radio_app_common_hdr));
124 /* one to one lls-CU to RU only and band sector is the same */
125 ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID);
127 ecpri_hdr->ecpri_seq_id.seq_id = seq_id;
129 /* no transport layer fragmentation supported */
130 ecpri_hdr->ecpri_seq_id.sub_seq_id = 0;
131 ecpri_hdr->ecpri_seq_id.e_bit = 1;
138 * @brief Builds application layer of xRAN packet
140 * @param mbuf Initialized rte_mbuf packet
141 * @param app_hdr_input Radio App common header structure to be set in mbuf
143 * @return int 0 on success, non zero on failure
145 static int build_application_layer(
146 struct rte_mbuf *mbuf,
147 const struct radio_app_common_hdr *app_hdr_input)
149 struct radio_app_common_hdr *app_hdr = (struct radio_app_common_hdr *)
150 rte_pktmbuf_append(mbuf, sizeof(struct radio_app_common_hdr));
155 rte_memcpy(app_hdr, app_hdr_input, sizeof(struct radio_app_common_hdr));
161 * @brief Builds section header in xRAN packet
163 * @param mbuf Initialized rte_mbuf packet
164 * @param sec_hdr Section header structure to be set in mbuf packet
165 * @return int 0 on success, non zero on failure
167 static int build_section_hdr(
168 struct rte_mbuf *mbuf,
169 const struct data_section_hdr *sec_hdr)
171 struct data_section_hdr *section_hdr = (struct data_section_hdr *)
172 rte_pktmbuf_append(mbuf, sizeof(struct data_section_hdr));
174 if (NULL == section_hdr)
177 rte_memcpy(section_hdr, sec_hdr, sizeof(struct data_section_hdr));
182 * @brief Function for appending IQ samples data to the mbuf.
184 * @param mbuf Initialized rte_mbuf packet.
185 * @param iq_data_start Address of the first element in IQ data array.
186 * @param iq_data_num_bytes Size of the IQ data array.
187 * @param iq_data_offset IQ data btyes already sent.
188 * @return uint16_t Bytes that have been appended to the packet.
190 static uint16_t append_iq_samples_ex(
191 struct rte_mbuf *mbuf,
192 const void *iq_data_start,
193 const uint32_t iq_data_num_bytes)
195 uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf);
197 if(free_space_in_pkt >= iq_data_num_bytes){
199 void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_data_num_bytes);
200 if (iq_sam_buf == NULL)
202 #ifdef XRAN_BYTE_ORDER_SWAP
204 uint16_t *restrict psrc = (uint16_t *)iq_data_start;
205 uint16_t *restrict pdst = (uint16_t *)iq_sam_buf;
206 /* CPU byte order (le) of IQ to network byte order (be) */
207 for (idx = 0; idx < iq_data_num_bytes/sizeof(int16_t); idx++){
208 pdst[idx] = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_cpu_to_be_16(psrc[idx]);
211 #error xran spec is network byte order
213 rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start, iq_data_num_bytes);
217 return iq_data_num_bytes;
225 * @brief Function for appending IQ samples data to the mbuf.
227 * @param mbuf Initialized rte_mbuf packet.
228 * @param iq_data_start Address of the first element in IQ data array.
229 * @param iq_data_num_bytes Size of the IQ data array.
230 * @param iq_data_offset IQ data btyes already sent.
231 * @return uint16_t Bytes that have been appended to the packet.
233 static uint16_t append_iq_samples(
234 struct rte_mbuf *mbuf,
235 const void *iq_data_start,
236 const uint32_t iq_data_num_bytes,
237 const uint32_t iq_data_offset,
238 const uint8_t alignment)
240 uint16_t iq_bytes_to_send = 0;
241 uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf);
243 if (free_space_in_pkt > iq_data_num_bytes - iq_data_offset)
244 iq_bytes_to_send = iq_data_num_bytes - iq_data_offset;
246 iq_bytes_to_send = free_space_in_pkt;
248 /* don't cut off an iq in half */
249 iq_bytes_to_send -= iq_bytes_to_send % alignment;
251 void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_bytes_to_send);
253 rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start + iq_data_offset,
256 return iq_bytes_to_send;
260 * @brief Builds compression header in xRAN packet
262 * @param mbuf Initialized rte_mbuf packet
263 * @param compression_hdr Section compression header structure
264 * to be set in mbuf packet
265 * @return int 0 on success, non zero on failure
267 static int build_compression_hdr(
268 struct rte_mbuf *mbuf,
269 const struct data_section_compression_hdr *compr_hdr)
271 struct data_section_compression_hdr *compression_hdr =
272 (struct data_section_compression_hdr *)
273 rte_pktmbuf_append(mbuf, sizeof(*compression_hdr));
275 if (NULL == compression_hdr)
278 rte_memcpy(compression_hdr, compr_hdr, sizeof(*compression_hdr));
284 * @brief Appends compression parameter in xRAN packet
286 * @param mbuf Initialized rte_mbuf packet
287 * @param ud_comp_paramr Compression param to be set in mbuf packet
288 * @return int 0 on success, non zero on failure
290 static int append_comp_param(struct rte_mbuf *mbuf, union compression_params *ud_comp_param)
292 union compression_params *compr_param =
293 (union compression_params *)rte_pktmbuf_append(mbuf, sizeof(union compression_params));
295 if (NULL == compr_param)
298 rte_memcpy(compr_param, ud_comp_param, sizeof(union compression_params));
304 * @brief Function for starting preparion of IQ samples portions
305 * to be sent in xRAN packet
307 * @param mbuf Initialized rte_mbuf packet.
308 * @param iq_data_start Address of the first element in IQ data array.
309 * @param iq_data_num_bytes Size of the IQ data array.
310 * @param iq_data_offset IQ data bytes already sent.
311 * @param alignment Size of IQ data alignment.
312 * @param pkt_gen_params Struct with parameters used for building packet
313 * @return int Number of bytes that have been appended
314 to the packet within a single data section appended.
316 int xran_prepare_iq_symbol_portion(
317 struct rte_mbuf *mbuf,
318 const void *iq_data_start,
319 const uint32_t iq_data_num_bytes,
320 uint32_t *iq_data_offset,
322 struct xran_up_pkt_gen_params *params,
326 uint16_t iq_sam_bytes_sent = 0;
328 if (build_ecpri_hdr(mbuf, iq_data_num_bytes, *iq_data_offset, alignment))
331 if (build_application_layer(mbuf, &(params->app_params)) != 0)
334 if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0)
337 if(params->compr_hdr_param.ud_comp_hdr.ud_comp_meth != XRAN_COMPMETHOD_NONE) {
338 if (build_compression_hdr(mbuf, &(params->compr_hdr_param)) !=0)
341 if(append_comp_param(mbuf, &(params->compr_param)) !=0)
345 return append_iq_samples(mbuf, iq_data_start, iq_data_num_bytes,
346 (*iq_data_offset), alignment);
350 * @brief Function for extracting all IQ samples from xRAN packet
351 * holding a single data section
352 * @param iq_data_start Address of the first element in IQ data array.
353 * @param symb_id Symbol ID to be extracted from ecpri header
354 * @param seq_id Sequence ID to be extracted from radio header
355 * @return int Size of remaining mbuf filled with IQ samples
358 int xran_extract_iq_samples(struct rte_mbuf *mbuf,
359 void **iq_data_start,
363 uint8_t *subframe_id,
366 struct ecpri_seq_id *seq_id)
368 uint32_t mlogVar[10];
369 uint32_t mlogVarCnt = 0;
370 struct xran_eaxc_info result;
374 if (NULL == iq_data_start)
377 /* Process eCPRI header. */
378 const struct xran_ecpri_hdr *ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *);
379 if (ecpri_hdr == NULL)
383 *seq_id = ecpri_hdr->ecpri_seq_id;
385 xran_decompose_cid((uint16_t)ecpri_hdr->ecpri_xtc_id, &result);
387 *CC_ID = result.ccId;
388 *Ant_ID = result.ruPortId;
390 /* Process radio header. */
391 struct radio_app_common_hdr *radio_hdr =
392 (void *)rte_pktmbuf_adj(mbuf, sizeof(*ecpri_hdr));
393 if (radio_hdr == NULL)
394 return 0; /* packet too short */
396 radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value);
399 *frame_id = radio_hdr->frame_id;
402 *subframe_id = radio_hdr->sf_slot_sym.subframe_id;
405 *slot_id = radio_hdr->sf_slot_sym.slot_id;
408 *symb_id = radio_hdr->sf_slot_sym.symb_id;
410 /* Process data section hdr */
411 const struct data_section_hdr *data_hdr =
412 (void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr));
413 if (data_hdr == NULL)
414 return 0; /* packet too short */
417 const struct data_section_compression_hdr *data_compr_hdr =
418 (void *) rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
420 const uint8_t *compr_param =
421 (void *)rte_pktmbuf_adj(mbuf, sizeof(*data_compr_hdr));
423 *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*compr_param));
426 *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
428 if (*iq_data_start == NULL)
431 mlogVar[mlogVarCnt++] = 0xBBBBBBB;
432 mlogVar[mlogVarCnt++] = xran_lib_ota_tti;
433 mlogVar[mlogVarCnt++] = radio_hdr->frame_id;
434 mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.subframe_id;
435 mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.slot_id;
436 mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.symb_id;
437 mlogVar[mlogVarCnt++] = rte_pktmbuf_pkt_len(mbuf);
438 MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
440 return rte_pktmbuf_pkt_len(mbuf);
444 * @brief Function for starting preparion of IQ samples portions
445 * to be sent in xRAN packet
447 * @param mbuf Initialized rte_mbuf packet.
448 * @param iq_data_start Address of the first element in IQ data array.
449 * @param iq_data_num_bytes Size of the IQ data array.
450 * @param iq_data_offset IQ data bytes already sent.
451 * @param alignment Size of IQ data alignment.
452 * @param pkt_gen_params Struct with parameters used for building packet
453 * @return int Number of bytes that have been appended
454 to the packet within all appended sections.
456 int xran_prepare_iq_symbol_portion_no_comp(
457 struct rte_mbuf *mbuf,
458 const void *iq_data_start,
459 const uint32_t iq_data_num_bytes,
460 struct xran_up_pkt_gen_no_compression_params *params,
465 if(xran_build_ecpri_hdr_ex(mbuf,
473 if (build_application_layer(mbuf, &(params->app_params)) != 0)
476 if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0)
479 return append_iq_samples_ex(mbuf, iq_data_start, iq_data_num_bytes);