O-RAN E Maintenance Release contribution for ODULOW
[o-du/phy.git] / fhi_lib / lib / src / xran_delay_measurement.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 XRAN layer one-way delay measurement support
21  * @file xran_delay_measurement.c
22  * @ingroup group_source_xran
23  * @author Intel Corporation
24  **/
25 #define _GNU_SOURCE
26 #include <immintrin.h>
27 #include <assert.h>
28 #include <err.h>
29 #include <arpa/inet.h>
30 #include <sys/time.h>
31 #include <time.h>
32 #include <stdio.h>
33 #include <pthread.h>
34 #include <rte_eal.h>
35 #include <rte_ethdev.h>
36 #include <rte_mbuf.h>
37
38 #include "xran_common.h"
39 #include "ethdi.h"
40 #include "xran_pkt.h"
41 #include "xran_dev.h"
42 #include "xran_lib_mlog_tasks_id.h"
43 #include "xran_ecpri_owd_measurements.h"
44
45 #include "xran_printf.h"
46 #include "xran_mlog_lnx.h"
47
48 //#define ORAN_OWD_DEBUG_MSG_FLOW
49 //#define XRAN_OWD_DEBUG_MSG_FLOW
50 //#define XRAN_OWD_DEBUG_DELAY_INFO
51 //#define XRAN_OWD_DEBUG_TIME_STAMPS_INFO
52 //#define XRAN_OWD_DEBUG_MEAS_DB
53 //#define XRAN_OWD_TIMING_MODS
54
55
56     // Support for 1-way eCPRI delay measurement per section 3.2.4.6 of eCPRI Specification V2.0
57
58 uint64_t xran_ptp_to_host(uint64_t compValue)
59 {
60     return (rte_be_to_cpu_64(compValue));
61 }
62 void xran_host_to_ptp_ts(TimeStamp *ts, struct timespec *t)
63 {
64     uint64_t seconds, nanoseconds;
65
66     seconds = t->tv_sec;
67     nanoseconds = t->tv_nsec%1000000000LL;
68 #ifdef XRAN_OWD_DEBUG_DELAY_CONV_FUNCTIONS
69     printf("H2P_ts tv_sec %8"PRIx64" tv_nsec %8"PRIx64" seconds %8"PRIx64" ns %8"PRIx64" \n",t->tv_sec,t->tv_nsec,seconds,nanoseconds);
70 #endif
71
72     ts->secs_msb = rte_cpu_to_be_16((rte_be16_t)((seconds >> 32) & 0xFFFF));
73     ts->secs_lsb = rte_cpu_to_be_32((rte_be32_t)(seconds & 0xFFFFFFFF));
74     ts->ns       = rte_cpu_to_be_32((rte_be32_t)nanoseconds);
75 #ifdef XRAN_OWD_DEBUG_DELAY_CONV_FUNCTIONS
76     printf("Net order s_msb %4"PRIx16" s_lsb %8"PRIx32" ns %8"PRIx32" \n", ts->secs_msb, ts->secs_lsb,ts->ns );
77 #endif
78 }
79
80 uint64_t xran_ptp_ts_to_ns(TimeStamp *t)
81 {
82         uint64_t seconds, nanoseconds;
83         uint64_t ret_value;
84         // Convert to host order
85         t->secs_msb=rte_be_to_cpu_16(t->secs_msb);
86         t->secs_lsb=rte_be_to_cpu_32(t->secs_lsb);
87         seconds = ((uint64_t)t->secs_msb << 32) | ((uint64_t)t->secs_lsb );
88         nanoseconds = rte_be_to_cpu_32((uint64_t)t->ns);
89         ret_value = seconds * NS_PER_SEC + nanoseconds;
90 #ifdef XRAN_OWD_DEBUG_DELAY_CONV_FUNCTIONS
91         printf("PTP ts to ns sec_msb %4"PRIx16" secs_lsb %4"PRIx32" ns %4"PRIx32"  seconds %8"PRIx64" nanosec %8"PRIx64" ret_value %8"PRIx64"\n",t->secs_msb,t->secs_lsb,t->ns,seconds, nanoseconds,ret_value);
92 #endif
93         return ret_value;
94
95 }
96 static inline uint64_t xran_timespec_to_ns(struct timespec *t)
97 {
98     uint64_t ret_val;
99
100     ret_val  = t->tv_sec * NS_PER_SEC + t->tv_nsec;
101 #ifdef XRAN_OWD_DEBUG_DELAY_CONV_FUNCTIONS
102     printf("t->tv_sec is %08"PRIx64" tv_nsec is %08"PRIx64" ret_val is %08"PRIx64" ts_to_ns\n",t->tv_sec,t->tv_nsec,ret_val);
103 #endif
104     return ret_val;
105
106 }
107
108 void xran_ns_to_timespec(uint64_t ns, struct timespec *t)
109 {
110     t->tv_sec = ns/NS_PER_SEC;
111     t->tv_nsec = ns % NS_PER_SEC;
112
113 }
114
115 void xran_initialize_and_verify_owd_pl_length(void* handle)
116 {
117     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)handle;
118     
119     if ((p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id].owdm_PlLength == 0)||(p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id].owdm_PlLength < MIN_OWDM_PL_LENGTH))
120     {
121          // Use default length value
122          p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id].owdm_PlLength = MIN_OWDM_PL_LENGTH;
123     }
124     else if ( p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id].owdm_PlLength > MAX_OWDM_PL_LENGTH)
125     {
126          p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id].owdm_PlLength  = MAX_OWDM_PL_LENGTH;
127     }
128     
129 }
130
131 void xran_adjust_timing_parameters(void* Handle)
132 {
133     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx*)Handle;
134 #ifdef XRAN_OWD_TIMING_MODS
135     printf("delayAvg is %d and DELAY_THRESHOLD is %d \n", p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][0].delayAvg, DELAY_THRESHOLD);
136 #endif
137     if (p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][0].delayAvg < DELAY_THRESHOLD )
138         {
139             /* Modify the timing parameters */
140             if (p_xran_dev_ctx->fh_cfg.T1a_max_up >= ADJUSTMENT)
141                 p_xran_dev_ctx->fh_cfg.T1a_max_up -= ADJUSTMENT;
142             if (p_xran_dev_ctx->fh_cfg.T2a_max_up >= ADJUSTMENT)
143                 p_xran_dev_ctx->fh_cfg.T2a_max_up -= ADJUSTMENT;
144             if (p_xran_dev_ctx->fh_cfg.Ta3_min >= ADJUSTMENT)
145                 p_xran_dev_ctx->fh_cfg.Ta3_min -= ADJUSTMENT;
146             if (p_xran_dev_ctx->fh_cfg.T1a_max_cp_dl >= ADJUSTMENT)
147                 p_xran_dev_ctx->fh_cfg.T1a_max_cp_dl -= ADJUSTMENT;
148             if (p_xran_dev_ctx->fh_cfg.T1a_min_up >= ADJUSTMENT)
149                 p_xran_dev_ctx->fh_cfg.T1a_min_up -= ADJUSTMENT;
150             if (p_xran_dev_ctx->fh_cfg.T1a_max_up >= ADJUSTMENT)
151                 p_xran_dev_ctx->fh_cfg.T1a_max_up -= ADJUSTMENT;
152             if (p_xran_dev_ctx->fh_cfg.Ta4_min >= ADJUSTMENT)
153                 p_xran_dev_ctx->fh_cfg.Ta4_min -= ADJUSTMENT;
154             if (p_xran_dev_ctx->fh_cfg.Ta4_max >= ADJUSTMENT)
155                 p_xran_dev_ctx->fh_cfg.Ta4_max -= ADJUSTMENT;
156 #ifdef XRAN_OWD_TIMING_MODS
157             printf("Mod T1a_max_up is %d\n",p_xran_dev_ctx->fh_cfg.T1a_max_up);
158             printf("Mod T2a_max_up is %d\n",p_xran_dev_ctx->fh_cfg.T2a_max_up);
159             printf("Mod Ta3_min is %d\n",p_xran_dev_ctx->fh_cfg.Ta3_min);
160             printf("Mod T1a_max_cp_dl is %d\n",p_xran_dev_ctx->fh_cfg.T1a_max_cp_dl);
161             printf("Mod T1a_min_up is %d\n",p_xran_dev_ctx->fh_cfg.T1a_min_up);
162             printf("Mod T1a_max_up is %d\n",p_xran_dev_ctx->fh_cfg.T1a_max_up);
163             printf("Mod Ta4_min is %d\n",p_xran_dev_ctx->fh_cfg.Ta4_min);
164             printf("Mod Ta4_max is %d\n",p_xran_dev_ctx->fh_cfg.Ta4_max);
165 #endif
166         }
167    
168 }
169
170
171
172 void xran_compute_and_report_delay_estimate (struct xran_ecpri_del_meas_port *portData, uint16_t totalSamples, uint16_t id )
173 {
174     uint16_t i;
175     uint64_t *samples= portData->delaySamples;
176
177
178     for (i=2 ; i < MX_NUM_SAMPLES; i++) //Ignore first 2 samples
179     {
180         portData->delayAvg += samples[i];
181
182     }
183
184     // Average the delay by the number of samples
185     if ((totalSamples != 0)&&(totalSamples > 2))
186     {
187         portData->delayAvg /= (totalSamples-2);
188     }
189     // Report Average with printf
190     flockfile(stdout);
191     printf("OWD for port %i is %lu [ns] id %d \n", portData->portid, portData->delayAvg, id);
192     funlockfile(stdout);
193
194 }
195
196 int xran_get_delay_measurements_results (void* handle,  uint16_t port_id, uint8_t id, uint64_t* pdelay_avg)
197 {
198     int ret_value = FAIL;
199     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx*)handle;
200     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[id][port_id];
201     // Check is the one way delay measurement completed successfully
202     if (powdp->msState == XRAN_OWDM_DONE)
203     {
204         *pdelay_avg = powdp->delayAvg;
205         ret_value = OK;
206     }
207     return (ret_value);
208 }
209
210
211 void xran_build_owd_meas_ecpri_hdr(char* mbuf,    struct xran_ecpri_del_meas_cmn* eowdcmn)
212 {
213     union xran_ecpri_cmn_hdr *tmp= (union xran_ecpri_cmn_hdr*)mbuf;
214     /* Fill common header */
215     tmp->bits.ecpri_ver           = XRAN_ECPRI_VER;
216     tmp->bits.ecpri_resv          = 0;     // should be zero
217     tmp->bits.ecpri_concat        = 0;
218     tmp->bits.ecpri_mesg_type     = ECPRI_DELAY_MEASUREMENT;
219     tmp->bits.ecpri_payl_size    = 10 + eowdcmn->owdm_PlLength;
220     tmp->bits.ecpri_payl_size    = rte_cpu_to_be_16(tmp->bits.ecpri_payl_size);
221 }
222
223 void xran_add_at_and_measId_info_to_header(void* pbuf, uint8_t actionType, uint8_t MeasurementID)
224 {
225     struct xran_ecpri_delay_meas_pl* tmp = (struct xran_ecpri_delay_meas_pl*)pbuf;
226     // Fill ActionType and MeasurementId
227     tmp->ActionType = actionType;
228     tmp->MeasurementID = MeasurementID;
229 }
230
231 void xran_initialize_ecpri_del_meas_port(struct xran_ecpri_del_meas_cmn* pCmn, struct xran_ecpri_del_meas_port* pPort, uint16_t full)
232 {
233
234     uint16_t i=0;
235     // Initialize port parameters during the first pass
236     pPort->currentMeasID++;
237     pPort->runMeas = 1;
238     pPort->txDone = 0;
239
240     if (full)
241     {
242         pPort->numMeas = 0;
243         pPort->portid = pCmn->measVf;
244         pPort->delayAvg = 0;
245         pPort->delta = 0;
246         pPort->t1 = 0;
247         pPort->t2 = 0;
248         pPort->tr = 0;
249 #ifdef XRAN_OWD_DEBUG_MEAS_DB
250         printf("Clearing t1 and delta\n");
251 #endif
252
253         for (i=0; i < MX_NUM_SAMPLES; i++)
254         {
255             pPort->delaySamples[i] = 0;
256         }
257     }
258     // Set msState based on measMethod and whether the FHI is initiator or recipient
259
260     if (pCmn->initiator_en)
261     {
262         switch (pCmn->measMethod)
263         {
264             case XRAN_REQUEST:
265                 pPort->msState = XRAN_OWDM_WAITRESP;
266                 break;
267             case XRAN_REM_REQ:
268                 pPort->msState = XRAN_OWDM_WAITREQ;
269                 break;
270             case XRAN_REQ_WFUP:
271                 pPort->msState = XRAN_OWDM_WAITRESP;
272                 break;
273             case XRAN_REM_REQ_WFUP:
274                 pPort->msState = XRAN_OWDM_WAITREQWFUP;
275                 break;
276             default:
277                 pPort->msState = XRAN_OWDM_WAITRESP;
278                 break;
279         }
280     }
281     else
282     {
283         switch (pCmn->measMethod)
284         {
285             case XRAN_REQUEST:
286                 pPort->msState = XRAN_OWDM_WAITREQ;
287                 break;
288             case XRAN_REM_REQ:
289                 pPort->msState = XRAN_OWDM_WAITREMREQ;
290                 break;
291             case XRAN_REQ_WFUP:
292                 pPort->msState = XRAN_OWDM_WAITREQWFUP;
293                 break;
294             case XRAN_REM_REQ_WFUP:
295                 pPort->msState = XRAN_OWDM_WAITREMREQWFUP;
296                 break;
297             default:
298                 pPort->msState = XRAN_OWDM_WAITREQ;
299                 break;
300        }
301     }
302 }
303
304 int32_t xran_ecpri_port_update_required (struct xran_io_cfg * cfg, uint16_t port_id)
305 {
306     int32_t ret_value = 0;
307     int32_t* port = &cfg->port[0];
308
309     if (cfg != NULL)
310     {
311
312         struct xran_ecpri_del_meas_port* eowdp = &cfg->eowd_port[cfg->id][port_id];
313         struct xran_ecpri_del_meas_cmn*  eowdc = &cfg->eowd_cmn[cfg->id];
314
315
316         // Check if the current port has completed all the measurements to move to the next port
317         if (eowdp->numMeas == eowdc->numberOfSamples)
318         {
319             // Mark state as done and move to the next port
320             if (port_id < cfg->num_vfs)
321             {
322                 port_id++;
323                 if (port[port_id] == 0xFF)
324                 {
325                     // Done with all ports disable further execution
326                     eowdc->owdm_enable = 0;
327                 }
328                 else
329                 {
330                     eowdc->measVf++;
331                     eowdp= &cfg->eowd_port[cfg->id][port_id];
332                     // Initialize the next port
333 #ifdef XRAN_OWD_DEBUG_MEAS_DB
334                     printf("Init call_1 port %d\n", port_id);
335 #endif
336                     xran_initialize_ecpri_del_meas_port(eowdc, eowdp,1);
337                 }
338                 ret_value = 1;  // Wait for the next pass through the loop to go to the next port
339             }
340             else
341             {
342                 // Disable the measurements
343                 eowdc->owdm_enable = 0;
344                 ret_value = 1;
345             }
346         }
347         else
348         {
349             // Continue running on the same port
350             ret_value = 0;
351 //              xran_initialize_ecpri_del_meas_port(eowdc, eowdp,0); //Now this logic is driven by the receiver
352         }
353     }
354     else
355     {
356         errx(1, "Exit 1 epur with cfg null");
357     }
358     return ret_value;
359 }
360
361
362 /**
363  * @brief ecpri 2.0 one-way delay measurement transmitter control
364  *
365  * @ingroup group_source_xran
366  *
367  * @param port_id
368  *  port_id to be used
369  * @param handle
370  *  Pointer to an xran_device_ctx (cast)
371  *
372  * @return
373  *  OK on success
374  *  FAIL if failed to process the packet
375
376  */
377 int xran_ecpri_one_way_delay_measurement_transmitter(uint16_t port_id, void* handle)
378 {
379     // The ecpri one way delay measurement transmitter handles the transmission
380     // of the owd measurement packets on each of the vfs present in the system in a sequential order
381     // so the owd_meas_method is provided from the configuration file and it can be one of 4 possible
382     // methods: REQUEST, REM_REQ, REQ_WFUP or REM_REQ_WFUP
383     // In the current implementation the measurement is performed on one vf until completion of the number
384     // of measurements defined from the configuration file.
385     // A variable in the xran_ecpri_del_meas_cmn keeps track of the current vf that is using the transmitter and
386     // when the current vf completes all the measurements it moves to the next vf until all of the vfs complete
387     // the measurements
388     // In the current implementation the measurements start after the xran_if_current_state has reached the
389     // XRAN_RUNNING state (i.e. after having executed the xran_start())
390     // The measurements run only once for the current release.
391     int ret_value = FAIL;
392     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
393     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
394     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
395
396     if (powdc->measState == OWDMTX_INIT)
397     {
398         // Perform the initialization for the very first call to the transmitter for a given port
399         powdc->measVf = port_id;
400         powdc->measState = OWDMTX_ACTIVE;
401         // Check whether PL length was passed in config file and if it is within bounds
402         if ((powdc->owdm_PlLength == 0)|| ( powdc->owdm_PlLength < MIN_OWDM_PL_LENGTH ))
403         {
404             // Use default length value
405             powdc->owdm_PlLength = MIN_OWDM_PL_LENGTH;
406         }
407         else if ( powdc->owdm_PlLength > MAX_OWDM_PL_LENGTH)
408         {
409             powdc->owdm_PlLength = MAX_OWDM_PL_LENGTH;
410         }
411 #ifdef XRAN_OWD_DEBUG_MEAS_DB
412         printf("Clear call 2 port_id %d\n", port_id);
413 #endif
414         xran_initialize_ecpri_del_meas_port(powdc, powdp,1);
415     }
416
417     // Initiator State Machine , recipient state machine driven from process_delay_meas()
418 //    printf("owdm tx w state %d runMeas %d inen %d\n", powdp->msState,powdp->runMeas,powdc->initiator_en);
419
420     if ((powdp->runMeas != 0 )&&(powdc->initiator_en != 0)) // Current port still running measurements
421     {
422         switch (powdp->msState)
423         {
424             case XRAN_OWDM_WAITRESP:
425                 // Check the measmethod to define the action
426                 if (powdc->measMethod == XRAN_REQUEST)
427                 {
428                     if (!powdp->txDone)
429                     {
430 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
431                         printf("owdm ecpri tx req gen\n");
432 #endif
433                         if (xran_generate_delay_meas(port_id, handle, (uint8_t)ECPRI_REQUEST, powdc->measId) == 0 )
434                         {
435                             errx(1, "Exit 1 owdm tx port_id %d measId %d", port_id, powdc->measId);
436                         }
437                         powdp->txDone =1;
438                     }
439                 }
440                 else
441                 {
442                     // The only else corresponds to XRAN_REQ_WFUP
443                     if (!powdp->txDone)
444                     {
445 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
446                         printf("owdm ecpri tx req w fup gen\n");
447 #endif
448                         if (xran_generate_delay_meas(port_id, handle, (uint8_t)ECPRI_REQUEST_W_FUP , powdc->measId) == 0 )
449                         {
450                             errx(1, "Exit 2 owdm tx port_id %d measId %d", port_id, powdc->measId );
451                         }
452                         powdp->txDone=0;            // Needs fup
453                     }
454                 }
455                 break;
456             case XRAN_OWDM_WAITREQ:
457                 if (!powdp->txDone)
458                 {
459 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
460                     printf("owdm ecpri tx rem req gen\n");
461 #endif
462                     if (xran_generate_delay_meas(port_id, handle, (uint8_t)ECPRI_REMOTE_REQ , powdc->measId) == 0 )
463                     {
464                         errx(1, "Exit 3 owdm tx port_id %d measId %d", port_id, powdc->measId );
465                     }
466                     powdp->txDone=1;
467                 }
468                 break;
469             case XRAN_OWDM_WAITREQWFUP:
470                 if (!powdp->txDone)
471                 {
472 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
473                     printf("owdm ecpri tx rem req w fup gen\n");
474 #endif
475                     if (xran_generate_delay_meas(port_id, handle, (uint8_t)ECPRI_REMOTE_REQ_W_FUP , powdc->measId) == 0 )
476                     {
477                         errx(1, "Exit 4 owdm tx port_id %d measId %d", port_id, powdc->measId );
478                     }
479                     powdp->txDone=1;
480                 }
481                 break;
482             case XRAN_OWDM_GENFUP:
483                 if (!powdp->txDone)
484                 {
485 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
486                     printf("owdm ecpri follow up gen\n");
487 #endif
488                     if (xran_generate_delay_meas(port_id, handle, (uint8_t)ECPRI_FOLLOW_UP , powdc->measId) == 0 )
489                     {
490                         errx(1, "Exit 4 owdm tx port_id %d measId %d", port_id, powdc->measId );
491                     }
492                     powdp->txDone=1;
493                 }
494                 break;
495             case XRAN_OWDM_WAITFUP:
496             case XRAN_OWDM_DONE:
497             case XRAN_OWDM_IDLE:
498                 // Transmitter doesn't have to do anything in these states
499                 break;
500             default:
501                 errx(1, "Exit 5 owdm tx port_id %d measId %d id %d state %d", port_id, powdc->measId, p_xran_dev_ctx->fh_init.io_cfg.id, powdp->msState );
502
503         }
504     }
505     ret_value = OK;
506     return ret_value;
507
508 }
509
510 /**
511  * @brief Generate a Delay Measurement packet
512  *  Transport layer fragmentation is not supported.
513  *
514  * @ingroup group_source_xran
515  *
516  * @param port_id
517  *  port_id to be used
518  * @param handle
519  *  Pointer to an xran_device_ctx (cast)
520  * @param actionType
521  * actionType to be used in the owd measurement packet
522  * @param MeasurementID
523  * MeasurementID to be populated in the owd measurement packet
524  * @return
525  *  OK on success
526  *  FAIL if failed to process the packet
527
528  */
529 int xran_generate_delay_meas(uint16_t port_id, void* handle, uint8_t actionType, uint8_t MeasurementID )
530 {
531     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
532     struct xran_ecpri_delay_meas_pkt *ecpri_delmeas_pkt;
533     int pkt_len;
534     struct rte_mbuf *mbuf,*pkt;
535     char* pChar;
536     struct xran_ecpri_delay_meas_pl * pdm= NULL;
537     uint64_t tcv1,tr2m,trm;
538     struct timespec tr2, tr;
539     struct xran_io_cfg* cfg = &p_xran_dev_ctx->fh_init.io_cfg;
540     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
541     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
542     int32_t *port = &cfg->port[port_id];
543     int ret_value = FAIL;
544     struct rte_ether_addr addr;
545     uint16_t ethertype = ETHER_TYPE_ECPRI;
546
547 //    printf("in xran_generate_delay_meas for action_type %d\n", actionType);
548
549     pkt_len = sizeof(struct xran_ecpri_del_meas_pkt);
550     // Allocate a buffer from the pool
551     mbuf =xran_ethdi_mbuf_alloc();
552     if (mbuf == NULL)
553     {
554         MLogPrint(NULL);
555         errx(1,"exit 1 owdm gen");
556     }
557     pChar = rte_pktmbuf_append(mbuf, pkt_len);
558     if (pChar == NULL)
559     {
560         MLogPrint(NULL);
561         errx(1,"exit 2 owdm gen");
562     }
563     pChar = rte_pktmbuf_prepend(mbuf, sizeof(struct rte_ether_hdr));
564     if (pChar == NULL)
565     {
566         MLogPrint(NULL);
567         errx(1,"exit 3 owdm gen");
568     }
569
570     struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx();
571
572     struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*);
573     PANIC_ON(h == NULL, "mbuf prepend of ether_hdr failed");
574
575     /* Fill in the ethernet header. */
576     rte_eth_macaddr_get(port_id, &h->s_addr);          /* set source addr */
577
578     if (p_xran_dev_ctx->fh_init.io_cfg.id)
579     {
580 //        rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_du_addr[port_id],&h->d_addr);
581         h->d_addr = ctx->entities[port_id][ID_O_DU];   /* set dst addr */
582     }
583     else
584     {
585         h->d_addr = ctx->entities[port_id][ID_O_RU];   /* set dst addr */
586 //        rte_ether_addr_copy( (struct rte_ether_addr *)p_xran_dev_ctx->fh_init.p_o_ru_addr[port_id],&h->d_addr);
587     }
588
589     h->ether_type = rte_cpu_to_be_16(ethertype);       /* ethertype too */
590     mbuf->port = ctx->io_cfg.port[port_id];
591
592
593     // Prepare the ecpri header info
594     // Advance pointer to the begining of the ecpri common header
595     pChar = pChar + sizeof (struct rte_ether_hdr);
596     xran_build_owd_meas_ecpri_hdr(pChar, powdc );
597     // Advance pointer to the begining of the xran_ecpri_delay_meas_pl
598     pChar  = pChar + sizeof (union xran_ecpri_cmn_hdr);
599     xran_add_at_and_measId_info_to_header(pChar, actionType, MeasurementID);
600
601     pdm  = (struct xran_ecpri_delay_meas_pl *)rte_pktmbuf_mtod_offset(mbuf, struct xran_ecpri_delay_meas_pl *, sizeof(struct rte_ether_hdr) + sizeof(union xran_ecpri_cmn_hdr));
602     switch (actionType)
603     {
604         // For owd meas originator there are a subset of actionTypes used see ecpri 2.0 Figures 25 and 26 for the details
605         case ECPRI_REQUEST:
606             // Record t1, prepare Request Message and determine tcv1 and include both time stamps in the packet
607             // 1) Record the current timestamp when the preparation of the message started i.e. t1
608             if (clock_gettime(CLOCK_REALTIME, &tr ))     // t1
609             {
610                 return ret_value;
611             }
612             trm = xran_timespec_to_ns(&tr);
613 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
614             printf("trm at gen is %8"PRIx64" \n", trm);
615 #endif
616             // 2) Prepare the delay measurement request packet
617             pdm->ActionType = ECPRI_REQUEST;
618             // 3) Record the current timestamp at the moment that the delay measurement packet is ready to be transmitted tr2 i.e.t1+tcv1 and write it
619             //    to the Delay Measurement request packet PL field
620             if (clock_gettime(CLOCK_REALTIME, &tr2 ))     // ts
621             {
622                 return ret_value;
623             }
624             // 4) Convert host to ptp time stamp format for tr and write to the outgoing packet
625             xran_host_to_ptp_ts(&pdm->ts, &tr);
626             // 5) Convert from Timestamp tr2 to ns before computing the compensation value
627             tr2m = xran_timespec_to_ns(&tr2);
628             // 6) Compute tcv1 as tr2m-trm
629             tcv1 = tr2m - trm;
630 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
631             printf("tcv1 is %08"PRIx64"\n",tcv1);
632 #endif
633
634             // 7) write tcv1 to the CompensationValue field of the delay measurement request packet
635             pdm->CompensationValue = rte_cpu_to_be_64(tcv1);
636 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
637             printf("compensation value after net order %8"PRIx64" \n", pdm->CompensationValue);
638 #endif
639             // 8) Store t1 and tcv1 to be used later once we get the response message
640             powdp->currentMeasID = pdm->MeasurementID;
641             powdp->t1 = trm;
642             powdp->delta = tcv1;
643             powdp->msState =   XRAN_OWDM_WAITRESP;
644 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
645             printf("At req gen t1 %8"PRIx64" and delta %8"PRIx64"  port %d  \n",powdp->t1,powdp->delta,port_id);
646 #endif
647             break;
648
649         case ECPRI_REMOTE_REQ:
650             // Prepare and send Remote Request Message with zero timestamp and correction values
651             tr.tv_sec = 0;
652             tr.tv_nsec = 0;
653             tcv1 = 0;
654             // Convert host to ptp time stamp format for tr and write to the outgoing packet
655             xran_host_to_ptp_ts(&pdm->ts, &tr);
656             // write zero to the CompensationValue field of the delay measurement remote request packet
657             pdm->CompensationValue = rte_cpu_to_be_64(tcv1);
658             // 1) Prepare the delay measurement request packet
659             pdm->ActionType = ECPRI_REMOTE_REQ;
660             // 2) Store MeasurementID and msState to be checked once the Request Message is received
661             powdp->currentMeasID = pdm->MeasurementID;
662             powdp->msState =   XRAN_OWDM_WAITREQ;
663
664             break;
665
666         case ECPRI_REQUEST_W_FUP:
667             // Record t1, prepare Request with follow up Message and determine tcv1, send zero timestamp and correction value  in the packet
668             // 1) Record the current timestamp when the message preparation started i.e. t1
669             if (clock_gettime(CLOCK_REALTIME, &tr ))     // t1
670             {
671                 return ret_value;
672             }
673             trm = xran_timespec_to_ns(&tr);
674             // 2) Prepare the delay measurement remote request with follow up packet
675             pdm->ActionType = ECPRI_REQUEST_W_FUP;
676             // 3) Record the current timestamp at the moment that the delay measurement packet is ready to be transmitted tr2 i.e.t1+tcv1
677             if (clock_gettime(CLOCK_REALTIME, &tr2 ))     // ts
678             {
679                 return ret_value;
680             }
681             // 4) Convert from Timestamp tr2 to ns before computing the compensation value
682             tr2m = xran_timespec_to_ns(&tr2);
683             // 5) Compute tcv1 as tr2m-trm
684             tcv1 = tr2m - trm;
685             // Prepare and send Remote Request Message with zero timestamp and correction values
686             tr.tv_sec = 0;
687             tr.tv_nsec = 0;
688             powdp->delta = tcv1; // Save tcv1 while waiting for the Response
689             tcv1 = 0;
690             // Convert host to ptp time stamp format for tr and write to the outgoing packet
691             xran_host_to_ptp_ts(&pdm->ts, &tr);
692             // write zero to the CompensationValue field of the delay measurement remote request packet
693             pdm->CompensationValue = rte_cpu_to_be_64(tcv1);
694             // 6) Store MeasurementID and msState to be checked once the Request Message is received
695             powdp->currentMeasID = pdm->MeasurementID;
696             powdp->t1 = trm;
697             powdp->msState =   XRAN_OWDM_GENFUP;
698
699             break;
700
701         case ECPRI_FOLLOW_UP:
702             // Use the t1 and tcv1 values recorded in the ECPRI_REQUEST_W_FUP packet generation step and send these values in the follow up packet
703             // 1) Prepare the delay measurement follow up packet
704             pdm->ActionType = ECPRI_FOLLOW_UP;
705             // 2) Convert t1 from host to ptp format
706             xran_ns_to_timespec(powdp->t1, &tr);
707             // 3) Convert host to ptp time stamp format for tr and write to the outgoing packet
708             xran_host_to_ptp_ts(&pdm->ts, &tr);
709             // 4) write tcv1 to the CompensationValue field of the delay measurement request packet
710             pdm->CompensationValue = rte_cpu_to_be_64(powdp->delta);
711             powdp->currentMeasID = pdm->MeasurementID;
712             powdp->msState =   XRAN_OWDM_WAITRESP;
713             break;
714
715         case ECPRI_REMOTE_REQ_W_FUP:
716             // Prepare the Remote Request with follow up Message, send zero timestamp and correction value  in the packet
717             tr.tv_sec = 0;
718             tr.tv_nsec = 0;
719             tcv1 = 0;
720             // Convert host to ptp time stamp format for tr and write to the outgoing packet
721             xran_host_to_ptp_ts(&pdm->ts, &tr);
722             // write zero to the CompensationValue field of the delay measurement remote request packet
723             pdm->CompensationValue = rte_cpu_to_be_64(tcv1);
724             // 1) Prepare the delay measurement request packet
725             pdm->ActionType = ECPRI_REMOTE_REQ_W_FUP;
726             // 2) Store MeasurementID and msState to be checked once the Request Message is received
727             powdp->currentMeasID = pdm->MeasurementID;
728             powdp->msState =   XRAN_OWDM_WAITREQWFUP;
729
730             break;
731
732         default:
733             errx(1,"exit 4 owdm gen");
734             break;
735     }
736
737  //   printf("xran_gen_del_4n");
738
739     // Retrieve Ethernet Header for the port and copy to the packet
740     rte_eth_macaddr_get(port_id, &addr);
741 #ifdef XRAN_OWD_DEBUG_PKTS
742     printf("id is %d\n", p_xran_dev_ctx->fh_init.io_cfg.id);
743     printf("Port %u SRC MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
744         " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
745         (unsigned)port_id,
746         addr.addr_bytes[0], addr.addr_bytes[1], addr.addr_bytes[2],
747         addr.addr_bytes[3], addr.addr_bytes[4], addr.addr_bytes[5]);
748 #endif
749
750     if (p_xran_dev_ctx->fh_init.io_cfg.id)
751     {
752 #ifdef XRAN_OWD_DEBUG_PKTS
753         int8_t *pa = &p_xran_dev_ctx->fh_init.p_o_du_addr[0];
754         printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pa[0],pa[1],pa[2],pa[3],pa[4],pa[5]);
755 #endif
756         rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_du_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]);
757
758     }
759     else
760     {
761 #ifdef XRAN_OWD_DEBUG_PKTS
762         int8_t *pb = &p_xran_dev_ctx->fh_init.p_o_ru_addr[0];
763         printf("DST_MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pb[0],pb[1],pb[2],pb[3],pb[4],pb[5]);
764 #endif
765         rte_ether_addr_copy((struct rte_ether_addr *)&p_xran_dev_ctx->fh_init.p_o_ru_addr[0], (struct rte_ether_addr *)&h->d_addr.addr_bytes[0]);
766
767     }
768 #ifdef XRAN_OWD_DEBUG_PKTS
769     uint8_t *pc = &h->s_addr.addr_bytes[0];
770     printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]);
771     uint8_t *pd = &h->d_addr.addr_bytes[0];
772     printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]);
773 #endif
774     // Copy dest address from above
775     // Send out the packet
776     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &mbuf, 1);
777 // Try using the normal scheme of passing through the ring
778 //    ret_value = xran_enqueue_mbuf(mbuf, ctx->tx_ring[port_id]);
779 #ifdef XRAN_OWD_DEBUG_PKTS
780     printf("owdt rte_eth_tx_burst returns %d for port %d\n", ret_value,port_id);
781 #endif
782     return ret_value;
783 }
784
785
786 /**
787  * @brief Process a Delay Measurement Request packet
788  *
789  * @ingroup group_source_xran
790  *
791  * @param mbuf
792  *  The pointer of the packet buffer to be processed
793  * @param handle
794  *  Pointer to an xran_device_ctx (cast)
795  * @param xran_ecpri_delay_meas_pl
796  * Pointer to an eCPRI delay measurement PL
797  * @return
798  *  OK on success
799  *  FAIL if failed to process the packet
800  */
801 int xran_process_delmeas_request(struct rte_mbuf *pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
802 {
803     int ret_value = FAIL;
804
805     struct xran_ecpri_delay_meas_pl *txDelayHdr;
806     TimeStamp pt1;
807     struct rte_mbuf* pkt1;
808     char* pchar;
809     uint64_t tcv1, tcv2,t2m,trm, td12, t1m;
810     struct xran_ecpri_del_meas_pkt *pdm= NULL;
811     union xran_ecpri_cmn_hdr *cmn;
812     struct timespec tr, t2;
813     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
814     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
815     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
816     struct rte_ether_hdr *eth_hdr;
817     struct rte_ether_addr addr;
818     struct xran_ethdi_ctx *ctx = xran_ethdi_get_ctx();
819 //101620
820     struct xran_io_cfg* cfg = &p_xran_dev_ctx->fh_init.io_cfg;
821 //    struct xran_io_cfg *cfg = &ctx->io_cfg;
822     int32_t *port = &cfg->port[port_id];
823
824 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
825     printf("RX ecpri  Measure Request \n");
826 #endif
827     // Since we are processing the receipt of a delay measurement request packet the following actions
828     // need to be taken (Per eCPRI V2.0 Figure 25)
829     // 1) Record the current timestamp when the message was received i.e. tr
830     if (clock_gettime(CLOCK_REALTIME, &tr ))     // tr
831     {
832         errx(1, "Exit 1 owd rx f1 port_id %d", port_id);
833         return ret_value;
834     }
835
836     trm = xran_timespec_to_ns(&tr);
837     // 2) Copy MeasurementID to the Delay Measurement Response packet
838     //     but first prepend ethernet header since the info is still in the buffer
839 //    pchar = rte_pktmbuf_prepend(pkt, (uint16_t)(sizeof(struct rte_ether_hdr)+ sizeof(union xran_ecpri_cmn_hdr ))); // Pointer to new data start address 10/20/20 Now not removing ecpri_cmn in process_delay_meas
840     pchar = rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(struct rte_ether_hdr));
841     pkt1 = rte_pktmbuf_copy(pkt, _eth_mbuf_pool, 0, UINT32_MAX);
842     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt*, sizeof(struct rte_ether_hdr));
843     // 3) Get time stamp T1 from the Timestamp field i.e. t1
844     pt1  = pdm->deMeasPl.ts;
845     // 3a) Convert to ns in the host format
846     t1m = xran_ptp_ts_to_ns(&pt1);
847     // 4) Get the compensation value from the packet i.e. tcv1
848     tcv1 = rte_be_to_cpu_64(pdm->deMeasPl.CompensationValue);
849     // 5) Prepare the delay measurement response packet
850     pdm->deMeasPl.ActionType = ECPRI_RESPONSE;
851     // 6) Record the current timestamp at the moment that the delay measurement packet is ready to be transmitted i.e.t2 and write it
852     //    to the Delay Measurement response packet PL field
853     if (clock_gettime(CLOCK_REALTIME, &t2 ))     // t2
854     {
855         errx(1,"Exit 2 owd rx f1 port_id %d", port_id);
856         return ret_value;
857     }
858     // 7) Convert host to ptp time stamp format for t2 and write to the outgoing packet
859     xran_host_to_ptp_ts(&pdm->deMeasPl.ts, &t2);
860     // 8) Convert from Timestamp t2 to ns before computing the compensation value
861     t2m = xran_timespec_to_ns(&t2);
862     // 9) Compute tcv2 as t2-tr
863     tcv2 = t2m - trm;
864     // 10) write cv2 to the CompensationValue field of the delay measurement response packet
865     pdm->deMeasPl.CompensationValue = rte_cpu_to_be_64(tcv2);
866     // 11) Fill the ethernet header properly by swapping src and dest addressed from the copied frame
867     eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *);
868     /* Swap dest and src mac addresses. */
869     rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
870     rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
871     rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
872     // Still need to check ol_flags state and update if necessary
873     // Compute the delay td12 and save
874     // Still need to define the DB to save the info and run averages
875     td12 = t2m - tcv2 - (t1m + tcv1);
876     // 12) Send the response right away
877     struct rte_ether_hdr *h = (struct rte_ether_hdr *)rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr*);
878 #ifdef XRAN_OWD_DEBUG_PKTS
879     uint8_t *pc = &h->s_addr.addr_bytes[0];
880     printf(" Src MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pc[0],pc[1],pc[2],pc[3],pc[4],pc[5]);
881     uint8_t *pd = &h->d_addr.addr_bytes[0];
882     printf(" Dst MAC from packet: %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8" %02"PRIx8"\n", pd[0],pd[1],pd[2],pd[3],pd[4],pd[5]);
883 //    printf("EtherType: %04"PRIx16" \n",&h->ether_type);
884 #endif
885     pdm  = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) );
886     pdm->cmnhdr.bits.ecpri_payl_size     = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent
887     pdm->cmnhdr.bits.ecpri_payl_size    = rte_cpu_to_be_16(pdm->cmnhdr.bits.ecpri_payl_size);
888     pdm->cmnhdr.bits.ecpri_mesg_type = ECPRI_DELAY_MEASUREMENT;
889 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
890     printf ("pdm has:%02"PRIx8" %04"PRIx16" %02"PRIx8" %02"PRIx8" \n", pdm->cmnhdr.bits.ecpri_mesg_type, pdm->cmnhdr.bits.ecpri_payl_size, pdm->cmnhdr.bits.ecpri_ver,pdm->deMeasPl.MeasurementID);
891 #endif
892
893     // Copy dest address from above
894     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &pkt1, 1);  // Need to check for the proper method of getting the port and mac address
895 #ifdef  XRAN_OWD_DEBUG_MSG_FLOW
896     printf ("in dly ms req sending response rte_eth_tx_burst returns %d for port %d\n",ret_value, *port);
897 #endif
898     // 13) Update measurements DB and check if completed
899     powdp->delaySamples[powdp->numMeas]= td12 ;
900 #ifdef XRAN_OWD_DEBUG_DELAY_INFO
901     printf("Computed delay is %08"PRIx64" MeasNum %d portId %d id is %d \n",powdp->delaySamples[powdp->numMeas],powdp->numMeas, port_id, p_xran_dev_ctx->fh_init.io_cfg.id);
902 #endif
903
904     powdp->numMeas++;
905
906     if (powdp->numMeas == powdc->numberOfSamples)
907     {
908         xran_compute_and_report_delay_estimate(powdp, powdc->numberOfSamples, p_xran_dev_ctx->fh_init.io_cfg.id);
909         powdp->msState = XRAN_OWDM_DONE;
910         xran_if_current_state = XRAN_RUNNING;
911     }
912     else
913     {
914
915 //        powdp->msState = XRAN_OWDM_IDLE;
916         if (powdc->initiator_en)
917         {
918             // Reinitialize txDone for next pass
919             powdp->txDone = 0;
920 #ifdef XRAN_OWD_DEBUG_MEAS_DB
921             printf("Clear call 3 port id %d \n", port_id);
922 #endif
923             xran_initialize_ecpri_del_meas_port(powdc, powdp,0);
924         }
925     }
926     return 1;
927
928 }
929
930 int xran_process_delmeas_request_w_fup(struct rte_mbuf *pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
931 {
932     int ret_value = FAIL;
933     struct xran_ecpri_delay_meas_pl* txDelayHdr;
934     TimeStamp pt2;
935     struct rte_mbuf* pkt1;
936     uint64_t trm;
937     struct xran_ecpri_del_meas_pkt* pdm= ptr;
938     struct timespec tr;
939     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
940     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
941     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
942     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
943     struct xran_io_cfg *cfg = &ctx->io_cfg;
944     int32_t* port = &cfg->port[port_id];
945
946     // Since we are processing the receipt of a delay measurement request with follow up packet the following actions
947     // need to be taken (Per eCPRI V2.0 Figure 26)
948 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
949     printf("RX ecpri  Measure Request with fup\n");
950 #endif
951
952     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod(pkt, struct xran_ecpri_del_meas_pkt*);
953     // Record tr and save to memory with the associated measurement Id and Port
954     // 1) Record the current timestamp when the message was received i.e. tr
955     if (clock_gettime(CLOCK_REALTIME, &tr ))     // tr
956     {
957         errx(1, "Exit 1 owd rx f2 port_id %d",port_id);
958         return ret_value;
959     }
960     trm = xran_timespec_to_ns(&tr);
961     // Save trm so when the Follow Up packet is received we can compute tcv2 as t2-trm
962     powdp->tr = trm;
963     // Save the measurement Id
964     powdp->currentMeasID = pdm->deMeasPl.MeasurementID;
965     // Change the state to waiting for follow up
966     powdp->msState = XRAN_OWDM_WAITFUP;
967
968     return ret_value;
969
970 }
971
972 int xran_process_delmeas_response(struct rte_mbuf *pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
973 {
974     int ret_value = 1;
975     struct xran_ecpri_delay_meas_pl* txDelayHdr;
976     TimeStamp pt2;
977     struct rte_mbuf* pkt1;
978     uint64_t tcv1, tcv2,t2m,trm, td12;
979     struct xran_ecpri_del_meas_pkt* pdm;
980     struct timespec tr, t2;
981     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
982     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
983     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
984     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
985     struct xran_io_cfg *cfg = &ctx->io_cfg;
986     struct xran_io_cfg* cfg1 = &p_xran_dev_ctx->fh_init.io_cfg;
987     int32_t* port = &cfg->port[port_id];
988
989
990     // Since we are processing the receipt of a delay measurement response packet the following actions
991     // need to be taken (Per eCPRI V2.0 Figure 25)
992     // Need to know if a Remote Request was processed against this measurement ID if so then the receipt of the response
993     // is used to compute the one-way delay as td= (t2-tcv2) - (t1+tcv1) with t2, tcv2 contained in the packet and
994     // t1 and tcv1 stored from the previous Remote Request packet processing task
995 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
996     printf("RX ecpri  Measure Response \n");
997 #endif
998
999     pdm = (struct xran_ecpri_del_meas_pkt*)(struct xran_ecpri_del_meas_pkt *)rte_pktmbuf_mtod(pkt,  struct xran_ecpri_del_meas_pkt *);
1000     // Save the measurement Id
1001     powdp->currentMeasID = pdm->deMeasPl.MeasurementID;
1002
1003     // 1) Get time stamp T2 from the Timestamp field i.e. t2
1004     pt2  = pdm->deMeasPl.ts;
1005
1006     // 2a) Convert to ns in the host format
1007     t2m = xran_ptp_ts_to_ns(&pt2);
1008     // 3) Get the compensation value from the packet i.e. tcv2
1009     tcv2 = rte_be_to_cpu_64(pdm->deMeasPl.CompensationValue);
1010 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
1011     printf ("tcv2 at Gen is %08"PRIx64" \n",tcv2);
1012 #endif
1013     // Compute the delay using the stored t1 and tcv1 used in the request message
1014     // td= (t2-tcv2) - (t1+tcv1) where t1 and tcv1 have been stored previously for the same measurement ID
1015 #ifdef XRAN_OWD_DEBUG_TIME_STAMPS_INFO
1016     printf("Delay comp at orig has t2m %08"PRIx64"  tcv2 %08"PRIx64" t1 %08"PRIx64" delta %08"PRIx64" port_id %d \n", t2m,tcv2,powdp->t1 ,powdp->delta,port_id);
1017 #endif
1018     powdp->delaySamples[powdp->numMeas]= (t2m-tcv2) -(powdp->t1 + powdp->delta);
1019 #ifdef XRAN_OWD_DEBUG_DELAY_INFO
1020         printf("Computed delay is %08"PRIx64" MeasNum %d portId %d id is %d \n",powdp->delaySamples[powdp->numMeas],powdp->numMeas, port_id,p_xran_dev_ctx->fh_init.io_cfg.id );
1021 #endif
1022
1023     powdp->numMeas++;
1024
1025
1026
1027     if (powdp->numMeas == powdc->numberOfSamples)
1028     {
1029         xran_compute_and_report_delay_estimate(powdp, powdc->numberOfSamples,p_xran_dev_ctx->fh_init.io_cfg.id);
1030         powdp->msState = XRAN_OWDM_DONE;
1031         xran_if_current_state= XRAN_RUNNING;
1032     }
1033     else
1034     {
1035
1036 //        powdp->msState = XRAN_OWDM_IDLE;
1037         if (powdc->initiator_en)
1038         {
1039             // Reinitialize txDone for next pass
1040             powdp->txDone = 0;
1041 #ifdef XRAN_OWD_DEBUG_MEAS_DB
1042             printf("Clear call_4 port_id %d \n", port_id);
1043 #endif
1044             xran_initialize_ecpri_del_meas_port(powdc, powdp,0);
1045 #ifdef XRAN_OWD_DEBUG_MEAS_DB
1046             printf("Reseting done \n");
1047 #endif
1048
1049         }
1050
1051     }
1052     // Needs work and change ret_value to OK
1053     return ret_value;
1054 }
1055
1056 int xran_process_delmeas_rem_request(struct rte_mbuf *pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
1057 {
1058     int ret_value = FAIL;
1059     struct xran_ecpri_delay_meas_pl* txDelayHdr;
1060     struct rte_mbuf* pkt1;
1061     uint64_t tcv1,tr2m,trm;
1062     struct xran_ecpri_del_meas_pkt* pdm;
1063     char* pchar;
1064     struct timespec tr2, tr;
1065     struct rte_ether_hdr *eth_hdr;
1066     struct rte_ether_addr addr;
1067     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
1068     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
1069     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
1070     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
1071     struct xran_io_cfg *cfg = &ctx->io_cfg;
1072     int32_t* port = &cfg->port[port_id];
1073
1074     // Since we are processing the receipt of a delay measurement remote request packet the following actions
1075     // need to be taken (Per eCPRI V2.0 Figure 25)
1076 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1077     printf("RX ecpri  Measure Remote Request \n");
1078 #endif
1079
1080     // 1) Record the current timestamp when the message was received i.e. t1
1081     if (clock_gettime(CLOCK_REALTIME, &tr ))     // t1
1082     {
1083         errx(1,"Exit 1 owd rx f4 port_id %d", port_id);
1084         return ret_value;
1085     }
1086     trm = xran_timespec_to_ns(&tr);
1087     // 2) Copy MeasurementID to the Delay Measurement Request packet
1088     //     but first prepend ethernet header since the info is still in the buffer
1089     pchar = rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(struct rte_ether_hdr));
1090     pkt1 = rte_pktmbuf_copy(pkt, _eth_mbuf_pool, 0, UINT32_MAX);
1091     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt*, sizeof(struct rte_ether_hdr));
1092
1093     // 3) Prepare the delay measurement request packet
1094     pdm->deMeasPl.ActionType = ECPRI_REQUEST;
1095     // 4) Record the current timestamp at the moment that the delay measurement packet is ready to be transmitted tr2 i.e.t1+tcv1 and write it
1096     //    to the Delay Measurement request packet PL field
1097     if (clock_gettime(CLOCK_REALTIME, &tr2 ))     // tr2
1098     {
1099         errx(1,"Exit 2 owd rx f4 port_id %d", port_id);
1100         return ret_value;
1101     }
1102     // 5) Convert host to ptp time stamp format for tr2 and write to the outgoing packet
1103     xran_host_to_ptp_ts(&pdm->deMeasPl.ts, &tr);
1104     // 6) Convert from Timestamp tr2 to ns before computing the compensation value
1105     tr2m = xran_timespec_to_ns(&tr2);
1106     // 7) Compute tcv1 as tr2m-trm
1107     tcv1 = tr2m - trm;
1108     // 8) write tcv1 to the CompensationValue field of the delay measurement request packet
1109     pdm->deMeasPl.CompensationValue = rte_cpu_to_be_64(tcv1);
1110     // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame
1111     eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *);
1112     /* Swap dest and src mac addresses. */
1113     rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
1114     rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
1115     rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
1116     // 10) Send the response right away
1117     pdm  = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) );
1118     pdm->cmnhdr.bits.ecpri_payl_size     = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent
1119     pdm->cmnhdr.bits.ecpri_payl_size    = rte_cpu_to_be_16(pdm->cmnhdr.bits.ecpri_payl_size);
1120     pdm->cmnhdr.bits.ecpri_mesg_type = ECPRI_DELAY_MEASUREMENT;
1121 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1122     printf("Ecpri  Measure Sending Request Msg \n");
1123 #endif
1124     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &pkt1, 1);  // Need to check for the proper method of getting the port and mac address
1125     // Still need to check ol_flags state and update if necessary
1126     // Save the computed delays and the measurementId
1127     powdp->t1 = trm;
1128     powdp->delta = tcv1;
1129     powdp->currentMeasID = pdm->deMeasPl.MeasurementID;
1130     powdp->msState = XRAN_OWDM_WAITRESP;
1131     return ret_value;
1132
1133
1134 }
1135 int xran_process_delmeas_rem_request_w_fup(struct rte_mbuf* pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
1136 {
1137     int ret_value = FAIL;
1138     struct xran_ecpri_delay_meas_pl* txDelayHdr;
1139     TimeStamp pt2;
1140     struct rte_mbuf* pkt1;
1141     struct rte_mbuf* pkt2;
1142     uint64_t tcv1,tsm,t1;
1143     struct rte_ether_hdr *eth_hdr;
1144     struct rte_ether_addr addr;
1145     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
1146     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
1147     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
1148     struct xran_ecpri_del_meas_pkt* pdm;
1149     struct timespec tr, ts;
1150     char* pchar;
1151
1152
1153     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
1154     struct xran_io_cfg *cfg = &ctx->io_cfg;
1155     int32_t* port = &cfg->port[port_id];
1156     tsm = 0;
1157
1158     // Since we are processing the receipt of a delay measurement remote request with follow up packet the following
1159     // actions need to be taken (Per eCPRI V2.0 Figure 26)
1160     // record t1 for the packet arrival time and then prepare Request with follow up packet which uses 0 for timsetamp
1161     // and for correctionvalue.
1162 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1163     printf("RX ecpri  Measure Remote Request w Fup \n");
1164 #endif
1165     // 1) Record the current timestamp when the message was received i.e. t1
1166     if (clock_gettime(CLOCK_REALTIME, &tr ))     // t1
1167     {
1168         errx(1,"Exit 1 owd rx f5 port_id %d", port_id);
1169         return ret_value;
1170     }
1171     t1 = xran_timespec_to_ns(&tr);
1172     // 2) Copy MeasurementID to the Delay Measurement Request packet
1173     //     but first prepend ethernet header since the info is still in the buffer
1174     pchar = rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(struct rte_ether_hdr));
1175     pkt1 = rte_pktmbuf_copy(pkt, _eth_mbuf_pool, 0, UINT32_MAX);
1176
1177     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt*, sizeof(struct rte_ether_hdr));
1178
1179
1180     // 3) Prepare the delay measurement request w fup packet
1181     pdm->deMeasPl.ActionType = ECPRI_REQUEST_W_FUP;
1182     // 4) Zero the ts and CompensationValue entries in the packet
1183     ts.tv_sec=0;
1184     ts.tv_nsec =0;
1185     // 5) Convert host to ptp time stamp format for t2 and write to the outgoing packet
1186     xran_host_to_ptp_ts(&pdm->deMeasPl.ts, &ts);
1187     // 6) write zero to the CompensationValue field of the delay measurement response packet
1188     pdm->deMeasPl.CompensationValue = rte_cpu_to_be_64(tsm);
1189     // 7) Fill the ethernet header properly by swapping src and dest addressed from the copied frame
1190     eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *);
1191     /* Swap dest and src mac addresses. */
1192     rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
1193     rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
1194     rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
1195     // 8) Duplicate packet to be used for the follow up packet
1196     pkt2 = rte_pktmbuf_copy(pkt1, _eth_mbuf_pool, 0, UINT32_MAX);
1197     // 9) Record the current timestamp when the request with follow up is being sent
1198     if (clock_gettime(CLOCK_REALTIME, &ts ))     // ts
1199     {
1200         errx(1,"Exit 2 owd rx f5 port_id %d", port_id);
1201         return ret_value;
1202     }
1203     // 10) Send the request with follow up
1204 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1205     printf("ecpri Measure sending Request with Fup \n");
1206 #endif
1207     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &pkt1, 1);  // Need to check for the proper method of getting the port and mac address
1208
1209     // After the Request with follow up packet has been sent, prepare follow up packet with t1 and tcv1, where
1210     // tcv1 = ts - t1 and writing it to the outgoing packet
1211     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt2, struct xran_ecpri_del_meas_pkt*, sizeof(struct rte_ether_hdr));
1212     // 11) Prepare the delay measurement request with follow up packet
1213     pdm->deMeasPl.ActionType = ECPRI_FOLLOW_UP;
1214     // 12) Convert host to ptp time stamp format for t1 and write to the outgoing packet
1215     xran_host_to_ptp_ts(&pdm->deMeasPl.ts, &tr);
1216     // 13) Convert from Timestamp t2 to ns before computing the compensation value
1217     tsm = xran_timespec_to_ns(&ts);
1218     // 14) Compute tcv1 as tsm-t1
1219     tcv1 = tsm - t1;
1220     // 15) write cv1 to the CompensationValue field of the delay measurement response packet
1221     pdm->deMeasPl.CompensationValue = rte_cpu_to_be_64(tcv1);
1222
1223     // 16) Send the follow up message
1224 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1225     printf("ecpri Measure sending Follow Up \n");
1226 #endif
1227     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &pkt2, 1);  // Need to check for the proper method of getting the port and mac address
1228
1229     // Save trm since it will be used to compute tcv2 based on the arrival of the Follow Up packet
1230     powdp->currentMeasID = pdm->deMeasPl.MeasurementID;
1231     powdp->t1 = t1;
1232     powdp->delta = tcv1;
1233     powdp->msState =   XRAN_OWDM_WAITRESP;
1234
1235     return ret_value;
1236
1237 }
1238
1239 int xran_process_delmeas_follow_up(struct rte_mbuf *pkt, void* handle, struct xran_ecpri_del_meas_pkt* ptr, uint16_t port_id)
1240 {
1241     int ret_value = FAIL;
1242     struct xran_ecpri_delay_meas_pl *txDelayHdr;
1243     struct rte_mbuf *pkt1;
1244     char* pChar= NULL;
1245     uint64_t tcv1,tr2m, tcv2, t1;
1246     struct xran_ecpri_del_meas_pkt *pdm;
1247     struct timespec tr2, tr;
1248     struct rte_ether_hdr *eth_hdr;
1249     struct rte_ether_addr addr;
1250     TimeStamp pt1;
1251     struct xran_device_ctx* p_xran_dev_ctx = (struct xran_device_ctx *)handle;
1252     struct xran_ecpri_del_meas_cmn* powdc  = &p_xran_dev_ctx->fh_init.io_cfg.eowd_cmn[p_xran_dev_ctx->fh_init.io_cfg.id];
1253     struct xran_ecpri_del_meas_port* powdp = &p_xran_dev_ctx->fh_init.io_cfg.eowd_port[p_xran_dev_ctx->fh_init.io_cfg.id][port_id];
1254     struct xran_ethdi_ctx *const ctx = xran_ethdi_get_ctx();
1255     struct xran_io_cfg *cfg = &ctx->io_cfg;
1256     int32_t *port = &cfg->port[0];
1257     // Since we are processing the receipt of a delay measurement follow up packet the following actions
1258     // need to be taken (Per eCPRI V2.0 Figure 26)
1259 #ifdef XRAN_OWD_DEBUG_MSG_FLOW
1260     printf("ecpri Measure received Followup \n");
1261 #endif
1262
1263     // 1) Record the current timestamp when the message was received i.e. tr2
1264     if (clock_gettime(CLOCK_REALTIME, &tr2 ))     // tr2
1265     {
1266         errx(1,"Exit 1 owd rx f6 port_id %d", port_id);
1267         return ret_value;
1268     }
1269     tr2m = xran_timespec_to_ns(&tr2);
1270
1271
1272     // 2) Copy MeasurementID to the Delay Measurement Response packet
1273     //     but first prepend ethernet header since the info is still in the buffer
1274     pChar = rte_pktmbuf_prepend(pkt, (uint16_t)sizeof(struct rte_ether_hdr));
1275     pkt1 = rte_pktmbuf_copy(pkt, _eth_mbuf_pool, 0, UINT32_MAX);
1276     pdm = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt*, sizeof(struct rte_ether_hdr));
1277
1278     // 3) Get time stamp T1 from the Timestamp field i.e. t1
1279     pt1  = pdm->deMeasPl.ts;
1280     // 4) Convert to ns in the host format
1281     t1 = xran_ptp_ts_to_ns(&pt1);
1282     // 5) Get the compensation value from the packet i.e. tcv1
1283     tcv1 = rte_be_to_cpu_64(pdm->deMeasPl.CompensationValue);
1284
1285     // 6) Prepare the delay measurement response packet
1286     pdm->deMeasPl.ActionType = ECPRI_RESPONSE;
1287
1288     // 7) Convert host to ptp time stamp format for tr2 and write to the outgoing packet
1289     xran_host_to_ptp_ts(&pdm->deMeasPl.ts, &tr2);
1290     // 8) Convert from Timestamp tr2 to ns before computing the compensation value
1291     tr2m = xran_timespec_to_ns(&tr2);
1292     // 9) Compute tcv2 as tr2m-trm
1293     tcv2 = tr2m - powdp->tr;
1294     // 0) write tcv2 to the CompensationValue field of the delay measurement request packet
1295     pdm->deMeasPl.CompensationValue = rte_cpu_to_be_64(tcv2);
1296     // 9) Fill the ethernet header properly by swapping src and dest addressed from the copied frame
1297     eth_hdr = rte_pktmbuf_mtod(pkt1, struct rte_ether_hdr *);
1298     /* Swap dest and src mac addresses. */
1299     rte_ether_addr_copy(&eth_hdr->d_addr, &addr);
1300     rte_ether_addr_copy(&eth_hdr->s_addr, &eth_hdr->d_addr);
1301     rte_ether_addr_copy(&addr, &eth_hdr->s_addr);
1302     pdm  = (struct xran_ecpri_del_meas_pkt*)rte_pktmbuf_mtod_offset(pkt1, struct xran_ecpri_del_meas_pkt *, sizeof(struct rte_ether_hdr) );
1303     pdm->cmnhdr.bits.ecpri_payl_size     = 10 + powdc->owdm_PlLength; // 10 correponds to the xran_ecpri_delay_meas_pl minus the dummy_bytes field which now allows the user to select the length for this field to be sent
1304     pdm->cmnhdr.bits.ecpri_payl_size    = rte_cpu_to_be_16(pdm->cmnhdr.bits.ecpri_payl_size);
1305     pdm->cmnhdr.bits.ecpri_mesg_type = ECPRI_DELAY_MEASUREMENT;
1306
1307     // 10) Send the response right away
1308     ret_value = rte_eth_tx_burst((uint16_t)*port, 0, &pkt1, 1);  // Need to check for the proper method of getting the port and mac address
1309
1310     // Compute the delay using the stored t1 and tcv1 used in the request message
1311     // td= (t2-tcv2) - (t1+tcv1) where t1 and tcv1 have been stored previously for the same measurement ID
1312     powdp->delaySamples[powdp->numMeas]= (tr2m-tcv2) -(t1 + tcv1);
1313 #ifdef XRAN_OWD_DEBUG_DELAY_INFO
1314     printf("Computed delay is %08"PRIx64" MeasNum %d portId %d id %d \n",powdp->delaySamples[powdp->numMeas],powdp->numMeas,port_id,p_xran_dev_ctx->fh_init.io_cfg.id);
1315 #endif
1316     powdp->numMeas++;
1317
1318     if (powdp->numMeas == powdc->numberOfSamples)
1319     {
1320         xran_compute_and_report_delay_estimate(powdp, powdc->numberOfSamples, p_xran_dev_ctx->fh_init.io_cfg.id);
1321         powdp->msState = XRAN_OWDM_DONE;
1322         xran_if_current_state = XRAN_RUNNING;
1323     }
1324     else
1325     {
1326 ;
1327 //        powdp->msState = XRAN_OWDM_IDLE;
1328         if (powdc->initiator_en)
1329         {
1330             // Reinitialize txDone for next pass
1331             powdp->txDone = 0;
1332 #ifdef XRAN_OWD_DEBUG_MEAS_DB
1333             printf("Clear Call_5 port_id %d \n", port_id);
1334 #endif
1335             xran_initialize_ecpri_del_meas_port(powdc, powdp,0);
1336         }
1337     }
1338
1339     return ret_value;
1340
1341 }
1342
1343
1344 /**
1345  * @brief Parse a Delay Measurement packet
1346  *  Transport layer fragmentation is not supported.
1347  *
1348  * @ingroup group_source_xran
1349  *
1350  * @param mbuf
1351  *  The pointer of the packet buffer to be parsed
1352  * @param handle
1353  *  Pointer to an xran_device_ctx (cast)
1354  * @return
1355  *  OK on success
1356  *  FAIL if failed to process the packet
1357  */
1358 int process_delay_meas(struct rte_mbuf *pkt,  void* handle, uint16_t port_id)
1359 {
1360     struct xran_device_ctx * p_xran_dev_ctx = (struct xran_device_ctx *)handle;
1361     struct xran_ecpri_del_meas_pkt *ecpri_delmeas_pkt;
1362     union  xran_ecpri_cmn_hdr * ecpricmn;
1363     int ret_value = FAIL;
1364 #ifdef XRAN_OWD_DEBUG_PKTS
1365     printf("pdm Device is %d\n", p_xran_dev_ctx->fh_init.io_cfg.id);
1366 #endif
1367         /* Process eCPRI cmn header. */
1368
1369  //   (void *)rte_pktmbuf_adj(pkt, sizeof(*ecpricmn));
1370     ecpri_delmeas_pkt = (struct xran_ecpri_del_meas_pkt *)rte_pktmbuf_mtod(pkt,  struct xran_ecpri_del_meas_pkt *);
1371     // The processing of the delay measurement here corresponds to eCPRI sections 3.2.4.6.2 and 3.42.6.3
1372
1373     switch(ecpri_delmeas_pkt->deMeasPl.ActionType) {
1374         case ECPRI_REQUEST:
1375 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1376             printf("Proc rx  Dly Meas Req\n");
1377 #endif
1378             ret_value = xran_process_delmeas_request(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1379             break;
1380         case ECPRI_REQUEST_W_FUP:
1381 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1382             printf("Proc Dly Meas rx Req w Fup\n");
1383 #endif
1384             ret_value = xran_process_delmeas_request_w_fup(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1385             break;
1386         case ECPRI_RESPONSE:
1387 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1388             printf("Proc Dly Meas rx Resp\n");
1389 #endif
1390             ret_value = xran_process_delmeas_response(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1391             break;
1392         case ECPRI_REMOTE_REQ:
1393 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1394             printf("Proc Dly Meas rx Rem Req\n");
1395 #endif
1396             ret_value = xran_process_delmeas_rem_request(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1397            break;
1398         case ECPRI_REMOTE_REQ_W_FUP:
1399 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1400             printf("Proc Dly Meas Rem rx Req w Fup\n");
1401 #endif
1402             ret_value = xran_process_delmeas_rem_request_w_fup(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1403            break;
1404         case ECPRI_FOLLOW_UP:
1405 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1406             printf("Proc Dly Meas rx Fup\n");
1407 #endif
1408             ret_value = xran_process_delmeas_follow_up(pkt, p_xran_dev_ctx, ecpri_delmeas_pkt, port_id);
1409            break;
1410         default:
1411 #ifdef ORAN_OWD_DEBUG_MSG_FLOW
1412             printf("Proc Dly Meas default\n");
1413 #endif
1414            break;
1415     }
1416     return ret_value;
1417
1418 }