Coverage Report

Created: 2026-09-28 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-oran.c
Line
Count
Source
1
/* packet-oran.c
2
 * Routines for O-RAN fronthaul UC-plane dissection
3
 * Copyright 2020, Jan Schiefer, Keysight Technologies, Inc.
4
 * Copyright 2020- Martin Mathieson
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
 /*
14
  * Dissector for the O-RAN Fronthaul CUS protocol specification.
15
  * See https://specifications.o-ran.org/specifications, WG4, Fronthaul Interfaces Workgroup
16
  * The current implementation is based on the ORAN-WG4.CUS.0-v21.00 specification.
17
  * Note that other eCPRI message types are handled in packet-ecpri.c
18
  */
19
20
#include <config.h>
21
22
#include <math.h>
23
24
#include <epan/packet.h>
25
#include <epan/expert.h>
26
#include <epan/prefs.h>
27
#include <epan/tap.h>
28
#include <epan/tfs.h>
29
#include <epan/reassemble.h>
30
31
#include <wsutil/ws_roundup.h>
32
#include <wsutil/ws_padding_to.h>
33
34
#include "epan/dissectors/packet-oran.h"
35
36
/* N.B. dissector preferences are taking the place of (some) M-plane parameters,
37
 * so unfortunately it can be fiddly to get the preferences into a good state to
38
 * decode a given capture..
39
 * TODO:
40
 * - Detect/indicate signs of application layer fragmentation?
41
 *      same eAxC in same symbol (same/different section ID?)
42
 * - Not handling M-plane setting for "little endian byte order" as applied to
43
 *   IQ samples and beam weights does anyone use this?
44
 * - for section extensions, check more constraints (which other extension types
45
 *   appear with them, order, repeated)
46
 * - re-order items (decl and hf definitions) to match spec order?
47
 * - track energy-saving status, and identify TRX or ASM commands as 'Sleep extension'
48
 * - when tracking between C-plane and U-plane, indicated in C-plane any missing sectionIds/PRBs/REs
49
 */
50
51
/* Prototypes */
52
void proto_register_oran(void);
53
54
/* Initialize the protocol and registered fields */
55
static int proto_oran;
56
57
static int oran_tap = -1;
58
59
static int hf_oran_du_port_id;
60
static int hf_oran_bandsector_id;
61
static int hf_oran_cc_id;
62
static int hf_oran_ru_port_id;
63
static int hf_oran_sequence_id;
64
static int hf_oran_e_bit;
65
static int hf_oran_subsequence_id;
66
static int hf_oran_previous_frame;
67
68
static int hf_oran_data_direction;
69
static int hf_oran_payload_version;
70
static int hf_oran_filter_index;
71
static int hf_oran_frame_id;
72
static int hf_oran_subframe_id;
73
static int hf_oran_slot_id;
74
static int hf_oran_slot_within_frame;
75
static int hf_oran_start_symbol_id;
76
static int hf_oran_numberOfSections;
77
static int hf_oran_sectionType;
78
79
static int hf_oran_udCompHdr;
80
static int hf_oran_udCompHdrIqWidth;
81
static int hf_oran_udCompHdrIqWidth_pref;
82
static int hf_oran_udCompHdrMeth;
83
static int hf_oran_udCompHdrMeth_pref;
84
static int hf_oran_udCompLen;
85
static int hf_oran_numberOfUEs;
86
static int hf_oran_timeOffset;
87
static int hf_oran_frameStructure_fft;
88
static int hf_oran_frameStructure_subcarrier_spacing;
89
static int hf_oran_cpLength;
90
static int hf_oran_timing_header;
91
static int hf_oran_section_id;
92
static int hf_oran_rb;
93
static int hf_oran_symInc;
94
static int hf_oran_startPrbc;
95
static int hf_oran_reMask_re1;
96
static int hf_oran_reMask_re2;
97
static int hf_oran_reMask_re3;
98
static int hf_oran_reMask_re4;
99
static int hf_oran_reMask_re5;
100
static int hf_oran_reMask_re6;
101
static int hf_oran_reMask_re7;
102
static int hf_oran_reMask_re8;
103
static int hf_oran_reMask_re9;
104
static int hf_oran_reMask_re10;
105
static int hf_oran_reMask_re11;
106
static int hf_oran_reMask_re12;
107
static int hf_oran_reMask;
108
static int hf_oran_numPrbc;
109
static int hf_oran_numSymbol;
110
static int hf_oran_ef;
111
static int hf_oran_beamId;
112
113
static int hf_oran_sinrCompHdrIqWidth_pref;
114
static int hf_oran_sinrCompHdrMeth_pref;
115
116
static int hf_oran_ciCompHdr;
117
static int hf_oran_ciCompHdrIqWidth;
118
static int hf_oran_ciCompHdrMeth;
119
static int hf_oran_ciCompOpt;
120
121
static int hf_oran_extension;
122
static int hf_oran_exttype;
123
static int hf_oran_extlen;
124
125
static int hf_oran_bfw_bundle;
126
static int hf_oran_bfw_bundle_id;
127
static int hf_oran_bfw;
128
static int hf_oran_bfw_i;
129
static int hf_oran_bfw_q;
130
131
static int hf_oran_ueId;
132
static int hf_oran_freqOffset;
133
static int hf_oran_regularizationFactor;
134
static int hf_oran_laaMsgType;
135
static int hf_oran_laaMsgLen;
136
static int hf_oran_lbtHandle;
137
static int hf_oran_lbtDeferFactor;
138
static int hf_oran_lbtBackoffCounter;
139
static int hf_oran_lbtOffset;
140
static int hf_oran_MCOT;
141
static int hf_oran_lbtMode;
142
static int hf_oran_sfnSfEnd;
143
static int hf_oran_lbtPdschRes;
144
static int hf_oran_sfStatus;
145
static int hf_oran_initialPartialSF;
146
static int hf_oran_lbtDrsRes;
147
static int hf_oran_lbtBufErr;
148
static int hf_oran_lbtTrafficClass;
149
static int hf_oran_lbtCWConfig_H;
150
static int hf_oran_lbtCWConfig_T;
151
static int hf_oran_lbtCWR_Rst;
152
153
static int hf_oran_reserved;
154
static int hf_oran_reserved_1bit;
155
static int hf_oran_reserved_2bits;
156
static int hf_oran_reserved_3bits;
157
static int hf_oran_reserved_4bits;
158
static int hf_oran_reserved_last_4bits;
159
static int hf_oran_reserved_last_5bits;
160
static int hf_oran_reserved_6bits;
161
static int hf_oran_reserved_last_6bits;
162
static int hf_oran_reserved_7bits;
163
static int hf_oran_reserved_last_7bits;
164
static int hf_oran_reserved_8bits;
165
static int hf_oran_reserved_16bits;
166
static int hf_oran_reserved_15bits;
167
static int hf_oran_reserved_bit1;
168
static int hf_oran_reserved_bit2;
169
static int hf_oran_reserved_bit4;
170
static int hf_oran_reserved_bit5;
171
static int hf_oran_reserved_bits123;
172
static int hf_oran_reserved_bits456;
173
174
static int hf_oran_bundle_offset;
175
static int hf_oran_cont_ind;
176
177
static int hf_oran_bfwCompHdr;
178
static int hf_oran_bfwCompHdr_iqWidth;
179
static int hf_oran_bfwCompHdr_compMeth;
180
static int hf_oran_symbolId;
181
static int hf_oran_startPrbu;
182
static int hf_oran_numPrbu;
183
184
static int hf_oran_udCompParam;
185
static int hf_oran_sReSMask;
186
static int hf_oran_sReSMask_re12;
187
static int hf_oran_sReSMask_re11;
188
static int hf_oran_sReSMask_re10;
189
static int hf_oran_sReSMask_re9;
190
static int hf_oran_sReSMask_re8;
191
static int hf_oran_sReSMask_re7;
192
static int hf_oran_sReSMask_re6;
193
static int hf_oran_sReSMask_re5;
194
static int hf_oran_sReSMask_re4;
195
static int hf_oran_sReSMask_re3;
196
static int hf_oran_sReSMask_re2;
197
static int hf_oran_sReSMask_re1;
198
199
static int hf_oran_sReSMask1;
200
static int hf_oran_sReSMask2;
201
static int hf_oran_sReSMask1_2_re12;
202
static int hf_oran_sReSMask1_2_re11;
203
static int hf_oran_sReSMask1_2_re10;
204
static int hf_oran_sReSMask1_2_re9;
205
206
static int hf_oran_bfwCompParam;
207
208
static int hf_oran_iSample;
209
static int hf_oran_qSample;
210
211
static int hf_oran_ciCompParam;
212
213
static int hf_oran_blockScaler;
214
static int hf_oran_compBitWidth;
215
static int hf_oran_compShift;
216
217
static int hf_oran_active_beamspace_coefficient_n1;
218
static int hf_oran_active_beamspace_coefficient_n2;
219
static int hf_oran_active_beamspace_coefficient_n3;
220
static int hf_oran_active_beamspace_coefficient_n4;
221
static int hf_oran_active_beamspace_coefficient_n5;
222
static int hf_oran_active_beamspace_coefficient_n6;
223
static int hf_oran_active_beamspace_coefficient_n7;
224
static int hf_oran_active_beamspace_coefficient_n8;
225
static int hf_oran_activeBeamspaceCoefficientMask;
226
static int hf_oran_activeBeamspaceCoefficientMask_bits_set;
227
228
static int hf_oran_se6_repetition;
229
230
static int hf_oran_rbgSize;
231
static int hf_oran_rbgMask;
232
static int hf_oran_noncontig_priority;
233
234
static int hf_oran_symbol_mask;
235
static int hf_oran_symbol_mask_s13;
236
static int hf_oran_symbol_mask_s12;
237
static int hf_oran_symbol_mask_s11;
238
static int hf_oran_symbol_mask_s10;
239
static int hf_oran_symbol_mask_s9;
240
static int hf_oran_symbol_mask_s8;
241
static int hf_oran_symbol_mask_s7;
242
static int hf_oran_symbol_mask_s6;
243
static int hf_oran_symbol_mask_s5;
244
static int hf_oran_symbol_mask_s4;
245
static int hf_oran_symbol_mask_s3;
246
static int hf_oran_symbol_mask_s2;
247
static int hf_oran_symbol_mask_s1;
248
static int hf_oran_symbol_mask_s0;
249
250
static int hf_oran_rbg_mask_27;
251
static int hf_oran_rbg_mask_26;
252
static int hf_oran_rbg_mask_25;
253
static int hf_oran_rbg_mask_24;
254
static int hf_oran_rbg_mask_23;
255
static int hf_oran_rbg_mask_22;
256
static int hf_oran_rbg_mask_21;
257
static int hf_oran_rbg_mask_20;
258
static int hf_oran_rbg_mask_19;
259
static int hf_oran_rbg_mask_18;
260
static int hf_oran_rbg_mask_17;
261
static int hf_oran_rbg_mask_16;
262
static int hf_oran_rbg_mask_15;
263
static int hf_oran_rbg_mask_14;
264
static int hf_oran_rbg_mask_13;
265
static int hf_oran_rbg_mask_12;
266
static int hf_oran_rbg_mask_11;
267
static int hf_oran_rbg_mask_10;
268
static int hf_oran_rbg_mask_9;
269
static int hf_oran_rbg_mask_8;
270
static int hf_oran_rbg_mask_7;
271
static int hf_oran_rbg_mask_6;
272
static int hf_oran_rbg_mask_5;
273
static int hf_oran_rbg_mask_4;
274
static int hf_oran_rbg_mask_3;
275
static int hf_oran_rbg_mask_2;
276
static int hf_oran_rbg_mask_1;
277
static int hf_oran_rbg_mask_0;
278
279
static int hf_oran_exponent;
280
static int hf_oran_iq_user_data;
281
282
static int hf_oran_disable_bfws;
283
static int hf_oran_rad;
284
static int hf_oran_num_bund_prbs;
285
static int hf_oran_beam_id;
286
static int hf_oran_num_weights_per_bundle;
287
288
static int hf_oran_ack_nack_req_id;
289
290
static int hf_oran_frequency_range;
291
static int hf_oran_off_start_prb;
292
static int hf_oran_num_prb;
293
294
static int hf_oran_samples_prb;
295
static int hf_oran_ciSample;
296
static int hf_oran_ciIsample;
297
static int hf_oran_ciQsample;
298
299
static int hf_oran_beamGroupType;
300
static int hf_oran_numPortc;
301
302
static int hf_oran_csf;
303
static int hf_oran_modcompscaler;
304
305
static int hf_oran_modcomp_param_set;
306
static int hf_oran_mc_scale_re_mask_re1;
307
static int hf_oran_mc_scale_re_mask_re2;
308
static int hf_oran_mc_scale_re_mask_re3;
309
static int hf_oran_mc_scale_re_mask_re4;
310
static int hf_oran_mc_scale_re_mask_re5;
311
static int hf_oran_mc_scale_re_mask_re6;
312
static int hf_oran_mc_scale_re_mask_re7;
313
static int hf_oran_mc_scale_re_mask_re8;
314
static int hf_oran_mc_scale_re_mask_re9;
315
static int hf_oran_mc_scale_re_mask_re10;
316
static int hf_oran_mc_scale_re_mask_re11;
317
static int hf_oran_mc_scale_re_mask_re12;
318
static int hf_oran_mc_scale_re_mask_re1_even;
319
static int hf_oran_mc_scale_re_mask_re2_even;
320
static int hf_oran_mc_scale_re_mask_re3_even;
321
static int hf_oran_mc_scale_re_mask_re4_even;
322
static int hf_oran_mc_scale_re_mask_re5_even;
323
static int hf_oran_mc_scale_re_mask_re6_even;
324
static int hf_oran_mc_scale_re_mask_re7_even;
325
static int hf_oran_mc_scale_re_mask_re8_even;
326
static int hf_oran_mc_scale_re_mask_re9_even;
327
static int hf_oran_mc_scale_re_mask_re10_even;
328
static int hf_oran_mc_scale_re_mask_re11_even;
329
static int hf_oran_mc_scale_re_mask_re12_even;
330
331
static int hf_oran_mc_scale_re_mask;
332
static int hf_oran_mc_scale_re_mask_even;
333
334
static int hf_oran_mc_scale_offset;
335
336
static int hf_oran_eAxC_mask;
337
static int hf_oran_technology;
338
static int hf_oran_nullLayerInd;
339
340
static int hf_oran_se19_repetition;
341
static int hf_oran_portReMask;
342
static int hf_oran_portSymbolMask;
343
344
static int hf_oran_ext19_port;
345
346
static int hf_oran_prb_allocation;
347
static int hf_oran_nextSymbolId;
348
static int hf_oran_nextStartPrbc;
349
350
static int hf_oran_puncPattern;
351
static int hf_oran_numPuncPatterns;
352
static int hf_oran_symbolMask_ext20;
353
static int hf_oran_startPuncPrb;
354
static int hf_oran_numPuncPrb;
355
static int hf_oran_puncReMask;
356
static int hf_oran_multiSDScope;
357
static int hf_oran_RbgIncl;
358
359
static int hf_oran_ci_prb_group_size;
360
static int hf_oran_prg_size_st5;
361
static int hf_oran_prg_size_st6;
362
363
static int hf_oran_num_ueid;
364
365
static int hf_oran_antMask;
366
367
static int hf_oran_transmissionWindowOffset;
368
static int hf_oran_transmissionWindowSize;
369
static int hf_oran_toT;
370
371
static int hf_oran_bfaCompHdr;
372
static int hf_oran_bfAzPtWidth;
373
static int hf_oran_bfZePtWidth;
374
static int hf_oran_bfAz3ddWidth;
375
static int hf_oran_bfZe3ddWidth;
376
static int hf_oran_bfAzPt;
377
static int hf_oran_bfZePt;
378
static int hf_oran_bfAz3dd;
379
static int hf_oran_bfZe3dd;
380
static int hf_oran_bfAzSl;
381
static int hf_oran_bfZeSl;
382
383
static int hf_oran_cmd_scope;
384
static int hf_oran_number_of_st4_cmds;
385
386
static int hf_oran_st4_cmd_header;
387
static int hf_oran_st4_cmd_type;
388
static int hf_oran_st4_cmd_len;
389
static int hf_oran_st4_cmd_num_slots;
390
static int hf_oran_st4_cmd_ack_nack_req_id;
391
392
static int hf_oran_st4_cmd;
393
394
static int hf_oran_sleepmode_trx;
395
static int hf_oran_sleepmode_asm;
396
static int hf_oran_log2maskbits;
397
static int hf_oran_num_slots_ext;
398
static int hf_oran_antMask_trx_control;
399
400
static int hf_oran_ready;
401
static int hf_oran_number_of_acks;
402
static int hf_oran_number_of_nacks;
403
static int hf_oran_ackid;
404
static int hf_oran_nackid;
405
406
static int hf_oran_acknack_request_frame;
407
static int hf_oran_acknack_request_time;
408
static int hf_oran_acknack_request_type;
409
static int hf_oran_acknack_response_frame;
410
static int hf_oran_acknack_response_time;
411
412
static int hf_oran_disable_tdbfns;
413
static int hf_oran_td_beam_group;
414
static int hf_oran_disable_tdbfws;
415
static int hf_oran_td_beam_num;
416
417
static int hf_oran_dir_pattern;
418
static int hf_oran_guard_pattern;
419
420
static int hf_oran_ecpri_pcid;
421
static int hf_oran_ecpri_rtcid;
422
static int hf_oran_ecpri_seqid;
423
424
static int hf_oran_num_sym_prb_pattern;
425
static int hf_oran_prb_mode;
426
static int hf_oran_sym_prb_pattern;
427
static int hf_oran_sym_mask;
428
static int hf_oran_num_mc_scale_offset;
429
static int hf_oran_prb_pattern;
430
static int hf_oran_prb_blk_offset;
431
static int hf_oran_prb_blk_size;
432
433
static int hf_oran_codebook_index;
434
static int hf_oran_layerid;
435
static int hf_oran_numlayers;
436
static int hf_oran_txscheme;
437
static int hf_oran_crs_remask;
438
static int hf_oran_crs_shift;
439
static int hf_oran_crs_symnum;
440
static int hf_oran_beamid_ap1;
441
static int hf_oran_beamid_ap2;
442
static int hf_oran_beamid_ap3;
443
444
static int hf_oran_port_list_index;
445
static int hf_oran_alpn_per_sym;
446
static int hf_oran_ant_dmrs_snr;
447
static int hf_oran_user_group_size;
448
static int hf_oran_user_group_id;
449
static int hf_oran_entry_type;
450
static int hf_oran_dmrs_port_number;
451
static int hf_oran_ueid_reset;
452
453
static int hf_oran_dmrs_symbol_mask;
454
static int hf_oran_dmrs_symbol_mask_s13;
455
static int hf_oran_dmrs_symbol_mask_s12;
456
static int hf_oran_dmrs_symbol_mask_s11;
457
static int hf_oran_dmrs_symbol_mask_s10;
458
static int hf_oran_dmrs_symbol_mask_s9;
459
static int hf_oran_dmrs_symbol_mask_s8;
460
static int hf_oran_dmrs_symbol_mask_s7;
461
static int hf_oran_dmrs_symbol_mask_s6;
462
static int hf_oran_dmrs_symbol_mask_s5;
463
static int hf_oran_dmrs_symbol_mask_s4;
464
static int hf_oran_dmrs_symbol_mask_s3;
465
static int hf_oran_dmrs_symbol_mask_s2;
466
static int hf_oran_dmrs_symbol_mask_s1;
467
static int hf_oran_dmrs_symbol_mask_s0;
468
469
static int hf_oran_scrambling;
470
static int hf_oran_nscid;
471
static int hf_oran_dtype;
472
static int hf_oran_cmd_without_data;
473
static int hf_oran_lambda;
474
static int hf_oran_first_prb;
475
static int hf_oran_last_prb;
476
static int hf_oran_low_papr_type;
477
static int hf_oran_hopping_mode;
478
479
static int hf_oran_tx_win_for_on_air_symbol_l;
480
static int hf_oran_tx_win_for_on_air_symbol_r;
481
482
static int hf_oran_num_fo_fb;
483
static int hf_oran_freq_offset_fb;
484
485
static int hf_oran_num_ue_sinr_rpt;
486
static int hf_oran_num_sinr_per_prb;
487
static int hf_oran_num_sinr_per_prb_right;
488
489
static int hf_oran_sinr_value;
490
491
static int hf_oran_measurement_report;
492
static int hf_oran_mf;
493
static int hf_oran_meas_data_size;
494
static int hf_oran_meas_type_id;
495
static int hf_oran_ipn_power;
496
static int hf_oran_ue_tae;
497
static int hf_oran_ue_layer_power;
498
static int hf_oran_num_elements;
499
static int hf_oran_ant_dmrs_snr_val;
500
static int hf_oran_ue_freq_offset;
501
static int hf_oran_curr_ue_freq_offset;
502
503
static int hf_oran_measurement_command;
504
505
static int hf_oran_beam_type;
506
static int hf_oran_meas_cmd_size;
507
508
static int hf_oran_symbol_reordering_layer;
509
static int hf_oran_dmrs_entry;
510
511
static int hf_oran_c_section_common;
512
static int hf_oran_c_section;
513
static int hf_oran_u_section;
514
515
static int hf_oran_u_section_ul_symbol_time;
516
static int hf_oran_u_section_ul_symbol_frames;
517
static int hf_oran_u_section_ul_symbol_first_frame;
518
static int hf_oran_u_section_ul_symbol_last_frame;
519
520
static int hf_oran_cd_scg_size;
521
static int hf_oran_cd_scg_phase_step;
522
523
static int hf_oran_sinr_prb;
524
static int hf_oran_oru_control_sinr_slot_mask_id;
525
static int hf_oran_pos_meas;
526
527
static int hf_oran_ue_radial_speed;
528
static int hf_oran_ue_az_aoa;
529
static int hf_oran_ue_ze_aoa;
530
static int hf_oran_ue_pos_toa_offset;
531
532
static int hf_oran_num_rep_ue;
533
static int hf_oran_rep_ueid;
534
static int hf_oran_is_last_rep;
535
static int hf_oran_rep_index;
536
static int hf_oran_num_reps;
537
538
static int hf_oran_mcs_table;
539
static int hf_oran_mcs_index;
540
541
static int hf_oran_num_meas_req;
542
static int hf_oran_num_of_ue_ant_ports;
543
static int hf_oran_ue_rank;
544
static int hf_oran_codebook_subset;
545
static int hf_oran_full_pwr_mode;
546
static int hf_oran_full_pwr_mode_2_tpmi_group;
547
548
static int hf_oran_num_cand_ranks;
549
static int hf_oran_ue_pref_rank;
550
static int hf_oran_ue_tpmi_rank_y;
551
static int hf_oran_ue_tpmi_rank_y_sinr_lx;
552
static int hf_oran_ue_layer_pre_eq_sinr;
553
554
555
/* Computed fields */
556
static int hf_oran_c_eAxC_ID;
557
static int hf_oran_refa;
558
559
static int hf_oran_bfws_frame_defined;
560
static int hf_oran_bfws_symbols_since_defined;
561
562
static int hf_oran_corresponding_cplane_frame;
563
static int hf_oran_corresponding_cplane_frame_time_delta;
564
static int hf_oran_corresponding_uplane_frame;
565
static int hf_oran_corresponding_uplane_frames_total;
566
567
568
/* Convenient fields for filtering, mostly shown as hidden */
569
static int hf_oran_cplane;
570
static int hf_oran_uplane;
571
static int hf_oran_bf;      /* to match frames that configure beamforming in any way */
572
static int hf_oran_zero_prb;
573
static int hf_oran_nonzero_prb;
574
static int hf_oran_bundle_weights_all_zero;
575
576
static int hf_oran_ul_cplane_ud_comp_hdr_frame;
577
578
/* For reassembly */
579
static int hf_oran_fragments;
580
static int hf_oran_fragment;
581
static int hf_oran_fragment_overlap;
582
static int hf_oran_fragment_overlap_conflict;
583
static int hf_oran_fragment_multiple_tails;
584
static int hf_oran_fragment_too_long_fragment;
585
static int hf_oran_fragment_error;
586
static int hf_oran_fragment_count;
587
static int hf_oran_reassembled_in;
588
static int hf_oran_reassembled_length;
589
static int hf_oran_reassembled_data;
590
591
static int hf_oran_payload;
592
593
594
/* Subtrees */
595
static int ett_oran;
596
static int ett_oran_ecpri_rtcid;
597
static int ett_oran_ecpri_pcid;
598
static int ett_oran_ecpri_seqid;
599
static int ett_oran_section;
600
static int ett_oran_section_type;
601
static int ett_oran_u_timing;
602
static int ett_oran_u_section;
603
static int ett_oran_u_prb;
604
static int ett_oran_iq;
605
static int ett_oran_bfw_bundle;
606
static int ett_oran_bfw;
607
static int ett_oran_frequency_range;
608
static int ett_oran_prb_cisamples;
609
static int ett_oran_cisample;
610
static int ett_oran_udcomphdr;
611
static int ett_oran_udcompparam;
612
static int ett_oran_cicomphdr;
613
static int ett_oran_cicompparam;
614
static int ett_oran_bfwcomphdr;
615
static int ett_oran_bfwcompparam;
616
static int ett_oran_ext19_port;
617
static int ett_oran_prb_allocation;
618
static int ett_oran_punc_pattern;
619
static int ett_oran_bfacomphdr;
620
static int ett_oran_modcomp_param_set;
621
static int ett_oran_st4_cmd_header;
622
static int ett_oran_st4_cmd;
623
static int ett_oran_sym_prb_pattern;
624
static int ett_oran_measurement_report;
625
static int ett_oran_measurement_command;
626
static int ett_oran_sresmask;
627
static int ett_oran_c_section_common;
628
static int ett_oran_c_section;
629
static int ett_oran_remask;
630
static int ett_oran_mc_scale_remask;
631
static int ett_oran_symbol_reordering_layer;
632
static int ett_oran_dmrs_entry;
633
static int ett_oran_dmrs_symbol_mask;
634
static int ett_oran_symbol_mask;
635
static int ett_oran_active_beamspace_coefficient_mask;
636
static int ett_oran_sinr_prb;
637
static int ett_oran_rbgMask;
638
639
static int ett_oran_fragment;
640
static int ett_oran_fragments;
641
642
/* Reassembly table. */
643
static reassembly_table oran_reassembly_table;
644
645
static void *oran_key(const packet_info *pinfo _U_, const uint32_t id _U_, const void *data)
646
61
{
647
61
    return (void *)data;
648
61
}
649
650
static void oran_free_key(void *ptr _U_)
651
33
{
652
33
}
653
654
static reassembly_table_functions oran_reassembly_table_functions =
655
{
656
    g_direct_hash,
657
    g_direct_equal,
658
    oran_key,
659
    oran_key,
660
    oran_free_key,
661
    oran_free_key
662
};
663
664
static const fragment_items oran_frag_items = {
665
  &ett_oran_fragment,
666
  &ett_oran_fragments,
667
  &hf_oran_fragments,
668
  &hf_oran_fragment,
669
  &hf_oran_fragment_overlap,
670
  &hf_oran_fragment_overlap_conflict,
671
  &hf_oran_fragment_multiple_tails,
672
  &hf_oran_fragment_too_long_fragment,
673
  &hf_oran_fragment_error,
674
  &hf_oran_fragment_count,
675
  &hf_oran_reassembled_in,
676
  &hf_oran_reassembled_length,
677
  &hf_oran_reassembled_data,
678
  "O-RAN FH CUS fragments"
679
};
680
681
682
/* Don't want all extensions to open and close together. Use [extType-1] entry */
683
static int ett_oran_c_section_extension[HIGHEST_EXTTYPE];
684
685
/* Expert info */
686
static expert_field ei_oran_unsupported_bfw_compression_method;
687
static expert_field ei_oran_invalid_sample_bit_width;
688
static expert_field ei_oran_reserved_numBundPrb;
689
static expert_field ei_oran_extlen_wrong;
690
static expert_field ei_oran_invalid_eaxc_bit_width;
691
static expert_field ei_oran_extlen_zero;
692
static expert_field ei_oran_rbg_size_reserved;
693
static expert_field ei_oran_frame_length;
694
static expert_field ei_oran_numprbc_ext21_zero;
695
static expert_field ei_oran_ci_prb_group_size_reserved;
696
static expert_field ei_oran_st8_nackid;
697
static expert_field ei_oran_st4_no_cmds;
698
static expert_field ei_oran_st4_zero_len_cmd;
699
static expert_field ei_oran_st4_wrong_len_cmd;
700
static expert_field ei_oran_st4_unknown_cmd;
701
static expert_field ei_oran_mcot_out_of_range;
702
static expert_field ei_oran_se10_unknown_beamgrouptype;
703
static expert_field ei_oran_se10_not_allowed;
704
static expert_field ei_oran_start_symbol_id_not_zero;
705
static expert_field ei_oran_trx_control_cmd_scope;
706
static expert_field ei_oran_unhandled_se;
707
static expert_field ei_oran_bad_symbolmask;
708
static expert_field ei_oran_numslots_not_zero;
709
static expert_field ei_oran_version_unsupported;
710
static expert_field ei_oran_laa_msg_type_unsupported;
711
static expert_field ei_oran_se_on_unsupported_st;
712
static expert_field ei_oran_cplane_unexpected_sequence_number_ul;
713
static expert_field ei_oran_cplane_unexpected_sequence_number_dl;
714
static expert_field ei_oran_uplane_unexpected_sequence_number_ul;
715
static expert_field ei_oran_uplane_unexpected_sequence_number_dl;
716
static expert_field ei_oran_acknack_no_request;
717
static expert_field ei_oran_udpcomphdr_should_be_zero;
718
static expert_field ei_oran_radio_fragmentation_c_plane;
719
static expert_field ei_oran_lastRbdid_out_of_range;
720
static expert_field ei_oran_rbgMask_beyond_last_rbdid;
721
static expert_field ei_oran_unexpected_measTypeId;
722
static expert_field ei_oran_unsupported_compression_method;
723
static expert_field ei_oran_ud_comp_len_wrong_size;
724
static expert_field ei_oran_sresmask2_not_zero_with_rb;
725
static expert_field ei_oran_st6_rb_shall_be_0;
726
static expert_field ei_oran_st9_not_ul;
727
static expert_field ei_oran_st10_numsymbol_not_14;
728
static expert_field ei_oran_st10_startsymbolid_not_0;
729
static expert_field ei_oran_st10_not_ul;
730
static expert_field ei_oran_se24_nothing_to_inherit;
731
static expert_field ei_oran_num_sinr_per_prb_unknown;
732
static expert_field ei_oran_start_symbol_id_bits_ignored;
733
static expert_field ei_oran_user_group_id_reserved_value;
734
static expert_field ei_oran_port_list_index_zero;
735
static expert_field ei_oran_ul_uplane_symbol_too_long;
736
static expert_field ei_oran_reserved_not_zero;
737
static expert_field ei_oran_too_many_symbols;
738
static expert_field ei_oran_se30_not_ul;
739
static expert_field ei_oran_se30_unknown_ueid;
740
static expert_field ei_oran_beamid_bfws_not_found;
741
static expert_field ei_oran_syminc_set_for_uplane;
742
static expert_field ei_oran_cplane_entry_not_found;
743
static expert_field ei_oran_se12_rb_set;
744
745
746
/* These are the message types handled by this dissector.  Others have handling in packet-ecpri.c */
747
202
#define ECPRI_MT_IQ_DATA            0
748
1.73k
#define ECPRI_MT_RT_CTRL_DATA       2
749
750
751
/* Preference settings - try to set reasonable defaults */
752
static unsigned pref_du_port_id_bits    = 4;
753
static unsigned pref_bandsector_id_bits = 4;
754
static unsigned pref_cc_id_bits         = 4;
755
static unsigned pref_ru_port_id_bits    = 4;
756
757
/* TODO: ideally should be per-flow */
758
static unsigned pref_sample_bit_width_uplink   = 14;
759
static unsigned pref_sample_bit_width_downlink = 14;
760
static unsigned pref_sample_bit_width_sinr   = 14;
761
762
/* TODO: these ideally should be per-flow too */
763
static int pref_iqCompressionUplink = COMP_BLOCK_FP;
764
static int pref_iqCompressionDownlink = COMP_BLOCK_FP;
765
766
static int pref_iqCompressionSINR = COMP_BLOCK_FP;
767
768
769
/* Is udCompHeader present (both directions) */
770
static int pref_includeUdCompHeaderUplink = 2;     /* start using heuristic */
771
static int pref_includeUdCompHeaderDownlink = 2;   /* start using heuristic */
772
773
/* Are we ignoring UL C-Plane udCompHdr? */
774
static bool pref_override_ul_compression = false;
775
776
static unsigned pref_data_plane_section_total_rbs = 273;
777
static unsigned pref_num_bf_antennas = 32;
778
static bool pref_showIQSampleValues = true;
779
780
/* Based upon m-plane param, so will be system-wide */
781
static int  pref_support_udcompLen = 2;            /* start heuristic, can force other settings if necessary */
782
static bool udcomplen_heuristic_result_set = false;
783
static bool udcomplen_heuristic_result = false;
784
785
/* st6-4byte-alignment-required */
786
static bool st6_4byte_alignment = false;
787
788
/* Requested, allows I/Q to be stored as integers.. */
789
static bool show_unscaled_values = false;
790
791
/* Initialized off. Timing is in microseconds. */
792
static unsigned us_allowed_for_ul_in_symbol = 0;
793
794
/* Reassemble U-Plane (at Radio Transport layer) */
795
static bool do_radio_transport_layer_reassembly = true;
796
797
/* Link U-plane back to C-plane using sectionIds */
798
static bool link_planes_together = true;
799
800
static const enum_val_t dl_compression_options[] = {
801
    { "COMP_NONE",                             "No Compression",                                                             COMP_NONE },
802
    { "COMP_BLOCK_FP",                         "Block Floating Point Compression",                                           COMP_BLOCK_FP },
803
    { "COMP_BLOCK_SCALE",                      "Block Scaling Compression",                                                  COMP_BLOCK_SCALE },
804
    { "COMP_U_LAW",                            "u-Law Compression",                                                          COMP_U_LAW },
805
    { "COMP_MODULATION",                       "Modulation Compression",                                                     COMP_MODULATION },
806
    { "BFP_AND_SELECTIVE_RE",                  "Block Floating Point + selective RE sending",                                BFP_AND_SELECTIVE_RE },
807
    { "MOD_COMPR_AND_SELECTIVE_RE",            "Modulation Compression + selective RE sending",                              MOD_COMPR_AND_SELECTIVE_RE },
808
    { "BFP_AND_SELECTIVE_RE_WITH_MASKS",       "Block Floating Point + selective RE sending with masks in section header",   BFP_AND_SELECTIVE_RE_WITH_MASKS },
809
    { "MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS", "Modulation Compression + selective RE sending with masks in section header", MOD_COMPR_AND_SELECTIVE_RE },
810
    { NULL, NULL, 0 }
811
};
812
813
/* No Modulation compression in UL.. */
814
static const enum_val_t ul_compression_options[] = {
815
    { "COMP_NONE",                             "No Compression",                                                           COMP_NONE },
816
    { "COMP_BLOCK_FP",                         "Block Floating Point Compression",                                         COMP_BLOCK_FP },
817
    { "COMP_BLOCK_SCALE",                      "Block Scaling Compression",                                                COMP_BLOCK_SCALE },
818
    { "COMP_U_LAW",                            "u-Law Compression",                                                        COMP_U_LAW },
819
    { "BFP_AND_SELECTIVE_RE",                  "Block Floating Point + selective RE sending",                              BFP_AND_SELECTIVE_RE },
820
    { "BFP_AND_SELECTIVE_RE_WITH_MASKS",       "Block Floating Point + selective RE sending with masks in section header", BFP_AND_SELECTIVE_RE_WITH_MASKS },
821
    { NULL, NULL, 0 }
822
};
823
824
static const enum_val_t udcomplen_support_options[] = {
825
    { "NOT_SUPPORTED",              "Not Supported",     0 },
826
    { "SUPPORTED",                  "Supported",         1 },
827
    { "HEURISTIC",                  "Attempt Heuristic", 2 },
828
    { NULL, NULL, 0 }
829
};
830
831
static const enum_val_t udcomphdr_present_options[] = {
832
    { "NOT_PRESENT",               "Not Present",       0 },
833
    { "PRESENT",                   "Present",           1 },
834
    { "HEURISTIC",                 "Attempt Heuristic", 2 },
835
    { NULL, NULL, 0 }
836
};
837
838
839
840
static const value_string e_bit[] = {
841
    { 0, "More fragments follow" },
842
    { 1, "Last fragment" },
843
    { 0, NULL}
844
};
845
846
2.92k
#define DIR_UPLINK      0
847
#define DIR_DOWNLINK    1
848
849
850
static const value_string data_direction_vals[] = {
851
    { DIR_UPLINK,   "Uplink" },   /* gNB Rx */
852
    { DIR_DOWNLINK, "Downlink" }, /* gNB Tx */
853
    { 0, NULL}
854
};
855
856
static const value_string rb_vals[] = {
857
    { 0, "Every RB used" },
858
    { 1, "Every other RB used" },
859
    { 0, NULL}
860
};
861
862
static const value_string sym_inc_vals[] = {
863
    { 0, "Use the current symbol number" },
864
    { 1, "Increment the current symbol number" },
865
    { 0, NULL}
866
};
867
868
static const value_string lbtMode_vals[] = {
869
    { 0,  "Full LBT (regular LBT, sending reservation signal until the beginning of the SF/slot)" },
870
    { 1,  "Partial LBT (looking back 25 usec prior to transmission" },
871
    { 2,  "Partial LBT (looking back 34 usec prior to transmission" },
872
    { 3,  "Full LBT and stop (regular LBT, without sending reservation signal" },
873
    { 0, NULL}
874
};
875
876
static const value_string ue_rank_vals[] = {
877
    { 1, "1" },
878
    { 2, "2" },
879
    { 3, "3" },
880
    { 4, "4" },
881
    { 0, NULL}
882
};
883
884
static const value_string num_of_ue_ant_ports_vals[] = {
885
    { 2, "2" },
886
    { 4, "4" },
887
    { 0, NULL}
888
};
889
890
static const value_string codebook_subset_vals[] = {
891
    { 0, "nonCoherent" },
892
    { 1, "partialAndNonCoherent" },
893
    { 2, "fullyAndPartialAndNonCoherent" },
894
    { 3, "reserved" },
895
    { 0, NULL}
896
};
897
898
899
static const range_string filter_indices[] = {
900
    {0, 0,  "standard channel filter"},
901
    {1, 1,  "UL filter for PRACH preamble formats 0, 1, 2; min. passband 839 x 1.25kHz = 1048.75 kHz"},
902
    {2, 2,  "UL filter for PRACH preamble format 3, min. passband 839 x 5 kHz = 4195 kHz"},
903
    {3, 3,  "UL filter for PRACH preamble formats A1, A2, A3, B1, B2, B3, B4, C0, C2; min. passband 139 x \u0394fRA"},
904
    {4, 4,  "UL filter for NPRACH 0, 1; min. passband 48 x 3.75KHz = 180 KHz"},
905
    {5, 5,  "UL filter for PRACH preamble formats"},
906
    {8, 8,  "UL filter NPUSCH"},
907
    {9, 9,  "Mixed numerology and other channels except PRACH and NB-IoT"},
908
    {9, 15, "Reserved"},
909
    {0, 0, NULL}
910
};
911
912
/* 7.3.1-1 */
913
static const range_string section_types[] = {
914
    { SEC_C_UNUSED_RB,         SEC_C_UNUSED_RB,         "Unused Resource Blocks or symbols in Downlink or Uplink" },
915
    { SEC_C_NORMAL,            SEC_C_NORMAL,            "Most DL/UL radio channels" },
916
    { SEC_C_RSVD2,             SEC_C_RSVD2,             "Reserved for future use" },
917
    { SEC_C_PRACH,             SEC_C_PRACH,             "PRACH and mixed-numerology channels" },
918
    { SEC_C_SLOT_CONTROL,      SEC_C_SLOT_CONTROL,      "Slot Configuration Control" },
919
    { SEC_C_UE_SCHED,          SEC_C_UE_SCHED,          "UE scheduling information (UE-ID assignment to section)" },
920
    { SEC_C_CH_INFO,           SEC_C_CH_INFO,           "Channel information" },
921
    { SEC_C_LAA,               SEC_C_LAA,               "LAA (License Assisted Access)" },
922
    { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "ACK/NACK Feedback" },
923
    { SEC_C_SINR_REPORTING,    SEC_C_SINR_REPORTING,    "SINR Reporting" },
924
    { SEC_C_RRM_MEAS_REPORTS,  SEC_C_RRM_MEAS_REPORTS,  "RRM Measurement Reports" },
925
    { SEC_C_REQUEST_RRM_MEAS,  SEC_C_REQUEST_RRM_MEAS,  "Request RRM Measurements" },
926
    { 12,                      255,                     "Reserved for future use" },
927
    { 0, 0, NULL} };
928
929
static const range_string section_types_short[] = {
930
    { SEC_C_UNUSED_RB,         SEC_C_UNUSED_RB,         "(Unused RBs)        " },
931
    { SEC_C_NORMAL,            SEC_C_NORMAL,            "(Most channels)     " },
932
    { SEC_C_RSVD2,             SEC_C_RSVD2,             "(reserved)          " },
933
    { SEC_C_PRACH,             SEC_C_PRACH,             "(PRACH/mixed-\u03bc)" },
934
    { SEC_C_SLOT_CONTROL,      SEC_C_SLOT_CONTROL,      "(Slot info)         " },
935
    { SEC_C_UE_SCHED,          SEC_C_UE_SCHED,          "(UE scheduling info)" },
936
    { SEC_C_CH_INFO,           SEC_C_CH_INFO,           "(Channel info)      " },
937
    { SEC_C_LAA,               SEC_C_LAA,               "(LAA)               " },
938
    { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "(ACK/NACK)          " },
939
    { SEC_C_SINR_REPORTING,    SEC_C_SINR_REPORTING,    "(SINR Reporting)    " },
940
    { SEC_C_RRM_MEAS_REPORTS,  SEC_C_RRM_MEAS_REPORTS,  "(RRM Meas Reports)  " },
941
    { SEC_C_REQUEST_RRM_MEAS,  SEC_C_REQUEST_RRM_MEAS,  "(Req RRM Meas)      " },
942
    { 12,                      255,                     "Reserved for future use" },
943
    { 0, 0, NULL }
944
};
945
946
static const range_string ud_comp_header_width[] = {
947
    {0, 0,  "I and Q are each 16 bits wide"},
948
    {1, 15, "Bit width of I and Q"},
949
    {0, 0, NULL} };
950
951
/* Table 8.3.3.13-3 */
952
static const range_string ud_comp_header_meth[] = {
953
    {COMP_NONE,                             COMP_NONE,                             "No compression" },
954
    {COMP_BLOCK_FP,                         COMP_BLOCK_FP,                         "Block floating point compression" },
955
    {COMP_BLOCK_SCALE,                      COMP_BLOCK_SCALE,                      "Block scaling" },
956
    {COMP_U_LAW,                            COMP_U_LAW,                            "Mu - law" },
957
    {COMP_MODULATION,                       COMP_MODULATION,                       "Modulation compression" },
958
    {BFP_AND_SELECTIVE_RE,                  BFP_AND_SELECTIVE_RE,                  "BFP + selective RE sending" },
959
    {MOD_COMPR_AND_SELECTIVE_RE,            MOD_COMPR_AND_SELECTIVE_RE,            "mod-compr + selective RE sending" },
960
    {BFP_AND_SELECTIVE_RE_WITH_MASKS,       BFP_AND_SELECTIVE_RE_WITH_MASKS,       "BFP + selective RE sending with masks in section header" },
961
    {MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, "mod-compr + selective RE sending with masks in section header"},
962
    {9, 15, "Reserved"},
963
    {0, 0, NULL}
964
};
965
966
/* Table 7.5.2.13-2 */
967
static const range_string frame_structure_fft[] = {
968
    {0,  0,  "Reserved (no FFT/iFFT processing)"},
969
    {1,  3,  "Reserved"},
970
    {4,  4,  "FFT size 16"},
971
    {5,  5,  "FFT size 32"},
972
    {6,  6,  "FFT size 64"},
973
    {7,  7,  "FFT size 128"},
974
    {8,  8,  "FFT size 256"},
975
    {9,  9,  "FFT size 512"},
976
    {10, 10, "FFT size 1024"},
977
    {11, 11, "FFT size 2048"},
978
    {12, 12, "FFT size 4096"},
979
    {13, 13, "FFT size 1536"},
980
    {14, 14, "FFT size 3072"},
981
    {15, 15, "Reserved"},
982
    {0, 0, NULL}
983
};
984
985
/* Table 7.5.2.13-3 */
986
static const range_string subcarrier_spacings[] = {
987
    { 0,  0,  "SCS 15 kHz, 1 slot/subframe, slot length 1 ms" },
988
    { 1,  1,  "SCS 30 kHz, 2 slots/subframe, slot length 500 \u03bcs" },
989
    { 2,  2,  "SCS 60 kHz, 4 slots/subframe, slot length 250 \u03bcs" },
990
    { 3,  3,  "SCS 120 kHz, 8 slots/subframe, slot length 125 \u03bcs" },
991
    { 4,  4,  "SCS 240 kHz, 16 slots/subframe, slot length 62.5 \u03bcs" },
992
    { 5,  11, "Reserved" }, /* N.B., 5 was 480kHz in early spec versions */
993
    { 12, 12, "SCS 1.25 kHz, 1 slot/subframe, slot length 1 ms" },
994
    { 13, 13, "SCS 3.75 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
995
    { 14, 14, "SCS 5 kHz, 1 slot/subframe, slot length 1 ms" },
996
    { 15, 15, "SCS 7.5 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
997
    { 0, 0, NULL }
998
};
999
1000
/* Table 7.5.3.14-1 laaMsgType definition */
1001
static const range_string laaMsgTypes[] = {
1002
    {0, 0,  "LBT_PDSCH_REQ - lls - O-DU to O-RU request to obtain a PDSCH channel"},
1003
    {1, 1,  "LBT_DRS_REQ - lls - O-DU to O-RU request to obtain the channel and send DRS"},
1004
    {2, 2,  "LBT_PDSCH_RSP - O-RU to O-DU response, channel acq success or failure"},
1005
    {3, 3,  "LBT_DRS_RSP - O-RU to O-DU response, DRS sending success or failure"},
1006
    {4, 4,  "LBT_Buffer_Error - O-RU to O-DU response, reporting buffer overflow"},
1007
    {5, 5,  "LBT_CWCONFIG_REQ - O-DU to O-RU request, congestion window configuration"},
1008
    {6, 6,  "LBT_CWCONFIG_RST - O-RU to O-DU request, congestion window config, response"},
1009
    {7, 15, "reserved for future methods"},
1010
    {0, 0, NULL}
1011
};
1012
1013
/* 7.7.26.3 */
1014
static const range_string freq_offset_fb_values[] = {
1015
    {0,      0,        "no frequency offset"},
1016
    {8000,   8000,     "value not provided"},
1017
    {1,      30000,    "positive frequency offset, (0, +0.5] subcarrier"},
1018
    {0x8ad0, 0xffff,   "negative frequency offset, [-0.5, 0) subcarrier"},
1019
    {0x0,    0xffff,   "reserved"},
1020
    {0, 0, NULL}
1021
};
1022
1023
/* 7.5.3.78 */
1024
static const range_string ue_tmpi_rank_sinr_vals[] = {
1025
    {0,      0,        "0 dB SINR"},
1026
    {0x0001, 0x07ff,   "positive SINR"},
1027
    {0xf800, 0xffff,   "-ve SINR"},
1028
    {0x8000, 0x8000,   "invalid measurement result"},
1029
    {0x0,    0xffff,   "reserved"},
1030
    {0, 0, NULL}
1031
};
1032
1033
1034
1035
/* Table 7.5.2.19-1 */
1036
static const value_string num_sinr_per_prb_vals[] = {
1037
    { 0,  "1" },
1038
    { 1,  "2" },
1039
    { 2,  "3" },
1040
    { 3,  "4" },
1041
    { 4,  "6" },
1042
    { 5,  "12" },
1043
    { 6,  "1 SINR value per section for DFT-s-OFDM" },
1044
    { 7,  "reserved" },
1045
    { 0, NULL}
1046
};
1047
1048
static const value_string meas_type_id_vals[] = {
1049
    { 1,  "UE Timing Advance Error" },
1050
    { 2,  "UE Layer power" },
1051
    { 3,  "UE frequency offset" },
1052
    { 4,  "Interference plus Noise for allocated PRBs" },
1053
    { 5,  "Interference plus Noise for unallocated PRBs" },
1054
    { 6,  "DMRS-SNR per antenna" },
1055
    { 7,  "UE positioning measurement report" },
1056
    { 8,  "UE radial speed measurement report" },
1057
    { 9,  "UE post-equalization MU inteference measurement" },
1058
    { 10, "UE TPMI and rank recommendation measurement" },
1059
    { 11, "UE layer pre-equalization SINR report" },
1060
    { 0, NULL}
1061
};
1062
1063
static const value_string beam_type_vals[] = {
1064
    { 0,  "List of beamId values" },
1065
    { 1,  "Range of beamId values" },
1066
    { 0, NULL}
1067
};
1068
1069
/* 7.7.24.3 */
1070
static const value_string entry_type_vals[] = {
1071
    { 0,  "inherit config from preceding entry (2 or 3) ueIdReset=0" },
1072
    { 1,  "inherit config from preceding entry (2 or 3) ueIdReset=1" },
1073
    { 2,  "related parameters if have transform precoding disabled " },
1074
    { 3,  "related parameters if have transform precoding enabled  " },
1075
    { 0, NULL}
1076
};
1077
1078
/* Table 7.7.29.3-1 */
1079
static const range_string cd_scg_size_vals[] = {
1080
    { 0, 0,  "1 subcarrier" },
1081
    { 1, 1,  "1 RB x N subcarriers" },
1082
    { 2, 2,  "2 RB x N subcarriers" },
1083
    { 3, 3,  "4 RB x N subcarriers" },
1084
    { 4, 4,  "8 RB x N subcarriers" },
1085
    { 5, 5,  "16 RB x N subcarriers" },
1086
    { 6, 6,  "32 RB x N subcarriers" },
1087
    { 7, 15, "reserved"},
1088
    { 0, 0, NULL}
1089
};
1090
1091
1092
/* Table 7.6.1-1 */
1093
static const value_string exttype_vals[] = {
1094
    {0,     "Reserved"},
1095
    {1,     "Beamforming weights"},
1096
    {2,     "Beamforming attributes"},
1097
    {3,     "DL Precoding configuration parameters and indications"},
1098
    {4,     "Modulation compr. params"},
1099
    {5,     "Modulation compression additional scaling parameters"},
1100
    {6,     "Non-contiguous PRB allocation"},
1101
    {7,     "Multiple-eAxC designation"},
1102
    {8,     "Regularization factor"},
1103
    {9,     "Dynamic Spectrum Sharing parameters"},
1104
    {10,    "Multiple ports grouping"},
1105
    {11,    "Flexible BF weights"},
1106
    {12,    "Non-Contiguous PRB Allocation with Frequency Ranges"},
1107
    {13,    "PRB Allocation with Frequency Hopping"},
1108
    {14,    "Nulling-layer Info. for ueId-based beamforming"},
1109
    {15,    "Mixed-numerology Info. for ueId-based beamforming"},
1110
    {16,    "Section description for antenna mapping in UE channel information based UL beamforming"},
1111
    {17,    "Section description for indication of user port group"},
1112
    {18,    "Section description for Uplink Transmission Management"},
1113
    {19,    "Compact beamforming information for multiple port"},
1114
    {20,    "Puncturing extension"},
1115
    {21,    "Variable PRB group size for channel information"},
1116
    {22,    "ACK/NACK request"},
1117
    {23,    "Multiple symbol modulation compression parameters"},
1118
    {24,    "PUSCH DMRS configuration"},
1119
    {25,    "Symbol reordering for DMRS-BF"},
1120
    {26,    "Frequency offset feedback"},
1121
    {27,    "O-DU controlled dimensionality reduction"},
1122
    {28,    "O-DU controlled frequency resolution for SINR reporting"},
1123
    {29,    "Cyclic delay adjustment"},
1124
    {30,    "PUSCH repetition indication"},
1125
    {31,    "MCS Information"},
1126
    {32,    "Rank and TPMI measurement request"},
1127
    {0, NULL}
1128
};
1129
static value_string_ext exttype_vals_ext = VALUE_STRING_EXT_INIT(exttype_vals);
1130
1131
1132
/**************************************************************************************/
1133
/* Keep track for each Section Extension, which section types are allowed to carry it */
1134
typedef struct {
1135
    bool ST0;
1136
    bool ST1;
1137
    bool ST3;
1138
    bool ST5;
1139
    bool ST6;
1140
    bool ST10;
1141
    bool ST11;
1142
} AllowedCTs_t;
1143
1144
1145
static const AllowedCTs_t ext_cts[HIGHEST_EXTTYPE] = {
1146
    /* ST0    ST1    ST3    ST5    ST6   ST10    ST11 */
1147
    { false, true,  true,  false, false, false, false},   // SE 1      (1,3)
1148
    { false, true,  true,  false, false, false, false},   // SE 2      (1,3)
1149
    { false, true,  true,  false, false, false, false},   // SE 3      (1,3)
1150
    { false, true,  true,  true,  false, false, false},   // SE 4      (1,3,5)
1151
    { false, true,  true,  true,  false, false, false},   // SE 5      (1,3,5)
1152
    { false, true,  true,  true,  false, true,  true },   // SE 6      (1,3,5,10,11)
1153
    { true,  false, false, false, false, false, false},   // SE 7      (0)
1154
    { false, false, false, true,  false, false, false},   // SE 8      (5)
1155
    { true,  true,  true,  true,  true,  true,  true },   // SE 9      (all)
1156
    { false, true,  true,  true,  false, false, false},   // SE 10     (1,3,5)
1157
    { false, true,  true,  false, false, false, false},   // SE 11     (1,3)
1158
    { false, true,  true,  true,  false, true,  true },   // SE 12     (1,3,5,10,11)
1159
    { false, true,  true,  true,  false, false, false},   // SE 13     (1,3,5)
1160
    { false, false, false, true,  false, false, false},   // SE 14     (5)
1161
    { false, false, false, true,  true,  false, false},   // SE 15     (5,6)
1162
    { false, false, false, true,  false, false, false},   // SE 16     (5)
1163
    { false, false, false, true,  false, false, false},   // SE 17     (5)
1164
    { false, true,  true,  true,  false, false, false},   // SE 18     (1,3,5)
1165
    { false, true,  true,  false, false, false, false},   // SE 19     (1,3)
1166
    { true,  true,  true,  true,  true,  true,  true },   // SE 20     (0,1,3,5,10,11)
1167
    { false, false, false, true,  true,  false, false},   // SE 21     (5,6)
1168
    { true,  true,  true,  true,  true,  true,  true },   // SE 22     (all)
1169
    { false, true,  true,  true,  false, false, false},   // SE 23     (1,3,5)
1170
    { false, false, false, true,  false, false, false},   // SE 24     (5)
1171
    { false, false, false, true,  false, false, false},   // SE 25     (5)
1172
    { false, false, false, true,  false, false, false},   // SE 26     (5)
1173
    { false, false, false, true,  false, false, false},   // SE 27     (5)
1174
    { false, false, false, true,  false, false, false},   // SE 28     (5)
1175
    { false, true,  true,  true,  false, false, false},   // SE 29     (1,3,5)
1176
    { false, false, false, true,  false, false, false},   // SE 30     (5)
1177
    { false, true,  true,  true,  false, false, false},   // SE 31     (1,3,5)
1178
    { false, false, false, true,  false, false, false},   // SE 32     (5)
1179
};
1180
1181
static bool se_allowed_in_st(unsigned se, unsigned st)
1182
2.71k
{
1183
2.71k
    if (se==0 || se>HIGHEST_EXTTYPE) {
1184
        /* Don't know about new SE, so don't complain.. */
1185
908
        return true;
1186
908
    }
1187
1188
1.81k
    switch (st) {
1189
417
        case 0:
1190
417
            return ext_cts[se-1].ST0;
1191
234
        case 1:
1192
234
            return ext_cts[se-1].ST1;
1193
241
        case 3:
1194
241
            return ext_cts[se-1].ST3;
1195
78
        case 5:
1196
78
            return ext_cts[se-1].ST5;
1197
6
        case 6:
1198
6
            return ext_cts[se-1].ST6;
1199
670
        case 10:
1200
670
            return ext_cts[se-1].ST10;
1201
164
        case 11:
1202
164
            return ext_cts[se-1].ST11;
1203
0
        default:
1204
            /* New/unknown section type that includes 'ef'.. assume ok */
1205
0
            return true;
1206
1.81k
    }
1207
1.81k
}
1208
1209
/************************************************************************************/
1210
1211
/* Table 7.7.1.2-2 */
1212
static const value_string bfw_comp_headers_iq_width[] = {
1213
    {0,     "I and Q are 16 bits wide"},
1214
    {1,     "I and Q are 1 bit wide"},
1215
    {2,     "I and Q are 2 bits wide"},
1216
    {3,     "I and Q are 3 bits wide"},
1217
    {4,     "I and Q are 4 bits wide"},
1218
    {5,     "I and Q are 5 bits wide"},
1219
    {6,     "I and Q are 6 bits wide"},
1220
    {7,     "I and Q are 7 bits wide"},
1221
    {8,     "I and Q are 8 bits wide"},
1222
    {9,     "I and Q are 9 bits wide"},
1223
    {10,    "I and Q are 10 bits wide"},
1224
    {11,    "I and Q are 11 bits wide"},
1225
    {12,    "I and Q are 12 bits wide"},
1226
    {13,    "I and Q are 13 bits wide"},
1227
    {14,    "I and Q are 14 bits wide"},
1228
    {15,    "I and Q are 15 bits wide"},
1229
    {0, NULL}
1230
};
1231
1232
/* Table 7.7.1.2-3 */
1233
static const value_string bfw_comp_headers_comp_meth[] = {
1234
    {COMP_NONE,         "no compression"},
1235
    {COMP_BLOCK_FP,     "block floating point"},
1236
    {COMP_BLOCK_SCALE,  "block scaling"},
1237
    {COMP_U_LAW,        "u-law"},
1238
    {4,                 "beamspace compression type I"},
1239
    {5,                 "beamspace compression type II"},
1240
    {0, NULL}
1241
};
1242
1243
/* 7.7.6.2 rbgSize (resource block group size) */
1244
static const value_string rbg_size_vals[] = {
1245
    {0,     "reserved"},
1246
    {1,     "1"},
1247
    {2,     "2"},
1248
    {3,     "3"},
1249
    {4,     "4"},
1250
    {5,     "6"},
1251
    {6,     "8"},
1252
    {7,     "16"},
1253
    {0, NULL}
1254
};
1255
1256
/* 7.7.6.5 */
1257
static const value_string priority_vals[] = {
1258
    {0,     "0"},
1259
    {1,     "+1"},
1260
    {2,     "-2 (reserved, should not be used)"},
1261
    {3,     "-1"},
1262
    {0, NULL}
1263
};
1264
1265
/* 7.7.10.2  beamGroupType */
1266
static const value_string beam_group_type_vals[] = {
1267
    {0x0, "common beam"},
1268
    {0x1, "beam matrix indication"},
1269
    {0x2, "beam vector listing"},
1270
    {0x3, "beamId/ueId listing with associated port-list index"},
1271
    {0, NULL}
1272
};
1273
1274
/* 7.7.9.2 technology (interface name) */
1275
static const value_string interface_name_vals[] = {
1276
    {0x0, "LTE"},
1277
    {0x1, "NR"},
1278
    {0, NULL}
1279
};
1280
1281
/* 7.7.18.4 toT (type of transmission) */
1282
static const value_string type_of_transmission_vals[] = {
1283
    {0x0, "normal transmission mode, data can be distributed in any way the O-RU is implemented to transmit data"},
1284
    {0x1, "uniformly distributed over the transmission window"},
1285
    {0x2, "Reserved"},
1286
    {0x3, "Reserved"},
1287
    {0, NULL}
1288
};
1289
1290
/* 7.7.2.2 (width of bfa parameters) */
1291
static const value_string bfa_bw_vals[] = {
1292
    {0,   "no bits, the field is not applicable (e.g., O-RU does not support it) or the default value shall be used"},
1293
    {1,   "2-bit bitwidth"},
1294
    {2,   "3-bit bitwidth"},
1295
    {3,   "4-bit bitwidth"},
1296
    {4,   "5-bit bitwidth"},
1297
    {5,   "6-bit bitwidth"},
1298
    {6,   "7-bit bitwidth"},
1299
    {7,   "8-bit bitwidth"},
1300
    {0,   NULL}
1301
};
1302
1303
/* 7.7.2.7 & 7.7.2.8 */
1304
static const value_string sidelobe_suppression_vals[] = {
1305
    {0,   "10 dB"},
1306
    {1,   "15 dB"},
1307
    {2,   "20 dB"},
1308
    {3,   "25 dB"},
1309
    {4,   "30 dB"},
1310
    {5,   "35 dB"},
1311
    {6,   "40 dB"},
1312
    {7,   ">= 45 dB"},
1313
    {0,   NULL}
1314
};
1315
1316
static const value_string lbtTrafficClass_vals[] = {
1317
    {1,   "Priority 1"},
1318
    {2,   "Priority 2"},
1319
    {3,   "Priority 3"},
1320
    {4,   "Priority 4"},
1321
    {0,   NULL}
1322
};
1323
1324
/* 7.5.3.22 */
1325
static const value_string lbtPdschRes_vals[] = {
1326
    {0,   "not sensing – indicates that the O-RU is transmitting data"},
1327
    {1,   "currently sensing – indicates the O-RU has not yet acquired the channel"},
1328
    {2,   "success – indicates that the channel was successfully acquired"},
1329
    {3,   "Failure – indicates expiration of the LBT timer. The LBT process should be reset"},
1330
    {0,   NULL}
1331
};
1332
1333
/* Table 7.5.2.15-3 */
1334
static const value_string ci_comp_opt_vals[] = {
1335
    {0,   "compression per UE, one ciCompParam exists before the I/Q value of each UE"},
1336
    {1,   "compression per PRB, one ciCompParam exists before the I/Q value of each PRB"},
1337
    {0,   NULL}
1338
};
1339
1340
/* 7.5.2.17 */
1341
static const range_string cmd_scope_vals[] = {
1342
    {0, 0,  "ARRAY-COMMAND"},
1343
    {1, 1,  "CARRIER-COMMAND"},
1344
    {2, 2,  "O-RU-COMMAND"},
1345
    {3, 15, "reserved"},
1346
    {0, 0,  NULL}
1347
};
1348
1349
/* N.B., table in 7.5.3.38 is truncated.. */
1350
static const range_string st4_cmd_type_vals[] = {
1351
    {0, 0,   "reserved for future command types"},
1352
    {1, 1,   "TIME_DOMAIN_BEAM_CONFIG"},
1353
    {2, 2,   "TDD_CONFIG_PATTERN"},
1354
    {3, 3,   "TRX_CONTROL"},
1355
    {4, 4,   "ASM"},
1356
    {5, 5,   "TRX_CONTROL_BIDIR"},
1357
    {6, 255, "reserved for future command types"},
1358
    {0, 0,   NULL}
1359
};
1360
1361
/* Table 7.5.3.51-1 */
1362
static const value_string log2maskbits_vals[] = {
1363
    {0,  "reserved"},
1364
    {1,  "min antMask size is 16 bits.."},
1365
    {2,  "min antMask size is 16 bits.."},
1366
    {3,  "min antMask size is 16 bits.."},
1367
    {4,  "16 bits"},
1368
    {5,  "32 bits"},
1369
    {6,  "64 bits"},
1370
    {7,  "128 bits"},
1371
    {8,  "256 bits"},
1372
    {9,  "512 bits"},
1373
    {10, "1024 bits"},
1374
    {11, "2048 bits"},
1375
    {12, "4096 bits"},
1376
    {13, "8192 bits"},
1377
    {14, "16384 bits"},
1378
    {15, "reserved"},
1379
    {0,  NULL}
1380
};
1381
1382
/* Table 16.1-1 Sleep modes */
1383
static const value_string sleep_mode_trx_vals[] = {
1384
    { 0, "TRXC-mode0-wake-up-duration (symbol)"},
1385
    { 1, "TRXC-mode1-wake-up-duration (L)"},
1386
    { 2, "TRXC-mode2-wake-up-duration (M)"},
1387
    { 3, "TRXC-mode3-wake-up-duration (N)"},
1388
    { 0, NULL}
1389
};
1390
1391
static const value_string sleep_mode_asm_vals[] = {
1392
    { 0, "ASM-mode0-wake-up-duration (symbol)"},
1393
    { 1, "ASM-mode1-wake-up-duration (L)"},
1394
    { 2, "ASM-mode2-wake-up-duration (M)"},
1395
    { 3, "ASM-mode3-wake-up-duration (N)"},
1396
    { 0, NULL}
1397
};
1398
1399
/* 7.7.21.3.1 */
1400
static const value_string prg_size_st5_vals[] = {
1401
    { 0, "reserved"},
1402
    { 1, "Precoding resource block group size as WIDEBAND"},
1403
    { 2, "Precoding resource block group size 2"},
1404
    { 3, "Precoding resource block group size 4"},
1405
    { 0, NULL}
1406
};
1407
1408
/* 7.7.21.3.2 */
1409
static const value_string prg_size_st6_vals[] = {
1410
    { 0, "if ciPrbGroupSize is 2 or 4, then ciPrbGroupSize, else WIDEBAND"},
1411
    { 1, "Precoding resource block group size as WIDEBAND"},
1412
    { 2, "Precoding resource block group size 2"},
1413
    { 3, "Precoding resource block group size 4"},
1414
    { 0, NULL}
1415
};
1416
1417
/* 7.7.24.4 */
1418
static const value_string alpn_per_sym_vals[] = {
1419
    { 0, "report one allocated IPN value per all allocated symbols with DMRS"},
1420
    { 1, "report one allocated IPN value per group of consecutive DMRS symbols"},
1421
    { 0, NULL}
1422
};
1423
1424
/* 7.7.24.5 */
1425
static const value_string ant_dmrs_snr_vals[] = {
1426
    { 0, "O-RU shall not report the MEAS_ANT_DMRS_SNR"},
1427
    { 1, "O-RU shall report the MEAS_ANT_DMRS_SNR"},
1428
    { 0, NULL}
1429
};
1430
1431
/* 7.7.24.14 */
1432
static const value_string dtype_vals[] = {
1433
    { 0, "assume DMRS configuration type 1"},
1434
    { 1, "assume DMRS configuration type 2"},
1435
    { 0, NULL}
1436
};
1437
1438
/* 7.7.24.17 */
1439
static const value_string papr_type_vals[] = {
1440
    { 0, "sequence generator type 1 for short sequence lengths"},
1441
    { 1, "sequence generator type 1 for long sequence lengths"},
1442
    { 2, "sequence generator type 2 for short sequence lengths"},
1443
    { 3, "sequence generator type 2 for long sequence lengths"},
1444
    { 0, NULL}
1445
};
1446
1447
/* 7.7.24.18 */
1448
static const value_string hopping_mode_vals[] = {
1449
    { 0, "neither group, nor sequence hopping is enabled"},
1450
    { 1, "group hopping is enabled and sequence hopping is disabled"},
1451
    { 2, "sequence hopping is enabled and group hopping is disabled"},
1452
    { 3, "reserved"},
1453
    { 0, NULL}
1454
};
1455
1456
/* Table 7.7.31.2-1 */
1457
static const value_string mcs_table_vals[] = {
1458
    { 0,  "MCS index table 1 for PDSCH and PUSCH without transform precoding" },
1459
    { 1,  "MCS index table 2 for PDSCH and PUSCH without transform precoding" },
1460
    { 2,  "MCS index table 3 for PDSCH and PUSCH without transform precoding" },
1461
    { 3,  "MCS index table 4 for PDSCH" },
1462
    { 4,  "MCS index table for PUSCH with transform precoding and 64QAM" },
1463
    { 5,  "MCS index table 2 for PUSCH with transform precoding and 64QAM" },
1464
    { 0, NULL}
1465
};
1466
1467
/* 7.7.32.9 */
1468
static const value_string full_pwr_mode_vals[] = {
1469
    { 0, "not configured"},
1470
    { 1, "full power mode 0"},
1471
    { 2, "full power mode 1"},
1472
    { 3, "full power mode 2"},
1473
    { 0, NULL}
1474
};
1475
1476
1477
static const true_false_string tfs_sfStatus =
1478
{
1479
    "subframe was transmitted",
1480
    "subframe was dropped"
1481
};
1482
1483
static const true_false_string tfs_lbtBufErr =
1484
{
1485
    "buffer overflow – data received at O-RU is larger than the available buffer size",
1486
    "reserved"
1487
};
1488
1489
static const true_false_string tfs_partial_full_sf = {
1490
    "partial SF",
1491
    "full SF"
1492
};
1493
1494
static const true_false_string disable_tdbfns_tfs = {
1495
    "beam numbers excluded",
1496
    "beam numbers included"
1497
};
1498
1499
static const true_false_string continuity_indication_tfs = {
1500
    "continuity between current and next bundle",
1501
    "discontinuity between current and next bundle"
1502
};
1503
1504
static const true_false_string prb_mode_tfs = {
1505
    "PRB-BLOCK mode",
1506
    "PRB-MASK mode"
1507
};
1508
1509
static const true_false_string symbol_direction_tfs = {
1510
    "DL symbol",
1511
    "UL symbol"
1512
};
1513
1514
static const true_false_string symbol_guard_tfs = {
1515
    "guard symbol",
1516
    "non-guard symbol"
1517
};
1518
1519
static const true_false_string beam_numbers_included_tfs = {
1520
    "time-domain beam numbers excluded in this command",
1521
    "time-domain beam numbers included in this command"
1522
};
1523
1524
static const true_false_string measurement_flag_tfs = {
1525
    "at least one additional measurement report or command after the current one",
1526
    "no additional measurement report or command"
1527
};
1528
1529
static const true_false_string repetition_se6_tfs = {
1530
    "repeated highest priority data section in the C-Plane message",
1531
    "no repetition"
1532
};
1533
1534
static const true_false_string repetition_se19_tfs = {
1535
    "per port information not present in the extension",
1536
    "per port info present in the extension"
1537
};
1538
1539
static const true_false_string tfs_report_no_report_pos_meas =
1540
{
1541
    "Report MEAS_UE_POS for UE",
1542
    "Do not report UE_POS for UE"
1543
};
1544
1545
static const true_false_string tfs_allocated_not_allocated =
1546
{
1547
    "allocated",
1548
    "not allocated"
1549
};
1550
1551
1552
1553
/* Forward declaration */
1554
static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
1555
                               unsigned comp_meth,
1556
                               uint32_t *exponent, uint16_t *sReSMask, bool for_sinr);
1557
1558
1559
static const true_false_string ready_tfs = {
1560
    "message is a \"ready\" message",
1561
    "message is a ACK message"
1562
};
1563
1564
static const true_false_string multi_sd_scope_tfs = {
1565
    "Puncturing pattern applies to current and following sections",
1566
    "Puncturing pattern applies to current section"
1567
};
1568
1569
static const true_false_string tfs_ueid_reset = {
1570
    "cannot assume same UE as in preceding slot",
1571
    "can assume same UE as in preceding slot"
1572
};
1573
1574
1575
typedef struct {
1576
    uint32_t start;      /* first prb of bundle */
1577
    uint32_t end;        /* last prb of bundle*/
1578
    bool     is_orphan;  /* true if not complete (i.e., end-start < numBundPrb) */
1579
    uint8_t  bit_from_rbg_mask; /* 0 means not set, other bits offset by 1 */
1580
} bundle_t;
1581
1582
1583
/* Config for (and later, worked-out allocations) bundles for ext11 (dynamic BFW) */
1584
typedef struct {
1585
    /* Ext 6 config */
1586
    bool     ext6_set;
1587
    uint8_t  ext6_rbg_size;      /* number of PRBs in resource block group (i.e., one bit in bitmask) */
1588
1589
    uint8_t  ext6_num_bits_set;  /* Total number of rbgMask bits set */
1590
    uint8_t  ext6_bits_set[28];  /* Which bit position this entry has */
1591
    /* TODO: store an f value for each bit position? */
1592
1593
    /* Ext 12 config */
1594
    bool     ext12_set;
1595
    unsigned ext12_num_pairs;
1596
8.39k
#define MAX_BFW_EXT12_PAIRS 128
1597
    struct {
1598
        uint8_t off_start_prb;
1599
        uint8_t num_prb;
1600
    } ext12_pairs[MAX_BFW_EXT12_PAIRS];
1601
1602
    /* Ext 13 config */
1603
    bool     ext13_set;
1604
    unsigned ext13_num_start_prbs;
1605
4.69k
#define MAX_BFW_EXT13_ALLOCATIONS 128
1606
    unsigned ext13_start_prbs[MAX_BFW_EXT13_ALLOCATIONS];
1607
    /* TODO: store nextSymbolId here too? */
1608
1609
    /* Ext 21 config */
1610
    bool     ext21_set;
1611
    uint8_t  ext21_ci_prb_group_size;
1612
1613
    /* Results/settings (after calling ext11_work_out_bundles()) */
1614
    uint32_t num_bundles;
1615
4.15k
#define MAX_BFW_BUNDLES 512
1616
    bundle_t bundles[MAX_BFW_BUNDLES];
1617
} ext11_settings_t;
1618
1619
1620
/* Work out bundle allocation for ext 11.  Take into account ext6/ext21, ext12 or ext13 in this section before ext 11. */
1621
/* Won't be called with numBundPrb=0 */
1622
static void ext11_work_out_bundles(unsigned startPrbc,
1623
                                   unsigned numPrbc,
1624
                                   unsigned numBundPrb,             /* number of PRBs per (full) bundle */
1625
                                   ext11_settings_t *settings)
1626
140
{
1627
    /* Allocation configured by ext 6 */
1628
140
    if (settings->ext6_set) {
1629
4
        unsigned bundles_per_mask_bit = (settings->ext6_rbg_size / numBundPrb);
1630
1631
        /* Need to cope with these not dividing exactly, or even having more PRbs in a bundle that
1632
           rbg size.  i.e. each bundle gets the correct number of PRBs until
1633
           all rbg entries are consumed... */
1634
1635
        /* TODO: need to check 7.9.4.2.  Different cases depending upon value of RAD */
1636
1637
4
        if (bundles_per_mask_bit == 0) {
1638
2
            bundles_per_mask_bit = 1;
1639
2
        }
1640
1641
        /* Ext6 behaviour may also be affected by ext 21 */
1642
4
        if (settings->ext21_set) {
1643
            /* N.B., have already checked that numPrbc is not 0 */
1644
1645
            /* ciPrbGroupSize overrides number of contiguous PRBs in group */
1646
0
            bundles_per_mask_bit = (settings->ext6_rbg_size / settings->ext21_ci_prb_group_size);
1647
1648
            /* numPrbc is the number of PRB groups per antenna - handled in call to dissect_bfw_bundle() */
1649
0
        }
1650
1651
4
        unsigned bundles_set = 0;
1652
4
        bool reached_orphan = false;
1653
1654
        /* For each bit set in ext6 rbg mask.. */
1655
4
        for (unsigned n=0;
1656
4
             !reached_orphan && n < 28 && n < (settings->ext6_num_bits_set * settings->ext6_rbg_size) / numBundPrb;
1657
4
             n++) {
1658
1659
            /* For each bundle... */
1660
1661
            /* TODO: Work out where first PRB is */
1662
            /* May not be the start of an rbg block... */
1663
2
            uint32_t prb_start = (settings->ext6_bits_set[n] * settings->ext6_rbg_size);
1664
1665
            /* For each bundle within identified rbgSize block */
1666
2
            for (unsigned m=0; !reached_orphan && m < bundles_per_mask_bit; m++) {
1667
1668
2
                settings->bundles[bundles_set].start = startPrbc+prb_start+(m*numBundPrb);
1669
1670
                /* Start already beyond end, so doesn't count. */
1671
2
                if (settings->bundles[bundles_set].start > (startPrbc+numPrbc-1)) {
1672
2
                    settings->num_bundles = bundles_set;
1673
2
                    return;
1674
2
                }
1675
1676
                /* Bundle consists of numBundPrb bundles */
1677
                /* TODO: may involve PRBs from >1 rbg blocks.. */
1678
0
                settings->bundles[bundles_set].end = startPrbc+prb_start+((m+1)*numBundPrb)-1;
1679
0
                if (settings->bundles[bundles_set].end > (startPrbc+numPrbc-1)) {
1680
                    /* Extends beyond end, so counts but is an orphan bundle */
1681
0
                    settings->bundles[bundles_set].end = startPrbc+numPrbc-1;
1682
0
                    settings->bundles[bundles_set].is_orphan = true;
1683
0
                    reached_orphan = true;
1684
0
                }
1685
1686
                /* Record which rbg this bundle comes from (+1) */
1687
0
                settings->bundles[bundles_set].bit_from_rbg_mask = settings->ext6_bits_set[n]+1;
1688
1689
                /* Get out if have reached array bound */
1690
0
                if (++bundles_set == MAX_BFW_BUNDLES) {
1691
0
                    return;
1692
0
                }
1693
0
            }
1694
2
        }
1695
2
        settings->num_bundles = bundles_set;
1696
2
    }
1697
1698
    /* Allocation configured by ext 12 */
1699
136
    else if (settings->ext12_set) {
1700
        /* First, allocate normally from startPrbc, numPrbc */
1701
6
        settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1702
1703
        /* Don't overflow settings->bundles[] ! */
1704
6
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1705
1706
73
        for (uint32_t n=0; n < settings->num_bundles; n++) {
1707
67
            settings->bundles[n].start = startPrbc + n*numBundPrb;
1708
67
            settings->bundles[n].end =   settings->bundles[n].start + numBundPrb-1;
1709
            /* Does it go beyond the end? */
1710
67
            if (settings->bundles[n].end > startPrbc+numPrbc) {
1711
5
                settings->bundles[n].end = startPrbc+numPrbc;
1712
5
                settings->bundles[n].is_orphan = true;
1713
5
            }
1714
67
        }
1715
6
        if (settings->num_bundles == MAX_BFW_BUNDLES) {
1716
0
            return;
1717
0
        }
1718
1719
6
        unsigned prb_offset = startPrbc + numPrbc;
1720
1721
        /* Loop over pairs, adding bundles for each */
1722
596
        for (unsigned p=0; p < settings->ext12_num_pairs; p++) {
1723
592
            prb_offset += settings->ext12_pairs[p].off_start_prb;
1724
592
            unsigned pair_bundles = (settings->ext12_pairs[p].num_prb+numBundPrb-1) / numBundPrb;
1725
1726
2.41k
            for (uint32_t n=0; n < pair_bundles; n++) {
1727
1.82k
                unsigned idx = settings->num_bundles;
1728
1729
1.82k
                settings->bundles[idx].start = prb_offset + n*numBundPrb;
1730
1.82k
                settings->bundles[idx].end =   settings->bundles[idx].start + numBundPrb-1;
1731
                /* Does it go beyond the end? */
1732
1.82k
                if (settings->bundles[idx].end > prb_offset + settings->ext12_pairs[p].num_prb) {
1733
351
                    settings->bundles[idx].end = prb_offset + settings->ext12_pairs[p].num_prb;
1734
351
                    settings->bundles[idx].is_orphan = true;
1735
351
                }
1736
                /* Range check / return */
1737
1.82k
                settings->num_bundles++;
1738
1.82k
                if (settings->num_bundles == MAX_BFW_BUNDLES) {
1739
2
                    return;
1740
2
                }
1741
1.82k
            }
1742
1743
590
            prb_offset += settings->ext12_pairs[p].num_prb;
1744
590
        }
1745
6
    }
1746
1747
    /* Allocation configured by ext 13 */
1748
130
    else if (settings->ext13_set) {
1749
11
        unsigned alloc_size = (numPrbc+numBundPrb-1) / numBundPrb;
1750
11
        settings->num_bundles = alloc_size * settings->ext13_num_start_prbs;
1751
1752
        /* Don't overflow settings->bundles[] ! */
1753
11
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1754
1755
445
        for (unsigned alloc=0; alloc < settings->ext13_num_start_prbs; alloc++) {
1756
437
            unsigned alloc_start = alloc * alloc_size;
1757
2.75k
            for (uint32_t n=0; n < alloc_size; n++) {
1758
2.31k
                if ((alloc_start+n) >= MAX_BFW_BUNDLES) {
1759
                    /* ERROR */
1760
3
                    return;
1761
3
                }
1762
2.31k
                settings->bundles[alloc_start+n].start = settings->ext13_start_prbs[alloc] + startPrbc + n*numBundPrb;
1763
2.31k
                settings->bundles[alloc_start+n].end =   settings->bundles[alloc_start+n].start + numBundPrb-1;
1764
2.31k
                if (settings->bundles[alloc_start+n].end > settings->ext13_start_prbs[alloc] + numPrbc) {
1765
1.40k
                    settings->bundles[alloc_start+n].end = settings->ext13_start_prbs[alloc] + numPrbc;
1766
1.40k
                    settings->bundles[alloc_start+n].is_orphan = true;
1767
1.40k
                }
1768
2.31k
            }
1769
437
        }
1770
11
    }
1771
1772
    /* Case where bundles are not controlled by other extensions - just divide up range into bundles we have */
1773
119
    else {
1774
119
        settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;   /* rounded up */
1775
1776
        /* Don't overflow settings->bundles[] */
1777
119
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1778
1779
        /* For each bundle.. */
1780
5.11k
        for (uint32_t n=0; n < settings->num_bundles; n++) {
1781
            /* Allocate start and end */
1782
4.99k
            settings->bundles[n].start = startPrbc + n*numBundPrb;
1783
4.99k
            settings->bundles[n].end =   settings->bundles[n].start + numBundPrb - 1;
1784
            /* If would go beyond end of PRBs, limit and identify as orphan */
1785
4.99k
            if (settings->bundles[n].end > startPrbc+numPrbc) {
1786
72
                settings->bundles[n].end = startPrbc+numPrbc;
1787
72
                settings->bundles[n].is_orphan = true;
1788
72
            }
1789
4.99k
        }
1790
119
    }
1791
140
}
1792
1793
1794
/* Modulation Compression configuration */
1795
typedef struct  {
1796
    /* Application of each entry is filtered by RE.
1797
     * TODO: should also be filtered by PRB + symbol... */
1798
    uint16_t mod_compr_re_mask;
1799
1800
    /* Settings to apply */
1801
    bool     mod_compr_csf;
1802
    float    mod_compr_scaler;
1803
} mod_compr_config_t;
1804
1805
/* Multiple configs with a section */
1806
typedef struct {
1807
    uint16_t section_id;
1808
    uint32_t num_configs;
1809
1810
2.07k
    #define MAX_MOD_COMPR_CONFIGS 12
1811
    mod_compr_config_t configs[MAX_MOD_COMPR_CONFIGS];
1812
} section_mod_compr_config_t;
1813
1814
/* Flow has separate configs for each section */
1815
typedef struct {
1816
    uint16_t num_sections;
1817
1818
    /* Separate config for each section */
1819
    section_mod_compr_config_t sections[MAX_SECTION_IDs];
1820
} mod_compr_params_t;
1821
1822
1823
typedef struct {
1824
    uint32_t frame_number;
1825
    nstime_t frame_time;
1826
1827
    /* Timing to match */
1828
    uint8_t frame;
1829
    uint8_t subframe;
1830
    uint8_t slot;
1831
    uint8_t startSymbol;
1832
1833
    bool     in_use;
1834
    uint16_t startPrb;
1835
    uint16_t numPrb;
1836
    uint16_t numSymbols;
1837
    uint16_t beamIds[273];
1838
} section_details_t;
1839
1840
typedef struct {
1841
    uint16_t sectionId;
1842
    /* For the same sectionId, can have 2 currently active entries.. */
1843
    section_details_t details[2];
1844
} expected_section_data_t;
1845
1846
1847
/*******************************************************/
1848
/* Overall state of a flow (eAxC/plane)                */
1849
typedef struct {
1850
    /* State for sequence analysis [each direction] */
1851
    bool     last_frame_seen[2];
1852
    uint32_t last_frame[2];
1853
    uint8_t  next_expected_sequence_number[2];
1854
1855
    /* expected frames.  sectionId -> expected_section_data_t* */
1856
    wmem_tree_t *expected_sections[2];  /* [direction] */
1857
1858
    /* Table recording ackNack requests (ackNackId -> ack_nack_request_t*)
1859
       Note that this assumes that the same ackNackId will not be reused within a state,
1860
       which may well not be valid */
1861
    wmem_tree_t *ack_nack_requests;
1862
1863
    /* Store udCompHdr seen in C-Plane for UL - can be looked up and used by U-PLane.
1864
       Note that this appears in the common section header parts of ST1, ST3, ST5,
1865
       so can still be over-written per sectionId in the U-Plane */
1866
    unsigned ul_ud_comp_hdr_frame;
1867
    bool     ul_ud_comp_hdr_set;
1868
    unsigned ul_ud_comp_hdr_bit_width;
1869
    int      ul_ud_comp_hdr_compression;
1870
1871
    bool udcomphdrDownlink_heuristic_result_set;
1872
    bool udcomphdrDownlink_heuristic_result;
1873
    bool udcomphdrUplink_heuristic_result_set;
1874
    bool udcomphdrUplink_heuristic_result;
1875
1876
    /* Modulation compression params */
1877
    mod_compr_params_t mod_comp_params;
1878
} flow_state_t;
1879
1880
static section_mod_compr_config_t* get_mod_compr_section_to_write(flow_state_t *flow,
1881
                                                           unsigned sectionId)
1882
2.07k
{
1883
2.07k
    if (flow == NULL) {
1884
0
        return NULL;
1885
0
    }
1886
1887
    /* Look for this section among existing entries */
1888
3.55k
    for (unsigned s=0; s < flow->mod_comp_params.num_sections; s++) {
1889
3.45k
        if (flow->mod_comp_params.sections[s].section_id == sectionId) {
1890
1.97k
            return &flow->mod_comp_params.sections[s];
1891
1.97k
        }
1892
3.45k
    }
1893
1894
    /* Not found, so try to add a new one */
1895
100
    if (flow->mod_comp_params.num_sections >= MAX_SECTION_IDs) {
1896
        /* Can't allocate one! */
1897
0
        return NULL;
1898
0
    }
1899
100
    else {
1900
100
        flow->mod_comp_params.sections[flow->mod_comp_params.num_sections].section_id = sectionId;
1901
100
        return &flow->mod_comp_params.sections[flow->mod_comp_params.num_sections++];
1902
100
    }
1903
100
}
1904
1905
static section_mod_compr_config_t* get_mod_compr_section_to_read(flow_state_t *flow,
1906
                                                           unsigned sectionId)
1907
1.08k
{
1908
1.08k
    if (flow == NULL) {
1909
1.07k
        return NULL;
1910
1.07k
    }
1911
1912
    /* Look for this section among existing entries */
1913
13
    for (unsigned s=0; s < flow->mod_comp_params.num_sections; s++) {
1914
3
        if (flow->mod_comp_params.sections[s].section_id == sectionId) {
1915
1
            return &flow->mod_comp_params.sections[s];
1916
1
        }
1917
3
    }
1918
1919
    /* Not found */
1920
10
    return NULL;
1921
11
}
1922
1923
1924
1925
typedef struct {
1926
    uint32_t request_frame_number;
1927
    nstime_t request_frame_time;
1928
    enum {
1929
        SE22,
1930
        ST4Cmd1,
1931
        ST4Cmd2,
1932
        ST4Cmd3,
1933
        ST4Cmd4
1934
    } requestType;
1935
1936
    uint32_t response_frame_number;
1937
    nstime_t response_frame_time;
1938
} ack_nack_request_t;
1939
1940
static const value_string acknack_type_vals[] = {
1941
    { SE22,    "SE 22" },
1942
    { ST4Cmd1, "ST4 (TIME_DOMAIN_BEAM_CONFIG)" },
1943
    { ST4Cmd2, "ST4 (TDD_CONFIG_PATTERN)" },
1944
    { ST4Cmd3, "ST4 (TRX_CONTROL)" },
1945
    { ST4Cmd4, "ST4 (ASM)" },
1946
    { 0, NULL}
1947
};
1948
1949
6.05k
#define ORAN_C_PLANE 0
1950
437
#define ORAN_U_PLANE 1
1951
1952
1953
1954
/* Table maintained on first pass from flow_key(uint32_t) -> flow_state_t* */
1955
static wmem_tree_t *flow_states_table;
1956
1957
1958
/* Includes transport details (eth addresses + vlan) */
1959
static flow_state_t* lookup_flow(packet_info *pinfo, uint16_t eaxc_id, uint8_t plane, bool opposite_dir)
1960
2.10k
{
1961
2.10k
    wmem_tree_key_t key[3];
1962
2.10k
    uint32_t word1, word2 = 0;
1963
1964
    /* 1st value is vlan_id(15) | plane(1) | eaxc_id(16) */
1965
2.10k
    word1 = eaxc_id | (plane << 16) | (pinfo->vlan_id << 17);
1966
2.10k
    key[0].length = 1;
1967
2.10k
    key[0].key = &word1;
1968
1969
    /* 2nd word is first/last bytes of eth src/dst */
1970
2.10k
    const uint8_t *src_eth = (uint8_t*)pinfo->dl_src.data;
1971
2.10k
    const uint8_t *dst_eth = (uint8_t*)pinfo->dl_dst.data;
1972
1973
2.10k
    if (!opposite_dir) {
1974
2.05k
        if (src_eth) {
1975
1.39k
            word2 |= src_eth[5] | (src_eth[0] << 8);
1976
1.39k
        }
1977
2.05k
        if (dst_eth) {
1978
1.39k
            word2 |= (dst_eth[5] << 16) | (dst_eth[0] << 24);
1979
1.39k
        }
1980
2.05k
    }
1981
41
    else {
1982
41
        if (src_eth) {
1983
22
            word2 |= (src_eth[5] << 16) | (src_eth[0] << 24);
1984
22
        }
1985
41
        if (dst_eth) {
1986
22
            word2 |= dst_eth[5] | (dst_eth[0] << 8);
1987
22
        }
1988
41
    }
1989
2.10k
    key[1].length = 1;
1990
2.10k
    key[1].key = &word2;
1991
2.10k
    key[2].length = 0;
1992
2.10k
    key[2].key = NULL;
1993
1994
2.10k
    return (flow_state_t*)wmem_tree_lookup32_array(flow_states_table, key);
1995
2.10k
}
1996
1997
static void store_flow(packet_info *pinfo, uint16_t eaxc_id, uint8_t plane, bool opposite_dir, flow_state_t *state)
1998
503
{
1999
503
    wmem_tree_key_t key[3];
2000
503
    uint32_t word1, word2 = 0;
2001
2002
    /* 1st value is vlan_id(15) | plane(1) | eaxc_id(16) */
2003
503
    word1 = eaxc_id | (plane << 16) | (pinfo->vlan_id << 17);
2004
503
    key[0].length = 1;
2005
503
    key[0].key = &word1;
2006
2007
    /* 2nd word is first/last bytes of eth src/dst */
2008
503
    const uint8_t *src_eth = (uint8_t*)pinfo->dl_src.data;
2009
503
    const uint8_t *dst_eth = (uint8_t*)pinfo->dl_dst.data;
2010
2011
503
    if (!opposite_dir) {
2012
503
        if (src_eth) {
2013
369
            word2 |= src_eth[5] | (src_eth[0] << 8);
2014
369
        }
2015
503
        if (dst_eth) {
2016
369
            word2 |= (dst_eth[5] << 16) | (dst_eth[0] << 24);
2017
369
        }
2018
503
    }
2019
0
    else {
2020
0
        if (src_eth) {
2021
0
            word2 |= (src_eth[5] << 16) | (src_eth[0] << 24);
2022
0
        }
2023
0
        if (dst_eth) {
2024
0
            word2 |= dst_eth[5] | (dst_eth[0] << 8);
2025
0
        }
2026
0
    }
2027
503
    key[1].length = 1;
2028
503
    key[1].key = &word2;
2029
503
    key[2].length = 0;
2030
503
    key[2].key = NULL;
2031
2032
503
    wmem_tree_insert32_array(flow_states_table, key, state);
2033
503
}
2034
2035
2036
2037
2038
typedef struct {
2039
    uint32_t frame_number;
2040
    uint16_t sectionId;
2041
    uint32_t gap_in_usecs;
2042
    uint8_t symbol;
2043
    uint16_t startPrbu;
2044
    uint16_t numPrbu;
2045
} corresponding_uplane_frame;
2046
2047
/* Table consulted on subsequent passes: frame_num -> flow_result_t* */
2048
static wmem_tree_t *flow_results_table;
2049
2050
typedef struct {
2051
    /* Sequence analysis */
2052
    bool     unexpected_seq_number;
2053
    uint8_t  expected_sequence_number;
2054
    uint32_t previous_frame;
2055
2056
    /* sectionId -> expected_section_data_t*   */
2057
    /* Frame only covers one direction */
2058
    wmem_tree_t *expected_sections;
2059
2060
    /* List of u-plane frames (corresponding_uplane_frame*) corresponding to a c-plane frame */
2061
    wmem_list_t *u_plane_frames;
2062
} flow_result_t;
2063
2064
2065
/* Uplink timing */
2066
/* For a given symbol, track first to last UL frame to find out first-last time */
2067
/* frameId (8) + subframeId (4) + slotId (6) + symbolId (6) = 24 bits */
2068
/* N.B. if a capture lasts > 2.5s, may see same timing come around again... */
2069
static uint32_t get_timing_key(uint8_t frameId, uint8_t subframeId, uint8_t slotId, uint8_t symbolId)
2070
0
{
2071
0
    return symbolId + (slotId<<8) + (subframeId<<14) + (frameId<<18);
2072
0
}
2073
2074
typedef struct {
2075
    uint32_t first_frame;
2076
    nstime_t first_frame_time;
2077
    uint32_t frames_seen_in_symbol;
2078
    uint32_t last_frame_in_symbol;
2079
} ul_timing_for_slot;
2080
2081
/* Set during first pass.  timing_key -> ul_timing_for_slot*  */
2082
static wmem_tree_t *ul_symbol_timing;
2083
2084
2085
/* Tracking lifetimes of DL beamIds */
2086
typedef struct {
2087
    uint32_t frame_defined;
2088
    uint32_t symbol_when_defined;
2089
} bfw_definition;
2090
2091
/* Maintained during first pass: beamId (from ext11) -> bfw_definition */
2092
static wmem_tree_t *dl_beam_ids_defined;
2093
/* Lookup where/when beamIds were defined (frameid:beamid) -> bfw_definition */
2094
static wmem_tree_t *dl_beam_ids_results;
2095
2096
2097
static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
2098
                                          ack_nack_request_t *response);
2099
2100
2101
2102
2103
static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
2104
    packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(4, 5);
2105
2106
 /* Write the given formatted text to:
2107
    - the info column (if pinfo != NULL)
2108
    - 1 or 2 other labels (optional)
2109
 */
2110
static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
2111
    packet_info *pinfo, const char *format, ...)
2112
19.8k
{
2113
19.8k
#define MAX_INFO_BUFFER 256
2114
19.8k
    char info_buffer[MAX_INFO_BUFFER];
2115
19.8k
    va_list ap;
2116
2117
19.8k
    if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
2118
0
        return;
2119
0
    }
2120
2121
19.8k
    va_start(ap, format);
2122
19.8k
    vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
2123
19.8k
    va_end(ap);
2124
2125
    /* Add to indicated places */
2126
19.8k
    if (pinfo != NULL) {
2127
19.8k
        col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
2128
19.8k
    }
2129
19.8k
    if (ti1 != NULL) {
2130
19.8k
        proto_item_append_text(ti1, "%s", info_buffer);
2131
19.8k
    }
2132
19.8k
    if (ti2 != NULL) {
2133
17.9k
        proto_item_append_text(ti2, "%s", info_buffer);
2134
17.9k
    }
2135
19.8k
}
2136
2137
/* Add section labels (type + PRB range) for C-Plane, U-Plane */
2138
static void
2139
write_section_info(proto_item *section_heading, packet_info *pinfo, proto_item *protocol_item,
2140
                   uint32_t section_id, uint32_t start_prbx, uint32_t num_prbx, uint32_t rb)
2141
17.9k
{
2142
17.9k
    switch (num_prbx) {
2143
47
        case 0:
2144
            /* None -> all */
2145
47
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d     (all PRBs)", section_id);
2146
47
            break;
2147
666
        case 1:
2148
            /* Single PRB */
2149
666
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %7u)", section_id, start_prbx);
2150
666
            break;
2151
17.2k
        default:
2152
            /* Range */
2153
17.2k
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %3u-%3u%s)", section_id, start_prbx,
2154
17.2k
                                     start_prbx + (num_prbx-1)*(1+rb), rb ? " (every-other)" : "");
2155
17.9k
    }
2156
17.9k
}
2157
2158
static void
2159
write_channel_section_info(proto_item *section_heading, packet_info *pinfo,
2160
                           uint32_t section_id, uint32_t ueId, uint32_t start_prbx, uint32_t num_prbx,
2161
                           uint32_t num_trx)
2162
355
{
2163
355
    switch (num_prbx) {
2164
224
        case 0:
2165
            /* TODO: ?? */
2166
224
            break;
2167
14
        case 1:
2168
            /* Single PRB */
2169
14
            write_pdu_label_and_info(section_heading, NULL, pinfo,
2170
14
                                     ", Id: %4d (UEId=%5u  PRB %7u, %2u antennas)",
2171
14
                                     section_id, ueId, start_prbx, num_trx);
2172
14
            break;
2173
117
        default:
2174
            /* Range */
2175
117
            write_pdu_label_and_info(section_heading, NULL, pinfo,
2176
117
                                     ", Id: %4d (UEId=%5u  PRBs %3u-%3u, %2u antennas)",
2177
117
                                     section_id, ueId, start_prbx, start_prbx+num_prbx-1, num_trx);
2178
355
    }
2179
355
}
2180
2181
/* Add a reserved field, and warn if value isn't 0 */
2182
/* TODO: maybe add a pref not to output expert warning if becomes too annoying? */
2183
static void add_reserved_field(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int len)
2184
53.4k
{
2185
53.4k
    uint32_t reserved;
2186
53.4k
    proto_item *res_ti = proto_tree_add_item_ret_uint(tree, hf, tvb, offset, len, ENC_NA, &reserved);
2187
53.4k
    if (reserved != 0) {
2188
29.2k
        expert_add_info_format(NULL, res_ti, &ei_oran_reserved_not_zero,
2189
29.2k
                               "reserved field saw value of 0x%x", reserved);
2190
29.2k
    }
2191
53.4k
}
2192
2193
/* 5.1.3.2.7 (real time control data / IQ data transfer message series identifier) */
2194
static void
2195
addPcOrRtcid(tvbuff_t *tvb, proto_tree *tree, unsigned *offset, int hf, uint16_t *eAxC, oran_tap_info *tap_info)
2196
1.94k
{
2197
    /* Subtree */
2198
1.94k
    proto_item *oran_pcid_ti = proto_tree_add_item(tree, hf,
2199
1.94k
                                                   tvb, *offset, 2, ENC_NA);
2200
1.94k
    proto_tree *oran_pcid_tree = proto_item_add_subtree(oran_pcid_ti, ett_oran_ecpri_pcid);
2201
2202
1.94k
    uint64_t duPortId, bandSectorId, ccId, ruPortId = 0;
2203
1.94k
    int id_offset = *offset;
2204
2205
    /* All parts of eAxC should be above 0, and should total 16 bits (breakdown controlled by preferences) */
2206
1.94k
    if (!((pref_du_port_id_bits > 0) && (pref_bandsector_id_bits > 0) && (pref_cc_id_bits > 0) && (pref_ru_port_id_bits > 0) &&
2207
1.93k
         ((pref_du_port_id_bits + pref_bandsector_id_bits + pref_cc_id_bits + pref_ru_port_id_bits) == 16))) {
2208
0
        expert_add_info(NULL, tree, &ei_oran_invalid_eaxc_bit_width);
2209
0
        *eAxC = 0;
2210
0
        *offset += 2;
2211
0
        return;
2212
0
    }
2213
2214
1.94k
    unsigned bit_offset = *offset * 8;
2215
2216
    /* N.B. For sequence analysis / tapping, just interpret these 2 bytes as eAxC ID... */
2217
1.94k
    *eAxC = tvb_get_uint16(tvb, *offset, ENC_BIG_ENDIAN);
2218
2219
    /* DU Port ID */
2220
1.94k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_du_port_id, tvb, bit_offset, pref_du_port_id_bits, &duPortId, ENC_BIG_ENDIAN);
2221
1.94k
    bit_offset += pref_du_port_id_bits;
2222
    /* BandSector ID */
2223
1.94k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_bandsector_id, tvb, bit_offset, pref_bandsector_id_bits, &bandSectorId, ENC_BIG_ENDIAN);
2224
1.94k
    bit_offset += pref_bandsector_id_bits;
2225
    /* CC ID */
2226
1.94k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_cc_id, tvb, bit_offset, pref_cc_id_bits, &ccId, ENC_BIG_ENDIAN);
2227
1.94k
    bit_offset += pref_cc_id_bits;
2228
    /* RU Port ID */
2229
1.94k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_ru_port_id, tvb, bit_offset, pref_ru_port_id_bits, &ruPortId, ENC_BIG_ENDIAN);
2230
1.94k
    *offset += 2;
2231
2232
1.94k
    proto_item_append_text(oran_pcid_ti, " (DU_Port_ID: %d, BandSector_ID: %d, CC_ID: %d, RU_Port_ID: %d)",
2233
1.94k
                           (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
2234
1.94k
    char id[16];
2235
1.94k
    snprintf(id, 16, "%x:%x:%x:%x", (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
2236
1.94k
    proto_item *pi = proto_tree_add_string(oran_pcid_tree, hf_oran_c_eAxC_ID, tvb, id_offset, 2, id);
2237
1.94k
    proto_item_set_generated(pi);
2238
2239
1.94k
    tap_info->eaxc = *eAxC;
2240
1.94k
    tap_info->eaxc_du_port_id = (uint16_t)duPortId;
2241
1.94k
    tap_info->eaxc_bandsector_id = (uint16_t)bandSectorId;
2242
1.94k
    tap_info->eaxc_cc_id = (uint16_t)ccId;
2243
1.94k
    tap_info->eaxc_ru_port_id = (uint16_t)ruPortId;
2244
1.94k
}
2245
2246
/* Uniquely identify the U-plane stream that may need to be reassembled */
2247
static uint32_t make_reassembly_id(uint32_t seqid, uint16_t eAxC, int direction)
2248
33
{
2249
33
    return ((seqid & 0xff) << 24) | ((direction&1)<<16) | (eAxC & 0xffff);
2250
33
}
2251
2252
/* 5.1.3.2.8  ecpriSeqid (message identifier) */
2253
/* Return out info that may be used for sequence number analysis and reassembly */
2254
static int
2255
addSeqid(tvbuff_t *tvb, proto_tree *oran_tree, int offset, int plane, uint32_t *seq_id, proto_item **seq_id_ti, packet_info *pinfo,
2256
         uint32_t *subseqid, uint32_t *e)
2257
1.93k
{
2258
    /* Subtree */
2259
1.93k
    proto_item *seqIdItem = proto_tree_add_item(oran_tree, hf_oran_ecpri_seqid, tvb, offset, 2, ENC_NA);
2260
1.93k
    proto_tree *oran_seqid_tree = proto_item_add_subtree(seqIdItem, ett_oran_ecpri_seqid);
2261
2262
    /* Sequence ID (8 bits) */
2263
1.93k
    *seq_id_ti = proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_sequence_id, tvb, offset, 1, ENC_NA, seq_id);
2264
1.93k
    offset += 1;
2265
2266
    /* Show link back to previous sequence ID, if set */
2267
1.93k
    flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
2268
1.93k
    if (result) {
2269
1
        proto_item *prev_ti = proto_tree_add_uint(oran_seqid_tree, hf_oran_previous_frame, tvb, 0, 0, result->previous_frame);
2270
1
        proto_item_set_generated(prev_ti);
2271
1
    }
2272
2273
    /* E bit */
2274
1.93k
    proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_e_bit, tvb, offset, 1, ENC_NA, e);
2275
    /* Subsequence ID (7 bits) */
2276
1.93k
    proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_subsequence_id, tvb, offset, 1, ENC_NA, subseqid);
2277
1.93k
    offset += 1;
2278
2279
    /* radio-transport fragmentation not allowed for C-Plane messages */
2280
1.93k
    if (plane == ORAN_C_PLANE) {
2281
1.73k
        if (*e !=1 || *subseqid != 0) {
2282
1.66k
            expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_c_plane);
2283
1.66k
        }
2284
1.73k
    }
2285
2286
    /* Summary */
2287
1.93k
    proto_item_append_text(seqIdItem, " (SeqId: %3d, E: %d, SubSeqId: %d)", *seq_id, *e, *subseqid);
2288
1.93k
    return offset;
2289
1.93k
}
2290
2291
static int dissect_symbolmask(tvbuff_t *tvb, proto_tree *tree, int offset, uint32_t *symbol_mask, proto_item **ti)
2292
668
{
2293
668
    uint64_t temp_val;
2294
2295
668
    static int * const  symbol_mask_flags[] = {
2296
668
        &hf_oran_symbol_mask_s13,
2297
668
        &hf_oran_symbol_mask_s12,
2298
668
        &hf_oran_symbol_mask_s11,
2299
668
        &hf_oran_symbol_mask_s10,
2300
668
        &hf_oran_symbol_mask_s9,
2301
668
        &hf_oran_symbol_mask_s8,
2302
668
        &hf_oran_symbol_mask_s7,
2303
668
        &hf_oran_symbol_mask_s6,
2304
668
        &hf_oran_symbol_mask_s5,
2305
668
        &hf_oran_symbol_mask_s4,
2306
668
        &hf_oran_symbol_mask_s3,
2307
668
        &hf_oran_symbol_mask_s2,
2308
668
        &hf_oran_symbol_mask_s1,
2309
668
        &hf_oran_symbol_mask_s0,
2310
668
        NULL
2311
668
    };
2312
2313
668
    proto_item *temp_ti = proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
2314
668
                                                            hf_oran_symbol_mask,
2315
668
                                                            ett_oran_symbol_mask, symbol_mask_flags,
2316
668
                                                            ENC_BIG_ENDIAN, &temp_val);
2317
    /* Set out parameters */
2318
668
    if (symbol_mask) {
2319
117
        *symbol_mask = (uint32_t)temp_val;
2320
117
    }
2321
668
    if (ti) {
2322
117
        *ti = temp_ti;
2323
117
    }
2324
668
    return offset+2;
2325
668
}
2326
2327
/* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
2328
static int dissect_bfwCompHdr(tvbuff_t *tvb, proto_tree *tree, int offset,
2329
                              uint32_t *iq_width, uint32_t *comp_meth, proto_item **comp_meth_ti)
2330
336
{
2331
    /* Subtree */
2332
336
    proto_item *bfwcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompHdr,
2333
336
                                                            tvb, offset, 1, "",
2334
336
                                                            "bfwCompHdr");
2335
336
    proto_tree *bfwcomphdr_tree = proto_item_add_subtree(bfwcomphdr_ti, ett_oran_bfwcomphdr);
2336
2337
    /* Width and method */
2338
336
    proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_iqWidth,
2339
336
                                 tvb, offset, 1, ENC_BIG_ENDIAN,  iq_width);
2340
    /* Special case: 0 -> 16 */
2341
336
    *iq_width = (*iq_width==0) ? 16 : *iq_width;
2342
336
    *comp_meth_ti = proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_compMeth,
2343
336
                                                 tvb, offset, 1, ENC_BIG_ENDIAN, comp_meth);
2344
336
    offset++;
2345
2346
    /* Summary */
2347
336
    proto_item_append_text(bfwcomphdr_ti, " (IqWidth=%u, compMeth=%s)",
2348
336
                           *iq_width,
2349
336
                           val_to_str_const(*comp_meth, bfw_comp_headers_comp_meth, "reserved"));
2350
2351
336
    return offset;
2352
336
}
2353
2354
/* Return offset */
2355
/* Returning number of entries set - would be good to also return an array of set TRX# so could show which array element
2356
   each BFW is actually for.. */
2357
static int dissect_active_beamspace_coefficient_mask(tvbuff_t *tvb, proto_tree *tree, int offset, unsigned *num_trx_entries, uint16_t **trx_entries)
2358
338
{
2359
    /* activeBeamspaceCoefficientMask - ceil(K/8) octets */
2360
    /* K is the number of elements in uncompressed beamforming weight vector.
2361
     * Calculated from parameters describing tx-array or tx-array */
2362
338
    unsigned k_octets = (pref_num_bf_antennas + 7) / 8;
2363
2364
338
    static uint16_t trx_enabled[1024];
2365
2366
    /* TODO: could use a bigger bitmask array, but for now just uses this bytes-worth for each byte */
2367
338
    static int * const mask_bits[] = {
2368
338
        &hf_oran_active_beamspace_coefficient_n1,
2369
338
        &hf_oran_active_beamspace_coefficient_n2,
2370
338
        &hf_oran_active_beamspace_coefficient_n3,
2371
338
        &hf_oran_active_beamspace_coefficient_n4,
2372
338
        &hf_oran_active_beamspace_coefficient_n5,
2373
338
        &hf_oran_active_beamspace_coefficient_n6,
2374
338
        &hf_oran_active_beamspace_coefficient_n7,
2375
338
        &hf_oran_active_beamspace_coefficient_n8,
2376
338
        NULL
2377
338
    };
2378
2379
338
    *num_trx_entries = 0;
2380
338
    uint64_t val;
2381
1.68k
    for (unsigned n=0; n < k_octets; n++) {
2382
1.34k
        proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
2383
1.34k
                                          hf_oran_activeBeamspaceCoefficientMask,
2384
1.34k
                                          ett_oran_active_beamspace_coefficient_mask, mask_bits,
2385
1.34k
                                          ENC_BIG_ENDIAN, &val);
2386
1.34k
        offset++;
2387
        /* Add up the set bits for this byte (but be careful not to count beyond last real K bit..) */
2388
12.0k
        for (unsigned b=0; b < 8; b++) {
2389
10.7k
            if ((1 << b) & (unsigned)val) {
2390
4.23k
                if (((n*8)+b) < pref_num_bf_antennas) {
2391
4.23k
                    if (*num_trx_entries < 1024-1) {   /* Don't write beyond array (which should be plenty big) */
2392
4.23k
                        trx_enabled[(*num_trx_entries)++] = (n*8) + b + 1;
2393
4.23k
                    }
2394
4.23k
                }
2395
4.23k
            }
2396
10.7k
        }
2397
1.34k
    }
2398
    /* Set pointer to static array */
2399
338
    *trx_entries = trx_enabled;
2400
2401
    /* Show how many bits set */
2402
338
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_activeBeamspaceCoefficientMask_bits_set, tvb,
2403
338
                                         offset-k_octets, k_octets, *num_trx_entries);
2404
338
    proto_item_set_generated(ti);
2405
2406
338
    return offset;
2407
338
}
2408
2409
static void add_beam_id_to_tap(oran_tap_info *tap_info, uint16_t beam_id)
2410
3.00k
{
2411
3.00k
    if (tap_info->num_beams < MAX_BEAMS_IN_FRAME) {
2412
2.71k
        tap_info->beams[tap_info->num_beams++] = beam_id;
2413
2.71k
    }
2414
3.00k
}
2415
2416
2417
/* 7.7.1.3 bfwCompParam (beamforming weight compression parameter).
2418
 * Depends upon passed-in bfwCompMeth (field may be empty) */
2419
static int dissect_bfwCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset,
2420
                                proto_item *meth_ti, uint32_t *bfw_comp_method,
2421
                                uint32_t *exponent, bool *supported, unsigned *num_trx_entries, uint16_t **trx_entries)
2422
1.31k
{
2423
1.31k
    if (*bfw_comp_method == COMP_NONE) {
2424
        /* Absent! */
2425
163
        *num_trx_entries = 0;
2426
163
        *supported = true;
2427
163
        return offset;
2428
163
    }
2429
2430
    /* Subtree */
2431
1.14k
    proto_item *bfwcompparam_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompParam,
2432
1.14k
                                                               tvb, offset, 1, "",
2433
1.14k
                                                              "bfwCompParam");
2434
1.14k
    proto_tree *bfwcompparam_tree = proto_item_add_subtree(bfwcompparam_ti, ett_oran_bfwcompparam);
2435
2436
1.14k
    proto_item_append_text(bfwcompparam_ti,
2437
1.14k
                           " (meth=%s)", val_to_str_const(*bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
2438
2439
1.14k
    *num_trx_entries = 0;
2440
1.14k
    *supported = false;
2441
1.14k
    switch (*bfw_comp_method) {
2442
367
        case COMP_BLOCK_FP:     /* block floating point */
2443
            /* 4 reserved bits +  exponent */
2444
367
            add_reserved_field(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
2445
367
            proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent,
2446
367
                                         tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
2447
367
            proto_item_append_text(bfwcompparam_ti, " exponent=%u", *exponent);
2448
367
            *supported = true;
2449
367
            offset++;
2450
367
            break;
2451
89
        case COMP_BLOCK_SCALE:  /* block scaling */
2452
            /* Separate into integer and fractional bits? */
2453
89
            proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
2454
89
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2455
89
            offset++;
2456
89
            break;
2457
138
        case COMP_U_LAW:        /* u-law */
2458
            /* compBitWidth, compShift */
2459
138
            proto_tree_add_item(bfwcompparam_tree, hf_oran_compBitWidth,
2460
138
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2461
138
            proto_tree_add_item(bfwcompparam_tree, hf_oran_compShift,
2462
138
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2463
138
            offset++;
2464
138
            break;
2465
105
        case 4:                 /* beamspace I (BLOCK SCALING) */
2466
            /* activeBeamspaceCoefficientMask */
2467
105
            offset = dissect_active_beamspace_coefficient_mask(tvb, bfwcompparam_tree, offset, num_trx_entries, trx_entries);
2468
105
            *bfw_comp_method = COMP_BLOCK_SCALE;
2469
105
            *supported = false;                  /* TODO: true once BLOCK SCALE is supported */
2470
105
            proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
2471
105
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2472
105
            offset++;
2473
105
            break;
2474
233
        case 5:                 /* beamspace II (BLOCK FLOATING POINT) */
2475
            /* activeBeamspaceCoefficientMask */
2476
233
            offset = dissect_active_beamspace_coefficient_mask(tvb, bfwcompparam_tree, offset, num_trx_entries, trx_entries);
2477
            /* reserved (4 bits) + exponent (4 bits) */
2478
233
            add_reserved_field(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
2479
233
            proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent, tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
2480
233
            offset += 1;
2481
233
            *bfw_comp_method = COMP_BLOCK_FP;
2482
233
            *supported = true;
2483
233
            break;
2484
2485
214
        default:
2486
            /* Not handled */
2487
214
             break;
2488
1.14k
    }
2489
2490
1.13k
    proto_item_set_end(bfwcompparam_ti, tvb, offset);
2491
2492
    /* Can't go on if compression scheme not supported */
2493
1.13k
    if (!(*supported) && meth_ti) {
2494
541
        expert_add_info_format(pinfo, meth_ti, &ei_oran_unsupported_bfw_compression_method,
2495
541
                               "BFW Compression method %u (%s) not decompressed by dissector",
2496
541
                               *bfw_comp_method,
2497
541
                               val_to_str_const(*bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
2498
541
    }
2499
1.13k
    return offset;
2500
1.14k
}
2501
2502
2503
/* Special case for uncompressed value with given iq_width */
2504
static float uncompressed_to_float(uint32_t bits, uint32_t iq_width)
2505
21.7k
{
2506
21.7k
    if (iq_width == 0 || iq_width > 16) {
2507
        /* Not valid */
2508
0
        return 0.0;
2509
0
    }
2510
2511
21.7k
    uint16_t mask = (1U << (iq_width-1)) - 1;
2512
21.7k
    int16_t i16 = (bits < mask) ? (bits & mask) : (bits - (1<<iq_width));
2513
2514
21.7k
    if (show_unscaled_values) {
2515
0
        return (float)i16;
2516
0
    }
2517
21.7k
    return ((float)i16) / (mask);
2518
21.7k
}
2519
2520
/* Decompress I/Q value, taking into account method, width, exponent, other input-specific methods */
2521
static float decompress_value(uint32_t bits, uint32_t comp_method, uint8_t iq_width,
2522
                              uint32_t exponent,
2523
                              /* Modulation compression settings. N.B. should also pass in PRB + symbol? */
2524
                              section_mod_compr_config_t *m_c_p, uint8_t re)
2525
165k
{
2526
165k
    switch (comp_method) {
2527
21.7k
        case COMP_NONE: /* no compression */
2528
21.7k
            return uncompressed_to_float(bits, iq_width);
2529
2530
63.5k
        case COMP_BLOCK_FP:         /* block floating point */
2531
77.7k
        case BFP_AND_SELECTIVE_RE:
2532
77.7k
        {
2533
            /* A.1.3 Block Floating Point Decompression Algorithm */
2534
77.7k
            int32_t cPRB = bits;
2535
77.7k
            uint32_t scaler = 1 << exponent;  /* i.e. 2^exponent */
2536
2537
            /* Check last bit, in case we need to flip to -ve */
2538
77.7k
            if (cPRB >= (1<<(iq_width-1))) {
2539
32.3k
                cPRB -= (1<<iq_width);
2540
32.3k
            }
2541
2542
            /* Unscale (8.1.3.1) */
2543
77.7k
            cPRB *= scaler;
2544
77.7k
            if (show_unscaled_values) {
2545
0
                return (float)cPRB;
2546
0
            }
2547
2548
77.7k
            uint32_t mantissa_scale_factor = 1 << (iq_width-1); /* 2^(mantissabits-1) */
2549
77.7k
            uint32_t exp_scale_factor = 1 << 15;  /* 2^(2^exponentbits - 1 ) The exponent bit width is fixed to 4, so the maximum exponent is 15 */
2550
2551
77.7k
            float ret = cPRB / ((float)(mantissa_scale_factor*exp_scale_factor));
2552
77.7k
            return ret;
2553
77.7k
        }
2554
2555
17.1k
        case COMP_BLOCK_SCALE:
2556
33.0k
        case COMP_U_LAW:
2557
            /* Not supported! But will be reported as expert info outside of this function! */
2558
33.0k
            return 0.0;
2559
2560
7.86k
        case COMP_MODULATION:
2561
16.3k
        case MOD_COMPR_AND_SELECTIVE_RE:
2562
16.3k
        {
2563
            /* Described in A.5 (with pseudo code) */
2564
            /* N.B., Applies to downlink data only - is not used for BFW */
2565
2566
            /* Defaults if not overridden. TODO: what should these be? */
2567
16.3k
            bool csf = false;
2568
16.3k
            float mcScaler = (float)(1 << 11);
2569
2570
            /* Find csf + mcScaler to use. Non-default configs gleaned from SE 4,5,23 */
2571
            /* TODO: should ideally be filtering by symbol and PRB too (as configured from SE23) */
2572
16.3k
            if (re > 0 && m_c_p && m_c_p->num_configs > 0) {
2573
0
                for (unsigned c=0; c<m_c_p->num_configs; c++) {
2574
0
                    if (m_c_p->configs[c].mod_compr_re_mask & (1 << (12-re))) {
2575
                        /* Return first (should be only) found */
2576
0
                        csf = m_c_p->configs[c].mod_compr_csf;
2577
0
                        mcScaler = m_c_p->configs[c].mod_compr_scaler;
2578
0
                        break;
2579
0
                    }
2580
0
                }
2581
0
            }
2582
2583
16.3k
            int32_t cPRB = bits;
2584
2585
            /* 2) Map iqSample to iqSampleFx */
2586
            /* Check last bit, in case we need to flip to -ve */
2587
16.3k
            if (cPRB >= (1<<(iq_width-1))) {
2588
7.21k
                cPRB -= (1<<iq_width);
2589
7.21k
            }
2590
16.3k
            float iqSampleFx = (float)cPRB / (1 << (iq_width-1));
2591
2592
2593
            /* 3) or 4) (b) - add unshifted value if csf set */
2594
16.3k
            float csf_to_add = 0.0;
2595
16.3k
            if (csf) {
2596
                /* Unshift the constellation point */
2597
0
                csf_to_add = (float)1.0 / (1 << (iq_width));
2598
0
            }
2599
16.3k
            iqSampleFx += csf_to_add;
2600
2601
            /* 3) or 4) (c) - unscaling */
2602
16.3k
            float iqSampleScaled = mcScaler * iqSampleFx * (float)sqrt(2);
2603
16.3k
            return iqSampleScaled;
2604
7.86k
        }
2605
2606
16.6k
        default:
2607
            /* Not supported! But will be reported as expert info outside of this function! */
2608
16.6k
            return 0.0;
2609
165k
    }
2610
165k
}
2611
2612
/* Out-of-range value used for special case */
2613
#define ORPHAN_BUNDLE_NUMBER 999
2614
2615
/* Bundle of PRBs/TRX I/Q samples (ext 11) */
2616
static uint32_t dissect_bfw_bundle(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, unsigned offset,
2617
                                  proto_item *comp_meth_ti, uint32_t bfwcomphdr_comp_meth,
2618
                                  section_mod_compr_config_t *mod_compr_params,
2619
                                  uint32_t num_weights_per_bundle,
2620
                                  uint8_t iq_width,
2621
                                  unsigned bundle_number,
2622
                                  bundle_t *bundle,
2623
                                  uint32_t symbol_count,
2624
                                  section_details_t *section_details,
2625
                                  oran_tap_info *tap_info)
2626
566
{
2627
    /* Set bundle name */
2628
566
    char bundle_name[32];
2629
566
    if (!bundle->is_orphan) {
2630
540
        snprintf(bundle_name, 32, "Bundle %3u", bundle_number);
2631
540
    }
2632
26
    else {
2633
26
        (void) g_strlcpy(bundle_name, "Orphaned  ", 32);
2634
26
    }
2635
2636
    /* Create Bundle root */
2637
566
    proto_item *bundle_ti;
2638
566
    if (bundle->start != bundle->end) {
2639
413
        bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
2640
413
                                                 tvb, offset, 0, "",
2641
413
                                                 "%s: (PRBs %3u-%3u)",
2642
413
                                                 bundle_name,
2643
413
                                                 bundle->start, bundle->end);
2644
413
    }
2645
153
    else {
2646
153
        bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
2647
153
                                                 tvb, offset, 0, "",
2648
153
                                                 "%s: (PRB      %3u)",
2649
153
                                                 bundle_name,
2650
153
                                                 bundle->start);
2651
153
    }
2652
566
    proto_tree *bundle_tree = proto_item_add_subtree(bundle_ti, ett_oran_bfw_bundle);
2653
2654
    /* Generated bundle id */
2655
566
    proto_item *bundleid_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfw_bundle_id, tvb, 0, 0,
2656
566
                                                  bundle_number);
2657
566
    proto_item_set_generated(bundleid_ti);
2658
566
    proto_item_set_hidden(bundleid_ti);
2659
2660
    /* bfwCompParam */
2661
566
    bool compression_method_supported = false;
2662
566
    unsigned exponent = 0;
2663
566
    unsigned num_trx_entries = 0;
2664
566
    uint16_t *trx_entries;
2665
566
    offset = dissect_bfwCompParam(tvb, bundle_tree, pinfo, offset, comp_meth_ti,
2666
566
                                  &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
2667
566
                                  &num_trx_entries, &trx_entries);
2668
2669
    /* Create Bundle subtree */
2670
566
    int bit_offset = offset*8;
2671
566
    int bfw_offset;
2672
2673
    /* contInd */
2674
566
    proto_tree_add_item(bundle_tree, hf_oran_cont_ind,
2675
566
                        tvb, offset, 1, ENC_BIG_ENDIAN);
2676
    /* beamId */
2677
566
    uint32_t beam_id;
2678
566
    proto_tree_add_item_ret_uint(bundle_tree, hf_oran_beam_id, tvb, offset, 2, ENC_BIG_ENDIAN, &beam_id);
2679
566
    proto_item_append_text(bundle_ti, " (beamId:%5u) ", beam_id);
2680
566
    bit_offset += 16;
2681
566
    add_beam_id_to_tap(tap_info, beam_id);
2682
2683
566
    if (!PINFO_FD_VISITED(pinfo)) {
2684
560
        if (section_details) {
2685
8.02k
            for (unsigned prb = bundle->start; prb <= bundle->end; prb++) {
2686
7.46k
                if (prb < 273) {
2687
4.42k
                    section_details->beamIds[prb] = beam_id;
2688
4.42k
                }
2689
7.46k
            }
2690
560
        }
2691
560
    }
2692
2693
    /* On first pass, record that beamId was defined here */
2694
566
    if (!PINFO_FD_VISITED(pinfo)) {
2695
560
        bfw_definition *definition = wmem_new0(wmem_file_scope(), bfw_definition);
2696
560
        definition->frame_defined = pinfo->num;
2697
560
        definition->symbol_when_defined = symbol_count;
2698
560
        wmem_tree_insert32(dl_beam_ids_defined, beam_id, definition);
2699
560
    }
2700
2701
2702
    /* Number of weights per bundle (from preference) */
2703
566
    proto_item *wpb_ti = proto_tree_add_uint(bundle_tree, hf_oran_num_weights_per_bundle, tvb, 0, 0,
2704
566
                                             num_weights_per_bundle);
2705
566
    proto_item_set_generated(wpb_ti);
2706
2707
    /* Add the weights for this bundle. Overwrite with what was seen in bfwCompParam if beamspace */
2708
566
    if (num_trx_entries != 0) {
2709
250
        num_weights_per_bundle = num_trx_entries;
2710
250
    }
2711
2712
566
    bool non_zero_weights_seen = false;
2713
566
    int bit_offset_before_weights = bit_offset;
2714
13.1k
    for (unsigned w=0; w < num_weights_per_bundle; w++) {
2715
2716
12.5k
        uint16_t trx_index = (num_trx_entries) ? trx_entries[w] : w+1;
2717
2718
        /* Create subtree */
2719
12.5k
        bfw_offset = bit_offset / 8;
2720
12.5k
        uint8_t bfw_extent = ((bit_offset + (iq_width*2)) / 8) - bfw_offset;
2721
12.5k
        proto_item *bfw_ti = proto_tree_add_string_format(bundle_tree, hf_oran_bfw,
2722
12.5k
                                                          tvb, bfw_offset, bfw_extent,
2723
12.5k
                                                          "", "TRX %3u: (", trx_index);
2724
12.5k
        proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
2725
2726
        /* I */
2727
        /* Get bits, and convert to float. */
2728
12.5k
        uint32_t bits = tvb_get_bits32(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
2729
12.5k
        if (bits) {
2730
6.07k
            non_zero_weights_seen = true;
2731
6.07k
        }
2732
12.5k
        float value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width,
2733
12.5k
                                       exponent, mod_compr_params, 0 /* RE */);
2734
        /* Add to tree. */
2735
12.5k
        proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8, (iq_width+7)/8, value, "#%u=%f", w, value);
2736
12.5k
        bit_offset += iq_width;
2737
12.5k
        proto_item_append_text(bfw_ti, "I%u=%f ", w, value);
2738
2739
        /* Q */
2740
        /* Get bits, and convert to float. */
2741
12.5k
        bits = tvb_get_bits32(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
2742
12.5k
        if (bits) {
2743
6.59k
            non_zero_weights_seen = true;
2744
6.59k
        }
2745
2746
12.5k
        value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width,
2747
12.5k
                                 exponent, mod_compr_params, 0 /* RE */);
2748
        /* Add to tree. */
2749
12.5k
        proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8, (iq_width+7)/8, value, "#%u=%f", w, value);
2750
12.5k
        bit_offset += iq_width;
2751
12.5k
        proto_item_append_text(bfw_ti, "Q%u=%f)", w, value);
2752
12.5k
    }
2753
2754
566
    if (!non_zero_weights_seen) {
2755
26
        proto_tree_add_item(bundle_tree, hf_oran_bundle_weights_all_zero, tvb,
2756
26
                            bit_offset_before_weights, (bit_offset+7)/8 - (bit_offset_before_weights/8), ENC_NA);
2757
26
    }
2758
2759
566
    if (bundle->bit_from_rbg_mask) {
2760
0
        proto_item_append_text(bundle_ti, " (rbg %u)", bundle->bit_from_rbg_mask-1);
2761
0
    }
2762
2763
    /* Set extent of bundle */
2764
566
    proto_item_set_end(bundle_ti, tvb, (bit_offset+7)/8);
2765
2766
566
    return (bit_offset+7)/8;
2767
566
}
2768
2769
/* Return new bit offset.  in/out will always be byte-aligned.. */
2770
static int dissect_ciCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, unsigned bit_offset,
2771
                               unsigned comp_meth, uint8_t *exponent)
2772
692
{
2773
692
    if (comp_meth == COMP_NONE) {
2774
        /* Nothing in frame so don't even create subtree */
2775
118
        return bit_offset;
2776
118
    }
2777
2778
    /* Subtree */
2779
574
    proto_item *cicompparam_ti = proto_tree_add_string_format(tree, hf_oran_ciCompParam,
2780
574
                                                            tvb, bit_offset/8, 1, "",
2781
574
                                                            "ciCompParam");
2782
574
    proto_tree *cicompparam_tree = proto_item_add_subtree(cicompparam_ti, ett_oran_cicompparam);
2783
574
    uint32_t ci_exponent;
2784
2785
    /* Contents differ by compression method */
2786
574
    switch (comp_meth) {
2787
249
        case COMP_BLOCK_FP:
2788
249
            add_reserved_field(cicompparam_tree, hf_oran_reserved_4bits, tvb, bit_offset/8, 1);
2789
249
            proto_tree_add_item_ret_uint(cicompparam_tree, hf_oran_exponent,
2790
249
                                         tvb, bit_offset/8, 1, ENC_BIG_ENDIAN, &ci_exponent);
2791
249
            *exponent = ci_exponent;
2792
249
            proto_item_append_text(cicompparam_ti, " (Exponent=%u)", ci_exponent);
2793
249
            bit_offset += 8; /* one byte */
2794
249
            break;
2795
86
        case COMP_BLOCK_SCALE:
2796
            /* Separate into integer (1) and fractional (7) bits? */
2797
86
            proto_tree_add_item(cicompparam_tree, hf_oran_blockScaler,
2798
86
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2799
86
            bit_offset += 8;
2800
86
            break;
2801
60
        case COMP_U_LAW:
2802
            /* compBitWidth, compShift (4 bits each) */
2803
60
            proto_tree_add_item(cicompparam_tree, hf_oran_compBitWidth,
2804
60
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2805
60
            proto_tree_add_item(cicompparam_tree, hf_oran_compShift,
2806
60
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2807
60
            bit_offset += 8;
2808
60
            break;
2809
2810
176
        default:
2811
            /* reserved, ? bytes of zeros.. */
2812
176
            break;
2813
574
    }
2814
2815
571
    return bit_offset;
2816
574
}
2817
2818
/* frameStructure (7.5.2.13) */
2819
static unsigned dissect_frame_structure(proto_item *tree, tvbuff_t *tvb, unsigned offset,
2820
                                        uint32_t subframeId, uint32_t slotId)
2821
444
{
2822
444
    uint32_t scs;
2823
    /* FFT Size (4 bits) */
2824
444
    proto_tree_add_item(tree, hf_oran_frameStructure_fft, tvb, offset, 1, ENC_NA);
2825
    /* Subcarrier spacing (SCS) */
2826
444
    proto_tree_add_item_ret_uint(tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
2827
2828
    /* Show slot within frame as a generated field. See table 7.5.13-3 */
2829
444
    uint32_t slots_per_subframe = 1;
2830
444
    if (scs <= 4) {
2831
258
        slots_per_subframe = 1 << scs;
2832
258
    }
2833
444
    if (scs <= 4 || scs >= 12) {
2834
329
        proto_item *ti = proto_tree_add_uint(tree, hf_oran_slot_within_frame, tvb, 0, 0,
2835
329
                                             (slots_per_subframe*subframeId) + slotId);
2836
329
        proto_item_set_generated(ti);
2837
329
    }
2838
444
    return offset + 1;
2839
444
}
2840
2841
static unsigned dissect_csf(proto_item *tree, tvbuff_t *tvb, unsigned bit_offset,
2842
                            unsigned iq_width, bool *p_csf)
2843
2.09k
{
2844
2.09k
    proto_item *csf_ti;
2845
2.09k
    uint64_t csf;
2846
2.09k
    csf_ti = proto_tree_add_bits_ret_val(tree, hf_oran_csf, tvb, bit_offset, 1, &csf, ENC_BIG_ENDIAN);
2847
2.09k
    if (csf) {
2848
        /* Table 7.7.4.2-1 Constellation shift definition (index is udIqWidth) */
2849
892
        const char* shift_value[] = { "n/a", "1/2", "1/4", "1/8", "1/16", "1/32" };
2850
892
        if (iq_width >=1 && iq_width <= 5) {
2851
86
            proto_item_append_text(csf_ti, " (Shift Value is %s)", shift_value[iq_width]);
2852
86
        }
2853
892
    }
2854
2855
    /* Set out parameter */
2856
2.09k
    if (p_csf != NULL) {
2857
2.08k
        *p_csf = (csf!=0);
2858
2.08k
    }
2859
2.09k
    return bit_offset+1;
2860
2.09k
}
2861
2862
static unsigned dissect_rbg_mask(proto_item *tree, tvbuff_t *tvb, unsigned offset, uint32_t *rbgMask, proto_item **item)
2863
677
{
2864
677
    uint64_t rbgMask64;
2865
2866
677
    static int * const  rbg_mask_bits[] = {
2867
677
        &hf_oran_rbg_mask_27,
2868
677
        &hf_oran_rbg_mask_26,
2869
677
        &hf_oran_rbg_mask_25,
2870
677
        &hf_oran_rbg_mask_24,
2871
677
        &hf_oran_rbg_mask_23,
2872
677
        &hf_oran_rbg_mask_22,
2873
677
        &hf_oran_rbg_mask_21,
2874
677
        &hf_oran_rbg_mask_20,
2875
677
        &hf_oran_rbg_mask_19,
2876
677
        &hf_oran_rbg_mask_18,
2877
677
        &hf_oran_rbg_mask_17,
2878
677
        &hf_oran_rbg_mask_16,
2879
677
        &hf_oran_rbg_mask_15,
2880
677
        &hf_oran_rbg_mask_14,
2881
677
        &hf_oran_rbg_mask_13,
2882
677
        &hf_oran_rbg_mask_12,
2883
677
        &hf_oran_rbg_mask_11,
2884
677
        &hf_oran_rbg_mask_10,
2885
677
        &hf_oran_rbg_mask_9,
2886
677
        &hf_oran_rbg_mask_8,
2887
677
        &hf_oran_rbg_mask_7,
2888
677
        &hf_oran_rbg_mask_6,
2889
677
        &hf_oran_rbg_mask_5,
2890
677
        &hf_oran_rbg_mask_4,
2891
677
        &hf_oran_rbg_mask_3,
2892
677
        &hf_oran_rbg_mask_2,
2893
677
        &hf_oran_rbg_mask_1,
2894
677
        &hf_oran_rbg_mask_0,
2895
677
        NULL
2896
677
    };
2897
2898
677
    *item = proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
2899
677
                                              hf_oran_rbgMask, ett_oran_rbgMask,
2900
677
                                              rbg_mask_bits,
2901
677
                                              ENC_BIG_ENDIAN, &rbgMask64);
2902
677
    *rbgMask = (uint32_t)rbgMask64;
2903
677
    return offset+4;
2904
677
}
2905
2906
2907
/* Section 7.
2908
 * N.B. these are the green parts of the tables showing Section Types, differing by section Type */
2909
static int dissect_oran_c_section(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
2910
                                  flow_state_t* state,
2911
                                  uint32_t sectionType, oran_tap_info *tap_info, proto_item *protocol_item,
2912
                                  uint32_t subframeId, uint32_t frameId, uint32_t slotId, uint32_t startSymbolId,
2913
                                  uint8_t ci_iq_width, uint8_t ci_comp_meth, unsigned ci_comp_opt,
2914
                                  unsigned num_sinr_per_prb)
2915
17.5k
{
2916
17.5k
    unsigned offset = 0;
2917
17.5k
    proto_tree *c_section_tree = NULL;
2918
17.5k
    proto_item *sectionHeading = NULL;
2919
2920
    /* Section subtree */
2921
17.5k
    sectionHeading = proto_tree_add_string_format(tree, hf_oran_c_section,
2922
17.5k
                                                  tvb, offset, 0, "", "Section");
2923
17.5k
    c_section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section);
2924
2925
17.5k
    uint32_t sectionId = 0;
2926
2927
17.5k
    uint32_t startPrbc=0, startPrbu=0;
2928
17.5k
    uint32_t numPrbc=0, numPrbu=0;
2929
17.5k
    uint32_t ueId = 0;
2930
17.5k
    proto_item *ueId_ti = NULL;
2931
17.5k
    uint32_t section_beamId = 0;
2932
17.5k
    proto_item *section_beamId_ti = NULL;
2933
17.5k
    bool section_beamId_ignored = false;
2934
2935
17.5k
    proto_item *numsymbol_ti = NULL;
2936
17.5k
    bool numsymbol_ignored = false;
2937
2938
17.5k
    proto_item *numprbc_ti = NULL;
2939
2940
17.5k
    proto_item *rb_ti = NULL;
2941
17.5k
    uint32_t rb;
2942
2943
    /* Config affecting ext11 bundles (initially unset) */
2944
17.5k
    ext11_settings_t ext11_settings;
2945
17.5k
    memset(&ext11_settings, 0, sizeof(ext11_settings));
2946
2947
    /* Section Type 10 needs to keep track of PRB range that should be reported
2948
       for msgTypeId=5 (Interference plus Noise for unallocated PRBs) */
2949
    /* All PRBs start as false */
2950
3.35M
#define MAX_PRBS 273
2951
17.5k
    bool prbs_for_st10_type5[MAX_PRBS];
2952
17.5k
    memset(&prbs_for_st10_type5, 0, sizeof(prbs_for_st10_type5));
2953
2954
    /* These UEIds are set by ST5, ST10 (single value), and extended by SE10 */
2955
17.5k
#define MAX_UEIDS 16
2956
17.5k
    uint32_t ueids[MAX_UEIDS];
2957
17.5k
    uint32_t number_of_ueids = 0;
2958
2959
2960
17.5k
    bool extension_flag = false;
2961
2962
    /* These sections (ST0, ST1, ST2, ST3, ST5, ST9, ST10, ST11) are similar, so handle as common with per-type differences */
2963
17.5k
    if (((sectionType <= SEC_C_UE_SCHED) || (sectionType >= SEC_C_SINR_REPORTING)) &&
2964
17.1k
         (sectionType != SEC_C_SLOT_CONTROL)) {
2965
2966
        /* sectionID */
2967
17.1k
        proto_item *ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
2968
17.1k
        if (sectionId == 4095) {
2969
801
            proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
2970
801
        }
2971
17.1k
        offset++;
2972
2973
17.1k
        if (tap_info->num_section_ids < MAX_SECTION_IDs) {
2974
14.0k
            tap_info->section_ids[tap_info->num_section_ids++] = sectionId;
2975
14.0k
        }
2976
2977
        /* rb */
2978
17.1k
        rb_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
2979
2980
        /* symInc (1 bit) */
2981
        /* TODO: mark as ignored if SE6, SE12 or SE19 present */
2982
17.1k
        if (sectionType != SEC_C_RRM_MEAS_REPORTS &&     /* Section Type 10 */
2983
11.5k
            sectionType != SEC_C_REQUEST_RRM_MEAS) {     /* Section Type 11 */
2984
10.3k
            unsigned int sym_inc;
2985
10.3k
            proto_item *sym_inc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA, &sym_inc);
2986
10.3k
            if (sym_inc !=0 && (sectionType == SEC_C_SINR_REPORTING)) {  /* Section Type 9 */
2987
                /* "0 shall be used" */
2988
35
                proto_item_append_text(sym_inc_ti, " (should be 0)");
2989
35
            }
2990
10.3k
        }
2991
6.82k
        else {
2992
            /* reserved (1 bit) */
2993
6.82k
            add_reserved_field(c_section_tree, hf_oran_reserved_bit5, tvb, offset, 1);
2994
6.82k
        }
2995
2996
        /* startPrbx and numPrbx */
2997
17.1k
        if (sectionType == SEC_C_SINR_REPORTING) {
2998
            /* startPrbu (10 bits) */
2999
86
            proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
3000
86
            offset += 2;
3001
3002
            /* numPrbu */
3003
86
            numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
3004
86
            if (numPrbu == 0) {
3005
18
                proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
3006
18
                numPrbu = pref_data_plane_section_total_rbs;
3007
18
            }
3008
86
            offset += 1;
3009
86
        }
3010
17.0k
        else {
3011
            /* startPrbc (10 bits) */
3012
17.0k
            proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
3013
17.0k
            offset += 2;
3014
3015
            /* numPrbc */
3016
17.0k
            numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
3017
17.0k
            if (numPrbc == 0) {
3018
4.41k
                proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
3019
                /* TODO: should probably set to pref_data_plane_section_total_rbs, and define MAX_PRBS to > 273 ? */
3020
4.41k
                numPrbc = MAX_PRBS;
3021
4.41k
            }
3022
17.0k
            offset += 1;
3023
17.0k
        }
3024
3025
        /* Start with range from section.  May get changed by SE6, SE12, SE20 */
3026
2.40M
        for (unsigned n=startPrbc; n < startPrbc+numPrbc; n++) {
3027
2.38M
            if (n < MAX_PRBS) {
3028
1.19M
                prbs_for_st10_type5[n] = true;
3029
1.19M
            }
3030
2.38M
        }
3031
3032
17.1k
        if (sectionType != SEC_C_SINR_REPORTING) {  /* *NOT* Section Type 9 */
3033
16.9k
            static int * const  remask_flags[] = {
3034
16.9k
                &hf_oran_reMask_re1,
3035
16.9k
                &hf_oran_reMask_re2,
3036
16.9k
                &hf_oran_reMask_re3,
3037
16.9k
                &hf_oran_reMask_re4,
3038
16.9k
                &hf_oran_reMask_re5,
3039
16.9k
                &hf_oran_reMask_re6,
3040
16.9k
                &hf_oran_reMask_re7,
3041
16.9k
                &hf_oran_reMask_re8,
3042
16.9k
                &hf_oran_reMask_re9,
3043
16.9k
                &hf_oran_reMask_re10,
3044
16.9k
                &hf_oran_reMask_re11,
3045
16.9k
                &hf_oran_reMask_re12,
3046
16.9k
                NULL
3047
16.9k
            };
3048
3049
            /* reMask */
3050
16.9k
            uint64_t remask;
3051
16.9k
            proto_tree_add_bitmask_ret_uint64(c_section_tree, tvb, offset,
3052
16.9k
                                              hf_oran_reMask, ett_oran_remask, remask_flags, ENC_BIG_ENDIAN, &remask);
3053
16.9k
            offset++;
3054
            /* numSymbol */
3055
16.9k
            uint32_t numSymbol;
3056
16.9k
            numsymbol_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numSymbol, tvb, offset, 1, ENC_NA, &numSymbol);
3057
16.9k
            if ((sectionType == SEC_C_RRM_MEAS_REPORTS) && (numSymbol != 14)) {     /* Section type 10 must have 14 symbols */
3058
5.24k
                proto_item_append_text(numsymbol_ti, " (for ST10, should be 14!)");
3059
5.24k
                expert_add_info_format(pinfo, numsymbol_ti, &ei_oran_st10_numsymbol_not_14,
3060
5.24k
                                       "numSymbol should be 14 for ST10 - found %u", numSymbol);
3061
5.24k
            }
3062
16.9k
            if ((startSymbolId + numSymbol) > 14) {
3063
                /* Warn if startSymbol + numSymbol would be > 14 */
3064
10.7k
                expert_add_info_format(pinfo, numsymbol_ti, &ei_oran_too_many_symbols,
3065
10.7k
                                       "startSymbolId (%u) + numSymbol (%u) exceeds max of 14",
3066
10.7k
                                       startSymbolId, numSymbol);
3067
10.7k
            }
3068
16.9k
            offset++;
3069
3070
            /* [ef] (extension flag) */
3071
16.9k
            switch (sectionType) {
3072
2.20k
                case SEC_C_UNUSED_RB:         /* Section Type 0 */
3073
3.70k
                case SEC_C_NORMAL:            /* Section Type 1 */
3074
5.35k
                case SEC_C_PRACH:             /* Section Type 3 */
3075
5.75k
                case SEC_C_UE_SCHED:          /* Section Type 5 */
3076
11.2k
                case SEC_C_RRM_MEAS_REPORTS:  /* Section Type 10 */
3077
12.4k
                case SEC_C_REQUEST_RRM_MEAS:  /* Section Type 11 */
3078
12.4k
                    proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
3079
12.4k
                    break;
3080
4.36k
                default:
3081
                    /* Other section types don't support extensions */
3082
4.36k
                    break;
3083
16.9k
            }
3084
3085
16.8k
            write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbc, numPrbc, rb);
3086
16.8k
            proto_item_append_text(sectionHeading, ", Symbols: %2u", numSymbol);
3087
3088
16.8k
            if (numPrbc == 0) {
3089
                /* Special case for all PRBs */
3090
0
                numPrbc = pref_data_plane_section_total_rbs;
3091
0
                startPrbc = 0;  /* may already be 0... */
3092
0
            }
3093
16.8k
        }
3094
236
        else {
3095
            /* Section Type 9 */
3096
236
            write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
3097
236
            proto_item_append_text(sectionHeading, ", numSinrPerPrb: %2u", num_sinr_per_prb);
3098
236
        }
3099
3100
        /* Section type specific fields (after 'numSymbol') */
3101
17.0k
        switch (sectionType) {
3102
2.19k
            case SEC_C_UNUSED_RB:    /* Section Type 0 - Table 7.4.2-1 */
3103
                /* reserved (15 bits) */
3104
2.19k
                add_reserved_field(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2);
3105
2.19k
                offset += 2;
3106
2.19k
                break;
3107
3108
1.50k
            case SEC_C_NORMAL:       /* Section Type 1 - Table 7.4.3-1 */
3109
                /* beamId */
3110
1.50k
                section_beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &section_beamId);
3111
1.50k
                offset += 2;
3112
3113
                /* beamId might get invalidated by e.g., ext-6, ext-11, so unused value will still be shown here.. */
3114
1.50k
                proto_item_append_text(sectionHeading, ", BeamId: %d", section_beamId);
3115
1.50k
                break;
3116
3117
1.65k
            case SEC_C_PRACH:       /* Section Type 3 - Table 7.4.5-1 */
3118
1.65k
            {
3119
                /* beamId */
3120
1.65k
                section_beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &section_beamId);
3121
1.65k
                offset += 2;
3122
3123
                /* freqOffset */
3124
1.65k
                int32_t freqOffset;          /* Yes, this is signed, so the cast is intentional. */
3125
1.65k
                proto_item *freq_offset_item = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN, (uint32_t*)&freqOffset);
3126
1.65k
                freqOffset |= 0xff000000;   /* Must sign-extend */
3127
1.65k
                proto_item_set_text(freq_offset_item, "Frequency offset: %d \u0394f", freqOffset);
3128
1.65k
                offset += 3;
3129
3130
                /* reserved (8 bits) */
3131
1.65k
                add_reserved_field(c_section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3132
1.65k
                offset += 1;
3133
3134
                /* beamId might get invalidated by e.g., ext-6, ext-11, so unused value will still be shown here.. */
3135
1.65k
                proto_item_append_text(sectionHeading, ", BeamId: %d, FreqOffset: %d \u0394f", section_beamId, freqOffset);
3136
1.65k
                break;
3137
0
            }
3138
3139
400
            case SEC_C_UE_SCHED:          /* Section Type 5  - Table 7.4.7-1 */
3140
5.87k
            case SEC_C_RRM_MEAS_REPORTS:  /* Section Type 10 - Table 7.4.12-1 */
3141
                /* ueId */
3142
5.87k
                ueId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_BIG_ENDIAN, &ueId);
3143
5.87k
                offset += 2;
3144
5.87k
                if (ueId == 0x7fff) {
3145
90
                    proto_item_append_text(ueId_ti, " (PRBs not scheduled for eAxC ID in transport header)");
3146
90
                }
3147
5.78k
                else {
3148
5.78k
                    ueids[number_of_ueids++] = ueId;
3149
5.78k
                }
3150
3151
5.87k
                proto_item_append_text(sectionHeading, ", UEId: %d", ueId);
3152
5.87k
                break;
3153
3154
86
            case SEC_C_SINR_REPORTING:   /* Section Type 9 - SINR Reporting */
3155
86
            {
3156
                /* Hidden filter for bf (DMFS-BF) */
3157
86
                proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3158
86
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3159
3160
86
                unsigned bit_offset = offset*8;
3161
3162
                /* sinr iqWidth */
3163
86
                proto_item *iq_width_item = proto_tree_add_uint(c_section_tree, hf_oran_sinrCompHdrIqWidth_pref, tvb, 0, 0, pref_sample_bit_width_sinr);
3164
86
                proto_item_append_text(iq_width_item, " (from preferences)");
3165
86
                proto_item_set_generated(iq_width_item);
3166
3167
                /* sinr compMethod */
3168
86
                proto_item *sinr_comp_meth_item = proto_tree_add_uint(c_section_tree, hf_oran_sinrCompHdrMeth_pref, tvb, 0, 0, pref_iqCompressionSINR);
3169
86
                proto_item_append_text(sinr_comp_meth_item, " (from preferences)");
3170
86
                proto_item_set_generated(sinr_comp_meth_item);
3171
3172
                /* Add SINR entries for each PRB */
3173
2.11k
                for (unsigned prb=startPrbu; prb < startPrbu+numPrbu; prb++) {
3174
                    /* Create a subtree for each PRB */
3175
2.03k
                    proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_sinr_prb,
3176
2.03k
                                                                      tvb, offset, 0, "", "PRB %3u (", prb);
3177
2.03k
                    proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_sinr_prb);
3178
3179
                    /* Each prb starts byte-aligned */
3180
2.03k
                    bit_offset = ((bit_offset+7)/8) * 8;
3181
3182
                    /* N.B., using width/method from UL U-plane preferences, not certain that this is correct.. */
3183
3184
                    /* sinrCompParam (udCompParam format, may be empty) */
3185
2.03k
                    uint32_t exponent = 0;  /* N.B. init to silence warnings, but will always be set if read in COMP_BLOCK_FP case */
3186
2.03k
                    uint16_t sReSMask;
3187
2.03k
                    bit_offset = dissect_udcompparam(tvb, pinfo, prb_tree, bit_offset/8,
3188
2.03k
                                                     pref_iqCompressionSINR, &exponent, &sReSMask,
3189
2.03k
                                                     true) * 8; /* last param is for_sinr */
3190
3191
                    /* sinrValues for this PRB. */
3192
                    /* TODO: not sure how numSinrPerPrb interacts with rb==1... */
3193
6.05k
                    for (unsigned n=0; n < num_sinr_per_prb; n++) {
3194
4.02k
                        unsigned sinr_bits = tvb_get_bits32(tvb, bit_offset, pref_sample_bit_width_sinr, ENC_BIG_ENDIAN);
3195
3196
                        /* Using SINR compression settings from preferences */
3197
4.02k
                        float value = decompress_value(sinr_bits,
3198
4.02k
                                                       pref_iqCompressionSINR, pref_sample_bit_width_sinr,
3199
4.02k
                                                       exponent,
3200
4.02k
                                                       NULL /* no ModCompr for SINR */, 0 /* RE */);
3201
4.02k
                        unsigned sample_len_in_bytes = ((bit_offset%8)+pref_sample_bit_width_sinr+7)/8;
3202
4.02k
                        proto_item *val_ti = proto_tree_add_float(prb_tree, hf_oran_sinr_value, tvb,
3203
4.02k
                                                                   bit_offset/8, sample_len_in_bytes, value);
3204
4.02k
                        proto_item_append_text(prb_ti, " %8f", value);
3205
3206
                        /* Show here which subcarriers share which values (they all divide 12..) */
3207
4.02k
                        if (num_sinr_per_prb == 12) {
3208
1.41k
                            proto_item_append_text(val_ti, " (PRB=%u, subcarrier %u)",
3209
1.41k
                                                   startPrbu+((prb-startPrbu)*(rb+1)), n*(12/num_sinr_per_prb));
3210
1.41k
                        }
3211
2.61k
                        else {
3212
2.61k
                            proto_item_append_text(val_ti, " (PRB=%u, subcarriers %u-%u)",
3213
2.61k
                                                   startPrbu+((prb-startPrbu)*(rb+1)),
3214
2.61k
                                                   n*(12/num_sinr_per_prb), (n+1)*(12/num_sinr_per_prb)-1);
3215
2.61k
                        }
3216
4.02k
                        bit_offset += pref_sample_bit_width_sinr;
3217
4.02k
                    }
3218
3219
                    /* 1-byte alignment per PRB (7.2.11) */
3220
2.03k
                    offset = (bit_offset+7)/8;
3221
2.03k
                    bit_offset = offset*8;
3222
3223
2.03k
                    proto_item_append_text(prb_ti, ")");
3224
2.03k
                    proto_item_set_end(prb_ti, tvb, offset);
3225
2.03k
                }
3226
86
                break;
3227
400
            }
3228
1.22k
            case SEC_C_REQUEST_RRM_MEAS:   /* Section Type 11 - Request RRM Measurements */
3229
                /* Reserved (15 bits) */
3230
1.22k
                add_reserved_field(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2);
3231
1.22k
                offset += 2;
3232
1.22k
                break;
3233
3234
4.36k
            default:
3235
4.36k
                break;
3236
17.0k
        }
3237
17.0k
    }
3238
357
    else if (sectionType == SEC_C_CH_INFO) {   /* Section Type 6 */
3239
        /* ef */
3240
357
        proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
3241
        /* ueId */
3242
357
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_BIG_ENDIAN, &ueId);
3243
357
        offset += 2;
3244
        /* regularizationFactor */
3245
357
        proto_tree_add_item(c_section_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
3246
357
        offset += 2;
3247
        /* reserved (4 bits) */
3248
357
        add_reserved_field(c_section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
3249
        /* rb ("Value=0 shall be set") */
3250
357
        rb_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
3251
357
        if (rb != 0) {
3252
69
            proto_item_append_text(rb_ti, " (should be set to 0)");
3253
69
            expert_add_info(pinfo, rb_ti, &ei_oran_st6_rb_shall_be_0);
3254
69
        }
3255
        /* symInc */
3256
357
        proto_tree_add_item(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
3257
        /* startPrbc */
3258
357
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
3259
357
        offset += 2;
3260
        /* numPrbc */
3261
357
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
3262
357
        offset += 1;
3263
3264
        /* Hidden filter for bf */
3265
357
        proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3266
357
        PROTO_ITEM_SET_HIDDEN(bf_ti);
3267
3268
        /* ciIsample,ciQsample pairs */
3269
357
        unsigned m;
3270
357
        unsigned prb;
3271
357
        uint32_t bit_offset = offset*8;
3272
3273
        /* Antenna count from preference */
3274
357
        unsigned num_trx = pref_num_bf_antennas;
3275
3276
357
        write_channel_section_info(sectionHeading, pinfo,
3277
357
                                   sectionId, ueId, startPrbc, numPrbc, num_trx);
3278
3279
357
        bool first_prb = true;
3280
357
        uint8_t exponent = 0;
3281
1.17k
        for (prb=startPrbc; prb < startPrbc+numPrbc; prb++) {
3282
3283
            /* PRB subtree */
3284
813
            unsigned prb_start_offset = bit_offset;
3285
813
            proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_samples_prb,
3286
813
                                                                 tvb, bit_offset/8, 0,
3287
813
                                                                 "", "PRB=%u", prb);
3288
813
            proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_prb_cisamples);
3289
3290
            /* There may be a ciCompParam here.. */
3291
813
            if (first_prb || ci_comp_opt==1) {
3292
692
                bit_offset = dissect_ciCompParam(tvb, prb_tree, pinfo, bit_offset, ci_comp_meth, &exponent);
3293
692
            }
3294
813
            first_prb = false;
3295
3296
            /* Antennas */
3297
25.0k
            for (m=0; m < num_trx; m++) {
3298
3299
24.2k
                unsigned sample_offset = bit_offset / 8;
3300
24.2k
                uint8_t sample_extent = ((bit_offset + (ci_iq_width*2)) / 8) - sample_offset;
3301
3302
                /* Create subtree for antenna */
3303
24.2k
                proto_item *sample_ti = proto_tree_add_string_format(prb_tree, hf_oran_ciSample,
3304
24.2k
                                                                     tvb, sample_offset, sample_extent,
3305
24.2k
                                                                     "", "TRX=%2u:  ", m);
3306
24.2k
                proto_tree *sample_tree = proto_item_add_subtree(sample_ti, ett_oran_cisample);
3307
3308
                /* I */
3309
                /* Get bits, and convert to float. */
3310
24.2k
                uint32_t bits = tvb_get_bits32(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
3311
24.2k
                float value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent, NULL /* no ModCompr for ST6 */, 0 /* RE */);
3312
3313
                /* Add to tree. */
3314
24.2k
                proto_tree_add_float_format_value(sample_tree, hf_oran_ciIsample, tvb, bit_offset/8, (ci_iq_width+7)/8, value, "#%u=%f", m, value);
3315
24.2k
                bit_offset += ci_iq_width;
3316
24.2k
                proto_item_append_text(sample_ti, "I%u=%f ", m, value);
3317
3318
                /* Q */
3319
                /* Get bits, and convert to float. */
3320
24.2k
                bits = tvb_get_bits32(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
3321
24.2k
                value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent, NULL /* no ModCompr for ST6 */, 0 /* RE */);
3322
3323
                /* Add to tree. */
3324
24.2k
                proto_tree_add_float_format_value(sample_tree, hf_oran_ciQsample, tvb, bit_offset/8, (ci_iq_width+7)/8, value, "#%u=%f", m, value);
3325
24.2k
                bit_offset += ci_iq_width;
3326
24.2k
                proto_item_append_text(sample_ti, "Q%u=%f ", m, value);
3327
24.2k
            }
3328
813
            proto_item_set_len(prb_ti, (bit_offset-prb_start_offset+7)/8);
3329
813
        }
3330
3331
        /* Pad out by 1 or 4 bytes, according to preference */
3332
357
        if (!st6_4byte_alignment) {
3333
263
            offset = (bit_offset + 7) / 8;
3334
263
        }
3335
94
        else {
3336
94
            int mode = bit_offset % 32;
3337
94
            if (mode != 0) {
3338
0
                offset = (bit_offset + (32-mode))/8;
3339
0
            }
3340
94
            else {
3341
94
                offset = bit_offset/8;
3342
94
            }
3343
94
        }
3344
357
        proto_item_set_end(c_section_tree, tvb, offset);
3345
357
    }
3346
3347
3348
17.1k
    expected_section_data_t *data_section = NULL;
3349
17.1k
    unsigned index_to_use = 0;
3350
3351
    /* On first pass, allocate a section entry to use */
3352
17.1k
    if (link_planes_together && !PINFO_FD_VISITED(pinfo)) {
3353
3354
        /* Look for existing entry for sectionId to overwrite first. */
3355
17.0k
        uint8_t direction = !tap_info->uplink;
3356
17.0k
        data_section = wmem_tree_lookup32(state->expected_sections[direction],
3357
17.0k
                                          sectionId);
3358
17.0k
        if (data_section == NULL) {
3359
            /* None, so create */
3360
6.49k
            data_section = wmem_new0(wmem_file_scope(), expected_section_data_t);
3361
6.49k
            wmem_tree_insert32(state->expected_sections[direction],
3362
6.49k
                               sectionId,
3363
6.49k
                               data_section);
3364
6.49k
        }
3365
3366
        /* If 2nd entry not in use, use that one */
3367
17.0k
        if (!data_section->details[1].in_use) {
3368
6.49k
            index_to_use = 1;
3369
6.49k
        }
3370
10.6k
        else {
3371
            /* Both in use, so replace the older of the 2 entries */
3372
10.6k
            if (data_section->details[1].frame_number < data_section->details[0].frame_number) {
3373
1.61k
                index_to_use = 1;
3374
1.61k
            }
3375
10.6k
        }
3376
3377
17.0k
        if (data_section) {
3378
17.0k
            section_details_t *details = &data_section->details[index_to_use];
3379
3380
17.0k
            details->in_use = true;
3381
17.0k
            details->frame = frameId;
3382
17.0k
            details->subframe = subframeId;
3383
17.0k
            details->slot = slotId;
3384
17.0k
            details->startSymbol = startSymbolId;
3385
3386
17.0k
            details->frame_number = pinfo->num;
3387
17.0k
            details->frame_time = pinfo->abs_ts;
3388
17.0k
            data_section->sectionId = sectionId;
3389
17.0k
            details->startPrb = startPrbc;
3390
17.0k
            details->numPrb = numPrbc;
3391
2.40M
            for (unsigned prb = startPrbc; prb <= startPrbc+numPrbc; prb++) {
3392
2.38M
                if (prb < 273) {
3393
1.19M
                    details->beamIds[prb] = section_beamId;
3394
1.19M
                }
3395
2.38M
            }
3396
17.0k
        }
3397
17.0k
    }
3398
3399
17.1k
    bool seen_se10 = false;
3400
17.1k
    uint32_t numPortc = 0;
3401
17.1k
    proto_item *bf_ti = NULL;
3402
3403
    /* Section extension commands */
3404
18.8k
    while (extension_flag) {
3405
2.97k
        int extension_start_offset = offset;
3406
3407
        /* Prefetch extType so can use specific extension type ett */
3408
2.97k
        uint32_t exttype = tvb_get_uint8(tvb, offset) & 0x7f;
3409
2.97k
        uint32_t exttype_ett_index = exttype;
3410
2.97k
        if (exttype == 0 || exttype > HIGHEST_EXTTYPE) {
3411
            /* Just use first one if out of range */
3412
908
            exttype_ett_index = 1;
3413
908
        }
3414
3415
        /* Create subtree for each extension (with summary) */
3416
2.97k
        proto_item *extension_ti = proto_tree_add_string_format(c_section_tree, hf_oran_extension,
3417
2.97k
                                                                tvb, offset, 0, "", "Extension");
3418
2.97k
        proto_tree *extension_tree = proto_item_add_subtree(extension_ti, ett_oran_c_section_extension[exttype_ett_index-1]);
3419
3420
        /* ef (i.e. another extension after this one?) */
3421
2.97k
        proto_tree_add_item_ret_boolean(extension_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
3422
3423
        /* extType */
3424
2.97k
        proto_item *exttype_ti;
3425
2.97k
        exttype_ti = proto_tree_add_item(extension_tree, hf_oran_exttype, tvb, offset, 1, ENC_BIG_ENDIAN);
3426
2.97k
        offset++;
3427
2.97k
        proto_item_append_text(sectionHeading, " (ext-%u)", exttype);
3428
3429
2.97k
        proto_item_append_text(extension_ti, " (ext-%u: %s)", exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"));
3430
3431
        /* Don't tap if out of range. */
3432
2.97k
        if (exttype > 0 && exttype <= HIGHEST_EXTTYPE) {
3433
1.81k
            tap_info->extensions[exttype] = true;
3434
1.81k
        }
3435
3436
        /* Is this SE allowed for this section type? */
3437
2.97k
        if (!se_allowed_in_st(exttype, sectionType)) {
3438
1.15k
            expert_add_info_format(pinfo, extension_tree, &ei_oran_se_on_unsupported_st,
3439
1.15k
                                   "SE %u (%s) should not appear in ST %u (%s)!",
3440
1.15k
                                   exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"),
3441
1.15k
                                   sectionType, rval_to_str_const(sectionType, section_types, "Unknown"));
3442
1.15k
        }
3443
3444
3445
        /* extLen (number of 32-bit words) */
3446
2.97k
        uint32_t extlen_len = ((exttype==11)||(exttype==19)||(exttype==20)) ? 2 : 1;  /* Extensions 11/19/20 are special */
3447
2.97k
        uint32_t extlen;
3448
2.97k
        proto_item *extlen_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_extlen, tvb,
3449
2.97k
                                                             offset, extlen_len, ENC_BIG_ENDIAN, &extlen);
3450
2.97k
        proto_item_append_text(extlen_ti, " (%u bytes)", extlen*4);
3451
2.97k
        offset += extlen_len;
3452
2.97k
        if (extlen == 0) {
3453
561
            expert_add_info(pinfo, extlen_ti, &ei_oran_extlen_zero);
3454
            /* Break out to avoid infinitely looping! */
3455
561
            break;
3456
561
        }
3457
3458
2.97k
        bool ext_unhandled = false;
3459
3460
2.41k
        switch (exttype) {
3461
3462
120
            case 1:  /* SE 1: Beamforming Weights */
3463
120
            {
3464
120
                uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
3465
120
                proto_item *comp_meth_ti = NULL;
3466
3467
                /* Hidden filter for bf */
3468
120
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3469
120
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3470
3471
                /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth) */
3472
120
                offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
3473
120
                                            &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
3474
3475
                /* bfwCompParam */
3476
120
                uint32_t exponent = 0;
3477
120
                bool compression_method_supported = false;
3478
120
                unsigned num_trx = 0;
3479
120
                uint16_t *trx;        /* ptr to array */
3480
120
                offset = dissect_bfwCompParam(tvb, extension_tree, pinfo, offset, comp_meth_ti,
3481
120
                                              &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
3482
120
                                              &num_trx, &trx);
3483
3484
                /* Can't show details of unsupported compression method */
3485
120
                if (!compression_method_supported) {
3486
30
                    break;
3487
30
                }
3488
3489
                /* We know:
3490
                   - iq_width (above)
3491
                   - numBfWeights (taken from preference)
3492
                   - remaining bytes in extension
3493
                   We can therefore derive TRX (number of antennas).
3494
                 */
3495
3496
120
                bool using_array = false;
3497
3498
                /* I & Q samples
3499
                   May know how many entries from activeBeamspaceCoefficientMask. */
3500
90
                if (num_trx == 0) {
3501
                    /* Don't know how many there will be, so just fill available bytes... */
3502
73
                    unsigned weights_bytes = (extlen*4)-3;
3503
73
                    unsigned num_weights_pairs = (weights_bytes*8) / (bfwcomphdr_iq_width*2);
3504
73
                    num_trx = num_weights_pairs;
3505
73
                }
3506
17
                else {
3507
17
                    using_array = true;
3508
17
                    num_trx = pref_num_bf_antennas;
3509
17
                }
3510
3511
90
                int bit_offset = offset*8;
3512
3513
1.37k
                for (unsigned n=0; n < num_trx; n++) {
3514
                    /* Create antenna subtree */
3515
1.28k
                    int bfw_offset = bit_offset / 8;
3516
3517
1.28k
                    uint16_t trx_index = (using_array) ? trx[n] : n+1;
3518
3519
1.28k
                    proto_item *bfw_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfw,
3520
1.28k
                                                                      tvb, bfw_offset, 0, "", "TRX %3u: (", trx_index);
3521
1.28k
                    proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
3522
3523
                    /* I value */
3524
                    /* Get bits, and convert to float. */
3525
1.28k
                    uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3526
1.28k
                    float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent,
3527
1.28k
                                                   NULL /* no ModCompr */, 0 /* RE */);
3528
                    /* Add to tree. */
3529
1.28k
                    proto_tree_add_float(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
3530
1.28k
                                         (bfwcomphdr_iq_width+7)/8, value);
3531
1.28k
                    bit_offset += bfwcomphdr_iq_width;
3532
1.28k
                    proto_item_append_text(bfw_ti, "I=%f ", value);
3533
3534
                    /* Leave a gap between I and Q values */
3535
1.28k
                    proto_item_append_text(bfw_ti, "  ");
3536
3537
                    /* Q value */
3538
                    /* Get bits, and convert to float. */
3539
1.28k
                    bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3540
1.28k
                    value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent,
3541
1.28k
                                             NULL /* no ModCompr */, 0 /* RE */);
3542
                    /* Add to tree. */
3543
1.28k
                    proto_tree_add_float(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
3544
1.28k
                                         (bfwcomphdr_iq_width+7)/8, value);
3545
1.28k
                    bit_offset += bfwcomphdr_iq_width;
3546
1.28k
                    proto_item_append_text(bfw_ti, "Q=%f", value);
3547
3548
1.28k
                    proto_item_append_text(bfw_ti, ")");
3549
1.28k
                    proto_item_set_len(bfw_ti, (bit_offset+7)/8  - bfw_offset);
3550
1.28k
                }
3551
                /* Need to round to next byte */
3552
90
                offset = (bit_offset+7)/8;
3553
3554
90
                break;
3555
120
            }
3556
3557
94
            case 2: /* SE 2: Beamforming attributes */
3558
94
            {
3559
                /* Hidden filter for bf */
3560
94
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3561
94
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3562
3563
                /* bfaCompHdr (get widths of fields to follow) */
3564
94
                uint32_t bfAzPtWidth, bfZePtWidth, bfAz3ddWidth, bfZe3ddWidth;
3565
                /* subtree */
3566
94
                proto_item *bfa_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfaCompHdr,
3567
94
                                                                  tvb, offset, 2, "", "bfaCompHdr");
3568
94
                proto_tree *bfa_tree = proto_item_add_subtree(bfa_ti, ett_oran_bfacomphdr);
3569
3570
                /* reserved (2 bits) */
3571
94
                add_reserved_field(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1);
3572
                /* bfAzPtWidth (3 bits) */
3573
94
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAzPtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAzPtWidth);
3574
                /* bfZePtWidth (3 bits) */
3575
94
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZePtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZePtWidth);
3576
94
                offset += 1;
3577
3578
                /* reserved (2 bits) */
3579
94
                add_reserved_field(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1);
3580
                /* bfAz3ddWidth (3 bits) */
3581
94
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAz3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAz3ddWidth);
3582
                /* bfZe3ddWidth (3 bits) */
3583
94
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZe3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZe3ddWidth);
3584
94
                offset += 1;
3585
3586
94
                unsigned bit_offset = offset*8;
3587
3588
                /* bfAzPt */
3589
94
                if (bfAzPtWidth > 0) {
3590
43
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfAzPt, tvb, bit_offset, bfAzPtWidth+1, ENC_BIG_ENDIAN);
3591
43
                    bit_offset += (bfAzPtWidth+1);
3592
43
                }
3593
                /* bfZePt */
3594
94
                if (bfZePtWidth > 0) {
3595
83
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfZePt, tvb, bit_offset, bfZePtWidth+1, ENC_BIG_ENDIAN);
3596
83
                    bit_offset += (bfZePtWidth+1);
3597
83
                }
3598
                /* bfAz3dd */
3599
94
                if (bfAz3ddWidth > 0) {
3600
37
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfAz3dd, tvb, bit_offset, bfAz3ddWidth+1, ENC_BIG_ENDIAN);
3601
37
                    bit_offset += (bfAz3ddWidth+1);
3602
37
                }
3603
                /* bfZe3dd */
3604
94
                if (bfZe3ddWidth > 0) {
3605
64
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfZe3dd, tvb, bit_offset, bfZe3ddWidth+1, ENC_BIG_ENDIAN);
3606
64
                    bit_offset += (bfZe3ddWidth+1);
3607
64
                }
3608
3609
                /* Pad to next byte (unless last 2 fields already fit in this one) */
3610
94
                if ((bit_offset % 8) > 2) {
3611
64
                    offset = (bit_offset+7) / 8;
3612
64
                }
3613
30
                else {
3614
30
                    offset = bit_offset / 8;
3615
30
                }
3616
3617
                /* bfAzSl (3 bits) */
3618
94
                proto_tree_add_item(extension_tree, hf_oran_bfAzSl, tvb, offset, 1, ENC_BIG_ENDIAN);
3619
                /* bfZeSl (3 bits) */
3620
94
                proto_tree_add_item(extension_tree, hf_oran_bfZeSl, tvb, offset, 1, ENC_BIG_ENDIAN);
3621
94
                offset += 1;
3622
94
                break;
3623
120
            }
3624
3625
84
            case 3: /* SE 3: DL precoding parameters */
3626
84
            {
3627
                /* codebookindex (8 bits) */
3628
                /* "This parameter is not used and shall be set to zero." */
3629
84
                proto_tree_add_item(extension_tree, hf_oran_codebook_index, tvb, offset, 1, ENC_BIG_ENDIAN);
3630
84
                offset += 1;
3631
                /* layerid */
3632
84
                uint32_t layerid;
3633
84
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_layerid, tvb, offset, 1, ENC_BIG_ENDIAN, &layerid);
3634
                /* numLayers */
3635
84
                proto_tree_add_item(extension_tree, hf_oran_numlayers, tvb, offset, 1, ENC_BIG_ENDIAN);
3636
84
                offset += 1;
3637
3638
                /* Stop here for non-first data layer */
3639
84
                if (layerid != 0 && layerid != 0xf) {
3640
18
                    break;
3641
18
                }
3642
3643
                /* First data layer case */
3644
                /* txScheme */
3645
66
                proto_tree_add_item(extension_tree, hf_oran_txscheme, tvb, offset, 1, ENC_BIG_ENDIAN);
3646
                /* crsReMask */
3647
66
                proto_tree_add_item(extension_tree, hf_oran_crs_remask, tvb, offset, 2, ENC_BIG_ENDIAN);
3648
66
                offset += 2;
3649
3650
                /* crsShift (1 bit) */
3651
66
                proto_tree_add_item(extension_tree, hf_oran_crs_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
3652
                /* reserved (3 bits) */
3653
66
                add_reserved_field(extension_tree, hf_oran_reserved_bits123, tvb, offset, 1);
3654
                /* crsSymNum (4 bits) */
3655
66
                proto_tree_add_item(extension_tree, hf_oran_crs_symnum, tvb, offset, 1, ENC_BIG_ENDIAN);
3656
66
                offset += 1;
3657
                /* reserved (8 bits) */
3658
66
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3659
66
                offset += 1;
3660
3661
                /* reserved (1 bit) */
3662
66
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3663
                /* beamIdAP1 (15 bits) */
3664
66
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap1, tvb, offset, 2, ENC_BIG_ENDIAN);
3665
66
                offset += 2;
3666
                /* reserved (1 bit) */
3667
66
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3668
                /* beamIdAP2 (15 bits) */
3669
66
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap2, tvb, offset, 2, ENC_BIG_ENDIAN);
3670
66
                offset += 2;
3671
                /* reserved (1 bit) */
3672
66
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3673
                /* beamIdAP3 (15 bits) */
3674
66
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap3, tvb, offset, 2, ENC_BIG_ENDIAN);
3675
66
                offset += 2;
3676
66
                break;
3677
84
            }
3678
3679
41
            case 4: /* SE 4: Modulation compression params (5.4.7.4) (single sets) */
3680
41
            {
3681
                /* csf */
3682
41
                bool csf;
3683
41
                dissect_csf(extension_tree, tvb, offset*8, ci_iq_width, &csf);
3684
3685
                /* modCompScaler (16 bits) */
3686
41
                uint32_t modCompScaler;
3687
41
                proto_item *ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_modcompscaler,
3688
41
                                                              tvb, offset, 2, ENC_BIG_ENDIAN, &modCompScaler);
3689
41
                offset += 2;
3690
3691
                /* Work out and show floating point value too. exponent and mantissa are both unsigned */
3692
41
                uint16_t exponent = (modCompScaler >> 11) & 0x000f; /* m.s. 4 bits */
3693
41
                uint16_t mantissa = modCompScaler & 0x07ff;         /* l.s. 11 bits */
3694
41
                float value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
3695
41
                proto_item_append_text(ti, " (%f)", value);
3696
3697
41
                section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
3698
3699
                /* Store these params in this flow's state */
3700
41
                if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
3701
40
                    unsigned i = sect_config->num_configs;
3702
40
                    sect_config->configs[i].mod_compr_re_mask = 0xfff;   /* Covers all REs */
3703
40
                    sect_config->configs[i].mod_compr_csf = csf;
3704
40
                    sect_config->configs[i].mod_compr_scaler = value;
3705
40
                    sect_config->num_configs++;
3706
40
                }
3707
41
                break;
3708
84
            }
3709
3710
58
            case 5: /* SE 5: Modulation Compression Additional Parameters (7.7.5) (multiple sets) */
3711
58
            {
3712
                /* Applies only to section types 1,3 and 5 */
3713
                /* N.B. there may be multiple instances of this SE in the same frame */
3714
3715
                /* There may be one or 2 entries, depending upon extlen */
3716
58
                int sets = 1, reserved_bits = 0;
3717
58
                switch (extlen) {
3718
3
                    case 2:
3719
3
                        sets = 1;
3720
3
                        reserved_bits = 20;
3721
3
                        break;
3722
1
                    case 3:
3723
1
                        sets = 2;
3724
1
                        reserved_bits = 24;
3725
1
                        break;
3726
28
                    case 4:
3727
                        /* sets can be 3 or 4, depending upon whether last 28 bits are 0.. */
3728
28
                        if ((tvb_get_ntohl(tvb, offset+10) & 0x0fffffff) == 0) {
3729
7
                            sets = 3;
3730
7
                            reserved_bits = 28;
3731
7
                        }
3732
21
                        else {
3733
21
                            sets = 4;
3734
21
                            reserved_bits = 0;
3735
21
                        }
3736
28
                        break;
3737
3738
26
                    default:
3739
                        /* Malformed error!!! */
3740
26
                        expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
3741
26
                                               "For section 5, extlen must be 2, 3 or 4, but %u was dissected",
3742
26
                                               extlen);
3743
26
                        break;
3744
58
                }
3745
3746
58
                unsigned bit_offset = offset*8;
3747
                /* Dissect each set */
3748
194
                for (int n=0; n < sets; n++) {
3749
                    /* Subtree for each set */
3750
136
                    unsigned set_start_offset = bit_offset/8;
3751
136
                    proto_item *set_ti = proto_tree_add_string(extension_tree, hf_oran_modcomp_param_set,
3752
136
                                                                tvb, set_start_offset, 0, "");
3753
136
                    proto_tree *set_tree = proto_item_add_subtree(set_ti, ett_oran_modcomp_param_set);
3754
3755
136
                    uint64_t mcScaleReMask, mcScaleOffset;
3756
136
                    bool csf;
3757
3758
                    /* mcScaleReMask (12 bits). Defines which REs the following csf and mcScaleOffset apply to */
3759
136
                    static int * const  remask_flags[] = {
3760
136
                        &hf_oran_mc_scale_re_mask_re1,
3761
136
                        &hf_oran_mc_scale_re_mask_re2,
3762
136
                        &hf_oran_mc_scale_re_mask_re3,
3763
136
                        &hf_oran_mc_scale_re_mask_re4,
3764
136
                        &hf_oran_mc_scale_re_mask_re5,
3765
136
                        &hf_oran_mc_scale_re_mask_re6,
3766
136
                        &hf_oran_mc_scale_re_mask_re7,
3767
136
                        &hf_oran_mc_scale_re_mask_re8,
3768
136
                        &hf_oran_mc_scale_re_mask_re9,
3769
136
                        &hf_oran_mc_scale_re_mask_re10,
3770
136
                        &hf_oran_mc_scale_re_mask_re11,
3771
136
                        &hf_oran_mc_scale_re_mask_re12,
3772
136
                        NULL
3773
136
                    };
3774
                    /* Same as above, but offset by 4 bits */
3775
136
                    static int * const  remask_flags_even[] = {
3776
136
                        &hf_oran_mc_scale_re_mask_re1_even,
3777
136
                        &hf_oran_mc_scale_re_mask_re2_even,
3778
136
                        &hf_oran_mc_scale_re_mask_re3_even,
3779
136
                        &hf_oran_mc_scale_re_mask_re4_even,
3780
136
                        &hf_oran_mc_scale_re_mask_re5_even,
3781
136
                        &hf_oran_mc_scale_re_mask_re6_even,
3782
136
                        &hf_oran_mc_scale_re_mask_re7_even,
3783
136
                        &hf_oran_mc_scale_re_mask_re8_even,
3784
136
                        &hf_oran_mc_scale_re_mask_re9_even,
3785
136
                        &hf_oran_mc_scale_re_mask_re10_even,
3786
136
                        &hf_oran_mc_scale_re_mask_re11_even,
3787
136
                        &hf_oran_mc_scale_re_mask_re12_even,
3788
136
                        NULL
3789
136
                    };
3790
3791
                    /* RE Mask (12 bits) */
3792
136
                    proto_tree_add_bitmask_ret_uint64(set_tree, tvb, bit_offset / 8,
3793
136
                                                      (n % 2) ? hf_oran_mc_scale_re_mask_even : hf_oran_mc_scale_re_mask,
3794
136
                                                      ett_oran_mc_scale_remask,
3795
136
                                                      (n % 2) ? remask_flags_even : remask_flags, ENC_BIG_ENDIAN, &mcScaleReMask);
3796
136
                    bit_offset += 12;
3797
3798
                    /* csf (1 bit) */
3799
136
                    bit_offset = dissect_csf(set_tree, tvb, bit_offset, ci_iq_width, &csf);
3800
                    /* mcScaleOffset (15 bits) */
3801
136
                    proto_item *ti = proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_offset, tvb, bit_offset, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
3802
136
                    uint16_t exponent = (mcScaleOffset >> 11) & 0x000f; /* m.s. 4 bits */
3803
136
                    uint16_t mantissa = mcScaleOffset & 0x07ff;         /* l.s. 11 bits */
3804
136
                    float mcScaleOffset_value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
3805
136
                    proto_item_append_text(ti, " (%f)", mcScaleOffset_value);
3806
136
                    bit_offset += 15;
3807
3808
136
                    section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
3809
3810
                    /* Record this config */
3811
136
                    if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
3812
76
                        unsigned i = sect_config->num_configs;
3813
76
                        sect_config->configs[i].mod_compr_re_mask = (uint16_t)mcScaleReMask;
3814
76
                        sect_config->configs[i].mod_compr_csf = csf;
3815
76
                        sect_config->configs[i].mod_compr_scaler = mcScaleOffset_value;
3816
76
                        sect_config->num_configs++;
3817
76
                    }
3818
3819
                    /* Summary */
3820
136
                    proto_item_set_len(set_ti, (bit_offset+7)/8 - set_start_offset);
3821
136
                    proto_item_append_text(set_ti, " (mcScaleReMask=0x%03x  csf=%5s  mcScaleOffset=%f)",
3822
136
                                           (unsigned)mcScaleReMask, tfs_get_true_false(csf), mcScaleOffset_value);
3823
136
                }
3824
3825
58
                proto_item_append_text(extension_ti, " (%u sets)", sets);
3826
3827
                /* Reserved (variable-length) */
3828
58
                if (reserved_bits) {
3829
11
                    proto_tree_add_bits_item(extension_tree, hf_oran_reserved, tvb, bit_offset, reserved_bits, ENC_BIG_ENDIAN);
3830
11
                    bit_offset += reserved_bits;
3831
11
                }
3832
3833
58
                offset = bit_offset/8;
3834
58
                break;
3835
58
            }
3836
3837
96
            case 6: /* SE 6: Non-contiguous PRB allocation in time and frequency domain */
3838
96
            {
3839
                /* numSymbol not used in this case */
3840
96
                if (numsymbol_ti && !numsymbol_ignored) {
3841
91
                    proto_item_append_text(numsymbol_ti, " (ignored)");
3842
91
                    numsymbol_ignored = true;
3843
91
                }
3844
3845
                /* Will update ext6 recorded info */
3846
96
                ext11_settings.ext6_set = true;
3847
3848
                /* TODO: rb bit must be zero (unless "se6-rb-bit-supported" is set) */
3849
3850
                /* repetition (only valid to be set if coupling via frequency and time with priorities (optimized) (7.8.1.5) */
3851
96
                proto_tree_add_bits_item(extension_tree, hf_oran_se6_repetition, tvb, offset*8, 1, ENC_BIG_ENDIAN);
3852
                /* rbgSize (PRBs per bit set in rbgMask) */
3853
96
                uint32_t rbgSize;
3854
96
                proto_item *rbg_size_ti;
3855
96
                rbg_size_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgSize);
3856
96
                if (rbgSize == 0) {
3857
                    /* N.B. this is only true if "se6-rb-bit-supported" is set... */
3858
33
                    expert_add_info(pinfo, rbg_size_ti, &ei_oran_rbg_size_reserved);
3859
33
                }
3860
                /* rbgMask (28 bits) */
3861
96
                uint32_t rbgMask;
3862
96
                proto_item *rbgmask_ti; // = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN, &rbgMask);
3863
96
                offset = dissect_rbg_mask(extension_tree, tvb, offset, &rbgMask, &rbgmask_ti);
3864
96
                if (rbgSize == 0) {
3865
32
                    proto_item_append_text(rbgmask_ti, " (value ignored since rbgSize is 0)");
3866
32
                }
3867
3868
                /* TODO: if receiver detects non-zero bits outside the valid range, those shall be ignored. */
3869
                /* priority (only valid to be set if coupling via frequency and time with priorities (7.8.1.3) */
3870
96
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3871
                /* symbolMask */
3872
96
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
3873
3874
                /* Look up rbg_size enum -> value */
3875
96
                switch (rbgSize) {
3876
32
                    case 0:
3877
                        /* N.B. reserved, but covered above with expert info (would remain 0) */
3878
                        /* Might also indicate that rb bit is valid */
3879
32
                        break;
3880
7
                    case 1:
3881
7
                        ext11_settings.ext6_rbg_size = 1; break;
3882
17
                    case 2:
3883
17
                        ext11_settings.ext6_rbg_size = 2; break;
3884
2
                    case 3:
3885
2
                        ext11_settings.ext6_rbg_size = 3; break;
3886
6
                    case 4:
3887
6
                        ext11_settings.ext6_rbg_size = 4; break;
3888
6
                    case 5:
3889
6
                        ext11_settings.ext6_rbg_size = 6; break;
3890
11
                    case 6:
3891
11
                        ext11_settings.ext6_rbg_size = 8; break;
3892
14
                    case 7:
3893
14
                        ext11_settings.ext6_rbg_size = 16; break;
3894
                    /* N.B., encoded in 3 bits, so no other values are possible */
3895
96
                }
3896
3897
                /* Set to looked-up value */
3898
95
                rbgSize = ext11_settings.ext6_rbg_size;
3899
3900
95
                uint32_t lastRbgid = 0;
3901
95
                if (rbgSize != 0) {
3902
                    /* The O-DU shall not use combinations of startPrbc, numPrbc and rbgSize leading to a value of lastRbgid larger than 27 */
3903
                    /* i.e., leftmost bit used should not need to go off left end of rbgMask! */
3904
64
                    lastRbgid = (uint32_t)ceil((numPrbc + (startPrbc % rbgSize)) / (float)rbgSize) - 1;
3905
64
                    if (lastRbgid > 27) {
3906
4
                        expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_lastRbdid_out_of_range,
3907
4
                                               "SE6: rbgSize (%u) not compatible with startPrbc(%u) and numPrbc(%u)",
3908
4
                                               rbgSize, startPrbc, numPrbc);
3909
4
                        break;
3910
4
                    }
3911
64
                }
3912
3913
                /* Record (and count) which bits are set in rbgMask */
3914
95
                bool first_seen = false;
3915
91
                unsigned first_seen_pos=0, last_seen_pos=0;
3916
2.61k
                for (unsigned n=0; n < 28 && ext11_settings.ext6_num_bits_set < 28; n++) {
3917
2.52k
                    if ((rbgMask >> n) & 0x01) {
3918
1.00k
                        ext11_settings.ext6_bits_set[ext11_settings.ext6_num_bits_set++] = n;
3919
1.00k
                        if (!first_seen) {
3920
86
                            first_seen = true;
3921
86
                            first_seen_pos = n;
3922
86
                        }
3923
1.00k
                        last_seen_pos = n;
3924
1.00k
                    }
3925
2.52k
                }
3926
3927
                /* Show how many bits were set in rbgMask */
3928
91
                proto_item_append_text(rbgmask_ti, " (%u bits set)", ext11_settings.ext6_num_bits_set);
3929
                /* Also, that is the range of bits */
3930
91
                if (first_seen) {
3931
86
                    proto_item_append_text(rbgmask_ti, " (%u bits spread)", last_seen_pos-first_seen_pos+1);
3932
3933
                    /* Complain if last set bit is beyond lastRbgid */
3934
86
                    if (last_seen_pos > lastRbgid) {
3935
83
                        expert_add_info_format(pinfo, rbgmask_ti, &ei_oran_rbgMask_beyond_last_rbdid,
3936
83
                                               "SE6: rbgMask (0x%07x) has bit %u set, but lastRbgId is %u",
3937
83
                                               rbgMask, last_seen_pos, lastRbgid);
3938
83
                    }
3939
86
                }
3940
3941
                /* Also update prbs_for_st10_type5[] */
3942
91
                if (sectionType == 10 && rbgSize != 0) {
3943
                    /* Unset all entries */
3944
40
                    memset(&prbs_for_st10_type5, 0, sizeof(prbs_for_st10_type5));
3945
3946
                    /* Work out which PRB first bit corresponds to */
3947
40
                    unsigned firstPrbStart = (startPrbc/rbgSize) * rbgSize;
3948
3949
                    /* Add PRBs corresponding to each bit set */
3950
1.16k
                    for (unsigned n=0; n < 28 ; n++) {
3951
1.12k
                        if ((rbgMask >> n) & 0x01) {
3952
                            /* Lazy way to clip any values that lie outside of range for section */
3953
4.15k
                            for (unsigned p=0; p < rbgSize; p++) {
3954
3.71k
                                unsigned start = firstPrbStart + (n*rbgSize);
3955
3.71k
                                if ((start+p < MAX_PRBS) && (start+p >= startPrbc) && (start+p <= startPrbc+numPrbc-1)) {
3956
448
                                    prbs_for_st10_type5[start+p] = true;
3957
448
                                }
3958
3.71k
                            }
3959
439
                        }
3960
1.12k
                    }
3961
40
                }
3962
3963
91
                break;
3964
95
            }
3965
3966
23
            case 7: /* SE 7: eAxC mask */
3967
                /* Allow ST0 to address multiple eAxC_ID values for transmission blanking */
3968
23
                proto_tree_add_item(extension_tree, hf_oran_eAxC_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3969
23
                offset += 2;
3970
23
                break;
3971
3972
18
            case 8: /* SE 8: Regularization factor */
3973
18
            {
3974
40
                for (unsigned ueid_index=0; ueid_index < number_of_ueids; ueid_index++) {
3975
                    /* regularizationFactor (2 bytes) */
3976
22
                    proto_item *rf_ti = proto_tree_add_item(extension_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
3977
22
                    proto_item_append_text(rf_ti, " (UeId=%u)", ueids[ueid_index]);
3978
22
                    offset += 2;
3979
22
                }
3980
18
                break;
3981
95
            }
3982
16
            case 9: /* SE 9: Dynamic Spectrum Sharing parameters */
3983
                /* Technology (1 byte) */
3984
16
                proto_tree_add_item(extension_tree, hf_oran_technology, tvb, offset, 1, ENC_BIG_ENDIAN);
3985
16
                offset += 1;
3986
                /* Reserved (1 byte) */
3987
16
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3988
16
                offset += 1;
3989
16
                break;
3990
3991
123
            case 10: /* SE 10: Group configuration of multiple ports */
3992
123
            {
3993
123
                seen_se10 = true;
3994
3995
                /* beamGroupType */
3996
123
                uint32_t beam_group_type = 0;
3997
123
                proto_item *bgt_ti;
3998
123
                bgt_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamGroupType,
3999
123
                                                      tvb, offset, 1, ENC_BIG_ENDIAN, &beam_group_type);
4000
123
                proto_item_append_text(extension_ti, " (%s)", val_to_str_const(beam_group_type, beam_group_type_vals, "Unknown"));
4001
4002
                /* numPortc */
4003
123
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
4004
123
                                             tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
4005
123
                offset++;
4006
4007
                /* Will append all beamId values to extension_ti, regardless of beamGroupType */
4008
123
                unsigned n;
4009
4010
123
                switch (beam_group_type) {
4011
11
                    case 0x0: /* common beam */
4012
13
                    case 0x1: /* beam matrix indication */
4013
                        /* Reserved byte */
4014
13
                        add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4015
13
                        offset++;
4016
4017
                        /* Explain how entries are allocated */
4018
13
                        if (beam_group_type == 0x0) {
4019
11
                            proto_item_append_text(extension_ti, " (all %u ueid/Beam entries are %u)", numPortc, ueId);
4020
11
                        }
4021
2
                        else {
4022
                            /* 'numPortc' consecutive BeamIds from section header */
4023
2
                            proto_item_append_text(extension_ti, " (ueId/beam entries are %u -> %u)", ueId, ueId+numPortc);
4024
2
                        }
4025
4026
13
                        if (sectionType == 5) {
4027
                            /* These types are not allowed */
4028
1
                            expert_add_info_format(pinfo, bgt_ti, &ei_oran_se10_not_allowed,
4029
1
                                                   "SE10: beamGroupType %u is not allowed for section type 5", beam_group_type);
4030
1
                        }
4031
13
                        break;
4032
4033
59
                    case 0x2: /* beam vector listing */
4034
59
                    {
4035
59
                        proto_item_append_text(extension_ti, " [ ");
4036
4037
                        /* Beam listing vector case */
4038
                        /* Work out how many port beam entries there is room for */
4039
                        /* Using numPortC as visible in issue 18116 */
4040
1.74k
                        for (n=0; n < numPortc; n++) {
4041
                            /* 1 reserved bit */
4042
1.68k
                            add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4043
4044
                            /* port beam ID (or UEID) (15 bits) */
4045
1.68k
                            uint32_t id;
4046
1.68k
                            proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
4047
1.68k
                                                                                         tvb, offset, 2, ENC_BIG_ENDIAN, &id);
4048
1.68k
                            proto_item_append_text(beamid_or_ueid_ti, " (or UEId) port #%u", n);
4049
1.68k
                            offset += 2;
4050
4051
1.68k
                            if (id != 0x7fff) {
4052
1.54k
                                if (number_of_ueids < MAX_UEIDS) {
4053
668
                                    ueids[number_of_ueids++] = id;
4054
668
                                }
4055
1.54k
                            }
4056
4057
1.68k
                            proto_item_append_text(extension_ti, "%u ", id);
4058
1.68k
                        }
4059
4060
59
                        proto_item_append_text(extension_ti, "]");
4061
59
                        break;
4062
11
                    }
4063
51
                    case 0x3: /* beamId/ueId listing with associated port-list index */
4064
51
                    {
4065
51
                        proto_item_append_text(extension_ti, " [ ");
4066
4067
51
                        if (numPortc > 0) {
4068
                            /* first portListIndex is outside loop */
4069
51
                            uint32_t port_list_index;
4070
51
                            proto_item *pli_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
4071
51
                                                         offset, 1, ENC_BIG_ENDIAN, &port_list_index);
4072
51
                            if (port_list_index == 0) {
4073
                                /* Value 0 is reserved */
4074
2
                                expert_add_info(pinfo, pli_ti, &ei_oran_port_list_index_zero);
4075
2
                            }
4076
51
                            offset += 1;
4077
4078
1.43k
                            for (n=0; n < numPortc-1; n++) {
4079
                                /* 1 reserved bit */
4080
1.38k
                                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4081
4082
                                /* port beam ID (or UEID) */
4083
1.38k
                                uint32_t id;
4084
1.38k
                                proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
4085
1.38k
                                                                                             tvb, offset, 2, ENC_BIG_ENDIAN, &id);
4086
1.38k
                                proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
4087
1.38k
                                offset += 2;
4088
4089
1.38k
                                if (id != 0x7fff) {
4090
1.15k
                                    if (number_of_ueids < MAX_UEIDS) {
4091
593
                                        ueids[number_of_ueids++] = id;
4092
593
                                    }
4093
1.15k
                                }
4094
4095
                                /* subsequent portListIndex */
4096
1.38k
                                pli_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
4097
1.38k
                                                             offset, 1, ENC_BIG_ENDIAN, &port_list_index);
4098
1.38k
                                if (port_list_index == 0) {
4099
                                    /* Value 0 is reserved */
4100
278
                                    expert_add_info(pinfo, pli_ti, &ei_oran_port_list_index_zero);
4101
278
                                }
4102
1.38k
                                offset += 1;
4103
4104
1.38k
                                proto_item_append_text(extension_ti, "%u:%u ", port_list_index, id);
4105
1.38k
                            }
4106
51
                        }
4107
4108
51
                        proto_item_append_text(extension_ti, "]");
4109
51
                        break;
4110
11
                    }
4111
4112
4113
0
                    default:
4114
                        /* Warning for unsupported/reserved value */
4115
0
                        expert_add_info(NULL, bgt_ti, &ei_oran_se10_unknown_beamgrouptype);
4116
0
                        break;
4117
123
                }
4118
86
                break;
4119
123
            }
4120
4121
149
            case 11: /* SE 11: Flexible Weights Extension Type */
4122
149
            {
4123
                /* Hidden filter for bf */
4124
149
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4125
149
                PROTO_ITEM_SET_HIDDEN(bf_ti);
4126
4127
                /* beamId in section header should be ignored. Guard against appending multiple times.. */
4128
149
                if (section_beamId_ti && !section_beamId_ignored) {
4129
51
                    proto_item_append_text(section_beamId_ti, " (ignored)");
4130
51
                    section_beamId_ignored = true;
4131
51
                }
4132
4133
149
                bool disableBFWs;
4134
149
                uint32_t numBundPrb;
4135
149
                bool rad;
4136
4137
                /* disableBFWs */
4138
149
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
4139
149
                                                tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
4140
149
                if (disableBFWs) {
4141
49
                    proto_item_append_text(extension_ti, " (disableBFWs)");
4142
49
                }
4143
4144
                /* RAD */
4145
149
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_rad,
4146
149
                                    tvb, offset, 1, ENC_BIG_ENDIAN, &rad);
4147
                /* bundleOffset (6 bits) */
4148
149
                proto_tree_add_item(extension_tree, hf_oran_bundle_offset, tvb,
4149
149
                                    offset, 1, ENC_BIG_ENDIAN);
4150
149
                offset++;
4151
4152
                /* numBundPrb (number of prbs in each bundle) */
4153
149
                proto_item *num_bund_prb_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_bund_prbs,
4154
149
                                                                           tvb, offset, 1, ENC_BIG_ENDIAN, &numBundPrb);
4155
149
                offset++;
4156
                /* value zero is reserved.. */
4157
149
                if (numBundPrb == 0) {
4158
9
                    expert_add_info(pinfo, num_bund_prb_ti, &ei_oran_reserved_numBundPrb);
4159
9
                }
4160
4161
149
                uint32_t num_bundles;
4162
149
                bool orphaned_prbs = false;
4163
4164
                /* N.B. glibly assuming that Mu=1 */
4165
149
                uint32_t symbol_count = (frameId*20 + slotId) * 14 + startSymbolId;
4166
4167
149
                if (!disableBFWs) {
4168
                    /********************************************/
4169
                    /* Table 7.7.11.1-1 */
4170
                    /* Weights are present */
4171
                    /********************************************/
4172
4173
100
                    uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
4174
100
                    proto_item *comp_meth_ti = NULL;
4175
4176
                    /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
4177
100
                    offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
4178
100
                                                &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
4179
4180
                    /* Work out number of bundles, but take care not to divide by zero. */
4181
100
                    if (numBundPrb == 0) {
4182
7
                        break;
4183
7
                    }
4184
4185
                    /* Work out bundles! */
4186
                    /* TODO: assuming that these modifying SEs appear before SE 11, but not sure that this is guaranteed?! */
4187
93
                    ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
4188
93
                    num_bundles = ext11_settings.num_bundles;
4189
4190
                    /* Add (complete) bundles */
4191
659
                    for (unsigned b=0; b < num_bundles; b++) {
4192
566
                        offset = dissect_bfw_bundle(tvb, extension_tree, pinfo, offset,
4193
566
                                                    comp_meth_ti, bfwcomphdr_comp_meth,
4194
566
                                                    NULL /* no ModCompr */,
4195
566
                                                    (ext11_settings.ext21_set) ?
4196
0
                                                        numPrbc :
4197
566
                                                        pref_num_bf_antennas,
4198
566
                                                    bfwcomphdr_iq_width,
4199
566
                                                    b,                                 /* bundle number */
4200
566
                                                    &ext11_settings.bundles[b],
4201
566
                                                    symbol_count,
4202
566
                                                    (link_planes_together && data_section) ? &data_section->details[index_to_use] : NULL,
4203
566
                                                    tap_info);
4204
566
                        if (!offset) {
4205
0
                            break;
4206
0
                        }
4207
566
                    }
4208
93
                    if (num_bundles > 0) {
4209
                        /* Set flag from last bundle entry */
4210
16
                        orphaned_prbs = ext11_settings.bundles[num_bundles-1].is_orphan;
4211
16
                    }
4212
93
                }
4213
49
                else {
4214
                    /********************************************/
4215
                    /* Table 7.7.11.1-2 */
4216
                    /* No weights in this case */
4217
                    /********************************************/
4218
4219
                    /* Work out number of bundles, but take care not to divide by zero. */
4220
49
                    if (numBundPrb == 0) {
4221
2
                        break;
4222
2
                    }
4223
4224
47
                    ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
4225
47
                    num_bundles = ext11_settings.num_bundles;
4226
4227
1.23k
                    for (unsigned n=0; n < num_bundles; n++) {
4228
1.18k
                        uint32_t first_prb = ext11_settings.bundles[n].start;
4229
1.18k
                        uint32_t last_prb = ext11_settings.bundles[n].end;
4230
4231
                        /* Still create a bundle subtree */
4232
1.18k
                        proto_item *bundle_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfw_bundle,
4233
1.18k
                                                                 tvb, offset, 2, "",
4234
1.18k
                                                                 "Bundle: (PRBs %3u-%3u)",
4235
1.18k
                                                                 first_prb, last_prb);
4236
1.18k
                        proto_tree *bundle_tree = proto_item_add_subtree(bundle_ti, ett_oran_bfw_bundle);
4237
4238
                        /* contInd */
4239
1.18k
                        proto_tree_add_item(bundle_tree, hf_oran_cont_ind,
4240
1.18k
                                            tvb, offset, 1, ENC_BIG_ENDIAN);
4241
                        /* beamId */
4242
                        /* N.B., only added to tap_info if not 0 or ignored (after SEs seen) */
4243
1.18k
                        uint32_t beam_id;
4244
1.18k
                        proto_item *beamid_ti = proto_tree_add_item_ret_uint(bundle_tree, hf_oran_beam_id,
4245
1.18k
                                                                             tvb, offset, 2, ENC_BIG_ENDIAN, &beam_id);
4246
1.18k
                        proto_item_append_text(bundle_ti, " (beamId:%u)", beam_id);
4247
4248
4249
1.18k
                        if (!ext11_settings.bundles[n].is_orphan) {
4250
623
                            proto_item_append_text(beamid_ti, "    (PRBs %3u-%3u)  (Bundle %2u)",
4251
623
                                                   ext11_settings.bundles[n].start,
4252
623
                                                   ext11_settings.bundles[n].end,
4253
623
                                                   n);
4254
623
                        }
4255
565
                        else {
4256
565
                            orphaned_prbs = true;
4257
565
                            proto_item_append_text(beamid_ti, "    (PRBs %3u-%3u)  (Orphaned PRBs)",
4258
565
                                                   ext11_settings.bundles[n].start,
4259
565
                                                   ext11_settings.bundles[n].end);
4260
565
                            proto_item_append_text(bundle_ti, "  (Orphaned PRBs)");
4261
565
                        }
4262
1.18k
                        offset += 2;
4263
4264
1.18k
                        if (!PINFO_FD_VISITED(pinfo)) {
4265
1.17k
                            if (data_section) {
4266
                                /* Set beamId only for range of PRBs */
4267
28.8k
                                for (unsigned prb = ext11_settings.bundles[n].start; prb <= ext11_settings.bundles[n].end; prb++) {
4268
27.7k
                                    if (prb < 273) {
4269
4.34k
                                        data_section->details[index_to_use].beamIds[prb] = beam_id;
4270
4.34k
                                    }
4271
27.7k
                                }
4272
1.17k
                            }
4273
1.17k
                        }
4274
4275
                        /* Look for where BFWs were sent for this beamId */
4276
1.18k
                        bfw_definition *definition;
4277
4278
1.18k
                        wmem_tree_key_t key[3];
4279
1.18k
                        key[0].length = 1;
4280
1.18k
                        key[0].key = &pinfo->num;
4281
1.18k
                        key[1].length = 1;
4282
1.18k
                        key[1].key = &beam_id;
4283
1.18k
                        key[2].length = 0;
4284
1.18k
                        key[2].key    = NULL;
4285
4286
1.18k
                        if (!PINFO_FD_VISITED(pinfo)) {
4287
                            /* Look up current result */
4288
1.17k
                            definition = wmem_tree_lookup32(dl_beam_ids_defined, beam_id);
4289
1.17k
                            if (definition != NULL) {
4290
                                /* Add to results table for this frame */
4291
330
                                wmem_tree_insert32_array(dl_beam_ids_results, key, definition);
4292
330
                            }
4293
1.17k
                        }
4294
15
                        else {
4295
                            /* Look up from result table */
4296
15
                            definition = wmem_tree_lookup32_array(dl_beam_ids_results, key);
4297
15
                        }
4298
4299
                        /* Show link back to frame where/when beamId was defined. Allow linking to self */
4300
1.18k
                        if (definition && definition->frame_defined != 0) {
4301
330
                            proto_item *defined_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfws_frame_defined, tvb, offset, 0, definition->frame_defined);
4302
330
                            proto_item_set_generated(defined_ti);
4303
330
                            proto_item *since_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfws_symbols_since_defined, tvb, offset, 0,
4304
330
                                                                       symbol_count - definition->symbol_when_defined);
4305
330
                            proto_item_set_generated(since_ti);
4306
330
                        }
4307
858
                        else {
4308
                            /* TODO: lookup needs to find beam if it was defined in this frame!! */
4309
858
                            expert_add_info_format(NULL, beamid_ti, &ei_oran_beamid_bfws_not_found,
4310
858
                                                   "ext11 for beamId %u and disableBFWs set, but can't find definition", beam_id);
4311
858
                        }
4312
1.18k
                    }
4313
4314
47
                }
4315
4316
                /* Add summary to extension root */
4317
140
                if (orphaned_prbs) {
4318
39
                    proto_item_append_text(extension_ti, " (%u full bundles + orphaned)", num_bundles-1);
4319
39
                }
4320
101
                else {
4321
101
                    proto_item_append_text(extension_ti, " (%u bundles)", num_bundles);
4322
101
                }
4323
140
            }
4324
4325
0
                break;
4326
4327
92
            case 12: /* SE 12: Non-Contiguous PRB Allocation with Frequency Ranges */
4328
92
            {
4329
                /* numSymbol not used in this case */
4330
92
                if (numsymbol_ti && !numsymbol_ignored) {
4331
85
                    proto_item_append_text(numsymbol_ti, " (ignored)");
4332
85
                    numsymbol_ignored = true;
4333
85
                }
4334
4335
                /* rb must be zero if this SE is present */
4336
92
                if (rb != 0) {
4337
41
                    expert_add_info(NULL, rb_ti, &ei_oran_se12_rb_set);
4338
41
                }
4339
4340
92
                ext11_settings.ext12_set = true;
4341
4342
                /* priority */
4343
92
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
4344
4345
                /* symbolMask */
4346
92
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
4347
4348
                /* There are now 'R' pairs of (offStartPrb, numPrb) values. Fill extlen bytes with values.  If last one is not set,
4349
                   should be populated with 0s. */
4350
92
                uint32_t extlen_remaining_bytes = (extlen*4) - 4;
4351
92
                uint8_t prb_index;
4352
4353
                /* This is for ST10/ST11.  First pair starts after frames signalled there */
4354
92
                uint16_t st10_st11_offset = startPrbc + numPrbc;
4355
4356
8.48k
                for (prb_index = 1; extlen_remaining_bytes > 0; prb_index++)
4357
8.39k
                {
4358
                    /* Create a subtree for each pair */
4359
8.39k
                    proto_item *pair_ti = proto_tree_add_string(extension_tree, hf_oran_frequency_range,
4360
8.39k
                                                                tvb, offset, 2, "");
4361
8.39k
                    proto_tree *pair_tree = proto_item_add_subtree(pair_ti, ett_oran_frequency_range);
4362
4363
                    /* offStartPrb */
4364
8.39k
                    uint32_t off_start_prb;
4365
8.39k
                    proto_tree_add_item_ret_uint(pair_tree, hf_oran_off_start_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &off_start_prb);
4366
8.39k
                    offset++;
4367
4368
                    /* numPrb */
4369
8.39k
                    uint32_t num_prb;
4370
8.39k
                    proto_tree_add_item_ret_uint(pair_tree, hf_oran_num_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_prb);
4371
8.39k
                    offset++;
4372
4373
8.39k
                    extlen_remaining_bytes -= 2;
4374
4375
                    /* Last pair may be 0,0 if not used. Check for this */
4376
8.39k
                    if ((extlen_remaining_bytes == 0) && (off_start_prb == 0) && (num_prb == 0)) {
4377
3
                        proto_item_append_text(pair_ti, " (not used)");
4378
3
                    }
4379
                    /* Add summary to pair root item, and configure details in ext11_settings */
4380
8.39k
                    else {
4381
8.39k
                        proto_item_append_text(pair_ti, "(%u) [%u : %u]",
4382
8.39k
                                              prb_index, off_start_prb, num_prb);
4383
8.39k
                        proto_item_append_text(extension_ti, "[%u : %u]",
4384
8.39k
                                              off_start_prb, num_prb);
4385
8.39k
                        if (ext11_settings.ext12_num_pairs < MAX_BFW_EXT12_PAIRS) {
4386
5.28k
                            ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs].off_start_prb = off_start_prb;
4387
5.28k
                            ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs++].num_prb = num_prb;
4388
5.28k
                        }
4389
4390
                        /* Also update PRBs to be covered for ST10 type 5 */
4391
                        /* Original range from section is added to.. */
4392
                        /* TODO: I don't think this is quite right.. */
4393
767k
                        for (unsigned prb=st10_st11_offset+off_start_prb; prb < st10_st11_offset+off_start_prb+num_prb; prb++) {
4394
758k
                            if (prb < MAX_PRBS) {
4395
1.74k
                                prbs_for_st10_type5[prb] = true;
4396
1.74k
                            }
4397
758k
                        }
4398
4399
                        /* Any next pair will begin after this one */
4400
8.39k
                        st10_st11_offset += (off_start_prb + num_prb);
4401
8.39k
                    }
4402
8.39k
                }
4403
92
                break;
4404
149
            }
4405
4406
79
            case 13:  /* SE 13: PRB Allocation with Frequency Hopping */
4407
79
            {
4408
                /* Will update settings for ext11 */
4409
79
                ext11_settings.ext13_set = true;
4410
4411
79
                uint32_t extlen_remaining_bytes = (extlen*4) - 2;
4412
79
                uint8_t allocation_index;
4413
4414
79
                unsigned prev_next_symbol_id = 0, prev_next_start_prbc = 0;
4415
4416
6.99k
                for (allocation_index = 1; extlen_remaining_bytes > 0; allocation_index++)
4417
6.91k
                {
4418
                    /* Subtree for allocation */
4419
6.91k
                    proto_item *allocation_ti = proto_tree_add_string(extension_tree, hf_oran_prb_allocation,
4420
6.91k
                                                                tvb, offset, 2, "");
4421
6.91k
                    proto_tree *allocation_tree = proto_item_add_subtree(allocation_ti, ett_oran_prb_allocation);
4422
4423
                    /* Reserved (2 bits) */
4424
6.91k
                    add_reserved_field(allocation_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4425
4426
                    /* nextSymbolId (4 bits) */
4427
6.91k
                    uint32_t next_symbol_id;
4428
6.91k
                    proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextSymbolId, tvb, offset, 1, ENC_BIG_ENDIAN, &next_symbol_id);
4429
4430
                    /* nextStartPrbc (10 bits) */
4431
6.91k
                    uint32_t next_start_prbc;
4432
6.91k
                    proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextStartPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &next_start_prbc);
4433
6.91k
                    offset += 2;
4434
4435
                    /* Add summary to allocation root item */
4436
6.91k
                    proto_item_append_text(allocation_ti, "(%u) nextSymbolId=%3u, nextStartPrbc=%u",
4437
6.91k
                                           allocation_index, next_symbol_id, next_start_prbc);
4438
4439
                    /* Checking for duplicates (expected if e.g. had only 2 entries but extlen bytes still to fill */
4440
6.91k
                    if ((allocation_index > 1) && (next_symbol_id == prev_next_symbol_id) && (next_start_prbc == prev_next_start_prbc)) {
4441
2.21k
                        proto_item_append_text(allocation_ti, " (repeated - to fill up extlen)");
4442
2.21k
                    }
4443
4.69k
                    else {
4444
                        /* Add entry for configuring ext11. don't store out of range */
4445
4.69k
                        if (ext11_settings.ext13_num_start_prbs < MAX_BFW_EXT13_ALLOCATIONS) {
4446
4.10k
                            ext11_settings.ext13_start_prbs[ext11_settings.ext13_num_start_prbs++] = next_start_prbc;
4447
4.10k
                        }
4448
4.69k
                    }
4449
6.91k
                    prev_next_symbol_id = next_symbol_id;
4450
6.91k
                    prev_next_start_prbc = next_start_prbc;
4451
4452
6.91k
                    extlen_remaining_bytes -= 2;
4453
6.91k
                }
4454
79
                break;
4455
149
            }
4456
4457
18
            case 14:  /* SE 14: Nulling-layer Info. for ueId-based beamforming */
4458
                /* Hidden filter for bf (DMRS BF) */
4459
18
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4460
18
                PROTO_ITEM_SET_HIDDEN(bf_ti);
4461
4462
18
                if (!seen_se10) {
4463
16
                    proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
4464
16
                    offset += 1;
4465
16
                    add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4466
16
                    offset += 1;
4467
16
                }
4468
2
                else {
4469
                    /* Loop over numPortc++1 (from SE 10) nullLayerInd fields  */
4470
130
                    for (unsigned port=0; port < numPortc+1; port++) {
4471
128
                        proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
4472
128
                        offset += 1;
4473
128
                    }
4474
2
                }
4475
18
                break;
4476
4477
32
            case 15:  /* SE 15: Mixed-numerology Info. for ueId-based beamforming */
4478
32
            {
4479
                /* frameStructure */
4480
32
                offset = dissect_frame_structure(extension_tree, tvb, offset,
4481
32
                                                 subframeId, slotId);
4482
                /* freqOffset */
4483
32
                proto_tree_add_item(extension_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN);
4484
32
                offset += 3;
4485
                /* cpLength */
4486
32
                proto_item *cplength_ti = proto_tree_add_item(extension_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
4487
32
                if (sectionType != 0 && sectionType != 3) {
4488
10
                    proto_item_append_text(cplength_ti, "  (ignored - used only with ST0 and ST3)");
4489
10
                }
4490
32
                offset += 2;
4491
32
                break;
4492
149
            }
4493
4494
11
            case 16:  /* SE 16: Antenna mapping in UE channel information based UL beamforming */
4495
11
            {
4496
                /* One entry for each UEId */
4497
36
                for (unsigned n=0; n < number_of_ueids; n++) {
4498
                    /* TODO: want to skip if ueId is 0x7fff and beamGroupType = 10b and 'non-scheduled-ueId-enabled'=TRUE */
4499
                    /* antMask */
4500
25
                    proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_antMask, tvb, offset, 8, ENC_BIG_ENDIAN);
4501
25
                    proto_item_append_text(ti, " (RX eAxC #%u, UEId=%u)", n+1, ueids[n]);
4502
25
                    offset += 8;
4503
25
                }
4504
11
                break;
4505
149
            }
4506
4507
11
            case 17:  /* SE 17: Indication of user port group. Applies to ST5 + SE10 with group type 1 (beam matrix indication) */
4508
11
            {
4509
11
                uint32_t extlen_remaining_bytes = (extlen*4) - 2;
4510
11
                uint32_t end_bit = (offset+extlen_remaining_bytes) * 8;
4511
11
                uint32_t ueid_index = 1;
4512
4513
                /* "the preceding Section Type and extension messages implicitly provide the number of scheduled users" */
4514
22
                for (uint32_t bit_offset=offset*8; (bit_offset < end_bit) && (ueid_index <= number_of_ueids); bit_offset+=4, ueid_index++) {
4515
                    /* numUeId (Number of UE Ids per user) */
4516
11
                    proto_item *ti = proto_tree_add_bits_item(extension_tree, hf_oran_num_ueid, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
4517
                    /* TODO: show ueids[ueid_index] here too? */
4518
11
                    proto_item_append_text(ti, " (user #%u)", ueid_index);
4519
11
                }
4520
11
                break;
4521
149
            }
4522
4523
20
            case 18:  /* SE 18: Uplink transmission management */
4524
                /* transmissionWindowOffset */
4525
20
                proto_tree_add_item(extension_tree, hf_oran_transmissionWindowOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
4526
20
                offset += 2;
4527
                /* reserved (2 bits) */
4528
20
                add_reserved_field(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4529
                /* transmissionWindowSize (14 bits) */
4530
20
                proto_tree_add_item(extension_tree, hf_oran_transmissionWindowSize, tvb, offset, 2, ENC_BIG_ENDIAN);
4531
20
                offset += 2;
4532
4533
                /* reserved (6 bits) */
4534
20
                add_reserved_field(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1);
4535
                /* toT (2 bits) */
4536
20
                proto_tree_add_item(extension_tree, hf_oran_toT, tvb, offset, 1, ENC_BIG_ENDIAN);
4537
20
                offset += 1;
4538
20
                break;
4539
4540
71
            case 19:  /* SE 19: Compact beamforming information for multiple port */
4541
71
            {
4542
                /* beamId in section header should be ignored. Guard against appending multiple times.. */
4543
71
                if (section_beamId_ti && !section_beamId_ignored) {
4544
16
                    proto_item_append_text(section_beamId_ti, " (ignored)");
4545
16
                    section_beamId_ignored = true;
4546
16
                }
4547
4548
                /* numSymbol not used in this case */
4549
71
                if (numsymbol_ti && !numsymbol_ignored) {
4550
70
                    proto_item_append_text(numsymbol_ti, " (ignored)");
4551
70
                    numsymbol_ignored = true;
4552
70
                }
4553
4554
                /* disableBFWs */
4555
71
                bool disableBFWs;
4556
71
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
4557
71
                                                tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
4558
71
                if (disableBFWs) {
4559
25
                    proto_item_append_text(extension_ti, " (disableBFWs)");
4560
25
                }
4561
                /* repetition (1 bit) */
4562
71
                uint64_t repetition;
4563
71
                proto_tree_add_bits_ret_val(extension_tree, hf_oran_se19_repetition, tvb, (offset*8)+1, 1, &repetition, ENC_BIG_ENDIAN);
4564
                /* numPortc (6 bits) */
4565
71
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
4566
71
                                             tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
4567
71
                offset++;
4568
4569
                /* priority (2 bits) */
4570
71
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
4571
                /* symbolMask (14 bits) */
4572
71
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
4573
4574
71
                uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
4575
71
                proto_item *comp_meth_ti = NULL;
4576
4577
71
                if (!repetition) {
4578
4579
68
                    if (!disableBFWs) {
4580
                        /* bfwCompHdr */
4581
44
                        offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
4582
44
                                                    &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
4583
44
                    }
4584
4585
                    /* Add entries for each port */
4586
802
                    for (unsigned port=0; port < numPortc; port++) {
4587
4588
                        /* Create subtree for port entry*/
4589
734
                        int port_start_offset = offset;
4590
734
                        proto_item *port_ti = proto_tree_add_string_format(extension_tree, hf_oran_ext19_port,
4591
734
                                                                           tvb, offset, 0,
4592
734
                                                                          "", "Port %u: ", port);
4593
734
                        proto_tree *port_tree = proto_item_add_subtree(port_ti, ett_oran_ext19_port);
4594
4595
                        /* Reserved (4 bits) */
4596
734
                        add_reserved_field(port_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4597
                        /* portReMask (12 bits) */
4598
734
                        proto_tree_add_item(port_tree, hf_oran_portReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4599
734
                        offset += 2;
4600
4601
                        /* Reserved (2 bits) */
4602
734
                        add_reserved_field(port_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4603
                        /* portSymbolMask (14 bits) */
4604
734
                        proto_tree_add_item(port_tree, hf_oran_portSymbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4605
734
                        offset += 2;
4606
4607
                        /* Reserved (1 bit) */
4608
734
                        add_reserved_field(port_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4609
                        /* beamID (15 bits) */
4610
734
                        uint16_t beamId;
4611
734
                        proto_tree_add_item_ret_uint16(port_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
4612
734
                        proto_item_append_text(port_ti, " (beamId=%u)", beamId);
4613
734
                        offset += 2;
4614
4615
                        /* No weights present */
4616
734
                        if (!disableBFWs) {
4617
                            /*******************************************************************/
4618
                            /* Table 7.7.19.1-1 (there is no part -2 for disableBFWs case...), */
4619
                            /* but for SE 11, bfwCompParam was only present for !disableBFWs   */
4620
                            /*******************************************************************/
4621
4622
                            /* bfwCompParam */
4623
265
                            bool compression_method_supported = false;
4624
265
                            uint32_t exponent = 0;
4625
265
                            unsigned num_trx_entries = 0;
4626
265
                            uint16_t *trx;
4627
265
                            offset = dissect_bfwCompParam(tvb, port_tree, pinfo, offset, comp_meth_ti,
4628
265
                                                          &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
4629
265
                                                          &num_trx_entries, &trx);
4630
4631
265
                            int bit_offset = offset*8;
4632
265
                            int bfw_offset;
4633
4634
                            /* Add weights for each TRX */
4635
265
                            unsigned trx_to_add = (num_trx_entries==0) ? pref_num_bf_antennas : num_trx_entries;
4636
7.85k
                            for (unsigned b=0; b < trx_to_add; b++) {
4637
4638
7.59k
                                uint16_t trx_index = (num_trx_entries) ? trx[b] : b+1;
4639
4640
                                /* Create BFW subtree */
4641
7.59k
                                bfw_offset = bit_offset / 8;
4642
7.59k
                                uint8_t bfw_extent = ((bit_offset + (bfwcomphdr_iq_width*2)) / 8) - bfw_offset;
4643
7.59k
                                proto_item *bfw_ti = proto_tree_add_string_format(port_tree, hf_oran_bfw,
4644
7.59k
                                                                                  tvb, bfw_offset, bfw_extent,
4645
7.59k
                                                                                  "", "TRX %u: (", trx_index);
4646
7.59k
                                proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
4647
4648
                                /* I */
4649
7.59k
                                uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4650
7.59k
                                float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr */, 0 /* RE */);
4651
                                /* Add to tree. */
4652
7.59k
                                proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
4653
7.59k
                                                                  (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
4654
7.59k
                                bit_offset += bfwcomphdr_iq_width;
4655
7.59k
                                proto_item_append_text(bfw_ti, "I%u=%f ", b, value);
4656
4657
                                /* Q */
4658
7.59k
                                bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4659
7.59k
                                value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr */, 0 /* RE */);
4660
                                /* Add to tree. */
4661
7.59k
                                proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
4662
7.59k
                                                                  (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
4663
7.59k
                                bit_offset += bfwcomphdr_iq_width;
4664
7.59k
                                proto_item_append_text(bfw_ti, "Q%u=%f)", b, value);
4665
7.59k
                            }
4666
4667
265
                            offset = (bit_offset+7)/8;
4668
265
                        }
4669
469
                        else {
4670
                            /* No weights... */
4671
469
                        }
4672
4673
                        /* Set length of this port entry */
4674
734
                        proto_item_set_len(port_ti, offset-port_start_offset);
4675
734
                    }
4676
68
                }
4677
71
                break;
4678
149
            }
4679
4680
71
            case 20:  /* SE 20: Puncturing extension */
4681
71
            {
4682
                /* numPuncPatterns */
4683
71
                uint32_t numPuncPatterns;
4684
71
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPuncPatterns, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPatterns);
4685
71
                offset += 1;
4686
4687
                /* Add each puncturing pattern */
4688
1.82k
                for (uint32_t n=0; n < numPuncPatterns; n++) {
4689
1.75k
                    unsigned pattern_start_offset = offset;
4690
4691
                    /* Subtree for this puncturing pattern */
4692
1.75k
                    proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_puncPattern,
4693
1.75k
                                                                         tvb, offset, 0,
4694
1.75k
                                                                         "", "Puncturing Pattern: %u/%u", n+1, numPuncPatterns);
4695
1.75k
                    proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_punc_pattern);
4696
4697
                    /* SymbolMask (14 bits) */
4698
1.75k
                    proto_tree_add_item(pattern_tree, hf_oran_symbolMask_ext20, tvb, offset, 2, ENC_BIG_ENDIAN);
4699
1.75k
                    offset += 1;
4700
4701
1.75k
                    uint32_t startPuncPrb, numPuncPrb;
4702
4703
                    /* startPuncPrb (10 bits) */
4704
1.75k
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_startPuncPrb, tvb, offset, 2, ENC_BIG_ENDIAN, &startPuncPrb);
4705
1.75k
                    offset += 2;
4706
                    /* numPuncPrb (8 bits) */
4707
1.75k
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_numPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPrb);
4708
1.75k
                    offset += 1;
4709
4710
1.75k
                    proto_item_append_text(pattern_ti, " [%u->%u]", startPuncPrb, startPuncPrb+numPuncPrb-1);
4711
4712
                    /* Make a hole in range of PRBs to report */
4713
156k
                    for (unsigned p=startPuncPrb; p < startPuncPrb+numPuncPrb; p++) {
4714
154k
                        if (p < MAX_PRBS) {
4715
44.4k
                            prbs_for_st10_type5[p] = false;
4716
44.4k
                        }
4717
154k
                    }
4718
4719
                    /* puncReMask (12 bits) */
4720
1.75k
                    proto_tree_add_item(pattern_tree, hf_oran_puncReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4721
1.75k
                    offset += 1;
4722
                    /* rb (1 bit) */
4723
1.75k
                    proto_item *se20_rb_ti = proto_tree_add_item(pattern_tree, hf_oran_rb, tvb, offset, 1, ENC_BIG_ENDIAN);
4724
                    /* reserved (1 bit) */
4725
1.75k
                    add_reserved_field(pattern_tree, hf_oran_reserved_bit5, tvb, offset, 1);
4726
                    /* multiSDScope (1 bit) */
4727
1.75k
                    proto_tree_add_item(pattern_tree, hf_oran_multiSDScope, tvb, offset, 1, ENC_BIG_ENDIAN);
4728
                    /* rbgIncl (1 bit) */
4729
1.75k
                    bool rbgIncl;
4730
1.75k
                    proto_tree_add_item_ret_boolean(pattern_tree, hf_oran_RbgIncl, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgIncl);
4731
1.75k
                    offset += 1;
4732
4733
1.75k
                    if (rbgIncl) {
4734
                        /* reserved (1 bit) */
4735
585
                        add_reserved_field(pattern_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4736
                        /* rbgSize(3 bits) */
4737
585
                        proto_tree_add_item(pattern_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN);
4738
                        /* rbgMask (28 bits) */
4739
585
                        proto_item *rbgmask_ti;
4740
585
                        uint32_t rbgMask;
4741
585
                        offset = dissect_rbg_mask(pattern_tree, tvb, offset, &rbgMask, &rbgmask_ti);
4742
4743
585
                        proto_item_append_text(se20_rb_ti, " (ignored)");
4744
585
                    }
4745
4746
1.75k
                    proto_item_set_len(pattern_ti, offset-pattern_start_offset);
4747
1.75k
                }
4748
4749
71
                break;
4750
149
            }
4751
21
            case 21:  /* SE 21: Variable PRB group size for channel information */
4752
21
            {
4753
                /* ciPrbGroupSize */
4754
21
                uint32_t ci_prb_group_size;
4755
21
                proto_item *prb_group_size_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_ci_prb_group_size, tvb, offset, 1, ENC_BIG_ENDIAN, &ci_prb_group_size);
4756
21
                offset += 1;
4757
4758
21
                switch (ci_prb_group_size) {
4759
1
                    case 0:
4760
2
                    case 1:
4761
4
                    case 255:
4762
                        /* Reserved value */
4763
4
                        expert_add_info_format(pinfo, prb_group_size_ti, &ei_oran_ci_prb_group_size_reserved,
4764
4
                                               "SE 11 ciPrbGroupSize is reserved value %u - must be 2-254",
4765
4
                                               ci_prb_group_size);
4766
4
                        break;
4767
17
                    default:
4768
                        /* This value affects how SE 11 is interpreted */
4769
17
                        ext11_settings.ext21_set = true;
4770
17
                        ext11_settings.ext21_ci_prb_group_size = ci_prb_group_size;
4771
4772
17
                        if (numPrbc == 0) {
4773
0
                            expert_add_info(pinfo, numprbc_ti, &ei_oran_numprbc_ext21_zero);
4774
0
                        }
4775
17
                        break;
4776
21
                }
4777
4778
                /* reserved (6 bits) */
4779
21
                add_reserved_field(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1);
4780
4781
                /* prgSize (2 bits). Interpretation depends upon section type (5 or 6), but also mplane parameters? */
4782
21
                if (sectionType == SEC_C_UE_SCHED) {             /* Section Type 5 */
4783
1
                    proto_tree_add_item(extension_tree, hf_oran_prg_size_st5, tvb, offset, 1, ENC_BIG_ENDIAN);
4784
1
                }
4785
20
                else if (sectionType == SEC_C_CH_INFO) {         /* Section Type 6 */
4786
1
                    proto_tree_add_item(extension_tree, hf_oran_prg_size_st6, tvb, offset, 1, ENC_BIG_ENDIAN);
4787
1
                }
4788
21
                offset += 1;
4789
21
                break;
4790
21
            }
4791
4792
9
            case 22:  /* SE 22: ACK/NACK request */
4793
9
            {
4794
9
                uint32_t ack_nack_req_id;
4795
9
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_ack_nack_req_id, tvb, offset, 2,
4796
9
                                             ENC_BIG_ENDIAN, &ack_nack_req_id);
4797
9
                offset += 2;
4798
4799
9
                if (state) {
4800
9
                    if (!PINFO_FD_VISITED(pinfo)) {
4801
                        /* Add this request into conversation state on first pass */
4802
9
                        ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
4803
9
                        request_details->request_frame_number = pinfo->num;
4804
9
                        request_details->request_frame_time = pinfo->abs_ts;
4805
9
                        request_details->requestType = SE22;
4806
                        /* Insert into flow's tree */
4807
9
                        wmem_tree_insert32(state->ack_nack_requests, ack_nack_req_id, request_details);
4808
9
                    }
4809
0
                    else {
4810
                        /* Try to link forward to ST8 response */
4811
0
                        ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
4812
0
                                                                          ack_nack_req_id);
4813
0
                        if (response) {
4814
0
                            show_link_to_acknack_response(extension_tree, tvb, pinfo, response);
4815
0
                        }
4816
0
                    }
4817
9
                }
4818
9
                break;
4819
21
            }
4820
4821
85
            case 23:  /* SE 23: Arbitrary symbol pattern modulation compression parameters */
4822
85
            {
4823
                /* Green common header */
4824
4825
                /* numSymPrbPattern (4 bits) */
4826
85
                uint32_t num_sym_prb_pattern;
4827
85
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_sym_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sym_prb_pattern);
4828
                /* reserved (3 bits) */
4829
85
                add_reserved_field(extension_tree, hf_oran_reserved_bits456, tvb, offset, 1);
4830
                /* prbMode (1 bit) */
4831
85
                bool prb_mode;
4832
85
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_prb_mode, tvb, offset, 1, ENC_BIG_ENDIAN, &prb_mode);
4833
85
                offset += 1;
4834
4835
                /* reserved (8 bits) */
4836
85
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4837
85
                offset += 1;
4838
4839
                /* Dissect each SymPrbPattern */
4840
544
                for (uint32_t n=0; n < num_sym_prb_pattern; n++) {
4841
4842
                    /* Subtree */
4843
459
                    proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_sym_prb_pattern,
4844
459
                                                                          tvb, offset, 1, "",
4845
459
                                                                          prb_mode ? "PRB-BLOCK" : "PRB-MASK");
4846
459
                    proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_sym_prb_pattern);
4847
4848
4849
                    /* Orange part */
4850
4851
                    /* Reserved (2 bits) */
4852
459
                    add_reserved_field(pattern_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4853
                    /* symMask (14 bits) */
4854
459
                    proto_tree_add_item(pattern_tree, hf_oran_sym_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
4855
459
                    offset += 2;
4856
                    /* numMcScaleOffset (4 bits) */
4857
459
                    uint32_t numMcScaleOffset;
4858
459
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_num_mc_scale_offset, tvb, offset, 1, ENC_BIG_ENDIAN, &numMcScaleOffset);
4859
4860
459
                    if (!prb_mode) {     /* PRB-MASK */
4861
                        /* prbPattern (4 bits) */
4862
320
                        proto_tree_add_item(pattern_tree, hf_oran_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN);
4863
320
                        offset += 1;
4864
                        /* reserved (8 bits) */
4865
320
                        add_reserved_field(pattern_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4866
320
                        offset += 1;
4867
                        /* reserved (4 bits) */
4868
320
                        add_reserved_field(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4869
320
                    }
4870
139
                    else {               /* PRB-BLOCK */
4871
                        /* prbBlkOffset (8 bits) */
4872
139
                        proto_tree_add_item(pattern_tree, hf_oran_prb_blk_offset, tvb, offset, 2, ENC_BIG_ENDIAN);
4873
139
                        offset += 1;
4874
                        /* prbBlkSize (8 bits) */
4875
139
                        proto_tree_add_item(pattern_tree, hf_oran_prb_blk_size, tvb, offset, 2, ENC_BIG_ENDIAN);
4876
139
                        offset += 1;
4877
139
                    }
4878
4879
2.38k
                    for (unsigned c=0; c < numMcScaleOffset; c++) {
4880
1.93k
                        if (c > 0) {
4881
                            /* reserved (4 bits) */
4882
1.64k
                            add_reserved_field(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4883
1.64k
                        }
4884
4885
1.93k
                        static int * const  remask_flags_even[] = {
4886
1.93k
                            &hf_oran_mc_scale_re_mask_re1_even,
4887
1.93k
                            &hf_oran_mc_scale_re_mask_re2_even,
4888
1.93k
                            &hf_oran_mc_scale_re_mask_re3_even,
4889
1.93k
                            &hf_oran_mc_scale_re_mask_re4_even,
4890
1.93k
                            &hf_oran_mc_scale_re_mask_re5_even,
4891
1.93k
                            &hf_oran_mc_scale_re_mask_re6_even,
4892
1.93k
                            &hf_oran_mc_scale_re_mask_re7_even,
4893
1.93k
                            &hf_oran_mc_scale_re_mask_re8_even,
4894
1.93k
                            &hf_oran_mc_scale_re_mask_re9_even,
4895
1.93k
                            &hf_oran_mc_scale_re_mask_re10_even,
4896
1.93k
                            &hf_oran_mc_scale_re_mask_re11_even,
4897
1.93k
                            &hf_oran_mc_scale_re_mask_re12_even,
4898
1.93k
                            NULL
4899
1.93k
                        };
4900
4901
                        /* mcScaleReMask (12 bits).  Defines which REs the following csf and mcScaleOffset apply to */
4902
1.93k
                        uint64_t mcScaleReMask, mcScaleOffset;
4903
1.93k
                        proto_tree_add_bitmask_ret_uint64(pattern_tree, tvb, offset,
4904
1.93k
                                                          hf_oran_mc_scale_re_mask_even,
4905
1.93k
                                                          ett_oran_mc_scale_remask,
4906
1.93k
                                                          remask_flags_even, ENC_BIG_ENDIAN, &mcScaleReMask);
4907
1.93k
                        offset += 2;
4908
4909
                        /* csf (1 bit) */
4910
1.93k
                        bool csf;
4911
1.93k
                        dissect_csf(pattern_tree, tvb, offset*8, ci_iq_width, &csf);
4912
                        /* mcScaleOffset (15 bits) */
4913
1.93k
                        proto_item *ti = proto_tree_add_bits_ret_val(pattern_tree, hf_oran_mc_scale_offset, tvb, offset*8 + 1, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
4914
1.93k
                        uint16_t exponent = (mcScaleOffset >> 11) & 0x000f; /* m.s. 4 bits */
4915
1.93k
                        uint16_t mantissa = mcScaleOffset & 0x07ff;         /* l.s. 11 bits */
4916
1.93k
                        float mcScaleOffset_value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
4917
1.93k
                        proto_item_append_text(ti, " (%f)", mcScaleOffset_value);
4918
4919
1.93k
                        offset += 2;
4920
4921
                        /* Record this config.  */
4922
                        /* TODO: at some point, will also want to store/use PRB + symbol filters */
4923
1.93k
                        section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
4924
4925
1.93k
                        if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
4926
445
                            unsigned i = sect_config->num_configs;
4927
445
                            sect_config->configs[i].mod_compr_re_mask = (uint16_t)mcScaleReMask;
4928
445
                            sect_config->configs[i].mod_compr_csf = csf;
4929
445
                            sect_config->configs[i].mod_compr_scaler = mcScaleOffset_value;
4930
445
                            sect_config->num_configs++;
4931
445
                        }
4932
1.93k
                    }
4933
4934
459
                    proto_item_set_end(pattern_ti, tvb, offset);
4935
459
                }
4936
85
                break;
4937
21
            }
4938
4939
44
            case 24:   /* SE 24: PUSCH DMRS configuration */
4940
44
            {
4941
                /* Hidden filter for bf (DMRS BF) */
4942
44
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4943
44
                PROTO_ITEM_SET_HIDDEN(bf_ti);
4944
4945
                /* alpnPerSym (1 bit) */
4946
44
                proto_tree_add_item(extension_tree, hf_oran_alpn_per_sym, tvb, offset, 1, ENC_BIG_ENDIAN);
4947
                /* antDmrsSnr (1 bit) */
4948
44
                proto_tree_add_item(extension_tree, hf_oran_ant_dmrs_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
4949
                /* reserved (1 bit) */
4950
44
                add_reserved_field(extension_tree, hf_oran_reserved_bit2, tvb, offset, 1);
4951
                /* userGroupSize (5 bits) */
4952
44
                uint32_t user_group_size;
4953
44
                proto_item *ugs_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_size, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_size);
4954
44
                if (user_group_size == 0) {
4955
18
                    proto_item_append_text(ugs_ti, " (not used)");
4956
18
                }
4957
26
                else if (user_group_size > 12) {
4958
15
                    proto_item_append_text(ugs_ti, " (reserved)");
4959
15
                }
4960
44
                offset += 1;
4961
                /* userGroupId (8 bits)*/
4962
44
                uint32_t user_group_id;
4963
44
                proto_item *ugi_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_id, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_id);
4964
44
                if (user_group_id == 0) {
4965
                    /* TODO: Value 0 can happen in several cases, described in 7.7.24.7.. */
4966
8
                }
4967
44
                if (user_group_id == 255) {
4968
                    /* Value 255 is reserved */
4969
3
                    expert_add_info(pinfo, ugi_ti, &ei_oran_user_group_id_reserved_value);
4970
3
                }
4971
44
                offset += 1;
4972
4973
44
                bool seen_value_to_inherit = false;
4974
44
                bool inherited_config_has_transform_precoding = false;
4975
44
                int dmrs_configs_seen = 0;
4976
4977
                /* Dissect each entry until reach number of configured ueIds (or run out of extlen bytes..) */
4978
44
                uint32_t ueid_index = 0;
4979
166
                while ((offset < (extension_start_offset + extlen*4)) && (ueid_index < number_of_ueids)) {
4980
122
                    dmrs_configs_seen++;
4981
4982
                    /* Subtree */
4983
122
                    proto_item *entry_ti = proto_tree_add_string_format(extension_tree, hf_oran_dmrs_entry,
4984
122
                                                                        tvb, offset, 0, "",
4985
122
                                                                        "Entry");
4986
122
                    proto_tree *entry_tree = proto_item_add_subtree(entry_ti, ett_oran_dmrs_entry);
4987
4988
                    /* entryType (3 bits) */
4989
122
                    uint32_t entry_type;
4990
122
                    proto_item *entry_type_ti;
4991
122
                    entry_type_ti = proto_tree_add_item_ret_uint(entry_tree, hf_oran_entry_type, tvb, offset, 1, ENC_BIG_ENDIAN, &entry_type);
4992
122
                    if (entry_type > 3) {
4993
38
                        proto_item_append_text(entry_type_ti, " (reserved)");
4994
38
                    }
4995
4996
                    /* dmrsPortNumber (5 bits).  Values 0-11 allowed */
4997
122
                    unsigned int dmrs_port_number;
4998
122
                    proto_item *dpn_ti = proto_tree_add_item_ret_uint(entry_tree, hf_oran_dmrs_port_number, tvb, offset, 1, ENC_BIG_ENDIAN, &dmrs_port_number);
4999
122
                    if (dmrs_port_number > 11) {
5000
62
                        proto_item_append_text(dpn_ti, " (12-31 are reserved)");
5001
62
                    }
5002
122
                    offset += 1;
5003
5004
                    /* What follows depends upon entryType */
5005
122
                    switch (entry_type) {
5006
52
                        case 0:    /* dmrsPortNumber config same as previous,  ueId ueIdReset=0 */
5007
61
                        case 1:    /* dmrsPortNumber config same as previous,  ueId ueIdReset=1 */
5008
                            /* No further fields for these */
5009
                            /* Error here if no previous values to inherit!! */
5010
61
                            if (!seen_value_to_inherit) {
5011
28
                                expert_add_info_format(pinfo, entry_type_ti, &ei_oran_se24_nothing_to_inherit,
5012
28
                                                       "SE24: have seen entry type %u, but no previous config (type 2 or 3) to inherit config from", entry_type);
5013
5014
28
                            }
5015
                            /* TODO: would be useful to repeat whole inherited config here? */
5016
61
                            break;
5017
5018
13
                        case 2:    /* transform precoding disabled */
5019
23
                        case 3:    /* transform precoding enabled */
5020
23
                        {
5021
                            /* Type 2/3 are very similar.. */
5022
5023
                            /* ueIdReset (1 bit) */
5024
23
                            proto_tree_add_item(entry_tree, hf_oran_ueid_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
5025
                            /* posMeas (1 bit) */
5026
23
                            proto_tree_add_item(entry_tree, hf_oran_pos_meas, tvb, offset, 1, ENC_BIG_ENDIAN);
5027
5028
                            /* dmrsSymbolMask (14 bits) */
5029
23
                            static int * const  dmrs_symbol_mask_flags[] = {
5030
23
                                &hf_oran_dmrs_symbol_mask_s13,
5031
23
                                &hf_oran_dmrs_symbol_mask_s12,
5032
23
                                &hf_oran_dmrs_symbol_mask_s11,
5033
23
                                &hf_oran_dmrs_symbol_mask_s10,
5034
23
                                &hf_oran_dmrs_symbol_mask_s9,
5035
23
                                &hf_oran_dmrs_symbol_mask_s8,
5036
23
                                &hf_oran_dmrs_symbol_mask_s7,
5037
23
                                &hf_oran_dmrs_symbol_mask_s6,
5038
23
                                &hf_oran_dmrs_symbol_mask_s5,
5039
23
                                &hf_oran_dmrs_symbol_mask_s4,
5040
23
                                &hf_oran_dmrs_symbol_mask_s3,
5041
23
                                &hf_oran_dmrs_symbol_mask_s2,
5042
23
                                &hf_oran_dmrs_symbol_mask_s1,
5043
23
                                &hf_oran_dmrs_symbol_mask_s0,
5044
23
                                NULL
5045
23
                            };
5046
23
                            proto_tree_add_bitmask(entry_tree, tvb, offset,
5047
23
                                                   hf_oran_dmrs_symbol_mask, ett_oran_dmrs_symbol_mask, dmrs_symbol_mask_flags, ENC_BIG_ENDIAN);
5048
23
                            offset += 2;
5049
5050
                            /* scrambling */
5051
23
                            proto_tree_add_item(entry_tree, hf_oran_scrambling, tvb, offset, 2, ENC_BIG_ENDIAN);
5052
23
                            offset += 2;
5053
5054
                            /* nscid (1 bit) */
5055
23
                            proto_tree_add_item(entry_tree, hf_oran_nscid, tvb, offset, 1, ENC_BIG_ENDIAN);
5056
5057
                            /* These 5 bits differ depending upon entry type */
5058
23
                            if (entry_type == 2) {       /* type 2 */
5059
                                /* dType (1 bit) */
5060
13
                                proto_tree_add_item(entry_tree, hf_oran_dtype, tvb, offset, 1, ENC_BIG_ENDIAN);
5061
                                /* cdmWithoutData (2 bits) */
5062
13
                                proto_tree_add_item(entry_tree, hf_oran_cmd_without_data, tvb, offset, 1, ENC_BIG_ENDIAN);
5063
                                /* lambda (2 bits) */
5064
13
                                proto_tree_add_item(entry_tree, hf_oran_lambda, tvb, offset, 1, ENC_BIG_ENDIAN);
5065
13
                            }
5066
10
                            else {                        /* type 3 */
5067
                                /* reserved (1 bit) */
5068
10
                                add_reserved_field(entry_tree, hf_oran_reserved_bit1, tvb, offset, 1);
5069
                                /* lowPaprType (2 bits) */
5070
10
                                proto_tree_add_item(entry_tree, hf_oran_low_papr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
5071
                                /* hoppingMode (2 bits) */
5072
10
                                proto_tree_add_item(entry_tree, hf_oran_hopping_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
5073
10
                            }
5074
5075
                            /* firstPrb (9 bits) */
5076
23
                            proto_tree_add_item(entry_tree, hf_oran_first_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
5077
23
                            offset += 1;
5078
                            /* lastPrb (9 bits) */
5079
23
                            proto_tree_add_item(entry_tree, hf_oran_last_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
5080
23
                            offset += 2;
5081
                            /* Reserved (16 bits) */
5082
23
                            add_reserved_field(entry_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5083
23
                            offset += 2;
5084
5085
                            /* Could now see entry types 0 or 1 - they have these values to inherit */
5086
23
                            seen_value_to_inherit = true;
5087
23
                            inherited_config_has_transform_precoding = (entry_type == 3);
5088
23
                            break;
5089
13
                        }
5090
5091
38
                        default:
5092
                            /* reserved - expert info */
5093
38
                            break;
5094
122
                    }
5095
5096
122
                    proto_item_append_text(entry_ti, " [UEId=%u] (dmrsPortNumber=%2u) (type %u - %s) ",
5097
122
                                           ueids[ueid_index++], dmrs_port_number, entry_type, val_to_str_const(entry_type, entry_type_vals, "Unknown"));
5098
122
                    proto_item_set_end(entry_ti, tvb, offset);
5099
5100
122
                    if (entry_type <= 1) {
5101
61
                        proto_item_append_text(entry_ti, " [transform-precoding %s]",
5102
61
                                               inherited_config_has_transform_precoding ? "enabled" : "disabled");
5103
61
                    }
5104
122
                }
5105
5106
44
                proto_item_append_text(extension_ti, " (%d DMRS configs seen)", dmrs_configs_seen);
5107
44
                break;
5108
44
            }
5109
5110
48
            case 25:  /* SE 25: Symbol reordering for DMRS-BF */
5111
                /* Just dissect each available block of 7 bytes as the 14 symbols for a layer,
5112
                   where each layer could be one or apply to all layers. */
5113
48
            {
5114
                /* TODO: should only appear in one section of a message - check? */
5115
48
                unsigned layer = 0;
5116
48
                proto_item *layer_ti;
5117
1.17k
                while (offset+7 <= (extension_start_offset + extlen*4)) {
5118
                    /* Layer subtree */
5119
1.12k
                    layer_ti = proto_tree_add_string_format(extension_tree, hf_oran_symbol_reordering_layer,
5120
1.12k
                                                            tvb, offset, 7, "",
5121
1.12k
                                                            "Layer");
5122
1.12k
                    proto_tree *layer_tree = proto_item_add_subtree(layer_ti, ett_oran_symbol_reordering_layer);
5123
5124
                    /* All 14 symbols for a layer (or all layers) */
5125
16.5k
                    for (unsigned s=0; s < 14; s++) {
5126
15.3k
                        proto_item *sym_ti;
5127
                        /* txWinForOnAirSymbol */
5128
15.3k
                        unsigned int tx_win_for_on_air_symbol;
5129
15.3k
                        sym_ti = proto_tree_add_item_ret_uint(layer_tree,
5130
15.3k
                                                              (s % 2) ? hf_oran_tx_win_for_on_air_symbol_r : hf_oran_tx_win_for_on_air_symbol_l,
5131
15.3k
                                                              tvb, offset, 1, ENC_BIG_ENDIAN, &tx_win_for_on_air_symbol);
5132
15.3k
                        if (tx_win_for_on_air_symbol == 0x0F) {
5133
                            /* Ordering not affected */
5134
2.01k
                            proto_item_append_text(sym_ti, " (sym %u - no info)", s);
5135
2.01k
                        }
5136
13.3k
                        else {
5137
13.3k
                            proto_item_append_text(sym_ti, " (sym %u)", s);
5138
13.3k
                        }
5139
15.3k
                        if (s % 2) {
5140
7.69k
                            offset += 1;
5141
7.69k
                        }
5142
15.3k
                    }
5143
5144
1.12k
                    proto_item_append_text(layer_ti,     " (layer %u)", ++layer);
5145
1.12k
                    proto_item_append_text(extension_ti, " (layer %u)", layer);
5146
1.12k
                }
5147
                /* Set layer subtree label */
5148
48
                if (layer == 1) {
5149
0
                    proto_item_append_text(layer_ti,     " (all)");
5150
0
                    proto_item_append_text(extension_ti, " (all)");
5151
0
                }
5152
48
                if (layer == 0) {
5153
                    /* TODO: are no layers valid?  What does it mean? */
5154
4
                    proto_item_append_text(extension_ti, " (none)");
5155
4
                }
5156
48
                break;
5157
44
            }
5158
5159
34
            case 26:  /* SE 26: Frequency offset feedback */
5160
                /* Reserved (8 bits) */
5161
34
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5162
34
                offset += 1;
5163
                /* Reserved (1 bit) */
5164
34
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5165
                /* numFoFb (7 bits) */
5166
34
                unsigned num_fo_fb;
5167
34
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_fo_fb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_fo_fb);
5168
34
                offset += 1;
5169
5170
                /* Add each freqOffsetFb value */
5171
731
                for (unsigned n=0; n < num_fo_fb; n++) {
5172
697
                    unsigned freq_offset_fb;
5173
                    /* freqOffsetFb (16 bits) */
5174
697
                    proto_item *offset_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_freq_offset_fb,
5175
697
                                                                         tvb, offset, 2, ENC_BIG_ENDIAN, &freq_offset_fb);
5176
                    /* Show if maps onto a -ve number */
5177
697
                    if ((freq_offset_fb >= 0x8ad0) && (freq_offset_fb <= 0xffff)) {
5178
215
                        proto_item_append_text(offset_ti, "(value %d)", -1 - (0xffff-freq_offset_fb));
5179
215
                    }
5180
697
                    proto_item_append_text(offset_ti, " [#%u]", n+1);
5181
697
                    offset += 2;
5182
697
                }
5183
34
                break;
5184
5185
34
            case 27: /* SE 27: O-DU controlled dimensionality reduction */
5186
34
            {
5187
                /* Hidden filter for bf (DMRS BF) */
5188
34
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
5189
34
                PROTO_ITEM_SET_HIDDEN(bf_ti);
5190
5191
                /* beamType (2 bits) */
5192
34
                unsigned beam_type;
5193
34
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_beam_type, tvb, offset, 1, ENC_BIG_ENDIAN, &beam_type);
5194
                /* reserved (6 bits) */
5195
34
                add_reserved_field(extension_tree, hf_oran_reserved_last_6bits, tvb, offset, 1);
5196
34
                offset += 1;
5197
5198
                /* numElements */
5199
34
                unsigned num_elements;
5200
34
                proto_item *num_elements_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_elements, tvb, offset, 1, ENC_BIG_ENDIAN, &num_elements);
5201
34
                if (num_elements == 0) {
5202
8
                    num_elements = 256;
5203
8
                    proto_item_append_text(num_elements_ti, " (256");
5204
8
                }
5205
5206
34
                offset += 1;
5207
5208
                /* beamId value(s) */
5209
34
                switch (beam_type) {
5210
22
                    case 0:
5211
761
                        for (unsigned n=0; n < num_elements; n++) {
5212
                            /* reserved (1 bit) + beamId */
5213
739
                            add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5214
739
                            proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
5215
739
                            offset += 2;
5216
739
                        }
5217
22
                        break;
5218
6
                    case 1:
5219
                        /* reserved (1 bit) + beamId */
5220
6
                        add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5221
6
                        proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
5222
6
                        offset += 2;
5223
6
                        break;
5224
6
                    default:
5225
                        /* Unknown type... */
5226
6
                        break;
5227
34
                }
5228
23
                break;
5229
34
            }
5230
5231
28
            case 28: /* SE 28: O-DU controlled frequency resolution for SINR reporting */
5232
28
            {
5233
                /* reserved (3 bits) */
5234
28
                add_reserved_field(extension_tree, hf_oran_reserved_3bits, tvb, offset, 1);
5235
                /* numUeSinrRpt (5 bits) */
5236
28
                uint32_t num_ue_sinr_rpt;
5237
28
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_ue_sinr_rpt, tvb, offset, 1, ENC_BIG_ENDIAN, &num_ue_sinr_rpt);
5238
28
                offset += 1;
5239
5240
419
                for (uint32_t n=0; n < num_ue_sinr_rpt; n++) {
5241
                    /* reserved (1 bit) */
5242
391
                    add_reserved_field(extension_tree, (n % 2) ? hf_oran_reserved_bit4 : hf_oran_reserved_1bit,
5243
391
                                       tvb, offset, 1);
5244
5245
                    /* numSinrPerPrb (3 bits).  Taken from alternate nibbles within byte.  */
5246
391
                    proto_tree_add_item(extension_tree, (n % 2) ? hf_oran_num_sinr_per_prb_right : hf_oran_num_sinr_per_prb,
5247
391
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
5248
391
                    if (n % 2) {
5249
189
                        offset += 1;
5250
189
                    }
5251
391
                }
5252
5253
                /* May need to skip beyond half-used byte */
5254
28
                if (num_ue_sinr_rpt % 2) {
5255
11
                    offset += 1;
5256
11
                }
5257
28
                break;
5258
34
            }
5259
5260
14
            case 29: /* SE 29: Cyclic delay adjustment */
5261
                /* reserved (4 bits) */
5262
14
                add_reserved_field(extension_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5263
                /* cdScgSize (4 bits) */
5264
14
                proto_tree_add_item(extension_tree, hf_oran_cd_scg_size, tvb, offset, 1, ENC_BIG_ENDIAN);
5265
14
                offset += 1;
5266
5267
                /* cdScgPhaseStep */
5268
14
                proto_tree_add_item(extension_tree, hf_oran_cd_scg_phase_step, tvb, offset, 1, ENC_BIG_ENDIAN);
5269
14
                offset += 1;
5270
14
                break;
5271
5272
76
            case 30: /* SE 30: PUSCH repetition indication */
5273
76
            {
5274
                /* Only valid for UL */
5275
76
                if (!tap_info->uplink) {
5276
13
                    expert_add_info(pinfo, extension_ti, &ei_oran_se30_not_ul);
5277
13
                }
5278
5279
                /* ueids[], number_of_ueids may have been rewritten by SE10 */
5280
5281
                /* reserved (4 bits) */
5282
76
                add_reserved_field(extension_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5283
                /* numRepUe (4 bits) */
5284
76
                uint8_t num_rep_ue;
5285
76
                proto_tree_add_item_ret_uint8(extension_tree, hf_oran_num_rep_ue, tvb, offset, 1, ENC_BIG_ENDIAN, &num_rep_ue);
5286
76
                offset ++;
5287
                /* reserved (8 bits) */
5288
76
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5289
76
                offset += 1;
5290
5291
76
                if (num_rep_ue == 1) {
5292
                    /* SE10 *not* present.  N.B. this should tally with number_of_ueids being set to only 1? */
5293
                    /* reserved (1 bit) */
5294
7
                    add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5295
                    /* isLastRep (1 bit). Value meaningless here? */
5296
7
                    proto_tree_add_item(extension_tree, hf_oran_is_last_rep, tvb, offset, 1, ENC_BIG_ENDIAN);
5297
                    /* repIndex (6 bits) */
5298
7
                    proto_tree_add_item(extension_tree, hf_oran_rep_index, tvb, offset, 1, ENC_BIG_ENDIAN);
5299
7
                    offset += 1;
5300
5301
                    /* reserved (2 bits) */
5302
7
                    add_reserved_field(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5303
                    /* numReps (6 bits) */
5304
7
                    uint8_t num_reps;
5305
7
                    proto_tree_add_item_ret_uint8(extension_tree, hf_oran_num_reps, tvb, offset, 1, ENC_BIG_ENDIAN, &num_reps);
5306
                    /* TODO: should numReps be 0 here? */
5307
7
                    offset += 1;
5308
5309
                    /* reserved (2 bits) */
5310
7
                    add_reserved_field(extension_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5311
7
                    offset += 2;
5312
5313
7
                }
5314
69
                else {
5315
                    /* SE10 present */
5316
69
                    bool is_last_rep = false;
5317
                    /* TODO: should is_last_rep (also) cause loop exit? */
5318
349
                    for (uint8_t ue_idx=0; (ue_idx < num_rep_ue) && !is_last_rep; ue_idx++) {
5319
                        /* reserved (1 bit) */
5320
280
                        add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5321
                        /* isLastRep (1 bit) */
5322
280
                        proto_tree_add_item_ret_boolean(extension_tree, hf_oran_is_last_rep, tvb, offset, 1, ENC_BIG_ENDIAN, &is_last_rep);
5323
                        /* repIndex (6 bits) */
5324
280
                        proto_tree_add_item(extension_tree, hf_oran_rep_index, tvb, offset, 1, ENC_BIG_ENDIAN);
5325
280
                        offset += 1;
5326
5327
                        /* reserved (2 bits) */
5328
280
                        add_reserved_field(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5329
                        /* numReps (6 bits) */
5330
280
                        uint8_t num_reps;
5331
280
                        proto_item *num_reps_ti = proto_tree_add_item_ret_uint8(extension_tree, hf_oran_num_reps, tvb, offset, 1, ENC_BIG_ENDIAN, &num_reps);
5332
                        /* TODO: values 33-63 are reserved */
5333
280
                        if (num_reps > 32) {
5334
56
                            proto_item_append_text(num_reps_ti, " (reserved)");
5335
56
                        }
5336
280
                        offset += 1;
5337
5338
4.50k
                        for (uint8_t rep=0; rep < num_reps; rep++) {
5339
                            /* reserved (1 bit) */
5340
4.22k
                            add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5341
                            /* repUeId (15 bits) */
5342
                            /* TODO: should be fetching and comparing with ueids[] from SE10? */
5343
4.22k
                            uint16_t ueid;
5344
4.22k
                            proto_item *ueid_ti = proto_tree_add_item_ret_uint16(extension_tree, hf_oran_rep_ueid, tvb, offset, 2, ENC_BIG_ENDIAN, &ueid);
5345
5346
                            /* Check that this ueid is recognised (among ueids[], number_of_ueids) */
5347
4.22k
                            bool matched = false;
5348
28.2k
                            for (unsigned u=0; u < number_of_ueids; u++) {
5349
24.0k
                                if (ueid == ueids[u])
5350
752
                                    matched = true;
5351
24.0k
                            }
5352
4.22k
                            if (!matched) {
5353
3.79k
                                expert_add_info_format(pinfo, ueid_ti, &ei_oran_se30_unknown_ueid,
5354
3.79k
                                                       "SE 30 mentions UEId %u - not seen in SE10", ueid);
5355
3.79k
                            }
5356
4.22k
                            offset += 2;
5357
4.22k
                        }
5358
280
                    }
5359
69
                }
5360
76
                break;
5361
34
            }
5362
16
            case 31: /* SE 31: MCS Information */
5363
16
            {
5364
                /* TODO: show ueid (from ST5 or SE10) as generated field?  Maybe add a subtree for each entry? */
5365
44
                for (uint32_t u=0; u < number_of_ueids; u++) {
5366
                    /* reserved (4 bits) */
5367
28
                    add_reserved_field(extension_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5368
                    /* mcsTable (4 bits) */
5369
28
                    proto_tree_add_item(extension_tree, hf_oran_mcs_table, tvb, offset, 1, ENC_BIG_ENDIAN);
5370
28
                    offset += 1;
5371
5372
                    /* reserved (2 bits) */
5373
28
                    add_reserved_field(extension_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5374
                    /* mcsIndex (6 bits) */
5375
28
                    proto_tree_add_item(extension_tree, hf_oran_mcs_index, tvb, offset, 1, ENC_BIG_ENDIAN);
5376
28
                }
5377
16
                break;
5378
34
            }
5379
5380
45
            case 32: /* SE 32: Rank and TPMI measurement request */
5381
45
            {
5382
                /* reserved (3 bits) */
5383
45
                add_reserved_field(extension_tree, hf_oran_reserved_3bits, tvb, offset, 1);
5384
                /* numMeasReq (5 bits) */
5385
45
                uint8_t num_meas_req;
5386
45
                proto_tree_add_item_ret_uint8(extension_tree, hf_oran_num_meas_req, tvb, offset, 1, ENC_BIG_ENDIAN, &num_meas_req);
5387
45
                offset += 1;
5388
5389
                /* reserved (8 bits) */
5390
45
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5391
45
                offset += 1;
5392
5393
                /* Show each measurement request */
5394
449
                for (unsigned r=0; r < num_meas_req; r++) {
5395
                    /* Reserved (1 bit) */
5396
404
                    add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
5397
                    /* ueId (14 bits) */
5398
404
                    proto_tree_add_item(extension_tree, hf_oran_ueId, tvb, offset, 2, ENC_BIG_ENDIAN);
5399
404
                    offset += 2;
5400
5401
                    /* numOfUeAntPorts (4 bits) */
5402
404
                    proto_tree_add_item(extension_tree, hf_oran_num_of_ue_ant_ports, tvb, offset, 1, ENC_BIG_ENDIAN);
5403
                    /* ueRank (4 bits) */
5404
404
                    proto_tree_add_item(extension_tree, hf_oran_ue_rank, tvb, offset, 1, ENC_BIG_ENDIAN);
5405
404
                    offset += 1;
5406
5407
                    /* codebookSubset (2 bits) */
5408
404
                    proto_tree_add_item(extension_tree, hf_oran_codebook_subset, tvb, offset, 1, ENC_BIG_ENDIAN);
5409
                    /* TODO: tpmiIndex (6 bits) */
5410
404
                    offset += 1;
5411
5412
                    /* fullPwrMode (2 bits) */
5413
404
                    proto_tree_add_item(extension_tree, hf_oran_full_pwr_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
5414
                    /* fullPwrMode2TmpiGroup (14 bits) */
5415
                    /* TODO: add as a bitset */
5416
404
                    proto_tree_add_item(extension_tree, hf_oran_full_pwr_mode_2_tpmi_group, tvb, offset, 2, ENC_BIG_ENDIAN);
5417
404
                    offset += 2;
5418
5419
                    /* reserved (2 bytes) */
5420
404
                    add_reserved_field(extension_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5421
404
                    offset += 2;
5422
404
                }
5423
45
                break;
5424
34
            }
5425
5426
470
            default:
5427
                /* Other/unexpected extension types */
5428
470
                expert_add_info_format(pinfo, exttype_ti, &ei_oran_unhandled_se,
5429
470
                                       "SE %u (%s) not supported by dissector",
5430
470
                                       exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"));
5431
470
                ext_unhandled = true;
5432
470
                break;
5433
2.41k
        }
5434
5435
        /* Check offset compared with extlen.  There should be 0-3 bytes of padding */
5436
1.64k
        int num_padding_bytes = (extension_start_offset + (extlen*4) - offset);
5437
1.64k
        if (!ext_unhandled && ((num_padding_bytes<0) || (num_padding_bytes>3))) {
5438
906
            expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
5439
906
                                   "extlen signalled %u bytes (+ 0-3 bytes padding), but %u were dissected",
5440
906
                                   extlen*4, offset-extension_start_offset);
5441
906
        }
5442
5443
        /* Move offset to beyond signalled length of extension */
5444
1.64k
        offset = extension_start_offset + (extlen*4);
5445
5446
        /* Set length of extension header. */
5447
1.64k
        proto_item_set_len(extension_ti, extlen*4);
5448
1.64k
    }
5449
    /* End of section extension handling */
5450
5451
    /* Tap section beamId if not overwritten by SEs */
5452
16.4k
    if (!section_beamId_ignored && section_beamId != 0) {
5453
2.44k
        add_beam_id_to_tap(tap_info, section_beamId);
5454
2.44k
    }
5455
5456
5457
    /* RRM measurement reports have measurement reports *after* extensions */
5458
16.4k
    if (sectionType == SEC_C_RRM_MEAS_REPORTS)   /* Section Type 10 */
5459
5.18k
    {
5460
        /* Hidden filter for bf (DMFS-BF). No BF weights though.. */
5461
5.18k
        bf_ti = proto_tree_add_item(c_section_tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
5462
5.18k
        PROTO_ITEM_SET_HIDDEN(bf_ti);
5463
5464
5.18k
        bool mf;
5465
6.93k
        do {
5466
            /* Measurement report subtree */
5467
6.93k
            proto_item *mr_ti = proto_tree_add_string_format(c_section_tree, hf_oran_measurement_report,
5468
6.93k
                                                             tvb, offset, 1, "", "Measurement Report");
5469
6.93k
            proto_tree *mr_tree = proto_item_add_subtree(mr_ti, ett_oran_measurement_report);
5470
6.93k
            unsigned report_start_offset = offset;
5471
5472
            /* measurement flag (i.e., more reports after this one) (1 bit) */
5473
6.93k
            proto_tree_add_item_ret_boolean(mr_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
5474
5475
            /* measTypeId (7 bits) */
5476
6.93k
            uint32_t meas_type_id;
5477
6.93k
            proto_item *meas_type_id_ti;
5478
6.93k
            meas_type_id_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_type_id, tvb, offset, 1, ENC_BIG_ENDIAN, &meas_type_id);
5479
6.93k
            offset += 1;
5480
5481
            /* Common to all measurement types */
5482
6.93k
            unsigned num_elements = 0;
5483
6.93k
            if (meas_type_id == 6) {
5484
                /* numElements */
5485
124
                proto_tree_add_item_ret_uint(mr_tree, hf_oran_num_elements, tvb, offset, 1, ENC_BIG_ENDIAN, &num_elements);
5486
124
            }
5487
6.80k
            else {
5488
                /* All other meas ids have a reserved byte */
5489
6.80k
                add_reserved_field(mr_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5490
6.80k
            }
5491
6.93k
            offset += 1;
5492
5493
            /* measDataSize (16 bits). N.B. begins at mf field, i.e. 2 bytes before this one  */
5494
6.93k
            unsigned meas_data_size;
5495
6.93k
            proto_item *meas_data_size_ti;
5496
6.93k
            meas_data_size_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_data_size, tvb, offset, 2, ENC_BIG_ENDIAN, &meas_data_size);
5497
6.93k
            meas_data_size *= 4;
5498
6.93k
            proto_item_append_text(meas_data_size_ti, " (%u bytes)", meas_data_size);
5499
6.93k
            offset += 2;
5500
5501
            /* Summary for measurement report root */
5502
6.93k
            proto_item_append_text(mr_ti, " (measTypeId=%u - %s)",
5503
6.93k
                                   meas_type_id, val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
5504
            /* And section header */
5505
6.93k
            proto_item_append_text(tree, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
5506
            /* And Info column */
5507
6.93k
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
5508
5509
            /* Handle specific message type fields */
5510
6.93k
            switch (meas_type_id) {
5511
276
                case 1:
5512
276
                {
5513
                    /* ueTae */
5514
276
                    unsigned ue_tae;
5515
276
                    proto_item *ue_tae_ti;
5516
276
                    ue_tae_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_tae, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_tae);
5517
                    /* Show if maps onto a -ve number */
5518
276
                    if ((ue_tae >= 0x8ad0) && (ue_tae <= 0xffff)) {
5519
40
                        proto_item_append_text(ue_tae_ti, "(value %d)", -1 - (0xffff-ue_tae));
5520
40
                    }
5521
276
                    offset += 2;
5522
5523
                    /* Reserved (16 bits) */
5524
276
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5525
276
                    offset += 2;
5526
276
                    break;
5527
0
                }
5528
81
                case 2:
5529
                    /* ueLayerPower entries, one for each UEId */
5530
                    /* i.e., should loop over 0-number_of_ues? */
5531
187
                    for (unsigned ueid_index=0; ueid_index < number_of_ueids; ueid_index++) {
5532
106
                        unsigned ue_layer_power;
5533
106
                        proto_item *ue_layer_power_ti;
5534
                        /* ueLayerPower */
5535
106
                        ue_layer_power_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_layer_power, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_layer_power);
5536
                        /* Show if maps onto a -ve number */
5537
106
                        if ((ue_layer_power >= 0x8ad0) && (ue_layer_power <= 0xffff)) {
5538
30
                            proto_item_append_text(ue_layer_power_ti, "(value %d) (ueId=%u)", -1 - (0xffff-ue_layer_power), ueids[ueid_index]);
5539
30
                        }
5540
106
                        offset += 2;
5541
106
                    }
5542
                    /* padding out to 4 bytes */
5543
81
                    break;
5544
79
                case 3:
5545
79
                {
5546
                    /* ueFreqOffset */
5547
79
                    unsigned ue_freq_offset;
5548
79
                    proto_item *ue_freq_offset_ti;
5549
79
                    ue_freq_offset_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_freq_offset, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_freq_offset);
5550
                    /* Show if maps onto a -ve number */
5551
79
                    if ((ue_freq_offset >= 0x8ad0) && (ue_freq_offset <= 0xffff)) {
5552
14
                        proto_item_append_text(ue_freq_offset_ti, "(value %d)", -1 - (0xffff-ue_freq_offset));
5553
14
                    }
5554
79
                    offset += 2;
5555
5556
                    /* currUeFreqOffset (16 bits) */
5557
79
                    unsigned curr_ue_freq_offset;
5558
79
                    proto_item *curr_ue_freq_offset_ti;
5559
79
                    curr_ue_freq_offset_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_curr_ue_freq_offset, tvb, offset, 2, ENC_BIG_ENDIAN, &curr_ue_freq_offset);
5560
                    /* Show if maps onto a -ve number */
5561
79
                    if ((curr_ue_freq_offset >= 0x8ad0) && (curr_ue_freq_offset <= 0xffff)) {
5562
15
                        proto_item_append_text(curr_ue_freq_offset_ti, "(value %d)", -1 - (0xffff-curr_ue_freq_offset));
5563
15
                    }
5564
79
                    offset += 2;
5565
79
                    break;
5566
0
                }
5567
128
                case 4:
5568
194
                case 5:
5569
                    /* reserved (2 bits) */
5570
194
                    add_reserved_field(mr_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5571
                    /* symbolMask (14 bits) */
5572
194
                    offset = dissect_symbolmask(tvb, mr_tree, offset, NULL, NULL);
5573
5574
                    /* 2 bytes for each PRB ipnPower */
5575
48.2k
                    for (unsigned prb=0; prb<MAX_PRBS; prb++) {
5576
                        /* Skip if should not be reported */
5577
48.0k
                        if (!prbs_for_st10_type5[prb]) {
5578
46.1k
                            continue;
5579
46.1k
                        }
5580
1.89k
                        unsigned ipn_power;
5581
1.89k
                        proto_item *ipn_power_ti;
5582
                        /* ipnPower (2 bytes) */
5583
1.89k
                        ipn_power_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ipn_power, tvb, offset, 2, ENC_BIG_ENDIAN, &ipn_power);
5584
1.89k
                        proto_item_append_text(ipn_power_ti, " (PRB %3d)", prb);
5585
                        /* Show if maps onto a -ve number */
5586
1.89k
                        if ((ipn_power >= 0x8ad0) && (ipn_power <= 0xffff)) {
5587
379
                            proto_item_append_text(ipn_power_ti, " (value %d)", -1 - (0xffff-ipn_power));
5588
379
                        }
5589
1.89k
                        offset += 2;
5590
1.89k
                    }
5591
                    /* padding out to 4 bytes */
5592
194
                    break;
5593
124
                case 6:
5594
                    /* antDmrsSnrVal entries */
5595
2.45k
                    for (unsigned n=0; n < num_elements; n++) {
5596
2.32k
                        unsigned snr_value;
5597
2.32k
                        proto_item *snr_value_ti;
5598
                        /* antDmrsSnrVal (2 bytes) */
5599
2.32k
                        snr_value_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ant_dmrs_snr_val, tvb, offset, 2, ENC_BIG_ENDIAN, &snr_value);
5600
2.32k
                        proto_item_append_text(snr_value_ti, " (elem %2u)", n+1);
5601
                        /* Show if maps onto a -ve number */
5602
2.32k
                        if ((snr_value >= 0x8ad0) && (snr_value <= 0xffff)) {
5603
672
                            proto_item_append_text(snr_value_ti, " (value %d)", -1 - (0xffff-snr_value));
5604
672
                        }
5605
2.32k
                        offset += 2;
5606
2.32k
                    }
5607
124
                    break;
5608
341
                case 7:
5609
341
                {
5610
                    /* UE positioning measurement report */
5611
341
                    float start_value;
5612
5613
                    /* ueAzAoa (16 bits) */
5614
341
                    uint32_t ue_az_aoa;
5615
341
                    proto_item *ue_az_aoa_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_az_aoa, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_az_aoa);
5616
341
                    if (ue_az_aoa <= 0xE0F) {
5617
282
                        if (ue_az_aoa >= 0x0708) {
5618
21
                            start_value = (ue_az_aoa-0x0708) * (float)0.1;
5619
21
                            proto_item_append_text(ue_az_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
5620
21
                        }
5621
261
                        else {
5622
261
                            start_value = 180 + (ue_az_aoa * (float)0.1);
5623
261
                            proto_item_append_text(ue_az_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
5624
261
                        }
5625
282
                    }
5626
59
                    else if (ue_az_aoa == 0xffff) {
5627
16
                        proto_item_append_text(ue_az_aoa_ti, " (invalid measurement result)");
5628
16
                    }
5629
43
                    else {
5630
43
                        proto_item_append_text(ue_az_aoa_ti, " (reserved)");
5631
43
                    }
5632
341
                    offset += 2;
5633
5634
                    /* Reserved (16 bits) */
5635
341
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5636
341
                    offset += 2;
5637
5638
                    /* ueZeAoa (16 bits) */
5639
341
                    uint32_t ue_ze_aoa;
5640
341
                    proto_item *ue_ze_aoa_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_ze_aoa, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_ze_aoa);
5641
341
                    if (ue_ze_aoa <= 0x707) {
5642
248
                        start_value = ue_ze_aoa * (float)0.1;
5643
248
                        proto_item_append_text(ue_ze_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
5644
248
                    }
5645
93
                    else if (ue_az_aoa == 0xffff) {
5646
15
                        proto_item_append_text(ue_ze_aoa_ti, " (invalid measurement result)");
5647
15
                    }
5648
78
                    else {
5649
78
                        proto_item_append_text(ue_ze_aoa_ti, " (reserved)");
5650
78
                    }
5651
341
                    offset += 2;
5652
5653
                    /* Reserved (16 bits) */
5654
341
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5655
341
                    offset += 2;
5656
5657
                    /* uePosToaOffset (16 bits) */
5658
341
                    uint32_t ue_pos_toa_offset;
5659
341
                    proto_item *ue_pos_toa_offset_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_pos_toa_offset, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_pos_toa_offset);
5660
341
                    if (ue_pos_toa_offset == 0) {
5661
60
                        proto_item_append_text(ue_pos_toa_offset_ti, " (no UE ToA offset, 0 symbols)");
5662
60
                    }
5663
281
                    else if (ue_pos_toa_offset <= 0x7fff) {
5664
224
                        proto_item_append_text(ue_pos_toa_offset_ti, " (+ve UE ToA offset)");
5665
224
                    }
5666
57
                    else if (ue_pos_toa_offset == 0x8000) {
5667
8
                        proto_item_append_text(ue_pos_toa_offset_ti, " (invalid measurement result)");
5668
8
                    }
5669
49
                    else {
5670
49
                        proto_item_append_text(ue_pos_toa_offset_ti, " (-ve UE ToA offset)");
5671
49
                    }
5672
341
                    offset += 2;
5673
5674
                    /* Reserved (16 bits) */
5675
341
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5676
341
                    offset += 2;
5677
341
                    break;
5678
128
                }
5679
108
                case 8:
5680
108
                {
5681
                    /* UE radial speed measurement report */
5682
5683
                    /* ueRadialSpeed (16 bits) */
5684
108
                    uint32_t radial_speed;
5685
108
                    proto_item *radial_speed_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_radial_speed, tvb, offset, 2, ENC_BIG_ENDIAN, &radial_speed);
5686
108
                    if (radial_speed <= 10000) {
5687
51
                        proto_item_append_text(radial_speed_ti, " (%.1f km/h)", radial_speed * (float)0.1);
5688
51
                    }
5689
57
                    else if (radial_speed == 0x8000) {
5690
0
                        proto_item_append_text(radial_speed_ti, " (invalid measurement result)");
5691
0
                    }
5692
57
                    else {
5693
57
                        proto_item_append_text(radial_speed_ti, " (reserved value)");
5694
57
                    }
5695
108
                    offset += 2;
5696
5697
                    /* Reserved (16 bits) */
5698
108
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5699
108
                    offset += 2;
5700
108
                    break;
5701
128
                }
5702
47
                case 9:
5703
47
                {
5704
                    /* TODO: UE post-equalization MU interference measurement */
5705
5706
                    /* reserved (16 bits) */
5707
47
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5708
47
                    offset += 2;
5709
5710
                    /* TODO: muInterferenceLevel (all layers * all PRB blocks) */
5711
47
                    break;
5712
128
                }
5713
116
                case 10:
5714
116
                {
5715
                    /* UE TPMI and rank recommendation measurement */
5716
5717
                    /* numCandRanks (4 bits - only 1-4 valid) */
5718
116
                    uint8_t num_cand_ranks;
5719
116
                    proto_tree_add_item_ret_uint8(mr_tree, hf_oran_num_cand_ranks, tvb, offset, 1, ENC_NA, &num_cand_ranks);
5720
116
                    if (num_cand_ranks > 4) {
5721
33
                        num_cand_ranks = 4;
5722
33
                    }
5723
116
                    if (num_cand_ranks < 1) {
5724
59
                        num_cand_ranks = 1;
5725
59
                    }
5726
5727
                    /* uePrefRank (4 bits) */
5728
116
                    add_reserved_field(mr_tree, hf_oran_ue_pref_rank, tvb, offset, 1);
5729
116
                    offset += 1;
5730
5731
366
                    for (uint8_t cand_rank=1; cand_rank <= num_cand_ranks; cand_rank++) {
5732
                        /* ueTpmiRankY (1 byte) */
5733
250
                        proto_item *rank_y_ti = proto_tree_add_item(mr_tree, hf_oran_ue_tpmi_rank_y,
5734
250
                                                                    tvb, offset, 1, ENC_BIG_ENDIAN);
5735
250
                        proto_item_append_text(rank_y_ti, " (rank %u)", cand_rank);
5736
5737
250
                        offset += 1;
5738
5739
752
                        for (uint8_t sinr = 1; sinr <= cand_rank; sinr++) {
5740
                            /* ueTpmiRankYSinrLX (2 bytes) */
5741
502
                            proto_item *rank_y_sinr_x_ti = proto_tree_add_item(mr_tree, hf_oran_ue_tpmi_rank_y_sinr_lx,
5742
502
                                                                        tvb, offset, 2, ENC_BIG_ENDIAN);
5743
502
                            proto_item_append_text(rank_y_sinr_x_ti, " (rank %u, sinr %u)", cand_rank, sinr);
5744
502
                            offset += 2;
5745
502
                        }
5746
250
                    }
5747
116
                    break;
5748
128
                }
5749
20
                case 11:
5750
20
                {
5751
                    /* UE layer pre-equalization SINR report */
5752
                    /* TODO: how to know how many layers? Just fill up available data? */
5753
20
                    unsigned num_layers = (meas_data_size-1) * 4;
5754
1.11k
                    for (unsigned layer=0; layer < num_layers; layer++) {
5755
                        /* ueLayerPreEqSinr (2 bytes each) */
5756
1.09k
                        proto_item *pre_eq_sinr_ti = proto_tree_add_item(mr_tree, hf_oran_ue_layer_pre_eq_sinr,
5757
1.09k
                                                                    tvb, offset, 2, ENC_BIG_ENDIAN);
5758
1.09k
                        proto_item_append_text(pre_eq_sinr_ti, " (layer %u)", layer);
5759
1.09k
                        offset += 2;
5760
1.09k
                    }
5761
20
                    break;
5762
128
                }
5763
5764
5.41k
                default:
5765
                    /* Anything else is not expected */
5766
5.41k
                    expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
5767
5.41k
                                           "measTypeId %u (%s) not supported - only 1-6 are expected",
5768
5.41k
                                           meas_type_id,
5769
5.41k
                                           val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
5770
5.41k
                    break;
5771
5772
6.93k
            }
5773
5774
            /* Pad out to next 4 bytes */
5775
6.72k
            offset += WS_PADDING_TO_4(offset-report_start_offset);
5776
5777
            /* TODO: verify dissected size of report vs meas_data_size? */
5778
5779
            /* End of measurement report tree */
5780
6.72k
            proto_item_set_end(mr_ti, tvb, offset);
5781
6.72k
        } while (mf);
5782
5.18k
    }
5783
5784
    /*  Request for RRM Measurements has measurement commands after extensions */
5785
11.2k
    else if (sectionType == SEC_C_REQUEST_RRM_MEAS)               /* Section Type 11 */
5786
1.14k
    {
5787
1.14k
        bool mf = true;
5788
1.78k
        do {
5789
            /* Measurement command subtree */
5790
1.78k
            proto_item *mc_ti = proto_tree_add_string_format(c_section_tree, hf_oran_measurement_command,
5791
1.78k
                                                             tvb, offset, 8, "", "Measurement Command");
5792
1.78k
            proto_tree *mc_tree = proto_item_add_subtree(mc_ti, ett_oran_measurement_command);
5793
5794
            /* mf (1 bit).  1st measurement command is always preset */
5795
1.78k
            proto_tree_add_item_ret_boolean(mc_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
5796
5797
            /* measTypeId (7 bits) */
5798
1.78k
            uint32_t meas_type_id;
5799
1.78k
            proto_item *meas_type_id_ti;
5800
1.78k
            meas_type_id_ti = proto_tree_add_item_ret_uint(mc_tree, hf_oran_meas_type_id, tvb, offset, 1, ENC_BIG_ENDIAN, &meas_type_id);
5801
1.78k
            offset += 1;
5802
5803
1.78k
            proto_item *meas_command_ti;
5804
1.78k
            uint32_t meas_command_size;
5805
5806
1.78k
            switch (meas_type_id) {
5807
99
                case 5:                           /* command for IpN for unallocated PRBs */
5808
                    /* reserved (1 byte) */
5809
99
                    add_reserved_field(mc_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5810
99
                    offset += 1;
5811
                    /* measCmdSize.  Presumably number of words so in future could skip unrecognised command types.. */
5812
99
                    meas_command_ti = proto_tree_add_item_ret_uint(mc_tree, hf_oran_meas_cmd_size, tvb, offset, 2, ENC_BIG_ENDIAN, &meas_command_size);
5813
99
                    proto_item_append_text(meas_command_ti, " (%u bytes)", meas_command_size*4);
5814
99
                    offset += 2;
5815
                    /* reserved (2 bits) */
5816
99
                    add_reserved_field(mc_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5817
                    /* symbolMask (14 bits) */
5818
99
                    offset = dissect_symbolmask(tvb, mc_tree, offset, NULL, NULL);
5819
                    /* reserved (16 bits) */
5820
99
                    add_reserved_field(mc_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5821
99
                    offset += 2;
5822
99
                    break;
5823
5824
1.64k
                default:
5825
                    /* Anything else is not expected */
5826
1.64k
                    expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
5827
1.64k
                                           "measTypeId %u (%s) not supported - only 5 is expected",
5828
1.64k
                                           meas_type_id,
5829
1.64k
                                           val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
5830
1.64k
                    break;
5831
1.78k
            }
5832
1.74k
            proto_item_append_text(mc_ti, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
5833
5834
1.74k
        } while (mf);
5835
1.14k
    }
5836
5837
    /* Set extent of overall section */
5838
16.1k
    proto_item_set_len(sectionHeading, offset);
5839
5840
16.1k
    return offset;
5841
16.4k
}
5842
5843
/* Dissect udCompHdr (user data compression header, 7.5.2.10) */
5844
/* bit_width and comp_meth are out params */
5845
static int dissect_udcomphdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
5846
                             bool cplane, bool ignore,
5847
                             unsigned *bit_width, unsigned *comp_meth, proto_item **comp_meth_ti,
5848
                             oran_tap_info *tap_info)
5849
1.39k
{
5850
    /* Subtree */
5851
1.39k
    proto_item *udcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_udCompHdr,
5852
1.39k
                                                         tvb, offset, 1, "",
5853
1.39k
                                                         "udCompHdr");
5854
1.39k
    proto_tree *udcomphdr_tree = proto_item_add_subtree(udcomphdr_ti, ett_oran_udcomphdr);
5855
5856
    /* udIqWidth */
5857
1.39k
    uint32_t hdr_iq_width;
5858
1.39k
    proto_item *iq_width_item = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
5859
1.39k
    *bit_width = (hdr_iq_width) ? hdr_iq_width : 16;
5860
1.39k
    proto_item_append_text(iq_width_item, " (%u bits)", *bit_width);
5861
5862
    /* udCompMeth */
5863
1.39k
    uint32_t ud_comp_meth;
5864
1.39k
    *comp_meth_ti = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrMeth, tvb, offset, 1, ENC_NA, &ud_comp_meth);
5865
1.39k
    if (comp_meth) {
5866
1.39k
        *comp_meth = ud_comp_meth;
5867
1.39k
    }
5868
5869
    /* Populate tap header with compression settings */
5870
1.39k
    if (!ignore) {
5871
1.25k
        tap_info->compression_methods |= (1 << ud_comp_meth);
5872
1.25k
        tap_info->compression_width = MAX(tap_info->compression_width, hdr_iq_width);
5873
        /* Summary */
5874
1.25k
        proto_item_append_text(udcomphdr_ti, " (IqWidth=%u, udCompMeth=%s)",
5875
1.25k
                               *bit_width, rval_to_str_const(ud_comp_meth, ud_comp_header_meth, "Unknown"));
5876
1.25k
    }
5877
141
    else  {
5878
141
        proto_item_append_text(udcomphdr_ti, " (ignored)");
5879
141
        if (hdr_iq_width || ud_comp_meth) {
5880
134
            if (cplane) {
5881
                /* Only ignore DL for cplane */
5882
0
                expert_add_info_format(pinfo, udcomphdr_ti, &ei_oran_udpcomphdr_should_be_zero,
5883
0
                                       "udCompHdr in C-Plane for DL should be 0 - found 0x%02x",
5884
0
                                       tvb_get_uint8(tvb, offset));
5885
0
            }
5886
134
            else {
5887
                /* TODO: Ignore UL if using m-plane/preference setting rather than c-plane, but wrong to be set? */
5888
                /* expert_add_info_format(pinfo, udcomphdr_ti, &ei_oran_udpcomphdr_should_be_zero,
5889
                                       "udCompHdr in C-Plane for UL should be 0 - found 0x%02x",
5890
                                       tvb_get_uint8(tvb, offset));
5891
                */
5892
134
            }
5893
5894
134
        }
5895
141
    }
5896
1.39k
    return offset+1;
5897
1.39k
}
5898
5899
/* Dissect udCompParam (user data compression parameter, 8.3.3.15) */
5900
/* bit_width and comp_meth are out params */
5901
static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
5902
                               unsigned comp_meth,
5903
                               uint32_t *exponent, uint16_t *sReSMask,
5904
                               bool for_sinr)
5905
125k
{
5906
125k
    if (for_sinr && (comp_meth != COMP_BLOCK_FP)) {
5907
        /* sinrCompParam only present when bfp is used */
5908
0
        return offset;
5909
0
    }
5910
5911
125k
    if (comp_meth == COMP_NONE ||
5912
125k
        comp_meth == COMP_MODULATION ||
5913
125k
        comp_meth == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) {
5914
5915
        /* Not even creating a subtree for udCompMeth 0, 4, 8 */
5916
1.02k
        return offset;
5917
1.02k
    }
5918
5919
    /* Subtree */
5920
124k
    unsigned start_offset = offset;
5921
124k
    proto_item *udcompparam_ti = proto_tree_add_string_format(tree, hf_oran_udCompParam,
5922
124k
                                                         tvb, offset, 1, "",
5923
124k
                                                         (for_sinr) ? "sinrCompParam" : "udCompParam");
5924
124k
    proto_tree *udcompparam_tree = proto_item_add_subtree(udcompparam_ti, ett_oran_udcompparam);
5925
5926
    /* Show comp_meth as a generated field */
5927
124k
    proto_item *meth_ti = proto_tree_add_uint(udcompparam_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, comp_meth);
5928
124k
    proto_item_set_generated(meth_ti);
5929
5930
124k
    uint32_t param_exponent;
5931
124k
    uint64_t param_sresmask;
5932
5933
124k
    static int * const  sres_mask_flags[] = {
5934
124k
        &hf_oran_sReSMask_re12,
5935
124k
        &hf_oran_sReSMask_re11,
5936
124k
        &hf_oran_sReSMask_re10,
5937
124k
        &hf_oran_sReSMask_re9,
5938
124k
        &hf_oran_sReSMask_re8,
5939
124k
        &hf_oran_sReSMask_re7,
5940
124k
        &hf_oran_sReSMask_re6,
5941
124k
        &hf_oran_sReSMask_re5,
5942
124k
        &hf_oran_sReSMask_re4,
5943
124k
        &hf_oran_sReSMask_re3,
5944
124k
        &hf_oran_sReSMask_re2,
5945
124k
        &hf_oran_sReSMask_re1,
5946
124k
        NULL
5947
124k
    };
5948
5949
124k
    switch (comp_meth) {
5950
2.52k
        case COMP_BLOCK_FP:                    /* 1 */
5951
2.99k
        case BFP_AND_SELECTIVE_RE_WITH_MASKS:  /* 7 */
5952
            /* reserved (4 bits) */
5953
2.99k
            add_reserved_field(udcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5954
            /* exponent (4 bits) */
5955
2.99k
            proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
5956
2.99k
                                         tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
5957
2.99k
            *exponent = param_exponent;
5958
2.99k
            proto_item_append_text(udcompparam_ti, " (Exponent=%u)", param_exponent);
5959
2.99k
            offset += 1;
5960
2.99k
            break;
5961
5962
175
        case COMP_BLOCK_SCALE:                 /* 2 */
5963
            /* Separate into integer and fractional bits? */
5964
175
            proto_tree_add_item(udcompparam_tree, hf_oran_blockScaler,
5965
175
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5966
175
            offset++;
5967
175
            break;
5968
5969
178
        case COMP_U_LAW:                      /* 3 */
5970
            /* compBitWidth, compShift */
5971
178
            proto_tree_add_item(udcompparam_tree, hf_oran_compBitWidth,
5972
178
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5973
178
            proto_tree_add_item(udcompparam_tree, hf_oran_compShift,
5974
178
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5975
178
            offset += 1;
5976
178
            break;
5977
5978
816
        case BFP_AND_SELECTIVE_RE:            /* 5 */
5979
816
        {
5980
            /* sReSMask (exponent in middle!) */
5981
816
            proto_item *sresmask_ti;
5982
816
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
5983
816
                                                            hf_oran_sReSMask,
5984
816
                                                            ett_oran_sresmask,
5985
816
                                                            sres_mask_flags,
5986
816
                                                            ENC_NA,
5987
816
                                                            &param_sresmask);
5988
5989
            /* Get rid of exponent-shaped gap */
5990
816
            param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
5991
816
            unsigned res = 0;
5992
10.5k
            for (unsigned n=0; n < 12; n++) {
5993
9.74k
                if ((param_sresmask >> n) & 0x1) {
5994
3.86k
                    res++;
5995
3.86k
                }
5996
9.74k
            }
5997
816
            proto_item_append_text(sresmask_ti, "   (%2u REs)", res);
5998
5999
            /* exponent */
6000
816
            proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
6001
816
                                         tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
6002
816
            *sReSMask = (uint16_t)param_sresmask;
6003
816
            *exponent = param_exponent;
6004
6005
816
            proto_item_append_text(udcompparam_ti, " (exponent=%u, %u REs)", *exponent, res);
6006
816
            offset += 2;
6007
816
            break;
6008
2.52k
        }
6009
6010
753
        case MOD_COMPR_AND_SELECTIVE_RE:      /* 6 */
6011
753
        {
6012
            /* sReSMask (exponent in middle!) */
6013
753
            proto_item *sresmask_ti;
6014
6015
753
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
6016
753
                                                            hf_oran_sReSMask,
6017
753
                                                            ett_oran_sresmask,
6018
753
                                                            sres_mask_flags,
6019
753
                                                            ENC_NA,
6020
753
                                                            &param_sresmask);
6021
6022
            /* Get rid of reserved-shaped gap */
6023
753
            param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
6024
753
            unsigned res = 0;
6025
9.75k
            for (unsigned n=0; n < 12; n++) {
6026
9.00k
                if ((param_sresmask >> n) & 0x1) {
6027
3.53k
                    res++;
6028
3.53k
                }
6029
9.00k
            }
6030
753
            proto_item_append_text(sresmask_ti, "   (%u REs)", res);
6031
6032
            /* reserved (4 bits) */
6033
753
            add_reserved_field(udcompparam_tree, hf_oran_reserved_last_4bits, tvb, offset, 1);
6034
753
            *sReSMask = (uint16_t)param_sresmask;
6035
6036
753
            proto_item_append_text(udcompparam_ti, " (%u REs)", res);
6037
753
            offset += 2;
6038
753
            break;
6039
2.52k
        }
6040
6041
119k
        default:
6042
            /* reserved (set to all zeros), but how many bytes?? */
6043
119k
            break;
6044
124k
    }
6045
6046
124k
    proto_item_set_len(udcompparam_ti, offset-start_offset);
6047
124k
    return offset;
6048
124k
}
6049
6050
6051
/* Dissect ciCompHdr (channel information compression header, 7.5.2.15) */
6052
/* bit_width and comp_meth are out params */
6053
static int dissect_cicomphdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
6054
                             unsigned *bit_width, unsigned *comp_meth, uint8_t *comp_opt)
6055
96
{
6056
    /* Subtree */
6057
96
    proto_item *cicomphdr_ti = proto_tree_add_string_format(tree, hf_oran_ciCompHdr,
6058
96
                                                         tvb, offset, 1, "",
6059
96
                                                         "ciCompHdr");
6060
96
    proto_tree *cicomphdr_tree = proto_item_add_subtree(cicomphdr_ti, ett_oran_cicomphdr);
6061
6062
    /* ciIqWidth */
6063
96
    uint32_t hdr_iq_width;
6064
96
    proto_item *iq_width_item = proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
6065
96
    hdr_iq_width = (hdr_iq_width) ? hdr_iq_width : 16;
6066
96
    if (bit_width) {
6067
96
        *bit_width = hdr_iq_width;
6068
96
    }
6069
96
    proto_item_append_text(iq_width_item, " (%u bits)", hdr_iq_width);
6070
6071
    /* ciCompMeth */
6072
96
    uint32_t ci_comp_meth;
6073
96
    proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrMeth, tvb, offset, 1, ENC_NA, &ci_comp_meth);
6074
96
    if (comp_meth) {
6075
96
        *comp_meth = ci_comp_meth;
6076
96
    }
6077
6078
    /* ciCompOpt */
6079
96
    uint32_t opt;
6080
96
    proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompOpt, tvb, offset, 1, ENC_NA, &opt);
6081
96
    *comp_opt = opt;
6082
96
    offset += 1;
6083
6084
    /* Summary */
6085
96
    proto_item_append_text(cicomphdr_ti, " (IqWidth=%u, ciCompMeth=%s, ciCompOpt=%s)",
6086
96
                           hdr_iq_width,
6087
96
                           rval_to_str_const(ci_comp_meth, ud_comp_header_meth, "Unknown"),
6088
96
                           (*comp_opt) ?  "compression per PRB" : "compression per UE");
6089
96
    return offset;
6090
96
}
6091
6092
static void dissect_payload_version(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, unsigned offset)
6093
1.91k
{
6094
1.91k
    unsigned version;
6095
1.91k
    proto_item *ti = proto_tree_add_item_ret_uint(tree, hf_oran_payload_version, tvb, offset, 1, ENC_NA, &version);
6096
1.91k
    if (version != 1) {
6097
1.78k
        expert_add_info_format(pinfo, ti, &ei_oran_version_unsupported,
6098
1.78k
                               "PayloadVersion %u not supported by dissector (only 1 is known)",
6099
1.78k
                               version);
6100
        /* TODO: should throw an exception? */
6101
1.78k
    }
6102
1.91k
}
6103
6104
static void show_link_to_acknack_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
6105
                                         ack_nack_request_t *request)
6106
0
{
6107
    /* Request frame */
6108
0
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_request_frame,
6109
0
                                         tvb, 0, 0, request->request_frame_number);
6110
0
    PROTO_ITEM_SET_GENERATED(ti);
6111
6112
    /* Work out gap between frames (in ms) */
6113
0
    int seconds_between_packets = (int)
6114
0
          (pinfo->abs_ts.secs - request->request_frame_time.secs);
6115
0
    int nseconds_between_packets =
6116
0
          pinfo->abs_ts.nsecs - request->request_frame_time.nsecs;
6117
6118
0
    int total_gap = (seconds_between_packets*1000) +
6119
0
                     ((nseconds_between_packets+500000) / 1000000);
6120
6121
0
    ti = proto_tree_add_uint(tree, hf_oran_acknack_request_time,
6122
0
                             tvb, 0, 0, total_gap);
6123
0
    PROTO_ITEM_SET_GENERATED(ti);
6124
6125
    /* Type of request */
6126
0
    ti = proto_tree_add_uint(tree, hf_oran_acknack_request_type,
6127
0
                             tvb, 0, 0, request->requestType);
6128
0
    PROTO_ITEM_SET_GENERATED(ti);
6129
0
}
6130
6131
static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
6132
                                          ack_nack_request_t *response)
6133
0
{
6134
0
    if (response->response_frame_number == 0) {
6135
        /* Requests may not get a response, and can't always tell when  to expect one */
6136
0
        return;
6137
0
    }
6138
6139
    /* Response frame */
6140
0
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_response_frame,
6141
0
                                         tvb, 0, 0, response->response_frame_number);
6142
0
    PROTO_ITEM_SET_GENERATED(ti);
6143
6144
    /* Work out gap between frames (in ms) */
6145
0
    int seconds_between_packets = (int)
6146
0
          (response->response_frame_time.secs - pinfo->abs_ts.secs);
6147
0
    int nseconds_between_packets =
6148
0
          response->response_frame_time.nsecs - pinfo->abs_ts.nsecs;
6149
6150
0
    int total_gap = (seconds_between_packets*1000) +
6151
0
                     ((nseconds_between_packets+500000) / 1000000);
6152
6153
0
    ti = proto_tree_add_uint(tree, hf_oran_acknack_response_time,
6154
0
                             tvb, 0, 0, total_gap);
6155
0
    PROTO_ITEM_SET_GENERATED(ti);
6156
0
}
6157
6158
6159
6160
/* Control plane dissector (section 7). */
6161
static int dissect_oran_c(tvbuff_t *tvb, packet_info *pinfo,
6162
                          proto_tree *tree, oran_tap_info *tap_info, void *data _U_)
6163
1.73k
{
6164
    /* Hidden filter for plane */
6165
1.73k
    proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_cplane, tvb, 0, 0, ENC_NA);
6166
1.73k
    PROTO_ITEM_SET_HIDDEN(plane_ti);
6167
6168
    /* Set up structures needed to add the protocol subtree and manage it */
6169
1.73k
    unsigned offset = 0;
6170
6171
1.73k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-C");
6172
1.73k
    col_set_str(pinfo->cinfo, COL_INFO, "C-Plane");
6173
6174
1.73k
    tap_info->userplane = false;
6175
6176
    /* Create display subtree for the protocol */
6177
1.73k
    proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
6178
1.73k
    proto_item_append_text(protocol_item, "-C");
6179
1.73k
    proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
6180
6181
    /* ecpriRtcid (eAxC ID) */
6182
1.73k
    uint16_t eAxC;
6183
1.73k
    addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_rtcid, &eAxC, tap_info);
6184
1.73k
    tap_info->eaxc = eAxC;
6185
6186
    /* Look up any existing conversation state for eAxC+plane */
6187
1.73k
    flow_state_t* state = lookup_flow(pinfo, eAxC, ORAN_C_PLANE, false);
6188
6189
    /* Message identifier */
6190
1.73k
    uint32_t seq_id, sub_seq_id, e;
6191
1.73k
    proto_item *seq_id_ti;
6192
1.73k
    offset = addSeqid(tvb, oran_tree, offset, ORAN_C_PLANE, &seq_id, &seq_id_ti, pinfo, &sub_seq_id, &e);
6193
6194
    /* Section common subtree */
6195
1.73k
    int section_tree_offset = offset;
6196
1.73k
    proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_c_section_common,
6197
1.73k
                                                              tvb, offset, 0, "", "C-Plane Section Type ");
6198
1.73k
    proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section_common);
6199
6200
    /* Peek ahead at the section type */
6201
1.73k
    uint32_t sectionType = 0;
6202
1.73k
    sectionType = tvb_get_uint8(tvb, offset+5);
6203
6204
1.73k
    uint32_t scs = 0;
6205
1.73k
    proto_item *scs_ti = NULL;
6206
6207
    /* dataDirection */
6208
1.73k
    uint32_t direction = 0;
6209
1.73k
    proto_item *datadir_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
6210
1.73k
    tap_info->uplink = (direction==0);
6211
6212
    /* Update/report status of conversation */
6213
1.73k
    if (!PINFO_FD_VISITED(pinfo)) {
6214
6215
1.73k
        if (state == NULL) {
6216
            /* Allocate state now */
6217
470
            state = wmem_new0(wmem_file_scope(), flow_state_t);
6218
470
            state->ack_nack_requests = wmem_tree_new(wmem_file_scope());
6219
470
            store_flow(pinfo, eAxC, ORAN_C_PLANE, false, state);
6220
            /* Tables for each direction */
6221
470
            state->expected_sections[0] = wmem_tree_new(wmem_file_scope());
6222
470
            state->expected_sections[1] = wmem_tree_new(wmem_file_scope());
6223
470
        }
6224
6225
        /* Check sequence analysis status */
6226
1.73k
        if (state->last_frame_seen[direction] && (seq_id != state->next_expected_sequence_number[direction])) {
6227
            /* Store this result */
6228
1.20k
            flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
6229
1.20k
            result->unexpected_seq_number = true;
6230
1.20k
            result->expected_sequence_number = state->next_expected_sequence_number[direction];
6231
1.20k
            result->previous_frame = state->last_frame[direction];
6232
1.20k
            result->u_plane_frames = wmem_list_new(wmem_file_scope());
6233
1.20k
            wmem_tree_insert32(flow_results_table, pinfo->num, result);
6234
1.20k
        }
6235
        /* Update conversation info */
6236
1.73k
        state->last_frame[direction] = pinfo->num;
6237
1.73k
        state->last_frame_seen[direction] = true;
6238
1.73k
        state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
6239
1.73k
    }
6240
6241
    /* Show any issues associated with this frame number */
6242
1.73k
    flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
6243
1.73k
    if (result!=NULL && result->unexpected_seq_number) {
6244
1.20k
        expert_add_info_format(pinfo, seq_id_ti,
6245
1.20k
                               (direction == DIR_UPLINK) ?
6246
925
                                   &ei_oran_cplane_unexpected_sequence_number_ul :
6247
1.20k
                                   &ei_oran_cplane_unexpected_sequence_number_dl,
6248
1.20k
                               "Sequence number %u expected, but got %u",
6249
1.20k
                               result->expected_sequence_number, seq_id);
6250
6251
        /* Update tap info */
6252
1.20k
        uint32_t missing_sns = (256 + seq_id - result->expected_sequence_number) % 256;
6253
        /* Don't get confused by being slightly out of order.. */
6254
1.20k
        if (missing_sns < 128) {
6255
78
            tap_info->missing_sns = missing_sns;
6256
78
        }
6257
1.13k
        else {
6258
1.13k
            tap_info->missing_sns = 0;
6259
1.13k
        }
6260
6261
        /* TODO: could add previous/next frames (in seqId tree?) ? */
6262
1.20k
    }
6263
6264
    /* payloadVersion */
6265
1.73k
    dissect_payload_version(section_tree, tvb, pinfo, offset);
6266
6267
    /* filterIndex */
6268
1.73k
    if (sectionType == SEC_C_SLOT_CONTROL || sectionType == SEC_C_ACK_NACK_FEEDBACK) {
6269
        /* scs (for ST4 and ST8) */
6270
126
        scs_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
6271
126
    }
6272
1.61k
    else if (sectionType == SEC_C_RRM_MEAS_REPORTS || sectionType == SEC_C_REQUEST_RRM_MEAS) {
6273
        /* reserved (4 bits) */
6274
696
        add_reserved_field(section_tree, hf_oran_reserved_last_4bits, tvb, offset, 1);
6275
696
    }
6276
916
    else if (sectionType != SEC_C_LAA) {
6277
        /* filterIndex (most common case) */
6278
897
        proto_tree_add_item(section_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
6279
897
    }
6280
1.73k
    offset += 1;
6281
6282
1.73k
    unsigned ref_a_offset = offset;
6283
    /* frameId */
6284
1.73k
    uint32_t frameId = 0;
6285
1.73k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
6286
1.73k
    tap_info->frame = frameId;
6287
1.73k
    offset += 1;
6288
6289
    /* subframeId */
6290
1.73k
    uint32_t subframeId = 0;
6291
1.73k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
6292
    /* slotId */
6293
1.73k
    uint32_t slotId = 0;
6294
1.73k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
6295
1.73k
    tap_info->slot = slotId;
6296
1.73k
    offset++;
6297
6298
    /* startSymbolId */
6299
1.73k
    uint32_t startSymbolId = 0;
6300
1.73k
    proto_item *ssid_ti = NULL;
6301
1.73k
    if ((sectionType == SEC_C_ACK_NACK_FEEDBACK) ||  /* Section Type 8 */
6302
1.71k
        (sectionType == SEC_C_SINR_REPORTING)) {     /* Section Type 9 */
6303
        /* symbolId */
6304
62
        proto_tree_add_item_ret_uint(section_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, &startSymbolId);
6305
62
    }
6306
1.67k
    else if (sectionType != SEC_C_LAA) {
6307
         /* startSymbolId is in most section types */
6308
1.65k
        ssid_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_start_symbol_id, tvb, offset, 1, ENC_NA, &startSymbolId);
6309
1.65k
        if (startSymbolId && (sectionType == SEC_C_RRM_MEAS_REPORTS)) {      /* Section Type 10 */
6310
474
            proto_item_append_text(ssid_ti, " (should be 0 for ST10!)");
6311
474
            expert_add_info_format(pinfo, ssid_ti, &ei_oran_st10_startsymbolid_not_0,
6312
474
                                   "startSymbolId should be 0 for ST10 - found %u", startSymbolId);
6313
474
        }
6314
1.65k
    }
6315
19
    else {
6316
        /* reserved (6 bits) */
6317
19
        add_reserved_field(section_tree, hf_oran_reserved_last_6bits, tvb, offset, 1);
6318
19
    }
6319
1.73k
    offset++;
6320
6321
6322
1.73k
    char id[16];
6323
1.73k
    snprintf(id, 16, "%u-%u-%u-%u", frameId, subframeId, slotId, startSymbolId);
6324
1.73k
    proto_item *pi = proto_tree_add_string(section_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
6325
1.73k
    proto_item_set_generated(pi);
6326
6327
1.73k
    uint32_t cmd_scope = 0;
6328
1.73k
    bool st8_ready = false;
6329
6330
    /* numberOfSections (or whatever section has instead) */
6331
1.73k
    uint32_t nSections = 0;
6332
1.73k
    if (sectionType == SEC_C_SLOT_CONTROL) {          /* Section Type 4 */
6333
        /* Slot Control has these fields instead */
6334
        /* reserved (4 bits) */
6335
109
        add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6336
        /* cmdScope (4 bits) */
6337
109
        proto_tree_add_item_ret_uint(section_tree, hf_oran_cmd_scope, tvb, offset, 1, ENC_NA, &cmd_scope);
6338
109
    }
6339
1.62k
    else if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {    /* Section Type 8 */
6340
        /* reserved (7 bits) */
6341
17
        add_reserved_field(section_tree, hf_oran_reserved_7bits, tvb, offset, 1);
6342
        /* ready (1 bit) */
6343
        /* TODO: when set, ready in slotId+1.. */
6344
17
        proto_tree_add_item_ret_boolean(section_tree, hf_oran_ready, tvb, offset, 1, ENC_NA, &st8_ready);
6345
17
        if (!st8_ready) {
6346
            /* SCS value is ignored, and may be set to any value by O-RU */
6347
10
            proto_item_append_text(scs_ti, " (ignored)");
6348
10
        }
6349
17
    }
6350
1.61k
    else if (sectionType != SEC_C_LAA) {
6351
        /* numberOfSections */
6352
1.59k
        proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfSections, tvb, offset, 1, ENC_NA, &nSections);
6353
1.59k
    }
6354
19
    else {
6355
19
        add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
6356
19
    }
6357
1.73k
    offset++;
6358
6359
    /* sectionType */
6360
1.73k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_sectionType, tvb, offset, 1, ENC_NA, &sectionType);
6361
1.73k
    offset += 1;
6362
6363
    /* Check that dataDirection is consistent with section type */
6364
1.73k
    if (sectionType == SEC_C_SINR_REPORTING && direction != 0) {   /* Section Type 9 */
6365
12
        expert_add_info(pinfo, datadir_ti, &ei_oran_st9_not_ul);
6366
12
    }
6367
1.73k
    if (sectionType == SEC_C_RRM_MEAS_REPORTS && direction != 0) {  /* Section Type 10 */
6368
123
        expert_add_info(pinfo, datadir_ti, &ei_oran_st10_not_ul);
6369
123
    }
6370
6371
    /* Note this section type in stats */
6372
1.73k
    if (sectionType < SEC_C_MAX_INDEX) {
6373
1.60k
        tap_info->section_types[sectionType] = true;
6374
1.60k
    }
6375
6376
    /* Section-type-specific fields following common header (white entries in Section Type diagrams) */
6377
1.73k
    unsigned bit_width = 0;
6378
1.73k
    unsigned comp_meth = 0;
6379
1.73k
    proto_item *comp_meth_ti;
6380
1.73k
    unsigned ci_comp_method = 0;
6381
1.73k
    uint8_t  ci_comp_opt = 0;
6382
6383
1.73k
    uint32_t num_ues = 0;
6384
1.73k
    uint32_t number_of_acks = 0, number_of_nacks = 0;
6385
6386
1.73k
    uint32_t num_sinr_per_prb = 0;
6387
6388
1.73k
    switch (sectionType) {
6389
284
        case SEC_C_UNUSED_RB:   /* Section Type 0 */
6390
            /* timeOffset */
6391
284
            proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
6392
284
            offset += 2;
6393
            /* frameStructure */
6394
284
            offset = dissect_frame_structure(section_tree, tvb, offset,
6395
284
                                             subframeId, slotId);
6396
6397
            /* cpLength */
6398
284
            proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
6399
284
            offset += 2;
6400
            /* reserved (8 bits) */
6401
284
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
6402
284
            offset += 1;
6403
284
            break;
6404
6405
159
        case SEC_C_NORMAL:       /* Section Type 1 */
6406
210
        case SEC_C_UE_SCHED:     /* Section Type 5 */
6407
            /* udCompHdr */
6408
210
            offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
6409
210
                                       true, direction==0 && pref_override_ul_compression, /* ignore for DL or if using mplane for UL settings */
6410
210
                                       &bit_width, &comp_meth, &comp_meth_ti, tap_info);
6411
            /* reserved (8 bits) */
6412
210
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
6413
210
            offset += 1;
6414
210
            break;
6415
6416
109
        case SEC_C_SLOT_CONTROL: /* Section Type 4 */
6417
109
            break;
6418
6419
128
        case SEC_C_PRACH:        /* Section Type 3 */
6420
            /* timeOffset */
6421
128
            proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
6422
128
            offset += 2;
6423
            /* frameStructure */
6424
128
            offset = dissect_frame_structure(section_tree, tvb, offset,
6425
128
                                             subframeId, slotId);
6426
            /* cpLength */
6427
128
            proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
6428
128
            offset += 2;
6429
            /* udCompHdr */
6430
128
            offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
6431
128
                                       true, direction==0 && pref_override_ul_compression, /* ignore for DL or if using mplane for UL settings */
6432
128
                                       &bit_width, &comp_meth, &comp_meth_ti, tap_info);
6433
128
            break;
6434
6435
96
        case SEC_C_CH_INFO:     /* Section Type 6 */
6436
            /* numberOfUEs */
6437
96
            proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfUEs, tvb, offset, 1, ENC_NA, &num_ues);
6438
96
            offset += 1;
6439
            /* ciCompHdr (was reserved) */
6440
96
            offset = dissect_cicomphdr(tvb, pinfo, section_tree, offset, &bit_width, &ci_comp_method, &ci_comp_opt);
6441
6442
            /* Number of sections may not be filled in (at all, or correctly), so set to the number of UEs.
6443
               The data entries are per-UE... they don't have a sectionID, but they could have section extensions... */
6444
96
            if (nSections == 0 || num_ues > nSections) {
6445
33
                nSections = num_ues;
6446
33
            }
6447
96
            break;
6448
6449
6
        case SEC_C_RSVD2:
6450
6
            break;
6451
6452
15
        case SEC_C_LAA:                   /* Section Type 7 */
6453
15
            add_reserved_field(section_tree, hf_oran_reserved_16bits, tvb, offset, 2);
6454
15
            offset += 2;
6455
15
            break;
6456
6457
17
        case SEC_C_ACK_NACK_FEEDBACK:     /* Section Type 8 */
6458
            /* numberOfAcks (1 byte) */
6459
17
            proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_acks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_acks);
6460
17
            offset += 1;
6461
            /* numberOfNacks (1 byte) */
6462
17
            proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_nacks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_nacks);
6463
17
            offset += 1;
6464
6465
            /* Show ACKs and NACKs. For both, try to link back to request. */
6466
331
            for (unsigned int n=1; n <= number_of_acks; n++) {
6467
314
                uint32_t ackid;
6468
314
                proto_item *ack_ti;
6469
314
                ack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_ackid, tvb, offset, 2, ENC_BIG_ENDIAN, &ackid);
6470
314
                offset += 2;
6471
6472
                /* Look up request table in state (which really should be set by now, but test anyway). */
6473
314
                if (state && state->ack_nack_requests) {
6474
311
                    ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, ackid);
6475
311
                    if (request != NULL) {
6476
                        /* On first pass, update with this response */
6477
0
                        if (!PINFO_FD_VISITED(pinfo)) {
6478
0
                            request->response_frame_number = pinfo->num;
6479
0
                            request->response_frame_time = pinfo->abs_ts;
6480
0
                        }
6481
6482
                        /* Show request details */
6483
0
                        show_link_to_acknack_request(section_tree, tvb, pinfo, request);
6484
0
                    }
6485
311
                    else {
6486
                        /* Request not found */
6487
311
                        expert_add_info_format(pinfo, ack_ti, &ei_oran_acknack_no_request,
6488
311
                                               "Response for ackId=%u received, but no request found",
6489
311
                                               ackid);
6490
311
                    }
6491
311
                }
6492
314
            }
6493
326
            for (unsigned int m=1; m <= number_of_nacks; m++) {
6494
309
                uint32_t nackid;
6495
309
                proto_item *nack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_nackid, tvb, offset, 2, ENC_BIG_ENDIAN, &nackid);
6496
309
                offset += 2;
6497
6498
309
                expert_add_info_format(pinfo, nack_ti, &ei_oran_st8_nackid,
6499
309
                                       "Received Nack for ackNackId=%u",
6500
309
                                       nackid);
6501
6502
                /* Look up request table in state. */
6503
309
                if (state && state->ack_nack_requests) {
6504
298
                    ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, nackid);
6505
298
                    if (request) {
6506
                        /* On first pass, update with this response */
6507
0
                        if (!PINFO_FD_VISITED(pinfo)) {
6508
0
                            request->response_frame_number = pinfo->num;
6509
0
                            request->response_frame_time = pinfo->abs_ts;
6510
0
                        }
6511
6512
                        /* Show request details */
6513
0
                        show_link_to_acknack_request(section_tree, tvb, pinfo, request);
6514
0
                    }
6515
298
                    else {
6516
                        /* Request not found */
6517
298
                        expert_add_info_format(pinfo, nack_ti, &ei_oran_acknack_no_request,
6518
298
                                               "Response for nackId=%u received, but no request found",
6519
298
                                               nackid);
6520
298
                    }
6521
298
                }
6522
309
            }
6523
17
            break;
6524
6525
45
        case SEC_C_SINR_REPORTING:     /* Section Type 9 */
6526
45
        {
6527
            /* numSinrPerPrb (3 bits) */
6528
45
            proto_item *nspp_ti;
6529
45
            nspp_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_num_sinr_per_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sinr_per_prb);
6530
45
            switch (num_sinr_per_prb) {
6531
17
                case 0:
6532
17
                    num_sinr_per_prb = 1; break;
6533
1
                case 1:
6534
1
                    num_sinr_per_prb = 2; break;
6535
3
                case 2:
6536
3
                    num_sinr_per_prb = 3; break;
6537
5
                case 3:
6538
5
                    num_sinr_per_prb = 4; break;
6539
4
                case 4:
6540
4
                    num_sinr_per_prb = 6; break;
6541
8
                case 5:
6542
8
                    num_sinr_per_prb = 12; break;
6543
6544
7
                default:
6545
7
                    proto_item_append_text(nspp_ti, " (invalid)");
6546
7
                    num_sinr_per_prb = 1;
6547
7
                    expert_add_info_format(pinfo, nspp_ti, &ei_oran_num_sinr_per_prb_unknown,
6548
7
                                           "Invalid numSinrPerPrb value (%u)",
6549
7
                                           num_sinr_per_prb);
6550
45
            }
6551
6552
            /* oruControlSinrSlotMaskId (5 bits) */
6553
45
            proto_tree_add_item(section_tree, hf_oran_oru_control_sinr_slot_mask_id, tvb, offset, 1, ENC_BIG_ENDIAN);
6554
45
            offset += 1;
6555
            /* reserved (8 bits) */
6556
45
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
6557
45
            offset += 1;
6558
45
            break;
6559
45
        }
6560
6561
574
        case SEC_C_RRM_MEAS_REPORTS:    /* Section Type 10 */
6562
696
        case SEC_C_REQUEST_RRM_MEAS:    /* Section Type 11 */
6563
            /* reserved (16 bits) */
6564
696
            add_reserved_field(section_tree, hf_oran_reserved_16bits, tvb, offset, 2);
6565
696
            offset += 2;
6566
696
            break;
6567
1.73k
    };
6568
6569
    /* Update udCompHdr details in state for UL U-Plane */
6570
1.72k
    if (state && direction==0) {
6571
1.27k
        switch (sectionType) {
6572
100
            case SEC_C_NORMAL:    /* Section Type 1 */
6573
194
            case SEC_C_PRACH:     /* Section Type 3 */
6574
224
            case SEC_C_UE_SCHED:  /* Section Type 5 */
6575
224
                state->ul_ud_comp_hdr_set = true;
6576
224
                state->ul_ud_comp_hdr_bit_width = bit_width;
6577
224
                state->ul_ud_comp_hdr_compression = comp_meth;
6578
224
                state->ul_ud_comp_hdr_frame = pinfo->num;
6579
224
                break;
6580
1.04k
            default:
6581
1.04k
                break;
6582
1.27k
        }
6583
1.27k
    }
6584
6585
6586
1.72k
    proto_item_append_text(sectionHeading, "%d, %s, frameId: %d, subframeId: %d, slotId: %d, startSymbolId: %d",
6587
1.72k
                           sectionType, val_to_str_const(direction, data_direction_vals, "Unknown"),
6588
1.72k
                           frameId, subframeId, slotId, startSymbolId);
6589
1.72k
    if (nSections) {
6590
1.58k
        proto_item_append_text(sectionHeading, ", numberOfSections=%u", nSections);
6591
1.58k
    }
6592
6593
1.72k
    write_pdu_label_and_info(protocol_item, NULL, pinfo, ", Type: %2d %s", sectionType,
6594
1.72k
                             rval_to_str_const(sectionType, section_types_short, "Unknown"));
6595
6596
    /* Set actual length of C-Plane section header */
6597
1.72k
    proto_item_set_len(section_tree, offset - section_tree_offset);
6598
6599
1.72k
    if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {
6600
3
        write_pdu_label_and_info(oran_tree, section_tree, pinfo,
6601
3
                                 (st8_ready) ? " (Ready)" : " (ACK)");
6602
3
    }
6603
6604
6605
    /* Section type 4 doesn't have normal sections, so deal with here before normal sections */
6606
1.72k
    if (sectionType == SEC_C_SLOT_CONTROL) {
6607
        /* numberOfST4Cmds */
6608
109
        uint32_t no_st4_cmds, st4_cmd_len, num_slots, ack_nack_req_id, st4_cmd_type;
6609
109
        proto_item *no_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_st4_cmds,
6610
109
                                                         tvb, offset, 1, ENC_NA, &no_st4_cmds);
6611
109
        if (no_st4_cmds == 0) {
6612
1
            expert_add_info(pinfo, no_ti, &ei_oran_st4_no_cmds);
6613
1
        }
6614
109
        offset += 1;
6615
6616
        /* reserved (1 byte) */
6617
109
        add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
6618
109
        offset += 1;
6619
6620
        /* Loop over commands.  Each has 8-byte common header, followed by cmd-specific payload */
6621
109
        proto_item *len_ti;
6622
320
        for (uint32_t n=0; n < no_st4_cmds; n++) {
6623
            /* Table 7.4.6-2: Section Type 4 Command common header format */
6624
317
            proto_item *hdr_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd_header,
6625
317
                                                              tvb, offset, 8, "",
6626
317
                                                              "Type 4 Command common header");
6627
317
            proto_tree *hdr_tree = proto_item_add_subtree(hdr_ti, ett_oran_st4_cmd_header);
6628
6629
            /* st4CmdType */
6630
317
            proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_type, tvb, offset, 1, ENC_NA, &st4_cmd_type);
6631
317
            offset += 1;
6632
6633
            /* st4CmdLen */
6634
317
            len_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_len, tvb, offset, 2, ENC_BIG_ENDIAN, &st4_cmd_len);
6635
317
            if (st4_cmd_len == 0) {
6636
                /* Meaning of 0 not yet defined (v15.00) */
6637
135
                proto_item_append_text(len_ti, " (reserved)");
6638
135
                expert_add_info(pinfo, len_ti, &ei_oran_st4_zero_len_cmd);
6639
135
            }
6640
182
            else {
6641
182
                proto_item_append_text(len_ti, " (%u bytes)", st4_cmd_len*4);
6642
182
            }
6643
317
            offset += 2;
6644
6645
            /* numSlots */
6646
317
            proto_item *slots_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_num_slots, tvb, offset, 1, ENC_NA, &num_slots);
6647
317
            if (num_slots == 0) {
6648
161
                proto_item_append_text(slots_ti, " (until changed)");
6649
161
            }
6650
317
            offset += 1;
6651
6652
            /* ackNackReqId */
6653
317
            proto_item *ack_nack_req_id_ti;
6654
317
            ack_nack_req_id_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_ack_nack_req_id, tvb, offset, 2, ENC_BIG_ENDIAN, &ack_nack_req_id);
6655
317
            offset += 2;
6656
317
            if (ack_nack_req_id == 0) {
6657
123
                proto_item_append_text(ack_nack_req_id_ti, " (no Section type 8 response expected)");
6658
123
            }
6659
6660
            /* reserved (16 bits) */
6661
317
            add_reserved_field(hdr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
6662
317
            offset += 2;
6663
6664
            /* Set common header summary */
6665
317
            proto_item_append_text(hdr_ti, " (cmd=%s, len=%u, slots=%u, ackNackReqId=%u)",
6666
317
                                   rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"),
6667
317
                                   st4_cmd_len, num_slots, ack_nack_req_id);
6668
6669
317
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
6670
317
                            rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
6671
6672
6673
            /* Subtree for this command body */
6674
317
            proto_item *command_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd,
6675
317
                                                              tvb, offset, 0, "",
6676
317
                                                              "Type 4 Command (%s)", rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
6677
317
            proto_tree *command_tree = proto_item_add_subtree(command_ti, ett_oran_st4_cmd);
6678
6679
317
            unsigned command_start_offset = offset;
6680
6681
            /* Check fields compatible with chosen command. */
6682
317
            if (st4_cmd_type==1) {
6683
72
                if (num_slots != 0) {
6684
                    /* "the value of numSlots should be set to zero for this command type" */
6685
42
                    expert_add_info_format(pinfo, slots_ti, &ei_oran_numslots_not_zero,
6686
42
                                           "numSlots should be zero for ST4 command 1 - found %u",
6687
42
                                           num_slots);
6688
42
                }
6689
72
            }
6690
6691
317
            if (st4_cmd_type==3 || st4_cmd_type==4) {
6692
44
                if (startSymbolId != 0) {
6693
                    /* "expected reception window for the commands is the symbol zero reception window" */
6694
39
                    expert_add_info_format(pinfo, ssid_ti, &ei_oran_start_symbol_id_not_zero,
6695
39
                                           "startSymbolId should be zero for ST4 commands 3&4 - found %u",
6696
39
                                           startSymbolId);
6697
39
                }
6698
44
            }
6699
6700
            /* Add format for this command */
6701
317
            switch (st4_cmd_type) {
6702
72
                case 1:  /* TIME_DOMAIN_BEAM_CONFIG */
6703
72
                {
6704
72
                    bool disable_tdbfns;
6705
72
                    uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
6706
6707
                    /* Hidden filter for bf */
6708
72
                    proto_item *bf_ti = proto_tree_add_item(command_tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
6709
72
                    PROTO_ITEM_SET_HIDDEN(bf_ti);
6710
6711
                    /* reserved (2 bits) */
6712
72
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6713
                    /* symbolMask (14 bits) */
6714
72
                    uint32_t symbol_mask;
6715
72
                    proto_item *symbol_mask_ti;
6716
72
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &symbol_mask_ti);
6717
                    /* Symbol bits before 'startSymbolId' in Section Type 4 common header should be set to 0 by O-DU and shall be ignored by O-RU */
6718
                    /* lsb is symbol 0 */
6719
253
                    for (unsigned s=0; s < 14; s++) {
6720
251
                        if ((startSymbolId & (1 << s)) && (startSymbolId > s)) {
6721
70
                            proto_item_append_text(symbol_mask_ti, " (startSymbolId is %u, so some lower symbol bits ignored!)", startSymbolId);
6722
70
                            expert_add_info(pinfo, symbol_mask_ti, &ei_oran_start_symbol_id_bits_ignored);
6723
70
                            break;
6724
70
                        }
6725
251
                    }
6726
6727
                    /* disableTDBFNs (1 bit) */
6728
72
                    proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfns, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfns);
6729
6730
                    /* tdBeamNum (15 bits) */
6731
72
                    proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
6732
72
                    offset += 2;
6733
6734
                    /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
6735
72
                    offset = dissect_bfwCompHdr(tvb, command_tree, offset,
6736
72
                                                &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
6737
                    /* reserved (3 bytes) */
6738
72
                    proto_tree_add_bits_item(command_tree, hf_oran_reserved, tvb, offset*8, 24, ENC_BIG_ENDIAN);
6739
72
                    offset += 3;
6740
6741
72
                    if (disable_tdbfns) {
6742
                        /* No beamnum information to show so get out. */
6743
6
                        break;
6744
6
                    }
6745
6746
                    /* Read beam entries until reach end of command length */
6747
691
                    while ((offset - command_start_offset) < (st4_cmd_len * 4)) {
6748
6749
                        /* disableTDBFWs (1 bit) */
6750
625
                        bool disable_tdbfws;
6751
625
                        proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfws, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfws);
6752
6753
                        /* tdBeamNum (15 bits) */
6754
625
                        proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
6755
625
                        offset += 2;
6756
6757
                        /* Showing BFWs? */
6758
625
                        if (!disable_tdbfws) {
6759
6760
                            /* bfwCompParam */
6761
360
                            unsigned exponent = 0;
6762
360
                            bool     supported = false;
6763
360
                            unsigned num_trx_entries;
6764
360
                            uint16_t *trx_entries;
6765
360
                            offset = dissect_bfwCompParam(tvb, command_tree, pinfo, offset, comp_meth_ti,
6766
360
                                                          &bfwcomphdr_comp_meth, &exponent, &supported,
6767
360
                                                          &num_trx_entries, &trx_entries);
6768
6769
                            /* Antenna count from preference */
6770
360
                            unsigned num_trx = pref_num_bf_antennas;
6771
360
                            int bit_offset = offset*8;
6772
6773
10.8k
                            for (unsigned trx=0; trx < num_trx; trx++) {
6774
                                /* Create antenna subtree */
6775
10.5k
                                int bfw_offset = bit_offset / 8;
6776
10.5k
                                proto_item *bfw_ti = proto_tree_add_string_format(command_tree, hf_oran_bfw,
6777
10.5k
                                                                                  tvb, bfw_offset, 0, "", "TRX %3u: (", trx);
6778
10.5k
                                proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
6779
6780
                                /* I value */
6781
                                /* Get bits, and convert to float. */
6782
10.5k
                                uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
6783
10.5k
                                float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr*/, 0 /* RE */);
6784
                                /* Add to tree. */
6785
10.5k
                                proto_tree_add_float(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
6786
10.5k
                                                     (bfwcomphdr_iq_width+7)/8, value);
6787
10.5k
                                bit_offset += bfwcomphdr_iq_width;
6788
10.5k
                                proto_item_append_text(bfw_ti, "I=%f ", value);
6789
6790
                                /* Leave a gap between I and Q values */
6791
10.5k
                                proto_item_append_text(bfw_ti, "  ");
6792
6793
                                /* Q value */
6794
                                /* Get bits, and convert to float. */
6795
10.5k
                                bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
6796
10.5k
                                value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr*/, 0 /* RE */);
6797
                                /* Add to tree. */
6798
10.5k
                                proto_tree_add_float(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
6799
10.5k
                                                     (bfwcomphdr_iq_width+7)/8, value);
6800
10.5k
                                bit_offset += bfwcomphdr_iq_width;
6801
10.5k
                                proto_item_append_text(bfw_ti, "Q=%f", value);
6802
6803
10.5k
                                proto_item_append_text(bfw_ti, ")");
6804
10.5k
                                proto_item_set_len(bfw_ti, (bit_offset+7)/8  - bfw_offset);
6805
10.5k
                            }
6806
                            /* Need to round to next byte */
6807
360
                            offset = (bit_offset+7)/8;
6808
360
                        }
6809
625
                    }
6810
66
                    break;
6811
72
                }
6812
3
                case 2:  /* TDD_CONFIG_PATTERN */
6813
                    /* reserved (2 bits) */
6814
3
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6815
                    /* dirPattern (14 bits) */
6816
3
                    proto_tree_add_item(command_tree, hf_oran_dir_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
6817
3
                    offset += 2;
6818
6819
                    /* reserved (2 bits) */
6820
3
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6821
                    /* guardPattern (14 bits) */
6822
3
                    proto_tree_add_item(command_tree, hf_oran_guard_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
6823
3
                    offset += 2;
6824
3
                    break;
6825
6826
39
                case 3:  /* TRX_CONTROL */
6827
40
                case 5:  /* TRX_CONTROL_BIDIR */
6828
40
                {
6829
                    /* Only allowed cmdScope is ARRAY-COMMAND */
6830
40
                    if (cmd_scope != 0) {
6831
34
                        expert_add_info(pinfo, command_tree, &ei_oran_trx_control_cmd_scope);
6832
34
                    }
6833
6834
                    /* reserved (2 bits) */
6835
40
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6836
                    /* log2MaskBits (4 bits) */
6837
40
                    unsigned log2maskbits;
6838
40
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_log2maskbits, tvb, offset, 1, ENC_BIG_ENDIAN, &log2maskbits);
6839
                    /* sleepMode (2 bits) */
6840
40
                    uint32_t sleep_mode;
6841
40
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_trx, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
6842
40
                    offset += 1;
6843
6844
                    /* reserved (4 bits) */
6845
40
                    add_reserved_field(command_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6846
                    /* numSlotsExt (20 bits) */
6847
40
                    uint32_t num_slots_ext;
6848
40
                    proto_item *num_slots_ext_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_num_slots_ext, tvb, offset, 3, ENC_BIG_ENDIAN, &num_slots_ext);
6849
40
                    if (num_slots==0 && num_slots_ext==0) {
6850
7
                        proto_item_append_text(num_slots_ext_ti, " (undefined sleep period)");
6851
7
                    }
6852
33
                    else {
6853
                        /* Time should be rounded up according to SCS */
6854
33
                        float total = (float)(num_slots + num_slots_ext);
6855
                        /* From table 7.5.2.13-3 */
6856
33
                        const float slot_length_by_scs[16] = { 1000, 500, 250, 125, 62.5, 31.25,
6857
33
                                                         0, 0, 0, 0, 0, 0,  /* reserved */
6858
33
                                                         1000, 1000, 1000, 1000 };
6859
33
                        float slot_length = slot_length_by_scs[scs];
6860
                        /* Only using valid SCS. TODO: is this test ok? */
6861
33
                        if (slot_length != 0) {
6862
                            /* Round up to next slot */
6863
24
                            total = ((int)(total / slot_length) + 1) * slot_length;
6864
24
                            proto_item_append_text(num_slots_ext_ti, " (defined sleep period of %f us)", total);
6865
24
                        }
6866
33
                    }
6867
40
                    offset += 3;
6868
6869
                    /* reserved (2 bits) */
6870
40
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6871
6872
                    /* symbolMask (14 bits) */
6873
40
                    uint32_t symbol_mask;
6874
40
                    proto_item *sm_ti;
6875
40
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &sm_ti);
6876
40
                    if (symbol_mask == 0x0) {
6877
8
                        proto_item_append_text(sm_ti, " (wake)");
6878
8
                        col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
6879
8
                    }
6880
32
                    else if (symbol_mask == 0x3fff) {
6881
5
                        proto_item_append_text(sm_ti, " (sleep)");
6882
5
                        col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
6883
5
                    }
6884
27
                    else {
6885
27
                        expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
6886
27
                                               "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
6887
27
                                               sleep_mode, symbol_mask);
6888
27
                    }
6889
40
                    offset += 2;
6890
6891
                    /* antMask (16-2048 bits).  Size is lookup from log2MaskBits enum.. */
6892
40
                    unsigned antmask_length = 2;
6893
40
                    if (log2maskbits >= 4) {
6894
23
                        antmask_length = (1 << log2maskbits) / 8;
6895
23
                    }
6896
40
                    proto_item *ant_mask_ti = proto_tree_add_item(command_tree, hf_oran_antMask_trx_control, tvb, offset, antmask_length, ENC_NA);
6897
                    /* show count */
6898
40
                    unsigned antenna_count = 0;
6899
2.07k
                    for (unsigned b=0; b < antmask_length; b++) {
6900
2.03k
                        uint8_t byte = tvb_get_uint8(tvb, offset+b);
6901
18.3k
                        for (unsigned bit=0; bit < 8; bit++) {
6902
16.3k
                            if ((1 << bit) & byte) {
6903
7.54k
                                antenna_count++;
6904
7.54k
                            }
6905
16.3k
                        }
6906
2.03k
                    }
6907
40
                    proto_item_append_text(ant_mask_ti, " (%u antennas)", antenna_count);
6908
40
                    offset += antmask_length;
6909
6910
                    /* Pad to next 4-byte boundary */
6911
40
                    offset = WS_ROUNDUP_4(offset);
6912
40
                    break;
6913
39
                }
6914
6915
5
                case 4:  /* ASM (advanced sleep mode) */
6916
                    /* reserved (2+4=6 bits) */
6917
5
                    add_reserved_field(command_tree, hf_oran_reserved_6bits, tvb, offset, 1);
6918
                    /* sleepMode (2 bits) */
6919
5
                    uint32_t sleep_mode;
6920
5
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_asm, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
6921
5
                    offset += 1;
6922
6923
                    /* reserved (4 bits) */
6924
5
                    add_reserved_field(command_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6925
                    /* numSlotsExt (20 bits) */
6926
5
                    proto_tree_add_item(command_tree, hf_oran_num_slots_ext, tvb, offset, 3, ENC_BIG_ENDIAN);
6927
5
                    offset += 3;
6928
6929
                    /* reserved (2 bits) */
6930
5
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6931
                    /* symbolMask (14 bits) */
6932
5
                    uint32_t symbol_mask;
6933
5
                    proto_item *sm_ti;
6934
5
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &sm_ti);
6935
5
                    if (symbol_mask == 0x0) {
6936
2
                        proto_item_append_text(sm_ti, " (wake)");
6937
2
                        col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
6938
2
                    }
6939
3
                    else if (symbol_mask == 0x3fff) {
6940
0
                        proto_item_append_text(sm_ti, " (sleep)");
6941
0
                        col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
6942
0
                    }
6943
3
                    else {
6944
3
                        expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
6945
3
                                               "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
6946
3
                                               sleep_mode, symbol_mask);
6947
3
                    }
6948
5
                    offset += 2;
6949
6950
                    /* reserved (2 bytes) */
6951
5
                    add_reserved_field(command_tree, hf_oran_reserved_16bits, tvb, offset, 2);
6952
5
                    offset += 2;
6953
5
                    break;
6954
6955
143
                default:
6956
                    /* Error! */
6957
143
                    expert_add_info_format(pinfo, len_ti, &ei_oran_st4_unknown_cmd,
6958
143
                                           "Dissected ST4 command (%u) not recognised",
6959
143
                                            st4_cmd_type);
6960
143
                    break;
6961
317
            }
6962
6963
            /* Check apparent size of padding (0-3 bytes ok) */
6964
211
            long padding_remaining = command_start_offset + (st4_cmd_len * 4) - offset;
6965
211
            if (padding_remaining > 3) {
6966
107
                expert_add_info_format(pinfo, len_ti, &ei_oran_st4_wrong_len_cmd,
6967
107
                                       "Dissected ST4 command does not match signalled st4CmdLen - set to %u (%u bytes) but dissected %u bytes",
6968
107
                                        st4_cmd_len, st4_cmd_len*4, offset-command_start_offset);
6969
107
            }
6970
6971
            /* Advance by signalled length (needs to be aligned on 4-byte boundary) */
6972
211
            offset = command_start_offset + (st4_cmd_len * 4);
6973
6974
            /* Set end of command tree */
6975
211
            proto_item_set_end(command_ti, tvb, offset);
6976
6977
211
            if (ack_nack_req_id != 0 && state && state->ack_nack_requests) {
6978
109
                if (!PINFO_FD_VISITED(pinfo)) {
6979
                    /* Add this request into conversation state on first pass */
6980
109
                    ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
6981
109
                    request_details->request_frame_number = pinfo->num;
6982
109
                    request_details->request_frame_time = pinfo->abs_ts;
6983
109
                    request_details->requestType = ST4Cmd1+st4_cmd_type-1;
6984
6985
109
                    wmem_tree_insert32(state->ack_nack_requests,
6986
109
                                       ack_nack_req_id,
6987
109
                                       request_details);
6988
109
                }
6989
0
                else {
6990
                    /* On later passes, try to link forward to ST8 response */
6991
0
                    ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
6992
0
                                                                      ack_nack_req_id);
6993
0
                    if (response) {
6994
0
                        show_link_to_acknack_response(section_tree, tvb, pinfo, response);
6995
0
                    }
6996
0
                }
6997
109
            }
6998
211
        }
6999
109
    }
7000
    /* LAA doesn't have sections either.. */
7001
1.61k
    else if (sectionType == SEC_C_LAA) {   /* Section Type 7 */
7002
        /* 7.2.5 Table 6.4-6 */
7003
15
        unsigned mcot;
7004
15
        proto_item *mcot_ti;
7005
7006
        /* laaMsgType */
7007
15
        uint32_t laa_msg_type;
7008
15
        proto_item *laa_msg_type_ti;
7009
15
        laa_msg_type_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgType, tvb, offset, 1, ENC_NA, &laa_msg_type);
7010
        /* laaMsgLen */
7011
15
        uint32_t laa_msg_len;
7012
15
        proto_item *len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgLen, tvb, offset, 1, ENC_NA, &laa_msg_len);
7013
15
        proto_item_append_text(len_ti, " (%u bytes)", 4*laa_msg_len);
7014
15
        if (laa_msg_len == 0) {
7015
4
            proto_item_append_text(len_ti, " (reserved)");
7016
4
        }
7017
15
        offset += 1;
7018
7019
15
        int payload_offset = offset;
7020
7021
        /* Payload */
7022
15
        switch (laa_msg_type) {
7023
6
            case 0:
7024
                /* LBT_PDSCH_REQ */
7025
                /* lbtHandle (16 bits) */
7026
6
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7027
6
                offset += 2;
7028
                /* lbtOffset (10 bits) */
7029
6
                proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
7030
6
                offset += 1;
7031
                /* lbtMode  (2 bits) */
7032
6
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
7033
                /* reserved (1 bit) */
7034
6
                add_reserved_field(section_tree, hf_oran_reserved_bit4, tvb, offset, 1);
7035
                /* lbtDeferFactor (3 bits) */
7036
6
                proto_tree_add_item(section_tree, hf_oran_lbtDeferFactor, tvb, offset, 1, ENC_BIG_ENDIAN);
7037
6
                offset += 1;
7038
                /* lbtBackoffCounter (10 bits) */
7039
6
                proto_tree_add_item(section_tree, hf_oran_lbtBackoffCounter, tvb, offset, 2, ENC_BIG_ENDIAN);
7040
6
                offset += 1;
7041
                /* MCOT (4 bits) */
7042
6
                mcot_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_MCOT, tvb, offset, 1, ENC_BIG_ENDIAN, &mcot);
7043
6
                if (mcot<1 || mcot>10) {
7044
5
                    proto_item_append_text(mcot_ti, " (should be in range 1-10!)");
7045
5
                    expert_add_info_format(pinfo, mcot_ti, &ei_oran_mcot_out_of_range,
7046
5
                                           "MCOT seen with value %u (must be 1-10)", mcot);
7047
7048
5
                }
7049
                /* reserved (10 bits) */
7050
6
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+6, 10, ENC_BIG_ENDIAN);
7051
6
                break;
7052
2
            case 1:
7053
                /* LBT_DRS_REQ */
7054
                /* lbtHandle (16 bits) */
7055
2
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7056
2
                offset += 2;
7057
                /* lbtOffset (10 bits) */
7058
2
                proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
7059
2
                offset += 1;
7060
                /* lbtMode  (2 bits) */
7061
2
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
7062
                /* reserved (28 bits) */
7063
2
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+4, 28, ENC_BIG_ENDIAN);
7064
2
                break;
7065
2
            case 2:
7066
                /* LBT_PDSCH_RSP */
7067
                /* lbtHandle (16 bits) */
7068
2
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7069
2
                offset += 2;
7070
                /* lbtPdschRes (2 bits) */
7071
2
                proto_tree_add_item(section_tree, hf_oran_lbtPdschRes, tvb, offset, 1, ENC_BIG_ENDIAN);
7072
                /* inParSF (1 bit) */
7073
2
                proto_tree_add_item(section_tree, hf_oran_initialPartialSF, tvb, offset, 1, ENC_BIG_ENDIAN);
7074
                /* sfStatus (1 bit) */
7075
2
                proto_tree_add_item(section_tree, hf_oran_sfStatus, tvb, offset, 1, ENC_BIG_ENDIAN);
7076
                /* sfnSf (12 bits) */
7077
2
                proto_tree_add_item(section_tree, hf_oran_sfnSfEnd, tvb, offset, 2, ENC_BIG_ENDIAN);
7078
2
                offset += 2;
7079
                /* reserved (24 bits) */
7080
2
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8), 24, ENC_BIG_ENDIAN);
7081
2
                break;
7082
1
            case 3:
7083
                /* LBT_DRS_RSP */
7084
                /* lbtHandle (16 bits) */
7085
1
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7086
1
                offset += 2;
7087
                /* lbtDrsRes (1 bit) */
7088
1
                proto_tree_add_item(section_tree, hf_oran_lbtDrsRes, tvb, offset, 1, ENC_BIG_ENDIAN);
7089
                /* reserved (7 bits) */
7090
1
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
7091
1
                break;
7092
1
            case 4:
7093
                /* LBT_Buffer_Error */
7094
                /* lbtHandle (16 bits) */
7095
1
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7096
1
                offset += 2;
7097
                /* lbtBufErr (1 bit) */
7098
1
                proto_tree_add_item(section_tree, hf_oran_lbtBufErr, tvb, offset, 1, ENC_BIG_ENDIAN);
7099
                /* reserved (7 bits) */
7100
1
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
7101
1
                break;
7102
1
            case 5:
7103
                /* LBT_CWCONFIG_REQ */
7104
                /* lbtHandle (16 bits) */
7105
1
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7106
1
                offset += 2;
7107
                /* lbtCWConfig_H (8 bits) */
7108
1
                proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_H, tvb, offset, 1, ENC_BIG_ENDIAN);
7109
1
                offset += 1;
7110
                /* lbtCWConfig_T (8 bits) */
7111
1
                proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_T, tvb, offset, 1, ENC_BIG_ENDIAN);
7112
1
                offset += 1;
7113
                /* lbtMode  (2 bits) */
7114
1
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
7115
                /* lbtTrafficClass (3 bits) */
7116
1
                proto_tree_add_item(section_tree, hf_oran_lbtTrafficClass, tvb, offset, 1, ENC_BIG_ENDIAN);
7117
                /* reserved (19 bits) */
7118
1
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+5, 19, ENC_BIG_ENDIAN);
7119
1
                break;
7120
1
            case 6:
7121
                /* LBT_CWCONFIG_RSP */
7122
                /* lbtHandle (16 bits) */
7123
1
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
7124
1
                offset += 2;
7125
                /* lbtCWR_Rst (1 bit) */
7126
1
                proto_tree_add_item(section_tree, hf_oran_lbtCWR_Rst, tvb, offset, 1, ENC_BIG_ENDIAN);
7127
                /* reserved (7 bits) */
7128
1
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
7129
1
                break;
7130
7131
1
            default:
7132
                /* Unhandled! */
7133
1
                expert_add_info_format(pinfo, laa_msg_type_ti, &ei_oran_laa_msg_type_unsupported,
7134
1
                                       "laaMsgType %u not supported by dissector",
7135
1
                                       laa_msg_type);
7136
7137
1
                break;
7138
15
        }
7139
        /* For now just skip indicated length of bytes */
7140
15
        offset = payload_offset + 4*(laa_msg_len+1);
7141
15
    }
7142
7143
7144
    /* Dissect each C section */
7145
19.2k
    for (uint32_t i = 0; i < nSections; ++i) {
7146
17.6k
        tvbuff_t *section_tvb = tvb_new_subset_remaining(tvb, offset);
7147
17.6k
        offset += dissect_oran_c_section(section_tvb, oran_tree, pinfo, state, sectionType, tap_info,
7148
17.6k
                                         protocol_item,
7149
17.6k
                                         subframeId, frameId, slotId, startSymbolId,
7150
17.6k
                                         bit_width, ci_comp_method, ci_comp_opt,
7151
17.6k
                                         num_sinr_per_prb);
7152
17.6k
    }
7153
7154
    /* Expert error if we are short of tvb by > 3 bytes */
7155
1.61k
    if (tvb_reported_length_remaining(tvb, offset) > 3) {
7156
43
        expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
7157
43
                               "%u bytes remain at end of frame - should be 0-3",
7158
43
                               tvb_reported_length_remaining(tvb, offset));
7159
43
    }
7160
7161
1.61k
    if (PINFO_FD_VISITED(pinfo) && result) {
7162
        /* Show list of frames that have corresponding U-plane data */
7163
0
        wmem_list_frame_t *list_frame;
7164
0
        for (list_frame = wmem_list_head(result->u_plane_frames); list_frame != NULL; list_frame = wmem_list_frame_next(list_frame)) {
7165
0
            corresponding_uplane_frame *frame = wmem_list_frame_data(list_frame);
7166
0
            proto_item *uplane_frame_ti = proto_tree_add_uint(oran_tree, hf_oran_corresponding_uplane_frame, tvb, 0, 0,
7167
0
                                                              frame->frame_number);
7168
0
            proto_item_append_text(uplane_frame_ti, "  sectionId:%2u symbol:%2u PRBs %3u->%3u  (in %uus)",
7169
0
                                   frame->sectionId, frame->symbol, frame->startPrbu, frame->startPrbu+frame->numPrbu-1, frame->gap_in_usecs);
7170
0
            proto_item_set_generated(uplane_frame_ti);
7171
0
        }
7172
        /* Also show total number of corresponding u-plane frames */
7173
0
        proto_item *uplane_frame_count_ti = proto_tree_add_uint(oran_tree, hf_oran_corresponding_uplane_frames_total, tvb, 0, 0,
7174
0
                                                                wmem_list_count(result->u_plane_frames));
7175
0
        proto_item_set_generated(uplane_frame_count_ti);
7176
0
    }
7177
7178
1.61k
    return tvb_captured_length(tvb);
7179
1.72k
}
7180
7181
static int dissect_oran_u_re(tvbuff_t *tvb, proto_tree *tree,
7182
                             unsigned sample_number, int samples_offset,
7183
                             oran_tap_info *tap_info,
7184
                             unsigned sample_bit_width,
7185
                             int comp_meth,
7186
                             uint32_t exponent,
7187
                             section_mod_compr_config_t *mod_compr_params,
7188
                             uint8_t re)
7189
24.8k
{
7190
    /* I */
7191
24.8k
    unsigned i_bits = tvb_get_bits32(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
7192
24.8k
    float i_value = decompress_value(i_bits, comp_meth, sample_bit_width, exponent, mod_compr_params, re);
7193
24.8k
    unsigned sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
7194
24.8k
    proto_item *i_ti = proto_tree_add_float(tree, hf_oran_iSample, tvb, samples_offset/8, sample_len_in_bytes, i_value);
7195
24.8k
    proto_item_set_text(i_ti, "iSample: % 0.7f  0x%04x (RE-%2u in the PRB)", i_value, i_bits, sample_number);
7196
24.8k
    samples_offset += sample_bit_width;
7197
    /* Q */
7198
24.8k
    unsigned q_bits = tvb_get_bits32(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
7199
24.8k
    float q_value = decompress_value(q_bits, comp_meth, sample_bit_width, exponent, mod_compr_params, re);
7200
24.8k
    sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
7201
24.8k
    proto_item *q_ti = proto_tree_add_float(tree, hf_oran_qSample, tvb, samples_offset/8, sample_len_in_bytes, q_value);
7202
24.8k
    proto_item_set_text(q_ti, "qSample: % 0.7f  0x%04x (RE-%2u in the PRB)", q_value, q_bits, sample_number);
7203
24.8k
    samples_offset += sample_bit_width;
7204
7205
    /* Update RE stats */
7206
24.8k
    tap_info->num_res++;
7207
    /* if (i_value == 0.0 && q_value == 0.0) { */
7208
    /* TODO: is just checking bits from frame good enough - assuming this always corresponds to a zero value? */
7209
24.8k
    if (i_bits == 0 && q_bits == 0) {
7210
5.82k
        tap_info->num_res_zero++;
7211
5.82k
    }
7212
19.0k
    else {
7213
19.0k
        tap_info->non_zero_re_in_current_prb = true;
7214
19.0k
    }
7215
24.8k
    return samples_offset;
7216
24.8k
}
7217
7218
7219
static bool udcomplen_appears_present(bool udcomphdr_present, tvbuff_t *tvb, int offset)
7220
921
{
7221
921
    if (!udcomplen_heuristic_result_set) {
7222
        /* All sections will start the same way */
7223
2
        unsigned int section_bytes_before_field = (udcomphdr_present) ? 6 : 4;
7224
7225
        /* Move offset back to the start of the section */
7226
2
        offset -= section_bytes_before_field;
7227
7228
2
        do {
7229
            /* This field appears several bytes into the U-plane section */
7230
2
            uint32_t length_remaining = tvb_reported_length_remaining(tvb, offset);
7231
            /* Are there enough bytes to still read the length field? */
7232
2
            if (section_bytes_before_field+2 > length_remaining) {
7233
0
                udcomplen_heuristic_result = false;
7234
0
                udcomplen_heuristic_result_set = true;
7235
0
                break;
7236
0
            }
7237
7238
            /* Read the length field */
7239
2
            uint16_t udcomplen = tvb_get_ntohs(tvb, offset+section_bytes_before_field);
7240
7241
            /* Is this less than a valid section? Realistic minimal section will be bigger than this..
7242
             * Could take into account numPrbU, etc */
7243
2
            if (udcomplen < section_bytes_before_field+2) {
7244
1
                udcomplen_heuristic_result = false;
7245
1
                udcomplen_heuristic_result_set = true;
7246
1
                break;
7247
1
            }
7248
7249
            /* Does this section fit into the frame? */
7250
1
            if (udcomplen > length_remaining) {
7251
1
                udcomplen_heuristic_result = false;
7252
1
                udcomplen_heuristic_result_set = true;
7253
1
                break;
7254
1
            }
7255
7256
            /* Move past this section */
7257
0
            offset += udcomplen;
7258
7259
            /* Are we at the end of the frame? */
7260
            /* TODO: if frame is less than 60 bytes, there may be > 4 bytes, likely zeros.. */
7261
0
            if (tvb_reported_length_remaining(tvb, offset) < 4) {
7262
0
                udcomplen_heuristic_result = true;
7263
0
                udcomplen_heuristic_result_set = true;
7264
0
            }
7265
0
        } while (!udcomplen_heuristic_result_set);
7266
2
    }
7267
921
    return udcomplen_heuristic_result;
7268
921
}
7269
7270
static bool at_udcomphdr(tvbuff_t *tvb, int offset)
7271
38
{
7272
38
    if (tvb_captured_length_remaining(tvb, offset) < 2) {
7273
1
        return false;
7274
1
    }
7275
37
    uint8_t first_byte = tvb_get_uint8(tvb, offset);
7276
37
    uint8_t reserved_byte = tvb_get_uint8(tvb, offset+1);
7277
7278
    /* - iq width could be anything, though unlikely to be signalled as (say) < 1-3? */
7279
    /* - meth should be 0-8 */
7280
    /* - reserved byte should be 0 */
7281
37
    return (((first_byte & 0x0f) <= MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) && (reserved_byte == 0));
7282
38
}
7283
7284
static bool udcomphdr_appears_present(flow_state_t *flow, uint32_t direction, tvbuff_t *tvb, int offset)
7285
1.08k
{
7286
    /* Should really not happen, but guard against this anyway. */
7287
1.08k
    if (flow == NULL) {
7288
        /* No state to update. */
7289
0
        return false;
7290
0
    }
7291
7292
1.08k
    if (direction == DIR_UPLINK) {
7293
159
        if (flow->udcomphdrUplink_heuristic_result_set) {
7294
            /* Return cached value */
7295
142
            return flow->udcomphdrUplink_heuristic_result;
7296
142
        }
7297
17
        else {
7298
            /* Work it out, and save answer for next time */
7299
17
            flow->udcomphdrUplink_heuristic_result_set = true;
7300
17
            flow->udcomphdrUplink_heuristic_result = at_udcomphdr(tvb, offset);
7301
17
            return flow->udcomphdrUplink_heuristic_result;
7302
17
        }
7303
159
    }
7304
925
    else {
7305
        /* Downlink */
7306
925
        if (flow->udcomphdrDownlink_heuristic_result_set) {
7307
            /* Return cached value */
7308
904
            return flow->udcomphdrDownlink_heuristic_result;
7309
904
        }
7310
21
        else {
7311
            /* Work it out, and save answer for next time */
7312
21
            flow->udcomphdrDownlink_heuristic_result_set = true;
7313
21
            flow->udcomphdrDownlink_heuristic_result = at_udcomphdr(tvb, offset);
7314
21
            return flow->udcomphdrDownlink_heuristic_result;
7315
21
        }
7316
925
    }
7317
1.08k
}
7318
7319
static bool copy_section_entry(const void *key, void* value, void *userdata)
7320
85
{
7321
    /* Cast parameters to their types */
7322
85
    uint32_t sectionId = GPOINTER_TO_UINT(key);
7323
85
    expected_section_data_t *result_value = (expected_section_data_t *)value;
7324
85
    wmem_tree_t *result_tree = (wmem_tree_t*)userdata;
7325
7326
    /* Deep copy of section data */
7327
85
    expected_section_data_t *copy = wmem_new0(wmem_file_scope(), expected_section_data_t);
7328
85
    *copy = *result_value;
7329
7330
    /* Add into result tree */
7331
85
    wmem_tree_insert32(result_tree, sectionId, copy);
7332
7333
85
    return false;
7334
85
}
7335
7336
/*
7337
  dissect_oran_u_timing_header()
7338
  Table 8.3.2-1, octets 9-12..
7339
 */
7340
static int dissect_oran_u_timing_header(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
7341
                                        proto_item * timingHeader, oran_tap_info *tap_info, uint32_t * frameIdPtr, uint32_t * subframeIdPtr, uint32_t * slotIdPtr,
7342
                                        uint32_t * symbolIdPtr, uint32_t * directionPtr )
7343
181
{
7344
    /* Now does the data combine correctly? */
7345
    /* Common header for time reference */
7346
181
    proto_tree *timing_header_tree = proto_item_add_subtree(timingHeader, ett_oran_u_timing);
7347
7348
    /* dataDirection */
7349
181
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, directionPtr);
7350
181
    tap_info->uplink = ((*directionPtr)==0);
7351
    /* payloadVersion */
7352
181
    dissect_payload_version(timing_header_tree, tvb, pinfo, offset);
7353
    /* filterIndex */
7354
181
    proto_tree_add_item(timing_header_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
7355
181
    offset += 1;
7356
7357
181
    int ref_a_offset = offset;
7358
7359
    /* frameId */
7360
181
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, frameIdPtr);
7361
181
    tap_info->frame = *frameIdPtr;
7362
181
    offset += 1;
7363
7364
    /* subframeId */
7365
181
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, subframeIdPtr);
7366
    /* slotId */
7367
181
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, slotIdPtr);
7368
181
    tap_info->slot = *slotIdPtr;
7369
181
    offset++;
7370
    /* symbolId */
7371
181
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, symbolIdPtr);
7372
181
    offset++;
7373
7374
181
    char id[16];
7375
181
    snprintf(id, 16, "%u-%u-%u-%u", *frameIdPtr, *subframeIdPtr, *slotIdPtr, *symbolIdPtr);
7376
181
    proto_item *pi = proto_tree_add_string(timing_header_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
7377
181
    proto_item_set_generated(pi);
7378
7379
181
    proto_item_append_text(timingHeader, "%s, frameId: %d, subframeId: %d, slotId: %d, symbolId: %d)",
7380
181
        val_to_str_const(*directionPtr, data_direction_vals, "Unknown"), *frameIdPtr, *subframeIdPtr, *slotIdPtr, *symbolIdPtr);
7381
181
    return offset;
7382
181
}
7383
7384
/*
7385
  dissect_oran_u_section_header()
7386
  Mandatory Section Header fields (darker green part)
7387
  Table 8.3.2-1, octets 13-16.  Optional fields handled elsewhere.
7388
 */
7389
static int dissect_oran_u_section_header(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
7390
                                         proto_tree * section_tree,
7391
                                         oran_tap_info *tap_info,
7392
                                         flow_result_t *result, flow_state_t *cplane_state,
7393
                                         uint32_t frameId, uint32_t subframeId, uint32_t slotId, uint32_t symbolId,
7394
                                         uint32_t direction, uint32_t * sectionIdPtr, uint32_t * rbPtr, uint32_t *startPrbuPtr, uint32_t *numPrbuPtr,
7395
                                         section_details_t **section_details_ptr)
7396
1.09k
{
7397
1.09k
    proto_item *sectionId_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, sectionIdPtr);
7398
1.09k
    if (*sectionIdPtr == 4095) {
7399
347
        proto_item_append_text(sectionId_ti, " (not default coupling C/U planes using sectionId)");
7400
347
    }
7401
1.09k
    offset++;
7402
7403
1.09k
    if (tap_info->num_section_ids < MAX_SECTION_IDs) {
7404
1.03k
        tap_info->section_ids[tap_info->num_section_ids++] = *sectionIdPtr;
7405
1.03k
    }
7406
7407
1.09k
    section_details_t *section_details = NULL;
7408
1.09k
    corresponding_uplane_frame *details = NULL;
7409
7410
    /* Lookup corresponding C-plane frame/info */
7411
1.09k
    if (link_planes_together) {
7412
1.09k
        if (cplane_state != NULL && result) {
7413
7414
11
            expected_section_data_t *section_data = NULL;
7415
11
            section_data = wmem_tree_lookup32(result->expected_sections, *sectionIdPtr);
7416
7417
11
            if (section_data) {
7418
                /* Need to work out which of 2 entries is in use for this data frame */
7419
1
                unsigned index_to_use = 0;
7420
7421
                /* Does the first entry match the timing for this frame? */
7422
1
                if (section_data->details[0].frame == frameId &&
7423
0
                    section_data->details[0].subframe == subframeId &&
7424
0
                    section_data->details[0].slot == slotId &&
7425
                    /* Check that symbolId is in range */
7426
0
                    section_data->details[0].startSymbol <= symbolId &&
7427
0
                    (unsigned)(section_data->details[0].startSymbol + section_data->details[0].numSymbols) <= (unsigned)symbolId) {
7428
7429
0
                    index_to_use = 0;
7430
0
                }
7431
1
                else if (section_data->details[1].frame == frameId &&
7432
0
                         section_data->details[1].subframe == subframeId &&
7433
0
                         section_data->details[1].slot == slotId &&
7434
                         /* Check that symbolId is in range */
7435
0
                         section_data->details[1].startSymbol <= symbolId &&
7436
0
                         (unsigned)(section_data->details[1].startSymbol + section_data->details[1].numSymbols) <= (unsigned)symbolId) {
7437
7438
0
                    index_to_use = 1;
7439
0
                }
7440
1
                else {
7441
                    /* There was a sectionId, but timing header didn't exactly match, so neither index may be used.. */
7442
1
                    index_to_use = 2;         /* invalid value */
7443
                    /* Expert info */
7444
1
                    expert_add_info_format(NULL, sectionId_ti,
7445
1
                                           &ei_oran_cplane_entry_not_found,
7446
1
                                           "C-plane entry for %s sectionId %u at timing header %u-%u-%u-%u"
7447
1
                                           " timing didn't match C-plane",
7448
1
                                           (direction) ? "DL" : "UL", *sectionIdPtr,
7449
1
                                           frameId, subframeId, slotId, symbolId);
7450
1
                }
7451
7452
1
                if (index_to_use <= 1) {
7453
0
                    section_details = &section_data->details[index_to_use];
7454
7455
                    /* Cplane frame number */
7456
0
                    proto_item *cplane_frame_ti = proto_tree_add_uint(section_tree, hf_oran_corresponding_cplane_frame, tvb, 0, 0,
7457
0
                                                                      section_details->frame_number);
7458
0
                    proto_item_set_generated(cplane_frame_ti);
7459
7460
                    /* usecs since cplane frame */
7461
0
                    time_t total_gap = 0;
7462
7463
0
                    if ((pinfo->abs_ts.secs == section_details->frame_time.secs) || (pinfo->abs_ts.secs == section_details->frame_time.secs+1)) {
7464
0
                        total_gap = ((pinfo->abs_ts.secs - section_details->frame_time.secs) * 1000000) +
7465
0
                            ((pinfo->abs_ts.nsecs - section_details->frame_time.nsecs)/1000);
7466
0
                    }
7467
7468
0
                    if (total_gap > 0) {
7469
0
                        proto_item *cplane_delta_ti = proto_tree_add_uint(section_tree, hf_oran_corresponding_cplane_frame_time_delta, tvb, 0, 0, (uint32_t)total_gap);
7470
0
                        proto_item_set_generated(cplane_delta_ti);
7471
0
                    }
7472
7473
0
                    if (!PINFO_FD_VISITED(pinfo)) {
7474
                        /* Look up 'result' for c-plane frame, and tell it about this frame.. */
7475
0
                        flow_result_t *cplane_result = wmem_tree_lookup32(flow_results_table, section_details->frame_number);
7476
0
                        if (!cplane_result) {
7477
0
                            cplane_result = wmem_new0(wmem_file_scope(), flow_result_t);
7478
0
                            cplane_result->u_plane_frames = wmem_list_new(wmem_file_scope());
7479
0
                            wmem_tree_insert32(flow_results_table, section_details->frame_number, cplane_result);
7480
0
                        }
7481
                        /* PRB range filled in below.. */
7482
7483
0
                        details = wmem_new(wmem_file_scope(), corresponding_uplane_frame);
7484
0
                        details->frame_number = pinfo->num;
7485
0
                        details->gap_in_usecs = (uint32_t)total_gap;
7486
0
                        details->sectionId = *sectionIdPtr;
7487
0
                        details->symbol = symbolId;
7488
7489
0
                        wmem_list_append(cplane_result->u_plane_frames, details);
7490
0
                    }
7491
0
                }
7492
1
            }
7493
10
            else {
7494
                /* No section entry at all */
7495
10
                expert_add_info_format(NULL, sectionId_ti,
7496
10
                                       &ei_oran_cplane_entry_not_found,
7497
10
                                       "C-plane entry for %s sectionId %u not found",
7498
10
                                       (direction) ? "DL" : "UL", *sectionIdPtr);
7499
10
            }
7500
11
        }
7501
1.09k
    }
7502
7503
    /* rb */
7504
1.09k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, rbPtr);
7505
    /* symInc. "use of symInc=1 shall be prohibited in the U-plane"  */
7506
1.09k
    uint8_t syminc;
7507
1.09k
    proto_item *syminc_ti = proto_tree_add_item_ret_uint8(section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA, &syminc);
7508
1.09k
    if (syminc) {
7509
758
        expert_add_info(NULL, syminc_ti, &ei_oran_syminc_set_for_uplane);
7510
758
    }
7511
    /* startPrbu */
7512
1.09k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, startPrbuPtr);
7513
1.09k
    offset += 2;
7514
7515
    /* numPrbu */
7516
1.09k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, numPrbuPtr);
7517
1.09k
    offset += 1;
7518
7519
1.09k
    if (!PINFO_FD_VISITED(pinfo) && details) {
7520
0
        details->startPrbu = *startPrbuPtr;
7521
0
        details->numPrbu = (*numPrbuPtr) ? (*numPrbuPtr) : 273;
7522
0
    }
7523
7524
1.09k
    *section_details_ptr = section_details;
7525
1.09k
    return offset;
7526
1.09k
}
7527
7528
static int dissect_oran_u_section(tvbuff_t *tvb, packet_info *pinfo, unsigned offset,
7529
                                  proto_tree * oran_tree,
7530
                                  proto_item * protocol_item,
7531
                                  oran_tap_info *tap_info,
7532
                                  flow_state_t *state, flow_result_t *result, flow_state_t *cplane_state,
7533
                                  uint32_t frameId, uint32_t subframeId, uint32_t slotId, uint32_t symbolId,
7534
                                  uint32_t direction, int includeUdCompHeader, unsigned * sample_bit_width_ptr,
7535
                                  unsigned compression, bool ud_cmp_hdr_cplane,     unsigned *nBytesPerPrbPtr)
7536
1.08k
{
7537
    /* Section subtree */
7538
1.08k
    unsigned section_start_offset = offset;
7539
1.08k
    proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_u_section,
7540
1.08k
                                                              tvb, offset, 0, "", "Section");
7541
1.08k
    proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_u_section);
7542
1.08k
    section_details_t *section_details = NULL;
7543
7544
    /* Section Header fields [fixed parts] (darker green part) */
7545
1.08k
    uint32_t sectionId = 0, rb, startPrbu = 0, numPrbu = 0;
7546
7547
1.08k
    offset = dissect_oran_u_section_header(tvb, pinfo, offset, section_tree, tap_info, result, cplane_state,
7548
1.08k
                                           frameId, subframeId, slotId, symbolId, direction, &sectionId, &rb, &startPrbu, &numPrbu,
7549
1.08k
                                           &section_details);
7550
7551
1.08k
    proto_item *ud_comp_meth_item, *ud_comp_len_ti=NULL;
7552
1.08k
    uint32_t ud_comp_len = 0;
7553
7554
    /* udCompHdr (if preferences indicate will be present) */
7555
1.08k
    bool included = (includeUdCompHeader==1) ||   /* 1 means present.. */
7556
1.08k
        (includeUdCompHeader==2 && udcomphdr_appears_present(state, direction, tvb, offset));
7557
1.08k
    if (included) {
7558
        /* 7.5.2.10 */
7559
        /* Extract these values to inform how wide IQ samples in each PRB will be. */
7560
1.05k
        offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset, false, direction == 0, sample_bit_width_ptr,
7561
1.05k
                                   &compression, &ud_comp_meth_item, tap_info);
7562
7563
        /* Not part of udCompHdr */
7564
1.05k
        uint32_t reserved;
7565
1.05k
        proto_item *res_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA, &reserved);
7566
1.05k
        offset += 1;
7567
1.05k
        if (reserved != 0) {
7568
894
            expert_add_info_format(pinfo, res_ti, &ei_oran_reserved_not_zero,
7569
894
                                   "reserved field (0x%x) not zero - perhaps udCompHdr is not really present?",
7570
894
                                   reserved);
7571
894
        }
7572
1.05k
    }
7573
31
    else {
7574
        /* No fields to dissect - just showing comp values from prefs */
7575
        /* iqWidth */
7576
31
        proto_item *iq_width_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrIqWidth_pref, tvb, 0, 0, *sample_bit_width_ptr);
7577
31
        proto_item_append_text(iq_width_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
7578
31
        proto_item_set_generated(iq_width_item);
7579
7580
        /* udCompMethod */
7581
31
        ud_comp_meth_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, compression);
7582
31
        proto_item_append_text(ud_comp_meth_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
7583
31
        proto_item_set_generated(ud_comp_meth_item);
7584
7585
        /* Point back to C-Plane, if used */
7586
        /* TODO: doesn't work with multiple port mappings using SE10.. */
7587
31
        if (ud_cmp_hdr_cplane) {
7588
6
            proto_item *cplane_ti = proto_tree_add_uint(section_tree, hf_oran_ul_cplane_ud_comp_hdr_frame, tvb, offset, 0, cplane_state->ul_ud_comp_hdr_frame);
7589
6
            proto_item_set_generated(cplane_ti);
7590
6
        }
7591
7592
31
        tap_info->compression_methods |= (1 << compression);
7593
31
        tap_info->compression_width = *sample_bit_width_ptr;
7594
31
    }
7595
7596
    /* Not supported! TODO: other places where comp method is looked up (e.g., bfw?) */
7597
1.08k
    switch (compression) {
7598
49
    case COMP_NONE:
7599
86
    case COMP_BLOCK_FP:
7600
122
    case BFP_AND_SELECTIVE_RE:
7601
136
    case COMP_MODULATION:
7602
225
    case MOD_COMPR_AND_SELECTIVE_RE:
7603
225
        break;
7604
858
    default:
7605
858
        expert_add_info_format(pinfo, ud_comp_meth_item, &ei_oran_unsupported_compression_method,
7606
858
                               "Compression method %u (%s) not supported by dissector",
7607
858
                               compression,
7608
858
                               rval_to_str_const(compression, ud_comp_header_meth, "reserved"));
7609
1.08k
    }
7610
7611
    /* udCompLen (when supported, methods 5,6,7,8) */
7612
1.08k
    if (compression >= BFP_AND_SELECTIVE_RE) {
7613
921
        bool supported = (pref_support_udcompLen==1) || /* supported */
7614
921
            (pref_support_udcompLen==2 && udcomplen_appears_present(includeUdCompHeader, tvb, offset));
7615
7616
921
        if (supported) {
7617
0
            ud_comp_len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_udCompLen, tvb, offset, 2, ENC_BIG_ENDIAN, &ud_comp_len);
7618
0
            if (ud_comp_len <= 1) {
7619
0
                proto_item_append_text(ud_comp_len_ti, " (reserved)");
7620
0
            }
7621
            /* TODO: report if less than a viable section in frame? */
7622
            /* Check that there is this much length left in the frame */
7623
0
            if (ud_comp_len > tvb_reported_length_remaining(tvb, section_start_offset)) {
7624
0
                expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
7625
0
                                       "udCompLen indicates %u bytes in section, but only %u are left in frame",
7626
0
                                       ud_comp_len, tvb_reported_length_remaining(tvb, section_start_offset));
7627
0
            }
7628
            /* Actual length of section will be checked below, at the end of the section */
7629
0
            offset += 2;
7630
0
        }
7631
921
    }
7632
7633
    /* sReSMask1 + sReSMask2 (depends upon compression method) */
7634
1.08k
    uint64_t sresmask1=0, sresmask2=0;
7635
1.08k
    if (compression == BFP_AND_SELECTIVE_RE_WITH_MASKS ||
7636
1.07k
        compression == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS)
7637
33
        {
7638
33
            static int * const  sres_mask1_2_flags[] = {
7639
33
                &hf_oran_sReSMask1_2_re12,
7640
33
                &hf_oran_sReSMask1_2_re11,
7641
33
                &hf_oran_sReSMask1_2_re10,
7642
33
                &hf_oran_sReSMask1_2_re9,
7643
33
                &hf_oran_sReSMask_re8,
7644
33
                &hf_oran_sReSMask_re7,
7645
33
                &hf_oran_sReSMask_re6,
7646
33
                &hf_oran_sReSMask_re5,
7647
33
                &hf_oran_sReSMask_re4,
7648
33
                &hf_oran_sReSMask_re3,
7649
33
                &hf_oran_sReSMask_re2,
7650
33
                &hf_oran_sReSMask_re1,
7651
33
                NULL
7652
33
            };
7653
7654
            /* reserved (4 bits) */
7655
33
            add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
7656
            /* sReSMask1 (12 bits) */
7657
33
            proto_item *sresmask_ti;
7658
33
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
7659
33
                                                            hf_oran_sReSMask1,
7660
33
                                                            ett_oran_sresmask,
7661
33
                                                            sres_mask1_2_flags,
7662
33
                                                            ENC_NA,
7663
33
                                                            &sresmask1);
7664
33
            offset += 2;
7665
            /* Count REs present */
7666
33
            unsigned res = 0;
7667
417
            for (unsigned n=0; n < 12; n++) {
7668
384
                if ((sresmask1 >> n) & 0x1) {
7669
125
                    res++;
7670
125
                }
7671
384
            }
7672
33
            proto_item_append_text(sresmask_ti, "   (%u REs)", res);
7673
7674
7675
            /* reserved (4 bits) */
7676
33
            add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
7677
            /* sReSMask2 (12 bits) */
7678
33
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
7679
33
                                                            hf_oran_sReSMask2,
7680
33
                                                            ett_oran_sresmask,
7681
33
                                                            sres_mask1_2_flags,
7682
33
                                                            ENC_NA,
7683
33
                                                            &sresmask2);
7684
33
            offset += 2;
7685
7686
33
            if (rb == 1) {
7687
19
                proto_item_append_text(sresmask_ti, " (ignored)");
7688
19
                if (sresmask2 != 0) {
7689
18
                    expert_add_info(pinfo, ud_comp_len_ti, &ei_oran_sresmask2_not_zero_with_rb);
7690
18
                }
7691
19
            }
7692
14
            else {
7693
                /* Count REs present */
7694
14
                res = 0;
7695
170
                for (unsigned n=0; n < 12; n++) {
7696
156
                    if ((sresmask2 >> n) & 0x1) {
7697
74
                        res++;
7698
74
                    }
7699
156
                }
7700
14
                proto_item_append_text(sresmask_ti, "   (%u REs)", res);
7701
14
            }
7702
33
        }
7703
7704
1.08k
    write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
7705
7706
    /* TODO: should this use the same pref as c-plane? */
7707
1.08k
    if (numPrbu == 0) {
7708
        /* Special case for all PRBs (NR: the total number of PRBs may be > 255) */
7709
47
        numPrbu = pref_data_plane_section_total_rbs;
7710
47
        startPrbu = 0;  /* may already be 0... */
7711
47
    }
7712
7713
1.08k
    section_mod_compr_config_t* mod_compr_config = get_mod_compr_section_to_read(cplane_state, sectionId);
7714
7715
    /* Add each PRB */
7716
124k
    for (unsigned i = 0; i < numPrbu; i++) {
7717
        /* Create subtree */
7718
123k
        proto_item *prbHeading = proto_tree_add_string_format(section_tree, hf_oran_samples_prb,
7719
123k
                                                              tvb, offset, 0,
7720
123k
                                                              "", "PRB");
7721
123k
        proto_tree *rb_tree = proto_item_add_subtree(prbHeading, ett_oran_u_prb);
7722
123k
        uint32_t exponent = 0;
7723
123k
        uint16_t sresmask = 0;
7724
7725
        /* udCompParam (depends upon compression method) */
7726
123k
        int before = offset;
7727
123k
        offset = dissect_udcompparam(tvb, pinfo, rb_tree, offset, compression, &exponent, &sresmask, false);
7728
123k
        int udcompparam_len = offset-before;
7729
7730
        /* Show PRB number in root */
7731
123k
        proto_item_append_text(prbHeading, " %3u", startPrbu + i*(1+rb));
7732
7733
        /* Work out how many REs / PRB */
7734
123k
        unsigned res_per_prb = 12;
7735
123k
        uint16_t sresmask_to_use = 0x0fff;
7736
7737
123k
        if (compression >= BFP_AND_SELECTIVE_RE) {
7738
            /* Work out which mask should be used */
7739
122k
            if (compression==BFP_AND_SELECTIVE_RE || compression==MOD_COMPR_AND_SELECTIVE_RE) {
7740
                /* Selective RE cases, use value from compModParam */
7741
1.56k
                sresmask_to_use = (uint16_t)sresmask;
7742
1.56k
            }
7743
120k
            else {
7744
                /* With masks (in section).  Choose between sresmask1 and sresmask2 */
7745
120k
                if (rb==1 || (i%2)==0) {
7746
                    /* Even values */
7747
117k
                    sresmask_to_use = (uint16_t)sresmask1;
7748
117k
                }
7749
3.31k
                else {
7750
                    /* Odd values */
7751
3.31k
                    sresmask_to_use = (uint16_t)sresmask2;
7752
3.31k
                }
7753
120k
            }
7754
7755
            /* Count REs present using sresmask */
7756
122k
            res_per_prb = 0;
7757
            /* Use sresmask to pick out which REs are present */
7758
1.58M
            for (unsigned n=0; n<12; n++) {
7759
1.46M
                if (sresmask_to_use & (1<<n)) {
7760
10.4k
                    res_per_prb++;
7761
10.4k
                }
7762
1.46M
            }
7763
122k
        }
7764
7765
        /* N.B. bytes for samples need to be padded out to next byte
7766
           (certainly where there aren't 12 REs in PRB..) */
7767
123k
        unsigned nBytesForSamples = ((*sample_bit_width_ptr) * res_per_prb * 2 + 7) / 8;
7768
123k
        *nBytesPerPrbPtr = nBytesForSamples + udcompparam_len;
7769
7770
123k
        proto_tree_add_item(rb_tree, hf_oran_iq_user_data, tvb, offset, nBytesForSamples, ENC_NA);
7771
7772
123k
        if (section_details) {
7773
0
            if ((startPrbu + i*(1+rb)) < 273) {
7774
0
                proto_item *beamid_ti = proto_tree_add_uint(rb_tree, hf_oran_beamId, tvb, 0, 0,
7775
0
                                                            section_details->beamIds[startPrbu + i*(1+rb)]);
7776
0
                proto_item_set_generated(beamid_ti);
7777
0
            }
7778
0
        }
7779
7780
7781
123k
        tap_info->non_zero_re_in_current_prb = false;
7782
7783
        /* Optionally trying to show I/Q RE values */
7784
123k
        if (pref_showIQSampleValues) {
7785
            /* Individual values */
7786
123k
            unsigned samples_offset = offset*8;
7787
123k
            unsigned samples_start = offset;
7788
123k
            unsigned samples = 0;
7789
7790
123k
            if (compression >= BFP_AND_SELECTIVE_RE) {
7791
                /* Use sresmask to pick out which REs are present */
7792
1.58M
                for (unsigned n=1; n<=12; n++) {
7793
1.46M
                    if (sresmask_to_use & (1<<(n-1))) {
7794
10.1k
                        samples_offset = dissect_oran_u_re(tvb, rb_tree,
7795
10.1k
                                                           n, samples_offset, tap_info, *sample_bit_width_ptr, compression, exponent, mod_compr_config, n);
7796
10.1k
                        samples++;
7797
10.1k
                    }
7798
1.46M
                }
7799
122k
            }
7800
1.22k
            else {
7801
                /* All 12 REs are present */
7802
15.9k
                for (unsigned n=1; n<=12; n++) {
7803
14.6k
                    samples_offset = dissect_oran_u_re(tvb, rb_tree,
7804
14.6k
                                                       n, samples_offset, tap_info, *sample_bit_width_ptr, compression, exponent, mod_compr_config, n);
7805
14.6k
                    samples++;
7806
14.6k
                }
7807
1.22k
            }
7808
123k
            proto_item_append_text(prbHeading, " (%u REs)", samples);
7809
123k
            if (section_details) {
7810
0
                if ((startPrbu + i*(1+rb)) < 273) {
7811
0
                    proto_item_append_text(prbHeading, " [BeamId:%u]", section_details->beamIds[startPrbu + i*(1+rb)]);
7812
0
                }
7813
0
            }
7814
7815
            /* Was this PRB all zeros? */
7816
123k
            if (!tap_info->non_zero_re_in_current_prb) {
7817
120k
                tap_info->num_prbs_zero++;
7818
                /* Add a filter to make zero-valued PRBs more findable */
7819
120k
                proto_item *zero_ti = proto_tree_add_item(rb_tree, hf_oran_zero_prb, tvb,
7820
120k
                                                          samples_start, nBytesForSamples, ENC_NA);
7821
120k
                proto_item_set_hidden(zero_ti);
7822
120k
                proto_item_append_text(prbHeading, " (all zeros)");
7823
120k
            }
7824
3.03k
            else {
7825
3.03k
                proto_item *nonzero_ti = proto_tree_add_item(rb_tree, hf_oran_nonzero_prb, tvb, samples_start, nBytesForSamples, ENC_NA);
7826
3.03k
                proto_item_set_hidden(nonzero_ti);
7827
3.03k
            }
7828
123k
        }
7829
7830
123k
        tap_info->num_prbs++;
7831
7832
7833
        /* Advance past samples */
7834
123k
        offset += nBytesForSamples;
7835
7836
        /* Set end of prb subtree */
7837
123k
        proto_item_set_end(prbHeading, tvb, offset);
7838
123k
    }
7839
7840
    /* Set extent of section */
7841
1.08k
    proto_item_set_len(sectionHeading, offset-section_start_offset);
7842
1.08k
    if (ud_comp_len_ti != NULL && ((offset-section_start_offset != ud_comp_len))) {
7843
0
        expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
7844
0
                               "udCompLen indicates %u bytes in section, but dissected %u instead",
7845
0
                               ud_comp_len, offset-section_start_offset);
7846
0
    }
7847
1.08k
    return offset;
7848
1.08k
}
7849
7850
/* User plane dissector (section 8) */
7851
static int
7852
dissect_oran_u(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
7853
               oran_tap_info *tap_info, void *data _U_)
7854
202
{
7855
    /* Hidden filter for plane */
7856
202
    proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_uplane, tvb, 0, 0, ENC_NA);
7857
202
    PROTO_ITEM_SET_HIDDEN(plane_ti);
7858
7859
    /* Set up structures needed to add the protocol subtree and manage it */
7860
202
    unsigned offset = 0;
7861
7862
202
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-U");
7863
202
    col_set_str(pinfo->cinfo, COL_INFO, "U-Plane");
7864
7865
202
    tap_info->userplane = true;
7866
7867
    /* Create display subtree for the protocol */
7868
202
    proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
7869
202
    proto_item_append_text(protocol_item, "-U");
7870
202
    proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
7871
7872
    /* Transport header */
7873
    /* Real-time control data / IQ data transfer message series identifier */
7874
202
    uint16_t eAxC;
7875
202
    addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_pcid, &eAxC, tap_info);
7876
202
    tap_info->eaxc = eAxC;
7877
7878
    /* Update/report status of conversation */
7879
202
    flow_state_t* state = lookup_flow(pinfo, eAxC, ORAN_U_PLANE, false);
7880
7881
202
    flow_result_t *result = NULL;
7882
7883
    /* Message identifier */
7884
202
    proto_item *seqIdItem;
7885
202
    uint32_t seqId, subSeqId, e;
7886
202
    offset = addSeqid(tvb, oran_tree, offset, ORAN_U_PLANE, &seqId, &seqIdItem, pinfo, &subSeqId, &e);
7887
7888
202
    uint32_t frameId  = 0, subframeId = 0, slotId = 0, symbolId = 0, direction;
7889
7890
    /* Add buffer to the reassembly ahead of cycling through the options */
7891
202
    if (do_radio_transport_layer_reassembly && (e !=1 || subSeqId!= 0)) {
7892
        /* Set fragmented flag. */
7893
33
        bool save_fragmented = pinfo->fragmented;
7894
33
        pinfo->fragmented = true;
7895
33
        fragment_head *fh;
7896
33
        unsigned frag_data_len = tvb_reported_length_remaining(tvb, offset);
7897
7898
        /* Add this fragment into reassembly table */
7899
        /* In the absence of information from the header [might not be present], use the MAC addresses. */
7900
33
        int dir = cmp_address(&pinfo->src, &pinfo->dst)>0;
7901
33
        uint32_t reassembly_id = make_reassembly_id(seqId, eAxC, dir);
7902
33
        fh = fragment_add_seq(&oran_reassembly_table, tvb, offset, pinfo,
7903
33
                              reassembly_id,                                 /* id */
7904
33
                              GUINT_TO_POINTER(reassembly_id),               /* data */
7905
33
                              subSeqId,                                      /* frag_number */
7906
33
                              frag_data_len,                                 /* frag_data_len */
7907
33
                              !e,                                             /* more_frags */
7908
33
                              0);
7909
7910
33
        bool update_col_info = true;
7911
7912
        /* See if this completes an SDU */
7913
33
        tvbuff_t *original_tvb = tvb;
7914
33
        tvbuff_t *next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled O-RAN FH CUS Payload",
7915
33
                                                      fh, &oran_frag_items,
7916
33
                                                      &update_col_info, oran_tree);
7917
33
        if (next_tvb) {
7918
            /* Have reassembled data */
7919
0
            proto_tree_add_item(oran_tree, hf_oran_payload, next_tvb, 0, -1, ENC_NA);
7920
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "  Reassembled Data (%u bytes)", tvb_reported_length(next_tvb));
7921
0
        }
7922
        /* Will continue with either reassembled tvb or NULL */
7923
33
        tvb = next_tvb;
7924
7925
        /* Restore fragmented flag */
7926
33
        pinfo->fragmented = save_fragmented;
7927
7928
        /* Don't dissect any more if not complete yet.. */
7929
33
        if (tvb == NULL) {
7930
            /* For subseq=0 it's possible to do a partial decode to display the timing header
7931
               and first section header, but not much more */
7932
33
            if ( subSeqId == 0 ) {
7933
18
                if ( tvb_reported_length_remaining(original_tvb, offset) >= 4 ) {
7934
16
                    proto_item * timingHeader = proto_tree_add_string_format(oran_tree, hf_oran_timing_header,
7935
16
                                                                             original_tvb, offset, 4, "", "Timing Header (");
7936
16
                    offset = dissect_oran_u_timing_header(original_tvb, pinfo, offset, timingHeader, tap_info, &frameId, &subframeId, &slotId, &symbolId, &direction);
7937
7938
16
                    if ( tvb_reported_length_remaining(original_tvb, offset) >= 4 ) {
7939
14
                        uint32_t sectionId, rb, startPrbu, numPrbu;
7940
14
                        section_details_t *section_details = NULL;
7941
14
                        proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_u_section,
7942
14
                                                                                  tvb, offset, 0, "", "Section");
7943
14
                        proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_u_section);
7944
7945
14
                        offset = dissect_oran_u_section_header(original_tvb, pinfo, offset, section_tree, tap_info, result, NULL,
7946
14
                                                               frameId, subframeId, slotId, symbolId, direction, &sectionId, &rb,
7947
14
                                                               &startPrbu, &numPrbu, &section_details);
7948
14
                    }
7949
16
                }
7950
18
            }
7951
33
            return tvb_captured_length(original_tvb);
7952
33
        }
7953
0
        offset = 0;  /* This sorts out the reading of the timing header and the first section header */
7954
0
    }
7955
7956
169
    proto_item * timingHeader = proto_tree_add_string_format(oran_tree, hf_oran_timing_header,
7957
169
                                                                          tvb, offset, 4, "", "Timing Header (");
7958
169
    offset = dissect_oran_u_timing_header(tvb, pinfo, offset, timingHeader, tap_info, &frameId, &subframeId, &slotId, &symbolId, &direction);
7959
7960
169
    unsigned sample_bit_width;
7961
169
    unsigned compression;
7962
169
    int includeUdCompHeader;
7963
7964
    /* Also lookup C-PLANE state (sent in opposite direction for UL) so may check current compression settings */
7965
169
    flow_state_t* cplane_state = lookup_flow(pinfo, eAxC, ORAN_C_PLANE, direction == 0);
7966
7967
169
    if (!PINFO_FD_VISITED(pinfo)) {
7968
        /* Create state/conversation if doesn't exist yet */
7969
165
        if (!state)  {
7970
            /* Allocate new state */
7971
33
            state = wmem_new0(wmem_file_scope(), flow_state_t);
7972
33
            state->ack_nack_requests = wmem_tree_new(wmem_file_scope());
7973
33
            state->expected_sections[0] = wmem_tree_new(wmem_file_scope());
7974
33
            state->expected_sections[1] = wmem_tree_new(wmem_file_scope());
7975
33
            store_flow(pinfo, eAxC, ORAN_U_PLANE, false, state);
7976
33
        }
7977
7978
165
        result = wmem_new0(wmem_file_scope(), flow_result_t);
7979
165
        result->expected_sections = wmem_tree_new(wmem_file_scope());
7980
165
        result->u_plane_frames = wmem_list_new(wmem_file_scope());
7981
7982
165
        wmem_tree_insert32(flow_results_table, pinfo->num, result);
7983
7984
        /* Check sequence analysis status (but not if later part of radio layer fragmentation) */
7985
165
        if (state->last_frame_seen[direction] && (subSeqId==0) && (seqId != state->next_expected_sequence_number[direction])) {
7986
            /* Store this result */
7987
126
            result->unexpected_seq_number = true;
7988
126
            result->expected_sequence_number = state->next_expected_sequence_number[direction];
7989
126
            result->previous_frame = state->last_frame[direction];
7990
126
        }
7991
        /* Update sequence analysis state */
7992
165
        state->last_frame[direction] = pinfo->num;
7993
165
        state->last_frame_seen[direction] = true;
7994
165
        state->next_expected_sequence_number[direction] = (seqId+1) % 256;
7995
165
    }
7996
7997
    /* Show any issues associated with this frame number */
7998
169
    result = wmem_tree_lookup32(flow_results_table, pinfo->num);
7999
169
    if (result) {
8000
165
        if (result->unexpected_seq_number) {
8001
126
            expert_add_info_format(pinfo, seqIdItem,
8002
126
                                   (direction == DIR_UPLINK) ?
8003
23
                                        &ei_oran_uplane_unexpected_sequence_number_ul :
8004
126
                                        &ei_oran_uplane_unexpected_sequence_number_dl,
8005
126
                                   "Sequence number %u expected, but got %u",
8006
126
                                   result->expected_sequence_number, seqId);
8007
126
            tap_info->missing_sns = (256 + seqId - result->expected_sequence_number) % 256;
8008
            /* TODO: could add previous/next frame (in seqId tree?) ? */
8009
126
        }
8010
165
    }
8011
8012
    /* Checking UL timing within current slot.  Disabled if limit set to 0. */
8013
    /* N.B., timing is relative to first seen frame,
8014
       not some notion of the beginning of the slot from sync, offset by some timing.. */
8015
169
    if (direction == DIR_UPLINK && us_allowed_for_ul_in_symbol > 0) {
8016
0
        uint32_t timing_key = get_timing_key(frameId, subframeId, slotId, symbolId);
8017
0
        if (!PINFO_FD_VISITED(pinfo)) {
8018
            /* Set state on first pass */
8019
0
            ul_timing_for_slot* timing = (ul_timing_for_slot*)wmem_tree_lookup32(ul_symbol_timing, timing_key);
8020
0
            if (!timing) {
8021
                /* Allocate new state */
8022
0
                timing = wmem_new0(wmem_file_scope(), ul_timing_for_slot);
8023
0
                timing->first_frame = pinfo->num;
8024
0
                timing->first_frame_time = pinfo->abs_ts;
8025
0
                timing->frames_seen_in_symbol = 1;
8026
0
                timing->last_frame_in_symbol = pinfo->num;
8027
0
                wmem_tree_insert32(ul_symbol_timing, timing_key, timing);
8028
0
            }
8029
0
            else {
8030
                /* Update existing state */
8031
0
                timing->frames_seen_in_symbol++;
8032
0
                timing->last_frame_in_symbol = pinfo->num;
8033
0
            }
8034
0
        }
8035
0
        else {
8036
            /* Subsequent passes - look up result */
8037
0
            ul_timing_for_slot* timing = (ul_timing_for_slot*)wmem_tree_lookup32(ul_symbol_timing, timing_key);
8038
0
            if (timing) {  /* Really shouldn't fail! */
8039
0
                if (timing->frames_seen_in_symbol > 1) {
8040
                    /* Work out gap between frames (in microseconds) back to frame carrying first seen symbol */
8041
0
                    int seconds_between_packets = (int)
8042
0
                          (pinfo->abs_ts.secs - timing->first_frame_time.secs);
8043
0
                    int nseconds_between_packets =
8044
0
                          pinfo->abs_ts.nsecs - timing->first_frame_time.nsecs;
8045
8046
                    /* Round to nearest microsecond. */
8047
0
                    uint32_t total_gap = (seconds_between_packets*1000000) +
8048
0
                                         ((nseconds_between_packets+500) / 1000);
8049
8050
                    /* Show how long it has been */
8051
0
                    proto_item *ti = NULL;
8052
0
                    if (pinfo->num != timing->first_frame) {
8053
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_time, tvb, 0, 0, total_gap);
8054
0
                        proto_item_set_generated(ti);
8055
0
                    }
8056
8057
0
                    if (total_gap > us_allowed_for_ul_in_symbol) {
8058
0
                        expert_add_info_format(pinfo, ti, &ei_oran_ul_uplane_symbol_too_long,
8059
0
                                               "UL U-Plane Tx took longer (%u us) than limit set in preferences (%u us)",
8060
0
                                               total_gap, us_allowed_for_ul_in_symbol);
8061
0
                        proto_item_append_text(timingHeader, "  (%uus since first frame seen for symbol)", total_gap);
8062
0
                    }
8063
8064
                    /* Show how many frames were received */
8065
0
                    ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_frames, tvb, 0, 0, timing->frames_seen_in_symbol);
8066
0
                    proto_item_set_generated(ti);
8067
8068
                    /* Link to first frame for this symbol */
8069
0
                    if (pinfo->num != timing->first_frame) {
8070
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_first_frame, tvb, 0, 0, timing->first_frame);
8071
0
                        proto_item_set_generated(ti);
8072
0
                    }
8073
8074
                    /* And also last frame */
8075
0
                    if (pinfo->num != timing->last_frame_in_symbol) {
8076
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_last_frame, tvb, 0, 0, timing->last_frame_in_symbol);
8077
0
                        proto_item_set_generated(ti);
8078
0
                    }
8079
8080
0
                    tap_info->ul_delay_in_us = total_gap;
8081
0
                }
8082
0
            }
8083
0
        }
8084
0
    }
8085
8086
8087
    /* Look up preferences for samples */
8088
169
    if (direction == DIR_UPLINK) {
8089
41
        sample_bit_width = pref_sample_bit_width_uplink;
8090
41
        compression = pref_iqCompressionUplink;
8091
41
        includeUdCompHeader = pref_includeUdCompHeaderUplink;
8092
128
    } else {
8093
128
        sample_bit_width = pref_sample_bit_width_downlink;
8094
128
        compression = pref_iqCompressionDownlink;
8095
128
        includeUdCompHeader = pref_includeUdCompHeaderDownlink;
8096
128
    }
8097
8098
    /* If uplink, load any udCompHdr settings written by C-Plane */
8099
169
    bool ud_cmp_hdr_cplane = false;
8100
169
    if (cplane_state && direction == 0) {
8101
        /* Initialise settings from udpCompHdr from C-Plane */
8102
7
        if (cplane_state->ul_ud_comp_hdr_set && !pref_override_ul_compression) {
8103
5
            sample_bit_width = cplane_state->ul_ud_comp_hdr_bit_width;
8104
5
            compression =      cplane_state->ul_ud_comp_hdr_compression;
8105
5
            ud_cmp_hdr_cplane = true;
8106
5
        }
8107
7
    }
8108
8109
    /* Need a valid value (e.g. 9, 14).  0 definitely won't work, as won't progress around loop! */
8110
    /* N.B. may yet be overwritten by udCompHdr settings in sections below! */
8111
169
    if (sample_bit_width == 0) {
8112
0
        expert_add_info_format(pinfo, protocol_item, &ei_oran_invalid_sample_bit_width,
8113
0
                               "%cL Sample bit width from %s (%u) not valid, so can't decode sections",
8114
0
                               (direction == DIR_UPLINK) ? 'U' : 'D',
8115
0
                               !ud_cmp_hdr_cplane ? "preference" : "C-Plane",
8116
0
                               sample_bit_width);
8117
0
        return offset;
8118
0
    }
8119
8120
169
    unsigned bytesLeft;
8121
169
    unsigned number_of_sections = 0;
8122
169
    unsigned nBytesPerPrb =0;
8123
8124
169
    if (link_planes_together && !PINFO_FD_VISITED(pinfo) && cplane_state && result) {
8125
        /* Take a deep-copy of this state on first pass */
8126
9
        wmem_tree_foreach(cplane_state->expected_sections[direction], copy_section_entry, result->expected_sections);
8127
9
    }
8128
8129
    /* Add each section (not from count, just keep parsing until payload used) */
8130
1.08k
    do {
8131
1.08k
        offset = dissect_oran_u_section(tvb, pinfo, offset, oran_tree, protocol_item, tap_info, state, result, cplane_state,
8132
1.08k
                                        frameId, subframeId, slotId, symbolId, direction, includeUdCompHeader,
8133
1.08k
                                        &sample_bit_width, compression, ud_cmp_hdr_cplane, &nBytesPerPrb);
8134
1.08k
        bytesLeft = tvb_captured_length(tvb) - offset;
8135
1.08k
        number_of_sections++;
8136
1.08k
    } while (bytesLeft >= (4 + nBytesPerPrb));     /* FIXME: bad heuristic */
8137
8138
    /* Show number of sections found */
8139
169
    proto_item *ti = proto_tree_add_uint(oran_tree, hf_oran_numberOfSections, tvb, 0, 0, number_of_sections);
8140
169
    proto_item_set_generated(ti);
8141
8142
    /* Expert error if we are short of tvb by > 3 bytes */
8143
169
    if (tvb_reported_length_remaining(tvb, offset) > 3) {
8144
9
        expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
8145
9
                               "%u bytes remain at end of frame - should be 0-3",
8146
9
                               tvb_reported_length_remaining(tvb, offset));
8147
9
    }
8148
8149
169
    return tvb_captured_length(tvb);
8150
169
}
8151
8152
8153
/**********************************************************************/
8154
/* Main dissection function.                                          */
8155
/* N.B. ecpri message type passed in as 'data' arg by eCPRI dissector */
8156
static int
8157
dissect_oran(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
8158
2.21k
{
8159
2.21k
    uint32_t ecpri_message_type = *(uint32_t *)data;
8160
2.21k
    unsigned offset = 0;
8161
8162
    /* Allocate and zero tap struct */
8163
2.21k
    oran_tap_info *tap_info = wmem_new0(wmem_file_scope(), oran_tap_info);
8164
2.21k
    tap_info->pdu_size = pinfo->fd->pkt_len;
8165
2.21k
    tap_info->ul_delay_configured_max = us_allowed_for_ul_in_symbol;
8166
8167
2.21k
    switch (ecpri_message_type) {
8168
202
        case ECPRI_MT_IQ_DATA:
8169
202
            offset = dissect_oran_u(tvb, pinfo, tree, tap_info, data);
8170
202
            break;
8171
1.73k
        case ECPRI_MT_RT_CTRL_DATA:
8172
1.73k
            offset = dissect_oran_c(tvb, pinfo, tree, tap_info, data);
8173
1.73k
            break;
8174
274
        default:
8175
            /* Not dissecting other types - assume these are handled by eCPRI dissector */
8176
274
            return 0;
8177
2.21k
    }
8178
8179
94
    tap_queue_packet(oran_tap, pinfo, tap_info);
8180
8181
94
    return offset;
8182
2.21k
}
8183
8184
static void oran_init_protocol(void)
8185
16
{
8186
16
    udcomplen_heuristic_result_set = false;
8187
16
    udcomplen_heuristic_result = false;
8188
16
}
8189
8190
8191
/* Register the protocol with Wireshark. */
8192
void
8193
proto_register_oran(void)
8194
16
{
8195
16
    static hf_register_info hf[] = {
8196
8197
        /* Section 5.1.3.2.7 */
8198
16
        { &hf_oran_du_port_id,
8199
16
          { "DU Port ID", "oran_fh_cus.du_port_id",
8200
16
            FT_UINT16, BASE_DEC,
8201
16
            NULL, 0x0,
8202
16
            "Processing unit at O-RU - width set in dissector preference", HFILL }
8203
16
        },
8204
8205
        /* Section 5.1.3.2.7 */
8206
16
        { &hf_oran_bandsector_id,
8207
16
          { "BandSector ID", "oran_fh_cus.bandsector_id",
8208
16
            FT_UINT16, BASE_DEC,
8209
16
            NULL, 0x0,
8210
16
            "Aggregated cell identified - width set in dissector preference", HFILL }
8211
16
        },
8212
8213
        /* Section 5.1.3.2.7 */
8214
16
        { &hf_oran_cc_id,
8215
16
          { "CC ID", "oran_fh_cus.cc_id",
8216
16
            FT_UINT16, BASE_DEC,
8217
16
            NULL, 0x0,
8218
16
            "Component Carrier - width set in dissector preference", HFILL }
8219
16
        },
8220
8221
        /* Section 5.1.3.2.7 */
8222
16
        { &hf_oran_ru_port_id,
8223
16
          { "RU Port ID", "oran_fh_cus.ru_port_id",
8224
16
            FT_UINT16, BASE_DEC,
8225
16
            NULL, 0x0,
8226
16
            "Logical flow - width set in dissector preference", HFILL }
8227
16
        },
8228
8229
        /* Section 5.1.3.2.8 */
8230
16
        { &hf_oran_sequence_id,
8231
16
          { "Sequence ID", "oran_fh_cus.sequence_id",
8232
16
            FT_UINT8, BASE_DEC,
8233
16
            NULL, 0x0,
8234
16
            "The Sequence ID wraps around individually per eAxC", HFILL }
8235
16
        },
8236
8237
        /* Section 5.1.3.2.8 */
8238
16
        { &hf_oran_e_bit,
8239
16
          { "E Bit", "oran_fh_cus.e_bit",
8240
16
            FT_UINT8, BASE_DEC,
8241
16
            VALS(e_bit), 0x80,
8242
16
            "Indicate the last message of a subsequence (U-Plane only)", HFILL }
8243
16
        },
8244
8245
        /* Section 5.1.3.2.8 */
8246
16
        { &hf_oran_subsequence_id,
8247
16
          { "Subsequence ID", "oran_fh_cus.subsequence_id",
8248
16
            FT_UINT8, BASE_DEC,
8249
16
            NULL, 0x7f,
8250
16
            "The subsequence ID (for eCPRI layer fragmentation)", HFILL }
8251
16
        },
8252
8253
16
        { &hf_oran_previous_frame,
8254
16
          { "Previous frame in stream", "oran_fh_cus.previous-frame",
8255
16
            FT_FRAMENUM, BASE_NONE,
8256
16
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
8257
16
            "Previous frame in sequence", HFILL }
8258
16
        },
8259
8260
        /* Section 7.5.2.1 */
8261
16
        { &hf_oran_data_direction,
8262
16
          { "Data Direction", "oran_fh_cus.data_direction",
8263
16
            FT_UINT8, BASE_DEC,
8264
16
            VALS(data_direction_vals), 0x80,
8265
16
            "gNB data direction", HFILL }
8266
16
        },
8267
8268
        /* Section 7.5.2.2 */
8269
16
        { &hf_oran_payload_version,
8270
16
          { "Payload Version", "oran_fh_cus.payloadVersion",
8271
16
            FT_UINT8, BASE_DEC,
8272
16
            NULL, 0x70,
8273
16
            "Payload protocol version the following IEs", HFILL}
8274
16
        },
8275
8276
        /* Section 7.5.2.3 */
8277
16
        { &hf_oran_filter_index,
8278
16
          { "Filter Index", "oran_fh_cus.filterIndex",
8279
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8280
16
            RVALS(filter_indices), 0x0f,
8281
16
            "used between IQ data and air interface, both in DL and UL", HFILL}
8282
16
        },
8283
8284
        /* Section 7.5.2.4 */
8285
16
        { &hf_oran_frame_id,
8286
16
          { "Frame ID", "oran_fh_cus.frameId",
8287
16
            FT_UINT8, BASE_DEC,
8288
16
            NULL, 0x0,
8289
16
            "A counter for 10 ms frames (wrapping period 2.56 seconds)", HFILL}
8290
16
        },
8291
8292
        /* Section 7.5.2.5 */
8293
16
        { &hf_oran_subframe_id,
8294
16
          { "Subframe ID", "oran_fh_cus.subframe_id",
8295
16
            FT_UINT8, BASE_DEC,
8296
16
            NULL, 0xf0,
8297
16
            "A counter for 1 ms sub-frames within 10ms frame", HFILL}
8298
16
        },
8299
8300
        /* Section 7.5.2.6 */
8301
16
        { &hf_oran_slot_id,
8302
16
          { "Slot ID", "oran_fh_cus.slotId",
8303
16
            FT_UINT16, BASE_DEC,
8304
16
            NULL, 0x0fc0,
8305
16
            "Slot number within a 1ms sub-frame", HFILL}
8306
16
        },
8307
8308
        /* Generated for convenience */
8309
16
        { &hf_oran_slot_within_frame,
8310
16
          { "Slot within frame", "oran_fh_cus.slot-within-frame",
8311
16
            FT_UINT16, BASE_DEC,
8312
16
            NULL, 0x0,
8313
16
            "Slot within frame, to match DCT logs", HFILL}
8314
16
        },
8315
8316
        /* Section 7.5.2.7 */
8317
16
        { &hf_oran_start_symbol_id,
8318
16
          { "Start Symbol ID", "oran_fh_cus.startSymbolId",
8319
16
            FT_UINT8, BASE_DEC,
8320
16
            NULL, 0x3f,
8321
16
            "The first symbol number within slot affected", HFILL}
8322
16
        },
8323
8324
        /* Section 7.5.2.8 */
8325
16
        { &hf_oran_numberOfSections,
8326
16
          { "Number of Sections", "oran_fh_cus.numberOfSections",
8327
16
            FT_UINT8, BASE_DEC,
8328
16
            NULL, 0x0,
8329
16
            "The number of section IDs included in this message", HFILL}
8330
16
        },
8331
8332
        /* Section 7.5.2.9 */
8333
16
        { &hf_oran_sectionType,
8334
16
          { "Section Type", "oran_fh_cus.sectionType",
8335
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8336
16
            RVALS(section_types), 0x0,
8337
16
            "Determines the characteristics of U-plane data", HFILL}
8338
16
        },
8339
8340
        /* Section 7.5.2.10 */
8341
16
        { &hf_oran_udCompHdr,
8342
16
          { "udCompHdr", "oran_fh_cus.udCompHdr",
8343
16
            FT_STRING, BASE_NONE,
8344
16
            NULL, 0x0,
8345
16
            NULL, HFILL}
8346
16
        },
8347
8348
        /* Section 7.5.2.11 */
8349
16
        { &hf_oran_numberOfUEs,
8350
16
          { "Number Of UEs", "oran_fh_cus.numberOfUEs",
8351
16
            FT_UINT8, BASE_DEC,
8352
16
            NULL, 0x0,
8353
16
            "Indicates number of UEs for which channel info is provided", HFILL}
8354
16
        },
8355
8356
        /* Section 7.5.2.12 */
8357
16
        { &hf_oran_timeOffset,
8358
16
          { "Time Offset", "oran_fh_cus.timeOffset",
8359
16
            FT_UINT16, BASE_DEC,
8360
16
            NULL, 0x0,
8361
16
            "from start of the slot to start of CP in samples", HFILL}
8362
16
        },
8363
8364
        /* Section 7.5.2.13 */
8365
16
        { &hf_oran_frameStructure_fft,
8366
16
          { "FFT Size", "oran_fh_cus.frameStructure.fft",
8367
16
            FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
8368
16
            RVALS(frame_structure_fft), 0xf0,
8369
16
            "The FFT/iFFT size being used for all IQ data processing related to this message", HFILL }
8370
16
        },
8371
8372
        /* Section 7.5.2.13 */
8373
16
        { &hf_oran_frameStructure_subcarrier_spacing,
8374
16
          { "Subcarrier Spacing", "oran_fh_cus.frameStructure.spacing",
8375
16
            FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
8376
16
            RVALS(subcarrier_spacings), 0x0f,
8377
16
            "The sub carrier spacing as well as the number of slots per 1ms sub-frame",
8378
16
            HFILL }
8379
16
        },
8380
8381
        /* Section 7.5.2.14 */
8382
16
        { &hf_oran_cpLength,
8383
16
          { "cpLength", "oran_fh_cus.cpLength",
8384
16
            FT_UINT16, BASE_DEC,
8385
16
            NULL, 0x0,
8386
16
            "cyclic prefix length", HFILL}
8387
16
        },
8388
8389
16
        { &hf_oran_timing_header,
8390
16
          { "Timing Header", "oran_fh_cus.timingHeader",
8391
16
            FT_STRING, BASE_NONE,
8392
16
            NULL, 0x0,
8393
16
            NULL, HFILL}
8394
16
        },
8395
8396
        /* Section 7.5.3.1 */
8397
16
        { &hf_oran_section_id,
8398
16
          { "sectionId", "oran_fh_cus.sectionId",
8399
16
            FT_UINT16, BASE_DEC,
8400
16
            NULL, 0xfff0,
8401
16
            "section identifier of data", HFILL}
8402
16
        },
8403
8404
        /* Section 7.5.3.2 */
8405
16
        { &hf_oran_rb,
8406
16
          { "rb", "oran_fh_cus.rb",
8407
16
            FT_UINT8, BASE_DEC,
8408
16
            VALS(rb_vals), 0x08,
8409
16
            "resource block indicator", HFILL}
8410
16
        },
8411
8412
        /* Section 7.5.5.3 */
8413
16
        { &hf_oran_symInc,
8414
16
          { "symInc", "oran_fh_cus.symInc",
8415
16
            FT_UINT8, BASE_DEC,
8416
16
            VALS(sym_inc_vals), 0x04,
8417
16
            "Symbol Number Increment Command", HFILL}
8418
16
        },
8419
8420
        /* Section 7.5.3.4 */
8421
16
        { &hf_oran_startPrbc,
8422
16
          { "startPrbc", "oran_fh_cus.startPrbc",
8423
16
            FT_UINT16, BASE_DEC,
8424
16
            NULL, 0x03ff,
8425
16
            "Starting PRB of Control Plane Section", HFILL}
8426
16
        },
8427
8428
        /* Section 7.5.3.5 */
8429
16
        { &hf_oran_reMask_re1,
8430
16
          { "RE 1", "oran_fh_cus.reMask-RE1",
8431
16
            FT_BOOLEAN, 16,
8432
16
            TFS(&tfs_applicable_not_applicable), 0x8000,
8433
16
            NULL, HFILL}
8434
16
        },
8435
16
        { &hf_oran_reMask_re2,
8436
16
          { "RE 2", "oran_fh_cus.reMask-RE2",
8437
16
            FT_BOOLEAN, 16,
8438
16
            TFS(&tfs_applicable_not_applicable), 0x4000,
8439
16
            NULL, HFILL}
8440
16
        },
8441
16
        { &hf_oran_reMask_re3,
8442
16
          { "RE 3", "oran_fh_cus.reMask-RE3",
8443
16
            FT_BOOLEAN, 16,
8444
16
            TFS(&tfs_applicable_not_applicable), 0x2000,
8445
16
            NULL, HFILL}
8446
16
        },
8447
16
        { &hf_oran_reMask_re4,
8448
16
          { "RE 4", "oran_fh_cus.reMask-RE4",
8449
16
            FT_BOOLEAN, 16,
8450
16
            TFS(&tfs_applicable_not_applicable), 0x1000,
8451
16
            NULL, HFILL}
8452
16
        },
8453
16
        { &hf_oran_reMask_re5,
8454
16
          { "RE 5", "oran_fh_cus.reMask-RE5",
8455
16
            FT_BOOLEAN, 16,
8456
16
            TFS(&tfs_applicable_not_applicable), 0x0800,
8457
16
            NULL, HFILL}
8458
16
        },
8459
16
        { &hf_oran_reMask_re6,
8460
16
          { "RE 6", "oran_fh_cus.reMask-RE6",
8461
16
            FT_BOOLEAN, 16,
8462
16
            TFS(&tfs_applicable_not_applicable), 0x0400,
8463
16
            NULL, HFILL}
8464
16
        },
8465
16
        { &hf_oran_reMask_re7,
8466
16
          { "RE 7", "oran_fh_cus.reMask-RE7",
8467
16
            FT_BOOLEAN, 16,
8468
16
            TFS(&tfs_applicable_not_applicable), 0x0200,
8469
16
            NULL, HFILL}
8470
16
        },
8471
16
        { &hf_oran_reMask_re8,
8472
16
          { "RE 8", "oran_fh_cus.reMask-RE8",
8473
16
            FT_BOOLEAN, 16,
8474
16
            TFS(&tfs_applicable_not_applicable), 0x0100,
8475
16
            NULL, HFILL}
8476
16
        },
8477
16
        { &hf_oran_reMask_re9,
8478
16
          { "RE 9", "oran_fh_cus.reMask-RE9",
8479
16
            FT_BOOLEAN, 16,
8480
16
            TFS(&tfs_applicable_not_applicable), 0x0080,
8481
16
            NULL, HFILL}
8482
16
        },
8483
16
        { &hf_oran_reMask_re10,
8484
16
          { "RE 10", "oran_fh_cus.reMask-RE10",
8485
16
            FT_BOOLEAN, 16,
8486
16
            TFS(&tfs_applicable_not_applicable), 0x0040,
8487
16
            NULL, HFILL}
8488
16
        },
8489
16
        { &hf_oran_reMask_re11,
8490
16
          { "RE 11", "oran_fh_cus.reMask-RE11",
8491
16
            FT_BOOLEAN, 16,
8492
16
            TFS(&tfs_applicable_not_applicable), 0x0020,
8493
16
            NULL, HFILL}
8494
16
        },
8495
16
        { &hf_oran_reMask_re12,
8496
16
          { "RE 12", "oran_fh_cus.reMask-RE12",
8497
16
            FT_BOOLEAN, 16,
8498
16
            TFS(&tfs_applicable_not_applicable), 0x0010,
8499
16
            NULL, HFILL}
8500
16
        },
8501
16
        { &hf_oran_reMask,
8502
16
          { "RE Mask", "oran_fh_cus.reMask",
8503
16
            FT_UINT16, BASE_HEX,
8504
16
            NULL, 0xfff0,
8505
16
            "The Resource Element (RE) mask within a PRB", HFILL}
8506
16
        },
8507
8508
        /* Section 7.5.3.6 */
8509
16
        { &hf_oran_numPrbc,
8510
16
          { "numPrbc", "oran_fh_cus.numPrbc",
8511
16
            FT_UINT8, BASE_DEC,
8512
16
            NULL, 0x0,
8513
16
            "Number of contiguous PRBs per data section description", HFILL}
8514
16
        },
8515
        /* Section 7.5.3.7 */
8516
16
        { &hf_oran_numSymbol,
8517
16
          { "Number of Symbols", "oran_fh_cus.numSymbol",
8518
16
            FT_UINT8, BASE_DEC,
8519
16
            NULL, 0x0f,
8520
16
            "Defines number of symbols to which the section control is applicable", HFILL}
8521
16
        },
8522
        /* Section 7.5.3.8 */
8523
16
        { &hf_oran_ef,
8524
16
          { "Extension Flag", "oran_fh_cus.ef",
8525
16
            FT_BOOLEAN, 8,
8526
16
            NULL, 0x80,
8527
16
            "Indicates if more section extensions follow", HFILL}
8528
16
        },
8529
        /* Section 7.5.3.9 */
8530
16
        { &hf_oran_beamId,
8531
16
          { "Beam ID", "oran_fh_cus.beamId",
8532
16
             FT_UINT16, BASE_DEC,
8533
16
             NULL, 0x7fff,
8534
16
             "Defines the beam pattern to be applied to the U-Plane data", HFILL}
8535
16
        },
8536
8537
16
        { &hf_oran_extension,
8538
16
          { "Extension", "oran_fh_cus.extension",
8539
16
            FT_STRING, BASE_NONE,
8540
16
            NULL, 0x0,
8541
16
            "Section extension", HFILL}
8542
16
        },
8543
8544
        /* Section 7.6.2.1 */
8545
16
        { &hf_oran_exttype,
8546
16
          { "extType", "oran_fh_cus.extType",
8547
16
            FT_UINT8, BASE_DEC|BASE_EXT_STRING,
8548
16
            &exttype_vals_ext, 0x7f,
8549
16
            "The extension type, which provides additional parameters specific to subject data extension", HFILL}
8550
16
        },
8551
8552
        /* Section 7.6.2.3 */
8553
16
        { &hf_oran_extlen,
8554
16
          { "extLen", "oran_fh_cus.extLen",
8555
16
            FT_UINT16, BASE_DEC,
8556
16
            NULL, 0x0,
8557
16
            "Extension length in 32-bit words", HFILL}
8558
16
        },
8559
8560
        /* Section 7.7.1 */
8561
16
        { &hf_oran_bfw,
8562
16
          { "bfw", "oran_fh_cus.bfw",
8563
16
            FT_STRING, BASE_NONE,
8564
16
            NULL, 0x0,
8565
16
            "Set of weights for a particular antenna", HFILL}
8566
16
        },
8567
16
        { &hf_oran_bfw_bundle,
8568
16
          { "Bundle", "oran_fh_cus.bfw.bundle",
8569
16
            FT_STRING, BASE_NONE,
8570
16
            NULL, 0x0,
8571
16
            "Bundle of BFWs", HFILL}
8572
16
        },
8573
16
        { &hf_oran_bfw_bundle_id,
8574
16
          { "Bundle Id", "oran_fh_cus.bfw.bundleId",
8575
16
            FT_UINT32, BASE_DEC,
8576
16
            NULL, 0x0,
8577
16
            NULL, HFILL}
8578
16
        },
8579
        /* Section 7.7.1.4 */
8580
16
        { &hf_oran_bfw_i,
8581
16
          { "bfwI", "oran_fh_cus.bfwI",
8582
16
            FT_FLOAT, BASE_NONE,
8583
16
            NULL, 0x0,
8584
16
            "In-phase", HFILL}
8585
16
        },
8586
        /* Section 7.7.1.5 */
8587
16
        { &hf_oran_bfw_q,
8588
16
          { "bfwQ", "oran_fh_cus.bfwQ",
8589
16
            FT_FLOAT, BASE_NONE,
8590
16
            NULL, 0x0,
8591
16
            "Quadrature", HFILL}
8592
16
        },
8593
8594
        /* Section 7.5.3.10 */
8595
16
        { &hf_oran_ueId,
8596
16
          { "UE ID", "oran_fh_cus.ueId",
8597
16
            FT_UINT16, BASE_DEC,
8598
16
            NULL, 0x7fff,
8599
16
            "logical identifier for set of channel info", HFILL}
8600
16
        },
8601
        /* Section 7.5.3.11 */
8602
16
        { &hf_oran_freqOffset,
8603
16
          { "Frequency Offset", "oran_fh_cus.freqOffset",
8604
16
            FT_UINT24, BASE_DEC,
8605
16
            NULL, 0x0,
8606
16
            "with respect to the carrier center frequency before additional filtering", HFILL}
8607
16
        },
8608
8609
        /* Section 7.5.3.12 */
8610
16
        { &hf_oran_regularizationFactor,
8611
16
          { "Regularization Factor", "oran_fh_cus.regularizationFactor",
8612
16
            FT_INT16, BASE_DEC,
8613
16
            NULL, 0x0,
8614
16
            "Signed value to support MMSE operation within O-RU", HFILL}
8615
16
        },
8616
        /* Section 7.5.3.14 */
8617
16
        { &hf_oran_laaMsgType,
8618
16
          { "LAA Message Type", "oran_fh_cus.laaMsgType",
8619
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8620
16
            RVALS(laaMsgTypes), 0xf0,
8621
16
            NULL, HFILL}
8622
16
        },
8623
        /* Section 7.5.3.15 */
8624
16
        { &hf_oran_laaMsgLen,
8625
16
          { "LAA Message Length", "oran_fh_cus.laaMsgLen",
8626
16
            FT_UINT8, BASE_DEC,
8627
16
            NULL, 0x0f,
8628
16
            "number of 32-bit words in the LAA section", HFILL}
8629
16
        },
8630
        /* Section 7.5.3.16 */
8631
16
        { &hf_oran_lbtHandle,
8632
16
          { "LBT Handle", "oran_fh_cus.lbtHandle",
8633
16
            FT_UINT16, BASE_HEX,
8634
16
            NULL, 0x0,
8635
16
            "label to identify transaction", HFILL}
8636
16
         },
8637
        /* Section 7.5.3.17 */
8638
16
        { &hf_oran_lbtDeferFactor,
8639
16
          { "Defer Factor", "oran_fh_cus.lbtDeferFactor",
8640
16
            FT_UINT8, BASE_DEC,
8641
16
            NULL, 0x07,
8642
16
            "Defer factor in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
8643
16
        },
8644
        /* Section 7.5.3.18 */
8645
16
        { &hf_oran_lbtBackoffCounter,
8646
16
          { "Backoff Counter", "oran_fh_cus.lbtBackoffCounter",
8647
16
            FT_UINT16, BASE_DEC,
8648
16
            NULL, 0xffc0,
8649
16
            "LBT backoff counter in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
8650
16
        },
8651
        /* Section 7.5.3.19 */
8652
16
        { &hf_oran_lbtOffset,
8653
16
          { "LBT Offset", "oran_fh_cus.lbtOffset",
8654
16
            FT_UINT16, BASE_DEC,
8655
16
            NULL, 0xffc0,
8656
16
            "LBT start time in microseconds from the beginning of the subframe scheduled by this message", HFILL}
8657
16
        },
8658
        /* Section 7.5.3.20 */
8659
16
        { &hf_oran_MCOT,
8660
16
          { "Maximum Channel Occupancy Time", "oran_fh_cus.MCOT",
8661
16
            FT_UINT8, BASE_DEC,
8662
16
            NULL, 0x3c,
8663
16
            "LTE TXOP duration in subframes as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
8664
16
        },
8665
        /* Section 7.5.3.21 */
8666
16
        { &hf_oran_lbtMode,
8667
16
          { "LBT Mode", "oran_fh_cus.lbtMode",
8668
16
            FT_UINT8, BASE_DEC,
8669
16
            VALS(lbtMode_vals), 0x0,
8670
16
            NULL, HFILL}
8671
16
        },
8672
        /* Section 7.5.3.22 */
8673
16
        { &hf_oran_lbtPdschRes,
8674
16
          { "lbtPdschRes", "oran_fh_cus.lbtPdschRes",
8675
16
            FT_UINT8, BASE_DEC,
8676
16
            VALS(lbtPdschRes_vals), 0xc0,
8677
16
            "LBT result of SFN/SF", HFILL}
8678
16
        },
8679
        /* Section 7.5.3.23 */
8680
16
        { &hf_oran_sfStatus,
8681
16
          { "sfStatus", "oran_fh_cus.sfStatus",
8682
16
            FT_BOOLEAN, 8,
8683
16
            TFS(&tfs_sfStatus), 0x10,
8684
16
            "Indicates whether the subframe was dropped or transmitted", HFILL}
8685
16
        },
8686
        /* Section 7.5.3.24 */
8687
16
        { &hf_oran_lbtDrsRes,
8688
16
          { "lbtDrsRes", "oran_fh_cus.lbtDrsRes",
8689
16
            FT_BOOLEAN, 8,
8690
16
            TFS(&tfs_fail_success), 0x80,
8691
16
            "Indicates whether the subframe was dropped or transmitted", HFILL}
8692
16
        },
8693
        /* Section 7.5.3.25 */
8694
16
        { &hf_oran_initialPartialSF,
8695
16
          { "Initial partial SF", "oran_fh_cus.initialPartialSF",
8696
16
            FT_BOOLEAN, 8,
8697
16
            TFS(&tfs_partial_full_sf), 0x40,
8698
16
            "Indicates whether the initial SF in the LBT process is full or partial", HFILL}
8699
16
        },
8700
        /* Section 7.5.3.26. */
8701
16
        { &hf_oran_lbtBufErr,
8702
16
          { "lbtBufErr", "oran_fh_cus.lbtBufErr",
8703
16
            FT_BOOLEAN, 8,
8704
16
            TFS(&tfs_lbtBufErr), 0x80,
8705
16
            "LBT buffer error", HFILL}
8706
16
        },
8707
        /* Section 7.5.3.27 */
8708
16
        { &hf_oran_sfnSfEnd,
8709
16
          { "SFN/SF End", "oran_fh_cus.sfnSfEnd",
8710
16
            FT_UINT16, BASE_DEC,
8711
16
            NULL, 0x0fff,
8712
16
            "SFN/SF by which the DRS window must end", HFILL}
8713
16
        },
8714
        /* Section 7.5.3.28 */
8715
16
        { &hf_oran_lbtCWConfig_H,
8716
16
          { "lbtCWConfig_H", "oran_fh_cus.lbtCWConfig_H",
8717
16
            FT_UINT8, BASE_DEC,
8718
16
            NULL, 0x0,
8719
16
            "HARQ parameters for congestion window management", HFILL}
8720
16
        },
8721
        /* Section 7.5.3.29 */
8722
16
        { &hf_oran_lbtCWConfig_T,
8723
16
          { "lbtCWConfig_T", "oran_fh_cus.lbtCWConfig_T",
8724
16
            FT_UINT8, BASE_DEC,
8725
16
            NULL, 0x0,
8726
16
            "TB parameters for congestion window management", HFILL}
8727
16
        },
8728
        /* Section 7.5.3.30 */
8729
16
        { &hf_oran_lbtTrafficClass,
8730
16
          { "lbtTrafficClass", "oran_fh_cus.lbtTrafficClass",
8731
16
            FT_UINT8, BASE_DEC,
8732
16
            VALS(lbtTrafficClass_vals), 0x38,
8733
16
            "Traffic class priority for congestion window management", HFILL}
8734
16
        },
8735
        /* Section 7.5.3.31 */
8736
16
        { &hf_oran_lbtCWR_Rst,
8737
16
          { "lbtCWR_Rst", "oran_fh_cus.lbtCWR_Rst",
8738
16
            FT_BOOLEAN, 8,
8739
16
            TFS(&tfs_fail_success), 0x80,
8740
16
            "notification about packet reception successful or not", HFILL}
8741
16
        },
8742
8743
        /* Reserved fields */
8744
16
        { &hf_oran_reserved,
8745
16
          { "reserved", "oran_fh_cus.reserved",
8746
16
            FT_UINT64, BASE_HEX,
8747
16
            NULL, 0x0,
8748
16
            NULL, HFILL}
8749
16
        },
8750
16
        { &hf_oran_reserved_1bit,
8751
16
          { "reserved", "oran_fh_cus.reserved",
8752
16
            FT_UINT8, BASE_HEX,
8753
16
            NULL, 0x80,
8754
16
            NULL, HFILL}
8755
16
        },
8756
16
        { &hf_oran_reserved_2bits,
8757
16
          { "reserved", "oran_fh_cus.reserved",
8758
16
            FT_UINT8, BASE_HEX,
8759
16
            NULL, 0xc0,
8760
16
            NULL, HFILL}
8761
16
        },
8762
16
        { &hf_oran_reserved_3bits,
8763
16
          { "reserved", "oran_fh_cus.reserved",
8764
16
            FT_UINT8, BASE_HEX,
8765
16
            NULL, 0xe0,
8766
16
            NULL, HFILL}
8767
16
        },
8768
16
        { &hf_oran_reserved_4bits,
8769
16
          { "reserved", "oran_fh_cus.reserved",
8770
16
            FT_UINT8, BASE_HEX,
8771
16
            NULL, 0xf0,
8772
16
            NULL, HFILL}
8773
16
        },
8774
16
        { &hf_oran_reserved_last_4bits,
8775
16
          { "reserved", "oran_fh_cus.reserved",
8776
16
            FT_UINT8, BASE_HEX,
8777
16
            NULL, 0x0f,
8778
16
            NULL, HFILL}
8779
16
        },
8780
16
        { &hf_oran_reserved_last_5bits,
8781
16
          { "reserved", "oran_fh_cus.reserved",
8782
16
            FT_UINT8, BASE_HEX,
8783
16
            NULL, 0x1f,
8784
16
            NULL, HFILL}
8785
16
        },
8786
16
        { &hf_oran_reserved_6bits,
8787
16
          { "reserved", "oran_fh_cus.reserved",
8788
16
            FT_UINT8, BASE_HEX,
8789
16
            NULL, 0xfc,
8790
16
            NULL, HFILL}
8791
16
        },
8792
16
        { &hf_oran_reserved_last_6bits,
8793
16
          { "reserved", "oran_fh_cus.reserved",
8794
16
            FT_UINT8, BASE_HEX,
8795
16
            NULL, 0x3f,
8796
16
            NULL, HFILL}
8797
16
        },
8798
16
        { &hf_oran_reserved_7bits,
8799
16
          { "reserved", "oran_fh_cus.reserved",
8800
16
            FT_UINT8, BASE_HEX,
8801
16
            NULL, 0xfe,
8802
16
            NULL, HFILL}
8803
16
        },
8804
16
        { &hf_oran_reserved_last_7bits,
8805
16
          { "reserved", "oran_fh_cus.reserved",
8806
16
            FT_UINT8, BASE_HEX,
8807
16
            NULL, 0x7f,
8808
16
            NULL, HFILL}
8809
16
        },
8810
16
        { &hf_oran_reserved_8bits,
8811
16
          { "reserved", "oran_fh_cus.reserved",
8812
16
            FT_UINT8, BASE_HEX,
8813
16
            NULL, 0x0,
8814
16
            NULL, HFILL}
8815
16
        },
8816
16
        { &hf_oran_reserved_16bits,
8817
16
          { "reserved", "oran_fh_cus.reserved",
8818
16
            FT_UINT16, BASE_HEX,
8819
16
            NULL, 0x0,
8820
16
            NULL, HFILL}
8821
16
        },
8822
16
        { &hf_oran_reserved_15bits,
8823
16
          { "reserved", "oran_fh_cus.reserved",
8824
16
            FT_UINT16, BASE_HEX,
8825
16
            NULL, 0x7fff,
8826
16
            NULL, HFILL}
8827
16
        },
8828
16
        { &hf_oran_reserved_bit1,
8829
16
          { "reserved", "oran_fh_cus.reserved",
8830
16
            FT_UINT8, BASE_HEX,
8831
16
            NULL, 0x40,
8832
16
            NULL, HFILL}
8833
16
        },
8834
16
        { &hf_oran_reserved_bit2,
8835
16
          { "reserved", "oran_fh_cus.reserved",
8836
16
            FT_UINT8, BASE_HEX,
8837
16
            NULL, 0x20,
8838
16
            NULL, HFILL}
8839
16
        },
8840
16
        { &hf_oran_reserved_bit4,
8841
16
          { "reserved", "oran_fh_cus.reserved",
8842
16
            FT_UINT8, BASE_HEX,
8843
16
            NULL, 0x08,
8844
16
            NULL, HFILL}
8845
16
        },
8846
16
        { &hf_oran_reserved_bit5,
8847
16
          { "reserved", "oran_fh_cus.reserved",
8848
16
            FT_UINT8, BASE_HEX,
8849
16
            NULL, 0x04,
8850
16
            NULL, HFILL}
8851
16
        },
8852
16
        { &hf_oran_reserved_bits123,
8853
16
          { "reserved", "oran_fh_cus.reserved",
8854
16
            FT_UINT8, BASE_HEX,
8855
16
            NULL, 0x70,
8856
16
            NULL, HFILL}
8857
16
        },
8858
16
        { &hf_oran_reserved_bits456,
8859
16
          { "reserved", "oran_fh_cus.reserved",
8860
16
            FT_UINT8, BASE_HEX,
8861
16
            NULL, 0x0e,
8862
16
            NULL, HFILL}
8863
16
        },
8864
8865
        /* 7.7.11.9 */
8866
16
        { &hf_oran_cont_ind,
8867
16
          { "contInd", "oran_fh_cus.contInd",
8868
16
            FT_BOOLEAN, 8,
8869
16
            TFS(&continuity_indication_tfs), 0x80,
8870
16
            "PRB region continuity flag", HFILL}
8871
16
        },
8872
        /* 7.7.11.10 */
8873
16
        { &hf_oran_bundle_offset,
8874
16
          { "BundleOffset", "oran_fh_cus.bundleOffset",
8875
16
            FT_UINT8, BASE_DEC,
8876
16
            NULL, 0x3f,
8877
16
            "offset between start of first PRB bundle and startPrbc", HFILL}
8878
16
        },
8879
8880
        /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
8881
16
        { &hf_oran_bfwCompHdr,
8882
16
          { "bfwCompHdr", "oran_fh_cus.bfwCompHdr",
8883
16
            FT_STRING, BASE_NONE,
8884
16
            NULL, 0x0,
8885
16
            "Compression method and IQ bit width for beamforming weights", HFILL}
8886
16
        },
8887
16
        { &hf_oran_bfwCompHdr_iqWidth,
8888
16
          { "IQ Bit Width", "oran_fh_cus.bfwCompHdr_iqWidth",
8889
16
            FT_UINT8, BASE_HEX,
8890
16
            VALS(bfw_comp_headers_iq_width), 0xf0,
8891
16
            "IQ bit width for the beamforming weights", HFILL}
8892
16
        },
8893
16
        { &hf_oran_bfwCompHdr_compMeth,
8894
16
          { "Compression Method", "oran_fh_cus.bfwCompHdr_compMeth",
8895
16
            FT_UINT8, BASE_HEX,
8896
16
            VALS(bfw_comp_headers_comp_meth), 0x0f,
8897
16
            "compression method for the beamforming weights", HFILL}
8898
16
        },
8899
8900
        /* 7.5.3.32 */
8901
16
        { &hf_oran_ciCompParam,
8902
16
          { "ciCompParam", "oran_fh_cus.ciCompParam",
8903
16
            FT_STRING, BASE_NONE,
8904
16
            NULL, 0x0,
8905
16
            "channel information compression parameter", HFILL}
8906
16
        },
8907
8908
        /* Table 7.5.3.32-1 */
8909
16
        { &hf_oran_blockScaler,
8910
16
          { "blockScaler", "oran_fh_cus.blockScaler",
8911
16
            FT_UINT8, BASE_HEX,
8912
16
            NULL, 0x0,
8913
16
            "unsigned, 1 integer bit, 7 fractional bits", HFILL}
8914
16
        },
8915
16
        { &hf_oran_compBitWidth,
8916
16
          { "compBitWidth", "oran_fh_cus.compBitWidth",
8917
16
            FT_UINT8, BASE_DEC,
8918
16
            NULL, 0xf0,
8919
16
            "Length of I bits and length of Q bits after compression over entire PRB", HFILL}
8920
16
        },
8921
16
        { &hf_oran_compShift,
8922
16
          { "compShift", "oran_fh_cus.compShift",
8923
16
            FT_UINT8, BASE_DEC,
8924
16
            NULL, 0x0f,
8925
16
            "The shift applied to the entire PRB", HFILL}
8926
16
        },
8927
8928
16
        { &hf_oran_active_beamspace_coefficient_n1,
8929
16
          { "N1", "oran_fh_cus.activeBeamspace_Coefficient_n1",
8930
16
            FT_BOOLEAN, 8,
8931
16
            TFS(&tfs_present_not_present), 0x80,
8932
16
            NULL, HFILL}
8933
16
        },
8934
16
        { &hf_oran_active_beamspace_coefficient_n2,
8935
16
          { "N2", "oran_fh_cus.activeBeamspace_Coefficient_n2",
8936
16
            FT_BOOLEAN, 8,
8937
16
            TFS(&tfs_present_not_present), 0x40,
8938
16
            NULL, HFILL}
8939
16
        },
8940
16
        { &hf_oran_active_beamspace_coefficient_n3,
8941
16
          { "N3", "oran_fh_cus.activeBeamspace_Coefficient_n3",
8942
16
            FT_BOOLEAN, 8,
8943
16
            TFS(&tfs_present_not_present), 0x20,
8944
16
            NULL, HFILL}
8945
16
        },
8946
16
        { &hf_oran_active_beamspace_coefficient_n4,
8947
16
          { "N4", "oran_fh_cus.activeBeamspace_Coefficient_n4",
8948
16
            FT_BOOLEAN, 8,
8949
16
            TFS(&tfs_present_not_present), 0x10,
8950
16
            NULL, HFILL}
8951
16
        },
8952
16
        { &hf_oran_active_beamspace_coefficient_n5,
8953
16
          { "N5", "oran_fh_cus.activeBeamspace_Coefficient_n5",
8954
16
            FT_BOOLEAN, 8,
8955
16
            TFS(&tfs_present_not_present), 0x08,
8956
16
            NULL, HFILL}
8957
16
        },
8958
16
        { &hf_oran_active_beamspace_coefficient_n6,
8959
16
          { "N6", "oran_fh_cus.activeBeamspace_Coefficient_n6",
8960
16
            FT_BOOLEAN, 8,
8961
16
            TFS(&tfs_present_not_present), 0x04,
8962
16
            NULL, HFILL}
8963
16
        },
8964
16
        { &hf_oran_active_beamspace_coefficient_n7,
8965
16
          { "N7", "oran_fh_cus.activeBeamspace_Coefficient_n7",
8966
16
            FT_BOOLEAN, 8,
8967
16
            TFS(&tfs_present_not_present), 0x02,
8968
16
            NULL, HFILL}
8969
16
        },
8970
16
        { &hf_oran_active_beamspace_coefficient_n8,
8971
16
          { "N8", "oran_fh_cus.activeBeamspace_Coefficient_n8",
8972
16
            FT_BOOLEAN, 8,
8973
16
            TFS(&tfs_present_not_present), 0x01,
8974
16
            NULL, HFILL}
8975
16
        },
8976
8977
16
        { &hf_oran_activeBeamspaceCoefficientMask,
8978
16
          { "activeBeamspaceCoefficientMask", "oran_fh_cus.activeBeamspaceCoefficientMask",
8979
16
            FT_UINT8, BASE_HEX,
8980
16
            NULL, 0xff,
8981
16
            NULL, HFILL}
8982
16
        },
8983
16
        { &hf_oran_activeBeamspaceCoefficientMask_bits_set,
8984
16
          { "Array elements set", "oran_fh_cus.activeBeamspaceCoefficientMask.bits-set",
8985
16
            FT_UINT32, BASE_DEC,
8986
16
            NULL, 0x0,
8987
16
            NULL, HFILL}
8988
16
        },
8989
8990
        /* Section 7.7.6.6 */
8991
16
        { &hf_oran_se6_repetition,
8992
16
          { "repetition", "oran_fh_cus.repetition",
8993
16
            FT_BOOLEAN, BASE_NONE,
8994
16
            TFS(&repetition_se6_tfs), 0x0,
8995
16
            "Repetition of a highest priority data section for C-Plane", HFILL}
8996
16
        },
8997
        /* 7.7.20.9 */
8998
16
        { &hf_oran_rbgSize,
8999
16
          { "rbgSize", "oran_fh_cus.rbgSize",
9000
16
            FT_UINT8, BASE_HEX,
9001
16
            VALS(rbg_size_vals), 0x70,
9002
16
            "Number of PRBs of the resource block groups allocated by the bit mask", HFILL}
9003
16
        },
9004
        /* 7.7.20.10 */
9005
16
        { &hf_oran_rbgMask,
9006
16
          { "rbgMask", "oran_fh_cus.rbgMask",
9007
16
            FT_UINT32, BASE_HEX,
9008
16
            NULL, 0x0fffffff,
9009
16
            "Each bit indicates whether a corresponding resource block group is present", HFILL}
9010
16
        },
9011
        /* 7.7.6.5.  Also 7.7.12.3 and 7.7.19.5 */
9012
16
        { &hf_oran_noncontig_priority,
9013
16
          { "priority", "oran_fh_cus.priority",
9014
16
            FT_UINT8, BASE_HEX,
9015
16
            VALS(priority_vals), 0xc0,
9016
16
            NULL, HFILL}
9017
16
        },
9018
9019
        /* 7.7.6.4 */
9020
16
        { &hf_oran_symbol_mask,
9021
16
          { "symbolMask", "oran_fh_cus.symbolMask",
9022
16
            FT_UINT16, BASE_HEX,
9023
16
            NULL, 0x3fff,
9024
16
            "Each bit indicates whether the rbgMask applies to a given symbol in the slot", HFILL}
9025
16
        },
9026
16
        { &hf_oran_symbol_mask_s13,
9027
16
          { "symbol 13", "oran_fh_cus.symbolMask.symbol-13",
9028
16
            FT_BOOLEAN, 16,
9029
16
            TFS(&tfs_present_not_present), 0x2000,
9030
16
            NULL, HFILL}
9031
16
        },
9032
16
        { &hf_oran_symbol_mask_s12,
9033
16
          { "symbol 12", "oran_fh_cus.symbolMask.symbol-12",
9034
16
            FT_BOOLEAN, 16,
9035
16
            TFS(&tfs_present_not_present), 0x1000,
9036
16
            NULL, HFILL}
9037
16
        },
9038
16
        { &hf_oran_symbol_mask_s11,
9039
16
          { "symbol 11", "oran_fh_cus.symbolMask.symbol-11",
9040
16
            FT_BOOLEAN, 16,
9041
16
            TFS(&tfs_present_not_present), 0x0800,
9042
16
            NULL, HFILL}
9043
16
        },
9044
16
        { &hf_oran_symbol_mask_s10,
9045
16
          { "symbol 10", "oran_fh_cus.symbolMask.symbol-10",
9046
16
            FT_BOOLEAN, 16,
9047
16
            TFS(&tfs_present_not_present), 0x0400,
9048
16
            NULL, HFILL}
9049
16
        },
9050
16
        { &hf_oran_symbol_mask_s9,
9051
16
          { "symbol  9", "oran_fh_cus.symbolMask.symbol-9",
9052
16
            FT_BOOLEAN, 16,
9053
16
            TFS(&tfs_present_not_present), 0x0200,
9054
16
            NULL, HFILL}
9055
16
        },
9056
16
        { &hf_oran_symbol_mask_s8,
9057
16
          { "symbol  8", "oran_fh_cus.symbolMask.symbol-8",
9058
16
            FT_BOOLEAN, 16,
9059
16
            TFS(&tfs_present_not_present), 0x0100,
9060
16
            NULL, HFILL}
9061
16
        },
9062
16
        { &hf_oran_symbol_mask_s7,
9063
16
          { "symbol  7", "oran_fh_cus.symbolMask.symbol-7",
9064
16
            FT_BOOLEAN, 16,
9065
16
            TFS(&tfs_present_not_present), 0x0080,
9066
16
            NULL, HFILL}
9067
16
        },
9068
16
        { &hf_oran_symbol_mask_s6,
9069
16
          { "symbol  6", "oran_fh_cus.symbolMask.symbol-6",
9070
16
            FT_BOOLEAN, 16,
9071
16
            TFS(&tfs_present_not_present), 0x0040,
9072
16
            NULL, HFILL}
9073
16
        },
9074
16
        { &hf_oran_symbol_mask_s5,
9075
16
          { "symbol  5", "oran_fh_cus.symbolMask.symbol-5",
9076
16
            FT_BOOLEAN, 16,
9077
16
            TFS(&tfs_present_not_present), 0x0020,
9078
16
            NULL, HFILL}
9079
16
        },
9080
16
        { &hf_oran_symbol_mask_s4,
9081
16
          { "symbol  4", "oran_fh_cus.symbolMask.symbol-4",
9082
16
            FT_BOOLEAN, 16,
9083
16
            TFS(&tfs_present_not_present), 0x0010,
9084
16
            NULL, HFILL}
9085
16
        },
9086
16
        { &hf_oran_symbol_mask_s3,
9087
16
          { "symbol  3", "oran_fh_cus.symbolMask.symbol-3",
9088
16
            FT_BOOLEAN, 16,
9089
16
            TFS(&tfs_present_not_present), 0x0008,
9090
16
            NULL, HFILL}
9091
16
        },
9092
16
        { &hf_oran_symbol_mask_s2,
9093
16
          { "symbol  2", "oran_fh_cus.symbolMask.symbol-2",
9094
16
            FT_BOOLEAN, 16,
9095
16
            TFS(&tfs_present_not_present), 0x0004,
9096
16
            NULL, HFILL}
9097
16
        },
9098
16
        { &hf_oran_symbol_mask_s1,
9099
16
          { "symbol  1", "oran_fh_cus.symbolMask.symbol-1",
9100
16
            FT_BOOLEAN, 16,
9101
16
            TFS(&tfs_present_not_present), 0x0002,
9102
16
            NULL, HFILL}
9103
16
        },
9104
16
        { &hf_oran_symbol_mask_s0,
9105
16
          { "symbol  0", "oran_fh_cus.symbolMask.symbol-0",
9106
16
            FT_BOOLEAN, 16,
9107
16
            TFS(&tfs_present_not_present), 0x0001,
9108
16
            NULL, HFILL}
9109
16
        },
9110
9111
        /* 7.7.6.3 */
9112
16
        { &hf_oran_rbg_mask_27,
9113
16
          { "bit 27", "oran_fh_cus.rbgMask.bit27",
9114
16
            FT_BOOLEAN, 32,
9115
16
            TFS(&tfs_allocated_not_allocated), 0x08000000,
9116
16
            NULL, HFILL}
9117
16
        },
9118
16
        { &hf_oran_rbg_mask_26,
9119
16
          { "bit 26", "oran_fh_cus.rbgMask.bit26",
9120
16
            FT_BOOLEAN, 32,
9121
16
            TFS(&tfs_allocated_not_allocated), 0x04000000,
9122
16
            NULL, HFILL}
9123
16
        },
9124
16
        { &hf_oran_rbg_mask_25,
9125
16
          { "bit 25", "oran_fh_cus.rbgMask.bit25",
9126
16
            FT_BOOLEAN, 32,
9127
16
            TFS(&tfs_allocated_not_allocated), 0x02000000,
9128
16
            NULL, HFILL}
9129
16
        },
9130
16
        { &hf_oran_rbg_mask_24,
9131
16
          { "bit 24", "oran_fh_cus.rbgMask.bit24",
9132
16
            FT_BOOLEAN, 32,
9133
16
            TFS(&tfs_allocated_not_allocated), 0x01000000,
9134
16
            NULL, HFILL}
9135
16
        },
9136
16
        { &hf_oran_rbg_mask_23,
9137
16
          { "bit 23", "oran_fh_cus.rbgMask.bit23",
9138
16
            FT_BOOLEAN, 32,
9139
16
            TFS(&tfs_allocated_not_allocated), 0x00800000,
9140
16
            NULL, HFILL}
9141
16
        },
9142
16
        { &hf_oran_rbg_mask_22,
9143
16
          { "bit 22", "oran_fh_cus.rbgMask.bit22",
9144
16
            FT_BOOLEAN, 32,
9145
16
            TFS(&tfs_allocated_not_allocated), 0x00400000,
9146
16
            NULL, HFILL}
9147
16
        },
9148
16
        { &hf_oran_rbg_mask_21,
9149
16
          { "bit 21", "oran_fh_cus.rbgMask.bit21",
9150
16
            FT_BOOLEAN, 32,
9151
16
            TFS(&tfs_allocated_not_allocated), 0x00200000,
9152
16
            NULL, HFILL}
9153
16
        },
9154
16
        { &hf_oran_rbg_mask_20,
9155
16
          { "bit 20", "oran_fh_cus.rbgMask.bit20",
9156
16
            FT_BOOLEAN, 32,
9157
16
            TFS(&tfs_allocated_not_allocated), 0x00100000,
9158
16
            NULL, HFILL}
9159
16
        },
9160
16
        { &hf_oran_rbg_mask_19,
9161
16
          { "bit 19", "oran_fh_cus.rbgMask.bit19",
9162
16
            FT_BOOLEAN, 32,
9163
16
            TFS(&tfs_allocated_not_allocated), 0x00080000,
9164
16
            NULL, HFILL}
9165
16
        },
9166
16
        { &hf_oran_rbg_mask_18,
9167
16
          { "bit 18", "oran_fh_cus.rbgMask.bit18",
9168
16
            FT_BOOLEAN, 32,
9169
16
            TFS(&tfs_allocated_not_allocated), 0x00040000,
9170
16
            NULL, HFILL}
9171
16
        },
9172
16
        { &hf_oran_rbg_mask_17,
9173
16
          { "bit 17", "oran_fh_cus.rbgMask.bit17",
9174
16
            FT_BOOLEAN, 32,
9175
16
            TFS(&tfs_allocated_not_allocated), 0x00020000,
9176
16
            NULL, HFILL}
9177
16
        },
9178
16
        { &hf_oran_rbg_mask_16,
9179
16
          { "bit 16", "oran_fh_cus.rbgMask.bit16",
9180
16
            FT_BOOLEAN, 32,
9181
16
            TFS(&tfs_allocated_not_allocated), 0x00010000,
9182
16
            NULL, HFILL}
9183
16
        },
9184
16
        { &hf_oran_rbg_mask_15,
9185
16
          { "bit 15", "oran_fh_cus.rbgMask.bit15",
9186
16
            FT_BOOLEAN, 32,
9187
16
            TFS(&tfs_allocated_not_allocated), 0x00008000,
9188
16
            NULL, HFILL}
9189
16
        },
9190
16
        { &hf_oran_rbg_mask_14,
9191
16
          { "bit 14", "oran_fh_cus.rbgMask.bit14",
9192
16
            FT_BOOLEAN, 32,
9193
16
            TFS(&tfs_allocated_not_allocated), 0x00004000,
9194
16
            NULL, HFILL}
9195
16
        },
9196
16
        { &hf_oran_rbg_mask_13,
9197
16
          { "bit 13", "oran_fh_cus.rbgMask.bit13",
9198
16
            FT_BOOLEAN, 32,
9199
16
            TFS(&tfs_allocated_not_allocated), 0x00002000,
9200
16
            NULL, HFILL}
9201
16
        },
9202
16
        { &hf_oran_rbg_mask_12,
9203
16
          { "bit 12", "oran_fh_cus.rbgMask.bit12",
9204
16
            FT_BOOLEAN, 32,
9205
16
            TFS(&tfs_allocated_not_allocated), 0x00001000,
9206
16
            NULL, HFILL}
9207
16
        },
9208
16
        { &hf_oran_rbg_mask_11,
9209
16
          { "bit 11", "oran_fh_cus.rbgMask.bit11",
9210
16
            FT_BOOLEAN, 32,
9211
16
            TFS(&tfs_allocated_not_allocated), 0x00000800,
9212
16
            NULL, HFILL}
9213
16
        },
9214
16
        { &hf_oran_rbg_mask_10,
9215
16
          { "bit 10", "oran_fh_cus.rbgMask.bit10",
9216
16
            FT_BOOLEAN, 32,
9217
16
            TFS(&tfs_allocated_not_allocated), 0x00000400,
9218
16
            NULL, HFILL}
9219
16
        },
9220
16
        { &hf_oran_rbg_mask_9,
9221
16
          { "bit 9", "oran_fh_cus.rbgMask.bit9",
9222
16
            FT_BOOLEAN, 32,
9223
16
            TFS(&tfs_allocated_not_allocated), 0x00000200,
9224
16
            NULL, HFILL}
9225
16
        },
9226
16
        { &hf_oran_rbg_mask_8,
9227
16
          { "bit 8", "oran_fh_cus.rbgMask.bit8",
9228
16
            FT_BOOLEAN, 32,
9229
16
            TFS(&tfs_allocated_not_allocated), 0x00000100,
9230
16
            NULL, HFILL}
9231
16
        },
9232
16
        { &hf_oran_rbg_mask_7,
9233
16
          { "bit 7", "oran_fh_cus.rbgMask.bit7",
9234
16
            FT_BOOLEAN, 32,
9235
16
            TFS(&tfs_allocated_not_allocated), 0x00000080,
9236
16
            NULL, HFILL}
9237
16
        },
9238
16
        { &hf_oran_rbg_mask_6,
9239
16
          { "bit 6", "oran_fh_cus.rbgMask.bit6",
9240
16
            FT_BOOLEAN, 32,
9241
16
            TFS(&tfs_allocated_not_allocated), 0x00000040,
9242
16
            NULL, HFILL}
9243
16
        },
9244
16
        { &hf_oran_rbg_mask_5,
9245
16
          { "bit 5", "oran_fh_cus.rbgMask.bit5",
9246
16
            FT_BOOLEAN, 32,
9247
16
            TFS(&tfs_allocated_not_allocated), 0x00000020,
9248
16
            NULL, HFILL}
9249
16
        },
9250
16
        { &hf_oran_rbg_mask_4,
9251
16
          { "bit 4", "oran_fh_cus.rbgMask.bit4",
9252
16
            FT_BOOLEAN, 32,
9253
16
            TFS(&tfs_allocated_not_allocated), 0x00000010,
9254
16
            NULL, HFILL}
9255
16
        },
9256
16
        { &hf_oran_rbg_mask_3,
9257
16
          { "bit 3", "oran_fh_cus.rbgMask.bit3",
9258
16
            FT_BOOLEAN, 32,
9259
16
            TFS(&tfs_allocated_not_allocated), 0x00000008,
9260
16
            NULL, HFILL}
9261
16
        },
9262
16
        { &hf_oran_rbg_mask_2,
9263
16
          { "bit 2", "oran_fh_cus.rbgMask.bit2",
9264
16
            FT_BOOLEAN, 32,
9265
16
            TFS(&tfs_allocated_not_allocated), 0x00000004,
9266
16
            NULL, HFILL}
9267
16
        },
9268
16
        { &hf_oran_rbg_mask_1,
9269
16
          { "bit 1", "oran_fh_cus.rbgMask.bit1",
9270
16
            FT_BOOLEAN, 32,
9271
16
            TFS(&tfs_allocated_not_allocated), 0x00000002,
9272
16
            NULL, HFILL}
9273
16
        },
9274
16
        { &hf_oran_rbg_mask_0,
9275
16
          { "bit 0", "oran_fh_cus.rbgMask.bit0",
9276
16
            FT_BOOLEAN, 32,
9277
16
            TFS(&tfs_allocated_not_allocated), 0x00000001,
9278
16
            NULL, HFILL}
9279
16
        },
9280
9281
9282
        /* 7.7.22.2 */
9283
16
        { &hf_oran_ack_nack_req_id,
9284
16
          { "ackNackReqId", "oran_fh_cus.ackNackReqId",
9285
16
            FT_UINT16, BASE_HEX,
9286
16
            NULL, 0x0,
9287
16
            "Indicates the ACK/NACK request ID of a section description", HFILL}
9288
16
        },
9289
9290
        /* Subtree for next 2 items */
9291
16
        { &hf_oran_frequency_range,
9292
16
          { "Frequency Range", "oran_fh_cus.frequencyRange",
9293
16
            FT_STRING, BASE_NONE,
9294
16
            NULL, 0x0,
9295
16
            NULL, HFILL}
9296
16
        },
9297
9298
        /* 7.7.12.4 */
9299
16
        { &hf_oran_off_start_prb,
9300
16
          { "offStartPrb", "oran_fh_cus.offStartPrb",
9301
16
            FT_UINT8, BASE_DEC,
9302
16
            NULL, 0x0,
9303
16
            "Offset of PRB range start", HFILL}
9304
16
        },
9305
        /* 7.7.12.5 */
9306
16
        { &hf_oran_num_prb,
9307
16
          { "numPrb", "oran_fh_cus.numPrb",
9308
16
            FT_UINT8, BASE_DEC,
9309
16
            NULL, 0x0,
9310
16
            "Number of PRBs in PRB range", HFILL}
9311
16
        },
9312
9313
        /* symbolId 8.3.3.7 */
9314
16
        { &hf_oran_symbolId,
9315
16
          { "Symbol Identifier", "oran_fh_cus.symbolId",
9316
16
            FT_UINT8, BASE_DEC,
9317
16
            NULL, 0x3f,
9318
16
            "Identifies a symbol number within a slot", HFILL}
9319
16
        },
9320
9321
        /* startPrbu 8.3.3.11 */
9322
16
        { &hf_oran_startPrbu,
9323
16
          { "startPrbu", "oran_fh_cus.startPrbu",
9324
16
            FT_UINT16, BASE_DEC,
9325
16
            NULL, 0x03ff,
9326
16
            "starting PRB of user plane section", HFILL}
9327
16
        },
9328
9329
        /* numPrbu 8.3.3.12 */
9330
16
        { &hf_oran_numPrbu,
9331
16
          { "numPrbu", "oran_fh_cus.numPrbu",
9332
16
            FT_UINT8, BASE_DEC,
9333
16
            NULL, 0x0,
9334
16
            "number of PRBs per user plane section", HFILL}
9335
16
        },
9336
9337
        /* 7.7.1.3 */
9338
16
        { &hf_oran_bfwCompParam,
9339
16
          { "bfwCompParam", "oran_fh_cus.bfwCompParam",
9340
16
            FT_STRING, BASE_NONE,
9341
16
            NULL, 0x0,
9342
16
            "Beamforming weight compression parameter", HFILL}
9343
16
        },
9344
9345
        /* 6.3.3.13 */
9346
16
        { &hf_oran_udCompHdrMeth,
9347
16
          { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
9348
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9349
16
            RVALS(ud_comp_header_meth), 0x0f,
9350
16
            "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
9351
16
        },
9352
16
        { &hf_oran_udCompHdrMeth_pref,
9353
16
          { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
9354
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9355
16
            RVALS(ud_comp_header_meth), 0x0,
9356
16
            "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
9357
16
        },
9358
        /* 8.3.3.18 */
9359
16
        { &hf_oran_udCompLen,
9360
16
          { "udCompLen", "oran_fh_cus.udCompLen",
9361
16
            FT_UINT16, BASE_DEC,
9362
16
            NULL, 0x0,
9363
16
            "PRB field length in octets", HFILL}
9364
16
        },
9365
9366
        /* 7.5.2.10 */
9367
16
        { &hf_oran_udCompHdrIqWidth,
9368
16
          { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
9369
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9370
16
            RVALS(ud_comp_header_width), 0xf0,
9371
16
            "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
9372
16
        },
9373
16
        { &hf_oran_udCompHdrIqWidth_pref,
9374
16
          { "User Data IQ width", "oran_fh_cus.udCompHdrWidth.pref",
9375
16
            FT_UINT8, BASE_DEC,
9376
16
            NULL, 0x0,
9377
16
            "IQ bit width for the user data in every section in the C-Plane message, from preference", HFILL}
9378
16
        },
9379
9380
16
        { &hf_oran_sinrCompHdrIqWidth_pref,
9381
16
          { "SINR IQ width", "oran_fh_cus.sinrCompHdrWidth",
9382
16
            FT_UINT8, BASE_DEC,
9383
16
            NULL, 0x0,
9384
16
            "Defines the IQ bit width for SINR data in section type 9", HFILL}
9385
16
        },
9386
16
        { &hf_oran_sinrCompHdrMeth_pref,
9387
16
          { "SINR Compression Method", "oran_fh_cus.sinrCompHdrMeth",
9388
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9389
16
            RVALS(ud_comp_header_meth), 0x0,
9390
16
            "Defines the compression method for SINR data in section type 9", HFILL}
9391
16
         },
9392
9393
        /* Section 8.3.3.15 (not always present - depends upon meth) */
9394
16
        { &hf_oran_udCompParam,
9395
16
          { "User Data Compression Parameter", "oran_fh_cus.udCompParam",
9396
16
            FT_STRING, BASE_NONE,
9397
16
            NULL, 0x0,
9398
16
            "Applies to whatever compression method is specified by the associated sectionID's compMeth value", HFILL}
9399
16
        },
9400
        /* 8.3.3.18 */
9401
16
        { &hf_oran_sReSMask,
9402
16
          { "sReSMask", "oran_fh_cus.sReSMask",
9403
16
            FT_UINT16, BASE_HEX,
9404
16
            NULL, 0xf0ff,
9405
16
            "selective RE sending mask", HFILL}
9406
16
        },
9407
9408
16
        { &hf_oran_sReSMask_re12,
9409
16
          { "RE-12", "oran_fh_cus.sReSMask-re12",
9410
16
            FT_BOOLEAN, 16,
9411
16
            TFS(&tfs_present_not_present), 0x8000,
9412
16
            NULL, HFILL}
9413
16
        },
9414
16
        { &hf_oran_sReSMask_re11,
9415
16
          { "RE-11", "oran_fh_cus.sReSMask-re11",
9416
16
            FT_BOOLEAN, 16,
9417
16
            TFS(&tfs_present_not_present), 0x4000,
9418
16
            NULL, HFILL}
9419
16
        },
9420
16
        { &hf_oran_sReSMask_re10,
9421
16
          { "RE-10", "oran_fh_cus.sReSMask-re10",
9422
16
            FT_BOOLEAN, 16,
9423
16
            TFS(&tfs_present_not_present), 0x2000,
9424
16
            NULL, HFILL}
9425
16
        },
9426
16
        { &hf_oran_sReSMask_re9,
9427
16
          { "RE-9", "oran_fh_cus.sReSMask-re9",
9428
16
            FT_BOOLEAN, 16,
9429
16
            TFS(&tfs_present_not_present), 0x1000,
9430
16
            NULL, HFILL}
9431
16
        },
9432
16
        { &hf_oran_sReSMask_re8,
9433
16
          { "RE-8", "oran_fh_cus.sReSMask-re8",
9434
16
            FT_BOOLEAN, 16,
9435
16
            TFS(&tfs_present_not_present), 0x0080,
9436
16
            NULL, HFILL}
9437
16
        },
9438
16
        { &hf_oran_sReSMask_re7,
9439
16
          { "RE-7", "oran_fh_cus.sReSMask-re7",
9440
16
            FT_BOOLEAN, 16,
9441
16
            TFS(&tfs_present_not_present), 0x0040,
9442
16
            NULL, HFILL}
9443
16
        },
9444
16
        { &hf_oran_sReSMask_re6,
9445
16
          { "RE-6", "oran_fh_cus.sReSMask-re6",
9446
16
            FT_BOOLEAN, 16,
9447
16
            TFS(&tfs_present_not_present), 0x0020,
9448
16
            NULL, HFILL}
9449
16
        },
9450
16
        { &hf_oran_sReSMask_re5,
9451
16
          { "RE-5", "oran_fh_cus.sReSMask-re5",
9452
16
            FT_BOOLEAN, 16,
9453
16
            TFS(&tfs_present_not_present), 0x0010,
9454
16
            NULL, HFILL}
9455
16
        },
9456
16
        { &hf_oran_sReSMask_re4,
9457
16
          { "RE-4", "oran_fh_cus.sReSMask-re4",
9458
16
            FT_BOOLEAN, 16,
9459
16
            TFS(&tfs_present_not_present), 0x0008,
9460
16
            NULL, HFILL}
9461
16
        },
9462
16
        { &hf_oran_sReSMask_re3,
9463
16
          { "RE-3", "oran_fh_cus.sReSMask-re3",
9464
16
            FT_BOOLEAN, 16,
9465
16
            TFS(&tfs_present_not_present), 0x0004,
9466
16
            NULL, HFILL}
9467
16
        },
9468
16
        { &hf_oran_sReSMask_re2,
9469
16
          { "RE-2", "oran_fh_cus.sReSMask-re2",
9470
16
            FT_BOOLEAN, 16,
9471
16
            TFS(&tfs_present_not_present), 0x0002,
9472
16
            NULL, HFILL}
9473
16
        },
9474
16
        { &hf_oran_sReSMask_re1,
9475
16
          { "RE-1", "oran_fh_cus.sReSMask-re1",
9476
16
            FT_BOOLEAN, 16,
9477
16
            TFS(&tfs_present_not_present), 0x0001,
9478
16
            NULL, HFILL}
9479
16
        },
9480
9481
        /* 8.3.3.20 */
9482
16
        { &hf_oran_sReSMask1,
9483
16
          { "sReSMask1", "oran_fh_cus.sReSMask1",
9484
16
            FT_UINT16, BASE_HEX,
9485
16
            NULL, 0x0fff,
9486
16
            "selective RE sending mask 1", HFILL}
9487
16
        },
9488
        /* 8.3.3.21 */
9489
16
        { &hf_oran_sReSMask2,
9490
16
          { "sReSMask2", "oran_fh_cus.sReSMask2",
9491
16
            FT_UINT16, BASE_HEX,
9492
16
            NULL, 0x0fff,
9493
16
            "selective RE sending mask 2", HFILL}
9494
16
        },
9495
9496
16
        { &hf_oran_sReSMask1_2_re12,
9497
16
          { "RE-12", "oran_fh_cus.sReSMask-re12",
9498
16
            FT_BOOLEAN, 16,
9499
16
            TFS(&tfs_present_not_present), 0x0800,
9500
16
            NULL, HFILL}
9501
16
        },
9502
16
        { &hf_oran_sReSMask1_2_re11,
9503
16
          { "RE-11", "oran_fh_cus.sReSMask-re11",
9504
16
            FT_BOOLEAN, 16,
9505
16
            TFS(&tfs_present_not_present), 0x0400,
9506
16
            NULL, HFILL}
9507
16
        },
9508
16
        { &hf_oran_sReSMask1_2_re10,
9509
16
          { "RE-10", "oran_fh_cus.sReSMask-re10",
9510
16
            FT_BOOLEAN, 16,
9511
16
            TFS(&tfs_present_not_present), 0x0200,
9512
16
            NULL, HFILL}
9513
16
        },
9514
16
        { &hf_oran_sReSMask1_2_re9,
9515
16
          { "RE-9", "oran_fh_cus.sReSMask-re9",
9516
16
            FT_BOOLEAN, 16,
9517
16
            TFS(&tfs_present_not_present), 0x0100,
9518
16
            NULL, HFILL}
9519
16
        },
9520
9521
        /* Section 6.3.3.15 */
9522
16
        { &hf_oran_iSample,
9523
16
          { "iSample", "oran_fh_cus.iSample",
9524
16
            FT_FLOAT, BASE_NONE,
9525
16
            NULL, 0x0,
9526
16
            "In-phase Sample value", HFILL}
9527
16
        },
9528
9529
        /* Section 6.3.3.16 */
9530
16
        { &hf_oran_qSample,
9531
16
          { "qSample", "oran_fh_cus.qSample",
9532
16
            FT_FLOAT, BASE_NONE,
9533
16
            NULL, 0x0,
9534
16
            "Quadrature Sample value", HFILL}
9535
16
        },
9536
9537
16
        { &hf_oran_exponent,
9538
16
          { "Exponent", "oran_fh_cus.exponent",
9539
16
            FT_UINT8, BASE_DEC,
9540
16
            NULL, 0x0f,
9541
16
            "Exponent applicable to the I & Q mantissas", HFILL }
9542
16
        },
9543
9544
16
        { &hf_oran_iq_user_data,
9545
16
          { "IQ User Data", "oran_fh_cus.iq_user_data",
9546
16
            FT_BYTES, BASE_NONE,
9547
16
            NULL, 0x0,
9548
16
            "Used for the In-phase and Quadrature sample mantissa", HFILL }
9549
16
        },
9550
9551
9552
16
        { &hf_oran_u_section_ul_symbol_time,
9553
16
          { "Microseconds since first UL U-plane frame for this symbol", "oran_fh_cus.us-since-first-ul-frame",
9554
16
            FT_UINT32, BASE_DEC,
9555
16
            NULL, 0x0,
9556
16
            NULL, HFILL }
9557
16
        },
9558
16
        { &hf_oran_u_section_ul_symbol_frames,
9559
16
          { "Number of UL frames sent for this symbol", "oran_fh_cus.number-ul-frames-in-symbol",
9560
16
            FT_UINT32, BASE_DEC,
9561
16
            NULL, 0x0,
9562
16
            NULL, HFILL }
9563
16
        },
9564
16
        { &hf_oran_u_section_ul_symbol_first_frame,
9565
16
          { "First UL frame for this symbol", "oran_fh_cus.first-ul-frame-in-symbol",
9566
16
            FT_FRAMENUM, BASE_NONE,
9567
16
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
9568
16
            NULL, HFILL }
9569
16
        },
9570
16
        { &hf_oran_u_section_ul_symbol_last_frame,
9571
16
          { "Last UL frame for this symbol", "oran_fh_cus.last-ul-frame-in-symbol",
9572
16
            FT_FRAMENUM, BASE_NONE,
9573
16
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
9574
16
            NULL, HFILL }
9575
16
        },
9576
9577
16
        { &hf_oran_c_eAxC_ID,
9578
16
          { "c_eAxC_ID", "oran_fh_cus.c_eaxc_id",
9579
16
            FT_STRING, BASE_NONE,
9580
16
            NULL, 0x0,
9581
16
            "This is a calculated field for the c_eAxC ID, which identifies the message stream", HFILL }
9582
16
        },
9583
9584
16
        { &hf_oran_refa,
9585
16
          { "RefA", "oran_fh_cus.refa",
9586
16
            FT_STRING, BASE_NONE,
9587
16
            NULL, 0x0,
9588
16
            "This is a calculated field for the RefA ID, which provides a reference in time", HFILL }
9589
16
        },
9590
9591
9592
        /* Section 7.5.2.15 */
9593
16
        { &hf_oran_ciCompHdr,
9594
16
          { "ciCompHdr", "oran_fh_cus.ciCompHdr",
9595
16
            FT_STRING, BASE_NONE,
9596
16
            NULL, 0x0,
9597
16
            "Channel Information Compression Header", HFILL}
9598
16
        },
9599
16
        { &hf_oran_ciCompHdrMeth,
9600
16
          { "User Data Compression Method", "oran_fh_cus.ciCompHdrMeth",
9601
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9602
16
            RVALS(ud_comp_header_meth), 0x0e,
9603
16
            "Compression method for Channel Information", HFILL}
9604
16
         },
9605
16
        { &hf_oran_ciCompHdrIqWidth,
9606
16
          { "User Data IQ width", "oran_fh_cus.ciCompHdrWidth",
9607
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9608
16
            RVALS(ud_comp_header_width), 0xf0,
9609
16
            "IQ bit width for Channel Information", HFILL}
9610
16
        },
9611
16
        { &hf_oran_ciCompOpt,
9612
16
          { "ciCompOpt", "oran_fh_cus.ciCompOpt",
9613
16
            FT_UINT8, BASE_DEC,
9614
16
            VALS(ci_comp_opt_vals), 0x01,
9615
16
            NULL, HFILL }
9616
16
        },
9617
9618
        /* 7.7.11.7 */
9619
16
        { &hf_oran_disable_bfws,
9620
16
          { "disableBFWs", "oran_fh_cus.disableBFWs",
9621
16
            FT_BOOLEAN, 8,
9622
16
            NULL, 0x80,
9623
16
            "Indicate if BFWs under section extension are disabled", HFILL }
9624
16
        },
9625
        /* 7.7.11.8 */
9626
16
        { &hf_oran_rad,
9627
16
          { "RAD", "oran_fh_cus.rad",
9628
16
            FT_BOOLEAN, 8,
9629
16
            NULL, 0x40,
9630
16
            "Reset After PRB Discontinuity", HFILL }
9631
16
        },
9632
        /* 7.7.11.4 */
9633
16
        { &hf_oran_num_bund_prbs,
9634
16
          { "numBundPrb", "oran_fh_cus.numBundPrb",
9635
16
            FT_UINT8, BASE_DEC,
9636
16
            NULL, 0x0,
9637
16
            "Number of bundled PRBs per BFWs", HFILL }
9638
16
        },
9639
16
        { &hf_oran_beam_id,
9640
16
          { "beamId", "oran_fh_cus.beamId",
9641
16
            FT_UINT16, BASE_DEC,
9642
16
            NULL, 0x7fff,
9643
16
            NULL, HFILL }
9644
16
        },
9645
16
        { &hf_oran_num_weights_per_bundle,
9646
16
          { "Num weights per bundle", "oran_fh_cus.num_weights_per_bundle",
9647
16
            FT_UINT16, BASE_DEC,
9648
16
            NULL, 0x0,
9649
16
            "From dissector preference", HFILL }
9650
16
        },
9651
9652
16
        { &hf_oran_samples_prb,
9653
16
          {"PRB", "oran_fh_cus.prb",
9654
16
            FT_STRING, BASE_NONE,
9655
16
            NULL, 0x0,
9656
16
            "Grouping of samples for a particular Physical Resource Block", HFILL}
9657
16
         },
9658
9659
        /* 7.5.3.13 */
9660
16
        { &hf_oran_ciSample,
9661
16
          { "ciSample", "oran_fh_cus.ciSample",
9662
16
            FT_STRING, BASE_NONE,
9663
16
            NULL, 0x0,
9664
16
            "Sample (I and Q values)", HFILL}
9665
16
        },
9666
16
        { &hf_oran_ciIsample,
9667
16
          { "ciIsample", "oran_fh_cus.ciISample",
9668
16
            FT_FLOAT, BASE_NONE,
9669
16
            NULL, 0x0,
9670
16
            "Channel information complex value - I part", HFILL}
9671
16
        },
9672
16
        { &hf_oran_ciQsample,
9673
16
          { "ciQsample", "oran_fh_cus.ciQSample",
9674
16
            FT_FLOAT, BASE_NONE,
9675
16
            NULL, 0x0,
9676
16
            "Channel information complex value - Q part", HFILL}
9677
16
        },
9678
9679
        /* 7.7.10.2 */
9680
16
        { &hf_oran_beamGroupType,
9681
16
          { "beamGroupType", "oran_fh_cus.beamGroupType",
9682
16
            FT_UINT8, BASE_DEC,
9683
16
            VALS(beam_group_type_vals), 0xc0,
9684
16
            "The type of beam grouping", HFILL }
9685
16
        },
9686
        /* 7.7.10.3 */
9687
16
        { &hf_oran_numPortc,
9688
16
          { "numPortc", "oran_fh_cus.numPortc",
9689
16
            FT_UINT8, BASE_DEC,
9690
16
            NULL, 0x3f,
9691
16
            "The number of eAxC ports", HFILL }
9692
16
        },
9693
9694
        /* 7.7.4.2 (1 bit) */
9695
16
        { &hf_oran_csf,
9696
16
          { "csf", "oran_fh_cus.csf",
9697
16
            FT_BOOLEAN, BASE_NONE,
9698
16
            NULL, 0x0,
9699
16
            "constellation shift flag", HFILL }
9700
16
        },
9701
        /* 7.7.4.3 */
9702
16
        { &hf_oran_modcompscaler,
9703
16
          { "modCompScaler", "oran_fh_cus.modcompscaler",
9704
16
            FT_UINT16, BASE_DEC,
9705
16
            NULL, 0x7fff,
9706
16
            "modulation compression scaler value", HFILL }
9707
16
        },
9708
9709
        /* 7.7.5.1 */
9710
16
        { &hf_oran_modcomp_param_set,
9711
16
          { "Set", "oran_fh_cus.modcomp-param-set",
9712
16
            FT_STRING, BASE_NONE,
9713
16
            NULL, 0x0,
9714
16
            NULL, HFILL }
9715
16
        },
9716
9717
9718
9719
        /* mcScaleReMask 7.7.5.2 (12 bits) */
9720
9721
        /* First entry (starts with msb within byte) */
9722
16
        { &hf_oran_mc_scale_re_mask_re1,
9723
16
          { "RE 1", "oran_fh_cus.mcscalermask-RE1",
9724
16
            FT_BOOLEAN, 16,
9725
16
            TFS(&tfs_applicable_not_applicable), 0x8000,
9726
16
            NULL, HFILL}
9727
16
        },
9728
16
        { &hf_oran_mc_scale_re_mask_re2,
9729
16
          { "RE 2", "oran_fh_cus.mcscalermask-RE2",
9730
16
            FT_BOOLEAN, 16,
9731
16
            TFS(&tfs_applicable_not_applicable), 0x4000,
9732
16
            NULL, HFILL}
9733
16
        },
9734
16
        { &hf_oran_mc_scale_re_mask_re3,
9735
16
          { "RE 3", "oran_fh_cus.mcscalermask-RE3",
9736
16
            FT_BOOLEAN, 16,
9737
16
            TFS(&tfs_applicable_not_applicable), 0x2000,
9738
16
            NULL, HFILL}
9739
16
        },
9740
16
        { &hf_oran_mc_scale_re_mask_re4,
9741
16
          { "RE 4", "oran_fh_cus.mcscalermask-RE4",
9742
16
            FT_BOOLEAN, 16,
9743
16
            TFS(&tfs_applicable_not_applicable), 0x1000,
9744
16
            NULL, HFILL}
9745
16
        },
9746
16
        { &hf_oran_mc_scale_re_mask_re5,
9747
16
          { "RE 5", "oran_fh_cus.mcscalermask-RE5",
9748
16
            FT_BOOLEAN, 16,
9749
16
            TFS(&tfs_applicable_not_applicable), 0x0800,
9750
16
            NULL, HFILL}
9751
16
        },
9752
16
        { &hf_oran_mc_scale_re_mask_re6,
9753
16
          { "RE 6", "oran_fh_cus.mcscalermask-RE6",
9754
16
            FT_BOOLEAN, 16,
9755
16
            TFS(&tfs_applicable_not_applicable), 0x0400,
9756
16
            NULL, HFILL}
9757
16
        },
9758
16
        { &hf_oran_mc_scale_re_mask_re7,
9759
16
          { "RE 7", "oran_fh_cus.mcscalermask-RE7",
9760
16
            FT_BOOLEAN, 16,
9761
16
            TFS(&tfs_applicable_not_applicable), 0x0200,
9762
16
            NULL, HFILL}
9763
16
        },
9764
16
        { &hf_oran_mc_scale_re_mask_re8,
9765
16
          { "RE 8", "oran_fh_cus.mcscalermask-RE8",
9766
16
            FT_BOOLEAN, 16,
9767
16
            TFS(&tfs_applicable_not_applicable), 0x0100,
9768
16
            NULL, HFILL}
9769
16
        },
9770
16
        { &hf_oran_mc_scale_re_mask_re9,
9771
16
          { "RE 9", "oran_fh_cus.mcscalermask-RE9",
9772
16
            FT_BOOLEAN, 16,
9773
16
            TFS(&tfs_applicable_not_applicable), 0x0080,
9774
16
            NULL, HFILL}
9775
16
        },
9776
16
        { &hf_oran_mc_scale_re_mask_re10,
9777
16
          { "RE 10", "oran_fh_cus.mcscalermask-RE10",
9778
16
            FT_BOOLEAN, 16,
9779
16
            TFS(&tfs_applicable_not_applicable), 0x0040,
9780
16
            NULL, HFILL}
9781
16
        },
9782
16
        { &hf_oran_mc_scale_re_mask_re11,
9783
16
          { "RE 11", "oran_fh_cus.mcscalermask-RE11",
9784
16
            FT_BOOLEAN, 16,
9785
16
            TFS(&tfs_applicable_not_applicable), 0x0020,
9786
16
            NULL, HFILL}
9787
16
        },
9788
16
        { &hf_oran_mc_scale_re_mask_re12,
9789
16
          { "RE 12", "oran_fh_cus.mcscalermask-RE12",
9790
16
            FT_BOOLEAN, 16,
9791
16
            TFS(&tfs_applicable_not_applicable), 0x0010,
9792
16
            NULL, HFILL}
9793
16
        },
9794
9795
        /* Even tries entry (starts with 5th bit within byte) */
9796
16
        { &hf_oran_mc_scale_re_mask_re1_even,
9797
16
          { "RE 1", "oran_fh_cus.mcscalermask-RE1",
9798
16
            FT_BOOLEAN, 16,
9799
16
            TFS(&tfs_applicable_not_applicable), 0x0800,
9800
16
            NULL, HFILL}
9801
16
        },
9802
16
        { &hf_oran_mc_scale_re_mask_re2_even,
9803
16
          { "RE 2", "oran_fh_cus.mcscalermask-RE2",
9804
16
            FT_BOOLEAN, 16,
9805
16
            TFS(&tfs_applicable_not_applicable), 0x0400,
9806
16
            NULL, HFILL}
9807
16
        },
9808
16
        { &hf_oran_mc_scale_re_mask_re3_even,
9809
16
          { "RE 3", "oran_fh_cus.mcscalermask-RE3",
9810
16
            FT_BOOLEAN, 16,
9811
16
            TFS(&tfs_applicable_not_applicable), 0x0200,
9812
16
            NULL, HFILL}
9813
16
        },
9814
16
        { &hf_oran_mc_scale_re_mask_re4_even,
9815
16
          { "RE 4", "oran_fh_cus.mcscalermask-RE4",
9816
16
            FT_BOOLEAN, 16,
9817
16
            TFS(&tfs_applicable_not_applicable), 0x0100,
9818
16
            NULL, HFILL}
9819
16
        },
9820
16
        { &hf_oran_mc_scale_re_mask_re5_even,
9821
16
          { "RE 5", "oran_fh_cus.mcscalermask-RE5",
9822
16
            FT_BOOLEAN, 16,
9823
16
            TFS(&tfs_applicable_not_applicable), 0x0080,
9824
16
            NULL, HFILL}
9825
16
        },
9826
16
        { &hf_oran_mc_scale_re_mask_re6_even,
9827
16
          { "RE 6", "oran_fh_cus.mcscalermask-RE6",
9828
16
            FT_BOOLEAN, 16,
9829
16
            TFS(&tfs_applicable_not_applicable), 0x0040,
9830
16
            NULL, HFILL}
9831
16
        },
9832
16
        { &hf_oran_mc_scale_re_mask_re7_even,
9833
16
          { "RE 7", "oran_fh_cus.mcscalermask-RE7",
9834
16
            FT_BOOLEAN, 16,
9835
16
            TFS(&tfs_applicable_not_applicable), 0x0020,
9836
16
            NULL, HFILL}
9837
16
        },
9838
16
        { &hf_oran_mc_scale_re_mask_re8_even,
9839
16
          { "RE 8", "oran_fh_cus.mcscalermask-RE8",
9840
16
            FT_BOOLEAN, 16,
9841
16
            TFS(&tfs_applicable_not_applicable), 0x0010,
9842
16
            NULL, HFILL}
9843
16
        },
9844
16
        { &hf_oran_mc_scale_re_mask_re9_even,
9845
16
          { "RE 9", "oran_fh_cus.mcscalermask-RE9",
9846
16
            FT_BOOLEAN, 16,
9847
16
            TFS(&tfs_applicable_not_applicable), 0x0008,
9848
16
            NULL, HFILL}
9849
16
        },
9850
16
        { &hf_oran_mc_scale_re_mask_re10_even,
9851
16
          { "RE 10", "oran_fh_cus.mcscalermask-RE10",
9852
16
            FT_BOOLEAN, 16,
9853
16
            TFS(&tfs_applicable_not_applicable), 0x0004,
9854
16
            NULL, HFILL}
9855
16
        },
9856
16
        { &hf_oran_mc_scale_re_mask_re11_even,
9857
16
          { "RE 11", "oran_fh_cus.mcscalermask-RE11",
9858
16
            FT_BOOLEAN, 16,
9859
16
            TFS(&tfs_applicable_not_applicable), 0x0002,
9860
16
            NULL, HFILL}
9861
16
        },
9862
16
        { &hf_oran_mc_scale_re_mask_re12_even,
9863
16
          { "RE 12", "oran_fh_cus.mcscalermask-RE12",
9864
16
            FT_BOOLEAN, 16,
9865
16
            TFS(&tfs_applicable_not_applicable), 0x0001,
9866
16
            NULL, HFILL}
9867
16
        },
9868
9869
16
        { &hf_oran_mc_scale_re_mask,
9870
16
          { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
9871
16
            FT_UINT16, BASE_HEX,
9872
16
            NULL, 0xfff0,
9873
16
            "modulation compression power scale RE mask", HFILL }
9874
16
        },
9875
16
        { &hf_oran_mc_scale_re_mask_even,
9876
16
          { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
9877
16
            FT_UINT16, BASE_HEX,
9878
16
            NULL, 0x0fff,
9879
16
            "modulation compression power scale RE mask", HFILL }
9880
16
        },
9881
9882
        /* mcScaleOffset 7.7.5.4 (15 bits) */
9883
16
        { &hf_oran_mc_scale_offset,
9884
16
          { "mcScaleOffset", "oran_fh_cus.mcscaleoffset",
9885
16
            FT_UINT24, BASE_DEC,
9886
16
            NULL, 0x0,
9887
16
            "scaling value for modulation compression", HFILL }
9888
16
        },
9889
        /* eAxCmask (7.7.7.2) */
9890
16
        { &hf_oran_eAxC_mask,
9891
16
          { "eAxC Mask", "oran_fh_cus.eaxcmask",
9892
16
            FT_UINT16, BASE_HEX,
9893
16
            NULL, 0xffff,
9894
16
            "Which eAxC_ID values the C-Plane message applies to", HFILL }
9895
16
        },
9896
        /* technology (interface name) 7.7.9.2 */
9897
16
        { &hf_oran_technology,
9898
16
          { "Technology", "oran_fh_cus.technology",
9899
16
            FT_UINT8, BASE_DEC,
9900
16
            VALS(interface_name_vals), 0x0,
9901
16
            "Interface name (that C-PLane section applies to)", HFILL }
9902
16
        },
9903
        /* Exttype 14 (7.7.14.2) */
9904
16
        { &hf_oran_nullLayerInd,
9905
16
          { "nullLayerInd", "oran_fh_cus.nulllayerind",
9906
16
            FT_BOOLEAN, BASE_NONE,
9907
16
            NULL, 0x0,
9908
16
            "Whether corresponding layer is nulling-layer or not", HFILL }
9909
16
        },
9910
9911
        /* Exttype 19 */
9912
        /* 7.7.19.3 */
9913
16
        { &hf_oran_se19_repetition,
9914
16
          { "repetition", "oran_fh_cus.repetition",
9915
16
            FT_BOOLEAN, BASE_NONE,
9916
16
            TFS(&repetition_se19_tfs), 0x0,
9917
16
            "repeat port info flag", HFILL}
9918
16
        },
9919
        /* 7.7.19.8 */
9920
        /* TODO: break down into each RE as done for 7.5.3.5 ? */
9921
16
        { &hf_oran_portReMask,
9922
16
          { "portReMask", "oran_fh_cus.portReMask",
9923
16
            FT_BOOLEAN, 16,
9924
16
            TFS(&tfs_set_notset), 0x0fff,
9925
16
            "RE bitmask per port", HFILL }
9926
16
        },
9927
        /* 7.7.19.9 */
9928
16
        { &hf_oran_portSymbolMask,
9929
16
          { "portSymbolMask", "oran_fh_cus.portSymbolMask",
9930
16
            FT_BOOLEAN, 16,
9931
16
            TFS(&tfs_set_notset), 0x3fff,
9932
16
            "Symbol bitmask port port", HFILL }
9933
16
        },
9934
9935
16
        { &hf_oran_ext19_port,
9936
16
          {"Port", "oran_fh_cus.ext19.port",
9937
16
            FT_STRING, BASE_NONE,
9938
16
            NULL, 0x0,
9939
16
            "Entry for a given port in ext19", HFILL}
9940
16
         },
9941
9942
        /* Ext 13 */
9943
16
        { &hf_oran_prb_allocation,
9944
16
          {"PRB allocation", "oran_fh_cus.prb-allocation",
9945
16
            FT_STRING, BASE_NONE,
9946
16
            NULL, 0x0,
9947
16
            NULL, HFILL}
9948
16
         },
9949
        /* 7.7.13.2 */
9950
16
        { &hf_oran_nextSymbolId,
9951
16
          { "nextSymbolId", "oran_fh_cus.nextSymbolId",
9952
16
            FT_UINT8, BASE_DEC,
9953
16
            NULL, 0x3c,
9954
16
            "offset of PRB range start", HFILL }
9955
16
        },
9956
        /* 7.7.13.3 */
9957
16
        { &hf_oran_nextStartPrbc,
9958
16
          { "nextStartPrbc", "oran_fh_cus.nextStartPrbc",
9959
16
            FT_UINT16, BASE_DEC,
9960
16
            NULL, 0x03ff,
9961
16
            "number of PRBs in PRB range", HFILL }
9962
16
        },
9963
9964
        /* Puncturing patters as appears in SE 20 */
9965
16
        { &hf_oran_puncPattern,
9966
16
          { "puncPattern", "oran_fh_cus.puncPattern",
9967
16
            FT_STRING, BASE_NONE,
9968
16
            NULL, 0x0,
9969
16
            NULL, HFILL}
9970
16
        },
9971
9972
        /* 7.7.20.2 numPuncPatterns */
9973
16
        { &hf_oran_numPuncPatterns,
9974
16
          { "numPuncPatterns", "oran_fh_cus.numPuncPatterns",
9975
16
            FT_UINT8, BASE_DEC,
9976
16
            NULL, 0x0,
9977
16
            "number of puncturing patterns", HFILL }
9978
16
        },
9979
        /* 7.7.20.3 symbolMask */
9980
16
        { &hf_oran_symbolMask_ext20,
9981
16
          { "symbolMask", "oran_fh_cus.symbolMask",
9982
16
            FT_UINT16, BASE_HEX,
9983
16
            NULL, 0xfffc,
9984
16
            "Bitmask where each bit indicates the symbols associated with the puncturing pattern", HFILL}
9985
16
        },
9986
        /* 7.7.20.4 startPuncPrb */
9987
16
        { &hf_oran_startPuncPrb,
9988
16
          { "startPuncPrb", "oran_fh_cus.startPuncPrb",
9989
16
            FT_UINT16, BASE_DEC,
9990
16
            NULL, 0x03ff,
9991
16
            "starting PRB to which one puncturing pattern applies", HFILL}
9992
16
        },
9993
        /* 7.7.20.5 numPuncPrb */
9994
16
        { &hf_oran_numPuncPrb,
9995
16
          { "numPuncPrb", "oran_fh_cus.numPuncPrb",
9996
16
            FT_UINT8, BASE_DEC,
9997
16
            NULL, 0x0,
9998
16
            "the number of PRBs of the puncturing pattern", HFILL}
9999
16
        },
10000
        /* 7.7.20.6 puncReMask */
10001
16
        { &hf_oran_puncReMask,
10002
16
          { "puncReMask", "oran_fh_cus.puncReMask",
10003
16
            FT_UINT16, BASE_DEC,
10004
16
            NULL, 0xffc0,
10005
16
            "puncturing pattern RE mask", HFILL}
10006
16
        },
10007
        /* 7.7.20.12 multiSDScope */
10008
16
        { &hf_oran_multiSDScope,
10009
16
          { "multiSDScope", "oran_fh_cus.multiSDScope",
10010
16
            FT_BOOLEAN, 8,
10011
16
            TFS(&multi_sd_scope_tfs), 0x02,
10012
16
            "multiple section description scope flag", HFILL}
10013
16
        },
10014
        /* 7.7.20.4 rbgIncl */
10015
16
        { &hf_oran_RbgIncl,
10016
16
          { "rbgIncl", "oran_fh_cus.rbgIncl",
10017
16
            FT_BOOLEAN, 8,
10018
16
            NULL, 0x01,
10019
16
            "rbg included flag", HFILL}
10020
16
        },
10021
10022
        /* 7.7.21.2 ciPrbGroupSize */
10023
16
        { &hf_oran_ci_prb_group_size,
10024
16
          { "ciPrbGroupSize", "oran_fh_cus.ciPrbGroupSize",
10025
16
            FT_UINT8, BASE_DEC,
10026
16
            NULL, 0x0,
10027
16
            "channel information PRB group size", HFILL}
10028
16
        },
10029
        /* 7.21.3 */
10030
16
        { &hf_oran_prg_size_st5,
10031
16
          { "prgSize", "oran_fh_cus.prgSize",
10032
16
            FT_UINT8, BASE_DEC,
10033
16
            VALS(prg_size_st5_vals), 0x03,
10034
16
            "precoding resource block group size", HFILL}
10035
16
        },
10036
16
        { &hf_oran_prg_size_st6,
10037
16
          { "prgSize", "oran_fh_cus.prgSize",
10038
16
            FT_UINT8, BASE_DEC,
10039
16
            VALS(prg_size_st6_vals), 0x03,
10040
16
            "precoding resource block group size", HFILL}
10041
16
        },
10042
10043
        /* 7.7.17.2 numUeID */
10044
16
        { &hf_oran_num_ueid,
10045
16
          { "numUeID", "oran_fh_cus.numUeID",
10046
16
            FT_UINT8, BASE_DEC,
10047
16
            NULL, 0x0,
10048
16
            "number of ueIDs per user", HFILL}
10049
16
        },
10050
10051
        /* 7.7.16.2 antMask */
10052
16
        { &hf_oran_antMask,
10053
16
          { "antMask", "oran_fh_cus.antMask",
10054
16
            FT_UINT64, BASE_HEX,
10055
16
            NULL, 0xffffffffffffffff,
10056
16
            "indices of antennas to be pre-combined per RX endpoint", HFILL}
10057
16
        },
10058
10059
        /* 7.7.18.2 transmissionWindowOffset */
10060
16
        { &hf_oran_transmissionWindowOffset,
10061
16
          { "transmissionWindowOffset", "oran_fh_cus.transmissionWindowOffset",
10062
16
            FT_UINT16, BASE_DEC,
10063
16
            NULL, 0x0,
10064
16
            "start of the transmission window as an offset to when the transmission window would have been without this parameter, i.e. (Ta3_max - Ta3_min)", HFILL}
10065
16
        },
10066
        /* 7.7.18.3 transmissionWindowSize */
10067
16
        { &hf_oran_transmissionWindowSize,
10068
16
          { "transmissionWindowSize", "oran_fh_cus.transmissionWindowSize",
10069
16
            FT_UINT16, BASE_DEC,
10070
16
            NULL, 0x3fff,
10071
16
            "size of the transmission window in resolution µs", HFILL}
10072
16
        },
10073
        /* 7.7.18.4 toT */
10074
16
        { &hf_oran_toT,
10075
16
          { "toT", "oran_fh_cus.toT",
10076
16
            FT_UINT8, BASE_DEC,
10077
16
            VALS(type_of_transmission_vals), 0x03,
10078
16
            "type of transmission", HFILL}
10079
16
        },
10080
10081
        /* 7.7.2.2 bfaCompHdr */
10082
16
        { &hf_oran_bfaCompHdr,
10083
16
          { "bfaCompHdr", "oran_fh_cus.bfaCompHdr",
10084
16
            FT_STRING, BASE_NONE,
10085
16
            NULL, 0x0,
10086
16
            "beamforming attributes compression header", HFILL}
10087
16
        },
10088
        /* 7.7.2.2-2: bfAzPtWidth */
10089
16
        { &hf_oran_bfAzPtWidth,
10090
16
          { "bfAzPtWidth", "oran_fh_cus.bfAzPtWidth",
10091
16
            FT_UINT8, BASE_DEC,
10092
16
            VALS(bfa_bw_vals), 0x38,
10093
16
            NULL, HFILL}
10094
16
        },
10095
        /* 7.7.2.2-3: bfZePtWidth */
10096
16
        { &hf_oran_bfZePtWidth,
10097
16
          { "bfZePtWidth", "oran_fh_cus.bfZePtWidth",
10098
16
            FT_UINT8, BASE_DEC,
10099
16
            VALS(bfa_bw_vals), 0x07,
10100
16
            NULL, HFILL}
10101
16
        },
10102
        /* 7.7.2.2-4: bfAz3ddWidth */
10103
16
        { &hf_oran_bfAz3ddWidth,
10104
16
          { "bfAz3ddWidth", "oran_fh_cus.bfAz3ddWidth",
10105
16
            FT_UINT8, BASE_DEC,
10106
16
            VALS(bfa_bw_vals), 0x38,
10107
16
            NULL, HFILL}
10108
16
        },
10109
        /* 7.7.2.2-5: bfZe3ddWidth */
10110
16
        { &hf_oran_bfZe3ddWidth,
10111
16
          { "bfZe3ddWidth", "oran_fh_cus.bfZe3ddWidth",
10112
16
            FT_UINT8, BASE_DEC,
10113
16
            VALS(bfa_bw_vals), 0x07,
10114
16
            NULL, HFILL}
10115
16
        },
10116
10117
        /* 7.7.2.3 bfAzPt */
10118
16
        { &hf_oran_bfAzPt,
10119
16
          { "bfAzPt", "oran_fh_cus.bfAzPt",
10120
16
            FT_UINT8, BASE_DEC,
10121
16
            NULL, 0x0,
10122
16
            "beamforming azimuth pointing parameter", HFILL}
10123
16
        },
10124
        /* 7.7.2.4 bfZePt */
10125
16
        { &hf_oran_bfZePt,
10126
16
          { "bfZePt", "oran_fh_cus.bfZePt",
10127
16
            FT_UINT8, BASE_DEC,
10128
16
            NULL, 0x0,
10129
16
            "beamforming zenith pointing parameter", HFILL}
10130
16
        },
10131
        /* 7.7.2.5 bfAz3dd */
10132
16
        { &hf_oran_bfAz3dd,
10133
16
          { "bfAz3dd", "oran_fh_cus.bfAz3dd",
10134
16
            FT_UINT8, BASE_DEC,
10135
16
            NULL, 0x0,
10136
16
            "beamforming azimuth beamwidth parameter", HFILL}
10137
16
        },
10138
        /* 7.7.2.6 bfZe3dd */
10139
16
        { &hf_oran_bfZe3dd,
10140
16
          { "bfZe3dd", "oran_fh_cus.bfZe3dd",
10141
16
            FT_UINT8, BASE_DEC,
10142
16
            NULL, 0x0,
10143
16
            "beamforming zenith beamwidth parameter", HFILL}
10144
16
        },
10145
10146
        /* 7.7.2.7 bfAzSl */
10147
16
        { &hf_oran_bfAzSl,
10148
16
          { "bfAzSl", "oran_fh_cus.bfAzSl",
10149
16
            FT_UINT8, BASE_DEC,
10150
16
            VALS(sidelobe_suppression_vals), 0x38,
10151
16
            "beamforming azimuth sidelobe parameter", HFILL}
10152
16
        },
10153
        /* 7.7.2.8 bfZeSl */
10154
16
        { &hf_oran_bfZeSl,
10155
16
          { "bfZeSl", "oran_fh_cus.bfZeSl",
10156
16
            FT_UINT8, BASE_DEC,
10157
16
            VALS(sidelobe_suppression_vals), 0x07,
10158
16
            "beamforming zenith sidelobe parameter", HFILL}
10159
16
        },
10160
10161
        /* 7.5.2.17 */
10162
16
        { &hf_oran_cmd_scope,
10163
16
          { "cmdScope", "oran_fh_cus.cmdScope",
10164
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
10165
16
            RVALS(cmd_scope_vals), 0x0f,
10166
16
            "command scope", HFILL}
10167
16
        },
10168
        /* 7.5.2.18 */
10169
16
        { &hf_oran_number_of_st4_cmds,
10170
16
          { "numberOfST4Cmds", "oran_fh_cus.numberOfST4Cmds",
10171
16
            FT_UINT8, BASE_DEC,
10172
16
            NULL, 0x0,
10173
16
            "Number of Section Type 4 commands", HFILL}
10174
16
        },
10175
10176
16
        { &hf_oran_st4_cmd_header,
10177
16
          { "Command common header", "oran_fh_cus.st4CmdCommonHeader",
10178
16
            FT_STRING, BASE_NONE,
10179
16
            NULL, 0x0,
10180
16
            NULL, HFILL}
10181
16
        },
10182
10183
        /* 7.5.3.38 */
10184
16
        { &hf_oran_st4_cmd_type,
10185
16
          { "st4CmdType", "oran_fh_cus.st4CmdType",
10186
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
10187
16
            RVALS(st4_cmd_type_vals), 0x0,
10188
16
            NULL, HFILL}
10189
16
        },
10190
        /* 7.5.3.39 */
10191
16
        { &hf_oran_st4_cmd_len,
10192
16
          { "st4CmdLen", "oran_fh_cus.st4CmdLen",
10193
16
            FT_UINT16, BASE_DEC,
10194
16
            NULL, 0x0,
10195
16
            "Length of command in 32-bit words", HFILL}
10196
16
        },
10197
        /* 7.5.3.40 */
10198
16
        { &hf_oran_st4_cmd_num_slots,
10199
16
          { "numSlots", "oran_fh_cus.st4NumSlots",
10200
16
            FT_UINT8, BASE_DEC,
10201
16
            NULL, 0x0,
10202
16
            "Contiguous slots for which command is applicable", HFILL}
10203
16
        },
10204
        /* 7.5.3.41 */
10205
16
        { &hf_oran_st4_cmd_ack_nack_req_id,
10206
16
          { "ackNackReqId", "oran_fh_cus.ackNackReqId",
10207
16
            FT_UINT16, BASE_DEC,
10208
16
            NULL, 0x0,
10209
16
            "ACK/NACK Request Id", HFILL}
10210
16
        },
10211
10212
16
        { &hf_oran_st4_cmd,
10213
16
          { "Command", "oran_fh_cus.st4Cmd",
10214
16
            FT_STRING, BASE_NONE,
10215
16
            NULL, 0x0,
10216
16
            NULL, HFILL}
10217
16
        },
10218
10219
        /* 7.5.3.52 */
10220
16
        { &hf_oran_sleepmode_trx,
10221
16
          { "sleepMode", "oran_fh_cus.sleepMode",
10222
16
            FT_UINT8, BASE_HEX,
10223
16
            VALS(sleep_mode_trx_vals), 0x03,
10224
16
            NULL, HFILL}
10225
16
        },
10226
16
        { &hf_oran_sleepmode_asm,
10227
16
          { "sleepMode", "oran_fh_cus.sleepMode",
10228
16
            FT_UINT8, BASE_HEX,
10229
16
            VALS(sleep_mode_asm_vals), 0x03,
10230
16
            NULL, HFILL}
10231
16
        },
10232
10233
        /* 7.5.3.51 */
10234
16
        { &hf_oran_log2maskbits,
10235
16
          { "log2MaskBits", "oran_fh_cus.log2MaskBits",
10236
16
            FT_UINT8, BASE_HEX,
10237
16
            VALS(log2maskbits_vals), 0x3c,
10238
16
            "Number of bits to appear in antMask", HFILL}
10239
16
        },
10240
        /* 7.5.3.53 */
10241
16
        { &hf_oran_num_slots_ext,
10242
16
          { "numSlotsExt", "oran_fh_cus.numSlotsExt",
10243
16
            FT_UINT24, BASE_HEX,
10244
16
            NULL, 0x0fffff,
10245
16
            NULL, HFILL}
10246
16
        },
10247
        /* 7.5.3.54 */
10248
16
        { &hf_oran_antMask_trx_control,
10249
16
          { "antMask", "oran_fh_cus.trxControl.antMask",
10250
16
            FT_BYTES, BASE_NONE,
10251
16
            NULL, 0x0,
10252
16
            "which antennas should sleep or wake-up", HFILL}
10253
16
        },
10254
        /* 7.5.3.55 */
10255
16
        { &hf_oran_ready,
10256
16
          { "ready", "oran_fh_cus.ready",
10257
16
            FT_BOOLEAN, 8,
10258
16
            TFS(&ready_tfs), 0x01,
10259
16
            "wake-up ready indicator", HFILL}
10260
16
        },
10261
        /* 7.5.3.34 */
10262
16
        { &hf_oran_number_of_acks,
10263
16
          { "numberOfAcks", "oran_fh_cus.numberOfAcks",
10264
16
            FT_UINT8, BASE_DEC,
10265
16
            NULL, 0x0,
10266
16
            "number of ACKs for one eAxC_ID", HFILL}
10267
16
        },
10268
        /* 7.5.3.35 */
10269
16
        { &hf_oran_number_of_nacks,
10270
16
          { "numberOfNacks", "oran_fh_cus.numberOfNacks",
10271
16
            FT_UINT8, BASE_DEC,
10272
16
            NULL, 0x0,
10273
16
            "number of NACKs for one eAxC_ID", HFILL}
10274
16
        },
10275
        /* 7.5.3.36 */
10276
16
        { &hf_oran_ackid,
10277
16
          { "ackId", "oran_fh_cus.ackId",
10278
16
            FT_UINT16, BASE_DEC,
10279
16
            NULL, 0x0,
10280
16
            NULL, HFILL}
10281
16
        },
10282
        /* 7.5.3.37 */
10283
16
        { &hf_oran_nackid,
10284
16
          { "nackId", "oran_fh_cus.nackId",
10285
16
            FT_UINT16, BASE_DEC,
10286
16
            NULL, 0x0,
10287
16
            NULL, HFILL}
10288
16
        },
10289
10290
        /* Links between acknack requests & responses */
10291
16
        { &hf_oran_acknack_request_frame,
10292
16
          { "Request Frame", "oran_fh_cus.ackNackId.request-frame",
10293
16
            FT_FRAMENUM, BASE_NONE,
10294
16
            FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
10295
16
            NULL, HFILL}
10296
16
        },
10297
16
        { &hf_oran_acknack_request_time,
10298
16
          { "Time since request in ms", "oran_fh_cus.ackNackId.time-since-request",
10299
16
            FT_UINT32, BASE_DEC,
10300
16
            NULL, 0x0,
10301
16
            "Time between request and response", HFILL}
10302
16
        },
10303
16
        { &hf_oran_acknack_request_type,
10304
16
          { "Request Type", "oran_fh_cus.ackNackId.request-type",
10305
16
            FT_UINT32, BASE_DEC,
10306
16
            VALS(acknack_type_vals), 0x0,
10307
16
            NULL, HFILL}
10308
16
        },
10309
16
        { &hf_oran_acknack_response_frame,
10310
16
          { "Response Frame", "oran_fh_cus.ackNackId.response-frame",
10311
16
            FT_FRAMENUM, BASE_NONE,
10312
16
            FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
10313
16
            NULL, HFILL}
10314
16
        },
10315
16
        { &hf_oran_acknack_response_time,
10316
16
          { "Time to response in ms", "oran_fh_cus.ackNackId.time-to-response",
10317
16
            FT_UINT32, BASE_DEC,
10318
16
            NULL, 0x0,
10319
16
            "Time between request and response", HFILL}
10320
16
        },
10321
10322
        /* 7.5.3.43 */
10323
16
        { &hf_oran_disable_tdbfns,
10324
16
          { "disableTDBFNs", "oran_fh_cus.disableTDBFNs",
10325
16
            FT_BOOLEAN, 8,
10326
16
            TFS(&disable_tdbfns_tfs), 0x80,
10327
16
            NULL, HFILL}
10328
16
        },
10329
10330
        /* 7.5.3.44 */
10331
16
        { &hf_oran_td_beam_group,
10332
16
          { "tdBeamGrp", "oran_fh_cus.tdBeamGrp",
10333
16
            FT_UINT16, BASE_HEX,
10334
16
            NULL, 0x7fff,
10335
16
            "Applies to symbolMask in command header", HFILL}
10336
16
        },
10337
        /* 7.5.3.43 */
10338
16
        { &hf_oran_disable_tdbfws,
10339
16
          { "disableTDBFWs", "oran_fh_cus.disableTDBFWs",
10340
16
            FT_BOOLEAN, 8,
10341
16
            TFS(&beam_numbers_included_tfs), 0x80,
10342
16
            NULL, HFILL}
10343
16
        },
10344
10345
        /* 7.5.3.56 */
10346
16
        { &hf_oran_td_beam_num,
10347
16
          { "tdBeamNum", "oran_fh_cus.tdBeamNum",
10348
16
            FT_UINT16, BASE_HEX,
10349
16
            NULL, 0x7fff,
10350
16
            "time-domain beam number", HFILL}
10351
16
        },
10352
10353
        /* 7.5.3.49 */
10354
16
        { &hf_oran_dir_pattern,
10355
16
          { "dirPattern", "oran_fh_cus.dirPattern",
10356
16
            FT_BOOLEAN, 16,
10357
16
            TFS(&symbol_direction_tfs), 0x3fff,
10358
16
            "symbol data direction (gNB Tx/Rx) pattern", HFILL}
10359
16
        },
10360
        /* 7.5.3.50 */
10361
16
        { &hf_oran_guard_pattern,
10362
16
          { "guardPattern", "oran_fh_cus.guardPattern",
10363
16
            FT_BOOLEAN, 16,
10364
16
            TFS(&symbol_guard_tfs), 0x3fff,
10365
16
            "guard pattern bitmask", HFILL}
10366
16
        },
10367
10368
        /* For convenient filtering */
10369
16
        { &hf_oran_cplane,
10370
16
          { "C-Plane", "oran_fh_cus.c-plane",
10371
16
            FT_NONE, BASE_NONE,
10372
16
            NULL, 0x0,
10373
16
            NULL, HFILL}
10374
16
        },
10375
16
        { &hf_oran_uplane,
10376
16
          { "U-Plane", "oran_fh_cus.u-plane",
10377
16
            FT_NONE, BASE_NONE,
10378
16
            NULL, 0x0,
10379
16
            NULL, HFILL}
10380
16
        },
10381
16
        { &hf_oran_bf,
10382
16
          { "BeamForming", "oran_fh_cus.bf",
10383
16
            FT_NONE, BASE_NONE,
10384
16
            NULL, 0x0,
10385
16
            NULL, HFILL}
10386
16
        },
10387
16
        { &hf_oran_zero_prb,
10388
16
          { "Zero PRB", "oran_fh_cus.zero-prb",
10389
16
            FT_NONE, BASE_NONE,
10390
16
            NULL, 0x0,
10391
16
            "All of the REs in this PRB are zero", HFILL}
10392
16
        },
10393
16
        { &hf_oran_nonzero_prb,
10394
16
          { "Non-Zero PRB", "oran_fh_cus.nonzero-prb",
10395
16
            FT_NONE, BASE_NONE,
10396
16
            NULL, 0x0,
10397
16
            "Not all of the REs in this PRB are zero", HFILL}
10398
16
        },
10399
16
        { &hf_oran_bundle_weights_all_zero,
10400
16
          { "Bundle Weights all zero", "oran_fh_cus.zero-bundle",
10401
16
            FT_NONE, BASE_NONE,
10402
16
            NULL, 0x0,
10403
16
            "All of the weights in a bundle are zero", HFILL}
10404
16
        },
10405
10406
10407
        /* 5.1.3.2.7 */
10408
16
        { &hf_oran_ecpri_pcid,
10409
16
          { "ecpriPcid", "oran_fh_cus.ecpriPcid",
10410
16
            FT_NONE, BASE_NONE,
10411
16
            NULL, 0x0,
10412
16
            "IQ data transfer message series identifier", HFILL}
10413
16
        },
10414
16
        { &hf_oran_ecpri_rtcid,
10415
16
          { "ecpriRtcid", "oran_fh_cus.ecpriRtcid",
10416
16
            FT_NONE, BASE_NONE,
10417
16
            NULL, 0x0,
10418
16
            "Real time control data identifier", HFILL}
10419
16
        },
10420
        /* 5.1.3.2.8 */
10421
16
        { &hf_oran_ecpri_seqid,
10422
16
          { "ecpriSeqid", "oran_fh_cus.ecpriSeqid",
10423
16
            FT_NONE, BASE_NONE,
10424
16
            NULL, 0x0,
10425
16
            "message identifier", HFILL}
10426
16
        },
10427
10428
        /* 7.7.23.2 */
10429
16
        { &hf_oran_num_sym_prb_pattern,
10430
16
          { "numSymPrbPattern", "oran_fh_cus.numSymPrbPattern",
10431
16
            FT_UINT8, BASE_DEC,
10432
16
            NULL, 0xf0,
10433
16
            "number of symbol and resource block patterns", HFILL}
10434
16
        },
10435
        /* 7.7.23.9 */
10436
16
        { &hf_oran_prb_mode,
10437
16
          { "prbMode", "oran_fh_cus.prbMode",
10438
16
            FT_BOOLEAN, 8,
10439
16
            TFS(&prb_mode_tfs), 0x01,
10440
16
            "PRB Mode", HFILL}
10441
16
        },
10442
        /* 7.7.23.4 */
10443
16
        { &hf_oran_sym_prb_pattern,
10444
16
          { "symPrbPattern", "oran_fh_cus.symPrbPattern",
10445
16
            FT_STRING, BASE_NONE,
10446
16
            NULL, 0x0,
10447
16
            NULL, HFILL}
10448
16
        },
10449
        /* 7.7.23.3 */
10450
16
        { &hf_oran_sym_mask,
10451
16
          { "symMask", "oran_fh_cus.symMask",
10452
16
            FT_UINT16, BASE_HEX,
10453
16
            NULL, 0x3fff,
10454
16
            "symbol mask part of symPrbPattern", HFILL}
10455
16
        },
10456
        /* 7.7.23.5 */
10457
16
        {&hf_oran_num_mc_scale_offset,
10458
16
         {"numMcScaleOffset", "oran_fh_cus.numMcScaleOffset",
10459
16
          FT_UINT8, BASE_DEC,
10460
16
          NULL, 0xf0,
10461
16
          "number of modulation compression scaling value per symPrbPattern",
10462
16
          HFILL}
10463
16
        },
10464
        /* 7.7.23.4 */
10465
16
        { &hf_oran_prb_pattern,
10466
16
          { "prbPattern", "oran_fh_cus.prbPattern",
10467
16
            FT_UINT8, BASE_DEC,
10468
16
            NULL, 0x0f,
10469
16
            "size of one PRB block of one SymPrbPattern", HFILL}
10470
16
        },
10471
        /* 7.7.23.10 */
10472
16
        { &hf_oran_prb_blk_offset,
10473
16
          { "prbBlkOffset", "oran_fh_cus.prbBlkOffset",
10474
16
            FT_UINT16, BASE_DEC,
10475
16
            NULL, 0x0ff0,
10476
16
            "offset to start of PRB block", HFILL}
10477
16
        },
10478
10479
        /* 7.7.23.11 */
10480
16
        { &hf_oran_prb_blk_size,
10481
16
          { "prbBlkSize", "oran_fh_cus.prbBlkSize",
10482
16
            FT_UINT16, BASE_DEC,
10483
16
            NULL, 0x0ff0,
10484
16
            "size of one PRB block of one SymPrbPattern", HFILL}
10485
16
        },
10486
10487
        /* 7.7.3.2 */
10488
16
        { &hf_oran_codebook_index,
10489
16
          { "codebookIndex", "oran_fh_cus.codebookIndex",
10490
16
            FT_UINT8, BASE_DEC,
10491
16
            NULL, 0x0,
10492
16
            "precoder codebook used for transmission", HFILL}
10493
16
        },
10494
        /* 7.7.3.3 */
10495
16
        { &hf_oran_layerid,
10496
16
          { "layerID", "oran_fh_cus.layerID",
10497
16
            FT_UINT8, BASE_DEC,
10498
16
            NULL, 0xf0,
10499
16
            "Layer ID for DL transmission", HFILL}
10500
16
        },
10501
        /* 7.7.3.5 */
10502
16
        { &hf_oran_numlayers,
10503
16
          { "numLayers", "oran_fh_cus.numLayers",
10504
16
            FT_UINT8, BASE_DEC,
10505
16
            NULL, 0x0f,
10506
16
            "number of layers for DL transmission", HFILL}
10507
16
        },
10508
        /* 7.7.3.4 */
10509
16
        { &hf_oran_txscheme,
10510
16
          { "txScheme", "oran_fh_cus.txScheme",
10511
16
            FT_UINT8, BASE_DEC,
10512
16
            NULL, 0xf0,
10513
16
            "transmission scheme", HFILL}
10514
16
        },
10515
        /* 7.7.3.6 */
10516
16
        { &hf_oran_crs_remask,
10517
16
          { "crsReMask", "oran_fh_cus.crsReMask",
10518
16
            FT_UINT16, BASE_HEX,
10519
16
            NULL, 0x0fff,
10520
16
            "CRS resource element mask", HFILL}
10521
16
        },
10522
        /* 7.7.3.8 */
10523
16
        { &hf_oran_crs_shift,
10524
16
          { "crsShift", "oran_fh_cus.crsShift",
10525
16
            FT_UINT8, BASE_HEX,
10526
16
            NULL, 0x80,
10527
16
            "CRS resource element mask", HFILL}
10528
16
        },
10529
        /* 7.7.3.7 */
10530
16
        { &hf_oran_crs_symnum,
10531
16
          { "crsSymNum", "oran_fh_cus.crsSymNum",
10532
16
            FT_UINT8, BASE_DEC,
10533
16
            NULL, 0x0f,
10534
16
            "CRS symbol number indication", HFILL}
10535
16
        },
10536
        /* 7.7.3.9 */
10537
16
        { &hf_oran_beamid_ap1,
10538
16
          { "beamIdAP1", "oran_fh_cus.beamIdAP1",
10539
16
            FT_UINT16, BASE_DEC,
10540
16
            NULL, 0x7f,
10541
16
            "beam id to be used for antenna port 1", HFILL}
10542
16
        },
10543
        /* 7.7.3.10 */
10544
16
        { &hf_oran_beamid_ap2,
10545
16
          { "beamIdAP2", "oran_fh_cus.beamIdAP2",
10546
16
            FT_UINT16, BASE_DEC,
10547
16
            NULL, 0x7f,
10548
16
            "beam id to be used for antenna port 2", HFILL}
10549
16
        },
10550
        /* 7.7.3.11 */
10551
16
        { &hf_oran_beamid_ap3,
10552
16
          { "beamIdAP3", "oran_fh_cus.beamIdAP3",
10553
16
            FT_UINT16, BASE_DEC,
10554
16
            NULL, 0x7f,
10555
16
            "beam id to be used for antenna port 3", HFILL}
10556
16
        },
10557
10558
        /* 7.7.10.3a */
10559
16
        { &hf_oran_port_list_index,
10560
16
          { "portListIndex", "oran_fh_cus.portListIndex",
10561
16
            FT_UINT8, BASE_DEC,
10562
16
            NULL, 0x0,
10563
16
            "the index of an eAxC_ID in the port-list", HFILL}
10564
16
        },
10565
10566
16
        { &hf_oran_alpn_per_sym,
10567
16
          { "alpnPerSym", "oran_fh_cus.alpnPerSym",
10568
16
            FT_UINT8, BASE_HEX,
10569
16
            VALS(alpn_per_sym_vals), 0x80,
10570
16
            NULL, HFILL}
10571
16
        },
10572
16
        { &hf_oran_ant_dmrs_snr,
10573
16
          { "antDmrsSnr", "oran_fh_cus.antDmrsSnr",
10574
16
            FT_UINT8, BASE_HEX,
10575
16
            VALS(ant_dmrs_snr_vals), 0x40,
10576
16
            NULL, HFILL}
10577
16
        },
10578
10579
        /* 7.7.24.6 */
10580
16
        { &hf_oran_user_group_size,
10581
16
          { "userGroupSize", "oran_fh_cus.userGroupSize",
10582
16
            FT_UINT8, BASE_DEC,
10583
16
            NULL, 0x1f,
10584
16
            "number of UE data layers in the user group identified by userGroupId", HFILL}
10585
16
        },
10586
        /* 7.7.24.7 */
10587
16
        { &hf_oran_user_group_id,
10588
16
          { "userGroupId", "oran_fh_cus.userGroupId",
10589
16
            FT_UINT8, BASE_DEC,
10590
16
            NULL, 0x0,
10591
16
            "indicates user group described by the section", HFILL}
10592
16
        },
10593
        /* 7.7.24.8 */
10594
16
        { &hf_oran_entry_type,
10595
16
          { "entryType", "oran_fh_cus.entryType",
10596
16
            FT_UINT8, BASE_DEC,
10597
16
            VALS(entry_type_vals), 0xe0,
10598
16
            "indicates format of the entry", HFILL}
10599
16
        },
10600
        /* 7.7.24.9 */
10601
16
        { &hf_oran_dmrs_port_number,
10602
16
          { "dmrsPortNumber", "oran_fh_cus.dmrsPortNumber",
10603
16
            FT_UINT8, BASE_DEC,
10604
16
            NULL, 0x1f,
10605
16
            "DMRS antenna port number for the associated ueId", HFILL}
10606
16
        },
10607
        /* 7.7.24.10 */
10608
16
        { &hf_oran_ueid_reset,
10609
16
          { "ueidReset", "oran_fh_cus.ueidReset",
10610
16
            FT_BOOLEAN, 8,
10611
16
            TFS(&tfs_ueid_reset), 0x80,
10612
16
            "same UEID as the previous slot", HFILL}
10613
16
        },
10614
        /* 7.7.24.11 */
10615
16
        { &hf_oran_dmrs_symbol_mask,
10616
16
          { "dmrsSymbolMask", "oran_fh_cus.dmrsSymbolMask",
10617
16
            FT_UINT16, BASE_HEX,
10618
16
            NULL, 0x3fff,
10619
16
            "symbols within the slot containing DMRS", HFILL}
10620
16
        },
10621
16
        { &hf_oran_dmrs_symbol_mask_s13,
10622
16
          { "symbol 13", "oran_fh_cus.dmrsSymbolMask.symbol-13",
10623
16
            FT_BOOLEAN, 16,
10624
16
            TFS(&tfs_present_not_present), 0x2000,
10625
16
            NULL, HFILL}
10626
16
        },
10627
16
        { &hf_oran_dmrs_symbol_mask_s12,
10628
16
          { "symbol 12", "oran_fh_cus.dmrsSymbolMask.symbol-12",
10629
16
            FT_BOOLEAN, 16,
10630
16
            TFS(&tfs_present_not_present), 0x1000,
10631
16
            NULL, HFILL}
10632
16
        },
10633
16
        { &hf_oran_dmrs_symbol_mask_s11,
10634
16
          { "symbol 11", "oran_fh_cus.dmrsSymbolMask.symbol-11",
10635
16
            FT_BOOLEAN, 16,
10636
16
            TFS(&tfs_present_not_present), 0x0800,
10637
16
            NULL, HFILL}
10638
16
        },
10639
16
        { &hf_oran_dmrs_symbol_mask_s10,
10640
16
          { "symbol 10", "oran_fh_cus.dmrsSymbolMask.symbol-10",
10641
16
            FT_BOOLEAN, 16,
10642
16
            TFS(&tfs_present_not_present), 0x0400,
10643
16
            NULL, HFILL}
10644
16
        },
10645
16
        { &hf_oran_dmrs_symbol_mask_s9,
10646
16
          { "symbol  9", "oran_fh_cus.dmrsSymbolMask.symbol-9",
10647
16
            FT_BOOLEAN, 16,
10648
16
            TFS(&tfs_present_not_present), 0x0200,
10649
16
            NULL, HFILL}
10650
16
        },
10651
16
        { &hf_oran_dmrs_symbol_mask_s8,
10652
16
          { "symbol  8", "oran_fh_cus.dmrsSymbolMask.symbol-8",
10653
16
            FT_BOOLEAN, 16,
10654
16
            TFS(&tfs_present_not_present), 0x0100,
10655
16
            NULL, HFILL}
10656
16
        },
10657
16
        { &hf_oran_dmrs_symbol_mask_s7,
10658
16
          { "symbol  7", "oran_fh_cus.dmrsSymbolMask.symbol-7",
10659
16
            FT_BOOLEAN, 16,
10660
16
            TFS(&tfs_present_not_present), 0x0080,
10661
16
            NULL, HFILL}
10662
16
        },
10663
16
        { &hf_oran_dmrs_symbol_mask_s6,
10664
16
          { "symbol  6", "oran_fh_cus.dmrsSymbolMask.symbol-6",
10665
16
            FT_BOOLEAN, 16,
10666
16
            TFS(&tfs_present_not_present), 0x0040,
10667
16
            NULL, HFILL}
10668
16
        },
10669
16
        { &hf_oran_dmrs_symbol_mask_s5,
10670
16
          { "symbol  5", "oran_fh_cus.dmrsSymbolMask.symbol-5",
10671
16
            FT_BOOLEAN, 16,
10672
16
            TFS(&tfs_present_not_present), 0x0020,
10673
16
            NULL, HFILL}
10674
16
        },
10675
16
        { &hf_oran_dmrs_symbol_mask_s4,
10676
16
          { "symbol  4", "oran_fh_cus.dmrsSymbolMask.symbol-4",
10677
16
            FT_BOOLEAN, 16,
10678
16
            TFS(&tfs_present_not_present), 0x0010,
10679
16
            NULL, HFILL}
10680
16
        },
10681
16
        { &hf_oran_dmrs_symbol_mask_s3,
10682
16
          { "symbol  3", "oran_fh_cus.dmrsSymbolMask.symbol-3",
10683
16
            FT_BOOLEAN, 16,
10684
16
            TFS(&tfs_present_not_present), 0x0008,
10685
16
            NULL, HFILL}
10686
16
        },
10687
16
        { &hf_oran_dmrs_symbol_mask_s2,
10688
16
          { "symbol  2", "oran_fh_cus.dmrsSymbolMask.symbol-2",
10689
16
            FT_BOOLEAN, 16,
10690
16
            TFS(&tfs_present_not_present), 0x0004,
10691
16
            NULL, HFILL}
10692
16
        },
10693
16
        { &hf_oran_dmrs_symbol_mask_s1,
10694
16
          { "symbol  1", "oran_fh_cus.dmrsSymbolMask.symbol-1",
10695
16
            FT_BOOLEAN, 16,
10696
16
            TFS(&tfs_present_not_present), 0x0002,
10697
16
            NULL, HFILL}
10698
16
        },
10699
16
        { &hf_oran_dmrs_symbol_mask_s0,
10700
16
          { "symbol  0", "oran_fh_cus.dmrsSymbolMask.symbol-0",
10701
16
            FT_BOOLEAN, 16,
10702
16
            TFS(&tfs_present_not_present), 0x0001,
10703
16
            NULL, HFILL}
10704
16
        },
10705
10706
        /* 7.7.24.12 */
10707
16
        { &hf_oran_scrambling,
10708
16
          { "scrambling", "oran_fh_cus.scrambling",
10709
16
            FT_UINT16, BASE_HEX,
10710
16
            NULL, 0x0,
10711
16
            "used to calculate the seed value required to initialize pseudo-random generator", HFILL}
10712
16
        },
10713
        /* 7.7.24.13 */
10714
16
        { &hf_oran_nscid,
10715
16
          { "nscid", "oran_fh_cus.nscid",
10716
16
            FT_UINT8, BASE_HEX,
10717
16
            NULL, 0x80,
10718
16
            "used to calculate the seed value for pseudo-random generator", HFILL}
10719
16
        },
10720
        /* 7.7.24.14 */
10721
16
        { &hf_oran_dtype,
10722
16
          { "dType", "oran_fh_cus.dType",
10723
16
            FT_UINT8, BASE_HEX,
10724
16
            VALS(dtype_vals), 0x40,
10725
16
            "PUSCH DMRS configuration type", HFILL}
10726
16
        },
10727
        /* 7.7.24.15 */
10728
16
        { &hf_oran_cmd_without_data,
10729
16
          { "cmdWithoutData", "oran_fh_cus.cmdWithoutData",
10730
16
            FT_UINT8, BASE_HEX,
10731
16
            NULL, 0x30,
10732
16
            "number of DMRS CDM groups without data", HFILL}
10733
16
        },
10734
        /* 7.7.24.16 */
10735
16
        { &hf_oran_lambda,
10736
16
          { "lambda", "oran_fh_cus.lambda",
10737
16
            FT_UINT8, BASE_HEX,
10738
16
            NULL, 0x0c,
10739
16
            NULL, HFILL}
10740
16
        },
10741
        /* 7.7.24.19 */
10742
16
        { &hf_oran_first_prb,
10743
16
          { "firstPrb", "oran_fh_cus.firstPrb",
10744
16
            FT_UINT16, BASE_DEC,
10745
16
            NULL, 0x03fe,
10746
16
            NULL, HFILL}
10747
16
        },
10748
        /* 7.7.24.20 */
10749
16
        { &hf_oran_last_prb,
10750
16
          { "lastPrb", "oran_fh_cus.lastPrb",
10751
16
            FT_UINT16, BASE_DEC,
10752
16
            NULL, 0x01ff,
10753
16
            NULL, HFILL}
10754
16
        },
10755
10756
        /* 7.7.24.17 */
10757
        /* TODO: add value_string */
10758
16
        { &hf_oran_low_papr_type,
10759
16
          { "lowPaprType", "oran_fh_cus.lowPaprType",
10760
16
            FT_UINT8, BASE_HEX,
10761
16
            VALS(papr_type_vals), 0x30,
10762
16
            NULL, HFILL}
10763
16
        },
10764
        /* 7.7.24.18 */
10765
16
        { &hf_oran_hopping_mode,
10766
16
          { "hoppingMode", "oran_fh_cus.hoppingMode",
10767
16
            FT_UINT8, BASE_HEX,
10768
16
            VALS(hopping_mode_vals), 0x0c,
10769
16
            NULL, HFILL}
10770
16
        },
10771
10772
16
        { &hf_oran_tx_win_for_on_air_symbol_l,
10773
16
          { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
10774
16
            FT_UINT8, BASE_DEC,
10775
16
            NULL, 0xf0,
10776
16
            NULL, HFILL}
10777
16
        },
10778
16
        { &hf_oran_tx_win_for_on_air_symbol_r,
10779
16
          { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
10780
16
            FT_UINT8, BASE_DEC,
10781
16
            NULL, 0x0f,
10782
16
            NULL, HFILL}
10783
16
        },
10784
        /* 7.7.26.2 */
10785
16
        { &hf_oran_num_fo_fb,
10786
16
          { "numFoFb", "oran_fh_cus.numFoFb",
10787
16
            FT_UINT8, BASE_DEC,
10788
16
            NULL, 0x7f,
10789
16
            "number of frequency offset feedback", HFILL}
10790
16
        },
10791
        /* 7.7.26.3 */
10792
16
        { &hf_oran_freq_offset_fb,
10793
16
          { "freqOffsetFb", "oran_fh_cus.freqOffsetFb",
10794
16
            FT_UINT16, BASE_HEX_DEC | BASE_RANGE_STRING,
10795
16
            RVALS(freq_offset_fb_values), 0x0,
10796
16
            "UE frequency offset feedback", HFILL}
10797
16
        },
10798
10799
        /* 7.7.28.2 */
10800
16
        { &hf_oran_num_ue_sinr_rpt,
10801
16
          { "numUeSinrRpt", "oran_fh_cus.numUeSinrRpt",
10802
16
            FT_UINT8, BASE_DEC,
10803
16
            NULL, 0x1f,
10804
16
            "number of sinr reported UEs {1 - 12}", HFILL}
10805
16
        },
10806
10807
        /* 7.5.2.19 */
10808
16
        { &hf_oran_num_sinr_per_prb,
10809
16
          { "numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
10810
16
            FT_UINT8, BASE_DEC,
10811
16
            VALS(num_sinr_per_prb_vals), 0x70,
10812
16
            "number of SINR values per PRB", HFILL}
10813
16
        },
10814
16
        { &hf_oran_num_sinr_per_prb_right,
10815
16
          { "numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
10816
16
            FT_UINT8, BASE_DEC,
10817
16
            VALS(num_sinr_per_prb_vals), 0x07,
10818
16
            "number of SINR values per PRB", HFILL}
10819
16
        },
10820
10821
        /* 7.5.3.68 */
10822
16
        { &hf_oran_sinr_value,
10823
16
          { "sinrValue", "oran_fh_cus.sinrValue",
10824
16
            FT_FLOAT, BASE_NONE,
10825
16
            NULL, 0x0,
10826
16
            NULL, HFILL}
10827
16
        },
10828
10829
16
        { &hf_oran_measurement_report,
10830
16
          { "Measurement Report", "oran_fh_cus.measurement-report",
10831
16
            FT_STRING, BASE_NONE,
10832
16
            NULL, 0x0,
10833
16
            NULL, HFILL}
10834
16
        },
10835
        /* 7.5.3.57 */
10836
16
        { &hf_oran_mf,
10837
16
          { "mf", "oran_fh_cus.mf",
10838
16
            FT_BOOLEAN, 8,
10839
16
            TFS(&measurement_flag_tfs), 0x80,
10840
16
            "measurement flag", HFILL}
10841
16
        },
10842
        /* 7.5.3.59 */
10843
16
        { &hf_oran_meas_data_size,
10844
16
          { "measDataSize", "oran_fh_cus.measDataSize",
10845
16
            FT_UINT16, BASE_DEC,
10846
16
            NULL, 0x0,
10847
16
            "measurement data size (in words)", HFILL}
10848
16
        },
10849
10850
        /* 7.5.3.58 */
10851
16
        { &hf_oran_meas_type_id,
10852
16
          { "measTypeId", "oran_fh_cus.measTypeId",
10853
16
            FT_UINT8, BASE_DEC,
10854
16
            VALS(meas_type_id_vals), 0x7F,
10855
16
            "measurement report type identifier", HFILL}
10856
16
        },
10857
        /* 7.5.3.66 */
10858
16
        { &hf_oran_num_elements,
10859
16
          { "numElements", "oran_fh_cus.numElements",
10860
16
            FT_UINT8, BASE_DEC,
10861
16
            NULL, 0x0,
10862
16
            "measurement report type identifier", HFILL}
10863
16
        },
10864
        /* 7.5.3.60 */
10865
16
        { &hf_oran_ue_tae,
10866
16
          { "ueTae", "oran_fh_cus.ueTae",
10867
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10868
16
            RVALS(freq_offset_fb_values), 0x0,
10869
16
            "UE Timing Advance Error", HFILL}
10870
16
        },
10871
        /* 7.5.3.61 */
10872
16
        { &hf_oran_ue_layer_power,
10873
16
          { "ueLayerPower", "oran_fh_cus.ueLayerPower",
10874
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10875
16
            RVALS(freq_offset_fb_values), 0x0,
10876
16
            "UE Layer Power", HFILL}
10877
16
        },
10878
10879
        /* 7.5.3.62 */
10880
16
        { &hf_oran_ue_freq_offset,
10881
16
          { "ueFreqOffset", "oran_fh_cus.ueFreqOffset",
10882
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10883
16
            RVALS(freq_offset_fb_values), 0x0,
10884
16
            "UE frequency offset", HFILL}
10885
16
        },
10886
        /* 7.5.3.63 */
10887
16
        { &hf_oran_ipn_power,
10888
16
          { "ipnPower", "oran_fh_cus.ipnPower",
10889
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10890
16
            RVALS(freq_offset_fb_values), 0x0,
10891
16
            "Interference plus Noise power", HFILL}
10892
16
        },
10893
        /* 7.5.3.64 */
10894
16
        { &hf_oran_ant_dmrs_snr_val,
10895
16
          { "antDmrsSnrVal", "oran_fh_cus.antDmrsSnrVal",
10896
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10897
16
            RVALS(freq_offset_fb_values), 0x0,
10898
16
            "antenna DMRS-SNR", HFILL}
10899
16
        },
10900
10901
16
        { &hf_oran_measurement_command,
10902
16
          { "Measurement Command", "oran_fh_cus.measurement-command",
10903
16
            FT_STRING, BASE_NONE,
10904
16
            NULL, 0x0,
10905
16
            NULL, HFILL}
10906
16
        },
10907
10908
        /* 7.5.27.2 */
10909
16
        { &hf_oran_beam_type,
10910
16
         {"beamType", "oran_fh_cus.beamType",
10911
16
          FT_UINT16, BASE_DEC,
10912
16
          VALS(beam_type_vals), 0xc0,
10913
16
          NULL,
10914
16
          HFILL}
10915
16
        },
10916
        /* 7.5.3.65 */
10917
16
        { &hf_oran_meas_cmd_size,
10918
16
         {"measCmdSize", "oran_fh_cus.measCmdSize",
10919
16
          FT_UINT16, BASE_DEC,
10920
16
          NULL, 0x0,
10921
16
          "measurement command size in words",
10922
16
          HFILL}
10923
16
        },
10924
        /* 7.5.3.73 */
10925
16
        { &hf_oran_curr_ue_freq_offset,
10926
16
          { "currUeFreqOffset", "oran_fh_cus.currUeFreqOffset",
10927
16
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
10928
16
            RVALS(freq_offset_fb_values), 0x0,
10929
16
            "Estimated UE frequency offset in current slot (Hz)", HFILL}
10930
16
        },
10931
10932
16
        { &hf_oran_symbol_reordering_layer,
10933
16
          { "Layer", "oran_fh_cus.layer",
10934
16
            FT_STRING, BASE_NONE,
10935
16
            NULL, 0x0,
10936
16
            NULL, HFILL}
10937
16
        },
10938
16
        { &hf_oran_dmrs_entry,
10939
16
          { "Entry", "oran_fh_cus.dmrs-entry",
10940
16
            FT_STRING, BASE_NONE,
10941
16
            NULL, 0x0,
10942
16
            NULL, HFILL}
10943
16
        },
10944
10945
        /* 7.7.29.3 */
10946
16
        { &hf_oran_cd_scg_size,
10947
16
          {"cdScgSize", "oran_fh_cus.cdScgSize",
10948
16
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
10949
16
            RVALS(cd_scg_size_vals), 0x0f,
10950
16
            "Cyclic delay subcarrier group size",
10951
16
            HFILL}
10952
16
        },
10953
        /* 7.7.29.4 */
10954
16
        { &hf_oran_cd_scg_phase_step,
10955
16
          {"cdScgPhaseStep", "oran_fh_cus.cdScgPhaseStep",
10956
16
            FT_INT8, BASE_DEC,
10957
16
            NULL, 0x0,
10958
16
            "Cyclic delay subcarrier group phase step",
10959
16
            HFILL}
10960
16
        },
10961
10962
16
        { &hf_oran_sinr_prb,
10963
16
          { "PRB", "oran_fh_cus.sinr.prb",
10964
16
            FT_STRING, BASE_NONE,
10965
16
            NULL, 0x0,
10966
16
            NULL, HFILL}
10967
16
        },
10968
        /* 7.5.2.20 */
10969
16
        { &hf_oran_oru_control_sinr_slot_mask_id,
10970
16
          {"oruControlSinrSlotMaskId", "oran_fh_cus.oruControlSinrSlotMaskId",
10971
16
            FT_UINT8, BASE_DEC,
10972
16
            NULL, 0x1f,
10973
16
            "SINR time resolution",
10974
16
            HFILL}
10975
16
        },
10976
        /* 7.7.24.21 */
10977
16
        { &hf_oran_pos_meas,
10978
16
          {"posMeas", "oran_fh_cus.posMeas",
10979
16
            FT_BOOLEAN, 8,
10980
16
            TFS(&tfs_report_no_report_pos_meas), 0x40,
10981
16
            "Positioning measurement report request",
10982
16
            HFILL}
10983
16
        },
10984
10985
        /* 7.5.3.69 */
10986
16
        { &hf_oran_ue_radial_speed,
10987
16
          {"ueRadialSpeed", "oran_fh_cus.ueRadialSpeed",
10988
16
            FT_UINT16, BASE_DEC,
10989
16
            NULL, 0x0,
10990
16
            "UE radial speed",
10991
16
            HFILL}
10992
16
        },
10993
        /* 7.5.3.70 */
10994
16
        { &hf_oran_ue_az_aoa,
10995
16
          {"ueAzAoa", "oran_fh_cus.ueAzAoa",
10996
16
            FT_UINT16, BASE_DEC,
10997
16
            NULL, 0x0,
10998
16
            "UE azimuth angle of arrival",
10999
16
            HFILL}
11000
16
        },
11001
        /* 7.5.3.71 */
11002
16
        { &hf_oran_ue_ze_aoa,
11003
16
          {"ueZeAoa", "oran_fh_cus.ueZeAoa",
11004
16
            FT_UINT16, BASE_DEC,
11005
16
            NULL, 0x0,
11006
16
            "UE zenith angle of arrival",
11007
16
            HFILL}
11008
16
        },
11009
        /* 7.5.3.72 */
11010
16
        { &hf_oran_ue_pos_toa_offset,
11011
16
          {"uePosToaOffset", "oran_fh_cus.uePosToaOffset",
11012
16
            FT_UINT16, BASE_DEC,
11013
16
            NULL, 0x0,
11014
16
            "UE positioning time of arrival offset",
11015
16
            HFILL}
11016
16
        },
11017
11018
        /* 7.7.30.2 */
11019
16
        { &hf_oran_num_rep_ue,
11020
16
          {"numRepUe", "oran_fh_cus.numRepUe",
11021
16
            FT_UINT8, BASE_DEC,
11022
16
            NULL, 0x0f,
11023
16
            "Number of UEs with PUSCH repetition",
11024
16
            HFILL}
11025
16
        },
11026
        /* 7.7.30.3 */
11027
16
        { &hf_oran_rep_ueid,
11028
16
          {"repUeId", "oran_fh_cus.repUeId",
11029
16
            FT_UINT16, BASE_DEC,
11030
16
            NULL, 0x7fff,
11031
16
            "UEId the PUSCH is part of",
11032
16
            HFILL}
11033
16
        },
11034
        /* 7.7.30.4 */
11035
16
        { &hf_oran_is_last_rep,
11036
16
          {"isLastRep", "oran_fh_cus.isLastRep",
11037
16
            FT_BOOLEAN, 8,
11038
16
            NULL, 0x40,
11039
16
            "Last transmission in the repetition",
11040
16
            HFILL}
11041
16
        },
11042
        /* 7.7.30.5 */
11043
16
        { &hf_oran_rep_index,
11044
16
          {"repIndex", "oran_fh_cus.repIndex",
11045
16
            FT_UINT8, BASE_DEC,
11046
16
            NULL, 0x3f,
11047
16
            "Repetition index of the PUSCH transmission",
11048
16
            HFILL}
11049
16
        },
11050
        /* 7.7.30.6 */
11051
16
        { &hf_oran_num_reps,
11052
16
          {"numReps", "oran_fh_cus.numReps",
11053
16
            FT_UINT8, BASE_DEC,
11054
16
            NULL, 0x3f,
11055
16
            "The number of total PUSCH repetitions",
11056
16
            HFILL}
11057
16
        },
11058
11059
        /* 7.7.31.2 */
11060
16
        { &hf_oran_mcs_table,
11061
16
          {"mcsTable", "oran_fh_cus.mcsTable",
11062
16
            FT_UINT8, BASE_DEC,
11063
16
            VALS(mcs_table_vals), 0x0f,
11064
16
            "MCS index table",
11065
16
            HFILL}
11066
16
        },
11067
        /* 7.7.31.3 */
11068
16
        { &hf_oran_mcs_index,
11069
16
          {"mcsIndex", "oran_fh_cus.mcsIndex",
11070
16
            FT_UINT8, BASE_DEC,
11071
16
            NULL, 0x3f,
11072
16
            "MCS index value",
11073
16
            HFILL}
11074
16
        },
11075
11076
        /* 7.7.33.3 */
11077
16
        { &hf_oran_num_meas_req,
11078
16
          {"numMeasReq", "oran_fh_cus.numMeasReq",
11079
16
            FT_UINT8, BASE_DEC,
11080
16
            NULL, 0x1f,
11081
16
            "Number of UEs for which meas is requested",
11082
16
            HFILL}
11083
16
        },
11084
        /* 7.7.32.5 */
11085
16
        { &hf_oran_ue_rank,
11086
16
          {"ueRank", "oran_fh_cus.ueRank",
11087
16
            FT_UINT8, BASE_DEC,
11088
16
            VALS(ue_rank_vals), 0x0f,
11089
16
            "Number of UE layers under evaluation",
11090
16
            HFILL}
11091
16
        },
11092
        /* 7.7.32.6 */
11093
16
        { &hf_oran_num_of_ue_ant_ports,
11094
16
          {"numOfUeAntPorts", "oran_fh_cus.numofUeAntPorts",
11095
16
            FT_UINT8, BASE_DEC,
11096
16
            VALS(num_of_ue_ant_ports_vals), 0xf0,
11097
16
            "Used for the PUSCH tx under evaluation",
11098
16
            HFILL}
11099
16
        },
11100
        /* 7.7.32.8 */
11101
16
        { &hf_oran_codebook_subset,
11102
16
          {"codebookSubset", "oran_fh_cus.codebookSubset",
11103
16
            FT_UINT8, BASE_DEC,
11104
16
            VALS(codebook_subset_vals), 0xc0,
11105
16
            "UE capability wrt ULTPMI sets",
11106
16
            HFILL}
11107
16
        },
11108
        /* 7.7.32.9 */
11109
16
        { &hf_oran_full_pwr_mode,
11110
16
          {"fullPwrMode", "oran_fh_cus.fullPwrMode",
11111
16
            FT_UINT8, BASE_DEC,
11112
16
            VALS(full_pwr_mode_vals), 0xc0,
11113
16
            "Transmission mode",
11114
16
            HFILL}
11115
16
        },
11116
        /* 7.7.32.10 */
11117
16
        { &hf_oran_full_pwr_mode_2_tpmi_group,
11118
16
          {"fullPwrMode2TpmiGroup", "oran_fh_cus.fullPwrMode2TpmiGroup",
11119
16
            FT_UINT16, BASE_HEX,
11120
16
            NULL, 0x3fff,
11121
16
            "Capabilities",
11122
16
            HFILL}
11123
16
        },
11124
11125
        /* 7.5.3.75 */
11126
16
        { &hf_oran_num_cand_ranks,
11127
16
          {"numCandRanks", "oran_fh_cus.numCandRanks",
11128
16
            FT_UINT8, BASE_DEC,
11129
16
            NULL, 0xf0,
11130
16
            NULL,
11131
16
            HFILL}
11132
16
        },
11133
        /* 7.5.3.76 */
11134
16
        { &hf_oran_ue_pref_rank,
11135
16
          {"uePrefRank", "oran_fh_cus.uePrefRank",
11136
16
            FT_UINT8, BASE_DEC,
11137
16
            NULL, 0x0f,
11138
16
            "Most optimal UL Tx rank for UE",
11139
16
            HFILL}
11140
16
        },
11141
        /* 7.5.3.77 */
11142
16
        { &hf_oran_ue_tpmi_rank_y,
11143
16
          {"ueTpmiRankY", "oran_fh_cus.ueTpmiRankY",
11144
16
            FT_UINT8, BASE_DEC,
11145
16
            NULL, 0x0,
11146
16
            "TPMI index for codebook-based PUSCH tx",
11147
16
            HFILL}
11148
16
        },
11149
        /* 7.5.3.78 */
11150
16
        { &hf_oran_ue_tpmi_rank_y_sinr_lx,
11151
16
          {"ueTpmiRankYSinrLX", "oran_fh_cus.ueTpmiRankYSinrLX",
11152
16
            FT_UINT16, BASE_HEX | BASE_RANGE_STRING,
11153
16
            RVALS(ue_tmpi_rank_sinr_vals), 0x0,
11154
16
            "Estimation of post-equalization SINR",
11155
16
            HFILL}
11156
16
        },
11157
        /* 7.5.3.79 */
11158
16
        { &hf_oran_ue_layer_pre_eq_sinr,
11159
16
          {"ueLayerPreEqSinr", "oran_fh_cus.ueLayerPreEqSinr",
11160
16
            FT_UINT16, BASE_HEX,
11161
16
            NULL, 0x0,
11162
16
            "Pre-equalization SINR of a UE layer",
11163
16
            HFILL}
11164
16
        },
11165
11166
16
        { &hf_oran_c_section_common,
11167
16
          { "Common Section", "oran_fh_cus.c-plane.section.common",
11168
16
            FT_STRING, BASE_NONE,
11169
16
            NULL, 0x0,
11170
16
            NULL, HFILL}
11171
16
        },
11172
16
        { &hf_oran_c_section,
11173
16
          { "Section", "oran_fh_cus.c-plane.section",
11174
16
            FT_STRING, BASE_NONE,
11175
16
            NULL, 0x0,
11176
16
            NULL, HFILL}
11177
16
        },
11178
16
        { &hf_oran_u_section,
11179
16
          { "Section", "oran_fh_cus.u-plane.section",
11180
16
            FT_STRING, BASE_NONE,
11181
16
            NULL, 0x0,
11182
16
            NULL, HFILL}
11183
16
        },
11184
11185
        /* Link back to UL C-plane where udCompHdr was recorded */
11186
16
        { &hf_oran_ul_cplane_ud_comp_hdr_frame,
11187
16
          { "C-Plane UL udCompHdr frame", "oran_fh_cus.ul-cplane.udCompHdr",
11188
16
            FT_FRAMENUM, BASE_NONE,
11189
16
            FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
11190
16
            NULL, HFILL}
11191
16
        },
11192
11193
        /* For ext11, where was a beamId (last) defined? */
11194
16
        { &hf_oran_bfws_frame_defined,
11195
16
          { "Beam defined in frame", "oran_fh_cus.bfw-defined",
11196
16
            FT_FRAMENUM, BASE_NONE,
11197
16
            FRAMENUM_TYPE(FT_FRAMENUM_RETRANS_PREV), 0x0,
11198
16
            NULL, HFILL}
11199
16
        },
11200
16
        { &hf_oran_bfws_symbols_since_defined,
11201
16
          { "Symbols since BFWs defined", "oran_fh_cus.symbols-since-bfw-defined",
11202
16
            FT_UINT32, BASE_DEC,
11203
16
            NULL, 0x0,
11204
16
            NULL, HFILL}
11205
16
        },
11206
11207
        /* Corresponding C-plane frame for DL U-plane */
11208
16
        { &hf_oran_corresponding_cplane_frame,
11209
16
          { "C-plane frame", "oran_fh_cus.cplane-frame",
11210
16
            FT_FRAMENUM, BASE_NONE,
11211
16
            FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0, NULL, HFILL}
11212
16
        },
11213
        /* Time since corresponding C-plane frame for U-plane */
11214
16
        { &hf_oran_corresponding_cplane_frame_time_delta,
11215
16
          { "Time since C-plane frame", "oran_fh_cus.cplane-frame-time-delta",
11216
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
11217
16
            "Microseconds since C-plane frame", HFILL}
11218
16
        },
11219
        /* Corresponding U-plane frame for C-plane */
11220
16
        { &hf_oran_corresponding_uplane_frame,
11221
16
          { "U-plane frame", "oran_fh_cus.uplane-frame",
11222
16
            FT_FRAMENUM, BASE_NONE,
11223
16
            FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0, NULL, HFILL}
11224
16
        },
11225
16
        { &hf_oran_corresponding_uplane_frames_total,
11226
16
          { "U-plane frames total", "oran_fh_cus.u-plane-frames-total",
11227
16
            FT_UINT32, BASE_DEC, NULL, 0x0,
11228
16
            "Number of corresponding U-plane frames", HFILL}
11229
16
        },
11230
11231
        /* Reassembly */
11232
16
        { &hf_oran_fragment,
11233
16
          { "Fragment", "oran_fh_cus.fragment", FT_FRAMENUM, BASE_NONE,
11234
16
            NULL, 0x0, NULL, HFILL }},
11235
16
        { &hf_oran_fragments,
11236
16
          { "Fragments", "oran_fh_cus.fragments", FT_BYTES, BASE_NONE,
11237
16
            NULL, 0x0, NULL, HFILL }},
11238
16
        { &hf_oran_fragment_overlap,
11239
16
          { "Fragment overlap", "oran_fh_cus.fragment.overlap", FT_BOOLEAN, BASE_NONE,
11240
16
            NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
11241
16
        { &hf_oran_fragment_overlap_conflict,
11242
16
          { "Conflicting data in fragment overlap", "oran_fh_cus.fragment.overlap.conflict",
11243
16
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
11244
16
            "Overlapping fragments contained conflicting data", HFILL }},
11245
16
        { &hf_oran_fragment_multiple_tails,
11246
16
          { "Multiple tail fragments found", "oran_fh_cus.fragment.multipletails",
11247
16
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
11248
16
            "Several tails were found when defragmenting the packet", HFILL }},
11249
16
        { &hf_oran_fragment_too_long_fragment,
11250
16
          { "Fragment too long", "oran_fh_cus.fragment.toolongfragment",
11251
16
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
11252
16
            "Fragment contained data past end of packet", HFILL }},
11253
16
        { &hf_oran_fragment_error,
11254
16
          { "Defragmentation error", "oran_fh_cus.fragment.error", FT_FRAMENUM, BASE_NONE,
11255
16
            NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
11256
16
        { &hf_oran_fragment_count,
11257
16
          { "Fragment count", "oran_fh_cus.fragment.count", FT_UINT32, BASE_DEC,
11258
16
            NULL, 0x0, NULL, HFILL }},
11259
16
        { &hf_oran_reassembled_in,
11260
16
          { "Reassembled payload in frame", "oran_fh_cus.reassembled_in", FT_FRAMENUM, BASE_NONE,
11261
16
          NULL, 0x0, "This payload packet is reassembled in this frame", HFILL }},
11262
16
        { &hf_oran_reassembled_length,
11263
16
          { "Reassembled payload length", "oran_fh_cus.reassembled.length", FT_UINT32, BASE_DEC,
11264
16
            NULL, 0x0, "The total length of the reassembled payload", HFILL }},
11265
16
        { &hf_oran_reassembled_data,
11266
16
          { "Reassembled data", "oran_fh_cus.reassembled.data", FT_BYTES, BASE_NONE,
11267
16
            NULL, 0x0, "The reassembled payload", HFILL }},
11268
11269
16
        { &hf_oran_payload,
11270
16
          { "Payload", "oran_fh_cus.payload", FT_BYTES, BASE_SHOW_ASCII_PRINTABLE,
11271
16
            NULL, 0x0, "Complete or reassembled payload", HFILL }},
11272
16
    };
11273
11274
    /* Setup protocol subtree array */
11275
16
    static int *ett[] = {
11276
16
        &ett_oran,
11277
16
        &ett_oran_ecpri_pcid,
11278
16
        &ett_oran_ecpri_rtcid,
11279
16
        &ett_oran_ecpri_seqid,
11280
16
        &ett_oran_section_type,
11281
16
        &ett_oran_u_timing,
11282
16
        &ett_oran_u_section,
11283
16
        &ett_oran_u_prb,
11284
16
        &ett_oran_section,
11285
16
        &ett_oran_iq,
11286
16
        &ett_oran_bfw_bundle,
11287
16
        &ett_oran_bfw,
11288
16
        &ett_oran_frequency_range,
11289
16
        &ett_oran_prb_cisamples,
11290
16
        &ett_oran_cisample,
11291
16
        &ett_oran_udcomphdr,
11292
16
        &ett_oran_udcompparam,
11293
16
        &ett_oran_cicomphdr,
11294
16
        &ett_oran_cicompparam,
11295
16
        &ett_oran_bfwcomphdr,
11296
16
        &ett_oran_bfwcompparam,
11297
16
        &ett_oran_ext19_port,
11298
16
        &ett_oran_prb_allocation,
11299
16
        &ett_oran_punc_pattern,
11300
16
        &ett_oran_bfacomphdr,
11301
16
        &ett_oran_modcomp_param_set,
11302
16
        &ett_oran_st4_cmd_header,
11303
16
        &ett_oran_st4_cmd,
11304
16
        &ett_oran_sym_prb_pattern,
11305
16
        &ett_oran_measurement_report,
11306
16
        &ett_oran_measurement_command,
11307
16
        &ett_oran_sresmask,
11308
16
        &ett_oran_c_section_common,
11309
16
        &ett_oran_c_section,
11310
16
        &ett_oran_remask,
11311
16
        &ett_oran_mc_scale_remask,
11312
16
        &ett_oran_symbol_reordering_layer,
11313
16
        &ett_oran_dmrs_entry,
11314
16
        &ett_oran_dmrs_symbol_mask,
11315
16
        &ett_oran_symbol_mask,
11316
16
        &ett_oran_active_beamspace_coefficient_mask,
11317
16
        &ett_oran_sinr_prb,
11318
16
        &ett_oran_rbgMask,
11319
11320
16
        &ett_oran_fragment,
11321
16
        &ett_oran_fragments
11322
16
    };
11323
11324
    /* Separate subtree array for extensions.  Used with [ext-1] */
11325
16
    static int *ext_ett[HIGHEST_EXTTYPE];
11326
528
    for (unsigned extno=0; extno<HIGHEST_EXTTYPE; extno++) {
11327
512
        ext_ett[extno] = &ett_oran_c_section_extension[extno];
11328
512
    }
11329
11330
16
    expert_module_t* expert_oran;
11331
11332
16
    static ei_register_info ei[] = {
11333
16
        { &ei_oran_unsupported_bfw_compression_method, { "oran_fh_cus.unsupported_bfw_compression_method", PI_UNDECODED, PI_WARN, "Unsupported BFW Compression Method", EXPFILL }},
11334
16
        { &ei_oran_invalid_sample_bit_width, { "oran_fh_cus.invalid_sample_bit_width", PI_UNDECODED, PI_ERROR, "Unsupported sample bit width", EXPFILL }},
11335
16
        { &ei_oran_reserved_numBundPrb, { "oran_fh_cus.reserved_numBundPrb", PI_MALFORMED, PI_ERROR, "Reserved value 0 for numBundPrb seen - not valid", EXPFILL }},
11336
16
        { &ei_oran_extlen_wrong, { "oran_fh_cus.extlen_wrong", PI_MALFORMED, PI_ERROR, "extlen doesn't match number of dissected bytes", EXPFILL }},
11337
16
        { &ei_oran_invalid_eaxc_bit_width, { "oran_fh_cus.invalid_eaxc_bit_width", PI_UNDECODED, PI_ERROR, "Inconsistent eAxC bit width", EXPFILL }},
11338
16
        { &ei_oran_extlen_zero, { "oran_fh_cus.extlen_zero", PI_MALFORMED, PI_ERROR, "extlen value of 0 is reserved", EXPFILL }},
11339
16
        { &ei_oran_rbg_size_reserved, { "oran_fh_cus.rbg_size_reserved", PI_MALFORMED, PI_ERROR, "rbgSize value of 0 is reserved", EXPFILL }},
11340
16
        { &ei_oran_frame_length, { "oran_fh_cus.frame_length", PI_MALFORMED, PI_ERROR, "there should be 0-3 bytes remaining after PDU in frame", EXPFILL }},
11341
16
        { &ei_oran_numprbc_ext21_zero, { "oran_fh_cus.numprbc_ext21_zero", PI_MALFORMED, PI_ERROR, "numPrbc shall not be set to 0 when ciPrbGroupSize is configured", EXPFILL }},
11342
16
        { &ei_oran_ci_prb_group_size_reserved, { "oran_fh_cus.ci_prb_group_size_reserved", PI_MALFORMED, PI_WARN, "ciPrbGroupSize should be 2-254", EXPFILL }},
11343
16
        { &ei_oran_st8_nackid, { "oran_fh_cus.st8_nackid", PI_SEQUENCE, PI_WARN, "operation for this ackId failed", EXPFILL }},
11344
16
        { &ei_oran_st4_no_cmds, { "oran_fh_cus.st4_nackid", PI_MALFORMED, PI_ERROR, "Not valid for ST4 to carry no commands", EXPFILL }},
11345
16
        { &ei_oran_st4_zero_len_cmd, { "oran_fh_cus.st4_zero_len_cmd", PI_MALFORMED, PI_WARN, "ST4 cmd with length 0 is reserved", EXPFILL }},
11346
16
        { &ei_oran_st4_wrong_len_cmd, { "oran_fh_cus.st4_wrong_len_cmd", PI_MALFORMED, PI_ERROR, "ST4 cmd with length not matching contents", EXPFILL }},
11347
16
        { &ei_oran_st4_unknown_cmd, { "oran_fh_cus.st4_unknown_cmd", PI_MALFORMED, PI_ERROR, "ST4 cmd with unknown command code", EXPFILL }},
11348
16
        { &ei_oran_mcot_out_of_range, { "oran_fh_cus.mcot_out_of_range", PI_MALFORMED, PI_ERROR, "MCOT should be 1-10", EXPFILL }},
11349
16
        { &ei_oran_se10_unknown_beamgrouptype, { "oran_fh_cus.se10_unknown_beamgrouptype", PI_MALFORMED, PI_WARN, "SE10 - unknown BeamGroupType value", EXPFILL }},
11350
16
        { &ei_oran_se10_not_allowed, { "oran_fh_cus.se10_not_allowed", PI_MALFORMED, PI_WARN, "SE10 - type not allowed for sectionType", EXPFILL }},
11351
16
        { &ei_oran_start_symbol_id_not_zero, { "oran_fh_cus.startsymbolid_shall_be_zero", PI_MALFORMED, PI_WARN, "For ST4 commands 3&4, startSymbolId shall be 0", EXPFILL }},
11352
16
        { &ei_oran_trx_control_cmd_scope, { "oran_fh_cus.trx_command.bad_cmdscope", PI_MALFORMED, PI_WARN, "TRX command must have cmdScope of ARRAY-COMMAND", EXPFILL }},
11353
16
        { &ei_oran_unhandled_se, { "oran_fh_cus.se_not_handled", PI_UNDECODED, PI_WARN, "SE not recognised/handled by dissector", EXPFILL }},
11354
16
        { &ei_oran_bad_symbolmask, { "oran_fh_cus.bad_symbol_mask", PI_MALFORMED, PI_WARN, "For non-zero sleepMode, symbolMask must be 0x0 or 0x3ffff", EXPFILL }},
11355
16
        { &ei_oran_numslots_not_zero, { "oran_fh_cus.numslots_not_zero", PI_MALFORMED, PI_WARN, "For ST4 TIME_DOMAIN_BEAM_WEIGHTS, numSlots should be 0", EXPFILL }},
11356
16
        { &ei_oran_version_unsupported, { "oran_fh_cus.version_unsupported", PI_UNDECODED, PI_WARN, "Protocol version unsupported", EXPFILL }},
11357
16
        { &ei_oran_laa_msg_type_unsupported, { "oran_fh_cus.laa_msg_type_unsupported", PI_UNDECODED, PI_WARN, "laaMsgType unsupported", EXPFILL }},
11358
16
        { &ei_oran_se_on_unsupported_st, { "oran_fh_cus.se_on_unsupported_st", PI_MALFORMED, PI_WARN, "Section Extension should not appear on this Section Type", EXPFILL }},
11359
16
        { &ei_oran_cplane_unexpected_sequence_number_ul, { "oran_fh_cus.unexpected_seq_no_cplane.ul", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in C-Plane UL", EXPFILL }},
11360
16
        { &ei_oran_cplane_unexpected_sequence_number_dl, { "oran_fh_cus.unexpected_seq_no_cplane.dl", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in C-Plane DL", EXPFILL }},
11361
16
        { &ei_oran_uplane_unexpected_sequence_number_ul, { "oran_fh_cus.unexpected_seq_no_uplane.ul", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in U-Plane UL", EXPFILL }},
11362
16
        { &ei_oran_uplane_unexpected_sequence_number_dl, { "oran_fh_cus.unexpected_seq_no_uplane.dl", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in U-Plane DL", EXPFILL }},
11363
16
        { &ei_oran_acknack_no_request, { "oran_fh_cus.acknack_no_request", PI_SEQUENCE, PI_WARN, "Have ackNackId response, but no request", EXPFILL }},
11364
16
        { &ei_oran_udpcomphdr_should_be_zero, { "oran_fh_cus.udcomphdr_should_be_zero", PI_MALFORMED, PI_WARN, "C-Plane udCompHdr in DL should be set to 0", EXPFILL }},
11365
16
        { &ei_oran_radio_fragmentation_c_plane, { "oran_fh_cus.radio_fragmentation_c_plane", PI_MALFORMED, PI_ERROR, "Radio fragmentation not allowed in C-PLane", EXPFILL }},
11366
16
        { &ei_oran_lastRbdid_out_of_range, { "oran_fh_cus.lastrbdid_out_of_range", PI_MALFORMED, PI_WARN, "SE 6 has bad rbgSize", EXPFILL }},
11367
16
        { &ei_oran_rbgMask_beyond_last_rbdid, { "oran_fh_cus.rbgmask_beyond_lastrbdid", PI_MALFORMED, PI_WARN, "rbgMask has bits set beyond lastRbgId", EXPFILL }},
11368
16
        { &ei_oran_unexpected_measTypeId, { "oran_fh_cus.unexpected_meastypeid", PI_MALFORMED, PI_WARN, "unexpected measTypeId", EXPFILL }},
11369
16
        { &ei_oran_unsupported_compression_method, { "oran_fh_cus.compression_type_unsupported", PI_UNDECODED, PI_WARN, "Unsupported compression type", EXPFILL }},
11370
16
        { &ei_oran_ud_comp_len_wrong_size, { "oran_fh_cus.ud_comp_len_wrong_size", PI_MALFORMED, PI_WARN, "udCompLen does not match length of U-Plane section", EXPFILL }},
11371
16
        { &ei_oran_sresmask2_not_zero_with_rb, { "oran_fh_cus.sresmask2_not_zero", PI_MALFORMED, PI_WARN, "sReSMask2 should be zero when rb set", EXPFILL }},
11372
16
        { &ei_oran_st6_rb_shall_be_0, { "oran_fh_cus.st6_rb_set", PI_MALFORMED, PI_WARN, "rb should not be set for Section Type 6", EXPFILL }},
11373
16
        { &ei_oran_st9_not_ul, { "oran_fh_cus.st9_not_ul", PI_MALFORMED, PI_WARN, "Section Type 9 should only be sent in uplink direction", EXPFILL }},
11374
16
        { &ei_oran_st10_numsymbol_not_14, { "oran_fh_cus.st10_numsymbol_not_14", PI_MALFORMED, PI_WARN, "numSymbol should be 14 for Section Type 10", EXPFILL }},
11375
16
        { &ei_oran_st10_startsymbolid_not_0, { "oran_fh_cus.st10_startsymbolid_not_0", PI_MALFORMED, PI_WARN, "startSymbolId should be 0 for Section Type 10", EXPFILL }},
11376
16
        { &ei_oran_st10_not_ul, { "oran_fh_cus.st10_not_ul", PI_MALFORMED, PI_WARN, "Section Type 10 should only be sent in uplink direction", EXPFILL }},
11377
16
        { &ei_oran_se24_nothing_to_inherit, { "oran_fh_cus.se24_nothing_to_inherit", PI_MALFORMED, PI_WARN, "SE10 doesn't have type 2 or 3 before trying to inherit", EXPFILL }},
11378
16
        { &ei_oran_num_sinr_per_prb_unknown, { "oran_fh_cus.unexpected_num_sinr_per_prb", PI_MALFORMED, PI_WARN, "invalid numSinrPerPrb value", EXPFILL }},
11379
16
        { &ei_oran_start_symbol_id_bits_ignored, { "oran_fh_cus.start_symbol_id_bits_ignored", PI_MALFORMED, PI_WARN, "some startSymbolId lower bits ignored", EXPFILL }},
11380
16
        { &ei_oran_user_group_id_reserved_value, { "oran_fh_cus.user_group_id.reserved_value", PI_MALFORMED, PI_WARN, "userGroupId value 255 is reserved", EXPFILL }},
11381
16
        { &ei_oran_port_list_index_zero, { "oran_fh_cus.port_list_index.zero", PI_MALFORMED, PI_WARN, "portListIndex should not be zero", EXPFILL }},
11382
16
        { &ei_oran_ul_uplane_symbol_too_long, { "oran_fh_cus.ul_uplane_symbol_tx_too_slow", PI_RECEIVE, PI_WARN, "UL U-Plane Tx took too long for symbol (limit set in preference)", EXPFILL }},
11383
16
        { &ei_oran_reserved_not_zero, { "oran_fh_cus.reserved_not_zero", PI_MALFORMED, PI_WARN, "Reserved field is not zero", EXPFILL }},
11384
16
        { &ei_oran_too_many_symbols, { "oran_fh_cus.too_many_symbols", PI_MALFORMED, PI_ERROR, "Range of symbols in slot exceeds 14", EXPFILL }},
11385
16
        { &ei_oran_se30_not_ul, { "oran_fh_cus.se30_not_ul", PI_MALFORMED, PI_WARN, "SE30 should only be sent in uplink direction", EXPFILL }},
11386
16
        { &ei_oran_se30_unknown_ueid, { "oran_fh_cus.se30_unknown_ue", PI_MALFORMED, PI_WARN, "SE30 UEId not recognised from SE10", EXPFILL }},
11387
16
        { &ei_oran_beamid_bfws_not_found, { "oran_fh_cus.beamid_bfws_not_found", PI_SEQUENCE, PI_WARN, "Have bundle with disableBFWs but no definition found", EXPFILL }},
11388
16
        { &ei_oran_syminc_set_for_uplane, { "oran_fh_cus.syminc_set_for_uplane", PI_MALFORMED, PI_ERROR, "symcInc is prohibited in the U-Plane", EXPFILL }},
11389
16
        { &ei_oran_cplane_entry_not_found, { "oran_fh_cus.cplane_entry_not_found", PI_SEQUENCE, PI_WARN, "C-plane for this U-plane section not found", EXPFILL }},
11390
16
        { &ei_oran_se12_rb_set, { "oran_fh_cus.se12_rb_set", PI_MALFORMED, PI_WARN, "rb should not be set when SE12 is present", EXPFILL }}
11391
16
    };
11392
11393
11394
    /* Register the protocol name and description */
11395
16
    proto_oran = proto_register_protocol("O-RAN Fronthaul CUS", "O-RAN FH CUS", "oran_fh_cus");
11396
11397
    /* Allow dissector to find be found by name. */
11398
16
    register_dissector("oran_fh_cus", dissect_oran, proto_oran);
11399
11400
    /* Register the tap name. */
11401
16
    oran_tap = register_tap("oran-fh-cus");
11402
11403
    /* Required function calls to register the header fields and subtrees */
11404
16
    proto_register_field_array(proto_oran, hf, array_length(hf));
11405
16
    proto_register_subtree_array(ett, array_length(ett));
11406
16
    proto_register_subtree_array(ext_ett, array_length(ext_ett));
11407
11408
16
    expert_oran = expert_register_protocol(proto_oran);
11409
16
    expert_register_field_array(expert_oran, ei, array_length(ei));
11410
11411
11412
    /* Preferences */
11413
16
    module_t * oran_module = prefs_register_protocol(proto_oran, NULL);
11414
11415
    /* Register bit width/compression preferences separately by direction. */
11416
16
    prefs_register_uint_preference(oran_module, "oran.du_port_id_bits", "DU Port ID bits [a]",
11417
16
        "The bit width of DU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_du_port_id_bits);
11418
16
    prefs_register_uint_preference(oran_module, "oran.bandsector_id_bits", "BandSector ID bits [b]",
11419
16
        "The bit width of BandSector ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_bandsector_id_bits);
11420
16
    prefs_register_uint_preference(oran_module, "oran.cc_id_bits", "CC ID bits [c]",
11421
16
        "The bit width of CC ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_cc_id_bits);
11422
16
    prefs_register_uint_preference(oran_module, "oran.ru_port_id_bits", "RU Port ID bits [d]",
11423
16
        "The bit width of RU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_ru_port_id_bits);
11424
11425
    /* Uplink userplane */
11426
16
    prefs_register_static_text_preference(oran_module, "oran.ul", "", "");
11427
16
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_up", "IQ Bitwidth Uplink",
11428
16
        "The bit width of a sample in the Uplink (if no udcompHdr and no C-Plane)", 10, &pref_sample_bit_width_uplink);
11429
16
    prefs_register_enum_preference(oran_module, "oran.ud_comp_up", "Uplink User Data Compression",
11430
16
        "Uplink User Data Compression (if no udcompHdr and no C-Plane)", &pref_iqCompressionUplink, ul_compression_options, false);
11431
16
    prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_up", "udCompHdr field is present for uplink",
11432
16
        "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
11433
16
        "configuration of the O-RU. This preference instructs the dissector to expect "
11434
16
        "this field to be present in uplink messages",
11435
16
        &pref_includeUdCompHeaderUplink, udcomphdr_present_options, false);
11436
16
    prefs_register_bool_preference(oran_module, "oran.ignore_cplane_ul_udcomphdr", "Ignore UL compression settings from C-plane",
11437
16
        "When set, override udCompHdr from UL C-Plane with compression method and width configured here", &pref_override_ul_compression);
11438
16
    prefs_register_uint_preference(oran_module, "oran.ul_slot_us_limit", "Microseconds allowed for UL tx in symbol",
11439
16
        "Maximum number of microseconds allowed for UL slot transmission before expert warning (zero to disable).  N.B. timing relative to first frame seen for same symbol",
11440
16
        10, &us_allowed_for_ul_in_symbol);
11441
11442
    /* Downlink userplane */
11443
16
    prefs_register_static_text_preference(oran_module, "oran.dl", "", "");
11444
16
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_down", "IQ Bitwidth Downlink",
11445
16
        "The bit width of a sample in the Downlink (if no udcompHdr)", 10, &pref_sample_bit_width_downlink);
11446
16
    prefs_register_enum_preference(oran_module, "oran.ud_comp_down", "Downlink User Data Compression",
11447
16
        "Downlink User Data Compression", &pref_iqCompressionDownlink, dl_compression_options, false);
11448
16
    prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_down", "udCompHdr field is present for downlink",
11449
16
        "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
11450
16
        "configuration of the O-RU. This preference instructs the dissector to expect "
11451
16
        "this field to be present in downlink messages",
11452
16
        &pref_includeUdCompHeaderDownlink, udcomphdr_present_options, false);
11453
11454
    /* SINR */
11455
16
    prefs_register_static_text_preference(oran_module, "oran.sinr", "", "");
11456
16
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_sinr", "IQ Bitwidth SINR",
11457
16
        "The bit width of a sample in SINR", 10, &pref_sample_bit_width_sinr);
11458
16
    prefs_register_enum_preference(oran_module, "oran.ud_comp_sinr", "SINR Compression",
11459
16
        "SINR Compression", &pref_iqCompressionSINR, ul_compression_options, false);
11460
11461
    /* BF-related */
11462
16
    prefs_register_static_text_preference(oran_module, "oran.bf", "", "");
11463
16
    prefs_register_uint_preference(oran_module, "oran.num_bf_antennas", "Number of beam weights",
11464
16
        "Number of array elements that BF weights will be provided for", 10, &pref_num_bf_antennas);
11465
16
    prefs_register_obsolete_preference(oran_module, "oran.num_weights_per_bundle");
11466
16
    prefs_register_obsolete_preference(oran_module, "oran.num_bf_weights");
11467
16
    prefs_register_bool_preference(oran_module, "oran.st6_4byte_alignment_required", "Use 4-byte alignment for ST6 sections",
11468
16
        "Default is 1-byte alignment", &st6_4byte_alignment);
11469
11470
    /* Misc (and will seldom need to be accessed) */
11471
16
    prefs_register_static_text_preference(oran_module, "oran.misc", "", "");
11472
16
    prefs_register_bool_preference(oran_module, "oran.show_iq_samples", "Show IQ Sample values",
11473
16
        "When enabled, for U-Plane frames show each I and Q value in PRB", &pref_showIQSampleValues);
11474
16
    prefs_register_enum_preference(oran_module, "oran.support_udcomplen", "udCompLen supported",
11475
16
        "When enabled, U-Plane messages with relevant compression schemes will include udCompLen",
11476
16
        &pref_support_udcompLen, udcomplen_support_options, false);
11477
16
    prefs_register_uint_preference(oran_module, "oran.rbs_in_uplane_section", "Total RBs in User-Plane data section",
11478
16
        "This is used if numPrbu is signalled as 0", 10, &pref_data_plane_section_total_rbs);
11479
16
    prefs_register_bool_preference(oran_module, "oran.unscaled_iq", "Show unscaled I/Q values",
11480
16
        "", &show_unscaled_values);
11481
16
    prefs_register_bool_preference(oran_module, "oran.attempt_reassembly",
11482
16
                                   "Attempt Radio Transport layer reassembly", "",
11483
16
                                   &do_radio_transport_layer_reassembly);
11484
16
    prefs_register_obsolete_preference(oran_module, "oran.k_antenna_ports");
11485
11486
16
    prefs_register_bool_preference(oran_module, "oran.link_planes",
11487
16
                                   "Link C-plane and U-plane using sectionId", "",
11488
16
                                   &link_planes_together);
11489
11490
11491
16
    flow_states_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
11492
16
    flow_results_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
11493
16
    ul_symbol_timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
11494
11495
16
    dl_beam_ids_defined = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
11496
16
    dl_beam_ids_results = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
11497
11498
16
    register_init_routine(&oran_init_protocol);
11499
11500
    /* Register reassembly table. */
11501
16
    reassembly_table_register(&oran_reassembly_table,
11502
16
                              &oran_reassembly_table_functions);
11503
16
}
11504
11505
/*
11506
* Editor modelines  -  http://www.wireshark.org/tools/modelines.html
11507
*
11508
* Local Variables:
11509
* c-basic-offset: 4
11510
* tab-width: 8
11511
* indent-tabs-mode: nil
11512
* End:
11513
*
11514
* ex: set shiftwidth=4 tabstop=8 expandtab:
11515
* :indentSize=4:tabSize=8:noTabs=true:
11516
*/