Coverage Report

Created: 2025-02-15 06:25

/src/wireshark/epan/dissectors/packet-ecpri.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-ecpri.c
2
 * Routines for eCPRI dissection
3
 * Copyright 2019, Maximilian Kohler <maximilian.kohler@viavisolutions.com>
4
 * Copyright 2024, Tomasz Woszczynski <duchowe50k@gmail.com>
5
 *
6
 * Wireshark - Network traffic analyzer
7
 * By Gerald Combs <gerald@wireshark.org>
8
 * Copyright 1998 Gerald Combs
9
 *
10
 * SPDX-License-Identifier: GPL-2.0-or-later
11
 *
12
 * ------------------------------------------------------------------------------------------------
13
 * eCPRI Transport Network V1.2 -- Specifications
14
 * http://www.cpri.info/downloads/Requirements_for_the_eCPRI_Transport_Network_V1_2_2018_06_25.pdf
15
 * eCPRI Transport Network V2.0 -- Specifications
16
 * https://www.cpri.info/downloads/eCPRI_v_2.0_2019_05_10c.pdf
17
 *
18
 * May carry ORAN FH-CUS (packet-oran.c) - Message Types, 0, 2
19
 * See https://specifications.o-ran.org/specifications, WG4, Fronthaul Interfaces Workgroup
20
 * ------------------------------------------------------------------------------------------------
21
 */
