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
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include <epan/prefs.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..
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..)
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 */
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
;
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 */
429 #define COMP_BLOCK_FP 1
430 #define COMP_BLOCK_SCALE 2
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
},
462 static const value_string e_bit
[] = {
463 { 0, "More fragments follow" },
464 { 1, "Last fragment" },
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 */
478 static const value_string rb_vals
[] = {
479 { 0, "Every RB used" },
480 { 1, "Every other RB used" },
484 static const value_string sym_inc_vals
[] = {
485 { 0, "Use the current symbol number" },
486 { 1, "Increment the current symbol number" },
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" },
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"},
511 /* Section types from Table 7.3.1-1 */
512 enum section_c_types
{
517 SEC_C_SLOT_CONTROL
= 4,
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" },
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" },
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"},
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"},
580 /* Table 7.5.2.13-2 */
581 static const range_string frame_structure_fft
[] = {
582 {0, 0, "Reserved (no FFT/iFFT processing)"},
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"},
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" },
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"},
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"},
636 static const value_string num_sinr_per_prb_vals
[] = {
651 static const value_string exttype_vals
[] = {
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"},
683 /**************************************************************************************/
684 /* Keep track for each Section Extension, which section types are allowed to carry it */
685 #define HIGHEST_EXTTYPE 27
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.. */
739 return ext_cts
[se
-1].ST1
;
741 return ext_cts
[se
-1].ST3
;
743 return ext_cts
[se
-1].ST5
;
745 return ext_cts
[se
-1].ST6
;
747 /* New section type that includes 'ef'.. assume ok */
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"},
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"},
785 /* 7.7.6.2 rbgSize (resource block group size) */
786 static const value_string rbg_size_vals
[] = {
799 static const value_string priority_vals
[] = {
802 {2, "-2 (reserved, should not be used)"},
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"},
816 /* 7.7.9.2 technology (interface name) */
817 static const value_string interface_name_vals
[] = {
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"},
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"},
845 /* 7.7.2.7 & 7.7.2.8 */
846 static const value_string sidelobe_suppression_vals
[] = {
858 static const value_string lbtTrafficClass_vals
[] = {
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"},
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"},
880 static const range_string cmd_scope_vals
[] = {
881 {0, 0, "ARRAY-COMMAND"},
882 {1, 1, "CARRIER-COMMAND"},
883 {2, 2, "O-RU-COMMAND"},
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"},
895 {5, 255, "reserved for future command types"},
899 /* Table 7.5.3.51-1 */
900 static const value_string log2maskbits_vals
[] = {
902 {1, "min antMask size is 16 bits.."},
903 {2, "min antMask size is 16 bits.."},
904 {3, "min antMask size is 16 bits.."},
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)"},
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)"},
938 static const value_string prg_size_st5_vals
[] = {
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"},
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"},
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",
968 static const true_false_string tfs_partial_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
= {
988 /* Forward declaration */
989 static int dissect_udcompparam(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, unsigned offset
,
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) */
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? */
1013 unsigned ext12_num_pairs
;
1014 #define MAX_BFW_EXT12_PAIRS 128
1016 uint8_t off_start_prb
;
1018 } ext12_pairs
[MAX_BFW_EXT12_PAIRS
];
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? */
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
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
];
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
,
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;
1075 n
< (settings
->ext6_num_bits_set
* settings
->ext6_rbg_size
) / numBundPrb
;
1078 /* Watch out for array bound */
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)) {
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
) {
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
) {
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
) {
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
) {
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 */
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) */
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
;
1229 uint32_t request_frame_number
;
1230 nstime_t request_frame_time
;
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
[] = {
1245 { ST4Cmd1
, "ST4 (TIME_DOMAIN_BEAM_CONFIG)" },
1246 { ST4Cmd2
, "ST4 (TDD_CONFIG_PATTERN)" },
1247 { ST4Cmd3
, "ST4 (TRX_CONTROL)" },
1248 { ST4Cmd4
, "ST4 (ASM)" },
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
;
1268 /* Sequence analysis */
1269 bool unexpected_seq_number
;
1270 uint8_t expected_sequence_number
;
1271 uint32_t previous_frame
;
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
];
1294 if ((ti1
== NULL
) && (ti2
== NULL
) && (pinfo
== NULL
)) {
1298 va_start(ap
, format
);
1299 vsnprintf(info_buffer
, MAX_INFO_BUFFER
, format
, ap
);
1302 /* Add to indicated places */
1303 if (pinfo
!= NULL
) {
1304 col_append_str(pinfo
->cinfo
, COL_INFO
, info_buffer
);
1307 proto_item_append_text(ti1
, "%s", info_buffer
);
1310 proto_item_append_text(ti2
, "%s", info_buffer
);
1314 /* Add section labels (type + PRB range) for C-Plane, U-Plane */
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
)
1322 write_pdu_label_and_info(section_heading
, protocol_item
, pinfo
, ", Id: %4d (all PRBs)", section_id
);
1326 write_pdu_label_and_info(section_heading
, protocol_item
, pinfo
, ", Id: %4d (PRB: %7u)", section_id
, start_prbx
);
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)" : "");
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
,
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
);
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) */
1361 addPcOrRtcid(tvbuff_t
*tvb
, proto_tree
*tree
, int *offset
, int hf
, uint16_t *eAxC
)
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
);
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
);
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
;
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
;
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
;
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
);
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
);
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) */
1408 addSeqid(tvbuff_t
*tvb
, proto_tree
*oran_tree
, int offset
, int plane
, uint8_t *seq_id
, proto_item
**seq_id_ti
)
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
);
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
);
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
);
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
);
1438 proto_item_append_text(seqIdItem
, " (SeqId: %3d, E: %d, SubSeqId: %d)", seqId
, e
, subSeqId
);
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
)
1448 proto_item
*bfwcomphdr_ti
= proto_tree_add_string_format(tree
, hf_oran_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
);
1463 proto_item_append_text(bfwcomphdr_ti
, " (IqWidth=%u, compMeth=%s)",
1465 val_to_str_const(*comp_meth
, bfw_comp_headers_comp_meth
, "reserved"));
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
) {
1483 proto_item
*bfwcompparam_ti
= proto_tree_add_string_format(tree
, hf_oran_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"));
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
);
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
);
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
);
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);
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);
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",
1540 val_to_str_const(bfw_comp_method
, bfw_comp_headers_comp_meth
, "reserved"));
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
:
1577 case COMP_MODULATION
:
1578 case BFP_AND_SELECTIVE_RE
:
1579 case MOD_COMPR_AND_SELECTIVE_RE
:
1581 /* Not supported! */
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
,
1594 unsigned bundle_number
,
1595 unsigned first_prb
, unsigned last_prb
, bool is_orphan
)
1597 /* Set bundle name */
1598 char bundle_name
[32];
1600 snprintf(bundle_name
, 32, "Bundle %3u", bundle_number
);
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
,
1611 "%s: (PRBs %3u-%3u)",
1613 first_prb
, last_prb
);
1616 bundle_ti
= proto_tree_add_string_format(tree
, hf_oran_bfw_bundle
,
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,
1627 proto_item_set_generated(bundleid_ti
);
1628 proto_item_set_hidden(bundleid_ti
);
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 */
1642 /* Create Bundle subtree */
1643 int bit_offset
= offset
*8;
1645 int prb_offset
= offset
;
1648 proto_tree_add_item(bundle_tree
, hf_oran_cont_ind
,
1649 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
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
);
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
);
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
);
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
);
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 */
1707 proto_item
*cicompparam_ti
= proto_tree_add_string_format(tree
, hf_oran_ciCompParam
,
1708 tvb
, bit_offset
/8, 1, "",
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
) {
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 */
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
);
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
);
1739 /* reserved, ? bytes of zeros.. */
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
)
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;
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
);
1769 static unsigned dissect_csf(proto_item
*tree
, tvbuff_t
*tvb
, unsigned bit_offset
,
1770 unsigned iq_width
, bool *p_csf
)
1774 csf_ti
= proto_tree_add_bits_ret_val(tree
, hf_oran_csf
, tvb
, bit_offset
, 1, &csf
, ENC_BIG_ENDIAN
);
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
) {
1787 return bit_offset
+1;
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
, §ionHeading
, "Section");
1805 uint32_t sectionId
= 0;
1807 uint32_t startPrbc
, startPrbu
;
1808 uint32_t numPrbc
, numPrbu
;
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
)) {
1825 proto_item
*ti
= proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_section_id
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, §ionId
);
1826 if (sectionId
== 4095) {
1827 proto_item_append_text(ti
, " (not default coupling C/U planes using sectionId)");
1833 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_rb
, tvb
, offset
, 1, ENC_NA
, &rb
);
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
);
1842 numprbc_ti
= proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_numPrbu
, tvb
, offset
, 1, ENC_NA
, &numPrbu
);
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
;
1850 /* startPrbc (10 bits) */
1851 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_startPrbc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &startPrbc
);
1854 numprbc_ti
= proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_numPrbc
, tvb
, offset
, 1, ENC_NA
, &numPrbc
);
1856 proto_item_append_text(numprbc_ti
, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs
);
1861 if (sectionType
!= SEC_C_SINR_REPORTING
) {
1863 proto_tree_add_item(c_section_tree
, hf_oran_reMask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
1867 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_numSymbol
, tvb
, offset
, 1, ENC_NA
, &numSymbol
);
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
);
1879 /* Other section types don't support extensions */
1883 write_section_info(sectionHeading
, pinfo
, protocol_item
, sectionId
, startPrbc
, numPrbc
, rb
);
1884 proto_item_append_text(sectionHeading
, ", Symbols: %2u", numSymbol
);
1887 /* Special case for all PRBs */
1888 numPrbc
= pref_data_plane_section_total_rbs
;
1889 startPrbc
= 0; /* may already be 0... */
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
);
1905 case SEC_C_NORMAL
: /* Section Type 1 - Table 7.4.3-1 */
1907 beamId_ti
= proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_beamId
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &beamId
);
1910 proto_item_append_text(sectionHeading
, ", BeamId: %d", beamId
);
1913 case SEC_C_PRACH
: /* Section Type 3 - Table 7.4.5-1 */
1916 beamId_ti
= proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_beamId
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &beamId
);
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
);
1927 proto_tree_add_item(c_section_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_NA
);
1930 proto_item_append_text(sectionHeading
, ", BeamId: %d, FreqOffset: %d \u0394f", beamId
, freqOffset
);
1934 case SEC_C_UE_SCHED
: /* Section Type 5 - Table 7.4.7-1 */
1936 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_ueId
, tvb
, offset
, 2, ENC_NA
, &ueId
);
1939 proto_item_append_text(sectionHeading
, ", UEId: %d", ueId
);
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.. */
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
;
1982 else if (sectionType
== SEC_C_CH_INFO
) { /* Section Type 6 */
1984 proto_tree_add_item_ret_boolean(c_section_tree
, hf_oran_ef
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &extension_flag
);
1986 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_ueId
, tvb
, offset
, 2, ENC_NA
, &ueId
);
1988 /* regularizationFactor */
1989 proto_tree_add_item(c_section_tree
, hf_oran_regularizationFactor
, tvb
, offset
, 2, ENC_NA
);
1992 proto_tree_add_item(c_section_tree
, hf_oran_reserved_4bits
, tvb
, offset
, 1, ENC_NA
);
1994 proto_tree_add_item(c_section_tree
, hf_oran_rb
, tvb
, offset
, 1, ENC_NA
);
1996 proto_tree_add_item(c_section_tree
, hf_oran_symInc
, tvb
, offset
, 1, ENC_NA
);
1998 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_startPrbc
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &startPrbc
);
2001 proto_tree_add_item_ret_uint(c_section_tree
, hf_oran_numPrbc
, tvb
, offset
, 1, ENC_NA
, &numPrbc
);
2004 /* ciIsample,ciQsample pairs */
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
++) {
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,
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
);
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
);
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
);
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
);
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
);
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 */
2072 proto_item
*mcot_ti
;
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
);
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));
2084 int payload_offset
= offset
;
2087 switch (laa_msg_type
) {
2090 /* lbtHandle (16 bits) */
2091 proto_tree_add_item(c_section_tree
, hf_oran_lbtHandle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2093 /* lbtOffset (10 bits) */
2094 proto_tree_add_item(c_section_tree
, hf_oran_lbtOffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2103 /* lbtBackoffCounter (10 bits) */
2104 proto_tree_add_item(c_section_tree
, hf_oran_lbtBackoffCounter
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2119 /* lbtHandle (16 bits) */
2120 proto_tree_add_item(c_section_tree
, hf_oran_lbtHandle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2122 /* lbtOffset (10 bits) */
2123 proto_tree_add_item(c_section_tree
, hf_oran_lbtOffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2132 /* lbtHandle (16 bits) */
2133 proto_tree_add_item(c_section_tree
, hf_oran_lbtHandle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2144 /* reserved (24 bits) */
2145 proto_tree_add_bits_item(c_section_tree
, hf_oran_reserved
, tvb
, (offset
*8), 24, ENC_BIG_ENDIAN
);
2149 /* lbtHandle (16 bits) */
2150 proto_tree_add_item(c_section_tree
, hf_oran_lbtHandle
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
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
);
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
);
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
);
2172 /* lbtCWConfig_H (8 bits) */
2173 proto_tree_add_item(c_section_tree
, hf_oran_lbtCWConfig_H
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2175 /* lbtCWConfig_T (8 bits) */
2176 proto_tree_add_item(c_section_tree
, hf_oran_lbtCWConfig_T
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
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
);
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
);
2198 expert_add_info_format(pinfo
, laa_msg_type_ti
, &ei_oran_laa_msg_type_unsupported
,
2199 "laaMsgType %u not supported by dissector",
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
);
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
);
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 */
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
;
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! */
2256 bool ext_unhandled
= false;
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
);
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
) {
2282 - numBfWeights (taken from preference)
2283 - remaining bytes in extension
2284 We can therefore derive TRX (number of antennas).
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
);
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
);
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
, " ");
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
);
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;
2334 case 2: /* SE 2: Beamforming attributes */
2336 /* bfaCompHdr (get widths of fields to follow) */
2337 uint32_t bfAzPtWidth
, bfZePtWidth
, bfAz3ddWidth
, bfZe3ddWidth
;
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
);
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
);
2359 unsigned bit_offset
= offset
*8;
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);
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);
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);
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
);
2393 case 3: /* SE 3: TODO: DL precoding parameters */
2396 proto_tree_add_item(extension_tree
, hf_oran_codebook_index
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2400 proto_tree_add_item_ret_uint(extension_tree
, hf_oran_layerid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &layerid
);
2402 proto_tree_add_item(extension_tree
, hf_oran_numlayers
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2405 /* Stop here for non-first data layer */
2406 if (layerid
!= 0 && layerid
!= 0xf) {
2410 /* First data layer case */
2412 proto_tree_add_item(extension_tree
, hf_oran_txscheme
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2414 proto_tree_add_item(extension_tree
, hf_oran_crs_remask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2424 proto_tree_add_item(extension_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2427 /* reserved (1 bit) */
2428 proto_tree_add_item(extension_tree
, hf_oran_reserved_1bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2430 proto_tree_add_item(extension_tree
, hf_oran_beamid_ap1
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2432 /* reserved (1 bit) */
2433 proto_tree_add_item(extension_tree
, hf_oran_reserved_1bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2435 proto_tree_add_item(extension_tree
, hf_oran_beamid_ap2
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2437 /* reserved (1 bit) */
2438 proto_tree_add_item(extension_tree
, hf_oran_reserved_1bit
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2440 proto_tree_add_item(extension_tree
, hf_oran_beamid_ap3
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2445 case 4: /* SE 4: Modulation compression params (5.4.7.4) */
2448 dissect_csf(extension_tree
, tvb
, offset
*8, ci_iq_width
, NULL
);
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
);
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
);
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;
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) {
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",
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
;
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
);
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
);
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;
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;
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) */
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
);
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) */
2557 proto_item
*rbgmask_ti
= proto_tree_add_item_ret_uint(extension_tree
, hf_oran_rbgMask
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &rbgMask
);
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. */
2565 proto_tree_add_item(extension_tree
, hf_oran_noncontig_priority
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2567 proto_tree_add_item(extension_tree
, hf_oran_symbolMask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
2570 /* Look up rbg_size enum -> value */
2573 /* N.B. reserved, but covered above with expert info (would remain 0) */
2576 ext11_settings
.ext6_rbg_size
= 1; break;
2578 ext11_settings
.ext6_rbg_size
= 2; break;
2580 ext11_settings
.ext6_rbg_size
= 3; break;
2582 ext11_settings
.ext6_rbg_size
= 4; break;
2584 ext11_settings
.ext6_rbg_size
= 6; break;
2586 ext11_settings
.ext6_rbg_size
= 8; break;
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;
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
);
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
;
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 */
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 */
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
);
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
);
2646 case 8: /* SE 8: Regularization factor */
2647 proto_tree_add_item(extension_tree
, hf_oran_regularizationFactor
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
2654 proto_tree_add_item(extension_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2658 case 10: /* SE 10: Group configuration of multiple ports */
2663 uint32_t beam_group_type
= 0;
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"));
2670 proto_tree_add_item_ret_uint(extension_tree
, hf_oran_numPortc
,
2671 tvb
, offset
, 1, ENC_BIG_ENDIAN
, &numPortc
);
2674 /* Will append all beamId values to extension_ti, regardless of beamGroupType */
2677 switch (beam_group_type
) {
2678 case 0x0: /* common beam */
2679 case 0x1: /* beam matrix indication */
2682 proto_tree_add_item(extension_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_NA
);
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) */
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
);
2703 proto_item_append_text(extension_ti
, "%u ", id
);
2706 proto_item_append_text(extension_ti
, "]");
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
++) {
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
);
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) */
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
);
2730 proto_item_append_text(extension_ti
, "%u:%u ", port_list_index
, id
);
2733 proto_item_append_text(extension_ti
, "]");
2739 /* Warning for unsupported/reserved value */
2740 expert_add_info(NULL
, bgt_ti
, &ei_oran_se10_unknown_beamgrouptype
);
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;
2755 uint32_t numBundPrb
;
2759 proto_tree_add_item_ret_boolean(extension_tree
, hf_oran_disable_bfws
,
2760 tvb
, offset
, 1, ENC_BIG_ENDIAN
, &disableBFWs
);
2762 proto_item_append_text(extension_ti
, " (disableBFWs)");
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
);
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
);
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;
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) {
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
) ?
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
);
2824 if (num_bundles
> 0) {
2825 /* Set flag from last bundle entry */
2826 orphaned_prbs
= ext11_settings
.bundles
[num_bundles
-1].is_orphan
;
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) {
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
++) {
2845 proto_tree_add_item(extension_tree
, hf_oran_cont_ind
,
2846 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
2854 orphaned_prbs
= true;
2855 proto_item_append_text(ti
, " (Orphaned PRBs)");
2861 /* Add summary to extension root */
2862 if (orphaned_prbs
) {
2863 proto_item_append_text(extension_ti
, " (%u bundles + orphaned)", num_bundles
);
2866 proto_item_append_text(extension_ti
, " (%u bundles)", num_bundles
);
2872 case 12: /* SE 12: Non-Contiguous PRB Allocation with Frequency Ranges */
2874 ext11_settings
.ext12_set
= true;
2877 proto_tree_add_item(extension_tree
, hf_oran_noncontig_priority
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2880 proto_tree_add_item(extension_tree
, hf_oran_symbolMask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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;
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
);
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
);
2902 proto_tree_add_item_ret_uint(pair_tree
, hf_oran_num_prb
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &num_prb
);
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 */
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
;
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
);
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)");
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;
2975 case 14: /* SE 14: Nulling-layer Info. for ueId-based beamforming */
2977 proto_tree_add_item(extension_tree
, hf_oran_nullLayerInd
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
2979 proto_tree_add_item(extension_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
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
);
2996 proto_tree_add_item(extension_tree
, hf_oran_freqOffset
, tvb
, offset
, 3, ENC_BIG_ENDIAN
);
2999 proto_tree_add_item(extension_tree
, hf_oran_cpLength
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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);
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
);
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
);
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
);
3041 /* reserved (6 bits) */
3042 proto_tree_add_item(extension_tree
, hf_oran_reserved_6bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3044 proto_tree_add_item(extension_tree
, hf_oran_toT
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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;
3058 proto_tree_add_item_ret_boolean(extension_tree
, hf_oran_disable_bfws
,
3059 tvb
, offset
, 1, ENC_BIG_ENDIAN
, &disableBFWs
);
3061 proto_item_append_text(extension_ti
, " (disableBFWs)");
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
);
3067 proto_tree_add_item_ret_uint(extension_tree
, hf_oran_numPortc
,
3068 tvb
, offset
, 1, ENC_BIG_ENDIAN
, &numPortc
);
3072 proto_tree_add_item(extension_tree
, hf_oran_noncontig_priority
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3074 proto_tree_add_item(extension_tree
, hf_oran_symbolMask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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
);
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
,
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
);
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
);
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
);
3114 /* No weights present */
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 /*******************************************************************/
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;
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
);
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
);
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
);
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
);
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;
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
);
3175 /* Set length of this port entry */
3176 proto_item_set_len(port_ti
, offset
-port_start_offset
);
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
);
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
,
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
);
3202 /* startPuncPrb (10 bits) */
3203 proto_tree_add_item(pattern_tree
, hf_oran_startPuncPrb
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3205 /* numPuncPrb (8 bits) */
3206 proto_tree_add_item(pattern_tree
, hf_oran_numPuncPrb
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3208 /* puncReMask (12 bits) */
3209 proto_tree_add_item(pattern_tree
, hf_oran_puncReMask
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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) */
3217 proto_tree_add_item_ret_boolean(pattern_tree
, hf_oran_RbgIncl
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &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
);
3229 proto_item_append_text(rb_ti
, " (ignored)");
3232 proto_item_set_len(pattern_ti
, offset
-pattern_start_offset
);
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
);
3244 switch (ci_prb_group_size
) {
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",
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
;
3260 expert_add_info(pinfo
, numprbc_ti
, &ei_oran_numprbc_ext21_zero
);
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
);
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
);
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
);
3297 /* Try to link forward to ST8 response */
3298 ack_nack_request_t
*response
= wmem_tree_lookup32(state
->ack_nack_requests
,
3301 show_link_to_acknack_response(extension_tree
, tvb
, pinfo
, response
);
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) */
3318 proto_tree_add_item_ret_boolean(extension_tree
, hf_oran_prb_mode
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &prb_mode
);
3321 /* reserved (8 bits) */
3322 proto_tree_add_item(extension_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3325 /* Dissect each SymPrbPattern */
3326 for (uint32_t n
=0; n
< num_sym_prb_pattern
; n
++) {
3329 proto_item
*pattern_ti
= proto_tree_add_string_format(extension_tree
, hf_oran_sym_prb_pattern
,
3331 prb_mode
? "PRB-BLOCK" : "PRB-MASK");
3332 proto_tree
*pattern_tree
= proto_item_add_subtree(pattern_ti
, ett_oran_sym_prb_pattern
);
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
);
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
);
3349 /* reserved (8 bits) */
3350 proto_tree_add_item(pattern_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
3357 /* prbBlkSize (4 bits) */
3358 proto_tree_add_item(pattern_tree
, hf_oran_prb_block_size
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
);
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
);
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
);
3382 proto_item_set_end(pattern_ti
, tvb
, offset
);
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
);
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
);
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
);
3419 /* What follows depends upon entryType */
3420 switch (entry_type
) {
3423 /* No further fields for these */
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
);
3438 proto_tree_add_item(extension_tree
, hf_oran_scrambling
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3442 proto_tree_add_item(extension_tree
, hf_oran_nscid
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3444 if (entry_type
== 2) {
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
);
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
);
3463 /* lastPrb (9 bits) */
3464 proto_tree_add_item(extension_tree
, hf_oran_last_prb
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3466 /* Reserved (16 bits) */
3471 /* reserved - expert info */
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
++) {
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
);
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
);
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) */
3505 proto_tree_add_item_ret_uint(extension_tree
, hf_oran_num_fo_fb
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &num_fo_fb
);
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);
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;
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
);
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
,
3558 unsigned *bit_width
, unsigned *comp_meth
)
3561 proto_item
*udcomphdr_ti
= proto_tree_add_string_format(tree
, hf_oran_udCompHdr
,
3564 proto_tree
*udcomphdr_tree
= proto_item_add_subtree(udcomphdr_ti
, ett_oran_udcomphdr
);
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
);
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
);
3576 *comp_meth
= ud_comp_meth
;
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"));
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
));
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
,
3600 uint32_t *exponent
, uint16_t *sReSMask
,
3603 if (comp_meth
== COMP_NONE
|| comp_meth
== COMP_MODULATION
) {
3604 /* Not even creating a subtree */
3609 proto_item
*udcompparam_ti
= proto_tree_add_string_format(tree
, hf_oran_udCompParam
,
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
) {
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
, ¶m_exponent
);
3621 *exponent
= param_exponent
;
3622 proto_item_append_text(udcompparam_ti
, " (Exponent=%u)", param_exponent
);
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
);
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
);
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
, ¶m_sresmask
);
3646 proto_tree_add_item_ret_uint(udcompparam_tree
, hf_oran_exponent
,
3647 tvb
, offset
, 1, ENC_BIG_ENDIAN
, ¶m_exponent
);
3648 *sReSMask
= param_sresmask
;
3649 *exponent
= param_exponent
;
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
, ¶m_sresmask
);
3657 proto_tree_add_item(udcompparam_tree
, hf_oran_reserved_4bits
,
3658 tvb
, offset
, 1, ENC_BIG_ENDIAN
);
3659 *sReSMask
= param_sresmask
;
3664 /* reserved (set to all zeros), but how many bytes?? */
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
)
3678 proto_item
*cicomphdr_ti
= proto_tree_add_string_format(tree
, hf_oran_ciCompHdr
,
3681 proto_tree
*cicomphdr_tree
= proto_item_add_subtree(cicomphdr_ti
, ett_oran_cicomphdr
);
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;
3688 *bit_width
= hdr_iq_width
;
3690 proto_item_append_text(iq_width_item
, " (%u bits)", hdr_iq_width
);
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
);
3696 *comp_meth
= ci_comp_meth
;
3701 proto_tree_add_item_ret_uint(cicomphdr_tree
, hf_oran_ciCompOpt
, tvb
, offset
, 1, ENC_NA
, &opt
);
3706 proto_item_append_text(cicomphdr_ti
, " (IqWidth=%u, ciCompMeth=%s, ciCompOpt=%s)",
3708 rval_to_str_const(ci_comp_meth
, ud_comp_header_meth
, "Unknown"),
3709 (*comp_opt
) ? "compression per PRB" : "compression per UE");
3713 static void dissect_payload_version(proto_tree
*tree
, tvbuff_t
*tvb
, packet_info
*pinfo
, unsigned offset
)
3716 proto_item
*ti
= proto_tree_add_item_ret_uint(tree
, hf_oran_payload_version
, tvb
, offset
, 1, ENC_NA
, &version
);
3718 expert_add_info_format(pinfo
, ti
, &ei_oran_version_unsupported
,
3719 "PayloadVersion %u not supported by dissector (only 1 is known)",
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
)
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 */
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
);
3800 addPcOrRtcid(tvb
, oran_tree
, &offset
, hf_oran_ecpri_rtcid
, &eAxC
);
3802 /* Message identifier */
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
, §ionHeading
, "C-Plane Section Type ");
3813 /* Peek ahead at the section type */
3814 uint32_t sectionType
= 0;
3815 sectionType
= tvb_get_uint8(tvb
, offset
+5);
3818 proto_item
*scs_ti
= NULL
;
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
);
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
);
3875 unsigned ref_a_offset
= offset
;
3877 uint32_t frameId
= 0;
3878 proto_tree_add_item_ret_uint(section_tree
, hf_oran_frame_id
, tvb
, offset
, 1, ENC_NA
, &frameId
);
3882 uint32_t subframeId
= 0;
3883 proto_tree_add_item_ret_uint(section_tree
, hf_oran_subframe_id
, tvb
, offset
, 1, ENC_NA
, &subframeId
);
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
);
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 */
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
);
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 */
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
);
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
);
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
);
3937 proto_tree_add_item_ret_uint(section_tree
, hf_oran_sectionType
, tvb
, offset
, 1, ENC_NA
, §ionType
);
3940 /* Section-specific fields (white entries in Section Type diagrams) */
3941 unsigned bit_width
= 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 */
3954 proto_tree_add_item(section_tree
, hf_oran_timeOffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3956 /* frameStructure */
3957 offset
= dissect_frame_structure(section_tree
, tvb
, offset
,
3958 subframeId
, slotId
);
3961 proto_tree_add_item(section_tree
, hf_oran_cpLength
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3964 proto_tree_add_item(section_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_NA
);
3968 case SEC_C_NORMAL
: /* Section Type 1 */
3969 case SEC_C_UE_SCHED
: /* Section Type 5 */
3971 offset
= dissect_udcomphdr(tvb
, pinfo
, section_tree
, offset
,
3972 (direction
==1), /* ignore for DL */
3973 &bit_width
, &comp_meth
);
3975 proto_tree_add_item(section_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_NA
);
3979 case SEC_C_SLOT_CONTROL
: /* Section Type 4 */
3982 case SEC_C_PRACH
: /* Section Type 3 */
3984 proto_tree_add_item(section_tree
, hf_oran_timeOffset
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3986 /* frameStructure */
3987 offset
= dissect_frame_structure(section_tree
, tvb
, offset
,
3988 subframeId
, slotId
);
3990 proto_tree_add_item(section_tree
, hf_oran_cpLength
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
3993 offset
= dissect_udcomphdr(tvb
, pinfo
, section_tree
, offset
,
3994 (direction
==1), /* ignore for DL */
3995 &bit_width
, &comp_meth
);
3998 case SEC_C_CH_INFO
: /* Section Type 6 */
4000 proto_tree_add_item_ret_uint(section_tree
, hf_oran_numberOfUEs
, tvb
, offset
, 1, ENC_NA
, &num_ues
);
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
;
4012 case SEC_C_LAA
: /* Section Type 7 */
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
);
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
);
4023 /* Show ACKs and NACKs. For both, try to link back to request. */
4024 for (unsigned int n
=1; n
<= number_of_acks
; n
++) {
4027 ack_ti
= proto_tree_add_item_ret_uint(section_tree
, hf_oran_ackid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &ackid
);
4030 /* Look up request table in state (which really should be set by now, but test anyway). */
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
);
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",
4051 for (unsigned int m
=1; m
<= number_of_nacks
; m
++) {
4053 proto_item
*nack_ti
= proto_tree_add_item_ret_uint(section_tree
, hf_oran_nackid
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &nackid
);
4056 expert_add_info_format(pinfo
, nack_ti
, &ei_oran_st8_nackid
,
4057 "Received Nack for ackNackId=%u",
4060 /* Look up request table in state. */
4062 ack_nack_request_t
*request
= wmem_tree_lookup32(state
->ack_nack_requests
, nackid
);
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
);
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",
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
) {
4088 num_sinr_per_prb
= 1; break;
4090 num_sinr_per_prb
= 2; break;
4092 num_sinr_per_prb
= 3; break;
4094 num_sinr_per_prb
= 4; break;
4096 num_sinr_per_prb
= 6; break;
4098 num_sinr_per_prb
= 12; break;
4101 /* reserved (13 bits) */
4103 proto_tree_add_item(section_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
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
;
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");
4152 /* reserved (1 byte) */
4153 proto_tree_add_item(section_tree
, hf_oran_reserved_8bits
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
4156 /* Loop over commands. Each has 8-byte common header, followed by cmd-specific payload */
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
,
4162 "Type 4 Command common header");
4163 proto_tree
*hdr_tree
= proto_item_add_subtree(hdr_ti
, ett_oran_st4_cmd_header
);
4166 proto_tree_add_item_ret_uint(hdr_tree
, hf_oran_st4_cmd_type
, tvb
, offset
, 1, ENC_NA
, &st4_cmd_type
);
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
);
4177 proto_item_append_text(len_ti
, " (%u bytes)", st4_cmd_len
*4);
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)");
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
);
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
);
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
,
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",
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",
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 */
4251 proto_tree_add_item_ret_boolean(command_tree
, hf_oran_disable_tdbfns
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &disable_tdbfns
);
4254 proto_tree_add_item(command_tree
, hf_oran_td_beam_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
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) */
4264 if (disable_tdbfns
) {
4265 /* No beamnum information to show so get out. */
4269 /* Read beam entries until reach end of command length */
4270 while ((offset
- command_start_offset
) < (st4_cmd_len
* 4)) {
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
);
4277 proto_tree_add_item(command_tree
, hf_oran_td_beam_num
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
4281 if (!disable_tdbfws
) {
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
);
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
);
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
, " ");
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
);
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;
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
);
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
);
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
);
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
);
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
);
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)");
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
);
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
;
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)");
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
);
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
);
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
) {
4425 proto_item_append_text(ant_mask_ti
, " (%u antennas)", antenna_count
);
4426 offset
+= antmask_length
;
4428 /* Pad to next 4-byte boundary */
4430 offset
+= (4-(offset
%4));
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
);
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
);
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
;
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
);
4462 /* reserved (2 bytes) */
4463 proto_tree_add_item(command_tree
, hf_oran_reserved_16bits
, tvb
, offset
, 2, ENC_BIG_ENDIAN
);
4469 expert_add_info_format(pinfo
, len_ti
, &ei_oran_st4_unknown_cmd
,
4470 "Dissected ST4 command (%u) not recognised",
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
,
4502 /* On later passes, try to link forward to ST8 response */
4503 ack_nack_request_t
*response
= wmem_tree_lookup32(state
->ack_nack_requests
,
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
,
4518 bit_width
, ci_comp_method
, ci_comp_opt
,
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
,
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
;
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) */
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 */
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 */
4579 addPcOrRtcid(tvb
, oran_tree
, &offset
, hf_oran_ecpri_pcid
, &eAxC
);
4581 /* Message identifier */
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 (");
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
);
4596 proto_tree_add_item(timing_header_tree
, hf_oran_filter_index
, tvb
, offset
, 1, ENC_NA
);
4599 int ref_a_offset
= offset
;
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
);
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
);
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
);
4614 uint32_t symbolId
= 0;
4615 proto_tree_add_item_ret_uint(timing_header_tree
, hf_oran_symbolId
, tvb
, offset
, 1, ENC_NA
, &symbolId
);
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
;
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 */
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
);
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
;
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",
4702 unsigned number_of_sections
= 0;
4703 unsigned nBytesPerPrb
=0;
4705 /* Add each section (no count, just keep parsing until payload used) */
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
, §ionHeading
, "Section");
4711 /* Section Header fields (darker green part) */
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
, §ionId
);
4716 if (sectionId
== 4095) {
4717 proto_item_append_text(ti
, " (not default coupling C/U planes using sectionId)");
4722 proto_tree_add_item_ret_uint(section_tree
, hf_oran_rb
, tvb
, offset
, 1, ENC_NA
, &rb
);
4724 proto_tree_add_item(section_tree
, hf_oran_symInc
, tvb
, offset
, 1, ENC_NA
);
4726 uint32_t startPrbu
= 0;
4727 proto_tree_add_item_ret_uint(section_tree
, hf_oran_startPrbu
, tvb
, offset
, 2, ENC_BIG_ENDIAN
, &startPrbu
);
4731 uint32_t numPrbu
= 0;
4732 proto_tree_add_item_ret_uint(section_tree
, hf_oran_numPrbu
, tvb
, offset
, 1, ENC_NA
, &numPrbu
);
4735 if (includeUdCompHeader
) {
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
);
4745 /* Showing comp values from prefs */
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
);
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? */
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... */
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
,
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
) {
4788 /* Use sresmask to pick out which REs are present */
4789 for (unsigned n
=0; n
<12; n
++) {
4790 if (sresmask
& (1<<n
)) {
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
);
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
);
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 */
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
);
4872 /* Not dissecting other types - assume these are handled by eCPRI dissector */
4878 /* Register the protocol with Wireshark. */
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
,
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
,
4897 "Width set in dissector preference", HFILL
}
4900 /* Section 3.1.3.1.6 */
4902 { "CC ID", "oran_fh_cus.cc_id",
4903 FT_UINT16
, BASE_DEC
,
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
,
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",
4921 "The Sequence ID wraps around individually per c_eAxC",
4925 /* Section 3.1.3.1.7 */
4927 { "E Bit", "oran_fh_cus.e_bit",
4930 "Indicate the last message of a subsequence (U-Plane only)",
4934 /* Section 3.1.3.1.7 */
4935 { &hf_oran_subsequence_id
,
4936 { "Subsequence ID", "oran_fh_cus.subsequence_id",
4939 "The subsequence ID (for eCPRI layer fragmentation)",
4943 /* Section 7.5.2.1 */
4944 { &hf_oran_data_direction
,
4945 { "Data Direction", "oran_fh_cus.data_direction",
4947 VALS(data_direction_vals
), 0x80,
4948 "gNB data direction",
4952 /* Section 7.5.2.2 */
4953 { &hf_oran_payload_version
,
4954 {"Payload Version", "oran_fh_cus.payloadVersion",
4957 "Payload protocol version the following IEs",
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",
4970 /* Section 7.5.2.4 */
4972 {"Frame ID", "oran_fh_cus.frameId",
4975 "A counter for 10 ms frames (wrapping period 2.56 seconds)",
4979 /* Section 7.5.2.5 */
4980 {&hf_oran_subframe_id
,
4981 {"Subframe ID", "oran_fh_cus.subframe_id",
4984 "A counter for 1 ms sub-frames within 10ms frame",
4988 /* Section 7.5.2.6 */
4990 {"Slot ID", "oran_fh_cus.slotId",
4991 FT_UINT16
, BASE_DEC
,
4993 "Slot number within a 1ms sub-frame",
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
,
5002 "Slot within frame, to match DCT logs",
5006 /* Section 7.5.2.7 */
5007 {&hf_oran_start_symbol_id
,
5008 {"Start Symbol ID", "oran_fh_cus.startSymbolId",
5011 "The first symbol number within slot affected",
5015 /* Section 7.5.2.8 */
5016 {&hf_oran_numberOfSections
,
5017 {"Number of Sections", "oran_fh_cus.numberOfSections",
5020 "The number of section IDs included in this C-Plane message",
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",
5033 /* Section 7.5.2.10 */
5034 {&hf_oran_udCompHdr
,
5035 {"udCompHdr", "oran_fh_cus.udCompHdr",
5036 FT_STRING
, BASE_NONE
,
5042 /* Section 7.5.2.11 */
5043 {&hf_oran_numberOfUEs
,
5044 {"Number Of UEs", "oran_fh_cus.numberOfUEs",
5047 "Indicates number of UEs for which channel info is provided",
5051 /* Section 7.5.2.12 */
5052 {&hf_oran_timeOffset
,
5053 {"Time Offset", "oran_fh_cus.timeOffset",
5054 FT_UINT16
, BASE_DEC
,
5056 "from start of the slot to start of CP in samples",
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",
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",
5078 /* Section 7.5.2.14 */
5080 {"cpLength", "oran_fh_cus.cpLength",
5081 FT_UINT16
, BASE_DEC
,
5083 "cyclic prefix length",
5087 /* Section 7.5.3.1 */
5088 {&hf_oran_section_id
,
5089 {"sectionId", "oran_fh_cus.sectionId",
5090 FT_UINT16
, BASE_DEC
,
5092 "section identifier of data",
5096 /* Section 7.5.3.2 */
5098 {"rb", "oran_fh_cus.rb",
5100 VALS(rb_vals
), 0x08,
5101 "resource block indicator",
5105 /* Section 7.5.5.3 */
5107 {"symInc", "oran_fh_cus.symInc",
5109 VALS(sym_inc_vals
), 0x04,
5110 "Symbol Number Increment Command",
5114 /* Section 7.5.3.4 */
5115 {&hf_oran_startPrbc
,
5116 {"startPrbc", "oran_fh_cus.startPrbc",
5117 FT_UINT16
, BASE_DEC
,
5119 "Starting PRB of Control Plane Section",
5123 /* Section 7.5.3.5 */
5125 {"RE Mask", "oran_fh_cus.reMask",
5126 FT_UINT16
, BASE_HEX
,
5128 "The Resource Element (RE) mask within a PRB",
5132 /* Section 7.5.3.6 */
5134 {"numPrbc", "oran_fh_cus.numPrbc",
5137 "Number of contiguous PRBs per data section description",
5141 /* Section 7.5.3.7 */
5142 {&hf_oran_numSymbol
,
5143 {"Number of Symbols", "oran_fh_cus.numSymbol",
5146 "Defines number of symbols to which the section control is applicable",
5150 /* Section 7.5.3.8 */
5152 {"Extension Flag", "oran_fh_cus.ef",
5155 "Indicates if more section extensions follow",
5159 /* Section 7.5.3.9 */
5161 {"Beam ID", "oran_fh_cus.beamId",
5162 FT_UINT16
, BASE_DEC
,
5164 "Defines the beam pattern to be applied to the U-Plane data",
5168 {&hf_oran_extension
,
5169 {"Extension", "oran_fh_cus.extension",
5170 FT_STRING
, BASE_NONE
,
5172 "Section extension",
5176 /* Section 7.6.2.1 */
5178 {"extType", "oran_fh_cus.extType",
5180 VALS(exttype_vals
), 0x7f,
5181 "The extension type, which provides additional parameters specific to subject data extension",
5185 /* Section 7.6.2.3 */
5187 {"extLen", "oran_fh_cus.extLen",
5188 FT_UINT16
, BASE_DEC
,
5190 "Extension length in 32-bit words",
5196 {"bfw", "oran_fh_cus.bfw",
5197 FT_STRING
, BASE_NONE
,
5199 "Set of weights for a particular antenna",
5202 {&hf_oran_bfw_bundle
,
5203 {"Bundle", "oran_fh_cus.bfw.bundle",
5204 FT_STRING
, BASE_NONE
,
5209 {&hf_oran_bfw_bundle_id
,
5210 {"Bundle Id", "oran_fh_cus.bfw.bundleId",
5211 FT_UINT32
, BASE_DEC
,
5216 /* Section 7.7.1.4 */
5218 {"bfwI", "oran_fh_cus.bfwI",
5219 FT_FLOAT
, BASE_NONE
,
5224 /* Section 7.7.1.5 */
5226 {"bfwQ", "oran_fh_cus.bfwQ",
5227 FT_FLOAT
, BASE_NONE
,
5233 /* Section 7.5.3.10 */
5235 {"UE ID", "oran_fh_cus.ueId",
5236 FT_UINT16
, BASE_DEC
,
5238 "logical identifier for set of channel info",
5242 /* Section 7.5.3.11 */
5243 {&hf_oran_freqOffset
,
5244 {"Frequency Offset", "oran_fh_cus.freqOffset",
5245 FT_UINT24
, BASE_DEC
,
5247 "with respect to the carrier center frequency before additional filtering",
5251 /* Section 7.5.3.12 */
5252 {&hf_oran_regularizationFactor
,
5253 {"Regularization Factor", "oran_fh_cus.regularizationFactor",
5256 "Signed value to support MMSE operation within O-RU",
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,
5269 /* Section 7.5.3.15 */
5270 {&hf_oran_laaMsgLen
,
5271 {"LAA Message Length", "oran_fh_cus.laaMsgLen",
5274 "number of 32-bit words in the LAA section",
5278 /* Section 7.5.3.16 */
5279 {&hf_oran_lbtHandle
,
5280 {"LBT Handle", "oran_fh_cus.lbtHandle",
5281 FT_UINT16
, BASE_HEX
,
5283 "label to identify transaction",
5287 /* Section 7.5.3.17 */
5288 {&hf_oran_lbtDeferFactor
,
5289 {"Defer Factor", "oran_fh_cus.lbtDeferFactor",
5292 "Defer factor in sensing slots as described in 3GPP TS 36.213 Section 15.1.1",
5296 /* Section 7.5.3.18 */
5297 {&hf_oran_lbtBackoffCounter
,
5298 {"Backoff Counter", "oran_fh_cus.lbtBackoffCounter",
5299 FT_UINT16
, BASE_DEC
,
5301 "LBT backoff counter in sensing slots as described in 3GPP TS 36.213 Section 15.1.1",
5305 /* Section 7.5.3.19 */
5306 {&hf_oran_lbtOffset
,
5307 {"LBT Offset", "oran_fh_cus.lbtOffset",
5308 FT_UINT16
, BASE_DEC
,
5310 "LBT start time in microseconds from the beginning of the subframe "
5311 "scheduled by this message",
5315 /* Section 7.5.3.20 */
5317 {"Maximum Channel Occupancy Time", "oran_fh_cus.MCOT",
5320 "LTE TXOP duration in subframes as described in 3GPP TS 36.213 Section 15.1.1",
5324 /* Section 7.5.3.21 */
5326 {"LBT Mode", "oran_fh_cus.lbtMode",
5328 VALS(lbtMode_vals
), 0x0,
5333 /* Section 7.5.3.22 */
5334 {&hf_oran_lbtPdschRes
,
5335 {"lbtPdschRes", "oran_fh_cus.lbtPdschRes",
5337 VALS(lbtPdschRes_vals
), 0xc0,
5338 "LBT result of SFN/SF",
5342 /* Section 7.5.3.23 */
5344 {"sfStatus", "oran_fh_cus.sfStatus",
5346 TFS(&tfs_sfStatus
), 0x10,
5347 "Indicates whether the subframe was dropped or transmitted",
5351 /* Section 7.5.3.22 */
5352 {&hf_oran_lbtDrsRes
,
5353 {"lbtDrsRes", "oran_fh_cus.lbtDrsRes",
5355 TFS(&tfs_fail_success
), 0x80,
5356 "Indicates whether the subframe was dropped or transmitted",
5360 /* Section 7.5.3.25 */
5361 {&hf_oran_initialPartialSF
,
5362 {"Initial partial SF", "oran_fh_cus.initialPartialSF",
5364 TFS(&tfs_partial_full_sf
), 0x40,
5365 "Indicates whether the initial SF in the LBT process is full or partial",
5369 /* Section 7.5.3.26. */
5370 {&hf_oran_lbtBufErr
,
5371 {"lbtBufErr", "oran_fh_cus.lbtBufErr",
5373 TFS(&tfs_lbtBufErr
), 0x80,
5378 /* Section 7.5.3.27 */
5380 {"SFN/SF End", "oran_fh_cus.sfnSfEnd",
5381 FT_UINT16
, BASE_DEC
,
5383 "SFN/SF by which the DRS window must end",
5387 /* Section 7.5.3.28 */
5388 {&hf_oran_lbtCWConfig_H
,
5389 {"lbtCWConfig_H", "oran_fh_cus.lbtCWConfig_H",
5392 "HARQ parameters for congestion window management",
5396 /* Section 7.5.3.29 */
5397 {&hf_oran_lbtCWConfig_T
,
5398 {"lbtCWConfig_T", "oran_fh_cus.lbtCWConfig_T",
5401 "TB parameters for congestion window management",
5405 /* Section 7.5.3.30 */
5406 {&hf_oran_lbtTrafficClass
,
5407 {"lbtTrafficClass", "oran_fh_cus.lbtTrafficClass",
5409 VALS(lbtTrafficClass_vals
), 0x38,
5410 "Traffic class priority for congestion window management",
5414 /* Section 7.5.3.31 */
5415 {&hf_oran_lbtCWR_Rst
,
5416 {"lbtCWR_Rst", "oran_fh_cus.lbtCWR_Rst",
5418 TFS(&tfs_fail_success
), 0x80,
5419 "notification about packet reception successful or not",
5424 {"reserved", "oran_fh_cus.reserved",
5425 FT_UINT64
, BASE_HEX
,
5431 {&hf_oran_reserved_1bit
,
5432 {"reserved", "oran_fh_cus.reserved",
5438 {&hf_oran_reserved_2bits
,
5439 {"reserved", "oran_fh_cus.reserved",
5445 {&hf_oran_reserved_4bits
,
5446 {"reserved", "oran_fh_cus.reserved",
5452 {&hf_oran_reserved_6bits
,
5453 {"reserved", "oran_fh_cus.reserved",
5459 {&hf_oran_reserved_7bits
,
5460 {"reserved", "oran_fh_cus.reserved",
5466 {&hf_oran_reserved_8bits
,
5467 {"reserved", "oran_fh_cus.reserved",
5473 {&hf_oran_reserved_16bits
,
5474 {"reserved", "oran_fh_cus.reserved",
5475 FT_UINT16
, BASE_HEX
,
5480 {&hf_oran_reserved_15bits
,
5481 {"reserved", "oran_fh_cus.reserved",
5482 FT_UINT16
, BASE_HEX
,
5489 {&hf_oran_bundle_offset
,
5490 {"BundleOffset", "oran_fh_cus.bundleOffset",
5493 "offset between start of first PRB bundle and startPrbc",
5498 {"contInd", "oran_fh_cus.contInd",
5500 TFS(&continuity_indication_tfs
), 0x80,
5501 "PRB region continuity flag",
5507 {&hf_oran_laa_msgtype0_reserved
,
5508 {"Reserved", "oran_fh_cus.reserved",
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
,
5520 "Compression method and IQ bit width for beamforming weights",
5523 {&hf_oran_bfwCompHdr_iqWidth
,
5524 {"IQ Bit Width", "oran_fh_cus.bfwCompHdr_iqWidth",
5526 VALS(bfw_comp_headers_iq_width
), 0xf0,
5527 "IQ bit width for the beamforming weights",
5530 {&hf_oran_bfwCompHdr_compMeth
,
5531 {"Compression Method", "oran_fh_cus.bfwCompHdr_compMeth",
5533 VALS(bfw_comp_headers_comp_meth
), 0x0f,
5534 "compression method for the beamforming weights",
5539 {&hf_oran_ciCompParam
,
5540 {"ciCompParam", "oran_fh_cus.ciCompParam",
5541 FT_STRING
, BASE_NONE
,
5543 "channel information compression parameter",
5547 /* Table 7.5.3.32-1 */
5548 {&hf_oran_blockScaler
,
5549 {"blockScaler", "oran_fh_cus.blockScaler",
5552 "unsigned, 1 integer bit, 7 fractional bits",
5555 {&hf_oran_compBitWidth
,
5556 {"compBitWidth", "oran_fh_cus.compBitWidth",
5559 "Length of I bits and length of Q bits after compression over entire PRB",
5562 {&hf_oran_compShift
,
5563 {"compShift", "oran_fh_cus.compShift",
5566 "The shift applied to the entire PRB",
5570 /* Section 7.7.6.6 */
5571 {&hf_oran_repetition
,
5572 {"repetition", "oran_fh_cus.repetition",
5573 FT_BOOLEAN
, BASE_NONE
,
5575 "Repetition of a highest priority data section for C-Plane",
5580 {"rbgSize", "oran_fh_cus.rbgSize",
5582 VALS(rbg_size_vals
), 0x70,
5583 "Number of PRBs of the resource block groups allocated by the bit mask",
5588 {"rbgMask", "oran_fh_cus.rbgMask",
5589 FT_UINT32
, BASE_HEX
,
5591 "Each bit indicates whether a corresponding resource block group is present",
5595 {&hf_oran_noncontig_priority
,
5596 {"priority", "oran_fh_cus.priority",
5598 VALS(priority_vals
), 0xc0,
5603 {&hf_oran_symbolMask
,
5604 {"symbolMask", "oran_fh_cus.symbolMask",
5605 FT_UINT16
, BASE_HEX
,
5607 "Each bit indicates whether the rbgMask applies to a given symbol in the slot",
5612 {&hf_oran_ack_nack_req_id
,
5613 {"ackNackReqId", "oran_fh_cus.ackNackReqId",
5614 FT_UINT16
, BASE_HEX
,
5616 "Indicates the ACK/NACK request ID of a section description",
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
,
5625 "Pair of offStartPrb and numPrb",
5630 {&hf_oran_off_start_prb
,
5631 {"offStartPrb", "oran_fh_cus.offStartPrb",
5634 "Offset of PRB range start",
5639 {"numPrb", "oran_fh_cus.numPrb",
5642 "Number of PRBs in PRB range",
5646 /* symbolId 8.3.3.7 */
5648 {"Symbol Identifier", "oran_fh_cus.symbolId",
5651 "Identifies a symbol number within a slot",
5655 /* startPrbu 8.3.3.11 */
5656 {&hf_oran_startPrbu
,
5657 {"startPrbu", "oran_fh_cus.startPrbu",
5658 FT_UINT16
, BASE_DEC
,
5660 "starting PRB of user plane section",
5664 /* numPrbu 8.3.3.12 */
5666 {"numPrbu", "oran_fh_cus.numPrbu",
5669 "number of PRBs per user plane section",
5674 {&hf_oran_bfwCompParam
,
5675 {"bfwCompParam", "oran_fh_cus.bfwCompParam",
5676 FT_STRING
, BASE_NONE
,
5678 "Beamforming weight compression parameter",
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",
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",
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",
5709 { &hf_oran_udCompHdrIqWidth_pref
,
5710 {"User Data IQ width", "oran_fh_cus.udCompHdrWidth",
5713 "Defines the IQ bit width "
5714 "for the user data in every section in the C-Plane message",
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
,
5724 "Applies to whatever compression method is specified "
5725 "by the associated sectionID's compMeth value",
5730 {"sReSMask", "oran_fh_cus.sReSMask",
5731 FT_UINT16
, BASE_HEX
,
5733 "selective RE sending mask", HFILL
}
5736 /* Section 6.3.3.15 */
5738 {"iSample", "oran_fh_cus.iSample",
5739 FT_FLOAT
, BASE_NONE
,
5741 "In-phase Sample value", HFILL
}
5744 /* Section 6.3.3.16 */
5746 {"qSample", "oran_fh_cus.qSample",
5747 FT_FLOAT
, BASE_NONE
,
5749 "Quadrature Sample value", HFILL
}
5752 { &hf_oran_exponent
,
5753 { "Exponent", "oran_fh_cus.exponent",
5756 "Exponent applicable to the I & Q mantissas",
5760 { &hf_oran_iq_user_data
,
5761 { "IQ User Data", "oran_fh_cus.iq_user_data",
5762 FT_BYTES
, BASE_NONE
,
5764 "Used for the In-phase and Quadrature sample mantissa",
5768 { &hf_oran_c_eAxC_ID
,
5769 { "c_eAxC_ID", "oran_fh_cus.c_eaxc_id",
5770 FT_STRING
, BASE_NONE
,
5772 "This is a calculated field for the c_eAxC ID, which identifies the message stream",
5776 { "RefA", "oran_fh_cus.refa",
5777 FT_STRING
, BASE_NONE
,
5779 "This is a calculated field for the RefA ID, which provides a reference in time",
5784 /* Section 7.5.2.15 */
5785 {&hf_oran_ciCompHdr
,
5786 {"ciCompHdr", "oran_fh_cus.ciCompHdr",
5787 FT_STRING
, BASE_NONE
,
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",
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",
5808 { &hf_oran_ciCompOpt
,
5809 {"ciCompOpt", "oran_fh_cus.ciCompOpt",
5811 VALS(ci_comp_opt_vals
), 0x01,
5817 { &hf_oran_disable_bfws
,
5818 { "disableBFWs", "oran_fh_cus.disableBFWs",
5821 "Indicate if BFWs under section extension are disabled",
5826 { "RAD", "oran_fh_cus.rad",
5829 "Reset After PRB Discontinuity",
5833 { &hf_oran_num_bund_prbs
,
5834 { "numBundPrb", "oran_fh_cus.numBundPrb",
5837 "Number of bundled PRBs per BFWs",
5841 { "beamId", "oran_fh_cus.beamId",
5842 FT_UINT16
, BASE_DEC
,
5847 { &hf_oran_num_weights_per_bundle
,
5848 { "Num weights per bundle", "oran_fh_cus.num_weights_per_bundle",
5849 FT_UINT16
, BASE_DEC
,
5851 "From dissector preference",
5856 { &hf_oran_samples_prb
,
5857 {"PRB", "oran_fh_cus.prb",
5858 FT_STRING
, BASE_NONE
,
5860 "Grouping of samples for a particular Physical Resource Block",
5866 {"ciSample", "oran_fh_cus.ciSample",
5867 FT_STRING
, BASE_NONE
,
5869 "Sample (I and Q values)",
5872 {&hf_oran_ciIsample
,
5873 {"ciIsample", "oran_fh_cus.ciISample",
5874 FT_FLOAT
, BASE_NONE
,
5876 "Channel information complex value - I part",
5879 {&hf_oran_ciQsample
,
5880 { "ciQsample", "oran_fh_cus.ciQSample",
5881 FT_FLOAT
, BASE_NONE
,
5883 "Channel information complex value - Q part",
5888 { &hf_oran_beamGroupType
,
5889 { "beamGroupType", "oran_fh_cus.beamGroupType",
5891 VALS(beam_group_type_vals
), 0xc0,
5892 "The type of beam grouping",
5896 { &hf_oran_numPortc
,
5897 { "numPortc", "oran_fh_cus.numPortc",
5900 "The number of eAxC ports",
5904 /* 7.7.4.2 (1 bit) */
5906 { "csf", "oran_fh_cus.csf",
5907 FT_BOOLEAN
, BASE_NONE
,
5909 "constellation shift flag",
5913 { &hf_oran_modcompscaler
,
5914 { "modCompScaler", "oran_fh_cus.modcompscaler",
5915 FT_UINT16
, BASE_DEC
,
5917 "modulation compression scaler value",
5922 { &hf_oran_modcomp_param_set
,
5923 { "Set", "oran_fh_cus.modcomp-param-set",
5924 FT_STRING
, BASE_NONE
,
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
,
5935 "modulation compression power scale RE mask",
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
,
5943 "scaling value for modulation compression",
5946 /* eAxCmask (7.7.7.2) */
5947 { &hf_oran_eAxC_mask
,
5948 { "eAxC Mask", "oran_fh_cus.eaxcmask",
5949 FT_UINT16
, BASE_HEX
,
5951 "Which eAxC_ID values the C-Plane message applies to",
5954 /* technology (interface name) 7.7.9.2 */
5955 { &hf_oran_technology
,
5956 { "Technology", "oran_fh_cus.technology",
5958 VALS(interface_name_vals
), 0x0,
5959 "Interface name (that C-PLane section applies to)",
5962 /* Exttype 14 (7.7.14.2) */
5963 { &hf_oran_nullLayerInd
,
5964 { "nullLayerInd", "oran_fh_cus.nulllayerind",
5965 FT_BOOLEAN
, BASE_NONE
,
5967 "Whether corresponding layer is nulling-layer or not",
5971 /* Exttype 19 (7.7.19.8) */
5972 { &hf_oran_portReMask
,
5973 { "portReMask", "oran_fh_cus.portReMask",
5975 TFS(&tfs_set_notset
), 0x0fff,
5976 "RE bitmask per port",
5980 { &hf_oran_portSymbolMask
,
5981 { "portSymbolMask", "oran_fh_cus.portSymbolMask",
5983 TFS(&tfs_set_notset
), 0x3fff,
5984 "Symbol bitmask port port",
5988 { &hf_oran_ext19_port
,
5989 {"Port", "oran_fh_cus.ext19.port",
5990 FT_STRING
, BASE_NONE
,
5992 "Entry for a given port in ext19",
5997 { &hf_oran_prb_allocation
,
5998 {"PRB allocation", "oran_fh_cus.prb-allocation",
5999 FT_STRING
, BASE_NONE
,
6005 { &hf_oran_nextSymbolId
,
6006 { "nextSymbolId", "oran_fh_cus.nextSymbolId",
6009 "offset of PRB range start",
6013 { &hf_oran_nextStartPrbc
,
6014 { "nextStartPrbc", "oran_fh_cus.nextStartPrbc",
6015 FT_UINT16
, BASE_DEC
,
6017 "number of PRBs in PRB range",
6021 /* Puncturing patters as appears in SE 20 */
6022 {&hf_oran_puncPattern
,
6023 {"puncPattern", "oran_fh_cus.puncPattern",
6024 FT_STRING
, BASE_NONE
,
6030 /* 7.7.20.2 numPuncPatterns */
6031 { &hf_oran_numPuncPatterns
,
6032 { "numPuncPatterns", "oran_fh_cus.numPuncPatterns",
6035 "number of puncturing patterns",
6038 /* 7.7.20.3 symbolMask */
6039 {&hf_oran_symbolMask_ext20
,
6040 {"symbolMask", "oran_fh_cus.symbolMask",
6041 FT_UINT16
, BASE_HEX
,
6043 "Bitmask where each bit indicates the symbols associated with the puncturing pattern",
6046 /* 7.7.20.4 startPuncPrb */
6047 {&hf_oran_startPuncPrb
,
6048 {"startPuncPrb", "oran_fh_cus.startPuncPrb",
6049 FT_UINT16
, BASE_DEC
,
6051 "starting PRB to which one puncturing pattern applies",
6054 /* 7.7.20.5 numPuncPrb */
6055 {&hf_oran_numPuncPrb
,
6056 {"numPuncPrb", "oran_fh_cus.numPuncPrb",
6057 FT_UINT24
, BASE_DEC
,
6059 "the number of PRBs of the puncturing pattern",
6062 /* 7.7.20.6 puncReMask */
6063 {&hf_oran_puncReMask
,
6064 {"puncReMask", "oran_fh_cus.puncReMask",
6065 FT_UINT16
, BASE_DEC
,
6067 "puncturing pattern RE mask",
6070 /* 7.7.20.4 rbgIncl */
6072 {"rbgIncl", "oran_fh_cus.rbgIncl",
6075 "rbg included flag",
6079 /* 7.7.21.2 ciPrbGroupSize */
6080 {&hf_oran_ci_prb_group_size
,
6081 {"ciPrbGroupSize", "oran_fh_cus.ciPrbGroupSize",
6084 "channel information PRB group size",
6088 {&hf_oran_prg_size_st5
,
6089 {"prgSize", "oran_fh_cus.prgSize",
6091 VALS(prg_size_st5_vals
), 0x03,
6092 "precoding resource block group size",
6095 {&hf_oran_prg_size_st6
,
6096 {"prgSize", "oran_fh_cus.prgSize",
6098 VALS(prg_size_st6_vals
), 0x03,
6099 "precoding resource block group size",
6103 /* 7.7.17.2 numUeID */
6105 {"numUeID", "oran_fh_cus.numUeID",
6108 "number of ueIDs per user",
6112 /* 7.7.16.2 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",
6121 /* 7.7.18.2 transmissionWindowOffset */
6122 {&hf_oran_transmissionWindowOffset
,
6123 {"transmissionWindowOffset", "oran_fh_cus.transmissionWindowOffset",
6124 FT_UINT16
, BASE_DEC
,
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)",
6129 /* 7.7.18.3 transmissionWindowSize */
6130 {&hf_oran_transmissionWindowSize
,
6131 {"transmissionWindowSize", "oran_fh_cus.transmissionWindowSize",
6132 FT_UINT16
, BASE_DEC
,
6134 "size of the transmission window in resolution µs",
6139 {"toT", "oran_fh_cus.toT",
6141 VALS(type_of_transmission_vals
), 0x03,
6142 "type of transmission",
6146 /* 7.7.2.2 bfaCompHdr */
6147 {&hf_oran_bfaCompHdr
,
6148 {"bfaCompHdr", "oran_fh_cus.bfaCompHdr",
6149 FT_STRING
, BASE_NONE
,
6151 "beamforming attributes compression header",
6154 /* 7.7.2.2-2: bfAzPtWidth */
6155 {&hf_oran_bfAzPtWidth
,
6156 {"bfAzPtWidth", "oran_fh_cus.bfAzPtWidth",
6158 VALS(bfa_bw_vals
), 0x38,
6162 /* 7.7.2.2-3: bfZePtWidth */
6163 {&hf_oran_bfZePtWidth
,
6164 {"bfZePtWidth", "oran_fh_cus.bfZePtWidth",
6166 VALS(bfa_bw_vals
), 0x07,
6170 /* 7.7.2.2-4: bfAz3ddWidth */
6171 {&hf_oran_bfAz3ddWidth
,
6172 {"bfAz3ddWidth", "oran_fh_cus.bfAz3ddWidth",
6174 VALS(bfa_bw_vals
), 0x38,
6178 /* 7.7.2.2-5: bfZe3ddWidth */
6179 {&hf_oran_bfZe3ddWidth
,
6180 {"bfZe3ddWidth", "oran_fh_cus.bfZe3ddWidth",
6182 VALS(bfa_bw_vals
), 0x07,
6187 /* 7.7.2.3 bfAzPt */
6189 {"bfAzPt", "oran_fh_cus.bfAzPt",
6192 "beamforming azimuth pointing parameter",
6195 /* 7.7.2.4 bfZePt */
6197 {"bfZePt", "oran_fh_cus.bfZePt",
6200 "beamforming zenith pointing parameter",
6203 /* 7.7.2.5 bfAz3dd */
6205 {"bfAz3dd", "oran_fh_cus.bfAz3dd",
6208 "beamforming azimuth beamwidth parameter",
6211 /* 7.7.2.6 bfZe3dd */
6213 {"bfZe3dd", "oran_fh_cus.bfZe3dd",
6216 "beamforming zenith beamwidth parameter",
6220 /* 7.7.2.7 bfAzSl */
6222 {"bfAzSl", "oran_fh_cus.bfAzSl",
6224 VALS(sidelobe_suppression_vals
), 0x38,
6225 "beamforming azimuth sidelobe parameter",
6228 /* 7.7.2.8 bfZeSl */
6230 {"bfZeSl", "oran_fh_cus.bfZeSl",
6232 VALS(sidelobe_suppression_vals
), 0x38,
6233 "beamforming zenith sidelobe parameter",
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,
6246 {&hf_oran_number_of_st4_cmds
,
6247 {"numberOfST4Cmds", "oran_fh_cus.numberOfST4Cmds",
6250 "Number of Section Type 4 commands",
6254 {&hf_oran_st4_cmd_header
,
6255 {"Command common header", "oran_fh_cus.st4CmdCommonHeader",
6256 FT_STRING
, BASE_NONE
,
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,
6271 {&hf_oran_st4_cmd_len
,
6272 {"st4CmdLen", "oran_fh_cus.st4CmdLen",
6273 FT_UINT16
, BASE_DEC
,
6275 "Length of command in 32-bit words",
6279 {&hf_oran_st4_cmd_num_slots
,
6280 {"numSlots", "oran_fh_cus.st4NumSlots",
6283 "Contiguous slots for which command is applicable",
6287 {&hf_oran_st4_cmd_ack_nack_req_id
,
6288 {"ackNackReqId", "oran_fh_cus.ackNackReqId",
6289 FT_UINT16
, BASE_DEC
,
6291 "ACK/NACK Request Id",
6296 {"Command", "oran_fh_cus.st4Cmd",
6297 FT_STRING
, BASE_NONE
,
6304 {&hf_oran_sleepmode_trx
,
6305 {"sleepMode", "oran_fh_cus.sleepMode",
6307 VALS(sleep_mode_trx_vals
), 0x03,
6311 {&hf_oran_sleepmode_asm
,
6312 {"sleepMode", "oran_fh_cus.sleepMode",
6314 VALS(sleep_mode_asm_vals
), 0x03,
6320 {&hf_oran_log2maskbits
,
6321 {"log2MaskBits", "oran_fh_cus.log2MaskBits",
6323 VALS(log2maskbits_vals
), 0x3c,
6324 "Number of bits to appear in antMask",
6328 {&hf_oran_num_slots_ext
,
6329 {"numSlotsExt", "oran_fh_cus.numSlotsExt",
6330 FT_UINT24
, BASE_HEX
,
6336 {&hf_oran_antMask_trx_control
,
6337 {"antMask", "oran_fh_cus.antMask",
6338 FT_BYTES
, BASE_NONE
,
6340 "which antennas should sleep or wake-up",
6345 {"ready", "oran_fh_cus.ready",
6347 TFS(&ready_tfs
), 0x01,
6348 "wake-up ready indicator",
6352 {&hf_oran_number_of_acks
,
6353 {"numberOfAcks", "oran_fh_cus.numberOfAcks",
6356 "number of ACKs for one eAxC_ID",
6360 {&hf_oran_number_of_nacks
,
6361 {"numberOfNacks", "oran_fh_cus.numberOfNacks",
6364 "number of NACKs for one eAxC_ID",
6369 {"ackId", "oran_fh_cus.ackId",
6370 FT_UINT16
, BASE_DEC
,
6377 {"nackId", "oran_fh_cus.nackId",
6378 FT_UINT16
, BASE_DEC
,
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,
6392 {&hf_oran_acknack_request_time
,
6393 {"Time since request in ms", "oran_fh_cus.ackNackId.time-since-request",
6394 FT_UINT32
, BASE_DEC
,
6396 "Time between request and response",
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,
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,
6413 {&hf_oran_acknack_response_time
,
6414 {"Time to response in ms", "oran_fh_cus.ackNackId.time-to-response",
6415 FT_UINT32
, BASE_DEC
,
6417 "Time between request and response",
6422 {&hf_oran_disable_tdbfns
,
6423 {"disableTDBFNs", "oran_fh_cus.disableTDBFNs",
6425 TFS(&disable_tdbfns_tfs
), 0x80,
6431 {&hf_oran_td_beam_group
,
6432 {"tdBeamGrp", "oran_fh_cus.tdBeamGrp",
6433 FT_UINT16
, BASE_HEX
,
6435 "Applies to symbolMask in command header",
6439 {&hf_oran_disable_tdbfws
,
6440 {"disableTDBFWs", "oran_fh_cus.disableTDBFWs",
6448 {&hf_oran_td_beam_num
,
6449 {"tdBeamNum", "oran_fh_cus.tdBeamNum",
6450 FT_UINT16
, BASE_HEX
,
6452 "time-domain beam number",
6457 {&hf_oran_dir_pattern
,
6458 {"dirPattern", "oran_fh_cus.dirPattern",
6465 {&hf_oran_guard_pattern
,
6466 {"guardPattern", "oran_fh_cus.guardPattern",
6473 /* For convenient filtering */
6475 {"C-Plane", "oran_fh_cus.c-plane",
6482 {"U-Plane", "oran_fh_cus.u-plane",
6490 {&hf_oran_ecpri_pcid
,
6491 {"ecpriPcid", "oran_fh_cus.ecpriPcid",
6494 "IQ data transfer message series identifier",
6497 {&hf_oran_ecpri_rtcid
,
6498 {"ecpriRtcid", "oran_fh_cus.ecpriRtcid",
6501 "Real time control data identifier",
6505 {&hf_oran_ecpri_seqid
,
6506 {"ecpriSeqid", "oran_fh_cus.ecpriSeqid",
6509 "message identifier",
6514 {&hf_oran_num_sym_prb_pattern
,
6515 {"numSymPrbPattern", "oran_fh_cus.numSymPrbPattern",
6518 "number of symbol and resource block patterns",
6523 {"prbMode", "oran_fh_cus.prbMode",
6525 TFS(&prb_mode_tfs
), 0x01,
6530 {&hf_oran_sym_prb_pattern
,
6531 {"symPrbPattern", "oran_fh_cus.symPrbPattern",
6532 FT_STRING
, BASE_NONE
,
6541 {"symMask", "oran_fh_cus.symMask",
6542 FT_UINT16
, BASE_HEX
,
6544 "symbol mask part of symPrbPattern",
6548 {&hf_oran_num_mc_scale_offset
,
6549 {"numMcScaleOffset", "oran_fh_cus.numMcScaleOffset",
6552 "number of modulation compression scaling value per symPrbPattern",
6556 {&hf_oran_prb_pattern
,
6557 {"prbPattern", "oran_fh_cus.prbPattern",
6560 "resource block pattern part of symPrbPattern",
6565 {&hf_oran_codebook_index
,
6566 {"codebookIndex", "oran_fh_cus.codebookIndex",
6569 "precoder codebook used for transmission",
6574 {"layerID", "oran_fh_cus.layerID",
6577 "Layer ID for DL transmission",
6581 {&hf_oran_numlayers
,
6582 {"numLayers", "oran_fh_cus.numLayers",
6585 "number of layers for DL transmission",
6590 {"txScheme", "oran_fh_cus.txScheme",
6593 "transmission scheme",
6597 {&hf_oran_crs_remask
,
6598 {"crsReMask", "oran_fh_cus.crsReMask",
6599 FT_UINT16
, BASE_HEX
,
6601 "CRS resource element mask",
6605 {&hf_oran_crs_shift
,
6606 {"crsShift", "oran_fh_cus.crsShift",
6609 "CRS resource element mask",
6613 {&hf_oran_crs_symnum
,
6614 {"crsSymNum", "oran_fh_cus.crsSymNum",
6617 "CRS symbol number indication",
6621 {&hf_oran_beamid_ap1
,
6622 {"beamIdAP1", "oran_fh_cus.beamIdAP1",
6623 FT_UINT16
, BASE_DEC
,
6625 "beam id to be used for antenna port 1",
6629 {&hf_oran_beamid_ap2
,
6630 {"beamIdAP2", "oran_fh_cus.beamIdAP2",
6631 FT_UINT16
, BASE_DEC
,
6633 "beam id to be used for antenna port 2",
6637 {&hf_oran_beamid_ap3
,
6638 {"beamIdAP3", "oran_fh_cus.beamIdAP3",
6639 FT_UINT16
, BASE_DEC
,
6641 "beam id to be used for antenna port 3",
6646 {&hf_oran_port_list_index
,
6647 {"portListIndex", "oran_fh_cus.portListIndex",
6650 "the index of an eAxC_ID in the port-list",
6654 {&hf_oran_alpn_per_sym
,
6655 {"alpnPerSym", "oran_fh_cus.alpnPerSym",
6661 {&hf_oran_ant_dmrs_snr
,
6662 {"antDmrsSnr", "oran_fh_cus.antDmrsSnr",
6672 {&hf_oran_user_group_size
,
6673 {"userGroupSize", "oran_fh_cus.userGroupSize",
6676 "number of UE data layers in the user group identified by userGroupId",
6680 {&hf_oran_user_group_id
,
6681 {"userGroupId", "oran_fh_cus.userGroupId",
6684 "number of UE data layers in the user group identified by userGroupId",
6688 {&hf_oran_entry_type
,
6689 {"entryType", "oran_fh_cus.entryType",
6692 "indicates format of the entry",
6696 {&hf_oran_dmrs_port_number
,
6697 {"dmrsPortNumber", "oran_fh_cus.dmrsPortNumber",
6700 "DMRS antenna port number for the associated ueId",
6704 {&hf_oran_ueid_reset
,
6705 {"ueidReset", "oran_fh_cus.ueidReset",
6708 "same UEID as the previous slot",
6712 {&hf_oran_dmrs_symbol_mask
,
6713 {"dmrsSymbolMask", "oran_fh_cus.dmrsSymbolMask",
6714 FT_UINT16
, BASE_HEX
,
6716 "symbols within the slot containing DMRS",
6720 {&hf_oran_scrambling
,
6721 {"scrambling", "oran_fh_cus.scrambling",
6722 FT_UINT16
, BASE_HEX
,
6724 "used to calculate the seed value required to initialize pseudo-random generator",
6729 {"nscid", "oran_fh_cus.nscid",
6732 "used to calculate the seed value for pseudo-random generator",
6737 {"dType", "oran_fh_cus.dType",
6740 "PUSCH DMRS configuration type",
6744 {&hf_oran_cmd_without_data
,
6745 {"cmdWithoutData", "oran_fh_cus.cmdWithoutData",
6748 "number of DMRS CDM groups without data",
6753 {"lambda", "oran_fh_cus.lambda",
6760 {&hf_oran_first_prb
,
6761 {"firstPrb", "oran_fh_cus.firstPrb",
6762 FT_UINT16
, BASE_HEX
,
6769 {"lastPrb", "oran_fh_cus.lastPrb",
6770 FT_UINT16
, BASE_HEX
,
6777 {&hf_oran_low_papr_type
,
6778 {"lowPaprType", "oran_fh_cus.lowPaprType",
6785 {&hf_oran_hopping_mode
,
6786 {"hoppingMode", "oran_fh_cus.hoppingMode",
6793 {&hf_oran_tx_win_for_on_air_symbol_l
,
6794 {"txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
6800 {&hf_oran_tx_win_for_on_air_symbol_r
,
6801 {"txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
6808 {&hf_oran_num_fo_fb
,
6809 {"numFoFb", "oran_fh_cus.numFoFb",
6812 "number of frequency offset feedback",
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",
6825 {&hf_oran_num_sinr_per_prb
,
6826 {"numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
6828 VALS(num_sinr_per_prb_vals
), 0xe0,
6829 "number of SINR values per PRB",
6834 /* Section 7.5.3.68 */
6835 {&hf_oran_sinr_value
,
6836 {"sinrValue", "oran_fh_cus.sinrValue",
6837 FT_FLOAT
, BASE_NONE
,
6845 /* Setup protocol subtree array */
6846 static int *ett
[] = {
6848 &ett_oran_ecpri_pcid
,
6849 &ett_oran_ecpri_rtcid
,
6850 &ett_oran_ecpri_seqid
,
6851 &ett_oran_section_type
,
6853 &ett_oran_u_section
,
6857 &ett_oran_c_section_extension
,
6858 &ett_oran_bfw_bundle
,
6860 &ett_oran_offset_start_prb_num_prb
,
6861 &ett_oran_prb_cisamples
,
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
,
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. */
6981 proto_reg_handoff_oran(void)
6986 * Editor modelines - http://www.wireshark.org/tools/modelines.html
6991 * indent-tabs-mode: nil
6994 * ex: set shiftwidth=4 tabstop=8 expandtab:
6995 * :indentSize=4:tabSize=8:noTabs=true: