epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-oran.c
blob0d50192b22d978eeb82299ac6f7a9963e26e0876
1 /* packet-oran.c
2 * Routines for O-RAN fronthaul UC-plane dissection
3 * Copyright 2020, Jan Schiefer, Keysight Technologies, Inc.
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Dissector for the O-RAN Fronthaul CUS protocol specification.
14 * See https://specifications.o-ran.org/specifications, WG4, Fronthaul Interfaces Workgroup
15 * The current implementation is based on the ORAN-WG4.CUS.0-v15.00 specification
18 #include <config.h>
20 #include <math.h>
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include <epan/prefs.h>
26 #include <epan/tfs.h>
27 #include <wsutil/array.h>
29 /* N.B. dissector preferences are taking the place of (some) M-plane parameters, so unfortunately it can be
30 * fiddly to get the preferences into a good state to decode a given capture..
31 * TODO:
32 * - tap stats by flow?
33 * - for U-Plane, track back to last C-Plane frame for that eAxC
34 * - use upCompHdr values from C-Plane if not overridden by U-Plane?
35 * N.B. this matching is tricky see 7.8.1 Coupling of C-Plane and U-Plane
36 * - Radio transport layer (eCPRI) fragmentation / reassembly
37 * - Detect/indicate signs of application layer fragmentation?
38 * - Not handling M-plane setting for "little endian byte order" as applied to IQ samples and beam weights
39 * - for section extensions, check more constraints (which other extension types appear with them, order)
40 * - when some section extensions are present, some section header fields are effectively ignored - flag any remaining?
41 * - re-order items (decl and hf definitions) to match spec order
42 * - add hf items to use as roots for remaining subtrees (blurb more useful than filter..)
45 /* Prototypes */
46 void proto_reg_handoff_oran(void);
47 void proto_register_oran(void);
49 /* Initialize the protocol and registered fields */
50 static int proto_oran;
52 static int hf_oran_du_port_id;
53 static int hf_oran_bandsector_id;
54 static int hf_oran_cc_id;
55 static int hf_oran_ru_port_id;
56 static int hf_oran_sequence_id;
57 static int hf_oran_e_bit;
58 static int hf_oran_subsequence_id;
60 static int hf_oran_data_direction;
61 static int hf_oran_payload_version;
62 static int hf_oran_filter_index;
63 static int hf_oran_frame_id;
64 static int hf_oran_subframe_id;
65 static int hf_oran_slot_id;
66 static int hf_oran_slot_within_frame;
67 static int hf_oran_start_symbol_id;
68 static int hf_oran_numberOfSections;
69 static int hf_oran_sectionType;
71 static int hf_oran_udCompHdr;
72 static int hf_oran_udCompHdrIqWidth;
73 static int hf_oran_udCompHdrIqWidth_pref;
74 static int hf_oran_udCompHdrMeth;
75 static int hf_oran_udCompHdrMeth_pref;
76 static int hf_oran_numberOfUEs;
77 static int hf_oran_timeOffset;
78 static int hf_oran_frameStructure_fft;
79 static int hf_oran_frameStructure_subcarrier_spacing;
80 static int hf_oran_cpLength;
81 static int hf_oran_section_id;
82 static int hf_oran_rb;
83 static int hf_oran_symInc;
84 static int hf_oran_startPrbc;
85 static int hf_oran_reMask;
86 static int hf_oran_numPrbc;
87 static int hf_oran_numSymbol;
88 static int hf_oran_ef;
89 static int hf_oran_beamId;
91 static int hf_oran_ciCompHdr;
92 static int hf_oran_ciCompHdrIqWidth;
93 static int hf_oran_ciCompHdrMeth;
94 static int hf_oran_ciCompOpt;
96 static int hf_oran_extension;
97 static int hf_oran_exttype;
98 static int hf_oran_extlen;
100 static int hf_oran_bfw_bundle;
101 static int hf_oran_bfw_bundle_id;
102 static int hf_oran_bfw;
103 static int hf_oran_bfw_i;
104 static int hf_oran_bfw_q;
106 static int hf_oran_ueId;
107 static int hf_oran_freqOffset;
108 static int hf_oran_regularizationFactor;
109 static int hf_oran_laaMsgType;
110 static int hf_oran_laaMsgLen;
111 static int hf_oran_lbtHandle;
112 static int hf_oran_lbtDeferFactor;
113 static int hf_oran_lbtBackoffCounter;
114 static int hf_oran_lbtOffset;
115 static int hf_oran_MCOT;
116 static int hf_oran_lbtMode;
117 static int hf_oran_sfnSfEnd;
118 static int hf_oran_lbtPdschRes;
119 static int hf_oran_sfStatus;
120 static int hf_oran_initialPartialSF;
121 static int hf_oran_lbtDrsRes;
122 static int hf_oran_lbtBufErr;
123 static int hf_oran_lbtTrafficClass;
124 static int hf_oran_lbtCWConfig_H;
125 static int hf_oran_lbtCWConfig_T;
126 static int hf_oran_lbtCWR_Rst;
128 static int hf_oran_reserved;
129 static int hf_oran_reserved_1bit;
130 static int hf_oran_reserved_2bits;
131 static int hf_oran_reserved_4bits;
132 static int hf_oran_reserved_6bits;
133 static int hf_oran_reserved_7bits;
134 static int hf_oran_reserved_8bits;
135 static int hf_oran_reserved_16bits;
136 static int hf_oran_reserved_15bits;
138 static int hf_oran_bundle_offset;
139 static int hf_oran_cont_ind;
141 static int hf_oran_laa_msgtype0_reserved;
143 static int hf_oran_bfwCompHdr;
144 static int hf_oran_bfwCompHdr_iqWidth;
145 static int hf_oran_bfwCompHdr_compMeth;
146 static int hf_oran_symbolId;
147 static int hf_oran_startPrbu;
148 static int hf_oran_numPrbu;
150 static int hf_oran_udCompParam;
151 static int hf_oran_sReSMask;
153 static int hf_oran_bfwCompParam;
155 static int hf_oran_iSample;
156 static int hf_oran_qSample;
158 static int hf_oran_ciCompParam;
160 static int hf_oran_blockScaler;
161 static int hf_oran_compBitWidth;
162 static int hf_oran_compShift;
164 static int hf_oran_repetition;
165 static int hf_oran_rbgSize;
166 static int hf_oran_rbgMask;
167 static int hf_oran_noncontig_priority;
168 static int hf_oran_symbolMask;
170 static int hf_oran_exponent;
171 static int hf_oran_iq_user_data;
173 static int hf_oran_disable_bfws;
174 static int hf_oran_rad;
175 static int hf_oran_num_bund_prbs;
176 static int hf_oran_beam_id;
177 static int hf_oran_num_weights_per_bundle;
179 static int hf_oran_ack_nack_req_id;
181 static int hf_oran_off_start_prb_num_prb_pair;
182 static int hf_oran_off_start_prb;
183 static int hf_oran_num_prb;
185 static int hf_oran_samples_prb;
186 static int hf_oran_ciSample;
187 static int hf_oran_ciIsample;
188 static int hf_oran_ciQsample;
190 static int hf_oran_beamGroupType;
191 static int hf_oran_numPortc;
193 static int hf_oran_csf;
194 static int hf_oran_modcompscaler;
196 static int hf_oran_modcomp_param_set;
197 static int hf_oran_mc_scale_re_mask;
198 static int hf_oran_mc_scale_offset;
200 static int hf_oran_eAxC_mask;
201 static int hf_oran_technology;
202 static int hf_oran_nullLayerInd;
204 static int hf_oran_portReMask;
205 static int hf_oran_portSymbolMask;
207 static int hf_oran_ext19_port;
209 static int hf_oran_prb_allocation;
210 static int hf_oran_nextSymbolId;
211 static int hf_oran_nextStartPrbc;
213 static int hf_oran_puncPattern;
214 static int hf_oran_numPuncPatterns;
215 static int hf_oran_symbolMask_ext20;
216 static int hf_oran_startPuncPrb;
217 static int hf_oran_numPuncPrb;
218 static int hf_oran_puncReMask;
219 static int hf_oran_RbgIncl;
221 static int hf_oran_ci_prb_group_size;
222 static int hf_oran_prg_size_st5;
223 static int hf_oran_prg_size_st6;
225 static int hf_oran_num_ueid;
227 static int hf_oran_antMask;
229 static int hf_oran_transmissionWindowOffset;
230 static int hf_oran_transmissionWindowSize;
231 static int hf_oran_toT;
233 static int hf_oran_bfaCompHdr;
234 static int hf_oran_bfAzPtWidth;
235 static int hf_oran_bfZePtWidth;
236 static int hf_oran_bfAz3ddWidth;
237 static int hf_oran_bfZe3ddWidth;
238 static int hf_oran_bfAzPt;
239 static int hf_oran_bfZePt;
240 static int hf_oran_bfAz3dd;
241 static int hf_oran_bfZe3dd;
242 static int hf_oran_bfAzSl;
243 static int hf_oran_bfZeSl;
245 static int hf_oran_cmd_scope;
246 static int hf_oran_number_of_st4_cmds;
248 static int hf_oran_st4_cmd_header;
249 static int hf_oran_st4_cmd_type;
250 static int hf_oran_st4_cmd_len;
251 static int hf_oran_st4_cmd_num_slots;
252 static int hf_oran_st4_cmd_ack_nack_req_id;
254 static int hf_oran_st4_cmd;
256 static int hf_oran_sleepmode_trx;
257 static int hf_oran_sleepmode_asm;
258 static int hf_oran_log2maskbits;
259 static int hf_oran_num_slots_ext;
260 static int hf_oran_antMask_trx_control;
262 static int hf_oran_ready;
263 static int hf_oran_number_of_acks;
264 static int hf_oran_number_of_nacks;
265 static int hf_oran_ackid;
266 static int hf_oran_nackid;
268 static int hf_oran_acknack_request_frame;
269 static int hf_oran_acknack_request_time;
270 static int hf_oran_acknack_request_type;
271 static int hf_oran_acknack_response_frame;
272 static int hf_oran_acknack_response_time;
274 static int hf_oran_disable_tdbfns;
275 static int hf_oran_td_beam_group;
276 static int hf_oran_disable_tdbfws;
277 static int hf_oran_td_beam_num;
279 static int hf_oran_dir_pattern;
280 static int hf_oran_guard_pattern;
282 static int hf_oran_ecpri_pcid;
283 static int hf_oran_ecpri_rtcid;
284 static int hf_oran_ecpri_seqid;
286 static int hf_oran_num_sym_prb_pattern;
287 static int hf_oran_prb_mode;
288 static int hf_oran_sym_prb_pattern;
289 static int hf_oran_sym_mask;
290 static int hf_oran_num_mc_scale_offset;
291 static int hf_oran_prb_pattern;
292 static int hf_oran_prb_block_offset;
293 static int hf_oran_prb_block_size;
295 static int hf_oran_codebook_index;
296 static int hf_oran_layerid;
297 static int hf_oran_numlayers;
298 static int hf_oran_txscheme;
299 static int hf_oran_crs_remask;
300 static int hf_oran_crs_shift;
301 static int hf_oran_crs_symnum;
302 static int hf_oran_beamid_ap1;
303 static int hf_oran_beamid_ap2;
304 static int hf_oran_beamid_ap3;
306 static int hf_oran_port_list_index;
307 static int hf_oran_alpn_per_sym;
308 static int hf_oran_ant_dmrs_snr;
309 static int hf_oran_user_group_size;
310 static int hf_oran_user_group_id;
311 static int hf_oran_entry_type;
312 static int hf_oran_dmrs_port_number;
313 static int hf_oran_ueid_reset;
314 static int hf_oran_dmrs_symbol_mask;
315 static int hf_oran_scrambling;
316 static int hf_oran_nscid;
317 static int hf_oran_dtype;
318 static int hf_oran_cmd_without_data;
319 static int hf_oran_lambda;
320 static int hf_oran_first_prb;
321 static int hf_oran_last_prb;
322 static int hf_oran_low_papr_type;
323 static int hf_oran_hopping_mode;
325 static int hf_oran_tx_win_for_on_air_symbol_l;
326 static int hf_oran_tx_win_for_on_air_symbol_r;
328 static int hf_oran_num_fo_fb;
329 static int hf_oran_freq_offset_fb;
331 static int hf_oran_num_sinr_per_prb;
332 static int hf_oran_sinr_value;
334 /* Computed fields */
335 static int hf_oran_c_eAxC_ID;
336 static int hf_oran_refa;
338 /* Hidden fields for filtering */
339 static int hf_oran_cplane;
340 static int hf_oran_uplane;
343 /* Initialize the subtree pointers */
344 static int ett_oran;
345 static int ett_oran_ecpri_rtcid;
346 static int ett_oran_ecpri_pcid;
347 static int ett_oran_ecpri_seqid;
348 static int ett_oran_section;
349 static int ett_oran_section_type;
350 static int ett_oran_u_timing;
351 static int ett_oran_u_section;
352 static int ett_oran_u_prb;
353 static int ett_oran_iq;
354 static int ett_oran_c_section_extension;
355 static int ett_oran_bfw_bundle;
356 static int ett_oran_bfw;
357 static int ett_oran_offset_start_prb_num_prb;
358 static int ett_oran_prb_cisamples;
359 static int ett_oran_cisample;
360 static int ett_oran_udcomphdr;
361 static int ett_oran_udcompparam;
362 static int ett_oran_cicomphdr;
363 static int ett_oran_cicompparam;
364 static int ett_oran_bfwcomphdr;
365 static int ett_oran_bfwcompparam;
366 static int ett_oran_ext19_port;
367 static int ett_oran_prb_allocation;
368 static int ett_oran_punc_pattern;
369 static int ett_oran_bfacomphdr;
370 static int ett_oran_modcomp_param_set;
371 static int ett_oran_st4_cmd_header;
372 static int ett_oran_st4_cmd;
373 static int ett_oran_sym_prb_pattern;
377 /* Expert info */
378 static expert_field ei_oran_unsupported_bfw_compression_method;
379 static expert_field ei_oran_invalid_sample_bit_width;
380 static expert_field ei_oran_reserved_numBundPrb;
381 static expert_field ei_oran_extlen_wrong;
382 static expert_field ei_oran_invalid_eaxc_bit_width;
383 static expert_field ei_oran_extlen_zero;
384 static expert_field ei_oran_rbg_size_reserved;
385 static expert_field ei_oran_frame_length;
386 static expert_field ei_oran_numprbc_ext21_zero;
387 static expert_field ei_oran_ci_prb_group_size_reserved;
388 static expert_field ei_oran_st8_nackid;
389 static expert_field ei_oran_st4_no_cmds;
390 static expert_field ei_oran_st4_zero_len_cmd;
391 static expert_field ei_oran_st4_wrong_len_cmd;
392 static expert_field ei_oran_st4_unknown_cmd;
393 static expert_field ei_oran_mcot_out_of_range;
394 static expert_field ei_oran_se10_unknown_beamgrouptype;
395 static expert_field ei_oran_start_symbol_id_not_zero;
396 static expert_field ei_oran_trx_control_cmd_scope;
397 static expert_field ei_oran_unhandled_se;
398 static expert_field ei_oran_bad_symbolmask;
399 static expert_field ei_oran_numslots_not_zero;
400 static expert_field ei_oran_version_unsupported;
401 static expert_field ei_oran_laa_msg_type_unsupported;
402 static expert_field ei_oran_se_on_unsupported_st;
403 static expert_field ei_oran_cplane_unexpected_sequence_number;
404 static expert_field ei_oran_uplane_unexpected_sequence_number;
405 static expert_field ei_oran_acknack_no_request;
406 static expert_field ei_oran_udpcomphdr_should_be_zero;
407 static expert_field ei_oran_radio_fragmentation_c_plane;
408 static expert_field ei_oran_radio_fragmentation_u_plane;
409 static expert_field ei_oran_lastRbdid_out_of_range;
410 static expert_field ei_oran_rbgMask_beyond_last_rbdid;
413 /* These are the message types handled by this dissector */
414 #define ECPRI_MT_IQ_DATA 0
415 #define ECPRI_MT_RT_CTRL_DATA 2
418 /* Preference settings - try to set reasonable defaults */
419 static unsigned pref_du_port_id_bits = 4;
420 static unsigned pref_bandsector_id_bits = 4;
421 static unsigned pref_cc_id_bits = 4;
422 static unsigned pref_ru_port_id_bits = 4;
424 static unsigned pref_sample_bit_width_uplink = 14;
425 static unsigned pref_sample_bit_width_downlink = 14;
427 /* Compression schemes */
428 #define COMP_NONE 0
429 #define COMP_BLOCK_FP 1
430 #define COMP_BLOCK_SCALE 2
431 #define COMP_U_LAW 3
432 #define COMP_MODULATION 4
433 #define BFP_AND_SELECTIVE_RE 5
434 #define MOD_COMPR_AND_SELECTIVE_RE 6
435 #define BFP_AND_SELECTIVE_RE_WITH_MASKS 7
436 #define MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS 8
438 static int pref_iqCompressionUplink = COMP_BLOCK_FP;
439 static int pref_iqCompressionDownlink = COMP_BLOCK_FP;
440 static bool pref_includeUdCompHeaderUplink;
441 static bool pref_includeUdCompHeaderDownlink;
443 static unsigned pref_data_plane_section_total_rbs = 273;
444 static unsigned pref_num_weights_per_bundle = 32;
445 static unsigned pref_num_bf_antennas = 32;
446 static bool pref_showIQSampleValues = true;
449 static const enum_val_t compression_options[] = {
450 { "COMP_NONE", "No Compression", COMP_NONE },
451 { "COMP_BLOCK_FP", "Block Floating Point Compression", COMP_BLOCK_FP },
452 { "COMP_BLOCK_SCALE", "Block Scaling Compression", COMP_BLOCK_SCALE },
453 { "COMP_U_LAW", "u-Law Compression", COMP_U_LAW },
454 { "COMP_MODULATION", "Modulation Compression", COMP_MODULATION },
455 { "BFP_AND_SELECTIVE_RE", "BFP + selective RE sending", BFP_AND_SELECTIVE_RE },
456 { "MOD_COMPR_AND_SELECTIVE_RE", "mod-compr + selective RE sending", MOD_COMPR_AND_SELECTIVE_RE },
457 { "BFP_AND_SELECTIVE_RE_WITH_MASKS", "BFP + selective RE sending with masks in section header", BFP_AND_SELECTIVE_RE_WITH_MASKS },
458 { "MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS", "mod-compr + selective RE sending with masks in section header", MOD_COMPR_AND_SELECTIVE_RE },
459 { NULL, NULL, 0 }
462 static const value_string e_bit[] = {
463 { 0, "More fragments follow" },
464 { 1, "Last fragment" },
465 { 0, NULL}
468 #define DIR_UPLINK 0
469 #define DIR_DOWNLINK 1
472 static const value_string data_direction_vals[] = {
473 { DIR_UPLINK, "Uplink" }, /* gNB Rx */
474 { DIR_DOWNLINK, "Downlink" }, /* gNB Tx */
475 { 0, NULL}
478 static const value_string rb_vals[] = {
479 { 0, "Every RB used" },
480 { 1, "Every other RB used" },
481 { 0, NULL}
484 static const value_string sym_inc_vals[] = {
485 { 0, "Use the current symbol number" },
486 { 1, "Increment the current symbol number" },
487 { 0, NULL}
490 static const value_string lbtMode_vals[] = {
491 { 0, "Full LBT (regular LBT, sending reservation signal until the beginning of the SF/slot)" },
492 { 1, "Partial LBT (looking back 25 usec prior to transmission" },
493 { 2, "Partial LBT (looking back 34 usec prior to transmission" },
494 { 3, "Full LBT and stop (regular LBT, without sending reservation signal" },
495 { 0, NULL}
498 static const range_string filter_indices[] = {
499 {0, 0, "standard channel filter"},
500 {1, 1, "UL filter for PRACH preamble formats 0, 1, 2; min. passband 839 x 1.25kHz = 1048.75 kHz"},
501 {2, 2, "UL filter for PRACH preamble format 3, min. passband 839 x 5 kHz = 4195 kHz"},
502 {3, 3, "UL filter for PRACH preamble formats A1, A2, A3, B1, B2, B3, B4, C0, C2; min. passband 139 x \u0394fRA"},
503 {4, 4, "UL filter for NPRACH 0, 1; min. passband 48 x 3.75KHz = 180 KHz"},
504 {5, 5, "UL filter for PRACH preamble formats"},
505 {8, 8, "UL filter NPUSCH"},
506 {9, 9, "Mixed numerology and other channels except PRACH and NB-IoT"},
507 {9, 15, "Reserved"},
508 {0, 0, NULL}
511 /* Section types from Table 7.3.1-1 */
512 enum section_c_types {
513 SEC_C_UNUSED_RB = 0,
514 SEC_C_NORMAL = 1,
515 SEC_C_RSVD2 = 2,
516 SEC_C_PRACH = 3,
517 SEC_C_SLOT_CONTROL = 4,
518 SEC_C_UE_SCHED = 5,
519 SEC_C_CH_INFO = 6,
520 SEC_C_LAA = 7,
521 SEC_C_ACK_NACK_FEEDBACK = 8,
522 SEC_C_SINR_REPORTING = 9,
523 SEC_C_RRM_MEAS_REPORTS = 10,
524 SEC_C_REQUEST_RRM_MEAS = 11
527 static const range_string section_types[] = {
528 { SEC_C_UNUSED_RB, SEC_C_UNUSED_RB, "Unused Resource Blocks or symbols in Downlink or Uplink" },
529 { SEC_C_NORMAL, SEC_C_NORMAL, "Most DL/UL radio channels" },
530 { SEC_C_RSVD2, SEC_C_RSVD2, "Reserved for future use" },
531 { SEC_C_PRACH, SEC_C_PRACH, "PRACH and mixed-numerology channels" },
532 { SEC_C_SLOT_CONTROL, SEC_C_SLOT_CONTROL, "Slot Configuration Control" },
533 { SEC_C_UE_SCHED, SEC_C_UE_SCHED, "UE scheduling information (UE-ID assignment to section)" },
534 { SEC_C_CH_INFO, SEC_C_CH_INFO, "Channel information" },
535 { SEC_C_LAA, SEC_C_LAA, "LAA (License Assisted Access)" },
536 { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "ACK/NACK Feedback" },
537 { SEC_C_SINR_REPORTING, SEC_C_SINR_REPORTING, "SINR Reporting" },
538 { SEC_C_RRM_MEAS_REPORTS, SEC_C_RRM_MEAS_REPORTS, "RRM Measurement Reports" },
539 { SEC_C_REQUEST_RRM_MEAS, SEC_C_REQUEST_RRM_MEAS, "Request RRM Measurements" },
540 { 12, 255, "Reserved for future use" },
541 { 0, 0, NULL} };
543 static const range_string section_types_short[] = {
544 { SEC_C_UNUSED_RB, SEC_C_UNUSED_RB, "(Unused RBs) " },
545 { SEC_C_NORMAL, SEC_C_NORMAL, "(Most channels) " },
546 { SEC_C_RSVD2, SEC_C_RSVD2, "(reserved) " },
547 { SEC_C_PRACH, SEC_C_PRACH, "(PRACH/mixed-\u03bc)" },
548 { SEC_C_SLOT_CONTROL, SEC_C_SLOT_CONTROL, "(Slot info) " },
549 { SEC_C_UE_SCHED, SEC_C_UE_SCHED, "(UE scheduling info)" },
550 { SEC_C_CH_INFO, SEC_C_CH_INFO, "(Channel info) " },
551 { SEC_C_LAA, SEC_C_LAA, "(LAA) " },
552 { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "(ACK/NACK) " },
553 { SEC_C_SINR_REPORTING, SEC_C_SINR_REPORTING, "(SINR Reporting) " },
554 { SEC_C_RRM_MEAS_REPORTS, SEC_C_RRM_MEAS_REPORTS, "(RRM Meas Reports) " },
555 { SEC_C_REQUEST_RRM_MEAS, SEC_C_REQUEST_RRM_MEAS, "(Req RRM Meas) " },
556 { 12, 255, "Reserved for future use" },
557 { 0, 0, NULL }
560 static const range_string ud_comp_header_width[] = {
561 {0, 0, "I and Q are each 16 bits wide"},
562 {1, 15, "Bit width of I and Q"},
563 {0, 0, NULL} };
565 /* Table 8.3.3.13-3 */
566 static const range_string ud_comp_header_meth[] = {
567 {COMP_NONE, COMP_NONE, "No compression" },
568 {COMP_BLOCK_FP, COMP_BLOCK_FP, "Block floating point compression" },
569 {COMP_BLOCK_SCALE, COMP_BLOCK_SCALE, "Block scaling" },
570 {COMP_U_LAW, COMP_U_LAW, "Mu - law" },
571 {COMP_MODULATION, COMP_MODULATION, "Modulation compression" },
572 {BFP_AND_SELECTIVE_RE, BFP_AND_SELECTIVE_RE, "BFP + selective RE sending" },
573 {MOD_COMPR_AND_SELECTIVE_RE, MOD_COMPR_AND_SELECTIVE_RE, "mod-compr + selective RE sending" },
574 {BFP_AND_SELECTIVE_RE_WITH_MASKS, BFP_AND_SELECTIVE_RE_WITH_MASKS, "BFP + selective RE sending with masks in section header" },
575 {MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, "mod-compr + selective RE sending with masks in section header"},
576 {9, 15, "Reserved"},
577 {0, 0, NULL}
580 /* Table 7.5.2.13-2 */
581 static const range_string frame_structure_fft[] = {
582 {0, 0, "Reserved (no FFT/iFFT processing)"},
583 {1, 3, "Reserved"},
584 {4, 4, "FFT size 16"},
585 {5, 5, "FFT size 32"},
586 {6, 6, "FFT size 64"},
587 {7, 7, "FFT size 128"},
588 {8, 8, "FFT size 256"},
589 {9, 9, "FFT size 512"},
590 {10, 10, "FFT size 1024"},
591 {11, 11, "FFT size 2048"},
592 {12, 12, "FFT size 4096"},
593 {13, 13, "FFT size 1536"},
594 {14, 14, "FFT size 3072"},
595 {15, 15, "Reserved"},
596 {0, 0, NULL}
599 /* Table 7.5.2.13-3 */
600 static const range_string subcarrier_spacings[] = {
601 { 0, 0, "SCS 15 kHz, 1 slot/subframe, slot length 1 ms" },
602 { 1, 1, "SCS 30 kHz, 2 slots/subframe, slot length 500 \u03bcs" },
603 { 2, 2, "SCS 60 kHz, 4 slots/subframe, slot length 250 \u03bcs" },
604 { 3, 3, "SCS 120 kHz, 8 slots/subframe, slot length 125 \u03bcs" },
605 { 4, 4, "SCS 240 kHz, 16 slots/subframe, slot length 62.5 \u03bcs" },
606 { 5, 11, "Reserved" }, /* N.B., 5 was 480kHz in early spec versions */
607 { 12, 12, "SCS 1.25 kHz, 1 slot/subframe, slot length 1 ms" },
608 { 13, 13, "SCS 3.75 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
609 { 14, 14, "SCS 5 kHz, 1 slot/subframe, slot length 1 ms" },
610 { 15, 15, "SCS 7.5 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
611 { 0, 0, NULL }
614 /* Table 7.5.3.14-1 laaMsgType definition */
615 static const range_string laaMsgTypes[] = {
616 {0, 0, "LBT_PDSCH_REQ - lls - O-DU to O-RU request to obtain a PDSCH channel"},
617 {1, 1, "LBT_DRS_REQ - lls - O-DU to O-RU request to obtain the channel and send DRS"},
618 {2, 2, "LBT_PDSCH_RSP - O-RU to O-DU response, channel acq success or failure"},
619 {3, 3, "LBT_DRS_RSP - O-RU to O-DU response, DRS sending success or failure"},
620 {4, 4, "LBT_Buffer_Error - O-RU to O-DU response, reporting buffer overflow"},
621 {5, 5, "LBT_CWCONFIG_REQ - O-DU to O-RU request, congestion window configuration"},
622 {6, 6, "LBT_CWCONFIG_RST - O-RU to O-DU request, congestion window config, response"},
623 {7, 15, "reserved for future methods"},
624 {0, 0, NULL}
627 static const range_string freq_offset_fb_values[] = {
628 {0, 0, "no frequency offset"},
629 {8000, 8000, "value not provided"},
630 {1, 30000, "positive frequency offset, (0, +0.5] subcarrier"},
631 {0x8ad0, 0xffff, "negative frequency offset, [-0.5, 0) subcarrier"},
632 {0x0, 0xffff, "reserved"},
633 {0, 0, NULL}
636 static const value_string num_sinr_per_prb_vals[] = {
637 { 0, "1" },
638 { 1, "2" },
639 { 2, "3" },
640 { 3, "4" },
641 { 4, "6" },
642 { 5, "12" },
643 { 6, "reserved" },
644 { 7, "reserved" },
645 { 0, NULL}
650 /* Table 7.6.1-1 */
651 static const value_string exttype_vals[] = {
652 {0, "Reserved"},
653 {1, "Beamforming weights"},
654 {2, "Beamforming attributes"},
655 {3, "DL Precoding configuration parameters and indications"},
656 {4, "Modulation compr. params"},
657 {5, "Modulation compression additional scaling parameters"},
658 {6, "Non-contiguous PRB allocation"},
659 {7, "Multiple-eAxC designation"},
660 {8, "Regularization factor"},
661 {9, "Dynamic Spectrum Sharing parameters"},
662 {10, "Multiple ports grouping"},
663 {11, "Flexible BF weights"},
664 {12, "Non-Contiguous PRB Allocation with Frequency Ranges"},
665 {13, "PRB Allocation with Frequency Hopping"},
666 {14, "Nulling-layer Info. for ueId-based beamforming"},
667 {15, "Mixed-numerology Info. for ueId-based beamforming"},
668 {16, "Section description for antenna mapping in UE channel information based UL beamforming"},
669 {17, "Section description for indication of user port group"},
670 {18, "Section description for Uplink Transmission Management"},
671 {19, "Compact beamforming information for multiple port"},
672 {20, "Puncturing extension"},
673 {21, "Variable PRB group size for channel information"},
674 {22, "ACK/NACK request"},
675 {23, "Multiple symbol modulation compression parameters"},
676 {24, "PUSCH DMRS configuration"},
677 {25, "Symbol reordering for DMRS-BF"},
678 {26, "Frequency offset feedback"},
679 {27, "O-DU controlled dimensionality reduction"},
680 {0, NULL}
683 /**************************************************************************************/
684 /* Keep track for each Section Extension, which section types are allowed to carry it */
685 #define HIGHEST_EXTTYPE 27
686 typedef struct {
687 bool ST0;
688 bool ST1;
689 bool ST3;
690 bool ST5;
691 bool ST6;
692 bool ST10;
693 bool ST11;
694 } AllowedCTs_t;
697 static AllowedCTs_t ext_cts[HIGHEST_EXTTYPE] = {
698 /* ST0 ST1 ST3 ST5 ST6 ST10 ST11 */
699 { false, true, true, false, false, false, false}, // SE 1 (1,3)
700 { false, true, true, false, false, false, false}, // SE 2 (1,3)
701 { false, true, true, false, false, false, false}, // SE 3 (1,3)
702 { false, true, true, true, false, false, false}, // SE 4 (1,3,5)
703 { false, true, true, true, false, false, false}, // SE 5 (1,3,5)
704 { false, true, true, true, false, false, false}, // SE 6 (1,3,5)
705 { true, false, false, false, false, false, false}, // SE 7 (0)
706 { false, false, false, true, false, false, false}, // SE 8 (5)
707 { true, true, true, true, true, true, true }, // SE 9 (all)
708 { false, true, true, true, false, false, false}, // SE 10 (1,3,5)
709 { false, true, true, false, false, false, false}, // SE 11 (1,3)
710 { false, true, true, true, false, false, false}, // SE 12 (1,3,5)
711 { false, true, true, true, false, false, false}, // SE 13 (1,3,5)
712 { false, false, false, true, false, false, false}, // SE 14 (5)
713 { false, false, false, true, true, false, false}, // SE 15 (5,6)
714 { false, false, false, true, false, false, false}, // SE 16 (5)
715 { false, false, false, true, false, false, false}, // SE 17 (5)
716 { false, true, true, true, false, false, false}, // SE 18 (1,3,5)
717 { false, true, true, false, false, false, false}, // SE 19 (1,3)
718 { true, true, true, true, true, false, false}, // SE 20 (0,1,3,5)
719 { false, false, false, true, true, false, false}, // SE 21 (5,6)
720 { true, true, true, true, true, true, true }, // SE 22 (all)
721 { false, true, true, true, false, false, false}, // SE 23 (1,3,5)
722 { false, false, false, true, false, false, false }, // SE 24 (5)
723 { false, false, false, true, false, false, false }, // SE 25 (5)
724 { false, false, false, true, false, false, false }, // SE 26 (5)
725 { false, false, false, true, false, false, false }, // SE 27 (5)
730 static bool se_allowed_in_st(unsigned se, unsigned ct)
732 if (se==0 || se>HIGHEST_EXTTYPE) {
733 /* Don't know about new SE, so don't complain.. */
734 return true;
737 switch (ct) {
738 case 1:
739 return ext_cts[se-1].ST1;
740 case 3:
741 return ext_cts[se-1].ST3;
742 case 5:
743 return ext_cts[se-1].ST5;
744 case 6:
745 return ext_cts[se-1].ST6;
746 default:
747 /* New section type that includes 'ef'.. assume ok */
748 return true;
752 /************************************************************************************/
754 static const value_string bfw_comp_headers_iq_width[] = {
755 {0, "I and Q are 16 bits wide"},
756 {1, "I and Q are 1 bit wide"},
757 {2, "I and Q are 2 bits wide"},
758 {3, "I and Q are 3 bits wide"},
759 {4, "I and Q are 4 bits wide"},
760 {5, "I and Q are 5 bits wide"},
761 {6, "I and Q are 6 bits wide"},
762 {7, "I and Q are 7 bits wide"},
763 {8, "I and Q are 8 bits wide"},
764 {9, "I and Q are 9 bits wide"},
765 {10, "I and Q are 10 bits wide"},
766 {11, "I and Q are 11 bits wide"},
767 {12, "I and Q are 12 bits wide"},
768 {13, "I and Q are 13 bits wide"},
769 {14, "I and Q are 14 bits wide"},
770 {15, "I and Q are 15 bits wide"},
771 {0, NULL}
774 /* Table 7.7.1.2-3 */
775 static const value_string bfw_comp_headers_comp_meth[] = {
776 {COMP_NONE, "no compression"},
777 {COMP_BLOCK_FP, "block floating point"},
778 {COMP_BLOCK_SCALE, "block scaling"},
779 {COMP_U_LAW, "u-law"},
780 {4, "beamspace compression type I"},
781 {5, "beamspace compression type II"},
782 {0, NULL}
785 /* 7.7.6.2 rbgSize (resource block group size) */
786 static const value_string rbg_size_vals[] = {
787 {0, "reserved"},
788 {1, "1"},
789 {2, "2"},
790 {3, "3"},
791 {4, "4"},
792 {5, "6"},
793 {6, "8"},
794 {7, "16"},
795 {0, NULL}
798 /* 7.7.6.5 */
799 static const value_string priority_vals[] = {
800 {0, "0"},
801 {1, "+1"},
802 {2, "-2 (reserved, should not be used)"},
803 {3, "-1"},
804 {0, NULL}
807 /* 7.7.10.2 beamGroupType */
808 static const value_string beam_group_type_vals[] = {
809 {0x0, "common beam"},
810 {0x1, "beam matrix indication"},
811 {0x2, "beam vector listing"},
812 {0x3, "beamId/ueId listing with associated port-list index"},
813 {0, NULL}
816 /* 7.7.9.2 technology (interface name) */
817 static const value_string interface_name_vals[] = {
818 {0x0, "LTE"},
819 {0x1, "NR"},
820 {0, NULL}
823 /* 7.7.18.4 toT (type of transmission) */
824 static const value_string type_of_transmission_vals[] = {
825 {0x0, "normal transmission mode, data can be distributed in any way the O-RU is implemented to transmit data"},
826 {0x1, "uniformly distributed over the transmission window"},
827 {0x2, "Reserved"},
828 {0x3, "Reserved"},
829 {0, NULL}
832 /* 7.7.2.2 (width of bfa parameters) */
833 static const value_string bfa_bw_vals[] = {
834 {0, "no bits, the field is not applicable (e.g., O-RU does not support it) or the default value shall be used"},
835 {1, "2-bit bitwidth"},
836 {2, "3-bit bitwidth"},
837 {3, "4-bit bitwidth"},
838 {4, "5-bit bitwidth"},
839 {5, "6-bit bitwidth"},
840 {6, "7-bit bitwidth"},
841 {7, "8-bit bitwidth"},
842 {0, NULL}
845 /* 7.7.2.7 & 7.7.2.8 */
846 static const value_string sidelobe_suppression_vals[] = {
847 {0, "10 dB"},
848 {1, "15 dB"},
849 {2, "20 dB"},
850 {3, "25 dB"},
851 {4, "30 dB"},
852 {5, "35 dB"},
853 {6, "40 dB"},
854 {7, ">= 45 dB"},
855 {0, NULL}
858 static const value_string lbtTrafficClass_vals[] = {
859 {1, "Priority 1"},
860 {2, "Priority 2"},
861 {3, "Priority 3"},
862 {4, "Priority 4"},
863 {0, NULL}
866 static const value_string lbtPdschRes_vals[] = {
867 {0, "not sensing – indicates that the O-RU is transmitting data"},
868 {1, "currently sensing – indicates the O-RU has not yet acquired the channel"},
869 {2, "success – indicates that the channel was successfully acquired"},
870 {3, "Failure – indicates expiration of the LBT timer. The LBT process should be reset"},
871 {0, NULL}
874 static const value_string ci_comp_opt_vals[] = {
875 {0, "compression per UE, one ciCompParam exists before the I/Q value of each UE"},
876 {1, "compression per PRB, one ciCompParam exists before the I/Q value of each PRB"},
877 {0, NULL}
880 static const range_string cmd_scope_vals[] = {
881 {0, 0, "ARRAY-COMMAND"},
882 {1, 1, "CARRIER-COMMAND"},
883 {2, 2, "O-RU-COMMAND"},
884 {3, 15, "reserved"},
885 {0, 0, NULL}
888 /* N.B., table in 7.5.3.38 is truncated.. */
889 static const range_string st4_cmd_type_vals[] = {
890 {0, 0, "reserved for future command types"},
891 {1, 1, "TIME_DOMAIN_BEAM_CONFIG"},
892 {2, 2, "TDD_CONFIG_PATTERN"},
893 {3, 3, "TRX_CONTROL"},
894 {4, 4, "ASM"},
895 {5, 255, "reserved for future command types"},
896 {0, 0, NULL}
899 /* Table 7.5.3.51-1 */
900 static const value_string log2maskbits_vals[] = {
901 {0, "reserved"},
902 {1, "min antMask size is 16 bits.."},
903 {2, "min antMask size is 16 bits.."},
904 {3, "min antMask size is 16 bits.."},
905 {4, "16 bits"},
906 {5, "32 bits"},
907 {6, "64 bits"},
908 {7, "128 bits"},
909 {8, "256 bits"},
910 {9, "512 bits"},
911 {10, "1024 bits"},
912 {11, "2048 bits"},
913 {12, "4096 bits"},
914 {13, "8192 bits"},
915 {14, "16384 bits"},
916 {15, "reserved"},
917 {0, NULL}
920 /* Table 16.1-1 Sleep modes */
921 static const value_string sleep_mode_trx_vals[] = {
922 { 0, "TRXC-mode0-wake-up-duration (symbol)"},
923 { 1, "TRXC-mode1-wake-up-duration (L)"},
924 { 2, "TRXC-mode2-wake-up-duration (M)"},
925 { 3, "TRXC-mode3-wake-up-duration (N)"},
926 { 0, NULL}
929 static const value_string sleep_mode_asm_vals[] = {
930 { 0, "ASM-mode0-wake-up-duration (symbol)"},
931 { 1, "ASM-mode1-wake-up-duration (L)"},
932 { 2, "ASM-mode2-wake-up-duration (M)"},
933 { 3, "ASM-mode3-wake-up-duration (N)"},
934 { 0, NULL}
937 /* 7.7.21.3.1 */
938 static const value_string prg_size_st5_vals[] = {
939 { 0, "reserved"},
940 { 1, "Precoding resource block group size as WIDEBAND"},
941 { 2, "Precoding resource block group size 2"},
942 { 3, "Precoding resource block group size 4"},
943 { 0, NULL}
946 static const value_string prg_size_st6_vals[] = {
947 { 0, "if ciPrbGroupSize is 2 or 4, then ciPrbGroupSize, else WIDEBAND"},
948 { 1, "Precoding resource block group size as WIDEBAND"},
949 { 2, "Precoding resource block group size 2"},
950 { 3, "Precoding resource block group size 4"},
951 { 0, NULL}
956 static const true_false_string tfs_sfStatus =
958 "subframe was transmitted",
959 "subframe was dropped"
962 static const true_false_string tfs_lbtBufErr =
964 "buffer overflow – data received at O-RU is larger than the available buffer size",
965 "reserved"
968 static const true_false_string tfs_partial_full_sf = {
969 "partial SF",
970 "full SF"
973 static const true_false_string disable_tdbfns_tfs = {
974 "beam numbers excluded",
975 "beam numbers included"
978 static const true_false_string continuity_indication_tfs = {
979 "continuity between current and next bundle",
980 "discontinuity between current and next bundle"
983 static const true_false_string prb_mode_tfs = {
984 "PRB-BLOCK mode",
985 "PRB-MASK mode"
988 /* Forward declaration */
989 static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
990 unsigned comp_meth,
991 uint32_t *exponent, uint16_t *sReSMask, bool for_sinr);
994 static const true_false_string ready_tfs = {
995 "message is a \"ready\" message",
996 "message is a ACK message"
1001 /* Config for (and later, worked-out allocations) bundles for ext11 (dynamic BFW) */
1002 typedef struct {
1003 /* Ext 6 config */
1004 bool ext6_set;
1005 uint8_t ext6_rbg_size; /* number of PRBs allocated by bitmask */
1007 uint8_t ext6_num_bits_set;
1008 uint8_t ext6_bits_set[28]; /* Which bit position this entry has */
1009 /* TODO: store an f value for each bit position? */
1011 /* Ext 12 config */
1012 bool ext12_set;
1013 unsigned ext12_num_pairs;
1014 #define MAX_BFW_EXT12_PAIRS 128
1015 struct {
1016 uint8_t off_start_prb;
1017 uint8_t num_prb;
1018 } ext12_pairs[MAX_BFW_EXT12_PAIRS];
1020 /* Ext 13 config */
1021 bool ext13_set;
1022 unsigned ext13_num_start_prbs;
1023 #define MAX_BFW_EXT13_ALLOCATIONS 128
1024 unsigned ext13_start_prbs[MAX_BFW_EXT13_ALLOCATIONS];
1025 /* TODO: store nextSymbolId here too? */
1027 /* Ext 21 config */
1028 bool ext21_set;
1029 uint8_t ext21_ci_prb_group_size;
1031 /* Results/settings (after calling ext11_work_out_bundles()) */
1032 uint32_t num_bundles;
1033 #define MAX_BFW_BUNDLES 512
1034 struct {
1035 uint32_t start; /* first prb of bundle */
1036 uint32_t end; /* last prb of bundle*/
1037 bool is_orphan; /* true if not complete (i.e., end-start < numBundPrb) */
1038 } bundles[MAX_BFW_BUNDLES];
1039 } ext11_settings_t;
1042 /* Work out bundle allocation for ext 11. Take into account ext6/ext21, ext12 or ext13 in this section before ext 11. */
1043 /* Won't be called with numBundPrb=0 */
1044 static void ext11_work_out_bundles(unsigned startPrbc,
1045 unsigned numPrbc,
1046 unsigned numBundPrb, /* number of PRBs pre (full) bundle */
1047 ext11_settings_t *settings)
1049 /* Allocation configured by ext 6 */
1050 if (settings->ext6_set) {
1051 unsigned bundles_per_entry = (settings->ext6_rbg_size / numBundPrb);
1053 /* Need to cope with these not dividing exactly, or even having more PRbs in a bundle that
1054 rbg size. i.e. each bundle gets the correct number of PRBs until
1055 all rbg entries are consumed... */
1057 /* TODO: need to check 7.9.4.2. Different cases depending upon value of RAD */
1059 if (bundles_per_entry == 0) {
1060 bundles_per_entry = 1;
1063 /* Maybe also be affected by ext 21 */
1064 if (settings->ext21_set) {
1065 /* N.B., have already checked that numPrbc is not 0 */
1067 /* ciPrbGroupSize overrides number of contiguous PRBs in group */
1068 bundles_per_entry = (settings->ext6_rbg_size / settings->ext21_ci_prb_group_size);
1070 /* numPrbc is the number of PRB groups per antenna - handled in call to dissect_bfw_bundle() */
1073 unsigned bundles_set = 0;
1074 for (uint8_t n=0;
1075 n < (settings->ext6_num_bits_set * settings->ext6_rbg_size) / numBundPrb;
1076 n++) {
1078 /* Watch out for array bound */
1079 if (n >= 28) {
1080 break;
1083 /* For each bundle... */
1085 /* TODO: Work out where first PRB is */
1086 /* May not be the start of an rbg block... */
1087 uint32_t prb_start = (settings->ext6_bits_set[n] * settings->ext6_rbg_size);
1089 /* For each bundle within identified rbgSize block */
1090 for (unsigned m=0; m < bundles_per_entry; m++) {
1091 settings->bundles[bundles_set].start = startPrbc+prb_start+(m*numBundPrb);
1092 /* Start already beyond end, so doesn't count. */
1093 if (settings->bundles[bundles_set].start > (startPrbc+numPrbc-1)) {
1094 break;
1096 /* Bundle consists of numBundPrb bundles */
1097 /* TODO: may involve PRBs from >1 rbg blocks.. */
1098 settings->bundles[bundles_set].end = startPrbc+prb_start+((m+1)*numBundPrb)-1;
1099 if (settings->bundles[bundles_set].end > (startPrbc+numPrbc-1)) {
1100 /* Extends beyond end, so counts but is an orphan bundle */
1101 settings->bundles[bundles_set].end = numPrbc;
1102 settings->bundles[bundles_set].is_orphan = true;
1105 /* Get out if have reached array bound */
1106 if (++bundles_set == MAX_BFW_BUNDLES) {
1107 return;
1111 settings->num_bundles = bundles_set;
1114 /* Allocation configured by ext 12 */
1115 else if (settings->ext12_set) {
1116 /* First, allocate normally from startPrbc, numPrbc */
1117 settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1119 /* Don't overflow settings->bundles[] ! */
1120 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1122 for (uint32_t n=0; n < settings->num_bundles; n++) {
1123 settings->bundles[n].start = startPrbc + n*numBundPrb;
1124 settings->bundles[n].end = settings->bundles[n].start + numBundPrb-1;
1125 /* Does it go beyond the end? */
1126 if (settings->bundles[n].end > startPrbc+numPrbc) {
1127 settings->bundles[n].end = numPrbc+numPrbc;
1128 settings->bundles[n].is_orphan = true;
1131 if (settings->num_bundles == MAX_BFW_BUNDLES) {
1132 return;
1135 unsigned prb_offset = startPrbc + numPrbc;
1137 /* Loop over pairs, adding bundles for each */
1138 for (unsigned p=0; p < settings->ext12_num_pairs; p++) {
1139 prb_offset += settings->ext12_pairs[p].off_start_prb;
1140 unsigned pair_bundles = (settings->ext12_pairs[p].num_prb+numBundPrb-1) / numBundPrb;
1142 for (uint32_t n=0; n < pair_bundles; n++) {
1143 unsigned idx = settings->num_bundles;
1145 settings->bundles[idx].start = prb_offset + n*numBundPrb;
1146 settings->bundles[idx].end = settings->bundles[idx].start + numBundPrb-1;
1147 /* Does it go beyond the end? */
1148 if (settings->bundles[idx].end > prb_offset + settings->ext12_pairs[p].num_prb) {
1149 settings->bundles[idx].end = prb_offset + settings->ext12_pairs[p].num_prb;
1150 settings->bundles[idx].is_orphan = true;
1152 /* Range check / return */
1153 settings->num_bundles++;
1154 if (settings->num_bundles == MAX_BFW_BUNDLES) {
1155 return;
1159 prb_offset += settings->ext12_pairs[p].num_prb;
1163 /* Allocation configured by ext 13 */
1164 else if (settings->ext13_set) {
1165 unsigned alloc_size = (numPrbc+numBundPrb-1) / numBundPrb;
1166 settings->num_bundles = alloc_size * settings->ext13_num_start_prbs;
1168 /* Don't overflow settings->bundles[] ! */
1169 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1171 for (unsigned alloc=0; alloc < settings->ext13_num_start_prbs; alloc++) {
1172 unsigned alloc_start = alloc * alloc_size;
1173 for (uint32_t n=0; n < alloc_size; n++) {
1174 if ((alloc_start+n) >= MAX_BFW_BUNDLES) {
1175 /* ERROR */
1176 return;
1178 settings->bundles[alloc_start+n].start = settings->ext13_start_prbs[alloc] + startPrbc + n*numBundPrb;
1179 settings->bundles[alloc_start+n].end = settings->bundles[alloc_start+n].start + numBundPrb-1;
1180 if (settings->bundles[alloc_start+n].end > settings->ext13_start_prbs[alloc] + numPrbc) {
1181 settings->bundles[alloc_start+n].end = settings->ext13_start_prbs[alloc] + numPrbc;
1182 settings->bundles[alloc_start+n].is_orphan = true;
1188 /* Bundles not controlled by other extensions - just divide up range into bundles we have */
1189 else {
1190 settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1192 /* Don't overflow settings->bundles[] ! */
1193 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1195 for (uint32_t n=0; n < settings->num_bundles; n++) {
1196 settings->bundles[n].start = startPrbc + n*numBundPrb;
1197 settings->bundles[n].end = settings->bundles[n].start + numBundPrb-1;
1198 /* Does it go beyond the end? */
1199 if (settings->bundles[n].end > startPrbc+numPrbc) {
1200 settings->bundles[n].end = numPrbc+numPrbc;
1201 settings->bundles[n].is_orphan = true;
1208 /*******************************************************/
1209 /* Overall state of a flow (eAxC/plane) */
1210 typedef struct {
1211 /* State for sequence analysis [each direction] */
1212 uint32_t last_frame[2];
1213 uint8_t next_expected_sequence_number[2];
1215 /* Table recording ackNack requests (ackNackId -> ack_nack_request_t*)
1216 Note that this assumes that the same ackNackId will not be reused within a state,
1217 which may well not be valid */
1218 wmem_tree_t *ack_nack_requests;
1220 /* Store udCompHdr seen in C-Plane for UL - can be looked up and used by U-PLane.
1221 Note that this appears in the common section header parts of ST1, ST3, ST5,
1222 so can still be over-written per sectionId in the U-Plane */
1223 bool ul_ud_comp_hdr_set;
1224 unsigned ul_ud_comp_hdr_bit_width;
1225 int ul_ud_comp_hdr_compression;
1226 } flow_state_t;
1228 typedef struct {
1229 uint32_t request_frame_number;
1230 nstime_t request_frame_time;
1231 enum {
1232 SE22,
1233 ST4Cmd1,
1234 ST4Cmd2,
1235 ST4Cmd3,
1236 ST4Cmd4
1237 } requestType;
1239 uint32_t response_frame_number;
1240 nstime_t response_frame_time;
1241 } ack_nack_request_t;
1243 static const value_string acknack_type_vals[] = {
1244 { SE22, "SE 22" },
1245 { ST4Cmd1, "ST4 (TIME_DOMAIN_BEAM_CONFIG)" },
1246 { ST4Cmd2, "ST4 (TDD_CONFIG_PATTERN)" },
1247 { ST4Cmd3, "ST4 (TRX_CONTROL)" },
1248 { ST4Cmd4, "ST4 (ASM)" },
1249 { 0, NULL}
1252 #define ORAN_C_PLANE 0
1253 #define ORAN_U_PLANE 1
1255 static uint32_t make_flow_key(uint16_t eaxc_id, uint8_t plane)
1257 return eaxc_id | (plane << 16);
1261 /* Table maintained on first pass from flow_key(uint32_t) -> flow_state_t* */
1262 static wmem_tree_t *flow_states_table;
1264 /* Table consulted on subsequent passes: frame_num -> flow_result_t* */
1265 static wmem_tree_t *flow_results_table;
1267 typedef struct {
1268 /* Sequence analysis */
1269 bool unexpected_seq_number;
1270 uint8_t expected_sequence_number;
1271 uint32_t previous_frame;
1272 } flow_result_t;
1274 static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
1275 ack_nack_request_t *response);
1280 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1281 packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(4, 5);
1283 /* Write the given formatted text to:
1284 - the info column (if pinfo != NULL)
1285 - 1 or 2 other labels (optional)
1287 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1288 packet_info *pinfo, const char *format, ...)
1290 #define MAX_INFO_BUFFER 256
1291 char info_buffer[MAX_INFO_BUFFER];
1292 va_list ap;
1294 if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
1295 return;
1298 va_start(ap, format);
1299 vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1300 va_end(ap);
1302 /* Add to indicated places */
1303 if (pinfo != NULL) {
1304 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1306 if (ti1 != NULL) {
1307 proto_item_append_text(ti1, "%s", info_buffer);
1309 if (ti2 != NULL) {
1310 proto_item_append_text(ti2, "%s", info_buffer);
1314 /* Add section labels (type + PRB range) for C-Plane, U-Plane */
1315 static void
1316 write_section_info(proto_item *section_heading, packet_info *pinfo, proto_item *protocol_item,
1317 uint32_t section_id, uint32_t start_prbx, uint32_t num_prbx, uint32_t rb)
1319 switch (num_prbx) {
1320 case 0:
1321 /* None -> all */
1322 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (all PRBs)", section_id);
1323 break;
1324 case 1:
1325 /* Single PRB */
1326 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %7u)", section_id, start_prbx);
1327 break;
1328 default:
1329 /* Range */
1330 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %3u-%3u%s)", section_id, start_prbx,
1331 start_prbx + (num_prbx-1)*(1+rb), rb ? " (every-other)" : "");
1335 static void
1336 write_channel_section_info(proto_item *section_heading, packet_info *pinfo,
1337 uint32_t section_id, uint32_t ueId, uint32_t start_prbx, uint32_t num_prbx,
1338 uint32_t num_trx)
1340 switch (num_prbx) {
1341 case 0:
1342 /* TODO: ?? */
1343 break;
1344 case 1:
1345 /* Single PRB */
1346 write_pdu_label_and_info(section_heading, NULL, pinfo,
1347 ", Id: %4d (UEId=%3u PRB %7u, %2u antennas)",
1348 section_id, ueId, start_prbx, num_trx);
1349 break;
1350 default:
1351 /* Range */
1352 write_pdu_label_and_info(section_heading, NULL, pinfo,
1353 ", Id: %4d (UEId=%3u PRBs %3u-%3u, %2u antennas)",
1354 section_id, ueId, start_prbx, start_prbx+num_prbx-1, num_trx);
1359 /* 5.1.3.2.7 (real time control data / IQ data transfer message series identifier) */
1360 static void
1361 addPcOrRtcid(tvbuff_t *tvb, proto_tree *tree, int *offset, int hf, uint16_t *eAxC)
1363 /* Subtree */
1364 proto_item *oran_pcid_ti = proto_tree_add_item(tree, hf,
1365 tvb, *offset, 2, ENC_NA);
1366 proto_tree *oran_pcid_tree = proto_item_add_subtree(oran_pcid_ti, ett_oran_ecpri_pcid);
1368 uint64_t duPortId, bandSectorId, ccId, ruPortId = 0;
1369 int id_offset = *offset;
1371 /* All parts of eAxC should be above 0, and should total 16 bits (breakdown controlled by preferences) */
1372 if (!((pref_du_port_id_bits > 0) && (pref_bandsector_id_bits > 0) && (pref_cc_id_bits > 0) && (pref_ru_port_id_bits > 0) &&
1373 ((pref_du_port_id_bits + pref_bandsector_id_bits + pref_cc_id_bits + pref_ru_port_id_bits) == 16))) {
1374 expert_add_info(NULL, tree, &ei_oran_invalid_eaxc_bit_width);
1375 *eAxC = 0;
1376 *offset += 2;
1377 return;
1380 unsigned bit_offset = *offset * 8;
1382 /* N.B. For sequence analysis / tapping, just interpret these 2 bytes as eAxC ID... */
1383 *eAxC = tvb_get_uint16(tvb, *offset, ENC_BIG_ENDIAN);
1385 /* DU Port ID */
1386 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);
1387 bit_offset += pref_du_port_id_bits;
1388 /* BandSector ID */
1389 proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_bandsector_id, tvb, bit_offset, pref_bandsector_id_bits, &bandSectorId, ENC_BIG_ENDIAN);
1390 bit_offset += pref_bandsector_id_bits;
1391 /* CC ID */
1392 proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_cc_id, tvb, bit_offset, pref_cc_id_bits, &ccId, ENC_BIG_ENDIAN);
1393 bit_offset += pref_cc_id_bits;
1394 /* RU Port ID */
1395 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);
1396 *offset += 2;
1398 proto_item_append_text(oran_pcid_ti, " (DU_Port_ID: %d, BandSector_ID: %d, CC_ID: %d, RU_Port_ID: %d)",
1399 (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1400 char id[16];
1401 snprintf(id, 16, "%x:%x:%x:%x", (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1402 proto_item *pi = proto_tree_add_string(oran_pcid_tree, hf_oran_c_eAxC_ID, tvb, id_offset, 2, id);
1403 proto_item_set_generated(pi);
1406 /* 5.1.3.2.8 ecpriSeqid (message identifier) */
1407 static int
1408 addSeqid(tvbuff_t *tvb, proto_tree *oran_tree, int offset, int plane, uint8_t *seq_id, proto_item **seq_id_ti)
1410 /* Subtree */
1411 proto_item *seqIdItem = proto_tree_add_item(oran_tree, hf_oran_ecpri_seqid, tvb, offset, 2, ENC_NA);
1412 proto_tree *oran_seqid_tree = proto_item_add_subtree(seqIdItem, ett_oran_ecpri_seqid);
1413 uint32_t seqId, subSeqId, e = 0;
1414 /* Sequence ID (8 bits) */
1415 *seq_id_ti = proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_sequence_id, tvb, offset, 1, ENC_NA, &seqId);
1416 *seq_id = seqId;
1417 offset += 1;
1418 /* E bit */
1419 proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_e_bit, tvb, offset, 1, ENC_NA, &e);
1420 /* Subsequence ID (7 bits) */
1421 proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_subsequence_id, tvb, offset, 1, ENC_NA, &subSeqId);
1422 offset += 1;
1424 /* radio-transport fragmentation not allowed for C-Plane messages */
1425 if (plane == ORAN_C_PLANE) {
1426 if (e !=1 || subSeqId != 0) {
1427 expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_c_plane);
1430 else {
1431 if (e !=1 || subSeqId != 0) {
1432 /* TODO: Re-assembly of any radio-fragmentation on U-Plane */
1433 expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_u_plane);
1437 /* Summary */
1438 proto_item_append_text(seqIdItem, " (SeqId: %3d, E: %d, SubSeqId: %d)", seqId, e, subSeqId);
1440 return offset;
1443 /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
1444 static int dissect_bfwCompHdr(tvbuff_t *tvb, proto_tree *tree, int offset,
1445 uint32_t *iq_width, uint32_t *comp_meth, proto_item **comp_meth_ti)
1447 /* Subtree */
1448 proto_item *bfwcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompHdr,
1449 tvb, offset, 1, "",
1450 "bfwCompHdr");
1451 proto_tree *bfwcomphdr_tree = proto_item_add_subtree(bfwcomphdr_ti, ett_oran_bfwcomphdr);
1453 /* Width and method */
1454 proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_iqWidth,
1455 tvb, offset, 1, ENC_BIG_ENDIAN, iq_width);
1456 /* Special case: 0 -> 16 */
1457 *iq_width = (*iq_width==0) ? 16 : *iq_width;
1458 *comp_meth_ti = proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_compMeth,
1459 tvb, offset, 1, ENC_BIG_ENDIAN, comp_meth);
1460 offset++;
1462 /* Summary */
1463 proto_item_append_text(bfwcomphdr_ti, " (IqWidth=%u, compMeth=%s)",
1464 *iq_width,
1465 val_to_str_const(*comp_meth, bfw_comp_headers_comp_meth, "reserved"));
1467 return offset;
1470 /* 7.7.1.3 bfwCompParam (beamforming weight compression parameter).
1471 * Depends upon passed-in bfwCompMeth (field may be empty) */
1472 static int dissect_bfwCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset,
1473 proto_item *meth_ti, uint32_t bfw_comp_method,
1474 uint32_t *exponent, bool *supported)
1476 if (bfw_comp_method == COMP_NONE) {
1477 /* Absent! */
1478 *supported = true;
1479 return offset;
1482 /* Subtree */
1483 proto_item *bfwcompparam_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompParam,
1484 tvb, offset, 1, "",
1485 "bfwCompParam");
1486 proto_tree *bfwcompparam_tree = proto_item_add_subtree(bfwcompparam_ti, ett_oran_bfwcompparam);
1488 proto_item_append_text(bfwcompparam_ti,
1489 " (meth=%s)", val_to_str_const(bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
1491 *supported = false;
1492 switch (bfw_comp_method) {
1493 case COMP_BLOCK_FP: /* block floating point */
1494 /* 4 reserved bits + exponent */
1495 proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent,
1496 tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
1497 proto_item_append_text(bfwcompparam_ti, " exponent=%u", *exponent);
1498 *supported = true;
1499 offset++;
1500 break;
1501 case COMP_BLOCK_SCALE: /* block scaling */
1502 /* Separate into integer and fractional bits? */
1503 proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
1504 tvb, offset, 1, ENC_BIG_ENDIAN);
1505 offset++;
1506 break;
1507 case COMP_U_LAW: /* u-law */
1508 /* compBitWidth, compShift */
1509 proto_tree_add_item(bfwcompparam_tree, hf_oran_compBitWidth,
1510 tvb, offset, 1, ENC_BIG_ENDIAN);
1511 proto_tree_add_item(bfwcompparam_tree, hf_oran_compShift,
1512 tvb, offset, 1, ENC_BIG_ENDIAN);
1513 offset++;
1514 break;
1515 case 4: /* beamspace I */
1516 /* TODO: activeBeamspaceCoefficientMask - ceil(K/8) octets */
1517 /* proto_tree_add_item(extension_tree, hf_oran_blockScaler,
1518 tvb, offset, 1, ENC_BIG_ENDIAN);
1519 offset++; */
1520 break;
1521 case 5: /* beamspace II */
1522 /* TODO: activeBeamspaceCoefficientMask - ceil(K/8) octets */
1523 /* reserved (4 bits) + exponent (4 bits)
1524 proto_tree_add_item(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
1525 proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent, tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
1526 offset += 1;
1528 break;
1530 default:
1531 /* Not handled */
1532 break;
1535 /* Can't go on if compression scheme not supported */
1536 if (!(*supported) && meth_ti) {
1537 expert_add_info_format(pinfo, meth_ti, &ei_oran_unsupported_bfw_compression_method,
1538 "BFW Compression method %u (%s) not supported by dissector",
1539 bfw_comp_method,
1540 val_to_str_const(bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
1542 return offset;
1546 /* Special case for uncompressed/16-bit value */
1547 static float uncompressed_to_float(uint32_t h)
1549 int16_t i16 = h & 0x0000ffff;
1550 return ((float)i16) / 0x7fff;
1553 /* Decompress I/Q value, taking into account method, width, other input-specific methods */
1554 static float decompress_value(uint32_t bits, uint32_t comp_method, uint8_t iq_width, uint32_t exponent)
1556 switch (comp_method) {
1557 case COMP_NONE: /* no compression */
1558 return uncompressed_to_float(bits);
1560 case COMP_BLOCK_FP: /* block floating point */
1562 /* A.1.2 Block Floating Point Decompression Algorithm */
1563 int32_t cPRB = bits;
1564 uint32_t scaler = 1 << exponent; /* i.e. 2^exponent */
1566 /* Check last bit, in case we need to flip to -ve */
1567 if (cPRB >= (1<<(iq_width-1))) {
1568 cPRB -= (1<<iq_width);
1571 const uint8_t mantissa_bits = iq_width-1;
1572 return (cPRB / (float)(1 << (mantissa_bits))) * scaler;
1575 case COMP_BLOCK_SCALE:
1576 case COMP_U_LAW:
1577 case COMP_MODULATION:
1578 case BFP_AND_SELECTIVE_RE:
1579 case MOD_COMPR_AND_SELECTIVE_RE:
1580 default:
1581 /* Not supported! */
1582 return 0.0;
1586 /* Out-of-range value used for special case */
1587 #define ORPHAN_BUNDLE_NUMBER 999
1589 /* Bundle of PRBs/TRX I/Q samples (ext 11) */
1590 static uint32_t dissect_bfw_bundle(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, unsigned offset,
1591 proto_item *comp_meth_ti, uint32_t bfwcomphdr_comp_meth,
1592 uint32_t num_weights_per_bundle,
1593 uint8_t iq_width,
1594 unsigned bundle_number,
1595 unsigned first_prb, unsigned last_prb, bool is_orphan)
1597 /* Set bundle name */
1598 char bundle_name[32];
1599 if (!is_orphan) {
1600 snprintf(bundle_name, 32, "Bundle %3u", bundle_number);
1602 else {
1603 g_strlcpy(bundle_name, "Orphaned ", 32);
1606 /* Create Bundle root */
1607 proto_item *bundle_ti;
1608 if (first_prb != last_prb) {
1609 bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
1610 tvb, offset, 0, "",
1611 "%s: (PRBs %3u-%3u)",
1612 bundle_name,
1613 first_prb, last_prb);
1615 else {
1616 bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
1617 tvb, offset, 0, "",
1618 "%s: (PRB %3u)",
1619 bundle_name,
1620 first_prb);
1622 proto_tree *bundle_tree = proto_item_add_subtree(bundle_ti, ett_oran_bfw_bundle);
1624 /* Generated bundle id */
1625 proto_item *bundleid_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfw_bundle_id, tvb, 0, 0,
1626 bundle_number);
1627 proto_item_set_generated(bundleid_ti);
1628 proto_item_set_hidden(bundleid_ti);
1630 /* bfwCompParam */
1631 bool compression_method_supported = false;
1632 unsigned exponent = 0;
1633 offset = dissect_bfwCompParam(tvb, bundle_tree, pinfo, offset, comp_meth_ti,
1634 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
1636 /* Can't show details of unsupported compression method */
1637 if (!compression_method_supported) {
1638 /* Don't know how to show, so give up */
1639 return offset;
1642 /* Create Bundle subtree */
1643 int bit_offset = offset*8;
1644 int bfw_offset;
1645 int prb_offset = offset;
1647 /* contInd */
1648 proto_tree_add_item(bundle_tree, hf_oran_cont_ind,
1649 tvb, offset, 1, ENC_BIG_ENDIAN);
1650 /* beamId */
1651 uint32_t beam_id;
1652 proto_tree_add_item_ret_uint(bundle_tree, hf_oran_beam_id, tvb, offset, 2, ENC_BIG_ENDIAN, &beam_id);
1653 proto_item_append_text(bundle_ti, " (beamId:%u) ", beam_id);
1654 bit_offset += 16;
1656 /* Number of weights per bundle (from preference) */
1657 proto_item *wpb_ti = proto_tree_add_uint(bundle_tree, hf_oran_num_weights_per_bundle, tvb, 0, 0,
1658 num_weights_per_bundle);
1659 proto_item_set_generated(wpb_ti);
1661 /* Add the weights for this bundle */
1662 for (unsigned w=0; w < num_weights_per_bundle; w++) {
1664 /* Create subtree */
1665 bfw_offset = bit_offset / 8;
1666 uint8_t bfw_extent = ((bit_offset + (iq_width*2)) / 8) - bfw_offset;
1667 proto_item *bfw_ti = proto_tree_add_string_format(bundle_tree, hf_oran_bfw,
1668 tvb, bfw_offset, bfw_extent,
1669 "", "TRX %3u: (", w);
1670 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
1672 /* I */
1673 /* Get bits, and convert to float. */
1674 uint32_t bits = tvb_get_bits(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
1675 float value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width, exponent);
1676 /* Add to tree. */
1677 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);
1678 bit_offset += iq_width;
1679 proto_item_append_text(bfw_ti, "I%u=%f ", w, value);
1681 /* Q */
1682 /* Get bits, and convert to float. */
1683 bits = tvb_get_bits(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
1684 value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width, exponent);
1685 /* Add to tree. */
1686 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);
1687 bit_offset += iq_width;
1688 proto_item_append_text(bfw_ti, "Q%u=%f)", w, value);
1691 /* Set extent of bundle */
1692 proto_item_set_len(bundle_ti, (bit_offset+7)/8 - prb_offset);
1694 return (bit_offset+7)/8;
1697 /* Return new bit offset. in/out will always be byte-aligned.. */
1698 static int dissect_ciCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, unsigned bit_offset,
1699 unsigned comp_meth, uint8_t *exponent)
1701 if (comp_meth == COMP_NONE) {
1702 /* Nothing in frame so don't even create subtree */
1703 return bit_offset;
1706 /* Subtree */
1707 proto_item *cicompparam_ti = proto_tree_add_string_format(tree, hf_oran_ciCompParam,
1708 tvb, bit_offset/8, 1, "",
1709 "ciCompParam");
1710 proto_tree *cicompparam_tree = proto_item_add_subtree(cicompparam_ti, ett_oran_cicompparam);
1711 uint32_t ci_exponent;
1713 /* Contents differ by compression method */
1714 switch (comp_meth) {
1715 case COMP_BLOCK_FP:
1716 proto_tree_add_item(cicompparam_tree, hf_oran_reserved_4bits, tvb, bit_offset/8, 1, ENC_NA);
1717 proto_tree_add_item_ret_uint(cicompparam_tree, hf_oran_exponent,
1718 tvb, bit_offset/8, 1, ENC_BIG_ENDIAN, &ci_exponent);
1719 *exponent = ci_exponent;
1720 proto_item_append_text(cicompparam_ti, " (Exponent=%u)", ci_exponent);
1721 bit_offset += 8; /* one byte */
1722 break;
1723 case COMP_BLOCK_SCALE:
1724 /* Separate into integer and fractional bits? */
1725 proto_tree_add_item(cicompparam_tree, hf_oran_blockScaler,
1726 tvb, bit_offset*8, 1, ENC_BIG_ENDIAN);
1727 bit_offset += 8;
1728 break;
1729 case COMP_U_LAW:
1730 /* compBitWidth, compShift */
1731 proto_tree_add_item(cicompparam_tree, hf_oran_compBitWidth,
1732 tvb, bit_offset*8, 1, ENC_BIG_ENDIAN);
1733 proto_tree_add_item(cicompparam_tree, hf_oran_compShift,
1734 tvb, bit_offset*8, 1, ENC_BIG_ENDIAN);
1735 bit_offset += 8;
1736 break;
1738 default:
1739 /* reserved, ? bytes of zeros.. */
1740 break;
1743 return bit_offset;
1746 /* frameStructure (7.5.2.13) */
1747 static unsigned dissect_frame_structure(proto_item *tree, tvbuff_t *tvb, unsigned offset,
1748 uint32_t subframeId, uint32_t slotId)
1750 uint32_t scs;
1751 /* FFT Size (4 bits) */
1752 proto_tree_add_item(tree, hf_oran_frameStructure_fft, tvb, offset, 1, ENC_NA);
1753 /* Subcarrier spacing (SCS) */
1754 proto_tree_add_item_ret_uint(tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
1756 /* Show slot within frame as a generated field. See table 7.5.13-3 */
1757 uint32_t slots_per_subframe = 1;
1758 if (scs <= 4) {
1759 slots_per_subframe = 1 << scs;
1761 if (scs <= 4 || scs >= 12) {
1762 proto_item *ti = proto_tree_add_uint(tree, hf_oran_slot_within_frame, tvb, 0, 0,
1763 (slots_per_subframe*subframeId) + slotId);
1764 proto_item_set_generated(ti);
1766 return offset + 1;
1769 static unsigned dissect_csf(proto_item *tree, tvbuff_t *tvb, unsigned bit_offset,
1770 unsigned iq_width, bool *p_csf)
1772 proto_item *csf_ti;
1773 uint64_t csf;
1774 csf_ti = proto_tree_add_bits_ret_val(tree, hf_oran_csf, tvb, bit_offset, 1, &csf, ENC_BIG_ENDIAN);
1775 if (csf) {
1776 /* Table 7.7.4.2-1 Constellation shift definition (index is udIqWidth) */
1777 const char* shift_value[] = { "n/a", "1/2", "1/4", "1/8", "1/16", "1/32" };
1778 if (iq_width >=1 && iq_width <= 5) {
1779 proto_item_append_text(csf_ti, " (Shift Value is %s)", shift_value[iq_width]);
1783 /* Set out parameter */
1784 if (p_csf != NULL) {
1785 *p_csf = (csf!=0);
1787 return bit_offset+1;
1791 /* Section 7.
1792 * N.B. these are the green parts of the tables showing Section Types, differing by section Type */
1793 static int dissect_oran_c_section(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
1794 flow_state_t* state,
1795 uint32_t sectionType, proto_item *protocol_item,
1796 uint32_t subframeId, uint32_t slotId,
1797 uint8_t ci_iq_width, uint8_t ci_comp_meth, unsigned ci_comp_opt,
1798 unsigned num_sinr_per_prb)
1800 unsigned offset = 0;
1801 proto_tree *c_section_tree = NULL;
1802 proto_item *sectionHeading = NULL;
1804 c_section_tree = proto_tree_add_subtree(tree, tvb, offset, 0, ett_oran_section, &sectionHeading, "Section");
1805 uint32_t sectionId = 0;
1807 uint32_t startPrbc, startPrbu;
1808 uint32_t numPrbc, numPrbu;
1809 uint32_t ueId = 0;
1810 uint32_t beamId = 0;
1811 proto_item *beamId_ti = NULL;
1812 bool beamId_ignored = false;
1814 proto_item *numprbc_ti = NULL;
1816 /* Config affecting ext11 bundles (initially unset) */
1817 ext11_settings_t ext11_settings;
1818 memset(&ext11_settings, 0, sizeof(ext11_settings));
1820 bool extension_flag = false;
1822 /* These sections (ST0, ST1, ST2, ST3, ST5, ST9) are similar, so handle as common with per-type differences */
1823 if (((sectionType <= SEC_C_UE_SCHED) || (sectionType == SEC_C_SINR_REPORTING)) && (sectionType != SEC_C_SLOT_CONTROL)) {
1824 /* sectionID */
1825 proto_item *ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
1826 if (sectionId == 4095) {
1827 proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
1829 offset++;
1831 /* rb */
1832 uint32_t rb;
1833 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
1834 /* symInc */
1835 proto_tree_add_item(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
1836 /* startPrbx and numPrbx */
1837 if (sectionType == SEC_C_SINR_REPORTING) {
1838 /* startPrbu (10 bits) */
1839 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
1840 offset += 2;
1841 /* numPrbu */
1842 numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
1843 if (numPrbu == 0) {
1844 proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
1845 numPrbu = pref_data_plane_section_total_rbs;
1847 offset += 1;
1849 else {
1850 /* startPrbc (10 bits) */
1851 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
1852 offset += 2;
1853 /* numPrbc */
1854 numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
1855 if (numPrbc == 0) {
1856 proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
1858 offset += 1;
1861 if (sectionType != SEC_C_SINR_REPORTING) {
1862 /* reMask */
1863 proto_tree_add_item(c_section_tree, hf_oran_reMask, tvb, offset, 2, ENC_BIG_ENDIAN);
1864 offset++;
1865 /* numSymbol */
1866 uint32_t numSymbol;
1867 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numSymbol, tvb, offset, 1, ENC_NA, &numSymbol);
1868 offset++;
1870 /* [ef] (extension flag) */
1871 switch (sectionType) {
1872 case SEC_C_UNUSED_RB: /* Section Type 0 */
1873 case SEC_C_NORMAL: /* Section Type 1 */
1874 case SEC_C_PRACH: /* Section Type 3 */
1875 case SEC_C_UE_SCHED: /* Section Type 5 */
1876 proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
1877 break;
1878 default:
1879 /* Other section types don't support extensions */
1880 break;
1883 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbc, numPrbc, rb);
1884 proto_item_append_text(sectionHeading, ", Symbols: %2u", numSymbol);
1886 if (numPrbc == 0) {
1887 /* Special case for all PRBs */
1888 numPrbc = pref_data_plane_section_total_rbs;
1889 startPrbc = 0; /* may already be 0... */
1892 else {
1893 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
1894 proto_item_append_text(sectionHeading, ", numSinrPrPrb: %2u", num_sinr_per_prb);
1897 /* Section type specific fields (after 'numSymbol') */
1898 switch (sectionType) {
1899 case SEC_C_UNUSED_RB: /* Section Type 0 - Table 7.4.2-1 */
1900 /* reserved (15 bits) */
1901 proto_tree_add_item(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2, ENC_NA);
1902 offset += 2;
1903 break;
1905 case SEC_C_NORMAL: /* Section Type 1 - Table 7.4.3-1 */
1906 /* beamId */
1907 beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
1908 offset += 2;
1910 proto_item_append_text(sectionHeading, ", BeamId: %d", beamId);
1911 break;
1913 case SEC_C_PRACH: /* Section Type 3 - Table 7.4.5-1 */
1915 /* beamId */
1916 beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
1917 offset += 2;
1919 /* freqOffset */
1920 int32_t freqOffset; /* Yes, this is signed, so the implicit cast is intentional. */
1921 proto_item *freq_offset_item = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN, &freqOffset);
1922 freqOffset |= 0xff000000; /* Must sign-extend */
1923 proto_item_set_text(freq_offset_item, "Frequency offset: %d \u0394f", freqOffset);
1924 offset += 3;
1926 /* reserved */
1927 proto_tree_add_item(c_section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
1928 offset += 1;
1930 proto_item_append_text(sectionHeading, ", BeamId: %d, FreqOffset: %d \u0394f", beamId, freqOffset);
1931 break;
1934 case SEC_C_UE_SCHED: /* Section Type 5 - Table 7.4.7-1 */
1935 /* ueId */
1936 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_NA, &ueId);
1937 offset += 2;
1939 proto_item_append_text(sectionHeading, ", UEId: %d", ueId);
1940 break;
1942 case SEC_C_SINR_REPORTING: /* Section Type 9 - SINR Reporting */
1944 unsigned bit_offset = offset+8;
1946 /* TODO: alternates if 'rb' set? */
1947 for (unsigned prb=startPrbu; prb < startPrbu+numPrbu; prb++) {
1948 /* TODO: create a subtree for each PRB entry with good summary? */
1950 /* Each prb starts bit-aligned */
1951 bit_offset = ((bit_offset+7)/8) * 8;
1953 /* N.B., using width/method from UL U-plane preferences, not certain that this is correct.. */
1955 /* sinrCompParam */
1956 uint32_t exponent;
1957 uint16_t sReSMask;
1958 offset = dissect_udcompparam(tvb, pinfo, c_section_tree, bit_offset/8,
1959 pref_iqCompressionUplink, &exponent, &sReSMask,
1960 true); /* last param is for_sinr */
1962 /* SINR Values for this PRB */
1963 for (unsigned n=0; n < num_sinr_per_prb; n++) {
1964 unsigned sinr_bits = tvb_get_bits(tvb, bit_offset, pref_sample_bit_width_uplink, ENC_BIG_ENDIAN);
1966 float value = decompress_value(sinr_bits, pref_iqCompressionUplink, pref_sample_bit_width_uplink, exponent);
1967 unsigned sample_len_in_bytes = ((bit_offset%8)+pref_sample_bit_width_uplink+7)/8;
1968 proto_item *val_ti = proto_tree_add_float(c_section_tree, hf_oran_sinr_value, tvb,
1969 bit_offset/8, sample_len_in_bytes, value);
1970 proto_item_append_text(val_ti, " (#%u for PRB=%u)", n+1, prb);
1972 bit_offset += pref_sample_bit_width_uplink;
1975 break;
1978 default:
1979 break;
1982 else if (sectionType == SEC_C_CH_INFO) { /* Section Type 6 */
1983 /* ef */
1984 proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
1985 /* ueId */
1986 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_NA, &ueId);
1987 offset += 2;
1988 /* regularizationFactor */
1989 proto_tree_add_item(c_section_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_NA);
1990 offset += 2;
1991 /* reserved */
1992 proto_tree_add_item(c_section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
1993 /* rb */
1994 proto_tree_add_item(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA);
1995 /* symInc */
1996 proto_tree_add_item(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
1997 /* startPrbc */
1998 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
1999 offset += 2;
2000 /* numPrbc */
2001 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
2002 offset += 1;
2004 /* ciIsample,ciQsample pairs */
2005 unsigned m;
2006 unsigned prb;
2007 uint32_t bit_offset = offset*8;
2009 /* Antenna count from preference */
2010 unsigned num_trx = pref_num_bf_antennas;
2012 write_channel_section_info(sectionHeading, pinfo,
2013 sectionId, ueId, startPrbc, numPrbc, num_trx);
2015 bool first_prb = true;
2016 uint8_t exponent = 0;
2017 for (prb=startPrbc; prb < startPrbc+numPrbc; prb++) {
2019 /* PRB subtree */
2020 unsigned prb_start_offset = bit_offset;
2021 proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_samples_prb,
2022 tvb, bit_offset/8, 0,
2023 "", "PRB=%u", prb);
2024 proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_prb_cisamples);
2026 /* There may be a ciCompParam here.. */
2027 if (first_prb || ci_comp_opt==1) {
2028 bit_offset = dissect_ciCompParam(tvb, prb_tree, pinfo, bit_offset, ci_comp_meth, &exponent);
2030 first_prb = false;
2032 /* Antennas */
2033 for (m=0; m < num_trx; m++) {
2035 unsigned sample_offset = bit_offset / 8;
2036 uint8_t sample_extent = ((bit_offset + (ci_iq_width*2)) / 8) - sample_offset;
2038 /* Create subtree for antenna */
2039 proto_item *sample_ti = proto_tree_add_string_format(prb_tree, hf_oran_ciSample,
2040 tvb, sample_offset, sample_extent,
2041 "", "TRX=%2u: ", m);
2042 proto_tree *sample_tree = proto_item_add_subtree(sample_ti, ett_oran_cisample);
2044 /* I */
2045 /* Get bits, and convert to float. */
2046 uint32_t bits = tvb_get_bits(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2047 float value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent);
2049 /* Add to tree. */
2050 proto_tree_add_float_format_value(sample_tree, hf_oran_ciIsample, tvb, bit_offset/8, (16+7)/8, value, "#%u=%f", m, value);
2051 bit_offset += ci_iq_width;
2052 proto_item_append_text(sample_ti, "I%u=%f ", m, value);
2054 /* Q */
2055 /* Get bits, and convert to float. */
2056 bits = tvb_get_bits(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2057 value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent);
2059 /* Add to tree. */
2060 proto_tree_add_float_format_value(sample_tree, hf_oran_ciQsample, tvb, bit_offset/8, (16+7)/8, value, "#%u=%f", m, value);
2061 bit_offset += ci_iq_width;
2062 proto_item_append_text(sample_ti, "Q%u=%f ", m, value);
2064 proto_item_set_len(prb_ti, (bit_offset-prb_start_offset)/8);
2066 offset = (bit_offset/8);
2068 else if (sectionType == SEC_C_LAA) { /* Section Type 7 */
2069 /* 7.2.5 Table 6.4-6 */
2070 /* N.B. untested */
2071 unsigned mcot;
2072 proto_item *mcot_ti;
2074 /* laaMsgType */
2075 uint32_t laa_msg_type;
2076 proto_item *laa_msg_type_ti;
2077 laa_msg_type_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_laaMsgType, tvb, offset, 1, ENC_NA, &laa_msg_type);
2078 /* laaMsgLen */
2079 uint32_t laa_msg_len;
2080 proto_item *len_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_laaMsgLen, tvb, offset, 1, ENC_NA, &laa_msg_len);
2081 proto_item_append_text(len_ti, " (%u bytes)", 4*(laa_msg_len+1));
2082 offset += 1;
2084 int payload_offset = offset;
2086 /* Payload */
2087 switch (laa_msg_type) {
2088 case 0:
2089 /* LBT_PDSCH_REQ */
2090 /* lbtHandle (16 bits) */
2091 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2092 offset += 2;
2093 /* lbtOffset (10 bits) */
2094 proto_tree_add_item(c_section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
2095 offset += 1;
2096 /* lbtMode (2 bits) */
2097 proto_tree_add_bits_item(c_section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
2098 /* reserved (1 bit) */
2099 proto_tree_add_item(c_section_tree, hf_oran_laa_msgtype0_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2100 /* lbtDeferFactor (3 bits) */
2101 proto_tree_add_item(c_section_tree, hf_oran_lbtDeferFactor, tvb, offset, 1, ENC_BIG_ENDIAN);
2102 offset += 1;
2103 /* lbtBackoffCounter (10 bits) */
2104 proto_tree_add_item(c_section_tree, hf_oran_lbtBackoffCounter, tvb, offset, 2, ENC_BIG_ENDIAN);
2105 offset += 1;
2106 /* MCOT (4 bits) */
2107 mcot_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_MCOT, tvb, offset, 1, ENC_BIG_ENDIAN, &mcot);
2108 if (mcot<1 || mcot>10) {
2109 proto_item_append_text(mcot_ti, " (should be in range 1-10!)");
2110 expert_add_info_format(pinfo, mcot_ti, &ei_oran_mcot_out_of_range,
2111 "MCOT seen with value %u (must be 1-10)", mcot);
2114 /* reserved (10 bits) */
2115 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+6, 10, ENC_BIG_ENDIAN);
2116 break;
2117 case 1:
2118 /* LBT_DRS_REQ */
2119 /* lbtHandle (16 bits) */
2120 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2121 offset += 2;
2122 /* lbtOffset (10 bits) */
2123 proto_tree_add_item(c_section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
2124 offset += 1;
2125 /* lbtMode (2 bits) */
2126 proto_tree_add_bits_item(c_section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
2127 /* reserved (28 bits) */
2128 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+4, 28, ENC_BIG_ENDIAN);
2129 break;
2130 case 2:
2131 /* LBT_PDSCH_RSP */
2132 /* lbtHandle (16 bits) */
2133 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2134 offset += 2;
2135 /* lbtPdschRes (2 bits) */
2136 proto_tree_add_item(c_section_tree, hf_oran_lbtPdschRes, tvb, offset, 1, ENC_BIG_ENDIAN);
2137 /* inParSF (1 bit) */
2138 proto_tree_add_item(c_section_tree, hf_oran_initialPartialSF, tvb, offset, 1, ENC_BIG_ENDIAN);
2139 /* sfStatus (1 bit) */
2140 proto_tree_add_item(c_section_tree, hf_oran_sfStatus, tvb, offset, 1, ENC_BIG_ENDIAN);
2141 /* sfnSf (12 bits) */
2142 proto_tree_add_item(c_section_tree, hf_oran_sfnSfEnd, tvb, offset, 2, ENC_BIG_ENDIAN);
2143 offset += 2;
2144 /* reserved (24 bits) */
2145 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8), 24, ENC_BIG_ENDIAN);
2146 break;
2147 case 3:
2148 /* LBT_DRS_RSP */
2149 /* lbtHandle (16 bits) */
2150 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2151 offset += 2;
2152 /* lbtDrsRes (1 bit) */
2153 proto_tree_add_item(c_section_tree, hf_oran_lbtDrsRes, tvb, offset, 1, ENC_BIG_ENDIAN);
2154 /* reserved (7 bits) */
2155 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+1, 7, ENC_BIG_ENDIAN);
2156 break;
2157 case 4:
2158 /* LBT_Buffer_Error */
2159 /* lbtHandle (16 bits) */
2160 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2161 offset += 2;
2162 /* lbtBufErr (1 bit) */
2163 proto_tree_add_item(c_section_tree, hf_oran_lbtBufErr, tvb, offset, 1, ENC_BIG_ENDIAN);
2164 /* reserved (7 bits) */
2165 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+1, 7, ENC_BIG_ENDIAN);
2166 break;
2167 case 5:
2168 /* LBT_CWCONFIG_REQ */
2169 /* lbtHandle (16 bits) */
2170 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2171 offset += 2;
2172 /* lbtCWConfig_H (8 bits) */
2173 proto_tree_add_item(c_section_tree, hf_oran_lbtCWConfig_H, tvb, offset, 1, ENC_BIG_ENDIAN);
2174 offset += 1;
2175 /* lbtCWConfig_T (8 bits) */
2176 proto_tree_add_item(c_section_tree, hf_oran_lbtCWConfig_T, tvb, offset, 1, ENC_BIG_ENDIAN);
2177 offset += 1;
2178 /* lbtMode (2 bits) */
2179 proto_tree_add_bits_item(c_section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
2180 /* lbtTrafficClass (3 bits) */
2181 proto_tree_add_item(c_section_tree, hf_oran_lbtTrafficClass, tvb, offset, 1, ENC_BIG_ENDIAN);
2182 /* reserved (19 bits) */
2183 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+5, 19, ENC_BIG_ENDIAN);
2184 break;
2185 case 6:
2186 /* LBT_CWCONFIG_RSP */
2187 /* lbtHandle (16 bits) */
2188 proto_tree_add_item(c_section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
2189 offset += 2;
2190 /* lbtCWR_Rst (1 bit) */
2191 proto_tree_add_item(c_section_tree, hf_oran_lbtCWR_Rst, tvb, offset, 1, ENC_BIG_ENDIAN);
2192 /* reserved (7 bits) */
2193 proto_tree_add_bits_item(c_section_tree, hf_oran_reserved, tvb, (offset*8)+1, 7, ENC_BIG_ENDIAN);
2194 break;
2196 default:
2197 /* Unhandled! */
2198 expert_add_info_format(pinfo, laa_msg_type_ti, &ei_oran_laa_msg_type_unsupported,
2199 "laaMsgType %u not supported by dissector",
2200 laa_msg_type);
2202 break;
2204 /* For now just skip indicated length of bytes */
2205 offset = payload_offset + 4*(laa_msg_len+1);
2208 bool seen_se10 = false;
2209 uint32_t numPortc = 0;
2211 /* Section extension commands */
2212 while (extension_flag) {
2214 int extension_start_offset = offset;
2216 /* Create subtree for each extension (with summary) */
2217 proto_item *extension_ti = proto_tree_add_string_format(c_section_tree, hf_oran_extension,
2218 tvb, offset, 0, "", "Extension");
2219 proto_tree *extension_tree = proto_item_add_subtree(extension_ti, ett_oran_c_section_extension);
2221 /* ef (i.e. another extension after this one?) */
2222 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2224 /* extType */
2225 uint32_t exttype;
2226 proto_item *exttype_ti;
2227 exttype_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_exttype, tvb, offset, 1, ENC_BIG_ENDIAN, &exttype);
2228 offset++;
2229 proto_item_append_text(sectionHeading, " (ext-%u)", exttype);
2231 proto_item_append_text(extension_ti, " (ext-%u: %s)", exttype, val_to_str_const(exttype, exttype_vals, "Reserved"));
2233 /* Is this SE allowed for this section type? */
2234 if (!se_allowed_in_st(exttype, sectionType)) {
2235 expert_add_info_format(pinfo, extension_tree, &ei_oran_se_on_unsupported_st,
2236 "SE %u (%s) should not appear in ST %u (%s)!",
2237 exttype, val_to_str_const(exttype, exttype_vals, "Reserved"),
2238 sectionType, rval_to_str_const(sectionType, section_types, "Unknown"));
2242 /* extLen (number of 32-bit words) */
2243 uint32_t extlen_len = ((exttype==11)||(exttype==19)||(exttype==20)) ? 2 : 1; /* Extensions 11/19/20 are special */
2244 uint32_t extlen;
2245 proto_item *extlen_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_extlen, tvb,
2246 offset, extlen_len, ENC_BIG_ENDIAN, &extlen);
2247 proto_item_append_text(extlen_ti, " (%u bytes)", extlen*4);
2248 offset += extlen_len;
2249 if (extlen == 0) {
2250 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_zero,
2251 "extlen value of 0 is reserved");
2252 /* Break out to avoid infinitely looping! */
2253 break;
2256 bool ext_unhandled = false;
2258 switch (exttype) {
2260 case 1: /* SE 1: Beamforming Weights */
2262 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
2263 proto_item *comp_meth_ti = NULL;
2265 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
2266 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
2267 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
2269 /* bfwCompParam */
2270 uint32_t exponent = 0;
2271 bool compression_method_supported = false;
2272 offset = dissect_bfwCompParam(tvb, extension_tree, pinfo, offset, comp_meth_ti,
2273 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
2275 /* Can't show details of unsupported compression method */
2276 if (!compression_method_supported) {
2277 break;
2280 /* We know:
2281 - iq_width (above)
2282 - numBfWeights (taken from preference)
2283 - remaining bytes in extension
2284 We can therefore derive TRX (number of antennas).
2287 /* I & Q samples
2288 Don't know how many there will be, so just fill available bytes...
2290 unsigned weights_bytes = (extlen*4)-3;
2291 unsigned num_weights_pairs = (weights_bytes*8) / (bfwcomphdr_iq_width*2);
2292 unsigned num_trx = num_weights_pairs;
2293 int bit_offset = offset*8;
2295 for (unsigned n=0; n < num_trx; n++) {
2296 /* Create antenna subtree */
2297 int bfw_offset = bit_offset / 8;
2298 proto_item *bfw_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfw,
2299 tvb, bfw_offset, 0, "", "TRX %3u: (", n);
2300 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
2302 /* I value */
2303 /* Get bits, and convert to float. */
2304 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
2305 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
2306 /* Add to tree. */
2307 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
2308 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
2309 bit_offset += bfwcomphdr_iq_width;
2310 proto_item_append_text(bfw_ti, "I=%f ", value);
2312 /* Leave a gap between I and Q values */
2313 proto_item_append_text(bfw_ti, " ");
2315 /* Q value */
2316 /* Get bits, and convert to float. */
2317 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
2318 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
2319 /* Add to tree. */
2320 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
2321 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
2322 bit_offset += bfwcomphdr_iq_width;
2323 proto_item_append_text(bfw_ti, "Q=%f", value);
2325 proto_item_append_text(bfw_ti, ")");
2326 proto_item_set_len(bfw_ti, (bit_offset+7)/8 - bfw_offset);
2328 /* Need to round to next byte */
2329 offset = (bit_offset+7)/8;
2331 break;
2334 case 2: /* SE 2: Beamforming attributes */
2336 /* bfaCompHdr (get widths of fields to follow) */
2337 uint32_t bfAzPtWidth, bfZePtWidth, bfAz3ddWidth, bfZe3ddWidth;
2338 /* subtree */
2339 proto_item *bfa_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfaCompHdr,
2340 tvb, offset, 2, "", "bfaCompHdr");
2341 proto_tree *bfa_tree = proto_item_add_subtree(bfa_ti, ett_oran_bfacomphdr);
2343 /* reserved (2 bits) */
2344 proto_tree_add_item(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2345 /* bfAzPtWidth (3 bits) */
2346 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAzPtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAzPtWidth);
2347 /* bfZePtWidth (3 bits) */
2348 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZePtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZePtWidth);
2349 offset += 1;
2351 /* reserved (2 bits) */
2352 proto_tree_add_item(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2353 /* bfAz3ddWidth (3 bits) */
2354 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAz3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAz3ddWidth);
2355 /* bfZe3ddWidth (3 bits) */
2356 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZe3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZe3ddWidth);
2357 offset += 1;
2359 unsigned bit_offset = offset*8;
2361 /* bfAzPt */
2362 if (bfAzPtWidth > 0) {
2363 proto_tree_add_bits_item(extension_tree, hf_oran_bfAzPt, tvb, bit_offset, bfAzPtWidth+1, ENC_BIG_ENDIAN);
2364 bit_offset += (bfAzPtWidth+1);
2366 /* bfZePt */
2367 if (bfZePtWidth > 0) {
2368 proto_tree_add_bits_item(extension_tree, hf_oran_bfZePt, tvb, bit_offset, bfZePtWidth+1, ENC_BIG_ENDIAN);
2369 bit_offset += (bfZePtWidth+1);
2371 /* bfAz3dd */
2372 if (bfAz3ddWidth > 0) {
2373 proto_tree_add_bits_item(extension_tree, hf_oran_bfAz3dd, tvb, bit_offset, bfAz3ddWidth+1, ENC_BIG_ENDIAN);
2374 bit_offset += (bfAz3ddWidth+1);
2376 /* bfZe3dd */
2377 if (bfZe3ddWidth > 0) {
2378 proto_tree_add_bits_item(extension_tree, hf_oran_bfZe3dd, tvb, bit_offset, bfZe3ddWidth+1, ENC_BIG_ENDIAN);
2379 bit_offset += (bfZe3ddWidth+1);
2382 /* go to next byte (zero-padding.. - a little confusing..) */
2383 offset = (bit_offset+7) / 8;
2385 /* 2 reserved/padding bits */
2386 /* bfAzSl (3 bits) */
2387 proto_tree_add_item(extension_tree, hf_oran_bfAzSl, tvb, offset, 1, ENC_BIG_ENDIAN);
2388 /* bfZeSl (3 bits) */
2389 proto_tree_add_item(extension_tree, hf_oran_bfZeSl, tvb, offset, 1, ENC_BIG_ENDIAN);
2390 break;
2393 case 3: /* SE 3: TODO: DL precoding parameters */
2395 /* codebookindex */
2396 proto_tree_add_item(extension_tree, hf_oran_codebook_index, tvb, offset, 1, ENC_BIG_ENDIAN);
2397 offset += 1;
2398 /* layerid */
2399 uint32_t layerid;
2400 proto_tree_add_item_ret_uint(extension_tree, hf_oran_layerid, tvb, offset, 1, ENC_BIG_ENDIAN, &layerid);
2401 /* numLayers */
2402 proto_tree_add_item(extension_tree, hf_oran_numlayers, tvb, offset, 1, ENC_BIG_ENDIAN);
2403 offset += 1;
2405 /* Stop here for non-first data layer */
2406 if (layerid != 0 && layerid != 0xf) {
2407 break;
2410 /* First data layer case */
2411 /* txScheme */
2412 proto_tree_add_item(extension_tree, hf_oran_txscheme, tvb, offset, 1, ENC_BIG_ENDIAN);
2413 /* crsReMask */
2414 proto_tree_add_item(extension_tree, hf_oran_crs_remask, tvb, offset, 2, ENC_BIG_ENDIAN);
2415 offset += 2;
2417 /* crsShift (1 bit) */
2418 proto_tree_add_item(extension_tree, hf_oran_crs_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
2419 /* reserved (3 bits) */
2420 /* crsSymNum (4 bits) */
2421 proto_tree_add_item(extension_tree, hf_oran_crs_symnum, tvb, offset, 1, ENC_BIG_ENDIAN);
2422 offset += 1;
2423 /* reserved */
2424 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2425 offset += 1;
2427 /* reserved (1 bit) */
2428 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2429 /* beamIdAP1 */
2430 proto_tree_add_item(extension_tree, hf_oran_beamid_ap1, tvb, offset, 2, ENC_BIG_ENDIAN);
2431 offset += 2;
2432 /* reserved (1 bit) */
2433 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2434 /* beamIdAP2 */
2435 proto_tree_add_item(extension_tree, hf_oran_beamid_ap2, tvb, offset, 2, ENC_BIG_ENDIAN);
2436 offset += 2;
2437 /* reserved (1 bit) */
2438 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2439 /* beamIdAP3 */
2440 proto_tree_add_item(extension_tree, hf_oran_beamid_ap3, tvb, offset, 2, ENC_BIG_ENDIAN);
2441 offset += 2;
2442 break;
2445 case 4: /* SE 4: Modulation compression params (5.4.7.4) */
2447 /* csf */
2448 dissect_csf(extension_tree, tvb, offset*8, ci_iq_width, NULL);
2450 /* modCompScaler */
2451 uint32_t modCompScaler;
2452 proto_item *ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_modcompscaler,
2453 tvb, offset, 2, ENC_BIG_ENDIAN, &modCompScaler);
2454 offset += 2;
2456 /* Work out and show floating point value too. */
2457 uint16_t exponent = (modCompScaler >> 11) & 0x000f; /* m.s. 4 bits */
2458 uint16_t mantissa = modCompScaler & 0x07ff; /* l.s. 11 bits */
2459 double value = (double)mantissa * (1.0 / (1 << exponent));
2460 proto_item_append_text(ti, " (%f)", value);
2461 break;
2464 case 5: /* SE 5: Modulation Compression Additional Parameters (7.7.5) */
2466 /* Applies only to section types 1,3 and 5 */
2467 /* N.B. there may be multiple instances of this SE in the same frame */
2469 /* There may be one or 2 entries, depending upon extlen */
2470 int sets = 1, reserved_bits = 0;
2471 switch (extlen) {
2472 case 2:
2473 sets = 1;
2474 reserved_bits = 20;
2475 break;
2476 case 3:
2477 sets = 2;
2478 reserved_bits = 24;
2479 break;
2480 case 4:
2481 /* sets can be 3 or 4, depending upon whether last 28 bits are 0.. */
2482 if ((tvb_get_ntohl(tvb, offset+10) & 0x0fffffff) == 0) {
2483 sets = 3;
2484 reserved_bits = 28;
2486 else {
2487 sets = 4;
2488 reserved_bits = 0;
2490 break;
2492 default:
2493 /* Malformed error!!! */
2494 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
2495 "For section 5, extlen must be 2, 3 or 4, but %u was dissected",
2496 extlen);
2497 break;
2500 unsigned bit_offset = offset*8;
2502 for (int n=0; n < sets; n++) {
2503 /* Subtree for each set */
2504 unsigned set_start_offset = bit_offset/8;
2505 proto_item *set_ti = proto_tree_add_string(extension_tree, hf_oran_modcomp_param_set,
2506 tvb, set_start_offset, 0, "");
2507 proto_tree *set_tree = proto_item_add_subtree(set_ti, ett_oran_modcomp_param_set);
2509 uint64_t mcScaleReMask, mcScaleOffset;
2510 bool csf;
2512 /* mcScaleReMask (12 bits) */
2513 proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_re_mask, tvb, bit_offset, 12, &mcScaleReMask, ENC_BIG_ENDIAN);
2514 bit_offset += 12;
2515 /* csf (1 bit) */
2516 bit_offset = dissect_csf(set_tree, tvb, bit_offset, ci_iq_width, &csf);
2517 /* mcScaleOffset (15 bits) */
2518 proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_offset, tvb, bit_offset, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
2519 bit_offset += 15;
2521 /* Summary */
2522 proto_item_set_len(set_ti, (bit_offset+7)/8 - set_start_offset);
2523 proto_item_append_text(set_ti, " (mcScaleReMask=0x%03x csf=%5s mcScaleOffset=%u)",
2524 (unsigned)mcScaleReMask, tfs_get_true_false(csf), (unsigned)mcScaleOffset);
2527 proto_item_append_text(extension_ti, " (%u sets)", sets);
2529 /* Reserved (variable-length) */
2530 if (reserved_bits) {
2531 proto_tree_add_bits_item(extension_tree, hf_oran_reserved, tvb, bit_offset, reserved_bits, ENC_BIG_ENDIAN);
2532 bit_offset += reserved_bits;
2535 offset = bit_offset/8;
2536 break;
2539 case 6: /* SE 6: Non-contiguous PRB allocation in time and frequency domain */
2541 /* Update ext6 recorded info */
2542 ext11_settings.ext6_set = true;
2544 /* repetition */
2545 proto_tree_add_bits_item(extension_tree, hf_oran_repetition, tvb, offset*8, 1, ENC_BIG_ENDIAN);
2546 /* rbgSize (PRBs per bit set in rbgMask) */
2547 uint32_t rbgSize;
2548 proto_item *rbg_size_ti;
2549 rbg_size_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgSize);
2550 if (rbgSize == 0) {
2551 /* N.B. this is only true if "se6-rb-bit-supported" is set... */
2552 expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_rbg_size_reserved,
2553 "rbgSize value of 0 is reserved");
2555 /* rbgMask (28 bits) */
2556 uint32_t rbgMask;
2557 proto_item *rbgmask_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN, &rbgMask);
2558 if (rbgSize == 0) {
2559 proto_item_append_text(rbgmask_ti, " (value ignored since rbgSize is 0)");
2562 /* TODO: if receiver detects non-zero bits outside the valid range, those shall be ignored. */
2563 offset += 4;
2564 /* priority */
2565 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
2566 /* symbolMask */
2567 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
2568 offset += 2;
2570 /* Look up rbg_size enum -> value */
2571 switch (rbgSize) {
2572 case 0:
2573 /* N.B. reserved, but covered above with expert info (would remain 0) */
2574 break;
2575 case 1:
2576 ext11_settings.ext6_rbg_size = 1; break;
2577 case 2:
2578 ext11_settings.ext6_rbg_size = 2; break;
2579 case 3:
2580 ext11_settings.ext6_rbg_size = 3; break;
2581 case 4:
2582 ext11_settings.ext6_rbg_size = 4; break;
2583 case 5:
2584 ext11_settings.ext6_rbg_size = 6; break;
2585 case 6:
2586 ext11_settings.ext6_rbg_size = 8; break;
2587 case 7:
2588 ext11_settings.ext6_rbg_size = 16; break;
2589 /* N.B., encoded in 3 bits, so no other values are possible */
2592 /* Set to looked-up value */
2593 rbgSize = ext11_settings.ext6_rbg_size;
2595 uint32_t lastRbgid = 0;
2596 if (rbgSize != 0) {
2597 /* The O-DU shall not use combinations of startPrbc, numPrbc and rbgSize leading to a value of lastRbgid larger than 27 */
2598 /* i.e., leftmost bit used should not need to go off left end of rbgMask! */
2599 lastRbgid = (uint32_t)ceil((numPrbc + (startPrbc % rbgSize)) / (float)rbgSize) - 1;
2600 if (lastRbgid > 27) {
2601 expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_lastRbdid_out_of_range,
2602 "SE6: rbgSize (%u) not compatible with startPrbc(%u) and numPrbc(%u)",
2603 rbgSize, startPrbc, numPrbc);
2604 break;
2608 /* Record (and count) which bits are set in rbgMask */
2609 bool first_seen = false;
2610 unsigned first_seen_pos=0, last_seen_pos=0;
2611 for (unsigned n=0; n < 28 && ext11_settings.ext6_num_bits_set < 28; n++) {
2612 if ((rbgMask >> n) & 0x01) {
2613 ext11_settings.ext6_bits_set[ext11_settings.ext6_num_bits_set++] = n;
2614 if (!first_seen) {
2615 first_seen = true;
2616 first_seen_pos = n;
2618 last_seen_pos = n;
2622 /* Show how many bits were set in rbgMask */
2623 proto_item_append_text(rbgmask_ti, " (%u bits set)", ext11_settings.ext6_num_bits_set);
2624 /* Also, that is the range of bits */
2625 if (first_seen) {
2626 proto_item_append_text(rbgmask_ti, " (%u bits spread)", last_seen_pos-first_seen_pos+1);
2629 /* Complain if last set bit is beyond lastRbgid */
2630 if (first_seen) {
2631 if (last_seen_pos > lastRbgid) {
2632 expert_add_info_format(pinfo, rbgmask_ti, &ei_oran_rbgMask_beyond_last_rbdid,
2633 "SE6: rbgMask (0x%07x) has bit %u set, but lastRbgId is %u",
2634 rbgMask, last_seen_pos, lastRbgid);
2637 break;
2640 case 7: /* SE 7: eAxC mask */
2641 /* Allow ST0 to address multiple eAxC_ID values for transmission blanking */
2642 proto_tree_add_item(extension_tree, hf_oran_eAxC_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
2643 offset += 2;
2644 break;
2646 case 8: /* SE 8: Regularization factor */
2647 proto_tree_add_item(extension_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
2648 offset += 2;
2649 break;
2651 case 9: /* SE 9: Dynamic Spectrum Sharing parameters */
2652 proto_tree_add_item(extension_tree, hf_oran_technology, tvb, offset, 1, ENC_BIG_ENDIAN);
2653 offset += 1;
2654 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2655 offset += 1;
2656 break;
2658 case 10: /* SE 10: Group configuration of multiple ports */
2660 seen_se10 = true;
2662 /* beamGroupType */
2663 uint32_t beam_group_type = 0;
2664 proto_item *bgt_ti;
2665 bgt_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamGroupType,
2666 tvb, offset, 1, ENC_BIG_ENDIAN, &beam_group_type);
2667 proto_item_append_text(extension_ti, " (%s)", val_to_str_const(beam_group_type, beam_group_type_vals, "Unknown"));
2669 /* numPortc */
2670 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
2671 tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
2672 offset++;
2674 /* Will append all beamId values to extension_ti, regardless of beamGroupType */
2675 unsigned n;
2677 switch (beam_group_type) {
2678 case 0x0: /* common beam */
2679 case 0x1: /* beam matrix indication */
2681 /* Reserved byte */
2682 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
2683 offset++;
2684 break;
2685 case 0x2: /* beam vector listing */
2687 proto_item_append_text(extension_ti, " [ ");
2689 /* Beam listing vector case */
2690 /* Work out how many port beam entries there is room for */
2691 /* Using numPortC as visible in issue 18116 */
2692 for (n=0; n < numPortc; n++) {
2693 /* 1 reserved bit */
2694 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2696 /* port beam ID (or UEID) */
2697 uint32_t id;
2698 proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
2699 tvb, offset, 2, ENC_BIG_ENDIAN, &id);
2700 proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
2701 offset += 2;
2703 proto_item_append_text(extension_ti, "%u ", id);
2706 proto_item_append_text(extension_ti, "]");
2707 break;
2709 case 0x3: /* beamId/ueId listing with associated port-list index */
2711 proto_item_append_text(extension_ti, " [ ");
2713 for (n=0; n < numPortc; n++) {
2714 /* postListIndex */
2715 uint32_t port_list_index;
2716 proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
2717 offset, 1, ENC_BIG_ENDIAN, &port_list_index);
2718 offset += 1;
2720 /* 1 reserved bit */
2721 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2723 /* port beam ID (or UEID) */
2724 uint32_t id;
2725 proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
2726 tvb, offset, 2, ENC_BIG_ENDIAN, &id);
2727 proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
2728 offset += 2;
2730 proto_item_append_text(extension_ti, "%u:%u ", port_list_index, id);
2733 proto_item_append_text(extension_ti, "]");
2734 break;
2738 default:
2739 /* Warning for unsupported/reserved value */
2740 expert_add_info(NULL, bgt_ti, &ei_oran_se10_unknown_beamgrouptype);
2741 break;
2743 break;
2746 case 11: /* SE 11: Flexible Weights Extension Type */
2748 /* beamId in section header should be ignored. Guard against appending multiple times.. */
2749 if (beamId_ti && !beamId_ignored) {
2750 proto_item_append_text(beamId_ti, " (ignored)");
2751 beamId_ignored = true;
2754 bool disableBFWs;
2755 uint32_t numBundPrb;
2756 bool rad;
2758 /* disableBFWs */
2759 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
2760 tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
2761 if (disableBFWs) {
2762 proto_item_append_text(extension_ti, " (disableBFWs)");
2765 /* RAD */
2766 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_rad,
2767 tvb, offset, 1, ENC_BIG_ENDIAN, &rad);
2768 /* bundleOffset (6 bits) */
2769 proto_tree_add_item(extension_tree, hf_oran_bundle_offset, tvb,
2770 offset, 1, ENC_BIG_ENDIAN);
2771 offset++;
2773 /* numBundPrb (number of prbs in each bundle) */
2774 proto_item *num_bund_prb_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_bund_prbs,
2775 tvb, offset, 1, ENC_BIG_ENDIAN, &numBundPrb);
2776 offset++;
2777 /* value zero is reserved.. */
2778 if (numBundPrb == 0) {
2779 expert_add_info_format(pinfo, num_bund_prb_ti, &ei_oran_reserved_numBundPrb,
2780 "Reserved value 0 for numBundPrb seen - not valid");
2783 uint32_t num_bundles;
2784 bool orphaned_prbs = false;
2786 if (!disableBFWs) {
2787 /********************************************/
2788 /* Table 7.7.1.1-1 */
2789 /********************************************/
2791 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
2792 proto_item *comp_meth_ti = NULL;
2794 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
2795 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
2796 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
2798 /* Work out number of bundles, but take care not to divide by zero. */
2799 if (numBundPrb == 0) {
2800 break;
2803 /* Work out bundles! */
2804 ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
2805 num_bundles = ext11_settings.num_bundles;
2807 /* Add (complete) bundles */
2808 for (unsigned b=0; b < num_bundles; b++) {
2810 offset = dissect_bfw_bundle(tvb, extension_tree, pinfo, offset,
2811 comp_meth_ti, bfwcomphdr_comp_meth,
2812 (ext11_settings.ext21_set) ?
2813 numPrbc :
2814 pref_num_weights_per_bundle,
2815 bfwcomphdr_iq_width,
2816 b, /* bundle number */
2817 ext11_settings.bundles[b].start,
2818 ext11_settings.bundles[b].end,
2819 ext11_settings.bundles[b].is_orphan);
2820 if (!offset) {
2821 break;
2824 if (num_bundles > 0) {
2825 /* Set flag from last bundle entry */
2826 orphaned_prbs = ext11_settings.bundles[num_bundles-1].is_orphan;
2829 else {
2830 /********************************************/
2831 /* Table 7.7.1.1-2 */
2832 /* No weights in this case */
2833 /********************************************/
2835 /* Work out number of bundles, but take care not to divide by zero. */
2836 if (numBundPrb == 0) {
2837 break;
2840 ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
2841 num_bundles = ext11_settings.num_bundles;
2843 for (unsigned n=0; n < num_bundles; n++) {
2844 /* contInd */
2845 proto_tree_add_item(extension_tree, hf_oran_cont_ind,
2846 tvb, offset, 1, ENC_BIG_ENDIAN);
2847 /* beamId */
2848 proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_beam_id,
2849 tvb, offset, 2, ENC_BIG_ENDIAN);
2850 if (!ext11_settings.bundles[n].is_orphan) {
2851 proto_item_append_text(ti, " (Bundle %u)", n);
2853 else {
2854 orphaned_prbs = true;
2855 proto_item_append_text(ti, " (Orphaned PRBs)");
2857 offset += 2;
2861 /* Add summary to extension root */
2862 if (orphaned_prbs) {
2863 proto_item_append_text(extension_ti, " (%u bundles + orphaned)", num_bundles);
2865 else {
2866 proto_item_append_text(extension_ti, " (%u bundles)", num_bundles);
2870 break;
2872 case 12: /* SE 12: Non-Contiguous PRB Allocation with Frequency Ranges */
2874 ext11_settings.ext12_set = true;
2876 /* priority */
2877 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
2879 /* symbolMask */
2880 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
2881 offset += 2;
2883 /* There are now 'R' pairs of (offStartPrb, numPrb) values. Fill extlen bytes with values. If last one is not set,
2884 should be populated with 0s. */
2885 uint32_t extlen_remaining_bytes = (extlen*4) - 4;
2886 uint8_t prb_index;
2888 for (prb_index = 1; extlen_remaining_bytes > 0; prb_index++)
2890 /* Create a subtree for each pair */
2891 proto_item *pair_ti = proto_tree_add_string(extension_tree, hf_oran_off_start_prb_num_prb_pair,
2892 tvb, offset, 2, "");
2893 proto_tree *pair_tree = proto_item_add_subtree(pair_ti, ett_oran_offset_start_prb_num_prb);
2895 /* offStartPrb */
2896 uint32_t off_start_prb;
2897 proto_tree_add_item_ret_uint(pair_tree, hf_oran_off_start_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &off_start_prb);
2898 offset++;
2900 /* numPrb */
2901 uint32_t num_prb;
2902 proto_tree_add_item_ret_uint(pair_tree, hf_oran_num_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_prb);
2903 offset++;
2905 extlen_remaining_bytes -= 2;
2907 /* Last pair may be 0,0 if not used. Check for this */
2908 if ((extlen_remaining_bytes == 0) && (off_start_prb == 0) && (num_prb == 0)) {
2909 proto_item_append_text(pair_ti, " (not used)");
2911 /* Add summary to pair root item, and configure details in ext11_settings */
2912 else {
2913 proto_item_append_text(pair_ti, "(%u) offStartPrb=%3u, numPrb=%u",
2914 prb_index, off_start_prb, num_prb);
2915 if (ext11_settings.ext12_num_pairs < MAX_BFW_EXT12_PAIRS) {
2916 ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs].off_start_prb = off_start_prb;
2917 ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs++].num_prb = num_prb;
2921 break;
2924 case 13: /* SE 13: PRB Allocation with Frequency Hopping */
2926 /* Will update settings for ext11 */
2927 ext11_settings.ext13_set = true;
2929 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
2930 uint8_t allocation_index;
2932 unsigned prev_next_symbol_id = 0, prev_next_start_prbc = 0;
2934 for (allocation_index = 1; extlen_remaining_bytes > 0; allocation_index++)
2936 /* Subtree for allocation */
2937 proto_item *allocation_ti = proto_tree_add_string(extension_tree, hf_oran_prb_allocation,
2938 tvb, offset, 2, "");
2939 proto_tree *allocation_tree = proto_item_add_subtree(allocation_ti, ett_oran_prb_allocation);
2941 /* Reserved (2 bits) */
2942 proto_tree_add_item(allocation_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2944 /* nextSymbolId (4 bits) */
2945 uint32_t next_symbol_id;
2946 proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextSymbolId, tvb, offset, 1, ENC_BIG_ENDIAN, &next_symbol_id);
2948 /* nextStartPrbc (10 bits) */
2949 uint32_t next_start_prbc;
2950 proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextStartPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &next_start_prbc);
2951 offset += 2;
2953 /* Add summary to allocation root item */
2954 proto_item_append_text(allocation_ti, "(%u) nextSymbolId=%3u, nextStartPrbc=%u",
2955 allocation_index, next_symbol_id, next_start_prbc);
2957 /* Checking for duplicates (expected if e.g. had only 2 entries but extlen bytes still to fill */
2958 if ((allocation_index > 1) && (next_symbol_id == prev_next_symbol_id) && (next_start_prbc == prev_next_start_prbc)) {
2959 proto_item_append_text(allocation_ti, " (repeated - to fill up extlen)");
2961 else {
2962 /* Add entry for configuring ext11. don't store out of range */
2963 if (ext11_settings.ext13_num_start_prbs < MAX_BFW_EXT13_ALLOCATIONS) {
2964 ext11_settings.ext13_start_prbs[ext11_settings.ext13_num_start_prbs++] = next_start_prbc;
2967 prev_next_symbol_id = next_symbol_id;
2968 prev_next_start_prbc = next_start_prbc;
2970 extlen_remaining_bytes -= 2;
2972 break;
2975 case 14: /* SE 14: Nulling-layer Info. for ueId-based beamforming */
2976 if (!seen_se10) {
2977 proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
2978 offset += 1;
2979 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2980 offset += 1;
2982 else {
2983 /* Loop over numPortc++1 (from SE 10) nullLayerInd fields */
2984 for (unsigned port=0; port < numPortc+1; port++) {
2985 proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
2986 offset += 1;
2989 break;
2991 case 15: /* SE 15: Mixed-numerology Info. for ueId-based beamforming */
2992 /* frameStructure */
2993 offset = dissect_frame_structure(extension_tree, tvb, offset,
2994 subframeId, slotId);
2995 /* freqOffset */
2996 proto_tree_add_item(extension_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN);
2997 offset += 3;
2998 /* cpLength */
2999 proto_tree_add_item(extension_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
3000 offset += 2;
3001 break;
3003 case 16: /* SE 16: Antenna mapping in UE channel information based UL beamforming */
3005 /* Just filling available bytes with antMask entries.
3006 N.B., if SE 10 also used, could associate each antMask with (beamId or UEId) RX eAxC */
3007 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3008 unsigned num_ant_masks = extlen_remaining_bytes / 8;
3009 for (unsigned n=0; n < num_ant_masks; n++) {
3010 proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_antMask, tvb, offset, 8, ENC_BIG_ENDIAN);
3011 proto_item_append_text(ti, " (RX eAxC #%u)", n+1);
3012 offset += 8;
3014 break;
3017 case 17: /* SE 17: Indication of user port group */
3019 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3020 uint32_t end_bit = (offset+extlen_remaining_bytes) * 8;
3021 uint32_t ueid_index = 1;
3022 /* TODO: just filling up all available bytes - some may actually be padding.. */
3023 /* "the preceding Section Type and extension messages implicitly provide the number of scheduled users" */
3024 for (uint32_t bit_offset=offset*8; bit_offset < end_bit; bit_offset+=4, ueid_index++) {
3025 proto_item *ti = proto_tree_add_bits_item(extension_tree, hf_oran_num_ueid, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
3026 proto_item_append_text(ti, " (user #%u)", ueid_index);
3028 break;
3031 case 18: /* SE 18: Uplink transmission management */
3032 /* transmissionWindowOffset */
3033 proto_tree_add_item(extension_tree, hf_oran_transmissionWindowOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
3034 offset += 2;
3035 /* reserved (2 bits) */
3036 proto_tree_add_item(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3037 /* transmissionWindowSize (14 bits) */
3038 proto_tree_add_item(extension_tree, hf_oran_transmissionWindowSize, tvb, offset, 2, ENC_BIG_ENDIAN);
3039 offset += 2;
3041 /* reserved (6 bits) */
3042 proto_tree_add_item(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3043 /* toT (2 bits) */
3044 proto_tree_add_item(extension_tree, hf_oran_toT, tvb, offset, 1, ENC_BIG_ENDIAN);
3045 offset += 1;
3046 break;
3048 case 19: /* SE 19: Compact beamforming information for multiple port */
3050 /* beamId in section header should be ignored. Guard against appending multiple times.. */
3051 if (beamId_ti && !beamId_ignored) {
3052 proto_item_append_text(beamId_ti, " (ignored)");
3053 beamId_ignored = true;
3056 /* disableBFWs */
3057 bool disableBFWs;
3058 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
3059 tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
3060 if (disableBFWs) {
3061 proto_item_append_text(extension_ti, " (disableBFWs)");
3063 /* Repetition */
3064 uint64_t repetition;
3065 proto_tree_add_bits_ret_val(extension_tree, hf_oran_repetition, tvb, (offset*8)+1, 1, &repetition, ENC_BIG_ENDIAN);
3066 /* numPortc */
3067 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
3068 tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
3069 offset++;
3071 /* priority */
3072 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3073 /* symbolMask */
3074 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3075 offset += 2;
3077 /* bfwCompHdr */
3078 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
3079 proto_item *comp_meth_ti = NULL;
3080 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
3081 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
3083 if (!repetition) {
3085 /* Add entries for each port */
3086 for (unsigned port=0; port < numPortc; port++) {
3088 /* Create subtree for port entry*/
3089 int port_start_offset = offset;
3090 proto_item *port_ti = proto_tree_add_string_format(extension_tree, hf_oran_ext19_port,
3091 tvb, offset, 0,
3092 "", "Port %u: ", port);
3093 proto_tree *port_tree = proto_item_add_subtree(port_ti, ett_oran_ext19_port);
3095 /* Reserved (4 bits) */
3096 proto_tree_add_item(port_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3097 /* portReMask (12 bits) */
3098 proto_tree_add_item(port_tree, hf_oran_portReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3099 offset += 2;
3101 /* Reserved (2 bits) */
3102 proto_tree_add_item(port_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3103 /* portSymbolMask (14 bits) */
3104 proto_tree_add_item(port_tree, hf_oran_portSymbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3105 offset += 2;
3107 /* Reserved (1 bit) */
3108 proto_tree_add_item(port_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3109 /* beamID (15 bits) */
3110 proto_tree_add_item_ret_uint(port_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
3111 proto_item_append_text(port_ti, " (beamId=%u)", beamId);
3112 offset += 2;
3114 /* No weights present */
3115 if (!disableBFWs) {
3116 /*******************************************************************/
3117 /* Table 7.7.19.1-1 (there is no part -2 for disableBFWs case...), */
3118 /* but for SE 11, bfwCompParam was only present for !disableBFWs */
3119 /*******************************************************************/
3121 /* bfwCompParam */
3122 bool compression_method_supported = false;
3123 uint32_t exponent = 0;
3124 offset = dissect_bfwCompParam(tvb, port_tree, pinfo, offset, comp_meth_ti,
3125 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
3127 int bit_offset = offset*8;
3128 int bfw_offset;
3130 /* Add weights for each TRX */
3131 for (unsigned b=0; b < pref_num_bf_antennas; b++) {
3133 /* Create BFW subtree */
3134 bfw_offset = bit_offset / 8;
3135 uint8_t bfw_extent = ((bit_offset + (bfwcomphdr_iq_width*2)) / 8) - bfw_offset;
3136 proto_item *bfw_ti = proto_tree_add_string_format(port_tree, hf_oran_bfw,
3137 tvb, bfw_offset, bfw_extent,
3138 "", "TRX %u: (", b);
3139 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
3141 /* I */
3142 /* Get bits, and convert to float. */
3143 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3144 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
3145 /* Add to tree. */
3146 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
3147 (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
3148 bit_offset += bfwcomphdr_iq_width;
3149 proto_item_append_text(bfw_ti, "I%u=%f ", b, value);
3151 /* Q */
3152 /* Get bits, and convert to float. */
3153 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3154 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
3155 /* Add to tree. */
3156 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
3157 (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
3158 bit_offset += bfwcomphdr_iq_width;
3159 proto_item_append_text(bfw_ti, "Q%u=%f)", b, value);
3162 offset = (bit_offset+7)/8;
3164 else {
3165 /* No weights... */
3167 /* Reserved (1 bit) */
3168 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3169 /* beamID (15 bits) */
3170 proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
3171 proto_item_append_text(port_ti, " (beamId=%u)", beamId);
3172 offset += 2;
3175 /* Set length of this port entry */
3176 proto_item_set_len(port_ti, offset-port_start_offset);
3179 break;
3182 case 20: /* SE 20: Puncturing extension */
3184 /* numPuncPatterns */
3185 uint32_t numPuncPatterns;
3186 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPuncPatterns, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPatterns);
3187 offset += 1;
3189 /* Add each puncturing pattern */
3190 for (uint32_t n=0; n < numPuncPatterns; n++) {
3191 unsigned pattern_start_offset = offset;
3193 /* Subtree for this puncturing pattern */
3194 proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_puncPattern,
3195 tvb, offset, 0,
3196 "", "Puncturing Pattern: %u/%u", n+1, hf_oran_numPuncPatterns);
3197 proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_punc_pattern);
3199 /* SymbolMask (14 bits) */
3200 proto_tree_add_item(pattern_tree, hf_oran_symbolMask_ext20, tvb, offset, 2, ENC_BIG_ENDIAN);
3201 offset += 1;
3202 /* startPuncPrb (10 bits) */
3203 proto_tree_add_item(pattern_tree, hf_oran_startPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN);
3204 offset += 2;
3205 /* numPuncPrb (8 bits) */
3206 proto_tree_add_item(pattern_tree, hf_oran_numPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN);
3207 offset += 1;
3208 /* puncReMask (12 bits) */
3209 proto_tree_add_item(pattern_tree, hf_oran_puncReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3210 offset += 1;
3211 /* rb (1 bit) */
3212 proto_item *rb_ti = proto_tree_add_item(pattern_tree, hf_oran_rb, tvb, offset, 1, ENC_BIG_ENDIAN);
3213 /* reserved (2 bits? - spec says 1) */
3214 proto_tree_add_bits_item(pattern_tree, hf_oran_reserved, tvb, offset*8, 2, ENC_BIG_ENDIAN);
3215 /* rbgIncl (1 bit) */
3216 bool rbgIncl;
3217 proto_tree_add_item_ret_boolean(pattern_tree, hf_oran_RbgIncl, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgIncl);
3218 offset += 1;
3220 if (rbgIncl) {
3221 /* reserved (1 bit) */
3222 proto_tree_add_item(pattern_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3223 /* rbgSize(3 bits) */
3224 proto_tree_add_item(pattern_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN);
3225 /* rbgMask (28 bits) */
3226 proto_tree_add_item(pattern_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN);
3227 offset += 4;
3229 proto_item_append_text(rb_ti, " (ignored)");
3232 proto_item_set_len(pattern_ti, offset-pattern_start_offset);
3235 break;
3237 case 21: /* SE 21: Variable PRB group size for channel information */
3239 /* ciPrbGroupSize */
3240 uint32_t ci_prb_group_size;
3241 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);
3242 offset += 1;
3244 switch (ci_prb_group_size) {
3245 case 0:
3246 case 1:
3247 case 255:
3248 /* Reserved value */
3249 expert_add_info_format(pinfo, prb_group_size_ti, &ei_oran_ci_prb_group_size_reserved,
3250 "SE 11 ciPrbGroupSize is reserved value %u - must be 2-254",
3251 ci_prb_group_size);
3253 break;
3254 default:
3255 /* This value affects how SE 11 is interpreted */
3256 ext11_settings.ext21_set = true;
3257 ext11_settings.ext21_ci_prb_group_size = ci_prb_group_size;
3259 if (numPrbc == 0) {
3260 expert_add_info(pinfo, numprbc_ti, &ei_oran_numprbc_ext21_zero);
3262 break;
3265 /* reserved (6 bits) */
3266 proto_tree_add_item(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3268 /* prgSize (2 bits). Interpretation depends upon section type (5 or 6), but also mplane parameters? */
3269 if (sectionType == SEC_C_UE_SCHED) { /* Section Type 5 */
3270 proto_tree_add_item(extension_tree, hf_oran_prg_size_st5, tvb, offset, 1, ENC_BIG_ENDIAN);
3272 else if (sectionType == SEC_C_CH_INFO) { /* Section Type 6 */
3273 proto_tree_add_item(extension_tree, hf_oran_prg_size_st6, tvb, offset, 1, ENC_BIG_ENDIAN);
3275 offset += 1;
3276 break;
3279 case 22: /* SE 22: ACK/NACK request */
3281 uint32_t ack_nack_req_id;
3282 proto_tree_add_item_ret_uint(extension_tree, hf_oran_ack_nack_req_id, tvb, offset, 2,
3283 ENC_BIG_ENDIAN, &ack_nack_req_id);
3284 offset += 2;
3286 if (state) {
3287 if (!PINFO_FD_VISITED(pinfo)) {
3288 /* Add this request into conversation state on first pass */
3289 ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
3290 request_details->request_frame_number = pinfo->num;
3291 request_details->request_frame_time = pinfo->abs_ts;
3292 request_details->requestType = SE22;
3293 /* Insert into flow's tree */
3294 wmem_tree_insert32(state->ack_nack_requests, ack_nack_req_id, request_details);
3296 else {
3297 /* Try to link forward to ST8 response */
3298 ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
3299 ack_nack_req_id);
3300 if (response) {
3301 show_link_to_acknack_response(extension_tree, tvb, pinfo, response);
3305 break;
3308 case 23: /* SE 23: Arbitrary symbol pattern modulation compression parameters */
3310 /* Green common header */
3312 /* numSymPrbPattern (4 bits) */
3313 uint32_t num_sym_prb_pattern;
3314 proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_sym_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sym_prb_pattern);
3315 /* reserved (3 bits) */
3316 /* prbMode (1 bit) */
3317 bool prb_mode;
3318 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_prb_mode, tvb, offset, 1, ENC_BIG_ENDIAN, &prb_mode);
3319 offset += 1;
3321 /* reserved (8 bits) */
3322 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3323 offset += 1;
3325 /* Dissect each SymPrbPattern */
3326 for (uint32_t n=0; n < num_sym_prb_pattern; n++) {
3328 /* Subtree */
3329 proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_sym_prb_pattern,
3330 tvb, offset, 1, "",
3331 prb_mode ? "PRB-BLOCK" : "PRB-MASK");
3332 proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_sym_prb_pattern);
3335 /* Orange part */
3337 /* Reserved (2 bits) */
3338 proto_tree_add_item(pattern_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3339 /* symMask (14 bits) */
3340 proto_tree_add_item(pattern_tree, hf_oran_sym_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3341 offset += 2;
3342 /* numMcScaleOffset (4 bits) */
3343 proto_tree_add_item(pattern_tree, hf_oran_num_mc_scale_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
3345 if (!prb_mode) { /* PRB-MASK */
3346 /* prbPattern (4 bits) */
3347 proto_tree_add_item(pattern_tree, hf_oran_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN);
3348 offset += 1;
3349 /* reserved (8 bits) */
3350 proto_tree_add_item(pattern_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3351 offset += 1;
3353 else { /* PRB-BLOCK */
3354 /* prbBlkOffset (8 bits) */
3355 proto_tree_add_item(pattern_tree, hf_oran_prb_block_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
3356 offset += 1;
3357 /* prbBlkSize (4 bits) */
3358 proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
3359 offset += 1;
3362 /* Yellowish part */
3363 if (prb_mode) { /* PRB-BLOCK */
3364 /* prbBlkSize (4 bits) */
3365 proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
3367 else {
3368 /* reserved (4 bits) */
3369 proto_tree_add_item(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3372 /* mcScaleReMask (12 bits) */
3373 uint64_t mcScaleReMask, mcScaleOffset;
3374 proto_tree_add_bits_ret_val(pattern_tree, hf_oran_mc_scale_re_mask, tvb, offset*8 + 4, 12, &mcScaleReMask, ENC_BIG_ENDIAN);
3375 offset += 2;
3376 /* csf */
3377 dissect_csf(pattern_tree, tvb, offset*8, ci_iq_width, NULL);
3378 /* mcScaleOffset (15 bits) */
3379 proto_tree_add_bits_ret_val(pattern_tree, hf_oran_mc_scale_offset, tvb, offset*8 + 1, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
3380 offset += 2;
3382 proto_item_set_end(pattern_ti, tvb, offset);
3384 break;
3387 case 24: /* SE 24: PUSCH DMRS configuration */
3389 /* alpnPerSym (1 bit) */
3390 proto_tree_add_item(extension_tree, hf_oran_alpn_per_sym, tvb, offset, 1, ENC_BIG_ENDIAN);
3391 /* antDmrsSnr (1 bit) */
3392 proto_tree_add_item(extension_tree, hf_oran_ant_dmrs_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
3393 /* reserved (1 bit */
3394 /* userGroupSize (5 bits) */
3395 uint32_t user_group_size;
3396 proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_size, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_size);
3398 offset += 1;
3399 /* userGroupId */
3400 uint32_t user_group_id;
3401 proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_id, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_id);
3402 offset += 1;
3404 /* Dissect each entry. Not sure how this works with padding bytes though... */
3405 while (offset < (extension_start_offset + extlen*4)) {
3407 /* entryType (3 bits) */
3408 uint32_t entry_type;
3409 proto_item *entry_type_ti;
3410 entry_type_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_entry_type, tvb, offset, 1, ENC_BIG_ENDIAN, &entry_type);
3411 if (entry_type > 3) {
3412 proto_item_append_text(entry_type_ti, " (reserved)");
3415 /* dmrsPortNumber (5 bits) */
3416 proto_tree_add_item(extension_tree, hf_oran_dmrs_port_number, tvb, offset, 1, ENC_BIG_ENDIAN);
3417 offset += 1;
3419 /* What follows depends upon entryType */
3420 switch (entry_type) {
3421 case 0:
3422 case 1:
3423 /* No further fields for these */
3424 break;
3426 case 2:
3427 case 3:
3428 /* Type 2/3 are very similar.. */
3430 /* ueIdReset (1 bit) */
3431 proto_tree_add_item(extension_tree, hf_oran_ueid_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
3432 /* reserved (1 bit) */
3433 /* dmrsSymbolMask (14 bits) */
3434 proto_tree_add_item(extension_tree, hf_oran_dmrs_symbol_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3435 offset += 2;
3437 /* scrambling */
3438 proto_tree_add_item(extension_tree, hf_oran_scrambling, tvb, offset, 2, ENC_BIG_ENDIAN);
3439 offset += 2;
3441 /* nscid (1 bit) */
3442 proto_tree_add_item(extension_tree, hf_oran_nscid, tvb, offset, 1, ENC_BIG_ENDIAN);
3444 if (entry_type == 2) {
3445 /* dType (1 bit) */
3446 proto_tree_add_item(extension_tree, hf_oran_dtype, tvb, offset, 1, ENC_BIG_ENDIAN);
3447 /* cdmWithoutData (2 bits) */
3448 proto_tree_add_item(extension_tree, hf_oran_cmd_without_data, tvb, offset, 1, ENC_BIG_ENDIAN);
3449 /* lambda (2 bits) */
3450 proto_tree_add_item(extension_tree, hf_oran_lambda, tvb, offset, 1, ENC_BIG_ENDIAN);
3452 else { /* type 3 */
3453 /* reserved (1 bit) */
3454 /* lowPaprType (2 bits) */
3455 proto_tree_add_item(extension_tree, hf_oran_low_papr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3456 /* hoppingMode (2 bits) */
3457 proto_tree_add_item(extension_tree, hf_oran_hopping_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
3460 /* firstPrb (9 bits) */
3461 proto_tree_add_item(extension_tree, hf_oran_first_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
3462 offset += 1;
3463 /* lastPrb (9 bits) */
3464 proto_tree_add_item(extension_tree, hf_oran_last_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
3465 offset += 1;
3466 /* Reserved (16 bits) */
3467 offset += 2;
3469 break;
3470 default:
3471 /* reserved - expert info */
3472 break;
3475 break;
3478 case 25: /* Symbol reordering for DMRS-BF */
3479 /* Just dissect each available block of 7 bytes as the 14 symbols for a layer,
3480 where each layer could be one or apply to all layers. Could place layer under a subtree? */
3481 while (offset+7 <= (extension_start_offset + extlen*4)) {
3482 /* All 14 symbols for a layer (or all layers) */
3483 for (unsigned s=0; s < 14; s++) {
3484 proto_item *sym_ti;
3485 sym_ti = proto_tree_add_item(extension_tree,
3486 (s % 2) ? hf_oran_tx_win_for_on_air_symbol_r : hf_oran_tx_win_for_on_air_symbol_l,
3487 tvb, offset, 1, ENC_BIG_ENDIAN);
3488 proto_item_append_text(sym_ti, " (sym %u)", s);
3489 if (s % 2) {
3490 offset += 1;
3494 break;
3496 case 26: /* Frequency offset feedback */
3497 /* Reserved (8 bits). N.B., added after draft? */
3498 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3499 offset += 1;
3501 /* Reserved (1 bit) */
3502 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3503 /* numFoFb (7 bits) */
3504 unsigned num_fo_fb;
3505 proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_fo_fb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_fo_fb);
3506 offset += 1;
3508 /* Add each freqOffsetFb value */
3509 for (unsigned n=0; n < num_fo_fb; n++) {
3510 unsigned freq_offset_fb;
3511 proto_item *offset_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_freq_offset_fb,
3512 tvb, offset, 2, ENC_BIG_ENDIAN, &freq_offset_fb);
3513 /* Show if maps onto a -ve number */
3514 if ((freq_offset_fb >= 0x8ad0) && (freq_offset_fb <= 0xffff)) {
3515 proto_item_append_text(offset_ti, "(value %d)", -1 - (0xffff-freq_offset_fb));
3517 proto_item_append_text(offset_ti, " [#%u]", n+1);
3518 offset += 2;
3521 break;
3524 default:
3525 /* Other/unexpected extension types */
3526 expert_add_info_format(pinfo, exttype_ti, &ei_oran_unhandled_se,
3527 "SE %u (%s) not supported by dissector",
3528 exttype, val_to_str_const(exttype, exttype_vals, "Reserved"));
3529 ext_unhandled = true;
3530 break;
3533 /* Check offset compared with extlen. There should be 0-3 bytes of padding */
3534 int num_padding_bytes = (extension_start_offset + (extlen*4) - offset);
3535 if (!ext_unhandled && ((num_padding_bytes<0) || (num_padding_bytes>3))) {
3536 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
3537 "extlen signalled %u bytes (+ 0-3 bytes padding), but %u were dissected",
3538 extlen*4, offset-extension_start_offset);
3541 /* Move offset to beyond signalled length of extension */
3542 offset = extension_start_offset + (extlen*4);
3544 /* Set length of extension header. */
3545 proto_item_set_len(extension_ti, extlen*4);
3548 /* Set extent of overall section */
3549 proto_item_set_len(sectionHeading, offset);
3551 return offset;
3554 /* Dissect udCompHdr (user data compression header, 7.5.2.10) */
3555 /* bit_width and comp_meth are out params */
3556 static int dissect_udcomphdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
3557 bool ignore,
3558 unsigned *bit_width, unsigned *comp_meth)
3560 /* Subtree */
3561 proto_item *udcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_udCompHdr,
3562 tvb, offset, 1, "",
3563 "udCompHdr");
3564 proto_tree *udcomphdr_tree = proto_item_add_subtree(udcomphdr_ti, ett_oran_udcomphdr);
3566 /* udIqWidth */
3567 uint32_t hdr_iq_width;
3568 proto_item *iq_width_item = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
3569 *bit_width = (hdr_iq_width) ? hdr_iq_width : 16;
3570 proto_item_append_text(iq_width_item, " (%u bits)", *bit_width);
3572 /* udCompMeth */
3573 uint32_t ud_comp_meth;
3574 proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrMeth, tvb, offset, 1, ENC_NA, &ud_comp_meth);
3575 if (comp_meth) {
3576 *comp_meth = ud_comp_meth;
3579 /* Summary */
3580 if (!ignore) {
3581 proto_item_append_text(udcomphdr_ti, " (IqWidth=%u, udCompMeth=%s)",
3582 *bit_width, rval_to_str_const(ud_comp_meth, ud_comp_header_meth, "Unknown"));
3584 else {
3585 proto_item_append_text(udcomphdr_ti, " (ignored)");
3586 if (hdr_iq_width || ud_comp_meth) {
3587 expert_add_info_format(pinfo, udcomphdr_ti, &ei_oran_udpcomphdr_should_be_zero,
3588 "udCompHdr in C-Plane for DL should be 0 - found %02x",
3589 tvb_get_uint8(tvb, offset));
3593 return offset+1;
3596 /* Dissect udCompParam (user data compression parameter, 8.3.3.15) */
3597 /* bit_width and comp_meth are out params */
3598 static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
3599 unsigned comp_meth,
3600 uint32_t *exponent, uint16_t *sReSMask,
3601 bool for_sinr)
3603 if (comp_meth == COMP_NONE || comp_meth == COMP_MODULATION) {
3604 /* Not even creating a subtree */
3605 return offset;
3608 /* Subtree */
3609 proto_item *udcompparam_ti = proto_tree_add_string_format(tree, hf_oran_udCompParam,
3610 tvb, offset, 1, "",
3611 (for_sinr) ? "sinrCompHdr" : "udCompHdr");
3612 proto_tree *udcompparam_tree = proto_item_add_subtree(udcompparam_ti, ett_oran_udcompparam);
3614 uint32_t param_exponent, param_sresmask;
3616 switch (comp_meth) {
3617 case COMP_BLOCK_FP:
3618 proto_tree_add_item(udcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
3619 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
3620 tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
3621 *exponent = param_exponent;
3622 proto_item_append_text(udcompparam_ti, " (Exponent=%u)", param_exponent);
3623 offset += 1;
3624 break;
3626 case COMP_BLOCK_SCALE:
3627 /* Separate into integer and fractional bits? */
3628 proto_tree_add_item(udcompparam_tree, hf_oran_blockScaler,
3629 tvb, offset, 1, ENC_BIG_ENDIAN);
3630 offset++;
3631 break;
3633 case COMP_U_LAW:
3634 /* compBitWidth, compShift */
3635 proto_tree_add_item(udcompparam_tree, hf_oran_compBitWidth,
3636 tvb, offset, 1, ENC_BIG_ENDIAN);
3637 proto_tree_add_item(udcompparam_tree, hf_oran_compShift,
3638 tvb, offset, 1, ENC_BIG_ENDIAN);
3639 offset += 1;
3640 break;
3642 case BFP_AND_SELECTIVE_RE:
3643 /* sReSMask + exponent */
3644 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_sReSMask,
3645 tvb, offset, 2, ENC_BIG_ENDIAN, &param_sresmask);
3646 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
3647 tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
3648 *sReSMask = param_sresmask;
3649 *exponent = param_exponent;
3650 offset += 2;
3651 break;
3653 case MOD_COMPR_AND_SELECTIVE_RE:
3654 /* sReSMask + reserved*/
3655 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_sReSMask,
3656 tvb, offset, 2, ENC_BIG_ENDIAN, &param_sresmask);
3657 proto_tree_add_item(udcompparam_tree, hf_oran_reserved_4bits,
3658 tvb, offset, 1, ENC_BIG_ENDIAN);
3659 *sReSMask = param_sresmask;
3660 offset += 2;
3661 break;
3663 default:
3664 /* reserved (set to all zeros), but how many bytes?? */
3665 break;
3668 return offset;
3672 /* Dissect ciCompHdr (channel information compression header, 7.5.2.15) */
3673 /* bit_width and comp_meth are out params */
3674 static int dissect_cicomphdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
3675 unsigned *bit_width, unsigned *comp_meth, uint8_t *comp_opt)
3677 /* Subtree */
3678 proto_item *cicomphdr_ti = proto_tree_add_string_format(tree, hf_oran_ciCompHdr,
3679 tvb, offset, 1, "",
3680 "ciCompHdr");
3681 proto_tree *cicomphdr_tree = proto_item_add_subtree(cicomphdr_ti, ett_oran_cicomphdr);
3683 /* ciIqWidth */
3684 uint32_t hdr_iq_width;
3685 proto_item *iq_width_item = proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
3686 hdr_iq_width = (hdr_iq_width) ? hdr_iq_width : 16;
3687 if (bit_width) {
3688 *bit_width = hdr_iq_width;
3690 proto_item_append_text(iq_width_item, " (%u bits)", hdr_iq_width);
3692 /* ciCompMeth */
3693 uint32_t ci_comp_meth;
3694 proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrMeth, tvb, offset, 1, ENC_NA, &ci_comp_meth);
3695 if (comp_meth) {
3696 *comp_meth = ci_comp_meth;
3699 /* ciCompOpt */
3700 uint32_t opt;
3701 proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompOpt, tvb, offset, 1, ENC_NA, &opt);
3702 *comp_opt = opt;
3703 offset += 1;
3705 /* Summary */
3706 proto_item_append_text(cicomphdr_ti, " (IqWidth=%u, ciCompMeth=%s, ciCompOpt=%s)",
3707 hdr_iq_width,
3708 rval_to_str_const(ci_comp_meth, ud_comp_header_meth, "Unknown"),
3709 (*comp_opt) ? "compression per PRB" : "compression per UE");
3710 return offset;
3713 static void dissect_payload_version(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, unsigned offset)
3715 unsigned version;
3716 proto_item *ti = proto_tree_add_item_ret_uint(tree, hf_oran_payload_version, tvb, offset, 1, ENC_NA, &version);
3717 if (version != 1) {
3718 expert_add_info_format(pinfo, ti, &ei_oran_version_unsupported,
3719 "PayloadVersion %u not supported by dissector (only 1 is known)",
3720 version);
3721 /* TODO: should throw an exception? */
3725 static void show_link_to_acknack_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
3726 ack_nack_request_t *request)
3728 /* Request frame */
3729 proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_request_frame,
3730 tvb, 0, 0, request->request_frame_number);
3731 PROTO_ITEM_SET_GENERATED(ti);
3733 /* Work out gap between frames (in ms) */
3734 int seconds_between_packets = (int)
3735 (pinfo->abs_ts.secs - request->request_frame_time.secs);
3736 int nseconds_between_packets =
3737 pinfo->abs_ts.nsecs - request->request_frame_time.nsecs;
3739 int total_gap = (seconds_between_packets*1000) +
3740 ((nseconds_between_packets+500000) / 1000000);
3742 ti = proto_tree_add_uint(tree, hf_oran_acknack_request_time,
3743 tvb, 0, 0, total_gap);
3744 PROTO_ITEM_SET_GENERATED(ti);
3746 /* Type of request */
3747 ti = proto_tree_add_uint(tree, hf_oran_acknack_request_type,
3748 tvb, 0, 0, request->requestType);
3749 PROTO_ITEM_SET_GENERATED(ti);
3752 static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
3753 ack_nack_request_t *response)
3755 if (response->response_frame_number == 0) {
3756 /* Requests may not get a response, and can't always tell when to expect one */
3757 return;
3760 /* Response frame */
3761 proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_response_frame,
3762 tvb, 0, 0, response->response_frame_number);
3763 PROTO_ITEM_SET_GENERATED(ti);
3765 /* Work out gap between frames (in ms) */
3766 int seconds_between_packets = (int)
3767 (response->response_frame_time.secs - pinfo->abs_ts.secs);
3768 int nseconds_between_packets =
3769 response->response_frame_time.nsecs - pinfo->abs_ts.nsecs;
3771 int total_gap = (seconds_between_packets*1000) +
3772 ((nseconds_between_packets+500000) / 1000000);
3774 ti = proto_tree_add_uint(tree, hf_oran_acknack_response_time,
3775 tvb, 0, 0, total_gap);
3776 PROTO_ITEM_SET_GENERATED(ti);
3781 /* Control plane dissector (section 7). */
3782 static int dissect_oran_c(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3784 /* Hidden filter for plane */
3785 proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_cplane, tvb, 0, 0, ENC_NA);
3786 PROTO_ITEM_SET_HIDDEN(plane_ti);
3788 /* Set up structures needed to add the protocol subtree and manage it */
3789 unsigned offset = 0;
3791 col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-C");
3792 col_set_str(pinfo->cinfo, COL_INFO, "C-Plane");
3794 /* Create display subtree for the protocol */
3795 proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
3796 proto_item_append_text(protocol_item, "-C");
3797 proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
3799 uint16_t eAxC;
3800 addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_rtcid, &eAxC);
3802 /* Message identifier */
3803 uint8_t seq_id;
3804 proto_item *seq_id_ti;
3805 offset = addSeqid(tvb, oran_tree, offset, ORAN_C_PLANE, &seq_id, &seq_id_ti);
3807 proto_item *sectionHeading;
3809 /* Section subtree */
3810 int section_tree_offset = offset;
3811 proto_tree *section_tree = proto_tree_add_subtree(oran_tree, tvb, offset, 2, ett_oran_section_type, &sectionHeading, "C-Plane Section Type ");
3813 /* Peek ahead at the section type */
3814 uint32_t sectionType = 0;
3815 sectionType = tvb_get_uint8(tvb, offset+5);
3817 uint32_t scs = 0;
3818 proto_item *scs_ti = NULL;
3820 /* dataDirection */
3821 uint32_t direction = 0;
3822 proto_tree_add_item_ret_uint(section_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
3824 /* Look up any existing conversation state for eAxC+plane */
3825 uint32_t key = make_flow_key(eAxC, ORAN_C_PLANE);
3826 flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
3828 /* Update/report status of conversation */
3829 if (!PINFO_FD_VISITED(pinfo)) {
3831 if (state == NULL) {
3832 /* Allocate new state */
3833 state = wmem_new0(wmem_file_scope(), flow_state_t);
3834 state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
3835 wmem_tree_insert32(flow_states_table, key, state);
3838 /* Check sequence analysis status */
3839 if (seq_id != state->next_expected_sequence_number[direction]) {
3840 /* Store this result */
3841 flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
3842 result->unexpected_seq_number = true;
3843 result->expected_sequence_number = state->next_expected_sequence_number[direction];
3844 result->previous_frame = state->last_frame[direction];
3845 wmem_tree_insert32(flow_results_table, pinfo->num, result);
3847 /* Update conversation info */
3848 state->last_frame[direction] = pinfo->num;
3849 state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
3852 /* Show any issues associated with this frame number */
3853 flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
3854 if (result!=NULL && result->unexpected_seq_number) {
3855 expert_add_info_format(pinfo, seq_id_ti, &ei_oran_cplane_unexpected_sequence_number,
3856 "Sequence number %u expected, but got %u",
3857 result->expected_sequence_number, seq_id);
3858 /* TODO: could add previous/next frames (in seqId tree?) ? */
3861 /* payloadVersion */
3862 dissect_payload_version(section_tree, tvb, pinfo, offset);
3864 /* filterIndex */
3865 if (sectionType == SEC_C_SLOT_CONTROL || sectionType == SEC_C_ACK_NACK_FEEDBACK) {
3866 /* scs (for ST4 and ST8) */
3867 scs_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
3869 else if (sectionType != SEC_C_LAA) {
3870 /* filterIndex (most common case) */
3871 proto_tree_add_item(section_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
3873 offset += 1;
3875 unsigned ref_a_offset = offset;
3876 /* frameId */
3877 uint32_t frameId = 0;
3878 proto_tree_add_item_ret_uint(section_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
3879 offset += 1;
3881 /* subframeId */
3882 uint32_t subframeId = 0;
3883 proto_tree_add_item_ret_uint(section_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
3884 /* slotId */
3885 uint32_t slotId = 0;
3886 proto_tree_add_item_ret_uint(section_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
3887 offset++;
3889 /* startSymbolId */
3890 uint32_t startSymbolId = 0;
3891 proto_item *ssid_ti = NULL;
3892 if ((sectionType == SEC_C_ACK_NACK_FEEDBACK) || /* Section Type 8 */
3893 (sectionType == SEC_C_SINR_REPORTING)) { /* Section Type 9 */
3894 /* symbolId */
3895 proto_tree_add_item(section_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA);
3897 else if (sectionType != SEC_C_LAA) {
3898 /* startSymbolId is in most section types */
3899 ssid_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_start_symbol_id, tvb, offset, 1, ENC_NA, &startSymbolId);
3901 offset++;
3903 char id[16];
3904 snprintf(id, 16, "%d-%d-%d", frameId, subframeId, slotId);
3905 proto_item *pi = proto_tree_add_string(section_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
3906 proto_item_set_generated(pi);
3908 uint32_t cmd_scope = 0;
3909 bool st8_ready = false;
3911 /* numberOfSections (or whatever section has instead) */
3912 uint32_t nSections = 0;
3913 if (sectionType == SEC_C_SLOT_CONTROL) { /* Section Type 4 */
3914 /* Slot Control has these fields instead */
3915 /* reserved */
3916 proto_tree_add_item(section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
3917 /* cmdScope (4 bits) */
3918 proto_tree_add_item_ret_uint(section_tree, hf_oran_cmd_scope, tvb, offset, 1, ENC_NA, &cmd_scope);
3920 else if (sectionType == SEC_C_ACK_NACK_FEEDBACK) { /* Section Type 8 */
3921 /* reserved (7 bits) */
3922 proto_tree_add_item(section_tree, hf_oran_reserved_7bits, tvb, offset, 1, ENC_NA);
3923 /* ready (1 bit) */
3924 /* TODO: when set, ready in slotId+1.. */
3925 proto_tree_add_item_ret_boolean(section_tree, hf_oran_ready, tvb, offset, 1, ENC_NA, &st8_ready);
3926 if (!st8_ready) {
3927 /* SCS value is ignored, and may be set to any value by O-RU */
3928 proto_item_append_text(scs_ti, " (ignored)");
3931 else if (sectionType != SEC_C_LAA) {
3932 proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfSections, tvb, offset, 1, ENC_NA, &nSections);
3934 offset++;
3936 /* sectionType */
3937 proto_tree_add_item_ret_uint(section_tree, hf_oran_sectionType, tvb, offset, 1, ENC_NA, &sectionType);
3938 offset += 1;
3940 /* Section-specific fields (white entries in Section Type diagrams) */
3941 unsigned bit_width = 0;
3942 int comp_meth = 0;
3943 unsigned ci_comp_method = 0;
3944 uint8_t ci_comp_opt = 0;
3946 uint32_t num_ues = 0;
3947 uint32_t number_of_acks = 0, number_of_nacks = 0;
3949 uint32_t num_sinr_per_prb = 0;
3951 switch (sectionType) {
3952 case SEC_C_UNUSED_RB: /* Section Type 0 */
3953 /* timeOffset */
3954 proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
3955 offset += 2;
3956 /* frameStructure */
3957 offset = dissect_frame_structure(section_tree, tvb, offset,
3958 subframeId, slotId);
3960 /* cpLength */
3961 proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
3962 offset += 2;
3963 /* reserved */
3964 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
3965 offset += 1;
3966 break;
3968 case SEC_C_NORMAL: /* Section Type 1 */
3969 case SEC_C_UE_SCHED: /* Section Type 5 */
3970 /* udCompHdr */
3971 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
3972 (direction==1), /* ignore for DL */
3973 &bit_width, &comp_meth);
3974 /* reserved */
3975 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
3976 offset += 1;
3977 break;
3979 case SEC_C_SLOT_CONTROL: /* Section Type 4 */
3980 break;
3982 case SEC_C_PRACH: /* Section Type 3 */
3983 /* timeOffset */
3984 proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
3985 offset += 2;
3986 /* frameStructure */
3987 offset = dissect_frame_structure(section_tree, tvb, offset,
3988 subframeId, slotId);
3989 /* cpLength */
3990 proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
3991 offset += 2;
3992 /* udCompHdr */
3993 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
3994 (direction==1), /* ignore for DL */
3995 &bit_width, &comp_meth);
3996 break;
3998 case SEC_C_CH_INFO: /* Section Type 6 */
3999 /* numberOfUEs */
4000 proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfUEs, tvb, offset, 1, ENC_NA, &num_ues);
4001 offset += 1;
4002 /* ciCompHdr (was reserved) */
4003 offset = dissect_cicomphdr(tvb, pinfo, section_tree, offset, &bit_width, &ci_comp_method, &ci_comp_opt);
4005 /* Number of sections may not be filled in, so set to the number of UEs */
4006 if (nSections == 0) {
4007 nSections = num_ues;
4009 break;
4011 case SEC_C_RSVD2:
4012 case SEC_C_LAA: /* Section Type 7 */
4013 break;
4015 case SEC_C_ACK_NACK_FEEDBACK: /* Section Type 8 */
4016 /* numberOfAcks (1 byte) */
4017 proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_acks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_acks);
4018 offset += 1;
4019 /* numberOfNacks (1 byte) */
4020 proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_nacks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_nacks);
4021 offset += 1;
4023 /* Show ACKs and NACKs. For both, try to link back to request. */
4024 for (unsigned int n=1; n <= number_of_acks; n++) {
4025 uint32_t ackid;
4026 proto_item *ack_ti;
4027 ack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_ackid, tvb, offset, 2, ENC_BIG_ENDIAN, &ackid);
4028 offset += 2;
4030 /* Look up request table in state (which really should be set by now, but test anyway). */
4031 if (state) {
4032 ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, ackid);
4033 if (request != NULL) {
4034 /* On first pass, update with this response */
4035 if (!PINFO_FD_VISITED(pinfo)) {
4036 request->response_frame_number = pinfo->num;
4037 request->response_frame_time = pinfo->abs_ts;
4040 /* Show request details */
4041 show_link_to_acknack_request(section_tree, tvb, pinfo, request);
4043 else {
4044 /* Request not found */
4045 expert_add_info_format(pinfo, ack_ti, &ei_oran_acknack_no_request,
4046 "Response for ackId=%u received, but no request found",
4047 ackid);
4051 for (unsigned int m=1; m <= number_of_nacks; m++) {
4052 uint32_t nackid;
4053 proto_item *nack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_nackid, tvb, offset, 2, ENC_BIG_ENDIAN, &nackid);
4054 offset += 2;
4056 expert_add_info_format(pinfo, nack_ti, &ei_oran_st8_nackid,
4057 "Received Nack for ackNackId=%u",
4058 nackid);
4060 /* Look up request table in state. */
4061 if (state) {
4062 ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, nackid);
4063 if (request) {
4064 /* On first pass, update with this response */
4065 if (!PINFO_FD_VISITED(pinfo)) {
4066 request->response_frame_number = pinfo->num;
4067 request->response_frame_time = pinfo->abs_ts;
4070 /* Show request details */
4071 show_link_to_acknack_request(section_tree, tvb, pinfo, request);
4073 else {
4074 /* Request not found */
4075 expert_add_info_format(pinfo, nack_ti, &ei_oran_acknack_no_request,
4076 "Response for nackId=%u received, but no request found",
4077 nackid);
4081 break;
4083 case SEC_C_SINR_REPORTING: /* Section Type 9 */
4084 /* numSinrPerPrb (3 bits) */
4085 proto_tree_add_item_ret_uint(section_tree, hf_oran_num_sinr_per_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sinr_per_prb);
4086 switch (num_sinr_per_prb) {
4087 case 0:
4088 num_sinr_per_prb = 1; break;
4089 case 1:
4090 num_sinr_per_prb = 2; break;
4091 case 2:
4092 num_sinr_per_prb = 3; break;
4093 case 3:
4094 num_sinr_per_prb = 4; break;
4095 case 4:
4096 num_sinr_per_prb = 6; break;
4097 case 5:
4098 num_sinr_per_prb = 12; break;
4101 /* reserved (13 bits) */
4102 offset += 1;
4103 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4104 offset += 1;
4105 break;
4109 /* Update udCompHdr details in state for UL U-Plane */
4110 if (!PINFO_FD_VISITED(pinfo) && state && direction==0) {
4111 switch (sectionType) {
4112 case SEC_C_NORMAL: /* Section Type 1 */
4113 case SEC_C_PRACH: /* Section Type 3 */
4114 case SEC_C_UE_SCHED: /* Section Type 5 */
4115 state->ul_ud_comp_hdr_set = true;
4116 state->ul_ud_comp_hdr_bit_width = bit_width;
4117 state->ul_ud_comp_hdr_compression = comp_meth;
4118 break;
4119 default:
4120 break;
4125 proto_item_append_text(sectionHeading, "%d, %s, Frame: %d, Subframe: %d, Slot: %d, StartSymbol: %d",
4126 sectionType, val_to_str_const(direction, data_direction_vals, "Unknown"),
4127 frameId, subframeId, slotId, startSymbolId);
4128 write_pdu_label_and_info(protocol_item, NULL, pinfo, ", Type: %2d %s", sectionType,
4129 rval_to_str_const(sectionType, section_types_short, "Unknown"));
4131 /* Set actual length of C-Plane section header */
4132 proto_item_set_len(section_tree, offset - section_tree_offset);
4134 if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {
4135 write_pdu_label_and_info(oran_tree, section_tree, pinfo,
4136 (st8_ready) ? " (Ready)" : " (ACK)");
4140 /* Section type 4 doesn't have normal sections, so deal with here before normal sections */
4141 if (sectionType == SEC_C_SLOT_CONTROL) {
4142 /* numberOfST4Cmds */
4143 uint32_t no_st4_cmds, st4_cmd_len, num_slots, ack_nack_req_id, st4_cmd_type;
4144 proto_item *no_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_st4_cmds,
4145 tvb, offset, 1, ENC_NA, &no_st4_cmds);
4146 if (no_st4_cmds == 0) {
4147 expert_add_info_format(pinfo, no_ti, &ei_oran_st4_no_cmds,
4148 "Not valid for ST4 to carry no commands");
4150 offset += 1;
4152 /* reserved (1 byte) */
4153 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4154 offset += 1;
4156 /* Loop over commands. Each has 8-byte common header, followed by cmd-specific payload */
4157 proto_item *len_ti;
4158 for (uint32_t n=0; n < no_st4_cmds; n++) {
4159 /* Table 7.4.6-2: Section Type 4 Command common header format */
4160 proto_item *hdr_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd_header,
4161 tvb, offset, 8, "",
4162 "Type 4 Command common header");
4163 proto_tree *hdr_tree = proto_item_add_subtree(hdr_ti, ett_oran_st4_cmd_header);
4165 /* st4CmdType */
4166 proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_type, tvb, offset, 1, ENC_NA, &st4_cmd_type);
4167 offset += 1;
4169 /* st4CmdLen */
4170 len_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_len, tvb, offset, 2, ENC_NA, &st4_cmd_len);
4171 if (st4_cmd_len == 0) {
4172 /* Meaning of 0 not yet defined (v15.00) */
4173 proto_item_append_text(len_ti, " (reserved)");
4174 expert_add_info(pinfo, len_ti, &ei_oran_st4_zero_len_cmd);
4176 else {
4177 proto_item_append_text(len_ti, " (%u bytes)", st4_cmd_len*4);
4179 offset += 2;
4181 /* numSlots */
4182 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);
4183 if (num_slots == 0) {
4184 proto_item_append_text(slots_ti, " (until changed)");
4186 offset += 1;
4188 /* ackNackReqId */
4189 proto_item *ack_nack_req_id_ti;
4190 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_NA, &ack_nack_req_id);
4191 offset += 2;
4192 if (ack_nack_req_id == 0) {
4193 proto_item_append_text(ack_nack_req_id_ti, " (no Section type 8 response expected)");
4196 /* reserved (16 bits) */
4197 proto_tree_add_item(hdr_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4198 offset += 2;
4200 /* Set common header summary */
4201 proto_item_append_text(hdr_ti, " (cmd=%s, len=%u, slots=%u, ackNackReqId=%u)",
4202 rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"),
4203 st4_cmd_len, num_slots, ack_nack_req_id);
4205 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
4206 rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
4209 /* Subtree for this command body */
4210 proto_item *command_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd,
4211 tvb, offset, 0, "",
4212 "Type 4 Command (%s)", rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
4213 proto_tree *command_tree = proto_item_add_subtree(command_ti, ett_oran_st4_cmd);
4215 unsigned command_start_offset = offset;
4217 /* Check fields compatible with chosen command. */
4218 if (st4_cmd_type==1) {
4219 if (num_slots != 0) {
4220 /* "the value of numSlots should be set to zero for this command type" */
4221 expert_add_info_format(pinfo, ssid_ti, &ei_oran_numslots_not_zero,
4222 "numSlots should be zero for ST4 command 1 - found %u",
4223 num_slots);
4227 if (st4_cmd_type==3 || st4_cmd_type==4) {
4228 if (startSymbolId != 0) {
4229 /* "expected reception window for the commands is the symbol zero reception window" */
4230 expert_add_info_format(pinfo, ssid_ti, &ei_oran_start_symbol_id_not_zero,
4231 "startSymbolId should be zero for ST4 commands 3&4 - found %u",
4232 startSymbolId);
4236 /* Add format for this command */
4237 switch (st4_cmd_type) {
4238 case 1: /* TIME_DOMAIN_BEAM_CONFIG */
4240 bool disable_tdbfns;
4241 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
4243 /* reserved (2 bits) */
4244 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4245 /* symbolMask (14 bits) */
4246 proto_tree_add_item(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4247 /* TODO: 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 */
4248 offset += 2;
4250 /* disableTDBFNs */
4251 proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfns, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfns);
4253 /* tdBeamNum */
4254 proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4255 offset += 2;
4257 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
4258 proto_item *comp_meth_ti;
4259 offset = dissect_bfwCompHdr(tvb, command_tree, offset,
4260 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
4261 /* reserved (3 bytes) */
4262 offset += 3;
4264 if (disable_tdbfns) {
4265 /* No beamnum information to show so get out. */
4266 break;
4269 /* Read beam entries until reach end of command length */
4270 while ((offset - command_start_offset) < (st4_cmd_len * 4)) {
4272 /* disableTDBFWs */
4273 bool disable_tdbfws;
4274 proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfws, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfws);
4276 /* tdBeamNum */
4277 proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4278 offset += 2;
4280 /* Showing BFWs? */
4281 if (!disable_tdbfws) {
4283 /* bfwCompParam */
4284 unsigned exponent = 0;
4285 bool supported = false;
4286 offset = dissect_bfwCompParam(tvb, command_tree, pinfo, offset,
4287 comp_meth_ti, bfwcomphdr_comp_meth, &exponent, &supported);
4289 /* Antenna count from preference */
4290 unsigned num_trx = pref_num_bf_antennas;
4291 int bit_offset = offset*8;
4293 for (unsigned trx=0; trx < num_trx; trx++) {
4294 /* Create antenna subtree */
4295 int bfw_offset = bit_offset / 8;
4296 proto_item *bfw_ti = proto_tree_add_string_format(command_tree, hf_oran_bfw,
4297 tvb, bfw_offset, 0, "", "TRX %3u: (", trx);
4298 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
4300 /* I value */
4301 /* Get bits, and convert to float. */
4302 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4303 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
4304 /* Add to tree. */
4305 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
4306 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
4307 bit_offset += bfwcomphdr_iq_width;
4308 proto_item_append_text(bfw_ti, "I=%f ", value);
4310 /* Leave a gap between I and Q values */
4311 proto_item_append_text(bfw_ti, " ");
4313 /* Q value */
4314 /* Get bits, and convert to float. */
4315 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4316 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
4317 /* Add to tree. */
4318 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
4319 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
4320 bit_offset += bfwcomphdr_iq_width;
4321 proto_item_append_text(bfw_ti, "Q=%f", value);
4323 proto_item_append_text(bfw_ti, ")");
4324 proto_item_set_len(bfw_ti, (bit_offset+7)/8 - bfw_offset);
4326 /* Need to round to next byte */
4327 offset = (bit_offset+7)/8;
4330 break;
4332 case 2: /* TDD_CONFIG_PATTERN */
4333 /* reserved (2 bits) */
4334 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4335 /* dirPattern (14 bits) */
4336 proto_tree_add_item(command_tree, hf_oran_dir_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
4337 offset += 2;
4338 /* reserved (2 bits) */
4339 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4340 /* guardPattern (14 bits) */
4341 proto_tree_add_item(command_tree, hf_oran_guard_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
4342 offset += 2;
4343 break;
4345 case 3: /* TRX_CONTROL */
4347 /* Only allowed cmdScope is ARRAY-COMMAND */
4348 if (cmd_scope != 0) {
4349 expert_add_info(pinfo, command_tree, &ei_oran_trx_control_cmd_scope);
4352 /* reserved */
4353 proto_tree_add_item(command_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
4354 /* log2MaskBits (4 bits) */
4355 unsigned log2maskbits;
4356 proto_tree_add_item_ret_uint(command_tree, hf_oran_log2maskbits, tvb, offset, 1, ENC_BIG_ENDIAN, &log2maskbits);
4357 /* sleepMode */
4358 uint32_t sleep_mode;
4359 proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_trx, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
4360 offset += 1;
4362 /* reserved (4 bits) */
4363 proto_tree_add_item(command_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4364 /* numSlotsExt (20 bits) */
4365 uint32_t num_slots_ext;
4366 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);
4367 if (num_slots==0 && num_slots_ext==0) {
4368 proto_item_append_text(num_slots_ext_ti, " (undefined sleep period)");
4370 else {
4371 /* Time should be rounded up according to SCS */
4372 float total = (float)(num_slots + num_slots_ext);
4373 /* From table 7.5.2.13-3 */
4374 float slot_length_by_scs[16] = { 1000, 500, 250, 125, 62.5, 31.25,
4375 0, 0, 0, 0, 0, 0, /* reserved */
4376 1000, 1000, 1000, 1000 };
4377 float slot_length = slot_length_by_scs[scs];
4378 /* Only using valid SCS. TODO: is this test ok? */
4379 if (slot_length != 0) {
4380 /* Round up to next slot */
4381 total = ((int)(total / slot_length) + 1) * slot_length;
4382 proto_item_append_text(num_slots_ext_ti, " (defined sleep period of %f us)", total);
4385 offset += 3;
4387 /* reserved (2 bits) */
4388 proto_tree_add_item(command_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
4390 /* symbolMask (14 bits) */
4391 uint32_t symbol_mask;
4392 proto_item *sm_ti;
4393 sm_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN, &symbol_mask);
4394 if (symbol_mask == 0x0) {
4395 proto_item_append_text(sm_ti, " (wake)");
4396 col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
4398 else if (symbol_mask == 0x3fff) {
4399 proto_item_append_text(sm_ti, " (sleep)");
4400 col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
4402 else {
4403 expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
4404 "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
4405 sleep_mode, symbol_mask);
4407 offset += 2;
4409 /* antMask (16-2048 bits). Size is lookup from log2MaskBits enum.. */
4410 unsigned antmask_length = 2;
4411 if (log2maskbits >= 4) {
4412 antmask_length = (1 << log2maskbits) / 8;
4414 proto_item *ant_mask_ti = proto_tree_add_item(command_tree, hf_oran_antMask_trx_control, tvb, offset, antmask_length, ENC_NA);
4415 /* show count */
4416 unsigned antenna_count = 0;
4417 for (unsigned b=0; b < antmask_length; b++) {
4418 uint8_t byte = tvb_get_uint8(tvb, offset+b);
4419 for (unsigned bit=0; bit < 8; bit++) {
4420 if ((1 << bit) & byte) {
4421 antenna_count++;
4425 proto_item_append_text(ant_mask_ti, " (%u antennas)", antenna_count);
4426 offset += antmask_length;
4428 /* Pad to next 4-byte boundary */
4429 if (offset%4) {
4430 offset += (4-(offset%4));
4432 break;
4435 case 4: /* ASM (advanced sleep mode) */
4436 /* reserved (2+4=6 bits) */
4437 proto_tree_add_item(command_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4438 /* sleepMode (2 bits) */
4439 uint32_t sleep_mode;
4440 proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_asm, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
4441 offset += 1;
4443 /* reserved (4 bits) */
4444 proto_tree_add_item(command_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4445 /* numSlotsExt (20 bits) */
4446 proto_tree_add_item(command_tree, hf_oran_num_slots_ext, tvb, offset, 3, ENC_BIG_ENDIAN);
4447 offset += 3;
4449 /* reserved (2 bits) */
4450 proto_tree_add_item(command_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
4451 /* symbolMask (14 bits) */
4452 uint32_t symbol_mask;
4453 proto_item *sm_ti;
4454 sm_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN, &symbol_mask);
4455 if ((sleep_mode != 0) && (symbol_mask != 0x0 && symbol_mask != 0x3fff)) {
4456 expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
4457 "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3ffff - found 0x%05x",
4458 sleep_mode, symbol_mask);
4460 offset += 2;
4462 /* reserved (2 bytes) */
4463 proto_tree_add_item(command_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4464 offset += 2;
4465 break;
4467 default:
4468 /* Error! */
4469 expert_add_info_format(pinfo, len_ti, &ei_oran_st4_unknown_cmd,
4470 "Dissected ST4 command (%u) not recognised",
4471 st4_cmd_type);
4472 break;
4475 /* Check apparent size of padding (0-3 bytes ok) */
4476 long padding_remaining = command_start_offset + (st4_cmd_len * 4) - offset;
4477 if (padding_remaining < 0 || padding_remaining > 3) {
4478 expert_add_info_format(pinfo, len_ti, &ei_oran_st4_wrong_len_cmd,
4479 "Dissected ST4 command does not match signalled st4CmdLen - set to %u (%u bytes) but dissected %u bytes",
4480 st4_cmd_len, st4_cmd_len*4, offset-command_start_offset);
4483 /* Advance by signalled length (needs to be aligned on 4-byte boundary) */
4484 offset = command_start_offset + (st4_cmd_len * 4);
4486 /* Set end of command tree */
4487 proto_item_set_end(command_ti, tvb, offset);
4489 if (ack_nack_req_id != 0) {
4490 if (!PINFO_FD_VISITED(pinfo)) {
4491 /* Add this request into conversation state on first pass */
4492 ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
4493 request_details->request_frame_number = pinfo->num;
4494 request_details->request_frame_time = pinfo->abs_ts;
4495 request_details->requestType = ST4Cmd1+st4_cmd_type-1;
4497 wmem_tree_insert32(state->ack_nack_requests,
4498 ack_nack_req_id,
4499 request_details);
4501 else {
4502 /* On later passes, try to link forward to ST8 response */
4503 ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
4504 ack_nack_req_id);
4505 if (response) {
4506 show_link_to_acknack_response(section_tree, tvb, pinfo, response);
4513 /* Dissect each C section */
4514 for (uint32_t i = 0; i < nSections; ++i) {
4515 tvbuff_t *section_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, -1);
4516 offset += dissect_oran_c_section(section_tvb, oran_tree, pinfo, state, sectionType, protocol_item,
4517 subframeId, slotId,
4518 bit_width, ci_comp_method, ci_comp_opt,
4519 num_sinr_per_prb);
4522 /* Expert error if we are short of tvb by > 3 bytes */
4523 if (tvb_reported_length_remaining(tvb, offset) > 3) {
4524 expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
4525 "%u bytes remain at end of frame - should be 0-3",
4526 tvb_reported_length_remaining(tvb, offset));
4529 return tvb_captured_length(tvb);
4532 static int dissect_oran_u_re(tvbuff_t *tvb, proto_tree *tree,
4533 unsigned sample_number, int samples_offset,
4534 unsigned sample_bit_width,
4535 int comp_meth,
4536 uint32_t exponent)
4538 /* I */
4539 unsigned i_bits = tvb_get_bits(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
4540 float i_value = decompress_value(i_bits, comp_meth, sample_bit_width, exponent);
4541 unsigned sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
4542 proto_item *i_ti = proto_tree_add_float(tree, hf_oran_iSample, tvb, samples_offset/8, sample_len_in_bytes, i_value);
4543 proto_item_set_text(i_ti, "iSample: %0.12f 0x%04x (iSample-%u in the PRB)", i_value, i_bits, sample_number);
4544 samples_offset += sample_bit_width;
4545 /* Q */
4546 unsigned q_bits = tvb_get_bits(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
4547 float q_value = decompress_value(q_bits, comp_meth, sample_bit_width, exponent);
4548 sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
4549 proto_item *q_ti = proto_tree_add_float(tree, hf_oran_qSample, tvb, samples_offset/8, sample_len_in_bytes, q_value);
4550 proto_item_set_text(q_ti, "qSample: %0.12f 0x%04x (qSample-%u in the PRB)", q_value, q_bits, sample_number);
4551 samples_offset += sample_bit_width;
4553 return samples_offset;
4557 /* User plane dissector (section 8) */
4558 static int
4559 dissect_oran_u(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
4561 /* Hidden filter for plane */
4562 proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_uplane, tvb, 0, 0, ENC_NA);
4563 PROTO_ITEM_SET_HIDDEN(plane_ti);
4565 /* Set up structures needed to add the protocol subtree and manage it */
4566 int offset = 0;
4568 col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-U");
4569 col_set_str(pinfo->cinfo, COL_INFO, "U-Plane");
4571 /* Create display subtree for the protocol */
4572 proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
4573 proto_item_append_text(protocol_item, "-U");
4574 proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
4576 /* Transport header */
4577 /* Real-time control data / IQ data transfer message series identifier */
4578 uint16_t eAxC;
4579 addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_pcid, &eAxC);
4581 /* Message identifier */
4582 uint8_t seq_id;
4583 proto_item *seq_id_ti;
4584 offset = addSeqid(tvb, oran_tree, offset, ORAN_U_PLANE, &seq_id, &seq_id_ti);
4586 /* Common header for time reference */
4587 proto_item *timingHeader;
4588 proto_tree *timing_header_tree = proto_tree_add_subtree(oran_tree, tvb, offset, 4, ett_oran_u_timing, &timingHeader, "Timing header (");
4590 /* dataDirection */
4591 uint32_t direction;
4592 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
4593 /* payloadVersion */
4594 dissect_payload_version(timing_header_tree, tvb, pinfo, offset);
4595 /* filterIndex */
4596 proto_tree_add_item(timing_header_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
4597 offset += 1;
4599 int ref_a_offset = offset;
4601 /* frameId */
4602 uint32_t frameId = 0;
4603 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
4604 offset += 1;
4606 /* subframeId */
4607 uint32_t subframeId = 0;
4608 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
4609 /* slotId */
4610 uint32_t slotId = 0;
4611 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
4612 offset++;
4613 /* symbolId */
4614 uint32_t symbolId = 0;
4615 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, &symbolId);
4616 offset++;
4618 char id[16];
4619 snprintf(id, 16, "%d-%d-%d", frameId, subframeId, slotId);
4620 proto_item *pi = proto_tree_add_string(timing_header_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
4621 proto_item_set_generated(pi);
4623 proto_item_append_text(timingHeader, "%s, Frame: %d, Subframe: %d, Slot: %d, Symbol: %d)",
4624 val_to_str_const(direction, data_direction_vals, "Unknown"), frameId, subframeId, slotId, symbolId);
4626 unsigned sample_bit_width;
4627 int compression;
4628 bool includeUdCompHeader;
4630 /* Update/report status of conversation */
4631 uint32_t key = make_flow_key(eAxC, ORAN_U_PLANE);
4632 flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
4634 if (!PINFO_FD_VISITED(pinfo)) {
4635 /* Create conversation if doesn't exist yet */
4636 if (!state) {
4637 /* Allocate new state */
4638 state = wmem_new0(wmem_file_scope(), flow_state_t);
4639 state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
4640 wmem_tree_insert32(flow_states_table, key, state);
4643 /* Check sequence analysis status */
4644 if (seq_id != state->next_expected_sequence_number[direction]) {
4645 /* Store this result */
4646 flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
4647 result->unexpected_seq_number = true;
4648 result->expected_sequence_number = state->next_expected_sequence_number[direction];
4649 result->previous_frame = state->last_frame[direction];
4650 wmem_tree_insert32(flow_results_table, pinfo->num, result);
4652 /* Update sequence analysis state */
4653 state->last_frame[direction] = pinfo->num;
4654 state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
4657 /* Show any issues associated with this frame number */
4658 flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
4659 if (result) {
4660 if (result->unexpected_seq_number) {
4661 expert_add_info_format(pinfo, seq_id_ti, &ei_oran_uplane_unexpected_sequence_number,
4662 "Sequence number %u expected, but got %u",
4663 result->expected_sequence_number, seq_id);
4664 /* TODO: could add previous frame (in seqId tree?) ? */
4668 if (direction == DIR_UPLINK) {
4669 sample_bit_width = pref_sample_bit_width_uplink;
4670 compression = pref_iqCompressionUplink;
4671 includeUdCompHeader = pref_includeUdCompHeaderUplink;
4672 } else {
4673 sample_bit_width = pref_sample_bit_width_downlink;
4674 compression = pref_iqCompressionDownlink;
4675 includeUdCompHeader = pref_includeUdCompHeaderDownlink;
4678 /* If uplink, load any udCompHdr settings written by C-Plane */
4679 bool ud_cmp_hdr_cplane = false;
4680 if (state && direction == 0) {
4681 /* Initialise settings from udpCompHdr from C-Plane */
4682 if (state->ul_ud_comp_hdr_set) {
4683 sample_bit_width = state->ul_ud_comp_hdr_bit_width;
4684 compression = state->ul_ud_comp_hdr_compression;
4686 ud_cmp_hdr_cplane = true;
4690 /* Need a valid value (e.g. 9, 14). 0 definitely won't work, as won't progress around loop! */
4691 /* N.B. may yet be overwritten by udCompHdr settings in sections below! */
4692 if (sample_bit_width == 0) {
4693 expert_add_info_format(pinfo, protocol_item, &ei_oran_invalid_sample_bit_width,
4694 "%cL Sample bit width from %s (%u) not valid, so can't decode sections",
4695 (direction == DIR_UPLINK) ? 'U' : 'D',
4696 !ud_cmp_hdr_cplane ? "preference" : "C-Plane",
4697 sample_bit_width);
4698 return offset;
4701 unsigned bytesLeft;
4702 unsigned number_of_sections = 0;
4703 unsigned nBytesPerPrb =0;
4705 /* Add each section (no count, just keep parsing until payload used) */
4706 do {
4707 unsigned section_start_offet = offset;
4708 proto_item *sectionHeading;
4709 proto_tree *section_tree = proto_tree_add_subtree(oran_tree, tvb, offset, 0, ett_oran_u_section, &sectionHeading, "Section");
4711 /* Section Header fields (darker green part) */
4713 /* sectionId */
4714 uint32_t sectionId = 0;
4715 proto_item *ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
4716 if (sectionId == 4095) {
4717 proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
4719 offset++;
4720 /* rb */
4721 uint32_t rb;
4722 proto_tree_add_item_ret_uint(section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
4723 /* symInc */
4724 proto_tree_add_item(section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
4725 /* startPrbu */
4726 uint32_t startPrbu = 0;
4727 proto_tree_add_item_ret_uint(section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
4728 offset += 2;
4730 /* numPrbu */
4731 uint32_t numPrbu = 0;
4732 proto_tree_add_item_ret_uint(section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
4733 offset += 1;
4735 if (includeUdCompHeader) {
4736 /* 7.5.2.10 */
4737 /* Extract these values to inform how wide IQ samples in each PRB will be. */
4738 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset, false, &sample_bit_width, &compression);
4740 /* Not part of udCompHdr */
4741 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
4742 offset += 1;
4744 else {
4745 /* Showing comp values from prefs */
4746 /* iqWidth */
4747 proto_item *iq_width_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrIqWidth_pref, tvb, 0, 0, sample_bit_width);
4748 proto_item_append_text(iq_width_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
4749 proto_item_set_generated(iq_width_item);
4751 /* udCompMethod */
4752 proto_item *ud_comp_meth_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, compression);
4753 proto_item_append_text(ud_comp_meth_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
4754 proto_item_set_generated(ud_comp_meth_item);
4757 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
4759 /* TODO: should this use the same pref as c-plane? */
4760 if (numPrbu == 0) {
4761 /* Special case for all PRBs (NR: the total number of PRBs may be > 255) */
4762 numPrbu = pref_data_plane_section_total_rbs;
4763 startPrbu = 0; /* may already be 0... */
4766 /* Add each PRB */
4767 for (unsigned i = 0; i < numPrbu; i++) {
4768 /* Create subtree */
4769 proto_item *prbHeading = proto_tree_add_string_format(section_tree, hf_oran_samples_prb,
4770 tvb, offset, 0,
4771 "", "PRB");
4772 proto_tree *rb_tree = proto_item_add_subtree(prbHeading, ett_oran_u_prb);
4773 uint32_t exponent = 0;
4774 uint16_t sresmask = 0;
4776 /* udCompParam (depends upon compression method) */
4777 int before = offset;
4778 offset = dissect_udcompparam(tvb, pinfo, rb_tree, offset, compression, &exponent, &sresmask, false);
4779 int udcompparam_len = offset-before;
4781 /* Show PRB number in root */
4782 proto_item_append_text(prbHeading, " %3u", startPrbu + i*(1+rb));
4784 /* Work out how many REs / PRB */
4785 unsigned res_per_prb = 12;
4786 if (compression==BFP_AND_SELECTIVE_RE || compression==MOD_COMPR_AND_SELECTIVE_RE) {
4787 res_per_prb = 0;
4788 /* Use sresmask to pick out which REs are present */
4789 for (unsigned n=0; n<12; n++) {
4790 if (sresmask & (1<<n)) {
4791 res_per_prb++;
4796 unsigned nBytesForSamples = (sample_bit_width * res_per_prb * 2) / 8;
4797 nBytesPerPrb = nBytesForSamples + udcompparam_len;
4799 proto_tree_add_item(rb_tree, hf_oran_iq_user_data, tvb, offset, nBytesForSamples, ENC_NA);
4801 /* Optionally trying to show I/Q samples */
4802 if (pref_showIQSampleValues) {
4803 /* Individual values */
4804 unsigned samples_offset = offset*8;
4805 unsigned samples = 0;
4807 if (compression==BFP_AND_SELECTIVE_RE || compression==MOD_COMPR_AND_SELECTIVE_RE) {
4808 /* Use sresmask to pick out which REs are present */
4809 for (unsigned n=0; n<12; n++) {
4810 if (sresmask & (1<<n)) {
4811 samples_offset = dissect_oran_u_re(tvb, rb_tree,
4812 n, samples_offset, sample_bit_width, compression, exponent);
4813 samples++;
4817 else {
4818 /* All 12 REs are present */
4819 for (unsigned n = 0; n<12; n++) {
4820 samples_offset = dissect_oran_u_re(tvb, rb_tree,
4821 n, samples_offset, sample_bit_width, compression, exponent);
4822 samples++;
4825 proto_item_append_text(prbHeading, " (%u samples)", samples);
4828 /* Advance past samples */
4829 offset += nBytesForSamples;
4831 /* Set end of prb subtree */
4832 proto_item_set_end(prbHeading, tvb, offset);
4835 /* Set extent of section */
4836 proto_item_set_len(sectionHeading, offset-section_start_offet);
4838 bytesLeft = tvb_captured_length(tvb) - offset;
4839 number_of_sections++;
4840 } while (bytesLeft >= (4 + nBytesPerPrb)); /* FIXME: bad heuristic */
4842 /* Show number of sections found */
4843 proto_item *ti = proto_tree_add_uint(oran_tree, hf_oran_numberOfSections, tvb, 0, 0, number_of_sections);
4844 proto_item_set_generated(ti);
4846 /* Expert error if we are short of tvb by > 3 bytes */
4847 if (tvb_reported_length_remaining(tvb, offset) > 3) {
4848 expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
4849 "%u bytes remain at end of frame - should be 0-3",
4850 tvb_reported_length_remaining(tvb, offset));
4853 return tvb_captured_length(tvb);
4857 /**********************************************************************/
4858 /* Main dissection function. */
4859 /* N.B. ecpri message type passed in as 'data' arg by eCPRI dissector */
4860 static int
4861 dissect_oran(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4863 uint32_t ecpri_message_type = *(uint32_t *)data;
4865 switch (ecpri_message_type) {
4866 case ECPRI_MT_IQ_DATA:
4867 return dissect_oran_u(tvb, pinfo, tree, data);
4868 case ECPRI_MT_RT_CTRL_DATA:
4869 return dissect_oran_c(tvb, pinfo, tree, data);
4871 default:
4872 /* Not dissecting other types - assume these are handled by eCPRI dissector */
4873 return 0;
4878 /* Register the protocol with Wireshark. */
4879 void
4880 proto_register_oran(void)
4882 static hf_register_info hf[] = {
4884 /* Section 3.1.3.1.6 */
4885 { &hf_oran_du_port_id,
4886 { "DU Port ID", "oran_fh_cus.du_port_id",
4887 FT_UINT16, BASE_DEC,
4888 NULL, 0x0,
4889 "Width set in dissector preference", HFILL }
4892 /* Section 3.1.3.1.6 */
4893 { &hf_oran_bandsector_id,
4894 { "BandSector ID", "oran_fh_cus.bandsector_id",
4895 FT_UINT16, BASE_DEC,
4896 NULL, 0x0,
4897 "Width set in dissector preference", HFILL }
4900 /* Section 3.1.3.1.6 */
4901 { &hf_oran_cc_id,
4902 { "CC ID", "oran_fh_cus.cc_id",
4903 FT_UINT16, BASE_DEC,
4904 NULL, 0x0,
4905 "Width set in dissector preference", HFILL }
4908 /* Section 3.1.3.1.6 */
4909 { &hf_oran_ru_port_id,
4910 { "RU Port ID", "oran_fh_cus.ru_port_id",
4911 FT_UINT16, BASE_DEC,
4912 NULL, 0x0,
4913 "Width set in dissector preference", HFILL }
4916 /* Section 3.1.3.1.7 */
4917 { &hf_oran_sequence_id,
4918 { "Sequence ID", "oran_fh_cus.sequence_id",
4919 FT_UINT8, BASE_DEC,
4920 NULL, 0x0,
4921 "The Sequence ID wraps around individually per c_eAxC",
4922 HFILL }
4925 /* Section 3.1.3.1.7 */
4926 { &hf_oran_e_bit,
4927 { "E Bit", "oran_fh_cus.e_bit",
4928 FT_UINT8, BASE_DEC,
4929 VALS(e_bit), 0x80,
4930 "Indicate the last message of a subsequence (U-Plane only)",
4931 HFILL }
4934 /* Section 3.1.3.1.7 */
4935 { &hf_oran_subsequence_id,
4936 { "Subsequence ID", "oran_fh_cus.subsequence_id",
4937 FT_UINT8, BASE_DEC,
4938 NULL, 0x7f,
4939 "The subsequence ID (for eCPRI layer fragmentation)",
4940 HFILL }
4943 /* Section 7.5.2.1 */
4944 { &hf_oran_data_direction,
4945 { "Data Direction", "oran_fh_cus.data_direction",
4946 FT_UINT8, BASE_DEC,
4947 VALS(data_direction_vals), 0x80,
4948 "gNB data direction",
4949 HFILL }
4952 /* Section 7.5.2.2 */
4953 { &hf_oran_payload_version,
4954 {"Payload Version", "oran_fh_cus.payloadVersion",
4955 FT_UINT8, BASE_DEC,
4956 NULL, 0x70,
4957 "Payload protocol version the following IEs",
4958 HFILL}
4961 /* Section 7.5.2.3 */
4962 {&hf_oran_filter_index,
4963 {"Filter Index", "oran_fh_cus.filterIndex",
4964 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
4965 RVALS(filter_indices), 0x0f,
4966 "used between IQ data and air interface, both in DL and UL",
4967 HFILL}
4970 /* Section 7.5.2.4 */
4971 {&hf_oran_frame_id,
4972 {"Frame ID", "oran_fh_cus.frameId",
4973 FT_UINT8, BASE_DEC,
4974 NULL, 0x0,
4975 "A counter for 10 ms frames (wrapping period 2.56 seconds)",
4976 HFILL}
4979 /* Section 7.5.2.5 */
4980 {&hf_oran_subframe_id,
4981 {"Subframe ID", "oran_fh_cus.subframe_id",
4982 FT_UINT8, BASE_DEC,
4983 NULL, 0xf0,
4984 "A counter for 1 ms sub-frames within 10ms frame",
4985 HFILL}
4988 /* Section 7.5.2.6 */
4989 {&hf_oran_slot_id,
4990 {"Slot ID", "oran_fh_cus.slotId",
4991 FT_UINT16, BASE_DEC,
4992 NULL, 0x0fc0,
4993 "Slot number within a 1ms sub-frame",
4994 HFILL}
4997 /* Generated for convenience */
4998 {&hf_oran_slot_within_frame,
4999 {"Slot within frame", "oran_fh_cus.slot-within-frame",
5000 FT_UINT16, BASE_DEC,
5001 NULL, 0x0,
5002 "Slot within frame, to match DCT logs",
5003 HFILL}
5006 /* Section 7.5.2.7 */
5007 {&hf_oran_start_symbol_id,
5008 {"Start Symbol ID", "oran_fh_cus.startSymbolId",
5009 FT_UINT8, BASE_DEC,
5010 NULL, 0x3f,
5011 "The first symbol number within slot affected",
5012 HFILL}
5015 /* Section 7.5.2.8 */
5016 {&hf_oran_numberOfSections,
5017 {"Number of Sections", "oran_fh_cus.numberOfSections",
5018 FT_UINT8, BASE_DEC,
5019 NULL, 0x0,
5020 "The number of section IDs included in this C-Plane message",
5021 HFILL}
5024 /* Section 7.5.2.9 */
5025 {&hf_oran_sectionType,
5026 {"Section Type", "oran_fh_cus.sectionType",
5027 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5028 RVALS(section_types), 0x0,
5029 "Determines the characteristics of U-plane data",
5030 HFILL}
5033 /* Section 7.5.2.10 */
5034 {&hf_oran_udCompHdr,
5035 {"udCompHdr", "oran_fh_cus.udCompHdr",
5036 FT_STRING, BASE_NONE,
5037 NULL, 0x0,
5038 NULL,
5039 HFILL}
5042 /* Section 7.5.2.11 */
5043 {&hf_oran_numberOfUEs,
5044 {"Number Of UEs", "oran_fh_cus.numberOfUEs",
5045 FT_UINT8, BASE_DEC,
5046 NULL, 0x0,
5047 "Indicates number of UEs for which channel info is provided",
5048 HFILL}
5051 /* Section 7.5.2.12 */
5052 {&hf_oran_timeOffset,
5053 {"Time Offset", "oran_fh_cus.timeOffset",
5054 FT_UINT16, BASE_DEC,
5055 NULL, 0x0,
5056 "from start of the slot to start of CP in samples",
5057 HFILL}
5060 /* Section 7.5.2.13 */
5061 { &hf_oran_frameStructure_fft,
5062 { "FFT Size", "oran_fh_cus.frameStructure.fft",
5063 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
5064 RVALS(frame_structure_fft), 0xf0,
5065 "The FFT/iFFT size being used for all IQ data processing related to this message",
5066 HFILL }
5069 /* Section 7.5.2.13 */
5070 { &hf_oran_frameStructure_subcarrier_spacing,
5071 { "Subcarrier Spacing", "oran_fh_cus.frameStructure.spacing",
5072 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
5073 RVALS(subcarrier_spacings), 0x0f,
5074 "The sub carrier spacing as well as the number of slots per 1ms sub-frame",
5075 HFILL }
5078 /* Section 7.5.2.14 */
5079 {&hf_oran_cpLength,
5080 {"cpLength", "oran_fh_cus.cpLength",
5081 FT_UINT16, BASE_DEC,
5082 NULL, 0x0,
5083 "cyclic prefix length",
5084 HFILL}
5087 /* Section 7.5.3.1 */
5088 {&hf_oran_section_id,
5089 {"sectionId", "oran_fh_cus.sectionId",
5090 FT_UINT16, BASE_DEC,
5091 NULL, 0xfff0,
5092 "section identifier of data",
5093 HFILL}
5096 /* Section 7.5.3.2 */
5097 {&hf_oran_rb,
5098 {"rb", "oran_fh_cus.rb",
5099 FT_UINT8, BASE_DEC,
5100 VALS(rb_vals), 0x08,
5101 "resource block indicator",
5102 HFILL}
5105 /* Section 7.5.5.3 */
5106 {&hf_oran_symInc,
5107 {"symInc", "oran_fh_cus.symInc",
5108 FT_UINT8, BASE_DEC,
5109 VALS(sym_inc_vals), 0x04,
5110 "Symbol Number Increment Command",
5111 HFILL}
5114 /* Section 7.5.3.4 */
5115 {&hf_oran_startPrbc,
5116 {"startPrbc", "oran_fh_cus.startPrbc",
5117 FT_UINT16, BASE_DEC,
5118 NULL, 0x03ff,
5119 "Starting PRB of Control Plane Section",
5120 HFILL}
5123 /* Section 7.5.3.5 */
5124 {&hf_oran_reMask,
5125 {"RE Mask", "oran_fh_cus.reMask",
5126 FT_UINT16, BASE_HEX,
5127 NULL, 0xfff0,
5128 "The Resource Element (RE) mask within a PRB",
5129 HFILL}
5132 /* Section 7.5.3.6 */
5133 {&hf_oran_numPrbc,
5134 {"numPrbc", "oran_fh_cus.numPrbc",
5135 FT_UINT8, BASE_DEC,
5136 NULL, 0x0,
5137 "Number of contiguous PRBs per data section description",
5138 HFILL}
5141 /* Section 7.5.3.7 */
5142 {&hf_oran_numSymbol,
5143 {"Number of Symbols", "oran_fh_cus.numSymbol",
5144 FT_UINT8, BASE_DEC,
5145 NULL, 0x0f,
5146 "Defines number of symbols to which the section control is applicable",
5147 HFILL}
5150 /* Section 7.5.3.8 */
5151 {&hf_oran_ef,
5152 {"Extension Flag", "oran_fh_cus.ef",
5153 FT_BOOLEAN, 8,
5154 NULL, 0x80,
5155 "Indicates if more section extensions follow",
5156 HFILL}
5159 /* Section 7.5.3.9 */
5160 {&hf_oran_beamId,
5161 {"Beam ID", "oran_fh_cus.beamId",
5162 FT_UINT16, BASE_DEC,
5163 NULL, 0x7fff,
5164 "Defines the beam pattern to be applied to the U-Plane data",
5165 HFILL}
5168 {&hf_oran_extension,
5169 {"Extension", "oran_fh_cus.extension",
5170 FT_STRING, BASE_NONE,
5171 NULL, 0x0,
5172 "Section extension",
5173 HFILL}
5176 /* Section 7.6.2.1 */
5177 {&hf_oran_exttype,
5178 {"extType", "oran_fh_cus.extType",
5179 FT_UINT8, BASE_DEC,
5180 VALS(exttype_vals), 0x7f,
5181 "The extension type, which provides additional parameters specific to subject data extension",
5182 HFILL}
5185 /* Section 7.6.2.3 */
5186 {&hf_oran_extlen,
5187 {"extLen", "oran_fh_cus.extLen",
5188 FT_UINT16, BASE_DEC,
5189 NULL, 0x0,
5190 "Extension length in 32-bit words",
5191 HFILL}
5194 /* Section 7.7.1 */
5195 {&hf_oran_bfw,
5196 {"bfw", "oran_fh_cus.bfw",
5197 FT_STRING, BASE_NONE,
5198 NULL, 0x0,
5199 "Set of weights for a particular antenna",
5200 HFILL}
5202 {&hf_oran_bfw_bundle,
5203 {"Bundle", "oran_fh_cus.bfw.bundle",
5204 FT_STRING, BASE_NONE,
5205 NULL, 0x0,
5206 "Bundle of BFWs",
5207 HFILL}
5209 {&hf_oran_bfw_bundle_id,
5210 {"Bundle Id", "oran_fh_cus.bfw.bundleId",
5211 FT_UINT32, BASE_DEC,
5212 NULL, 0x0,
5213 NULL,
5214 HFILL}
5216 /* Section 7.7.1.4 */
5217 {&hf_oran_bfw_i,
5218 {"bfwI", "oran_fh_cus.bfwI",
5219 FT_FLOAT, BASE_NONE,
5220 NULL, 0x0,
5221 "In-phase",
5222 HFILL}
5224 /* Section 7.7.1.5 */
5225 {&hf_oran_bfw_q,
5226 {"bfwQ", "oran_fh_cus.bfwQ",
5227 FT_FLOAT, BASE_NONE,
5228 NULL, 0x0,
5229 "Quadrature",
5230 HFILL}
5233 /* Section 7.5.3.10 */
5234 {&hf_oran_ueId,
5235 {"UE ID", "oran_fh_cus.ueId",
5236 FT_UINT16, BASE_DEC,
5237 NULL, 0x7fff,
5238 "logical identifier for set of channel info",
5239 HFILL}
5242 /* Section 7.5.3.11 */
5243 {&hf_oran_freqOffset,
5244 {"Frequency Offset", "oran_fh_cus.freqOffset",
5245 FT_UINT24, BASE_DEC,
5246 NULL, 0x0,
5247 "with respect to the carrier center frequency before additional filtering",
5248 HFILL}
5251 /* Section 7.5.3.12 */
5252 {&hf_oran_regularizationFactor,
5253 {"Regularization Factor", "oran_fh_cus.regularizationFactor",
5254 FT_INT16, BASE_DEC,
5255 NULL, 0x0,
5256 "Signed value to support MMSE operation within O-RU",
5257 HFILL}
5260 /* Section 7.5.3.14 */
5261 {&hf_oran_laaMsgType,
5262 {"LAA Message Type", "oran_fh_cus.laaMsgType",
5263 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5264 RVALS(laaMsgTypes), 0xf0,
5265 NULL,
5266 HFILL}
5269 /* Section 7.5.3.15 */
5270 {&hf_oran_laaMsgLen,
5271 {"LAA Message Length", "oran_fh_cus.laaMsgLen",
5272 FT_UINT8, BASE_DEC,
5273 NULL, 0x0f,
5274 "number of 32-bit words in the LAA section",
5275 HFILL}
5278 /* Section 7.5.3.16 */
5279 {&hf_oran_lbtHandle,
5280 {"LBT Handle", "oran_fh_cus.lbtHandle",
5281 FT_UINT16, BASE_HEX,
5282 NULL, 0x0,
5283 "label to identify transaction",
5284 HFILL}
5287 /* Section 7.5.3.17 */
5288 {&hf_oran_lbtDeferFactor,
5289 {"Defer Factor", "oran_fh_cus.lbtDeferFactor",
5290 FT_UINT8, BASE_DEC,
5291 NULL, 0x1c,
5292 "Defer factor in sensing slots as described in 3GPP TS 36.213 Section 15.1.1",
5293 HFILL}
5296 /* Section 7.5.3.18 */
5297 {&hf_oran_lbtBackoffCounter,
5298 {"Backoff Counter", "oran_fh_cus.lbtBackoffCounter",
5299 FT_UINT16, BASE_DEC,
5300 NULL, 0x03ff,
5301 "LBT backoff counter in sensing slots as described in 3GPP TS 36.213 Section 15.1.1",
5302 HFILL}
5305 /* Section 7.5.3.19 */
5306 {&hf_oran_lbtOffset,
5307 {"LBT Offset", "oran_fh_cus.lbtOffset",
5308 FT_UINT16, BASE_DEC,
5309 NULL, 0xff80,
5310 "LBT start time in microseconds from the beginning of the subframe "
5311 "scheduled by this message",
5312 HFILL}
5315 /* Section 7.5.3.20 */
5316 {&hf_oran_MCOT,
5317 {"Maximum Channel Occupancy Time", "oran_fh_cus.MCOT",
5318 FT_UINT8, BASE_DEC,
5319 NULL, 0xf0,
5320 "LTE TXOP duration in subframes as described in 3GPP TS 36.213 Section 15.1.1",
5321 HFILL}
5324 /* Section 7.5.3.21 */
5325 {&hf_oran_lbtMode,
5326 {"LBT Mode", "oran_fh_cus.lbtMode",
5327 FT_UINT8, BASE_DEC,
5328 VALS(lbtMode_vals), 0x0,
5329 NULL,
5330 HFILL}
5333 /* Section 7.5.3.22 */
5334 {&hf_oran_lbtPdschRes,
5335 {"lbtPdschRes", "oran_fh_cus.lbtPdschRes",
5336 FT_UINT8, BASE_DEC,
5337 VALS(lbtPdschRes_vals), 0xc0,
5338 "LBT result of SFN/SF",
5339 HFILL}
5342 /* Section 7.5.3.23 */
5343 {&hf_oran_sfStatus,
5344 {"sfStatus", "oran_fh_cus.sfStatus",
5345 FT_BOOLEAN, 8,
5346 TFS(&tfs_sfStatus), 0x10,
5347 "Indicates whether the subframe was dropped or transmitted",
5348 HFILL}
5351 /* Section 7.5.3.22 */
5352 {&hf_oran_lbtDrsRes,
5353 {"lbtDrsRes", "oran_fh_cus.lbtDrsRes",
5354 FT_BOOLEAN, 8,
5355 TFS(&tfs_fail_success), 0x80,
5356 "Indicates whether the subframe was dropped or transmitted",
5357 HFILL}
5360 /* Section 7.5.3.25 */
5361 {&hf_oran_initialPartialSF,
5362 {"Initial partial SF", "oran_fh_cus.initialPartialSF",
5363 FT_BOOLEAN, 8,
5364 TFS(&tfs_partial_full_sf), 0x40,
5365 "Indicates whether the initial SF in the LBT process is full or partial",
5366 HFILL}
5369 /* Section 7.5.3.26. */
5370 {&hf_oran_lbtBufErr,
5371 {"lbtBufErr", "oran_fh_cus.lbtBufErr",
5372 FT_BOOLEAN, 8,
5373 TFS(&tfs_lbtBufErr), 0x80,
5374 "LBT buffer error",
5375 HFILL}
5378 /* Section 7.5.3.27 */
5379 {&hf_oran_sfnSfEnd,
5380 {"SFN/SF End", "oran_fh_cus.sfnSfEnd",
5381 FT_UINT16, BASE_DEC,
5382 NULL, 0x0fff,
5383 "SFN/SF by which the DRS window must end",
5384 HFILL}
5387 /* Section 7.5.3.28 */
5388 {&hf_oran_lbtCWConfig_H,
5389 {"lbtCWConfig_H", "oran_fh_cus.lbtCWConfig_H",
5390 FT_UINT8, BASE_DEC,
5391 NULL, 0x0,
5392 "HARQ parameters for congestion window management",
5393 HFILL}
5396 /* Section 7.5.3.29 */
5397 {&hf_oran_lbtCWConfig_T,
5398 {"lbtCWConfig_T", "oran_fh_cus.lbtCWConfig_T",
5399 FT_UINT8, BASE_DEC,
5400 NULL, 0x0,
5401 "TB parameters for congestion window management",
5402 HFILL}
5405 /* Section 7.5.3.30 */
5406 {&hf_oran_lbtTrafficClass,
5407 {"lbtTrafficClass", "oran_fh_cus.lbtTrafficClass",
5408 FT_UINT8, BASE_DEC,
5409 VALS(lbtTrafficClass_vals), 0x38,
5410 "Traffic class priority for congestion window management",
5411 HFILL}
5414 /* Section 7.5.3.31 */
5415 {&hf_oran_lbtCWR_Rst,
5416 {"lbtCWR_Rst", "oran_fh_cus.lbtCWR_Rst",
5417 FT_BOOLEAN, 8,
5418 TFS(&tfs_fail_success), 0x80,
5419 "notification about packet reception successful or not",
5420 HFILL}
5423 {&hf_oran_reserved,
5424 {"reserved", "oran_fh_cus.reserved",
5425 FT_UINT64, BASE_HEX,
5426 NULL, 0x0,
5427 NULL,
5428 HFILL}
5431 {&hf_oran_reserved_1bit,
5432 {"reserved", "oran_fh_cus.reserved",
5433 FT_UINT8, BASE_HEX,
5434 NULL, 0x80,
5435 NULL,
5436 HFILL}
5438 {&hf_oran_reserved_2bits,
5439 {"reserved", "oran_fh_cus.reserved",
5440 FT_UINT8, BASE_HEX,
5441 NULL, 0xc0,
5442 NULL,
5443 HFILL}
5445 {&hf_oran_reserved_4bits,
5446 {"reserved", "oran_fh_cus.reserved",
5447 FT_UINT8, BASE_HEX,
5448 NULL, 0xf0,
5449 NULL,
5450 HFILL}
5452 {&hf_oran_reserved_6bits,
5453 {"reserved", "oran_fh_cus.reserved",
5454 FT_UINT8, BASE_HEX,
5455 NULL, 0xfc,
5456 NULL,
5457 HFILL}
5459 {&hf_oran_reserved_7bits,
5460 {"reserved", "oran_fh_cus.reserved",
5461 FT_UINT8, BASE_HEX,
5462 NULL, 0xfe,
5463 NULL,
5464 HFILL}
5466 {&hf_oran_reserved_8bits,
5467 {"reserved", "oran_fh_cus.reserved",
5468 FT_UINT8, BASE_HEX,
5469 NULL, 0x0,
5470 NULL,
5471 HFILL}
5473 {&hf_oran_reserved_16bits,
5474 {"reserved", "oran_fh_cus.reserved",
5475 FT_UINT16, BASE_HEX,
5476 NULL, 0x0,
5477 NULL,
5478 HFILL}
5480 {&hf_oran_reserved_15bits,
5481 {"reserved", "oran_fh_cus.reserved",
5482 FT_UINT16, BASE_HEX,
5483 NULL, 0x7fff,
5484 NULL,
5485 HFILL}
5488 /* 7.7.11.10 */
5489 {&hf_oran_bundle_offset,
5490 {"BundleOffset", "oran_fh_cus.bundleOffset",
5491 FT_UINT8, BASE_DEC,
5492 NULL, 0x3f,
5493 "offset between start of first PRB bundle and startPrbc",
5494 HFILL}
5496 /* 7.7.11.9 */
5497 {&hf_oran_cont_ind,
5498 {"contInd", "oran_fh_cus.contInd",
5499 FT_BOOLEAN, 8,
5500 TFS(&continuity_indication_tfs), 0x80,
5501 "PRB region continuity flag",
5502 HFILL}
5506 /* Table 7.4.9-2 */
5507 {&hf_oran_laa_msgtype0_reserved,
5508 {"Reserved", "oran_fh_cus.reserved",
5509 FT_UINT8, BASE_HEX,
5510 NULL, 0x08,
5511 NULL,
5512 HFILL}
5515 /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
5516 {&hf_oran_bfwCompHdr,
5517 {"bfwCompHdr", "oran_fh_cus.bfwCompHdr",
5518 FT_STRING, BASE_NONE,
5519 NULL, 0x0,
5520 "Compression method and IQ bit width for beamforming weights",
5521 HFILL}
5523 {&hf_oran_bfwCompHdr_iqWidth,
5524 {"IQ Bit Width", "oran_fh_cus.bfwCompHdr_iqWidth",
5525 FT_UINT8, BASE_HEX,
5526 VALS(bfw_comp_headers_iq_width), 0xf0,
5527 "IQ bit width for the beamforming weights",
5528 HFILL}
5530 {&hf_oran_bfwCompHdr_compMeth,
5531 {"Compression Method", "oran_fh_cus.bfwCompHdr_compMeth",
5532 FT_UINT8, BASE_HEX,
5533 VALS(bfw_comp_headers_comp_meth), 0x0f,
5534 "compression method for the beamforming weights",
5535 HFILL}
5538 /* 7.5.3.32 */
5539 {&hf_oran_ciCompParam,
5540 {"ciCompParam", "oran_fh_cus.ciCompParam",
5541 FT_STRING, BASE_NONE,
5542 NULL, 0x0,
5543 "channel information compression parameter",
5544 HFILL}
5547 /* Table 7.5.3.32-1 */
5548 {&hf_oran_blockScaler,
5549 {"blockScaler", "oran_fh_cus.blockScaler",
5550 FT_UINT8, BASE_HEX,
5551 NULL, 0x0,
5552 "unsigned, 1 integer bit, 7 fractional bits",
5553 HFILL}
5555 {&hf_oran_compBitWidth,
5556 {"compBitWidth", "oran_fh_cus.compBitWidth",
5557 FT_UINT8, BASE_DEC,
5558 NULL, 0xf0,
5559 "Length of I bits and length of Q bits after compression over entire PRB",
5560 HFILL}
5562 {&hf_oran_compShift,
5563 {"compShift", "oran_fh_cus.compShift",
5564 FT_UINT8, BASE_DEC,
5565 NULL, 0x0f,
5566 "The shift applied to the entire PRB",
5567 HFILL}
5570 /* Section 7.7.6.6 */
5571 {&hf_oran_repetition,
5572 {"repetition", "oran_fh_cus.repetition",
5573 FT_BOOLEAN, BASE_NONE,
5574 NULL, 0x0,
5575 "Repetition of a highest priority data section for C-Plane",
5576 HFILL}
5578 /* 7.7.20.9 */
5579 {&hf_oran_rbgSize,
5580 {"rbgSize", "oran_fh_cus.rbgSize",
5581 FT_UINT8, BASE_HEX,
5582 VALS(rbg_size_vals), 0x70,
5583 "Number of PRBs of the resource block groups allocated by the bit mask",
5584 HFILL}
5586 /* 7.7.20.10 */
5587 {&hf_oran_rbgMask,
5588 {"rbgMask", "oran_fh_cus.rbgMask",
5589 FT_UINT32, BASE_HEX,
5590 NULL, 0x0fffffff,
5591 "Each bit indicates whether a corresponding resource block group is present",
5592 HFILL}
5594 /* 7.7.6.5 */
5595 {&hf_oran_noncontig_priority,
5596 {"priority", "oran_fh_cus.priority",
5597 FT_UINT8, BASE_HEX,
5598 VALS(priority_vals), 0xc0,
5599 NULL,
5600 HFILL}
5602 /* 7.7.6.4 */
5603 {&hf_oran_symbolMask,
5604 {"symbolMask", "oran_fh_cus.symbolMask",
5605 FT_UINT16, BASE_HEX,
5606 NULL, 0x3fff,
5607 "Each bit indicates whether the rbgMask applies to a given symbol in the slot",
5608 HFILL}
5611 /* 7.7.22.2 */
5612 {&hf_oran_ack_nack_req_id,
5613 {"ackNackReqId", "oran_fh_cus.ackNackReqId",
5614 FT_UINT16, BASE_HEX,
5615 NULL, 0x0,
5616 "Indicates the ACK/NACK request ID of a section description",
5617 HFILL}
5620 /* Subtree for next 2 items */
5621 {&hf_oran_off_start_prb_num_prb_pair,
5622 {"Pair", "oran_fh_cus.offStartPrb_numPrb",
5623 FT_STRING, BASE_NONE,
5624 NULL, 0x0,
5625 "Pair of offStartPrb and numPrb",
5626 HFILL}
5629 /* 7.7.12.4 */
5630 {&hf_oran_off_start_prb,
5631 {"offStartPrb", "oran_fh_cus.offStartPrb",
5632 FT_UINT8, BASE_DEC,
5633 NULL, 0x0,
5634 "Offset of PRB range start",
5635 HFILL}
5637 /* 7.7.12.5 */
5638 {&hf_oran_num_prb,
5639 {"numPrb", "oran_fh_cus.numPrb",
5640 FT_UINT8, BASE_DEC,
5641 NULL, 0x0,
5642 "Number of PRBs in PRB range",
5643 HFILL}
5646 /* symbolId 8.3.3.7 */
5647 {&hf_oran_symbolId,
5648 {"Symbol Identifier", "oran_fh_cus.symbolId",
5649 FT_UINT8, BASE_DEC,
5650 NULL, 0x3f,
5651 "Identifies a symbol number within a slot",
5652 HFILL}
5655 /* startPrbu 8.3.3.11 */
5656 {&hf_oran_startPrbu,
5657 {"startPrbu", "oran_fh_cus.startPrbu",
5658 FT_UINT16, BASE_DEC,
5659 NULL, 0x03ff,
5660 "starting PRB of user plane section",
5661 HFILL}
5664 /* numPrbu 8.3.3.12 */
5665 { &hf_oran_numPrbu,
5666 {"numPrbu", "oran_fh_cus.numPrbu",
5667 FT_UINT8, BASE_DEC,
5668 NULL, 0x0,
5669 "number of PRBs per user plane section",
5670 HFILL}
5673 /* 7.7.1.3 */
5674 {&hf_oran_bfwCompParam,
5675 {"bfwCompParam", "oran_fh_cus.bfwCompParam",
5676 FT_STRING, BASE_NONE,
5677 NULL, 0x0,
5678 "Beamforming weight compression parameter",
5679 HFILL}
5682 /* 6.3.3.13 */
5683 { &hf_oran_udCompHdrMeth,
5684 {"User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
5685 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5686 RVALS(ud_comp_header_meth), 0x0f,
5687 "Defines the compression method for "
5688 "the user data in every section in the C-Plane message",
5689 HFILL}
5691 { &hf_oran_udCompHdrMeth_pref,
5692 {"User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
5693 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5694 RVALS(ud_comp_header_meth), 0x0,
5695 "Defines the compression method for "
5696 "the user data in every section in the C-Plane message",
5697 HFILL}
5700 /* 6.3.3.13 */
5701 { &hf_oran_udCompHdrIqWidth,
5702 {"User Data IQ width", "oran_fh_cus.udCompHdrWidth",
5703 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5704 RVALS(ud_comp_header_width), 0xf0,
5705 "Defines the IQ bit width "
5706 "for the user data in every section in the C-Plane message",
5707 HFILL}
5709 { &hf_oran_udCompHdrIqWidth_pref,
5710 {"User Data IQ width", "oran_fh_cus.udCompHdrWidth",
5711 FT_UINT8, BASE_DEC,
5712 NULL, 0x0,
5713 "Defines the IQ bit width "
5714 "for the user data in every section in the C-Plane message",
5715 HFILL}
5719 /* Section 8.3.3.15 (not always present - depends upon meth) */
5720 {&hf_oran_udCompParam,
5721 {"User Data Compression Parameter", "oran_fh_cus.udCompParam",
5722 FT_STRING, BASE_NONE,
5723 NULL, 0x0,
5724 "Applies to whatever compression method is specified "
5725 "by the associated sectionID's compMeth value",
5726 HFILL}
5728 /* 8.3.3.17 */
5729 {&hf_oran_sReSMask,
5730 {"sReSMask", "oran_fh_cus.sReSMask",
5731 FT_UINT16, BASE_HEX,
5732 NULL, 0xf0ff,
5733 "selective RE sending mask", HFILL}
5736 /* Section 6.3.3.15 */
5737 {&hf_oran_iSample,
5738 {"iSample", "oran_fh_cus.iSample",
5739 FT_FLOAT, BASE_NONE,
5740 NULL, 0x0,
5741 "In-phase Sample value", HFILL}
5744 /* Section 6.3.3.16 */
5745 {&hf_oran_qSample,
5746 {"qSample", "oran_fh_cus.qSample",
5747 FT_FLOAT, BASE_NONE,
5748 NULL, 0x0,
5749 "Quadrature Sample value", HFILL}
5752 { &hf_oran_exponent,
5753 { "Exponent", "oran_fh_cus.exponent",
5754 FT_UINT8, BASE_DEC,
5755 NULL, 0x0f,
5756 "Exponent applicable to the I & Q mantissas",
5757 HFILL }
5760 { &hf_oran_iq_user_data,
5761 { "IQ User Data", "oran_fh_cus.iq_user_data",
5762 FT_BYTES, BASE_NONE,
5763 NULL, 0x0,
5764 "Used for the In-phase and Quadrature sample mantissa",
5765 HFILL }
5768 { &hf_oran_c_eAxC_ID,
5769 { "c_eAxC_ID", "oran_fh_cus.c_eaxc_id",
5770 FT_STRING, BASE_NONE,
5771 NULL, 0x0,
5772 "This is a calculated field for the c_eAxC ID, which identifies the message stream",
5773 HFILL } },
5775 { &hf_oran_refa,
5776 { "RefA", "oran_fh_cus.refa",
5777 FT_STRING, BASE_NONE,
5778 NULL, 0x0,
5779 "This is a calculated field for the RefA ID, which provides a reference in time",
5780 HFILL }
5784 /* Section 7.5.2.15 */
5785 {&hf_oran_ciCompHdr,
5786 {"ciCompHdr", "oran_fh_cus.ciCompHdr",
5787 FT_STRING, BASE_NONE,
5788 NULL, 0x0,
5789 NULL,
5790 HFILL}
5792 { &hf_oran_ciCompHdrMeth,
5793 {"User Data Compression Method", "oran_fh_cus.ciCompHdrMeth",
5794 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5795 RVALS(ud_comp_header_meth), 0x0e,
5796 "Defines the compression method for "
5797 "the user data in every section in the C-Plane message",
5798 HFILL}
5800 { &hf_oran_ciCompHdrIqWidth,
5801 {"User Data IQ width", "oran_fh_cus.udCompHdrWidth",
5802 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
5803 RVALS(ud_comp_header_width), 0xf0,
5804 "Defines the IQ bit width "
5805 "for the user data in every section in the C-Plane message",
5806 HFILL}
5808 { &hf_oran_ciCompOpt,
5809 {"ciCompOpt", "oran_fh_cus.ciCompOpt",
5810 FT_UINT8, BASE_DEC,
5811 VALS(ci_comp_opt_vals), 0x01,
5812 NULL,
5813 HFILL}
5816 /* 7.7.11.7 */
5817 { &hf_oran_disable_bfws,
5818 { "disableBFWs", "oran_fh_cus.disableBFWs",
5819 FT_BOOLEAN, 8,
5820 NULL, 0x80,
5821 "Indicate if BFWs under section extension are disabled",
5822 HFILL }
5824 /* 7.7.11.8 */
5825 { &hf_oran_rad,
5826 { "RAD", "oran_fh_cus.rad",
5827 FT_BOOLEAN, 8,
5828 NULL, 0x40,
5829 "Reset After PRB Discontinuity",
5830 HFILL }
5832 /* 7.7.11.4 */
5833 { &hf_oran_num_bund_prbs,
5834 { "numBundPrb", "oran_fh_cus.numBundPrb",
5835 FT_UINT8, BASE_DEC,
5836 NULL, 0x0,
5837 "Number of bundled PRBs per BFWs",
5838 HFILL }
5840 { &hf_oran_beam_id,
5841 { "beamId", "oran_fh_cus.beamId",
5842 FT_UINT16, BASE_DEC,
5843 NULL, 0x7fff,
5844 NULL,
5845 HFILL }
5847 { &hf_oran_num_weights_per_bundle,
5848 { "Num weights per bundle", "oran_fh_cus.num_weights_per_bundle",
5849 FT_UINT16, BASE_DEC,
5850 NULL, 0x0,
5851 "From dissector preference",
5852 HFILL }
5856 { &hf_oran_samples_prb,
5857 {"PRB", "oran_fh_cus.prb",
5858 FT_STRING, BASE_NONE,
5859 NULL, 0x0,
5860 "Grouping of samples for a particular Physical Resource Block",
5861 HFILL}
5864 /* 7.5.3.13 */
5865 {&hf_oran_ciSample,
5866 {"ciSample", "oran_fh_cus.ciSample",
5867 FT_STRING, BASE_NONE,
5868 NULL, 0x0,
5869 "Sample (I and Q values)",
5870 HFILL}
5872 {&hf_oran_ciIsample,
5873 {"ciIsample", "oran_fh_cus.ciISample",
5874 FT_FLOAT, BASE_NONE,
5875 NULL, 0x0,
5876 "Channel information complex value - I part",
5877 HFILL}
5879 {&hf_oran_ciQsample,
5880 { "ciQsample", "oran_fh_cus.ciQSample",
5881 FT_FLOAT, BASE_NONE,
5882 NULL, 0x0,
5883 "Channel information complex value - Q part",
5884 HFILL}
5887 /* 7.7.10.2 */
5888 { &hf_oran_beamGroupType,
5889 { "beamGroupType", "oran_fh_cus.beamGroupType",
5890 FT_UINT8, BASE_DEC,
5891 VALS(beam_group_type_vals), 0xc0,
5892 "The type of beam grouping",
5893 HFILL }
5895 /* 7.7.10.3 */
5896 { &hf_oran_numPortc,
5897 { "numPortc", "oran_fh_cus.numPortc",
5898 FT_UINT8, BASE_DEC,
5899 NULL, 0x3f,
5900 "The number of eAxC ports",
5901 HFILL }
5904 /* 7.7.4.2 (1 bit) */
5905 { &hf_oran_csf,
5906 { "csf", "oran_fh_cus.csf",
5907 FT_BOOLEAN, BASE_NONE,
5908 NULL, 0x0,
5909 "constellation shift flag",
5910 HFILL }
5912 /* 7.7.4.3 */
5913 { &hf_oran_modcompscaler,
5914 { "modCompScaler", "oran_fh_cus.modcompscaler",
5915 FT_UINT16, BASE_DEC,
5916 NULL, 0x7fff,
5917 "modulation compression scaler value",
5918 HFILL }
5921 /* 7.7.5.1 */
5922 { &hf_oran_modcomp_param_set,
5923 { "Set", "oran_fh_cus.modcomp-param-set",
5924 FT_STRING, BASE_NONE,
5925 NULL, 0x0,
5926 NULL,
5927 HFILL }
5930 /* mcScaleReMask 7.7.5.2 (12 bits) */
5931 { &hf_oran_mc_scale_re_mask,
5932 { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
5933 FT_BOOLEAN, BASE_NONE,
5934 NULL, 0x0,
5935 "modulation compression power scale RE mask",
5936 HFILL }
5938 /* mcScaleOffset 7.7.5.4 (15 bits) */
5939 { &hf_oran_mc_scale_offset,
5940 { "mcScaleOffset", "oran_fh_cus.mcscaleoffset",
5941 FT_UINT24, BASE_DEC,
5942 NULL, 0x0,
5943 "scaling value for modulation compression",
5944 HFILL }
5946 /* eAxCmask (7.7.7.2) */
5947 { &hf_oran_eAxC_mask,
5948 { "eAxC Mask", "oran_fh_cus.eaxcmask",
5949 FT_UINT16, BASE_HEX,
5950 NULL, 0x0,
5951 "Which eAxC_ID values the C-Plane message applies to",
5952 HFILL }
5954 /* technology (interface name) 7.7.9.2 */
5955 { &hf_oran_technology,
5956 { "Technology", "oran_fh_cus.technology",
5957 FT_UINT8, BASE_DEC,
5958 VALS(interface_name_vals), 0x0,
5959 "Interface name (that C-PLane section applies to)",
5960 HFILL }
5962 /* Exttype 14 (7.7.14.2) */
5963 { &hf_oran_nullLayerInd,
5964 { "nullLayerInd", "oran_fh_cus.nulllayerind",
5965 FT_BOOLEAN, BASE_NONE,
5966 NULL, 0x0,
5967 "Whether corresponding layer is nulling-layer or not",
5968 HFILL }
5971 /* Exttype 19 (7.7.19.8) */
5972 { &hf_oran_portReMask,
5973 { "portReMask", "oran_fh_cus.portReMask",
5974 FT_BOOLEAN, 16,
5975 TFS(&tfs_set_notset), 0x0fff,
5976 "RE bitmask per port",
5977 HFILL }
5979 /* 7.7.19.9 */
5980 { &hf_oran_portSymbolMask,
5981 { "portSymbolMask", "oran_fh_cus.portSymbolMask",
5982 FT_BOOLEAN, 16,
5983 TFS(&tfs_set_notset), 0x3fff,
5984 "Symbol bitmask port port",
5985 HFILL }
5988 { &hf_oran_ext19_port,
5989 {"Port", "oran_fh_cus.ext19.port",
5990 FT_STRING, BASE_NONE,
5991 NULL, 0x0,
5992 "Entry for a given port in ext19",
5993 HFILL}
5996 /* Ext 13 */
5997 { &hf_oran_prb_allocation,
5998 {"PRB allocation", "oran_fh_cus.prb-allocation",
5999 FT_STRING, BASE_NONE,
6000 NULL, 0x0,
6001 NULL,
6002 HFILL}
6004 /* 7.7.13.2 */
6005 { &hf_oran_nextSymbolId,
6006 { "nextSymbolId", "oran_fh_cus.nextSymbolId",
6007 FT_UINT8, BASE_DEC,
6008 NULL, 0x3c,
6009 "offset of PRB range start",
6010 HFILL }
6012 /* 7.7.13.3 */
6013 { &hf_oran_nextStartPrbc,
6014 { "nextStartPrbc", "oran_fh_cus.nextStartPrbc",
6015 FT_UINT16, BASE_DEC,
6016 NULL, 0x03ff,
6017 "number of PRBs in PRB range",
6018 HFILL }
6021 /* Puncturing patters as appears in SE 20 */
6022 {&hf_oran_puncPattern,
6023 {"puncPattern", "oran_fh_cus.puncPattern",
6024 FT_STRING, BASE_NONE,
6025 NULL, 0x0,
6026 NULL,
6027 HFILL}
6030 /* 7.7.20.2 numPuncPatterns */
6031 { &hf_oran_numPuncPatterns,
6032 { "numPuncPatterns", "oran_fh_cus.numPuncPatterns",
6033 FT_UINT8, BASE_DEC,
6034 NULL, 0x0,
6035 "number of puncturing patterns",
6036 HFILL }
6038 /* 7.7.20.3 symbolMask */
6039 {&hf_oran_symbolMask_ext20,
6040 {"symbolMask", "oran_fh_cus.symbolMask",
6041 FT_UINT16, BASE_HEX,
6042 NULL, 0xfffc,
6043 "Bitmask where each bit indicates the symbols associated with the puncturing pattern",
6044 HFILL}
6046 /* 7.7.20.4 startPuncPrb */
6047 {&hf_oran_startPuncPrb,
6048 {"startPuncPrb", "oran_fh_cus.startPuncPrb",
6049 FT_UINT16, BASE_DEC,
6050 NULL, 0x03ff,
6051 "starting PRB to which one puncturing pattern applies",
6052 HFILL}
6054 /* 7.7.20.5 numPuncPrb */
6055 {&hf_oran_numPuncPrb,
6056 {"numPuncPrb", "oran_fh_cus.numPuncPrb",
6057 FT_UINT24, BASE_DEC,
6058 NULL, 0x03ffff,
6059 "the number of PRBs of the puncturing pattern",
6060 HFILL}
6062 /* 7.7.20.6 puncReMask */
6063 {&hf_oran_puncReMask,
6064 {"puncReMask", "oran_fh_cus.puncReMask",
6065 FT_UINT16, BASE_DEC,
6066 NULL, 0xffc0,
6067 "puncturing pattern RE mask",
6068 HFILL}
6070 /* 7.7.20.4 rbgIncl */
6071 {&hf_oran_RbgIncl,
6072 {"rbgIncl", "oran_fh_cus.rbgIncl",
6073 FT_BOOLEAN, 8,
6074 NULL, 0x01,
6075 "rbg included flag",
6076 HFILL}
6079 /* 7.7.21.2 ciPrbGroupSize */
6080 {&hf_oran_ci_prb_group_size,
6081 {"ciPrbGroupSize", "oran_fh_cus.ciPrbGroupSize",
6082 FT_UINT8, BASE_DEC,
6083 NULL, 0x0,
6084 "channel information PRB group size",
6085 HFILL}
6087 /* 7.21.3 */
6088 {&hf_oran_prg_size_st5,
6089 {"prgSize", "oran_fh_cus.prgSize",
6090 FT_UINT8, BASE_DEC,
6091 VALS(prg_size_st5_vals), 0x03,
6092 "precoding resource block group size",
6093 HFILL}
6095 {&hf_oran_prg_size_st6,
6096 {"prgSize", "oran_fh_cus.prgSize",
6097 FT_UINT8, BASE_DEC,
6098 VALS(prg_size_st6_vals), 0x03,
6099 "precoding resource block group size",
6100 HFILL}
6103 /* 7.7.17.2 numUeID */
6104 {&hf_oran_num_ueid,
6105 {"numUeID", "oran_fh_cus.numUeID",
6106 FT_UINT8, BASE_DEC,
6107 NULL, 0x0,
6108 "number of ueIDs per user",
6109 HFILL}
6112 /* 7.7.16.2 antMask */
6113 {&hf_oran_antMask,
6114 {"antMask", "oran_fh_cus.antMask",
6115 FT_UINT64, BASE_HEX,
6116 NULL, 0xffffffffffffffff,
6117 "indices of antennas to be pre-combined per RX endpoint",
6118 HFILL}
6121 /* 7.7.18.2 transmissionWindowOffset */
6122 {&hf_oran_transmissionWindowOffset,
6123 {"transmissionWindowOffset", "oran_fh_cus.transmissionWindowOffset",
6124 FT_UINT16, BASE_DEC,
6125 NULL, 0x0,
6126 "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)",
6127 HFILL}
6129 /* 7.7.18.3 transmissionWindowSize */
6130 {&hf_oran_transmissionWindowSize,
6131 {"transmissionWindowSize", "oran_fh_cus.transmissionWindowSize",
6132 FT_UINT16, BASE_DEC,
6133 NULL, 0x3fff,
6134 "size of the transmission window in resolution µs",
6135 HFILL}
6137 /* 7.7.18.4 toT */
6138 {&hf_oran_toT,
6139 {"toT", "oran_fh_cus.toT",
6140 FT_UINT8, BASE_DEC,
6141 VALS(type_of_transmission_vals), 0x03,
6142 "type of transmission",
6143 HFILL}
6146 /* 7.7.2.2 bfaCompHdr */
6147 {&hf_oran_bfaCompHdr,
6148 {"bfaCompHdr", "oran_fh_cus.bfaCompHdr",
6149 FT_STRING, BASE_NONE,
6150 NULL, 0x0,
6151 "beamforming attributes compression header",
6152 HFILL}
6154 /* 7.7.2.2-2: bfAzPtWidth */
6155 {&hf_oran_bfAzPtWidth,
6156 {"bfAzPtWidth", "oran_fh_cus.bfAzPtWidth",
6157 FT_UINT8, BASE_DEC,
6158 VALS(bfa_bw_vals), 0x38,
6159 NULL,
6160 HFILL}
6162 /* 7.7.2.2-3: bfZePtWidth */
6163 {&hf_oran_bfZePtWidth,
6164 {"bfZePtWidth", "oran_fh_cus.bfZePtWidth",
6165 FT_UINT8, BASE_DEC,
6166 VALS(bfa_bw_vals), 0x07,
6167 NULL,
6168 HFILL}
6170 /* 7.7.2.2-4: bfAz3ddWidth */
6171 {&hf_oran_bfAz3ddWidth,
6172 {"bfAz3ddWidth", "oran_fh_cus.bfAz3ddWidth",
6173 FT_UINT8, BASE_DEC,
6174 VALS(bfa_bw_vals), 0x38,
6175 NULL,
6176 HFILL}
6178 /* 7.7.2.2-5: bfZe3ddWidth */
6179 {&hf_oran_bfZe3ddWidth,
6180 {"bfZe3ddWidth", "oran_fh_cus.bfZe3ddWidth",
6181 FT_UINT8, BASE_DEC,
6182 VALS(bfa_bw_vals), 0x07,
6183 NULL,
6184 HFILL}
6187 /* 7.7.2.3 bfAzPt */
6188 {&hf_oran_bfAzPt,
6189 {"bfAzPt", "oran_fh_cus.bfAzPt",
6190 FT_UINT8, BASE_DEC,
6191 NULL, 0x0,
6192 "beamforming azimuth pointing parameter",
6193 HFILL}
6195 /* 7.7.2.4 bfZePt */
6196 {&hf_oran_bfZePt,
6197 {"bfZePt", "oran_fh_cus.bfZePt",
6198 FT_UINT8, BASE_DEC,
6199 NULL, 0x0,
6200 "beamforming zenith pointing parameter",
6201 HFILL}
6203 /* 7.7.2.5 bfAz3dd */
6204 {&hf_oran_bfAz3dd,
6205 {"bfAz3dd", "oran_fh_cus.bfAz3dd",
6206 FT_UINT8, BASE_DEC,
6207 NULL, 0x0,
6208 "beamforming azimuth beamwidth parameter",
6209 HFILL}
6211 /* 7.7.2.6 bfZe3dd */
6212 {&hf_oran_bfZe3dd,
6213 {"bfZe3dd", "oran_fh_cus.bfZe3dd",
6214 FT_UINT8, BASE_DEC,
6215 NULL, 0x0,
6216 "beamforming zenith beamwidth parameter",
6217 HFILL}
6220 /* 7.7.2.7 bfAzSl */
6221 {&hf_oran_bfAzSl,
6222 {"bfAzSl", "oran_fh_cus.bfAzSl",
6223 FT_UINT8, BASE_DEC,
6224 VALS(sidelobe_suppression_vals), 0x38,
6225 "beamforming azimuth sidelobe parameter",
6226 HFILL}
6228 /* 7.7.2.8 bfZeSl */
6229 {&hf_oran_bfZeSl,
6230 {"bfZeSl", "oran_fh_cus.bfZeSl",
6231 FT_UINT8, BASE_DEC,
6232 VALS(sidelobe_suppression_vals), 0x38,
6233 "beamforming zenith sidelobe parameter",
6234 HFILL}
6237 /* 7.5.2.17 */
6238 {&hf_oran_cmd_scope,
6239 {"cmdScope", "oran_fh_cus.cmdScope",
6240 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6241 RVALS(cmd_scope_vals), 0x0f,
6242 "command scope",
6243 HFILL}
6245 /* 7.5.2.18 */
6246 {&hf_oran_number_of_st4_cmds,
6247 {"numberOfST4Cmds", "oran_fh_cus.numberOfST4Cmds",
6248 FT_UINT8, BASE_DEC,
6249 NULL, 0x0,
6250 "Number of Section Type 4 commands",
6251 HFILL}
6254 {&hf_oran_st4_cmd_header,
6255 {"Command common header", "oran_fh_cus.st4CmdCommonHeader",
6256 FT_STRING, BASE_NONE,
6257 NULL, 0x0,
6258 NULL,
6259 HFILL}
6262 /* 7.5.3.38 */
6263 {&hf_oran_st4_cmd_type,
6264 {"st4CmdType", "oran_fh_cus.st4CmdType",
6265 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6266 RVALS(st4_cmd_type_vals), 0x0,
6267 NULL,
6268 HFILL}
6270 /* 7.5.3.39 */
6271 {&hf_oran_st4_cmd_len,
6272 {"st4CmdLen", "oran_fh_cus.st4CmdLen",
6273 FT_UINT16, BASE_DEC,
6274 NULL, 0x0,
6275 "Length of command in 32-bit words",
6276 HFILL}
6278 /* 7.5.3.40 */
6279 {&hf_oran_st4_cmd_num_slots,
6280 {"numSlots", "oran_fh_cus.st4NumSlots",
6281 FT_UINT8, BASE_DEC,
6282 NULL, 0x0,
6283 "Contiguous slots for which command is applicable",
6284 HFILL}
6286 /* 7.5.3.41 */
6287 {&hf_oran_st4_cmd_ack_nack_req_id,
6288 {"ackNackReqId", "oran_fh_cus.ackNackReqId",
6289 FT_UINT16, BASE_DEC,
6290 NULL, 0x0,
6291 "ACK/NACK Request Id",
6292 HFILL}
6295 {&hf_oran_st4_cmd,
6296 {"Command", "oran_fh_cus.st4Cmd",
6297 FT_STRING, BASE_NONE,
6298 NULL, 0x0,
6299 NULL,
6300 HFILL}
6303 /* 7.5.3.52 */
6304 {&hf_oran_sleepmode_trx,
6305 {"sleepMode", "oran_fh_cus.sleepMode",
6306 FT_UINT8, BASE_HEX,
6307 VALS(sleep_mode_trx_vals), 0x03,
6308 NULL,
6309 HFILL}
6311 {&hf_oran_sleepmode_asm,
6312 {"sleepMode", "oran_fh_cus.sleepMode",
6313 FT_UINT8, BASE_HEX,
6314 VALS(sleep_mode_asm_vals), 0x03,
6315 NULL,
6316 HFILL}
6319 /* 7.5.3.51 */
6320 {&hf_oran_log2maskbits,
6321 {"log2MaskBits", "oran_fh_cus.log2MaskBits",
6322 FT_UINT8, BASE_HEX,
6323 VALS(log2maskbits_vals), 0x3c,
6324 "Number of bits to appear in antMask",
6325 HFILL}
6327 /* 7.5.3.53 */
6328 {&hf_oran_num_slots_ext,
6329 {"numSlotsExt", "oran_fh_cus.numSlotsExt",
6330 FT_UINT24, BASE_HEX,
6331 NULL, 0x0fffff,
6332 NULL,
6333 HFILL}
6335 /* 7.5.3.54 */
6336 {&hf_oran_antMask_trx_control,
6337 {"antMask", "oran_fh_cus.antMask",
6338 FT_BYTES, BASE_NONE,
6339 NULL, 0x0,
6340 "which antennas should sleep or wake-up",
6341 HFILL}
6343 /* 7.5.3.55 */
6344 {&hf_oran_ready,
6345 {"ready", "oran_fh_cus.ready",
6346 FT_BOOLEAN, 8,
6347 TFS(&ready_tfs), 0x01,
6348 "wake-up ready indicator",
6349 HFILL}
6351 /* 7.5.3.34 */
6352 {&hf_oran_number_of_acks,
6353 {"numberOfAcks", "oran_fh_cus.numberOfAcks",
6354 FT_UINT8, BASE_DEC,
6355 NULL, 0x0,
6356 "number of ACKs for one eAxC_ID",
6357 HFILL}
6359 /* 7.5.3.35 */
6360 {&hf_oran_number_of_nacks,
6361 {"numberOfNacks", "oran_fh_cus.numberOfNacks",
6362 FT_UINT8, BASE_DEC,
6363 NULL, 0x0,
6364 "number of NACKs for one eAxC_ID",
6365 HFILL}
6367 /* 7.5.3.36 */
6368 {&hf_oran_ackid,
6369 {"ackId", "oran_fh_cus.ackId",
6370 FT_UINT16, BASE_DEC,
6371 NULL, 0x0,
6372 NULL,
6373 HFILL}
6375 /* 7.5.3.37 */
6376 {&hf_oran_nackid,
6377 {"nackId", "oran_fh_cus.nackId",
6378 FT_UINT16, BASE_DEC,
6379 NULL, 0x0,
6380 NULL,
6381 HFILL}
6384 /* Links between acknack requests & responses */
6385 {&hf_oran_acknack_request_frame,
6386 {"Request Frame", "oran_fh_cus.ackNackId.request-frame",
6387 FT_FRAMENUM, BASE_NONE,
6388 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
6389 NULL,
6390 HFILL}
6392 {&hf_oran_acknack_request_time,
6393 {"Time since request in ms", "oran_fh_cus.ackNackId.time-since-request",
6394 FT_UINT32, BASE_DEC,
6395 NULL, 0x0,
6396 "Time between request and response",
6397 HFILL}
6399 {&hf_oran_acknack_request_type,
6400 {"Request Type", "oran_fh_cus.ackNackId.request-type",
6401 FT_UINT32, BASE_DEC,
6402 VALS(acknack_type_vals), 0x0,
6403 NULL,
6404 HFILL}
6406 {&hf_oran_acknack_response_frame,
6407 {"Response Frame", "oran_fh_cus.ackNackId.response-frame",
6408 FT_FRAMENUM, BASE_NONE,
6409 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
6410 NULL,
6411 HFILL}
6413 {&hf_oran_acknack_response_time,
6414 {"Time to response in ms", "oran_fh_cus.ackNackId.time-to-response",
6415 FT_UINT32, BASE_DEC,
6416 NULL, 0x0,
6417 "Time between request and response",
6418 HFILL}
6421 /* 7.5.3.43 */
6422 {&hf_oran_disable_tdbfns,
6423 {"disableTDBFNs", "oran_fh_cus.disableTDBFNs",
6424 FT_BOOLEAN, 8,
6425 TFS(&disable_tdbfns_tfs), 0x80,
6426 NULL,
6427 HFILL}
6430 /* 7.5.3.44 */
6431 {&hf_oran_td_beam_group,
6432 {"tdBeamGrp", "oran_fh_cus.tdBeamGrp",
6433 FT_UINT16, BASE_HEX,
6434 NULL, 0x7fff,
6435 "Applies to symbolMask in command header",
6436 HFILL}
6438 /* 7.5.3.43 */
6439 {&hf_oran_disable_tdbfws,
6440 {"disableTDBFWs", "oran_fh_cus.disableTDBFWs",
6441 FT_BOOLEAN, 8,
6442 NULL, 0x80,
6443 NULL,
6444 HFILL}
6447 /* 7.5.3.56 */
6448 {&hf_oran_td_beam_num,
6449 {"tdBeamNum", "oran_fh_cus.tdBeamNum",
6450 FT_UINT16, BASE_HEX,
6451 NULL, 0x7fff,
6452 "time-domain beam number",
6453 HFILL}
6456 /* 7.5.3.49 */
6457 {&hf_oran_dir_pattern,
6458 {"dirPattern", "oran_fh_cus.dirPattern",
6459 FT_BOOLEAN, 16,
6460 NULL, 0x3fff,
6461 NULL,
6462 HFILL}
6464 /* 7.5.3.50 */
6465 {&hf_oran_guard_pattern,
6466 {"guardPattern", "oran_fh_cus.guardPattern",
6467 FT_BOOLEAN, 16,
6468 NULL, 0x3fff,
6469 NULL,
6470 HFILL}
6473 /* For convenient filtering */
6474 {&hf_oran_cplane,
6475 {"C-Plane", "oran_fh_cus.c-plane",
6476 FT_NONE, BASE_NONE,
6477 NULL, 0x0,
6478 NULL,
6479 HFILL}
6481 {&hf_oran_uplane,
6482 {"U-Plane", "oran_fh_cus.u-plane",
6483 FT_NONE, BASE_NONE,
6484 NULL, 0x0,
6485 NULL,
6486 HFILL}
6489 /* 5.1.3.2.7 */
6490 {&hf_oran_ecpri_pcid,
6491 {"ecpriPcid", "oran_fh_cus.ecpriPcid",
6492 FT_NONE, BASE_NONE,
6493 NULL, 0x0,
6494 "IQ data transfer message series identifier",
6495 HFILL}
6497 {&hf_oran_ecpri_rtcid,
6498 {"ecpriRtcid", "oran_fh_cus.ecpriRtcid",
6499 FT_NONE, BASE_NONE,
6500 NULL, 0x0,
6501 "Real time control data identifier",
6502 HFILL}
6504 /* 5.1.3.2.8 */
6505 {&hf_oran_ecpri_seqid,
6506 {"ecpriSeqid", "oran_fh_cus.ecpriSeqid",
6507 FT_NONE, BASE_NONE,
6508 NULL, 0x0,
6509 "message identifier",
6510 HFILL}
6513 /* 7.7.23.2 */
6514 {&hf_oran_num_sym_prb_pattern,
6515 {"numSymPrbPattern", "oran_fh_cus.numSymPrbPattern",
6516 FT_UINT8, BASE_DEC,
6517 NULL, 0xf0,
6518 "number of symbol and resource block patterns",
6519 HFILL}
6521 /* 7.7.23.11 */
6522 {&hf_oran_prb_mode,
6523 {"prbMode", "oran_fh_cus.prbMode",
6524 FT_BOOLEAN, 8,
6525 TFS(&prb_mode_tfs), 0x01,
6526 "PRB Mode",
6527 HFILL}
6530 {&hf_oran_sym_prb_pattern,
6531 {"symPrbPattern", "oran_fh_cus.symPrbPattern",
6532 FT_STRING, BASE_NONE,
6533 NULL, 0x0,
6534 NULL,
6535 HFILL}
6539 /* 7.7.23.3 */
6540 {&hf_oran_sym_mask,
6541 {"symMask", "oran_fh_cus.symMask",
6542 FT_UINT16, BASE_HEX,
6543 NULL, 0x3fff,
6544 "symbol mask part of symPrbPattern",
6545 HFILL}
6547 /* 7.7.23.5 */
6548 {&hf_oran_num_mc_scale_offset,
6549 {"numMcScaleOffset", "oran_fh_cus.numMcScaleOffset",
6550 FT_UINT8, BASE_DEC,
6551 NULL, 0xf0,
6552 "number of modulation compression scaling value per symPrbPattern",
6553 HFILL}
6555 /* 7.7.23.4 */
6556 {&hf_oran_prb_pattern,
6557 {"prbPattern", "oran_fh_cus.prbPattern",
6558 FT_UINT8, BASE_DEC,
6559 NULL, 0x0f,
6560 "resource block pattern part of symPrbPattern",
6561 HFILL}
6564 /* 7.7.3.2 */
6565 {&hf_oran_codebook_index,
6566 {"codebookIndex", "oran_fh_cus.codebookIndex",
6567 FT_UINT8, BASE_DEC,
6568 NULL, 0x0,
6569 "precoder codebook used for transmission",
6570 HFILL}
6572 /* 7.7.3.3 */
6573 {&hf_oran_layerid,
6574 {"layerID", "oran_fh_cus.layerID",
6575 FT_UINT8, BASE_DEC,
6576 NULL, 0xf0,
6577 "Layer ID for DL transmission",
6578 HFILL}
6580 /* 7.7.3.5 */
6581 {&hf_oran_numlayers,
6582 {"numLayers", "oran_fh_cus.numLayers",
6583 FT_UINT8, BASE_DEC,
6584 NULL, 0x0f,
6585 "number of layers for DL transmission",
6586 HFILL}
6588 /* 7.7.3.4 */
6589 {&hf_oran_txscheme,
6590 {"txScheme", "oran_fh_cus.txScheme",
6591 FT_UINT8, BASE_DEC,
6592 NULL, 0xf0,
6593 "transmission scheme",
6594 HFILL}
6596 /* 7.7.3.6 */
6597 {&hf_oran_crs_remask,
6598 {"crsReMask", "oran_fh_cus.crsReMask",
6599 FT_UINT16, BASE_HEX,
6600 NULL, 0x0fff,
6601 "CRS resource element mask",
6602 HFILL}
6604 /* 7.7.3.8 */
6605 {&hf_oran_crs_shift,
6606 {"crsShift", "oran_fh_cus.crsShift",
6607 FT_UINT8, BASE_HEX,
6608 NULL, 0x80,
6609 "CRS resource element mask",
6610 HFILL}
6612 /* 7.7.3.7 */
6613 {&hf_oran_crs_symnum,
6614 {"crsSymNum", "oran_fh_cus.crsSymNum",
6615 FT_UINT8, BASE_DEC,
6616 NULL, 0x0f,
6617 "CRS symbol number indication",
6618 HFILL}
6620 /* 7.7.3.9 */
6621 {&hf_oran_beamid_ap1,
6622 {"beamIdAP1", "oran_fh_cus.beamIdAP1",
6623 FT_UINT16, BASE_DEC,
6624 NULL, 0x7f,
6625 "beam id to be used for antenna port 1",
6626 HFILL}
6628 /* 7.7.3.10 */
6629 {&hf_oran_beamid_ap2,
6630 {"beamIdAP2", "oran_fh_cus.beamIdAP2",
6631 FT_UINT16, BASE_DEC,
6632 NULL, 0x7f,
6633 "beam id to be used for antenna port 2",
6634 HFILL}
6636 /* 7.7.3.11 */
6637 {&hf_oran_beamid_ap3,
6638 {"beamIdAP3", "oran_fh_cus.beamIdAP3",
6639 FT_UINT16, BASE_DEC,
6640 NULL, 0x7f,
6641 "beam id to be used for antenna port 3",
6642 HFILL}
6645 /* 7.7.10.3a */
6646 {&hf_oran_port_list_index,
6647 {"portListIndex", "oran_fh_cus.portListIndex",
6648 FT_UINT8, BASE_DEC,
6649 NULL, 0x0,
6650 "the index of an eAxC_ID in the port-list",
6651 HFILL}
6654 {&hf_oran_alpn_per_sym,
6655 {"alpnPerSym", "oran_fh_cus.alpnPerSym",
6656 FT_UINT8, BASE_HEX,
6657 NULL, 0x80,
6658 NULL,
6659 HFILL}
6661 {&hf_oran_ant_dmrs_snr,
6662 {"antDmrsSnr", "oran_fh_cus.antDmrsSnr",
6663 FT_UINT8, BASE_HEX,
6664 NULL, 0x40,
6665 NULL,
6666 HFILL}
6671 /* 7.7.24.6 */
6672 {&hf_oran_user_group_size,
6673 {"userGroupSize", "oran_fh_cus.userGroupSize",
6674 FT_UINT8, BASE_DEC,
6675 NULL, 0x1f,
6676 "number of UE data layers in the user group identified by userGroupId",
6677 HFILL}
6679 /* 7.7.24.7 */
6680 {&hf_oran_user_group_id,
6681 {"userGroupId", "oran_fh_cus.userGroupId",
6682 FT_UINT8, BASE_DEC,
6683 NULL, 0x0,
6684 "number of UE data layers in the user group identified by userGroupId",
6685 HFILL}
6687 /* 7.7.24.8 */
6688 {&hf_oran_entry_type,
6689 {"entryType", "oran_fh_cus.entryType",
6690 FT_UINT8, BASE_DEC,
6691 NULL, 0xe0,
6692 "indicates format of the entry",
6693 HFILL}
6695 /* 7.7.24.9 */
6696 {&hf_oran_dmrs_port_number,
6697 {"dmrsPortNumber", "oran_fh_cus.dmrsPortNumber",
6698 FT_UINT8, BASE_DEC,
6699 NULL, 0x1f,
6700 "DMRS antenna port number for the associated ueId",
6701 HFILL}
6703 /* 7.7.24.10 */
6704 {&hf_oran_ueid_reset,
6705 {"ueidReset", "oran_fh_cus.ueidReset",
6706 FT_BOOLEAN, 8,
6707 NULL, 0x80,
6708 "same UEID as the previous slot",
6709 HFILL}
6711 /* 7.7.24.11 */
6712 {&hf_oran_dmrs_symbol_mask,
6713 {"dmrsSymbolMask", "oran_fh_cus.dmrsSymbolMask",
6714 FT_UINT16, BASE_HEX,
6715 NULL, 0x3fff,
6716 "symbols within the slot containing DMRS",
6717 HFILL}
6719 /* 7.7.24.12 */
6720 {&hf_oran_scrambling,
6721 {"scrambling", "oran_fh_cus.scrambling",
6722 FT_UINT16, BASE_HEX,
6723 NULL, 0x0,
6724 "used to calculate the seed value required to initialize pseudo-random generator",
6725 HFILL}
6727 /* 7.7.24.13 */
6728 {&hf_oran_nscid,
6729 {"nscid", "oran_fh_cus.nscid",
6730 FT_UINT8, BASE_HEX,
6731 NULL, 0x80,
6732 "used to calculate the seed value for pseudo-random generator",
6733 HFILL}
6735 /* 7.7.24.14 */
6736 {&hf_oran_dtype,
6737 {"dType", "oran_fh_cus.dType",
6738 FT_UINT8, BASE_HEX,
6739 NULL, 0x40,
6740 "PUSCH DMRS configuration type",
6741 HFILL}
6743 /* 7.7.24.15 */
6744 {&hf_oran_cmd_without_data,
6745 {"cmdWithoutData", "oran_fh_cus.cmdWithoutData",
6746 FT_UINT8, BASE_HEX,
6747 NULL, 0x30,
6748 "number of DMRS CDM groups without data",
6749 HFILL}
6751 /* 7.7.24.16 */
6752 {&hf_oran_lambda,
6753 {"lambda", "oran_fh_cus.lambda",
6754 FT_UINT8, BASE_HEX,
6755 NULL, 0x0c,
6756 NULL,
6757 HFILL}
6759 /* 7.7.24.19 */
6760 {&hf_oran_first_prb,
6761 {"firstPrb", "oran_fh_cus.firstPrb",
6762 FT_UINT16, BASE_HEX,
6763 NULL, 0x03fe,
6764 NULL,
6765 HFILL}
6767 /* 7.7.24.20 */
6768 {&hf_oran_last_prb,
6769 {"lastPrb", "oran_fh_cus.lastPrb",
6770 FT_UINT16, BASE_HEX,
6771 NULL, 0x01ff,
6772 NULL,
6773 HFILL}
6776 /* 7.7.24.17 */
6777 {&hf_oran_low_papr_type,
6778 {"lowPaprType", "oran_fh_cus.lowPaprType",
6779 FT_UINT8, BASE_HEX,
6780 NULL, 0x30,
6781 NULL,
6782 HFILL}
6784 /* 7.7.24.18 */
6785 {&hf_oran_hopping_mode,
6786 {"hoppingMode", "oran_fh_cus.hoppingMode",
6787 FT_UINT8, BASE_HEX,
6788 NULL, 0x0c,
6789 NULL,
6790 HFILL}
6793 {&hf_oran_tx_win_for_on_air_symbol_l,
6794 {"txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
6795 FT_UINT8, BASE_DEC,
6796 NULL, 0xf0,
6797 NULL,
6798 HFILL}
6800 {&hf_oran_tx_win_for_on_air_symbol_r,
6801 {"txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
6802 FT_UINT8, BASE_DEC,
6803 NULL, 0x0f,
6804 NULL,
6805 HFILL}
6807 /* 7.7.26.2 */
6808 {&hf_oran_num_fo_fb,
6809 {"numFoFb", "oran_fh_cus.numFoFb",
6810 FT_UINT8, BASE_DEC,
6811 NULL, 0x7f,
6812 "number of frequency offset feedback",
6813 HFILL}
6815 /* 7.7.26.3 */
6816 {&hf_oran_freq_offset_fb,
6817 {"freqOffsetFb", "oran_fh_cus.freqOffsetFb",
6818 FT_UINT16, BASE_HEX_DEC | BASE_RANGE_STRING,
6819 RVALS(freq_offset_fb_values), 0x0,
6820 "UE frequency offset feedback",
6821 HFILL}
6824 /* 7.5.2.19 */
6825 {&hf_oran_num_sinr_per_prb,
6826 {"numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
6827 FT_UINT8, BASE_DEC,
6828 VALS(num_sinr_per_prb_vals), 0xe0,
6829 "number of SINR values per PRB",
6830 HFILL}
6834 /* Section 7.5.3.68 */
6835 {&hf_oran_sinr_value,
6836 {"sinrValue", "oran_fh_cus.sinrValue",
6837 FT_FLOAT, BASE_NONE,
6838 NULL, 0x0,
6839 NULL,
6840 HFILL}
6845 /* Setup protocol subtree array */
6846 static int *ett[] = {
6847 &ett_oran,
6848 &ett_oran_ecpri_pcid,
6849 &ett_oran_ecpri_rtcid,
6850 &ett_oran_ecpri_seqid,
6851 &ett_oran_section_type,
6852 &ett_oran_u_timing,
6853 &ett_oran_u_section,
6854 &ett_oran_u_prb,
6855 &ett_oran_section,
6856 &ett_oran_iq,
6857 &ett_oran_c_section_extension,
6858 &ett_oran_bfw_bundle,
6859 &ett_oran_bfw,
6860 &ett_oran_offset_start_prb_num_prb,
6861 &ett_oran_prb_cisamples,
6862 &ett_oran_cisample,
6863 &ett_oran_udcomphdr,
6864 &ett_oran_udcompparam,
6865 &ett_oran_cicomphdr,
6866 &ett_oran_cicompparam,
6867 &ett_oran_bfwcomphdr,
6868 &ett_oran_bfwcompparam,
6869 &ett_oran_ext19_port,
6870 &ett_oran_prb_allocation,
6871 &ett_oran_punc_pattern,
6872 &ett_oran_bfacomphdr,
6873 &ett_oran_modcomp_param_set,
6874 &ett_oran_st4_cmd_header,
6875 &ett_oran_st4_cmd,
6876 &ett_oran_sym_prb_pattern
6879 expert_module_t* expert_oran;
6881 static ei_register_info ei[] = {
6882 { &ei_oran_unsupported_bfw_compression_method, { "oran_fh_cus.unsupported_bfw_compression_method", PI_UNDECODED, PI_WARN, "Unsupported BFW Compression Method", EXPFILL }},
6883 { &ei_oran_invalid_sample_bit_width, { "oran_fh_cus.invalid_sample_bit_width", PI_UNDECODED, PI_ERROR, "Unsupported sample bit width", EXPFILL }},
6884 { &ei_oran_reserved_numBundPrb, { "oran_fh_cus.reserved_numBundPrb", PI_MALFORMED, PI_ERROR, "Reserved value of numBundPrb", EXPFILL }},
6885 { &ei_oran_extlen_wrong, { "oran_fh_cus.extlen_wrong", PI_MALFORMED, PI_ERROR, "extlen doesn't match number of dissected bytes", EXPFILL }},
6886 { &ei_oran_invalid_eaxc_bit_width, { "oran_fh_cus.invalid_exac_bit_width", PI_UNDECODED, PI_ERROR, "Inconsistent eAxC bit width", EXPFILL }},
6887 { &ei_oran_extlen_zero, { "oran_fh_cus.extlen_zero", PI_MALFORMED, PI_ERROR, "extlen - zero is reserved value", EXPFILL }},
6888 { &ei_oran_rbg_size_reserved, { "oran_fh_cus.rbg_size_reserved", PI_MALFORMED, PI_ERROR, "rbgSize - zero is reserved value", EXPFILL }},
6889 { &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 }},
6890 { &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 }},
6891 { &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 }},
6892 { &ei_oran_st8_nackid, { "oran_fh_cus.st8_nackid", PI_SEQUENCE, PI_WARN, "operation for this ackId failed", EXPFILL }},
6893 { &ei_oran_st4_no_cmds, { "oran_fh_cus.st4_nackid", PI_MALFORMED, PI_ERROR, "Not valid to have no commands in ST4", EXPFILL }},
6894 { &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 }},
6895 { &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 }},
6896 { &ei_oran_st4_unknown_cmd, { "oran_fh_cus.st4_unknown_cmd", PI_MALFORMED, PI_ERROR, "ST4 cmd with unknown command code", EXPFILL }},
6897 { &ei_oran_mcot_out_of_range, { "oran_fh_cus.mcot_out_of_range", PI_MALFORMED, PI_ERROR, "MCOT should be 1-10", EXPFILL }},
6898 { &ei_oran_se10_unknown_beamgrouptype, { "oran_fh_cus.se10_unknown_beamgrouptype", PI_MALFORMED, PI_WARN, "SE10 - unknown BeamGroupType value", EXPFILL }},
6899 { &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 }},
6900 { &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 }},
6901 { &ei_oran_unhandled_se, { "oran_fh_cus.se_not_handled", PI_UNDECODED, PI_WARN, "SE not recognised/handled by dissector", EXPFILL }},
6902 { &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 }},
6903 { &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 }},
6904 { &ei_oran_version_unsupported, { "oran_fh_cus.version_unsupported", PI_UNDECODED, PI_WARN, "Protocol version unsupported", EXPFILL }},
6905 { &ei_oran_laa_msg_type_unsupported, { "oran_fh_cus.laa_msg_type_unsupported", PI_UNDECODED, PI_WARN, "laaMsgType unsupported", EXPFILL }},
6906 { &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 }},
6907 { &ei_oran_cplane_unexpected_sequence_number, { "oran_fh_cus.unexpected_seq_no_cplane", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in C-Plane", EXPFILL }},
6908 { &ei_oran_uplane_unexpected_sequence_number, { "oran_fh_cus.unexpected_seq_no_uplane", PI_SEQUENCE, PI_WARN, "Unexpected sequence number seen in U-Plane", EXPFILL }},
6909 { &ei_oran_acknack_no_request, { "oran_fh_cus.acknack_no_request", PI_SEQUENCE, PI_WARN, "Have ackNackId response, but no request", EXPFILL }},
6910 { &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 }},
6911 { &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 }},
6912 { &ei_oran_radio_fragmentation_u_plane, { "oran_fh_cus.radio_fragmentation_u_plane", PI_UNDECODED, PI_WARN, "Radio fragmentation in C-PLane not yet supported", EXPFILL }},
6913 { &ei_oran_lastRbdid_out_of_range, { "oran_fh_cus.lastrbdid_out_of_range", PI_MALFORMED, PI_WARN, "SE 6 has bad rbgSize", EXPFILL }},
6914 { &ei_oran_rbgMask_beyond_last_rbdid, { "oran_fh_cus.rbgmask_beyond_lastrbdid", PI_MALFORMED, PI_WARN, "rbgMask has bits set beyond lastRbgId", EXPFILL }}
6917 /* Register the protocol name and description */
6918 proto_oran = proto_register_protocol("O-RAN Fronthaul CUS", "O-RAN FH CUS", "oran_fh_cus");
6920 /* Allow dissector to find be found by name. */
6921 register_dissector("oran_fh_cus", dissect_oran, proto_oran);
6923 /* Required function calls to register the header fields and subtrees */
6924 proto_register_field_array(proto_oran, hf, array_length(hf));
6925 proto_register_subtree_array(ett, array_length(ett));
6927 expert_oran = expert_register_protocol(proto_oran);
6928 expert_register_field_array(expert_oran, ei, array_length(ei));
6930 module_t * oran_module = prefs_register_protocol(proto_oran, NULL);
6932 /* Register bit width/compression preferences separately by direction. */
6933 prefs_register_uint_preference(oran_module, "oran.du_port_id_bits", "DU Port ID bits [a]",
6934 "The bit width of DU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_du_port_id_bits);
6935 prefs_register_uint_preference(oran_module, "oran.bandsector_id_bits", "BandSector ID bits [b]",
6936 "The bit width of BandSector ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_bandsector_id_bits);
6937 prefs_register_uint_preference(oran_module, "oran.cc_id_bits", "CC ID bits [c]",
6938 "The bit width of CC ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_cc_id_bits);
6939 prefs_register_uint_preference(oran_module, "oran.ru_port_id_bits", "RU Port ID bits [d]",
6940 "The bit width of RU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_ru_port_id_bits);
6942 prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_up", "IQ Bitwidth Uplink",
6943 "The bit width of a sample in the Uplink (if no udcompHdr)", 10, &pref_sample_bit_width_uplink);
6944 prefs_register_enum_preference(oran_module, "oran.ud_comp_up", "Uplink User Data Compression",
6945 "Uplink User Data Compression", &pref_iqCompressionUplink, compression_options, true);
6946 prefs_register_bool_preference(oran_module, "oran.ud_comp_hdr_up", "udCompHdr field is present for uplink",
6947 "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
6948 "configuration of the O-RU. This preference instructs the dissector to expect "
6949 "this field to be present in uplink messages", &pref_includeUdCompHeaderUplink);
6951 prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_down", "IQ Bitwidth Downlink",
6952 "The bit width of a sample in the Downlink (if no udcompHdr)", 10, &pref_sample_bit_width_downlink);
6953 prefs_register_enum_preference(oran_module, "oran.ud_comp_down", "Downlink User Data Compression",
6954 "Downlink User Data Compression", &pref_iqCompressionDownlink, compression_options, true);
6955 prefs_register_bool_preference(oran_module, "oran.ud_comp_hdr_down", "udCompHdr field is present for downlink",
6956 "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
6957 "configuration of the O-RU. This preference instructs the dissector to expect "
6958 "this field to be present in downlink messages", &pref_includeUdCompHeaderDownlink);
6960 prefs_register_uint_preference(oran_module, "oran.rbs_in_uplane_section", "Total RBs in User-Plane data section",
6961 "This is used if numPrbu is signalled as 0", 10, &pref_data_plane_section_total_rbs);
6963 prefs_register_uint_preference(oran_module, "oran.num_weights_per_bundle", "Number of weights per bundle",
6964 "Used in decoding of section extension type 11 (Flexible BF weights)", 10, &pref_num_weights_per_bundle);
6966 prefs_register_uint_preference(oran_module, "oran.num_bf_antennas", "Number of BF Antennas",
6967 "Number of BF Antennas (used for C section type 6)", 10, &pref_num_bf_antennas);
6969 prefs_register_bool_preference(oran_module, "oran.show_iq_samples", "Show IQ Sample values",
6970 "When enabled, for U-Plane frames show each I and Q value in PRB", &pref_showIQSampleValues);
6972 prefs_register_obsolete_preference(oran_module, "oran.num_bf_weights");
6974 flow_states_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6975 flow_results_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
6978 /* Simpler form of proto_reg_handoff_oran which can be used if there are
6979 * no prefs-dependent registration function calls. */
6980 void
6981 proto_reg_handoff_oran(void)
6986 * Editor modelines - http://www.wireshark.org/tools/modelines.html
6988 * Local Variables:
6989 * c-basic-offset: 4
6990 * tab-width: 8
6991 * indent-tabs-mode: nil
6992 * End:
6994 * ex: set shiftwidth=4 tabstop=8 expandtab:
6995 * :indentSize=4:tabSize=8:noTabs=true: