3fb5ba943d1e634b2d17dadb49625bcc7b9bd26f
[o-du/phy.git] / fhi_lib / lib / src / xran_up_api.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2019 Intel.
4 *
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
8 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief This file provides the implementation of User Plane Messages APIs.
21  *
22  * @file xran_up_api.c
23  * @ingroup group_lte_source_xran
24  * @author Intel Corporation
25  *
26  **/
27 #include <inttypes.h>
28
29 #include <rte_memcpy.h>
30 #include <rte_mbuf.h>
31
32 #include "xran_fh_o_du.h"
33 #include "xran_transport.h"
34 #include "xran_up_api.h"
35 #include "xran_printf.h"
36 #include "xran_mlog_lnx.h"
37
38 extern uint32_t xran_lib_ota_tti;
39
40 /**
41  * @brief Builds eCPRI header in xRAN packet
42  *
43  * @param mbuf Initialized rte_mbuf packet
44  * @param iq_data_num_bytes Number of bytes in IQ data buffer
45  * @param iq_data_offset Number of elements already sent
46  * @return int int 0 on success, non zero on failure
47  */
48 static int build_ecpri_hdr(struct rte_mbuf *mbuf,
49     const uint32_t iq_data_num_bytes,
50     const uint32_t iq_data_offset,
51     uint8_t alignment)
52 {
53     struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *)
54         rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr));
55
56     uint16_t iq_samples_bytes_in_mbuf = rte_pktmbuf_tailroom(mbuf) -
57         sizeof(struct radio_app_common_hdr) - sizeof(struct data_section_hdr);
58
59     iq_samples_bytes_in_mbuf -= (iq_samples_bytes_in_mbuf % alignment);
60
61     if (NULL == ecpri_hdr)
62         return 1;
63
64     ecpri_hdr->cmnhdr.ecpri_ver = XRAN_ECPRI_VER;
65     ecpri_hdr->cmnhdr.ecpri_resv = 0;
66     ecpri_hdr->cmnhdr.ecpri_concat = 0;
67     ecpri_hdr->cmnhdr.ecpri_mesg_type = ECPRI_IQ_DATA;
68
69     if (iq_data_offset + iq_samples_bytes_in_mbuf > iq_data_num_bytes) {
70         ecpri_hdr->cmnhdr.ecpri_payl_size =
71             rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) +
72                 sizeof(struct data_section_hdr) +
73                 (iq_data_num_bytes - iq_data_offset) +
74                 xran_get_ecpri_hdr_size());
75         ecpri_hdr->ecpri_seq_id.e_bit = 1;  /* last segment */
76     } else {
77         ecpri_hdr->cmnhdr.ecpri_payl_size =
78             rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) +
79                 sizeof(struct data_section_hdr) +
80                 iq_samples_bytes_in_mbuf +
81                 xran_get_ecpri_hdr_size());
82         ecpri_hdr->ecpri_seq_id.e_bit = 0;
83     }
84
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;
89
90     return 0;
91 }
92
93 /**
94  * @brief Builds eCPRI header in xRAN packet
95  *
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
103  */
104 static int xran_build_ecpri_hdr_ex(struct rte_mbuf *mbuf,
105                               uint8_t ecpri_mesg_type,
106                               int payl_size,
107                               uint8_t CC_ID,
108                               uint8_t Ant_ID,
109                               uint8_t seq_id)
110 {
111     char *pChar = rte_pktmbuf_mtod(mbuf, char*);
112     struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *)(pChar + sizeof(struct ether_hdr));
113
114     if (NULL == ecpri_hdr)
115         return 1;
116
117     ecpri_hdr->cmnhdr.ecpri_ver       = XRAN_ECPRI_VER;
118     ecpri_hdr->cmnhdr.ecpri_resv      = 0;     // should be zero
119     ecpri_hdr->cmnhdr.ecpri_concat    = 0;
120     ecpri_hdr->cmnhdr.ecpri_mesg_type = ecpri_mesg_type;
121     ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(payl_size
122                                     + sizeof(struct data_section_hdr)
123                                     + sizeof(struct radio_app_common_hdr)
124                                     + xran_get_ecpri_hdr_size());
125
126     /* one to one lls-CU to RU only and band sector is the same */
127     ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID);
128
129     ecpri_hdr->ecpri_seq_id.seq_id = seq_id;
130
131     /* no transport layer fragmentation supported */
132     ecpri_hdr->ecpri_seq_id.sub_seq_id  = 0;
133     ecpri_hdr->ecpri_seq_id.e_bit       = 1;
134
135     return 0;
136 }
137
138
139 /**
140  * @brief Builds application layer of xRAN packet
141  *
142  * @param mbuf Initialized rte_mbuf packet
143  * @param app_hdr_input Radio App common header structure to be set in mbuf
144  *                      packet.
145  * @return int 0 on success, non zero on failure
146  */
147 static int build_application_layer(
148     struct rte_mbuf *mbuf,
149     const struct radio_app_common_hdr *app_hdr_input)
150 {
151     char *pChar = rte_pktmbuf_mtod(mbuf, char*);
152     struct radio_app_common_hdr *app_hdr = (struct radio_app_common_hdr *)(pChar + sizeof(struct ether_hdr)
153         + sizeof (struct xran_ecpri_hdr));
154
155     if (NULL == app_hdr)
156         return 1;
157
158     rte_memcpy(app_hdr, app_hdr_input, sizeof(struct radio_app_common_hdr));
159
160     return 0;
161 }
162
163 /**
164  * @brief Builds section header in xRAN packet
165  *
166  * @param mbuf Initialized rte_mbuf packet
167  * @param sec_hdr Section header structure to be set in mbuf packet
168  * @return int 0 on success, non zero on failure
169  */
170 static int build_section_hdr(
171     struct rte_mbuf *mbuf,
172     const struct data_section_hdr *sec_hdr)
173 {
174     char *pChar = rte_pktmbuf_mtod(mbuf, char*);
175     struct data_section_hdr *section_hdr = (struct data_section_hdr *)
176         (pChar + sizeof(struct ether_hdr) + sizeof (struct xran_ecpri_hdr) + sizeof(struct radio_app_common_hdr));
177
178     if (NULL == section_hdr)
179         return 1;
180
181     rte_memcpy(section_hdr, sec_hdr, sizeof(struct data_section_hdr));
182
183     return 0;
184 }
185 /**
186  * @brief Function for appending IQ samples data to the mbuf.
187  *
188  * @param mbuf Initialized rte_mbuf packet.
189  * @param iq_data_start Address of the first element in IQ data array.
190  * @param iq_data_num_bytes Size of the IQ data array.
191  * @param iq_data_offset IQ data btyes already sent.
192  * @return uint16_t Bytes that have been appended to the packet.
193  */
194 static uint16_t append_iq_samples_ex(
195     struct rte_mbuf *mbuf,
196     const void *iq_data_start,
197     const uint32_t iq_data_num_bytes,
198     enum xran_input_byte_order iq_buf_byte_order,
199     uint32_t do_copy)
200 {
201     char *pChar = rte_pktmbuf_mtod(mbuf, char*);
202     void *iq_sam_buf  = (pChar + sizeof(struct ether_hdr) + sizeof (struct xran_ecpri_hdr)
203                         + sizeof(struct radio_app_common_hdr)
204                         + sizeof(struct data_section_hdr));
205
206     if (iq_sam_buf == NULL){
207         print_err("iq_sam_buf == NULL\n");
208         return 0;
209     }
210     if(iq_buf_byte_order == XRAN_CPU_LE_BYTE_ORDER){
211         int idx = 0;
212         uint16_t *psrc = (uint16_t *)iq_data_start;
213         uint16_t *pdst = (uint16_t *)iq_sam_buf;
214         /* CPU byte order (le) of IQ to network byte order (be) */
215         for (idx = 0; idx < iq_data_num_bytes/sizeof(int16_t); idx++){
216             pdst[idx]  =  (psrc[idx]>>8) | (psrc[idx]<<8); //rte_cpu_to_be_16(psrc[idx]);
217         }
218     }else if(iq_buf_byte_order == XRAN_NE_BE_BYTE_ORDER){
219         if(do_copy)
220            rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start,  iq_data_num_bytes);
221     }
222
223     return iq_data_num_bytes;
224 }
225
226 /**
227  * @brief Function for appending IQ samples data to the mbuf.
228  *
229  * @param mbuf Initialized rte_mbuf packet.
230  * @param iq_data_start Address of the first element in IQ data array.
231  * @param iq_data_num_bytes Size of the IQ data array.
232  * @param iq_data_offset IQ data btyes already sent.
233  * @return uint16_t Bytes that have been appended to the packet.
234  */
235 static uint16_t append_iq_samples(
236     struct rte_mbuf *mbuf,
237     const void *iq_data_start,
238     const uint32_t iq_data_num_bytes,
239     const uint32_t iq_data_offset,
240     const uint8_t alignment)
241 {
242     uint16_t iq_bytes_to_send = 0;
243     uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf);
244
245     if (free_space_in_pkt > iq_data_num_bytes - iq_data_offset)
246         iq_bytes_to_send = iq_data_num_bytes - iq_data_offset;
247     else
248         iq_bytes_to_send = free_space_in_pkt;
249
250     /* don't cut off an iq in half */
251     iq_bytes_to_send -= iq_bytes_to_send % alignment;
252
253     void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_bytes_to_send);
254
255     rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start + iq_data_offset,
256             iq_bytes_to_send);
257
258     return iq_bytes_to_send;
259 }
260
261 /**
262  * @brief Builds compression header in xRAN packet
263  *
264  * @param mbuf Initialized rte_mbuf packet
265  * @param compression_hdr Section compression header structure
266  *                to be set in mbuf packet
267  * @return int 0 on success, non zero on failure
268  */
269 static int build_compression_hdr(
270     struct rte_mbuf *mbuf,
271     const struct data_section_compression_hdr *compr_hdr)
272 {
273     struct data_section_compression_hdr *compression_hdr =
274         (struct data_section_compression_hdr *)
275         rte_pktmbuf_append(mbuf, sizeof(*compression_hdr));
276
277     if (NULL == compression_hdr)
278         return 1;
279
280     rte_memcpy(compression_hdr, compr_hdr, sizeof(*compression_hdr));
281
282     return 0;
283 }
284
285 /**
286  * @brief Appends compression parameter in xRAN packet
287  *
288  * @param mbuf Initialized rte_mbuf packet
289  * @param ud_comp_paramr Compression param to be set in mbuf packet
290  * @return int 0 on success, non zero on failure
291  */
292 static int append_comp_param(struct rte_mbuf *mbuf, union compression_params *ud_comp_param)
293 {
294     union compression_params *compr_param =
295         (union compression_params *)rte_pktmbuf_append(mbuf, sizeof(union compression_params));
296
297     if (NULL == compr_param)
298         return 1;
299
300     rte_memcpy(compr_param, ud_comp_param, sizeof(union compression_params));
301
302     return 0;
303 }
304
305 /**
306  * @brief Function for starting preparion of IQ samples portions
307  *        to be sent in xRAN packet
308  *
309  * @param mbuf Initialized rte_mbuf packet.
310  * @param iq_data_start Address of the first element in IQ data array.
311  * @param iq_data_num_bytes Size of the IQ data array.
312  * @param iq_data_offset IQ data bytes already sent.
313  * @param alignment Size of IQ data alignment.
314  * @param pkt_gen_params Struct with parameters used for building packet
315  * @return int Number of bytes that have been appended
316                to the packet within a single data section appended.
317  */
318 int xran_prepare_iq_symbol_portion(
319     struct rte_mbuf *mbuf,
320     const void *iq_data_start,
321     const uint32_t iq_data_num_bytes,
322     uint32_t *iq_data_offset,
323     uint8_t alignment,
324     struct xran_up_pkt_gen_params *params,
325     int sub_seq_id)
326 {
327     uint8_t i = 0;
328     uint16_t iq_sam_bytes_sent = 0;
329
330     if (build_ecpri_hdr(mbuf, iq_data_num_bytes, *iq_data_offset, alignment))
331         return 0;
332
333     if (build_application_layer(mbuf, &(params->app_params)) != 0)
334         return 0;
335
336     if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0)
337         return 0;
338
339     if(params->compr_hdr_param.ud_comp_hdr.ud_comp_meth != XRAN_COMPMETHOD_NONE) {
340         if (build_compression_hdr(mbuf, &(params->compr_hdr_param)) !=0)
341             return 0;
342
343         if(append_comp_param(mbuf, &(params->compr_param)) !=0)
344             return 0;
345         }
346
347     return append_iq_samples(mbuf, iq_data_start, iq_data_num_bytes,
348            (*iq_data_offset), alignment);
349 }
350
351 /**
352  * @brief Function for extracting all IQ samples from xRAN packet
353  *        holding a single data section
354  * @param iq_data_start Address of the first element in IQ data array.
355  * @param symb_id Symbol ID to be extracted from ecpri header
356  * @param seq_id  Sequence ID to be extracted from radio header
357  * @return int Size of remaining mbuf filled with IQ samples
358                zero on failure
359  */
360 int xran_extract_iq_samples(struct rte_mbuf *mbuf,
361     void **iq_data_start,
362     uint8_t *CC_ID,
363     uint8_t *Ant_ID,
364     uint8_t *frame_id,
365     uint8_t *subframe_id,
366     uint8_t *slot_id,
367     uint8_t *symb_id,
368     struct ecpri_seq_id *seq_id,
369     uint16_t *num_prbu,
370     uint16_t *start_prbu,
371     uint16_t *sym_inc,
372     uint16_t *rb,
373     uint16_t *sect_id)
374 {
375 #if XRAN_MLOG_VAR
376     uint32_t mlogVar[10];
377     uint32_t mlogVarCnt = 0;
378 #endif
379     struct xran_eaxc_info result;
380
381     if (NULL == mbuf)
382         return 0;
383     if (NULL == iq_data_start)
384         return 0;
385
386     /* Process eCPRI header. */
387     const struct xran_ecpri_hdr *ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *);
388     if (ecpri_hdr == NULL)
389         return 0;
390
391     if (seq_id)
392         *seq_id = ecpri_hdr->ecpri_seq_id;
393
394     xran_decompose_cid((uint16_t)ecpri_hdr->ecpri_xtc_id, &result);
395
396     *CC_ID  = result.ccId;
397     *Ant_ID = result.ruPortId;
398
399     /* Process radio header. */
400     struct radio_app_common_hdr *radio_hdr =
401         (void *)rte_pktmbuf_adj(mbuf, sizeof(*ecpri_hdr));
402     if (radio_hdr == NULL)
403         return 0;       /* packet too short */
404
405     radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value);
406
407     if (frame_id)
408         *frame_id    = radio_hdr->frame_id;
409
410     if (subframe_id)
411         *subframe_id = radio_hdr->sf_slot_sym.subframe_id;
412
413     if (slot_id)
414         *slot_id     = radio_hdr->sf_slot_sym.slot_id;
415
416     if (symb_id)
417         *symb_id = radio_hdr->sf_slot_sym.symb_id;
418
419     /* Process data section hdr */
420     struct data_section_hdr *data_hdr =
421         (void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr));
422     if (data_hdr == NULL)
423         return 0;       /* packet too short */
424
425     /* cpu byte order */
426     data_hdr->fields.all_bits  = rte_be_to_cpu_32(data_hdr->fields.all_bits);
427
428     *num_prbu   = data_hdr->fields.num_prbu;
429     *start_prbu = data_hdr->fields.start_prbu;
430     *sym_inc    = data_hdr->fields.sym_inc;
431     *rb         = data_hdr->fields.rb;
432     *sect_id    = data_hdr->fields.sect_id;
433
434 #ifdef COMPRESSION
435     const struct data_section_compression_hdr *data_compr_hdr =
436         (void *) rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
437
438     const uint8_t *compr_param =
439         (void *)rte_pktmbuf_adj(mbuf, sizeof(*data_compr_hdr));
440
441     *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*compr_param));
442
443 #else
444     *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
445 #endif
446     if (*iq_data_start == NULL)
447         return 0;
448
449 #if XRAN_MLOG_VAR
450     mlogVar[mlogVarCnt++] = 0xBBBBBBBB;
451     mlogVar[mlogVarCnt++] = xran_lib_ota_tti;
452     mlogVar[mlogVarCnt++] = radio_hdr->frame_id;
453     mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.subframe_id;
454     mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.slot_id;
455     mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.symb_id;
456     mlogVar[mlogVarCnt++] = data_hdr->fields.sect_id;
457     mlogVar[mlogVarCnt++] = data_hdr->fields.start_prbu;
458     mlogVar[mlogVarCnt++] = data_hdr->fields.num_prbu;
459     mlogVar[mlogVarCnt++] = rte_pktmbuf_pkt_len(mbuf);
460     MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
461 #endif
462
463     return rte_pktmbuf_pkt_len(mbuf);
464 }
465
466 /**
467  * @brief Function for starting preparion of IQ samples portions
468  *        to be sent in xRAN packet
469  *
470  * @param mbuf Initialized rte_mbuf packet.
471  * @param iq_data_start Address of the first element in IQ data array.
472  * @param iq_data_num_bytes Size of the IQ data array.
473  * @param iq_data_offset IQ data bytes already sent.
474  * @param alignment Size of IQ data alignment.
475  * @param pkt_gen_params Struct with parameters used for building packet
476  * @return int Number of bytes that have been appended
477                to the packet within all appended sections.
478  */
479 int xran_prepare_iq_symbol_portion_no_comp(
480                         struct rte_mbuf *mbuf,
481                         const void *iq_data_start,
482                         const enum xran_input_byte_order iq_buf_byte_order,
483                         const uint32_t iq_data_num_bytes,
484                         struct xran_up_pkt_gen_no_compression_params *params,
485                         uint8_t CC_ID,
486                         uint8_t Ant_ID,
487                         uint8_t seq_id,
488                         uint32_t do_copy)
489 {
490     if(xran_build_ecpri_hdr_ex(mbuf,
491                            ECPRI_IQ_DATA,
492                            iq_data_num_bytes,
493                            CC_ID,
494                            Ant_ID,
495                            seq_id)){
496         print_err("xran_build_ecpri_hdr_ex return 0\n");
497         return 0;
498     }
499
500     if (build_application_layer(mbuf, &(params->app_params)) != 0){
501         print_err("build_application_layer return != 0\n");
502         return 0;
503     }
504
505     if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0){
506         print_err("build_section_hdr return != 0\n");
507         return 0;
508     }
509
510     return append_iq_samples_ex(mbuf, iq_data_start, iq_data_num_bytes, iq_buf_byte_order, do_copy);
511 }
512