22
23
#include "config.h"
24
#include <epan/packet.h>
25
#include <epan/prefs.h>
26
#include <epan/expert.h>
27
#include <epan/etypes.h>
28
#include <epan/tfs.h>
29
#include <epan/unit_strings.h>
30
#include <proto.h>
31
32
#include "epan/dissectors/packet-ptp.h"
33
34
/**************************************************************************************************/
35
/* Definition for eCPRI lengths                                                                   */
36
/**************************************************************************************************/
37
/* eCPRI Common Header (4 Bytes) */
38
6.79k
#define ECPRI_HEADER_LENGTH                         4U
39
/* Message Type Length */
40
0
#define ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH         4U
41
30
#define ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH         4U
42
0
#define ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH         4U
43
12
#define ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH         8U
44
18
#define ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH        12U
45
35
#define ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH        20U
46
20
#define ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH         3U
47
33
#define ECPRI_MSG_TYPE_7_PAYLOAD_MIN_LENGTH         4U
48
8
#define ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH         9U
49
2
#define ECPRI_MSG_TYPE_11_PAYLOAD_LENGTH           12U
50
1
#define ECPRI_MSG_TYPE_7_ELEMENT_SIZE               8U
51
52
/**************************************************************************************************/
53
/* Definition for Action Types in Message Type 5: One-way Delay Measurement                       */
54
/**************************************************************************************************/
55
42
#define ECPRI_MSG_TYPE_5_REQ                    0x00
56
0
#define ECPRI_MSG_TYPE_5_REQ_FOLLOWUP           0x01
57
28
#define ECPRI_MSG_TYPE_5_RESPONSE               0x02
58
#define ECPRI_MSG_TYPE_5_REMOTE_REQ             0x03
59
#define ECPRI_MSG_TYPE_5_REMOTE_REQ_FOLLOWUP    0x04
60
24
#define ECPRI_MSG_TYPE_5_FOLLOWUP               0x05
61
#define ECPRI_MSG_TYPE_5_RESERVED_MIN           0x06
62
#define ECPRI_MSG_TYPE_5_RESERVED_MAX           0xFF
63
64
/**************************************************************************************************/
65
/* Definition for Event Types in Message Type 7: Event Indication                                 */
66
/**************************************************************************************************/
67
32
#define ECPRI_MSG_TYPE_7_FAULT_INDICATION       0x00
68
28
#define ECPRI_MSG_TYPE_7_FAULT_INDICATION_ACK   0x01
69
15
#define ECPRI_MSG_TYPE_7_NOTIF_INDICATION       0x02
70
27
#define ECPRI_MSG_TYPE_7_SYNC_REQUEST           0x03
71
27
#define ECPRI_MSG_TYPE_7_SYNC_ACK               0x04
72
13
#define ECPRI_MSG_TYPE_7_SYNC_END_INDICATION    0x05
73
#define ECPRI_MSG_TYPE_7_RESERVED_MIN           0x06
74
#define ECPRI_MSG_TYPE_7_RESERVED_MAX           0xFF
75
76
/**************************************************************************************************/
77
/* Definition for Fault/Notification Ranges in Message Type 7: Event Indication                   */
78
/**************************************************************************************************/
79
#define ECPRI_MSG_TYPE_7_FAULTS_MIN             0x000
80
0
#define ECPRI_MSG_TYPE_7_FAULTS_MAX             0x3FF
81
0
#define ECPRI_MSG_TYPE_7_NOTIF_MIN              0x400
82
0
#define ECPRI_MSG_TYPE_7_NOTIF_MAX              0x7FF
83
0
#define ECPRI_MSG_TYPE_7_VENDOR_MIN             0x800
84
0
#define ECPRI_MSG_TYPE_7_VENDOR_MAX             0xFFF
85
86
/**************************************************************************************************/
87
/* Definition for Action Types in Message Type 11: IWF Delay Control                              */
88
/**************************************************************************************************/
89
0
#define ECPRI_MSG_TYPE_11_REQUEST_GET_DELAYS    0x00
90
#define ECPRI_MSG_TYPE_11_RESPONSE_GET_DELAYS   0x01
91
#define ECPRI_MSG_TYPE_11_RESERVED_MIN          0x02
92
#define ECPRI_MSG_TYPE_11_RESERVED_MAX          0xFF
93
94
/**************************************************************************************************/
95
/* Function Prototypes                                                                            */
96
/**************************************************************************************************/
97
void proto_register_ecpri(void);
98
void proto_reg_handoff_ecpri(void);
99
100
/**************************************************************************************************/
101
/* Initialize the subtree pointers                                                                */
102
/**************************************************************************************************/
103
static int ett_ecpri;
104
static int ett_ecpri_header;
105
static int ett_ecpri_payload;
106
static int ett_ecpri_timestamp;
107
static int ett_ecpri_element;
108
109
/**************************************************************************************************/
110
/* Initialize the protocol and registered fields                                                  */
111
/**************************************************************************************************/
112
static int proto_ecpri;
113
114
static int hf_payload;
115
116
/* Fields for eCPRI Common Header */
117
static int hf_common_header;
118
static int hf_common_header_ecpri_protocol_revision;
119
static int hf_common_header_reserved;
120
static int hf_common_header_c_bit;
121
static int hf_common_header_ecpri_message_type;
122
static int hf_common_header_ecpri_payload_size;
123
124
/* Common to several message types */
125
static int hf_pc_id;
126
127
/* Fields for Message Type 0: IQ Data */
128
static int hf_iq_data_seq_id;
129
static int hf_iq_data_iq_samples_of_user_data;
130
131
/* Fields for Message Type 1: Bit Sequence */
132
static int hf_bit_sequence_seq_id;
133
static int hf_bit_sequence_bit_sequence_of_user_data;
134
135
/* Fields for Message Type 2: Real-Time Control Data */
136
static int hf_real_time_control_data_rtc_id;
137
static int hf_real_time_control_data_seq_id;
138
static int hf_real_time_control_data_rtc_data;
139
140
/* Fields for Message Type 3: Generic Data Transfer */
141
static int hf_generic_data_transfer_seq_id;
142
static int hf_generic_data_transfer_data_transferred;
143
144
/* Fields for Message Type 4: Remote Memory Access */
145
static int hf_remote_memory_access_id;
146
static int hf_remote_memory_access_read_write;
147
static int hf_remote_memory_access_request_response;
148
static int hf_remote_memory_access_element_id;
149
static int hf_remote_memory_access_address;
150
static int hf_remote_memory_access_data_length;
151
static int hf_remote_memory_access_data;
152
153
/* Fields for Message Type 5: One-Way Delay Measurement */
154
static int hf_one_way_delay_measurement_id;
155
static int hf_one_way_delay_measurement_action_type;
156
static int hf_one_way_delay_measurement_timestamp;
157
static int hf_one_way_delay_measurement_timestamp_seconds;
158
static int hf_one_way_delay_measurement_timestamp_nanoseconds;
159
static int hf_one_way_delay_measurement_compensation_value;
160
static int hf_one_way_delay_measurement_compensation_value_subns;
161
static int hf_one_way_delay_measurement_dummy_bytes;
162
163
static int hf_one_way_delay_measurement_calculated_delay;
164
static int hf_one_way_delay_measurement_calculated_delay_request_frame;
165
static int hf_one_way_delay_measurement_calculated_delay_response_frame;
166
167
168
/* Fields for Message Type 6: Remote Reset */
169
static int hf_remote_reset_reset_id;
170
static int hf_remote_reset_reset_code;
171
static int hf_remote_reset_vendor_specific_payload;
172
173
/* Fields for Message Type 7: Event Indication */
174
static int hf_event_indication_event_id;
175
static int hf_event_indication_event_type;
176
static int hf_event_indication_sequence_number;
177
static int hf_event_indication_number_of_faults_notifications;
178
static int hf_event_indication_element;
179
static int hf_event_indication_element_id;
180
static int hf_event_indication_raise_cease;
181
static int hf_event_indication_fault_notification;
182
static int hf_event_indication_additional_information;
183
184
/* Fields for Message Type 8: IWF Start-Up */
185
static int hf_iwf_start_up_hyperframe_number; /* #Z field */
186
static int hf_iwf_start_up_subframe_number; /* #X field */
187
static int hf_iwf_start_up_timestamp;
188
static int hf_iwf_start_up_fec_bit_indicator;
189
static int hf_iwf_start_up_scrambling_bit_indicator;
190
static int hf_iwf_start_up_line_rate;
191
static int hf_iwf_start_up_data_transferred;
192
193
/* Fields for Message Type 11: IWF Delay Control */
194
static int hf_iwf_delay_control_delay_control_id;
195
static int hf_iwf_delay_control_action_type;
196
static int hf_iwf_delay_control_delay_a;
197
static int hf_iwf_delay_control_delay_b;
198
199
/**************************************************************************************************/
200
/* Preference to use the eCPRI Specification 2.0 encoding                                         */
201
/**************************************************************************************************/
202
static bool pref_message_type_decoding = true;
203
204
/**************************************************************************************************/
205
/* eCPRI Handle                                                                                   */
206
/**************************************************************************************************/
207
static dissector_handle_t ecpri_handle;
208
209
/**************************************************************************************************/
210
/* Initialize expert info fields                                                                  */
211
/**************************************************************************************************/
212
static expert_field ei_ecpri_frame_length;
213
static expert_field ei_payload_size;
214
static expert_field ei_comp_val;
215
static expert_field ei_time_stamp;
216
static expert_field ei_compensation_value_nonzero;
217
static expert_field ei_data_length;
218
static expert_field ei_c_bit;
219
static expert_field ei_fault_notif;
220
static expert_field ei_number_faults;
221
static expert_field ei_iwf_delay_control_action_type;
222
static expert_field ei_ecpri_not_dis_yet;
223
static expert_field ei_owd_no_response;
224
static expert_field ei_owd_no_request;
225
226
227
/**************************************************************************************************/
228
/* Field Encoding of Message Types                                                                */
229
/**************************************************************************************************/
230
231
0
#define ECPRI_MESSAGE_TYPE_IQ_DATA                      0
232
9
#define ECPRI_MESSAGE_TYPE_BIT_SEQUENCE                 1
233
0
#define ECPRI_MESSAGE_TYPE_REAL_TIME_CONTROL_DATA       2
234
2
#define ECPRI_MESSAGE_TYPE_GENERIC_DATA_TRANSFER        3
235
4
#define ECPRI_MESSAGE_TYPE_REMOTE_MEMORY_ACCESS         4
236
7
#define ECPRI_MESSAGE_TYPE_ONE_WAY_DELAY_MEASUREMENT    5
237
4
#define ECPRI_MESSAGE_TYPE_REMOTE_RESET                 6
238
16
#define ECPRI_MESSAGE_TYPE_EVENT_INDICATION             7
239
2
#define ECPRI_MESSAGE_TYPE_IWF_STARTUP                  8
240
1
#define ECPRI_MESSAGE_TYPE_IWF_OPERATION                9
241
1
#define ECPRI_MESSAGE_TYPE_IWF_MAPPING                  10
242
1
#define ECPRI_MESSAGE_TYPE_IWF_DELAY_CONTROL            11
243
244
static const range_string ecpri_msg_types[] = {
245
    /* Message Types (3.2.4) */
246
    { ECPRI_MESSAGE_TYPE_IQ_DATA,                   ECPRI_MESSAGE_TYPE_IQ_DATA,                   "IQ Data" },
247
    { ECPRI_MESSAGE_TYPE_BIT_SEQUENCE,              ECPRI_MESSAGE_TYPE_BIT_SEQUENCE,              "Bit Sequence" },
248
    { ECPRI_MESSAGE_TYPE_REAL_TIME_CONTROL_DATA,    ECPRI_MESSAGE_TYPE_REAL_TIME_CONTROL_DATA,    "Real-Time Control Data" },
249
    { ECPRI_MESSAGE_TYPE_GENERIC_DATA_TRANSFER,     ECPRI_MESSAGE_TYPE_GENERIC_DATA_TRANSFER,     "Generic Data Transfer" },
250
    { ECPRI_MESSAGE_TYPE_REMOTE_MEMORY_ACCESS,      ECPRI_MESSAGE_TYPE_REMOTE_MEMORY_ACCESS,      "Remote Memory Access" },
251
    { ECPRI_MESSAGE_TYPE_ONE_WAY_DELAY_MEASUREMENT, ECPRI_MESSAGE_TYPE_ONE_WAY_DELAY_MEASUREMENT, "One-Way Delay Measurement" },
252
    { ECPRI_MESSAGE_TYPE_REMOTE_RESET,              ECPRI_MESSAGE_TYPE_REMOTE_RESET,              "Remote Reset" },
253
    { ECPRI_MESSAGE_TYPE_EVENT_INDICATION,          ECPRI_MESSAGE_TYPE_EVENT_INDICATION,          "Event Indication" },
254
    { ECPRI_MESSAGE_TYPE_IWF_STARTUP,               ECPRI_MESSAGE_TYPE_IWF_STARTUP,               "IWF Start-Up" },
255
    { ECPRI_MESSAGE_TYPE_IWF_OPERATION,             ECPRI_MESSAGE_TYPE_IWF_OPERATION,             "IWF Operation" },
256
    { ECPRI_MESSAGE_TYPE_IWF_MAPPING,               ECPRI_MESSAGE_TYPE_IWF_MAPPING,               "IWF Mapping" },
257
    { ECPRI_MESSAGE_TYPE_IWF_DELAY_CONTROL,         ECPRI_MESSAGE_TYPE_IWF_DELAY_CONTROL,         "IWF Delay Control" },
258
    /* Message Types 12 -  63*/
259
    { 12,  63,   "Reserved" },
260
    /* Message Types 64 - 255 */
261
    { 64,  255,  "Vendor Specific" },
262
    { 0,   0,    NULL }
263
};
264
265
/**************************************************************************************************/
266
/* Field Encoding of Message Type 4: Remote Memory Access                                         */
267
/**************************************************************************************************/
268
static const value_string remote_memory_access_read_write_coding[] = {
269
    { 0x0,    "Read"          },
270
    { 0x1,    "Write"         },
271
    { 0x2,    "Write_No_resp" },
272
    { 0x3,    "Reserved"      },
273
    { 0x4,    "Reserved"      },
274
    { 0x5,    "Reserved"      },
275
    { 0x6,    "Reserved"      },
276
    { 0x7,    "Reserved"      },
277
    { 0x8,    "Reserved"      },
278
    { 0x9,    "Reserved"      },
279
    { 0xA,    "Reserved"      },
280
    { 0xB,    "Reserved"      },
281
    { 0xC,    "Reserved"      },
282
    { 0xD,    "Reserved"      },
283
    { 0xE,    "Reserved"      },
284
    { 0xF,    "Reserved"      },
285
    { 0,      NULL            }
286
};
287
288
static const value_string remote_memory_access_request_response_coding[] = {
289
    { 0x0,    "Request"  },
290
    { 0x1,    "Response" },
291
    { 0x2,    "Failure"  },
292
    { 0x3,    "Reserved" },
293
    { 0x4,    "Reserved" },
294
    { 0x5,    "Reserved" },
295
    { 0x6,    "Reserved" },
296
    { 0x7,    "Reserved" },
297
    { 0x8,    "Reserved" },
298
    { 0x9,    "Reserved" },
299
    { 0xA,    "Reserved" },
300
    { 0xB,    "Reserved" },
301
    { 0xC,    "Reserved" },
302
    { 0xD,    "Reserved" },
303
    { 0xE,    "Reserved" },
304
    { 0xF,    "Reserved" },
305
    { 0,      NULL       }
306
};
307
308
/**************************************************************************************************/
309
/* Field Encoding of Message Type 5: One-way Delay Measurement                                    */
310
/**************************************************************************************************/
311
static const range_string one_way_delay_measurement_action_type_coding[] = {
312
    { 0x00,    0x00,    "Request"                       },
313
    { 0x01,    0x01,    "Request with Follow_Up"        },
314
    { 0x02,    0x02,    "Response"                      },
315
    { 0x03,    0x03,    "Remote Request"                },
316
    { 0x04,    0x04,    "Remote request with Follow_Up" },
317
    { 0x05,    0x05,    "Follow_Up"                     },
318
    { 0x06,    0xFF,    "Reserved"                      },
319
    { 0,       0,       NULL                            }
320
};
321
322
/**************************************************************************************************/
323
/* Field Encoding of Message Type 6: Remote Reset                                                 */
324
/**************************************************************************************************/
325
static const range_string remote_reset_reset_coding[] = {
326
    { 0x00,    0x00,    "Reserved"              },
327
    { 0x01,    0x01,    "Remote reset request"  },
328
    { 0x02,    0x02,    "Remote reset response" },
329
    { 0x03,    0xFF,    "Reserved"              },
330
    { 0,       0,       NULL                    }
331
};
332
333
/**************************************************************************************************/
334
/* Field Encoding of Message Type 7: Event Indication                                             */
335
/**************************************************************************************************/
336
static const range_string event_indication_event_type_coding[] = {
337
    { 0x00,    0x00,    "Fault(s) Indication"             },
338
    { 0x01,    0x01,    "Fault(s) Indication Acknowledge" },
339
    { 0x02,    0x02,    "Notification(s) Indication"      },
340
    { 0x03,    0x03,    "Synchronization Request"         },
341
    { 0x04,    0x04,    "Synchronization Acknowledge"     },
342
    { 0x05,    0x05,    "Synchronization End Indication"  },
343
    { 0x06,    0xFF,    "Reserved"                        },
344
    { 0,       0,       NULL                              }
345
};
346
347
static const range_string event_indication_element_id_coding[] = {
348
    { 0x0000,    0xFFFE,    "Vendor specific usage"                          },
349
    { 0xFFFF,    0xFFFF,    "Fault/Notification applicable for all Elements" },
350
    { 0,         0,         NULL                                             }
351
};
352
353
static const value_string event_indication_raise_ceased_coding[] = {
354
    { 0x00,    "Raise a fault" },
355
    { 0x01,    "Cease a fault" },
356
    { 0x02,    "Reserved"     },
357
    { 0x03,    "Reserved"     },
358
    { 0x04,    "Reserved"     },
359
    { 0x05,    "Reserved"     },
360
    { 0x06,    "Reserved"     },
361
    { 0x07,    "Reserved"     },
362
    { 0x08,    "Reserved"     },
363
    { 0x09,    "Reserved"     },
364
    { 0x0A,    "Reserved"     },
365
    { 0x0B,    "Reserved"     },
366
    { 0x0C,    "Reserved"     },
367
    { 0x0D,    "Reserved"     },
368
    { 0x0E,    "Reserved"     },
369
    { 0x0F,    "Reserved"     },
370
    { 0,       NULL           }
371
};
372
373
static const range_string event_indication_fault_notif_coding[] = {
374
    /* eCPRI reserved Faults from 0x000 to 0x3FF */
375
    { 0x000,    0x000,    "General Userplane HW Fault"                    },
376
    { 0x001,    0x001,    "General Userplane SW Fault"                    },
377
    { 0x002,    0x3FF,    "eCPRI reserved Faults"                         },
378
    /* eCPRI reserved Notifications from 0x400 to 0x7FF */
379
    { 0x400,    0x400,    "Unknown message type received"                 },
380
    { 0x401,    0x401,    "Userplane data buffer underflow"               },
381
    { 0x402,    0x402,    "Userplane data buffer overflow"                },
382
    { 0x403,    0x403,    "Userplane data arrived too early"              },
383
    { 0x404,    0x404,    "Userplane data received too late"              },
384
    { 0x405,    0x7FF,    "eCPRI reserved Notifications"                  },
385
    /* Vendor Specific Fault Indication and Notification from 0x800 to 0xFFF */
386
    { 0x800,    0xFFF,    "Vendor Specific Fault Indication/Notification" },
387
    { 0,        0,        NULL                                            }
388
};
389
390
/**************************************************************************************************/
391
/* Field Encoding of Message Type 8: IWF Start-Up                                                 */
392
/**************************************************************************************************/
393
static const range_string iwf_start_up_line_rate_coding[] = {
394
    { 0x00,  0x00,    "Reserved"                     },
395
    { 0x01,  0x01,    "CPRI line bit rate option 1"  },
396
    { 0x02,  0x02,    "CPRI line bit rate option 2"  },
397
    { 0x03,  0x03,    "CPRI line bit rate option 3"  },
398
    { 0x04,  0x04,    "CPRI line bit rate option 4"  },
399
    { 0x05,  0x05,    "CPRI line bit rate option 5"  },
400
    { 0x06,  0x06,    "CPRI line bit rate option 6"  },
401
    { 0x07,  0x07,    "CPRI line bit rate option 7"  },
402
    { 0x08,  0x08,    "CPRI line bit rate option 7A" },
403
    { 0x09,  0x09,    "CPRI line bit rate option 8"  },
404
    { 0x0A,  0x0A,    "CPRI line bit rate option 9"  },
405
    { 0x0B,  0x0B,    "CPRI line bit rate option 10" },
406
    { 0x0C,  0x1F,    "Reserved"                     },
407
    { 0,        0,    NULL                           }
408
};
409
410
/**************************************************************************************************/
411
/* Field Encoding of Message Type 11: IWF Delay Control                                           */
412
/**************************************************************************************************/
413
static const range_string iwf_delay_control_action_type_coding[] = {
414
    { 0x00,  0x00,    "Request get delays"   },
415
    { 0x01,  0x01,    "Response get delays"  },
416
    { 0x02,  0xFF,    "Reserved"             },
417
    { 0,     0,       NULL                   }
418
};
419
420
static const true_false_string tfs_c_bit =
421
{
422
    "Another eCPRI message follows this one with eCPRI PDU",
423
    "This eCPRI message is last one inside eCPRI PDU"
424
};
425
426
427
/**************************************************************************************************/
428
/* Tracking/remembering One-Way Delay measurements                                                */
429
/**************************************************************************************************/
430
431
/* Table maintained on first pass from measurement-id (uint32_t) -> meas_state_t* */
432
/* N.B. maintaining in a single table, assuming that the same ID will not be reused within */
433
/* the same capture. If this is not valid, can move table into conversation object later. */
434
static wmem_tree_t *meas_id_table;
435
436
/* Table consulted on subsequent passes: frame_num -> meas_result_t */
437
static wmem_tree_t *meas_results_table;
438
439
typedef struct {
440
    /* Inputs for delay calculation */
441
    bool         t1_known;
442
    uint64_t     t1;
443
    int64_t      tcv1;
444
    uint32_t     t1_frame_number;
445
    bool         t2_known;
446
    uint64_t     t2;
447
    int64_t      tcv2;
448
    uint32_t     t2_frame_number;
449
} meas_state_t;
450
451
typedef struct {
452
    uint64_t delay_in_ns;
453
    uint32_t request_frame;
454
    uint32_t response_frame;
455
} meas_result_t;
456
457
458
/* Cached for calling ORAN FH CUS dissector for message types that it handles */
459
static dissector_handle_t oran_fh_handle;
460
461
/**************************************************************************************************/
462
/* Implementation of the functions                                                                */
463
/**************************************************************************************************/
464
static int dissect_ecpri(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
465
1.03k
{
466
1.03k
    tvbuff_t *next_tvb;
467
468
    /* Proto Items/Trees for eCPRI */
469
1.03k
    proto_item *ecpri_item;
470
1.03k
    proto_tree *ecpri_tree;
471
472
    /* Proto Items/Trees for eCPRI Common Header */
473
1.03k
    proto_item *header_item;
474
1.03k
    proto_tree *header_tree;
475
1.03k
    proto_item *ti_payload_size;
476
1.03k
    proto_item *ti_c_bit;
477
478
    /* Proto Items/Trees for eCPRI Payload */
479
1.03k
    proto_item *payload_item;
480
1.03k
    proto_tree *payload_tree;
481
    /* Proto Items/Trees for Message Type 4: Remote Memory Access */
482
1.03k
    proto_item *ti_data_length;
483
    /* Proto Items/Trees for Message Type 5: One-way Delay Measurement */
484
1.03k
    proto_item *timestamp_item;
485
1.03k
    proto_tree *timestamp_tree;
486
1.03k
    proto_tree *comp_tree;
487
    /* Proto Items/Trees for Message Type 7: Event Indication */
488
1.03k
    proto_item *element_item;
489
1.03k
    proto_tree *element_tree;
490
1.03k
    proto_item *ti_num_faults;
491
1.03k
    proto_item *ti_fault_notif;
492
493
1.03k
    int offset;
494
1.03k
    uint32_t msg_type;
495
1.03k
    uint32_t event_type;
496
1.03k
    uint32_t concatenation;
497
1.03k
    uint32_t num_faults_notif;
498
1.03k
    uint32_t action_type;
499
1.03k
    uint32_t fault_notif;
500
1.03k
    uint16_t payload_size;           /* size of this ecpri message beyond 4-byte header */
501
502
1.03k
    unsigned int reported_length;    /* total reported length of this overall tvb */
503
1.03k
    unsigned int remaining_length;   /* length remaining in current message */
504
505
1.03k
    uint32_t time_stamp_ns;
506
1.03k
    uint64_t time_stamp_s;
507
1.03k
    int64_t  comp_val;
508
509
1.03k
    reported_length = tvb_reported_length(tvb);
510
511
    /* Check of eCPRI min. length (header-length) */
512
1.03k
    if (reported_length < ECPRI_HEADER_LENGTH)
513
1
        return 0;
514
515
    /* Set column of protocol eCPRI */
516
1.03k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "eCPRI");
517
1.03k
    col_clear(pinfo->cinfo, COL_INFO);
518
519
1.03k
    offset = 0;
520
1.03k
    concatenation = tvb_get_uint8(tvb, offset) & 0x01;
521
1.03k
    if (concatenation != 0x00)
522
928
    {
523
928
        col_append_str(pinfo->cinfo, COL_INFO, "Concatenation");
524
928
    }
525
526
    /* do-while loop for concatenation check */
527
1.03k
    bool concatenation_bit;
528
1.03k
    do
529
1.14k
    {
530
        /* 4-byte boundary check for concatenation */
531
1.14k
        if (offset % 4 != 0)
532
45
        {
533
45
            offset = offset + 4 - (offset % 4);
534
45
        }
535
536
        /* Read ahead to eCPRI Payload Size */
537
1.14k
        payload_size = tvb_get_ntohs(tvb, offset+2);
538
539
        /* eCPRI tree */
540
1.14k
        if ((unsigned int)(offset + ECPRI_HEADER_LENGTH + payload_size) <= reported_length)
541
80
        {
542
80
            ecpri_item = proto_tree_add_item(tree, proto_ecpri, tvb, offset, payload_size + ECPRI_HEADER_LENGTH, ENC_NA);
543
80
        }
544
1.06k
        else
545
1.06k
        {
546
1.06k
            ecpri_item = proto_tree_add_item(tree, proto_ecpri, tvb, offset, -1, ENC_NA);
547
1.06k
            expert_add_info_format(
548
1.06k
                pinfo, ecpri_item, &ei_ecpri_frame_length,
549
1.06k
                "eCPRI frame length %u is too small, Should be min. %d",
550
1.06k
                reported_length-offset, ECPRI_HEADER_LENGTH + payload_size);
551
1.06k
        }
552
1.14k
        ecpri_tree = proto_item_add_subtree(ecpri_item, ett_ecpri);
553
        /* TODO: create a subtvb for just this message (ECPRI_HEADER_LENGTH + payload_size) from offset? */
554
        /* This would simplify some of the confusing range checks below.. */
555
556
        /* eCPRI header subtree */
557
1.14k
        header_item = proto_tree_add_string_format(ecpri_tree, hf_common_header, tvb, offset, ECPRI_HEADER_LENGTH, "", "eCPRI Common Header");
558
1.14k
        header_tree = proto_item_add_subtree(header_item, ett_ecpri_header);
559
560
        /* eCPRI Protocol Revision */
561
1.14k
        proto_tree_add_item(header_tree, hf_common_header_ecpri_protocol_revision, tvb, offset, 1, ENC_NA);
562
        /* Reserved */
563
1.14k
        proto_tree_add_item(header_tree, hf_common_header_reserved, tvb, offset, 1, ENC_NA);
564
        /* Concatenated */
565
1.14k
        ti_c_bit = proto_tree_add_item_ret_boolean(header_tree, hf_common_header_c_bit, tvb, offset, 1, ENC_NA, &concatenation_bit);
566
1.14k
        offset += 1;
567
568
        /* eCPRI Message Type */
569
1.14k
        proto_tree_add_item_ret_uint(header_tree, hf_common_header_ecpri_message_type, tvb, offset, 1, ENC_NA, &msg_type);
570
        /* Append Message Type into info column & header item */
571
1.14k
        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ",", "Message Type: %s", try_rval_to_str(msg_type, ecpri_msg_types));
572
1.14k
        proto_item_append_text(header_item, "   MessageType: %s", try_rval_to_str(msg_type, ecpri_msg_types));
573
1.14k
        offset += 1;
574
575
        /* eCPRI Payload Size */
576
1.14k
        ti_payload_size = proto_tree_add_item(header_tree, hf_common_header_ecpri_payload_size, tvb, offset, 2, ENC_BIG_ENDIAN);
577
1.14k
        offset += 2;
578
579
        /* Note if C is set (i.e. further messages to follow after this one) */
580
1.14k
        if (concatenation_bit) {
581
963
            proto_item_append_text(header_item, "   (further eCPRI message in frame)");
582
963
        }
583
584
        /* eCPRI payload-subtree */
585
        /* Length Check */
586
1.14k
        if (reported_length >= ECPRI_HEADER_LENGTH + payload_size)
587
80
        {
588
            /* OK, add undecoded payload */
589
80
            payload_item = proto_tree_add_item(ecpri_tree, hf_payload, tvb, offset, payload_size, ENC_NA);
590
80
        }
591
1.06k
        else
592
1.06k
        {
593
1.06k
            expert_add_info_format(
594
1.06k
                pinfo, ti_payload_size, &ei_payload_size,
595
1.06k
                "Payload Size %u is too big, maximal %u is possible",
596
1.06k
                payload_size, reported_length - ECPRI_HEADER_LENGTH);
597
1.06k
            payload_item = proto_tree_add_item(ecpri_tree, hf_payload, tvb, offset, -1, ENC_NA);
598
1.06k
        }
599
600
1.14k
        payload_tree = proto_item_add_subtree(payload_item, ett_ecpri_payload);
601
1.14k
        remaining_length = payload_size;
602
603
        /* Call the FH CUS dissector (for all message types) if preference set */
604
1.14k
        if (pref_message_type_decoding)
605
1.09k
        {
606
1.09k
            tvbuff_t *fh_tvb = tvb_new_subset_length(tvb, offset, payload_size);
607
            /***********************************************************************************************/
608
            /* See whether O-RAN fronthaul sub-dissector handles this, otherwise decode as vanilla eCPRI   */
609
            /* N.B. FH CUS dissector only handles:                                                         */
610
            /* - message type 0 (IQ DATA)                                                                  */
611
            /* - message type 2 (RT CTRL DATA)                                                             */
612
            /***********************************************************************************************/
613
1.09k
            if (call_dissector_only(oran_fh_handle, fh_tvb, pinfo, tree, &msg_type))
614
49
            {
615
                /* Assume that it has claimed the entire paylength offered to it */
616
49
                offset += payload_size;
617
49
            }
618
1.04k
            else
619
1.04k
            {
620
                /* ORAN FH-CUS dissector didn't handle it */
621
1.04k
                switch (msg_type)
622
1.04k
                {
623
0
                case ECPRI_MESSAGE_TYPE_IQ_DATA: /* Message Type 0: 3.2.4.1. IQ Data */
624
                    /* N.B. if ORAN dissector is enabled, it will handle this type instead! */
625
0
                    if (payload_size < ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH)
626
0
                    {
627
0
                        expert_add_info_format(
628
0
                            pinfo, ti_payload_size, &ei_payload_size,
629
0
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
630
0
                            payload_size, msg_type, ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH);
631
632
0
                        offset += payload_size;
633
0
                        break;
634
0
                    }
635
636
0
                    if (remaining_length >= ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH)
637
0
                    {
638
0
                        proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
639
0
                        offset += 2;
640
0
                        proto_tree_add_item(ecpri_tree, hf_iq_data_seq_id, tvb, offset, 2, ENC_BIG_ENDIAN);
641
0
                        offset += 2;
642
0
                        remaining_length -= ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH;
643
0
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH)
644
0
                        {
645
0
                            proto_tree_add_item(ecpri_tree, hf_iq_data_iq_samples_of_user_data, tvb, offset, payload_size - ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH, ENC_NA);
646
0
                            offset += payload_size - ECPRI_MSG_TYPE_0_PAYLOAD_MIN_LENGTH;
647
0
                        }
648
0
                    }
649
0
                    break;
650
9
                case ECPRI_MESSAGE_TYPE_BIT_SEQUENCE: /* Message Type 1: 3.2.4.2. Bit Sequence */
651
9
                    if (payload_size < ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH)
652
6
                    {
653
6
                        expert_add_info_format(
654
6
                            pinfo, ti_payload_size, &ei_payload_size,
655
6
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
656
6
                            payload_size, msg_type, ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH);
657
658
6
                        offset += payload_size;
659
6
                        break;
660
6
                    }
661
662
3
                    if (remaining_length >= ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH)
663
3
                    {
664
3
                        proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
665
3
                        offset += 2;
666
3
                        proto_tree_add_item(ecpri_tree, hf_bit_sequence_seq_id, tvb, offset, 2, ENC_BIG_ENDIAN);
667
3
                        offset += 2;
668
3
                        remaining_length -= ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH;
669
3
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH)
670
3
                        {
671
3
                            proto_tree_add_item(ecpri_tree, hf_bit_sequence_bit_sequence_of_user_data, tvb, offset, payload_size - ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH, ENC_NA);
672
3
                            offset += payload_size - ECPRI_MSG_TYPE_1_PAYLOAD_MIN_LENGTH;
673
3
                        }
674
3
                    }
675
3
                    break;
676
677
0
                case ECPRI_MESSAGE_TYPE_REAL_TIME_CONTROL_DATA: /* Message Type 2: 3.2.4.3. Real-Time Control Data */
678
                    /* N.B. if ORAN dissector is enabled, it will handle this type instead! */
679
0
                    if (payload_size < ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH)
680
0
                    {
681
0
                        expert_add_info_format(
682
0
                            pinfo, ti_payload_size, &ei_payload_size,
683
0
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
684
0
                            payload_size, msg_type, ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH);
685
686
0
                        offset += payload_size;
687
0
                        break;
688
0
                    }
689
690
0
                    if (remaining_length >= ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH)
691
0
                    {
692
0
                        proto_tree_add_item(ecpri_tree, hf_real_time_control_data_rtc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
693
0
                        offset += 2;
694
0
                        proto_tree_add_item(ecpri_tree, hf_real_time_control_data_seq_id, tvb, offset, 2, ENC_BIG_ENDIAN);
695
0
                        offset += 2;
696
0
                        remaining_length -= ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH;
697
0
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH)
698
0
                        {
699
0
                            proto_tree_add_item(ecpri_tree, hf_real_time_control_data_rtc_data, tvb, offset, payload_size - ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH, ENC_NA);
700
0
                            offset += payload_size - ECPRI_MSG_TYPE_2_PAYLOAD_MIN_LENGTH;
701
0
                        }
702
0
                    }
703
0
                    break;
704
705
2
                case ECPRI_MESSAGE_TYPE_GENERIC_DATA_TRANSFER: /* Message Type 3: 3.2.4.4. Generic Data Transfer */
706
2
                    if (payload_size < ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH)
707
0
                    {
708
0
                        expert_add_info_format(
709
0
                            pinfo, ti_payload_size, &ei_payload_size,
710
0
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
711
0
                            payload_size, msg_type, ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH);
712
713
0
                        offset += payload_size;
714
0
                        break;
715
0
                    }
716
717
2
                    if (remaining_length >= ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH)
718
2
                    {
719
2
                        proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 4, ENC_BIG_ENDIAN);
720
2
                        offset += 4;
721
2
                        proto_tree_add_item(ecpri_tree, hf_generic_data_transfer_seq_id, tvb, offset, 4, ENC_BIG_ENDIAN);
722
2
                        offset += 4;
723
2
                        remaining_length -= ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH;
724
2
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH)
725
2
                        {
726
2
                            proto_tree_add_item(ecpri_tree, hf_generic_data_transfer_data_transferred, tvb, offset, payload_size - ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH, ENC_NA);
727
2
                            offset += payload_size - ECPRI_MSG_TYPE_3_PAYLOAD_MIN_LENGTH;
728
2
                        }
729
2
                    }
