Coverage Report

Created: 2025-12-27 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-v19.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, so unfortunately it can be
37
 * fiddly to get the preferences into a good state to decode a given capture..
38
 * TODO:
39
 * - for U-Plane, track back to last C-Plane frame for that eAxC
40
 *     N.B. this matching is tricky see 7.8.1 Coupling of C-Plane and U-Plane
41
 * - Detect/indicate signs of application layer fragmentation?
42
 * - Not handling M-plane setting for "little endian byte order" as applied to IQ samples and beam weights
43
 * - for section extensions, check more constraints (which other extension types appear with them, order)
44
 * - re-order items (decl and hf definitions) to match spec order?
45
 * - track energy-saving status, and identify TRX or ASM commands as 'Sleep extension'
46
 */
47
48
/* Prototypes */
49
void proto_reg_handoff_oran(void);
50
void proto_register_oran(void);
51
52
/* Initialize the protocol and registered fields */
53
static int proto_oran;
54
55
static int oran_tap = -1;
56
57
static int hf_oran_du_port_id;
58
static int hf_oran_bandsector_id;
59
static int hf_oran_cc_id;
60
static int hf_oran_ru_port_id;
61
static int hf_oran_sequence_id;
62
static int hf_oran_e_bit;
63
static int hf_oran_subsequence_id;
64
static int hf_oran_previous_frame;
65
66
static int hf_oran_data_direction;
67
static int hf_oran_payload_version;
68
static int hf_oran_filter_index;
69
static int hf_oran_frame_id;
70
static int hf_oran_subframe_id;
71
static int hf_oran_slot_id;
72
static int hf_oran_slot_within_frame;
73
static int hf_oran_start_symbol_id;
74
static int hf_oran_numberOfSections;
75
static int hf_oran_sectionType;
76
77
static int hf_oran_udCompHdr;
78
static int hf_oran_udCompHdrIqWidth;
79
static int hf_oran_udCompHdrIqWidth_pref;
80
static int hf_oran_udCompHdrMeth;
81
static int hf_oran_udCompHdrMeth_pref;
82
static int hf_oran_udCompLen;
83
static int hf_oran_numberOfUEs;
84
static int hf_oran_timeOffset;
85
static int hf_oran_frameStructure_fft;
86
static int hf_oran_frameStructure_subcarrier_spacing;
87
static int hf_oran_cpLength;
88
static int hf_oran_timing_header;
89
static int hf_oran_section_id;
90
static int hf_oran_rb;
91
static int hf_oran_symInc;
92
static int hf_oran_startPrbc;
93
static int hf_oran_reMask_re1;
94
static int hf_oran_reMask_re2;
95
static int hf_oran_reMask_re3;
96
static int hf_oran_reMask_re4;
97
static int hf_oran_reMask_re5;
98
static int hf_oran_reMask_re6;
99
static int hf_oran_reMask_re7;
100
static int hf_oran_reMask_re8;
101
static int hf_oran_reMask_re9;
102
static int hf_oran_reMask_re10;
103
static int hf_oran_reMask_re11;
104
static int hf_oran_reMask_re12;
105
static int hf_oran_reMask;
106
static int hf_oran_numPrbc;
107
static int hf_oran_numSymbol;
108
static int hf_oran_ef;
109
static int hf_oran_beamId;
110
111
static int hf_oran_sinrCompHdrIqWidth_pref;
112
static int hf_oran_sinrCompHdrMeth_pref;
113
114
static int hf_oran_ciCompHdr;
115
static int hf_oran_ciCompHdrIqWidth;
116
static int hf_oran_ciCompHdrMeth;
117
static int hf_oran_ciCompOpt;
118
119
static int hf_oran_extension;
120
static int hf_oran_exttype;
121
static int hf_oran_extlen;
122
123
static int hf_oran_bfw_bundle;
124
static int hf_oran_bfw_bundle_id;
125
static int hf_oran_bfw;
126
static int hf_oran_bfw_i;
127
static int hf_oran_bfw_q;
128
129
static int hf_oran_ueId;
130
static int hf_oran_freqOffset;
131
static int hf_oran_regularizationFactor;
132
static int hf_oran_laaMsgType;
133
static int hf_oran_laaMsgLen;
134
static int hf_oran_lbtHandle;
135
static int hf_oran_lbtDeferFactor;
136
static int hf_oran_lbtBackoffCounter;
137
static int hf_oran_lbtOffset;
138
static int hf_oran_MCOT;
139
static int hf_oran_lbtMode;
140
static int hf_oran_sfnSfEnd;
141
static int hf_oran_lbtPdschRes;
142
static int hf_oran_sfStatus;
143
static int hf_oran_initialPartialSF;
144
static int hf_oran_lbtDrsRes;
145
static int hf_oran_lbtBufErr;
146
static int hf_oran_lbtTrafficClass;
147
static int hf_oran_lbtCWConfig_H;
148
static int hf_oran_lbtCWConfig_T;
149
static int hf_oran_lbtCWR_Rst;
150
151
static int hf_oran_reserved;
152
static int hf_oran_reserved_1bit;
153
static int hf_oran_reserved_2bits;
154
static int hf_oran_reserved_3bits;
155
static int hf_oran_reserved_4bits;
156
static int hf_oran_reserved_last_4bits;
157
static int hf_oran_reserved_last_5bits;
158
static int hf_oran_reserved_6bits;
159
static int hf_oran_reserved_last_6bits;
160
static int hf_oran_reserved_7bits;
161
static int hf_oran_reserved_last_7bits;
162
static int hf_oran_reserved_8bits;
163
static int hf_oran_reserved_16bits;
164
static int hf_oran_reserved_15bits;
165
static int hf_oran_reserved_bit1;
166
static int hf_oran_reserved_bit2;
167
static int hf_oran_reserved_bit4;
168
static int hf_oran_reserved_bit5;
169
static int hf_oran_reserved_bits123;
170
static int hf_oran_reserved_bits456;
171
172
static int hf_oran_bundle_offset;
173
static int hf_oran_cont_ind;
174
175
static int hf_oran_bfwCompHdr;
176
static int hf_oran_bfwCompHdr_iqWidth;
177
static int hf_oran_bfwCompHdr_compMeth;
178
static int hf_oran_symbolId;
179
static int hf_oran_startPrbu;
180
static int hf_oran_numPrbu;
181
182
static int hf_oran_udCompParam;
183
static int hf_oran_sReSMask;
184
static int hf_oran_sReSMask_re12;
185
static int hf_oran_sReSMask_re11;
186
static int hf_oran_sReSMask_re10;
187
static int hf_oran_sReSMask_re9;
188
static int hf_oran_sReSMask_re8;
189
static int hf_oran_sReSMask_re7;
190
static int hf_oran_sReSMask_re6;
191
static int hf_oran_sReSMask_re5;
192
static int hf_oran_sReSMask_re4;
193
static int hf_oran_sReSMask_re3;
194
static int hf_oran_sReSMask_re2;
195
static int hf_oran_sReSMask_re1;
196
197
static int hf_oran_sReSMask1;
198
static int hf_oran_sReSMask2;
199
static int hf_oran_sReSMask1_2_re12;
200
static int hf_oran_sReSMask1_2_re11;
201
static int hf_oran_sReSMask1_2_re10;
202
static int hf_oran_sReSMask1_2_re9;
203
204
static int hf_oran_bfwCompParam;
205
206
static int hf_oran_iSample;
207
static int hf_oran_qSample;
208
209
static int hf_oran_ciCompParam;
210
211
static int hf_oran_blockScaler;
212
static int hf_oran_compBitWidth;
213
static int hf_oran_compShift;
214
215
static int hf_oran_active_beamspace_coefficient_n1;
216
static int hf_oran_active_beamspace_coefficient_n2;
217
static int hf_oran_active_beamspace_coefficient_n3;
218
static int hf_oran_active_beamspace_coefficient_n4;
219
static int hf_oran_active_beamspace_coefficient_n5;
220
static int hf_oran_active_beamspace_coefficient_n6;
221
static int hf_oran_active_beamspace_coefficient_n7;
222
static int hf_oran_active_beamspace_coefficient_n8;
223
static int hf_oran_activeBeamspaceCoefficientMask;
224
static int hf_oran_activeBeamspaceCoefficientMask_bits_set;
225
226
static int hf_oran_se6_repetition;
227
228
static int hf_oran_rbgSize;
229
static int hf_oran_rbgMask;
230
static int hf_oran_noncontig_priority;
231
232
static int hf_oran_symbol_mask;
233
static int hf_oran_symbol_mask_s13;
234
static int hf_oran_symbol_mask_s12;
235
static int hf_oran_symbol_mask_s11;
236
static int hf_oran_symbol_mask_s10;
237
static int hf_oran_symbol_mask_s9;
238
static int hf_oran_symbol_mask_s8;
239
static int hf_oran_symbol_mask_s7;
240
static int hf_oran_symbol_mask_s6;
241
static int hf_oran_symbol_mask_s5;
242
static int hf_oran_symbol_mask_s4;
243
static int hf_oran_symbol_mask_s3;
244
static int hf_oran_symbol_mask_s2;
245
static int hf_oran_symbol_mask_s1;
246
static int hf_oran_symbol_mask_s0;
247
248
static int hf_oran_exponent;
249
static int hf_oran_iq_user_data;
250
251
static int hf_oran_disable_bfws;
252
static int hf_oran_rad;
253
static int hf_oran_num_bund_prbs;
254
static int hf_oran_beam_id;
255
static int hf_oran_num_weights_per_bundle;
256
257
static int hf_oran_ack_nack_req_id;
258
259
static int hf_oran_frequency_range;
260
static int hf_oran_off_start_prb;
261
static int hf_oran_num_prb;
262
263
static int hf_oran_samples_prb;
264
static int hf_oran_ciSample;
265
static int hf_oran_ciIsample;
266
static int hf_oran_ciQsample;
267
268
static int hf_oran_beamGroupType;
269
static int hf_oran_numPortc;
270
271
static int hf_oran_csf;
272
static int hf_oran_modcompscaler;
273
274
static int hf_oran_modcomp_param_set;
275
static int hf_oran_mc_scale_re_mask_re1;
276
static int hf_oran_mc_scale_re_mask_re2;
277
static int hf_oran_mc_scale_re_mask_re3;
278
static int hf_oran_mc_scale_re_mask_re4;
279
static int hf_oran_mc_scale_re_mask_re5;
280
static int hf_oran_mc_scale_re_mask_re6;
281
static int hf_oran_mc_scale_re_mask_re7;
282
static int hf_oran_mc_scale_re_mask_re8;
283
static int hf_oran_mc_scale_re_mask_re9;
284
static int hf_oran_mc_scale_re_mask_re10;
285
static int hf_oran_mc_scale_re_mask_re11;
286
static int hf_oran_mc_scale_re_mask_re12;
287
static int hf_oran_mc_scale_re_mask_re1_even;
288
static int hf_oran_mc_scale_re_mask_re2_even;
289
static int hf_oran_mc_scale_re_mask_re3_even;
290
static int hf_oran_mc_scale_re_mask_re4_even;
291
static int hf_oran_mc_scale_re_mask_re5_even;
292
static int hf_oran_mc_scale_re_mask_re6_even;
293
static int hf_oran_mc_scale_re_mask_re7_even;
294
static int hf_oran_mc_scale_re_mask_re8_even;
295
static int hf_oran_mc_scale_re_mask_re9_even;
296
static int hf_oran_mc_scale_re_mask_re10_even;
297
static int hf_oran_mc_scale_re_mask_re11_even;
298
static int hf_oran_mc_scale_re_mask_re12_even;
299
300
static int hf_oran_mc_scale_re_mask;
301
static int hf_oran_mc_scale_re_mask_even;
302
303
static int hf_oran_mc_scale_offset;
304
305
static int hf_oran_eAxC_mask;
306
static int hf_oran_technology;
307
static int hf_oran_nullLayerInd;
308
309
static int hf_oran_se19_repetition;
310
static int hf_oran_portReMask;
311
static int hf_oran_portSymbolMask;
312
313
static int hf_oran_ext19_port;
314
315
static int hf_oran_prb_allocation;
316
static int hf_oran_nextSymbolId;
317
static int hf_oran_nextStartPrbc;
318
319
static int hf_oran_puncPattern;
320
static int hf_oran_numPuncPatterns;
321
static int hf_oran_symbolMask_ext20;
322
static int hf_oran_startPuncPrb;
323
static int hf_oran_numPuncPrb;
324
static int hf_oran_puncReMask;
325
static int hf_oran_multiSDScope;
326
static int hf_oran_RbgIncl;
327
328
static int hf_oran_ci_prb_group_size;
329
static int hf_oran_prg_size_st5;
330
static int hf_oran_prg_size_st6;
331
332
static int hf_oran_num_ueid;
333
334
static int hf_oran_antMask;
335
336
static int hf_oran_transmissionWindowOffset;
337
static int hf_oran_transmissionWindowSize;
338
static int hf_oran_toT;
339
340
static int hf_oran_bfaCompHdr;
341
static int hf_oran_bfAzPtWidth;
342
static int hf_oran_bfZePtWidth;
343
static int hf_oran_bfAz3ddWidth;
344
static int hf_oran_bfZe3ddWidth;
345
static int hf_oran_bfAzPt;
346
static int hf_oran_bfZePt;
347
static int hf_oran_bfAz3dd;
348
static int hf_oran_bfZe3dd;
349
static int hf_oran_bfAzSl;
350
static int hf_oran_bfZeSl;
351
352
static int hf_oran_cmd_scope;
353
static int hf_oran_number_of_st4_cmds;
354
355
static int hf_oran_st4_cmd_header;
356
static int hf_oran_st4_cmd_type;
357
static int hf_oran_st4_cmd_len;
358
static int hf_oran_st4_cmd_num_slots;
359
static int hf_oran_st4_cmd_ack_nack_req_id;
360
361
static int hf_oran_st4_cmd;
362
363
static int hf_oran_sleepmode_trx;
364
static int hf_oran_sleepmode_asm;
365
static int hf_oran_log2maskbits;
366
static int hf_oran_num_slots_ext;
367
static int hf_oran_antMask_trx_control;
368
369
static int hf_oran_ready;
370
static int hf_oran_number_of_acks;
371
static int hf_oran_number_of_nacks;
372
static int hf_oran_ackid;
373
static int hf_oran_nackid;
374
375
static int hf_oran_acknack_request_frame;
376
static int hf_oran_acknack_request_time;
377
static int hf_oran_acknack_request_type;
378
static int hf_oran_acknack_response_frame;
379
static int hf_oran_acknack_response_time;
380
381
static int hf_oran_disable_tdbfns;
382
static int hf_oran_td_beam_group;
383
static int hf_oran_disable_tdbfws;
384
static int hf_oran_td_beam_num;
385
386
static int hf_oran_dir_pattern;
387
static int hf_oran_guard_pattern;
388
389
static int hf_oran_ecpri_pcid;
390
static int hf_oran_ecpri_rtcid;
391
static int hf_oran_ecpri_seqid;
392
393
static int hf_oran_num_sym_prb_pattern;
394
static int hf_oran_prb_mode;
395
static int hf_oran_sym_prb_pattern;
396
static int hf_oran_sym_mask;
397
static int hf_oran_num_mc_scale_offset;
398
static int hf_oran_prb_pattern;
399
static int hf_oran_prb_block_offset;
400
static int hf_oran_prb_block_size;
401
402
static int hf_oran_codebook_index;
403
static int hf_oran_layerid;
404
static int hf_oran_numlayers;
405
static int hf_oran_txscheme;
406
static int hf_oran_crs_remask;
407
static int hf_oran_crs_shift;
408
static int hf_oran_crs_symnum;
409
static int hf_oran_beamid_ap1;
410
static int hf_oran_beamid_ap2;
411
static int hf_oran_beamid_ap3;
412
413
static int hf_oran_port_list_index;
414
static int hf_oran_alpn_per_sym;
415
static int hf_oran_ant_dmrs_snr;
416
static int hf_oran_user_group_size;
417
static int hf_oran_user_group_id;
418
static int hf_oran_entry_type;
419
static int hf_oran_dmrs_port_number;
420
static int hf_oran_ueid_reset;
421
422
static int hf_oran_dmrs_symbol_mask;
423
static int hf_oran_dmrs_symbol_mask_s13;
424
static int hf_oran_dmrs_symbol_mask_s12;
425
static int hf_oran_dmrs_symbol_mask_s11;
426
static int hf_oran_dmrs_symbol_mask_s10;
427
static int hf_oran_dmrs_symbol_mask_s9;
428
static int hf_oran_dmrs_symbol_mask_s8;
429
static int hf_oran_dmrs_symbol_mask_s7;
430
static int hf_oran_dmrs_symbol_mask_s6;
431
static int hf_oran_dmrs_symbol_mask_s5;
432
static int hf_oran_dmrs_symbol_mask_s4;
433
static int hf_oran_dmrs_symbol_mask_s3;
434
static int hf_oran_dmrs_symbol_mask_s2;
435
static int hf_oran_dmrs_symbol_mask_s1;
436
static int hf_oran_dmrs_symbol_mask_s0;
437
438
static int hf_oran_scrambling;
439
static int hf_oran_nscid;
440
static int hf_oran_dtype;
441
static int hf_oran_cmd_without_data;
442
static int hf_oran_lambda;
443
static int hf_oran_first_prb;
444
static int hf_oran_last_prb;
445
static int hf_oran_low_papr_type;
446
static int hf_oran_hopping_mode;
447
448
static int hf_oran_tx_win_for_on_air_symbol_l;
449
static int hf_oran_tx_win_for_on_air_symbol_r;
450
451
static int hf_oran_num_fo_fb;
452
static int hf_oran_freq_offset_fb;
453
454
static int hf_oran_num_ue_sinr_rpt;
455
static int hf_oran_num_sinr_per_prb;
456
static int hf_oran_num_sinr_per_prb_right;
457
458
static int hf_oran_sinr_value;
459
460
static int hf_oran_measurement_report;
461
static int hf_oran_mf;
462
static int hf_oran_meas_data_size;
463
static int hf_oran_meas_type_id;
464
static int hf_oran_ipn_power;
465
static int hf_oran_ue_tae;
466
static int hf_oran_ue_layer_power;
467
static int hf_oran_num_elements;
468
static int hf_oran_ant_dmrs_snr_val;
469
static int hf_oran_ue_freq_offset;
470
471
static int hf_oran_measurement_command;
472
473
static int hf_oran_beam_type;
474
static int hf_oran_meas_cmd_size;
475
476
static int hf_oran_symbol_reordering_layer;
477
static int hf_oran_dmrs_entry;
478
479
static int hf_oran_c_section_common;
480
static int hf_oran_c_section;
481
static int hf_oran_u_section;
482
483
static int hf_oran_u_section_ul_symbol_time;
484
static int hf_oran_u_section_ul_symbol_frames;
485
static int hf_oran_u_section_ul_symbol_first_frame;
486
static int hf_oran_u_section_ul_symbol_last_frame;
487
488
static int hf_oran_cd_scg_size;
489
static int hf_oran_cd_scg_phase_step;
490
491
static int hf_oran_sinr_prb;
492
static int hf_oran_oru_control_sinr_slot_mask_id;
493
static int hf_oran_pos_meas;
494
495
static int hf_oran_ue_radial_speed;
496
static int hf_oran_ue_az_aoa;
497
static int hf_oran_ue_ze_aoa;
498
static int hf_oran_ue_pos_toa_offset;
499
500
501
/* Computed fields */
502
static int hf_oran_c_eAxC_ID;
503
static int hf_oran_refa;
504
505
/* Convenient fields for filtering, mostly shown as hidden */
506
static int hf_oran_cplane;
507
static int hf_oran_uplane;
508
static int hf_oran_bf;      /* to match frames that configure beamforming in any way */
509
static int hf_oran_zero_prb;
510
511
static int hf_oran_ul_cplane_ud_comp_hdr_frame;
512
513
/* For reassembly */
514
static int hf_oran_fragments;
515
static int hf_oran_fragment;
516
static int hf_oran_fragment_overlap;
517
static int hf_oran_fragment_overlap_conflict;
518
static int hf_oran_fragment_multiple_tails;
519
static int hf_oran_fragment_too_long_fragment;
520
static int hf_oran_fragment_error;
521
static int hf_oran_fragment_count;
522
static int hf_oran_reassembled_in;
523
static int hf_oran_reassembled_length;
524
static int hf_oran_reassembled_data;
525
526
static int hf_oran_payload;
527
528
529
/* Subtrees */
530
static int ett_oran;
531
static int ett_oran_ecpri_rtcid;
532
static int ett_oran_ecpri_pcid;
533
static int ett_oran_ecpri_seqid;
534
static int ett_oran_section;
535
static int ett_oran_section_type;
536
static int ett_oran_u_timing;
537
static int ett_oran_u_section;
538
static int ett_oran_u_prb;
539
static int ett_oran_iq;
540
static int ett_oran_bfw_bundle;
541
static int ett_oran_bfw;
542
static int ett_oran_frequency_range;
543
static int ett_oran_prb_cisamples;
544
static int ett_oran_cisample;
545
static int ett_oran_udcomphdr;
546
static int ett_oran_udcompparam;
547
static int ett_oran_cicomphdr;
548
static int ett_oran_cicompparam;
549
static int ett_oran_bfwcomphdr;
550
static int ett_oran_bfwcompparam;
551
static int ett_oran_ext19_port;
552
static int ett_oran_prb_allocation;
553
static int ett_oran_punc_pattern;
554
static int ett_oran_bfacomphdr;
555
static int ett_oran_modcomp_param_set;
556
static int ett_oran_st4_cmd_header;
557
static int ett_oran_st4_cmd;
558
static int ett_oran_sym_prb_pattern;
559
static int ett_oran_measurement_report;
560
static int ett_oran_measurement_command;
561
static int ett_oran_sresmask;
562
static int ett_oran_c_section_common;
563
static int ett_oran_c_section;
564
static int ett_oran_remask;
565
static int ett_oran_mc_scale_remask;
566
static int ett_oran_symbol_reordering_layer;
567
static int ett_oran_dmrs_entry;
568
static int ett_oran_dmrs_symbol_mask;
569
static int ett_oran_symbol_mask;
570
static int ett_oran_active_beamspace_coefficient_mask;
571
static int ett_oran_sinr_prb;
572
573
static int ett_oran_fragment;
574
static int ett_oran_fragments;
575
576
/* Reassembly table. */
577
static reassembly_table oran_reassembly_table;
578
579
static void *oran_temporary_key(const packet_info *pinfo _U_, const uint32_t id _U_, const void *data)
580
66
{
581
66
    return (void *)data;
582
66
}
583
584
static void *oran_persistent_key(const packet_info *pinfo _U_, const uint32_t id _U_,
585
                                 const void *data)
586
54
{
587
54
    return (void *)data;
588
54
}
589
590
static void oran_free_temporary_key(void *ptr _U_)
591
66
{
592
66
}
593
594
static void oran_free_persistent_key(void *ptr _U_)
595
0
{
596
0
}
597
598
static reassembly_table_functions oran_reassembly_table_functions =
599
{
600
    g_direct_hash,
601
    g_direct_equal,
602
    oran_temporary_key,
603
    oran_persistent_key,
604
    oran_free_temporary_key,
605
    oran_free_persistent_key
606
};
607
608
static const fragment_items oran_frag_items = {
609
  &ett_oran_fragment,
610
  &ett_oran_fragments,
611
  &hf_oran_fragments,
612
  &hf_oran_fragment,
613
  &hf_oran_fragment_overlap,
614
  &hf_oran_fragment_overlap_conflict,
615
  &hf_oran_fragment_multiple_tails,
616
  &hf_oran_fragment_too_long_fragment,
617
  &hf_oran_fragment_error,
618
  &hf_oran_fragment_count,
619
  &hf_oran_reassembled_in,
620
  &hf_oran_reassembled_length,
621
  &hf_oran_reassembled_data,
622
  "O-RAN FH CUS fragments"
623
};
624
625
626
627
/* Don't want all extensions to open and close together. Use extType-1 entry */
628
static int ett_oran_c_section_extension[HIGHEST_EXTTYPE];
629
630
/* Expert info */
631
static expert_field ei_oran_unsupported_bfw_compression_method;
632
static expert_field ei_oran_invalid_sample_bit_width;
633
static expert_field ei_oran_reserved_numBundPrb;
634
static expert_field ei_oran_extlen_wrong;
635
static expert_field ei_oran_invalid_eaxc_bit_width;
636
static expert_field ei_oran_extlen_zero;
637
static expert_field ei_oran_rbg_size_reserved;
638
static expert_field ei_oran_frame_length;
639
static expert_field ei_oran_numprbc_ext21_zero;
640
static expert_field ei_oran_ci_prb_group_size_reserved;
641
static expert_field ei_oran_st8_nackid;
642
static expert_field ei_oran_st4_no_cmds;
643
static expert_field ei_oran_st4_zero_len_cmd;
644
static expert_field ei_oran_st4_wrong_len_cmd;
645
static expert_field ei_oran_st4_unknown_cmd;
646
static expert_field ei_oran_mcot_out_of_range;
647
static expert_field ei_oran_se10_unknown_beamgrouptype;
648
static expert_field ei_oran_se10_not_allowed;
649
static expert_field ei_oran_start_symbol_id_not_zero;
650
static expert_field ei_oran_trx_control_cmd_scope;
651
static expert_field ei_oran_unhandled_se;
652
static expert_field ei_oran_bad_symbolmask;
653
static expert_field ei_oran_numslots_not_zero;
654
static expert_field ei_oran_version_unsupported;
655
static expert_field ei_oran_laa_msg_type_unsupported;
656
static expert_field ei_oran_se_on_unsupported_st;
657
static expert_field ei_oran_cplane_unexpected_sequence_number_ul;
658
static expert_field ei_oran_cplane_unexpected_sequence_number_dl;
659
static expert_field ei_oran_uplane_unexpected_sequence_number_ul;
660
static expert_field ei_oran_uplane_unexpected_sequence_number_dl;
661
static expert_field ei_oran_acknack_no_request;
662
static expert_field ei_oran_udpcomphdr_should_be_zero;
663
static expert_field ei_oran_radio_fragmentation_c_plane;
664
static expert_field ei_oran_lastRbdid_out_of_range;
665
static expert_field ei_oran_rbgMask_beyond_last_rbdid;
666
static expert_field ei_oran_unexpected_measTypeId;
667
static expert_field ei_oran_unsupported_compression_method;
668
static expert_field ei_oran_ud_comp_len_wrong_size;
669
static expert_field ei_oran_sresmask2_not_zero_with_rb;
670
static expert_field ei_oran_st6_rb_shall_be_0;
671
static expert_field ei_oran_st9_not_ul;
672
static expert_field ei_oran_st10_numsymbol_not_14;
673
static expert_field ei_oran_st10_startsymbolid_not_0;
674
static expert_field ei_oran_st10_not_ul;
675
static expert_field ei_oran_se24_nothing_to_inherit;
676
static expert_field ei_oran_num_sinr_per_prb_unknown;
677
static expert_field ei_oran_start_symbol_id_bits_ignored;
678
static expert_field ei_oran_user_group_id_reserved_value;
679
static expert_field ei_oran_port_list_index_zero;
680
static expert_field ei_oran_ul_uplane_symbol_too_long;
681
static expert_field ei_oran_reserved_not_zero;
682
683
684
/* These are the message types handled by this dissector.  Others have handling in packet-ecpri.c */
685
311
#define ECPRI_MT_IQ_DATA            0
686
2.37k
#define ECPRI_MT_RT_CTRL_DATA       2
687
688
689
/* Preference settings - try to set reasonable defaults */
690
static unsigned pref_du_port_id_bits    = 4;
691
static unsigned pref_bandsector_id_bits = 4;
692
static unsigned pref_cc_id_bits         = 4;
693
static unsigned pref_ru_port_id_bits    = 4;
694
695
/* TODO: ideally should be per-flow */
696
static unsigned pref_sample_bit_width_uplink   = 14;
697
static unsigned pref_sample_bit_width_downlink = 14;
698
static unsigned pref_sample_bit_width_sinr   = 14;
699
700
/* 8.3.3.15 Compression schemes */
701
226k
#define COMP_NONE                             0
702
117k
#define COMP_BLOCK_FP                         1
703
28.1k
#define COMP_BLOCK_SCALE                      2
704
46.5k
#define COMP_U_LAW                            3
705
201k
#define COMP_MODULATION                       4
706
517k
#define BFP_AND_SELECTIVE_RE                  5
707
124k
#define MOD_COMPR_AND_SELECTIVE_RE            6
708
8.05k
#define BFP_AND_SELECTIVE_RE_WITH_MASKS       7
709
98.5k
#define MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS 8
710
711
/* TODO: these ideally should be per-flow too */
712
static int pref_iqCompressionUplink = COMP_BLOCK_FP;
713
static int pref_iqCompressionDownlink = COMP_BLOCK_FP;
714
715
static int pref_iqCompressionSINR = COMP_BLOCK_FP;
716
717
718
/* Is udCompHeader present (both directions) */
719
static int pref_includeUdCompHeaderUplink = 2;     /* start using heuristic */
720
static int pref_includeUdCompHeaderDownlink = 2;   /* start using heuristic */
721
722
/* Are we ignoring UL C-Plane udCompHdr? */
723
static bool pref_override_ul_compression = false;
724
725
static unsigned pref_data_plane_section_total_rbs = 273;
726
static unsigned pref_num_bf_antennas = 32;
727
static bool pref_showIQSampleValues = true;
728
729
/* Based upon m-plane param, so will be system-wide */
730
static int  pref_support_udcompLen = 2;            /* start heuristic, can force other settings if necessary */
731
static bool udcomplen_heuristic_result_set = false;
732
static bool udcomplen_heuristic_result = false;
733
734
/* st6-4byte-alignment-required */
735
static bool st6_4byte_alignment = false;
736
737
/* Requested, allows I/Q to be stored as integers.. */
738
static bool show_unscaled_values = false;
739
740
/* Initialized off. Timing is in microseconds. */
741
static unsigned us_allowed_for_ul_in_symbol = 0;
742
743
/* Reassemble U-Plane (at Radio Transport layer) */
744
static bool do_radio_transport_layer_reassembly = true;
745
746
static const enum_val_t dl_compression_options[] = {
747
    { "COMP_NONE",                             "No Compression",                                                             COMP_NONE },
748
    { "COMP_BLOCK_FP",                         "Block Floating Point Compression",                                           COMP_BLOCK_FP },
749
    { "COMP_BLOCK_SCALE",                      "Block Scaling Compression",                                                  COMP_BLOCK_SCALE },
750
    { "COMP_U_LAW",                            "u-Law Compression",                                                          COMP_U_LAW },
751
    { "COMP_MODULATION",                       "Modulation Compression",                                                     COMP_MODULATION },
752
    { "BFP_AND_SELECTIVE_RE",                  "Block Floating Point + selective RE sending",                                BFP_AND_SELECTIVE_RE },
753
    { "MOD_COMPR_AND_SELECTIVE_RE",            "Modulation Compression + selective RE sending",                              MOD_COMPR_AND_SELECTIVE_RE },
754
    { "BFP_AND_SELECTIVE_RE_WITH_MASKS",       "Block Floating Point + selective RE sending with masks in section header",   BFP_AND_SELECTIVE_RE_WITH_MASKS },
755
    { "MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS", "Modulation Compression + selective RE sending with masks in section header", MOD_COMPR_AND_SELECTIVE_RE },
756
    { NULL, NULL, 0 }
757
};
758
759
/* No Modulation compression in UL.. */
760
static const enum_val_t ul_compression_options[] = {
761
    { "COMP_NONE",                             "No Compression",                                                           COMP_NONE },
762
    { "COMP_BLOCK_FP",                         "Block Floating Point Compression",                                         COMP_BLOCK_FP },
763
    { "COMP_BLOCK_SCALE",                      "Block Scaling Compression",                                                COMP_BLOCK_SCALE },
764
    { "COMP_U_LAW",                            "u-Law Compression",                                                        COMP_U_LAW },
765
    { "BFP_AND_SELECTIVE_RE",                  "Block Floating Point + selective RE sending",                              BFP_AND_SELECTIVE_RE },
766
    { "BFP_AND_SELECTIVE_RE_WITH_MASKS",       "Block Floating Point + selective RE sending with masks in section header", BFP_AND_SELECTIVE_RE_WITH_MASKS },
767
    { NULL, NULL, 0 }
768
};
769
770
static const enum_val_t udcomplen_support_options[] = {
771
    { "NOT_SUPPORTED",              "Not Supported",     0 },
772
    { "SUPPORTED",                  "Supported",         1 },
773
    { "HEURISTIC",                  "Attempt Heuristic", 2 },
774
    { NULL, NULL, 0 }
775
};
776
777
static const enum_val_t udcomphdr_present_options[] = {
778
    { "NOT_PRESENT",               "Not Present",       0 },
779
    { "PRESENT",                   "Present",           1 },
780
    { "HEURISTIC",                 "Attempt Heuristic", 2 },
781
    { NULL, NULL, 0 }
782
};
783
784
785
786
static const value_string e_bit[] = {
787
    { 0, "More fragments follow" },
788
    { 1, "Last fragment" },
789
    { 0, NULL}
790
};
791
792
3.91k
#define DIR_UPLINK      0
793
#define DIR_DOWNLINK    1
794
795
796
static const value_string data_direction_vals[] = {
797
    { DIR_UPLINK,   "Uplink" },   /* gNB Rx */
798
    { DIR_DOWNLINK, "Downlink" }, /* gNB Tx */
799
    { 0, NULL}
800
};
801
802
static const value_string rb_vals[] = {
803
    { 0, "Every RB used" },
804
    { 1, "Every other RB used" },
805
    { 0, NULL}
806
};
807
808
static const value_string sym_inc_vals[] = {
809
    { 0, "Use the current symbol number" },
810
    { 1, "Increment the current symbol number" },
811
    { 0, NULL}
812
};
813
814
static const value_string lbtMode_vals[] = {
815
    { 0,  "Full LBT (regular LBT, sending reservation signal until the beginning of the SF/slot)" },
816
    { 1,  "Partial LBT (looking back 25 usec prior to transmission" },
817
    { 2,  "Partial LBT (looking back 34 usec prior to transmission" },
818
    { 3,  "Full LBT and stop (regular LBT, without sending reservation signal" },
819
    { 0, NULL}
820
};
821
822
static const range_string filter_indices[] = {
823
    {0, 0,  "standard channel filter"},
824
    {1, 1,  "UL filter for PRACH preamble formats 0, 1, 2; min. passband 839 x 1.25kHz = 1048.75 kHz"},
825
    {2, 2,  "UL filter for PRACH preamble format 3, min. passband 839 x 5 kHz = 4195 kHz"},
826
    {3, 3,  "UL filter for PRACH preamble formats A1, A2, A3, B1, B2, B3, B4, C0, C2; min. passband 139 x \u0394fRA"},
827
    {4, 4,  "UL filter for NPRACH 0, 1; min. passband 48 x 3.75KHz = 180 KHz"},
828
    {5, 5,  "UL filter for PRACH preamble formats"},
829
    {8, 8,  "UL filter NPUSCH"},
830
    {9, 9,  "Mixed numerology and other channels except PRACH and NB-IoT"},
831
    {9, 15, "Reserved"},
832
    {0, 0, NULL}
833
};
834
835
static const range_string section_types[] = {
836
    { SEC_C_UNUSED_RB,         SEC_C_UNUSED_RB,         "Unused Resource Blocks or symbols in Downlink or Uplink" },
837
    { SEC_C_NORMAL,            SEC_C_NORMAL,            "Most DL/UL radio channels" },
838
    { SEC_C_RSVD2,             SEC_C_RSVD2,             "Reserved for future use" },
839
    { SEC_C_PRACH,             SEC_C_PRACH,             "PRACH and mixed-numerology channels" },
840
    { SEC_C_SLOT_CONTROL,      SEC_C_SLOT_CONTROL,      "Slot Configuration Control" },
841
    { SEC_C_UE_SCHED,          SEC_C_UE_SCHED,          "UE scheduling information (UE-ID assignment to section)" },
842
    { SEC_C_CH_INFO,           SEC_C_CH_INFO,           "Channel information" },
843
    { SEC_C_LAA,               SEC_C_LAA,               "LAA (License Assisted Access)" },
844
    { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "ACK/NACK Feedback" },
845
    { SEC_C_SINR_REPORTING,    SEC_C_SINR_REPORTING,    "SINR Reporting" },
846
    { SEC_C_RRM_MEAS_REPORTS,  SEC_C_RRM_MEAS_REPORTS,  "RRM Measurement Reports" },
847
    { SEC_C_REQUEST_RRM_MEAS,  SEC_C_REQUEST_RRM_MEAS,  "Request RRM Measurements" },
848
    { 12,                      255,                     "Reserved for future use" },
849
    { 0, 0, NULL} };
850
851
static const range_string section_types_short[] = {
852
    { SEC_C_UNUSED_RB,         SEC_C_UNUSED_RB,         "(Unused RBs)        " },
853
    { SEC_C_NORMAL,            SEC_C_NORMAL,            "(Most channels)     " },
854
    { SEC_C_RSVD2,             SEC_C_RSVD2,             "(reserved)          " },
855
    { SEC_C_PRACH,             SEC_C_PRACH,             "(PRACH/mixed-\u03bc)" },
856
    { SEC_C_SLOT_CONTROL,      SEC_C_SLOT_CONTROL,      "(Slot info)         " },
857
    { SEC_C_UE_SCHED,          SEC_C_UE_SCHED,          "(UE scheduling info)" },
858
    { SEC_C_CH_INFO,           SEC_C_CH_INFO,           "(Channel info)      " },
859
    { SEC_C_LAA,               SEC_C_LAA,               "(LAA)               " },
860
    { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "(ACK/NACK)          " },
861
    { SEC_C_SINR_REPORTING,    SEC_C_SINR_REPORTING,    "(SINR Reporting)    " },
862
    { SEC_C_RRM_MEAS_REPORTS,  SEC_C_RRM_MEAS_REPORTS,  "(RRM Meas Reports)  " },
863
    { SEC_C_REQUEST_RRM_MEAS,  SEC_C_REQUEST_RRM_MEAS,  "(Req RRM Meas)      " },
864
    { 12,                      255,                     "Reserved for future use" },
865
    { 0, 0, NULL }
866
};
867
868
static const range_string ud_comp_header_width[] = {
869
    {0, 0,  "I and Q are each 16 bits wide"},
870
    {1, 15, "Bit width of I and Q"},
871
    {0, 0, NULL} };
872
873
/* Table 8.3.3.13-3 */
874
static const range_string ud_comp_header_meth[] = {
875
    {COMP_NONE,                             COMP_NONE,                             "No compression" },
876
    {COMP_BLOCK_FP,                         COMP_BLOCK_FP,                         "Block floating point compression" },
877
    {COMP_BLOCK_SCALE,                      COMP_BLOCK_SCALE,                      "Block scaling" },
878
    {COMP_U_LAW,                            COMP_U_LAW,                            "Mu - law" },
879
    {COMP_MODULATION,                       COMP_MODULATION,                       "Modulation compression" },
880
    {BFP_AND_SELECTIVE_RE,                  BFP_AND_SELECTIVE_RE,                  "BFP + selective RE sending" },
881
    {MOD_COMPR_AND_SELECTIVE_RE,            MOD_COMPR_AND_SELECTIVE_RE,            "mod-compr + selective RE sending" },
882
    {BFP_AND_SELECTIVE_RE_WITH_MASKS,       BFP_AND_SELECTIVE_RE_WITH_MASKS,       "BFP + selective RE sending with masks in section header" },
883
    {MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, "mod-compr + selective RE sending with masks in section header"},
884
    {9, 15, "Reserved"},
885
    {0, 0, NULL}
886
};
887
888
/* Table 7.5.2.13-2 */
889
static const range_string frame_structure_fft[] = {
890
    {0,  0,  "Reserved (no FFT/iFFT processing)"},
891
    {1,  3,  "Reserved"},
892
    {4,  4,  "FFT size 16"},
893
    {5,  5,  "FFT size 32"},
894
    {6,  6,  "FFT size 64"},
895
    {7,  7,  "FFT size 128"},
896
    {8,  8,  "FFT size 256"},
897
    {9,  9,  "FFT size 512"},
898
    {10, 10, "FFT size 1024"},
899
    {11, 11, "FFT size 2048"},
900
    {12, 12, "FFT size 4096"},
901
    {13, 13, "FFT size 1536"},
902
    {14, 14, "FFT size 3072"},
903
    {15, 15, "Reserved"},
904
    {0, 0, NULL}
905
};
906
907
/* Table 7.5.2.13-3 */
908
static const range_string subcarrier_spacings[] = {
909
    { 0,  0,  "SCS 15 kHz, 1 slot/subframe, slot length 1 ms" },
910
    { 1,  1,  "SCS 30 kHz, 2 slots/subframe, slot length 500 \u03bcs" },
911
    { 2,  2,  "SCS 60 kHz, 4 slots/subframe, slot length 250 \u03bcs" },
912
    { 3,  3,  "SCS 120 kHz, 8 slots/subframe, slot length 125 \u03bcs" },
913
    { 4,  4,  "SCS 240 kHz, 16 slots/subframe, slot length 62.5 \u03bcs" },
914
    { 5,  11, "Reserved" }, /* N.B., 5 was 480kHz in early spec versions */
915
    { 12, 12, "SCS 1.25 kHz, 1 slot/subframe, slot length 1 ms" },
916
    { 13, 13, "SCS 3.75 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
917
    { 14, 14, "SCS 5 kHz, 1 slot/subframe, slot length 1 ms" },
918
    { 15, 15, "SCS 7.5 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
919
    { 0, 0, NULL }
920
};
921
922
/* Table 7.5.3.14-1 laaMsgType definition */
923
static const range_string laaMsgTypes[] = {
924
    {0, 0,  "LBT_PDSCH_REQ - lls - O-DU to O-RU request to obtain a PDSCH channel"},
925
    {1, 1,  "LBT_DRS_REQ - lls - O-DU to O-RU request to obtain the channel and send DRS"},
926
    {2, 2,  "LBT_PDSCH_RSP - O-RU to O-DU response, channel acq success or failure"},
927
    {3, 3,  "LBT_DRS_RSP - O-RU to O-DU response, DRS sending success or failure"},
928
    {4, 4,  "LBT_Buffer_Error - O-RU to O-DU response, reporting buffer overflow"},
929
    {5, 5,  "LBT_CWCONFIG_REQ - O-DU to O-RU request, congestion window configuration"},
930
    {6, 6,  "LBT_CWCONFIG_RST - O-RU to O-DU request, congestion window config, response"},
931
    {7, 15, "reserved for future methods"},
932
    {0, 0, NULL}
933
};
934
935
static const range_string freq_offset_fb_values[] = {
936
    {0,      0,        "no frequency offset"},
937
    {8000,   8000,     "value not provided"},
938
    {1,      30000,    "positive frequency offset, (0, +0.5] subcarrier"},
939
    {0x8ad0, 0xffff,   "negative frequency offset, [-0.5, 0) subcarrier"},
940
    {0x0,    0xffff,   "reserved"},
941
    {0, 0, NULL}
942
};
943
944
static const value_string num_sinr_per_prb_vals[] = {
945
    { 0,  "1" },
946
    { 1,  "2" },
947
    { 2,  "3" },
948
    { 3,  "4" },
949
    { 4,  "6" },
950
    { 5,  "12" },
951
    { 6,  "reserved" },
952
    { 7,  "reserved" },
953
    { 0, NULL}
954
};
955
956
static const value_string meas_type_id_vals[] = {
957
    { 1,  "UE Timing Advance Error" },
958
    { 2,  "UE Layer power" },
959
    { 3,  "UE frequency offset" },
960
    { 4,  "Interference plus Noise for allocated PRBs" },
961
    { 5,  "Interference plus Noise for unallocated PRBs" },
962
    { 6,  "DMRS-SNR per antenna" },
963
    { 7,  "UE positioning measurement report" },
964
    { 8,  "UE radial speed measurement report" },
965
    { 0, NULL}
966
};
967
968
static const value_string beam_type_vals[] = {
969
    { 0,  "List of beamId values" },
970
    { 1,  "Range of beamId values" },
971
    { 0, NULL}
972
};
973
974
/* 7.7.24.3 */
975
static const value_string entry_type_vals[] = {
976
    { 0,  "inherit config from preceding entry (2 or 3) ueIdReset=0" },
977
    { 1,  "inherit config from preceding entry (2 or 3) ueIdReset=1" },
978
    { 2,  "related parameters if have transform precoding disabled " },
979
    { 3,  "related parameters if have transform precoding enabled  " },
980
    { 0, NULL}
981
};
982
983
/* Table 7.7.29.3-1 */
984
static const range_string cd_scg_size_vals[] = {
985
    { 0, 0,  "1 subcarrier" },
986
    { 1, 1,  "1 RB x N subcarriers" },
987
    { 2, 2,  "2 RB x N subcarriers" },
988
    { 3, 3,  "4 RB x N subcarriers" },
989
    { 4, 4,  "8 RB x N subcarriers" },
990
    { 5, 5,  "16 RB x N subcarriers" },
991
    { 6, 6,  "32 RB x N subcarriers" },
992
    { 7, 15, "reserved"},
993
    { 0, 0, NULL}
994
};
995
996
997
/* Table 7.6.1-1 */
998
static const value_string exttype_vals[] = {
999
    {0,     "Reserved"},
1000
    {1,     "Beamforming weights"},
1001
    {2,     "Beamforming attributes"},
1002
    {3,     "DL Precoding configuration parameters and indications"},
1003
    {4,     "Modulation compr. params"},
1004
    {5,     "Modulation compression additional scaling parameters"},
1005
    {6,     "Non-contiguous PRB allocation"},
1006
    {7,     "Multiple-eAxC designation"},
1007
    {8,     "Regularization factor"},
1008
    {9,     "Dynamic Spectrum Sharing parameters"},
1009
    {10,    "Multiple ports grouping"},
1010
    {11,    "Flexible BF weights"},
1011
    {12,    "Non-Contiguous PRB Allocation with Frequency Ranges"},
1012
    {13,    "PRB Allocation with Frequency Hopping"},
1013
    {14,    "Nulling-layer Info. for ueId-based beamforming"},
1014
    {15,    "Mixed-numerology Info. for ueId-based beamforming"},
1015
    {16,    "Section description for antenna mapping in UE channel information based UL beamforming"},
1016
    {17,    "Section description for indication of user port group"},
1017
    {18,    "Section description for Uplink Transmission Management"},
1018
    {19,    "Compact beamforming information for multiple port"},
1019
    {20,    "Puncturing extension"},
1020
    {21,    "Variable PRB group size for channel information"},
1021
    {22,    "ACK/NACK request"},
1022
    {23,    "Multiple symbol modulation compression parameters"},
1023
    {24,    "PUSCH DMRS configuration"},
1024
    {25,    "Symbol reordering for DMRS-BF"},
1025
    {26,    "Frequency offset feedback"},
1026
    {27,    "O-DU controlled dimensionality reduction"},
1027
    {28,    "O-DU controlled frequency resolution for SINR reporting"},
1028
    {29,    "Cyclic delay adjustment"},
1029
    {0, NULL}
1030
};
1031
static value_string_ext exttype_vals_ext = VALUE_STRING_EXT_INIT(exttype_vals);
1032
1033
1034
/**************************************************************************************/
1035
/* Keep track for each Section Extension, which section types are allowed to carry it */
1036
typedef struct {
1037
    bool ST0;
1038
    bool ST1;
1039
    bool ST3;
1040
    bool ST5;
1041
    bool ST6;
1042
    bool ST10;
1043
    bool ST11;
1044
} AllowedCTs_t;
1045
1046
1047
static const AllowedCTs_t ext_cts[HIGHEST_EXTTYPE] = {
1048
    /* ST0    ST1    ST3    ST5    ST6   ST10    ST11 */
1049
    { false, true,  true,  false, false, false, false},   // SE 1      (1,3)
1050
    { false, true,  true,  false, false, false, false},   // SE 2      (1,3)
1051
    { false, true,  true,  false, false, false, false},   // SE 3      (1,3)
1052
    { false, true,  true,  true,  false, false, false},   // SE 4      (1,3,5)
1053
    { false, true,  true,  true,  false, false, false},   // SE 5      (1,3,5)
1054
    { false, true,  true,  true,  false, true,  true },   // SE 6      (1,3,5,10,11)
1055
    { true,  false, false, false, false, false, false},   // SE 7      (0)
1056
    { false, false, false, true,  false, false, false},   // SE 8      (5)
1057
    { true,  true,  true,  true,  true,  true,  true },   // SE 9      (all)
1058
    { false, true,  true,  true,  false, false, false},   // SE 10     (1,3,5)
1059
    { false, true,  true,  false, false, false, false},   // SE 11     (1,3)
1060
    { false, true,  true,  true,  false, true,  true },   // SE 12     (1,3,5,10,11)
1061
    { false, true,  true,  true,  false, false, false},   // SE 13     (1,3,5)
1062
    { false, false, false, true,  false, false, false},   // SE 14     (5)
1063
    { false, false, false, true,  true,  false, false},   // SE 15     (5,6)
1064
    { false, false, false, true,  false, false, false},   // SE 16     (5)
1065
    { false, false, false, true,  false, false, false},   // SE 17     (5)
1066
    { false, true,  true,  true,  false, false, false},   // SE 18     (1,3,5)
1067
    { false, true,  true,  false, false, false, false},   // SE 19     (1,3)
1068
    { true,  true,  true,  true,  true,  true,  true },   // SE 20     (0,1,3,5,10,11)
1069
    { false, false, false, true,  true,  false, false},   // SE 21     (5,6)
1070
    { true,  true,  true,  true,  true,  true,  true },   // SE 22     (all)
1071
    { false, true,  true,  true,  false, false, false},   // SE 23     (1,3,5)
1072
    { false, false, false, true,  false, false, false},   // SE 24     (5)
1073
    { false, false, false, true,  false, false, false},   // SE 25     (5)
1074
    { false, false, false, true,  false, false, false},   // SE 26     (5)
1075
    { false, false, false, true,  false, false, false},   // SE 27     (5)
1076
    { false, false, false, true,  false, false, false},   // SE 28     (5)
1077
    { false, true,  true,  true,  false, false, false},   // SE 29     (1,3,5)
1078
};
1079
1080
static bool se_allowed_in_st(unsigned se, unsigned ct)
1081
3.41k
{
1082
3.41k
    if (se==0 || se>HIGHEST_EXTTYPE) {
1083
        /* Don't know about new SE, so don't complain.. */
1084
1.19k
        return true;
1085
1.19k
    }
1086
1087
2.21k
    switch (ct) {
1088
429
        case 1:
1089
429
            return ext_cts[se-1].ST1;
1090
258
        case 3:
1091
258
            return ext_cts[se-1].ST3;
1092
128
        case 5:
1093
128
            return ext_cts[se-1].ST5;
1094
23
        case 6:
1095
23
            return ext_cts[se-1].ST6;
1096
529
        case 10:
1097
529
            return ext_cts[se-1].ST10;
1098
254
        case 11:
1099
254
            return ext_cts[se-1].ST11;
1100
591
        default:
1101
            /* New/unknown section type that includes 'ef'.. assume ok */
1102
591
            return true;
1103
2.21k
    }
1104
2.21k
}
1105
1106
/************************************************************************************/
1107
1108
/* Table 7.7.1.2-2 */
1109
static const value_string bfw_comp_headers_iq_width[] = {
1110
    {0,     "I and Q are 16 bits wide"},
1111
    {1,     "I and Q are 1 bit wide"},
1112
    {2,     "I and Q are 2 bits wide"},
1113
    {3,     "I and Q are 3 bits wide"},
1114
    {4,     "I and Q are 4 bits wide"},
1115
    {5,     "I and Q are 5 bits wide"},
1116
    {6,     "I and Q are 6 bits wide"},
1117
    {7,     "I and Q are 7 bits wide"},
1118
    {8,     "I and Q are 8 bits wide"},
1119
    {9,     "I and Q are 9 bits wide"},
1120
    {10,    "I and Q are 10 bits wide"},
1121
    {11,    "I and Q are 11 bits wide"},
1122
    {12,    "I and Q are 12 bits wide"},
1123
    {13,    "I and Q are 13 bits wide"},
1124
    {14,    "I and Q are 14 bits wide"},
1125
    {15,    "I and Q are 15 bits wide"},
1126
    {0, NULL}
1127
};
1128
1129
/* Table 7.7.1.2-3 */
1130
static const value_string bfw_comp_headers_comp_meth[] = {
1131
    {COMP_NONE,         "no compression"},
1132
    {COMP_BLOCK_FP,     "block floating point"},
1133
    {COMP_BLOCK_SCALE,  "block scaling"},
1134
    {COMP_U_LAW,        "u-law"},
1135
    {4,                 "beamspace compression type I"},
1136
    {5,                 "beamspace compression type II"},
1137
    {0, NULL}
1138
};
1139
1140
/* 7.7.6.2 rbgSize (resource block group size) */
1141
static const value_string rbg_size_vals[] = {
1142
    {0,     "reserved"},
1143
    {1,     "1"},
1144
    {2,     "2"},
1145
    {3,     "3"},
1146
    {4,     "4"},
1147
    {5,     "6"},
1148
    {6,     "8"},
1149
    {7,     "16"},
1150
    {0, NULL}
1151
};
1152
1153
/* 7.7.6.5 */
1154
static const value_string priority_vals[] = {
1155
    {0,     "0"},
1156
    {1,     "+1"},
1157
    {2,     "-2 (reserved, should not be used)"},
1158
    {3,     "-1"},
1159
    {0, NULL}
1160
};
1161
1162
/* 7.7.10.2  beamGroupType */
1163
static const value_string beam_group_type_vals[] = {
1164
    {0x0, "common beam"},
1165
    {0x1, "beam matrix indication"},
1166
    {0x2, "beam vector listing"},
1167
    {0x3, "beamId/ueId listing with associated port-list index"},
1168
    {0, NULL}
1169
};
1170
1171
/* 7.7.9.2 technology (interface name) */
1172
static const value_string interface_name_vals[] = {
1173
    {0x0, "LTE"},
1174
    {0x1, "NR"},
1175
    {0, NULL}
1176
};
1177
1178
/* 7.7.18.4 toT (type of transmission) */
1179
static const value_string type_of_transmission_vals[] = {
1180
    {0x0, "normal transmission mode, data can be distributed in any way the O-RU is implemented to transmit data"},
1181
    {0x1, "uniformly distributed over the transmission window"},
1182
    {0x2, "Reserved"},
1183
    {0x3, "Reserved"},
1184
    {0, NULL}
1185
};
1186
1187
/* 7.7.2.2 (width of bfa parameters) */
1188
static const value_string bfa_bw_vals[] = {
1189
    {0,   "no bits, the field is not applicable (e.g., O-RU does not support it) or the default value shall be used"},
1190
    {1,   "2-bit bitwidth"},
1191
    {2,   "3-bit bitwidth"},
1192
    {3,   "4-bit bitwidth"},
1193
    {4,   "5-bit bitwidth"},
1194
    {5,   "6-bit bitwidth"},
1195
    {6,   "7-bit bitwidth"},
1196
    {7,   "8-bit bitwidth"},
1197
    {0,   NULL}
1198
};
1199
1200
/* 7.7.2.7 & 7.7.2.8 */
1201
static const value_string sidelobe_suppression_vals[] = {
1202
    {0,   "10 dB"},
1203
    {1,   "15 dB"},
1204
    {2,   "20 dB"},
1205
    {3,   "25 dB"},
1206
    {4,   "30 dB"},
1207
    {5,   "35 dB"},
1208
    {6,   "40 dB"},
1209
    {7,   ">= 45 dB"},
1210
    {0,   NULL}
1211
};
1212
1213
static const value_string lbtTrafficClass_vals[] = {
1214
    {1,   "Priority 1"},
1215
    {2,   "Priority 2"},
1216
    {3,   "Priority 3"},
1217
    {4,   "Priority 4"},
1218
    {0,   NULL}
1219
};
1220
1221
/* 7.5.3.22 */
1222
static const value_string lbtPdschRes_vals[] = {
1223
    {0,   "not sensing – indicates that the O-RU is transmitting data"},
1224
    {1,   "currently sensing – indicates the O-RU has not yet acquired the channel"},
1225
    {2,   "success – indicates that the channel was successfully acquired"},
1226
    {3,   "Failure – indicates expiration of the LBT timer. The LBT process should be reset"},
1227
    {0,   NULL}
1228
};
1229
1230
/* Table 7.5.2.15-3 */
1231
static const value_string ci_comp_opt_vals[] = {
1232
    {0,   "compression per UE, one ciCompParam exists before the I/Q value of each UE"},
1233
    {1,   "compression per PRB, one ciCompParam exists before the I/Q value of each PRB"},
1234
    {0,   NULL}
1235
};
1236
1237
/* 7.5.2.17 */
1238
static const range_string cmd_scope_vals[] = {
1239
    {0, 0,  "ARRAY-COMMAND"},
1240
    {1, 1,  "CARRIER-COMMAND"},
1241
    {2, 2,  "O-RU-COMMAND"},
1242
    {3, 15, "reserved"},
1243
    {0, 0,  NULL}
1244
};
1245
1246
/* N.B., table in 7.5.3.38 is truncated.. */
1247
static const range_string st4_cmd_type_vals[] = {
1248
    {0, 0,   "reserved for future command types"},
1249
    {1, 1,   "TIME_DOMAIN_BEAM_CONFIG"},
1250
    {2, 2,   "TDD_CONFIG_PATTERN"},
1251
    {3, 3,   "TRX_CONTROL"},
1252
    {4, 4,   "ASM"},
1253
    {5, 255, "reserved for future command types"},
1254
    {0, 0,   NULL}
1255
};
1256
1257
/* Table 7.5.3.51-1 */
1258
static const value_string log2maskbits_vals[] = {
1259
    {0,  "reserved"},
1260
    {1,  "min antMask size is 16 bits.."},
1261
    {2,  "min antMask size is 16 bits.."},
1262
    {3,  "min antMask size is 16 bits.."},
1263
    {4,  "16 bits"},
1264
    {5,  "32 bits"},
1265
    {6,  "64 bits"},
1266
    {7,  "128 bits"},
1267
    {8,  "256 bits"},
1268
    {9,  "512 bits"},
1269
    {10, "1024 bits"},
1270
    {11, "2048 bits"},
1271
    {12, "4096 bits"},
1272
    {13, "8192 bits"},
1273
    {14, "16384 bits"},
1274
    {15, "reserved"},
1275
    {0,  NULL}
1276
};
1277
1278
/* Table 16.1-1 Sleep modes */
1279
static const value_string sleep_mode_trx_vals[] = {
1280
    { 0, "TRXC-mode0-wake-up-duration (symbol)"},
1281
    { 1, "TRXC-mode1-wake-up-duration (L)"},
1282
    { 2, "TRXC-mode2-wake-up-duration (M)"},
1283
    { 3, "TRXC-mode3-wake-up-duration (N)"},
1284
    { 0, NULL}
1285
};
1286
1287
static const value_string sleep_mode_asm_vals[] = {
1288
    { 0, "ASM-mode0-wake-up-duration (symbol)"},
1289
    { 1, "ASM-mode1-wake-up-duration (L)"},
1290
    { 2, "ASM-mode2-wake-up-duration (M)"},
1291
    { 3, "ASM-mode3-wake-up-duration (N)"},
1292
    { 0, NULL}
1293
};
1294
1295
/* 7.7.21.3.1 */
1296
static const value_string prg_size_st5_vals[] = {
1297
    { 0, "reserved"},
1298
    { 1, "Precoding resource block group size as WIDEBAND"},
1299
    { 2, "Precoding resource block group size 2"},
1300
    { 3, "Precoding resource block group size 4"},
1301
    { 0, NULL}
1302
};
1303
1304
/* 7.7.21.3.2 */
1305
static const value_string prg_size_st6_vals[] = {
1306
    { 0, "if ciPrbGroupSize is 2 or 4, then ciPrbGroupSize, else WIDEBAND"},
1307
    { 1, "Precoding resource block group size as WIDEBAND"},
1308
    { 2, "Precoding resource block group size 2"},
1309
    { 3, "Precoding resource block group size 4"},
1310
    { 0, NULL}
1311
};
1312
1313
/* 7.7.24.4 */
1314
static const value_string alpn_per_sym_vals[] = {
1315
    { 0, "report one allocated IPN value per all allocated symbols with DMRS"},
1316
    { 1, "report one allocated IPN value per group of consecutive DMRS symbols"},
1317
    { 0, NULL}
1318
};
1319
1320
/* 7.7.24.5 */
1321
static const value_string ant_dmrs_snr_vals[] = {
1322
    { 0, "O-RU shall not report the MEAS_ANT_DMRS_SNR"},
1323
    { 1, "O-RU shall report the MEAS_ANT_DMRS_SNR"},
1324
    { 0, NULL}
1325
};
1326
1327
/* 7.7.24.14 */
1328
static const value_string dtype_vals[] = {
1329
    { 0, "assume DMRS configuration type 1"},
1330
    { 1, "assume DMRS configuration type 2"},
1331
    { 0, NULL}
1332
};
1333
1334
/* 7.7.24.17 */
1335
static const value_string papr_type_vals[] = {
1336
    { 0, "sequence generator type 1 for short sequence lengths"},
1337
    { 1, "sequence generator type 1 for long sequence lengths"},
1338
    { 2, "sequence generator type 2 for short sequence lengths"},
1339
    { 3, "sequence generator type 2 for long sequence lengths"},
1340
    { 0, NULL}
1341
};
1342
1343
/* 7.7.24.18 */
1344
static const value_string hopping_mode_vals[] = {
1345
    { 0, "neither group, nor sequence hopping is enabled"},
1346
    { 1, "group hopping is enabled and sequence hopping is disabled"},
1347
    { 2, "sequence hopping is enabled and group hopping is disabled"},
1348
    { 3, "reserved"},
1349
    { 0, NULL}
1350
};
1351
1352
1353
static const true_false_string tfs_sfStatus =
1354
{
1355
    "subframe was transmitted",
1356
    "subframe was dropped"
1357
};
1358
1359
static const true_false_string tfs_lbtBufErr =
1360
{
1361
    "buffer overflow – data received at O-RU is larger than the available buffer size",
1362
    "reserved"
1363
};
1364
1365
static const true_false_string tfs_partial_full_sf = {
1366
  "partial SF",
1367
  "full SF"
1368
};
1369
1370
static const true_false_string disable_tdbfns_tfs = {
1371
  "beam numbers excluded",
1372
  "beam numbers included"
1373
};
1374
1375
static const true_false_string continuity_indication_tfs = {
1376
  "continuity between current and next bundle",
1377
  "discontinuity between current and next bundle"
1378
};
1379
1380
static const true_false_string prb_mode_tfs = {
1381
  "PRB-BLOCK mode",
1382
  "PRB-MASK mode"
1383
};
1384
1385
static const true_false_string symbol_direction_tfs = {
1386
  "DL symbol",
1387
  "UL symbol"
1388
};
1389
1390
static const true_false_string symbol_guard_tfs = {
1391
  "guard symbol",
1392
  "non-guard symbol"
1393
};
1394
1395
static const true_false_string beam_numbers_included_tfs = {
1396
  "time-domain beam numbers excluded in this command",
1397
  "time-domain beam numbers included in this command"
1398
};
1399
1400
static const true_false_string measurement_flag_tfs = {
1401
  "at least one additional measurement report or command after the current one",
1402
  "no additional measurement report or command"
1403
};
1404
1405
static const true_false_string repetition_se6_tfs = {
1406
  "repeated highest priority data section in the C-Plane message",
1407
  "no repetition"
1408
};
1409
1410
static const true_false_string repetition_se19_tfs = {
1411
  "per port information not present in the extension",
1412
  "per port info present in the extension"
1413
};
1414
1415
static const true_false_string tfs_report_no_report_pos_meas =
1416
{
1417
    "Report MEAS_UE_POS for UE",
1418
    "Do not report UE_POS for UE"
1419
};
1420
1421
1422
/* Forward declaration */
1423
static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
1424
                               unsigned comp_meth,
1425
                               uint32_t *exponent, uint16_t *sReSMask, bool for_sinr);
1426
1427
1428
static const true_false_string ready_tfs = {
1429
  "message is a \"ready\" message",
1430
  "message is a ACK message"
1431
};
1432
1433
static const true_false_string multi_sd_scope_tfs = {
1434
  "Puncturing pattern applies to current and following sections",
1435
  "Puncturing pattern applies to current section"
1436
};
1437
1438
static const true_false_string tfs_ueid_reset = {
1439
  "cannot assume same UE as in preceding slot",
1440
  "can assume same UE as in preceding slot"
1441
};
1442
1443
1444
/* Config for (and later, worked-out allocations) bundles for ext11 (dynamic BFW) */
1445
typedef struct {
1446
    /* Ext 6 config */
1447
    bool     ext6_set;
1448
    uint8_t  ext6_rbg_size;      /* number of PRBs allocated by bitmask */
1449
1450
    uint8_t  ext6_num_bits_set;
1451
    uint8_t  ext6_bits_set[28];  /* Which bit position this entry has */
1452
    /* TODO: store an f value for each bit position? */
1453
1454
    /* Ext 12 config */
1455
    bool     ext12_set;
1456
    unsigned ext12_num_pairs;
1457
17.4k
#define MAX_BFW_EXT12_PAIRS 128
1458
    struct {
1459
        uint8_t off_start_prb;
1460
        uint8_t num_prb;
1461
    } ext12_pairs[MAX_BFW_EXT12_PAIRS];
1462
1463
    /* Ext 13 config */
1464
    bool     ext13_set;
1465
    unsigned ext13_num_start_prbs;
1466
7.90k
#define MAX_BFW_EXT13_ALLOCATIONS 128
1467
    unsigned ext13_start_prbs[MAX_BFW_EXT13_ALLOCATIONS];
1468
    /* TODO: store nextSymbolId here too? */
1469
1470
    /* Ext 21 config */
1471
    bool     ext21_set;
1472
    uint8_t  ext21_ci_prb_group_size;
1473
1474
    /* Results/settings (after calling ext11_work_out_bundles()) */
1475
    uint32_t num_bundles;
1476
13.7k
#define MAX_BFW_BUNDLES 512
1477
    struct {
1478
        uint32_t start;      /* first prb of bundle */
1479
        uint32_t end;        /* last prb of bundle*/
1480
        bool     is_orphan;  /* true if not complete (i.e., end-start < numBundPrb) */
1481
    } bundles[MAX_BFW_BUNDLES];
1482
} ext11_settings_t;
1483
1484
1485
/* Work out bundle allocation for ext 11.  Take into account ext6/ext21, ext12 or ext13 in this section before ext 11. */
1486
/* Won't be called with numBundPrb=0 */
1487
static void ext11_work_out_bundles(unsigned startPrbc,
1488
                                   unsigned numPrbc,
1489
                                   unsigned numBundPrb,             /* number of PRBs pre (full) bundle */
1490
                                   ext11_settings_t *settings)
1491
166
{
1492
    /* Allocation configured by ext 6 */
1493
166
    if (settings->ext6_set) {
1494
5
        unsigned bundles_per_entry = (settings->ext6_rbg_size / numBundPrb);
1495
1496
        /* Need to cope with these not dividing exactly, or even having more PRbs in a bundle that
1497
           rbg size.  i.e. each bundle gets the correct number of PRBs until
1498
           all rbg entries are consumed... */
1499
1500
        /* TODO: need to check 7.9.4.2.  Different cases depending upon value of RAD */
1501
1502
5
        if (bundles_per_entry == 0) {
1503
3
            bundles_per_entry = 1;
1504
3
        }
1505
1506
        /* Ext6 behaviour may also be affected by ext 21 */
1507
5
        if (settings->ext21_set) {
1508
            /* N.B., have already checked that numPrbc is not 0 */
1509
1510
            /* ciPrbGroupSize overrides number of contiguous PRBs in group */
1511
0
            bundles_per_entry = (settings->ext6_rbg_size / settings->ext21_ci_prb_group_size);
1512
1513
            /* numPrbc is the number of PRB groups per antenna - handled in call to dissect_bfw_bundle() */
1514
0
        }
1515
1516
5
        unsigned bundles_set = 0;
1517
5
        bool reached_orphan = false;
1518
        /* For each bit set in ext6 rbg mask.. */
1519
5
        for (unsigned n=0;
1520
62
             !reached_orphan && n < (settings->ext6_num_bits_set * settings->ext6_rbg_size) / numBundPrb;
1521
59
             n++) {
1522
1523
            /* Watch out for array bound */
1524
59
            if (n >= 28) {
1525
2
                break;
1526
2
            }
1527
1528
            /* For each bundle... */
1529
1530
            /* TODO: Work out where first PRB is */
1531
            /* May not be the start of an rbg block... */
1532
57
            uint32_t prb_start = (settings->ext6_bits_set[n] * settings->ext6_rbg_size);
1533
1534
            /* For each bundle within identified rbgSize block */
1535
394
            for (unsigned m=0; !reached_orphan && m < bundles_per_entry; m++) {
1536
351
                settings->bundles[bundles_set].start = startPrbc+prb_start+(m*numBundPrb);
1537
                /* Start already beyond end, so doesn't count. */
1538
351
                if (settings->bundles[bundles_set].start > (startPrbc+numPrbc-1)) {
1539
14
                    break;
1540
14
                }
1541
                /* Bundle consists of numBundPrb bundles */
1542
                /* TODO: may involve PRBs from >1 rbg blocks.. */
1543
337
                settings->bundles[bundles_set].end = startPrbc+prb_start+((m+1)*numBundPrb)-1;
1544
337
                if (settings->bundles[bundles_set].end > (startPrbc+numPrbc-1)) {
1545
                    /* Extends beyond end, so counts but is an orphan bundle */
1546
1
                    settings->bundles[bundles_set].end = startPrbc+numPrbc-1;
1547
1
                    settings->bundles[bundles_set].is_orphan = true;
1548
1
                    reached_orphan = true;
1549
1
                }
1550
1551
                /* Get out if have reached array bound */
1552
337
                if (++bundles_set == MAX_BFW_BUNDLES) {
1553
0
                    return;
1554
0
                }
1555
337
            }
1556
57
        }
1557
5
        settings->num_bundles = bundles_set;
1558
5
    }
1559
1560
    /* Allocation configured by ext 12 */
1561
161
    else if (settings->ext12_set) {
1562
        /* First, allocate normally from startPrbc, numPrbc */
1563
27
        settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1564
1565
        /* Don't overflow settings->bundles[] ! */
1566
27
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1567
1568
484
        for (uint32_t n=0; n < settings->num_bundles; n++) {
1569
457
            settings->bundles[n].start = startPrbc + n*numBundPrb;
1570
457
            settings->bundles[n].end =   settings->bundles[n].start + numBundPrb-1;
1571
            /* Does it go beyond the end? */
1572
457
            if (settings->bundles[n].end > startPrbc+numPrbc) {
1573
22
                settings->bundles[n].end = startPrbc+numPrbc;
1574
22
                settings->bundles[n].is_orphan = true;
1575
22
            }
1576
457
        }
1577
27
        if (settings->num_bundles == MAX_BFW_BUNDLES) {
1578
0
            return;
1579
0
        }
1580
1581
27
        unsigned prb_offset = startPrbc + numPrbc;
1582
1583
        /* Loop over pairs, adding bundles for each */
1584
2.20k
        for (unsigned p=0; p < settings->ext12_num_pairs; p++) {
1585
2.18k
            prb_offset += settings->ext12_pairs[p].off_start_prb;
1586
2.18k
            unsigned pair_bundles = (settings->ext12_pairs[p].num_prb+numBundPrb-1) / numBundPrb;
1587
1588
9.85k
            for (uint32_t n=0; n < pair_bundles; n++) {
1589
7.68k
                unsigned idx = settings->num_bundles;
1590
1591
7.68k
                settings->bundles[idx].start = prb_offset + n*numBundPrb;
1592
7.68k
                settings->bundles[idx].end =   settings->bundles[idx].start + numBundPrb-1;
1593
                /* Does it go beyond the end? */
1594
7.68k
                if (settings->bundles[idx].end > prb_offset + settings->ext12_pairs[p].num_prb) {
1595
1.52k
                    settings->bundles[idx].end = prb_offset + settings->ext12_pairs[p].num_prb;
1596
1.52k
                    settings->bundles[idx].is_orphan = true;
1597
1.52k
                }
1598
                /* Range check / return */
1599
7.68k
                settings->num_bundles++;
1600
7.68k
                if (settings->num_bundles == MAX_BFW_BUNDLES) {
1601
10
                    return;
1602
10
                }
1603
7.68k
            }
1604
1605
2.17k
            prb_offset += settings->ext12_pairs[p].num_prb;
1606
2.17k
        }
1607
27
    }
1608
1609
    /* Allocation configured by ext 13 */
1610
134
    else if (settings->ext13_set) {
1611
16
        unsigned alloc_size = (numPrbc+numBundPrb-1) / numBundPrb;
1612
16
        settings->num_bundles = alloc_size * settings->ext13_num_start_prbs;
1613
1614
        /* Don't overflow settings->bundles[] ! */
1615
16
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1616
1617
1.18k
        for (unsigned alloc=0; alloc < settings->ext13_num_start_prbs; alloc++) {
1618
1.18k
            unsigned alloc_start = alloc * alloc_size;
1619
6.91k
            for (uint32_t n=0; n < alloc_size; n++) {
1620
5.74k
                if ((alloc_start+n) >= MAX_BFW_BUNDLES) {
1621
                    /* ERROR */
1622
8
                    return;
1623
8
                }
1624
5.73k
                settings->bundles[alloc_start+n].start = settings->ext13_start_prbs[alloc] + startPrbc + n*numBundPrb;
1625
5.73k
                settings->bundles[alloc_start+n].end =   settings->bundles[alloc_start+n].start + numBundPrb-1;
1626
5.73k
                if (settings->bundles[alloc_start+n].end > settings->ext13_start_prbs[alloc] + numPrbc) {
1627
3.40k
                    settings->bundles[alloc_start+n].end = settings->ext13_start_prbs[alloc] + numPrbc;
1628
3.40k
                    settings->bundles[alloc_start+n].is_orphan = true;
1629
3.40k
                }
1630
5.73k
            }
1631
1.18k
        }
1632
16
    }
1633
1634
    /* Case where bundles are not controlled by other extensions - just divide up range into bundles we have */
1635
118
    else {
1636
118
        settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;   /* rounded up */
1637
1638
        /* Don't overflow settings->bundles[] */
1639
118
        settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1640
1641
        /* For each bundle.. */
1642
7.63k
        for (uint32_t n=0; n < settings->num_bundles; n++) {
1643
            /* Allocate start and end */
1644
7.52k
            settings->bundles[n].start = startPrbc + n*numBundPrb;
1645
7.52k
            settings->bundles[n].end =   settings->bundles[n].start + numBundPrb - 1;
1646
            /* If would go beyond end of PRBs, limit and identify as orphan */
1647
7.52k
            if (settings->bundles[n].end > startPrbc+numPrbc) {
1648
73
                settings->bundles[n].end = startPrbc+numPrbc;
1649
73
                settings->bundles[n].is_orphan = true;
1650
73
            }
1651
7.52k
        }
1652
118
    }
1653
166
}
1654
1655
1656
/* Modulation Compression configuration */
1657
typedef struct  {
1658
    /* Application of each entry is filtered by RE.
1659
     * TODO: should also be filtered by PRB + symbol... */
1660
    uint16_t section_id;
1661
    uint16_t mod_compr_re_mask;
1662
1663
    /* Settings to apply */
1664
    bool     mod_compr_csf;
1665
    float    mod_compr_scaler;
1666
} mod_compr_config_t;
1667
1668
/* Multiple configs with a section */
1669
typedef struct {
1670
    uint16_t section_id;
1671
    uint32_t num_configs;
1672
1673
2.06k
    #define MAX_MOD_COMPR_CONFIGS 12
1674
    mod_compr_config_t configs[MAX_MOD_COMPR_CONFIGS];
1675
} section_mod_compr_config_t;
1676
1677
/* Flow has separate configs for each section */
1678
typedef struct {
1679
    uint16_t num_sections;
1680
1681
    /* Separate config for each section */
1682
    section_mod_compr_config_t sections[MAX_SECTION_IDs];
1683
} mod_compr_params_t;
1684
1685
1686
1687
/*******************************************************/
1688
/* Overall state of a flow (eAxC/plane)                */
1689
typedef struct {
1690
    /* State for sequence analysis [each direction] */
1691
    bool     last_frame_seen[2];
1692
    uint32_t last_frame[2];
1693
    uint8_t  next_expected_sequence_number[2];
1694
1695
    /* Table recording ackNack requests (ackNackId -> ack_nack_request_t*)
1696
       Note that this assumes that the same ackNackId will not be reused within a state,
1697
       which may well not be valid */
1698
    wmem_tree_t *ack_nack_requests;
1699
1700
    /* Store udCompHdr seen in C-Plane for UL - can be looked up and used by U-PLane.
1701
       Note that this appears in the common section header parts of ST1, ST3, ST5,
1702
       so can still be over-written per sectionId in the U-Plane */
1703
    unsigned ul_ud_comp_hdr_frame;
1704
    bool     ul_ud_comp_hdr_set;
1705
    unsigned ul_ud_comp_hdr_bit_width;
1706
    int      ul_ud_comp_hdr_compression;
1707
1708
    bool udcomphdrDownlink_heuristic_result_set;
1709
    bool udcomphdrDownlink_heuristic_result;
1710
    bool udcomphdrUplink_heuristic_result_set;
1711
    bool udcomphdrUplink_heuristic_result;
1712
1713
    /* Modulation compression params */
1714
    /* This probably needs to be per section!? */
1715
    mod_compr_params_t mod_comp_params;
1716
} flow_state_t;
1717
1718
static section_mod_compr_config_t* get_mod_compr_section_to_write(flow_state_t *flow,
1719
                                                           unsigned sectionId)
1720
2.06k
{
1721
2.06k
    if (flow == NULL) {
1722
0
        return NULL;
1723
0
    }
1724
1725
    /* Look for this section among existing entries */
1726
8.33k
    for (unsigned s=0; s < flow->mod_comp_params.num_sections; s++) {
1727
8.21k
        if (flow->mod_comp_params.sections[s].section_id == sectionId) {
1728
1.94k
            return &flow->mod_comp_params.sections[s];
1729
1.94k
        }
1730
8.21k
    }
1731
1732
    /* Not found, so try to add a new one */
1733
118
    if (flow->mod_comp_params.num_sections >= MAX_SECTION_IDs) {
1734
        /* Can't allocate one! */
1735
0
        return NULL;
1736
0
    }
1737
118
    else {
1738
118
        flow->mod_comp_params.sections[flow->mod_comp_params.num_sections].section_id = sectionId;
1739
118
        return &flow->mod_comp_params.sections[flow->mod_comp_params.num_sections++];
1740
118
    }
1741
118
}
1742
1743
static section_mod_compr_config_t* get_mod_compr_section_to_read(flow_state_t *flow,
1744
                                                           unsigned sectionId)
1745
875
{
1746
875
    if (flow == NULL) {
1747
345
        return NULL;
1748
345
    }
1749
1750
    /* Look for this section among existing entries */
1751
564
    for (unsigned s=0; s < flow->mod_comp_params.num_sections; s++) {
1752
34
        if (flow->mod_comp_params.sections[s].section_id == sectionId) {
1753
0
            return &flow->mod_comp_params.sections[s];
1754
0
        }
1755
34
    }
1756
1757
    /* Not found */
1758
530
    return NULL;
1759
530
}
1760
1761
1762
1763
typedef struct {
1764
    uint32_t request_frame_number;
1765
    nstime_t request_frame_time;
1766
    enum {
1767
        SE22,
1768
        ST4Cmd1,
1769
        ST4Cmd2,
1770
        ST4Cmd3,
1771
        ST4Cmd4
1772
    } requestType;
1773
1774
    uint32_t response_frame_number;
1775
    nstime_t response_frame_time;
1776
} ack_nack_request_t;
1777
1778
static const value_string acknack_type_vals[] = {
1779
    { SE22,    "SE 22" },
1780
    { ST4Cmd1, "ST4 (TIME_DOMAIN_BEAM_CONFIG)" },
1781
    { ST4Cmd2, "ST4 (TDD_CONFIG_PATTERN)" },
1782
    { ST4Cmd3, "ST4 (TRX_CONTROL)" },
1783
    { ST4Cmd4, "ST4 (ASM)" },
1784
    { 0, NULL}
1785
};
1786
1787
8.04k
#define ORAN_C_PLANE 0
1788
622
#define ORAN_U_PLANE 1
1789
1790
/* Using parts of src/dst MAC address, so don't confuse UL messages with DL messages configuring UL.. */
1791
static uint32_t make_flow_key(packet_info *pinfo, uint16_t eaxc_id, uint8_t plane, bool opposite_dir)
1792
3.27k
{
1793
3.27k
    uint16_t eth_bits = 0;
1794
3.27k
    if (pinfo->dl_src.len == 6 && pinfo->dl_dst.len == 6) {
1795
        /* Only using (most of) 2 bytes from addresses for now, but reluctant to make key longer.. */
1796
1.73k
        uint8_t *src_eth = (uint8_t*)pinfo->dl_src.data;
1797
1.73k
        uint8_t *dst_eth = (uint8_t*)pinfo->dl_dst.data;
1798
1.73k
        if (!opposite_dir) {
1799
1.55k
            eth_bits = (src_eth[0]<<8) | dst_eth[5];
1800
1.55k
        }
1801
179
        else {
1802
179
            eth_bits = (dst_eth[0]<<8) | src_eth[5];
1803
179
        }
1804
1.73k
    }
1805
3.27k
    return eaxc_id | (plane << 16) | (eth_bits << 17);
1806
3.27k
}
1807
1808
1809
/* Table maintained on first pass from flow_key(uint32_t) -> flow_state_t* */
1810
static wmem_tree_t *flow_states_table;
1811
1812
/* Table consulted on subsequent passes: frame_num -> flow_result_t* */
1813
static wmem_tree_t *flow_results_table;
1814
1815
typedef struct {
1816
    /* Sequence analysis */
1817
    bool     unexpected_seq_number;
1818
    uint8_t  expected_sequence_number;
1819
    uint32_t previous_frame;
1820
} flow_result_t;
1821
1822
1823
/* Uplink timing */
1824
/* For a given symbol, track first to last UL frame to find out first-last time */
1825
/* frameId (8) + subframeId (4) + slotId (6) + symbolId (6) = 24 bits */
1826
/* N.B. if a capture lasts > 2.5s, may see same timing come around again... */
1827
static uint32_t get_timing_key(uint8_t frameId, uint8_t subframeId, uint8_t slotId, uint8_t symbolId)
1828
0
{
1829
0
    return symbolId + (slotId<<8) + (subframeId<<14) + (frameId<<18);
1830
0
}
1831
1832
typedef struct {
1833
    uint32_t first_frame;
1834
    nstime_t first_frame_time;
1835
    uint32_t frames_seen_in_symbol;
1836
    uint32_t last_frame_in_symbol;
1837
} ul_timing_for_slot;
1838
1839
/* Set during first pass.  timing_key -> ul_timing_for_slot*  */
1840
static wmem_tree_t *ul_symbol_timing;
1841
1842
1843
static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
1844
                                          ack_nack_request_t *response);
1845
1846
1847
1848
1849
static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1850
    packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(4, 5);
1851
1852
 /* Write the given formatted text to:
1853
    - the info column (if pinfo != NULL)
1854
    - 1 or 2 other labels (optional)
1855
 */
1856
static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1857
    packet_info *pinfo, const char *format, ...)
1858
23.1k
{
1859
23.1k
#define MAX_INFO_BUFFER 256
1860
23.1k
    char info_buffer[MAX_INFO_BUFFER];
1861
23.1k
    va_list ap;
1862
1863
23.1k
    if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
1864
0
        return;
1865
0
    }
1866
1867
23.1k
    va_start(ap, format);
1868
23.1k
    vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1869
23.1k
    va_end(ap);
1870
1871
    /* Add to indicated places */
1872
23.1k
    if (pinfo != NULL) {
1873
23.1k
        col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1874
23.1k
    }
1875
23.1k
    if (ti1 != NULL) {
1876
23.1k
        proto_item_append_text(ti1, "%s", info_buffer);
1877
23.1k
    }
1878
23.1k
    if (ti2 != NULL) {
1879
20.5k
        proto_item_append_text(ti2, "%s", info_buffer);
1880
20.5k
    }
1881
23.1k
}
1882
1883
/* Add section labels (type + PRB range) for C-Plane, U-Plane */
1884
static void
1885
write_section_info(proto_item *section_heading, packet_info *pinfo, proto_item *protocol_item,
1886
                   uint32_t section_id, uint32_t start_prbx, uint32_t num_prbx, uint32_t rb)
1887
20.5k
{
1888
20.5k
    switch (num_prbx) {
1889
78
        case 0:
1890
            /* None -> all */
1891
78
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d     (all PRBs)", section_id);
1892
78
            break;
1893
932
        case 1:
1894
            /* Single PRB */
1895
932
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %7u)", section_id, start_prbx);
1896
932
            break;
1897
19.5k
        default:
1898
            /* Range */
1899
19.5k
            write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %3u-%3u%s)", section_id, start_prbx,
1900
19.5k
                                     start_prbx + (num_prbx-1)*(1+rb), rb ? " (every-other)" : "");
1901
20.5k
    }
1902
20.5k
}
1903
1904
static void
1905
write_channel_section_info(proto_item *section_heading, packet_info *pinfo,
1906
                           uint32_t section_id, uint32_t ueId, uint32_t start_prbx, uint32_t num_prbx,
1907
                           uint32_t num_trx)
1908
577
{
1909
577
    switch (num_prbx) {
1910
319
        case 0:
1911
            /* TODO: ?? */
1912
319
            break;
1913
31
        case 1:
1914
            /* Single PRB */
1915
31
            write_pdu_label_and_info(section_heading, NULL, pinfo,
1916
31
                                     ", Id: %4d (UEId=%5u  PRB %7u, %2u antennas)",
1917
31
                                     section_id, ueId, start_prbx, num_trx);
1918
31
            break;
1919
227
        default:
1920
            /* Range */
1921
227
            write_pdu_label_and_info(section_heading, NULL, pinfo,
1922
227
                                     ", Id: %4d (UEId=%5u  PRBs %3u-%3u, %2u antennas)",
1923
227
                                     section_id, ueId, start_prbx, start_prbx+num_prbx-1, num_trx);
1924
577
    }
1925
577
}
1926
1927
/* Add a reserved field, and warn if value isn't 0 */
1928
/* TODO: maybe add a pref not to output expert warning if becomes too annoying? */
1929
static void add_reserved_field(proto_tree *tree, int hf, tvbuff_t *tvb, int offset, int len)
1930
62.3k
{
1931
62.3k
    uint32_t reserved;
1932
62.3k
    proto_item *res_ti = proto_tree_add_item_ret_uint(tree, hf, tvb, offset, len, ENC_NA, &reserved);
1933
62.3k
    if (reserved != 0) {
1934
34.8k
        expert_add_info_format(NULL, res_ti, &ei_oran_reserved_not_zero,
1935
34.8k
                               "reserved field saw value of 0x%x", reserved);
1936
34.8k
    }
1937
62.3k
}
1938
1939
/* 5.1.3.2.7 (real time control data / IQ data transfer message series identifier) */
1940
static void
1941
addPcOrRtcid(tvbuff_t *tvb, proto_tree *tree, int *offset, int hf, uint16_t *eAxC)
1942
2.68k
{
1943
    /* Subtree */
1944
2.68k
    proto_item *oran_pcid_ti = proto_tree_add_item(tree, hf,
1945
2.68k
                                                   tvb, *offset, 2, ENC_NA);
1946
2.68k
    proto_tree *oran_pcid_tree = proto_item_add_subtree(oran_pcid_ti, ett_oran_ecpri_pcid);
1947
1948
2.68k
    uint64_t duPortId, bandSectorId, ccId, ruPortId = 0;
1949
2.68k
    int id_offset = *offset;
1950
1951
    /* All parts of eAxC should be above 0, and should total 16 bits (breakdown controlled by preferences) */
1952
2.68k
    if (!((pref_du_port_id_bits > 0) && (pref_bandsector_id_bits > 0) && (pref_cc_id_bits > 0) && (pref_ru_port_id_bits > 0) &&
1953
2.68k
         ((pref_du_port_id_bits + pref_bandsector_id_bits + pref_cc_id_bits + pref_ru_port_id_bits) == 16))) {
1954
0
        expert_add_info(NULL, tree, &ei_oran_invalid_eaxc_bit_width);
1955
0
        *eAxC = 0;
1956
0
        *offset += 2;
1957
0
        return;
1958
0
    }
1959
1960
2.68k
    unsigned bit_offset = *offset * 8;
1961
1962
    /* N.B. For sequence analysis / tapping, just interpret these 2 bytes as eAxC ID... */
1963
2.68k
    *eAxC = tvb_get_uint16(tvb, *offset, ENC_BIG_ENDIAN);
1964
1965
    /* DU Port ID */
1966
2.68k
    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);
1967
2.68k
    bit_offset += pref_du_port_id_bits;
1968
    /* BandSector ID */
1969
2.68k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_bandsector_id, tvb, bit_offset, pref_bandsector_id_bits, &bandSectorId, ENC_BIG_ENDIAN);
1970
2.68k
    bit_offset += pref_bandsector_id_bits;
1971
    /* CC ID */
1972
2.68k
    proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_cc_id, tvb, bit_offset, pref_cc_id_bits, &ccId, ENC_BIG_ENDIAN);
1973
2.68k
    bit_offset += pref_cc_id_bits;
1974
    /* RU Port ID */
1975
2.68k
    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);
1976
2.68k
    *offset += 2;
1977
1978
2.68k
    proto_item_append_text(oran_pcid_ti, " (DU_Port_ID: %d, BandSector_ID: %d, CC_ID: %d, RU_Port_ID: %d)",
1979
2.68k
                           (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1980
2.68k
    char id[16];
1981
2.68k
    snprintf(id, 16, "%x:%x:%x:%x", (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1982
2.68k
    proto_item *pi = proto_tree_add_string(oran_pcid_tree, hf_oran_c_eAxC_ID, tvb, id_offset, 2, id);
1983
2.68k
    proto_item_set_generated(pi);
1984
2.68k
}
1985
1986
/* Uniquely identify the U-plane stream that may need to be reassembled */
1987
static uint32_t make_reassembly_id(uint32_t seqid, uint32_t direction, uint16_t eAxC,
1988
                                   uint8_t frameid, uint8_t subframeid,
1989
                                   uint8_t slotid,  uint8_t symbolid)
1990
66
{
1991
    /* N.B., no room in 32-bits for all of this info, so cut down some of the fields
1992
       and hope for no collisions */
1993
66
    return (seqid << 24) | (direction << 23) | (slotid << 22) | (subframeid << 18) |
1994
66
           (frameid << 9) | (symbolid << 6) | (eAxC & 0x3f);
1995
66
}
1996
1997
/* 5.1.3.2.8  ecpriSeqid (message identifier) */
1998
/* Return out info that may be used for sequence number analysis and reassembly */
1999
static int
2000
addSeqid(tvbuff_t *tvb, proto_tree *oran_tree, int offset, int plane, uint32_t *seq_id, proto_item **seq_id_ti, packet_info *pinfo,
2001
         uint32_t *subseqid, uint32_t *e)
2002
2.67k
{
2003
    /* Subtree */
2004
2.67k
    proto_item *seqIdItem = proto_tree_add_item(oran_tree, hf_oran_ecpri_seqid, tvb, offset, 2, ENC_NA);
2005
2.67k
    proto_tree *oran_seqid_tree = proto_item_add_subtree(seqIdItem, ett_oran_ecpri_seqid);
2006
2007
    /* Sequence ID (8 bits) */
2008
2.67k
    *seq_id_ti = proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_sequence_id, tvb, offset, 1, ENC_NA, seq_id);
2009
2.67k
    offset += 1;
2010
2011
    /* Show link back to previous sequence ID, if set */
2012
2.67k
    flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
2013
2.67k
    if (result) {
2014
11
        proto_item *prev_ti = proto_tree_add_uint(oran_seqid_tree, hf_oran_previous_frame, tvb, 0, 0, result->previous_frame);
2015
11
        proto_item_set_generated(prev_ti);
2016
11
    }
2017
2018
    /* E bit */
2019
2.67k
    proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_e_bit, tvb, offset, 1, ENC_NA, e);
2020
    /* Subsequence ID (7 bits) */
2021
2.67k
    proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_subsequence_id, tvb, offset, 1, ENC_NA, subseqid);
2022
2.67k
    offset += 1;
2023
2024
    /* radio-transport fragmentation not allowed for C-Plane messages */
2025
2.67k
    if (plane == ORAN_C_PLANE) {
2026
2.37k
        if (*e !=1 || *subseqid != 0) {
2027
2.30k
            expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_c_plane);
2028
2.30k
        }
2029
2.37k
    }
2030
2031
    /* Summary */
2032
2.67k
    proto_item_append_text(seqIdItem, " (SeqId: %3d, E: %d, SubSeqId: %d)", *seq_id, *e, *subseqid);
2033
2.67k
    return offset;
2034
2.67k
}
2035
2036
static int dissect_symbolmask(tvbuff_t *tvb, proto_tree *tree, int offset, uint32_t *symbol_mask, proto_item **ti)
2037
954
{
2038
954
    uint64_t temp_val;
2039
2040
954
    static int * const  symbol_mask_flags[] = {
2041
954
        &hf_oran_symbol_mask_s13,
2042
954
        &hf_oran_symbol_mask_s12,
2043
954
        &hf_oran_symbol_mask_s11,
2044
954
        &hf_oran_symbol_mask_s10,
2045
954
        &hf_oran_symbol_mask_s9,
2046
954
        &hf_oran_symbol_mask_s8,
2047
954
        &hf_oran_symbol_mask_s7,
2048
954
        &hf_oran_symbol_mask_s6,
2049
954
        &hf_oran_symbol_mask_s5,
2050
954
        &hf_oran_symbol_mask_s4,
2051
954
        &hf_oran_symbol_mask_s3,
2052
954
        &hf_oran_symbol_mask_s2,
2053
954
        &hf_oran_symbol_mask_s1,
2054
954
        &hf_oran_symbol_mask_s0,
2055
954
        NULL
2056
954
    };
2057
2058
954
    proto_item *temp_ti = proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
2059
954
                                                            hf_oran_symbol_mask,
2060
954
                                                            ett_oran_symbol_mask, symbol_mask_flags,
2061
954
                                                            ENC_BIG_ENDIAN, &temp_val);
2062
    /* Set out parameters */
2063
954
    if (symbol_mask) {
2064
231
        *symbol_mask = (uint32_t)temp_val;
2065
231
    }
2066
954
    if (ti) {
2067
231
        *ti = temp_ti;
2068
231
    }
2069
954
    return offset+2;
2070
954
}
2071
2072
/* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
2073
static int dissect_bfwCompHdr(tvbuff_t *tvb, proto_tree *tree, int offset,
2074
                              uint32_t *iq_width, uint32_t *comp_meth, proto_item **comp_meth_ti)
2075
561
{
2076
    /* Subtree */
2077
561
    proto_item *bfwcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompHdr,
2078
561
                                                            tvb, offset, 1, "",
2079
561
                                                            "bfwCompHdr");
2080
561
    proto_tree *bfwcomphdr_tree = proto_item_add_subtree(bfwcomphdr_ti, ett_oran_bfwcomphdr);
2081
2082
    /* Width and method */
2083
561
    proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_iqWidth,
2084
561
                                 tvb, offset, 1, ENC_BIG_ENDIAN,  iq_width);
2085
    /* Special case: 0 -> 16 */
2086
561
    *iq_width = (*iq_width==0) ? 16 : *iq_width;
2087
561
    *comp_meth_ti = proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_compMeth,
2088
561
                                                 tvb, offset, 1, ENC_BIG_ENDIAN, comp_meth);
2089
561
    offset++;
2090
2091
    /* Summary */
2092
561
    proto_item_append_text(bfwcomphdr_ti, " (IqWidth=%u, compMeth=%s)",
2093
561
                           *iq_width,
2094
561
                           val_to_str_const(*comp_meth, bfw_comp_headers_comp_meth, "reserved"));
2095
2096
561
    return offset;
2097
561
}
2098
2099
/* Return offset */
2100
/* Returning number of entries set - would be good to also return an array of set TRX# so could show which array element
2101
   each BFW is actually for.. */
2102
static int dissect_active_beamspace_coefficient_mask(tvbuff_t *tvb, proto_tree *tree, int offset, unsigned *num_trx_entries, uint16_t **trx_entries)
2103
977
{
2104
    /* activeBeamspaceCoefficientMask - ceil(K/8) octets */
2105
    /* K is the number of elements in uncompressed beamforming weight vector.
2106
     * Calculated from parameters describing tx-array or tx-array */
2107
977
    unsigned k_octets = (pref_num_bf_antennas + 7) / 8;
2108
2109
977
    static uint16_t trx_enabled[1024];
2110
2111
    /* TODO: could use a bigger bitmask array, but for now just uses this bytes-worth for each byte */
2112
977
    static int * const mask_bits[] = {
2113
977
        &hf_oran_active_beamspace_coefficient_n1,
2114
977
        &hf_oran_active_beamspace_coefficient_n2,
2115
977
        &hf_oran_active_beamspace_coefficient_n3,
2116
977
        &hf_oran_active_beamspace_coefficient_n4,
2117
977
        &hf_oran_active_beamspace_coefficient_n5,
2118
977
        &hf_oran_active_beamspace_coefficient_n6,
2119
977
        &hf_oran_active_beamspace_coefficient_n7,
2120
977
        &hf_oran_active_beamspace_coefficient_n8,
2121
977
        NULL
2122
977
    };
2123
2124
977
    *num_trx_entries = 0;
2125
977
    uint64_t val;
2126
4.87k
    for (unsigned n=0; n < k_octets; n++) {
2127
3.89k
        proto_tree_add_bitmask_ret_uint64(tree, tvb, offset,
2128
3.89k
                                          hf_oran_activeBeamspaceCoefficientMask,
2129
3.89k
                                          ett_oran_active_beamspace_coefficient_mask, mask_bits,
2130
3.89k
                                          ENC_BIG_ENDIAN, &val);
2131
3.89k
        offset++;
2132
        /* Add up the set bits for this byte (but be careful not to count beyond last real K bit..) */
2133
34.9k
        for (unsigned b=0; b < 8; b++) {
2134
31.0k
            if ((1 << b) & (unsigned)val) {
2135
11.3k
                if (((n*8)+b) < pref_num_bf_antennas) {
2136
11.3k
                    if (*num_trx_entries < 1024-1) {   /* Don't write beyond array (which should be plenty big) */
2137
11.3k
                        trx_enabled[(*num_trx_entries)++] = (n*8) + b + 1;
2138
11.3k
                    }
2139
11.3k
                }
2140
11.3k
            }
2141
31.0k
        }
2142
3.89k
    }
2143
    /* Set pointer to static array */
2144
977
    *trx_entries = trx_enabled;
2145
2146
    /* Show how many bits set */
2147
977
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_activeBeamspaceCoefficientMask_bits_set, tvb,
2148
977
                                         offset-k_octets, k_octets, *num_trx_entries);
2149
977
    proto_item_set_generated(ti);
2150
2151
977
    return offset;
2152
977
}
2153
2154
/* 7.7.1.3 bfwCompParam (beamforming weight compression parameter).
2155
 * Depends upon passed-in bfwCompMeth (field may be empty) */
2156
static int dissect_bfwCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset,
2157
                                proto_item *meth_ti, uint32_t *bfw_comp_method,
2158
                                uint32_t *exponent, bool *supported, unsigned *num_trx_entries, uint16_t **trx_entries)
2159
2.56k
{
2160
2.56k
    if (*bfw_comp_method == COMP_NONE) {
2161
        /* Absent! */
2162
271
        *num_trx_entries = 0;
2163
271
        *supported = true;
2164
271
        return offset;
2165
271
    }
2166
2167
    /* Subtree */
2168
2.29k
    proto_item *bfwcompparam_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompParam,
2169
2.29k
                                                               tvb, offset, 1, "",
2170
2.29k
                                                              "bfwCompParam");
2171
2.29k
    proto_tree *bfwcompparam_tree = proto_item_add_subtree(bfwcompparam_ti, ett_oran_bfwcompparam);
2172
2173
2.29k
    proto_item_append_text(bfwcompparam_ti,
2174
2.29k
                           " (meth=%s)", val_to_str_const(*bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
2175
2176
2.29k
    *num_trx_entries = 0;
2177
2.29k
    *supported = false;
2178
2.29k
    switch (*bfw_comp_method) {
2179
612
        case COMP_BLOCK_FP:     /* block floating point */
2180
            /* 4 reserved bits +  exponent */
2181
612
            add_reserved_field(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
2182
612
            proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent,
2183
612
                                         tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
2184
612
            proto_item_append_text(bfwcompparam_ti, " exponent=%u", *exponent);
2185
612
            *supported = true;
2186
612
            offset++;
2187
612
            break;
2188
90
        case COMP_BLOCK_SCALE:  /* block scaling */
2189
            /* Separate into integer and fractional bits? */
2190
90
            proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
2191
90
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2192
90
            offset++;
2193
90
            break;
2194
94
        case COMP_U_LAW:        /* u-law */
2195
            /* compBitWidth, compShift */
2196
94
            proto_tree_add_item(bfwcompparam_tree, hf_oran_compBitWidth,
2197
94
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2198
94
            proto_tree_add_item(bfwcompparam_tree, hf_oran_compShift,
2199
94
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2200
94
            offset++;
2201
94
            break;
2202
149
        case 4:                 /* beamspace I (BLOCK SCALING) */
2203
            /* activeBeamspaceCoefficientMask */
2204
149
            offset = dissect_active_beamspace_coefficient_mask(tvb, bfwcompparam_tree, offset, num_trx_entries, trx_entries);
2205
149
            *bfw_comp_method = COMP_BLOCK_SCALE;
2206
149
            *supported = false;                  /* TODO: true once BLOCK SCALE is supported */
2207
149
            proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
2208
149
                                tvb, offset, 1, ENC_BIG_ENDIAN);
2209
149
            offset++;
2210
149
            break;
2211
828
        case 5:                 /* beamspace II (BLOCK FLOATING POINT) */
2212
            /* activeBeamspaceCoefficientMask */
2213
828
            offset = dissect_active_beamspace_coefficient_mask(tvb, bfwcompparam_tree, offset, num_trx_entries, trx_entries);
2214
            /* reserved (4 bits) + exponent (4 bits) */
2215
828
            add_reserved_field(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
2216
828
            proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent, tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
2217
828
            offset += 1;
2218
828
            *bfw_comp_method = COMP_BLOCK_FP;
2219
828
            *supported = true;
2220
828
            break;
2221
2222
518
        default:
2223
            /* Not handled */
2224
518
             break;
2225
2.29k
    }
2226
2227
2.27k
    proto_item_set_end(bfwcompparam_ti, tvb, offset);
2228
2229
    /* Can't go on if compression scheme not supported */
2230
2.27k
    if (!(*supported) && meth_ti) {
2231
846
        expert_add_info_format(pinfo, meth_ti, &ei_oran_unsupported_bfw_compression_method,
2232
846
                               "BFW Compression method %u (%s) not decompressed by dissector",
2233
846
                               *bfw_comp_method,
2234
846
                               val_to_str_const(*bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
2235
846
    }
2236
2.27k
    return offset;
2237
2.29k
}
2238
2239
2240
/* Special case for uncompressed/16-bit value */
2241
static float uncompressed_to_float(uint32_t h)
2242
26.7k
{
2243
26.7k
    int16_t i16 = h & 0x0000ffff;
2244
26.7k
    if (show_unscaled_values) {
2245
0
        return (float)i16;
2246
0
    }
2247
26.7k
    return ((float)i16) / 0x7fff;
2248
26.7k
}
2249
2250
/* Decompress I/Q value, taking into account method, width, exponent, other input-specific methods */
2251
static float decompress_value(uint32_t bits, uint32_t comp_method, uint8_t iq_width,
2252
                              uint32_t exponent,
2253
                              /* Modulation compression settings. N.B. should also pass in PRB + symbol? */
2254
                              section_mod_compr_config_t *m_c_p, uint8_t re)
2255
280k
{
2256
280k
    switch (comp_method) {
2257
26.7k
        case COMP_NONE: /* no compression */
2258
26.7k
            return uncompressed_to_float(bits);
2259
2260
104k
        case COMP_BLOCK_FP:         /* block floating point */
2261
143k
        case BFP_AND_SELECTIVE_RE:
2262
143k
        {
2263
            /* A.1.3 Block Floating Point Decompression Algorithm */
2264
143k
            int32_t cPRB = bits;
2265
143k
            uint32_t scaler = 1 << exponent;  /* i.e. 2^exponent */
2266
2267
            /* Check last bit, in case we need to flip to -ve */
2268
143k
            if (cPRB >= (1<<(iq_width-1))) {
2269
58.3k
                cPRB -= (1<<iq_width);
2270
58.3k
            }
2271
2272
            /* Unscale (8.1.3.1) */
2273
143k
            cPRB *= scaler;
2274
143k
            if (show_unscaled_values) {
2275
0
                return (float)cPRB;
2276
0
            }
2277
2278
143k
            uint32_t mantissa_scale_factor = 1 << (iq_width-1); /* 2^(mantissabits-1) */
2279
143k
            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 */
2280
2281
143k
            float ret = cPRB / ((float)(mantissa_scale_factor*exp_scale_factor));
2282
143k
            return ret;
2283
143k
        }
2284
2285
27.5k
        case COMP_BLOCK_SCALE:
2286
46.0k
        case COMP_U_LAW:
2287
            /* Not supported! But will be reported as expert info outside of this function! */
2288
46.0k
            return 0.0;
2289
2290
5.83k
        case COMP_MODULATION:
2291
33.5k
        case MOD_COMPR_AND_SELECTIVE_RE:
2292
33.5k
        {
2293
            /* Described in A.5 (with pseudo code) */
2294
            /* N.B., Applies to downlink data only - is not used for BFW */
2295
2296
            /* Defaults if not overridden. TODO: what should these be? */
2297
33.5k
            bool csf = false;
2298
33.5k
            float mcScaler = (float)(1 << 11);
2299
2300
            /* Find csf + mcScaler to use. Non-default configs gleaned from SE 4,5,23 */
2301
            /* TODO: should ideally be filtering by symbol and PRB too (at least from SE23) */
2302
33.5k
            if (re > 0 && m_c_p && m_c_p->num_configs > 0) {
2303
0
                for (unsigned c=0; c<m_c_p->num_configs; c++) {
2304
0
                    if (m_c_p->configs[c].mod_compr_re_mask & (1 << (12-re))) {
2305
                        /* Return first (should be only) found */
2306
0
                        csf = m_c_p->configs[c].mod_compr_csf;
2307
0
                        mcScaler = m_c_p->configs[c].mod_compr_scaler;
2308
0
                        break;
2309
0
                    }
2310
0
                }
2311
0
            }
2312
2313
33.5k
            int32_t cPRB = bits;
2314
2315
            /* 2) Map iqSample to iqSampleFx */
2316
            /* Check last bit, in case we need to flip to -ve */
2317
33.5k
            if (cPRB >= (1<<(iq_width-1))) {
2318
14.0k
                cPRB -= (1<<iq_width);
2319
14.0k
            }
2320
33.5k
            float iqSampleFx = (float)cPRB / (1 << (iq_width-1));
2321
2322
2323
            /* 3) or 4) (b) - add unshifted value if csf set */
2324
33.5k
            float csf_to_add = 0.0;
2325
33.5k
            if (csf) {
2326
                /* Unshift the constellation point */
2327
0
                csf_to_add = (float)2.0 / (1 << (iq_width));
2328
0
            }
2329
33.5k
            iqSampleFx += csf_to_add;
2330
2331
            /* 3) or 4) (c) - unscaling */
2332
33.5k
            float iqSampleScaled = mcScaler * iqSampleFx * (float)sqrt(2);
2333
33.5k
            return iqSampleScaled;
2334
5.83k
        }
2335
2336
30.3k
        default:
2337
            /* Not supported! But will be reported as expert info outside of this function! */
2338
30.3k
            return 0.0;
2339
280k
    }
2340
280k
}
2341
2342
/* Out-of-range value used for special case */
2343
#define ORPHAN_BUNDLE_NUMBER 999
2344
2345
/* Bundle of PRBs/TRX I/Q samples (ext 11) */
2346
static uint32_t dissect_bfw_bundle(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, unsigned offset,
2347
                                  proto_item *comp_meth_ti, uint32_t bfwcomphdr_comp_meth,
2348
                                  section_mod_compr_config_t *mod_compr_params,
2349
                                  uint32_t num_weights_per_bundle,
2350
                                  uint8_t iq_width,
2351
                                  unsigned bundle_number,
2352
                                  unsigned first_prb, unsigned last_prb, bool is_orphan)
2353
1.11k
{
2354
    /* Set bundle name */
2355
1.11k
    char bundle_name[32];
2356
1.11k
    if (!is_orphan) {
2357
1.05k
        snprintf(bundle_name, 32, "Bundle %3u", bundle_number);
2358
1.05k
    }
2359
57
    else {
2360
57
        g_strlcpy(bundle_name, "Orphaned  ", 32);
2361
57
    }
2362
2363
    /* Create Bundle root */
2364
1.11k
    proto_item *bundle_ti;
2365
1.11k
    if (first_prb != last_prb) {
2366
445
        bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
2367
445
                                                 tvb, offset, 0, "",
2368
445
                                                 "%s: (PRBs %3u-%3u)",
2369
445
                                                 bundle_name,
2370
445
                                                 first_prb, last_prb);
2371
445
    }
2372
668
    else {
2373
668
        bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
2374
668
                                                 tvb, offset, 0, "",
2375
668
                                                 "%s: (PRB %3u)",
2376
668
                                                 bundle_name,
2377
668
                                                 first_prb);
2378
668
    }
2379
1.11k
    proto_tree *bundle_tree = proto_item_add_subtree(bundle_ti, ett_oran_bfw_bundle);
2380
2381
    /* Generated bundle id */
2382
1.11k
    proto_item *bundleid_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfw_bundle_id, tvb, 0, 0,
2383
1.11k
                                                  bundle_number);
2384
1.11k
    proto_item_set_generated(bundleid_ti);
2385
1.11k
    proto_item_set_hidden(bundleid_ti);
2386
2387
    /* bfwCompParam */
2388
1.11k
    bool compression_method_supported = false;
2389
1.11k
    unsigned exponent = 0;
2390
1.11k
    unsigned num_trx_entries = 0;
2391
1.11k
    uint16_t *trx_entries;
2392
1.11k
    offset = dissect_bfwCompParam(tvb, bundle_tree, pinfo, offset, comp_meth_ti,
2393
1.11k
                                  &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
2394
1.11k
                                  &num_trx_entries, &trx_entries);
2395
2396
    /* Create Bundle subtree */
2397
1.11k
    int bit_offset = offset*8;
2398
1.11k
    int bfw_offset;
2399
2400
    /* contInd */
2401
1.11k
    proto_tree_add_item(bundle_tree, hf_oran_cont_ind,
2402
1.11k
                        tvb, offset, 1, ENC_BIG_ENDIAN);
2403
    /* beamId */
2404
1.11k
    uint32_t beam_id;
2405
1.11k
    proto_tree_add_item_ret_uint(bundle_tree, hf_oran_beam_id, tvb, offset, 2, ENC_BIG_ENDIAN, &beam_id);
2406
1.11k
    proto_item_append_text(bundle_ti, " (beamId:%u) ", beam_id);
2407
1.11k
    bit_offset += 16;
2408
2409
    /* Number of weights per bundle (from preference) */
2410
1.11k
    proto_item *wpb_ti = proto_tree_add_uint(bundle_tree, hf_oran_num_weights_per_bundle, tvb, 0, 0,
2411
1.11k
                                             num_weights_per_bundle);
2412
1.11k
    proto_item_set_generated(wpb_ti);
2413
2414
    /* Add the weights for this bundle. Overwrite with what was seen in bfwCompParam if beamspace */
2415
1.11k
    if (num_trx_entries != 0) {
2416
806
        num_weights_per_bundle = num_trx_entries;
2417
806
    }
2418
2419
19.0k
    for (unsigned w=0; w < num_weights_per_bundle; w++) {
2420
2421
17.9k
        uint16_t trx_index = (num_trx_entries) ? trx_entries[w] : w+1;
2422
2423
        /* Create subtree */
2424
17.9k
        bfw_offset = bit_offset / 8;
2425
17.9k
        uint8_t bfw_extent = ((bit_offset + (iq_width*2)) / 8) - bfw_offset;
2426
17.9k
        proto_item *bfw_ti = proto_tree_add_string_format(bundle_tree, hf_oran_bfw,
2427
17.9k
                                                          tvb, bfw_offset, bfw_extent,
2428
17.9k
                                                          "", "TRX %3u: (", trx_index);
2429
17.9k
        proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
2430
2431
        /* I */
2432
        /* Get bits, and convert to float. */
2433
17.9k
        uint32_t bits = tvb_get_bits32(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
2434
17.9k
        float value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width,
2435
17.9k
                                       exponent, mod_compr_params, 0 /* RE */);
2436
        /* Add to tree. */
2437
17.9k
        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);
2438
17.9k
        bit_offset += iq_width;
2439
17.9k
        proto_item_append_text(bfw_ti, "I%u=%f ", w, value);
2440
2441
        /* Q */
2442
        /* Get bits, and convert to float. */
2443
17.9k
        bits = tvb_get_bits32(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
2444
17.9k
        value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width,
2445
17.9k
                                 exponent, mod_compr_params, 0 /* RE */);
2446
        /* Add to tree. */
2447
17.9k
        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);
2448
17.9k
        bit_offset += iq_width;
2449
17.9k
        proto_item_append_text(bfw_ti, "Q%u=%f)", w, value);
2450
17.9k
    }
2451
2452
    /* Set extent of bundle */
2453
1.11k
    proto_item_set_end(bundle_ti, tvb, (bit_offset+7)/8);
2454
2455
1.11k
    return (bit_offset+7)/8;
2456
1.11k
}
2457
2458
/* Return new bit offset.  in/out will always be byte-aligned.. */
2459
static int dissect_ciCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, unsigned bit_offset,
2460
                               unsigned comp_meth, uint8_t *exponent)
2461
1.23k
{
2462
1.23k
    if (comp_meth == COMP_NONE) {
2463
        /* Nothing in frame so don't even create subtree */
2464
78
        return bit_offset;
2465
78
    }
2466
2467
    /* Subtree */
2468
1.15k
    proto_item *cicompparam_ti = proto_tree_add_string_format(tree, hf_oran_ciCompParam,
2469
1.15k
                                                            tvb, bit_offset/8, 1, "",
2470
1.15k
                                                            "ciCompParam");
2471
1.15k
    proto_tree *cicompparam_tree = proto_item_add_subtree(cicompparam_ti, ett_oran_cicompparam);
2472
1.15k
    uint32_t ci_exponent;
2473
2474
    /* Contents differ by compression method */
2475
1.15k
    switch (comp_meth) {
2476
349
        case COMP_BLOCK_FP:
2477
349
            add_reserved_field(cicompparam_tree, hf_oran_reserved_4bits, tvb, bit_offset/8, 1);
2478
349
            proto_tree_add_item_ret_uint(cicompparam_tree, hf_oran_exponent,
2479
349
                                         tvb, bit_offset/8, 1, ENC_BIG_ENDIAN, &ci_exponent);
2480
349
            *exponent = ci_exponent;
2481
349
            proto_item_append_text(cicompparam_ti, " (Exponent=%u)", ci_exponent);
2482
349
            bit_offset += 8; /* one byte */
2483
349
            break;
2484
248
        case COMP_BLOCK_SCALE:
2485
            /* Separate into integer (1) and fractional (7) bits? */
2486
248
            proto_tree_add_item(cicompparam_tree, hf_oran_blockScaler,
2487
248
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2488
248
            bit_offset += 8;
2489
248
            break;
2490
166
        case COMP_U_LAW:
2491
            /* compBitWidth, compShift (4 bits each) */
2492
166
            proto_tree_add_item(cicompparam_tree, hf_oran_compBitWidth,
2493
166
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2494
166
            proto_tree_add_item(cicompparam_tree, hf_oran_compShift,
2495
166
                                tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
2496
166
            bit_offset += 8;
2497
166
            break;
2498
2499
388
        default:
2500
            /* reserved, ? bytes of zeros.. */
2501
388
            break;
2502
1.15k
    }
2503
2504
1.15k
    return bit_offset;
2505
1.15k
}
2506
2507
/* frameStructure (7.5.2.13) */
2508
static unsigned dissect_frame_structure(proto_item *tree, tvbuff_t *tvb, unsigned offset,
2509
                                        uint32_t subframeId, uint32_t slotId)
2510
604
{
2511
604
    uint32_t scs;
2512
    /* FFT Size (4 bits) */
2513
604
    proto_tree_add_item(tree, hf_oran_frameStructure_fft, tvb, offset, 1, ENC_NA);
2514
    /* Subcarrier spacing (SCS) */
2515
604
    proto_tree_add_item_ret_uint(tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
2516
2517
    /* Show slot within frame as a generated field. See table 7.5.13-3 */
2518
604
    uint32_t slots_per_subframe = 1;
2519
604
    if (scs <= 4) {
2520
399
        slots_per_subframe = 1 << scs;
2521
399
    }
2522
604
    if (scs <= 4 || scs >= 12) {
2523
527
        proto_item *ti = proto_tree_add_uint(tree, hf_oran_slot_within_frame, tvb, 0, 0,
2524
527
                                             (slots_per_subframe*subframeId) + slotId);
2525
527
        proto_item_set_generated(ti);
2526
527
    }
2527
604
    return offset + 1;
2528
604
}
2529
2530
static unsigned dissect_csf(proto_item *tree, tvbuff_t *tvb, unsigned bit_offset,
2531
                            unsigned iq_width, bool *p_csf)
2532
2.08k
{
2533
2.08k
    proto_item *csf_ti;
2534
2.08k
    uint64_t csf;
2535
2.08k
    csf_ti = proto_tree_add_bits_ret_val(tree, hf_oran_csf, tvb, bit_offset, 1, &csf, ENC_BIG_ENDIAN);
2536
2.08k
    if (csf) {
2537
        /* Table 7.7.4.2-1 Constellation shift definition (index is udIqWidth) */
2538
831
        const char* shift_value[] = { "n/a", "1/2", "1/4", "1/8", "1/16", "1/32" };
2539
831
        if (iq_width >=1 && iq_width <= 5) {
2540
183
            proto_item_append_text(csf_ti, " (Shift Value is %s)", shift_value[iq_width]);
2541
183
        }
2542
831
    }
2543
2544
    /* Set out parameter */
2545
2.08k
    if (p_csf != NULL) {
2546
2.07k
        *p_csf = (csf!=0);
2547
2.07k
    }
2548
2.08k
    return bit_offset+1;
2549
2.08k
}
2550
2551
2552
/* Section 7.
2553
 * N.B. these are the green parts of the tables showing Section Types, differing by section Type */
2554
static int dissect_oran_c_section(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
2555
                                  flow_state_t* state,
2556
                                  uint32_t sectionType, oran_tap_info *tap_info, proto_item *protocol_item,
2557
                                  uint32_t subframeId, uint32_t slotId,
2558
                                  uint8_t ci_iq_width, uint8_t ci_comp_meth, unsigned ci_comp_opt,
2559
                                  unsigned num_sinr_per_prb)
2560
20.5k
{
2561
20.5k
    unsigned offset = 0;
2562
20.5k
    proto_tree *c_section_tree = NULL;
2563
20.5k
    proto_item *sectionHeading = NULL;
2564
2565
    /* Section subtree */
2566
20.5k
    sectionHeading = proto_tree_add_string_format(tree, hf_oran_c_section,
2567
20.5k
                                                  tvb, offset, 0, "", "Section");
2568
20.5k
    c_section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section);
2569
2570
20.5k
    uint32_t sectionId = 0;
2571
2572
20.5k
    uint32_t startPrbc=0, startPrbu=0;
2573
20.5k
    uint32_t numPrbc=0, numPrbu=0;
2574
20.5k
    uint32_t ueId = 0;
2575
20.5k
    proto_item *ueId_ti = NULL;
2576
20.5k
    uint32_t beamId = 0;
2577
20.5k
    proto_item *beamId_ti = NULL;
2578
20.5k
    bool beamId_ignored = false;
2579
2580
20.5k
    proto_item *numsymbol_ti = NULL;
2581
20.5k
    bool numsymbol_ignored = false;
2582
2583
20.5k
    proto_item *numprbc_ti = NULL;
2584
2585
    /* Config affecting ext11 bundles (initially unset) */
2586
20.5k
    ext11_settings_t ext11_settings;
2587
20.5k
    memset(&ext11_settings, 0, sizeof(ext11_settings));
2588
2589
    /* Section Type 10 needs to keep track of PRB range that should be reported
2590
       for msgTypeId=5 (Interference plus Noise for unallocated PRBs) */
2591
    /* All PRBs start as false */
2592
4.82M
#define MAX_PRBS 273
2593
20.5k
    bool prbs_for_st10_type5[MAX_PRBS];
2594
20.5k
    memset(&prbs_for_st10_type5, 0, sizeof(prbs_for_st10_type5));
2595
2596
2597
20.5k
#define MAX_UEIDS 16
2598
20.5k
    uint32_t ueids[MAX_UEIDS];
2599
20.5k
    uint32_t number_of_ueids = 0;
2600
2601
20.5k
    bool extension_flag = false;
2602
2603
    /* These sections (ST0, ST1, ST2, ST3, ST5, ST9, ST10, ST11) are similar, so handle as common with per-type differences */
2604
20.5k
    if (((sectionType <= SEC_C_UE_SCHED) || (sectionType >= SEC_C_SINR_REPORTING)) &&
2605
19.9k
         (sectionType != SEC_C_SLOT_CONTROL)) {
2606
2607
        /* sectionID */
2608
19.9k
        proto_item *ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
2609
19.9k
        if (sectionId == 4095) {
2610
975
            proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
2611
975
        }
2612
19.9k
        offset++;
2613
2614
19.9k
        if (tap_info->num_section_ids < MAX_SECTION_IDs) {
2615
15.8k
            tap_info->section_ids[tap_info->num_section_ids++] = sectionId;
2616
15.8k
        }
2617
2618
        /* rb */
2619
19.9k
        uint32_t rb;
2620
19.9k
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
2621
        /* symInc (1 bit) */
2622
19.9k
        if (sectionType != SEC_C_RRM_MEAS_REPORTS &&     /* Section Type 10 */
2623
15.8k
            sectionType != SEC_C_REQUEST_RRM_MEAS) {     /* Section Type 11 */
2624
13.6k
            unsigned int sym_inc;
2625
13.6k
            proto_item *sym_inc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA, &sym_inc);
2626
13.6k
            if (sym_inc !=0 && (sectionType == SEC_C_SINR_REPORTING)) {  /* Section Type 9 */
2627
                /* "0 shall be used" */
2628
56
                proto_item_append_text(sym_inc_ti, " (should be 0)");
2629
56
            }
2630
13.6k
        }
2631
6.31k
        else {
2632
            /* reserved (1 bit) */
2633
6.31k
            add_reserved_field(c_section_tree, hf_oran_reserved_bit5, tvb, offset, 1);
2634
6.31k
        }
2635
2636
        /* startPrbx and numPrbx */
2637
19.9k
        if (sectionType == SEC_C_SINR_REPORTING) {
2638
            /* startPrbu (10 bits) */
2639
179
            proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
2640
179
            offset += 2;
2641
            /* numPrbu */
2642
179
            numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
2643
179
            if (numPrbu == 0) {
2644
30
                proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
2645
30
                numPrbu = pref_data_plane_section_total_rbs;
2646
30
            }
2647
179
            offset += 1;
2648
179
        }
2649
19.7k
        else {
2650
            /* startPrbc (10 bits) */
2651
19.7k
            proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
2652
19.7k
            offset += 2;
2653
            /* numPrbc */
2654
19.7k
            numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
2655
19.7k
            if (numPrbc == 0) {
2656
5.45k
                proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
2657
                /* TODO: should probably set to pref_data_plane_section_total_rbs, and define MAX_PRBS to > 273 ? */
2658
5.45k
                numPrbc = MAX_PRBS;
2659
5.45k
            }
2660
19.7k
            offset += 1;
2661
19.7k
        }
2662
2663
        /* Start with range from section.  May get changed by SE6, SE12, SE20 */
2664
2.88M
        for (unsigned n=startPrbc; n < startPrbc+numPrbc; n++) {
2665
2.86M
            if (n < MAX_PRBS) {
2666
1.41M
                prbs_for_st10_type5[n] = true;
2667
1.41M
            }
2668
2.86M
        }
2669
2670
19.9k
        if (sectionType != SEC_C_SINR_REPORTING) {  /* Section Type 9 */
2671
19.5k
            static int * const  remask_flags[] = {
2672
19.5k
                &hf_oran_reMask_re1,
2673
19.5k
                &hf_oran_reMask_re2,
2674
19.5k
                &hf_oran_reMask_re3,
2675
19.5k
                &hf_oran_reMask_re4,
2676
19.5k
                &hf_oran_reMask_re5,
2677
19.5k
                &hf_oran_reMask_re6,
2678
19.5k
                &hf_oran_reMask_re7,
2679
19.5k
                &hf_oran_reMask_re8,
2680
19.5k
                &hf_oran_reMask_re9,
2681
19.5k
                &hf_oran_reMask_re10,
2682
19.5k
                &hf_oran_reMask_re11,
2683
19.5k
                &hf_oran_reMask_re12,
2684
19.5k
                NULL
2685
19.5k
            };
2686
2687
            /* reMask */
2688
19.5k
            uint64_t remask;
2689
19.5k
            proto_tree_add_bitmask_ret_uint64(c_section_tree, tvb, offset,
2690
19.5k
                                              hf_oran_reMask, ett_oran_remask, remask_flags, ENC_BIG_ENDIAN, &remask);
2691
19.5k
            offset++;
2692
            /* numSymbol */
2693
            /* TODO: should warn if startSymbol + numSymbol would be > 14? */
2694
19.5k
            uint32_t numSymbol;
2695
19.5k
            numsymbol_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numSymbol, tvb, offset, 1, ENC_NA, &numSymbol);
2696
19.5k
            if ((sectionType == SEC_C_RRM_MEAS_REPORTS) && (numSymbol != 14)) {     /* Section type 10 */
2697
3.79k
                proto_item_append_text(numsymbol_ti, " (for ST10, should be 14!)");
2698
3.79k
                expert_add_info_format(pinfo, numsymbol_ti, &ei_oran_st10_numsymbol_not_14,
2699
3.79k
                                       "numSymbol should be 14 for ST10 - found %u", numSymbol);
2700
3.79k
            }
2701
19.5k
            offset++;
2702
2703
            /* [ef] (extension flag) */
2704
19.5k
            switch (sectionType) {
2705
3.29k
                case SEC_C_UNUSED_RB:         /* Section Type 0 */
2706
5.40k
                case SEC_C_NORMAL:            /* Section Type 1 */
2707
7.21k
                case SEC_C_PRACH:             /* Section Type 3 */
2708
7.93k
                case SEC_C_UE_SCHED:          /* Section Type 5 */
2709
11.9k
                case SEC_C_RRM_MEAS_REPORTS:  /* Section Type 10 */
2710
14.1k
                case SEC_C_REQUEST_RRM_MEAS:  /* Section Type 11 */
2711
14.1k
                    proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2712
14.1k
                    break;
2713
5.35k
                default:
2714
                    /* Other section types don't support extensions */
2715
5.35k
                    break;
2716
19.5k
            }
2717
2718
19.4k
            write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbc, numPrbc, rb);
2719
19.4k
            proto_item_append_text(sectionHeading, ", Symbols: %2u", numSymbol);
2720
2721
19.4k
            if (numPrbc == 0) {
2722
                /* Special case for all PRBs */
2723
0
                numPrbc = pref_data_plane_section_total_rbs;
2724
0
                startPrbc = 0;  /* may already be 0... */
2725
0
            }
2726
19.4k
        }
2727
348
        else {
2728
            /* Section Type 9 */
2729
348
            write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
2730
348
            proto_item_append_text(sectionHeading, ", numSinrPerPrb: %2u", num_sinr_per_prb);
2731
348
        }
2732
2733
        /* Section type specific fields (after 'numSymbol') */
2734
19.8k
        switch (sectionType) {
2735
3.28k
            case SEC_C_UNUSED_RB:    /* Section Type 0 - Table 7.4.2-1 */
2736
                /* reserved (15 bits) */
2737
3.28k
                add_reserved_field(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2);
2738
3.28k
                offset += 2;
2739
3.28k
                break;
2740
2741
2.11k
            case SEC_C_NORMAL:       /* Section Type 1 - Table 7.4.3-1 */
2742
                /* beamId */
2743
2.11k
                beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
2744
2.11k
                offset += 2;
2745
2746
2.11k
                proto_item_append_text(sectionHeading, ", BeamId: %d", beamId);
2747
2.11k
                break;
2748
2749
1.79k
            case SEC_C_PRACH:       /* Section Type 3 - Table 7.4.5-1 */
2750
1.79k
            {
2751
                /* beamId */
2752
1.79k
                beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
2753
1.79k
                offset += 2;
2754
2755
                /* freqOffset */
2756
1.79k
                int32_t freqOffset;          /* Yes, this is signed, so the cast is intentional. */
2757
1.79k
                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);
2758
1.79k
                freqOffset |= 0xff000000;   /* Must sign-extend */
2759
1.79k
                proto_item_set_text(freq_offset_item, "Frequency offset: %d \u0394f", freqOffset);
2760
1.79k
                offset += 3;
2761
2762
                /* reserved (8 bits) */
2763
1.79k
                add_reserved_field(c_section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
2764
1.79k
                offset += 1;
2765
2766
1.79k
                proto_item_append_text(sectionHeading, ", BeamId: %d, FreqOffset: %d \u0394f", beamId, freqOffset);
2767
1.79k
                break;
2768
0
            }
2769
2770
719
            case SEC_C_UE_SCHED:          /* Section Type 5  - Table 7.4.7-1 */
2771
4.70k
            case SEC_C_RRM_MEAS_REPORTS:  /* Section Type 10 - Table 7.4.12-1 */
2772
                /* ueId */
2773
4.70k
                ueId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_BIG_ENDIAN, &ueId);
2774
4.70k
                offset += 2;
2775
4.70k
                if (ueId == 0x7fff) {
2776
98
                    proto_item_append_text(ueId_ti, " (PRBs not scheduled for eAxC ID in transport header)");
2777
98
                }
2778
4.60k
                else {
2779
4.60k
                    ueids[number_of_ueids++] = ueId;
2780
4.60k
                }
2781
2782
4.70k
                proto_item_append_text(sectionHeading, ", UEId: %d", ueId);
2783
4.70k
                break;
2784
2785
178
            case SEC_C_SINR_REPORTING:   /* Section Type 9 - SINR Reporting */
2786
178
            {
2787
                /* Hidden filter for bf (DMFS-BF) */
2788
178
                proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2789
178
                PROTO_ITEM_SET_HIDDEN(bf_ti);
2790
2791
178
                unsigned bit_offset = offset*8;
2792
2793
                /* sinr iqWidth */
2794
178
                proto_item *iq_width_item = proto_tree_add_uint(c_section_tree, hf_oran_sinrCompHdrIqWidth_pref, tvb, 0, 0, pref_sample_bit_width_sinr);
2795
178
                proto_item_append_text(iq_width_item, " (from preferences)");
2796
178
                proto_item_set_generated(iq_width_item);
2797
2798
                /* sinr compMethod */
2799
178
                proto_item *sinr_comp_meth_item = proto_tree_add_uint(c_section_tree, hf_oran_sinrCompHdrMeth_pref, tvb, 0, 0, pref_iqCompressionSINR);
2800
178
                proto_item_append_text(sinr_comp_meth_item, " (from preferences)");
2801
178
                proto_item_set_generated(sinr_comp_meth_item);
2802
2803
                /* Add SINR entries for each PRB */
2804
5.09k
                for (unsigned prb=startPrbu; prb < startPrbu+numPrbu; prb++) {
2805
                    /* Create a subtree for each PRB */
2806
4.91k
                    proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_sinr_prb,
2807
4.91k
                                                                tvb, offset, 0, "", "PRB %3u (", prb);
2808
4.91k
                    proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_sinr_prb);
2809
2810
                    /* Each prb starts byte-aligned */
2811
4.91k
                    bit_offset = ((bit_offset+7)/8) * 8;
2812
2813
                    /* N.B., using width/method from UL U-plane preferences, not certain that this is correct.. */
2814
2815
                    /* sinrCompParam (udCompParam format, may be empty) */
2816
4.91k
                    uint32_t exponent = 0;  /* N.B. init to silence warnings, but will always be set if read in COMP_BLOCK_FP case */
2817
4.91k
                    uint16_t sReSMask;
2818
4.91k
                    bit_offset = dissect_udcompparam(tvb, pinfo, prb_tree, bit_offset/8,
2819
4.91k
                                                     pref_iqCompressionSINR, &exponent, &sReSMask,
2820
4.91k
                                                     true) * 8; /* last param is for_sinr */
2821
2822
                    /* sinrValues for this PRB. */
2823
                    /* TODO: not sure how numSinrPerPrb interacts with rb==1... */
2824
11.7k
                    for (unsigned n=0; n < num_sinr_per_prb; n++) {
2825
6.84k
                        unsigned sinr_bits = tvb_get_bits32(tvb, bit_offset, pref_sample_bit_width_sinr, ENC_BIG_ENDIAN);
2826
2827
                        /* Using SINR compression settings from preferences */
2828
6.84k
                        float value = decompress_value(sinr_bits,
2829
6.84k
                                                       pref_iqCompressionSINR, pref_sample_bit_width_sinr,
2830
6.84k
                                                       exponent,
2831
6.84k
                                                       NULL /* no ModCompr for SINR */, 0 /* RE */);
2832
6.84k
                        unsigned sample_len_in_bytes = ((bit_offset%8)+pref_sample_bit_width_sinr+7)/8;
2833
6.84k
                        proto_item *val_ti = proto_tree_add_float(prb_tree, hf_oran_sinr_value, tvb,
2834
6.84k
                                                                   bit_offset/8, sample_len_in_bytes, value);
2835
6.84k
                        proto_item_append_text(prb_ti, " %8f", value);
2836
2837
                        /* Show here which subcarriers share which values (they all divide 12..) */
2838
6.84k
                        if (num_sinr_per_prb == 12) {
2839
879
                            proto_item_append_text(val_ti, " (PRB=%u, subcarrier %u)",
2840
879
                                                   startPrbu+((prb-startPrbu)*(rb+1)), n*(12/num_sinr_per_prb));
2841
879
                        }
2842
5.96k
                        else {
2843
5.96k
                            proto_item_append_text(val_ti, " (PRB=%u, subcarriers %u-%u)",
2844
5.96k
                                                   startPrbu+((prb-startPrbu)*(rb+1)),
2845
5.96k
                                                   n*(12/num_sinr_per_prb), (n+1)*(12/num_sinr_per_prb)-1);
2846
5.96k
                        }
2847
6.84k
                        bit_offset += pref_sample_bit_width_sinr;
2848
6.84k
                    }
2849
2850
                    /* 1-byte alignment per PRB (7.2.11) */
2851
4.91k
                    offset = (bit_offset+7)/8;
2852
4.91k
                    bit_offset = offset*8;
2853
2854
4.91k
                    proto_item_append_text(prb_ti, ")");
2855
4.91k
                    proto_item_set_end(prb_ti, tvb, offset);
2856
4.91k
                }
2857
178
                break;
2858
719
            }
2859
2.20k
            case SEC_C_REQUEST_RRM_MEAS:   /* Section Type 11 - Request RRM Measurements */
2860
                /* Reserved (15 bits) */
2861
2.20k
                add_reserved_field(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2);
2862
2.20k
                offset += 2;
2863
2.20k
                break;
2864
2865
5.35k
            default:
2866
5.35k
                break;
2867
19.8k
        }
2868
19.8k
    }
2869
585
    else if (sectionType == SEC_C_CH_INFO) {   /* Section Type 6 */
2870
        /* ef */
2871
585
        proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2872
        /* ueId */
2873
585
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_BIG_ENDIAN, &ueId);
2874
585
        offset += 2;
2875
        /* regularizationFactor */
2876
585
        proto_tree_add_item(c_section_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
2877
585
        offset += 2;
2878
        /* reserved (4 bits) */
2879
585
        add_reserved_field(c_section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
2880
        /* rb ("Value=0 shall be set") */
2881
585
        uint32_t rb;
2882
585
        proto_item *rb_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
2883
585
        if (rb != 0) {
2884
169
            proto_item_append_text(rb_ti, " (should be set to 0)");
2885
169
            expert_add_info(pinfo, rb_ti, &ei_oran_st6_rb_shall_be_0);
2886
169
        }
2887
        /* symInc */
2888
585
        proto_tree_add_item(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
2889
        /* startPrbc */
2890
585
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
2891
585
        offset += 2;
2892
        /* numPrbc */
2893
585
        proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
2894
585
        offset += 1;
2895
2896
        /* Hidden filter for bf */
2897
585
        proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2898
585
        PROTO_ITEM_SET_HIDDEN(bf_ti);
2899
2900
        /* ciIsample,ciQsample pairs */
2901
585
        unsigned m;
2902
585
        unsigned prb;
2903
585
        uint32_t bit_offset = offset*8;
2904
2905
        /* Antenna count from preference */
2906
585
        unsigned num_trx = pref_num_bf_antennas;
2907
2908
585
        write_channel_section_info(sectionHeading, pinfo,
2909
585
                                   sectionId, ueId, startPrbc, numPrbc, num_trx);
2910
2911
585
        bool first_prb = true;
2912
585
        uint8_t exponent = 0;
2913
2.08k
        for (prb=startPrbc; prb < startPrbc+numPrbc; prb++) {
2914
2915
            /* PRB subtree */
2916
1.49k
            unsigned prb_start_offset = bit_offset;
2917
1.49k
            proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_samples_prb,
2918
1.49k
                                                                 tvb, bit_offset/8, 0,
2919
1.49k
                                                                 "", "PRB=%u", prb);
2920
1.49k
            proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_prb_cisamples);
2921
2922
            /* There may be a ciCompParam here.. */
2923
1.49k
            if (first_prb || ci_comp_opt==1) {
2924
1.23k
                bit_offset = dissect_ciCompParam(tvb, prb_tree, pinfo, bit_offset, ci_comp_meth, &exponent);
2925
1.23k
            }
2926
1.49k
            first_prb = false;
2927
2928
            /* Antennas */
2929
45.6k
            for (m=0; m < num_trx; m++) {
2930
2931
44.1k
                unsigned sample_offset = bit_offset / 8;
2932
44.1k
                uint8_t sample_extent = ((bit_offset + (ci_iq_width*2)) / 8) - sample_offset;
2933
2934
                /* Create subtree for antenna */
2935
44.1k
                proto_item *sample_ti = proto_tree_add_string_format(prb_tree, hf_oran_ciSample,
2936
44.1k
                                                                     tvb, sample_offset, sample_extent,
2937
44.1k
                                                                     "", "TRX=%2u:  ", m);
2938
44.1k
                proto_tree *sample_tree = proto_item_add_subtree(sample_ti, ett_oran_cisample);
2939
2940
                /* I */
2941
                /* Get bits, and convert to float. */
2942
44.1k
                uint32_t bits = tvb_get_bits32(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2943
44.1k
                float value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent, NULL /* no ModCompr for ST6 */, 0 /* RE */);
2944
2945
                /* Add to tree. */
2946
44.1k
                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);
2947
44.1k
                bit_offset += ci_iq_width;
2948
44.1k
                proto_item_append_text(sample_ti, "I%u=%f ", m, value);
2949
2950
                /* Q */
2951
                /* Get bits, and convert to float. */
2952
44.1k
                bits = tvb_get_bits32(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2953
44.1k
                value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent, NULL /* no ModCompr for ST6 */, 0 /* RE */);
2954
2955
                /* Add to tree. */
2956
44.1k
                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);
2957
44.1k
                bit_offset += ci_iq_width;
2958
44.1k
                proto_item_append_text(sample_ti, "Q%u=%f ", m, value);
2959
44.1k
            }
2960
1.49k
            proto_item_set_len(prb_ti, (bit_offset-prb_start_offset+7)/8);
2961
1.49k
        }
2962
2963
        /* Pad out by 1 or 4 bytes, according to preference */
2964
585
        if (!st6_4byte_alignment) {
2965
393
            offset = (bit_offset + 7) / 8;
2966
393
        }
2967
192
        else {
2968
192
            int mode = bit_offset % 32;
2969
192
            if (mode != 0) {
2970
0
                offset = (bit_offset + (32-mode))/8;
2971
0
            }
2972
192
            else {
2973
192
                offset = bit_offset/8;
2974
192
            }
2975
192
        }
2976
585
        proto_item_set_end(c_section_tree, tvb, offset);
2977
585
    }
2978
2979
20.5k
    bool seen_se10 = false;
2980
20.1k
    uint32_t numPortc = 0;
2981
20.1k
    proto_item *bf_ti = NULL;
2982
2983
    /* Section extension commands */
2984
22.0k
    while (extension_flag) {
2985
3.65k
        int extension_start_offset = offset;
2986
2987
        /* Prefetch extType so can use specific extension type ett */
2988
3.65k
        uint32_t exttype = tvb_get_uint8(tvb, offset) & 0x7f;
2989
3.65k
        uint32_t exttype_ett_index = exttype;
2990
3.65k
        if (exttype == 0 || exttype > HIGHEST_EXTTYPE) {
2991
            /* Just use first one if out of range */
2992
1.19k
            exttype_ett_index = 1;
2993
1.19k
        }
2994
2995
        /* Create subtree for each extension (with summary) */
2996
3.65k
        proto_item *extension_ti = proto_tree_add_string_format(c_section_tree, hf_oran_extension,
2997
3.65k
                                                                tvb, offset, 0, "", "Extension");
2998
3.65k
        proto_tree *extension_tree = proto_item_add_subtree(extension_ti, ett_oran_c_section_extension[exttype_ett_index-1]);
2999
3000
        /* ef (i.e. another extension after this one?) */
3001
3.65k
        proto_tree_add_item_ret_boolean(extension_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
3002
3003
        /* extType */
3004
3.65k
        proto_item *exttype_ti;
3005
3.65k
        exttype_ti = proto_tree_add_item(extension_tree, hf_oran_exttype, tvb, offset, 1, ENC_BIG_ENDIAN);
3006
3.65k
        offset++;
3007
3.65k
        proto_item_append_text(sectionHeading, " (ext-%u)", exttype);
3008
3009
3.65k
        proto_item_append_text(extension_ti, " (ext-%u: %s)", exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"));
3010
3011
        /* Don't tap if out of range. */
3012
3.65k
        if (exttype > 0 && exttype <= HIGHEST_EXTTYPE) {
3013
2.21k
            tap_info->extensions[exttype] = true;
3014
2.21k
        }
3015
3016
        /* Is this SE allowed for this section type? */
3017
3.65k
        if (!se_allowed_in_st(exttype, sectionType)) {
3018
784
            expert_add_info_format(pinfo, extension_tree, &ei_oran_se_on_unsupported_st,
3019
784
                                   "SE %u (%s) should not appear in ST %u (%s)!",
3020
784
                                   exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"),
3021
784
                                   sectionType, rval_to_str_const(sectionType, section_types, "Unknown"));
3022
784
        }
3023
3024
3025
        /* extLen (number of 32-bit words) */
3026
3.65k
        uint32_t extlen_len = ((exttype==11)||(exttype==19)||(exttype==20)) ? 2 : 1;  /* Extensions 11/19/20 are special */
3027
3.65k
        uint32_t extlen;
3028
3.65k
        proto_item *extlen_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_extlen, tvb,
3029
3.65k
                                                             offset, extlen_len, ENC_BIG_ENDIAN, &extlen);
3030
3.65k
        proto_item_append_text(extlen_ti, " (%u bytes)", extlen*4);
3031
3.65k
        offset += extlen_len;
3032
3.65k
        if (extlen == 0) {
3033
737
            expert_add_info(pinfo, extlen_ti, &ei_oran_extlen_zero);
3034
            /* Break out to avoid infinitely looping! */
3035
737
            break;
3036
737
        }
3037
3038
3.65k
        bool ext_unhandled = false;
3039
3040
2.92k
        switch (exttype) {
3041
3042
192
            case 1:  /* SE 1: Beamforming Weights */
3043
192
            {
3044
192
                uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
3045
192
                proto_item *comp_meth_ti = NULL;
3046
3047
                /* Hidden filter for bf */
3048
192
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3049
192
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3050
3051
                /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
3052
192
                offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
3053
192
                                            &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
3054
3055
                /* bfwCompParam */
3056
192
                uint32_t exponent = 0;
3057
192
                bool compression_method_supported = false;
3058
192
                unsigned num_trx = 0;
3059
192
                uint16_t *trx;        /* ptr to array */
3060
192
                offset = dissect_bfwCompParam(tvb, extension_tree, pinfo, offset, comp_meth_ti,
3061
192
                                              &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
3062
192
                                              &num_trx, &trx);
3063
3064
                /* Can't show details of unsupported compression method */
3065
192
                if (!compression_method_supported) {
3066
50
                    break;
3067
50
                }
3068
3069
                /* We know:
3070
                   - iq_width (above)
3071
                   - numBfWeights (taken from preference)
3072
                   - remaining bytes in extension
3073
                   We can therefore derive TRX (number of antennas).
3074
                 */
3075
3076
192
                bool using_array = false;
3077
3078
                /* I & Q samples
3079
                   May know how many entries from activeBeamspaceCoefficientMask. */
3080
142
                if (num_trx == 0) {
3081
                    /* Don't know how many there will be, so just fill available bytes... */
3082
119
                    unsigned weights_bytes = (extlen*4)-3;
3083
119
                    unsigned num_weights_pairs = (weights_bytes*8) / (bfwcomphdr_iq_width*2);
3084
119
                    num_trx = num_weights_pairs;
3085
119
                }
3086
23
                else {
3087
23
                    using_array = true;
3088
23
                    num_trx = pref_num_bf_antennas;
3089
23
                }
3090
3091
142
                int bit_offset = offset*8;
3092
3093
5.39k
                for (unsigned n=0; n < num_trx; n++) {
3094
                    /* Create antenna subtree */
3095
5.25k
                    int bfw_offset = bit_offset / 8;
3096
3097
5.25k
                    uint16_t trx_index = (using_array) ? trx[n] : n+1;
3098
3099
5.25k
                    proto_item *bfw_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfw,
3100
5.25k
                                                                      tvb, bfw_offset, 0, "", "TRX %3u: (", trx_index);
3101
5.25k
                    proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
3102
3103
                    /* I value */
3104
                    /* Get bits, and convert to float. */
3105
5.25k
                    uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3106
5.25k
                    float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent,
3107
5.25k
                                                   NULL /* no ModCompr */, 0 /* RE */);
3108
                    /* Add to tree. */
3109
5.25k
                    proto_tree_add_float(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
3110
5.25k
                                         (bfwcomphdr_iq_width+7)/8, value);
3111
5.25k
                    bit_offset += bfwcomphdr_iq_width;
3112
5.25k
                    proto_item_append_text(bfw_ti, "I=%f ", value);
3113
3114
                    /* Leave a gap between I and Q values */
3115
5.25k
                    proto_item_append_text(bfw_ti, "  ");
3116
3117
                    /* Q value */
3118
                    /* Get bits, and convert to float. */
3119
5.25k
                    bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3120
5.25k
                    value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent,
3121
5.25k
                                             NULL /* no ModCompr */, 0 /* RE */);
3122
                    /* Add to tree. */
3123
5.25k
                    proto_tree_add_float(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
3124
5.25k
                                         (bfwcomphdr_iq_width+7)/8, value);
3125
5.25k
                    bit_offset += bfwcomphdr_iq_width;
3126
5.25k
                    proto_item_append_text(bfw_ti, "Q=%f", value);
3127
3128
5.25k
                    proto_item_append_text(bfw_ti, ")");
3129
5.25k
                    proto_item_set_len(bfw_ti, (bit_offset+7)/8  - bfw_offset);
3130
5.25k
                }
3131
                /* Need to round to next byte */
3132
142
                offset = (bit_offset+7)/8;
3133
3134
142
                break;
3135
192
            }
3136
3137
90
            case 2: /* SE 2: Beamforming attributes */
3138
90
            {
3139
                /* Hidden filter for bf */
3140
90
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3141
90
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3142
3143
                /* bfaCompHdr (get widths of fields to follow) */
3144
90
                uint32_t bfAzPtWidth, bfZePtWidth, bfAz3ddWidth, bfZe3ddWidth;
3145
                /* subtree */
3146
90
                proto_item *bfa_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfaCompHdr,
3147
90
                                                                  tvb, offset, 2, "", "bfaCompHdr");
3148
90
                proto_tree *bfa_tree = proto_item_add_subtree(bfa_ti, ett_oran_bfacomphdr);
3149
3150
                /* reserved (2 bits) */
3151
90
                add_reserved_field(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1);
3152
                /* bfAzPtWidth (3 bits) */
3153
90
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAzPtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAzPtWidth);
3154
                /* bfZePtWidth (3 bits) */
3155
90
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZePtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZePtWidth);
3156
90
                offset += 1;
3157
3158
                /* reserved (2 bits) */
3159
90
                add_reserved_field(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1);
3160
                /* bfAz3ddWidth (3 bits) */
3161
90
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAz3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAz3ddWidth);
3162
                /* bfZe3ddWidth (3 bits) */
3163
90
                proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZe3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZe3ddWidth);
3164
90
                offset += 1;
3165
3166
90
                unsigned bit_offset = offset*8;
3167
3168
                /* bfAzPt */
3169
90
                if (bfAzPtWidth > 0) {
3170
38
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfAzPt, tvb, bit_offset, bfAzPtWidth+1, ENC_BIG_ENDIAN);
3171
38
                    bit_offset += (bfAzPtWidth+1);
3172
38
                }
3173
                /* bfZePt */
3174
90
                if (bfZePtWidth > 0) {
3175
71
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfZePt, tvb, bit_offset, bfZePtWidth+1, ENC_BIG_ENDIAN);
3176
71
                    bit_offset += (bfZePtWidth+1);
3177
71
                }
3178
                /* bfAz3dd */
3179
90
                if (bfAz3ddWidth > 0) {
3180
30
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfAz3dd, tvb, bit_offset, bfAz3ddWidth+1, ENC_BIG_ENDIAN);
3181
30
                    bit_offset += (bfAz3ddWidth+1);
3182
30
                }
3183
                /* bfZe3dd */
3184
90
                if (bfZe3ddWidth > 0) {
3185
51
                    proto_tree_add_bits_item(extension_tree, hf_oran_bfZe3dd, tvb, bit_offset, bfZe3ddWidth+1, ENC_BIG_ENDIAN);
3186
51
                    bit_offset += (bfZe3ddWidth+1);
3187
51
                }
3188
3189
                /* Pad to next byte (unless last 2 fields already fit in this one) */
3190
90
                if ((bit_offset % 8) > 2) {
3191
51
                    offset = (bit_offset+7) / 8;
3192
51
                }
3193
39
                else {
3194
39
                    offset = bit_offset / 8;
3195
39
                }
3196
3197
                /* bfAzSl (3 bits) */
3198
90
                proto_tree_add_item(extension_tree, hf_oran_bfAzSl, tvb, offset, 1, ENC_BIG_ENDIAN);
3199
                /* bfZeSl (3 bits) */
3200
90
                proto_tree_add_item(extension_tree, hf_oran_bfZeSl, tvb, offset, 1, ENC_BIG_ENDIAN);
3201
90
                offset += 1;
3202
90
                break;
3203
192
            }
3204
3205
98
            case 3: /* SE 3: DL precoding parameters */
3206
98
            {
3207
                /* codebookindex (8 bits) */
3208
                /* "This parameter is not used and shall be set to zero." */
3209
98
                proto_tree_add_item(extension_tree, hf_oran_codebook_index, tvb, offset, 1, ENC_BIG_ENDIAN);
3210
98
                offset += 1;
3211
                /* layerid */
3212
98
                uint32_t layerid;
3213
98
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_layerid, tvb, offset, 1, ENC_BIG_ENDIAN, &layerid);
3214
                /* numLayers */
3215
98
                proto_tree_add_item(extension_tree, hf_oran_numlayers, tvb, offset, 1, ENC_BIG_ENDIAN);
3216
98
                offset += 1;
3217
3218
                /* Stop here for non-first data layer */
3219
98
                if (layerid != 0 && layerid != 0xf) {
3220
17
                    break;
3221
17
                }
3222
3223
                /* First data layer case */
3224
                /* txScheme */
3225
81
                proto_tree_add_item(extension_tree, hf_oran_txscheme, tvb, offset, 1, ENC_BIG_ENDIAN);
3226
                /* crsReMask */
3227
81
                proto_tree_add_item(extension_tree, hf_oran_crs_remask, tvb, offset, 2, ENC_BIG_ENDIAN);
3228
81
                offset += 2;
3229
3230
                /* crsShift (1 bit) */
3231
81
                proto_tree_add_item(extension_tree, hf_oran_crs_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
3232
                /* reserved (3 bits) */
3233
81
                add_reserved_field(extension_tree, hf_oran_reserved_bits123, tvb, offset, 1);
3234
                /* crsSymNum (4 bits) */
3235
81
                proto_tree_add_item(extension_tree, hf_oran_crs_symnum, tvb, offset, 1, ENC_BIG_ENDIAN);
3236
81
                offset += 1;
3237
                /* reserved (8 bits) */
3238
81
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3239
81
                offset += 1;
3240
3241
                /* reserved (1 bit) */
3242
81
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3243
                /* beamIdAP1 (15 bits) */
3244
81
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap1, tvb, offset, 2, ENC_BIG_ENDIAN);
3245
81
                offset += 2;
3246
                /* reserved (1 bit) */
3247
81
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3248
                /* beamIdAP2 (15 bits) */
3249
81
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap2, tvb, offset, 2, ENC_BIG_ENDIAN);
3250
81
                offset += 2;
3251
                /* reserved (1 bit) */
3252
81
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3253
                /* beamIdAP3 (15 bits) */
3254
81
                proto_tree_add_item(extension_tree, hf_oran_beamid_ap3, tvb, offset, 2, ENC_BIG_ENDIAN);
3255
81
                offset += 2;
3256
81
                break;
3257
98
            }
3258
3259
64
            case 4: /* SE 4: Modulation compression params (5.4.7.4) (single sets) */
3260
64
            {
3261
                /* csf */
3262
64
                bool csf;
3263
64
                dissect_csf(extension_tree, tvb, offset*8, ci_iq_width, &csf);
3264
3265
                /* modCompScaler */
3266
64
                uint32_t modCompScaler;
3267
64
                proto_item *ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_modcompscaler,
3268
64
                                                              tvb, offset, 2, ENC_BIG_ENDIAN, &modCompScaler);
3269
64
                offset += 2;
3270
3271
                /* Work out and show floating point value too. exponent and mantissa are both unsigned */
3272
64
                uint16_t exponent = (modCompScaler >> 11) & 0x000f; /* m.s. 4 bits */
3273
64
                uint16_t mantissa = modCompScaler & 0x07ff;         /* l.s. 11 bits */
3274
64
                float value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
3275
64
                proto_item_append_text(ti, " (%f)", value);
3276
3277
64
                section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
3278
3279
                /* Store these params in this flow's state */
3280
64
                if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
3281
64
                    unsigned i = sect_config->num_configs;
3282
64
                    sect_config->configs[i].mod_compr_re_mask = 0xfff;   /* Covers all REs */
3283
64
                    sect_config->configs[i].mod_compr_csf = csf;
3284
64
                    sect_config->configs[i].mod_compr_scaler = value;
3285
64
                    sect_config->num_configs++;
3286
64
                }
3287
64
                break;
3288
98
            }
3289
3290
69
            case 5: /* SE 5: Modulation Compression Additional Parameters (7.7.5) (multiple sets) */
3291
69
            {
3292
                /* Applies only to section types 1,3 and 5 */
3293
                /* N.B. there may be multiple instances of this SE in the same frame */
3294
3295
                /* There may be one or 2 entries, depending upon extlen */
3296
69
                int sets = 1, reserved_bits = 0;
3297
69
                switch (extlen) {
3298
0
                    case 2:
3299
0
                        sets = 1;
3300
0
                        reserved_bits = 20;
3301
0
                        break;
3302
2
                    case 3:
3303
2
                        sets = 2;
3304
2
                        reserved_bits = 24;
3305
2
                        break;
3306
16
                    case 4:
3307
                        /* sets can be 3 or 4, depending upon whether last 28 bits are 0.. */
3308
16
                        if ((tvb_get_ntohl(tvb, offset+10) & 0x0fffffff) == 0) {
3309
1
                            sets = 3;
3310
1
                            reserved_bits = 28;
3311
1
                        }
3312
15
                        else {
3313
15
                            sets = 4;
3314
15
                            reserved_bits = 0;
3315
15
                        }
3316
16
                        break;
3317
3318
51
                    default:
3319
                        /* Malformed error!!! */
3320
51
                        expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
3321
51
                                               "For section 5, extlen must be 2, 3 or 4, but %u was dissected",
3322
51
                                               extlen);
3323
51
                        break;
3324
69
                }
3325
3326
69
                unsigned bit_offset = offset*8;
3327
                /* Dissect each set */
3328
187
                for (int n=0; n < sets; n++) {
3329
                    /* Subtree for each set */
3330
118
                    unsigned set_start_offset = bit_offset/8;
3331
118
                    proto_item *set_ti = proto_tree_add_string(extension_tree, hf_oran_modcomp_param_set,
3332
118
                                                                tvb, set_start_offset, 0, "");
3333
118
                    proto_tree *set_tree = proto_item_add_subtree(set_ti, ett_oran_modcomp_param_set);
3334
3335
118
                    uint64_t mcScaleReMask, mcScaleOffset;
3336
118
                    bool csf;
3337
3338
                    /* mcScaleReMask (12 bits). Defines which REs the following csf and mcScaleOffset apply to */
3339
118
                    static int * const  remask_flags[] = {
3340
118
                        &hf_oran_mc_scale_re_mask_re1,
3341
118
                        &hf_oran_mc_scale_re_mask_re2,
3342
118
                        &hf_oran_mc_scale_re_mask_re3,
3343
118
                        &hf_oran_mc_scale_re_mask_re4,
3344
118
                        &hf_oran_mc_scale_re_mask_re5,
3345
118
                        &hf_oran_mc_scale_re_mask_re6,
3346
118
                        &hf_oran_mc_scale_re_mask_re7,
3347
118
                        &hf_oran_mc_scale_re_mask_re8,
3348
118
                        &hf_oran_mc_scale_re_mask_re9,
3349
118
                        &hf_oran_mc_scale_re_mask_re10,
3350
118
                        &hf_oran_mc_scale_re_mask_re11,
3351
118
                        &hf_oran_mc_scale_re_mask_re12,
3352
118
                        NULL
3353
118
                    };
3354
                    /* Same as above, but offset by 4 bits */
3355
118
                    static int * const  remask_flags_even[] = {
3356
118
                        &hf_oran_mc_scale_re_mask_re1_even,
3357
118
                        &hf_oran_mc_scale_re_mask_re2_even,
3358
118
                        &hf_oran_mc_scale_re_mask_re3_even,
3359
118
                        &hf_oran_mc_scale_re_mask_re4_even,
3360
118
                        &hf_oran_mc_scale_re_mask_re5_even,
3361
118
                        &hf_oran_mc_scale_re_mask_re6_even,
3362
118
                        &hf_oran_mc_scale_re_mask_re7_even,
3363
118
                        &hf_oran_mc_scale_re_mask_re8_even,
3364
118
                        &hf_oran_mc_scale_re_mask_re9_even,
3365
118
                        &hf_oran_mc_scale_re_mask_re10_even,
3366
118
                        &hf_oran_mc_scale_re_mask_re11_even,
3367
118
                        &hf_oran_mc_scale_re_mask_re12_even,
3368
118
                        NULL
3369
118
                    };
3370
3371
                    /* RE Mask (12 bits) */
3372
118
                    proto_tree_add_bitmask_ret_uint64(set_tree, tvb, bit_offset / 8,
3373
118
                                                      (n % 2) ? hf_oran_mc_scale_re_mask_even : hf_oran_mc_scale_re_mask,
3374
118
                                                      ett_oran_mc_scale_remask,
3375
118
                                                      (n % 2) ? remask_flags_even : remask_flags, ENC_BIG_ENDIAN, &mcScaleReMask);
3376
118
                    bit_offset += 12;
3377
3378
                    /* csf (1 bit) */
3379
118
                    bit_offset = dissect_csf(set_tree, tvb, bit_offset, ci_iq_width, &csf);
3380
                    /* mcScaleOffset (15 bits) */
3381
118
                    proto_item *ti = proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_offset, tvb, bit_offset, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
3382
118
                    uint16_t exponent = (mcScaleOffset >> 11) & 0x000f; /* m.s. 4 bits */
3383
118
                    uint16_t mantissa = mcScaleOffset & 0x07ff;         /* l.s. 11 bits */
3384
118
                    float mcScaleOffset_value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
3385
118
                    proto_item_append_text(ti, " (%f)", mcScaleOffset_value);
3386
118
                    bit_offset += 15;
3387
3388
118
                    section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
3389
3390
                    /* Record this config */
3391
118
                    if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
3392
109
                        unsigned i = sect_config->num_configs;
3393
109
                        sect_config->configs[i].mod_compr_re_mask = (uint16_t)mcScaleReMask;
3394
109
                        sect_config->configs[i].mod_compr_csf = csf;
3395
109
                        sect_config->configs[i].mod_compr_scaler = mcScaleOffset_value;
3396
109
                        sect_config->num_configs++;
3397
109
                    }
3398
3399
                    /* Summary */
3400
118
                    proto_item_set_len(set_ti, (bit_offset+7)/8 - set_start_offset);
3401
118
                    proto_item_append_text(set_ti, " (mcScaleReMask=0x%03x  csf=%5s  mcScaleOffset=%f)",
3402
118
                                           (unsigned)mcScaleReMask, tfs_get_true_false(csf), mcScaleOffset_value);
3403
118
                }
3404
3405
69
                proto_item_append_text(extension_ti, " (%u sets)", sets);
3406
3407
                /* Reserved (variable-length) */
3408
69
                if (reserved_bits) {
3409
3
                    proto_tree_add_bits_item(extension_tree, hf_oran_reserved, tvb, bit_offset, reserved_bits, ENC_BIG_ENDIAN);
3410
3
                    bit_offset += reserved_bits;
3411
3
                }
3412
3413
69
                offset = bit_offset/8;
3414
69
                break;
3415
69
            }
3416
3417
124
            case 6: /* SE 6: Non-contiguous PRB allocation in time and frequency domain */
3418
124
            {
3419
                /* numSymbol not used in this case */
3420
124
                if (numsymbol_ti && !numsymbol_ignored) {
3421
116
                    proto_item_append_text(numsymbol_ti, " (ignored)");
3422
116
                    numsymbol_ignored = true;
3423
116
                }
3424
3425
                /* Will update ext6 recorded info */
3426
124
                ext11_settings.ext6_set = true;
3427
3428
                /* repetition */
3429
124
                proto_tree_add_bits_item(extension_tree, hf_oran_se6_repetition, tvb, offset*8, 1, ENC_BIG_ENDIAN);
3430
                /* rbgSize (PRBs per bit set in rbgMask) */
3431
124
                uint32_t rbgSize;
3432
124
                proto_item *rbg_size_ti;
3433
124
                rbg_size_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgSize);
3434
124
                if (rbgSize == 0) {
3435
                    /* N.B. this is only true if "se6-rb-bit-supported" is set... */
3436
55
                    expert_add_info(pinfo, rbg_size_ti, &ei_oran_rbg_size_reserved);
3437
55
                }
3438
                /* rbgMask (28 bits) */
3439
124
                uint32_t rbgMask;
3440
124
                proto_item *rbgmask_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN, &rbgMask);
3441
124
                if (rbgSize == 0) {
3442
55
                    proto_item_append_text(rbgmask_ti, " (value ignored since rbgSize is 0)");
3443
55
                }
3444
3445
                /* TODO: if receiver detects non-zero bits outside the valid range, those shall be ignored. */
3446
124
                offset += 4;
3447
                /* priority */
3448
124
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3449
                /* symbolMask */
3450
124
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
3451
3452
                /* Look up rbg_size enum -> value */
3453
124
                switch (rbgSize) {
3454
55
                    case 0:
3455
                        /* N.B. reserved, but covered above with expert info (would remain 0) */
3456
55
                        break;
3457
5
                    case 1:
3458
5
                        ext11_settings.ext6_rbg_size = 1; break;
3459
20
                    case 2:
3460
20
                        ext11_settings.ext6_rbg_size = 2; break;
3461
3
                    case 3:
3462
3
                        ext11_settings.ext6_rbg_size = 3; break;
3463
6
                    case 4:
3464
6
                        ext11_settings.ext6_rbg_size = 4; break;
3465
8
                    case 5:
3466
8
                        ext11_settings.ext6_rbg_size = 6; break;
3467
6
                    case 6:
3468
6
                        ext11_settings.ext6_rbg_size = 8; break;
3469
21
                    case 7:
3470
21
                        ext11_settings.ext6_rbg_size = 16; break;
3471
                    /* N.B., encoded in 3 bits, so no other values are possible */
3472
124
                }
3473
3474
                /* Set to looked-up value */
3475
124
                rbgSize = ext11_settings.ext6_rbg_size;
3476
3477
124
                uint32_t lastRbgid = 0;
3478
124
                if (rbgSize != 0) {
3479
                    /* The O-DU shall not use combinations of startPrbc, numPrbc and rbgSize leading to a value of lastRbgid larger than 27 */
3480
                    /* i.e., leftmost bit used should not need to go off left end of rbgMask! */
3481
70
                    lastRbgid = (uint32_t)ceil((numPrbc + (startPrbc % rbgSize)) / (float)rbgSize) - 1;
3482
70
                    if (lastRbgid > 27) {
3483
12
                        expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_lastRbdid_out_of_range,
3484
12
                                               "SE6: rbgSize (%u) not compatible with startPrbc(%u) and numPrbc(%u)",
3485
12
                                               rbgSize, startPrbc, numPrbc);
3486
12
                        break;
3487
12
                    }
3488
70
                }
3489
3490
                /* Record (and count) which bits are set in rbgMask */
3491
124
                bool first_seen = false;
3492
112
                unsigned first_seen_pos=0, last_seen_pos=0;
3493
3.20k
                for (unsigned n=0; n < 28 && ext11_settings.ext6_num_bits_set < 28; n++) {
3494
3.09k
                    if ((rbgMask >> n) & 0x01) {
3495
1.24k
                        ext11_settings.ext6_bits_set[ext11_settings.ext6_num_bits_set++] = n;
3496
1.24k
                        if (!first_seen) {
3497
109
                            first_seen = true;
3498
109
                            first_seen_pos = n;
3499
109
                        }
3500
1.24k
                        last_seen_pos = n;
3501
1.24k
                    }
3502
3.09k
                }
3503
3504
                /* Show how many bits were set in rbgMask */
3505
112
                proto_item_append_text(rbgmask_ti, " (%u bits set)", ext11_settings.ext6_num_bits_set);
3506
                /* Also, that is the range of bits */
3507
112
                if (first_seen) {
3508
109
                    proto_item_append_text(rbgmask_ti, " (%u bits spread)", last_seen_pos-first_seen_pos+1);
3509
109
                }
3510
3511
                /* Complain if last set bit is beyond lastRbgid */
3512
112
                if (first_seen) {
3513
109
                    if (last_seen_pos > lastRbgid) {
3514
104
                        expert_add_info_format(pinfo, rbgmask_ti, &ei_oran_rbgMask_beyond_last_rbdid,
3515
104
                                               "SE6: rbgMask (0x%07x) has bit %u set, but lastRbgId is %u",
3516
104
                                               rbgMask, last_seen_pos, lastRbgid);
3517
104
                    }
3518
109
                }
3519
3520
                /* Also update prbs_for_st10_type5[] */
3521
112
                if (sectionType == 10 && rbgSize != 0) {
3522
                    /* Unset all entries */
3523
36
                    memset(&prbs_for_st10_type5, 0, sizeof(prbs_for_st10_type5));
3524
3525
                    /* Work out which PRB first bit corresponds to */
3526
36
                    unsigned firstPrbStart = (startPrbc/rbgSize) * rbgSize;
3527
3528
                    /* Add PRBs corresponding to each bit set */
3529
1.04k
                    for (unsigned n=0; n < 28 ; n++) {
3530
1.00k
                        if ((rbgMask >> n) & 0x01) {
3531
                            /* Lazy way to clip any values that lie outside of range for section */
3532
5.14k
                            for (unsigned p=0; p < rbgSize; p++) {
3533
4.72k
                                unsigned start = firstPrbStart + (n*rbgSize);
3534
4.72k
                                if ((start+p < MAX_PRBS) && (start+p >= startPrbc) && (start+p <= startPrbc+numPrbc-1)) {
3535
1.16k
                                    prbs_for_st10_type5[start+p] = true;
3536
1.16k
                                }
3537
4.72k
                            }
3538
420
                        }
3539
1.00k
                    }
3540
36
                }
3541
3542
112
                break;
3543
124
            }
3544
3545
32
            case 7: /* SE 7: eAxC mask */
3546
                /* Allow ST0 to address multiple eAxC_ID values for transmission blanking */
3547
32
                proto_tree_add_item(extension_tree, hf_oran_eAxC_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3548
32
                offset += 2;
3549
32
                break;
3550
3551
23
            case 8: /* SE 8: Regularization factor */
3552
23
                proto_tree_add_item(extension_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
3553
23
                offset += 2;
3554
23
                break;
3555
3556
26
            case 9: /* SE 9: Dynamic Spectrum Sharing parameters */
3557
26
                proto_tree_add_item(extension_tree, hf_oran_technology, tvb, offset, 1, ENC_BIG_ENDIAN);
3558
26
                offset += 1;
3559
26
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3560
26
                offset += 1;
3561
26
                break;
3562
3563
132
            case 10: /* SE 10: Group configuration of multiple ports */
3564
132
            {
3565
132
                seen_se10 = true;
3566
3567
                /* beamGroupType */
3568
132
                uint32_t beam_group_type = 0;
3569
132
                proto_item *bgt_ti;
3570
132
                bgt_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamGroupType,
3571
132
                                                      tvb, offset, 1, ENC_BIG_ENDIAN, &beam_group_type);
3572
132
                proto_item_append_text(extension_ti, " (%s)", val_to_str_const(beam_group_type, beam_group_type_vals, "Unknown"));
3573
3574
                /* numPortc */
3575
132
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
3576
132
                                             tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
3577
132
                offset++;
3578
3579
                /* Will append all beamId values to extension_ti, regardless of beamGroupType */
3580
132
                unsigned n;
3581
3582
132
                switch (beam_group_type) {
3583
29
                    case 0x0: /* common beam */
3584
34
                    case 0x1: /* beam matrix indication */
3585
                        /* Reserved byte */
3586
34
                        add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3587
34
                        offset++;
3588
3589
                        /* Explain how entries are allocated */
3590
34
                        if (beam_group_type == 0x0) {
3591
29
                            proto_item_append_text(extension_ti, " (all %u ueid/Beam entries are %u)", numPortc, ueId);
3592
29
                        }
3593
5
                        else {
3594
                            /* 'numPortc' consecutive BeamIds from section header */
3595
5
                            proto_item_append_text(extension_ti, " (ueId/beam entries are %u -> %u)", ueId, ueId+numPortc);
3596
5
                        }
3597
3598
34
                        if (sectionType == 5) {
3599
                            /* These types are not allowed */
3600
5
                            expert_add_info_format(pinfo, bgt_ti, &ei_oran_se10_not_allowed,
3601
5
                                                   "SE10: beamGroupType %u is not allowed for section type 5", beam_group_type);
3602
5
                        }
3603
34
                        break;
3604
3605
46
                    case 0x2: /* beam vector listing */
3606
46
                    {
3607
46
                        proto_item_append_text(extension_ti, " [ ");
3608
3609
                        /* Beam listing vector case */
3610
                        /* Work out how many port beam entries there is room for */
3611
                        /* Using numPortC as visible in issue 18116 */
3612
1.07k
                        for (n=0; n < numPortc; n++) {
3613
                            /* 1 reserved bit */
3614
1.02k
                            add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3615
3616
                            /* port beam ID (or UEID) (15 bits) */
3617
1.02k
                            uint32_t id;
3618
1.02k
                            proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
3619
1.02k
                                                                                         tvb, offset, 2, ENC_BIG_ENDIAN, &id);
3620
1.02k
                            proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
3621
1.02k
                            offset += 2;
3622
3623
1.02k
                            if (id != 0x7fff) {
3624
894
                                if (number_of_ueids < MAX_UEIDS) {
3625
443
                                    ueids[number_of_ueids++] = id;
3626
443
                                }
3627
894
                            }
3628
3629
1.02k
                            proto_item_append_text(extension_ti, "%u ", id);
3630
1.02k
                        }
3631
3632
46
                        proto_item_append_text(extension_ti, "]");
3633
46
                        break;
3634
29
                    }
3635
52
                    case 0x3: /* beamId/ueId listing with associated port-list index */
3636
52
                    {
3637
52
                        proto_item_append_text(extension_ti, " [ ");
3638
3639
52
                        if (numPortc > 0) {
3640
                            /* first portListIndex is outside loop */
3641
52
                            uint32_t port_list_index;
3642
52
                            proto_item *pli_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
3643
52
                                                         offset, 1, ENC_BIG_ENDIAN, &port_list_index);
3644
52
                            if (port_list_index == 0) {
3645
                                /* Value 0 is reserved */
3646
6
                                expert_add_info(pinfo, pli_ti, &ei_oran_port_list_index_zero);
3647
6
                            }
3648
52
                            offset += 1;
3649
3650
1.26k
                            for (n=0; n < numPortc-1; n++) {
3651
                                /* 1 reserved bit */
3652
1.20k
                                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
3653
3654
                                /* port beam ID (or UEID) */
3655
1.20k
                                uint32_t id;
3656
1.20k
                                proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
3657
1.20k
                                                                                             tvb, offset, 2, ENC_BIG_ENDIAN, &id);
3658
1.20k
                                proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
3659
1.20k
                                offset += 2;
3660
3661
1.20k
                                if (id != 0x7fff) {
3662
987
                                    if (number_of_ueids < MAX_UEIDS) {
3663
579
                                        ueids[number_of_ueids++] = id;
3664
579
                                    }
3665
987
                                }
3666
3667
                                /* subsequent portListIndex */
3668
1.20k
                                pli_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
3669
1.20k
                                                             offset, 1, ENC_BIG_ENDIAN, &port_list_index);
3670
1.20k
                                if (port_list_index == 0) {
3671
                                    /* Value 0 is reserved */
3672
404
                                    expert_add_info(pinfo, pli_ti, &ei_oran_port_list_index_zero);
3673
404
                                }
3674
1.20k
                                offset += 1;
3675
3676
1.20k
                                proto_item_append_text(extension_ti, "%u:%u ", port_list_index, id);
3677
1.20k
                            }
3678
52
                        }
3679
3680
52
                        proto_item_append_text(extension_ti, "]");
3681
52
                        break;
3682
29
                    }
3683
3684
3685
0
                    default:
3686
                        /* Warning for unsupported/reserved value */
3687
0
                        expert_add_info(NULL, bgt_ti, &ei_oran_se10_unknown_beamgrouptype);
3688
0
                        break;
3689
132
                }
3690
86
                break;
3691
132
            }
3692
3693
176
            case 11: /* SE 11: Flexible Weights Extension Type */
3694
176
            {
3695
                /* Hidden filter for bf */
3696
176
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3697
176
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3698
3699
                /* beamId in section header should be ignored. Guard against appending multiple times.. */
3700
176
                if (beamId_ti && !beamId_ignored) {
3701
52
                    proto_item_append_text(beamId_ti, " (ignored)");
3702
52
                    beamId_ignored = true;
3703
52
                }
3704
3705
176
                bool disableBFWs;
3706
176
                uint32_t numBundPrb;
3707
176
                bool rad;
3708
3709
                /* disableBFWs */
3710
176
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
3711
176
                                                tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
3712
176
                if (disableBFWs) {
3713
38
                    proto_item_append_text(extension_ti, " (disableBFWs)");
3714
38
                }
3715
3716
                /* RAD */
3717
176
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_rad,
3718
176
                                    tvb, offset, 1, ENC_BIG_ENDIAN, &rad);
3719
                /* bundleOffset (6 bits) */
3720
176
                proto_tree_add_item(extension_tree, hf_oran_bundle_offset, tvb,
3721
176
                                    offset, 1, ENC_BIG_ENDIAN);
3722
176
                offset++;
3723
3724
                /* numBundPrb (number of prbs in each bundle) */
3725
176
                proto_item *num_bund_prb_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_bund_prbs,
3726
176
                                                                           tvb, offset, 1, ENC_BIG_ENDIAN, &numBundPrb);
3727
176
                offset++;
3728
                /* value zero is reserved.. */
3729
176
                if (numBundPrb == 0) {
3730
9
                    expert_add_info(pinfo, num_bund_prb_ti, &ei_oran_reserved_numBundPrb);
3731
9
                }
3732
3733
176
                uint32_t num_bundles;
3734
176
                bool orphaned_prbs = false;
3735
3736
176
                if (!disableBFWs) {
3737
                    /********************************************/
3738
                    /* Table 7.7.1.1-1 */
3739
                    /********************************************/
3740
3741
137
                    uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
3742
137
                    proto_item *comp_meth_ti = NULL;
3743
3744
                    /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
3745
137
                    offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
3746
137
                                                &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
3747
3748
                    /* Work out number of bundles, but take care not to divide by zero. */
3749
137
                    if (numBundPrb == 0) {
3750
6
                        break;
3751
6
                    }
3752
3753
                    /* Work out bundles! */
3754
131
                    ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
3755
131
                    num_bundles = ext11_settings.num_bundles;
3756
3757
                    /* Add (complete) bundles */
3758
1.24k
                    for (unsigned b=0; b < num_bundles; b++) {
3759
1.11k
                        offset = dissect_bfw_bundle(tvb, extension_tree, pinfo, offset,
3760
1.11k
                                                    comp_meth_ti, bfwcomphdr_comp_meth,
3761
1.11k
                                                    NULL /* no ModCompr */,
3762
1.11k
                                                    (ext11_settings.ext21_set) ?
3763
2
                                                        numPrbc :
3764
1.11k
                                                        pref_num_bf_antennas,
3765
1.11k
                                                    bfwcomphdr_iq_width,
3766
1.11k
                                                    b,                                 /* bundle number */
3767
1.11k
                                                    ext11_settings.bundles[b].start,
3768
1.11k
                                                    ext11_settings.bundles[b].end,
3769
1.11k
                                                    ext11_settings.bundles[b].is_orphan);
3770
1.11k
                        if (!offset) {
3771
0
                            break;
3772
0
                        }
3773
1.11k
                    }
3774
131
                    if (num_bundles > 0) {
3775
                        /* Set flag from last bundle entry */
3776
16
                        orphaned_prbs = ext11_settings.bundles[num_bundles-1].is_orphan;
3777
16
                    }
3778
131
                }
3779
39
                else {
3780
                    /********************************************/
3781
                    /* Table 7.7.1.1-2 */
3782
                    /* No weights in this case */
3783
                    /********************************************/
3784
3785
                    /* Work out number of bundles, but take care not to divide by zero. */
3786
39
                    if (numBundPrb == 0) {
3787
3
                        break;
3788
3
                    }
3789
3790
36
                    ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
3791
36
                    num_bundles = ext11_settings.num_bundles;
3792
3793
1.41k
                    for (unsigned n=0; n < num_bundles; n++) {
3794
                        /* contInd */
3795
1.38k
                        proto_tree_add_item(extension_tree, hf_oran_cont_ind,
3796
1.38k
                                            tvb, offset, 1, ENC_BIG_ENDIAN);
3797
                        /* beamId */
3798
1.38k
                        proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_beam_id,
3799
1.38k
                                                             tvb, offset, 2, ENC_BIG_ENDIAN);
3800
1.38k
                        if (!ext11_settings.bundles[n].is_orphan) {
3801
669
                            proto_item_append_text(ti, "    (PRBs %3u-%3u)  (Bundle %2u)",
3802
669
                                                   ext11_settings.bundles[n].start,
3803
669
                                                   ext11_settings.bundles[n].end,
3804
669
                                                   n);
3805
669
                        }
3806
713
                        else {
3807
713
                            orphaned_prbs = true;
3808
713
                            proto_item_append_text(ti, "    (PRBs %3u-%3u)  (Orphaned PRBs)",
3809
713
                                                   ext11_settings.bundles[n].start,
3810
713
                                                   ext11_settings.bundles[n].end);
3811
713
                        }
3812
1.38k
                        offset += 2;
3813
1.38k
                    }
3814
36
                }
3815
3816
                /* Add summary to extension root */
3817
167
                if (orphaned_prbs) {
3818
32
                    proto_item_append_text(extension_ti, " (%u full bundles + orphaned)", num_bundles-1);
3819
32
                }
3820
135
                else {
3821
135
                    proto_item_append_text(extension_ti, " (%u bundles)", num_bundles);
3822
135
                }
3823
167
            }
3824
3825
0
                break;
3826
3827
163
            case 12: /* SE 12: Non-Contiguous PRB Allocation with Frequency Ranges */
3828
163
            {
3829
                /* numSymbol not used in this case */
3830
163
                if (numsymbol_ti && !numsymbol_ignored) {
3831
155
                    proto_item_append_text(numsymbol_ti, " (ignored)");
3832
155
                    numsymbol_ignored = true;
3833
155
                }
3834
3835
163
                ext11_settings.ext12_set = true;
3836
3837
                /* priority */
3838
163
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3839
3840
                /* symbolMask */
3841
163
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
3842
3843
                /* There are now 'R' pairs of (offStartPrb, numPrb) values. Fill extlen bytes with values.  If last one is not set,
3844
                   should be populated with 0s. */
3845
163
                uint32_t extlen_remaining_bytes = (extlen*4) - 4;
3846
163
                uint8_t prb_index;
3847
3848
                /* This is for ST10/ST11.  First pair starts after frames signalled there */
3849
163
                uint16_t st10_st11_offset = startPrbc + numPrbc;
3850
3851
17.5k
                for (prb_index = 1; extlen_remaining_bytes > 0; prb_index++)
3852
17.4k
                {
3853
                    /* Create a subtree for each pair */
3854
17.4k
                    proto_item *pair_ti = proto_tree_add_string(extension_tree, hf_oran_frequency_range,
3855
17.4k
                                                                tvb, offset, 2, "");
3856
17.4k
                    proto_tree *pair_tree = proto_item_add_subtree(pair_ti, ett_oran_frequency_range);
3857
3858
                    /* offStartPrb */
3859
17.4k
                    uint32_t off_start_prb;
3860
17.4k
                    proto_tree_add_item_ret_uint(pair_tree, hf_oran_off_start_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &off_start_prb);
3861
17.4k
                    offset++;
3862
3863
                    /* numPrb */
3864
17.4k
                    uint32_t num_prb;
3865
17.4k
                    proto_tree_add_item_ret_uint(pair_tree, hf_oran_num_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_prb);
3866
17.4k
                    offset++;
3867
3868
17.4k
                    extlen_remaining_bytes -= 2;
3869
3870
                    /* Last pair may be 0,0 if not used. Check for this */
3871
17.4k
                    if ((extlen_remaining_bytes == 0) && (off_start_prb == 0) && (num_prb == 0)) {
3872
8
                        proto_item_append_text(pair_ti, " (not used)");
3873
8
                    }
3874
                    /* Add summary to pair root item, and configure details in ext11_settings */
3875
17.4k
                    else {
3876
17.4k
                        proto_item_append_text(pair_ti, "(%u) [%u : %u]",
3877
17.4k
                                              prb_index, off_start_prb, num_prb);
3878
17.4k
                        proto_item_append_text(extension_ti, "[%u : %u]",
3879
17.4k
                                              off_start_prb, num_prb);
3880
17.4k
                        if (ext11_settings.ext12_num_pairs < MAX_BFW_EXT12_PAIRS) {
3881
10.7k
                            ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs].off_start_prb = off_start_prb;
3882
10.7k
                            ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs++].num_prb = num_prb;
3883
10.7k
                        }
3884
3885
                        /* Also update PRBs to be covered for ST10 type 5 */
3886
                        /* Original range from section is added to.. */
3887
                        /* TODO: I don't think this is quite right.. */
3888
1.64M
                        for (unsigned prb=st10_st11_offset+off_start_prb; prb < st10_st11_offset+off_start_prb+num_prb; prb++) {
3889
1.62M
                            if (prb < MAX_PRBS) {
3890
2.90k
                                prbs_for_st10_type5[prb] = true;
3891
2.90k
                            }
3892
1.62M
                        }
3893
3894
                        /* Any next pair will begin after this one */
3895
17.4k
                        st10_st11_offset += (off_start_prb + num_prb);
3896
17.4k
                    }
3897
17.4k
                }
3898
163
                break;
3899
176
            }
3900
3901
107
            case 13:  /* SE 13: PRB Allocation with Frequency Hopping */
3902
107
            {
3903
                /* Will update settings for ext11 */
3904
107
                ext11_settings.ext13_set = true;
3905
3906
107
                uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3907
107
                uint8_t allocation_index;
3908
3909
107
                unsigned prev_next_symbol_id = 0, prev_next_start_prbc = 0;
3910
3911
12.6k
                for (allocation_index = 1; extlen_remaining_bytes > 0; allocation_index++)
3912
12.5k
                {
3913
                    /* Subtree for allocation */
3914
12.5k
                    proto_item *allocation_ti = proto_tree_add_string(extension_tree, hf_oran_prb_allocation,
3915
12.5k
                                                                tvb, offset, 2, "");
3916
12.5k
                    proto_tree *allocation_tree = proto_item_add_subtree(allocation_ti, ett_oran_prb_allocation);
3917
3918
                    /* Reserved (2 bits) */
3919
12.5k
                    add_reserved_field(allocation_tree, hf_oran_reserved_2bits, tvb, offset, 1);
3920
3921
                    /* nextSymbolId (4 bits) */
3922
12.5k
                    uint32_t next_symbol_id;
3923
12.5k
                    proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextSymbolId, tvb, offset, 1, ENC_BIG_ENDIAN, &next_symbol_id);
3924
3925
                    /* nextStartPrbc (10 bits) */
3926
12.5k
                    uint32_t next_start_prbc;
3927
12.5k
                    proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextStartPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &next_start_prbc);
3928
12.5k
                    offset += 2;
3929
3930
                    /* Add summary to allocation root item */
3931
12.5k
                    proto_item_append_text(allocation_ti, "(%u) nextSymbolId=%3u, nextStartPrbc=%u",
3932
12.5k
                                           allocation_index, next_symbol_id, next_start_prbc);
3933
3934
                    /* Checking for duplicates (expected if e.g. had only 2 entries but extlen bytes still to fill */
3935
12.5k
                    if ((allocation_index > 1) && (next_symbol_id == prev_next_symbol_id) && (next_start_prbc == prev_next_start_prbc)) {
3936
4.61k
                        proto_item_append_text(allocation_ti, " (repeated - to fill up extlen)");
3937
4.61k
                    }
3938
7.90k
                    else {
3939
                        /* Add entry for configuring ext11. don't store out of range */
3940
7.90k
                        if (ext11_settings.ext13_num_start_prbs < MAX_BFW_EXT13_ALLOCATIONS) {
3941
6.59k
                            ext11_settings.ext13_start_prbs[ext11_settings.ext13_num_start_prbs++] = next_start_prbc;
3942
6.59k
                        }
3943
7.90k
                    }
3944
12.5k
                    prev_next_symbol_id = next_symbol_id;
3945
12.5k
                    prev_next_start_prbc = next_start_prbc;
3946
3947
12.5k
                    extlen_remaining_bytes -= 2;
3948
12.5k
                }
3949
107
                break;
3950
176
            }
3951
3952
27
            case 14:  /* SE 14: Nulling-layer Info. for ueId-based beamforming */
3953
                /* Hidden filter for bf (DMRS BF) */
3954
27
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3955
27
                PROTO_ITEM_SET_HIDDEN(bf_ti);
3956
3957
27
                if (!seen_se10) {
3958
26
                    proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
3959
26
                    offset += 1;
3960
26
                    add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
3961
26
                    offset += 1;
3962
26
                }
3963
1
                else {
3964
                    /* Loop over numPortc++1 (from SE 10) nullLayerInd fields  */
3965
41
                    for (unsigned port=0; port < numPortc+1; port++) {
3966
40
                        proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
3967
40
                        offset += 1;
3968
40
                    }
3969
1
                }
3970
27
                break;
3971
3972
22
            case 15:  /* SE 15: Mixed-numerology Info. for ueId-based beamforming */
3973
22
            {
3974
                /* frameStructure */
3975
22
                offset = dissect_frame_structure(extension_tree, tvb, offset,
3976
22
                                                 subframeId, slotId);
3977
                /* freqOffset */
3978
22
                proto_tree_add_item(extension_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN);
3979
22
                offset += 3;
3980
                /* cpLength */
3981
22
                proto_item *cplength_ti = proto_tree_add_item(extension_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
3982
22
                if (sectionType != 0 && sectionType != 3) {
3983
5
                    proto_item_append_text(cplength_ti, "  (ignored - used only with ST0 and ST3)");
3984
5
                }
3985
22
                offset += 2;
3986
22
                break;
3987
176
            }
3988
3989
39
            case 16:  /* SE 16: Antenna mapping in UE channel information based UL beamforming */
3990
39
            {
3991
                /* Just filling available bytes with antMask entries.
3992
                   N.B., if SE 10 also used, could associate each antMask with (beamId or UEId) RX eAxC */
3993
39
                uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3994
39
                unsigned num_ant_masks = extlen_remaining_bytes / 8;
3995
442
                for (unsigned n=0; n < num_ant_masks; n++) {
3996
403
                    proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_antMask, tvb, offset, 8, ENC_BIG_ENDIAN);
3997
403
                    proto_item_append_text(ti, " (RX eAxC #%u)", n+1);
3998
403
                    offset += 8;
3999
403
                }
4000
39
                break;
4001
176
            }
4002
4003
24
            case 17:  /* SE 17: Indication of user port group */
4004
24
            {
4005
24
                uint32_t extlen_remaining_bytes = (extlen*4) - 2;
4006
24
                uint32_t end_bit = (offset+extlen_remaining_bytes) * 8;
4007
24
                uint32_t ueid_index = 1;
4008
                /* TODO: just filling up all available bytes - some may actually be padding.. */
4009
                /* "the preceding Section Type and extension messages implicitly provide the number of scheduled users" */
4010
2.31k
                for (uint32_t bit_offset=offset*8; bit_offset < end_bit; bit_offset+=4, ueid_index++) {
4011
2.29k
                    proto_item *ti = proto_tree_add_bits_item(extension_tree, hf_oran_num_ueid, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
4012
2.29k
                    proto_item_append_text(ti, " (user #%u)", ueid_index);
4013
2.29k
                }
4014
24
                break;
4015
176
            }
4016
4017
21
            case 18:  /* SE 18: Uplink transmission management */
4018
                /* transmissionWindowOffset */
4019
21
                proto_tree_add_item(extension_tree, hf_oran_transmissionWindowOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
4020
21
                offset += 2;
4021
                /* reserved (2 bits) */
4022
21
                add_reserved_field(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4023
                /* transmissionWindowSize (14 bits) */
4024
21
                proto_tree_add_item(extension_tree, hf_oran_transmissionWindowSize, tvb, offset, 2, ENC_BIG_ENDIAN);
4025
21
                offset += 2;
4026
4027
                /* reserved (6 bits) */
4028
21
                add_reserved_field(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1);
4029
                /* toT (2 bits) */
4030
21
                proto_tree_add_item(extension_tree, hf_oran_toT, tvb, offset, 1, ENC_BIG_ENDIAN);
4031
21
                offset += 1;
4032
21
                break;
4033
4034
121
            case 19:  /* SE 19: Compact beamforming information for multiple port */
4035
121
            {
4036
                /* beamId in section header should be ignored. Guard against appending multiple times.. */
4037
121
                if (beamId_ti && !beamId_ignored) {
4038
24
                    proto_item_append_text(beamId_ti, " (ignored)");
4039
24
                    beamId_ignored = true;
4040
24
                }
4041
4042
                /* numSymbol not used in this case */
4043
121
                if (numsymbol_ti && !numsymbol_ignored) {
4044
119
                    proto_item_append_text(numsymbol_ti, " (ignored)");
4045
119
                    numsymbol_ignored = true;
4046
119
                }
4047
4048
                /* disableBFWs */
4049
121
                bool disableBFWs;
4050
121
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
4051
121
                                                tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
4052
121
                if (disableBFWs) {
4053
31
                    proto_item_append_text(extension_ti, " (disableBFWs)");
4054
31
                }
4055
                /* repetition (1 bit) */
4056
121
                uint64_t repetition;
4057
121
                proto_tree_add_bits_ret_val(extension_tree, hf_oran_se19_repetition, tvb, (offset*8)+1, 1, &repetition, ENC_BIG_ENDIAN);
4058
                /* numPortc (6 bits) */
4059
121
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
4060
121
                                             tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
4061
121
                offset++;
4062
4063
                /* priority (2 bits) */
4064
121
                proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
4065
                /* symbolMask (14 bits) */
4066
121
                offset = dissect_symbolmask(tvb, extension_tree, offset, NULL, NULL);
4067
4068
121
                uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
4069
121
                proto_item *comp_meth_ti = NULL;
4070
4071
121
                if (!repetition) {
4072
4073
119
                    if (!disableBFWs) {
4074
                        /* bfwCompHdr */
4075
89
                        offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
4076
89
                                                    &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
4077
89
                    }
4078
4079
                    /* Add entries for each port */
4080
1.22k
                    for (unsigned port=0; port < numPortc; port++) {
4081
4082
                        /* Create subtree for port entry*/
4083
1.10k
                        int port_start_offset = offset;
4084
1.10k
                        proto_item *port_ti = proto_tree_add_string_format(extension_tree, hf_oran_ext19_port,
4085
1.10k
                                                                           tvb, offset, 0,
4086
1.10k
                                                                          "", "Port %u: ", port);
4087
1.10k
                        proto_tree *port_tree = proto_item_add_subtree(port_ti, ett_oran_ext19_port);
4088
4089
                        /* Reserved (4 bits) */
4090
1.10k
                        add_reserved_field(port_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4091
                        /* portReMask (12 bits) */
4092
1.10k
                        proto_tree_add_item(port_tree, hf_oran_portReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4093
1.10k
                        offset += 2;
4094
4095
                        /* Reserved (2 bits) */
4096
1.10k
                        add_reserved_field(port_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4097
                        /* portSymbolMask (14 bits) */
4098
1.10k
                        proto_tree_add_item(port_tree, hf_oran_portSymbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4099
1.10k
                        offset += 2;
4100
4101
                        /* Reserved (1 bit) */
4102
1.10k
                        add_reserved_field(port_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4103
                        /* beamID (15 bits) */
4104
1.10k
                        proto_tree_add_item_ret_uint(port_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
4105
1.10k
                        proto_item_append_text(port_ti, " (beamId=%u)", beamId);
4106
1.10k
                        offset += 2;
4107
4108
                        /* No weights present */
4109
1.10k
                        if (!disableBFWs) {
4110
                            /*******************************************************************/
4111
                            /* Table 7.7.19.1-1 (there is no part -2 for disableBFWs case...), */
4112
                            /* but for SE 11, bfwCompParam was only present for !disableBFWs   */
4113
                            /*******************************************************************/
4114
4115
                            /* bfwCompParam */
4116
575
                            bool compression_method_supported = false;
4117
575
                            uint32_t exponent = 0;
4118
575
                            unsigned num_trx_entries = 0;
4119
575
                            uint16_t *trx;
4120
575
                            offset = dissect_bfwCompParam(tvb, port_tree, pinfo, offset, comp_meth_ti,
4121
575
                                                          &bfwcomphdr_comp_meth, &exponent, &compression_method_supported,
4122
575
                                                          &num_trx_entries, &trx);
4123
4124
575
                            int bit_offset = offset*8;
4125
575
                            int bfw_offset;
4126
4127
                            /* Add weights for each TRX */
4128
575
                            unsigned trx_to_add = (num_trx_entries==0) ? pref_num_bf_antennas : num_trx_entries;
4129
17.1k
                            for (unsigned b=0; b < trx_to_add; b++) {
4130
4131
16.6k
                                uint16_t trx_index = (num_trx_entries) ? trx[b] : b+1;
4132
4133
                                /* Create BFW subtree */
4134
16.6k
                                bfw_offset = bit_offset / 8;
4135
16.6k
                                uint8_t bfw_extent = ((bit_offset + (bfwcomphdr_iq_width*2)) / 8) - bfw_offset;
4136
16.6k
                                proto_item *bfw_ti = proto_tree_add_string_format(port_tree, hf_oran_bfw,
4137
16.6k
                                                                                  tvb, bfw_offset, bfw_extent,
4138
16.6k
                                                                                  "", "TRX %u: (", trx_index);
4139
16.6k
                                proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
4140
4141
                                /* I */
4142
16.6k
                                uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4143
16.6k
                                float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr */, 0 /* RE */);
4144
                                /* Add to tree. */
4145
16.6k
                                proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
4146
16.6k
                                                                  (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
4147
16.6k
                                bit_offset += bfwcomphdr_iq_width;
4148
16.6k
                                proto_item_append_text(bfw_ti, "I%u=%f ", b, value);
4149
4150
                                /* Q */
4151
16.6k
                                bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4152
16.6k
                                value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr */, 0 /* RE */);
4153
                                /* Add to tree. */
4154
16.6k
                                proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
4155
16.6k
                                                                  (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
4156
16.6k
                                bit_offset += bfwcomphdr_iq_width;
4157
16.6k
                                proto_item_append_text(bfw_ti, "Q%u=%f)", b, value);
4158
16.6k
                            }
4159
4160
575
                            offset = (bit_offset+7)/8;
4161
575
                        }
4162
527
                        else {
4163
                            /* No weights... */
4164
527
                        }
4165
4166
                        /* Set length of this port entry */
4167
1.10k
                        proto_item_set_len(port_ti, offset-port_start_offset);
4168
1.10k
                    }
4169
119
                }
4170
121
                break;
4171
176
            }
4172
4173
108
            case 20:  /* SE 20: Puncturing extension */
4174
108
            {
4175
                /* numPuncPatterns */
4176
108
                uint32_t numPuncPatterns;
4177
108
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPuncPatterns, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPatterns);
4178
108
                offset += 1;
4179
4180
                /* Add each puncturing pattern */
4181
3.43k
                for (uint32_t n=0; n < numPuncPatterns; n++) {
4182
3.32k
                    unsigned pattern_start_offset = offset;
4183
4184
                    /* Subtree for this puncturing pattern */
4185
3.32k
                    proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_puncPattern,
4186
3.32k
                                                                         tvb, offset, 0,
4187
3.32k
                                                                         "", "Puncturing Pattern: %u/%u", n+1, numPuncPatterns);
4188
3.32k
                    proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_punc_pattern);
4189
4190
                    /* SymbolMask (14 bits) */
4191
3.32k
                    proto_tree_add_item(pattern_tree, hf_oran_symbolMask_ext20, tvb, offset, 2, ENC_BIG_ENDIAN);
4192
3.32k
                    offset += 1;
4193
4194
3.32k
                    uint32_t startPuncPrb, numPuncPrb;
4195
4196
                    /* startPuncPrb (10 bits) */
4197
3.32k
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_startPuncPrb, tvb, offset, 2, ENC_BIG_ENDIAN, &startPuncPrb);
4198
3.32k
                    offset += 2;
4199
                    /* numPuncPrb (8 bits) */
4200
3.32k
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_numPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPrb);
4201
3.32k
                    offset += 1;
4202
4203
3.32k
                    proto_item_append_text(pattern_ti, " [%u->%u]", startPuncPrb, startPuncPrb+numPuncPrb-1);
4204
4205
                    /* Make a hole in range of PRBs to report */
4206
277k
                    for (unsigned p=startPuncPrb; p < startPuncPrb+numPuncPrb; p++) {
4207
273k
                        if (p < MAX_PRBS) {
4208
95.1k
                            prbs_for_st10_type5[p] = false;
4209
95.1k
                        }
4210
273k
                    }
4211
4212
                    /* puncReMask (12 bits) */
4213
3.32k
                    proto_tree_add_item(pattern_tree, hf_oran_puncReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4214
3.32k
                    offset += 1;
4215
                    /* rb (1 bit) */
4216
3.32k
                    proto_item *rb_ti = proto_tree_add_item(pattern_tree, hf_oran_rb, tvb, offset, 1, ENC_BIG_ENDIAN);
4217
                    /* reserved (1 bit) */
4218
3.32k
                    add_reserved_field(pattern_tree, hf_oran_reserved_bit5, tvb, offset, 1);
4219
                    /* multiSDScope (1 bit) */
4220
3.32k
                    proto_tree_add_item(pattern_tree, hf_oran_multiSDScope, tvb, offset, 1, ENC_BIG_ENDIAN);
4221
                    /* rbgIncl (1 bit) */
4222
3.32k
                    bool rbgIncl;
4223
3.32k
                    proto_tree_add_item_ret_boolean(pattern_tree, hf_oran_RbgIncl, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgIncl);
4224
3.32k
                    offset += 1;
4225
4226
3.32k
                    if (rbgIncl) {
4227
                        /* reserved (1 bit) */
4228
914
                        add_reserved_field(pattern_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4229
                        /* rbgSize(3 bits) */
4230
914
                        proto_tree_add_item(pattern_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN);
4231
                        /* rbgMask (28 bits) */
4232
914
                        proto_tree_add_item(pattern_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN);
4233
914
                        offset += 4;
4234
4235
914
                        proto_item_append_text(rb_ti, " (ignored)");
4236
914
                    }
4237
4238
3.32k
                    proto_item_set_len(pattern_ti, offset-pattern_start_offset);
4239
3.32k
                }
4240
4241
108
                break;
4242
176
            }
4243
19
            case 21:  /* SE 21: Variable PRB group size for channel information */
4244
19
            {
4245
                /* ciPrbGroupSize */
4246
19
                uint32_t ci_prb_group_size;
4247
19
                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);
4248
19
                offset += 1;
4249
4250
19
                switch (ci_prb_group_size) {
4251
2
                    case 0:
4252
4
                    case 1:
4253
5
                    case 255:
4254
                        /* Reserved value */
4255
5
                        expert_add_info_format(pinfo, prb_group_size_ti, &ei_oran_ci_prb_group_size_reserved,
4256
5
                                               "SE 11 ciPrbGroupSize is reserved value %u - must be 2-254",
4257
5
                                               ci_prb_group_size);
4258
5
                        break;
4259
14
                    default:
4260
                        /* This value affects how SE 11 is interpreted */
4261
14
                        ext11_settings.ext21_set = true;
4262
14
                        ext11_settings.ext21_ci_prb_group_size = ci_prb_group_size;
4263
4264
14
                        if (numPrbc == 0) {
4265
1
                            expert_add_info(pinfo, numprbc_ti, &ei_oran_numprbc_ext21_zero);
4266
1
                        }
4267
14
                        break;
4268
19
                }
4269
4270
                /* reserved (6 bits) */
4271
19
                add_reserved_field(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1);
4272
4273
                /* prgSize (2 bits). Interpretation depends upon section type (5 or 6), but also mplane parameters? */
4274
19
                if (sectionType == SEC_C_UE_SCHED) {             /* Section Type 5 */
4275
4
                    proto_tree_add_item(extension_tree, hf_oran_prg_size_st5, tvb, offset, 1, ENC_BIG_ENDIAN);
4276
4
                }
4277
15
                else if (sectionType == SEC_C_CH_INFO) {         /* Section Type 6 */
4278
2
                    proto_tree_add_item(extension_tree, hf_oran_prg_size_st6, tvb, offset, 1, ENC_BIG_ENDIAN);
4279
2
                }
4280
19
                offset += 1;
4281
19
                break;
4282
19
            }
4283
4284
7
            case 22:  /* SE 22: ACK/NACK request */
4285
7
            {
4286
7
                uint32_t ack_nack_req_id;
4287
7
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_ack_nack_req_id, tvb, offset, 2,
4288
7
                                             ENC_BIG_ENDIAN, &ack_nack_req_id);
4289
7
                offset += 2;
4290
4291
7
                if (state) {
4292
7
                    if (!PINFO_FD_VISITED(pinfo)) {
4293
                        /* Add this request into conversation state on first pass */
4294
7
                        ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
4295
7
                        request_details->request_frame_number = pinfo->num;
4296
7
                        request_details->request_frame_time = pinfo->abs_ts;
4297
7
                        request_details->requestType = SE22;
4298
                        /* Insert into flow's tree */
4299
7
                        wmem_tree_insert32(state->ack_nack_requests, ack_nack_req_id, request_details);
4300
7
                    }
4301
0
                    else {
4302
                        /* Try to link forward to ST8 response */
4303
0
                        ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
4304
0
                                                                          ack_nack_req_id);
4305
0
                        if (response) {
4306
0
                            show_link_to_acknack_response(extension_tree, tvb, pinfo, response);
4307
0
                        }
4308
0
                    }
4309
7
                }
4310
7
                break;
4311
19
            }
4312
4313
89
            case 23:  /* SE 23: Arbitrary symbol pattern modulation compression parameters */
4314
89
            {
4315
                /* Green common header */
4316
4317
                /* numSymPrbPattern (4 bits) */
4318
89
                uint32_t num_sym_prb_pattern;
4319
89
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_sym_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sym_prb_pattern);
4320
                /* reserved (3 bits) */
4321
89
                add_reserved_field(extension_tree, hf_oran_reserved_bits456, tvb, offset, 1);
4322
                /* prbMode (1 bit) */
4323
89
                bool prb_mode;
4324
89
                proto_tree_add_item_ret_boolean(extension_tree, hf_oran_prb_mode, tvb, offset, 1, ENC_BIG_ENDIAN, &prb_mode);
4325
89
                offset += 1;
4326
4327
                /* reserved (8 bits) */
4328
89
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4329
89
                offset += 1;
4330
4331
                /* Dissect each SymPrbPattern */
4332
639
                for (uint32_t n=0; n < num_sym_prb_pattern; n++) {
4333
4334
                    /* Subtree */
4335
550
                    proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_sym_prb_pattern,
4336
550
                                                                          tvb, offset, 1, "",
4337
550
                                                                          prb_mode ? "PRB-BLOCK" : "PRB-MASK");
4338
550
                    proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_sym_prb_pattern);
4339
4340
4341
                    /* Orange part */
4342
4343
                    /* Reserved (2 bits) */
4344
550
                    add_reserved_field(pattern_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4345
                    /* symMask (14 bits) */
4346
550
                    proto_tree_add_item(pattern_tree, hf_oran_sym_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
4347
550
                    offset += 2;
4348
                    /* numMcScaleOffset (4 bits) */
4349
550
                    uint32_t numMcScaleOffset;
4350
550
                    proto_tree_add_item_ret_uint(pattern_tree, hf_oran_num_mc_scale_offset, tvb, offset, 1, ENC_BIG_ENDIAN, &numMcScaleOffset);
4351
4352
550
                    if (!prb_mode) {     /* PRB-MASK */
4353
                        /* prbPattern (4 bits) */
4354
541
                        proto_tree_add_item(pattern_tree, hf_oran_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN);
4355
541
                        offset += 1;
4356
                        /* reserved (8 bits) */
4357
541
                        add_reserved_field(pattern_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4358
541
                        offset += 1;
4359
541
                    }
4360
9
                    else {               /* PRB-BLOCK */
4361
                        /* prbBlkOffset (8 bits) */
4362
9
                        proto_tree_add_item(pattern_tree, hf_oran_prb_block_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
4363
9
                        offset += 1;
4364
                        /* prbBlkSize (4 bits) */
4365
9
                        proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
4366
9
                        offset += 1;
4367
9
                    }
4368
4369
                    /* Yellowish part */
4370
550
                    if (prb_mode) {   /* PRB-BLOCK */
4371
                        /* prbBlkSize (4 bits) */
4372
0
                        proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
4373
0
                    }
4374
550
                    else {
4375
                        /* reserved (4 bits) */
4376
550
                        add_reserved_field(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4377
550
                    }
4378
4379
2.46k
                    for (unsigned c=0; c < numMcScaleOffset; c++) {
4380
4381
1.91k
                        if (c > 0) {
4382
                            /* reserved (4 bits) */
4383
1.60k
                            add_reserved_field(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4384
1.60k
                        }
4385
4386
1.91k
                        static int * const  remask_flags_even[] = {
4387
1.91k
                            &hf_oran_mc_scale_re_mask_re1_even,
4388
1.91k
                            &hf_oran_mc_scale_re_mask_re2_even,
4389
1.91k
                            &hf_oran_mc_scale_re_mask_re3_even,
4390
1.91k
                            &hf_oran_mc_scale_re_mask_re4_even,
4391
1.91k
                            &hf_oran_mc_scale_re_mask_re5_even,
4392
1.91k
                            &hf_oran_mc_scale_re_mask_re6_even,
4393
1.91k
                            &hf_oran_mc_scale_re_mask_re7_even,
4394
1.91k
                            &hf_oran_mc_scale_re_mask_re8_even,
4395
1.91k
                            &hf_oran_mc_scale_re_mask_re9_even,
4396
1.91k
                            &hf_oran_mc_scale_re_mask_re10_even,
4397
1.91k
                            &hf_oran_mc_scale_re_mask_re11_even,
4398
1.91k
                            &hf_oran_mc_scale_re_mask_re12_even,
4399
1.91k
                            NULL
4400
1.91k
                        };
4401
4402
                        /* mcScaleReMask (12 bits).  Defines which REs the following csf and mcScaleOffset apply to */
4403
1.91k
                        uint64_t mcScaleReMask, mcScaleOffset;
4404
1.91k
                        proto_tree_add_bitmask_ret_uint64(pattern_tree, tvb, offset,
4405
1.91k
                                                          hf_oran_mc_scale_re_mask_even,
4406
1.91k
                                                          ett_oran_mc_scale_remask,
4407
1.91k
                                                          remask_flags_even, ENC_BIG_ENDIAN, &mcScaleReMask);
4408
4409
1.91k
                        offset += 2;
4410
                        /* csf (1 bit) */
4411
1.91k
                        bool csf;
4412
1.91k
                        dissect_csf(pattern_tree, tvb, offset*8, ci_iq_width, &csf);
4413
                        /* mcScaleOffset (15 bits) */
4414
1.91k
                        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);
4415
1.91k
                        uint16_t exponent = (mcScaleOffset >> 11) & 0x000f; /* m.s. 4 bits */
4416
1.91k
                        uint16_t mantissa = mcScaleOffset & 0x07ff;         /* l.s. 11 bits */
4417
1.91k
                        float mcScaleOffset_value = ((float)mantissa/(1<<11)) * ((float)1.0 / (1 << exponent));
4418
1.91k
                        proto_item_append_text(ti, " (%f)", mcScaleOffset_value);
4419
4420
1.91k
                        offset += 2;
4421
4422
                        /* Record this config.  */
4423
1.91k
                        section_mod_compr_config_t* sect_config = get_mod_compr_section_to_write(state, sectionId);
4424
4425
1.91k
                        if (sect_config && sect_config->num_configs < MAX_MOD_COMPR_CONFIGS) {
4426
483
                            unsigned i = sect_config->num_configs;
4427
483
                            sect_config->configs[i].mod_compr_re_mask = (uint16_t)mcScaleReMask;
4428
483
                            sect_config->configs[i].mod_compr_csf = csf;
4429
483
                            sect_config->configs[i].mod_compr_scaler = mcScaleOffset_value;
4430
483
                            sect_config->num_configs++;
4431
483
                        }
4432
1.91k
                    }
4433
4434
550
                    proto_item_set_end(pattern_ti, tvb, offset);
4435
550
                }
4436
89
                break;
4437
19
            }
4438
4439
49
            case 24:   /* SE 24: PUSCH DMRS configuration */
4440
49
            {
4441
                /* Hidden filter for bf (DMRS BF) */
4442
49
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4443
49
                PROTO_ITEM_SET_HIDDEN(bf_ti);
4444
4445
                /* alpnPerSym (1 bit) */
4446
49
                proto_tree_add_item(extension_tree, hf_oran_alpn_per_sym, tvb, offset, 1, ENC_BIG_ENDIAN);
4447
                /* antDmrsSnr (1 bit) */
4448
49
                proto_tree_add_item(extension_tree, hf_oran_ant_dmrs_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
4449
                /* reserved (1 bit) */
4450
49
                add_reserved_field(extension_tree, hf_oran_reserved_bit2, tvb, offset, 1);
4451
                /* userGroupSize (5 bits) */
4452
49
                uint32_t user_group_size;
4453
49
                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);
4454
49
                if (user_group_size == 0) {
4455
16
                    proto_item_append_text(ugs_ti, " (not used)");
4456
16
                }
4457
33
                else if (user_group_size > 12) {
4458
16
                    proto_item_append_text(ugs_ti, " (reserved)");
4459
16
                }
4460
49
                offset += 1;
4461
                /* userGroupId (8 bits)*/
4462
49
                uint32_t user_group_id;
4463
49
                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);
4464
49
                if (user_group_id == 0) {
4465
                    /* TODO: Value 0 can happen in several cases, described in 7.7.24.7.. */
4466
16
                }
4467
49
                if (user_group_id == 255) {
4468
                    /* Value 255 is reserved */
4469
3
                    expert_add_info(pinfo, ugi_ti, &ei_oran_user_group_id_reserved_value);
4470
3
                }
4471
49
                offset += 1;
4472
4473
49
                bool seen_value_to_inherit = false;
4474
49
                bool inherited_config_has_transform_precoding = false;
4475
49
                int dmrs_configs_seen = 0;
4476
4477
                /* Dissect each entry until reach number of configured ueIds (or run out of extlen bytes..) */
4478
49
                uint32_t ueid_index = 0;
4479
82
                while ((offset < (extension_start_offset + extlen*4)) && (ueid_index < number_of_ueids)) {
4480
34
                    dmrs_configs_seen++;
4481
4482
                    /* Subtree */
4483
34
                    proto_item *entry_ti = proto_tree_add_string_format(extension_tree, hf_oran_dmrs_entry,
4484
34
                                                                        tvb, offset, 0, "",
4485
34
                                                                        "Entry");
4486
34
                    proto_tree *entry_tree = proto_item_add_subtree(entry_ti, ett_oran_dmrs_entry);
4487
4488
                    /* entryType (3 bits) */
4489
34
                    uint32_t entry_type;
4490
34
                    proto_item *entry_type_ti;
4491
34
                    entry_type_ti = proto_tree_add_item_ret_uint(entry_tree, hf_oran_entry_type, tvb, offset, 1, ENC_BIG_ENDIAN, &entry_type);
4492
34
                    if (entry_type > 3) {
4493
15
                        proto_item_append_text(entry_type_ti, " (reserved)");
4494
15
                    }
4495
4496
                    /* dmrsPortNumber (5 bits).  Values 0-11 allowed */
4497
34
                    unsigned int dmrs_port_number;
4498
34
                    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);
4499
34
                    if (dmrs_port_number > 11) {
4500
19
                        proto_item_append_text(dpn_ti, " (12-31 are reserved)");
4501
19
                    }
4502
34
                    offset += 1;
4503
4504
                    /* What follows depends upon entryType */
4505
34
                    switch (entry_type) {
4506
8
                        case 0:    /* dmrsPortNumber config same as previous,  ueId ueIdReset=0 */
4507
10
                        case 1:    /* dmrsPortNumber config same as previous,  ueId ueIdReset=1 */
4508
                            /* No further fields for these */
4509
                            /* Error here if no previous values to inherit!! */
4510
10
                            if (!seen_value_to_inherit) {
4511
4
                                expert_add_info_format(pinfo, entry_type_ti, &ei_oran_se24_nothing_to_inherit,
4512
4
                                                       "SE24: have seen entry type %u, but no previous config (type 2 or 3) to inherit config from", entry_type);
4513
4514
4
                            }
4515
                            /* TODO: would be useful to repeat whole inherited config here? */
4516
10
                            break;
4517
4518
6
                        case 2:    /* transform precoding disabled */
4519
9
                        case 3:    /* transform precoding enabled */
4520
9
                        {
4521
                            /* Type 2/3 are very similar.. */
4522
4523
                            /* ueIdReset (1 bit) */
4524
9
                            proto_tree_add_item(entry_tree, hf_oran_ueid_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
4525
                            /* posMeas (1 bit) */
4526
9
                            proto_tree_add_item(entry_tree, hf_oran_pos_meas, tvb, offset, 1, ENC_BIG_ENDIAN);
4527
4528
                            /* dmrsSymbolMask (14 bits) */
4529
9
                            static int * const  dmrs_symbol_mask_flags[] = {
4530
9
                                &hf_oran_dmrs_symbol_mask_s13,
4531
9
                                &hf_oran_dmrs_symbol_mask_s12,
4532
9
                                &hf_oran_dmrs_symbol_mask_s11,
4533
9
                                &hf_oran_dmrs_symbol_mask_s10,
4534
9
                                &hf_oran_dmrs_symbol_mask_s9,
4535
9
                                &hf_oran_dmrs_symbol_mask_s8,
4536
9
                                &hf_oran_dmrs_symbol_mask_s7,
4537
9
                                &hf_oran_dmrs_symbol_mask_s6,
4538
9
                                &hf_oran_dmrs_symbol_mask_s5,
4539
9
                                &hf_oran_dmrs_symbol_mask_s4,
4540
9
                                &hf_oran_dmrs_symbol_mask_s3,
4541
9
                                &hf_oran_dmrs_symbol_mask_s2,
4542
9
                                &hf_oran_dmrs_symbol_mask_s1,
4543
9
                                &hf_oran_dmrs_symbol_mask_s0,
4544
9
                                NULL
4545
9
                            };
4546
9
                            proto_tree_add_bitmask(entry_tree, tvb, offset,
4547
9
                                                   hf_oran_dmrs_symbol_mask, ett_oran_dmrs_symbol_mask, dmrs_symbol_mask_flags, ENC_BIG_ENDIAN);
4548
9
                            offset += 2;
4549
4550
                            /* scrambling */
4551
9
                            proto_tree_add_item(entry_tree, hf_oran_scrambling, tvb, offset, 2, ENC_BIG_ENDIAN);
4552
9
                            offset += 2;
4553
4554
                            /* nscid (1 bit) */
4555
9
                            proto_tree_add_item(entry_tree, hf_oran_nscid, tvb, offset, 1, ENC_BIG_ENDIAN);
4556
4557
                            /* These 5 bits differ depending upon entry type */
4558
9
                            if (entry_type == 2) {       /* type 2 */
4559
                                /* dType (1 bit) */
4560
5
                                proto_tree_add_item(entry_tree, hf_oran_dtype, tvb, offset, 1, ENC_BIG_ENDIAN);
4561
                                /* cdmWithoutData (2 bits) */
4562
5
                                proto_tree_add_item(entry_tree, hf_oran_cmd_without_data, tvb, offset, 1, ENC_BIG_ENDIAN);
4563
                                /* lambda (2 bits) */
4564
5
                                proto_tree_add_item(entry_tree, hf_oran_lambda, tvb, offset, 1, ENC_BIG_ENDIAN);
4565
5
                            }
4566
4
                            else {                        /* type 3 */
4567
                                /* reserved (1 bit) */
4568
4
                                add_reserved_field(entry_tree, hf_oran_reserved_bit1, tvb, offset, 1);
4569
                                /* lowPaprType (2 bits) */
4570
4
                                proto_tree_add_item(entry_tree, hf_oran_low_papr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
4571
                                /* hoppingMode (2 bits) */
4572
4
                                proto_tree_add_item(entry_tree, hf_oran_hopping_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
4573
4
                            }
4574
4575
                            /* firstPrb (9 bits) */
4576
9
                            proto_tree_add_item(entry_tree, hf_oran_first_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
4577
9
                            offset += 1;
4578
                            /* lastPrb (9 bits) */
4579
9
                            proto_tree_add_item(entry_tree, hf_oran_last_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
4580
9
                            offset += 2;
4581
                            /* Reserved (16 bits) */
4582
9
                            add_reserved_field(entry_tree, hf_oran_reserved_16bits, tvb, offset, 2);
4583
9
                            offset += 2;
4584
4585
                            /* Could now see entry types 0 or 1 - they have these values to inherit */
4586
9
                            seen_value_to_inherit = true;
4587
9
                            inherited_config_has_transform_precoding = (entry_type == 3);
4588
9
                            break;
4589
6
                        }
4590
4591
15
                        default:
4592
                            /* reserved - expert info */
4593
15
                            break;
4594
34
                    }
4595
4596
33
                    proto_item_append_text(entry_ti, " [UEId=%u] (dmrsPortNumber=%2u) (type %u - %s) ",
4597
33
                                           ueids[ueid_index++], dmrs_port_number, entry_type, val_to_str_const(entry_type, entry_type_vals, "Unknown"));
4598
33
                    proto_item_set_end(entry_ti, tvb, offset);
4599
4600
33
                    if (entry_type <= 1) {
4601
10
                        proto_item_append_text(entry_ti, " [transform-precoding %s]",
4602
10
                                               inherited_config_has_transform_precoding ? "enabled" : "disabled");
4603
10
                    }
4604
33
                }
4605
4606
48
                proto_item_append_text(extension_ti, " (%d DMRS configs seen)", dmrs_configs_seen);
4607
48
                break;
4608
49
            }
4609
4610
53
            case 25:  /* SE 25: Symbol reordering for DMRS-BF */
4611
                /* Just dissect each available block of 7 bytes as the 14 symbols for a layer,
4612
                   where each layer could be one or apply to all layers. */
4613
53
            {
4614
                /* TODO: should only appear in one section of a message - check? */
4615
53
                unsigned layer = 0;
4616
53
                proto_item *layer_ti;
4617
1.32k
                while (offset+7 <= (extension_start_offset + extlen*4)) {
4618
                    /* Layer subtree */
4619
1.27k
                    layer_ti = proto_tree_add_string_format(extension_tree, hf_oran_symbol_reordering_layer,
4620
1.27k
                                                            tvb, offset, 7, "",
4621
1.27k
                                                            "Layer");
4622
1.27k
                    proto_tree *layer_tree = proto_item_add_subtree(layer_ti, ett_oran_symbol_reordering_layer);
4623
4624
                    /* All 14 symbols for a layer (or all layers) */
4625
18.6k
                    for (unsigned s=0; s < 14; s++) {
4626
17.3k
                        proto_item *sym_ti;
4627
                        /* txWinForOnAirSymbol */
4628
17.3k
                        unsigned int tx_win_for_on_air_symbol;
4629
17.3k
                        sym_ti = proto_tree_add_item_ret_uint(layer_tree,
4630
17.3k
                                                              (s % 2) ? hf_oran_tx_win_for_on_air_symbol_r : hf_oran_tx_win_for_on_air_symbol_l,
4631
17.3k
                                                              tvb, offset, 1, ENC_BIG_ENDIAN, &tx_win_for_on_air_symbol);
4632
17.3k
                        if (tx_win_for_on_air_symbol == 0x0F) {
4633
                            /* Ordering not affected */
4634
3.18k
                            proto_item_append_text(sym_ti, " (sym %u - no info)", s);
4635
3.18k
                        }
4636
14.1k
                        else {
4637
14.1k
                            proto_item_append_text(sym_ti, " (sym %u)", s);
4638
14.1k
                        }
4639
17.3k
                        if (s % 2) {
4640
8.68k
                            offset += 1;
4641
8.68k
                        }
4642
17.3k
                    }
4643
4644
1.27k
                    proto_item_append_text(layer_ti,     " (layer %u)", ++layer);
4645
1.27k
                    proto_item_append_text(extension_ti, " (layer %u)", layer);
4646
1.27k
                }
4647
                /* Set layer subtree label */
4648
53
                if (layer == 1) {
4649
2
                    proto_item_append_text(layer_ti,     " (all)");
4650
2
                    proto_item_append_text(extension_ti, " (all)");
4651
2
                }
4652
53
                if (layer == 0) {
4653
                    /* TODO: are no layers valid?  What does it mean? */
4654
3
                    proto_item_append_text(extension_ti, " (none)");
4655
3
                }
4656
53
                break;
4657
49
            }
4658
4659
67
            case 26:  /* SE 26: Frequency offset feedback */
4660
                /* Reserved (8 bits) */
4661
67
                add_reserved_field(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4662
67
                offset += 1;
4663
                /* Reserved (1 bit) */
4664
67
                add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4665
                /* numFoFb (7 bits) */
4666
67
                unsigned num_fo_fb;
4667
67
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_fo_fb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_fo_fb);
4668
67
                offset += 1;
4669
4670
                /* Add each freqOffsetFb value */
4671
1.49k
                for (unsigned n=0; n < num_fo_fb; n++) {
4672
1.42k
                    unsigned freq_offset_fb;
4673
                    /* freqOffsetFb (16 bits) */
4674
1.42k
                    proto_item *offset_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_freq_offset_fb,
4675
1.42k
                                                                         tvb, offset, 2, ENC_BIG_ENDIAN, &freq_offset_fb);
4676
                    /* Show if maps onto a -ve number */
4677
1.42k
                    if ((freq_offset_fb >= 0x8ad0) && (freq_offset_fb <= 0xffff)) {
4678
367
                        proto_item_append_text(offset_ti, "(value %d)", -1 - (0xffff-freq_offset_fb));
4679
367
                    }
4680
1.42k
                    proto_item_append_text(offset_ti, " [#%u]", n+1);
4681
1.42k
                    offset += 2;
4682
1.42k
                }
4683
67
                break;
4684
4685
46
            case 27: /* SE 27: O-DU controlled dimensionality reduction */
4686
46
            {
4687
                /* Hidden filter for bf (DMRS BF) */
4688
46
                bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4689
46
                PROTO_ITEM_SET_HIDDEN(bf_ti);
4690
4691
                /* beamType (2 bits) */
4692
46
                unsigned beam_type;
4693
46
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_beam_type, tvb, offset, 1, ENC_BIG_ENDIAN, &beam_type);
4694
                /* reserved (6 bits) */
4695
46
                add_reserved_field(extension_tree, hf_oran_reserved_last_6bits, tvb, offset, 1);
4696
46
                offset += 1;
4697
4698
                /* numElements */
4699
46
                unsigned num_elements;
4700
46
                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);
4701
46
                if (num_elements == 0) {
4702
8
                    num_elements = 256;
4703
8
                    proto_item_append_text(num_elements_ti, " (256");
4704
8
                }
4705
4706
46
                offset += 1;
4707
4708
                /* beamId value(s) */
4709
46
                switch (beam_type) {
4710
34
                    case 0:
4711
1.65k
                        for (unsigned n=0; n < num_elements; n++) {
4712
                            /* reserved (1 bit) + beamId */
4713
1.61k
                            add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4714
1.61k
                            proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
4715
1.61k
                            offset += 2;
4716
1.61k
                        }
4717
34
                        break;
4718
4
                    case 1:
4719
                        /* reserved (1 bit) + beamId */
4720
4
                        add_reserved_field(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1);
4721
4
                        proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
4722
4
                        offset += 2;
4723
4
                        break;
4724
8
                    default:
4725
                        /* Unknown type... */
4726
8
                        break;
4727
46
                }
4728
28
                break;
4729
46
            }
4730
4731
39
            case 28: /* SE 28: O-DU controlled frequency resolution for SINR reporting */
4732
39
            {
4733
                /* reserved (3 bits) */
4734
39
                add_reserved_field(extension_tree, hf_oran_reserved_3bits, tvb, offset, 1);
4735
                /* numUeSinrRpt */
4736
39
                uint32_t num_ue_sinr_rpt;
4737
39
                proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_ue_sinr_rpt, tvb, offset, 1, ENC_BIG_ENDIAN, &num_ue_sinr_rpt);
4738
39
                offset += 1;
4739
4740
474
                for (uint32_t n=0; n < num_ue_sinr_rpt; n++) {
4741
                    /* reserved (1 bit) */
4742
435
                    add_reserved_field(extension_tree, (n % 2) ? hf_oran_reserved_bit4 : hf_oran_reserved_1bit,
4743
435
                                       tvb, offset, 1);
4744
4745
                    /* numSinrPerPrb (3 bits).  Taken from alternate nibbles within byte.  */
4746
435
                    proto_tree_add_item(extension_tree, (n % 2) ? hf_oran_num_sinr_per_prb_right : hf_oran_num_sinr_per_prb,
4747
435
                                        tvb, offset, 1, ENC_BIG_ENDIAN);
4748
435
                    if (n % 2) {
4749
208
                        offset += 1;
4750
208
                    }
4751
435
                }
4752
4753
                /* May need to skip beyond half-used byte */
4754
39
                if (num_ue_sinr_rpt % 2) {
4755
16
                    offset += 1;
4756
16
                }
4757
39
                break;
4758
46
            }
4759
4760
18
            case 29: /* SE 29: Cyclic delay adjustment */
4761
                /* reserved (4 bits) */
4762
18
                add_reserved_field(extension_tree, hf_oran_reserved_4bits, tvb, offset, 1);
4763
                /* cdScgSize (4 bits) */
4764
18
                proto_tree_add_item(extension_tree, hf_oran_cd_scg_size, tvb, offset, 1, ENC_BIG_ENDIAN);
4765
18
                offset += 1;
4766
4767
                /* cdScgPhaseStep */
4768
18
                proto_tree_add_item(extension_tree, hf_oran_cd_scg_phase_step, tvb, offset, 1, ENC_BIG_ENDIAN);
4769
18
                offset += 1;
4770
18
                break;
4771
4772
4773
623
            default:
4774
                /* Other/unexpected extension types */
4775
623
                expert_add_info_format(pinfo, exttype_ti, &ei_oran_unhandled_se,
4776
623
                                       "SE %u (%s) not supported by dissector",
4777
623
                                       exttype, val_to_str_ext_const(exttype, &exttype_vals_ext, "Reserved"));
4778
623
                ext_unhandled = true;
4779
623
                break;
4780
2.92k
        }
4781
4782
        /* Check offset compared with extlen.  There should be 0-3 bytes of padding */
4783
1.92k
        int num_padding_bytes = (extension_start_offset + (extlen*4) - offset);
4784
1.92k
        if (!ext_unhandled && ((num_padding_bytes<0) || (num_padding_bytes>3))) {
4785
957
            expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
4786
957
                                   "extlen signalled %u bytes (+ 0-3 bytes padding), but %u were dissected",
4787
957
                                   extlen*4, offset-extension_start_offset);
4788
957
        }
4789
4790
        /* Move offset to beyond signalled length of extension */
4791
1.92k
        offset = extension_start_offset + (extlen*4);
4792
4793
        /* Set length of extension header. */
4794
1.92k
        proto_item_set_len(extension_ti, extlen*4);
4795
1.92k
    }
4796
    /* End of section extension handling */
4797
4798
4799
4800
    /* RRM measurement reports have measurement reports *after* extensions */
4801
19.1k
    if (sectionType == SEC_C_RRM_MEAS_REPORTS)   /* Section Type 10 */
4802
3.71k
    {
4803
        /* Hidden filter for bf (DMFS-BF). No BF weights though.. */
4804
3.71k
        bf_ti = proto_tree_add_item(c_section_tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
4805
3.71k
        PROTO_ITEM_SET_HIDDEN(bf_ti);
4806
4807
3.71k
        bool mf;
4808
5.09k
        do {
4809
            /* Measurement report subtree */
4810
5.09k
            proto_item *mr_ti = proto_tree_add_string_format(c_section_tree, hf_oran_measurement_report,
4811
5.09k
                                                             tvb, offset, 1, "", "Measurement Report");
4812
5.09k
            proto_tree *mr_tree = proto_item_add_subtree(mr_ti, ett_oran_measurement_report);
4813
5.09k
            unsigned report_start_offset = offset;
4814
4815
            /* measurement flag (i.e., more reports after this one) (1 bit) */
4816
5.09k
            proto_tree_add_item_ret_boolean(mr_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
4817
4818
            /* measTypeId (7 bits) */
4819
5.09k
            uint32_t meas_type_id;
4820
5.09k
            proto_item *meas_type_id_ti;
4821
5.09k
            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);
4822
5.09k
            offset += 1;
4823
4824
            /* Common to all measurement types */
4825
5.09k
            unsigned num_elements = 0;
4826
5.09k
            if (meas_type_id == 6) {
4827
                /* numElements */
4828
111
                proto_tree_add_item_ret_uint(mr_tree, hf_oran_num_elements, tvb, offset, 1, ENC_BIG_ENDIAN, &num_elements);
4829
111
            }
4830
4.98k
            else {
4831
                /* All other meas ids have a reserved byte */
4832
4.98k
                add_reserved_field(mr_tree, hf_oran_reserved_8bits, tvb, offset, 1);
4833
4.98k
            }
4834
5.09k
            offset += 1;
4835
4836
            /* measDataSize (16 bits). N.B. begins at mf field, i.e. 2 bytes before this one  */
4837
5.09k
            unsigned meas_data_size;
4838
5.09k
            proto_item *meas_data_size_ti;
4839
5.09k
            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);
4840
5.09k
            meas_data_size *= 4;
4841
5.09k
            proto_item_append_text(meas_data_size_ti, " (%u bytes)", meas_data_size);
4842
5.09k
            offset += 2;
4843
4844
            /* Summary for measurement report root */
4845
5.09k
            proto_item_append_text(mr_ti, " (measTypeId=%u - %s)",
4846
5.09k
                                   meas_type_id, val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
4847
            /* And section header */
4848
5.09k
            proto_item_append_text(tree, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
4849
            /* And Info column */
4850
5.09k
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
4851
4852
            /* Handle specific message type fields */
4853
5.09k
            switch (meas_type_id) {
4854
232
                case 1:
4855
232
                {
4856
                    /* ueTae */
4857
232
                    unsigned ue_tae;
4858
232
                    proto_item *ue_tae_ti;
4859
232
                    ue_tae_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_tae, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_tae);
4860
                    /* Show if maps onto a -ve number */
4861
232
                    if ((ue_tae >= 0x8ad0) && (ue_tae <= 0xffff)) {
4862
36
                        proto_item_append_text(ue_tae_ti, "(value %d)", -1 - (0xffff-ue_tae));
4863
36
                    }
4864
232
                    offset += 2;
4865
4866
                    /* Reserved (16 bits) */
4867
232
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
4868
232
                    offset += 2;
4869
232
                    break;
4870
0
                }
4871
55
                case 2:
4872
                    /* ueLayerPower entries (how many? for now just use up meas_data_size..) */
4873
                    /* TODO: add number of distinct dmrsPortNumber entries seen in SE24 and save in state? */
4874
                    /* Or would it make sense to use the preference 'pref_num_bf_antennas' ? */
4875
2.58k
                    for (unsigned n=0; n < (meas_data_size-4)/2; n++) {
4876
2.53k
                        unsigned ue_layer_power;
4877
2.53k
                        proto_item *ue_layer_power_ti;
4878
2.53k
                        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);
4879
                        /* Show if maps onto a -ve number */
4880
2.53k
                        if ((ue_layer_power >= 0x8ad0) && (ue_layer_power <= 0xffff)) {
4881
857
                            proto_item_append_text(ue_layer_power_ti, "(value %d)", -1 - (0xffff-ue_layer_power));
4882
857
                        }
4883
2.53k
                        offset += 2;
4884
2.53k
                    }
4885
                    /* padding out to 4 bytes */
4886
55
                    break;
4887
179
                case 3:
4888
179
                {
4889
                    /* ueFreqOffset */
4890
179
                    unsigned ue_freq_offset;
4891
179
                    proto_item *ue_freq_offset_ti;
4892
179
                    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);
4893
                    /* Show if maps onto a -ve number */
4894
179
                    if ((ue_freq_offset >= 0x8ad0) && (ue_freq_offset <= 0xffff)) {
4895
29
                        proto_item_append_text(ue_freq_offset_ti, "(value %d)", -1 - (0xffff-ue_freq_offset));
4896
29
                    }
4897
179
                    offset += 2;
4898
4899
                    /* Reserved (16 bits) */
4900
179
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
4901
179
                    offset += 2;
4902
179
                    break;
4903
0
                }
4904
136
                case 4:
4905
209
                case 5:
4906
                    /* reserved (2 bits) */
4907
209
                    add_reserved_field(mr_tree, hf_oran_reserved_2bits, tvb, offset, 1);
4908
                    /* symbolMask (14 bits) */
4909
209
                    offset = dissect_symbolmask(tvb, mr_tree, offset, NULL, NULL);
4910
4911
                    /* 2 bytes for each PRB ipnPower */
4912
52.0k
                    for (unsigned prb=0; prb<MAX_PRBS; prb++) {
4913
                        /* Skip if should not be reported */
4914
51.8k
                        if (!prbs_for_st10_type5[prb]) {
4915
48.3k
                            continue;
4916
48.3k
                        }
4917
3.51k
                        unsigned ipn_power;
4918
3.51k
                        proto_item *ipn_power_ti;
4919
                        /* ipnPower (2 bytes) */
4920
3.51k
                        ipn_power_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ipn_power, tvb, offset, 2, ENC_BIG_ENDIAN, &ipn_power);
4921
3.51k
                        proto_item_append_text(ipn_power_ti, " (PRB %3d)", prb);
4922
                        /* Show if maps onto a -ve number */
4923
3.51k
                        if ((ipn_power >= 0x8ad0) && (ipn_power <= 0xffff)) {
4924
979
                            proto_item_append_text(ipn_power_ti, " (value %d)", -1 - (0xffff-ipn_power));
4925
979
                        }
4926
3.51k
                        offset += 2;
4927
3.51k
                    }
4928
                    /* padding out to 4 bytes */
4929
209
                    break;
4930
110
                case 6:
4931
                    /* antDmrsSnrVal entries */
4932
2.51k
                    for (unsigned n=0; n < num_elements; n++) {
4933
2.40k
                        unsigned snr_value;
4934
2.40k
                        proto_item *snr_value_ti;
4935
                        /* antDmrsSnrVal (2 bytes) */
4936
2.40k
                        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);
4937
2.40k
                        proto_item_append_text(snr_value_ti, " (elem %2u)", n+1);
4938
                        /* Show if maps onto a -ve number */
4939
2.40k
                        if ((snr_value >= 0x8ad0) && (snr_value <= 0xffff)) {
4940
813
                            proto_item_append_text(snr_value_ti, " (value %d)", -1 - (0xffff-snr_value));
4941
813
                        }
4942
2.40k
                        offset += 2;
4943
2.40k
                    }
4944
110
                    break;
4945
102
                case 7:
4946
102
                {
4947
                    /* UE positioning measurement report */
4948
102
                    float start_value;
4949
4950
                    /* ueAzAoa (16 bits) */
4951
102
                    uint32_t ue_az_aoa;
4952
102
                    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);
4953
102
                    if (ue_az_aoa <= 0xE0F) {
4954
72
                        if (ue_az_aoa >= 0x0708) {
4955
16
                            start_value = (ue_az_aoa-0x0708) * (float)0.1;
4956
16
                            proto_item_append_text(ue_az_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
4957
16
                        }
4958
56
                        else {
4959
56
                            start_value = 180 + (ue_az_aoa * (float)0.1);
4960
56
                            proto_item_append_text(ue_az_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
4961
56
                        }
4962
72
                    }
4963
30
                    else if (ue_az_aoa == 0xffff) {
4964
3
                        proto_item_append_text(ue_az_aoa_ti, " (invalid measurement result)");
4965
3
                    }
4966
27
                    else {
4967
27
                        proto_item_append_text(ue_az_aoa_ti, " (reserved)");
4968
27
                    }
4969
102
                    offset += 2;
4970
4971
                    /* Reserved (16 bits) */
4972
102
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
4973
102
                    offset += 2;
4974
4975
                    /* ueZeAoa (16 bits) */
4976
102
                    uint32_t ue_ze_aoa;
4977
102
                    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);
4978
102
                    if (ue_ze_aoa <= 0x707) {
4979
54
                        start_value = ue_ze_aoa * (float)0.1;
4980
54
                        proto_item_append_text(ue_ze_aoa_ti, " (%.1f <= val < %.1f degrees)", start_value, start_value + (float)0.1);
4981
54
                    }
4982
48
                    else if (ue_az_aoa == 0xffff) {
4983
3
                        proto_item_append_text(ue_ze_aoa_ti, " (invalid measurement result)");
4984
3
                    }
4985
45
                    else {
4986
45
                        proto_item_append_text(ue_ze_aoa_ti, " (reserved)");
4987
45
                    }
4988
102
                    offset += 2;
4989
4990
                    /* Reserved (16 bits) */
4991
102
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
4992
102
                    offset += 2;
4993
4994
                    /* uePosToaOffset (16 bits) */
4995
102
                    uint32_t ue_pos_toa_offset;
4996
102
                    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);
4997
102
                    if (ue_pos_toa_offset == 0) {
4998
14
                        proto_item_append_text(ue_pos_toa_offset_ti, " (no UE ToA offset, 0 symbols)");
4999
14
                    }
5000
88
                    else if (ue_pos_toa_offset <= 0x7fff) {
5001
73
                        proto_item_append_text(ue_pos_toa_offset_ti, " (+ve UE ToA offset)");
5002
73
                    }
5003
15
                    else if (ue_pos_toa_offset == 0x8000) {
5004
0
                        proto_item_append_text(ue_pos_toa_offset_ti, " (invalid measurement result)");
5005
0
                    }
5006
15
                    else {
5007
15
                        proto_item_append_text(ue_pos_toa_offset_ti, " (-ve UE ToA offset)");
5008
15
                    }
5009
102
                    offset += 2;
5010
5011
                    /* Reserved (16 bits) */
5012
102
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5013
102
                    offset += 2;
5014
102
                    break;
5015
136
                }
5016
82
                case 8:
5017
82
                {
5018
                    /* UE radial speed measurement report */
5019
5020
                    /* ueRadialSpeed (16 bits) */
5021
82
                    uint32_t radial_speed;
5022
82
                    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);
5023
82
                    if (radial_speed <= 10000) {
5024
52
                        proto_item_append_text(radial_speed_ti, " (%.1f km/h)", radial_speed * (float)0.1);
5025
52
                    }
5026
30
                    else if (radial_speed == 0x8000) {
5027
0
                        proto_item_append_text(radial_speed_ti, " (invalid measurement result)");
5028
0
                    }
5029
30
                    else {
5030
30
                        proto_item_append_text(radial_speed_ti, " (reserved value)");
5031
30
                    }
5032
82
                    offset += 2;
5033
5034
                    /* Reserved (16 bits) */
5035
82
                    add_reserved_field(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5036
82
                    offset += 2;
5037
82
                    break;
5038
136
                }
5039
5040
4.00k
                default:
5041
                    /* Anything else is not expected */
5042
4.00k
                    expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
5043
4.00k
                                           "measTypeId %u (%s) not supported - only 1-6 are expected",
5044
4.00k
                                           meas_type_id,
5045
4.00k
                                           val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
5046
4.00k
                    break;
5047
5048
5.09k
            }
5049
5050
            /* Pad out to next 4 bytes */
5051
4.86k
            offset += WS_PADDING_TO_4(offset-report_start_offset);
5052
5053
            /* TODO: verify dissected size of report vs meas_data_size? */
5054
5055
            /* End of measurement report tree */
5056
4.86k
            proto_item_set_end(mr_ti, tvb, offset);
5057
4.86k
        } while (mf);
5058
3.71k
    }
5059
5060
    /*  Request for RRM Measurements has measurement commands after extensions */
5061
15.3k
    else if (sectionType == SEC_C_REQUEST_RRM_MEAS)               /* Section Type 11 */
5062
2.11k
    {
5063
2.11k
        bool mf = true;
5064
3.75k
        do {
5065
            /* Measurement command subtree */
5066
3.75k
            proto_item *mc_ti = proto_tree_add_string_format(c_section_tree, hf_oran_measurement_command,
5067
3.75k
                                                             tvb, offset, 8, "", "Measurement Command");
5068
3.75k
            proto_tree *mc_tree = proto_item_add_subtree(mc_ti, ett_oran_measurement_command);
5069
5070
            /* mf (1 bit).  1st measurement command is always preset */
5071
3.75k
            proto_tree_add_item_ret_boolean(mc_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
5072
5073
            /* measTypeId (7 bits) */
5074
3.75k
            uint32_t meas_type_id;
5075
3.75k
            proto_item *meas_type_id_ti;
5076
3.75k
            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);
5077
3.75k
            offset += 1;
5078
5079
3.75k
            proto_item *meas_command_ti;
5080
3.75k
            uint32_t meas_command_size;
5081
5082
3.75k
            switch (meas_type_id) {
5083
106
                case 5:                           /* command for IpN for unallocated PRBs */
5084
                    /* reserved (1 byte) */
5085
106
                    add_reserved_field(mc_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5086
106
                    offset += 1;
5087
                    /* measCmdSize.  Presumably number of words so in future could skip unrecognised command types.. */
5088
106
                    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);
5089
106
                    proto_item_append_text(meas_command_ti, " (%u bytes)", meas_command_size*4);
5090
106
                    offset += 2;
5091
                    /* reserved (2 bits) */
5092
106
                    add_reserved_field(mc_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5093
                    /* symbolMask (14 bits) */
5094
106
                    offset = dissect_symbolmask(tvb, mc_tree, offset, NULL, NULL);
5095
                    /* reserved (16 bits) */
5096
106
                    add_reserved_field(mc_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5097
106
                    offset += 2;
5098
106
                    break;
5099
5100
3.59k
                default:
5101
                    /* Anything else is not expected */
5102
3.59k
                    expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
5103
3.59k
                                           "measTypeId %u (%s) not supported - only 5 is expected",
5104
3.59k
                                           meas_type_id,
5105
3.59k
                                           val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
5106
3.59k
                    break;
5107
3.75k
            }
5108
3.70k
            proto_item_append_text(mc_ti, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
5109
5110
3.70k
        } while (mf);
5111
2.11k
    }
5112
5113
    /* Set extent of overall section */
5114
18.8k
    proto_item_set_len(sectionHeading, offset);
5115
5116
18.8k
    return offset;
5117
19.1k
}
5118
5119
/* Dissect udCompHdr (user data compression header, 7.5.2.10) */
5120
/* bit_width and comp_meth are out params */
5121
static int dissect_udcomphdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
5122
                             bool ignore,
5123
                             unsigned *bit_width, unsigned *comp_meth, proto_item **comp_meth_ti)
5124
1.28k
{
5125
    /* Subtree */
5126
1.28k
    proto_item *udcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_udCompHdr,
5127
1.28k
                                                         tvb, offset, 1, "",
5128
1.28k
                                                         "udCompHdr");
5129
1.28k
    proto_tree *udcomphdr_tree = proto_item_add_subtree(udcomphdr_ti, ett_oran_udcomphdr);
5130
5131
    /* udIqWidth */
5132
1.28k
    uint32_t hdr_iq_width;
5133
1.28k
    proto_item *iq_width_item = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
5134
1.28k
    *bit_width = (hdr_iq_width) ? hdr_iq_width : 16;
5135
1.28k
    proto_item_append_text(iq_width_item, " (%u bits)", *bit_width);
5136
5137
    /* udCompMeth */
5138
1.28k
    uint32_t ud_comp_meth;
5139
1.28k
    *comp_meth_ti = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrMeth, tvb, offset, 1, ENC_NA, &ud_comp_meth);
5140
1.28k
    if (comp_meth) {
5141
1.28k
        *comp_meth = ud_comp_meth;
5142
1.28k
    }
5143
5144
    /* Summary */
5145
1.28k
    if (!ignore) {
5146
1.12k
        proto_item_append_text(udcomphdr_ti, " (IqWidth=%u, udCompMeth=%s)",
5147
1.12k
                               *bit_width, rval_to_str_const(ud_comp_meth, ud_comp_header_meth, "Unknown"));
5148
1.12k
    }
5149
156
    else {
5150
156
        proto_item_append_text(udcomphdr_ti, " (ignored)");
5151
156
        if (hdr_iq_width || ud_comp_meth) {
5152
98
            expert_add_info_format(pinfo, udcomphdr_ti, &ei_oran_udpcomphdr_should_be_zero,
5153
98
                                   "udCompHdr in C-Plane for DL should be 0 - found 0x%02x",
5154
98
                                   tvb_get_uint8(tvb, offset));
5155
98
        }
5156
5157
156
    }
5158
1.28k
    return offset+1;
5159
1.28k
}
5160
5161
/* Dissect udCompParam (user data compression parameter, 8.3.3.15) */
5162
/* bit_width and comp_meth are out params */
5163
static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
5164
                               unsigned comp_meth,
5165
                               uint32_t *exponent, uint16_t *sReSMask,
5166
                               bool for_sinr)
5167
97.9k
{
5168
97.9k
    if (for_sinr && (comp_meth != COMP_BLOCK_FP)) {
5169
        /* sinrCompParam only present when bfp is used */
5170
0
        return offset;
5171
0
    }
5172
5173
97.9k
    if (comp_meth == COMP_NONE ||
5174
97.7k
        comp_meth == COMP_MODULATION ||
5175
97.6k
        comp_meth == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) {
5176
5177
        /* Not even creating a subtree for udCompMeth 0, 4, 8 */
5178
1.13k
        return offset;
5179
1.13k
    }
5180
5181
    /* Subtree */
5182
96.8k
    unsigned start_offset = offset;
5183
96.8k
    proto_item *udcompparam_ti = proto_tree_add_string_format(tree, hf_oran_udCompParam,
5184
96.8k
                                                         tvb, offset, 1, "",
5185
96.8k
                                                         (for_sinr) ? "sinrCompParam" : "udCompParam");
5186
96.8k
    proto_tree *udcompparam_tree = proto_item_add_subtree(udcompparam_ti, ett_oran_udcompparam);
5187
5188
    /* Show comp_meth as a generated field */
5189
96.8k
    proto_item *meth_ti = proto_tree_add_uint(udcompparam_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, comp_meth);
5190
96.8k
    proto_item_set_generated(meth_ti);
5191
5192
96.8k
    uint32_t param_exponent;
5193
96.8k
    uint64_t param_sresmask;
5194
5195
96.8k
    static int * const  sres_mask_flags[] = {
5196
96.8k
        &hf_oran_sReSMask_re12,
5197
96.8k
        &hf_oran_sReSMask_re11,
5198
96.8k
        &hf_oran_sReSMask_re10,
5199
96.8k
        &hf_oran_sReSMask_re9,
5200
96.8k
        &hf_oran_sReSMask_re8,
5201
96.8k
        &hf_oran_sReSMask_re7,
5202
96.8k
        &hf_oran_sReSMask_re6,
5203
96.8k
        &hf_oran_sReSMask_re5,
5204
96.8k
        &hf_oran_sReSMask_re4,
5205
96.8k
        &hf_oran_sReSMask_re3,
5206
96.8k
        &hf_oran_sReSMask_re2,
5207
96.8k
        &hf_oran_sReSMask_re1,
5208
96.8k
        NULL
5209
96.8k
    };
5210
5211
96.8k
    switch (comp_meth) {
5212
5.47k
        case COMP_BLOCK_FP:                    /* 1 */
5213
6.30k
        case BFP_AND_SELECTIVE_RE_WITH_MASKS:  /* 7 */
5214
            /* reserved (4 bits) */
5215
6.30k
            add_reserved_field(udcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5216
            /* exponent (4 bits) */
5217
6.30k
            proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
5218
6.30k
                                         tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
5219
6.30k
            *exponent = param_exponent;
5220
6.30k
            proto_item_append_text(udcompparam_ti, " (Exponent=%u)", param_exponent);
5221
6.30k
            offset += 1;
5222
6.30k
            break;
5223
5224
94
        case COMP_BLOCK_SCALE:                 /* 2 */
5225
            /* Separate into integer and fractional bits? */
5226
94
            proto_tree_add_item(udcompparam_tree, hf_oran_blockScaler,
5227
94
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5228
94
            offset++;
5229
94
            break;
5230
5231
175
        case COMP_U_LAW:                      /* 3 */
5232
            /* compBitWidth, compShift */
5233
175
            proto_tree_add_item(udcompparam_tree, hf_oran_compBitWidth,
5234
175
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5235
175
            proto_tree_add_item(udcompparam_tree, hf_oran_compShift,
5236
175
                                tvb, offset, 1, ENC_BIG_ENDIAN);
5237
175
            offset += 1;
5238
175
            break;
5239
5240
2.83k
        case BFP_AND_SELECTIVE_RE:            /* 5 */
5241
2.83k
        {
5242
            /* sReSMask (exponent in middle!) */
5243
2.83k
            proto_item *sresmask_ti;
5244
2.83k
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
5245
2.83k
                                                            hf_oran_sReSMask,
5246
2.83k
                                                            ett_oran_sresmask,
5247
2.83k
                                                            sres_mask_flags,
5248
2.83k
                                                            ENC_NA,
5249
2.83k
                                                            &param_sresmask);
5250
5251
            /* Get rid of exponent-shaped gap */
5252
2.83k
            param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
5253
2.83k
            unsigned res = 0;
5254
36.8k
            for (unsigned n=0; n < 12; n++) {
5255
34.0k
                if ((param_sresmask >> n) & 0x1) {
5256
11.6k
                    res++;
5257
11.6k
                }
5258
34.0k
            }
5259
2.83k
            proto_item_append_text(sresmask_ti, "   (%2u REs)", res);
5260
5261
            /* exponent */
5262
2.83k
            proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
5263
2.83k
                                         tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
5264
2.83k
            *sReSMask = (uint16_t)param_sresmask;
5265
2.83k
            *exponent = param_exponent;
5266
5267
2.83k
            proto_item_append_text(udcompparam_ti, " (exponent=%u, %u REs)", *exponent, res);
5268
2.83k
            offset += 2;
5269
2.83k
            break;
5270
5.47k
        }
5271
5272
1.24k
        case MOD_COMPR_AND_SELECTIVE_RE:      /* 6 */
5273
1.24k
        {
5274
            /* sReSMask (exponent in middle!) */
5275
1.24k
            proto_item *sresmask_ti;
5276
5277
1.24k
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
5278
1.24k
                                                            hf_oran_sReSMask,
5279
1.24k
                                                            ett_oran_sresmask,
5280
1.24k
                                                            sres_mask_flags,
5281
1.24k
                                                            ENC_NA,
5282
1.24k
                                                            &param_sresmask);
5283
5284
            /* Get rid of reserved-shaped gap */
5285
1.24k
            param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
5286
1.24k
            unsigned res = 0;
5287
16.1k
            for (unsigned n=0; n < 12; n++) {
5288
14.9k
                if ((param_sresmask >> n) & 0x1) {
5289
4.15k
                    res++;
5290
4.15k
                }
5291
14.9k
            }
5292
1.24k
            proto_item_append_text(sresmask_ti, "   (%u REs)", res);
5293
5294
            /* reserved (4 bits) */
5295
1.24k
            add_reserved_field(udcompparam_tree, hf_oran_reserved_last_4bits, tvb, offset, 1);
5296
1.24k
            *sReSMask = (uint16_t)param_sresmask;
5297
5298
1.24k
            proto_item_append_text(udcompparam_ti, " (%u REs)", res);
5299
1.24k
            offset += 2;
5300
1.24k
            break;
5301
5.47k
        }
5302
5303
86.1k
        default:
5304
            /* reserved (set to all zeros), but how many bytes?? */
5305
86.1k
            break;
5306
96.8k
    }
5307
5308
96.8k
    proto_item_set_len(udcompparam_ti, offset-start_offset);
5309
96.8k
    return offset;
5310
96.8k
}
5311
5312
5313
/* Dissect ciCompHdr (channel information compression header, 7.5.2.15) */
5314
/* bit_width and comp_meth are out params */
5315
static int dissect_cicomphdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
5316
                             unsigned *bit_width, unsigned *comp_meth, uint8_t *comp_opt)
5317
208
{
5318
    /* Subtree */
5319
208
    proto_item *cicomphdr_ti = proto_tree_add_string_format(tree, hf_oran_ciCompHdr,
5320
208
                                                         tvb, offset, 1, "",
5321
208
                                                         "ciCompHdr");
5322
208
    proto_tree *cicomphdr_tree = proto_item_add_subtree(cicomphdr_ti, ett_oran_cicomphdr);
5323
5324
    /* ciIqWidth */
5325
208
    uint32_t hdr_iq_width;
5326
208
    proto_item *iq_width_item = proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
5327
208
    hdr_iq_width = (hdr_iq_width) ? hdr_iq_width : 16;
5328
208
    if (bit_width) {
5329
208
        *bit_width = hdr_iq_width;
5330
208
    }
5331
208
    proto_item_append_text(iq_width_item, " (%u bits)", hdr_iq_width);
5332
5333
    /* ciCompMeth */
5334
208
    uint32_t ci_comp_meth;
5335
208
    proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrMeth, tvb, offset, 1, ENC_NA, &ci_comp_meth);
5336
208
    if (comp_meth) {
5337
208
        *comp_meth = ci_comp_meth;
5338
208
    }
5339
5340
    /* ciCompOpt */
5341
208
    uint32_t opt;
5342
208
    proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompOpt, tvb, offset, 1, ENC_NA, &opt);
5343
208
    *comp_opt = opt;
5344
208
    offset += 1;
5345
5346
    /* Summary */
5347
208
    proto_item_append_text(cicomphdr_ti, " (IqWidth=%u, ciCompMeth=%s, ciCompOpt=%s)",
5348
208
                           hdr_iq_width,
5349
208
                           rval_to_str_const(ci_comp_meth, ud_comp_header_meth, "Unknown"),
5350
208
                           (*comp_opt) ?  "compression per PRB" : "compression per UE");
5351
208
    return offset;
5352
208
}
5353
5354
static void dissect_payload_version(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, unsigned offset)
5355
2.67k
{
5356
2.67k
    unsigned version;
5357
2.67k
    proto_item *ti = proto_tree_add_item_ret_uint(tree, hf_oran_payload_version, tvb, offset, 1, ENC_NA, &version);
5358
2.67k
    if (version != 1) {
5359
2.51k
        expert_add_info_format(pinfo, ti, &ei_oran_version_unsupported,
5360
2.51k
                               "PayloadVersion %u not supported by dissector (only 1 is known)",
5361
2.51k
                               version);
5362
        /* TODO: should throw an exception? */
5363
2.51k
    }
5364
2.67k
}
5365
5366
static void show_link_to_acknack_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
5367
                                         ack_nack_request_t *request)
5368
10
{
5369
    /* Request frame */
5370
10
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_request_frame,
5371
10
                                         tvb, 0, 0, request->request_frame_number);
5372
10
    PROTO_ITEM_SET_GENERATED(ti);
5373
5374
    /* Work out gap between frames (in ms) */
5375
10
    int seconds_between_packets = (int)
5376
10
          (pinfo->abs_ts.secs - request->request_frame_time.secs);
5377
10
    int nseconds_between_packets =
5378
10
          pinfo->abs_ts.nsecs - request->request_frame_time.nsecs;
5379
5380
10
    int total_gap = (seconds_between_packets*1000) +
5381
10
                     ((nseconds_between_packets+500000) / 1000000);
5382
5383
10
    ti = proto_tree_add_uint(tree, hf_oran_acknack_request_time,
5384
10
                             tvb, 0, 0, total_gap);
5385
10
    PROTO_ITEM_SET_GENERATED(ti);
5386
5387
    /* Type of request */
5388
10
    ti = proto_tree_add_uint(tree, hf_oran_acknack_request_type,
5389
10
                             tvb, 0, 0, request->requestType);
5390
10
    PROTO_ITEM_SET_GENERATED(ti);
5391
10
}
5392
5393
static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
5394
                                          ack_nack_request_t *response)
5395
0
{
5396
0
    if (response->response_frame_number == 0) {
5397
        /* Requests may not get a response, and can't always tell when  to expect one */
5398
0
        return;
5399
0
    }
5400
5401
    /* Response frame */
5402
0
    proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_response_frame,
5403
0
                                         tvb, 0, 0, response->response_frame_number);
5404
0
    PROTO_ITEM_SET_GENERATED(ti);
5405
5406
    /* Work out gap between frames (in ms) */
5407
0
    int seconds_between_packets = (int)
5408
0
          (response->response_frame_time.secs - pinfo->abs_ts.secs);
5409
0
    int nseconds_between_packets =
5410
0
          response->response_frame_time.nsecs - pinfo->abs_ts.nsecs;
5411
5412
0
    int total_gap = (seconds_between_packets*1000) +
5413
0
                     ((nseconds_between_packets+500000) / 1000000);
5414
5415
0
    ti = proto_tree_add_uint(tree, hf_oran_acknack_response_time,
5416
0
                             tvb, 0, 0, total_gap);
5417
0
    PROTO_ITEM_SET_GENERATED(ti);
5418
0
}
5419
5420
5421
5422
/* Control plane dissector (section 7). */
5423
static int dissect_oran_c(tvbuff_t *tvb, packet_info *pinfo,
5424
                          proto_tree *tree, oran_tap_info *tap_info, void *data _U_)
5425
2.37k
{
5426
    /* Hidden filter for plane */
5427
2.37k
    proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_cplane, tvb, 0, 0, ENC_NA);
5428
2.37k
    PROTO_ITEM_SET_HIDDEN(plane_ti);
5429
5430
    /* Set up structures needed to add the protocol subtree and manage it */
5431
2.37k
    int offset = 0;
5432
5433
2.37k
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-C");
5434
2.37k
    col_set_str(pinfo->cinfo, COL_INFO, "C-Plane");
5435
5436
2.37k
    tap_info->userplane = false;
5437
5438
    /* Create display subtree for the protocol */
5439
2.37k
    proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
5440
2.37k
    proto_item_append_text(protocol_item, "-C");
5441
2.37k
    proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
5442
5443
    /* ecpriRtcid (eAxC ID) */
5444
2.37k
    uint16_t eAxC;
5445
2.37k
    addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_rtcid, &eAxC);
5446
2.37k
    tap_info->eaxc = eAxC;
5447
5448
    /* Look up any existing conversation state for eAxC+plane */
5449
2.37k
    uint32_t key = make_flow_key(pinfo, eAxC, ORAN_C_PLANE, false);
5450
2.37k
    flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
5451
5452
    /* Message identifier */
5453
2.37k
    uint32_t seq_id, sub_seq_id, e;
5454
2.37k
    proto_item *seq_id_ti;
5455
2.37k
    offset = addSeqid(tvb, oran_tree, offset, ORAN_C_PLANE, &seq_id, &seq_id_ti, pinfo, &sub_seq_id, &e);
5456
5457
    /* Section common subtree */
5458
2.37k
    int section_tree_offset = offset;
5459
2.37k
    proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_c_section_common,
5460
2.37k
                                                              tvb, offset, 0, "", "C-Plane Section Type ");
5461
2.37k
    proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section_common);
5462
5463
    /* Peek ahead at the section type */
5464
2.37k
    uint32_t sectionType = 0;
5465
2.37k
    sectionType = tvb_get_uint8(tvb, offset+5);
5466
5467
2.37k
    uint32_t scs = 0;
5468
2.37k
    proto_item *scs_ti = NULL;
5469
5470
    /* dataDirection */
5471
2.37k
    uint32_t direction = 0;
5472
2.37k
    proto_item *datadir_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
5473
2.37k
    tap_info->uplink = (direction==0);
5474
5475
    /* Update/report status of conversation */
5476
2.37k
    if (!PINFO_FD_VISITED(pinfo)) {
5477
5478
2.37k
        if (state == NULL) {
5479
            /* Allocate new state */
5480
469
            state = wmem_new0(wmem_file_scope(), flow_state_t);
5481
469
            state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
5482
469
            wmem_tree_insert32(flow_states_table, key, state);
5483
469
        }
5484
5485
        /* Check sequence analysis status */
5486
2.37k
        if (state->last_frame_seen[direction] && (seq_id != state->next_expected_sequence_number[direction])) {
5487
            /* Store this result */
5488
1.82k
            flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
5489
1.82k
            result->unexpected_seq_number = true;
5490
1.82k
            result->expected_sequence_number = state->next_expected_sequence_number[direction];
5491
1.82k
            result->previous_frame = state->last_frame[direction];
5492
1.82k
            wmem_tree_insert32(flow_results_table, pinfo->num, result);
5493
1.82k
        }
5494
        /* Update conversation info */
5495
2.37k
        state->last_frame[direction] = pinfo->num;
5496
2.37k
        state->last_frame_seen[direction] = true;
5497
2.37k
        state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
5498
2.37k
    }
5499
5500
    /* Show any issues associated with this frame number */
5501
2.37k
    flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
5502
2.37k
    if (result!=NULL && result->unexpected_seq_number) {
5503
1.83k
        expert_add_info_format(pinfo, seq_id_ti,
5504
1.83k
                               (direction == DIR_UPLINK) ?
5505
1.33k
                                   &ei_oran_cplane_unexpected_sequence_number_ul :
5506
1.83k
                                   &ei_oran_cplane_unexpected_sequence_number_dl,
5507
1.83k
                               "Sequence number %u expected, but got %u",
5508
1.83k
                               result->expected_sequence_number, seq_id);
5509
5510
        /* Update tap info */
5511
1.83k
        uint32_t missing_sns = (256 + seq_id - result->expected_sequence_number) % 256;
5512
        /* Don't get confused by being slightly out of order.. */
5513
1.83k
        if (missing_sns < 128) {
5514
134
            tap_info->missing_sns = missing_sns;
5515
134
        }
5516
1.69k
        else {
5517
1.69k
            tap_info->missing_sns = 0;
5518
1.69k
        }
5519
5520
        /* TODO: could add previous/next frames (in seqId tree?) ? */
5521
1.83k
    }
5522
5523
    /* payloadVersion */
5524
2.37k
    dissect_payload_version(section_tree, tvb, pinfo, offset);
5525
5526
    /* filterIndex */
5527
2.37k
    if (sectionType == SEC_C_SLOT_CONTROL || sectionType == SEC_C_ACK_NACK_FEEDBACK) {
5528
        /* scs (for ST4 and ST8) */
5529
272
        scs_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
5530
272
    }
5531
2.10k
    else if (sectionType == SEC_C_RRM_MEAS_REPORTS || sectionType == SEC_C_REQUEST_RRM_MEAS) {
5532
        /* reserved (4 bits) */
5533
710
        add_reserved_field(section_tree, hf_oran_reserved_last_4bits, tvb, offset, 1);
5534
710
    }
5535
1.39k
    else if (sectionType != SEC_C_LAA) {
5536
        /* filterIndex (most common case) */
5537
1.36k
        proto_tree_add_item(section_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
5538
1.36k
    }
5539
2.37k
    offset += 1;
5540
5541
2.37k
    unsigned ref_a_offset = offset;
5542
    /* frameId */
5543
2.37k
    uint32_t frameId = 0;
5544
2.37k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
5545
2.37k
    tap_info->frame = frameId;
5546
2.37k
    offset += 1;
5547
5548
    /* subframeId */
5549
2.37k
    uint32_t subframeId = 0;
5550
2.37k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
5551
    /* slotId */
5552
2.37k
    uint32_t slotId = 0;
5553
2.37k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
5554
2.37k
    tap_info->slot = slotId;
5555
2.37k
    offset++;
5556
5557
    /* startSymbolId */
5558
2.37k
    uint32_t startSymbolId = 0;
5559
2.37k
    proto_item *ssid_ti = NULL;
5560
2.37k
    if ((sectionType == SEC_C_ACK_NACK_FEEDBACK) ||  /* Section Type 8 */
5561
2.33k
        (sectionType == SEC_C_SINR_REPORTING)) {     /* Section Type 9 */
5562
        /* symbolId */
5563
120
        proto_tree_add_item_ret_uint(section_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, &startSymbolId);
5564
120
    }
5565
2.25k
    else if (sectionType != SEC_C_LAA) {
5566
         /* startSymbolId is in most section types */
5567
2.22k
        ssid_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_start_symbol_id, tvb, offset, 1, ENC_NA, &startSymbolId);
5568
2.22k
        if (startSymbolId && (sectionType == SEC_C_RRM_MEAS_REPORTS)) {      /* Section Type 10 */
5569
500
            proto_item_append_text(ssid_ti, " (should be 0 for ST10!)");
5570
500
            expert_add_info_format(pinfo, ssid_ti, &ei_oran_st10_startsymbolid_not_0,
5571
500
                                   "startSymbolId should be 0 for ST10 - found %u", startSymbolId);
5572
500
        }
5573
2.22k
    }
5574
30
    else {
5575
        /* reserved (6 bits) */
5576
30
        add_reserved_field(section_tree, hf_oran_reserved_last_6bits, tvb, offset, 1);
5577
30
    }
5578
2.37k
    offset++;
5579
5580
2.37k
    char id[16];
5581
2.37k
    snprintf(id, 16, "%d-%d-%d-%d", frameId, subframeId, slotId, startSymbolId);
5582
2.37k
    proto_item *pi = proto_tree_add_string(section_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
5583
2.37k
    proto_item_set_generated(pi);
5584
5585
2.37k
    uint32_t cmd_scope = 0;
5586
2.37k
    bool st8_ready = false;
5587
5588
    /* numberOfSections (or whatever section has instead) */
5589
2.37k
    uint32_t nSections = 0;
5590
2.37k
    if (sectionType == SEC_C_SLOT_CONTROL) {          /* Section Type 4 */
5591
        /* Slot Control has these fields instead */
5592
        /* reserved (4 bits) */
5593
235
        add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
5594
        /* cmdScope (4 bits) */
5595
235
        proto_tree_add_item_ret_uint(section_tree, hf_oran_cmd_scope, tvb, offset, 1, ENC_NA, &cmd_scope);
5596
235
    }
5597
2.14k
    else if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {    /* Section Type 8 */
5598
        /* reserved (7 bits) */
5599
37
        add_reserved_field(section_tree, hf_oran_reserved_7bits, tvb, offset, 1);
5600
        /* ready (1 bit) */
5601
        /* TODO: when set, ready in slotId+1.. */
5602
37
        proto_tree_add_item_ret_boolean(section_tree, hf_oran_ready, tvb, offset, 1, ENC_NA, &st8_ready);
5603
37
        if (!st8_ready) {
5604
            /* SCS value is ignored, and may be set to any value by O-RU */
5605
28
            proto_item_append_text(scs_ti, " (ignored)");
5606
28
        }
5607
37
    }
5608
2.10k
    else if (sectionType != SEC_C_LAA) {
5609
        /* numberOfSections */
5610
2.07k
        proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfSections, tvb, offset, 1, ENC_NA, &nSections);
5611
2.07k
    }
5612
30
    else {
5613
30
        add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5614
30
    }
5615
2.37k
    offset++;
5616
5617
    /* sectionType */
5618
2.37k
    proto_tree_add_item_ret_uint(section_tree, hf_oran_sectionType, tvb, offset, 1, ENC_NA, &sectionType);
5619
2.37k
    offset += 1;
5620
5621
    /* Check that dataDirection is consistent with section type */
5622
2.37k
    if (sectionType == SEC_C_SINR_REPORTING && direction != 0) {   /* Section Type 9 */
5623
19
        expert_add_info(pinfo, datadir_ti, &ei_oran_st9_not_ul);
5624
19
    }
5625
2.37k
    if (sectionType == SEC_C_RRM_MEAS_REPORTS && direction != 0) {  /* Section Type 10 */
5626
148
        expert_add_info(pinfo, datadir_ti, &ei_oran_st10_not_ul);
5627
148
    }
5628
5629
    /* Note this section type in stats */
5630
2.37k
    if (sectionType < SEC_C_MAX_INDEX) {
5631
2.23k
        tap_info->section_types[sectionType] = true;
5632
2.23k
    }
5633
5634
    /* Section-type-specific fields following common header (white entries in Section Type diagrams) */
5635
2.37k
    unsigned bit_width = 0;
5636
2.37k
    unsigned comp_meth = 0;
5637
2.37k
    proto_item *comp_meth_ti;
5638
2.37k
    unsigned ci_comp_method = 0;
5639
2.37k
    uint8_t  ci_comp_opt = 0;
5640
5641
2.37k
    uint32_t num_ues = 0;
5642
2.37k
    uint32_t number_of_acks = 0, number_of_nacks = 0;
5643
5644
2.37k
    uint32_t num_sinr_per_prb = 0;
5645
5646
2.37k
    switch (sectionType) {
5647
436
        case SEC_C_UNUSED_RB:   /* Section Type 0 */
5648
            /* timeOffset */
5649
436
            proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
5650
436
            offset += 2;
5651
            /* frameStructure */
5652
436
            offset = dissect_frame_structure(section_tree, tvb, offset,
5653
436
                                             subframeId, slotId);
5654
5655
            /* cpLength */
5656
436
            proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
5657
436
            offset += 2;
5658
            /* reserved (8 bits) */
5659
436
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5660
436
            offset += 1;
5661
436
            break;
5662
5663
255
        case SEC_C_NORMAL:       /* Section Type 1 */
5664
341
        case SEC_C_UE_SCHED:     /* Section Type 5 */
5665
            /* udCompHdr */
5666
341
            offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
5667
341
                                       (direction==1), /* ignore for DL */
5668
341
                                       &bit_width, &comp_meth, &comp_meth_ti);
5669
            /* reserved (8 bits) */
5670
341
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5671
341
            offset += 1;
5672
341
            break;
5673
5674
235
        case SEC_C_SLOT_CONTROL: /* Section Type 4 */
5675
235
            break;
5676
5677
146
        case SEC_C_PRACH:        /* Section Type 3 */
5678
            /* timeOffset */
5679
146
            proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
5680
146
            offset += 2;
5681
            /* frameStructure */
5682
146
            offset = dissect_frame_structure(section_tree, tvb, offset,
5683
146
                                             subframeId, slotId);
5684
            /* cpLength */
5685
146
            proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
5686
146
            offset += 2;
5687
            /* udCompHdr */
5688
146
            offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
5689
146
                                       (direction==1), /* ignore for DL */
5690
146
                                       &bit_width, &comp_meth, &comp_meth_ti);
5691
146
            break;
5692
5693
208
        case SEC_C_CH_INFO:     /* Section Type 6 */
5694
            /* numberOfUEs */
5695
208
            proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfUEs, tvb, offset, 1, ENC_NA, &num_ues);
5696
208
            offset += 1;
5697
            /* ciCompHdr (was reserved) */
5698
208
            offset = dissect_cicomphdr(tvb, pinfo, section_tree, offset, &bit_width, &ci_comp_method, &ci_comp_opt);
5699
5700
            /* Number of sections may not be filled in (at all, or correctly), so set to the number of UEs.
5701
               The data entries are per-UE... they don't have a sectionID, but they could have section extensions... */
5702
208
            if (nSections == 0 || num_ues > nSections) {
5703
77
                nSections = num_ues;
5704
77
            }
5705
208
            break;
5706
5707
12
        case SEC_C_RSVD2:
5708
12
            break;
5709
5710
25
        case SEC_C_LAA:                   /* Section Type 7 */
5711
25
            add_reserved_field(section_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5712
25
            offset += 2;
5713
25
            break;
5714
5715
37
        case SEC_C_ACK_NACK_FEEDBACK:     /* Section Type 8 */
5716
            /* numberOfAcks (1 byte) */
5717
37
            proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_acks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_acks);
5718
37
            offset += 1;
5719
            /* numberOfNacks (1 byte) */
5720
37
            proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_nacks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_nacks);
5721
37
            offset += 1;
5722
5723
            /* Show ACKs and NACKs. For both, try to link back to request. */
5724
1.10k
            for (unsigned int n=1; n <= number_of_acks; n++) {
5725
1.06k
                uint32_t ackid;
5726
1.06k
                proto_item *ack_ti;
5727
1.06k
                ack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_ackid, tvb, offset, 2, ENC_BIG_ENDIAN, &ackid);
5728
1.06k
                offset += 2;
5729
5730
                /* Look up request table in state (which really should be set by now, but test anyway). */
5731
1.06k
                if (state && state->ack_nack_requests) {
5732
1.05k
                    ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, ackid);
5733
1.05k
                    if (request != NULL) {
5734
                        /* On first pass, update with this response */
5735
1
                        if (!PINFO_FD_VISITED(pinfo)) {
5736
1
                            request->response_frame_number = pinfo->num;
5737
1
                            request->response_frame_time = pinfo->abs_ts;
5738
1
                        }
5739
5740
                        /* Show request details */
5741
1
                        show_link_to_acknack_request(section_tree, tvb, pinfo, request);
5742
1
                    }
5743
1.05k
                    else {
5744
                        /* Request not found */
5745
1.05k
                        expert_add_info_format(pinfo, ack_ti, &ei_oran_acknack_no_request,
5746
1.05k
                                               "Response for ackId=%u received, but no request found",
5747
1.05k
                                               ackid);
5748
1.05k
                    }
5749
1.05k
                }
5750
1.06k
            }
5751
773
            for (unsigned int m=1; m <= number_of_nacks; m++) {
5752
736
                uint32_t nackid;
5753
736
                proto_item *nack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_nackid, tvb, offset, 2, ENC_BIG_ENDIAN, &nackid);
5754
736
                offset += 2;
5755
5756
736
                expert_add_info_format(pinfo, nack_ti, &ei_oran_st8_nackid,
5757
736
                                       "Received Nack for ackNackId=%u",
5758
736
                                       nackid);
5759
5760
                /* Look up request table in state. */
5761
736
                if (state && state->ack_nack_requests) {
5762
720
                    ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, nackid);
5763
720
                    if (request) {
5764
                        /* On first pass, update with this response */
5765
9
                        if (!PINFO_FD_VISITED(pinfo)) {
5766
9
                            request->response_frame_number = pinfo->num;
5767
9
                            request->response_frame_time = pinfo->abs_ts;
5768
9
                        }
5769
5770
                        /* Show request details */
5771
9
                        show_link_to_acknack_request(section_tree, tvb, pinfo, request);
5772
9
                    }
5773
711
                    else {
5774
                        /* Request not found */
5775
711
                        expert_add_info_format(pinfo, nack_ti, &ei_oran_acknack_no_request,
5776
711
                                               "Response for nackId=%u received, but no request found",
5777
711
                                               nackid);
5778
711
                    }
5779
720
                }
5780
736
            }
5781
37
            break;
5782
5783
83
        case SEC_C_SINR_REPORTING:     /* Section Type 9 */
5784
83
        {
5785
            /* numSinrPerPrb (3 bits) */
5786
83
            proto_item *nspp_ti;
5787
83
            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);
5788
83
            switch (num_sinr_per_prb) {
5789
40
                case 0:
5790
40
                    num_sinr_per_prb = 1; break;
5791
5
                case 1:
5792
5
                    num_sinr_per_prb = 2; break;
5793
10
                case 2:
5794
10
                    num_sinr_per_prb = 3; break;
5795
7
                case 3:
5796
7
                    num_sinr_per_prb = 4; break;
5797
3
                case 4:
5798
3
                    num_sinr_per_prb = 6; break;
5799
9
                case 5:
5800
9
                    num_sinr_per_prb = 12; break;
5801
5802
9
                default:
5803
9
                    proto_item_append_text(nspp_ti, " (invalid)");
5804
9
                    num_sinr_per_prb = 1;
5805
9
                    expert_add_info_format(pinfo, nspp_ti, &ei_oran_num_sinr_per_prb_unknown,
5806
9
                                           "Invalid numSinrPerPrb value (%u)",
5807
9
                                           num_sinr_per_prb);
5808
83
            }
5809
5810
            /* oruControlSinrSlotMaskId (5 bits) */
5811
83
            proto_tree_add_item(section_tree, hf_oran_oru_control_sinr_slot_mask_id, tvb, offset, 1, ENC_BIG_ENDIAN);
5812
83
            offset += 1;
5813
            /* reserved (8 bits) */
5814
83
            add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5815
83
            offset += 1;
5816
83
            break;
5817
83
        }
5818
5819
563
        case SEC_C_RRM_MEAS_REPORTS:    /* Section Type 10 */
5820
710
        case SEC_C_REQUEST_RRM_MEAS:    /* Section Type 11 */
5821
            /* reserved (16 bits) */
5822
710
            add_reserved_field(section_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5823
710
            offset += 2;
5824
710
            break;
5825
2.37k
    };
5826
5827
    /* Update udCompHdr details in state for UL U-Plane */
5828
2.34k
    if (state && direction==0) {
5829
1.67k
        switch (sectionType) {
5830
143
            case SEC_C_NORMAL:    /* Section Type 1 */
5831
271
            case SEC_C_PRACH:     /* Section Type 3 */
5832
331
            case SEC_C_UE_SCHED:  /* Section Type 5 */
5833
331
                state->ul_ud_comp_hdr_set = true;
5834
331
                state->ul_ud_comp_hdr_bit_width = bit_width;
5835
331
                state->ul_ud_comp_hdr_compression = comp_meth;
5836
331
                state->ul_ud_comp_hdr_frame = pinfo->num;
5837
331
                break;
5838
1.34k
            default:
5839
1.34k
                break;
5840
1.67k
        }
5841
1.67k
    }
5842
5843
5844
2.34k
    proto_item_append_text(sectionHeading, "%d, %s, frameId: %d, subframeId: %d, slotId: %d, startSymbolId: %d",
5845
2.34k
                           sectionType, val_to_str_const(direction, data_direction_vals, "Unknown"),
5846
2.34k
                           frameId, subframeId, slotId, startSymbolId);
5847
2.34k
    if (nSections) {
5848
2.06k
        proto_item_append_text(sectionHeading, ", numberOfSections=%u", nSections);
5849
2.06k
    }
5850
5851
2.34k
    write_pdu_label_and_info(protocol_item, NULL, pinfo, ", Type: %2d %s", sectionType,
5852
2.34k
                             rval_to_str_const(sectionType, section_types_short, "Unknown"));
5853
5854
    /* Set actual length of C-Plane section header */
5855
2.34k
    proto_item_set_len(section_tree, offset - section_tree_offset);
5856
5857
2.34k
    if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {
5858
9
        write_pdu_label_and_info(oran_tree, section_tree, pinfo,
5859
9
                                 (st8_ready) ? " (Ready)" : " (ACK)");
5860
9
    }
5861
5862
5863
    /* Section type 4 doesn't have normal sections, so deal with here before normal sections */
5864
2.34k
    if (sectionType == SEC_C_SLOT_CONTROL) {
5865
        /* numberOfST4Cmds */
5866
235
        uint32_t no_st4_cmds, st4_cmd_len, num_slots, ack_nack_req_id, st4_cmd_type;
5867
235
        proto_item *no_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_st4_cmds,
5868
235
                                                         tvb, offset, 1, ENC_NA, &no_st4_cmds);
5869
235
        if (no_st4_cmds == 0) {
5870
2
            expert_add_info(pinfo, no_ti, &ei_oran_st4_no_cmds);
5871
2
        }
5872
235
        offset += 1;
5873
5874
        /* reserved (1 byte) */
5875
235
        add_reserved_field(section_tree, hf_oran_reserved_8bits, tvb, offset, 1);
5876
235
        offset += 1;
5877
5878
        /* Loop over commands.  Each has 8-byte common header, followed by cmd-specific payload */
5879
235
        proto_item *len_ti;
5880
784
        for (uint32_t n=0; n < no_st4_cmds; n++) {
5881
            /* Table 7.4.6-2: Section Type 4 Command common header format */
5882
778
            proto_item *hdr_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd_header,
5883
778
                                                              tvb, offset, 8, "",
5884
778
                                                              "Type 4 Command common header");
5885
778
            proto_tree *hdr_tree = proto_item_add_subtree(hdr_ti, ett_oran_st4_cmd_header);
5886
5887
            /* st4CmdType */
5888
778
            proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_type, tvb, offset, 1, ENC_NA, &st4_cmd_type);
5889
778
            offset += 1;
5890
5891
            /* st4CmdLen */
5892
778
            len_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_len, tvb, offset, 2, ENC_BIG_ENDIAN, &st4_cmd_len);
5893
778
            if (st4_cmd_len == 0) {
5894
                /* Meaning of 0 not yet defined (v15.00) */
5895
424
                proto_item_append_text(len_ti, " (reserved)");
5896
424
                expert_add_info(pinfo, len_ti, &ei_oran_st4_zero_len_cmd);
5897
424
            }
5898
354
            else {
5899
354
                proto_item_append_text(len_ti, " (%u bytes)", st4_cmd_len*4);
5900
354
            }
5901
778
            offset += 2;
5902
5903
            /* numSlots */
5904
778
            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);
5905
778
            if (num_slots == 0) {
5906
435
                proto_item_append_text(slots_ti, " (until changed)");
5907
435
            }
5908
778
            offset += 1;
5909
5910
            /* ackNackReqId */
5911
778
            proto_item *ack_nack_req_id_ti;
5912
778
            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);
5913
778
            offset += 2;
5914
778
            if (ack_nack_req_id == 0) {
5915
350
                proto_item_append_text(ack_nack_req_id_ti, " (no Section type 8 response expected)");
5916
350
            }
5917
5918
            /* reserved (16 bits) */
5919
778
            add_reserved_field(hdr_tree, hf_oran_reserved_16bits, tvb, offset, 2);
5920
778
            offset += 2;
5921
5922
            /* Set common header summary */
5923
778
            proto_item_append_text(hdr_ti, " (cmd=%s, len=%u, slots=%u, ackNackReqId=%u)",
5924
778
                                   rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"),
5925
778
                                   st4_cmd_len, num_slots, ack_nack_req_id);
5926
5927
778
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
5928
778
                            rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
5929
5930
5931
            /* Subtree for this command body */
5932
778
            proto_item *command_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd,
5933
778
                                                              tvb, offset, 0, "",
5934
778
                                                              "Type 4 Command (%s)", rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
5935
778
            proto_tree *command_tree = proto_item_add_subtree(command_ti, ett_oran_st4_cmd);
5936
5937
778
            unsigned command_start_offset = offset;
5938
5939
            /* Check fields compatible with chosen command. */
5940
778
            if (st4_cmd_type==1) {
5941
143
                if (num_slots != 0) {
5942
                    /* "the value of numSlots should be set to zero for this command type" */
5943
76
                    expert_add_info_format(pinfo, slots_ti, &ei_oran_numslots_not_zero,
5944
76
                                           "numSlots should be zero for ST4 command 1 - found %u",
5945
76
                                           num_slots);
5946
76
                }
5947
143
            }
5948
5949
778
            if (st4_cmd_type==3 || st4_cmd_type==4) {
5950
91
                if (startSymbolId != 0) {
5951
                    /* "expected reception window for the commands is the symbol zero reception window" */
5952
74
                    expert_add_info_format(pinfo, ssid_ti, &ei_oran_start_symbol_id_not_zero,
5953
74
                                           "startSymbolId should be zero for ST4 commands 3&4 - found %u",
5954
74
                                           startSymbolId);
5955
74
                }
5956
91
            }
5957
5958
            /* Add format for this command */
5959
778
            switch (st4_cmd_type) {
5960
143
                case 1:  /* TIME_DOMAIN_BEAM_CONFIG */
5961
143
                {
5962
143
                    bool disable_tdbfns;
5963
143
                    uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
5964
5965
                    /* Hidden filter for bf */
5966
143
                    proto_item *bf_ti = proto_tree_add_item(command_tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
5967
143
                    PROTO_ITEM_SET_HIDDEN(bf_ti);
5968
5969
                    /* reserved (2 bits) */
5970
143
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
5971
                    /* symbolMask (14 bits) */
5972
143
                    uint32_t symbol_mask;
5973
143
                    proto_item *symbol_mask_ti;
5974
143
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &symbol_mask_ti);
5975
                    /* 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 */
5976
                    /* lsb is symbol 0 */
5977
626
                    for (unsigned s=0; s < 14; s++) {
5978
611
                        if ((startSymbolId & (1 << s)) && (startSymbolId > s)) {
5979
128
                            proto_item_append_text(symbol_mask_ti, " (startSymbolId is %u, so some lower symbol bits ignored!)", startSymbolId);
5980
128
                            expert_add_info(pinfo, symbol_mask_ti, &ei_oran_start_symbol_id_bits_ignored);
5981
128
                            break;
5982
128
                        }
5983
611
                    }
5984
5985
                    /* disableTDBFNs (1 bit) */
5986
143
                    proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfns, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfns);
5987
5988
                    /* tdBeamNum (15 bits) */
5989
143
                    proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
5990
143
                    offset += 2;
5991
5992
                    /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
5993
143
                    offset = dissect_bfwCompHdr(tvb, command_tree, offset,
5994
143
                                                &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
5995
                    /* reserved (3 bytes) */
5996
143
                    proto_tree_add_bits_item(command_tree, hf_oran_reserved, tvb, offset*8, 24, ENC_BIG_ENDIAN);
5997
143
                    offset += 3;
5998
5999
143
                    if (disable_tdbfns) {
6000
                        /* No beamnum information to show so get out. */
6001
3
                        break;
6002
3
                    }
6003
6004
                    /* Read beam entries until reach end of command length */
6005
1.91k
                    while ((offset - command_start_offset) < (st4_cmd_len * 4)) {
6006
6007
                        /* disableTDBFWs (1 bit) */
6008
1.77k
                        bool disable_tdbfws;
6009
1.77k
                        proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfws, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfws);
6010
6011
                        /* tdBeamNum (15 bits) */
6012
1.77k
                        proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
6013
1.77k
                        offset += 2;
6014
6015
                        /* Showing BFWs? */
6016
1.77k
                        if (!disable_tdbfws) {
6017
6018
                            /* bfwCompParam */
6019
686
                            unsigned exponent = 0;
6020
686
                            bool     supported = false;
6021
686
                            unsigned num_trx_entries;
6022
686
                            uint16_t *trx_entries;
6023
686
                            offset = dissect_bfwCompParam(tvb, command_tree, pinfo, offset, comp_meth_ti,
6024
686
                                                          &bfwcomphdr_comp_meth, &exponent, &supported,
6025
686
                                                          &num_trx_entries, &trx_entries);
6026
6027
                            /* Antenna count from preference */
6028
686
                            unsigned num_trx = pref_num_bf_antennas;
6029
686
                            int bit_offset = offset*8;
6030
6031
20.2k
                            for (unsigned trx=0; trx < num_trx; trx++) {
6032
                                /* Create antenna subtree */
6033
19.5k
                                int bfw_offset = bit_offset / 8;
6034
19.5k
                                proto_item *bfw_ti = proto_tree_add_string_format(command_tree, hf_oran_bfw,
6035
19.5k
                                                                                  tvb, bfw_offset, 0, "", "TRX %3u: (", trx);
6036
19.5k
                                proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
6037
6038
                                /* I value */
6039
                                /* Get bits, and convert to float. */
6040
19.5k
                                uint32_t bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
6041
19.5k
                                float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr*/, 0 /* RE */);
6042
                                /* Add to tree. */
6043
19.5k
                                proto_tree_add_float(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
6044
19.5k
                                                     (bfwcomphdr_iq_width+7)/8, value);
6045
19.5k
                                bit_offset += bfwcomphdr_iq_width;
6046
19.5k
                                proto_item_append_text(bfw_ti, "I=%f ", value);
6047
6048
                                /* Leave a gap between I and Q values */
6049
19.5k
                                proto_item_append_text(bfw_ti, "  ");
6050
6051
                                /* Q value */
6052
                                /* Get bits, and convert to float. */
6053
19.5k
                                bits = tvb_get_bits32(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
6054
19.5k
                                value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent, NULL /* no ModCompr*/, 0 /* RE */);
6055
                                /* Add to tree. */
6056
19.5k
                                proto_tree_add_float(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
6057
19.5k
                                                     (bfwcomphdr_iq_width+7)/8, value);
6058
19.5k
                                bit_offset += bfwcomphdr_iq_width;
6059
19.5k
                                proto_item_append_text(bfw_ti, "Q=%f", value);
6060
6061
19.5k
                                proto_item_append_text(bfw_ti, ")");
6062
19.5k
                                proto_item_set_len(bfw_ti, (bit_offset+7)/8  - bfw_offset);
6063
19.5k
                            }
6064
                            /* Need to round to next byte */
6065
686
                            offset = (bit_offset+7)/8;
6066
686
                        }
6067
1.77k
                    }
6068
140
                    break;
6069
143
                }
6070
14
                case 2:  /* TDD_CONFIG_PATTERN */
6071
                    /* reserved (2 bits) */
6072
14
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6073
                    /* dirPattern (14 bits) */
6074
14
                    proto_tree_add_item(command_tree, hf_oran_dir_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
6075
14
                    offset += 2;
6076
6077
                    /* reserved (2 bits) */
6078
14
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6079
                    /* guardPattern (14 bits) */
6080
14
                    proto_tree_add_item(command_tree, hf_oran_guard_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
6081
14
                    offset += 2;
6082
14
                    break;
6083
6084
76
                case 3:  /* TRX_CONTROL */
6085
76
                {
6086
                    /* Only allowed cmdScope is ARRAY-COMMAND */
6087
76
                    if (cmd_scope != 0) {
6088
63
                        expert_add_info(pinfo, command_tree, &ei_oran_trx_control_cmd_scope);
6089
63
                    }
6090
6091
                    /* reserved (2 bits) */
6092
76
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6093
                    /* log2MaskBits (4 bits) */
6094
76
                    unsigned log2maskbits;
6095
76
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_log2maskbits, tvb, offset, 1, ENC_BIG_ENDIAN, &log2maskbits);
6096
                    /* sleepMode (2 bits) */
6097
76
                    uint32_t sleep_mode;
6098
76
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_trx, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
6099
76
                    offset += 1;
6100
6101
                    /* reserved (4 bits) */
6102
76
                    add_reserved_field(command_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6103
                    /* numSlotsExt (20 bits) */
6104
76
                    uint32_t num_slots_ext;
6105
76
                    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);
6106
76
                    if (num_slots==0 && num_slots_ext==0) {
6107
5
                        proto_item_append_text(num_slots_ext_ti, " (undefined sleep period)");
6108
5
                    }
6109
71
                    else {
6110
                        /* Time should be rounded up according to SCS */
6111
71
                        float total = (float)(num_slots + num_slots_ext);
6112
                        /* From table 7.5.2.13-3 */
6113
71
                        float slot_length_by_scs[16] = { 1000, 500, 250, 125, 62.5, 31.25,
6114
71
                                                         0, 0, 0, 0, 0, 0,  /* reserved */
6115
71
                                                         1000, 1000, 1000, 1000 };
6116
71
                        float slot_length = slot_length_by_scs[scs];
6117
                        /* Only using valid SCS. TODO: is this test ok? */
6118
71
                        if (slot_length != 0) {
6119
                            /* Round up to next slot */
6120
43
                            total = ((int)(total / slot_length) + 1) * slot_length;
6121
43
                            proto_item_append_text(num_slots_ext_ti, " (defined sleep period of %f us)", total);
6122
43
                        }
6123
71
                    }
6124
76
                    offset += 3;
6125
6126
                    /* reserved (2 bits) */
6127
76
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6128
6129
                    /* symbolMask (14 bits) */
6130
76
                    uint32_t symbol_mask;
6131
76
                    proto_item *sm_ti;
6132
76
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &sm_ti);
6133
76
                    if (symbol_mask == 0x0) {
6134
14
                        proto_item_append_text(sm_ti, " (wake)");
6135
14
                        col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
6136
14
                    }
6137
62
                    else if (symbol_mask == 0x3fff) {
6138
15
                        proto_item_append_text(sm_ti, " (sleep)");
6139
15
                        col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
6140
15
                    }
6141
47
                    else {
6142
47
                        expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
6143
47
                                               "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
6144
47
                                               sleep_mode, symbol_mask);
6145
47
                    }
6146
76
                    offset += 2;
6147
6148
                    /* antMask (16-2048 bits).  Size is lookup from log2MaskBits enum.. */
6149
76
                    unsigned antmask_length = 2;
6150
76
                    if (log2maskbits >= 4) {
6151
46
                        antmask_length = (1 << log2maskbits) / 8;
6152
46
                    }
6153
76
                    proto_item *ant_mask_ti = proto_tree_add_item(command_tree, hf_oran_antMask_trx_control, tvb, offset, antmask_length, ENC_NA);
6154
                    /* show count */
6155
76
                    unsigned antenna_count = 0;
6156
2.59k
                    for (unsigned b=0; b < antmask_length; b++) {
6157
2.51k
                        uint8_t byte = tvb_get_uint8(tvb, offset+b);
6158
22.6k
                        for (unsigned bit=0; bit < 8; bit++) {
6159
20.1k
                            if ((1 << bit) & byte) {
6160
8.43k
                                antenna_count++;
6161
8.43k
                            }
6162
20.1k
                        }
6163
2.51k
                    }
6164
76
                    proto_item_append_text(ant_mask_ti, " (%u antennas)", antenna_count);
6165
76
                    offset += antmask_length;
6166
6167
                    /* Pad to next 4-byte boundary */
6168
76
                    offset = WS_ROUNDUP_4(offset);
6169
76
                    break;
6170
143
                }
6171
6172
15
                case 4:  /* ASM (advanced sleep mode) */
6173
                    /* reserved (2+4=6 bits) */
6174
15
                    add_reserved_field(command_tree, hf_oran_reserved_6bits, tvb, offset, 1);
6175
                    /* sleepMode (2 bits) */
6176
15
                    uint32_t sleep_mode;
6177
15
                    proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_asm, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
6178
15
                    offset += 1;
6179
6180
                    /* reserved (4 bits) */
6181
15
                    add_reserved_field(command_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6182
                    /* numSlotsExt (20 bits) */
6183
15
                    proto_tree_add_item(command_tree, hf_oran_num_slots_ext, tvb, offset, 3, ENC_BIG_ENDIAN);
6184
15
                    offset += 3;
6185
6186
                    /* reserved (2 bits) */
6187
15
                    add_reserved_field(command_tree, hf_oran_reserved_2bits, tvb, offset, 1);
6188
                    /* symbolMask (14 bits) */
6189
15
                    uint32_t symbol_mask;
6190
15
                    proto_item *sm_ti;
6191
15
                    offset = dissect_symbolmask(tvb, command_tree, offset, &symbol_mask, &sm_ti);
6192
15
                    if (symbol_mask == 0x0) {
6193
5
                        proto_item_append_text(sm_ti, " (wake)");
6194
5
                        col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
6195
5
                    }
6196
10
                    else if (symbol_mask == 0x3fff) {
6197
2
                        proto_item_append_text(sm_ti, " (sleep)");
6198
2
                        col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
6199
2
                    }
6200
8
                    else {
6201
8
                        expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
6202
8
                                               "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
6203
8
                                               sleep_mode, symbol_mask);
6204
8
                    }
6205
15
                    offset += 2;
6206
6207
                    /* reserved (2 bytes) */
6208
15
                    add_reserved_field(command_tree, hf_oran_reserved_16bits, tvb, offset, 2);
6209
15
                    offset += 2;
6210
15
                    break;
6211
6212
426
                default:
6213
                    /* Error! */
6214
426
                    expert_add_info_format(pinfo, len_ti, &ei_oran_st4_unknown_cmd,
6215
426
                                           "Dissected ST4 command (%u) not recognised",
6216
426
                                            st4_cmd_type);
6217
426
                    break;
6218
778
            }
6219
6220
            /* Check apparent size of padding (0-3 bytes ok) */
6221
549
            long padding_remaining = command_start_offset + (st4_cmd_len * 4) - offset;
6222
549
            if (padding_remaining < 0 || padding_remaining > 3) {
6223
200
                expert_add_info_format(pinfo, len_ti, &ei_oran_st4_wrong_len_cmd,
6224
200
                                       "Dissected ST4 command does not match signalled st4CmdLen - set to %u (%u bytes) but dissected %u bytes",
6225
200
                                        st4_cmd_len, st4_cmd_len*4, offset-command_start_offset);
6226
200
            }
6227
6228
            /* Advance by signalled length (needs to be aligned on 4-byte boundary) */
6229
549
            offset = command_start_offset + (st4_cmd_len * 4);
6230
6231
            /* Set end of command tree */
6232
549
            proto_item_set_end(command_ti, tvb, offset);
6233
6234
549
            if (ack_nack_req_id != 0 && state && state->ack_nack_requests) {
6235
236
                if (!PINFO_FD_VISITED(pinfo)) {
6236
                    /* Add this request into conversation state on first pass */
6237
236
                    ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
6238
236
                    request_details->request_frame_number = pinfo->num;
6239
236
                    request_details->request_frame_time = pinfo->abs_ts;
6240
236
                    request_details->requestType = ST4Cmd1+st4_cmd_type-1;
6241
6242
236
                    wmem_tree_insert32(state->ack_nack_requests,
6243
236
                                       ack_nack_req_id,
6244
236
                                       request_details);
6245
236
                }
6246
0
                else {
6247
                    /* On later passes, try to link forward to ST8 response */
6248
0
                    ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
6249
0
                                                                      ack_nack_req_id);
6250
0
                    if (response) {
6251
0
                        show_link_to_acknack_response(section_tree, tvb, pinfo, response);
6252
0
                    }
6253
0
                }
6254
236
            }
6255
549
        }
6256
235
    }
6257
    /* LAA doesn't have sections either.. */
6258
2.10k
    else if (sectionType == SEC_C_LAA) {   /* Section Type 7 */
6259
        /* 7.2.5 Table 6.4-6 */
6260
25
        unsigned mcot;
6261
25
        proto_item *mcot_ti;
6262
6263
        /* laaMsgType */
6264
25
        uint32_t laa_msg_type;
6265
25
        proto_item *laa_msg_type_ti;
6266
25
        laa_msg_type_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgType, tvb, offset, 1, ENC_NA, &laa_msg_type);
6267
        /* laaMsgLen */
6268
25
        uint32_t laa_msg_len;
6269
25
        proto_item *len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgLen, tvb, offset, 1, ENC_NA, &laa_msg_len);
6270
25
        proto_item_append_text(len_ti, " (%u bytes)", 4*laa_msg_len);
6271
25
        if (laa_msg_len == 0) {
6272
5
            proto_item_append_text(len_ti, " (reserved)");
6273
5
        }
6274
25
        offset += 1;
6275
6276
25
        int payload_offset = offset;
6277
6278
        /* Payload */
6279
25
        switch (laa_msg_type) {
6280
6
            case 0:
6281
                /* LBT_PDSCH_REQ */
6282
                /* lbtHandle (16 bits) */
6283
6
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6284
6
                offset += 2;
6285
                /* lbtOffset (10 bits) */
6286
6
                proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
6287
6
                offset += 1;
6288
                /* lbtMode  (2 bits) */
6289
6
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
6290
                /* reserved (1 bit) */
6291
6
                add_reserved_field(section_tree, hf_oran_reserved_bit4, tvb, offset, 1);
6292
                /* lbtDeferFactor (3 bits) */
6293
6
                proto_tree_add_item(section_tree, hf_oran_lbtDeferFactor, tvb, offset, 1, ENC_BIG_ENDIAN);
6294
6
                offset += 1;
6295
                /* lbtBackoffCounter (10 bits) */
6296
6
                proto_tree_add_item(section_tree, hf_oran_lbtBackoffCounter, tvb, offset, 2, ENC_BIG_ENDIAN);
6297
6
                offset += 1;
6298
                /* MCOT (4 bits) */
6299
6
                mcot_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_MCOT, tvb, offset, 1, ENC_BIG_ENDIAN, &mcot);
6300
6
                if (mcot<1 || mcot>10) {
6301
3
                    proto_item_append_text(mcot_ti, " (should be in range 1-10!)");
6302
3
                    expert_add_info_format(pinfo, mcot_ti, &ei_oran_mcot_out_of_range,
6303
3
                                           "MCOT seen with value %u (must be 1-10)", mcot);
6304
6305
3
                }
6306
                /* reserved (10 bits) */
6307
6
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+6, 10, ENC_BIG_ENDIAN);
6308
6
                break;
6309
1
            case 1:
6310
                /* LBT_DRS_REQ */
6311
                /* lbtHandle (16 bits) */
6312
1
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6313
1
                offset += 2;
6314
                /* lbtOffset (10 bits) */
6315
1
                proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
6316
1
                offset += 1;
6317
                /* lbtMode  (2 bits) */
6318
1
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
6319
                /* reserved (28 bits) */
6320
1
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+4, 28, ENC_BIG_ENDIAN);
6321
1
                break;
6322
2
            case 2:
6323
                /* LBT_PDSCH_RSP */
6324
                /* lbtHandle (16 bits) */
6325
2
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6326
2
                offset += 2;
6327
                /* lbtPdschRes (2 bits) */
6328
2
                proto_tree_add_item(section_tree, hf_oran_lbtPdschRes, tvb, offset, 1, ENC_BIG_ENDIAN);
6329
                /* inParSF (1 bit) */
6330
2
                proto_tree_add_item(section_tree, hf_oran_initialPartialSF, tvb, offset, 1, ENC_BIG_ENDIAN);
6331
                /* sfStatus (1 bit) */
6332
2
                proto_tree_add_item(section_tree, hf_oran_sfStatus, tvb, offset, 1, ENC_BIG_ENDIAN);
6333
                /* sfnSf (12 bits) */
6334
2
                proto_tree_add_item(section_tree, hf_oran_sfnSfEnd, tvb, offset, 2, ENC_BIG_ENDIAN);
6335
2
                offset += 2;
6336
                /* reserved (24 bits) */
6337
2
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8), 24, ENC_BIG_ENDIAN);
6338
2
                break;
6339
4
            case 3:
6340
                /* LBT_DRS_RSP */
6341
                /* lbtHandle (16 bits) */
6342
4
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6343
4
                offset += 2;
6344
                /* lbtDrsRes (1 bit) */
6345
4
                proto_tree_add_item(section_tree, hf_oran_lbtDrsRes, tvb, offset, 1, ENC_BIG_ENDIAN);
6346
                /* reserved (7 bits) */
6347
4
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
6348
4
                break;
6349
3
            case 4:
6350
                /* LBT_Buffer_Error */
6351
                /* lbtHandle (16 bits) */
6352
3
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6353
3
                offset += 2;
6354
                /* lbtBufErr (1 bit) */
6355
3
                proto_tree_add_item(section_tree, hf_oran_lbtBufErr, tvb, offset, 1, ENC_BIG_ENDIAN);
6356
                /* reserved (7 bits) */
6357
3
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
6358
3
                break;
6359
3
            case 5:
6360
                /* LBT_CWCONFIG_REQ */
6361
                /* lbtHandle (16 bits) */
6362
3
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6363
3
                offset += 2;
6364
                /* lbtCWConfig_H (8 bits) */
6365
3
                proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_H, tvb, offset, 1, ENC_BIG_ENDIAN);
6366
3
                offset += 1;
6367
                /* lbtCWConfig_T (8 bits) */
6368
3
                proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_T, tvb, offset, 1, ENC_BIG_ENDIAN);
6369
3
                offset += 1;
6370
                /* lbtMode  (2 bits) */
6371
3
                proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
6372
                /* lbtTrafficClass (3 bits) */
6373
3
                proto_tree_add_item(section_tree, hf_oran_lbtTrafficClass, tvb, offset, 1, ENC_BIG_ENDIAN);
6374
                /* reserved (19 bits) */
6375
3
                proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+5, 19, ENC_BIG_ENDIAN);
6376
3
                break;
6377
3
            case 6:
6378
                /* LBT_CWCONFIG_RSP */
6379
                /* lbtHandle (16 bits) */
6380
3
                proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
6381
3
                offset += 2;
6382
                /* lbtCWR_Rst (1 bit) */
6383
3
                proto_tree_add_item(section_tree, hf_oran_lbtCWR_Rst, tvb, offset, 1, ENC_BIG_ENDIAN);
6384
                /* reserved (7 bits) */
6385
3
                add_reserved_field(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1);
6386
3
                break;
6387
6388
3
            default:
6389
                /* Unhandled! */
6390
3
                expert_add_info_format(pinfo, laa_msg_type_ti, &ei_oran_laa_msg_type_unsupported,
6391
3
                                       "laaMsgType %u not supported by dissector",
6392
3
                                       laa_msg_type);
6393
6394
3
                break;
6395
25
        }
6396
        /* For now just skip indicated length of bytes */
6397
25
        offset = payload_offset + 4*(laa_msg_len+1);
6398
25
    }
6399
6400
6401
    /* Dissect each C section */
6402
22.7k
    for (uint32_t i = 0; i < nSections; ++i) {
6403
20.6k
        tvbuff_t *section_tvb = tvb_new_subset_remaining(tvb, offset);
6404
20.6k
        offset += dissect_oran_c_section(section_tvb, oran_tree, pinfo, state, sectionType, tap_info,
6405
20.6k
                                         protocol_item,
6406
20.6k
                                         subframeId, slotId,
6407
20.6k
                                         bit_width, ci_comp_method, ci_comp_opt,
6408
20.6k
                                         num_sinr_per_prb);
6409
20.6k
    }
6410
6411
    /* Expert error if we are short of tvb by > 3 bytes */
6412
2.11k
    if (tvb_reported_length_remaining(tvb, offset) > 3) {
6413
72
        expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
6414
72
                               "%u bytes remain at end of frame - should be 0-3",
6415
72
                               tvb_reported_length_remaining(tvb, offset));
6416
72
    }
6417
6418
2.11k
    return tvb_captured_length(tvb);
6419
2.34k
}
6420
6421
static int dissect_oran_u_re(tvbuff_t *tvb, proto_tree *tree,
6422
                             unsigned sample_number, int samples_offset,
6423
                             oran_tap_info *tap_info,
6424
                             unsigned sample_bit_width,
6425
                             int comp_meth,
6426
                             uint32_t exponent,
6427
                             section_mod_compr_config_t *mod_compr_params,
6428
                             uint8_t re)
6429
33.8k
{
6430
    /* I */
6431
33.8k
    unsigned i_bits = tvb_get_bits32(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
6432
33.8k
    float i_value = decompress_value(i_bits, comp_meth, sample_bit_width, exponent, mod_compr_params, re);
6433
33.8k
    unsigned sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
6434
33.8k
    proto_item *i_ti = proto_tree_add_float(tree, hf_oran_iSample, tvb, samples_offset/8, sample_len_in_bytes, i_value);
6435
33.8k
    proto_item_set_text(i_ti, "iSample: % 0.7f  0x%04x (RE-%2u in the PRB)", i_value, i_bits, sample_number);
6436
33.8k
    samples_offset += sample_bit_width;
6437
    /* Q */
6438
33.8k
    unsigned q_bits = tvb_get_bits32(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
6439
33.8k
    float q_value = decompress_value(q_bits, comp_meth, sample_bit_width, exponent, mod_compr_params, re);
6440
33.8k
    sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
6441
33.8k
    proto_item *q_ti = proto_tree_add_float(tree, hf_oran_qSample, tvb, samples_offset/8, sample_len_in_bytes, q_value);
6442
33.8k
    proto_item_set_text(q_ti, "qSample: % 0.7f  0x%04x (RE-%2u in the PRB)", q_value, q_bits, sample_number);
6443
33.8k
    samples_offset += sample_bit_width;
6444
6445
    /* Update RE stats */
6446
33.8k
    tap_info->num_res++;
6447
    /* if (i_value == 0.0 && q_value == 0.0) { */
6448
    /* TODO: is just checking bits from frame good enough - assuming this always corresponds to a zero value? */
6449
33.8k
    if (i_bits == 0 && q_bits == 0) {
6450
5.21k
        tap_info->num_res_zero++;
6451
5.21k
    }
6452
28.6k
    else {
6453
28.6k
        tap_info->non_zero_re_in_current_prb = true;
6454
28.6k
    }
6455
33.8k
    return samples_offset;
6456
33.8k
}
6457
6458
6459
static bool udcomplen_appears_present(bool udcomphdr_present, tvbuff_t *tvb, int offset)
6460
668
{
6461
668
    if (!udcomplen_heuristic_result_set) {
6462
        /* All sections will start the same way */
6463
2
        unsigned int section_bytes_before_field = (udcomphdr_present) ? 6 : 4;
6464
6465
        /* Move offset back to the start of the section */
6466
2
        offset -= section_bytes_before_field;
6467
6468
2
        do {
6469
            /* This field appears several bytes into the U-plane section */
6470
2
            uint32_t length_remaining = tvb_reported_length_remaining(tvb, offset);
6471
            /* Are there enough bytes to still read the length field? */
6472
2
            if (section_bytes_before_field+2 > length_remaining) {
6473
0
                udcomplen_heuristic_result = false;
6474
0
                udcomplen_heuristic_result_set = true;
6475
0
                break;
6476
0
            }
6477
6478
            /* Read the length field */
6479
2
            uint16_t udcomplen = tvb_get_ntohs(tvb, offset+section_bytes_before_field);
6480
6481
            /* Is this less than a valid section? Realistic minimal section will be bigger than this..
6482
             * Could take into account numPrbU, etc */
6483
2
            if (udcomplen < section_bytes_before_field+2) {
6484
0
                udcomplen_heuristic_result = false;
6485
0
                udcomplen_heuristic_result_set = true;
6486
0
                break;
6487
0
            }
6488
6489
            /* Does this section fit into the frame? */
6490
2
            if (udcomplen > length_remaining) {
6491
1
                udcomplen_heuristic_result = false;
6492
1
                udcomplen_heuristic_result_set = true;
6493
1
                break;
6494
1
            }
6495
6496
            /* Move past this section */
6497
1
            offset += udcomplen;
6498
6499
            /* Are we at the end of the frame? */
6500
            /* TODO: if frame is less than 60 bytes, there may be > 4 bytes, likely zeros.. */
6501
1
            if (tvb_reported_length_remaining(tvb, offset) < 4) {
6502
1
                udcomplen_heuristic_result = true;
6503
1
                udcomplen_heuristic_result_set = true;
6504
1
            }
6505
1
        } while (!udcomplen_heuristic_result_set);
6506
2
    }
6507
668
    return udcomplen_heuristic_result;
6508
668
}
6509
6510
static bool at_udcomphdr(tvbuff_t *tvb, int offset)
6511
81
{
6512
81
    if (tvb_captured_length_remaining(tvb, offset) < 2) {
6513
7
        return false;
6514
7
    }
6515
74
    uint8_t first_byte = tvb_get_uint8(tvb, offset);
6516
74
    uint8_t reserved_byte = tvb_get_uint8(tvb, offset+1);
6517
6518
    /* - iq width could be anything, though unlikely to be signalled as (say) < 1-3? */
6519
    /* - meth should be 0-8 */
6520
    /* - reserved byte should be 0 */
6521
74
    return (((first_byte & 0x0f) <= MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) && (reserved_byte == 0));
6522
81
}
6523
6524
static bool udcomphdr_appears_present(flow_state_t *flow, uint32_t direction, tvbuff_t *tvb, int offset)
6525
942
{
6526
    /* Should really not happen, but guard against this anyway. */
6527
942
    if (flow == NULL) {
6528
        /* No state to update. */
6529
0
        return false;
6530
0
    }
6531
6532
942
    if (direction == DIR_UPLINK) {
6533
185
        if (flow->udcomphdrUplink_heuristic_result_set) {
6534
            /* Return cached value */
6535
145
            return flow->udcomphdrUplink_heuristic_result;
6536
145
        }
6537
40
        else {
6538
            /* Work it out, and save answer for next time */
6539
40
            flow->udcomphdrUplink_heuristic_result_set = true;
6540
40
            flow->udcomphdrUplink_heuristic_result = at_udcomphdr(tvb, offset);
6541
40
            return flow->udcomphdrUplink_heuristic_result;
6542
40
        }
6543
185
    }
6544
757
    else {
6545
        /* Downlink */
6546
757
        if (flow->udcomphdrDownlink_heuristic_result_set) {
6547
            /* Return cached value */
6548
716
            return flow->udcomphdrDownlink_heuristic_result;
6549
716
        }
6550
41
        else {
6551
            /* Work it out, and save answer for next time */
6552
41
            flow->udcomphdrDownlink_heuristic_result_set = true;
6553
41
            flow->udcomphdrDownlink_heuristic_result = at_udcomphdr(tvb, offset);
6554
41
            return flow->udcomphdrDownlink_heuristic_result;
6555
41
        }
6556
757
    }
6557
942
}
6558
6559
/* User plane dissector (section 8) */
6560
static int
6561
dissect_oran_u(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
6562
               oran_tap_info *tap_info, void *data _U_)
6563
311
{
6564
    /* Hidden filter for plane */
6565
311
    proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_uplane, tvb, 0, 0, ENC_NA);
6566
311
    PROTO_ITEM_SET_HIDDEN(plane_ti);
6567
6568
    /* Set up structures needed to add the protocol subtree and manage it */
6569
311
    int offset = 0;
6570
6571
311
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-U");
6572
311
    col_set_str(pinfo->cinfo, COL_INFO, "U-Plane");
6573
6574
311
    tap_info->userplane = true;
6575
6576
    /* Create display subtree for the protocol */
6577
311
    proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
6578
311
    proto_item_append_text(protocol_item, "-U");
6579
311
    proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
6580
6581
    /* Transport header */
6582
    /* Real-time control data / IQ data transfer message series identifier */
6583
311
    uint16_t eAxC;
6584
311
    addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_pcid, &eAxC);
6585
311
    tap_info->eaxc = eAxC;
6586
6587
    /* Update/report status of conversation */
6588
311
    uint32_t key = make_flow_key(pinfo, eAxC, ORAN_U_PLANE, false);
6589
311
    flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
6590
6591
    /* Message identifier */
6592
311
    proto_item *seqIdItem;
6593
311
    uint32_t seqId, subSeqId, e;
6594
311
    offset = addSeqid(tvb, oran_tree, offset, ORAN_U_PLANE, &seqId, &seqIdItem, pinfo, &subSeqId, &e);
6595
6596
    /* Common header for time reference */
6597
311
    proto_item *timingHeader = proto_tree_add_string_format(oran_tree, hf_oran_timing_header,
6598
311
                                                            tvb, offset, 4, "", "Timing Header (");
6599
311
    proto_tree *timing_header_tree = proto_item_add_subtree(timingHeader, ett_oran_u_timing);
6600
6601
    /* dataDirection */
6602
311
    uint32_t direction;
6603
311
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
6604
311
    tap_info->uplink = (direction==0);
6605
    /* payloadVersion */
6606
311
    dissect_payload_version(timing_header_tree, tvb, pinfo, offset);
6607
    /* filterIndex */
6608
311
    proto_tree_add_item(timing_header_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
6609
311
    offset += 1;
6610
6611
311
    int ref_a_offset = offset;
6612
6613
    /* frameId */
6614
311
    uint32_t frameId = 0;
6615
311
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
6616
311
    tap_info->frame = frameId;
6617
311
    offset += 1;
6618
6619
    /* subframeId */
6620
311
    uint32_t subframeId = 0;
6621
311
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
6622
    /* slotId */
6623
311
    uint32_t slotId = 0;
6624
311
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
6625
311
    tap_info->slot = slotId;
6626
311
    offset++;
6627
    /* symbolId */
6628
311
    uint32_t symbolId = 0;
6629
311
    proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, &symbolId);
6630
311
    offset++;
6631
6632
311
    char id[16];
6633
311
    snprintf(id, 16, "%d-%d-%d-%d", frameId, subframeId, slotId, symbolId);
6634
311
    proto_item *pi = proto_tree_add_string(timing_header_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
6635
311
    proto_item_set_generated(pi);
6636
6637
311
    proto_item_append_text(timingHeader, "%s, frameId: %d, subframeId: %d, slotId: %d, symbolId: %d)",
6638
311
        val_to_str_const(direction, data_direction_vals, "Unknown"), frameId, subframeId, slotId, symbolId);
6639
6640
311
    unsigned sample_bit_width;
6641
311
    unsigned compression;
6642
311
    int includeUdCompHeader;
6643
6644
    /* Also look up C-PLANE state (sent in opposite direction) so may check current compression settings */
6645
311
    uint32_t cplane_key = make_flow_key(pinfo, eAxC, ORAN_C_PLANE, true);
6646
311
    flow_state_t* cplane_state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, cplane_key);
6647
311
    uint32_t cplane_samedir_key = make_flow_key(pinfo, eAxC, ORAN_C_PLANE, false);
6648
311
    flow_state_t* cplane_samedir_state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, cplane_samedir_key);
6649
6650
6651
311
    if (!PINFO_FD_VISITED(pinfo)) {
6652
        /* Create conversation if doesn't exist yet */
6653
300
        if (!state)  {
6654
            /* Allocate new state */
6655
80
            state = wmem_new0(wmem_file_scope(), flow_state_t);
6656
80
            state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
6657
80
            wmem_tree_insert32(flow_states_table, key, state);
6658
80
        }
6659
6660
        /* Check sequence analysis status (but not if later part of radio layer fragmentation) */
6661
300
        if (state->last_frame_seen[direction] && (subSeqId==0) && (seqId != state->next_expected_sequence_number[direction])) {
6662
            /* Store this result */
6663
199
            flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
6664
199
            result->unexpected_seq_number = true;
6665
199
            result->expected_sequence_number = state->next_expected_sequence_number[direction];
6666
199
            result->previous_frame = state->last_frame[direction];
6667
199
            wmem_tree_insert32(flow_results_table, pinfo->num, result);
6668
199
        }
6669
        /* Update sequence analysis state */
6670
300
        state->last_frame[direction] = pinfo->num;
6671
300
        state->last_frame_seen[direction] = true;
6672
300
        state->next_expected_sequence_number[direction] = (seqId+1) % 256;
6673
300
    }
6674
6675
    /* Show any issues associated with this frame number */
6676
311
    flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
6677
311
    if (result) {
6678
204
        if (result->unexpected_seq_number) {
6679
204
            expert_add_info_format(pinfo, seqIdItem,
6680
204
                                   (direction == DIR_UPLINK) ?
6681
45
                                        &ei_oran_uplane_unexpected_sequence_number_ul :
6682
204
                                        &ei_oran_uplane_unexpected_sequence_number_dl,
6683
204
                                   "Sequence number %u expected, but got %u",
6684
204
                                   result->expected_sequence_number, seqId);
6685
204
            tap_info->missing_sns = (256 + seqId - result->expected_sequence_number) % 256;
6686
            /* TODO: could add previous/next frame (in seqId tree?) ? */
6687
204
        }
6688
204
    }
6689
6690
    /* Checking UL timing within current slot.  Disabled if limit set to 0. */
6691
    /* N.B., timing is relative to first seen frame,
6692
       not some notion of the beginning of the slot from sync, offset by some timing.. */
6693
311
    if (direction == DIR_UPLINK && us_allowed_for_ul_in_symbol > 0) {
6694
0
        uint32_t timing_key = get_timing_key(frameId, subframeId, slotId, symbolId);
6695
0
        if (!PINFO_FD_VISITED(pinfo)) {
6696
            /* Set state on first pass */
6697
0
            ul_timing_for_slot* timing = (ul_timing_for_slot*)wmem_tree_lookup32(ul_symbol_timing, timing_key);
6698
0
            if (!timing) {
6699
                /* Allocate new state */
6700
0
                timing = wmem_new0(wmem_file_scope(), ul_timing_for_slot);
6701
0
                timing->first_frame = pinfo->num;
6702
0
                timing->first_frame_time = pinfo->abs_ts;
6703
0
                timing->frames_seen_in_symbol = 1;
6704
0
                timing->last_frame_in_symbol = pinfo->num;
6705
0
                wmem_tree_insert32(ul_symbol_timing, timing_key, timing);
6706
0
            }
6707
0
            else {
6708
                /* Update existing state */
6709
0
                timing->frames_seen_in_symbol++;
6710
0
                timing->last_frame_in_symbol = pinfo->num;
6711
0
            }
6712
0
        }
6713
0
        else {
6714
            /* Subsequent passes - look up result */
6715
0
            ul_timing_for_slot* timing = (ul_timing_for_slot*)wmem_tree_lookup32(ul_symbol_timing, timing_key);
6716
0
            if (timing) {  /* Really shouldn't fail! */
6717
0
                if (timing->frames_seen_in_symbol > 1) {
6718
                    /* Work out gap between frames (in microseconds) back to frame carrying first seen symbol */
6719
0
                    int seconds_between_packets = (int)
6720
0
                          (pinfo->abs_ts.secs - timing->first_frame_time.secs);
6721
0
                    int nseconds_between_packets =
6722
0
                          pinfo->abs_ts.nsecs - timing->first_frame_time.nsecs;
6723
6724
6725
                    /* Round to nearest microsecond. */
6726
0
                    uint32_t total_gap = (seconds_between_packets*1000000) +
6727
0
                                         ((nseconds_between_packets+500) / 1000);
6728
6729
                    /* Show how long it has been */
6730
0
                    proto_item *ti = NULL;
6731
0
                    if (pinfo->num != timing->first_frame) {
6732
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_time, tvb, 0, 0, total_gap);
6733
0
                        proto_item_set_generated(ti);
6734
0
                    }
6735
6736
0
                    if (total_gap > us_allowed_for_ul_in_symbol) {
6737
0
                        expert_add_info_format(pinfo, ti, &ei_oran_ul_uplane_symbol_too_long,
6738
0
                                               "UL U-Plane Tx took longer (%u us) than limit set in preferences (%u us)",
6739
0
                                               total_gap, us_allowed_for_ul_in_symbol);
6740
0
                    }
6741
6742
                    /* Show how many frames were received */
6743
0
                    ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_frames, tvb, 0, 0, timing->frames_seen_in_symbol);
6744
0
                    proto_item_set_generated(ti);
6745
6746
                    /* Link to first frame for this symbol */
6747
0
                    if (pinfo->num != timing->first_frame) {
6748
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_first_frame, tvb, 0, 0, timing->first_frame);
6749
0
                        proto_item_set_generated(ti);
6750
0
                    }
6751
6752
                    /* And also last frame */
6753
0
                    if (pinfo->num != timing->last_frame_in_symbol) {
6754
0
                        ti = proto_tree_add_uint(timingHeader, hf_oran_u_section_ul_symbol_last_frame, tvb, 0, 0, timing->last_frame_in_symbol);
6755
0
                        proto_item_set_generated(ti);
6756
0
                    }
6757
6758
0
                    tap_info->ul_delay_in_us = total_gap;
6759
0
                    tap_info->ul_delay_configured_max = us_allowed_for_ul_in_symbol;
6760
0
                }
6761
0
            }
6762
0
        }
6763
0
    }
6764
6765
6766
    /* Look up preferences for samples */
6767
311
    if (direction == DIR_UPLINK) {
6768
96
        sample_bit_width = pref_sample_bit_width_uplink;
6769
96
        compression = pref_iqCompressionUplink;
6770
96
        includeUdCompHeader = pref_includeUdCompHeaderUplink;
6771
215
    } else {
6772
215
        sample_bit_width = pref_sample_bit_width_downlink;
6773
215
        compression = pref_iqCompressionDownlink;
6774
215
        includeUdCompHeader = pref_includeUdCompHeaderDownlink;
6775
215
    }
6776
6777
    /* If uplink, load any udCompHdr settings written by C-Plane */
6778
311
    bool ud_cmp_hdr_cplane = false;
6779
311
    if (cplane_state && direction == 0) {
6780
        /* Initialise settings from udpCompHdr from C-Plane */
6781
11
        if (cplane_state->ul_ud_comp_hdr_set && !pref_override_ul_compression) {
6782
10
            sample_bit_width = cplane_state->ul_ud_comp_hdr_bit_width;
6783
10
            compression =      cplane_state->ul_ud_comp_hdr_compression;
6784
10
            ud_cmp_hdr_cplane = true;
6785
10
        }
6786
11
    }
6787
6788
    /* Need a valid value (e.g. 9, 14).  0 definitely won't work, as won't progress around loop! */
6789
    /* N.B. may yet be overwritten by udCompHdr settings in sections below! */
6790
311
    if (sample_bit_width == 0) {
6791
0
        expert_add_info_format(pinfo, protocol_item, &ei_oran_invalid_sample_bit_width,
6792
0
                               "%cL Sample bit width from %s (%u) not valid, so can't decode sections",
6793
0
                               (direction == DIR_UPLINK) ? 'U' : 'D',
6794
0
                               !ud_cmp_hdr_cplane ? "preference" : "C-Plane",
6795
0
                               sample_bit_width);
6796
0
        return offset;
6797
0
    }
6798
6799
311
    unsigned bytesLeft;
6800
311
    unsigned number_of_sections = 0;
6801
311
    unsigned nBytesPerPrb =0;
6802
6803
    /* Add each section (not from count, just keep parsing until payload used) */
6804
959
    do {
6805
        /* Section subtree */
6806
959
        unsigned section_start_offset = offset;
6807
959
        proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_u_section,
6808
959
                                                                  tvb, offset, 0, "", "Section");
6809
959
        proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_u_section);
6810
6811
        /* Section Header fields (darker green part) */
6812
6813
        /* sectionId */
6814
959
        uint32_t sectionId = 0;
6815
959
        proto_item *ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
6816
959
        if (sectionId == 4095) {
6817
164
            proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
6818
164
        }
6819
959
        offset++;
6820
6821
959
        if (tap_info->num_section_ids < MAX_SECTION_IDs) {
6822
895
            tap_info->section_ids[tap_info->num_section_ids++] = sectionId;
6823
895
        }
6824
6825
        /* rb */
6826
959
        uint32_t rb;
6827
959
        proto_tree_add_item_ret_uint(section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
6828
        /* symInc */
6829
959
        proto_tree_add_item(section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
6830
        /* startPrbu */
6831
959
        uint32_t startPrbu = 0;
6832
959
        proto_tree_add_item_ret_uint(section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
6833
959
        offset += 2;
6834
6835
        /* numPrbu */
6836
959
        uint32_t numPrbu = 0;
6837
959
        proto_tree_add_item_ret_uint(section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
6838
959
        offset += 1;
6839
6840
959
        proto_item *ud_comp_meth_item, *ud_comp_len_ti=NULL;
6841
959
        uint32_t ud_comp_len;
6842
6843
        /* udCompHdr (if preferences indicate will be present) */
6844
959
        bool included = (includeUdCompHeader==1) ||   /* 1 means present.. */
6845
942
                        (includeUdCompHeader==2 && udcomphdr_appears_present(state, direction, tvb, offset));
6846
959
        if (included) {
6847
            /* 7.5.2.10 */
6848
            /* Extract these values to inform how wide IQ samples in each PRB will be. */
6849
794
            offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset, false, &sample_bit_width,
6850
794
                                       &compression, &ud_comp_meth_item);
6851
6852
            /* Not part of udCompHdr */
6853
794
            uint32_t reserved;
6854
794
            proto_item *res_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA, &reserved);
6855
794
            offset += 1;
6856
794
            if (reserved != 0) {
6857
586
                expert_add_info_format(pinfo, res_ti, &ei_oran_reserved_not_zero,
6858
586
                                       "reserved field (0x%x) not zero - perhaps udCompHdr is not really present?",
6859
586
                                       reserved);
6860
586
            }
6861
794
        }
6862
165
        else {
6863
            /* No fields to dissect - just showing comp values from prefs */
6864
            /* iqWidth */
6865
165
            proto_item *iq_width_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrIqWidth_pref, tvb, 0, 0, sample_bit_width);
6866
165
            proto_item_append_text(iq_width_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
6867
165
            proto_item_set_generated(iq_width_item);
6868
6869
            /* udCompMethod */
6870
165
            ud_comp_meth_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, compression);
6871
165
            proto_item_append_text(ud_comp_meth_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
6872
165
            proto_item_set_generated(ud_comp_meth_item);
6873
6874
            /* Point back to C-Plane, if used */
6875
            /* TODO: doesn't work with multiple port mappings using SE10.. */
6876
165
            if (ud_cmp_hdr_cplane) {
6877
1
                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);
6878
1
                proto_item_set_generated(cplane_ti);
6879
1
            }
6880
165
        }
6881
6882
        /* Consider fragmentation after first section header */
6883
959
        if (do_radio_transport_layer_reassembly && (number_of_sections == 0) && (e !=1 || subSeqId!= 0)) {
6884
6885
            /* Set fragmented flag. */
6886
66
            bool save_fragmented = pinfo->fragmented;
6887
66
            pinfo->fragmented = true;
6888
66
            fragment_head *fh;
6889
66
            unsigned frag_data_len = tvb_reported_length_remaining(tvb, offset);
6890
6891
            /* Add this fragment into reassembly table */
6892
66
            uint32_t reassembly_id = make_reassembly_id(seqId, direction, eAxC,
6893
66
                                                        frameId, subframeId, slotId, symbolId);
6894
66
            fh = fragment_add_seq(&oran_reassembly_table, tvb, offset, pinfo,
6895
66
                                        reassembly_id,                                 /* id */
6896
66
                                        GUINT_TO_POINTER(reassembly_id),               /* data */
6897
66
                                        subSeqId,                                      /* frag_number */
6898
66
                                        frag_data_len,                                 /* frag_data_len */
6899
66
                                        !e,                                             /* more_frags */
6900
66
                                        0);
6901
6902
66
            bool update_col_info = true;
6903
6904
            /* See if this completes an SDU */
6905
66
            tvbuff_t *original_tvb = tvb;
6906
66
            tvbuff_t *next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled O-RAN FH CUS Payload",
6907
66
                                                          fh, &oran_frag_items,
6908
66
                                                          &update_col_info, oran_tree);
6909
66
            if (next_tvb) {
6910
                /* Have reassembled data */
6911
0
                proto_tree_add_item(oran_tree, hf_oran_payload, next_tvb, 0, -1, ENC_NA);
6912
0
                col_append_fstr(pinfo->cinfo, COL_INFO, "  Reassembled Data (%u bytes)", tvb_reported_length(next_tvb));
6913
                /* Dissection should resume at start of reassembled tvb */
6914
0
                offset = 0;
6915
0
            }
6916
            /* Will continue with either reassembled tvb or NULL */
6917
66
            tvb = next_tvb;
6918
6919
            /* Restore fragmented flag */
6920
66
            pinfo->fragmented = save_fragmented;
6921
6922
            /* Don't dissect any more if not complete yet.. */
6923
66
            if (tvb == NULL) {
6924
66
                return tvb_captured_length(original_tvb);
6925
66
            }
6926
66
        }
6927
6928
6929
        /* Not supported! TODO: other places where comp method is looked up (e.g., bfw?) */
6930
893
        switch (compression) {
6931
58
            case COMP_NONE:
6932
171
            case COMP_BLOCK_FP:
6933
257
            case BFP_AND_SELECTIVE_RE:
6934
268
            case COMP_MODULATION:
6935
309
            case MOD_COMPR_AND_SELECTIVE_RE:
6936
309
                break;
6937
566
            default:
6938
566
                expert_add_info_format(pinfo, ud_comp_meth_item, &ei_oran_unsupported_compression_method,
6939
566
                                   "Compression method %u (%s) not supported by dissector",
6940
566
                                   compression,
6941
566
                                   rval_to_str_const(compression, ud_comp_header_meth, "reserved"));
6942
893
        }
6943
6944
        /* udCompLen (when supported, methods 5,6,7,8) */
6945
875
        if (compression >= BFP_AND_SELECTIVE_RE) {
6946
668
            bool supported = (pref_support_udcompLen==1) || /* supported */
6947
668
                             (pref_support_udcompLen==2 && udcomplen_appears_present(includeUdCompHeader, tvb, offset));
6948
6949
668
            if (supported) {
6950
43
                ud_comp_len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_udCompLen, tvb, offset, 2, ENC_BIG_ENDIAN, &ud_comp_len);
6951
43
                if (ud_comp_len <= 1) {
6952
3
                    proto_item_append_text(ud_comp_len_ti, " (reserved)");
6953
3
                }
6954
                /* TODO: report if less than a viable section in frame? */
6955
                /* Check that there is this much length left in the frame */
6956
43
                if ((int)ud_comp_len > tvb_reported_length_remaining(tvb, section_start_offset)) {
6957
25
                    expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
6958
25
                                           "udCompLen indicates %u bytes in section, but only %u are left in frame",
6959
25
                                           ud_comp_len, tvb_reported_length_remaining(tvb, section_start_offset));
6960
25
                }
6961
                /* Actual length of section will be checked below, at the end of the section */
6962
43
                offset += 2;
6963
43
            }
6964
668
        }
6965
6966
        /* sReSMask1 + sReSMask2 (depends upon compression method) */
6967
875
        uint64_t sresmask1=0, sresmask2=0;
6968
875
        if (compression == BFP_AND_SELECTIVE_RE_WITH_MASKS ||
6969
843
            compression == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS)
6970
45
        {
6971
45
            static int * const  sres_mask1_2_flags[] = {
6972
45
                &hf_oran_sReSMask1_2_re12,
6973
45
                &hf_oran_sReSMask1_2_re11,
6974
45
                &hf_oran_sReSMask1_2_re10,
6975
45
                &hf_oran_sReSMask1_2_re9,
6976
45
                &hf_oran_sReSMask_re8,
6977
45
                &hf_oran_sReSMask_re7,
6978
45
                &hf_oran_sReSMask_re6,
6979
45
                &hf_oran_sReSMask_re5,
6980
45
                &hf_oran_sReSMask_re4,
6981
45
                &hf_oran_sReSMask_re3,
6982
45
                &hf_oran_sReSMask_re2,
6983
45
                &hf_oran_sReSMask_re1,
6984
45
                NULL
6985
45
            };
6986
6987
            /* reserved (4 bits) */
6988
45
            add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
6989
            /* sReSMask1 (12 bits) */
6990
45
            proto_item *sresmask_ti;
6991
45
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
6992
45
                                                            hf_oran_sReSMask1,
6993
45
                                                            ett_oran_sresmask,
6994
45
                                                            sres_mask1_2_flags,
6995
45
                                                            ENC_NA,
6996
45
                                                            &sresmask1);
6997
45
            offset += 2;
6998
            /* Count REs present */
6999
45
            unsigned res = 0;
7000
585
            for (unsigned n=0; n < 12; n++) {
7001
540
                if ((sresmask1 >> n) & 0x1) {
7002
264
                    res++;
7003
264
                }
7004
540
            }
7005
45
            proto_item_append_text(sresmask_ti, "   (%u REs)", res);
7006
7007
7008
            /* reserved (4 bits) */
7009
45
            add_reserved_field(section_tree, hf_oran_reserved_4bits, tvb, offset, 1);
7010
            /* sReSMask2 (12 bits) */
7011
45
            sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
7012
45
                                                            hf_oran_sReSMask2,
7013
45
                                                            ett_oran_sresmask,
7014
45
                                                            sres_mask1_2_flags,
7015
45
                                                            ENC_NA,
7016
45
                                                            &sresmask2);
7017
45
            offset += 2;
7018
7019
45
            if (rb == 1) {
7020
9
                proto_item_append_text(sresmask_ti, " (ignored)");
7021
9
                if (sresmask2 != 0) {
7022
7
                    expert_add_info(pinfo, ud_comp_len_ti, &ei_oran_sresmask2_not_zero_with_rb);
7023
7
                }
7024
9
            }
7025
36
            else {
7026
                /* Count REs present */
7027
36
                res = 0;
7028
468
                for (unsigned n=0; n < 12; n++) {
7029
432
                    if ((sresmask2 >> n) & 0x1) {
7030
236
                        res++;
7031
236
                    }
7032
432
                }
7033
36
                proto_item_append_text(sresmask_ti, "   (%u REs)", res);
7034
36
            }
7035
45
        }
7036
7037
875
        write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
7038
7039
        /* TODO: should this use the same pref as c-plane? */
7040
875
        if (numPrbu == 0) {
7041
            /* Special case for all PRBs (NR: the total number of PRBs may be > 255) */
7042
78
            numPrbu = pref_data_plane_section_total_rbs;
7043
78
            startPrbu = 0;  /* may already be 0... */
7044
78
        }
7045
7046
875
        section_mod_compr_config_t* mod_compr_config = get_mod_compr_section_to_read(cplane_samedir_state, sectionId);
7047
7048
        /* Add each PRB */
7049
93.9k
        for (unsigned i = 0; i < numPrbu; i++) {
7050
            /* Create subtree */
7051
93.0k
            proto_item *prbHeading = proto_tree_add_string_format(section_tree, hf_oran_samples_prb,
7052
93.0k
                                                                  tvb, offset, 0,
7053
93.0k
                                                                  "", "PRB");
7054
93.0k
            proto_tree *rb_tree = proto_item_add_subtree(prbHeading, ett_oran_u_prb);
7055
93.0k
            uint32_t exponent = 0;
7056
93.0k
            uint16_t sresmask = 0;
7057
7058
            /* udCompParam (depends upon compression method) */
7059
93.0k
            int before = offset;
7060
93.0k
            offset = dissect_udcompparam(tvb, pinfo, rb_tree, offset, compression, &exponent, &sresmask, false);
7061
93.0k
            int udcompparam_len = offset-before;
7062
7063
            /* Show PRB number in root */
7064
93.0k
            proto_item_append_text(prbHeading, " %3u", startPrbu + i*(1+rb));
7065
7066
            /* Work out how many REs / PRB */
7067
93.0k
            unsigned res_per_prb = 12;
7068
93.0k
            uint16_t sresmask_to_use = 0x0fff;
7069
7070
93.0k
            if (compression >= BFP_AND_SELECTIVE_RE) {
7071
                /* Work out which mask should be used */
7072
91.8k
                if (compression==BFP_AND_SELECTIVE_RE || compression==MOD_COMPR_AND_SELECTIVE_RE) {
7073
                    /* Selective RE cases, use value from compModParam */
7074
4.08k
                    sresmask_to_use = (uint16_t)sresmask;
7075
4.08k
                }
7076
87.8k
                else {
7077
                    /* With masks (in section).  Choose between sresmask1 and sresmask2 */
7078
87.8k
                    if (rb==1 || (i%1)==0) {
7079
                        /* Even values */
7080
87.8k
                        sresmask_to_use = (uint16_t)sresmask1;
7081
87.8k
                    }
7082
0
                    else {
7083
                        /* Odd values */
7084
0
                        sresmask_to_use = (uint16_t)sresmask2;
7085
0
                    }
7086
87.8k
                }
7087
7088
                /* Count REs present using sresmask */
7089
91.8k
                res_per_prb = 0;
7090
                /* Use sresmask to pick out which REs are present */
7091
1.19M
                for (unsigned n=0; n<12; n++) {
7092
1.10M
                    if (sresmask_to_use & (1<<n)) {
7093
22.1k
                        res_per_prb++;
7094
22.1k
                    }
7095
1.10M
                }
7096
91.8k
            }
7097
7098
            /* N.B. bytes for samples need to be padded out to next byte
7099
               (certainly where there aren't 12 REs in PRB..) */
7100
93.0k
            unsigned nBytesForSamples = (sample_bit_width * res_per_prb * 2 + 7) / 8;
7101
93.0k
            nBytesPerPrb = nBytesForSamples + udcompparam_len;
7102
7103
93.0k
            proto_tree_add_item(rb_tree, hf_oran_iq_user_data, tvb, offset, nBytesForSamples, ENC_NA);
7104
7105
93.0k
            tap_info->non_zero_re_in_current_prb = false;
7106
7107
            /* Optionally trying to show I/Q RE values */
7108
93.0k
            if (pref_showIQSampleValues) {
7109
                /* Individual values */
7110
92.8k
                unsigned samples_offset = offset*8;
7111
92.8k
                unsigned samples = 0;
7112
7113
92.8k
                if (compression >= BFP_AND_SELECTIVE_RE) {
7114
                    /* Use sresmask to pick out which REs are present */
7115
1.19M
                    for (unsigned n=1; n<=12; n++) {
7116
1.10M
                        if (sresmask_to_use & (1<<(n-1))) {
7117
21.6k
                            samples_offset = dissect_oran_u_re(tvb, rb_tree,
7118
21.6k
                                                               n, samples_offset, tap_info, sample_bit_width, compression, exponent, mod_compr_config, n);
7119
21.6k
                            samples++;
7120
21.6k
                        }
7121
1.10M
                    }
7122
91.8k
                }
7123
1.01k
                else {
7124
                    /* All 12 REs are present */
7125
13.1k
                    for (unsigned n=1; n<=12; n++) {
7126
12.1k
                        samples_offset = dissect_oran_u_re(tvb, rb_tree,
7127
12.1k
                                                           n, samples_offset, tap_info, sample_bit_width, compression, exponent, mod_compr_config, n);
7128
12.1k
                        samples++;
7129
12.1k
                    }
7130
1.01k
                }
7131
92.8k
                proto_item_append_text(prbHeading, " (%u REs)", samples);
7132
7133
                /* Was this PRB all zeros? */
7134
92.8k
                if (!tap_info->non_zero_re_in_current_prb) {
7135
88.1k
                    tap_info->num_prbs_zero++;
7136
                    /* Add a filter to make zero-valued PRBs more findable */
7137
88.1k
                    proto_tree_add_item(rb_tree, hf_oran_zero_prb, tvb,
7138
88.1k
                                                            samples_offset/8, nBytesForSamples, ENC_NA);
7139
88.1k
                    proto_item_append_text(prbHeading, " (all zeros)");
7140
88.1k
                }
7141
92.8k
            }
7142
7143
93.0k
            tap_info->num_prbs++;
7144
7145
7146
            /* Advance past samples */
7147
93.0k
            offset += nBytesForSamples;
7148
7149
            /* Set end of prb subtree */
7150
93.0k
            proto_item_set_end(prbHeading, tvb, offset);
7151
93.0k
        }
7152
7153
        /* Set extent of section */
7154
875
        proto_item_set_len(sectionHeading, offset-section_start_offset);
7155
875
        if (ud_comp_len_ti != NULL && ((offset-section_start_offset != ud_comp_len))) {
7156
32
            expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
7157
32
                                   "udCompLen indicates %u bytes in section, but dissected %u instead",
7158
32
                                   ud_comp_len, offset-section_start_offset);
7159
32
        }
7160
7161
875
        bytesLeft = tvb_captured_length(tvb) - offset;
7162
875
        number_of_sections++;
7163
875
    } while (bytesLeft >= (4 + nBytesPerPrb));     /* FIXME: bad heuristic */
7164
7165
    /* Show number of sections found */
7166
227
    proto_item *ti = proto_tree_add_uint(oran_tree, hf_oran_numberOfSections, tvb, 0, 0, number_of_sections);
7167
227
    proto_item_set_generated(ti);
7168
7169
    /* Expert error if we are short of tvb by > 3 bytes */
7170
227
    if (tvb_reported_length_remaining(tvb, offset) > 3) {
7171
4
        expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
7172
4
                               "%u bytes remain at end of frame - should be 0-3",
7173
4
                               tvb_reported_length_remaining(tvb, offset));
7174
4
    }
7175
7176
227
    return tvb_captured_length(tvb);
7177
311
}
7178
7179
7180
/**********************************************************************/
7181
/* Main dissection function.                                          */
7182
/* N.B. ecpri message type passed in as 'data' arg by eCPRI dissector */
7183
static int
7184
dissect_oran(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
7185
3.15k
{
7186
3.15k
    uint32_t ecpri_message_type = *(uint32_t *)data;
7187
3.15k
    int offset = 0;
7188
7189
    /* Allocate and zero tap struct */
7190
3.15k
    oran_tap_info *tap_info = wmem_new0(wmem_file_scope(), oran_tap_info);
7191
3.15k
    tap_info->pdu_size = pinfo->fd->pkt_len;
7192
7193
3.15k
    switch (ecpri_message_type) {
7194
311
        case ECPRI_MT_IQ_DATA:
7195
311
            offset = dissect_oran_u(tvb, pinfo, tree, tap_info, data);
7196
311
            break;
7197
2.37k
        case ECPRI_MT_RT_CTRL_DATA:
7198
2.37k
            offset = dissect_oran_c(tvb, pinfo, tree, tap_info, data);
7199
2.37k
            break;
7200
464
        default:
7201
            /* Not dissecting other types - assume these are handled by eCPRI dissector */
7202
464
            return 0;
7203
3.15k
    }
7204
7205
159
    tap_queue_packet(oran_tap, pinfo, tap_info);
7206
7207
159
    return offset;
7208
3.15k
}
7209
7210
static void oran_init_protocol(void)
7211
14
{
7212
14
    udcomplen_heuristic_result_set = false;
7213
14
    udcomplen_heuristic_result = false;
7214
14
}
7215
7216
7217
/* Register the protocol with Wireshark. */
7218
void
7219
proto_register_oran(void)
7220
14
{
7221
14
    static hf_register_info hf[] = {
7222
7223
       /* Section 5.1.3.2.7 */
7224
14
       { &hf_oran_du_port_id,
7225
14
         { "DU Port ID", "oran_fh_cus.du_port_id",
7226
14
           FT_UINT16, BASE_DEC,
7227
14
           NULL, 0x0,
7228
14
           "Processing unit at O-RU - width set in dissector preference", HFILL }
7229
14
       },
7230
7231
       /* Section 5.1.3.2.7 */
7232
14
       { &hf_oran_bandsector_id,
7233
14
         { "BandSector ID", "oran_fh_cus.bandsector_id",
7234
14
           FT_UINT16, BASE_DEC,
7235
14
           NULL, 0x0,
7236
14
           "Aggregated cell identified - width set in dissector preference", HFILL }
7237
14
       },
7238
7239
       /* Section 5.1.3.2.7 */
7240
14
       { &hf_oran_cc_id,
7241
14
         { "CC ID", "oran_fh_cus.cc_id",
7242
14
           FT_UINT16, BASE_DEC,
7243
14
           NULL, 0x0,
7244
14
           "Component Carrier - width set in dissector preference", HFILL }
7245
14
       },
7246
7247
        /* Section 5.1.3.2.7 */
7248
14
        { &hf_oran_ru_port_id,
7249
14
          { "RU Port ID", "oran_fh_cus.ru_port_id",
7250
14
            FT_UINT16, BASE_DEC,
7251
14
            NULL, 0x0,
7252
14
            "Logical flow - width set in dissector preference", HFILL }
7253
14
        },
7254
7255
        /* Section 5.1.3.2.8 */
7256
14
        { &hf_oran_sequence_id,
7257
14
          { "Sequence ID", "oran_fh_cus.sequence_id",
7258
14
            FT_UINT8, BASE_DEC,
7259
14
            NULL, 0x0,
7260
14
            "The Sequence ID wraps around individually per eAxC", HFILL }
7261
14
        },
7262
7263
        /* Section 5.1.3.2.8 */
7264
14
        { &hf_oran_e_bit,
7265
14
          { "E Bit", "oran_fh_cus.e_bit",
7266
14
            FT_UINT8, BASE_DEC,
7267
14
            VALS(e_bit), 0x80,
7268
14
            "Indicate the last message of a subsequence (U-Plane only)", HFILL }
7269
14
        },
7270
7271
        /* Section 5.1.3.2.8 */
7272
14
        { &hf_oran_subsequence_id,
7273
14
          { "Subsequence ID", "oran_fh_cus.subsequence_id",
7274
14
            FT_UINT8, BASE_DEC,
7275
14
            NULL, 0x7f,
7276
14
            "The subsequence ID (for eCPRI layer fragmentation)", HFILL }
7277
14
        },
7278
7279
14
        { &hf_oran_previous_frame,
7280
14
          { "Previous frame in stream", "oran_fh_cus.previous-frame",
7281
14
            FT_FRAMENUM, BASE_NONE,
7282
14
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
7283
14
            "Previous frame in sequence", HFILL }
7284
14
        },
7285
7286
        /* Section 7.5.2.1 */
7287
14
        { &hf_oran_data_direction,
7288
14
          { "Data Direction", "oran_fh_cus.data_direction",
7289
14
            FT_UINT8, BASE_DEC,
7290
14
            VALS(data_direction_vals), 0x80,
7291
14
            "gNB data direction", HFILL }
7292
14
        },
7293
7294
        /* Section 7.5.2.2 */
7295
14
        { &hf_oran_payload_version,
7296
14
          { "Payload Version", "oran_fh_cus.payloadVersion",
7297
14
            FT_UINT8, BASE_DEC,
7298
14
            NULL, 0x70,
7299
14
            "Payload protocol version the following IEs", HFILL}
7300
14
        },
7301
7302
        /* Section 7.5.2.3 */
7303
14
        { &hf_oran_filter_index,
7304
14
          { "Filter Index", "oran_fh_cus.filterIndex",
7305
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7306
14
            RVALS(filter_indices), 0x0f,
7307
14
            "used between IQ data and air interface, both in DL and UL", HFILL}
7308
14
        },
7309
7310
        /* Section 7.5.2.4 */
7311
14
        { &hf_oran_frame_id,
7312
14
          { "Frame ID", "oran_fh_cus.frameId",
7313
14
            FT_UINT8, BASE_DEC,
7314
14
            NULL, 0x0,
7315
14
            "A counter for 10 ms frames (wrapping period 2.56 seconds)", HFILL}
7316
14
        },
7317
7318
        /* Section 7.5.2.5 */
7319
14
        { &hf_oran_subframe_id,
7320
14
          { "Subframe ID", "oran_fh_cus.subframe_id",
7321
14
            FT_UINT8, BASE_DEC,
7322
14
            NULL, 0xf0,
7323
14
            "A counter for 1 ms sub-frames within 10ms frame", HFILL}
7324
14
        },
7325
7326
        /* Section 7.5.2.6 */
7327
14
        { &hf_oran_slot_id,
7328
14
          { "Slot ID", "oran_fh_cus.slotId",
7329
14
            FT_UINT16, BASE_DEC,
7330
14
            NULL, 0x0fc0,
7331
14
            "Slot number within a 1ms sub-frame", HFILL}
7332
14
        },
7333
7334
        /* Generated for convenience */
7335
14
        { &hf_oran_slot_within_frame,
7336
14
          { "Slot within frame", "oran_fh_cus.slot-within-frame",
7337
14
            FT_UINT16, BASE_DEC,
7338
14
            NULL, 0x0,
7339
14
            "Slot within frame, to match DCT logs", HFILL}
7340
14
        },
7341
7342
        /* Section 7.5.2.7 */
7343
14
        { &hf_oran_start_symbol_id,
7344
14
          { "Start Symbol ID", "oran_fh_cus.startSymbolId",
7345
14
            FT_UINT8, BASE_DEC,
7346
14
            NULL, 0x3f,
7347
14
            "The first symbol number within slot affected", HFILL}
7348
14
        },
7349
7350
        /* Section 7.5.2.8 */
7351
14
        { &hf_oran_numberOfSections,
7352
14
          { "Number of Sections", "oran_fh_cus.numberOfSections",
7353
14
            FT_UINT8, BASE_DEC,
7354
14
            NULL, 0x0,
7355
14
            "The number of section IDs included in this message", HFILL}
7356
14
        },
7357
7358
        /* Section 7.5.2.9 */
7359
14
        { &hf_oran_sectionType,
7360
14
          { "Section Type", "oran_fh_cus.sectionType",
7361
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7362
14
            RVALS(section_types), 0x0,
7363
14
            "Determines the characteristics of U-plane data", HFILL}
7364
14
        },
7365
7366
        /* Section 7.5.2.10 */
7367
14
        { &hf_oran_udCompHdr,
7368
14
          { "udCompHdr", "oran_fh_cus.udCompHdr",
7369
14
            FT_STRING, BASE_NONE,
7370
14
            NULL, 0x0,
7371
14
            NULL, HFILL}
7372
14
        },
7373
7374
        /* Section 7.5.2.11 */
7375
14
        { &hf_oran_numberOfUEs,
7376
14
          { "Number Of UEs", "oran_fh_cus.numberOfUEs",
7377
14
            FT_UINT8, BASE_DEC,
7378
14
            NULL, 0x0,
7379
14
            "Indicates number of UEs for which channel info is provided", HFILL}
7380
14
        },
7381
7382
        /* Section 7.5.2.12 */
7383
14
        { &hf_oran_timeOffset,
7384
14
          { "Time Offset", "oran_fh_cus.timeOffset",
7385
14
            FT_UINT16, BASE_DEC,
7386
14
            NULL, 0x0,
7387
14
            "from start of the slot to start of CP in samples", HFILL}
7388
14
        },
7389
7390
        /* Section 7.5.2.13 */
7391
14
        { &hf_oran_frameStructure_fft,
7392
14
          { "FFT Size", "oran_fh_cus.frameStructure.fft",
7393
14
            FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
7394
14
            RVALS(frame_structure_fft), 0xf0,
7395
14
            "The FFT/iFFT size being used for all IQ data processing related to this message", HFILL }
7396
14
        },
7397
7398
        /* Section 7.5.2.13 */
7399
14
        { &hf_oran_frameStructure_subcarrier_spacing,
7400
14
          { "Subcarrier Spacing", "oran_fh_cus.frameStructure.spacing",
7401
14
            FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
7402
14
            RVALS(subcarrier_spacings), 0x0f,
7403
14
            "The sub carrier spacing as well as the number of slots per 1ms sub-frame",
7404
14
            HFILL }
7405
14
        },
7406
7407
        /* Section 7.5.2.14 */
7408
14
        { &hf_oran_cpLength,
7409
14
          { "cpLength", "oran_fh_cus.cpLength",
7410
14
            FT_UINT16, BASE_DEC,
7411
14
            NULL, 0x0,
7412
14
            "cyclic prefix length", HFILL}
7413
14
        },
7414
7415
14
        { &hf_oran_timing_header,
7416
14
          { "Timing Header", "oran_fh_cus.timingHeader",
7417
14
            FT_STRING, BASE_NONE,
7418
14
            NULL, 0x0,
7419
14
            NULL, HFILL}
7420
14
        },
7421
7422
        /* Section 7.5.3.1 */
7423
14
        { &hf_oran_section_id,
7424
14
          { "sectionId", "oran_fh_cus.sectionId",
7425
14
            FT_UINT16, BASE_DEC,
7426
14
            NULL, 0xfff0,
7427
14
            "section identifier of data", HFILL}
7428
14
        },
7429
7430
        /* Section 7.5.3.2 */
7431
14
        { &hf_oran_rb,
7432
14
          { "rb", "oran_fh_cus.rb",
7433
14
            FT_UINT8, BASE_DEC,
7434
14
            VALS(rb_vals), 0x08,
7435
14
            "resource block indicator", HFILL}
7436
14
        },
7437
7438
        /* Section 7.5.5.3 */
7439
14
        { &hf_oran_symInc,
7440
14
          { "symInc", "oran_fh_cus.symInc",
7441
14
            FT_UINT8, BASE_DEC,
7442
14
            VALS(sym_inc_vals), 0x04,
7443
14
            "Symbol Number Increment Command", HFILL}
7444
14
        },
7445
7446
        /* Section 7.5.3.4 */
7447
14
        { &hf_oran_startPrbc,
7448
14
          { "startPrbc", "oran_fh_cus.startPrbc",
7449
14
            FT_UINT16, BASE_DEC,
7450
14
            NULL, 0x03ff,
7451
14
            "Starting PRB of Control Plane Section", HFILL}
7452
14
        },
7453
7454
        /* Section 7.5.3.5 */
7455
14
        { &hf_oran_reMask_re1,
7456
14
          { "RE 1", "oran_fh_cus.reMask-RE1",
7457
14
            FT_BOOLEAN, 16,
7458
14
            TFS(&tfs_applicable_not_applicable), 0x8000,
7459
14
            NULL, HFILL}
7460
14
        },
7461
14
        { &hf_oran_reMask_re2,
7462
14
          { "RE 2", "oran_fh_cus.reMask-RE2",
7463
14
            FT_BOOLEAN, 16,
7464
14
            TFS(&tfs_applicable_not_applicable), 0x4000,
7465
14
            NULL, HFILL}
7466
14
        },
7467
14
        { &hf_oran_reMask_re3,
7468
14
          { "RE 3", "oran_fh_cus.reMask-RE3",
7469
14
            FT_BOOLEAN, 16,
7470
14
            TFS(&tfs_applicable_not_applicable), 0x2000,
7471
14
            NULL, HFILL}
7472
14
        },
7473
14
        { &hf_oran_reMask_re4,
7474
14
          { "RE 4", "oran_fh_cus.reMask-RE4",
7475
14
            FT_BOOLEAN, 16,
7476
14
            TFS(&tfs_applicable_not_applicable), 0x1000,
7477
14
            NULL, HFILL}
7478
14
        },
7479
14
        { &hf_oran_reMask_re5,
7480
14
          { "RE 5", "oran_fh_cus.reMask-RE5",
7481
14
            FT_BOOLEAN, 16,
7482
14
            TFS(&tfs_applicable_not_applicable), 0x0800,
7483
14
            NULL, HFILL}
7484
14
        },
7485
14
        { &hf_oran_reMask_re6,
7486
14
          { "RE 6", "oran_fh_cus.reMask-RE6",
7487
14
            FT_BOOLEAN, 16,
7488
14
            TFS(&tfs_applicable_not_applicable), 0x0400,
7489
14
            NULL, HFILL}
7490
14
        },
7491
14
        { &hf_oran_reMask_re7,
7492
14
          { "RE 7", "oran_fh_cus.reMask-RE7",
7493
14
            FT_BOOLEAN, 16,
7494
14
            TFS(&tfs_applicable_not_applicable), 0x0200,
7495
14
            NULL, HFILL}
7496
14
        },
7497
14
        { &hf_oran_reMask_re8,
7498
14
          { "RE 8", "oran_fh_cus.reMask-RE8",
7499
14
            FT_BOOLEAN, 16,
7500
14
            TFS(&tfs_applicable_not_applicable), 0x0100,
7501
14
            NULL, HFILL}
7502
14
        },
7503
14
        { &hf_oran_reMask_re9,
7504
14
          { "RE 9", "oran_fh_cus.reMask-RE9",
7505
14
            FT_BOOLEAN, 16,
7506
14
            TFS(&tfs_applicable_not_applicable), 0x0080,
7507
14
            NULL, HFILL}
7508
14
        },
7509
14
        { &hf_oran_reMask_re10,
7510
14
          { "RE 10", "oran_fh_cus.reMask-RE10",
7511
14
            FT_BOOLEAN, 16,
7512
14
            TFS(&tfs_applicable_not_applicable), 0x0040,
7513
14
            NULL, HFILL}
7514
14
        },
7515
14
        { &hf_oran_reMask_re11,
7516
14
          { "RE 11", "oran_fh_cus.reMask-RE11",
7517
14
            FT_BOOLEAN, 16,
7518
14
            TFS(&tfs_applicable_not_applicable), 0x0020,
7519
14
            NULL, HFILL}
7520
14
        },
7521
14
        { &hf_oran_reMask_re12,
7522
14
          { "RE 12", "oran_fh_cus.reMask-RE12",
7523
14
            FT_BOOLEAN, 16,
7524
14
            TFS(&tfs_applicable_not_applicable), 0x0010,
7525
14
            NULL, HFILL}
7526
14
        },
7527
14
        { &hf_oran_reMask,
7528
14
          { "RE Mask", "oran_fh_cus.reMask",
7529
14
            FT_UINT16, BASE_HEX,
7530
14
            NULL, 0xfff0,
7531
14
            "The Resource Element (RE) mask within a PRB", HFILL}
7532
14
        },
7533
7534
        /* Section 7.5.3.6 */
7535
14
        { &hf_oran_numPrbc,
7536
14
          { "numPrbc", "oran_fh_cus.numPrbc",
7537
14
            FT_UINT8, BASE_DEC,
7538
14
            NULL, 0x0,
7539
14
            "Number of contiguous PRBs per data section description", HFILL}
7540
14
        },
7541
        /* Section 7.5.3.7 */
7542
14
        { &hf_oran_numSymbol,
7543
14
          { "Number of Symbols", "oran_fh_cus.numSymbol",
7544
14
            FT_UINT8, BASE_DEC,
7545
14
            NULL, 0x0f,
7546
14
            "Defines number of symbols to which the section control is applicable", HFILL}
7547
14
        },
7548
        /* Section 7.5.3.8 */
7549
14
        { &hf_oran_ef,
7550
14
          { "Extension Flag", "oran_fh_cus.ef",
7551
14
            FT_BOOLEAN, 8,
7552
14
            NULL, 0x80,
7553
14
            "Indicates if more section extensions follow", HFILL}
7554
14
        },
7555
        /* Section 7.5.3.9 */
7556
14
        { &hf_oran_beamId,
7557
14
          { "Beam ID", "oran_fh_cus.beamId",
7558
14
             FT_UINT16, BASE_DEC,
7559
14
             NULL, 0x7fff,
7560
14
             "Defines the beam pattern to be applied to the U-Plane data", HFILL}
7561
14
        },
7562
7563
14
        { &hf_oran_extension,
7564
14
          { "Extension", "oran_fh_cus.extension",
7565
14
            FT_STRING, BASE_NONE,
7566
14
            NULL, 0x0,
7567
14
            "Section extension", HFILL}
7568
14
        },
7569
7570
        /* Section 7.6.2.1 */
7571
14
        { &hf_oran_exttype,
7572
14
          { "extType", "oran_fh_cus.extType",
7573
14
            FT_UINT8, BASE_DEC|BASE_EXT_STRING,
7574
14
            &exttype_vals_ext, 0x7f,
7575
14
            "The extension type, which provides additional parameters specific to subject data extension", HFILL}
7576
14
        },
7577
7578
        /* Section 7.6.2.3 */
7579
14
        { &hf_oran_extlen,
7580
14
          { "extLen", "oran_fh_cus.extLen",
7581
14
            FT_UINT16, BASE_DEC,
7582
14
            NULL, 0x0,
7583
14
            "Extension length in 32-bit words", HFILL}
7584
14
        },
7585
7586
        /* Section 7.7.1 */
7587
14
        { &hf_oran_bfw,
7588
14
          { "bfw", "oran_fh_cus.bfw",
7589
14
            FT_STRING, BASE_NONE,
7590
14
            NULL, 0x0,
7591
14
            "Set of weights for a particular antenna", HFILL}
7592
14
        },
7593
14
        { &hf_oran_bfw_bundle,
7594
14
          { "Bundle", "oran_fh_cus.bfw.bundle",
7595
14
            FT_STRING, BASE_NONE,
7596
14
            NULL, 0x0,
7597
14
            "Bundle of BFWs", HFILL}
7598
14
        },
7599
14
        { &hf_oran_bfw_bundle_id,
7600
14
          { "Bundle Id", "oran_fh_cus.bfw.bundleId",
7601
14
            FT_UINT32, BASE_DEC,
7602
14
            NULL, 0x0,
7603
14
            NULL, HFILL}
7604
14
        },
7605
        /* Section 7.7.1.4 */
7606
14
        { &hf_oran_bfw_i,
7607
14
          { "bfwI", "oran_fh_cus.bfwI",
7608
14
            FT_FLOAT, BASE_NONE,
7609
14
            NULL, 0x0,
7610
14
            "In-phase", HFILL}
7611
14
        },
7612
        /* Section 7.7.1.5 */
7613
14
        { &hf_oran_bfw_q,
7614
14
          { "bfwQ", "oran_fh_cus.bfwQ",
7615
14
            FT_FLOAT, BASE_NONE,
7616
14
            NULL, 0x0,
7617
14
            "Quadrature", HFILL}
7618
14
        },
7619
7620
        /* Section 7.5.3.10 */
7621
14
        { &hf_oran_ueId,
7622
14
          { "UE ID", "oran_fh_cus.ueId",
7623
14
            FT_UINT16, BASE_DEC,
7624
14
            NULL, 0x7fff,
7625
14
            "logical identifier for set of channel info", HFILL}
7626
14
        },
7627
        /* Section 7.5.3.11 */
7628
14
        { &hf_oran_freqOffset,
7629
14
          { "Frequency Offset", "oran_fh_cus.freqOffset",
7630
14
            FT_UINT24, BASE_DEC,
7631
14
            NULL, 0x0,
7632
14
            "with respect to the carrier center frequency before additional filtering", HFILL}
7633
14
        },
7634
7635
        /* Section 7.5.3.12 */
7636
14
        { &hf_oran_regularizationFactor,
7637
14
          { "Regularization Factor", "oran_fh_cus.regularizationFactor",
7638
14
            FT_INT16, BASE_DEC,
7639
14
            NULL, 0x0,
7640
14
            "Signed value to support MMSE operation within O-RU", HFILL}
7641
14
        },
7642
        /* Section 7.5.3.14 */
7643
14
        { &hf_oran_laaMsgType,
7644
14
          { "LAA Message Type", "oran_fh_cus.laaMsgType",
7645
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7646
14
            RVALS(laaMsgTypes), 0xf0,
7647
14
            NULL, HFILL}
7648
14
        },
7649
        /* Section 7.5.3.15 */
7650
14
        { &hf_oran_laaMsgLen,
7651
14
          { "LAA Message Length", "oran_fh_cus.laaMsgLen",
7652
14
            FT_UINT8, BASE_DEC,
7653
14
            NULL, 0x0f,
7654
14
            "number of 32-bit words in the LAA section", HFILL}
7655
14
        },
7656
        /* Section 7.5.3.16 */
7657
14
        { &hf_oran_lbtHandle,
7658
14
          { "LBT Handle", "oran_fh_cus.lbtHandle",
7659
14
            FT_UINT16, BASE_HEX,
7660
14
            NULL, 0x0,
7661
14
            "label to identify transaction", HFILL}
7662
14
         },
7663
        /* Section 7.5.3.17 */
7664
14
        { &hf_oran_lbtDeferFactor,
7665
14
          { "Defer Factor", "oran_fh_cus.lbtDeferFactor",
7666
14
            FT_UINT8, BASE_DEC,
7667
14
            NULL, 0x07,
7668
14
            "Defer factor in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
7669
14
        },
7670
        /* Section 7.5.3.18 */
7671
14
        { &hf_oran_lbtBackoffCounter,
7672
14
          { "Backoff Counter", "oran_fh_cus.lbtBackoffCounter",
7673
14
            FT_UINT16, BASE_DEC,
7674
14
            NULL, 0xffc0,
7675
14
            "LBT backoff counter in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
7676
14
        },
7677
        /* Section 7.5.3.19 */
7678
14
        { &hf_oran_lbtOffset,
7679
14
          { "LBT Offset", "oran_fh_cus.lbtOffset",
7680
14
            FT_UINT16, BASE_DEC,
7681
14
            NULL, 0xffc0,
7682
14
            "LBT start time in microseconds from the beginning of the subframe scheduled by this message", HFILL}
7683
14
        },
7684
        /* Section 7.5.3.20 */
7685
14
        { &hf_oran_MCOT,
7686
14
          { "Maximum Channel Occupancy Time", "oran_fh_cus.MCOT",
7687
14
            FT_UINT8, BASE_DEC,
7688
14
            NULL, 0x3c,
7689
14
            "LTE TXOP duration in subframes as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
7690
14
        },
7691
        /* Section 7.5.3.21 */
7692
14
        { &hf_oran_lbtMode,
7693
14
          { "LBT Mode", "oran_fh_cus.lbtMode",
7694
14
            FT_UINT8, BASE_DEC,
7695
14
            VALS(lbtMode_vals), 0x0,
7696
14
            NULL, HFILL}
7697
14
        },
7698
        /* Section 7.5.3.22 */
7699
14
        { &hf_oran_lbtPdschRes,
7700
14
          { "lbtPdschRes", "oran_fh_cus.lbtPdschRes",
7701
14
            FT_UINT8, BASE_DEC,
7702
14
            VALS(lbtPdschRes_vals), 0xc0,
7703
14
            "LBT result of SFN/SF", HFILL}
7704
14
        },
7705
        /* Section 7.5.3.23 */
7706
14
        { &hf_oran_sfStatus,
7707
14
          { "sfStatus", "oran_fh_cus.sfStatus",
7708
14
            FT_BOOLEAN, 8,
7709
14
            TFS(&tfs_sfStatus), 0x10,
7710
14
            "Indicates whether the subframe was dropped or transmitted", HFILL}
7711
14
        },
7712
        /* Section 7.5.3.24 */
7713
14
        { &hf_oran_lbtDrsRes,
7714
14
          { "lbtDrsRes", "oran_fh_cus.lbtDrsRes",
7715
14
            FT_BOOLEAN, 8,
7716
14
            TFS(&tfs_fail_success), 0x80,
7717
14
            "Indicates whether the subframe was dropped or transmitted", HFILL}
7718
14
        },
7719
        /* Section 7.5.3.25 */
7720
14
        { &hf_oran_initialPartialSF,
7721
14
          { "Initial partial SF", "oran_fh_cus.initialPartialSF",
7722
14
            FT_BOOLEAN, 8,
7723
14
            TFS(&tfs_partial_full_sf), 0x40,
7724
14
            "Indicates whether the initial SF in the LBT process is full or partial", HFILL}
7725
14
        },
7726
        /* Section 7.5.3.26. */
7727
14
        { &hf_oran_lbtBufErr,
7728
14
          { "lbtBufErr", "oran_fh_cus.lbtBufErr",
7729
14
            FT_BOOLEAN, 8,
7730
14
            TFS(&tfs_lbtBufErr), 0x80,
7731
14
            "LBT buffer error", HFILL}
7732
14
        },
7733
        /* Section 7.5.3.27 */
7734
14
        { &hf_oran_sfnSfEnd,
7735
14
          { "SFN/SF End", "oran_fh_cus.sfnSfEnd",
7736
14
            FT_UINT16, BASE_DEC,
7737
14
            NULL, 0x0fff,
7738
14
            "SFN/SF by which the DRS window must end", HFILL}
7739
14
        },
7740
        /* Section 7.5.3.28 */
7741
14
        { &hf_oran_lbtCWConfig_H,
7742
14
          { "lbtCWConfig_H", "oran_fh_cus.lbtCWConfig_H",
7743
14
            FT_UINT8, BASE_DEC,
7744
14
            NULL, 0x0,
7745
14
            "HARQ parameters for congestion window management", HFILL}
7746
14
        },
7747
        /* Section 7.5.3.29 */
7748
14
        { &hf_oran_lbtCWConfig_T,
7749
14
          { "lbtCWConfig_T", "oran_fh_cus.lbtCWConfig_T",
7750
14
            FT_UINT8, BASE_DEC,
7751
14
            NULL, 0x0,
7752
14
            "TB parameters for congestion window management", HFILL}
7753
14
        },
7754
        /* Section 7.5.3.30 */
7755
14
        { &hf_oran_lbtTrafficClass,
7756
14
          { "lbtTrafficClass", "oran_fh_cus.lbtTrafficClass",
7757
14
            FT_UINT8, BASE_DEC,
7758
14
            VALS(lbtTrafficClass_vals), 0x38,
7759
14
            "Traffic class priority for congestion window management", HFILL}
7760
14
        },
7761
        /* Section 7.5.3.31 */
7762
14
        { &hf_oran_lbtCWR_Rst,
7763
14
          { "lbtCWR_Rst", "oran_fh_cus.lbtCWR_Rst",
7764
14
            FT_BOOLEAN, 8,
7765
14
            TFS(&tfs_fail_success), 0x80,
7766
14
            "notification about packet reception successful or not", HFILL}
7767
14
        },
7768
7769
        /* Reserved fields */
7770
14
        { &hf_oran_reserved,
7771
14
          { "reserved", "oran_fh_cus.reserved",
7772
14
            FT_UINT64, BASE_HEX,
7773
14
            NULL, 0x0,
7774
14
            NULL, HFILL}
7775
14
        },
7776
14
        { &hf_oran_reserved_1bit,
7777
14
          { "reserved", "oran_fh_cus.reserved",
7778
14
            FT_UINT8, BASE_HEX,
7779
14
            NULL, 0x80,
7780
14
            NULL, HFILL}
7781
14
        },
7782
14
        { &hf_oran_reserved_2bits,
7783
14
          { "reserved", "oran_fh_cus.reserved",
7784
14
            FT_UINT8, BASE_HEX,
7785
14
            NULL, 0xc0,
7786
14
            NULL, HFILL}
7787
14
        },
7788
14
        { &hf_oran_reserved_3bits,
7789
14
          { "reserved", "oran_fh_cus.reserved",
7790
14
            FT_UINT8, BASE_HEX,
7791
14
            NULL, 0xe0,
7792
14
            NULL, HFILL}
7793
14
        },
7794
14
        { &hf_oran_reserved_4bits,
7795
14
          { "reserved", "oran_fh_cus.reserved",
7796
14
            FT_UINT8, BASE_HEX,
7797
14
            NULL, 0xf0,
7798
14
            NULL, HFILL}
7799
14
        },
7800
14
        { &hf_oran_reserved_last_4bits,
7801
14
          { "reserved", "oran_fh_cus.reserved",
7802
14
            FT_UINT8, BASE_HEX,
7803
14
            NULL, 0x0f,
7804
14
            NULL, HFILL}
7805
14
        },
7806
14
        { &hf_oran_reserved_last_5bits,
7807
14
          { "reserved", "oran_fh_cus.reserved",
7808
14
            FT_UINT8, BASE_HEX,
7809
14
            NULL, 0x1f,
7810
14
            NULL, HFILL}
7811
14
        },
7812
14
        { &hf_oran_reserved_6bits,
7813
14
          { "reserved", "oran_fh_cus.reserved",
7814
14
            FT_UINT8, BASE_HEX,
7815
14
            NULL, 0xfc,
7816
14
            NULL, HFILL}
7817
14
        },
7818
14
        { &hf_oran_reserved_last_6bits,
7819
14
          { "reserved", "oran_fh_cus.reserved",
7820
14
            FT_UINT8, BASE_HEX,
7821
14
            NULL, 0x3f,
7822
14
            NULL, HFILL}
7823
14
        },
7824
14
        { &hf_oran_reserved_7bits,
7825
14
          { "reserved", "oran_fh_cus.reserved",
7826
14
            FT_UINT8, BASE_HEX,
7827
14
            NULL, 0xfe,
7828
14
            NULL, HFILL}
7829
14
        },
7830
14
        { &hf_oran_reserved_last_7bits,
7831
14
          { "reserved", "oran_fh_cus.reserved",
7832
14
            FT_UINT8, BASE_HEX,
7833
14
            NULL, 0x7f,
7834
14
            NULL, HFILL}
7835
14
        },
7836
14
        { &hf_oran_reserved_8bits,
7837
14
          { "reserved", "oran_fh_cus.reserved",
7838
14
            FT_UINT8, BASE_HEX,
7839
14
            NULL, 0x0,
7840
14
            NULL, HFILL}
7841
14
        },
7842
14
        { &hf_oran_reserved_16bits,
7843
14
          { "reserved", "oran_fh_cus.reserved",
7844
14
            FT_UINT16, BASE_HEX,
7845
14
            NULL, 0x0,
7846
14
            NULL, HFILL}
7847
14
        },
7848
14
        { &hf_oran_reserved_15bits,
7849
14
          { "reserved", "oran_fh_cus.reserved",
7850
14
            FT_UINT16, BASE_HEX,
7851
14
            NULL, 0x7fff,
7852
14
            NULL, HFILL}
7853
14
        },
7854
14
        { &hf_oran_reserved_bit1,
7855
14
          { "reserved", "oran_fh_cus.reserved",
7856
14
            FT_UINT8, BASE_HEX,
7857
14
            NULL, 0x40,
7858
14
            NULL, HFILL}
7859
14
        },
7860
14
        { &hf_oran_reserved_bit2,
7861
14
          { "reserved", "oran_fh_cus.reserved",
7862
14
            FT_UINT8, BASE_HEX,
7863
14
            NULL, 0x20,
7864
14
            NULL, HFILL}
7865
14
        },
7866
14
        { &hf_oran_reserved_bit4,
7867
14
          { "reserved", "oran_fh_cus.reserved",
7868
14
            FT_UINT8, BASE_HEX,
7869
14
            NULL, 0x08,
7870
14
            NULL, HFILL}
7871
14
        },
7872
14
        { &hf_oran_reserved_bit5,
7873
14
          { "reserved", "oran_fh_cus.reserved",
7874
14
            FT_UINT8, BASE_HEX,
7875
14
            NULL, 0x04,
7876
14
            NULL, HFILL}
7877
14
        },
7878
14
        { &hf_oran_reserved_bits123,
7879
14
          { "reserved", "oran_fh_cus.reserved",
7880
14
            FT_UINT8, BASE_HEX,
7881
14
            NULL, 0x70,
7882
14
            NULL, HFILL}
7883
14
        },
7884
14
        { &hf_oran_reserved_bits456,
7885
14
          { "reserved", "oran_fh_cus.reserved",
7886
14
            FT_UINT8, BASE_HEX,
7887
14
            NULL, 0x0e,
7888
14
            NULL, HFILL}
7889
14
        },
7890
7891
        /* 7.7.11.9 */
7892
14
        { &hf_oran_cont_ind,
7893
14
          { "contInd", "oran_fh_cus.contInd",
7894
14
            FT_BOOLEAN, 8,
7895
14
            TFS(&continuity_indication_tfs), 0x80,
7896
14
            "PRB region continuity flag", HFILL}
7897
14
        },
7898
        /* 7.7.11.10 */
7899
14
        { &hf_oran_bundle_offset,
7900
14
          { "BundleOffset", "oran_fh_cus.bundleOffset",
7901
14
            FT_UINT8, BASE_DEC,
7902
14
            NULL, 0x3f,
7903
14
            "offset between start of first PRB bundle and startPrbc", HFILL}
7904
14
        },
7905
7906
        /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
7907
14
        { &hf_oran_bfwCompHdr,
7908
14
          { "bfwCompHdr", "oran_fh_cus.bfwCompHdr",
7909
14
            FT_STRING, BASE_NONE,
7910
14
            NULL, 0x0,
7911
14
            "Compression method and IQ bit width for beamforming weights", HFILL}
7912
14
        },
7913
14
        { &hf_oran_bfwCompHdr_iqWidth,
7914
14
          { "IQ Bit Width", "oran_fh_cus.bfwCompHdr_iqWidth",
7915
14
            FT_UINT8, BASE_HEX,
7916
14
            VALS(bfw_comp_headers_iq_width), 0xf0,
7917
14
            "IQ bit width for the beamforming weights", HFILL}
7918
14
        },
7919
14
        { &hf_oran_bfwCompHdr_compMeth,
7920
14
          { "Compression Method", "oran_fh_cus.bfwCompHdr_compMeth",
7921
14
            FT_UINT8, BASE_HEX,
7922
14
            VALS(bfw_comp_headers_comp_meth), 0x0f,
7923
14
            "compression method for the beamforming weights", HFILL}
7924
14
        },
7925
7926
        /* 7.5.3.32 */
7927
14
        { &hf_oran_ciCompParam,
7928
14
          { "ciCompParam", "oran_fh_cus.ciCompParam",
7929
14
            FT_STRING, BASE_NONE,
7930
14
            NULL, 0x0,
7931
14
            "channel information compression parameter", HFILL}
7932
14
        },
7933
7934
        /* Table 7.5.3.32-1 */
7935
14
        { &hf_oran_blockScaler,
7936
14
          { "blockScaler", "oran_fh_cus.blockScaler",
7937
14
            FT_UINT8, BASE_HEX,
7938
14
            NULL, 0x0,
7939
14
            "unsigned, 1 integer bit, 7 fractional bits", HFILL}
7940
14
        },
7941
14
        { &hf_oran_compBitWidth,
7942
14
          { "compBitWidth", "oran_fh_cus.compBitWidth",
7943
14
            FT_UINT8, BASE_DEC,
7944
14
            NULL, 0xf0,
7945
14
            "Length of I bits and length of Q bits after compression over entire PRB", HFILL}
7946
14
        },
7947
14
        { &hf_oran_compShift,
7948
14
          { "compShift", "oran_fh_cus.compShift",
7949
14
            FT_UINT8, BASE_DEC,
7950
14
            NULL, 0x0f,
7951
14
            "The shift applied to the entire PRB", HFILL}
7952
14
        },
7953
7954
14
        { &hf_oran_active_beamspace_coefficient_n1,
7955
14
          { "N1", "oran_fh_cus.activeBeamspace_Coefficient_n1",
7956
14
            FT_BOOLEAN, 8,
7957
14
            TFS(&tfs_present_not_present), 0x80,
7958
14
            NULL, HFILL}
7959
14
        },
7960
14
        { &hf_oran_active_beamspace_coefficient_n2,
7961
14
          { "N2", "oran_fh_cus.activeBeamspace_Coefficient_n2",
7962
14
            FT_BOOLEAN, 8,
7963
14
            TFS(&tfs_present_not_present), 0x40,
7964
14
            NULL, HFILL}
7965
14
        },
7966
14
        { &hf_oran_active_beamspace_coefficient_n3,
7967
14
          { "N3", "oran_fh_cus.activeBeamspace_Coefficient_n3",
7968
14
            FT_BOOLEAN, 8,
7969
14
            TFS(&tfs_present_not_present), 0x20,
7970
14
            NULL, HFILL}
7971
14
        },
7972
14
        { &hf_oran_active_beamspace_coefficient_n4,
7973
14
          { "N4", "oran_fh_cus.activeBeamspace_Coefficient_n4",
7974
14
            FT_BOOLEAN, 8,
7975
14
            TFS(&tfs_present_not_present), 0x10,
7976
14
            NULL, HFILL}
7977
14
        },
7978
14
        { &hf_oran_active_beamspace_coefficient_n5,
7979
14
          { "N5", "oran_fh_cus.activeBeamspace_Coefficient_n5",
7980
14
            FT_BOOLEAN, 8,
7981
14
            TFS(&tfs_present_not_present), 0x08,
7982
14
            NULL, HFILL}
7983
14
        },
7984
14
        { &hf_oran_active_beamspace_coefficient_n6,
7985
14
          { "N6", "oran_fh_cus.activeBeamspace_Coefficient_n6",
7986
14
            FT_BOOLEAN, 8,
7987
14
            TFS(&tfs_present_not_present), 0x04,
7988
14
            NULL, HFILL}
7989
14
        },
7990
14
        { &hf_oran_active_beamspace_coefficient_n7,
7991
14
          { "N7", "oran_fh_cus.activeBeamspace_Coefficient_n7",
7992
14
            FT_BOOLEAN, 8,
7993
14
            TFS(&tfs_present_not_present), 0x02,
7994
14
            NULL, HFILL}
7995
14
        },
7996
14
        { &hf_oran_active_beamspace_coefficient_n8,
7997
14
          { "N8", "oran_fh_cus.activeBeamspace_Coefficient_n8",
7998
14
            FT_BOOLEAN, 8,
7999
14
            TFS(&tfs_present_not_present), 0x01,
8000
14
            NULL, HFILL}
8001
14
        },
8002
8003
14
        { &hf_oran_activeBeamspaceCoefficientMask,
8004
14
          { "activeBeamspaceCoefficientMask", "oran_fh_cus.activeBeamspaceCoefficientMask",
8005
14
            FT_UINT8, BASE_HEX,
8006
14
            NULL, 0xff,
8007
14
            NULL, HFILL}
8008
14
        },
8009
14
        { &hf_oran_activeBeamspaceCoefficientMask_bits_set,
8010
14
          { "Array elements set", "oran_fh_cus.activeBeamspaceCoefficientMask.bits-set",
8011
14
            FT_UINT32, BASE_DEC,
8012
14
            NULL, 0x0,
8013
14
            NULL, HFILL}
8014
14
        },
8015
8016
        /* Section 7.7.6.6 */
8017
14
        { &hf_oran_se6_repetition,
8018
14
          { "repetition", "oran_fh_cus.repetition",
8019
14
            FT_BOOLEAN, BASE_NONE,
8020
14
            TFS(&repetition_se6_tfs), 0x0,
8021
14
            "Repetition of a highest priority data section for C-Plane", HFILL}
8022
14
        },
8023
        /* 7.7.20.9 */
8024
14
        { &hf_oran_rbgSize,
8025
14
          { "rbgSize", "oran_fh_cus.rbgSize",
8026
14
            FT_UINT8, BASE_HEX,
8027
14
            VALS(rbg_size_vals), 0x70,
8028
14
            "Number of PRBs of the resource block groups allocated by the bit mask", HFILL}
8029
14
        },
8030
        /* 7.7.20.10 */
8031
14
        { &hf_oran_rbgMask,
8032
14
          { "rbgMask", "oran_fh_cus.rbgMask",
8033
14
            FT_UINT32, BASE_HEX,
8034
14
            NULL, 0x0fffffff,
8035
14
            "Each bit indicates whether a corresponding resource block group is present", HFILL}
8036
14
        },
8037
        /* 7.7.6.5.  Also 7.7.12.3 and 7.7.19.5 */
8038
14
        { &hf_oran_noncontig_priority,
8039
14
          { "priority", "oran_fh_cus.priority",
8040
14
            FT_UINT8, BASE_HEX,
8041
14
            VALS(priority_vals), 0xc0,
8042
14
            NULL, HFILL}
8043
14
        },
8044
8045
        /* 7.7.6.4 */
8046
14
        { &hf_oran_symbol_mask,
8047
14
          { "symbolMask", "oran_fh_cus.symbolMask",
8048
14
            FT_UINT16, BASE_HEX,
8049
14
            NULL, 0x3fff,
8050
14
            "Each bit indicates whether the rbgMask applies to a given symbol in the slot", HFILL}
8051
14
        },
8052
14
        { &hf_oran_symbol_mask_s13,
8053
14
          { "symbol 13", "oran_fh_cus.symbolMask.symbol-13",
8054
14
            FT_BOOLEAN, 16,
8055
14
            TFS(&tfs_present_not_present), 0x2000,
8056
14
            NULL, HFILL}
8057
14
        },
8058
14
        { &hf_oran_symbol_mask_s12,
8059
14
          { "symbol 12", "oran_fh_cus.symbolMask.symbol-12",
8060
14
            FT_BOOLEAN, 16,
8061
14
            TFS(&tfs_present_not_present), 0x1000,
8062
14
            NULL, HFILL}
8063
14
        },
8064
14
        { &hf_oran_symbol_mask_s11,
8065
14
          { "symbol 11", "oran_fh_cus.symbolMask.symbol-11",
8066
14
            FT_BOOLEAN, 16,
8067
14
            TFS(&tfs_present_not_present), 0x0800,
8068
14
            NULL, HFILL}
8069
14
        },
8070
14
        { &hf_oran_symbol_mask_s10,
8071
14
          { "symbol 10", "oran_fh_cus.symbolMask.symbol-10",
8072
14
            FT_BOOLEAN, 16,
8073
14
            TFS(&tfs_present_not_present), 0x0400,
8074
14
            NULL, HFILL}
8075
14
        },
8076
14
        { &hf_oran_symbol_mask_s9,
8077
14
          { "symbol  9", "oran_fh_cus.symbolMask.symbol-9",
8078
14
            FT_BOOLEAN, 16,
8079
14
            TFS(&tfs_present_not_present), 0x0200,
8080
14
            NULL, HFILL}
8081
14
        },
8082
14
        { &hf_oran_symbol_mask_s8,
8083
14
          { "symbol  8", "oran_fh_cus.symbolMask.symbol-8",
8084
14
            FT_BOOLEAN, 16,
8085
14
            TFS(&tfs_present_not_present), 0x0100,
8086
14
            NULL, HFILL}
8087
14
        },
8088
14
        { &hf_oran_symbol_mask_s7,
8089
14
          { "symbol  7", "oran_fh_cus.symbolMask.symbol-7",
8090
14
            FT_BOOLEAN, 16,
8091
14
            TFS(&tfs_present_not_present), 0x0080,
8092
14
            NULL, HFILL}
8093
14
        },
8094
14
        { &hf_oran_symbol_mask_s6,
8095
14
          { "symbol  6", "oran_fh_cus.symbolMask.symbol-6",
8096
14
            FT_BOOLEAN, 16,
8097
14
            TFS(&tfs_present_not_present), 0x0040,
8098
14
            NULL, HFILL}
8099
14
        },
8100
14
        { &hf_oran_symbol_mask_s5,
8101
14
          { "symbol  5", "oran_fh_cus.symbolMask.symbol-5",
8102
14
            FT_BOOLEAN, 16,
8103
14
            TFS(&tfs_present_not_present), 0x0020,
8104
14
            NULL, HFILL}
8105
14
        },
8106
14
        { &hf_oran_symbol_mask_s4,
8107
14
          { "symbol  4", "oran_fh_cus.symbolMask.symbol-4",
8108
14
            FT_BOOLEAN, 16,
8109
14
            TFS(&tfs_present_not_present), 0x0010,
8110
14
            NULL, HFILL}
8111
14
        },
8112
14
        { &hf_oran_symbol_mask_s3,
8113
14
          { "symbol  3", "oran_fh_cus.symbolMask.symbol-3",
8114
14
            FT_BOOLEAN, 16,
8115
14
            TFS(&tfs_present_not_present), 0x0008,
8116
14
            NULL, HFILL}
8117
14
        },
8118
14
        { &hf_oran_symbol_mask_s2,
8119
14
          { "symbol  2", "oran_fh_cus.symbolMask.symbol-2",
8120
14
            FT_BOOLEAN, 16,
8121
14
            TFS(&tfs_present_not_present), 0x0004,
8122
14
            NULL, HFILL}
8123
14
        },
8124
14
        { &hf_oran_symbol_mask_s1,
8125
14
          { "symbol  1", "oran_fh_cus.symbolMask.symbol-1",
8126
14
            FT_BOOLEAN, 16,
8127
14
            TFS(&tfs_present_not_present), 0x0002,
8128
14
            NULL, HFILL}
8129
14
        },
8130
14
        { &hf_oran_symbol_mask_s0,
8131
14
          { "symbol  0", "oran_fh_cus.symbolMask.symbol-0",
8132
14
            FT_BOOLEAN, 16,
8133
14
            TFS(&tfs_present_not_present), 0x0001,
8134
14
            NULL, HFILL}
8135
14
        },
8136
8137
8138
        /* 7.7.22.2 */
8139
14
        { &hf_oran_ack_nack_req_id,
8140
14
          { "ackNackReqId", "oran_fh_cus.ackNackReqId",
8141
14
            FT_UINT16, BASE_HEX,
8142
14
            NULL, 0x0,
8143
14
            "Indicates the ACK/NACK request ID of a section description", HFILL}
8144
14
        },
8145
8146
        /* Subtree for next 2 items */
8147
14
        { &hf_oran_frequency_range,
8148
14
          { "Frequency Range", "oran_fh_cus.frequencyRange",
8149
14
            FT_STRING, BASE_NONE,
8150
14
            NULL, 0x0,
8151
14
            NULL, HFILL}
8152
14
        },
8153
8154
        /* 7.7.12.4 */
8155
14
        { &hf_oran_off_start_prb,
8156
14
          { "offStartPrb", "oran_fh_cus.offStartPrb",
8157
14
            FT_UINT8, BASE_DEC,
8158
14
            NULL, 0x0,
8159
14
            "Offset of PRB range start", HFILL}
8160
14
        },
8161
        /* 7.7.12.5 */
8162
14
        { &hf_oran_num_prb,
8163
14
          { "numPrb", "oran_fh_cus.numPrb",
8164
14
            FT_UINT8, BASE_DEC,
8165
14
            NULL, 0x0,
8166
14
            "Number of PRBs in PRB range", HFILL}
8167
14
        },
8168
8169
        /* symbolId 8.3.3.7 */
8170
14
        { &hf_oran_symbolId,
8171
14
          { "Symbol Identifier", "oran_fh_cus.symbolId",
8172
14
            FT_UINT8, BASE_DEC,
8173
14
            NULL, 0x3f,
8174
14
            "Identifies a symbol number within a slot", HFILL}
8175
14
        },
8176
8177
        /* startPrbu 8.3.3.11 */
8178
14
        { &hf_oran_startPrbu,
8179
14
          { "startPrbu", "oran_fh_cus.startPrbu",
8180
14
            FT_UINT16, BASE_DEC,
8181
14
            NULL, 0x03ff,
8182
14
            "starting PRB of user plane section", HFILL}
8183
14
        },
8184
8185
        /* numPrbu 8.3.3.12 */
8186
14
        { &hf_oran_numPrbu,
8187
14
          { "numPrbu", "oran_fh_cus.numPrbu",
8188
14
            FT_UINT8, BASE_DEC,
8189
14
            NULL, 0x0,
8190
14
            "number of PRBs per user plane section", HFILL}
8191
14
        },
8192
8193
        /* 7.7.1.3 */
8194
14
        { &hf_oran_bfwCompParam,
8195
14
          { "bfwCompParam", "oran_fh_cus.bfwCompParam",
8196
14
            FT_STRING, BASE_NONE,
8197
14
            NULL, 0x0,
8198
14
            "Beamforming weight compression parameter", HFILL}
8199
14
        },
8200
8201
        /* 6.3.3.13 */
8202
14
        { &hf_oran_udCompHdrMeth,
8203
14
          { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
8204
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8205
14
            RVALS(ud_comp_header_meth), 0x0f,
8206
14
            "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
8207
14
        },
8208
14
        { &hf_oran_udCompHdrMeth_pref,
8209
14
          { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
8210
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8211
14
            RVALS(ud_comp_header_meth), 0x0,
8212
14
            "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
8213
14
        },
8214
        /* 8.3.3.18 */
8215
14
        { &hf_oran_udCompLen,
8216
14
          { "udCompLen", "oran_fh_cus.udCompLen",
8217
14
            FT_UINT16, BASE_DEC,
8218
14
            NULL, 0x0,
8219
14
            "PRB field length in octets", HFILL}
8220
14
        },
8221
8222
        /* 7.5.2.10 */
8223
14
        { &hf_oran_udCompHdrIqWidth,
8224
14
          { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
8225
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8226
14
            RVALS(ud_comp_header_width), 0xf0,
8227
14
            "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
8228
14
        },
8229
14
        { &hf_oran_udCompHdrIqWidth_pref,
8230
14
          { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
8231
14
            FT_UINT8, BASE_DEC,
8232
14
            NULL, 0x0,
8233
14
            "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
8234
14
        },
8235
8236
14
        { &hf_oran_sinrCompHdrIqWidth_pref,
8237
14
          { "SINR IQ width", "oran_fh_cus.sinrCompHdrWidth",
8238
14
            FT_UINT8, BASE_DEC,
8239
14
            NULL, 0x0,
8240
14
            "Defines the IQ bit width for SINR data in section type 9", HFILL}
8241
14
        },
8242
14
        { &hf_oran_sinrCompHdrMeth_pref,
8243
14
          { "SINR Compression Method", "oran_fh_cus.sinrCompHdrMeth",
8244
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8245
14
            RVALS(ud_comp_header_meth), 0x0,
8246
14
            "Defines the compression method for SINR data in section type 9", HFILL}
8247
14
         },
8248
8249
        /* Section 8.3.3.15 (not always present - depends upon meth) */
8250
14
        { &hf_oran_udCompParam,
8251
14
          { "User Data Compression Parameter", "oran_fh_cus.udCompParam",
8252
14
            FT_STRING, BASE_NONE,
8253
14
            NULL, 0x0,
8254
14
            "Applies to whatever compression method is specified by the associated sectionID's compMeth value", HFILL}
8255
14
        },
8256
        /* 8.3.3.18 */
8257
14
        { &hf_oran_sReSMask,
8258
14
          { "sReSMask", "oran_fh_cus.sReSMask",
8259
14
            FT_UINT16, BASE_HEX,
8260
14
            NULL, 0xf0ff,
8261
14
            "selective RE sending mask", HFILL}
8262
14
        },
8263
8264
14
        { &hf_oran_sReSMask_re12,
8265
14
          { "RE-12", "oran_fh_cus.sReSMask-re12",
8266
14
            FT_BOOLEAN, 16,
8267
14
            TFS(&tfs_present_not_present), 0x8000,
8268
14
            NULL, HFILL}
8269
14
        },
8270
14
        { &hf_oran_sReSMask_re11,
8271
14
          { "RE-11", "oran_fh_cus.sReSMask-re11",
8272
14
            FT_BOOLEAN, 16,
8273
14
            TFS(&tfs_present_not_present), 0x4000,
8274
14
            NULL, HFILL}
8275
14
        },
8276
14
        { &hf_oran_sReSMask_re10,
8277
14
          { "RE-10", "oran_fh_cus.sReSMask-re10",
8278
14
            FT_BOOLEAN, 16,
8279
14
            TFS(&tfs_present_not_present), 0x2000,
8280
14
            NULL, HFILL}
8281
14
        },
8282
14
        { &hf_oran_sReSMask_re9,
8283
14
          { "RE-9", "oran_fh_cus.sReSMask-re9",
8284
14
            FT_BOOLEAN, 16,
8285
14
            TFS(&tfs_present_not_present), 0x1000,
8286
14
            NULL, HFILL}
8287
14
        },
8288
14
        { &hf_oran_sReSMask_re8,
8289
14
          { "RE-8", "oran_fh_cus.sReSMask-re8",
8290
14
            FT_BOOLEAN, 16,
8291
14
            TFS(&tfs_present_not_present), 0x0080,
8292
14
            NULL, HFILL}
8293
14
        },
8294
14
        { &hf_oran_sReSMask_re7,
8295
14
          { "RE-7", "oran_fh_cus.sReSMask-re7",
8296
14
            FT_BOOLEAN, 16,
8297
14
            TFS(&tfs_present_not_present), 0x0040,
8298
14
            NULL, HFILL}
8299
14
        },
8300
14
        { &hf_oran_sReSMask_re6,
8301
14
          { "RE-6", "oran_fh_cus.sReSMask-re6",
8302
14
            FT_BOOLEAN, 16,
8303
14
            TFS(&tfs_present_not_present), 0x0020,
8304
14
            NULL, HFILL}
8305
14
        },
8306
14
        { &hf_oran_sReSMask_re5,
8307
14
          { "RE-5", "oran_fh_cus.sReSMask-re5",
8308
14
            FT_BOOLEAN, 16,
8309
14
            TFS(&tfs_present_not_present), 0x0010,
8310
14
            NULL, HFILL}
8311
14
        },
8312
14
        { &hf_oran_sReSMask_re4,
8313
14
          { "RE-4", "oran_fh_cus.sReSMask-re4",
8314
14
            FT_BOOLEAN, 16,
8315
14
            TFS(&tfs_present_not_present), 0x0008,
8316
14
            NULL, HFILL}
8317
14
        },
8318
14
        { &hf_oran_sReSMask_re3,
8319
14
          { "RE-3", "oran_fh_cus.sReSMask-re3",
8320
14
            FT_BOOLEAN, 16,
8321
14
            TFS(&tfs_present_not_present), 0x0004,
8322
14
            NULL, HFILL}
8323
14
        },
8324
14
        { &hf_oran_sReSMask_re2,
8325
14
          { "RE-2", "oran_fh_cus.sReSMask-re2",
8326
14
            FT_BOOLEAN, 16,
8327
14
            TFS(&tfs_present_not_present), 0x0002,
8328
14
            NULL, HFILL}
8329
14
        },
8330
14
        { &hf_oran_sReSMask_re1,
8331
14
          { "RE-1", "oran_fh_cus.sReSMask-re1",
8332
14
            FT_BOOLEAN, 16,
8333
14
            TFS(&tfs_present_not_present), 0x0001,
8334
14
            NULL, HFILL}
8335
14
        },
8336
8337
        /* 8.3.3.20 */
8338
14
        { &hf_oran_sReSMask1,
8339
14
          { "sReSMask1", "oran_fh_cus.sReSMask1",
8340
14
            FT_UINT16, BASE_HEX,
8341
14
            NULL, 0x0fff,
8342
14
            "selective RE sending mask 1", HFILL}
8343
14
        },
8344
        /* 8.3.3.21 */
8345
14
        { &hf_oran_sReSMask2,
8346
14
          { "sReSMask2", "oran_fh_cus.sReSMask2",
8347
14
            FT_UINT16, BASE_HEX,
8348
14
            NULL, 0x0fff,
8349
14
            "selective RE sending mask 2", HFILL}
8350
14
        },
8351
8352
14
        { &hf_oran_sReSMask1_2_re12,
8353
14
          { "RE-12", "oran_fh_cus.sReSMask-re12",
8354
14
            FT_BOOLEAN, 16,
8355
14
            TFS(&tfs_present_not_present), 0x0800,
8356
14
            NULL, HFILL}
8357
14
        },
8358
14
        { &hf_oran_sReSMask1_2_re11,
8359
14
          { "RE-11", "oran_fh_cus.sReSMask-re11",
8360
14
            FT_BOOLEAN, 16,
8361
14
            TFS(&tfs_present_not_present), 0x0400,
8362
14
            NULL, HFILL}
8363
14
        },
8364
14
        { &hf_oran_sReSMask1_2_re10,
8365
14
          { "RE-10", "oran_fh_cus.sReSMask-re10",
8366
14
            FT_BOOLEAN, 16,
8367
14
            TFS(&tfs_present_not_present), 0x0200,
8368
14
            NULL, HFILL}
8369
14
        },
8370
14
        { &hf_oran_sReSMask1_2_re9,
8371
14
          { "RE-9", "oran_fh_cus.sReSMask-re9",
8372
14
            FT_BOOLEAN, 16,
8373
14
            TFS(&tfs_present_not_present), 0x0100,
8374
14
            NULL, HFILL}
8375
14
        },
8376
8377
        /* Section 6.3.3.15 */
8378
14
        { &hf_oran_iSample,
8379
14
          { "iSample", "oran_fh_cus.iSample",
8380
14
            FT_FLOAT, BASE_NONE,
8381
14
            NULL, 0x0,
8382
14
            "In-phase Sample value", HFILL}
8383
14
        },
8384
8385
        /* Section 6.3.3.16 */
8386
14
        { &hf_oran_qSample,
8387
14
          { "qSample", "oran_fh_cus.qSample",
8388
14
            FT_FLOAT, BASE_NONE,
8389
14
            NULL, 0x0,
8390
14
            "Quadrature Sample value", HFILL}
8391
14
        },
8392
8393
14
        { &hf_oran_exponent,
8394
14
          { "Exponent", "oran_fh_cus.exponent",
8395
14
            FT_UINT8, BASE_DEC,
8396
14
            NULL, 0x0f,
8397
14
            "Exponent applicable to the I & Q mantissas", HFILL }
8398
14
        },
8399
8400
14
        { &hf_oran_iq_user_data,
8401
14
          { "IQ User Data", "oran_fh_cus.iq_user_data",
8402
14
            FT_BYTES, BASE_NONE,
8403
14
            NULL, 0x0,
8404
14
            "Used for the In-phase and Quadrature sample mantissa", HFILL }
8405
14
        },
8406
8407
8408
14
        { &hf_oran_u_section_ul_symbol_time,
8409
14
          { "Microseconds since first UL U-plane frame for this symbol", "oran_fh_cus.us-since-first-ul-frame",
8410
14
            FT_UINT32, BASE_DEC,
8411
14
            NULL, 0x0,
8412
14
            NULL, HFILL }
8413
14
        },
8414
14
        { &hf_oran_u_section_ul_symbol_frames,
8415
14
          { "Number of UL frames sent for this symbol", "oran_fh_cus.number-ul-frames-in-symbol",
8416
14
            FT_UINT32, BASE_DEC,
8417
14
            NULL, 0x0,
8418
14
            NULL, HFILL }
8419
14
        },
8420
14
        { &hf_oran_u_section_ul_symbol_first_frame,
8421
14
          { "First UL frame for this symbol", "oran_fh_cus.first-ul-frame-in-symbol",
8422
14
            FT_FRAMENUM, BASE_NONE,
8423
14
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
8424
14
            NULL, HFILL }
8425
14
        },
8426
14
        { &hf_oran_u_section_ul_symbol_last_frame,
8427
14
          { "Last UL frame for this symbol", "oran_fh_cus.last-ul-frame-in-symbol",
8428
14
            FT_FRAMENUM, BASE_NONE,
8429
14
            FRAMENUM_TYPE(FT_FRAMENUM_NONE), 0x0,
8430
14
            NULL, HFILL }
8431
14
        },
8432
8433
14
        { &hf_oran_c_eAxC_ID,
8434
14
          { "c_eAxC_ID", "oran_fh_cus.c_eaxc_id",
8435
14
            FT_STRING, BASE_NONE,
8436
14
            NULL, 0x0,
8437
14
            "This is a calculated field for the c_eAxC ID, which identifies the message stream", HFILL }
8438
14
        },
8439
8440
14
        { &hf_oran_refa,
8441
14
          { "RefA", "oran_fh_cus.refa",
8442
14
            FT_STRING, BASE_NONE,
8443
14
            NULL, 0x0,
8444
14
            "This is a calculated field for the RefA ID, which provides a reference in time", HFILL }
8445
14
        },
8446
8447
8448
        /* Section 7.5.2.15 */
8449
14
        { &hf_oran_ciCompHdr,
8450
14
          { "ciCompHdr", "oran_fh_cus.ciCompHdr",
8451
14
            FT_STRING, BASE_NONE,
8452
14
            NULL, 0x0,
8453
14
            NULL, HFILL}
8454
14
        },
8455
14
        { &hf_oran_ciCompHdrMeth,
8456
14
          { "User Data Compression Method", "oran_fh_cus.ciCompHdrMeth",
8457
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8458
14
            RVALS(ud_comp_header_meth), 0x0e,
8459
14
            "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
8460
14
         },
8461
14
        { &hf_oran_ciCompHdrIqWidth,
8462
14
          { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
8463
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
8464
14
            RVALS(ud_comp_header_width), 0xf0,
8465
14
            "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
8466
14
        },
8467
14
        { &hf_oran_ciCompOpt,
8468
14
          { "ciCompOpt", "oran_fh_cus.ciCompOpt",
8469
14
            FT_UINT8, BASE_DEC,
8470
14
            VALS(ci_comp_opt_vals), 0x01,
8471
14
            NULL, HFILL }
8472
14
        },
8473
8474
        /* 7.7.11.7 */
8475
14
        { &hf_oran_disable_bfws,
8476
14
          { "disableBFWs", "oran_fh_cus.disableBFWs",
8477
14
            FT_BOOLEAN, 8,
8478
14
            NULL, 0x80,
8479
14
            "Indicate if BFWs under section extension are disabled", HFILL }
8480
14
        },
8481
        /* 7.7.11.8 */
8482
14
        { &hf_oran_rad,
8483
14
          { "RAD", "oran_fh_cus.rad",
8484
14
            FT_BOOLEAN, 8,
8485
14
            NULL, 0x40,
8486
14
            "Reset After PRB Discontinuity", HFILL }
8487
14
        },
8488
        /* 7.7.11.4 */
8489
14
        { &hf_oran_num_bund_prbs,
8490
14
          { "numBundPrb", "oran_fh_cus.numBundPrb",
8491
14
            FT_UINT8, BASE_DEC,
8492
14
            NULL, 0x0,
8493
14
            "Number of bundled PRBs per BFWs", HFILL }
8494
14
        },
8495
14
        { &hf_oran_beam_id,
8496
14
          { "beamId", "oran_fh_cus.beamId",
8497
14
            FT_UINT16, BASE_DEC,
8498
14
            NULL, 0x7fff,
8499
14
            NULL, HFILL }
8500
14
        },
8501
14
        { &hf_oran_num_weights_per_bundle,
8502
14
          { "Num weights per bundle", "oran_fh_cus.num_weights_per_bundle",
8503
14
            FT_UINT16, BASE_DEC,
8504
14
            NULL, 0x0,
8505
14
            "From dissector preference", HFILL }
8506
14
        },
8507
8508
14
        { &hf_oran_samples_prb,
8509
14
          {"PRB", "oran_fh_cus.prb",
8510
14
            FT_STRING, BASE_NONE,
8511
14
            NULL, 0x0,
8512
14
            "Grouping of samples for a particular Physical Resource Block", HFILL}
8513
14
         },
8514
8515
        /* 7.5.3.13 */
8516
14
        { &hf_oran_ciSample,
8517
14
          { "ciSample", "oran_fh_cus.ciSample",
8518
14
            FT_STRING, BASE_NONE,
8519
14
            NULL, 0x0,
8520
14
            "Sample (I and Q values)", HFILL}
8521
14
        },
8522
14
        { &hf_oran_ciIsample,
8523
14
          { "ciIsample", "oran_fh_cus.ciISample",
8524
14
            FT_FLOAT, BASE_NONE,
8525
14
            NULL, 0x0,
8526
14
            "Channel information complex value - I part", HFILL}
8527
14
        },
8528
14
        { &hf_oran_ciQsample,
8529
14
          { "ciQsample", "oran_fh_cus.ciQSample",
8530
14
            FT_FLOAT, BASE_NONE,
8531
14
            NULL, 0x0,
8532
14
            "Channel information complex value - Q part", HFILL}
8533
14
        },
8534
8535
        /* 7.7.10.2 */
8536
14
        { &hf_oran_beamGroupType,
8537
14
          { "beamGroupType", "oran_fh_cus.beamGroupType",
8538
14
            FT_UINT8, BASE_DEC,
8539
14
            VALS(beam_group_type_vals), 0xc0,
8540
14
            "The type of beam grouping", HFILL }
8541
14
        },
8542
        /* 7.7.10.3 */
8543
14
        { &hf_oran_numPortc,
8544
14
          { "numPortc", "oran_fh_cus.numPortc",
8545
14
            FT_UINT8, BASE_DEC,
8546
14
            NULL, 0x3f,
8547
14
            "The number of eAxC ports", HFILL }
8548
14
        },
8549
8550
        /* 7.7.4.2 (1 bit) */
8551
14
        { &hf_oran_csf,
8552
14
          { "csf", "oran_fh_cus.csf",
8553
14
            FT_BOOLEAN, BASE_NONE,
8554
14
            NULL, 0x0,
8555
14
            "constellation shift flag", HFILL }
8556
14
        },
8557
        /* 7.7.4.3 */
8558
14
        { &hf_oran_modcompscaler,
8559
14
          { "modCompScaler", "oran_fh_cus.modcompscaler",
8560
14
            FT_UINT16, BASE_DEC,
8561
14
            NULL, 0x7fff,
8562
14
            "modulation compression scaler value", HFILL }
8563
14
        },
8564
8565
        /* 7.7.5.1 */
8566
14
        { &hf_oran_modcomp_param_set,
8567
14
          { "Set", "oran_fh_cus.modcomp-param-set",
8568
14
            FT_STRING, BASE_NONE,
8569
14
            NULL, 0x0,
8570
14
            NULL, HFILL }
8571
14
        },
8572
8573
8574
8575
        /* mcScaleReMask 7.7.5.2 (12 bits) */
8576
8577
        /* First entry (starts with msb within byte) */
8578
14
        { &hf_oran_mc_scale_re_mask_re1,
8579
14
          { "RE 1", "oran_fh_cus.mcscalermask-RE1",
8580
14
            FT_BOOLEAN, 16,
8581
14
            TFS(&tfs_applicable_not_applicable), 0x8000,
8582
14
            NULL, HFILL}
8583
14
        },
8584
14
        { &hf_oran_mc_scale_re_mask_re2,
8585
14
          { "RE 2", "oran_fh_cus.mcscalermask-RE2",
8586
14
            FT_BOOLEAN, 16,
8587
14
            TFS(&tfs_applicable_not_applicable), 0x4000,
8588
14
            NULL, HFILL}
8589
14
        },
8590
14
        { &hf_oran_mc_scale_re_mask_re3,
8591
14
          { "RE 3", "oran_fh_cus.mcscalermask-RE3",
8592
14
            FT_BOOLEAN, 16,
8593
14
            TFS(&tfs_applicable_not_applicable), 0x2000,
8594
14
            NULL, HFILL}
8595
14
        },
8596
14
        { &hf_oran_mc_scale_re_mask_re4,
8597
14
          { "RE 4", "oran_fh_cus.mcscalermask-RE4",
8598
14
            FT_BOOLEAN, 16,
8599
14
            TFS(&tfs_applicable_not_applicable), 0x1000,
8600
14
            NULL, HFILL}
8601
14
        },
8602
14
        { &hf_oran_mc_scale_re_mask_re5,
8603
14
          { "RE 5", "oran_fh_cus.mcscalermask-RE5",
8604
14
            FT_BOOLEAN, 16,
8605
14
            TFS(&tfs_applicable_not_applicable), 0x0800,
8606
14
            NULL, HFILL}
8607
14
        },
8608
14
        { &hf_oran_mc_scale_re_mask_re6,
8609
14
          { "RE 6", "oran_fh_cus.mcscalermask-RE6",
8610
14
            FT_BOOLEAN, 16,
8611
14
            TFS(&tfs_applicable_not_applicable), 0x0400,
8612
14
            NULL, HFILL}
8613
14
        },
8614
14
        { &hf_oran_mc_scale_re_mask_re7,
8615
14
          { "RE 7", "oran_fh_cus.mcscalermask-RE7",
8616
14
            FT_BOOLEAN, 16,
8617
14
            TFS(&tfs_applicable_not_applicable), 0x0200,
8618
14
            NULL, HFILL}
8619
14
        },
8620
14
        { &hf_oran_mc_scale_re_mask_re8,
8621
14
          { "RE 8", "oran_fh_cus.mcscalermask-RE8",
8622
14
            FT_BOOLEAN, 16,
8623
14
            TFS(&tfs_applicable_not_applicable), 0x0100,
8624
14
            NULL, HFILL}
8625
14
        },
8626
14
        { &hf_oran_mc_scale_re_mask_re9,
8627
14
          { "RE 9", "oran_fh_cus.mcscalermask-RE9",
8628
14
            FT_BOOLEAN, 16,
8629
14
            TFS(&tfs_applicable_not_applicable), 0x0080,
8630
14
            NULL, HFILL}
8631
14
        },
8632
14
        { &hf_oran_mc_scale_re_mask_re10,
8633
14
          { "RE 10", "oran_fh_cus.mcscalermask-RE10",
8634
14
            FT_BOOLEAN, 16,
8635
14
            TFS(&tfs_applicable_not_applicable), 0x0040,
8636
14
            NULL, HFILL}
8637
14
        },
8638
14
        { &hf_oran_mc_scale_re_mask_re11,
8639
14
          { "RE 11", "oran_fh_cus.mcscalermask-RE11",
8640
14
            FT_BOOLEAN, 16,
8641
14
            TFS(&tfs_applicable_not_applicable), 0x0020,
8642
14
            NULL, HFILL}
8643
14
        },
8644
14
        { &hf_oran_mc_scale_re_mask_re12,
8645
14
          { "RE 12", "oran_fh_cus.mcscalermask-RE12",
8646
14
            FT_BOOLEAN, 16,
8647
14
            TFS(&tfs_applicable_not_applicable), 0x0010,
8648
14
            NULL, HFILL}
8649
14
        },
8650
8651
        /* Even tries entry (starts with 5th bit within byte) */
8652
14
        { &hf_oran_mc_scale_re_mask_re1_even,
8653
14
          { "RE 1", "oran_fh_cus.mcscalermask-RE1",
8654
14
            FT_BOOLEAN, 16,
8655
14
            TFS(&tfs_applicable_not_applicable), 0x0800,
8656
14
            NULL, HFILL}
8657
14
        },
8658
14
        { &hf_oran_mc_scale_re_mask_re2_even,
8659
14
          { "RE 2", "oran_fh_cus.mcscalermask-RE2",
8660
14
            FT_BOOLEAN, 16,
8661
14
            TFS(&tfs_applicable_not_applicable), 0x0400,
8662
14
            NULL, HFILL}
8663
14
        },
8664
14
        { &hf_oran_mc_scale_re_mask_re3_even,
8665
14
          { "RE 3", "oran_fh_cus.mcscalermask-RE3",
8666
14
            FT_BOOLEAN, 16,
8667
14
            TFS(&tfs_applicable_not_applicable), 0x0200,
8668
14
            NULL, HFILL}
8669
14
        },
8670
14
        { &hf_oran_mc_scale_re_mask_re4_even,
8671
14
          { "RE 4", "oran_fh_cus.mcscalermask-RE4",
8672
14
            FT_BOOLEAN, 16,
8673
14
            TFS(&tfs_applicable_not_applicable), 0x0100,
8674
14
            NULL, HFILL}
8675
14
        },
8676
14
        { &hf_oran_mc_scale_re_mask_re5_even,
8677
14
          { "RE 5", "oran_fh_cus.mcscalermask-RE5",
8678
14
            FT_BOOLEAN, 16,
8679
14
            TFS(&tfs_applicable_not_applicable), 0x0080,
8680
14
            NULL, HFILL}
8681
14
        },
8682
14
        { &hf_oran_mc_scale_re_mask_re6_even,
8683
14
          { "RE 6", "oran_fh_cus.mcscalermask-RE6",
8684
14
            FT_BOOLEAN, 16,
8685
14
            TFS(&tfs_applicable_not_applicable), 0x0040,
8686
14
            NULL, HFILL}
8687
14
        },
8688
14
        { &hf_oran_mc_scale_re_mask_re7_even,
8689
14
          { "RE 7", "oran_fh_cus.mcscalermask-RE7",
8690
14
            FT_BOOLEAN, 16,
8691
14
            TFS(&tfs_applicable_not_applicable), 0x0020,
8692
14
            NULL, HFILL}
8693
14
        },
8694
14
        { &hf_oran_mc_scale_re_mask_re8_even,
8695
14
          { "RE 8", "oran_fh_cus.mcscalermask-RE8",
8696
14
            FT_BOOLEAN, 16,
8697
14
            TFS(&tfs_applicable_not_applicable), 0x0010,
8698
14
            NULL, HFILL}
8699
14
        },
8700
14
        { &hf_oran_mc_scale_re_mask_re9_even,
8701
14
          { "RE 9", "oran_fh_cus.mcscalermask-RE9",
8702
14
            FT_BOOLEAN, 16,
8703
14
            TFS(&tfs_applicable_not_applicable), 0x0008,
8704
14
            NULL, HFILL}
8705
14
        },
8706
14
        { &hf_oran_mc_scale_re_mask_re10_even,
8707
14
          { "RE 10", "oran_fh_cus.mcscalermask-RE10",
8708
14
            FT_BOOLEAN, 16,
8709
14
            TFS(&tfs_applicable_not_applicable), 0x0004,
8710
14
            NULL, HFILL}
8711
14
        },
8712
14
        { &hf_oran_mc_scale_re_mask_re11_even,
8713
14
          { "RE 11", "oran_fh_cus.mcscalermask-RE11",
8714
14
            FT_BOOLEAN, 16,
8715
14
            TFS(&tfs_applicable_not_applicable), 0x0002,
8716
14
            NULL, HFILL}
8717
14
        },
8718
14
        { &hf_oran_mc_scale_re_mask_re12_even,
8719
14
          { "RE 12", "oran_fh_cus.mcscalermask-RE12",
8720
14
            FT_BOOLEAN, 16,
8721
14
            TFS(&tfs_applicable_not_applicable), 0x0001,
8722
14
            NULL, HFILL}
8723
14
        },
8724
8725
14
        { &hf_oran_mc_scale_re_mask,
8726
14
          { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
8727
14
            FT_UINT16, BASE_HEX,
8728
14
            NULL, 0xfff0,
8729
14
            "modulation compression power scale RE mask", HFILL }
8730
14
        },
8731
14
        { &hf_oran_mc_scale_re_mask_even,
8732
14
          { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
8733
14
            FT_UINT16, BASE_HEX,
8734
14
            NULL, 0x0fff,
8735
14
            "modulation compression power scale RE mask", HFILL }
8736
14
        },
8737
8738
        /* mcScaleOffset 7.7.5.4 (15 bits) */
8739
14
        { &hf_oran_mc_scale_offset,
8740
14
          { "mcScaleOffset", "oran_fh_cus.mcscaleoffset",
8741
14
            FT_UINT24, BASE_DEC,
8742
14
            NULL, 0x0,
8743
14
            "scaling value for modulation compression", HFILL }
8744
14
        },
8745
        /* eAxCmask (7.7.7.2) */
8746
14
        { &hf_oran_eAxC_mask,
8747
14
          { "eAxC Mask", "oran_fh_cus.eaxcmask",
8748
14
            FT_UINT16, BASE_HEX,
8749
14
            NULL, 0xffff,
8750
14
            "Which eAxC_ID values the C-Plane message applies to", HFILL }
8751
14
        },
8752
        /* technology (interface name) 7.7.9.2 */
8753
14
        { &hf_oran_technology,
8754
14
          { "Technology", "oran_fh_cus.technology",
8755
14
            FT_UINT8, BASE_DEC,
8756
14
            VALS(interface_name_vals), 0x0,
8757
14
            "Interface name (that C-PLane section applies to)", HFILL }
8758
14
        },
8759
        /* Exttype 14 (7.7.14.2) */
8760
14
        { &hf_oran_nullLayerInd,
8761
14
          { "nullLayerInd", "oran_fh_cus.nulllayerind",
8762
14
            FT_BOOLEAN, BASE_NONE,
8763
14
            NULL, 0x0,
8764
14
            "Whether corresponding layer is nulling-layer or not", HFILL }
8765
14
        },
8766
8767
        /* Exttype 19 */
8768
        /* 7.7.19.3 */
8769
14
        { &hf_oran_se19_repetition,
8770
14
          { "repetition", "oran_fh_cus.repetition",
8771
14
            FT_BOOLEAN, BASE_NONE,
8772
14
            TFS(&repetition_se19_tfs), 0x0,
8773
14
            "repeat port info flag", HFILL}
8774
14
        },
8775
        /* 7.7.19.8 */
8776
        /* TODO: break down into each RE as done for 7.5.3.5 ? */
8777
14
        { &hf_oran_portReMask,
8778
14
          { "portReMask", "oran_fh_cus.portReMask",
8779
14
            FT_BOOLEAN, 16,
8780
14
            TFS(&tfs_set_notset), 0x0fff,
8781
14
            "RE bitmask per port", HFILL }
8782
14
        },
8783
        /* 7.7.19.9 */
8784
14
        { &hf_oran_portSymbolMask,
8785
14
          { "portSymbolMask", "oran_fh_cus.portSymbolMask",
8786
14
            FT_BOOLEAN, 16,
8787
14
            TFS(&tfs_set_notset), 0x3fff,
8788
14
            "Symbol bitmask port port", HFILL }
8789
14
        },
8790
8791
14
        { &hf_oran_ext19_port,
8792
14
          {"Port", "oran_fh_cus.ext19.port",
8793
14
            FT_STRING, BASE_NONE,
8794
14
            NULL, 0x0,
8795
14
            "Entry for a given port in ext19", HFILL}
8796
14
         },
8797
8798
        /* Ext 13 */
8799
14
        { &hf_oran_prb_allocation,
8800
14
          {"PRB allocation", "oran_fh_cus.prb-allocation",
8801
14
            FT_STRING, BASE_NONE,
8802
14
            NULL, 0x0,
8803
14
            NULL, HFILL}
8804
14
         },
8805
        /* 7.7.13.2 */
8806
14
        { &hf_oran_nextSymbolId,
8807
14
          { "nextSymbolId", "oran_fh_cus.nextSymbolId",
8808
14
            FT_UINT8, BASE_DEC,
8809
14
            NULL, 0x3c,
8810
14
            "offset of PRB range start", HFILL }
8811
14
        },
8812
        /* 7.7.13.3 */
8813
14
        { &hf_oran_nextStartPrbc,
8814
14
          { "nextStartPrbc", "oran_fh_cus.nextStartPrbc",
8815
14
            FT_UINT16, BASE_DEC,
8816
14
            NULL, 0x03ff,
8817
14
            "number of PRBs in PRB range", HFILL }
8818
14
        },
8819
8820
        /* Puncturing patters as appears in SE 20 */
8821
14
        { &hf_oran_puncPattern,
8822
14
          { "puncPattern", "oran_fh_cus.puncPattern",
8823
14
            FT_STRING, BASE_NONE,
8824
14
            NULL, 0x0,
8825
14
            NULL, HFILL}
8826
14
        },
8827
8828
        /* 7.7.20.2 numPuncPatterns */
8829
14
        { &hf_oran_numPuncPatterns,
8830
14
          { "numPuncPatterns", "oran_fh_cus.numPuncPatterns",
8831
14
            FT_UINT8, BASE_DEC,
8832
14
            NULL, 0x0,
8833
14
            "number of puncturing patterns", HFILL }
8834
14
        },
8835
        /* 7.7.20.3 symbolMask */
8836
14
        { &hf_oran_symbolMask_ext20,
8837
14
          { "symbolMask", "oran_fh_cus.symbolMask",
8838
14
            FT_UINT16, BASE_HEX,
8839
14
            NULL, 0xfffc,
8840
14
            "Bitmask where each bit indicates the symbols associated with the puncturing pattern", HFILL}
8841
14
        },
8842
        /* 7.7.20.4 startPuncPrb */
8843
14
        { &hf_oran_startPuncPrb,
8844
14
          { "startPuncPrb", "oran_fh_cus.startPuncPrb",
8845
14
            FT_UINT16, BASE_DEC,
8846
14
            NULL, 0x03ff,
8847
14
            "starting PRB to which one puncturing pattern applies", HFILL}
8848
14
        },
8849
        /* 7.7.20.5 numPuncPrb */
8850
14
        { &hf_oran_numPuncPrb,
8851
14
          { "numPuncPrb", "oran_fh_cus.numPuncPrb",
8852
14
            FT_UINT8, BASE_DEC,
8853
14
            NULL, 0x0,
8854
14
            "the number of PRBs of the puncturing pattern", HFILL}
8855
14
        },
8856
        /* 7.7.20.6 puncReMask */
8857
14
        { &hf_oran_puncReMask,
8858
14
          { "puncReMask", "oran_fh_cus.puncReMask",
8859
14
            FT_UINT16, BASE_DEC,
8860
14
            NULL, 0xffc0,
8861
14
            "puncturing pattern RE mask", HFILL}
8862
14
        },
8863
        /* 7.7.20.12 multiSDScope */
8864
14
        { &hf_oran_multiSDScope,
8865
14
          { "multiSDScope", "oran_fh_cus.multiSDScope",
8866
14
            FT_BOOLEAN, 8,
8867
14
            TFS(&multi_sd_scope_tfs), 0x02,
8868
14
            "multiple section description scope flag", HFILL}
8869
14
        },
8870
        /* 7.7.20.4 rbgIncl */
8871
14
        { &hf_oran_RbgIncl,
8872
14
          { "rbgIncl", "oran_fh_cus.rbgIncl",
8873
14
            FT_BOOLEAN, 8,
8874
14
            NULL, 0x01,
8875
14
            "rbg included flag", HFILL}
8876
14
        },
8877
8878
        /* 7.7.21.2 ciPrbGroupSize */
8879
14
        { &hf_oran_ci_prb_group_size,
8880
14
          { "ciPrbGroupSize", "oran_fh_cus.ciPrbGroupSize",
8881
14
            FT_UINT8, BASE_DEC,
8882
14
            NULL, 0x0,
8883
14
            "channel information PRB group size", HFILL}
8884
14
        },
8885
        /* 7.21.3 */
8886
14
        { &hf_oran_prg_size_st5,
8887
14
          { "prgSize", "oran_fh_cus.prgSize",
8888
14
            FT_UINT8, BASE_DEC,
8889
14
            VALS(prg_size_st5_vals), 0x03,
8890
14
            "precoding resource block group size", HFILL}
8891
14
        },
8892
14
        { &hf_oran_prg_size_st6,
8893
14
          { "prgSize", "oran_fh_cus.prgSize",
8894
14
            FT_UINT8, BASE_DEC,
8895
14
            VALS(prg_size_st6_vals), 0x03,
8896
14
            "precoding resource block group size", HFILL}
8897
14
        },
8898
8899
        /* 7.7.17.2 numUeID */
8900
14
        { &hf_oran_num_ueid,
8901
14
          { "numUeID", "oran_fh_cus.numUeID",
8902
14
            FT_UINT8, BASE_DEC,
8903
14
            NULL, 0x0,
8904
14
            "number of ueIDs per user", HFILL}
8905
14
        },
8906
8907
        /* 7.7.16.2 antMask */
8908
14
        { &hf_oran_antMask,
8909
14
          { "antMask", "oran_fh_cus.antMask",
8910
14
            FT_UINT64, BASE_HEX,
8911
14
            NULL, 0xffffffffffffffff,
8912
14
            "indices of antennas to be pre-combined per RX endpoint", HFILL}
8913
14
        },
8914
8915
        /* 7.7.18.2 transmissionWindowOffset */
8916
14
        { &hf_oran_transmissionWindowOffset,
8917
14
          { "transmissionWindowOffset", "oran_fh_cus.transmissionWindowOffset",
8918
14
            FT_UINT16, BASE_DEC,
8919
14
            NULL, 0x0,
8920
14
            "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}
8921
14
        },
8922
        /* 7.7.18.3 transmissionWindowSize */
8923
14
        { &hf_oran_transmissionWindowSize,
8924
14
          { "transmissionWindowSize", "oran_fh_cus.transmissionWindowSize",
8925
14
            FT_UINT16, BASE_DEC,
8926
14
            NULL, 0x3fff,
8927
14
            "size of the transmission window in resolution µs", HFILL}
8928
14
        },
8929
        /* 7.7.18.4 toT */
8930
14
        { &hf_oran_toT,
8931
14
          { "toT", "oran_fh_cus.toT",
8932
14
            FT_UINT8, BASE_DEC,
8933
14
            VALS(type_of_transmission_vals), 0x03,
8934
14
            "type of transmission", HFILL}
8935
14
        },
8936
8937
        /* 7.7.2.2 bfaCompHdr */
8938
14
        { &hf_oran_bfaCompHdr,
8939
14
          { "bfaCompHdr", "oran_fh_cus.bfaCompHdr",
8940
14
            FT_STRING, BASE_NONE,
8941
14
            NULL, 0x0,
8942
14
            "beamforming attributes compression header", HFILL}
8943
14
        },
8944
        /* 7.7.2.2-2: bfAzPtWidth */
8945
14
        { &hf_oran_bfAzPtWidth,
8946
14
          { "bfAzPtWidth", "oran_fh_cus.bfAzPtWidth",
8947
14
            FT_UINT8, BASE_DEC,
8948
14
            VALS(bfa_bw_vals), 0x38,
8949
14
            NULL, HFILL}
8950
14
        },
8951
        /* 7.7.2.2-3: bfZePtWidth */
8952
14
        { &hf_oran_bfZePtWidth,
8953
14
          { "bfZePtWidth", "oran_fh_cus.bfZePtWidth",
8954
14
            FT_UINT8, BASE_DEC,
8955
14
            VALS(bfa_bw_vals), 0x07,
8956
14
            NULL, HFILL}
8957
14
        },
8958
        /* 7.7.2.2-4: bfAz3ddWidth */
8959
14
        { &hf_oran_bfAz3ddWidth,
8960
14
          { "bfAz3ddWidth", "oran_fh_cus.bfAz3ddWidth",
8961
14
            FT_UINT8, BASE_DEC,
8962
14
            VALS(bfa_bw_vals), 0x38,
8963
14
            NULL, HFILL}
8964
14
        },
8965
        /* 7.7.2.2-5: bfZe3ddWidth */
8966
14
        { &hf_oran_bfZe3ddWidth,
8967
14
          { "bfZe3ddWidth", "oran_fh_cus.bfZe3ddWidth",
8968
14
            FT_UINT8, BASE_DEC,
8969
14
            VALS(bfa_bw_vals), 0x07,
8970
14
            NULL, HFILL}
8971
14
        },
8972
8973
        /* 7.7.2.3 bfAzPt */
8974
14
        { &hf_oran_bfAzPt,
8975
14
          { "bfAzPt", "oran_fh_cus.bfAzPt",
8976
14
            FT_UINT8, BASE_DEC,
8977
14
            NULL, 0x0,
8978
14
            "beamforming azimuth pointing parameter", HFILL}
8979
14
        },
8980
        /* 7.7.2.4 bfZePt */
8981
14
        { &hf_oran_bfZePt,
8982
14
          { "bfZePt", "oran_fh_cus.bfZePt",
8983
14
            FT_UINT8, BASE_DEC,
8984
14
            NULL, 0x0,
8985
14
            "beamforming zenith pointing parameter", HFILL}
8986
14
        },
8987
        /* 7.7.2.5 bfAz3dd */
8988
14
        { &hf_oran_bfAz3dd,
8989
14
          { "bfAz3dd", "oran_fh_cus.bfAz3dd",
8990
14
            FT_UINT8, BASE_DEC,
8991
14
            NULL, 0x0,
8992
14
            "beamforming azimuth beamwidth parameter", HFILL}
8993
14
        },
8994
        /* 7.7.2.6 bfZe3dd */
8995
14
        { &hf_oran_bfZe3dd,
8996
14
          { "bfZe3dd", "oran_fh_cus.bfZe3dd",
8997
14
            FT_UINT8, BASE_DEC,
8998
14
            NULL, 0x0,
8999
14
            "beamforming zenith beamwidth parameter", HFILL}
9000
14
        },
9001
9002
        /* 7.7.2.7 bfAzSl */
9003
14
        { &hf_oran_bfAzSl,
9004
14
          { "bfAzSl", "oran_fh_cus.bfAzSl",
9005
14
            FT_UINT8, BASE_DEC,
9006
14
            VALS(sidelobe_suppression_vals), 0x38,
9007
14
            "beamforming azimuth sidelobe parameter", HFILL}
9008
14
        },
9009
        /* 7.7.2.8 bfZeSl */
9010
14
        { &hf_oran_bfZeSl,
9011
14
          { "bfZeSl", "oran_fh_cus.bfZeSl",
9012
14
            FT_UINT8, BASE_DEC,
9013
14
            VALS(sidelobe_suppression_vals), 0x07,
9014
14
            "beamforming zenith sidelobe parameter", HFILL}
9015
14
        },
9016
9017
        /* 7.5.2.17 */
9018
14
        { &hf_oran_cmd_scope,
9019
14
          { "cmdScope", "oran_fh_cus.cmdScope",
9020
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9021
14
            RVALS(cmd_scope_vals), 0x0f,
9022
14
            "command scope", HFILL}
9023
14
        },
9024
        /* 7.5.2.18 */
9025
14
        { &hf_oran_number_of_st4_cmds,
9026
14
          { "numberOfST4Cmds", "oran_fh_cus.numberOfST4Cmds",
9027
14
            FT_UINT8, BASE_DEC,
9028
14
            NULL, 0x0,
9029
14
            "Number of Section Type 4 commands", HFILL}
9030
14
        },
9031
9032
14
        { &hf_oran_st4_cmd_header,
9033
14
          { "Command common header", "oran_fh_cus.st4CmdCommonHeader",
9034
14
            FT_STRING, BASE_NONE,
9035
14
            NULL, 0x0,
9036
14
            NULL, HFILL}
9037
14
        },
9038
9039
        /* 7.5.3.38 */
9040
14
        { &hf_oran_st4_cmd_type,
9041
14
          { "st4CmdType", "oran_fh_cus.st4CmdType",
9042
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9043
14
            RVALS(st4_cmd_type_vals), 0x0,
9044
14
            NULL, HFILL}
9045
14
        },
9046
        /* 7.5.3.39 */
9047
14
        { &hf_oran_st4_cmd_len,
9048
14
          { "st4CmdLen", "oran_fh_cus.st4CmdLen",
9049
14
            FT_UINT16, BASE_DEC,
9050
14
            NULL, 0x0,
9051
14
            "Length of command in 32-bit words", HFILL}
9052
14
        },
9053
        /* 7.5.3.40 */
9054
14
        { &hf_oran_st4_cmd_num_slots,
9055
14
          { "numSlots", "oran_fh_cus.st4NumSlots",
9056
14
            FT_UINT8, BASE_DEC,
9057
14
            NULL, 0x0,
9058
14
            "Contiguous slots for which command is applicable", HFILL}
9059
14
        },
9060
        /* 7.5.3.41 */
9061
14
        { &hf_oran_st4_cmd_ack_nack_req_id,
9062
14
          { "ackNackReqId", "oran_fh_cus.ackNackReqId",
9063
14
            FT_UINT16, BASE_DEC,
9064
14
            NULL, 0x0,
9065
14
            "ACK/NACK Request Id", HFILL}
9066
14
        },
9067
9068
14
        { &hf_oran_st4_cmd,
9069
14
          { "Command", "oran_fh_cus.st4Cmd",
9070
14
            FT_STRING, BASE_NONE,
9071
14
            NULL, 0x0,
9072
14
            NULL, HFILL}
9073
14
        },
9074
9075
        /* 7.5.3.52 */
9076
14
        { &hf_oran_sleepmode_trx,
9077
14
          { "sleepMode", "oran_fh_cus.sleepMode",
9078
14
            FT_UINT8, BASE_HEX,
9079
14
            VALS(sleep_mode_trx_vals), 0x03,
9080
14
            NULL, HFILL}
9081
14
        },
9082
14
        { &hf_oran_sleepmode_asm,
9083
14
          { "sleepMode", "oran_fh_cus.sleepMode",
9084
14
            FT_UINT8, BASE_HEX,
9085
14
            VALS(sleep_mode_asm_vals), 0x03,
9086
14
            NULL, HFILL}
9087
14
        },
9088
9089
        /* 7.5.3.51 */
9090
14
        { &hf_oran_log2maskbits,
9091
14
          { "log2MaskBits", "oran_fh_cus.log2MaskBits",
9092
14
            FT_UINT8, BASE_HEX,
9093
14
            VALS(log2maskbits_vals), 0x3c,
9094
14
            "Number of bits to appear in antMask", HFILL}
9095
14
        },
9096
        /* 7.5.3.53 */
9097
14
        { &hf_oran_num_slots_ext,
9098
14
          { "numSlotsExt", "oran_fh_cus.numSlotsExt",
9099
14
            FT_UINT24, BASE_HEX,
9100
14
            NULL, 0x0fffff,
9101
14
            NULL, HFILL}
9102
14
        },
9103
        /* 7.5.3.54 */
9104
14
        { &hf_oran_antMask_trx_control,
9105
14
          { "antMask", "oran_fh_cus.trxControl.antMask",
9106
14
            FT_BYTES, BASE_NONE,
9107
14
            NULL, 0x0,
9108
14
            "which antennas should sleep or wake-up", HFILL}
9109
14
        },
9110
        /* 7.5.3.55 */
9111
14
        { &hf_oran_ready,
9112
14
          { "ready", "oran_fh_cus.ready",
9113
14
            FT_BOOLEAN, 8,
9114
14
            TFS(&ready_tfs), 0x01,
9115
14
            "wake-up ready indicator", HFILL}
9116
14
        },
9117
        /* 7.5.3.34 */
9118
14
        { &hf_oran_number_of_acks,
9119
14
          { "numberOfAcks", "oran_fh_cus.numberOfAcks",
9120
14
            FT_UINT8, BASE_DEC,
9121
14
            NULL, 0x0,
9122
14
            "number of ACKs for one eAxC_ID", HFILL}
9123
14
        },
9124
        /* 7.5.3.35 */
9125
14
        { &hf_oran_number_of_nacks,
9126
14
          { "numberOfNacks", "oran_fh_cus.numberOfNacks",
9127
14
            FT_UINT8, BASE_DEC,
9128
14
            NULL, 0x0,
9129
14
            "number of NACKs for one eAxC_ID", HFILL}
9130
14
        },
9131
        /* 7.5.3.36 */
9132
14
        { &hf_oran_ackid,
9133
14
          { "ackId", "oran_fh_cus.ackId",
9134
14
            FT_UINT16, BASE_DEC,
9135
14
            NULL, 0x0,
9136
14
            NULL, HFILL}
9137
14
        },
9138
        /* 7.5.3.37 */
9139
14
        { &hf_oran_nackid,
9140
14
          { "nackId", "oran_fh_cus.nackId",
9141
14
            FT_UINT16, BASE_DEC,
9142
14
            NULL, 0x0,
9143
14
            NULL, HFILL}
9144
14
        },
9145
9146
        /* Links between acknack requests & responses */
9147
14
        { &hf_oran_acknack_request_frame,
9148
14
          { "Request Frame", "oran_fh_cus.ackNackId.request-frame",
9149
14
            FT_FRAMENUM, BASE_NONE,
9150
14
            FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
9151
14
            NULL, HFILL}
9152
14
        },
9153
14
        { &hf_oran_acknack_request_time,
9154
14
          { "Time since request in ms", "oran_fh_cus.ackNackId.time-since-request",
9155
14
            FT_UINT32, BASE_DEC,
9156
14
            NULL, 0x0,
9157
14
            "Time between request and response", HFILL}
9158
14
        },
9159
14
        { &hf_oran_acknack_request_type,
9160
14
          { "Request Type", "oran_fh_cus.ackNackId.request-type",
9161
14
            FT_UINT32, BASE_DEC,
9162
14
            VALS(acknack_type_vals), 0x0,
9163
14
            NULL, HFILL}
9164
14
        },
9165
14
        { &hf_oran_acknack_response_frame,
9166
14
          { "Response Frame", "oran_fh_cus.ackNackId.response-frame",
9167
14
            FT_FRAMENUM, BASE_NONE,
9168
14
            FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
9169
14
            NULL, HFILL}
9170
14
        },
9171
14
        { &hf_oran_acknack_response_time,
9172
14
          { "Time to response in ms", "oran_fh_cus.ackNackId.time-to-response",
9173
14
            FT_UINT32, BASE_DEC,
9174
14
            NULL, 0x0,
9175
14
            "Time between request and response", HFILL}
9176
14
        },
9177
9178
        /* 7.5.3.43 */
9179
14
        { &hf_oran_disable_tdbfns,
9180
14
          { "disableTDBFNs", "oran_fh_cus.disableTDBFNs",
9181
14
            FT_BOOLEAN, 8,
9182
14
            TFS(&disable_tdbfns_tfs), 0x80,
9183
14
            NULL, HFILL}
9184
14
        },
9185
9186
        /* 7.5.3.44 */
9187
14
        { &hf_oran_td_beam_group,
9188
14
          { "tdBeamGrp", "oran_fh_cus.tdBeamGrp",
9189
14
            FT_UINT16, BASE_HEX,
9190
14
            NULL, 0x7fff,
9191
14
            "Applies to symbolMask in command header", HFILL}
9192
14
        },
9193
        /* 7.5.3.43 */
9194
14
        { &hf_oran_disable_tdbfws,
9195
14
          { "disableTDBFWs", "oran_fh_cus.disableTDBFWs",
9196
14
            FT_BOOLEAN, 8,
9197
14
            TFS(&beam_numbers_included_tfs), 0x80,
9198
14
            NULL, HFILL}
9199
14
        },
9200
9201
        /* 7.5.3.56 */
9202
14
        { &hf_oran_td_beam_num,
9203
14
          { "tdBeamNum", "oran_fh_cus.tdBeamNum",
9204
14
            FT_UINT16, BASE_HEX,
9205
14
            NULL, 0x7fff,
9206
14
            "time-domain beam number", HFILL}
9207
14
        },
9208
9209
        /* 7.5.3.49 */
9210
14
        { &hf_oran_dir_pattern,
9211
14
          { "dirPattern", "oran_fh_cus.dirPattern",
9212
14
            FT_BOOLEAN, 16,
9213
14
            TFS(&symbol_direction_tfs), 0x3fff,
9214
14
            "symbol data direction (gNB Tx/Rx) pattern", HFILL}
9215
14
        },
9216
        /* 7.5.3.50 */
9217
14
        { &hf_oran_guard_pattern,
9218
14
          { "guardPattern", "oran_fh_cus.guardPattern",
9219
14
            FT_BOOLEAN, 16,
9220
14
            TFS(&symbol_guard_tfs), 0x3fff,
9221
14
            "guard pattern bitmask", HFILL}
9222
14
        },
9223
9224
        /* For convenient filtering */
9225
14
        { &hf_oran_cplane,
9226
14
          { "C-Plane", "oran_fh_cus.c-plane",
9227
14
            FT_NONE, BASE_NONE,
9228
14
            NULL, 0x0,
9229
14
            NULL, HFILL}
9230
14
        },
9231
14
        { &hf_oran_uplane,
9232
14
          { "U-Plane", "oran_fh_cus.u-plane",
9233
14
            FT_NONE, BASE_NONE,
9234
14
            NULL, 0x0,
9235
14
            NULL, HFILL}
9236
14
        },
9237
14
        { &hf_oran_bf,
9238
14
          { "BeamForming", "oran_fh_cus.bf",
9239
14
            FT_NONE, BASE_NONE,
9240
14
            NULL, 0x0,
9241
14
            NULL, HFILL}
9242
14
        },
9243
14
        { &hf_oran_zero_prb,
9244
14
          { "Zero PRB", "oran_fh_cus.zero-prb",
9245
14
            FT_NONE, BASE_NONE,
9246
14
            NULL, 0x0,
9247
14
            "All of the REs in this PRB are zero", HFILL}
9248
14
        },
9249
9250
        /* 5.1.3.2.7 */
9251
14
        { &hf_oran_ecpri_pcid,
9252
14
          { "ecpriPcid", "oran_fh_cus.ecpriPcid",
9253
14
            FT_NONE, BASE_NONE,
9254
14
            NULL, 0x0,
9255
14
            "IQ data transfer message series identifier", HFILL}
9256
14
        },
9257
14
        { &hf_oran_ecpri_rtcid,
9258
14
          { "ecpriRtcid", "oran_fh_cus.ecpriRtcid",
9259
14
            FT_NONE, BASE_NONE,
9260
14
            NULL, 0x0,
9261
14
            "Real time control data identifier", HFILL}
9262
14
        },
9263
        /* 5.1.3.2.8 */
9264
14
        { &hf_oran_ecpri_seqid,
9265
14
          { "ecpriSeqid", "oran_fh_cus.ecpriSeqid",
9266
14
            FT_NONE, BASE_NONE,
9267
14
            NULL, 0x0,
9268
14
            "message identifier", HFILL}
9269
14
        },
9270
9271
        /* 7.7.23.2 */
9272
14
        { &hf_oran_num_sym_prb_pattern,
9273
14
          { "numSymPrbPattern", "oran_fh_cus.numSymPrbPattern",
9274
14
            FT_UINT8, BASE_DEC,
9275
14
            NULL, 0xf0,
9276
14
            "number of symbol and resource block patterns", HFILL}
9277
14
        },
9278
        /* 7.7.23.11 */
9279
14
        { &hf_oran_prb_mode,
9280
14
          { "prbMode", "oran_fh_cus.prbMode",
9281
14
            FT_BOOLEAN, 8,
9282
14
            TFS(&prb_mode_tfs), 0x01,
9283
14
            "PRB Mode", HFILL}
9284
14
        },
9285
9286
14
        { &hf_oran_sym_prb_pattern,
9287
14
          { "symPrbPattern", "oran_fh_cus.symPrbPattern",
9288
14
            FT_STRING, BASE_NONE,
9289
14
            NULL, 0x0,
9290
14
            NULL, HFILL}
9291
14
        },
9292
9293
        /* 7.7.23.3 */
9294
14
        { &hf_oran_sym_mask,
9295
14
          { "symMask", "oran_fh_cus.symMask",
9296
14
            FT_UINT16, BASE_HEX,
9297
14
            NULL, 0x3fff,
9298
14
            "symbol mask part of symPrbPattern", HFILL}
9299
14
        },
9300
        /* 7.7.23.5 */
9301
14
        {&hf_oran_num_mc_scale_offset,
9302
14
         {"numMcScaleOffset", "oran_fh_cus.numMcScaleOffset",
9303
14
          FT_UINT8, BASE_DEC,
9304
14
          NULL, 0xf0,
9305
14
          "number of modulation compression scaling value per symPrbPattern",
9306
14
          HFILL}
9307
14
        },
9308
        /* 7.7.23.4 */
9309
14
        { &hf_oran_prb_pattern,
9310
14
          { "prbPattern", "oran_fh_cus.prbPattern",
9311
14
            FT_UINT8, BASE_DEC,
9312
14
            NULL, 0x0f,
9313
14
            "resource block pattern part of symPrbPattern", HFILL}
9314
14
        },
9315
9316
        /* 7.7.3.2 */
9317
14
        { &hf_oran_codebook_index,
9318
14
          { "codebookIndex", "oran_fh_cus.codebookIndex",
9319
14
            FT_UINT8, BASE_DEC,
9320
14
            NULL, 0x0,
9321
14
            "precoder codebook used for transmission", HFILL}
9322
14
        },
9323
        /* 7.7.3.3 */
9324
14
        { &hf_oran_layerid,
9325
14
          { "layerID", "oran_fh_cus.layerID",
9326
14
            FT_UINT8, BASE_DEC,
9327
14
            NULL, 0xf0,
9328
14
            "Layer ID for DL transmission", HFILL}
9329
14
        },
9330
        /* 7.7.3.5 */
9331
14
        { &hf_oran_numlayers,
9332
14
          { "numLayers", "oran_fh_cus.numLayers",
9333
14
            FT_UINT8, BASE_DEC,
9334
14
            NULL, 0x0f,
9335
14
            "number of layers for DL transmission", HFILL}
9336
14
        },
9337
        /* 7.7.3.4 */
9338
14
        { &hf_oran_txscheme,
9339
14
          { "txScheme", "oran_fh_cus.txScheme",
9340
14
            FT_UINT8, BASE_DEC,
9341
14
            NULL, 0xf0,
9342
14
            "transmission scheme", HFILL}
9343
14
        },
9344
        /* 7.7.3.6 */
9345
14
        { &hf_oran_crs_remask,
9346
14
          { "crsReMask", "oran_fh_cus.crsReMask",
9347
14
            FT_UINT16, BASE_HEX,
9348
14
            NULL, 0x0fff,
9349
14
            "CRS resource element mask", HFILL}
9350
14
        },
9351
        /* 7.7.3.8 */
9352
14
        { &hf_oran_crs_shift,
9353
14
          { "crsShift", "oran_fh_cus.crsShift",
9354
14
            FT_UINT8, BASE_HEX,
9355
14
            NULL, 0x80,
9356
14
            "CRS resource element mask", HFILL}
9357
14
        },
9358
        /* 7.7.3.7 */
9359
14
        { &hf_oran_crs_symnum,
9360
14
          { "crsSymNum", "oran_fh_cus.crsSymNum",
9361
14
            FT_UINT8, BASE_DEC,
9362
14
            NULL, 0x0f,
9363
14
            "CRS symbol number indication", HFILL}
9364
14
        },
9365
        /* 7.7.3.9 */
9366
14
        { &hf_oran_beamid_ap1,
9367
14
          { "beamIdAP1", "oran_fh_cus.beamIdAP1",
9368
14
            FT_UINT16, BASE_DEC,
9369
14
            NULL, 0x7f,
9370
14
            "beam id to be used for antenna port 1", HFILL}
9371
14
        },
9372
        /* 7.7.3.10 */
9373
14
        { &hf_oran_beamid_ap2,
9374
14
          { "beamIdAP2", "oran_fh_cus.beamIdAP2",
9375
14
            FT_UINT16, BASE_DEC,
9376
14
            NULL, 0x7f,
9377
14
            "beam id to be used for antenna port 2", HFILL}
9378
14
        },
9379
        /* 7.7.3.11 */
9380
14
        { &hf_oran_beamid_ap3,
9381
14
          { "beamIdAP3", "oran_fh_cus.beamIdAP3",
9382
14
            FT_UINT16, BASE_DEC,
9383
14
            NULL, 0x7f,
9384
14
            "beam id to be used for antenna port 3", HFILL}
9385
14
        },
9386
9387
        /* 7.7.10.3a */
9388
14
        { &hf_oran_port_list_index,
9389
14
          { "portListIndex", "oran_fh_cus.portListIndex",
9390
14
            FT_UINT8, BASE_DEC,
9391
14
            NULL, 0x0,
9392
14
            "the index of an eAxC_ID in the port-list", HFILL}
9393
14
        },
9394
9395
14
        { &hf_oran_alpn_per_sym,
9396
14
          { "alpnPerSym", "oran_fh_cus.alpnPerSym",
9397
14
            FT_UINT8, BASE_HEX,
9398
14
            VALS(alpn_per_sym_vals), 0x80,
9399
14
            NULL, HFILL}
9400
14
        },
9401
14
        { &hf_oran_ant_dmrs_snr,
9402
14
          { "antDmrsSnr", "oran_fh_cus.antDmrsSnr",
9403
14
            FT_UINT8, BASE_HEX,
9404
14
            VALS(ant_dmrs_snr_vals), 0x40,
9405
14
            NULL, HFILL}
9406
14
        },
9407
9408
        /* 7.7.24.6 */
9409
14
        { &hf_oran_user_group_size,
9410
14
          { "userGroupSize", "oran_fh_cus.userGroupSize",
9411
14
            FT_UINT8, BASE_DEC,
9412
14
            NULL, 0x1f,
9413
14
            "number of UE data layers in the user group identified by userGroupId", HFILL}
9414
14
        },
9415
        /* 7.7.24.7 */
9416
14
        { &hf_oran_user_group_id,
9417
14
          { "userGroupId", "oran_fh_cus.userGroupId",
9418
14
            FT_UINT8, BASE_DEC,
9419
14
            NULL, 0x0,
9420
14
            "indicates user group described by the section", HFILL}
9421
14
        },
9422
        /* 7.7.24.8 */
9423
14
        { &hf_oran_entry_type,
9424
14
          { "entryType", "oran_fh_cus.entryType",
9425
14
            FT_UINT8, BASE_DEC,
9426
14
            VALS(entry_type_vals), 0xe0,
9427
14
            "indicates format of the entry", HFILL}
9428
14
        },
9429
        /* 7.7.24.9 */
9430
14
        { &hf_oran_dmrs_port_number,
9431
14
          { "dmrsPortNumber", "oran_fh_cus.dmrsPortNumber",
9432
14
            FT_UINT8, BASE_DEC,
9433
14
            NULL, 0x1f,
9434
14
            "DMRS antenna port number for the associated ueId", HFILL}
9435
14
        },
9436
        /* 7.7.24.10 */
9437
14
        { &hf_oran_ueid_reset,
9438
14
          { "ueidReset", "oran_fh_cus.ueidReset",
9439
14
            FT_BOOLEAN, 8,
9440
14
            TFS(&tfs_ueid_reset), 0x80,
9441
14
            "same UEID as the previous slot", HFILL}
9442
14
        },
9443
        /* 7.7.24.11 */
9444
14
        { &hf_oran_dmrs_symbol_mask,
9445
14
          { "dmrsSymbolMask", "oran_fh_cus.dmrsSymbolMask",
9446
14
            FT_UINT16, BASE_HEX,
9447
14
            NULL, 0x3fff,
9448
14
            "symbols within the slot containing DMRS", HFILL}
9449
14
        },
9450
14
        { &hf_oran_dmrs_symbol_mask_s13,
9451
14
          { "symbol 13", "oran_fh_cus.dmrsSymbolMask.symbol-13",
9452
14
            FT_BOOLEAN, 16,
9453
14
            TFS(&tfs_present_not_present), 0x2000,
9454
14
            NULL, HFILL}
9455
14
        },
9456
14
        { &hf_oran_dmrs_symbol_mask_s12,
9457
14
          { "symbol 12", "oran_fh_cus.dmrsSymbolMask.symbol-12",
9458
14
            FT_BOOLEAN, 16,
9459
14
            TFS(&tfs_present_not_present), 0x1000,
9460
14
            NULL, HFILL}
9461
14
        },
9462
14
        { &hf_oran_dmrs_symbol_mask_s11,
9463
14
          { "symbol 11", "oran_fh_cus.dmrsSymbolMask.symbol-11",
9464
14
            FT_BOOLEAN, 16,
9465
14
            TFS(&tfs_present_not_present), 0x0800,
9466
14
            NULL, HFILL}
9467
14
        },
9468
14
        { &hf_oran_dmrs_symbol_mask_s10,
9469
14
          { "symbol 10", "oran_fh_cus.dmrsSymbolMask.symbol-10",
9470
14
            FT_BOOLEAN, 16,
9471
14
            TFS(&tfs_present_not_present), 0x0400,
9472
14
            NULL, HFILL}
9473
14
        },
9474
14
        { &hf_oran_dmrs_symbol_mask_s9,
9475
14
          { "symbol  9", "oran_fh_cus.dmrsSymbolMask.symbol-9",
9476
14
            FT_BOOLEAN, 16,
9477
14
            TFS(&tfs_present_not_present), 0x0200,
9478
14
            NULL, HFILL}
9479
14
        },
9480
14
        { &hf_oran_dmrs_symbol_mask_s8,
9481
14
          { "symbol  8", "oran_fh_cus.dmrsSymbolMask.symbol-8",
9482
14
            FT_BOOLEAN, 16,
9483
14
            TFS(&tfs_present_not_present), 0x0100,
9484
14
            NULL, HFILL}
9485
14
        },
9486
14
        { &hf_oran_dmrs_symbol_mask_s7,
9487
14
          { "symbol  7", "oran_fh_cus.dmrsSymbolMask.symbol-7",
9488
14
            FT_BOOLEAN, 16,
9489
14
            TFS(&tfs_present_not_present), 0x0080,
9490
14
            NULL, HFILL}
9491
14
        },
9492
14
        { &hf_oran_dmrs_symbol_mask_s6,
9493
14
          { "symbol  6", "oran_fh_cus.dmrsSymbolMask.symbol-6",
9494
14
            FT_BOOLEAN, 16,
9495
14
            TFS(&tfs_present_not_present), 0x0040,
9496
14
            NULL, HFILL}
9497
14
        },
9498
14
        { &hf_oran_dmrs_symbol_mask_s5,
9499
14
          { "symbol  5", "oran_fh_cus.dmrsSymbolMask.symbol-5",
9500
14
            FT_BOOLEAN, 16,
9501
14
            TFS(&tfs_present_not_present), 0x0020,
9502
14
            NULL, HFILL}
9503
14
        },
9504
14
        { &hf_oran_dmrs_symbol_mask_s4,
9505
14
          { "symbol  4", "oran_fh_cus.dmrsSymbolMask.symbol-4",
9506
14
            FT_BOOLEAN, 16,
9507
14
            TFS(&tfs_present_not_present), 0x0010,
9508
14
            NULL, HFILL}
9509
14
        },
9510
14
        { &hf_oran_dmrs_symbol_mask_s3,
9511
14
          { "symbol  3", "oran_fh_cus.dmrsSymbolMask.symbol-3",
9512
14
            FT_BOOLEAN, 16,
9513
14
            TFS(&tfs_present_not_present), 0x0008,
9514
14
            NULL, HFILL}
9515
14
        },
9516
14
        { &hf_oran_dmrs_symbol_mask_s2,
9517
14
          { "symbol  2", "oran_fh_cus.dmrsSymbolMask.symbol-2",
9518
14
            FT_BOOLEAN, 16,
9519
14
            TFS(&tfs_present_not_present), 0x0004,
9520
14
            NULL, HFILL}
9521
14
        },
9522
14
        { &hf_oran_dmrs_symbol_mask_s1,
9523
14
          { "symbol  1", "oran_fh_cus.dmrsSymbolMask.symbol-1",
9524
14
            FT_BOOLEAN, 16,
9525
14
            TFS(&tfs_present_not_present), 0x0002,
9526
14
            NULL, HFILL}
9527
14
        },
9528
14
        { &hf_oran_dmrs_symbol_mask_s0,
9529
14
          { "symbol  0", "oran_fh_cus.dmrsSymbolMask.symbol-0",
9530
14
            FT_BOOLEAN, 16,
9531
14
            TFS(&tfs_present_not_present), 0x0001,
9532
14
            NULL, HFILL}
9533
14
        },
9534
9535
        /* 7.7.24.12 */
9536
14
        { &hf_oran_scrambling,
9537
14
          { "scrambling", "oran_fh_cus.scrambling",
9538
14
            FT_UINT16, BASE_HEX,
9539
14
            NULL, 0x0,
9540
14
            "used to calculate the seed value required to initialize pseudo-random generator", HFILL}
9541
14
        },
9542
        /* 7.7.24.13 */
9543
14
        { &hf_oran_nscid,
9544
14
          { "nscid", "oran_fh_cus.nscid",
9545
14
            FT_UINT8, BASE_HEX,
9546
14
            NULL, 0x80,
9547
14
            "used to calculate the seed value for pseudo-random generator", HFILL}
9548
14
        },
9549
        /* 7.7.24.14 */
9550
14
        { &hf_oran_dtype,
9551
14
          { "dType", "oran_fh_cus.dType",
9552
14
            FT_UINT8, BASE_HEX,
9553
14
            VALS(dtype_vals), 0x40,
9554
14
            "PUSCH DMRS configuration type", HFILL}
9555
14
        },
9556
        /* 7.7.24.15 */
9557
14
        { &hf_oran_cmd_without_data,
9558
14
          { "cmdWithoutData", "oran_fh_cus.cmdWithoutData",
9559
14
            FT_UINT8, BASE_HEX,
9560
14
            NULL, 0x30,
9561
14
            "number of DMRS CDM groups without data", HFILL}
9562
14
        },
9563
        /* 7.7.24.16 */
9564
14
        { &hf_oran_lambda,
9565
14
          { "lambda", "oran_fh_cus.lambda",
9566
14
            FT_UINT8, BASE_HEX,
9567
14
            NULL, 0x0c,
9568
14
            NULL, HFILL}
9569
14
        },
9570
        /* 7.7.24.19 */
9571
14
        { &hf_oran_first_prb,
9572
14
          { "firstPrb", "oran_fh_cus.firstPrb",
9573
14
            FT_UINT16, BASE_DEC,
9574
14
            NULL, 0x03fe,
9575
14
            NULL, HFILL}
9576
14
        },
9577
        /* 7.7.24.20 */
9578
14
        { &hf_oran_last_prb,
9579
14
          { "lastPrb", "oran_fh_cus.lastPrb",
9580
14
            FT_UINT16, BASE_DEC,
9581
14
            NULL, 0x01ff,
9582
14
            NULL, HFILL}
9583
14
        },
9584
9585
        /* 7.7.24.17 */
9586
        /* TODO: add value_string */
9587
14
        { &hf_oran_low_papr_type,
9588
14
          { "lowPaprType", "oran_fh_cus.lowPaprType",
9589
14
            FT_UINT8, BASE_HEX,
9590
14
            VALS(papr_type_vals), 0x30,
9591
14
            NULL, HFILL}
9592
14
        },
9593
        /* 7.7.24.18 */
9594
14
        { &hf_oran_hopping_mode,
9595
14
          { "hoppingMode", "oran_fh_cus.hoppingMode",
9596
14
            FT_UINT8, BASE_HEX,
9597
14
            VALS(hopping_mode_vals), 0x0c,
9598
14
            NULL, HFILL}
9599
14
        },
9600
9601
14
        { &hf_oran_tx_win_for_on_air_symbol_l,
9602
14
          { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
9603
14
            FT_UINT8, BASE_DEC,
9604
14
            NULL, 0xf0,
9605
14
            NULL, HFILL}
9606
14
        },
9607
14
        { &hf_oran_tx_win_for_on_air_symbol_r,
9608
14
          { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
9609
14
            FT_UINT8, BASE_DEC,
9610
14
            NULL, 0x0f,
9611
14
            NULL, HFILL}
9612
14
        },
9613
        /* 7.7.26.2 */
9614
14
        { &hf_oran_num_fo_fb,
9615
14
          { "numFoFb", "oran_fh_cus.numFoFb",
9616
14
            FT_UINT8, BASE_DEC,
9617
14
            NULL, 0x7f,
9618
14
            "number of frequency offset feedback", HFILL}
9619
14
        },
9620
        /* 7.7.26.3 */
9621
14
        { &hf_oran_freq_offset_fb,
9622
14
          { "freqOffsetFb", "oran_fh_cus.freqOffsetFb",
9623
14
            FT_UINT16, BASE_HEX_DEC | BASE_RANGE_STRING,
9624
14
            RVALS(freq_offset_fb_values), 0x0,
9625
14
            "UE frequency offset feedback", HFILL}
9626
14
        },
9627
9628
        /* 7.7.28.2 */
9629
14
        { &hf_oran_num_ue_sinr_rpt,
9630
14
          { "numUeSinrRpt", "oran_fh_cus.numUeSinrRpt",
9631
14
            FT_UINT8, BASE_DEC,
9632
14
            NULL, 0x1f,
9633
14
            "number of sinr reported UEs {1 - 12}", HFILL}
9634
14
        },
9635
9636
        /* 7.5.2.19 */
9637
14
        { &hf_oran_num_sinr_per_prb,
9638
14
          { "numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
9639
14
            FT_UINT8, BASE_DEC,
9640
14
            VALS(num_sinr_per_prb_vals), 0x70,
9641
14
            "number of SINR values per PRB", HFILL}
9642
14
        },
9643
14
        { &hf_oran_num_sinr_per_prb_right,
9644
14
          { "numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
9645
14
            FT_UINT8, BASE_DEC,
9646
14
            VALS(num_sinr_per_prb_vals), 0x07,
9647
14
            "number of SINR values per PRB", HFILL}
9648
14
        },
9649
9650
        /* 7.5.3.68 */
9651
14
        { &hf_oran_sinr_value,
9652
14
          { "sinrValue", "oran_fh_cus.sinrValue",
9653
14
            FT_FLOAT, BASE_NONE,
9654
14
            NULL, 0x0,
9655
14
            NULL, HFILL}
9656
14
        },
9657
9658
14
        { &hf_oran_measurement_report,
9659
14
          { "Measurement Report", "oran_fh_cus.measurement-report",
9660
14
            FT_STRING, BASE_NONE,
9661
14
            NULL, 0x0,
9662
14
            NULL, HFILL}
9663
14
        },
9664
        /* 7.5.3.57 */
9665
14
        { &hf_oran_mf,
9666
14
          { "mf", "oran_fh_cus.mf",
9667
14
            FT_BOOLEAN, 8,
9668
14
            TFS(&measurement_flag_tfs), 0x80,
9669
14
            "measurement flag", HFILL}
9670
14
        },
9671
        /* 7.5.3.59 */
9672
14
        { &hf_oran_meas_data_size,
9673
14
          { "measDataSize", "oran_fh_cus.measDataSize",
9674
14
            FT_UINT16, BASE_DEC,
9675
14
            NULL, 0x0,
9676
14
            "measurement data size (in words)", HFILL}
9677
14
        },
9678
9679
        /* 7.5.3.58 */
9680
14
        { &hf_oran_meas_type_id,
9681
14
          { "measTypeId", "oran_fh_cus.measTypeId",
9682
14
            FT_UINT8, BASE_DEC,
9683
14
            VALS(meas_type_id_vals), 0x7F,
9684
14
            "measurement report type identifier", HFILL}
9685
14
        },
9686
        /* 7.5.3.66 */
9687
14
        { &hf_oran_num_elements,
9688
14
          { "numElements", "oran_fh_cus.numElements",
9689
14
            FT_UINT8, BASE_DEC,
9690
14
            NULL, 0x0,
9691
14
            "measurement report type identifier", HFILL}
9692
14
        },
9693
        /* 7.5.3.60 */
9694
14
        { &hf_oran_ue_tae,
9695
14
          { "ueTae", "oran_fh_cus.ueTae",
9696
14
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
9697
14
            RVALS(freq_offset_fb_values), 0x0,
9698
14
            "UE Timing Advance Error", HFILL}
9699
14
        },
9700
        /* 7.5.3.61 */
9701
14
        { &hf_oran_ue_layer_power,
9702
14
          { "ueLayerPower", "oran_fh_cus.ueLayerPower",
9703
14
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
9704
14
            RVALS(freq_offset_fb_values), 0x0,
9705
14
            "UE Layer Power", HFILL}
9706
14
        },
9707
9708
        /* 7.5.3.62 */
9709
14
        { &hf_oran_ue_freq_offset,
9710
14
          { "ueFreqOffset", "oran_fh_cus.ueFreqOffset",
9711
14
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
9712
14
            RVALS(freq_offset_fb_values), 0x0,
9713
14
            "UE frequency offset", HFILL}
9714
14
        },
9715
        /* 7.5.3.63 */
9716
14
        { &hf_oran_ipn_power,
9717
14
          { "ipnPower", "oran_fh_cus.ipnPower",
9718
14
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
9719
14
            RVALS(freq_offset_fb_values), 0x0,
9720
14
            "Interference plus Noise power", HFILL}
9721
14
        },
9722
        /* 7.5.3.64 */
9723
14
        { &hf_oran_ant_dmrs_snr_val,
9724
14
          { "antDmrsSnrVal", "oran_fh_cus.antDmrsSnrVal",
9725
14
            FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
9726
14
            RVALS(freq_offset_fb_values), 0x0,
9727
14
            "antenna DMRS-SNR", HFILL}
9728
14
        },
9729
9730
14
        { &hf_oran_measurement_command,
9731
14
          { "Measurement Command", "oran_fh_cus.measurement-command",
9732
14
            FT_STRING, BASE_NONE,
9733
14
            NULL, 0x0,
9734
14
            NULL, HFILL}
9735
14
        },
9736
9737
        /* 7.5.27.2 */
9738
14
        { &hf_oran_beam_type,
9739
14
         {"beamType", "oran_fh_cus.beamType",
9740
14
          FT_UINT16, BASE_DEC,
9741
14
          VALS(beam_type_vals), 0xc0,
9742
14
          NULL,
9743
14
          HFILL}
9744
14
        },
9745
        /* 7.5.3.65 */
9746
14
        { &hf_oran_meas_cmd_size,
9747
14
         {"measCmdSize", "oran_fh_cus.measCmdSize",
9748
14
          FT_UINT16, BASE_DEC,
9749
14
          NULL, 0x0,
9750
14
          "measurement command size in words",
9751
14
          HFILL}
9752
14
        },
9753
9754
14
        { &hf_oran_symbol_reordering_layer,
9755
14
          { "Layer", "oran_fh_cus.layer",
9756
14
            FT_STRING, BASE_NONE,
9757
14
            NULL, 0x0,
9758
14
            NULL, HFILL}
9759
14
        },
9760
14
        { &hf_oran_dmrs_entry,
9761
14
          { "Entry", "oran_fh_cus.dmrs-entry",
9762
14
            FT_STRING, BASE_NONE,
9763
14
            NULL, 0x0,
9764
14
            NULL, HFILL}
9765
14
        },
9766
9767
        /* 7.7.29.3 */
9768
14
        { &hf_oran_cd_scg_size,
9769
14
          {"cdScgSize", "oran_fh_cus.cdScgSize",
9770
14
            FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
9771
14
            RVALS(cd_scg_size_vals), 0x0f,
9772
14
            "Cyclic delay subcarrier group size",
9773
14
            HFILL}
9774
14
        },
9775
        /* 7.7.29.4 */
9776
14
        { &hf_oran_cd_scg_phase_step,
9777
14
          {"cdScgPhaseStep", "oran_fh_cus.cdScgPhaseStep",
9778
14
            FT_INT8, BASE_DEC,
9779
14
            NULL, 0x0,
9780
14
            "Cyclic delay subcarrier group phase step",
9781
14
            HFILL}
9782
14
        },
9783
9784
14
        { &hf_oran_sinr_prb,
9785
14
          { "PRB", "oran_fh_cus.sinr.prb",
9786
14
            FT_STRING, BASE_NONE,
9787
14
            NULL, 0x0,
9788
14
            NULL, HFILL}
9789
14
        },
9790
        /* 7.5.2.20 */
9791
14
        { &hf_oran_oru_control_sinr_slot_mask_id,
9792
14
          {"oruControlSinrSlotMaskId", "oran_fh_cus.oruControlSinrSlotMaskId",
9793
14
            FT_UINT8, BASE_DEC,
9794
14
            NULL, 0x1f,
9795
14
            "SINR time resolution",
9796
14
            HFILL}
9797
14
        },
9798
        /* 7.7.24.21 */
9799
14
        { &hf_oran_pos_meas,
9800
14
          {"posMeas", "oran_fh_cus.posMeas",
9801
14
            FT_BOOLEAN, 8,
9802
14
            TFS(&tfs_report_no_report_pos_meas), 0x40,
9803
14
            "Positioning measurement report request",
9804
14
            HFILL}
9805
14
        },
9806
9807
        /* 7.5.3.69 */
9808
14
        { &hf_oran_ue_radial_speed,
9809
14
          {"ueRadialSpeed", "oran_fh_cus.ueRadialSpeed",
9810
14
            FT_UINT16, BASE_DEC,
9811
14
            NULL, 0x0,
9812
14
            "UE radial speed",
9813
14
            HFILL}
9814
14
        },
9815
        /* 7.5.3.70 */
9816
14
        { &hf_oran_ue_az_aoa,
9817
14
          {"ueAzAoa", "oran_fh_cus.ueAzAoa",
9818
14
            FT_UINT16, BASE_DEC,
9819
14
            NULL, 0x0,
9820
14
            "UE azimuth angle of arrival",
9821
14
            HFILL}
9822
14
        },
9823
        /* 7.5.3.71 */
9824
14
        { &hf_oran_ue_ze_aoa,
9825
14
          {"ueZeAoa", "oran_fh_cus.ueZeAoa",
9826
14
            FT_UINT16, BASE_DEC,
9827
14
            NULL, 0x0,
9828
14
            "UE zenith angle of arrival",
9829
14
            HFILL}
9830
14
        },
9831
        /* 7.5.3.72 */
9832
14
        { &hf_oran_ue_pos_toa_offset,
9833
14
          {"uePosToaOffset", "oran_fh_cus.uePosToaOffset",
9834
14
            FT_UINT16, BASE_DEC,
9835
14
            NULL, 0x0,
9836
14
            "UE positioning time of arrival offset",
9837
14
            HFILL}
9838
14
        },
9839
9840
9841
14
        { &hf_oran_c_section_common,
9842
14
          { "Common Section", "oran_fh_cus.c-plane.section.common",
9843
14
            FT_STRING, BASE_NONE,
9844
14
            NULL, 0x0,
9845
14
            NULL, HFILL}
9846
14
        },
9847
14
        { &hf_oran_c_section,
9848
14
          { "Section", "oran_fh_cus.c-plane.section",
9849
14
            FT_STRING, BASE_NONE,
9850
14
            NULL, 0x0,
9851
14
            NULL, HFILL}
9852
14
        },
9853
14
        { &hf_oran_u_section,
9854
14
          { "Section", "oran_fh_cus.u-plane.section",
9855
14
            FT_STRING, BASE_NONE,
9856
14
            NULL, 0x0,
9857
14
            NULL, HFILL}
9858
14
        },
9859
9860
        /* Link back to UL C-plane where udCompHdr was recorded */
9861
14
        { &hf_oran_ul_cplane_ud_comp_hdr_frame,
9862
14
          { "C-Plane UL udCompHdr frame", "oran_fh_cus.ul-cplane.udCompHdr",
9863
14
            FT_FRAMENUM, BASE_NONE,
9864
14
            FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
9865
14
            NULL, HFILL}
9866
14
        },
9867
9868
        /* Reassembly */
9869
14
        { &hf_oran_fragment,
9870
14
          { "Fragment", "oran_fh_cus.fragment", FT_FRAMENUM, BASE_NONE,
9871
14
            NULL, 0x0, NULL, HFILL }},
9872
14
        { &hf_oran_fragments,
9873
14
          { "Fragments", "oran_fh_cus.fragments", FT_BYTES, BASE_NONE,
9874
14
            NULL, 0x0, NULL, HFILL }},
9875
14
        { &hf_oran_fragment_overlap,
9876
14
          { "Fragment overlap", "oran_fh_cus.fragment.overlap", FT_BOOLEAN, BASE_NONE,
9877
14
            NULL, 0x0, "Fragment overlaps with other fragments", HFILL }},
9878
14
        { &hf_oran_fragment_overlap_conflict,
9879
14
          { "Conflicting data in fragment overlap", "oran_fh_cus.fragment.overlap.conflict",
9880
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9881
14
            "Overlapping fragments contained conflicting data", HFILL }},
9882
14
        { &hf_oran_fragment_multiple_tails,
9883
14
          { "Multiple tail fragments found", "oran_fh_cus.fragment.multipletails",
9884
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9885
14
            "Several tails were found when defragmenting the packet", HFILL }},
9886
14
        { &hf_oran_fragment_too_long_fragment,
9887
14
          { "Fragment too long", "oran_fh_cus.fragment.toolongfragment",
9888
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
9889
14
            "Fragment contained data past end of packet", HFILL }},
9890
14
        { &hf_oran_fragment_error,
9891
14
          { "Defragmentation error", "oran_fh_cus.fragment.error", FT_FRAMENUM, BASE_NONE,
9892
14
            NULL, 0x0, "Defragmentation error due to illegal fragments", HFILL }},
9893
14
        { &hf_oran_fragment_count,
9894
14
          { "Fragment count", "oran_fh_cus.fragment.count", FT_UINT32, BASE_DEC,
9895
14
            NULL, 0x0, NULL, HFILL }},
9896
14
        { &hf_oran_reassembled_in,
9897
14
          { "Reassembled payload in frame", "oran_fh_cus.reassembled_in", FT_FRAMENUM, BASE_NONE,
9898
14
          NULL, 0x0, "This payload packet is reassembled in this frame", HFILL }},
9899
14
        { &hf_oran_reassembled_length,
9900
14
          { "Reassembled payload length", "oran_fh_cus.reassembled.length", FT_UINT32, BASE_DEC,
9901
14
            NULL, 0x0, "The total length of the reassembled payload", HFILL }},
9902
14
        { &hf_oran_reassembled_data,
9903
14
          { "Reassembled data", "oran_fh_cus.reassembled.data", FT_BYTES, BASE_NONE,
9904
14
            NULL, 0x0, "The reassembled payload", HFILL }},
9905
9906
14
        { &hf_oran_payload,
9907
14
          { "Payload", "oran_fh_cus.payload", FT_BYTES, BASE_SHOW_ASCII_PRINTABLE,
9908
14
            NULL, 0x0, "Complete or reassembled payload", HFILL }},
9909
14
    };
9910
9911
    /* Setup protocol subtree array */
9912
14
    static int *ett[] = {
9913
14
        &ett_oran,
9914
14
        &ett_oran_ecpri_pcid,
9915
14
        &ett_oran_ecpri_rtcid,
9916
14
        &ett_oran_ecpri_seqid,
9917
14
        &ett_oran_section_type,
9918
14
        &ett_oran_u_timing,
9919
14
        &ett_oran_u_section,
9920
14
        &ett_oran_u_prb,
9921
14
        &ett_oran_section,
9922
14
        &ett_oran_iq,
9923
14
        &ett_oran_bfw_bundle,
9924
14
        &ett_oran_bfw,
9925
14
        &ett_oran_frequency_range,
9926
14
        &ett_oran_prb_cisamples,
9927
14
        &ett_oran_cisample,
9928
14
        &ett_oran_udcomphdr,
9929
14
        &ett_oran_udcompparam,
9930
14
        &ett_oran_cicomphdr,
9931
14
        &ett_oran_cicompparam,
9932
14
        &ett_oran_bfwcomphdr,
9933
14
        &ett_oran_bfwcompparam,
9934
14
        &ett_oran_ext19_port,
9935
14
        &ett_oran_prb_allocation,
9936
14
        &ett_oran_punc_pattern,
9937
14
        &ett_oran_bfacomphdr,
9938
14
        &ett_oran_modcomp_param_set,
9939
14
        &ett_oran_st4_cmd_header,
9940
14
        &ett_oran_st4_cmd,
9941
14
        &ett_oran_sym_prb_pattern,
9942
14
        &ett_oran_measurement_report,
9943
14
        &ett_oran_measurement_command,
9944
14
        &ett_oran_sresmask,
9945
14
        &ett_oran_c_section_common,
9946
14
        &ett_oran_c_section,
9947
14
        &ett_oran_remask,
9948
14
        &ett_oran_mc_scale_remask,
9949
14
        &ett_oran_symbol_reordering_layer,
9950
14
        &ett_oran_dmrs_entry,
9951
14
        &ett_oran_dmrs_symbol_mask,
9952
14
        &ett_oran_symbol_mask,
9953
14
        &ett_oran_active_beamspace_coefficient_mask,
9954
14
        &ett_oran_sinr_prb,
9955
9956
14
        &ett_oran_fragment,
9957
14
        &ett_oran_fragments
9958
14
    };
9959
9960
14
    static int *ext_ett[HIGHEST_EXTTYPE];
9961
420
    for (unsigned extno=0; extno<HIGHEST_EXTTYPE; extno++) {
9962
406
        ext_ett[extno] = &ett_oran_c_section_extension[extno];
9963
406
    }
9964
9965
14
    expert_module_t* expert_oran;
9966
9967
14
    static ei_register_info ei[] = {
9968
14
        { &ei_oran_unsupported_bfw_compression_method, { "oran_fh_cus.unsupported_bfw_compression_method", PI_UNDECODED, PI_WARN, "Unsupported BFW Compression Method", EXPFILL }},
9969
14
        { &ei_oran_invalid_sample_bit_width, { "oran_fh_cus.invalid_sample_bit_width", PI_UNDECODED, PI_ERROR, "Unsupported sample bit width", EXPFILL }},
9970
14
        { &ei_oran_reserved_numBundPrb, { "oran_fh_cus.reserved_numBundPrb", PI_MALFORMED, PI_ERROR, "Reserved value 0 for numBundPrb seen - not valid", EXPFILL }},
9971
14
        { &ei_oran_extlen_wrong, { "oran_fh_cus.extlen_wrong", PI_MALFORMED, PI_ERROR, "extlen doesn't match number of dissected bytes", EXPFILL }},
9972
14
        { &ei_oran_invalid_eaxc_bit_width, { "oran_fh_cus.invalid_eaxc_bit_width", PI_UNDECODED, PI_ERROR, "Inconsistent eAxC bit width", EXPFILL }},
9973
14
        { &ei_oran_extlen_zero, { "oran_fh_cus.extlen_zero", PI_MALFORMED, PI_ERROR, "extlen value of 0 is reserved", EXPFILL }},
9974
14
        { &ei_oran_rbg_size_reserved, { "oran_fh_cus.rbg_size_reserved", PI_MALFORMED, PI_ERROR, "rbgSize value of 0 is reserved", EXPFILL }},
9975
14
        { &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 }},
9976
14
        { &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 }},
9977
14
        { &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 }},
9978
14
        { &ei_oran_st8_nackid, { "oran_fh_cus.st8_nackid", PI_SEQUENCE, PI_WARN, "operation for this ackId failed", EXPFILL }},
9979
14
        { &ei_oran_st4_no_cmds, { "oran_fh_cus.st4_nackid", PI_MALFORMED, PI_ERROR, "Not valid for ST4 to carry no commands", EXPFILL }},
9980
14
        { &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 }},
9981
14
        { &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 }},
9982
14
        { &ei_oran_st4_unknown_cmd, { "oran_fh_cus.st4_unknown_cmd", PI_MALFORMED, PI_ERROR, "ST4 cmd with unknown command code", EXPFILL }},
9983
14
        { &ei_oran_mcot_out_of_range, { "oran_fh_cus.mcot_out_of_range", PI_MALFORMED, PI_ERROR, "MCOT should be 1-10", EXPFILL }},
9984
14
        { &ei_oran_se10_unknown_beamgrouptype, { "oran_fh_cus.se10_unknown_beamgrouptype", PI_MALFORMED, PI_WARN, "SE10 - unknown BeamGroupType value", EXPFILL }},
9985
14
        { &ei_oran_se10_not_allowed, { "oran_fh_cus.se10_not_allowed", PI_MALFORMED, PI_WARN, "SE10 - type not allowed for sectionType", EXPFILL }},
9986
14
        { &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 }},
9987
14
        { &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 }},
9988
14
        { &ei_oran_unhandled_se, { "oran_fh_cus.se_not_handled", PI_UNDECODED, PI_WARN, "SE not recognised/handled by dissector", EXPFILL }},
9989
14
        { &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 }},
9990
14
        { &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 }},
9991
14
        { &ei_oran_version_unsupported, { "oran_fh_cus.version_unsupported", PI_UNDECODED, PI_WARN, "Protocol version unsupported", EXPFILL }},
9992
14
        { &ei_oran_laa_msg_type_unsupported, { "oran_fh_cus.laa_msg_type_unsupported", PI_UNDECODED, PI_WARN, "laaMsgType unsupported", EXPFILL }},
9993
14
        { &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 }},
9994
14
        { &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 }},
9995
14
        { &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 }},
9996
14
        { &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 }},
9997
14
        { &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 }},
9998
14
        { &ei_oran_acknack_no_request, { "oran_fh_cus.acknack_no_request", PI_SEQUENCE, PI_WARN, "Have ackNackId response, but no request", EXPFILL }},
9999
14
        { &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 }},
10000
14
        { &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 }},
10001
14
        { &ei_oran_lastRbdid_out_of_range, { "oran_fh_cus.lastrbdid_out_of_range", PI_MALFORMED, PI_WARN, "SE 6 has bad rbgSize", EXPFILL }},
10002
14
        { &ei_oran_rbgMask_beyond_last_rbdid, { "oran_fh_cus.rbgmask_beyond_lastrbdid", PI_MALFORMED, PI_WARN, "rbgMask has bits set beyond lastRbgId", EXPFILL }},
10003
14
        { &ei_oran_unexpected_measTypeId, { "oran_fh_cus.unexpected_meastypeid", PI_MALFORMED, PI_WARN, "unexpected measTypeId", EXPFILL }},
10004
14
        { &ei_oran_unsupported_compression_method, { "oran_fh_cus.compression_type_unsupported", PI_UNDECODED, PI_WARN, "Unsupported compression type", EXPFILL }},
10005
14
        { &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 }},
10006
14
        { &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 }},
10007
14
        { &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 }},
10008
14
        { &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 }},
10009
14
        { &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 }},
10010
14
        { &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 }},
10011
14
        { &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 }},
10012
14
        { &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 }},
10013
14
        { &ei_oran_num_sinr_per_prb_unknown, { "oran_fh_cus.unexpected_num_sinr_per_prb", PI_MALFORMED, PI_WARN, "invalid numSinrPerPrb value", EXPFILL }},
10014
14
        { &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 }},
10015
14
        { &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 }},
10016
14
        { &ei_oran_port_list_index_zero, { "oran_fh_cus.port_list_index.zero", PI_MALFORMED, PI_WARN, "portListIndex should not be zero", EXPFILL }},
10017
14
        { &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 }},
10018
14
        { &ei_oran_reserved_not_zero, { "oran_fh_cus.reserved_not_zero", PI_MALFORMED, PI_WARN, "Reserved field is not zero", EXPFILL }}
10019
14
    };
10020
10021
    /* Register the protocol name and description */
10022
14
    proto_oran = proto_register_protocol("O-RAN Fronthaul CUS", "O-RAN FH CUS", "oran_fh_cus");
10023
10024
    /* Allow dissector to find be found by name. */
10025
14
    register_dissector("oran_fh_cus", dissect_oran, proto_oran);
10026
10027
    /* Register the tap name. */
10028
14
    oran_tap = register_tap("oran-fh-cus");
10029
10030
    /* Required function calls to register the header fields and subtrees */
10031
14
    proto_register_field_array(proto_oran, hf, array_length(hf));
10032
14
    proto_register_subtree_array(ett, array_length(ett));
10033
14
    proto_register_subtree_array(ext_ett, array_length(ext_ett));
10034
10035
10036
14
    expert_oran = expert_register_protocol(proto_oran);
10037
14
    expert_register_field_array(expert_oran, ei, array_length(ei));
10038
10039
10040
    /* Preferences */
10041
14
    module_t * oran_module = prefs_register_protocol(proto_oran, NULL);
10042
10043
    /* prefs_register_static_text_preference(oran_module, "oran.stream", "", ""); */
10044
10045
    /* Register bit width/compression preferences separately by direction. */
10046
14
    prefs_register_uint_preference(oran_module, "oran.du_port_id_bits", "DU Port ID bits [a]",
10047
14
        "The bit width of DU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_du_port_id_bits);
10048
14
    prefs_register_uint_preference(oran_module, "oran.bandsector_id_bits", "BandSector ID bits [b]",
10049
14
        "The bit width of BandSector ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_bandsector_id_bits);
10050
14
    prefs_register_uint_preference(oran_module, "oran.cc_id_bits", "CC ID bits [c]",
10051
14
        "The bit width of CC ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_cc_id_bits);
10052
14
    prefs_register_uint_preference(oran_module, "oran.ru_port_id_bits", "RU Port ID bits [d]",
10053
14
        "The bit width of RU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_ru_port_id_bits);
10054
10055
14
    prefs_register_static_text_preference(oran_module, "oran.ul", "", "");
10056
10057
    /* Uplink userplane */
10058
14
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_up", "IQ Bitwidth Uplink",
10059
14
        "The bit width of a sample in the Uplink (if no udcompHdr and no C-Plane)", 10, &pref_sample_bit_width_uplink);
10060
14
    prefs_register_enum_preference(oran_module, "oran.ud_comp_up", "Uplink User Data Compression",
10061
14
        "Uplink User Data Compression (if no udcompHdr and no C-Plane)", &pref_iqCompressionUplink, ul_compression_options, false);
10062
14
    prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_up", "udCompHdr field is present for uplink",
10063
14
        "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
10064
14
        "configuration of the O-RU. This preference instructs the dissector to expect "
10065
14
        "this field to be present in uplink messages",
10066
14
        &pref_includeUdCompHeaderUplink, udcomphdr_present_options, false);
10067
14
    prefs_register_bool_preference(oran_module, "oran.ignore_cplane_ul_udcomphdr", "Ignore compression settings from C-plane",
10068
14
        "When set, override udCompHdr from UL C-Plane with compression method and width configured here", &pref_override_ul_compression);
10069
14
    prefs_register_uint_preference(oran_module, "oran.ul_slot_us_limit", "Microseconds allowed for UL tx in symbol",
10070
14
        "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",
10071
14
        10, &us_allowed_for_ul_in_symbol);
10072
10073
10074
10075
14
    prefs_register_static_text_preference(oran_module, "oran.dl", "", "");
10076
10077
    /* Downlink userplane */
10078
14
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_down", "IQ Bitwidth Downlink",
10079
14
        "The bit width of a sample in the Downlink (if no udcompHdr)", 10, &pref_sample_bit_width_downlink);
10080
14
    prefs_register_enum_preference(oran_module, "oran.ud_comp_down", "Downlink User Data Compression",
10081
14
        "Downlink User Data Compression", &pref_iqCompressionDownlink, dl_compression_options, false);
10082
14
    prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_down", "udCompHdr field is present for downlink",
10083
14
        "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
10084
14
        "configuration of the O-RU. This preference instructs the dissector to expect "
10085
14
        "this field to be present in downlink messages",
10086
14
        &pref_includeUdCompHeaderDownlink, udcomphdr_present_options, false);
10087
10088
14
    prefs_register_static_text_preference(oran_module, "oran.sinr", "", "");
10089
10090
    /* SINR */
10091
14
    prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_sinr", "IQ Bitwidth SINR",
10092
14
        "The bit width of a sample in SINR", 10, &pref_sample_bit_width_sinr);
10093
14
    prefs_register_enum_preference(oran_module, "oran.ud_comp_sinr", "SINR Compression",
10094
14
        "SINR Compression", &pref_iqCompressionSINR, ul_compression_options, false);
10095
10096
10097
    /* BF-related */
10098
14
    prefs_register_static_text_preference(oran_module, "oran.bf", "", "");
10099
10100
14
    prefs_register_obsolete_preference(oran_module, "oran.num_weights_per_bundle");
10101
10102
14
    prefs_register_uint_preference(oran_module, "oran.num_bf_antennas", "Number of beam weights",
10103
14
        "Number of array elements that BF weights will be provided for", 10, &pref_num_bf_antennas);
10104
10105
14
    prefs_register_obsolete_preference(oran_module, "oran.num_bf_weights");
10106
10107
14
    prefs_register_bool_preference(oran_module, "oran.st6_4byte_alignment_required", "Use 4-byte alignment for ST6 sections",
10108
14
        "Default is 1-byte alignment", &st6_4byte_alignment);
10109
10110
10111
    /* Misc (and will seldom need to be accessed) */
10112
14
    prefs_register_static_text_preference(oran_module, "oran.misc", "", "");
10113
10114
14
    prefs_register_bool_preference(oran_module, "oran.show_iq_samples", "Show IQ Sample values",
10115
14
        "When enabled, for U-Plane frames show each I and Q value in PRB", &pref_showIQSampleValues);
10116
10117
14
    prefs_register_enum_preference(oran_module, "oran.support_udcomplen", "udCompLen supported",
10118
14
        "When enabled, U-Plane messages with relevant compression schemes will include udCompLen",
10119
14
        &pref_support_udcompLen, udcomplen_support_options, false);
10120
10121
14
    prefs_register_uint_preference(oran_module, "oran.rbs_in_uplane_section", "Total RBs in User-Plane data section",
10122
14
        "This is used if numPrbu is signalled as 0", 10, &pref_data_plane_section_total_rbs);
10123
10124
14
    prefs_register_bool_preference(oran_module, "oran.unscaled_iq", "Show unscaled I/Q values",
10125
14
        "", &show_unscaled_values);
10126
10127
14
    prefs_register_bool_preference(oran_module, "oran.attempt_reassembly",
10128
14
                                   "Attempt Radio Transport layer reassembly", "",
10129
14
                                   &do_radio_transport_layer_reassembly);
10130
10131
14
    prefs_register_obsolete_preference(oran_module, "oran.k_antenna_ports");
10132
10133
10134
14
    flow_states_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
10135
14
    flow_results_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
10136
14
    ul_symbol_timing = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
10137
10138
14
    register_init_routine(&oran_init_protocol);
10139
10140
    /* Register reassembly table. */
10141
14
    reassembly_table_register(&oran_reassembly_table,
10142
14
                              &oran_reassembly_table_functions);
10143
14
}
10144
10145
/* Simpler form of proto_reg_handoff_oran which can be used if there are
10146
 * no prefs-dependent registration function calls. */
10147
void
10148
proto_reg_handoff_oran(void)
10149
14
{
10150
14
}
10151
10152
/*
10153
* Editor modelines  -  http://www.wireshark.org/tools/modelines.html
10154
*
10155
* Local Variables:
10156
* c-basic-offset: 4
10157
* tab-width: 8
10158
* indent-tabs-mode: nil
10159
* End:
10160
*
10161
* ex: set shiftwidth=4 tabstop=8 expandtab:
10162
* :indentSize=4:tabSize=8:noTabs=true:
10163
*/