o-du/phy
Intel O-RAN/X-RAN Generated Doxygen Documentation
xran_app_frag.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 <stdio.h>
28 #include <stddef.h>
29 #include <errno.h>
30 
31 #include <rte_mbuf.h>
32 #include <rte_memcpy.h>
33 #include <rte_mempool.h>
34 #include <rte_debug.h>
35 
36 #include "xran_app_frag.h"
37 #include "xran_cp_api.h"
38 #include "xran_pkt_up.h"
39 #include "xran_printf.h"
40 #include "xran_common.h"
41 
42 /* Fragment alignment */
43 #define XRAN_PAYLOAD_RB_ALIGN (N_SC_PER_PRB*(IQ_BITS/8)*2)
45 static inline void __fill_xranhdr_frag(struct xran_up_pkt_hdr *dst,
46  const struct xran_up_pkt_hdr *src, uint16_t rblen_bytes,
47  uint16_t rboff_bytes, struct xran_section_info *sectinfo, uint32_t mf, uint8_t *seqid)
48 {
49  struct data_section_hdr loc_data_sec_hdr;
50  struct xran_ecpri_hdr loc_ecpri_hdr;
51 
52  rte_memcpy(dst, src, sizeof(*dst));
53 
54  dst->ecpri_hdr.ecpri_seq_id.seq_id = (*seqid)++;
55 
56  print_dbg("sec [%d %d] sec %d mf %d g_sec %d\n",sectinfo->startPrbc, sectinfo->numPrbc, dst->ecpri_hdr.ecpri_seq_id.seq_id, mf, *seqid);
57 
58  loc_data_sec_hdr.fields.all_bits = rte_be_to_cpu_32(dst->data_sec_hdr.fields.all_bits);
59 
60  /* update RBs */
61  loc_data_sec_hdr.fields.start_prbu = sectinfo->startPrbc + rboff_bytes/(N_SC_PER_PRB*(IQ_BITS/8*2));
62  loc_data_sec_hdr.fields.num_prbu = rblen_bytes/(N_SC_PER_PRB*(IQ_BITS/8*2));
63 
64  print_dbg("sec [%d %d] pkt [%d %d] rboff_bytes %d rblen_bytes %d\n",sectinfo->startPrbc, sectinfo->numPrbc, loc_data_sec_hdr.fields.start_prbu, loc_data_sec_hdr.fields.num_prbu,
65  rboff_bytes, rblen_bytes);
66 
67  dst->data_sec_hdr.fields.all_bits = rte_cpu_to_be_32(loc_data_sec_hdr.fields.all_bits);
68 
69  /* update length */
70  dst->ecpri_hdr.cmnhdr.ecpri_payl_size = rte_cpu_to_be_16(sizeof(struct radio_app_common_hdr) +
71  sizeof(struct data_section_hdr) + rblen_bytes + xran_get_ecpri_hdr_size());
72 }
73 
74 
75 static inline void __free_fragments(struct rte_mbuf *mb[], uint32_t num)
76 {
77  uint32_t i;
78  for (i = 0; i != num; i++)
79  rte_pktmbuf_free(mb[i]);
80 }
81 
103 int32_t
104 xran_app_fragment_packet(struct rte_mbuf *pkt_in, /* eth hdr is prepended */
105  struct rte_mbuf **pkts_out,
106  uint16_t nb_pkts_out,
107  uint16_t mtu_size,
108  struct rte_mempool *pool_direct,
109  struct rte_mempool *pool_indirect,
110  struct xran_section_info *sectinfo,
111  uint8_t *seqid)
112 {
113  struct rte_mbuf *in_seg = NULL;
114  uint32_t out_pkt_pos = 0, in_seg_data_pos = 0;
115  uint32_t more_in_segs;
116  uint16_t fragment_offset, frag_size;
117  uint16_t frag_bytes_remaining;
118  struct eth_xran_up_pkt_hdr *in_hdr;
119  struct xran_up_pkt_hdr *in_hdr_xran;
120 
121  /*
122  * Ensure the XRAN payload length of all fragments is aligned to a
123  * multiple of 48 bytes (1 RB with IQ of 16 bits each)
124  */
125  frag_size = ((mtu_size - sizeof(struct eth_xran_up_pkt_hdr) - RTE_PKTMBUF_HEADROOM)/XRAN_PAYLOAD_RB_ALIGN)*XRAN_PAYLOAD_RB_ALIGN;
126 
127 
128  print_dbg("frag_size %d\n",frag_size);
129 
130  in_hdr = rte_pktmbuf_mtod(pkt_in, struct eth_xran_up_pkt_hdr *);
131 
132  in_hdr_xran = &in_hdr->xran_hdr;
133 
134  /* Check that pkts_out is big enough to hold all fragments */
135  if (unlikely(frag_size * nb_pkts_out <
136  (uint16_t)(pkt_in->pkt_len - sizeof (struct xran_up_pkt_hdr)))){
137  print_err("-EINVAL\n");
138  return -EINVAL;
139  }
140 
141  in_seg = pkt_in;
142  in_seg_data_pos = sizeof(struct eth_xran_up_pkt_hdr);
143  out_pkt_pos = 0;
144  fragment_offset = 0;
145 
146  more_in_segs = 1;
147  while (likely(more_in_segs)) {
148  struct rte_mbuf *out_pkt = NULL, *out_seg_prev = NULL;
149  uint32_t more_out_segs;
150  struct xran_up_pkt_hdr *out_hdr;
151 
152  /* Allocate direct buffer */
153  out_pkt = rte_pktmbuf_alloc(pool_direct);
154  if (unlikely(out_pkt == NULL)) {
155  print_err("pool_direct -ENOMEM\n");
156  __free_fragments(pkts_out, out_pkt_pos);
157  return -ENOMEM;
158  }
159 
160  print_dbg("[%d] out_pkt %p\n",more_in_segs, out_pkt);
161 
162  /* Reserve space for the XRAN header that will be built later */
163  //out_pkt->data_len = sizeof(struct xran_up_pkt_hdr);
164  //out_pkt->pkt_len = sizeof(struct xran_up_pkt_hdr);
165  if(rte_pktmbuf_append(out_pkt, sizeof(struct xran_up_pkt_hdr)) ==NULL){
166  rte_panic("sizeof(struct xran_up_pkt_hdr)");
167  }
168  frag_bytes_remaining = frag_size;
169 
170  out_seg_prev = out_pkt;
171  more_out_segs = 1;
172  while (likely(more_out_segs && more_in_segs)) {
173  uint32_t len;
174 #ifdef XRAN_ATTACH_MBUF
175  struct rte_mbuf *out_seg = NULL;
176 
177  /* Allocate indirect buffer */
178  print_dbg("Allocate indirect buffer \n");
179  out_seg = rte_pktmbuf_alloc(pool_indirect);
180  if (unlikely(out_seg == NULL)) {
181  print_err("pool_indirect -ENOMEM\n");
182  rte_pktmbuf_free(out_pkt);
183  __free_fragments(pkts_out, out_pkt_pos);
184  return -ENOMEM;
185  }
186 
187  print_dbg("[%d %d] out_seg %p\n",more_out_segs, more_in_segs, out_seg);
188  out_seg_prev->next = out_seg;
189  out_seg_prev = out_seg;
190 
191  /* Prepare indirect buffer */
192  rte_pktmbuf_attach(out_seg, in_seg);
193 #endif
194  len = frag_bytes_remaining;
195  if (len > (in_seg->data_len - in_seg_data_pos)) {
196  len = in_seg->data_len - in_seg_data_pos;
197  }
198 #ifdef XRAN_ATTACH_MBUF
199  out_seg->data_off = in_seg->data_off + in_seg_data_pos;
200  out_seg->data_len = (uint16_t)len;
201  out_pkt->pkt_len = (uint16_t)(len +
202  out_pkt->pkt_len);
203  out_pkt->nb_segs += 1;
204 #else
205 {
206  char* pChar = rte_pktmbuf_mtod(in_seg, char*);
207  void *iq_src = (pChar + in_seg_data_pos);
208  void *iq_dst = rte_pktmbuf_append(out_pkt, len);
209 
210  print_dbg("rte_pktmbuf_attach\n");
211  if(iq_src && iq_dst)
212  rte_memcpy(iq_dst, iq_src, len);
213  else
214  print_err("iq_src %p iq_dst %p\n len %d room %d\n", iq_src, iq_dst, len, rte_pktmbuf_tailroom(out_pkt));
215 }
216 #endif
217  in_seg_data_pos += len;
218  frag_bytes_remaining -= len;
219 
220  /* Current output packet (i.e. fragment) done ? */
221  if (unlikely(frag_bytes_remaining == 0))
222  more_out_segs = 0;
223 
224  /* Current input segment done ? */
225  if (unlikely(in_seg_data_pos == in_seg->data_len)) {
226  in_seg = in_seg->next;
227  in_seg_data_pos = 0;
228 
229  if (unlikely(in_seg == NULL))
230  more_in_segs = 0;
231  }
232  }
233 
234  /* Build the XRAN header */
235  print_dbg("Build the XRAN header\n");
236  out_hdr = rte_pktmbuf_mtod(out_pkt, struct xran_up_pkt_hdr *);
237 
238  __fill_xranhdr_frag(out_hdr, in_hdr_xran,
239  (uint16_t)out_pkt->pkt_len - sizeof(struct xran_up_pkt_hdr),
240  fragment_offset, sectinfo, more_in_segs, seqid);
241 
242  fragment_offset = (uint16_t)(fragment_offset +
243  out_pkt->pkt_len - sizeof(struct xran_up_pkt_hdr));
244 
245  //out_pkt->l3_len = sizeof(struct xran_up_pkt_hdr);
246 
247  /* Write the fragment to the output list */
248  pkts_out[out_pkt_pos] = out_pkt;
249  print_dbg("out_pkt_pos %d data_len %d pkt_len %d\n", out_pkt_pos, out_pkt->data_len, out_pkt->pkt_len);
250  out_pkt_pos ++;
251  //rte_pktmbuf_dump(stdout, out_pkt, 96);
252  }
253 
254  return out_pkt_pos;
255 }
256 
257 
#define N_SC_PER_PRB
Definition: common.h:49
#define print_dbg(fmt, args...)
Definition: xran_printf.h:54
struct xran_up_pkt_hdr xran_hdr
Definition: xran_pkt_up.h:168
uint32_t num_prbu
Definition: xran_pkt_up.h:71
#define print_err(fmt, args...)
Definition: xran_printf.h:62
uint16_t startPrbc
Definition: xran_cp_api.h:193
int xran_get_ecpri_hdr_size(void)
return eCPRI header size without eCPRI common header
uint32_t all_bits
Definition: xran_pkt_up.h:69
#define XRAN_PAYLOAD_RB_ALIGN
Definition: xran_app_frag.c:43
int32_t xran_app_fragment_packet(struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t nb_pkts_out, uint16_t mtu_size, struct rte_mempool *pool_direct, struct rte_mempool *pool_indirect, struct xran_section_info *sectinfo, uint8_t *seqid)
#define IQ_BITS
Definition: xran_pkt_up.h:50
Header file for functions to perform application level fragmentation.
Modules provide debug prints and utility functions.
XRAN layer common functionality for both lls-CU and RU as well as C-plane and U-plane.
uint32_t start_prbu
Definition: xran_pkt_up.h:72
Definitions and support functions to process XRAN packet.
union data_section_hdr::@18 fields
This file provides the definitions for Control Plane Messages APIs.