730
2
                    break;
731
732
4
                case ECPRI_MESSAGE_TYPE_REMOTE_MEMORY_ACCESS: /* Message Type 4: 3.2.4.5. Remote Memory Access */
733
4
                    if (payload_size < ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH)
734
2
                    {
735
2
                        expert_add_info_format(
736
2
                            pinfo, ti_payload_size, &ei_payload_size,
737
2
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
738
2
                            payload_size, msg_type, ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH);
739
740
2
                        offset += payload_size;
741
2
                        break;
742
2
                    }
743
744
2
                    if (remaining_length >= ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH)
745
2
                    {
746
2
                        proto_tree_add_item(ecpri_tree, hf_remote_memory_access_id, tvb, offset, 1, ENC_NA);
747
2
                        offset += 1;
748
2
                        proto_tree_add_item(ecpri_tree, hf_remote_memory_access_read_write, tvb, offset, 1, ENC_NA);
749
2
                        proto_tree_add_item(ecpri_tree, hf_remote_memory_access_request_response, tvb, offset, 1, ENC_NA);
750
2
                        offset += 1;
751
2
                        proto_tree_add_item(ecpri_tree, hf_remote_memory_access_element_id, tvb, offset, 2, ENC_BIG_ENDIAN);
752
2
                        offset += 2;
753
2
                        proto_tree_add_item(ecpri_tree, hf_remote_memory_access_address, tvb, offset, 6, ENC_NA);
754
2
                        offset += 6;
755
                        /* Data length */
756
2
                        unsigned int data_length;
757
2
                        ti_data_length = proto_tree_add_item_ret_uint(ecpri_tree, hf_remote_memory_access_data_length, tvb, offset, 2, ENC_BIG_ENDIAN, &data_length);
758
2
                        offset += 2;
759
2
                        remaining_length -= ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH;
760
2
                        if (remaining_length >= (payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH))
761
2
                        {
762
2
                            if (data_length == ((uint32_t)(payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH)))
763
0
                            {
764
0
                                proto_tree_add_item(ecpri_tree, hf_remote_memory_access_data, tvb, offset, payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH, ENC_NA);
765
0
                                offset += payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH;
766
0
                            }
767
2
                            else if (data_length < ((uint32_t)(payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH)))
768
0
                            {
769
0
                                expert_add_info_format(
770
0
                                    pinfo, ti_data_length, &ei_data_length,
771
0
                                    "Data Length %u is too small, should be %u",
772
0
                                    data_length, payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH);
773
0
                            }
774
2
                            else
775
2
                            {
776
2
                                expert_add_info_format(
777
2
                                    pinfo, ti_data_length, &ei_data_length,
778
2
                                    "Data Length %u is too big, should be %u",
779
2
                                    data_length, payload_size - ECPRI_MSG_TYPE_4_PAYLOAD_MIN_LENGTH);
780
2
                            }
781
2
                        }
782
2
                    }
