o-du/phy
Intel O-RAN/X-RAN Generated Doxygen Documentation
xran_up_api.c
Go to the documentation of this file.
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 
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 
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;
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) +
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 +
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 
105 static int xran_build_ecpri_hdr_ex(struct rte_mbuf *mbuf,
106  uint8_t ecpri_mesg_type,
107  int payl_size,
108  uint8_t CC_ID,
109  uint8_t Ant_ID,
110  uint8_t seq_id,
111  uint8_t comp_meth)
112 {
113  char *pChar = rte_pktmbuf_mtod(mbuf, char*);
114  struct xran_ecpri_hdr *ecpri_hdr = (struct xran_ecpri_hdr *)(pChar + sizeof(struct ether_hdr));
115  uint16_t ecpri_payl_size = payl_size
116  + sizeof(struct data_section_hdr)
117  + sizeof(struct radio_app_common_hdr)
119 
120  if (comp_meth != XRAN_COMPMETHOD_NONE)
121  ecpri_payl_size += sizeof(struct data_section_compression_hdr);
122 
123  if (NULL == ecpri_hdr)
124  return 1;
125 
126  ecpri_hdr->cmnhdr.ecpri_ver = XRAN_ECPRI_VER;
127  ecpri_hdr->cmnhdr.ecpri_resv = 0; // should be zero
128  ecpri_hdr->cmnhdr.ecpri_concat = 0;
129  ecpri_hdr->cmnhdr.ecpri_mesg_type = ecpri_mesg_type;
130  ecpri_hdr->cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(ecpri_payl_size);
131 
132  /* one to one lls-CU to RU only and band sector is the same */
133  ecpri_hdr->ecpri_xtc_id = xran_compose_cid(0, 0, CC_ID, Ant_ID);
134 
135  ecpri_hdr->ecpri_seq_id.seq_id = seq_id;
136 
137  /* no transport layer fragmentation supported */
138  ecpri_hdr->ecpri_seq_id.sub_seq_id = 0;
139  ecpri_hdr->ecpri_seq_id.e_bit = 1;
140 
141  return 0;
142 }
143 
144 
153 static int build_application_layer(
154  struct rte_mbuf *mbuf,
155  const struct radio_app_common_hdr *app_hdr_input)
156 {
157  char *pChar = rte_pktmbuf_mtod(mbuf, char*);
158  struct radio_app_common_hdr *app_hdr = (struct radio_app_common_hdr *)(pChar + sizeof(struct ether_hdr)
159  + sizeof (struct xran_ecpri_hdr));
160 
161  if (NULL == app_hdr)
162  return 1;
163 
164  rte_memcpy(app_hdr, app_hdr_input, sizeof(struct radio_app_common_hdr));
165 
166  return 0;
167 }
168 
176 static int build_section_hdr(
177  struct rte_mbuf *mbuf,
178  const struct data_section_hdr *sec_hdr)
179 {
180  char *pChar = rte_pktmbuf_mtod(mbuf, char*);
181  struct data_section_hdr *section_hdr = (struct data_section_hdr *)
182  (pChar + sizeof(struct ether_hdr) + sizeof (struct xran_ecpri_hdr) + sizeof(struct radio_app_common_hdr));
183 
184  if (NULL == section_hdr)
185  return 1;
186 
187  rte_memcpy(section_hdr, sec_hdr, sizeof(struct data_section_hdr));
188 
189  return 0;
190 }
200 static uint16_t append_iq_samples_ex(
201  struct rte_mbuf *mbuf,
202  const void *iq_data_start,
203  const uint32_t iq_data_num_bytes,
204  enum xran_input_byte_order iq_buf_byte_order,
205  uint32_t do_copy)
206 {
207  char *pChar = rte_pktmbuf_mtod(mbuf, char*);
208  void *iq_sam_buf = (pChar + sizeof(struct ether_hdr) + sizeof (struct xran_ecpri_hdr)
209  + sizeof(struct radio_app_common_hdr)
210  + sizeof(struct data_section_hdr));
211 
212  if (iq_sam_buf == NULL){
213  print_err("iq_sam_buf == NULL\n");
214  return 0;
215  }
216  if(iq_buf_byte_order == XRAN_CPU_LE_BYTE_ORDER){
217  int idx = 0;
218  uint16_t *psrc = (uint16_t *)iq_data_start;
219  uint16_t *pdst = (uint16_t *)iq_sam_buf;
220  /* CPU byte order (le) of IQ to network byte order (be) */
221  for (idx = 0; idx < iq_data_num_bytes/sizeof(int16_t); idx++){
222  pdst[idx] = (psrc[idx]>>8) | (psrc[idx]<<8); //rte_cpu_to_be_16(psrc[idx]);
223  }
224  }
225 
226 #if 0
227  /* do not expect to do copy anymore */
228  else if(iq_buf_byte_order == XRAN_NE_BE_BYTE_ORDER){
229  if(do_copy) {
230  rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start, iq_data_num_bytes);
231  }
232  }
233 #endif
234 
235  return iq_data_num_bytes;
236 }
237 
247 static uint16_t append_iq_samples(
248  struct rte_mbuf *mbuf,
249  const void *iq_data_start,
250  const uint32_t iq_data_num_bytes,
251  const uint32_t iq_data_offset,
252  const uint8_t alignment)
253 {
254  uint16_t iq_bytes_to_send = 0;
255  uint16_t free_space_in_pkt = rte_pktmbuf_tailroom(mbuf);
256 
257  if (free_space_in_pkt > iq_data_num_bytes - iq_data_offset)
258  iq_bytes_to_send = iq_data_num_bytes - iq_data_offset;
259  else
260  iq_bytes_to_send = free_space_in_pkt;
261 
262  /* don't cut off an iq in half */
263  iq_bytes_to_send -= iq_bytes_to_send % alignment;
264 
265  void *iq_sam_buf = (void *)rte_pktmbuf_append(mbuf, iq_bytes_to_send);
266 
267  rte_memcpy(iq_sam_buf, (uint8_t *)iq_data_start + iq_data_offset,
268  iq_bytes_to_send);
269 
270  return iq_bytes_to_send;
271 }
272 
281 static int build_compression_hdr(
282  struct rte_mbuf *mbuf,
283  const struct data_section_compression_hdr *compr_hdr)
284 {
285  char *pChar = rte_pktmbuf_mtod(mbuf, char*);
287  (pChar + sizeof(struct ether_hdr) + sizeof (struct xran_ecpri_hdr) + sizeof(struct radio_app_common_hdr)
288  + sizeof(struct data_section_hdr));
289 
290  if (NULL == compression_hdr)
291  return 1;
292 
293  rte_memcpy(compression_hdr, compr_hdr, sizeof(*compression_hdr));
294 
295  return 0;
296 }
297 
305 static int append_comp_param(struct rte_mbuf *mbuf, union compression_params *ud_comp_param)
306 {
307  union compression_params *compr_param =
308  (union compression_params *)rte_pktmbuf_append(mbuf, sizeof(union compression_params));
309 
310  if (NULL == compr_param)
311  return 1;
312 
313  rte_memcpy(compr_param, ud_comp_param, sizeof(union compression_params));
314 
315  return 0;
316 }
317 
327 int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf,
328  void **iq_data_start,
329  uint8_t *CC_ID,
330  uint8_t *Ant_ID,
331  uint8_t *frame_id,
332  uint8_t *subframe_id,
333  uint8_t *slot_id,
334  uint8_t *symb_id,
335  struct ecpri_seq_id *seq_id,
336  uint16_t *num_prbu,
337  uint16_t *start_prbu,
338  uint16_t *sym_inc,
339  uint16_t *rb,
340  uint16_t *sect_id,
341  int8_t expect_comp,
342  uint8_t *compMeth,
343  uint8_t *iqWidth)
344 {
345 #if XRAN_MLOG_VAR
346  uint32_t mlogVar[10];
347  uint32_t mlogVarCnt = 0;
348 #endif
349  struct xran_eaxc_info result;
350 
351  if (NULL == mbuf)
352  return 0;
353  if (NULL == iq_data_start)
354  return 0;
355 
356  /* Process eCPRI header. */
357  const struct xran_ecpri_hdr *ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *);
358  if (ecpri_hdr == NULL)
359  return 0;
360 
361  if (seq_id)
362  *seq_id = ecpri_hdr->ecpri_seq_id;
363 
364  xran_decompose_cid((uint16_t)ecpri_hdr->ecpri_xtc_id, &result);
365 
366  *CC_ID = result.ccId;
367  *Ant_ID = result.ruPortId;
368 
369  /* Process radio header. */
370  struct radio_app_common_hdr *radio_hdr =
371  (void *)rte_pktmbuf_adj(mbuf, sizeof(*ecpri_hdr));
372  if (radio_hdr == NULL)
373  return 0; /* packet too short */
374 
375  radio_hdr->sf_slot_sym.value = rte_be_to_cpu_16(radio_hdr->sf_slot_sym.value);
376 
377  if (frame_id)
378  *frame_id = radio_hdr->frame_id;
379 
380  if (subframe_id)
381  *subframe_id = radio_hdr->sf_slot_sym.subframe_id;
382 
383  if (slot_id)
384  *slot_id = radio_hdr->sf_slot_sym.slot_id;
385 
386  if (symb_id)
387  *symb_id = radio_hdr->sf_slot_sym.symb_id;
388 
389  /* Process data section hdr */
390  struct data_section_hdr *data_hdr =
391  (void *)rte_pktmbuf_adj(mbuf, sizeof(*radio_hdr));
392  if (data_hdr == NULL)
393  return 0; /* packet too short */
394 
395  /* cpu byte order */
396  data_hdr->fields.all_bits = rte_be_to_cpu_32(data_hdr->fields.all_bits);
397 
398  *num_prbu = data_hdr->fields.num_prbu;
399  *start_prbu = data_hdr->fields.start_prbu;
400  *sym_inc = data_hdr->fields.sym_inc;
401  *rb = data_hdr->fields.rb;
402  *sect_id = data_hdr->fields.sect_id;
403 
404  if(expect_comp) {
405  const struct data_section_compression_hdr *data_compr_hdr =
406  (void *) rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
407 
408  if (data_compr_hdr == NULL)
409  return 0;
410 
411  *compMeth = data_compr_hdr->ud_comp_hdr.ud_comp_meth;
412  *iqWidth = data_compr_hdr->ud_comp_hdr.ud_iq_width;
413 
414  const uint8_t *compr_param =
415  (void *)rte_pktmbuf_adj(mbuf, sizeof(*data_compr_hdr));
416 
417  *iq_data_start = (void *)compr_param; /*rte_pktmbuf_adj(mbuf, sizeof(*compr_param))*/;
418  } else {
419  *iq_data_start = rte_pktmbuf_adj(mbuf, sizeof(*data_hdr));
420  }
421 
422  if (*iq_data_start == NULL)
423  return 0;
424 
425 #if XRAN_MLOG_VAR
426  mlogVar[mlogVarCnt++] = 0xBBBBBBBB;
427  mlogVar[mlogVarCnt++] = xran_lib_ota_tti;
428  mlogVar[mlogVarCnt++] = radio_hdr->frame_id;
429  mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.subframe_id;
430  mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.slot_id;
431  mlogVar[mlogVarCnt++] = radio_hdr->sf_slot_sym.symb_id;
432  mlogVar[mlogVarCnt++] = data_hdr->fields.sect_id;
433  mlogVar[mlogVarCnt++] = data_hdr->fields.start_prbu;
434  mlogVar[mlogVarCnt++] = data_hdr->fields.num_prbu;
435  mlogVar[mlogVarCnt++] = rte_pktmbuf_pkt_len(mbuf);
436  MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
437 #endif
438 
439  return rte_pktmbuf_pkt_len(mbuf);
440 }
441 
456  struct rte_mbuf *mbuf,
457  const void *iq_data_start,
458  const enum xran_input_byte_order iq_buf_byte_order,
459  const uint32_t iq_data_num_bytes,
460  struct xran_up_pkt_gen_params *params,
461  uint8_t CC_ID,
462  uint8_t Ant_ID,
463  uint8_t seq_id,
464  uint32_t do_copy)
465 {
466  if(xran_build_ecpri_hdr_ex(mbuf,
468  iq_data_num_bytes,
469  CC_ID,
470  Ant_ID,
471  seq_id,
473  print_err("xran_build_ecpri_hdr_ex return 0\n");
474  return 0;
475  }
476 
477  if (build_application_layer(mbuf, &(params->app_params)) != 0){
478  print_err("build_application_layer return != 0\n");
479  return 0;
480  }
481 
482  if (build_section_hdr(mbuf, &(params->sec_hdr)) != 0){
483  print_err("build_section_hdr return != 0\n");
484  return 0;
485  }
486 
487 
489  if (build_compression_hdr(mbuf, &(params->compr_hdr_param)) !=0)
490  return 0;
491 
492  /* payload expected to start with udCompParam */
493 
494  /*if(append_comp_param(mbuf, &(params->compr_param)) !=0)
495  return 0;*/
496  }
497 
498 
499  return append_iq_samples_ex(mbuf, iq_data_start, iq_data_num_bytes, iq_buf_byte_order, do_copy);
500 }
501 
uint8_t ecpri_concat
Definition: xran_pkt.h:115
uint32_t sym_inc
Definition: xran_pkt_up.h:73
uint32_t rb
Definition: xran_pkt_cp.h:243
#define XRAN_ECPRI_VER
Definition: xran_pkt.h:61
struct radio_app_common_hdr app_params
Definition: xran_up_api.h:47
uint8_t seq_id
Definition: xran_pkt.h:99
uint32_t xran_lib_ota_tti
Definition: xran_main.c:111
union radio_app_common_hdr::@5 sf_slot_sym
void xran_decompose_cid(uint16_t cid, struct xran_eaxc_info *result)
Decompose ecpriRtcid/ecpriPcid.
#define MLogAddVariables(x, y, z)
Definition: xran_mlog_lnx.h:49
struct compression_hdr ud_comp_hdr
Definition: xran_pkt_up.h:92
uint16_t xran_compose_cid(uint8_t CU_Port_ID, uint8_t BandSector_ID, uint8_t CC_ID, uint8_t Ant_ID)
Compose ecpriRtcid/ecpriPcid.
uint8_t ecpri_ver
Definition: xran_pkt.h:117
uint32_t num_prbu
Definition: xran_pkt_up.h:71
#define print_err(fmt, args...)
Definition: xran_printf.h:62
uint8_t ecpri_resv
Definition: xran_pkt.h:116
int xran_get_ecpri_hdr_size(void)
return eCPRI header size without eCPRI common header
xran_input_byte_order
Definition: xran_fh_o_du.h:471
int32_t xran_prepare_iq_symbol_portion(struct rte_mbuf *mbuf, const void *iq_data_start, const enum xran_input_byte_order iq_buf_byte_order, const uint32_t iq_data_num_bytes, struct xran_up_pkt_gen_params *params, uint8_t CC_ID, uint8_t Ant_ID, uint8_t seq_id, uint32_t do_copy)
Function for starting preparion of IQ samples portions to be sent in xRAN packet. ...
Definition: xran_up_api.c:455
uint32_t all_bits
Definition: xran_pkt_up.h:69
struct data_section_hdr sec_hdr
Definition: xran_up_api.h:48
uint8_t ud_iq_width
Definition: xran_pkt.h:208
uint8_t e_bit
Definition: xran_pkt.h:101
uint8_t sub_seq_id
Definition: xran_pkt.h:100
Modules provide debug prints and utility functions.
uint8_t ud_comp_meth
Definition: xran_pkt.h:213
struct xran_ecpri_cmn_hdr cmnhdr
Definition: xran_pkt.h:132
This file provides the definitions for User Plane Messages APIs.
uint32_t start_prbu
Definition: xran_pkt_up.h:72
rte_be16_t ecpri_xtc_id
Definition: xran_pkt.h:133
uint16_t subframe_id
Definition: xran_pkt.h:189
This file provides public interface to xRAN Front Haul layer implementation as defined in the ORAN-WG...
int32_t xran_extract_iq_samples(struct rte_mbuf *mbuf, void **iq_data_start, uint8_t *CC_ID, uint8_t *Ant_ID, uint8_t *frame_id, uint8_t *subframe_id, uint8_t *slot_id, uint8_t *symb_id, struct ecpri_seq_id *seq_id, uint16_t *num_prbu, uint16_t *start_prbu, uint16_t *sym_inc, uint16_t *rb, uint16_t *sect_id, int8_t expect_comp, uint8_t *compMeth, uint8_t *iqWidth)
Function for extracting all IQ samples from xRAN packet holding a single data section.
Definition: xran_up_api.c:327
struct ecpri_seq_id ecpri_seq_id
Definition: xran_pkt.h:134
uint32_t sect_id
Definition: xran_pkt_up.h:75
uint8_t ecpri_mesg_type
Definition: xran_pkt.h:118
union data_section_hdr::@18 fields
#define MLogTick()
Definition: xran_mlog_lnx.h:42
struct data_section_compression_hdr compr_hdr_param
Definition: xran_up_api.h:49
uint16_t ecpri_payl_size
Definition: xran_pkt.h:119
This file provides the definitions for Transport layer (eCPRI) API.