* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / lib / src / xran_transport.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 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 for Transport lyaer (eCPRI) API.
21  *
22  * @file xran_transport.c
23  * @ingroup group_lte_source_xran
24  * @author Intel Corporation
25  *
26  **/
27
28 #include <stdint.h>
29 #include <endian.h>
30 #include <immintrin.h>
31 #include <rte_common.h>
32 #include <rte_config.h>
33
34 #include "xran_fh_o_du.h"
35 #include "xran_common.h"
36 #include "xran_transport.h"
37 #include "xran_pkt_cp.h"
38 #include "xran_cp_api.h"
39 #include "xran_up_api.h"
40 #include "xran_printf.h"
41
42
43 /**
44  * @brief return eCPRI header size without eCPRI common header
45  *
46  * @ingroup xran
47  *
48  * @return the size of eCPRI header without common header
49  */
50 int xran_get_ecpri_hdr_size(void)
51 {
52     return(sizeof(struct xran_ecpri_hdr) - sizeof(union xran_ecpri_cmn_hdr));
53 }
54
55 /**
56  * @brief Compose ecpriRtcid/ecpriPcid
57  *
58  * @ingroup xran
59  *
60  * @param CU_Port_ID CU Port ID
61  * @param BanbSector_ID Band Sector ID
62  * @param CC_ID Component Carrier ID
63  * @param Ant_ID RU Port ID (antenna ID)
64  * @return uint16_t composed ecpriRtcid/ecpriPcid (network byte order)
65  */
66 uint16_t xran_compose_cid(uint8_t CU_Port_ID, uint8_t BandSector_ID, uint8_t CC_ID, uint8_t Ant_ID)
67 {
68   uint16_t cid;
69   struct xran_eaxcid_config *conf;
70
71     conf = xran_get_conf_eAxC(NULL);
72
73     if(conf == NULL)
74       rte_panic("conf == NULL");
75
76     cid = ((CU_Port_ID      << conf->bit_cuPortId)      & conf->mask_cuPortId)
77         | ((BandSector_ID   << conf->bit_bandSectorId)  & conf->mask_bandSectorId)
78         | ((CC_ID           << conf->bit_ccId)          & conf->mask_ccId)
79         | ((Ant_ID          << conf->bit_ruPortId)      & conf->mask_ruPortId);
80
81     return (rte_cpu_to_be_16(cid));
82 }
83
84 /**
85  * @brief Decompose ecpriRtcid/ecpriPcid
86  *
87  * @ingroup xran
88  *
89  * @param cid composed ecpriRtcid/ecpriPcid (network byte order)
90  * @param result the pointer of the structure to store decomposed values
91  * @return none
92  */
93 void xran_decompose_cid(uint16_t cid, struct xran_eaxc_info *result)
94 {
95   struct xran_eaxcid_config *conf;
96
97     conf = xran_get_conf_eAxC(NULL);
98     cid = rte_be_to_cpu_16(cid);
99
100     if(conf == NULL)
101       rte_panic("conf == NULL");
102
103     result->cuPortId        = (cid&conf->mask_cuPortId)     >> conf->bit_cuPortId;
104     result->bandSectorId    = (cid&conf->mask_bandSectorId) >> conf->bit_bandSectorId;
105     result->ccId            = (cid&conf->mask_ccId)         >> conf->bit_ccId;
106     result->ruPortId        = (cid&conf->mask_ruPortId)     >> conf->bit_ruPortId;
107
108     return;
109 }
110
111 /**
112  * @brief modify the payload size of eCPRI header in xRAN packet
113  *
114  * @ingroup xran
115  *
116  * @param mbuf Initialized rte_mbuf packet which has eCPRI header already
117  * @param size payload size to be updated
118  * @return none
119  */
120 inline void xran_update_ecpri_payload_size(struct rte_mbuf *mbuf, int size)
121 {
122   struct xran_ecpri_hdr *ecpri_hdr;
123
124     ecpri_hdr = rte_pktmbuf_mtod(mbuf, struct xran_ecpri_hdr *);
125
126     ecpri_hdr->cmnhdr.bits.ecpri_payl_size = rte_cpu_to_be_16(size);
127 }
128
129
130 /**
131  * @brief Build ECPRI header and returns added length
132  *
133  * @ingroup xran
134  *
135  * @param mbuf
136  *  The pointer of the packet buffer to be parsed
137  * @param CC_ID
138  *  Component Carrier ID for this C-Plane message
139  * @param Ant_ID
140  *  Antenna ID(RU Port ID) for this C-Plane message
141  * @param seq_id
142  *  Sequence ID for this C-Plane message
143  * @param ecpri_hdr
144  *  The pointer to ECPRI header
145  * @return
146  *  added payload size on success
147  *  XRAN_STATUS_RESOURCE if failed to allocate the space to packet buffer
148  */
149 int xran_build_ecpri_hdr(struct rte_mbuf *mbuf,
150                         uint8_t CC_ID, uint8_t Ant_ID,
151                         uint8_t seq_id,
152                         struct xran_ecpri_hdr **ecpri_hdr)
153 {
154   uint32_t payloadlen;
155   struct xran_ecpri_hdr *tmp;
156
157     tmp = (struct xran_ecpri_hdr *)rte_pktmbuf_append(mbuf, sizeof(struct xran_ecpri_hdr));
158     if(unlikely(tmp == NULL)) {
159         print_err("Fail to allocate the space for eCPRI hedaer!");
160         return (XRAN_STATUS_RESOURCE);
161         }
162
163     /* Fill common header */
164     /*tmp->cmnhdr.bits.ecpri_ver           = XRAN_ECPRI_VER;
165     //tmp->cmnhdr.bits.ecpri_resv          = 0;     // should be zero
166     //tmp->cmnhdr.bits.ecpri_concat        = 0;
167     //tmp->cmnhdr.bits.ecpri_mesg_type     = ECPRI_RT_CONTROL_DATA;*/
168
169     tmp->cmnhdr.data.data_num_1 = (XRAN_ECPRI_VER << xran_ecpri_cmn_hdr_bitfield_EcpriVer)
170                                 | (ECPRI_RT_CONTROL_DATA << xran_ecpri_cmn_hdr_bitfield_EcpriMsgType);
171     tmp->ecpri_xtc_id               = xran_compose_cid(0, 0, CC_ID, Ant_ID);
172
173     /* TODO: Transport layer fragmentation is not supported */
174     //tmp->ecpri_seq_id.bits.seq_id        = seq_id;
175     //tmp->ecpri_seq_id.bits.sub_seq_id    = 0;
176     //tmp->ecpri_seq_id.bits.e_bit         = 1;
177     tmp->ecpri_seq_id.data.data_num_1 = (seq_id << ecpri_seq_id_bitfield_seq_id)
178                                       | (1 << ecpri_seq_id_bitfield_e_bit);
179
180     /* Starts with eCPRI header size */
181     payloadlen = XRAN_ECPRI_HDR_SZ; //xran_get_ecpri_hdr_size();
182
183     *ecpri_hdr = tmp;
184
185     return (payloadlen);
186 }
187
188 /**
189  * @brief Parse ECPRI header
190  *
191  * @ingroup xran
192  *
193  * @param mbuf
194  *  The pointer of the packet buffer to be parsed
195  * @param ecpri_hdr
196  *  The pointer to ECPRI header
197  * @param pkt_info
198  *  The pointer of sturcture to store the information from header
199  * @return
200  *  XRAN_STATUS_SUCCESS on success
201  *  XRAN_STATUS_INVALID_PACKET if failed to parse the packet
202  */
203 int xran_parse_ecpri_hdr(struct rte_mbuf *mbuf,
204                     struct xran_ecpri_hdr **ecpri_hdr,
205                     struct xran_recv_packet_info *pkt_info)
206 {
207     int ret = XRAN_STATUS_SUCCESS;
208
209     *ecpri_hdr = rte_pktmbuf_mtod(mbuf, void *);
210     if(*ecpri_hdr == NULL) {
211         print_err("Invalid packet - eCPRI hedaer!");
212         return (XRAN_STATUS_INVALID_PACKET);
213         }
214
215     if(((*ecpri_hdr)->cmnhdr.bits.ecpri_ver != XRAN_ECPRI_VER) || ((*ecpri_hdr)->cmnhdr.bits.ecpri_resv != 0)){
216         print_err("Invalid eCPRI version - %d", (*ecpri_hdr)->cmnhdr.bits.ecpri_ver);
217         print_err("Invalid reserved field - %d", (*ecpri_hdr)->cmnhdr.bits.ecpri_resv);
218         return (XRAN_STATUS_INVALID_PACKET);
219     }
220
221     /* Process eCPRI header */
222     /*if((*ecpri_hdr)->cmnhdr.ecpri_ver != XRAN_ECPRI_VER) {
223         print_err("Invalid eCPRI version - %d", (*ecpri_hdr)->cmnhdr.ecpri_ver);
224         ret = XRAN_STATUS_INVALID_PACKET;
225         }*/
226     /*if((*ecpri_hdr)->cmnhdr.ecpri_resv != 0) {
227         print_err("Invalid reserved field - %d", (*ecpri_hdr)->cmnhdr.ecpri_resv);
228         ret = XRAN_STATUS_INVALID_PACKET;
229         }*/
230
231
232     if(pkt_info != NULL) {
233         /* store the information from header */
234         pkt_info->ecpri_version = (*ecpri_hdr)->cmnhdr.bits.ecpri_ver;
235         pkt_info->msg_type      = (enum ecpri_msg_type)(*ecpri_hdr)->cmnhdr.bits.ecpri_mesg_type;
236         pkt_info->payload_len   = rte_be_to_cpu_16((*ecpri_hdr)->cmnhdr.bits.ecpri_payl_size);
237
238         pkt_info->seq_id        = (*ecpri_hdr)->ecpri_seq_id.bits.seq_id;
239         pkt_info->subseq_id     = (*ecpri_hdr)->ecpri_seq_id.bits.sub_seq_id;
240         pkt_info->ebit          = (*ecpri_hdr)->ecpri_seq_id.bits.e_bit;
241         xran_decompose_cid((*ecpri_hdr)->ecpri_xtc_id, &(pkt_info->eaxc));
242         }
243
244     return (ret);
245 }
246