783
2
                    break;
784
785
7
                case ECPRI_MESSAGE_TYPE_ONE_WAY_DELAY_MEASUREMENT: /* Message Type 5: 3.2.4.6. One-way Delay Measurement */
786
7
                    if (payload_size < ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH)
787
0
                    {
788
0
                        expert_add_info_format(
789
0
                            pinfo, ti_payload_size, &ei_payload_size,
790
0
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
791
0
                            payload_size, msg_type, ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH);
792
793
0
                        offset += payload_size;
794
0
                        break;
795
0
                    }
796
797
7
                    if (remaining_length >= ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH)
798
7
                    {
799
                        /* Measurement ID (1 byte) */
800
7
                        unsigned int meas_id;
801
7
                        proto_tree_add_item_ret_uint(ecpri_tree, hf_one_way_delay_measurement_id, tvb, offset, 1, ENC_NA, &meas_id);
802
7
                        offset += 1;
803
                        /* Action Type (1 byte) */
804
7
                        proto_tree_add_item_ret_uint(ecpri_tree, hf_one_way_delay_measurement_action_type, tvb, offset, 1, ENC_NA, &action_type);
805
7
                        offset += 1;
806
807
7
                        col_append_fstr(pinfo->cinfo, COL_INFO, "   (MeasId=%u, ActionType=%s)",
808
7
                                        meas_id,
809
7
                                        rval_to_str_const(action_type, one_way_delay_measurement_action_type_coding, "Unknown"));
810
811
                        /* Time Stamp for seconds and nano-seconds (6 bytes seconds, 4 bytes nanoseconds) */
812
7
                        timestamp_item = proto_tree_add_item(ecpri_tree, hf_one_way_delay_measurement_timestamp, tvb, offset, 10, ENC_NA);
813
7
                        timestamp_tree = proto_item_add_subtree(timestamp_item, ett_ecpri_timestamp);
814
7
                        proto_tree_add_item_ret_uint64(timestamp_tree, hf_one_way_delay_measurement_timestamp_seconds, tvb, offset, 6, ENC_BIG_ENDIAN, &time_stamp_s);
815
7
                        offset += 6;
816
7
                        proto_tree_add_item_ret_uint(timestamp_tree, hf_one_way_delay_measurement_timestamp_nanoseconds, tvb, offset, 4, ENC_BIG_ENDIAN, &time_stamp_ns);
817
7
                        offset += 4;
818
                        /* Isn't set for all action types */
819
7
                        if (action_type != ECPRI_MSG_TYPE_5_REQ &&
820
7
                            action_type != ECPRI_MSG_TYPE_5_RESPONSE &&
821
7
                            action_type != ECPRI_MSG_TYPE_5_FOLLOWUP &&
822
7
                            time_stamp_s != 0 && time_stamp_ns != 0)
823
4
                        {
824
4
                            expert_add_info_format(
825
4
                                pinfo, timestamp_item, &ei_time_stamp,
826
4
                                "Time stamp is not defined for Action Type %u (%s), should be 0",
827
4
                                action_type, rval_to_str_const(action_type, one_way_delay_measurement_action_type_coding, "Unknown"));
828
4
                        }
829
3
                        else {
830
                            /* Show value in ts root */
831
3
                            proto_item_append_text(timestamp_item, " (%" PRId64 ".%09u seconds)", time_stamp_s, time_stamp_ns);
832
3
                        }
833
834
                        /* Compensation value (8 bytes). Same format as PTP's correctionField */
835
7
                        dissect_ptp_v2_timeInterval(tvb, &offset, ecpri_tree, "Compensation value",
836
7
                                                    hf_one_way_delay_measurement_compensation_value,
837
7
                                                    hf_one_way_delay_measurement_compensation_value_subns,
838
7
                                                    &comp_tree,
839
7
                                                    &comp_val);
840
                        /* Isn't valid for all Action Types */
841
7
                        if (action_type != ECPRI_MSG_TYPE_5_REQ &&
842
7
                            action_type != ECPRI_MSG_TYPE_5_RESPONSE &&
843
7
                            action_type != ECPRI_MSG_TYPE_5_FOLLOWUP &&
844
7
                            comp_val != 0)
845
4
                        {
846
4
                            expert_add_info_format(
847
4
                                pinfo, comp_tree, &ei_compensation_value_nonzero,
848
4
                                "Compensation Value is not defined for Action Type %u (%s), should be 0",
849
4
                                action_type, rval_to_str_const(action_type, one_way_delay_measurement_action_type_coding, "Unknown"));
850
4
                        }
851
852
                        /* Any remaining bytes are dummy */
853
7
                        remaining_length -= ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH;
854
7
                        if (remaining_length > 0)
855
7
                        {
856
7
                            proto_item *dummy_ti = proto_tree_add_item(ecpri_tree, hf_one_way_delay_measurement_dummy_bytes, tvb, offset,
857
7
                                                                       payload_size - ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH, ENC_NA);
858
7
                            offset += (payload_size - ECPRI_MSG_TYPE_5_PAYLOAD_MIN_LENGTH);
859
                            /* Only useful to send dummy bytes for requests */
860
7
                            if ((action_type != ECPRI_MSG_TYPE_5_REQ) &&
861
7
                                (action_type != ECPRI_MSG_TYPE_5_REQ_FOLLOWUP)) {
862
0
                                proto_item_append_text(dummy_ti, " (dummy bytes are only needed for action types 0-1");
863
0
                            }
864
7
                        }
865
866
                        /* For involved message types, try to work out and show the delay */
867
7
                        if ((action_type == ECPRI_MSG_TYPE_5_REQ) ||
868
7
                            (action_type == ECPRI_MSG_TYPE_5_FOLLOWUP) ||
869
7
                            (action_type == ECPRI_MSG_TYPE_5_RESPONSE)) {
870
871
0
                            meas_state_t* meas = (meas_state_t*)wmem_tree_lookup32(meas_id_table, meas_id);
872
0
                            if (!PINFO_FD_VISITED(pinfo)) {
873
                                /* First pass, fill in details for this measurement ID */
874
0
                                if (meas == NULL) {
875
                                    /* Allocate new state, and add to table */
876
0
                                    meas = wmem_new0(wmem_file_scope(), meas_state_t);
877
0
                                    wmem_tree_insert32(meas_id_table, meas_id, meas);
878
0
                                }
879
880
                                /* Request - fill in t1 and tcv1 */
881
0
                                if ((action_type == ECPRI_MSG_TYPE_5_REQ) ||
882
0
                                    (action_type == ECPRI_MSG_TYPE_5_FOLLOWUP)) {
883
0
                                    meas->t1_known = true;
884
0
                                    meas->t1 = time_stamp_s*1000000000 + time_stamp_ns;
885
0
                                    meas->tcv1 = comp_val;
886
0
                                    meas->t1_frame_number = pinfo->num;
887
0
                                }
888
                                /* Response - fill in t2 and tcv2 */
889
0
                                else {
890
0
                                    meas->t2_known = true;
891
0
                                    meas->t2 = time_stamp_s*1000000000 + time_stamp_ns;
892
0
                                    meas->tcv2 = comp_val;
893
0
                                    meas->t2_frame_number = pinfo->num;
894
0
                                }
895
896
                                /* Do calculation if possible */
897
0
                                if (meas->t1_known && meas->t2_known) {
898
0
                                    meas_result_t *result = wmem_new0(wmem_file_scope(), meas_result_t);
899
0
                                    result->delay_in_ns = (meas->t2 - meas->tcv2) - (meas->t1 - meas->tcv1);
900
0
                                    result->request_frame = meas->t1_frame_number;
901
0
                                    result->response_frame = meas->t2_frame_number;
902
                                    /* Insert result for this frame and the requesting frame.. */
903
0
                                    wmem_tree_insert32(meas_results_table, meas->t2_frame_number, result);
904
0
                                    wmem_tree_insert32(meas_results_table, meas->t1_frame_number, result);
905
0
                                }
906
0
                            }
907
0
                            else {
908
                                /* Subsequent passes, show any calculated delays */
909
0
                                meas_result_t *result = wmem_tree_lookup32(meas_results_table, pinfo->num);
910
0
                                if (result) {
911
0
                                    proto_item *delay_ti = proto_tree_add_uint64(ecpri_tree, hf_one_way_delay_measurement_calculated_delay,
912
0
                                                                                 tvb, 0, 0, result->delay_in_ns);
913
0
                                    PROTO_ITEM_SET_GENERATED(delay_ti);
914
915
                                    /* Link to other frame involved in the calculation */
916
0
                                    proto_item *frame_ti;
917
0
                                    if (action_type == ECPRI_MSG_TYPE_5_RESPONSE) {
918
0
                                        frame_ti = proto_tree_add_uint(ecpri_tree, hf_one_way_delay_measurement_calculated_delay_request_frame,
919
0
                                                                       tvb, 0, 0, result->request_frame);
920
0
                                        col_append_fstr(pinfo->cinfo, COL_INFO, "   [Delay=%" PRIu64 "uns]", result->delay_in_ns);
921
0
                                    }
922
0
                                    else {
923
0
                                        frame_ti = proto_tree_add_uint(ecpri_tree, hf_one_way_delay_measurement_calculated_delay_response_frame,
924
0
                                                                       tvb, 0, 0, result->response_frame);
925
0
                                    }
926
0
                                    PROTO_ITEM_SET_GENERATED(frame_ti);
927
0
                                }
928
0
                                else {
929
                                    /* The other part of the exchange must be missing, so report */
930
0
                                    if ((action_type == ECPRI_MSG_TYPE_5_REQ) ||
931
0
                                        (action_type == ECPRI_MSG_TYPE_5_FOLLOWUP)) {
932
                                        /* Missing response */
933
0
                                        expert_add_info(pinfo, ecpri_tree, &ei_owd_no_response);
934
0
                                    }
935
0
                                    else {
936
                                        /* Request not found */
937
0
                                        expert_add_info(pinfo, ecpri_tree, &ei_owd_no_request);
938
0
                                    }
939
940
0
                                }
941
0
                            }
942
0
                        }
943
7
                    }
944
7
                    break;
945
946
4
                case ECPRI_MESSAGE_TYPE_REMOTE_RESET: /* Message Type 6: 3.2.4.7. Remote Reset */
947
4
                    if (payload_size < ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH)
948
1
                    {
949
1
                        expert_add_info_format(
950
1
                            pinfo, ti_payload_size, &ei_payload_size,
951
1
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
952
1
                            payload_size, msg_type, ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH);
953
954
1
                        offset += payload_size;
955
1
                        break;
956
1
                    }
957
958
3
                    if (remaining_length >= ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH)
959
3
                    {
960
3
                        proto_tree_add_item(ecpri_tree, hf_remote_reset_reset_id, tvb, offset, 2, ENC_BIG_ENDIAN);
961
3
                        offset += 2;
962
3
                        proto_tree_add_item(ecpri_tree, hf_remote_reset_reset_code, tvb, offset, 1, ENC_NA);
963
3
                        offset += 1;
964
3
                        remaining_length -= ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH;
965
3
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH)
966
3
                        {
967
3
                            proto_tree_add_item(ecpri_tree, hf_remote_reset_vendor_specific_payload, tvb, offset, payload_size - ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH, ENC_NA);
968
3
                            offset += payload_size - ECPRI_MSG_TYPE_6_PAYLOAD_MIN_LENGTH;
969
3
                        }
970
3
                    }
971
3
                    break;
972
973
16
                case ECPRI_MESSAGE_TYPE_EVENT_INDICATION: /* Message Type 7: 3.2.4.8. Event Indication */
974
16
                    if (payload_size < ECPRI_MSG_TYPE_7_PAYLOAD_MIN_LENGTH)
975
0
                    {
976
0
                        expert_add_info_format(
977
0
                            pinfo, ti_payload_size, &ei_payload_size,
978
0
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
979
0
                            payload_size, msg_type, ECPRI_MSG_TYPE_7_PAYLOAD_MIN_LENGTH);
980
981
0
                        offset += payload_size;
982
0
                        break;
983
0
                    }
984
985
16
                    if (remaining_length >= ECPRI_MSG_TYPE_7_PAYLOAD_MIN_LENGTH)
986
16
                    {
987
16
                        proto_tree_add_item(ecpri_tree, hf_event_indication_event_id, tvb, offset, 1, ENC_NA);
988
16
                        offset += 1;
989
16
                        proto_tree_add_item_ret_uint(ecpri_tree, hf_event_indication_event_type, tvb, offset, 1, ENC_NA, &event_type);
990
16
                        offset += 1;
991
16
                        proto_tree_add_item(ecpri_tree, hf_event_indication_sequence_number, tvb, offset, 1, ENC_NA);
992
16
                        offset += 1;
993
16
                        ti_num_faults = proto_tree_add_item_ret_uint(ecpri_tree, hf_event_indication_number_of_faults_notifications, tvb, offset, 1, ENC_NA, &num_faults_notif);
994
16
                        offset += 1;
995
                        /* Only for Event Type Fault Indication (0x00) and Notification Indication (0x02) */
996
16
                        if (event_type == ECPRI_MSG_TYPE_7_FAULT_INDICATION || event_type == ECPRI_MSG_TYPE_7_NOTIF_INDICATION)
997
2
                        {
998
                            /* These two Event Types should have notifications or faults */
999
2
                            if (num_faults_notif == 0)
1000
1
                            {
1001
1
                                expert_add_info_format(
1002
1
                                    pinfo, ti_num_faults, &ei_number_faults,
1003
1
                                    "Number of Faults/Notif %u should be > 0",
1004
1
                                    num_faults_notif);
1005
1
                                break;
1006
1
                            }
1007
1008
                            /* Check Size of Elements */
1009
1
                            const uint16_t expected_payload_size = ECPRI_MSG_TYPE_7_PAYLOAD_MIN_LENGTH + num_faults_notif * ECPRI_MSG_TYPE_7_ELEMENT_SIZE;
1010
1
                            if (payload_size == expected_payload_size)
1011
0
                            {
1012
                                /* Dissect elements in loop */
1013
0
                                for (uint32_t i = 0; i < num_faults_notif; i++)
1014
0
                                {
1015
0
                                    element_item = proto_tree_add_item(ecpri_tree, hf_event_indication_element, tvb, offset, ECPRI_MSG_TYPE_7_ELEMENT_SIZE, ENC_NA);
1016
0
                                    proto_item_prepend_text(element_item, "#%u: ", i + 1);
1017
0
                                    element_tree = proto_item_add_subtree(element_item, ett_ecpri_element);
1018
1019
0
                                    proto_tree_add_item(element_tree, hf_event_indication_element_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1020
0
                                    offset += 2;
1021
0
                                    proto_tree_add_item(element_tree, hf_event_indication_raise_cease, tvb, offset, 1, ENC_NA);
1022
0
                                    ti_fault_notif = proto_tree_add_item_ret_uint(element_tree, hf_event_indication_fault_notification, tvb, offset, 2, ENC_BIG_ENDIAN, &fault_notif);
1023
1024
                                    /* Faults and Notifications cannot be mixed */
1025
0
                                    const bool is_fault_event = event_type == ECPRI_MSG_TYPE_7_FAULT_INDICATION;
1026
0
                                    const bool is_notif_event = event_type == ECPRI_MSG_TYPE_7_NOTIF_INDICATION;
1027
1028
0
                                    const bool is_fault_notif_in_fault_range = fault_notif <= ECPRI_MSG_TYPE_7_FAULTS_MAX;
1029
1030
0
                                    const bool is_fault_notif_in_notif_range =
1031
0
                                        fault_notif >= ECPRI_MSG_TYPE_7_NOTIF_MIN &&
1032
0
                                        fault_notif <= ECPRI_MSG_TYPE_7_NOTIF_MAX;
1033
1034
0
                                    const bool is_fault_notif_in_vendor_range =
1035
0
                                        fault_notif >= ECPRI_MSG_TYPE_7_VENDOR_MIN &&
1036
0
                                        fault_notif <= ECPRI_MSG_TYPE_7_VENDOR_MAX;
1037
1038
0
                                    if (is_fault_event && !(is_fault_notif_in_fault_range || is_fault_notif_in_vendor_range))
1039
0
                                    {
1040
0
                                        expert_add_info_format(
1041
0
                                            pinfo, ti_fault_notif, &ei_fault_notif,
1042
0
                                            "Only Faults are permitted with Event Type Faults Indication (0x%.2X)",
1043
0
                                            event_type);
1044
0
                                    }
1045
0
                                    else if (is_notif_event && !(is_fault_notif_in_notif_range || is_fault_notif_in_vendor_range))
1046
0
                                    {
1047
0
                                        expert_add_info_format(
1048
0
                                            pinfo, ti_fault_notif, &ei_fault_notif,
1049
0
                                            "Only Notifications are permitted with Event Type Notifications Indication (0x%.2X)",
1050
0
                                            event_type);
1051
0
                                    }
1052
0
                                    offset += 2;
1053
0
                                    proto_tree_add_item(element_tree, hf_event_indication_additional_information, tvb, offset, 4, ENC_BIG_ENDIAN);
1054
0
                                    offset += 4;
1055
0
                                }
1056
0
                            }
1057
1
                            else if (payload_size < expected_payload_size)
1058
0
                            {
1059
0
                                expert_add_info_format(
1060
0
                                    pinfo, ti_num_faults, &ei_number_faults,
1061
0
                                    "Number of Faults/Notif %u is maybe too big",
1062
0
                                    num_faults_notif);
1063
1064
0
                                expert_add_info_format(
1065
0
                                    pinfo, ti_payload_size, &ei_payload_size,
1066
0
                                    "Payload Size is maybe too small: %u",
1067
0
                                    payload_size);
1068
0
                            }
1069
1
                            else
1070
1
                            {
1071
1
                                expert_add_info_format(
1072
1
                                    pinfo, ti_num_faults, &ei_number_faults,
1073
1
                                    "Number of Faults/Notif %u is maybe too small",
1074
1
                                    num_faults_notif);
1075
1076
1
                                expert_add_info_format(
1077
1
                                    pinfo, ti_payload_size, &ei_payload_size,
1078
1
                                    "Payload Size is maybe too big: %u",
1079
1
                                    payload_size);
1080
1
                            }
1081
1082
1
                        }
1083
14
                        else if (
1084
14
                            event_type == ECPRI_MSG_TYPE_7_FAULT_INDICATION_ACK ||
1085
14
                            event_type == ECPRI_MSG_TYPE_7_SYNC_REQUEST ||
1086
14
                            event_type == ECPRI_MSG_TYPE_7_SYNC_ACK ||
1087
14
                            event_type == ECPRI_MSG_TYPE_7_SYNC_END_INDICATION)
1088
1
                        {
1089
                            /* Number of Faults/Notifs should be 0, only 4 Byte possible*/
1090
1
                            if (payload_size > 4)
1091
1
                            {
1092
1
                                expert_add_info_format(
1093
1
                                    pinfo, ti_payload_size, &ei_payload_size,
1094
1
                                    "Payload Size %u should be 4",
1095
1
                                    payload_size);
1096
1
                            }
1097
                            /* These Event Types shouldn't have faults or notifications */
1098
1
                            if (num_faults_notif != 0)
1099
0
                            {
1100
0
                                expert_add_info_format(
1101
0
                                    pinfo, ti_num_faults, &ei_number_faults,
1102
0
                                    "Number of Faults/Notif %u should be 0",
1103
0
                                    num_faults_notif);
1104
0
                            }
1105
1
                        }
1106
13
                        else
1107
13
                        {
1108
                            /* These Event Types are reserved, don't know how to decode */
1109
13
                            if (num_faults_notif != 0)
1110
13
                            {
1111
13
                                expert_add_info_format(
1112
13
                                    pinfo, ti_num_faults, &ei_number_faults,
1113
13
                                    "Number of Faults/Notif %u, but no knowledge about encoding, because Event Type is reserved.",
1114
13
                                    num_faults_notif);
1115
13
                            }
1116
13
                        }
1117
16
                    }
1118
15
                    break;
1119
1120
15
                case ECPRI_MESSAGE_TYPE_IWF_STARTUP: /* Message Type 8: 3.2.4.9. IWF Start-Up */
1121
2
                    if (payload_size < ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH)
1122
1
                    {
1123
1
                        expert_add_info_format(
1124
1
                            pinfo, ti_payload_size, &ei_payload_size,
1125
1
                            "Payload Size %u is too small for encoding Message Type %u. Should be min. %d",
1126
1
                            payload_size, msg_type, ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH);
1127
1128
1
                        offset += payload_size;
1129
1
                        break;
1130
1
                    }
1131
1132
1
                    if (remaining_length >= ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH)
1133
1
                    {
1134
1
                        proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1135
1
                        offset += 2;
1136
1137
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_hyperframe_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1138
1
                        offset += 1;
1139
1140
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_subframe_number, tvb, offset, 1, ENC_BIG_ENDIAN);
1141
1
                        offset += 1;
1142
1143
                        /* Time Stamp as nanoseconds */
1144
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_timestamp, tvb, offset, 4, ENC_BIG_ENDIAN);
1145
1
                        offset += 4;
1146
1147
                        /* F, S, r (skipped), Line Rate */
1148
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_fec_bit_indicator, tvb, offset, 1, ENC_BIG_ENDIAN);
1149
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_scrambling_bit_indicator, tvb, offset, 1, ENC_BIG_ENDIAN);
1150
1
                        proto_tree_add_item(ecpri_tree, hf_iwf_start_up_line_rate, tvb, offset, 1, ENC_BIG_ENDIAN);
1151
1
                        offset += 1;
1152
1153
1
                        remaining_length -= ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH;
1154
1
                        if (remaining_length >= payload_size - ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH)
1155
1
                        {
1156
1
                            proto_tree_add_item(ecpri_tree, hf_iwf_start_up_data_transferred, tvb, offset, payload_size - ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH, ENC_NA);
1157
1
                            offset += payload_size - ECPRI_MSG_TYPE_8_PAYLOAD_MIN_LENGTH;
1158
1
                        }
1159
1
                    }
1160
1
                    break;
1161
1
                case ECPRI_MESSAGE_TYPE_IWF_OPERATION: /* Message Type 9: 3.2.4.10. IWF Operation */
1162
                    //proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1163
                    //offset += 2;
1164
                    /* TODO: */
1165
1
                    proto_tree_add_expert(payload_tree, pinfo, &ei_ecpri_not_dis_yet, tvb, offset, payload_size);
1166
1
                    break;
1167
1
                case ECPRI_MESSAGE_TYPE_IWF_MAPPING: /* Message Type 10: 3.2.4.11. IWF Mapping */
1168
                    //proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1169
                    //offset += 2;
1170
                    /* TODO: */
1171
1
                    proto_tree_add_expert(payload_tree, pinfo, &ei_ecpri_not_dis_yet, tvb, offset, payload_size);
1172
1
                    break;
1173
1
                case ECPRI_MESSAGE_TYPE_IWF_DELAY_CONTROL: /* Message Type 11: 3.2.4.12. IWF Delay Control */
1174
1
                    if (payload_size != ECPRI_MSG_TYPE_11_PAYLOAD_LENGTH)
1175
1
                    {
1176
1
                        expert_add_info_format(
1177
1
                            pinfo, ti_payload_size, &ei_payload_size,
1178
1
                            "Payload Size %u is too small or too big for encoding Message Type %u. Should be exactly %d",
1179
1
                            payload_size, msg_type, ECPRI_MSG_TYPE_11_PAYLOAD_LENGTH);
1180
1181
1
                        offset += payload_size;
1182
1
                        break;
1183
1
                    }
1184
1185
0
                    if (remaining_length >= ECPRI_MSG_TYPE_11_PAYLOAD_LENGTH)
1186
0
                    {
1187
0
                        proto_tree_add_item(ecpri_tree, hf_pc_id, tvb, offset, 2, ENC_BIG_ENDIAN);
1188
0
                        offset += 2;
1189
1190
0
                        proto_tree_add_item(ecpri_tree, hf_iwf_delay_control_delay_control_id, tvb, offset, 1, ENC_BIG_ENDIAN);
1191
0
                        offset += 1;
1192
1193
0
                        proto_item *ti_iwf_delay_control_action_type;
1194
0
                        uint32_t iwf_delay_control_action_type;
1195
0
                        ti_iwf_delay_control_action_type = proto_tree_add_item_ret_uint(
1196
0
                            ecpri_tree, hf_iwf_delay_control_action_type, tvb, offset, 1, ENC_NA, &iwf_delay_control_action_type);
1197
0
                        offset += 1;
1198
1199
0
                        proto_item *ti_iwf_delay_control_delay_a;
1200
0
                        uint32_t iwf_delay_control_delay_a;
1201
0
                        ti_iwf_delay_control_delay_a = proto_tree_add_item_ret_uint(
1202
0
                            ecpri_tree, hf_iwf_delay_control_delay_a, tvb, offset, 4, ENC_BIG_ENDIAN, &iwf_delay_control_delay_a);
1203
0
                        proto_item_append_text(ti_iwf_delay_control_delay_a, " = %fns", iwf_delay_control_delay_a / 16.0);
1204
0
                        offset += 4;
1205
1206
0
                        proto_item *ti_iwf_delay_control_delay_b;
1207
0
                        uint32_t iwf_delay_control_delay_b;
1208
0
                        ti_iwf_delay_control_delay_b = proto_tree_add_item_ret_uint(
1209
0
                            ecpri_tree, hf_iwf_delay_control_delay_b, tvb, offset, 4, ENC_BIG_ENDIAN, &iwf_delay_control_delay_b);
1210
0
                        proto_item_append_text(ti_iwf_delay_control_delay_b, " = %fns", iwf_delay_control_delay_b / 16.0);
1211
0
                        offset += 4;
1212
1213
0
                        const bool is_action_type_req = iwf_delay_control_action_type == ECPRI_MSG_TYPE_11_REQUEST_GET_DELAYS;
1214
0
                        const bool are_delays_zero = iwf_delay_control_delay_a == 0 && iwf_delay_control_delay_b == 0;
1215
0
                        if (is_action_type_req && !are_delays_zero)
1216
0
                        {
1217
0
                            expert_add_info_format(
1218
0
                                pinfo, ti_iwf_delay_control_action_type, &ei_iwf_delay_control_action_type,
1219
0
                                "Action Type %u is Request Get Delays, but Delays are not 0",
1220
0
                                iwf_delay_control_action_type);
1221
0
                        }
1222
0
                        else if (!is_action_type_req && are_delays_zero)
1223
0
                        {
1224
0
                            expert_add_info_format(
1225
0
                                pinfo, ti_iwf_delay_control_action_type, &ei_iwf_delay_control_action_type,
1226
0
                                "Action Type %u is not Request Get Delays, but Delays are 0",
1227
0
                                iwf_delay_control_action_type);
1228
0
                        }
1229
0
                    }
1230
0
                    break;
1231
43
                default:
1232
                    /* Reserved or Vendor Specific */
1233
43
                    offset += payload_size;
1234
43
                    break;
1235
1.04k
                }
1236
1.04k
            }
1237
1.09k
        }
1238
        /* If Preference not chosen,  Payload will be not decoded */
1239
52
        else
1240
52
        {
1241
52
            if ((unsigned int)(offset + payload_size) <= reported_length)
1242
0
            {
1243
0
                offset += payload_size;
1244
0
            }
1245
52
        }
1246
1.14k
    } while (concatenation_bit != 0 && ((reported_length - offset) >= ECPRI_HEADER_LENGTH));
1247
1248
    /* Expecting last concatenation bit to be false */
1249
68
    if (concatenation_bit != false)
1250
1
    {
1251
1
        expert_add_info_format(pinfo, ti_c_bit, &ei_c_bit, "Last concatenation Bit is 1, should be 0");
1252
1
    }
1253
1254
    /* Not dissected buffer - any remainder passed to data dissector */
1255
68
    if (offset != 0)
1256
16
    {
1257
16
        next_tvb = tvb_new_subset_remaining(tvb, offset);
1258
16
        call_data_dissector(next_tvb, pinfo, tree);
1259
16
    }
1260
1261
    /* Claiming entire frame */
1262
68
    return reported_length;
1263
1.03k
}
1264
1265
void proto_register_ecpri(void)
1266
14
{
1267
14
    static hf_register_info hf[] = {
1268
    /* eCPRI Common Header */
1269
14
        { &hf_common_header, { "eCPRI Common Header", "ecpri.header", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
1270
14
        { &hf_common_header_ecpri_protocol_revision, { "Protocol Revision", "ecpri.revision", FT_UINT8, BASE_DEC, NULL, 0xF0, NULL, HFILL } },
1271
14
        { &hf_common_header_reserved, { "Reserved", "ecpri.reserved", FT_UINT8, BASE_DEC, NULL, 0x0E, NULL, HFILL } },
1272
14
        { &hf_common_header_c_bit, { "C-Bit", "ecpri.cbit", FT_BOOLEAN, 8, TFS(&tfs_c_bit), 0x01, "Concatenation indicator", HFILL } },
1273
14
        { &hf_common_header_ecpri_message_type, { "Message Type", "ecpri.type", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(ecpri_msg_types), 0x0, NULL, HFILL } },
1274
14
        { &hf_common_header_ecpri_payload_size, { "Payload Size", "ecpri.size", FT_UINT16, BASE_DEC, NULL, 0x0, "Size of eCPRI message payload in bytes", HFILL } },
1275
    /* eCPRI Payload */
1276
14
        { &hf_payload,   { "eCPRI Payload", "ecpri.payload", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1277
    /* Common to several message types */
1278
14
        { &hf_pc_id, { "PC_ID", "ecpri.pcid", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1279
    /* Message Type 0: IQ Data */
1280
14
        { &hf_iq_data_seq_id, { "SEQ_ID", "ecpri.iqd.seqid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1281
14
        { &hf_iq_data_iq_samples_of_user_data, { "IQ Samples of User Data", "ecpri.iqd.iqdata", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1282
    /* Message Type 1: Bit Sequence */
1283
14
        { &hf_bit_sequence_seq_id, { "SEQ_ID", "ecpri.bs.seqid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1284
14
        { &hf_bit_sequence_bit_sequence_of_user_data, { "Bit Sequence", "ecpri.bs.bitseq", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1285
    /* Message Type 2: Real-Time Control Data */
1286
14
        { &hf_real_time_control_data_rtc_id, { "RTC_ID", "ecpri.rtcd.rtcid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1287
14
        { &hf_real_time_control_data_seq_id, { "SEQ_ID", "ecpri.rtcd.seqid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1288
14
        { &hf_real_time_control_data_rtc_data, { "Real-Time Control Data", "ecpri.rtcd.rtcdata", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1289
    /* Message Type 3: Generic Data Transfer */
1290
14
        { &hf_generic_data_transfer_seq_id, { "SEQ_ID", "ecpri.gdt.seqid", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1291
14
        { &hf_generic_data_transfer_data_transferred, { "Data transferred", "ecpri.gdt.gendata", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1292
    /* Message Type 4: Remote Memory Access */
1293
14
        { &hf_remote_memory_access_id, { "Remote Memory Access ID", "ecpri.rma.rmaid", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1294
14
        { &hf_remote_memory_access_read_write, { "Read/Write", "ecpri.rma.rw", FT_UINT8, BASE_HEX, VALS(remote_memory_access_read_write_coding), 0xF0, NULL, HFILL } },
1295
14
        { &hf_remote_memory_access_request_response, { "Request/Response", "ecpri.rma.reqresp", FT_UINT8, BASE_HEX, VALS(remote_memory_access_request_response_coding), 0x0F, NULL, HFILL } },
1296
14
        { &hf_remote_memory_access_element_id, { "Element ID", "ecpri.rma.elementid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1297
14
        { &hf_remote_memory_access_address, { "Address", "ecpri.rma.address", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1298
14
        { &hf_remote_memory_access_data_length, { "Data Length", "ecpri.rma.datalength", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1299
14
        { &hf_remote_memory_access_data, { "Data", "ecpri.rma.rmadata", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1300
    /* Message Type 5: One-Way Delay Measurement */
1301
14
        { &hf_one_way_delay_measurement_id, { "Measurement ID", "ecpri.owdm.measurementid", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1302
14
        { &hf_one_way_delay_measurement_action_type, { "Action Type", "ecpri.owdm.actiontype", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(one_way_delay_measurement_action_type_coding), 0x0, NULL, HFILL } },
1303
14
        { &hf_one_way_delay_measurement_timestamp, { "Timestamp", "ecpri.owdm.timestamp", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1304
14
        { &hf_one_way_delay_measurement_timestamp_seconds, { "Seconds", "ecpri.owdm.sec", FT_UINT48, BASE_DEC|BASE_UNIT_STRING, UNS(&units_seconds), 0x0, NULL, HFILL } },
1305
14
        { &hf_one_way_delay_measurement_timestamp_nanoseconds, { "Nanoseconds", "ecpri.owdm.nanosec", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanoseconds), 0x0, NULL, HFILL } },
1306
14
        { &hf_one_way_delay_measurement_compensation_value, { "Compensation", "ecpri.owdm.compval", FT_INT64, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanosecond_nanoseconds), 0x0, NULL, HFILL } },
1307
14
        { &hf_one_way_delay_measurement_compensation_value_subns, { "Compensation (subns)", "ecpri.owdm.compval-subns", FT_DOUBLE, BASE_NONE|BASE_UNIT_STRING, UNS(&units_nanosecond_nanoseconds), 0x0, NULL, HFILL } },
1308
14
        { &hf_one_way_delay_measurement_dummy_bytes, { "Dummy bytes", "ecpri.owdm.owdmdata", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1309
14
        { &hf_one_way_delay_measurement_calculated_delay, { "Calculated Delay", "ecpri.owdm.calculated-delay", FT_UINT64, BASE_DEC, NULL, 0x0, "Calculated delay in ns", HFILL } },
1310
14
        { &hf_one_way_delay_measurement_calculated_delay_request_frame, { "Request Frame", "ecpri.owdm.request-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "Request frame used in calculation", HFILL } },
1311
14
        { &hf_one_way_delay_measurement_calculated_delay_response_frame, { "Response Frame", "ecpri.owdm.response-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, "Response frame used to answer this request", HFILL } },
1312
    /* Message Type 6: Remote Reset */
1313
14
        { &hf_remote_reset_reset_id, { "Reset ID", "ecpri.rr.resetid", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1314
14
        { &hf_remote_reset_reset_code, { "Reset Code Op", "ecpri.rr.resetcode", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(remote_reset_reset_coding), 0x0, NULL, HFILL } },
1315
14
        { &hf_remote_reset_vendor_specific_payload, { "Vendor Specific Payload", "ecpri.rr.vendorpayload", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1316
    /* Message Type 7: Event Indication */
1317
14
        { &hf_event_indication_event_id, { "Event ID", "ecpri.ei.eventid", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1318
14
        { &hf_event_indication_event_type, { "Event Type", "ecpri.ei.eventtype", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(event_indication_event_type_coding), 0x0, NULL, HFILL } },
1319
14
        { &hf_event_indication_sequence_number, { "Sequence Number", "ecpri.ei.seqnum", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1320
14
        { &hf_event_indication_number_of_faults_notifications, { "Number of Faults/Notifications", "ecpri.ei.numberfaultnotif", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1321
14
        { &hf_event_indication_element, { "Element", "ecpri.ei.element", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1322
14
        { &hf_event_indication_element_id, { "Element ID", "ecpri.ei.elementid", FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(event_indication_element_id_coding),  0x0, NULL, HFILL } },
1323
14
        { &hf_event_indication_raise_cease, { "Raise/Cease", "ecpri.ei.raisecease", FT_UINT8, BASE_HEX, VALS(event_indication_raise_ceased_coding), 0xF0, NULL, HFILL } },
1324
14
        { &hf_event_indication_fault_notification, { "Fault/Notification", "ecpri.ei.faultnotif", FT_UINT16, BASE_HEX|BASE_RANGE_STRING, RVALS(event_indication_fault_notif_coding), 0x0FFF, NULL, HFILL } },
1325
14
        { &hf_event_indication_additional_information, { "Additional Information", "ecpri.ei.addinfo", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1326
    /* Message Type 8: IWF Start-Up */
1327
14
        { &hf_iwf_start_up_hyperframe_number, { "Hyperframe Number #Z", "ecpri.iwfsu.hfn", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1328
14
        { &hf_iwf_start_up_subframe_number, { "Subframe Number #Y", "ecpri.iwfsu.sfn", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1329
14
        { &hf_iwf_start_up_timestamp, { "Timestamp", "ecpri.iwfsu.timestamp", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_nanoseconds), 0x0, NULL, HFILL } },
1330
14
        { &hf_iwf_start_up_fec_bit_indicator, { "FEC Bit Indicator", "ecpri.iwfsu.fecbit", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x80, NULL, HFILL } },
1331
14
        { &hf_iwf_start_up_scrambling_bit_indicator, { "Scrambling Bit Indicator", "ecpri.iwfsu.scramblingbit", FT_BOOLEAN, 8, TFS(&tfs_enabled_disabled), 0x40, NULL, HFILL } },
1332
14
        { &hf_iwf_start_up_line_rate, { "Line Rate", "ecpri.iwfsu.linerate", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(iwf_start_up_line_rate_coding), 0x1F, NULL, HFILL } },
1333
14
        { &hf_iwf_start_up_data_transferred, { "Data transferred", "ecpri.iwfsu.vendorpayload", FT_BYTES, SEP_COLON, NULL, 0x0, NULL, HFILL } },
1334
    /* Message Type 11: IWF Delay Control */
1335
14
        { &hf_iwf_delay_control_delay_control_id, { "Delay Control ID", "ecpri.iwfdc.id", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
1336
14
        { &hf_iwf_delay_control_action_type, { "Action Type", "ecpri.iwfdc.actiontype", FT_UINT8, BASE_HEX|BASE_RANGE_STRING, RVALS(iwf_delay_control_action_type_coding), 0x0, NULL, HFILL } },
1337
14
        { &hf_iwf_delay_control_delay_a, { "Delay A", "ecpri.iwfdc.delaya", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1338
14
        { &hf_iwf_delay_control_delay_b, { "Delay B", "ecpri.iwfdc.delayb", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
1339
14
    };
1340
1341
    /* Setup protocol subtree array */
1342
14
    static int *ett[] = {
1343
14
        &ett_ecpri,
1344
14
        &ett_ecpri_header,
1345
14
        &ett_ecpri_payload,
1346
14
        &ett_ecpri_timestamp,
1347
14
        &ett_ecpri_element
1348
14
    };
1349
1350
14
    static ei_register_info ei[] = {
1351
14
        { &ei_ecpri_frame_length,            { "ecpri.frame.length.invalid",       PI_PROTOCOL, PI_ERROR, "Invalid eCPRI Frame Length", EXPFILL }},
1352
14
        { &ei_payload_size,                  { "ecpri.payload.size.invalid",       PI_PROTOCOL, PI_ERROR, "Invalid Payload Size",       EXPFILL }},
1353
14
        { &ei_data_length,                   { "ecpri.data.length.invalid",        PI_PROTOCOL, PI_ERROR, "Invalid Data Length",        EXPFILL }},
1354
14
        { &ei_comp_val,                      { "ecpri.comp.val.invalid",           PI_PROTOCOL, PI_ERROR, "Invalid Compensation Value", EXPFILL }},
1355
14
        { &ei_time_stamp,                    { "ecpri.time.stamp.invalid",         PI_PROTOCOL, PI_ERROR, "Invalid Time Stamp",         EXPFILL }},
1356
14
        { &ei_compensation_value_nonzero,    { "ecpri.compensation-value.nonzero", PI_PROTOCOL, PI_WARN,  "Compensation Value should be zero",  EXPFILL }},
1357
14
        { &ei_c_bit,                         { "ecpri.concat.bit.invalid",         PI_PROTOCOL, PI_ERROR, "Invalid Concatenation Bit",  EXPFILL }},
1358
14
        { &ei_fault_notif,                   { "ecpri.fault.notif.invalid",        PI_PROTOCOL, PI_ERROR, "Invalid Fault/Notification", EXPFILL }},
1359
14
        { &ei_number_faults,                 { "ecpri.num.faults.invalid",         PI_PROTOCOL, PI_ERROR, "Invalid Number of Faults",   EXPFILL }},
1360
14
        { &ei_iwf_delay_control_action_type, { "ecpri.action.type.invalid",        PI_PROTOCOL, PI_ERROR, "Invalid Action Type", EXPFILL }},
1361
14
        { &ei_ecpri_not_dis_yet,             { "ecpri.not_dissected_yet",          PI_PROTOCOL, PI_NOTE,  "Not dissected yet",   EXPFILL }},
1362
14
        { &ei_owd_no_response,               { "ecpri.owd.no_response",            PI_SEQUENCE, PI_WARN,  "No Response for One-Way Delay Measurement Request",   EXPFILL }},
1363
14
        { &ei_owd_no_request,                { "ecpri.owd.no_rerequest",           PI_SEQUENCE, PI_WARN,  "Request for One-Way Delay Measurement Response not found",   EXPFILL }}
1364
14
    };
1365
1366
14
    expert_module_t* expert_ecpri;
1367
14
    module_t* ecpri_module;
1368
1369
    /* Register the protocol name and description */
1370
14
    proto_ecpri = proto_register_protocol("evolved Common Public Radio Interface",    /* Protoname */
1371
14
                                          "eCPRI",                                    /* Proto Shortname */
1372
14
                                          "ecpri");                                   /* Proto Abbrev */
1373
14
    ecpri_handle = register_dissector("ecpri", dissect_ecpri, proto_ecpri);
1374
1375
1376
    /* Required function calls to register the header fields and subtrees used */
1377
14
    proto_register_field_array(proto_ecpri, hf, array_length(hf));
1378
14
    proto_register_subtree_array(ett, array_length(ett));
1379
    /* Register Expert Info */
1380
14
    expert_ecpri = expert_register_protocol(proto_ecpri);
1381
14
    expert_register_field_array(expert_ecpri, ei, array_length(ei));
1382
    /* Register Preference */
1383
14
    ecpri_module = prefs_register_protocol(proto_ecpri, NULL);
1384
    /* If not set, it shows which message type was used, but no decoding of payload */
1385
14
    prefs_register_bool_preference(ecpri_module,
1386
14
            "ecpripref.msg.decoding",
1387
14
            "Decode Message Types",
1388
14
            "Decode the Message Types according to eCPRI Specification V2.0",
1389
14
            &pref_message_type_decoding);
1390
1391
14
    meas_id_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1392
14
    meas_results_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1393
14
}
1394
1395
void proto_reg_handoff_ecpri(void)
1396
14
{
1397
14
    dissector_add_uint("ethertype", ETHERTYPE_ECPRI, ecpri_handle);             /* Ethertypes 0xAEFE */
1398
14
    dissector_add_uint_range_with_preference("udp.port", "", ecpri_handle);     /* UDP Port Preference */
1399
1400
14
    oran_fh_handle = find_dissector("oran_fh_cus");
1401
14
}
1402
1403
/*
1404
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1405
 *
1406
 * Local variables:
1407
 * c-basic-offset: 4
1408
 * tab-width: 8
1409
 * indent-tabs-mode: nil
1410
 * End:
1411
 *
1412
 * vi: set shiftwidth=4 tabstop=8 expandtab:
1413
 * :indentSize=4:tabSize=8:noTabs=true:
1414
 */