Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-oran.c
blobf40f1d70ba5bea5ab56ba460388e3768f36306ec
1 /* packet-oran.c
2 * Routines for O-RAN fronthaul UC-plane dissection
3 * Copyright 2020, Jan Schiefer, Keysight Technologies, Inc.
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Dissector for the O-RAN Fronthaul CUS protocol specification.
14 * See https://specifications.o-ran.org/specifications, WG4, Fronthaul Interfaces Workgroup
15 * The current implementation is based on the ORAN-WG4.CUS.0-v16.01 specification
18 #include <config.h>
20 #include <math.h>
22 #include <epan/packet.h>
23 #include <epan/expert.h>
24 #include <epan/prefs.h>
25 #include <epan/tap.h>
27 #include <epan/tfs.h>
28 #include <wsutil/array.h>
30 #include "epan/dissectors/packet-oran.h"
32 /* N.B. dissector preferences are taking the place of (some) M-plane parameters, so unfortunately it can be
33 * fiddly to get the preferences into a good state to decode a given capture..
34 * TODO:
35 * - for U-Plane, track back to last C-Plane frame for that eAxC
36 * - use upCompHdr values from C-Plane if not overridden by U-Plane?
37 * N.B. this matching is tricky see 7.8.1 Coupling of C-Plane and U-Plane
38 * - Radio transport layer (eCPRI) fragmentation / reassembly
39 * - Detect/indicate signs of application layer fragmentation?
40 * - Not handling M-plane setting for "little endian byte order" as applied to IQ samples and beam weights
41 * - for section extensions, check more constraints (which other extension types appear with them, order)
42 * - when some section extensions are present, some section header fields are effectively ignored - flag any remaining ("ignored, "shall")?
43 * - re-order items (decl and hf definitions) to match spec order?
46 /* Prototypes */
47 void proto_reg_handoff_oran(void);
48 void proto_register_oran(void);
50 /* Initialize the protocol and registered fields */
51 static int proto_oran;
53 static int oran_tap = -1;
55 static int hf_oran_du_port_id;
56 static int hf_oran_bandsector_id;
57 static int hf_oran_cc_id;
58 static int hf_oran_ru_port_id;
59 static int hf_oran_sequence_id;
60 static int hf_oran_e_bit;
61 static int hf_oran_subsequence_id;
63 static int hf_oran_data_direction;
64 static int hf_oran_payload_version;
65 static int hf_oran_filter_index;
66 static int hf_oran_frame_id;
67 static int hf_oran_subframe_id;
68 static int hf_oran_slot_id;
69 static int hf_oran_slot_within_frame;
70 static int hf_oran_start_symbol_id;
71 static int hf_oran_numberOfSections;
72 static int hf_oran_sectionType;
74 static int hf_oran_udCompHdr;
75 static int hf_oran_udCompHdrIqWidth;
76 static int hf_oran_udCompHdrIqWidth_pref;
77 static int hf_oran_udCompHdrMeth;
78 static int hf_oran_udCompHdrMeth_pref;
79 static int hf_oran_udCompLen;
80 static int hf_oran_numberOfUEs;
81 static int hf_oran_timeOffset;
82 static int hf_oran_frameStructure_fft;
83 static int hf_oran_frameStructure_subcarrier_spacing;
84 static int hf_oran_cpLength;
85 static int hf_oran_timing_header;
86 static int hf_oran_section_id;
87 static int hf_oran_rb;
88 static int hf_oran_symInc;
89 static int hf_oran_startPrbc;
90 static int hf_oran_reMask_re1;
91 static int hf_oran_reMask_re2;
92 static int hf_oran_reMask_re3;
93 static int hf_oran_reMask_re4;
94 static int hf_oran_reMask_re5;
95 static int hf_oran_reMask_re6;
96 static int hf_oran_reMask_re7;
97 static int hf_oran_reMask_re8;
98 static int hf_oran_reMask_re9;
99 static int hf_oran_reMask_re10;
100 static int hf_oran_reMask_re11;
101 static int hf_oran_reMask_re12;
102 static int hf_oran_reMask;
103 static int hf_oran_numPrbc;
104 static int hf_oran_numSymbol;
105 static int hf_oran_ef;
106 static int hf_oran_beamId;
108 static int hf_oran_ciCompHdr;
109 static int hf_oran_ciCompHdrIqWidth;
110 static int hf_oran_ciCompHdrMeth;
111 static int hf_oran_ciCompOpt;
113 static int hf_oran_extension;
114 static int hf_oran_exttype;
115 static int hf_oran_extlen;
117 static int hf_oran_bfw_bundle;
118 static int hf_oran_bfw_bundle_id;
119 static int hf_oran_bfw;
120 static int hf_oran_bfw_i;
121 static int hf_oran_bfw_q;
123 static int hf_oran_ueId;
124 static int hf_oran_freqOffset;
125 static int hf_oran_regularizationFactor;
126 static int hf_oran_laaMsgType;
127 static int hf_oran_laaMsgLen;
128 static int hf_oran_lbtHandle;
129 static int hf_oran_lbtDeferFactor;
130 static int hf_oran_lbtBackoffCounter;
131 static int hf_oran_lbtOffset;
132 static int hf_oran_MCOT;
133 static int hf_oran_lbtMode;
134 static int hf_oran_sfnSfEnd;
135 static int hf_oran_lbtPdschRes;
136 static int hf_oran_sfStatus;
137 static int hf_oran_initialPartialSF;
138 static int hf_oran_lbtDrsRes;
139 static int hf_oran_lbtBufErr;
140 static int hf_oran_lbtTrafficClass;
141 static int hf_oran_lbtCWConfig_H;
142 static int hf_oran_lbtCWConfig_T;
143 static int hf_oran_lbtCWR_Rst;
145 static int hf_oran_reserved;
146 static int hf_oran_reserved_1bit;
147 static int hf_oran_reserved_2bits;
148 static int hf_oran_reserved_4bits;
149 static int hf_oran_reserved_last_4bits;
150 static int hf_oran_reserved_last_5bits;
151 static int hf_oran_reserved_6bits;
152 static int hf_oran_reserved_last_6bits;
153 static int hf_oran_reserved_7bits;
154 static int hf_oran_reserved_last_7bits;
155 static int hf_oran_reserved_8bits;
156 static int hf_oran_reserved_16bits;
157 static int hf_oran_reserved_15bits;
158 static int hf_oran_reserved_bit1;
159 static int hf_oran_reserved_bit2;
160 static int hf_oran_reserved_bit4;
161 static int hf_oran_reserved_bit5;
162 static int hf_oran_reserved_bits123;
163 static int hf_oran_reserved_bits456;
165 static int hf_oran_bundle_offset;
166 static int hf_oran_cont_ind;
168 static int hf_oran_bfwCompHdr;
169 static int hf_oran_bfwCompHdr_iqWidth;
170 static int hf_oran_bfwCompHdr_compMeth;
171 static int hf_oran_symbolId;
172 static int hf_oran_startPrbu;
173 static int hf_oran_numPrbu;
175 static int hf_oran_udCompParam;
176 static int hf_oran_sReSMask;
177 static int hf_oran_sReSMask_re12;
178 static int hf_oran_sReSMask_re11;
179 static int hf_oran_sReSMask_re10;
180 static int hf_oran_sReSMask_re9;
181 static int hf_oran_sReSMask_re8;
182 static int hf_oran_sReSMask_re7;
183 static int hf_oran_sReSMask_re6;
184 static int hf_oran_sReSMask_re5;
185 static int hf_oran_sReSMask_re4;
186 static int hf_oran_sReSMask_re3;
187 static int hf_oran_sReSMask_re2;
188 static int hf_oran_sReSMask_re1;
190 static int hf_oran_sReSMask1;
191 static int hf_oran_sReSMask2;
192 static int hf_oran_sReSMask1_2_re12;
193 static int hf_oran_sReSMask1_2_re11;
194 static int hf_oran_sReSMask1_2_re10;
195 static int hf_oran_sReSMask1_2_re9;
197 static int hf_oran_bfwCompParam;
199 static int hf_oran_iSample;
200 static int hf_oran_qSample;
202 static int hf_oran_ciCompParam;
204 static int hf_oran_blockScaler;
205 static int hf_oran_compBitWidth;
206 static int hf_oran_compShift;
208 static int hf_oran_repetition;
209 static int hf_oran_rbgSize;
210 static int hf_oran_rbgMask;
211 static int hf_oran_noncontig_priority;
212 static int hf_oran_symbolMask;
214 static int hf_oran_exponent;
215 static int hf_oran_iq_user_data;
217 static int hf_oran_disable_bfws;
218 static int hf_oran_rad;
219 static int hf_oran_num_bund_prbs;
220 static int hf_oran_beam_id;
221 static int hf_oran_num_weights_per_bundle;
223 static int hf_oran_ack_nack_req_id;
225 static int hf_oran_off_start_prb_num_prb_pair;
226 static int hf_oran_off_start_prb;
227 static int hf_oran_num_prb;
229 static int hf_oran_samples_prb;
230 static int hf_oran_ciSample;
231 static int hf_oran_ciIsample;
232 static int hf_oran_ciQsample;
234 static int hf_oran_beamGroupType;
235 static int hf_oran_numPortc;
237 static int hf_oran_csf;
238 static int hf_oran_modcompscaler;
240 static int hf_oran_modcomp_param_set;
241 static int hf_oran_mc_scale_re_mask;
242 static int hf_oran_mc_scale_offset;
244 static int hf_oran_eAxC_mask;
245 static int hf_oran_technology;
246 static int hf_oran_nullLayerInd;
248 static int hf_oran_portReMask;
249 static int hf_oran_portSymbolMask;
251 static int hf_oran_ext19_port;
253 static int hf_oran_prb_allocation;
254 static int hf_oran_nextSymbolId;
255 static int hf_oran_nextStartPrbc;
257 static int hf_oran_puncPattern;
258 static int hf_oran_numPuncPatterns;
259 static int hf_oran_symbolMask_ext20;
260 static int hf_oran_startPuncPrb;
261 static int hf_oran_numPuncPrb;
262 static int hf_oran_puncReMask;
263 static int hf_oran_multiSDScope;
264 static int hf_oran_RbgIncl;
266 static int hf_oran_ci_prb_group_size;
267 static int hf_oran_prg_size_st5;
268 static int hf_oran_prg_size_st6;
270 static int hf_oran_num_ueid;
272 static int hf_oran_antMask;
274 static int hf_oran_transmissionWindowOffset;
275 static int hf_oran_transmissionWindowSize;
276 static int hf_oran_toT;
278 static int hf_oran_bfaCompHdr;
279 static int hf_oran_bfAzPtWidth;
280 static int hf_oran_bfZePtWidth;
281 static int hf_oran_bfAz3ddWidth;
282 static int hf_oran_bfZe3ddWidth;
283 static int hf_oran_bfAzPt;
284 static int hf_oran_bfZePt;
285 static int hf_oran_bfAz3dd;
286 static int hf_oran_bfZe3dd;
287 static int hf_oran_bfAzSl;
288 static int hf_oran_bfZeSl;
290 static int hf_oran_cmd_scope;
291 static int hf_oran_number_of_st4_cmds;
293 static int hf_oran_st4_cmd_header;
294 static int hf_oran_st4_cmd_type;
295 static int hf_oran_st4_cmd_len;
296 static int hf_oran_st4_cmd_num_slots;
297 static int hf_oran_st4_cmd_ack_nack_req_id;
299 static int hf_oran_st4_cmd;
301 static int hf_oran_sleepmode_trx;
302 static int hf_oran_sleepmode_asm;
303 static int hf_oran_log2maskbits;
304 static int hf_oran_num_slots_ext;
305 static int hf_oran_antMask_trx_control;
307 static int hf_oran_ready;
308 static int hf_oran_number_of_acks;
309 static int hf_oran_number_of_nacks;
310 static int hf_oran_ackid;
311 static int hf_oran_nackid;
313 static int hf_oran_acknack_request_frame;
314 static int hf_oran_acknack_request_time;
315 static int hf_oran_acknack_request_type;
316 static int hf_oran_acknack_response_frame;
317 static int hf_oran_acknack_response_time;
319 static int hf_oran_disable_tdbfns;
320 static int hf_oran_td_beam_group;
321 static int hf_oran_disable_tdbfws;
322 static int hf_oran_td_beam_num;
324 static int hf_oran_dir_pattern;
325 static int hf_oran_guard_pattern;
327 static int hf_oran_ecpri_pcid;
328 static int hf_oran_ecpri_rtcid;
329 static int hf_oran_ecpri_seqid;
331 static int hf_oran_num_sym_prb_pattern;
332 static int hf_oran_prb_mode;
333 static int hf_oran_sym_prb_pattern;
334 static int hf_oran_sym_mask;
335 static int hf_oran_num_mc_scale_offset;
336 static int hf_oran_prb_pattern;
337 static int hf_oran_prb_block_offset;
338 static int hf_oran_prb_block_size;
340 static int hf_oran_codebook_index;
341 static int hf_oran_layerid;
342 static int hf_oran_numlayers;
343 static int hf_oran_txscheme;
344 static int hf_oran_crs_remask;
345 static int hf_oran_crs_shift;
346 static int hf_oran_crs_symnum;
347 static int hf_oran_beamid_ap1;
348 static int hf_oran_beamid_ap2;
349 static int hf_oran_beamid_ap3;
351 static int hf_oran_port_list_index;
352 static int hf_oran_alpn_per_sym;
353 static int hf_oran_ant_dmrs_snr;
354 static int hf_oran_user_group_size;
355 static int hf_oran_user_group_id;
356 static int hf_oran_entry_type;
357 static int hf_oran_dmrs_port_number;
358 static int hf_oran_ueid_reset;
359 static int hf_oran_dmrs_symbol_mask;
360 static int hf_oran_scrambling;
361 static int hf_oran_nscid;
362 static int hf_oran_dtype;
363 static int hf_oran_cmd_without_data;
364 static int hf_oran_lambda;
365 static int hf_oran_first_prb;
366 static int hf_oran_last_prb;
367 static int hf_oran_low_papr_type;
368 static int hf_oran_hopping_mode;
370 static int hf_oran_tx_win_for_on_air_symbol_l;
371 static int hf_oran_tx_win_for_on_air_symbol_r;
373 static int hf_oran_num_fo_fb;
374 static int hf_oran_freq_offset_fb;
376 static int hf_oran_num_sinr_per_prb;
377 static int hf_oran_sinr_value;
379 static int hf_oran_measurement_report;
380 static int hf_oran_mf;
381 static int hf_oran_meas_data_size;
382 static int hf_oran_meas_type_id;
383 static int hf_oran_ipn_power;
384 static int hf_oran_ue_tae;
385 static int hf_oran_ue_layer_power;
386 static int hf_oran_num_elements;
387 static int hf_oran_ant_dmrs_snr_val;
388 static int hf_oran_ue_freq_offset;
390 static int hf_oran_beam_type;
391 static int hf_oran_meas_cmd_size;
393 static int hf_oran_symbol_reordering_layer;
394 static int hf_oran_dmrs_entry;
396 static int hf_oran_c_section_common;
397 static int hf_oran_c_section;
398 static int hf_oran_u_section;
400 /* Computed fields */
401 static int hf_oran_c_eAxC_ID;
402 static int hf_oran_refa;
404 /* Hidden fields for filtering */
405 static int hf_oran_cplane;
406 static int hf_oran_uplane;
407 static int hf_oran_bf; /* to match frames that configure beamforming in any way */
410 /* Initialize the subtree pointers */
411 static int ett_oran;
412 static int ett_oran_ecpri_rtcid;
413 static int ett_oran_ecpri_pcid;
414 static int ett_oran_ecpri_seqid;
415 static int ett_oran_section;
416 static int ett_oran_section_type;
417 static int ett_oran_u_timing;
418 static int ett_oran_u_section;
419 static int ett_oran_u_prb;
420 static int ett_oran_iq;
421 static int ett_oran_bfw_bundle;
422 static int ett_oran_bfw;
423 static int ett_oran_offset_start_prb_num_prb;
424 static int ett_oran_prb_cisamples;
425 static int ett_oran_cisample;
426 static int ett_oran_udcomphdr;
427 static int ett_oran_udcompparam;
428 static int ett_oran_cicomphdr;
429 static int ett_oran_cicompparam;
430 static int ett_oran_bfwcomphdr;
431 static int ett_oran_bfwcompparam;
432 static int ett_oran_ext19_port;
433 static int ett_oran_prb_allocation;
434 static int ett_oran_punc_pattern;
435 static int ett_oran_bfacomphdr;
436 static int ett_oran_modcomp_param_set;
437 static int ett_oran_st4_cmd_header;
438 static int ett_oran_st4_cmd;
439 static int ett_oran_sym_prb_pattern;
440 static int ett_oran_measurement_report;
441 static int ett_oran_sresmask;
442 static int ett_oran_c_section_common;
443 static int ett_oran_c_section;
444 static int ett_oran_remask;
445 static int ett_oran_symbol_reordering_layer;
446 static int ett_oran_dmrs_entry;
448 /* Don't want all extensions to open and close together. Use extType-1 entry */
449 static int ett_oran_c_section_extension[HIGHEST_EXTTYPE];
451 /* Expert info */
452 static expert_field ei_oran_unsupported_bfw_compression_method;
453 static expert_field ei_oran_invalid_sample_bit_width;
454 static expert_field ei_oran_reserved_numBundPrb;
455 static expert_field ei_oran_extlen_wrong;
456 static expert_field ei_oran_invalid_eaxc_bit_width;
457 static expert_field ei_oran_extlen_zero;
458 static expert_field ei_oran_rbg_size_reserved;
459 static expert_field ei_oran_frame_length;
460 static expert_field ei_oran_numprbc_ext21_zero;
461 static expert_field ei_oran_ci_prb_group_size_reserved;
462 static expert_field ei_oran_st8_nackid;
463 static expert_field ei_oran_st4_no_cmds;
464 static expert_field ei_oran_st4_zero_len_cmd;
465 static expert_field ei_oran_st4_wrong_len_cmd;
466 static expert_field ei_oran_st4_unknown_cmd;
467 static expert_field ei_oran_mcot_out_of_range;
468 static expert_field ei_oran_se10_unknown_beamgrouptype;
469 static expert_field ei_oran_start_symbol_id_not_zero;
470 static expert_field ei_oran_trx_control_cmd_scope;
471 static expert_field ei_oran_unhandled_se;
472 static expert_field ei_oran_bad_symbolmask;
473 static expert_field ei_oran_numslots_not_zero;
474 static expert_field ei_oran_version_unsupported;
475 static expert_field ei_oran_laa_msg_type_unsupported;
476 static expert_field ei_oran_se_on_unsupported_st;
477 static expert_field ei_oran_cplane_unexpected_sequence_number;
478 static expert_field ei_oran_uplane_unexpected_sequence_number;
479 static expert_field ei_oran_acknack_no_request;
480 static expert_field ei_oran_udpcomphdr_should_be_zero;
481 static expert_field ei_oran_radio_fragmentation_c_plane;
482 static expert_field ei_oran_radio_fragmentation_u_plane;
483 static expert_field ei_oran_lastRbdid_out_of_range;
484 static expert_field ei_oran_rbgMask_beyond_last_rbdid;
485 static expert_field ei_oran_unexpected_measTypeId;
486 static expert_field ei_oran_unsupported_compression_method;
487 static expert_field ei_oran_ud_comp_len_wrong_size;
488 static expert_field ei_oran_sresmask2_not_zero_with_rb;
489 static expert_field ei_oran_st6_rb_shall_be_0;
490 static expert_field ei_oran_st10_numsymbol_not_14;
491 static expert_field ei_oran_st10_startsymbolid_not_0;
494 /* These are the message types handled by this dissector */
495 #define ECPRI_MT_IQ_DATA 0
496 #define ECPRI_MT_RT_CTRL_DATA 2
499 /* Preference settings - try to set reasonable defaults */
500 static unsigned pref_du_port_id_bits = 4;
501 static unsigned pref_bandsector_id_bits = 4;
502 static unsigned pref_cc_id_bits = 4;
503 static unsigned pref_ru_port_id_bits = 4;
505 /* TODO: ideally should be per-flow */
506 static unsigned pref_sample_bit_width_uplink = 14;
507 static unsigned pref_sample_bit_width_downlink = 14;
509 /* 8.3.3.15 Compression schemes */
510 #define COMP_NONE 0
511 #define COMP_BLOCK_FP 1
512 #define COMP_BLOCK_SCALE 2
513 #define COMP_U_LAW 3
514 #define COMP_MODULATION 4
515 #define BFP_AND_SELECTIVE_RE 5
516 #define MOD_COMPR_AND_SELECTIVE_RE 6
517 #define BFP_AND_SELECTIVE_RE_WITH_MASKS 7
518 #define MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS 8
520 /* TODO: these ideally should be per-flow too */
521 static int pref_iqCompressionUplink = COMP_BLOCK_FP;
522 static int pref_iqCompressionDownlink = COMP_BLOCK_FP;
524 /* Is udCompHeader present (both directions) */
525 static int pref_includeUdCompHeaderUplink = 2; /* start heuristic */
526 static int pref_includeUdCompHeaderDownlink = 2; /* start heuristic */
528 static unsigned pref_data_plane_section_total_rbs = 273;
529 static unsigned pref_num_weights_per_bundle = 32;
530 static unsigned pref_num_bf_antennas = 32;
531 static bool pref_showIQSampleValues = true;
533 /* Based upon m-plane param, so will be system-wide */
534 static int pref_support_udcompLen = 2; /* start heuristic, can force other settings if necessary */
535 static bool udcomplen_heuristic_result_set = false;
536 static bool udcomplen_heuristic_result = false;
539 static const enum_val_t dl_compression_options[] = {
540 { "COMP_NONE", "No Compression", COMP_NONE },
541 { "COMP_BLOCK_FP", "Block Floating Point Compression", COMP_BLOCK_FP },
542 { "COMP_BLOCK_SCALE", "Block Scaling Compression", COMP_BLOCK_SCALE },
543 { "COMP_U_LAW", "u-Law Compression", COMP_U_LAW },
544 { "COMP_MODULATION", "Modulation Compression", COMP_MODULATION },
545 { "BFP_AND_SELECTIVE_RE", "Block Floating Point + selective RE sending", BFP_AND_SELECTIVE_RE },
546 { "MOD_COMPR_AND_SELECTIVE_RE", "Modulation Compression + selective RE sending", MOD_COMPR_AND_SELECTIVE_RE },
547 { "BFP_AND_SELECTIVE_RE_WITH_MASKS", "Block Floating Point + selective RE sending with masks in section header", BFP_AND_SELECTIVE_RE_WITH_MASKS },
548 { "MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS", "Modulation Compression + selective RE sending with masks in section header", MOD_COMPR_AND_SELECTIVE_RE },
549 { NULL, NULL, 0 }
552 static const enum_val_t ul_compression_options[] = {
553 { "COMP_NONE", "No Compression", COMP_NONE },
554 { "COMP_BLOCK_FP", "Block Floating Point Compression", COMP_BLOCK_FP },
555 { "COMP_BLOCK_SCALE", "Block Scaling Compression", COMP_BLOCK_SCALE },
556 { "COMP_U_LAW", "u-Law Compression", COMP_U_LAW },
557 { "BFP_AND_SELECTIVE_RE", "Block Floating Point + selective RE sending", BFP_AND_SELECTIVE_RE },
558 { "BFP_AND_SELECTIVE_RE_WITH_MASKS", "Block Floating Point + selective RE sending with masks in section header", BFP_AND_SELECTIVE_RE_WITH_MASKS },
559 { NULL, NULL, 0 }
562 static const enum_val_t udcomp_support_options[] = {
563 { "NOT_SUPPORTED", "Not Supported", 0 },
564 { "SUPPORTED", "Supported", 1 },
565 { "HEURISTIC", "Use Heuristic", 2 },
566 { NULL, NULL, 0 }
569 static const enum_val_t udcomphdr_present_options[] = {
570 { "NOT_PRESENT", "Present", 0 },
571 { "PRESENT", "Not Present", 1 },
572 { "HEURISTIC", "Attempt Heuristic", 2 },
573 { NULL, NULL, 0 }
577 static const value_string e_bit[] = {
578 { 0, "More fragments follow" },
579 { 1, "Last fragment" },
580 { 0, NULL}
583 #define DIR_UPLINK 0
584 #define DIR_DOWNLINK 1
587 static const value_string data_direction_vals[] = {
588 { DIR_UPLINK, "Uplink" }, /* gNB Rx */
589 { DIR_DOWNLINK, "Downlink" }, /* gNB Tx */
590 { 0, NULL}
593 static const value_string rb_vals[] = {
594 { 0, "Every RB used" },
595 { 1, "Every other RB used" },
596 { 0, NULL}
599 static const value_string sym_inc_vals[] = {
600 { 0, "Use the current symbol number" },
601 { 1, "Increment the current symbol number" },
602 { 0, NULL}
605 static const value_string lbtMode_vals[] = {
606 { 0, "Full LBT (regular LBT, sending reservation signal until the beginning of the SF/slot)" },
607 { 1, "Partial LBT (looking back 25 usec prior to transmission" },
608 { 2, "Partial LBT (looking back 34 usec prior to transmission" },
609 { 3, "Full LBT and stop (regular LBT, without sending reservation signal" },
610 { 0, NULL}
613 static const range_string filter_indices[] = {
614 {0, 0, "standard channel filter"},
615 {1, 1, "UL filter for PRACH preamble formats 0, 1, 2; min. passband 839 x 1.25kHz = 1048.75 kHz"},
616 {2, 2, "UL filter for PRACH preamble format 3, min. passband 839 x 5 kHz = 4195 kHz"},
617 {3, 3, "UL filter for PRACH preamble formats A1, A2, A3, B1, B2, B3, B4, C0, C2; min. passband 139 x \u0394fRA"},
618 {4, 4, "UL filter for NPRACH 0, 1; min. passband 48 x 3.75KHz = 180 KHz"},
619 {5, 5, "UL filter for PRACH preamble formats"},
620 {8, 8, "UL filter NPUSCH"},
621 {9, 9, "Mixed numerology and other channels except PRACH and NB-IoT"},
622 {9, 15, "Reserved"},
623 {0, 0, NULL}
626 static const range_string section_types[] = {
627 { SEC_C_UNUSED_RB, SEC_C_UNUSED_RB, "Unused Resource Blocks or symbols in Downlink or Uplink" },
628 { SEC_C_NORMAL, SEC_C_NORMAL, "Most DL/UL radio channels" },
629 { SEC_C_RSVD2, SEC_C_RSVD2, "Reserved for future use" },
630 { SEC_C_PRACH, SEC_C_PRACH, "PRACH and mixed-numerology channels" },
631 { SEC_C_SLOT_CONTROL, SEC_C_SLOT_CONTROL, "Slot Configuration Control" },
632 { SEC_C_UE_SCHED, SEC_C_UE_SCHED, "UE scheduling information (UE-ID assignment to section)" },
633 { SEC_C_CH_INFO, SEC_C_CH_INFO, "Channel information" },
634 { SEC_C_LAA, SEC_C_LAA, "LAA (License Assisted Access)" },
635 { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "ACK/NACK Feedback" },
636 { SEC_C_SINR_REPORTING, SEC_C_SINR_REPORTING, "SINR Reporting" },
637 { SEC_C_RRM_MEAS_REPORTS, SEC_C_RRM_MEAS_REPORTS, "RRM Measurement Reports" },
638 { SEC_C_REQUEST_RRM_MEAS, SEC_C_REQUEST_RRM_MEAS, "Request RRM Measurements" },
639 { 12, 255, "Reserved for future use" },
640 { 0, 0, NULL} };
642 static const range_string section_types_short[] = {
643 { SEC_C_UNUSED_RB, SEC_C_UNUSED_RB, "(Unused RBs) " },
644 { SEC_C_NORMAL, SEC_C_NORMAL, "(Most channels) " },
645 { SEC_C_RSVD2, SEC_C_RSVD2, "(reserved) " },
646 { SEC_C_PRACH, SEC_C_PRACH, "(PRACH/mixed-\u03bc)" },
647 { SEC_C_SLOT_CONTROL, SEC_C_SLOT_CONTROL, "(Slot info) " },
648 { SEC_C_UE_SCHED, SEC_C_UE_SCHED, "(UE scheduling info)" },
649 { SEC_C_CH_INFO, SEC_C_CH_INFO, "(Channel info) " },
650 { SEC_C_LAA, SEC_C_LAA, "(LAA) " },
651 { SEC_C_ACK_NACK_FEEDBACK, SEC_C_ACK_NACK_FEEDBACK, "(ACK/NACK) " },
652 { SEC_C_SINR_REPORTING, SEC_C_SINR_REPORTING, "(SINR Reporting) " },
653 { SEC_C_RRM_MEAS_REPORTS, SEC_C_RRM_MEAS_REPORTS, "(RRM Meas Reports) " },
654 { SEC_C_REQUEST_RRM_MEAS, SEC_C_REQUEST_RRM_MEAS, "(Req RRM Meas) " },
655 { 12, 255, "Reserved for future use" },
656 { 0, 0, NULL }
659 static const range_string ud_comp_header_width[] = {
660 {0, 0, "I and Q are each 16 bits wide"},
661 {1, 15, "Bit width of I and Q"},
662 {0, 0, NULL} };
664 /* Table 8.3.3.13-3 */
665 static const range_string ud_comp_header_meth[] = {
666 {COMP_NONE, COMP_NONE, "No compression" },
667 {COMP_BLOCK_FP, COMP_BLOCK_FP, "Block floating point compression" },
668 {COMP_BLOCK_SCALE, COMP_BLOCK_SCALE, "Block scaling" },
669 {COMP_U_LAW, COMP_U_LAW, "Mu - law" },
670 {COMP_MODULATION, COMP_MODULATION, "Modulation compression" },
671 {BFP_AND_SELECTIVE_RE, BFP_AND_SELECTIVE_RE, "BFP + selective RE sending" },
672 {MOD_COMPR_AND_SELECTIVE_RE, MOD_COMPR_AND_SELECTIVE_RE, "mod-compr + selective RE sending" },
673 {BFP_AND_SELECTIVE_RE_WITH_MASKS, BFP_AND_SELECTIVE_RE_WITH_MASKS, "BFP + selective RE sending with masks in section header" },
674 {MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS, "mod-compr + selective RE sending with masks in section header"},
675 {9, 15, "Reserved"},
676 {0, 0, NULL}
679 /* Table 7.5.2.13-2 */
680 static const range_string frame_structure_fft[] = {
681 {0, 0, "Reserved (no FFT/iFFT processing)"},
682 {1, 3, "Reserved"},
683 {4, 4, "FFT size 16"},
684 {5, 5, "FFT size 32"},
685 {6, 6, "FFT size 64"},
686 {7, 7, "FFT size 128"},
687 {8, 8, "FFT size 256"},
688 {9, 9, "FFT size 512"},
689 {10, 10, "FFT size 1024"},
690 {11, 11, "FFT size 2048"},
691 {12, 12, "FFT size 4096"},
692 {13, 13, "FFT size 1536"},
693 {14, 14, "FFT size 3072"},
694 {15, 15, "Reserved"},
695 {0, 0, NULL}
698 /* Table 7.5.2.13-3 */
699 static const range_string subcarrier_spacings[] = {
700 { 0, 0, "SCS 15 kHz, 1 slot/subframe, slot length 1 ms" },
701 { 1, 1, "SCS 30 kHz, 2 slots/subframe, slot length 500 \u03bcs" },
702 { 2, 2, "SCS 60 kHz, 4 slots/subframe, slot length 250 \u03bcs" },
703 { 3, 3, "SCS 120 kHz, 8 slots/subframe, slot length 125 \u03bcs" },
704 { 4, 4, "SCS 240 kHz, 16 slots/subframe, slot length 62.5 \u03bcs" },
705 { 5, 11, "Reserved" }, /* N.B., 5 was 480kHz in early spec versions */
706 { 12, 12, "SCS 1.25 kHz, 1 slot/subframe, slot length 1 ms" },
707 { 13, 13, "SCS 3.75 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
708 { 14, 14, "SCS 5 kHz, 1 slot/subframe, slot length 1 ms" },
709 { 15, 15, "SCS 7.5 kHz(LTE - specific), 1 slot/subframe, slot length 1 ms" },
710 { 0, 0, NULL }
713 /* Table 7.5.3.14-1 laaMsgType definition */
714 static const range_string laaMsgTypes[] = {
715 {0, 0, "LBT_PDSCH_REQ - lls - O-DU to O-RU request to obtain a PDSCH channel"},
716 {1, 1, "LBT_DRS_REQ - lls - O-DU to O-RU request to obtain the channel and send DRS"},
717 {2, 2, "LBT_PDSCH_RSP - O-RU to O-DU response, channel acq success or failure"},
718 {3, 3, "LBT_DRS_RSP - O-RU to O-DU response, DRS sending success or failure"},
719 {4, 4, "LBT_Buffer_Error - O-RU to O-DU response, reporting buffer overflow"},
720 {5, 5, "LBT_CWCONFIG_REQ - O-DU to O-RU request, congestion window configuration"},
721 {6, 6, "LBT_CWCONFIG_RST - O-RU to O-DU request, congestion window config, response"},
722 {7, 15, "reserved for future methods"},
723 {0, 0, NULL}
726 static const range_string freq_offset_fb_values[] = {
727 {0, 0, "no frequency offset"},
728 {8000, 8000, "value not provided"},
729 {1, 30000, "positive frequency offset, (0, +0.5] subcarrier"},
730 {0x8ad0, 0xffff, "negative frequency offset, [-0.5, 0) subcarrier"},
731 {0x0, 0xffff, "reserved"},
732 {0, 0, NULL}
735 static const value_string num_sinr_per_prb_vals[] = {
736 { 0, "1" },
737 { 1, "2" },
738 { 2, "3" },
739 { 3, "4" },
740 { 4, "6" },
741 { 5, "12" },
742 { 6, "reserved" },
743 { 7, "reserved" },
744 { 0, NULL}
747 static const value_string meas_type_id_vals[] = {
748 { 1, "UE Timing Advance Error" },
749 { 2, "UE Layer power" },
750 { 3, "UE frequency offset" },
751 { 4, "Interference plus Noise for allocated PRBs" },
752 { 5, "Interference plus Noise for unallocated PRBs" },
753 { 6, "DMRS SNR per antenna" },
754 { 0, NULL}
757 static const value_string beam_type_vals[] = {
758 { 0, "List of beamId values" },
759 { 1, "Range of beamId values" },
760 { 0, NULL}
764 /* Table 7.6.1-1 */
765 static const value_string exttype_vals[] = {
766 {0, "Reserved"},
767 {1, "Beamforming weights"},
768 {2, "Beamforming attributes"},
769 {3, "DL Precoding configuration parameters and indications"},
770 {4, "Modulation compr. params"},
771 {5, "Modulation compression additional scaling parameters"},
772 {6, "Non-contiguous PRB allocation"},
773 {7, "Multiple-eAxC designation"},
774 {8, "Regularization factor"},
775 {9, "Dynamic Spectrum Sharing parameters"},
776 {10, "Multiple ports grouping"},
777 {11, "Flexible BF weights"},
778 {12, "Non-Contiguous PRB Allocation with Frequency Ranges"},
779 {13, "PRB Allocation with Frequency Hopping"},
780 {14, "Nulling-layer Info. for ueId-based beamforming"},
781 {15, "Mixed-numerology Info. for ueId-based beamforming"},
782 {16, "Section description for antenna mapping in UE channel information based UL beamforming"},
783 {17, "Section description for indication of user port group"},
784 {18, "Section description for Uplink Transmission Management"},
785 {19, "Compact beamforming information for multiple port"},
786 {20, "Puncturing extension"},
787 {21, "Variable PRB group size for channel information"},
788 {22, "ACK/NACK request"},
789 {23, "Multiple symbol modulation compression parameters"},
790 {24, "PUSCH DMRS configuration"},
791 {25, "Symbol reordering for DMRS-BF"},
792 {26, "Frequency offset feedback"},
793 {27, "O-DU controlled dimensionality reduction"},
794 {0, NULL}
797 /**************************************************************************************/
798 /* Keep track for each Section Extension, which section types are allowed to carry it */
799 typedef struct {
800 bool ST0;
801 bool ST1;
802 bool ST3;
803 bool ST5;
804 bool ST6;
805 bool ST10;
806 bool ST11;
807 } AllowedCTs_t;
810 static AllowedCTs_t ext_cts[HIGHEST_EXTTYPE] = {
811 /* ST0 ST1 ST3 ST5 ST6 ST10 ST11 */
812 { false, true, true, false, false, false, false}, // SE 1 (1,3)
813 { false, true, true, false, false, false, false}, // SE 2 (1,3)
814 { false, true, true, false, false, false, false}, // SE 3 (1,3)
815 { false, true, true, true, false, false, false}, // SE 4 (1,3,5)
816 { false, true, true, true, false, false, false}, // SE 5 (1,3,5)
817 { false, true, true, true, false, false, false}, // SE 6 (1,3,5)
818 { true, false, false, false, false, false, false}, // SE 7 (0)
819 { false, false, false, true, false, false, false}, // SE 8 (5)
820 { true, true, true, true, true, true, true }, // SE 9 (all)
821 { false, true, true, true, false, false, false}, // SE 10 (1,3,5)
822 { false, true, true, false, false, false, false}, // SE 11 (1,3)
823 { false, true, true, true, false, false, false}, // SE 12 (1,3,5)
824 { false, true, true, true, false, false, false}, // SE 13 (1,3,5)
825 { false, false, false, true, false, false, false}, // SE 14 (5)
826 { false, false, false, true, true, false, false}, // SE 15 (5,6)
827 { false, false, false, true, false, false, false}, // SE 16 (5)
828 { false, false, false, true, false, false, false}, // SE 17 (5)
829 { false, true, true, true, false, false, false}, // SE 18 (1,3,5)
830 { false, true, true, false, false, false, false}, // SE 19 (1,3)
831 { true, true, true, true, true, false, false}, // SE 20 (0,1,3,5)
832 { false, false, false, true, true, false, false}, // SE 21 (5,6)
833 { true, true, true, true, true, true, true }, // SE 22 (all)
834 { false, true, true, true, false, false, false}, // SE 23 (1,3,5)
835 { false, false, false, true, false, false, false }, // SE 24 (5)
836 { false, false, false, true, false, false, false }, // SE 25 (5)
837 { false, false, false, true, false, false, false }, // SE 26 (5)
838 { false, false, false, true, false, false, false }, // SE 27 (5)
843 static bool se_allowed_in_st(unsigned se, unsigned ct)
845 if (se==0 || se>HIGHEST_EXTTYPE) {
846 /* Don't know about new SE, so don't complain.. */
847 return true;
850 switch (ct) {
851 case 1:
852 return ext_cts[se-1].ST1;
853 case 3:
854 return ext_cts[se-1].ST3;
855 case 5:
856 return ext_cts[se-1].ST5;
857 case 6:
858 return ext_cts[se-1].ST6;
859 default:
860 /* New section type that includes 'ef'.. assume ok */
861 return true;
865 /************************************************************************************/
867 static const value_string bfw_comp_headers_iq_width[] = {
868 {0, "I and Q are 16 bits wide"},
869 {1, "I and Q are 1 bit wide"},
870 {2, "I and Q are 2 bits wide"},
871 {3, "I and Q are 3 bits wide"},
872 {4, "I and Q are 4 bits wide"},
873 {5, "I and Q are 5 bits wide"},
874 {6, "I and Q are 6 bits wide"},
875 {7, "I and Q are 7 bits wide"},
876 {8, "I and Q are 8 bits wide"},
877 {9, "I and Q are 9 bits wide"},
878 {10, "I and Q are 10 bits wide"},
879 {11, "I and Q are 11 bits wide"},
880 {12, "I and Q are 12 bits wide"},
881 {13, "I and Q are 13 bits wide"},
882 {14, "I and Q are 14 bits wide"},
883 {15, "I and Q are 15 bits wide"},
884 {0, NULL}
887 /* Table 7.7.1.2-3 */
888 static const value_string bfw_comp_headers_comp_meth[] = {
889 {COMP_NONE, "no compression"},
890 {COMP_BLOCK_FP, "block floating point"},
891 {COMP_BLOCK_SCALE, "block scaling"},
892 {COMP_U_LAW, "u-law"},
893 {4, "beamspace compression type I"},
894 {5, "beamspace compression type II"},
895 {0, NULL}
898 /* 7.7.6.2 rbgSize (resource block group size) */
899 static const value_string rbg_size_vals[] = {
900 {0, "reserved"},
901 {1, "1"},
902 {2, "2"},
903 {3, "3"},
904 {4, "4"},
905 {5, "6"},
906 {6, "8"},
907 {7, "16"},
908 {0, NULL}
911 /* 7.7.6.5 */
912 static const value_string priority_vals[] = {
913 {0, "0"},
914 {1, "+1"},
915 {2, "-2 (reserved, should not be used)"},
916 {3, "-1"},
917 {0, NULL}
920 /* 7.7.10.2 beamGroupType */
921 static const value_string beam_group_type_vals[] = {
922 {0x0, "common beam"},
923 {0x1, "beam matrix indication"},
924 {0x2, "beam vector listing"},
925 {0x3, "beamId/ueId listing with associated port-list index"},
926 {0, NULL}
929 /* 7.7.9.2 technology (interface name) */
930 static const value_string interface_name_vals[] = {
931 {0x0, "LTE"},
932 {0x1, "NR"},
933 {0, NULL}
936 /* 7.7.18.4 toT (type of transmission) */
937 static const value_string type_of_transmission_vals[] = {
938 {0x0, "normal transmission mode, data can be distributed in any way the O-RU is implemented to transmit data"},
939 {0x1, "uniformly distributed over the transmission window"},
940 {0x2, "Reserved"},
941 {0x3, "Reserved"},
942 {0, NULL}
945 /* 7.7.2.2 (width of bfa parameters) */
946 static const value_string bfa_bw_vals[] = {
947 {0, "no bits, the field is not applicable (e.g., O-RU does not support it) or the default value shall be used"},
948 {1, "2-bit bitwidth"},
949 {2, "3-bit bitwidth"},
950 {3, "4-bit bitwidth"},
951 {4, "5-bit bitwidth"},
952 {5, "6-bit bitwidth"},
953 {6, "7-bit bitwidth"},
954 {7, "8-bit bitwidth"},
955 {0, NULL}
958 /* 7.7.2.7 & 7.7.2.8 */
959 static const value_string sidelobe_suppression_vals[] = {
960 {0, "10 dB"},
961 {1, "15 dB"},
962 {2, "20 dB"},
963 {3, "25 dB"},
964 {4, "30 dB"},
965 {5, "35 dB"},
966 {6, "40 dB"},
967 {7, ">= 45 dB"},
968 {0, NULL}
971 static const value_string lbtTrafficClass_vals[] = {
972 {1, "Priority 1"},
973 {2, "Priority 2"},
974 {3, "Priority 3"},
975 {4, "Priority 4"},
976 {0, NULL}
979 static const value_string lbtPdschRes_vals[] = {
980 {0, "not sensing – indicates that the O-RU is transmitting data"},
981 {1, "currently sensing – indicates the O-RU has not yet acquired the channel"},
982 {2, "success – indicates that the channel was successfully acquired"},
983 {3, "Failure – indicates expiration of the LBT timer. The LBT process should be reset"},
984 {0, NULL}
987 static const value_string ci_comp_opt_vals[] = {
988 {0, "compression per UE, one ciCompParam exists before the I/Q value of each UE"},
989 {1, "compression per PRB, one ciCompParam exists before the I/Q value of each PRB"},
990 {0, NULL}
993 static const range_string cmd_scope_vals[] = {
994 {0, 0, "ARRAY-COMMAND"},
995 {1, 1, "CARRIER-COMMAND"},
996 {2, 2, "O-RU-COMMAND"},
997 {3, 15, "reserved"},
998 {0, 0, NULL}
1001 /* N.B., table in 7.5.3.38 is truncated.. */
1002 static const range_string st4_cmd_type_vals[] = {
1003 {0, 0, "reserved for future command types"},
1004 {1, 1, "TIME_DOMAIN_BEAM_CONFIG"},
1005 {2, 2, "TDD_CONFIG_PATTERN"},
1006 {3, 3, "TRX_CONTROL"},
1007 {4, 4, "ASM"},
1008 {5, 255, "reserved for future command types"},
1009 {0, 0, NULL}
1012 /* Table 7.5.3.51-1 */
1013 static const value_string log2maskbits_vals[] = {
1014 {0, "reserved"},
1015 {1, "min antMask size is 16 bits.."},
1016 {2, "min antMask size is 16 bits.."},
1017 {3, "min antMask size is 16 bits.."},
1018 {4, "16 bits"},
1019 {5, "32 bits"},
1020 {6, "64 bits"},
1021 {7, "128 bits"},
1022 {8, "256 bits"},
1023 {9, "512 bits"},
1024 {10, "1024 bits"},
1025 {11, "2048 bits"},
1026 {12, "4096 bits"},
1027 {13, "8192 bits"},
1028 {14, "16384 bits"},
1029 {15, "reserved"},
1030 {0, NULL}
1033 /* Table 16.1-1 Sleep modes */
1034 static const value_string sleep_mode_trx_vals[] = {
1035 { 0, "TRXC-mode0-wake-up-duration (symbol)"},
1036 { 1, "TRXC-mode1-wake-up-duration (L)"},
1037 { 2, "TRXC-mode2-wake-up-duration (M)"},
1038 { 3, "TRXC-mode3-wake-up-duration (N)"},
1039 { 0, NULL}
1042 static const value_string sleep_mode_asm_vals[] = {
1043 { 0, "ASM-mode0-wake-up-duration (symbol)"},
1044 { 1, "ASM-mode1-wake-up-duration (L)"},
1045 { 2, "ASM-mode2-wake-up-duration (M)"},
1046 { 3, "ASM-mode3-wake-up-duration (N)"},
1047 { 0, NULL}
1050 /* 7.7.21.3.1 */
1051 static const value_string prg_size_st5_vals[] = {
1052 { 0, "reserved"},
1053 { 1, "Precoding resource block group size as WIDEBAND"},
1054 { 2, "Precoding resource block group size 2"},
1055 { 3, "Precoding resource block group size 4"},
1056 { 0, NULL}
1059 static const value_string prg_size_st6_vals[] = {
1060 { 0, "if ciPrbGroupSize is 2 or 4, then ciPrbGroupSize, else WIDEBAND"},
1061 { 1, "Precoding resource block group size as WIDEBAND"},
1062 { 2, "Precoding resource block group size 2"},
1063 { 3, "Precoding resource block group size 4"},
1064 { 0, NULL}
1067 static const value_string alpn_per_sym_vals[] = {
1068 { 0, "report one allocated IPN value per all allocated symbols with DMRS"},
1069 { 1, "report one allocated IPN value per group of consecutive DMRS symbols"},
1070 { 0, NULL}
1073 static const value_string ant_dmrs_snr_vals[] = {
1074 { 0, "O-RU shall not report the MEAS_ANT_DMRS_SNR"},
1075 { 1, "O-RU shall report the MEAS_ANT_DMRS_SNR"},
1076 { 0, NULL}
1079 /* 7.7.24.14 */
1080 static const value_string dtype_vals[] = {
1081 { 0, "assume DMRS configuration type 1"},
1082 { 1, "assume DMRS configuration type 2"},
1083 { 0, NULL}
1086 /* 7.7.24.17 */
1087 static const value_string papr_type_vals[] = {
1088 { 0, "sequence generator type 1 for short sequence lengths"},
1089 { 1, "sequence generator type 1 for long sequence lengths"},
1090 { 2, "sequence generator type 2 for short sequence lengths"},
1091 { 3, "sequence generator type 2 for long sequence lengths"},
1092 { 0, NULL}
1095 /* 7.7.24.18 */
1096 static const value_string hopping_mode_vals[] = {
1097 { 0, "neither group, nor sequence hopping is enabled"},
1098 { 1, "group hopping is enabled and sequence hopping is disabled"},
1099 { 2, "sequence hopping is enabled and group hopping is disabled"},
1100 { 3, "reserved"},
1101 { 0, NULL}
1105 static const true_false_string tfs_sfStatus =
1107 "subframe was transmitted",
1108 "subframe was dropped"
1111 static const true_false_string tfs_lbtBufErr =
1113 "buffer overflow – data received at O-RU is larger than the available buffer size",
1114 "reserved"
1117 static const true_false_string tfs_partial_full_sf = {
1118 "partial SF",
1119 "full SF"
1122 static const true_false_string disable_tdbfns_tfs = {
1123 "beam numbers excluded",
1124 "beam numbers included"
1127 static const true_false_string continuity_indication_tfs = {
1128 "continuity between current and next bundle",
1129 "discontinuity between current and next bundle"
1132 static const true_false_string prb_mode_tfs = {
1133 "PRB-BLOCK mode",
1134 "PRB-MASK mode"
1137 static const true_false_string symbol_direction_tfs = {
1138 "DL symbol",
1139 "UL symbol"
1142 static const true_false_string symbol_guard_tfs = {
1143 "guard symbol",
1144 "non-guard symbol"
1147 static const true_false_string beam_numbers_included_tfs = {
1148 "time-domain beam numbers excluded in this command",
1149 "time-domain beam numbers included in this command"
1152 static const true_false_string measurement_flag_tfs = {
1153 "at least one additional measurement report or command after the current one",
1154 "no additional measurement report or command"
1158 /* Forward declaration */
1159 static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
1160 unsigned comp_meth,
1161 uint32_t *exponent, uint16_t *sReSMask, bool for_sinr);
1164 static const true_false_string ready_tfs = {
1165 "message is a \"ready\" message",
1166 "message is a ACK message"
1169 static const true_false_string multi_sd_scope_tfs = {
1170 "Puncturing pattern applies to current and following sections",
1171 "Puncturing pattern applies to current section"
1174 static const true_false_string tfs_ueid_reset = {
1175 "cannot assume same UE as in preceding slot",
1176 "can assume same UE as in preceding slot"
1180 /* Config for (and later, worked-out allocations) bundles for ext11 (dynamic BFW) */
1181 typedef struct {
1182 /* Ext 6 config */
1183 bool ext6_set;
1184 uint8_t ext6_rbg_size; /* number of PRBs allocated by bitmask */
1186 uint8_t ext6_num_bits_set;
1187 uint8_t ext6_bits_set[28]; /* Which bit position this entry has */
1188 /* TODO: store an f value for each bit position? */
1190 /* Ext 12 config */
1191 bool ext12_set;
1192 unsigned ext12_num_pairs;
1193 #define MAX_BFW_EXT12_PAIRS 128
1194 struct {
1195 uint8_t off_start_prb;
1196 uint8_t num_prb;
1197 } ext12_pairs[MAX_BFW_EXT12_PAIRS];
1199 /* Ext 13 config */
1200 bool ext13_set;
1201 unsigned ext13_num_start_prbs;
1202 #define MAX_BFW_EXT13_ALLOCATIONS 128
1203 unsigned ext13_start_prbs[MAX_BFW_EXT13_ALLOCATIONS];
1204 /* TODO: store nextSymbolId here too? */
1206 /* Ext 21 config */
1207 bool ext21_set;
1208 uint8_t ext21_ci_prb_group_size;
1210 /* Results/settings (after calling ext11_work_out_bundles()) */
1211 uint32_t num_bundles;
1212 #define MAX_BFW_BUNDLES 512
1213 struct {
1214 uint32_t start; /* first prb of bundle */
1215 uint32_t end; /* last prb of bundle*/
1216 bool is_orphan; /* true if not complete (i.e., end-start < numBundPrb) */
1217 } bundles[MAX_BFW_BUNDLES];
1218 } ext11_settings_t;
1221 /* Work out bundle allocation for ext 11. Take into account ext6/ext21, ext12 or ext13 in this section before ext 11. */
1222 /* Won't be called with numBundPrb=0 */
1223 static void ext11_work_out_bundles(unsigned startPrbc,
1224 unsigned numPrbc,
1225 unsigned numBundPrb, /* number of PRBs pre (full) bundle */
1226 ext11_settings_t *settings)
1228 /* Allocation configured by ext 6 */
1229 if (settings->ext6_set) {
1230 unsigned bundles_per_entry = (settings->ext6_rbg_size / numBundPrb);
1232 /* Need to cope with these not dividing exactly, or even having more PRbs in a bundle that
1233 rbg size. i.e. each bundle gets the correct number of PRBs until
1234 all rbg entries are consumed... */
1236 /* TODO: need to check 7.9.4.2. Different cases depending upon value of RAD */
1238 if (bundles_per_entry == 0) {
1239 bundles_per_entry = 1;
1242 /* Maybe also be affected by ext 21 */
1243 if (settings->ext21_set) {
1244 /* N.B., have already checked that numPrbc is not 0 */
1246 /* ciPrbGroupSize overrides number of contiguous PRBs in group */
1247 bundles_per_entry = (settings->ext6_rbg_size / settings->ext21_ci_prb_group_size);
1249 /* numPrbc is the number of PRB groups per antenna - handled in call to dissect_bfw_bundle() */
1252 unsigned bundles_set = 0;
1253 for (uint8_t n=0;
1254 n < (settings->ext6_num_bits_set * settings->ext6_rbg_size) / numBundPrb;
1255 n++) {
1257 /* Watch out for array bound */
1258 if (n >= 28) {
1259 break;
1262 /* For each bundle... */
1264 /* TODO: Work out where first PRB is */
1265 /* May not be the start of an rbg block... */
1266 uint32_t prb_start = (settings->ext6_bits_set[n] * settings->ext6_rbg_size);
1268 /* For each bundle within identified rbgSize block */
1269 for (unsigned m=0; m < bundles_per_entry; m++) {
1270 settings->bundles[bundles_set].start = startPrbc+prb_start+(m*numBundPrb);
1271 /* Start already beyond end, so doesn't count. */
1272 if (settings->bundles[bundles_set].start > (startPrbc+numPrbc-1)) {
1273 break;
1275 /* Bundle consists of numBundPrb bundles */
1276 /* TODO: may involve PRBs from >1 rbg blocks.. */
1277 settings->bundles[bundles_set].end = startPrbc+prb_start+((m+1)*numBundPrb)-1;
1278 if (settings->bundles[bundles_set].end > (startPrbc+numPrbc-1)) {
1279 /* Extends beyond end, so counts but is an orphan bundle */
1280 settings->bundles[bundles_set].end = numPrbc;
1281 settings->bundles[bundles_set].is_orphan = true;
1284 /* Get out if have reached array bound */
1285 if (++bundles_set == MAX_BFW_BUNDLES) {
1286 return;
1290 settings->num_bundles = bundles_set;
1293 /* Allocation configured by ext 12 */
1294 else if (settings->ext12_set) {
1295 /* First, allocate normally from startPrbc, numPrbc */
1296 settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1298 /* Don't overflow settings->bundles[] ! */
1299 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1301 for (uint32_t n=0; n < settings->num_bundles; n++) {
1302 settings->bundles[n].start = startPrbc + n*numBundPrb;
1303 settings->bundles[n].end = settings->bundles[n].start + numBundPrb-1;
1304 /* Does it go beyond the end? */
1305 if (settings->bundles[n].end > startPrbc+numPrbc) {
1306 settings->bundles[n].end = numPrbc+numPrbc;
1307 settings->bundles[n].is_orphan = true;
1310 if (settings->num_bundles == MAX_BFW_BUNDLES) {
1311 return;
1314 unsigned prb_offset = startPrbc + numPrbc;
1316 /* Loop over pairs, adding bundles for each */
1317 for (unsigned p=0; p < settings->ext12_num_pairs; p++) {
1318 prb_offset += settings->ext12_pairs[p].off_start_prb;
1319 unsigned pair_bundles = (settings->ext12_pairs[p].num_prb+numBundPrb-1) / numBundPrb;
1321 for (uint32_t n=0; n < pair_bundles; n++) {
1322 unsigned idx = settings->num_bundles;
1324 settings->bundles[idx].start = prb_offset + n*numBundPrb;
1325 settings->bundles[idx].end = settings->bundles[idx].start + numBundPrb-1;
1326 /* Does it go beyond the end? */
1327 if (settings->bundles[idx].end > prb_offset + settings->ext12_pairs[p].num_prb) {
1328 settings->bundles[idx].end = prb_offset + settings->ext12_pairs[p].num_prb;
1329 settings->bundles[idx].is_orphan = true;
1331 /* Range check / return */
1332 settings->num_bundles++;
1333 if (settings->num_bundles == MAX_BFW_BUNDLES) {
1334 return;
1338 prb_offset += settings->ext12_pairs[p].num_prb;
1342 /* Allocation configured by ext 13 */
1343 else if (settings->ext13_set) {
1344 unsigned alloc_size = (numPrbc+numBundPrb-1) / numBundPrb;
1345 settings->num_bundles = alloc_size * settings->ext13_num_start_prbs;
1347 /* Don't overflow settings->bundles[] ! */
1348 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1350 for (unsigned alloc=0; alloc < settings->ext13_num_start_prbs; alloc++) {
1351 unsigned alloc_start = alloc * alloc_size;
1352 for (uint32_t n=0; n < alloc_size; n++) {
1353 if ((alloc_start+n) >= MAX_BFW_BUNDLES) {
1354 /* ERROR */
1355 return;
1357 settings->bundles[alloc_start+n].start = settings->ext13_start_prbs[alloc] + startPrbc + n*numBundPrb;
1358 settings->bundles[alloc_start+n].end = settings->bundles[alloc_start+n].start + numBundPrb-1;
1359 if (settings->bundles[alloc_start+n].end > settings->ext13_start_prbs[alloc] + numPrbc) {
1360 settings->bundles[alloc_start+n].end = settings->ext13_start_prbs[alloc] + numPrbc;
1361 settings->bundles[alloc_start+n].is_orphan = true;
1367 /* Bundles not controlled by other extensions - just divide up range into bundles we have */
1368 else {
1369 settings->num_bundles = (numPrbc+numBundPrb-1) / numBundPrb;
1371 /* Don't overflow settings->bundles[] ! */
1372 settings->num_bundles = MIN(MAX_BFW_BUNDLES, settings->num_bundles);
1374 for (uint32_t n=0; n < settings->num_bundles; n++) {
1375 settings->bundles[n].start = startPrbc + n*numBundPrb;
1376 settings->bundles[n].end = settings->bundles[n].start + numBundPrb-1;
1377 /* Does it go beyond the end? */
1378 if (settings->bundles[n].end > startPrbc+numPrbc) {
1379 settings->bundles[n].end = numPrbc+numPrbc;
1380 settings->bundles[n].is_orphan = true;
1387 /*******************************************************/
1388 /* Overall state of a flow (eAxC/plane) */
1389 typedef struct {
1390 /* State for sequence analysis [each direction] */
1391 bool last_frame_seen[2];
1392 uint32_t last_frame[2];
1393 uint8_t next_expected_sequence_number[2];
1395 /* Table recording ackNack requests (ackNackId -> ack_nack_request_t*)
1396 Note that this assumes that the same ackNackId will not be reused within a state,
1397 which may well not be valid */
1398 wmem_tree_t *ack_nack_requests;
1400 /* Store udCompHdr seen in C-Plane for UL - can be looked up and used by U-PLane.
1401 Note that this appears in the common section header parts of ST1, ST3, ST5,
1402 so can still be over-written per sectionId in the U-Plane */
1403 bool ul_ud_comp_hdr_set;
1404 unsigned ul_ud_comp_hdr_bit_width;
1405 int ul_ud_comp_hdr_compression;
1407 bool udcomphdrDownlink_heuristic_result_set;
1408 bool udcomphdrDownlink_heuristic_result;
1409 bool udcomphdrUplink_heuristic_result_set;
1410 bool udcomphdrUplink_heuristic_result;
1412 /* Modulation compression params */
1413 /* TODO: incomplete (see SE4, SE5, SE23), and needs to be per section! */
1414 //uint16_t mod_comp_re_mask;
1415 //bool mod_compr_csf;
1416 //double mod_compr_mod_comp_scaler;
1417 } flow_state_t;
1419 typedef struct {
1420 uint32_t request_frame_number;
1421 nstime_t request_frame_time;
1422 enum {
1423 SE22,
1424 ST4Cmd1,
1425 ST4Cmd2,
1426 ST4Cmd3,
1427 ST4Cmd4
1428 } requestType;
1430 uint32_t response_frame_number;
1431 nstime_t response_frame_time;
1432 } ack_nack_request_t;
1434 static const value_string acknack_type_vals[] = {
1435 { SE22, "SE 22" },
1436 { ST4Cmd1, "ST4 (TIME_DOMAIN_BEAM_CONFIG)" },
1437 { ST4Cmd2, "ST4 (TDD_CONFIG_PATTERN)" },
1438 { ST4Cmd3, "ST4 (TRX_CONTROL)" },
1439 { ST4Cmd4, "ST4 (ASM)" },
1440 { 0, NULL}
1443 #define ORAN_C_PLANE 0
1444 #define ORAN_U_PLANE 1
1446 static uint32_t make_flow_key(uint16_t eaxc_id, uint8_t plane)
1448 return eaxc_id | (plane << 16);
1452 /* Table maintained on first pass from flow_key(uint32_t) -> flow_state_t* */
1453 static wmem_tree_t *flow_states_table;
1455 /* Table consulted on subsequent passes: frame_num -> flow_result_t* */
1456 static wmem_tree_t *flow_results_table;
1458 typedef struct {
1459 /* Sequence analysis */
1460 bool unexpected_seq_number;
1461 uint8_t expected_sequence_number;
1462 uint32_t previous_frame;
1463 } flow_result_t;
1465 static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
1466 ack_nack_request_t *response);
1471 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1472 packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(4, 5);
1474 /* Write the given formatted text to:
1475 - the info column (if pinfo != NULL)
1476 - 1 or 2 other labels (optional)
1478 static void write_pdu_label_and_info(proto_item *ti1, proto_item *ti2,
1479 packet_info *pinfo, const char *format, ...)
1481 #define MAX_INFO_BUFFER 256
1482 char info_buffer[MAX_INFO_BUFFER];
1483 va_list ap;
1485 if ((ti1 == NULL) && (ti2 == NULL) && (pinfo == NULL)) {
1486 return;
1489 va_start(ap, format);
1490 vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1491 va_end(ap);
1493 /* Add to indicated places */
1494 if (pinfo != NULL) {
1495 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1497 if (ti1 != NULL) {
1498 proto_item_append_text(ti1, "%s", info_buffer);
1500 if (ti2 != NULL) {
1501 proto_item_append_text(ti2, "%s", info_buffer);
1505 /* Add section labels (type + PRB range) for C-Plane, U-Plane */
1506 static void
1507 write_section_info(proto_item *section_heading, packet_info *pinfo, proto_item *protocol_item,
1508 uint32_t section_id, uint32_t start_prbx, uint32_t num_prbx, uint32_t rb)
1510 switch (num_prbx) {
1511 case 0:
1512 /* None -> all */
1513 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (all PRBs) ", section_id);
1514 break;
1515 case 1:
1516 /* Single PRB */
1517 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %7u)", section_id, start_prbx);
1518 break;
1519 default:
1520 /* Range */
1521 write_pdu_label_and_info(section_heading, protocol_item, pinfo, ", Id: %4d (PRB: %3u-%3u%s)", section_id, start_prbx,
1522 start_prbx + (num_prbx-1)*(1+rb), rb ? " (every-other)" : "");
1526 static void
1527 write_channel_section_info(proto_item *section_heading, packet_info *pinfo,
1528 uint32_t section_id, uint32_t ueId, uint32_t start_prbx, uint32_t num_prbx,
1529 uint32_t num_trx)
1531 switch (num_prbx) {
1532 case 0:
1533 /* TODO: ?? */
1534 break;
1535 case 1:
1536 /* Single PRB */
1537 write_pdu_label_and_info(section_heading, NULL, pinfo,
1538 ", Id: %4d (UEId=%3u PRB %7u, %2u antennas)",
1539 section_id, ueId, start_prbx, num_trx);
1540 break;
1541 default:
1542 /* Range */
1543 write_pdu_label_and_info(section_heading, NULL, pinfo,
1544 ", Id: %4d (UEId=%3u PRBs %3u-%3u, %2u antennas)",
1545 section_id, ueId, start_prbx, start_prbx+num_prbx-1, num_trx);
1550 /* 5.1.3.2.7 (real time control data / IQ data transfer message series identifier) */
1551 static void
1552 addPcOrRtcid(tvbuff_t *tvb, proto_tree *tree, int *offset, int hf, uint16_t *eAxC)
1554 /* Subtree */
1555 proto_item *oran_pcid_ti = proto_tree_add_item(tree, hf,
1556 tvb, *offset, 2, ENC_NA);
1557 proto_tree *oran_pcid_tree = proto_item_add_subtree(oran_pcid_ti, ett_oran_ecpri_pcid);
1559 uint64_t duPortId, bandSectorId, ccId, ruPortId = 0;
1560 int id_offset = *offset;
1562 /* All parts of eAxC should be above 0, and should total 16 bits (breakdown controlled by preferences) */
1563 if (!((pref_du_port_id_bits > 0) && (pref_bandsector_id_bits > 0) && (pref_cc_id_bits > 0) && (pref_ru_port_id_bits > 0) &&
1564 ((pref_du_port_id_bits + pref_bandsector_id_bits + pref_cc_id_bits + pref_ru_port_id_bits) == 16))) {
1565 expert_add_info(NULL, tree, &ei_oran_invalid_eaxc_bit_width);
1566 *eAxC = 0;
1567 *offset += 2;
1568 return;
1571 unsigned bit_offset = *offset * 8;
1573 /* N.B. For sequence analysis / tapping, just interpret these 2 bytes as eAxC ID... */
1574 *eAxC = tvb_get_uint16(tvb, *offset, ENC_BIG_ENDIAN);
1576 /* DU Port ID */
1577 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);
1578 bit_offset += pref_du_port_id_bits;
1579 /* BandSector ID */
1580 proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_bandsector_id, tvb, bit_offset, pref_bandsector_id_bits, &bandSectorId, ENC_BIG_ENDIAN);
1581 bit_offset += pref_bandsector_id_bits;
1582 /* CC ID */
1583 proto_tree_add_bits_ret_val(oran_pcid_tree, hf_oran_cc_id, tvb, bit_offset, pref_cc_id_bits, &ccId, ENC_BIG_ENDIAN);
1584 bit_offset += pref_cc_id_bits;
1585 /* RU Port ID */
1586 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);
1587 *offset += 2;
1589 proto_item_append_text(oran_pcid_ti, " (DU_Port_ID: %d, BandSector_ID: %d, CC_ID: %d, RU_Port_ID: %d)",
1590 (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1591 char id[16];
1592 snprintf(id, 16, "%x:%x:%x:%x", (int)duPortId, (int)bandSectorId, (int)ccId, (int)ruPortId);
1593 proto_item *pi = proto_tree_add_string(oran_pcid_tree, hf_oran_c_eAxC_ID, tvb, id_offset, 2, id);
1594 proto_item_set_generated(pi);
1597 /* 5.1.3.2.8 ecpriSeqid (message identifier) */
1598 static int
1599 addSeqid(tvbuff_t *tvb, proto_tree *oran_tree, int offset, int plane, uint8_t *seq_id, proto_item **seq_id_ti)
1601 /* Subtree */
1602 proto_item *seqIdItem = proto_tree_add_item(oran_tree, hf_oran_ecpri_seqid, tvb, offset, 2, ENC_NA);
1603 proto_tree *oran_seqid_tree = proto_item_add_subtree(seqIdItem, ett_oran_ecpri_seqid);
1604 uint32_t seqId, subSeqId, e = 0;
1605 /* Sequence ID (8 bits) */
1606 *seq_id_ti = proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_sequence_id, tvb, offset, 1, ENC_NA, &seqId);
1607 *seq_id = seqId;
1608 offset += 1;
1609 /* E bit */
1610 proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_e_bit, tvb, offset, 1, ENC_NA, &e);
1611 /* Subsequence ID (7 bits) */
1612 proto_tree_add_item_ret_uint(oran_seqid_tree, hf_oran_subsequence_id, tvb, offset, 1, ENC_NA, &subSeqId);
1613 offset += 1;
1615 /* radio-transport fragmentation not allowed for C-Plane messages */
1616 if (plane == ORAN_C_PLANE) {
1617 if (e !=1 || subSeqId != 0) {
1618 expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_c_plane);
1621 else {
1622 if (e !=1 || subSeqId != 0) {
1623 /* TODO: Re-assembly of any radio-fragmentation on U-Plane */
1624 expert_add_info(NULL, seqIdItem, &ei_oran_radio_fragmentation_u_plane);
1628 /* Summary */
1629 proto_item_append_text(seqIdItem, " (SeqId: %3d, E: %d, SubSeqId: %d)", seqId, e, subSeqId);
1631 return offset;
1634 /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
1635 static int dissect_bfwCompHdr(tvbuff_t *tvb, proto_tree *tree, int offset,
1636 uint32_t *iq_width, uint32_t *comp_meth, proto_item **comp_meth_ti)
1638 /* Subtree */
1639 proto_item *bfwcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompHdr,
1640 tvb, offset, 1, "",
1641 "bfwCompHdr");
1642 proto_tree *bfwcomphdr_tree = proto_item_add_subtree(bfwcomphdr_ti, ett_oran_bfwcomphdr);
1644 /* Width and method */
1645 proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_iqWidth,
1646 tvb, offset, 1, ENC_BIG_ENDIAN, iq_width);
1647 /* Special case: 0 -> 16 */
1648 *iq_width = (*iq_width==0) ? 16 : *iq_width;
1649 *comp_meth_ti = proto_tree_add_item_ret_uint(bfwcomphdr_tree, hf_oran_bfwCompHdr_compMeth,
1650 tvb, offset, 1, ENC_BIG_ENDIAN, comp_meth);
1651 offset++;
1653 /* Summary */
1654 proto_item_append_text(bfwcomphdr_ti, " (IqWidth=%u, compMeth=%s)",
1655 *iq_width,
1656 val_to_str_const(*comp_meth, bfw_comp_headers_comp_meth, "reserved"));
1658 return offset;
1661 /* 7.7.1.3 bfwCompParam (beamforming weight compression parameter).
1662 * Depends upon passed-in bfwCompMeth (field may be empty) */
1663 static int dissect_bfwCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset,
1664 proto_item *meth_ti, uint32_t bfw_comp_method,
1665 uint32_t *exponent, bool *supported)
1667 if (bfw_comp_method == COMP_NONE) {
1668 /* Absent! */
1669 *supported = true;
1670 return offset;
1673 /* Subtree */
1674 proto_item *bfwcompparam_ti = proto_tree_add_string_format(tree, hf_oran_bfwCompParam,
1675 tvb, offset, 1, "",
1676 "bfwCompParam");
1677 proto_tree *bfwcompparam_tree = proto_item_add_subtree(bfwcompparam_ti, ett_oran_bfwcompparam);
1679 proto_item_append_text(bfwcompparam_ti,
1680 " (meth=%s)", val_to_str_const(bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
1682 *supported = false;
1683 switch (bfw_comp_method) {
1684 case COMP_BLOCK_FP: /* block floating point */
1685 /* 4 reserved bits + exponent */
1686 proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent,
1687 tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
1688 proto_item_append_text(bfwcompparam_ti, " exponent=%u", *exponent);
1689 *supported = true;
1690 offset++;
1691 break;
1692 case COMP_BLOCK_SCALE: /* block scaling */
1693 /* Separate into integer and fractional bits? */
1694 proto_tree_add_item(bfwcompparam_tree, hf_oran_blockScaler,
1695 tvb, offset, 1, ENC_BIG_ENDIAN);
1696 offset++;
1697 break;
1698 case COMP_U_LAW: /* u-law */
1699 /* compBitWidth, compShift */
1700 proto_tree_add_item(bfwcompparam_tree, hf_oran_compBitWidth,
1701 tvb, offset, 1, ENC_BIG_ENDIAN);
1702 proto_tree_add_item(bfwcompparam_tree, hf_oran_compShift,
1703 tvb, offset, 1, ENC_BIG_ENDIAN);
1704 offset++;
1705 break;
1706 case 4: /* beamspace I */
1707 /* TODO: activeBeamspaceCoefficientMask - ceil(K/8) octets */
1708 /* proto_tree_add_item(extension_tree, hf_oran_blockScaler,
1709 tvb, offset, 1, ENC_BIG_ENDIAN);
1710 offset++; */
1711 break;
1712 case 5: /* beamspace II */
1713 /* TODO: activeBeamspaceCoefficientMask - ceil(K/8) octets */
1714 /* reserved (4 bits) + exponent (4 bits)
1715 proto_tree_add_item(bfwcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
1716 proto_tree_add_item_ret_uint(bfwcompparam_tree, hf_oran_exponent, tvb, offset, 1, ENC_BIG_ENDIAN, exponent);
1717 offset += 1;
1719 break;
1721 default:
1722 /* Not handled */
1723 break;
1726 /* Can't go on if compression scheme not supported */
1727 if (!(*supported) && meth_ti) {
1728 expert_add_info_format(pinfo, meth_ti, &ei_oran_unsupported_bfw_compression_method,
1729 "BFW Compression method %u (%s) not decompressed by dissector",
1730 bfw_comp_method,
1731 val_to_str_const(bfw_comp_method, bfw_comp_headers_comp_meth, "reserved"));
1733 return offset;
1737 /* Special case for uncompressed/16-bit value */
1738 static float uncompressed_to_float(uint32_t h)
1740 int16_t i16 = h & 0x0000ffff;
1741 return ((float)i16) / 0x7fff;
1744 /* Decompress I/Q value, taking into account method, width, exponent, other input-specific methods */
1745 /* TODO: pass in info needed for Modulation (reMask, csf, mcScaler values) gleaned from SE 4,5,23 */
1746 static float decompress_value(uint32_t bits, uint32_t comp_method, uint8_t iq_width, uint32_t exponent)
1748 switch (comp_method) {
1749 case COMP_NONE: /* no compression */
1750 return uncompressed_to_float(bits);
1752 case COMP_BLOCK_FP: /* block floating point */
1753 case BFP_AND_SELECTIVE_RE:
1755 /* A.1.2 Block Floating Point Decompression Algorithm */
1756 int32_t cPRB = bits;
1757 uint32_t scaler = 1 << exponent; /* i.e. 2^exponent */
1759 /* Check last bit, in case we need to flip to -ve */
1760 if (cPRB >= (1<<(iq_width-1))) {
1761 cPRB -= (1<<iq_width);
1764 /* Unscale */
1765 cPRB *= scaler;
1766 uint32_t mantissa_scale_factor = (1 << (iq_width-1)) - 1;
1767 uint32_t exp_scale_factor = 1 << (iq_width+4);
1769 float ret = cPRB / ((float)(mantissa_scale_factor*exp_scale_factor));
1770 return ret;
1773 case COMP_BLOCK_SCALE:
1774 case COMP_U_LAW:
1775 /* Not supported! But will be reported as expert info outside of this function! */
1776 return 0.0;
1778 case COMP_MODULATION:
1779 case MOD_COMPR_AND_SELECTIVE_RE:
1780 /* TODO: ! */
1781 return 0.0;
1784 default:
1785 /* Not supported! But will be reported as expert info outside of this function! */
1786 return 0.0;
1790 /* Out-of-range value used for special case */
1791 #define ORPHAN_BUNDLE_NUMBER 999
1793 /* Bundle of PRBs/TRX I/Q samples (ext 11) */
1794 static uint32_t dissect_bfw_bundle(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, unsigned offset,
1795 proto_item *comp_meth_ti, uint32_t bfwcomphdr_comp_meth,
1796 uint32_t num_weights_per_bundle,
1797 uint8_t iq_width,
1798 unsigned bundle_number,
1799 unsigned first_prb, unsigned last_prb, bool is_orphan)
1801 /* Set bundle name */
1802 char bundle_name[32];
1803 if (!is_orphan) {
1804 snprintf(bundle_name, 32, "Bundle %3u", bundle_number);
1806 else {
1807 g_strlcpy(bundle_name, "Orphaned ", 32);
1810 /* Create Bundle root */
1811 proto_item *bundle_ti;
1812 if (first_prb != last_prb) {
1813 bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
1814 tvb, offset, 0, "",
1815 "%s: (PRBs %3u-%3u)",
1816 bundle_name,
1817 first_prb, last_prb);
1819 else {
1820 bundle_ti = proto_tree_add_string_format(tree, hf_oran_bfw_bundle,
1821 tvb, offset, 0, "",
1822 "%s: (PRB %3u)",
1823 bundle_name,
1824 first_prb);
1826 proto_tree *bundle_tree = proto_item_add_subtree(bundle_ti, ett_oran_bfw_bundle);
1828 /* Generated bundle id */
1829 proto_item *bundleid_ti = proto_tree_add_uint(bundle_tree, hf_oran_bfw_bundle_id, tvb, 0, 0,
1830 bundle_number);
1831 proto_item_set_generated(bundleid_ti);
1832 proto_item_set_hidden(bundleid_ti);
1834 /* bfwCompParam */
1835 bool compression_method_supported = false;
1836 unsigned exponent = 0;
1837 offset = dissect_bfwCompParam(tvb, bundle_tree, pinfo, offset, comp_meth_ti,
1838 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
1840 /* Can't show details of unsupported compression method */
1841 if (!compression_method_supported) {
1842 /* Don't know how to show, so give up */
1843 return offset;
1846 /* Create Bundle subtree */
1847 int bit_offset = offset*8;
1848 int bfw_offset;
1849 int prb_offset = offset;
1851 /* contInd */
1852 proto_tree_add_item(bundle_tree, hf_oran_cont_ind,
1853 tvb, offset, 1, ENC_BIG_ENDIAN);
1854 /* beamId */
1855 uint32_t beam_id;
1856 proto_tree_add_item_ret_uint(bundle_tree, hf_oran_beam_id, tvb, offset, 2, ENC_BIG_ENDIAN, &beam_id);
1857 proto_item_append_text(bundle_ti, " (beamId:%u) ", beam_id);
1858 bit_offset += 16;
1860 /* Number of weights per bundle (from preference) */
1861 proto_item *wpb_ti = proto_tree_add_uint(bundle_tree, hf_oran_num_weights_per_bundle, tvb, 0, 0,
1862 num_weights_per_bundle);
1863 proto_item_set_generated(wpb_ti);
1865 /* Add the weights for this bundle */
1866 for (unsigned w=0; w < num_weights_per_bundle; w++) {
1868 /* Create subtree */
1869 bfw_offset = bit_offset / 8;
1870 uint8_t bfw_extent = ((bit_offset + (iq_width*2)) / 8) - bfw_offset;
1871 proto_item *bfw_ti = proto_tree_add_string_format(bundle_tree, hf_oran_bfw,
1872 tvb, bfw_offset, bfw_extent,
1873 "", "TRX %3u: (", w);
1874 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
1876 /* I */
1877 /* Get bits, and convert to float. */
1878 uint32_t bits = tvb_get_bits(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
1879 float value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width, exponent);
1880 /* Add to tree. */
1881 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);
1882 bit_offset += iq_width;
1883 proto_item_append_text(bfw_ti, "I%u=%f ", w, value);
1885 /* Q */
1886 /* Get bits, and convert to float. */
1887 bits = tvb_get_bits(tvb, bit_offset, iq_width, ENC_BIG_ENDIAN);
1888 value = decompress_value(bits, bfwcomphdr_comp_meth, iq_width, exponent);
1889 /* Add to tree. */
1890 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);
1891 bit_offset += iq_width;
1892 proto_item_append_text(bfw_ti, "Q%u=%f)", w, value);
1895 /* Set extent of bundle */
1896 proto_item_set_len(bundle_ti, (bit_offset+7)/8 - prb_offset);
1898 return (bit_offset+7)/8;
1901 /* Return new bit offset. in/out will always be byte-aligned.. */
1902 static int dissect_ciCompParam(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo _U_, unsigned bit_offset,
1903 unsigned comp_meth, uint8_t *exponent)
1905 if (comp_meth == COMP_NONE) {
1906 /* Nothing in frame so don't even create subtree */
1907 return bit_offset;
1910 /* Subtree */
1911 proto_item *cicompparam_ti = proto_tree_add_string_format(tree, hf_oran_ciCompParam,
1912 tvb, bit_offset/8, 1, "",
1913 "ciCompParam");
1914 proto_tree *cicompparam_tree = proto_item_add_subtree(cicompparam_ti, ett_oran_cicompparam);
1915 uint32_t ci_exponent;
1917 /* Contents differ by compression method */
1918 switch (comp_meth) {
1919 case COMP_BLOCK_FP:
1920 proto_tree_add_item(cicompparam_tree, hf_oran_reserved_4bits, tvb, bit_offset/8, 1, ENC_NA);
1921 proto_tree_add_item_ret_uint(cicompparam_tree, hf_oran_exponent,
1922 tvb, bit_offset/8, 1, ENC_BIG_ENDIAN, &ci_exponent);
1923 *exponent = ci_exponent;
1924 proto_item_append_text(cicompparam_ti, " (Exponent=%u)", ci_exponent);
1925 bit_offset += 8; /* one byte */
1926 break;
1927 case COMP_BLOCK_SCALE:
1928 /* Separate into integer and fractional bits? */
1929 proto_tree_add_item(cicompparam_tree, hf_oran_blockScaler,
1930 tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
1931 bit_offset += 8;
1932 break;
1933 case COMP_U_LAW:
1934 /* compBitWidth, compShift */
1935 proto_tree_add_item(cicompparam_tree, hf_oran_compBitWidth,
1936 tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
1937 proto_tree_add_item(cicompparam_tree, hf_oran_compShift,
1938 tvb, bit_offset/8, 1, ENC_BIG_ENDIAN);
1939 bit_offset += 8;
1940 break;
1942 default:
1943 /* reserved, ? bytes of zeros.. */
1944 break;
1947 return bit_offset;
1950 /* frameStructure (7.5.2.13) */
1951 static unsigned dissect_frame_structure(proto_item *tree, tvbuff_t *tvb, unsigned offset,
1952 uint32_t subframeId, uint32_t slotId)
1954 uint32_t scs;
1955 /* FFT Size (4 bits) */
1956 proto_tree_add_item(tree, hf_oran_frameStructure_fft, tvb, offset, 1, ENC_NA);
1957 /* Subcarrier spacing (SCS) */
1958 proto_tree_add_item_ret_uint(tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
1960 /* Show slot within frame as a generated field. See table 7.5.13-3 */
1961 uint32_t slots_per_subframe = 1;
1962 if (scs <= 4) {
1963 slots_per_subframe = 1 << scs;
1965 if (scs <= 4 || scs >= 12) {
1966 proto_item *ti = proto_tree_add_uint(tree, hf_oran_slot_within_frame, tvb, 0, 0,
1967 (slots_per_subframe*subframeId) + slotId);
1968 proto_item_set_generated(ti);
1970 return offset + 1;
1973 static unsigned dissect_csf(proto_item *tree, tvbuff_t *tvb, unsigned bit_offset,
1974 unsigned iq_width, bool *p_csf)
1976 proto_item *csf_ti;
1977 uint64_t csf;
1978 csf_ti = proto_tree_add_bits_ret_val(tree, hf_oran_csf, tvb, bit_offset, 1, &csf, ENC_BIG_ENDIAN);
1979 if (csf) {
1980 /* Table 7.7.4.2-1 Constellation shift definition (index is udIqWidth) */
1981 const char* shift_value[] = { "n/a", "1/2", "1/4", "1/8", "1/16", "1/32" };
1982 if (iq_width >=1 && iq_width <= 5) {
1983 proto_item_append_text(csf_ti, " (Shift Value is %s)", shift_value[iq_width]);
1987 /* Set out parameter */
1988 if (p_csf != NULL) {
1989 *p_csf = (csf!=0);
1991 return bit_offset+1;
1995 /* Section 7.
1996 * N.B. these are the green parts of the tables showing Section Types, differing by section Type */
1997 static int dissect_oran_c_section(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo,
1998 flow_state_t* state,
1999 uint32_t sectionType, oran_tap_info *tap_info, proto_item *protocol_item,
2000 uint32_t subframeId, uint32_t slotId,
2001 uint8_t ci_iq_width, uint8_t ci_comp_meth, unsigned ci_comp_opt,
2002 unsigned num_sinr_per_prb)
2004 unsigned offset = 0;
2005 proto_tree *c_section_tree = NULL;
2006 proto_item *sectionHeading = NULL;
2008 /* Section subtree */
2009 sectionHeading = proto_tree_add_string_format(tree, hf_oran_c_section,
2010 tvb, offset, 0, "", "Section");
2011 c_section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section);
2013 uint32_t sectionId = 0;
2015 uint32_t startPrbc=0, startPrbu=0;
2016 uint32_t numPrbc=0, numPrbu=0;
2017 uint32_t ueId = 0;
2018 proto_item *ueId_ti = NULL;
2019 uint32_t beamId = 0;
2020 proto_item *beamId_ti = NULL;
2021 bool beamId_ignored = false;
2023 proto_item *numprbc_ti = NULL;
2025 /* Config affecting ext11 bundles (initially unset) */
2026 ext11_settings_t ext11_settings;
2027 memset(&ext11_settings, 0, sizeof(ext11_settings));
2029 bool extension_flag = false;
2031 /* These sections (ST0, ST1, ST2, ST3, ST5, ST9) are similar, so handle as common with per-type differences */
2032 if (((sectionType <= SEC_C_UE_SCHED) || (sectionType >= SEC_C_SINR_REPORTING)) &&
2033 (sectionType != SEC_C_SLOT_CONTROL)) {
2035 /* sectionID */
2036 proto_item *ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
2037 if (sectionId == 4095) {
2038 proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
2040 offset++;
2042 /* rb */
2043 uint32_t rb;
2044 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
2045 /* symInc (1 bit) */
2046 if (sectionType != SEC_C_RRM_MEAS_REPORTS && /* Section Type 10 */
2047 sectionType != SEC_C_REQUEST_RRM_MEAS) { /* Section Type 11 */
2048 unsigned int sym_inc;
2049 proto_item *sym_inc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA, &sym_inc);
2050 if (sym_inc !=0 && (sectionType == SEC_C_SINR_REPORTING)) { /* Section Type 9 */
2051 /* "0 shall be used" */
2052 proto_item_append_text(sym_inc_ti, " (should be 0)");
2055 else {
2056 /* reserved (1 bit) */
2057 proto_tree_add_item(c_section_tree, hf_oran_reserved_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
2060 /* startPrbx and numPrbx */
2061 if (sectionType == SEC_C_SINR_REPORTING) {
2062 /* startPrbu (10 bits) */
2063 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
2064 offset += 2;
2065 /* numPrbu */
2066 numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
2067 if (numPrbu == 0) {
2068 proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
2069 numPrbu = pref_data_plane_section_total_rbs;
2071 offset += 1;
2073 else {
2074 /* startPrbc (10 bits) */
2075 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
2076 offset += 2;
2077 /* numPrbc */
2078 numprbc_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
2079 if (numPrbc == 0) {
2080 proto_item_append_text(numprbc_ti, " (all PRBs - configured as %u)", pref_data_plane_section_total_rbs);
2082 offset += 1;
2085 if (sectionType != SEC_C_SINR_REPORTING) {
2086 static int * const remask_flags[] = {
2087 &hf_oran_reMask_re1,
2088 &hf_oran_reMask_re2,
2089 &hf_oran_reMask_re3,
2090 &hf_oran_reMask_re4,
2091 &hf_oran_reMask_re5,
2092 &hf_oran_reMask_re6,
2093 &hf_oran_reMask_re7,
2094 &hf_oran_reMask_re8,
2095 &hf_oran_reMask_re9,
2096 &hf_oran_reMask_re10,
2097 &hf_oran_reMask_re11,
2098 &hf_oran_reMask_re12,
2099 NULL
2102 /* reMask */
2103 uint64_t remask;
2104 proto_tree_add_bitmask_ret_uint64(c_section_tree, tvb, offset,
2105 hf_oran_reMask, ett_oran_remask, remask_flags, ENC_BIG_ENDIAN, &remask);
2106 offset++;
2107 /* numSymbol */
2108 uint32_t numSymbol;
2109 proto_item *numsymbol_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numSymbol, tvb, offset, 1, ENC_NA, &numSymbol);
2110 if ((sectionType == SEC_C_RRM_MEAS_REPORTS) && (numSymbol != 14)) {
2111 proto_item_append_text(numsymbol_ti, " (for ST10, should be 14!)");
2112 expert_add_info_format(pinfo, numsymbol_ti, &ei_oran_st10_numsymbol_not_14,
2113 "numSymbol should be 14 for ST10 - found %u", numSymbol);
2115 offset++;
2117 /* [ef] (extension flag) */
2118 switch (sectionType) {
2119 case SEC_C_UNUSED_RB: /* Section Type 0 */
2120 case SEC_C_NORMAL: /* Section Type 1 */
2121 case SEC_C_PRACH: /* Section Type 3 */
2122 case SEC_C_UE_SCHED: /* Section Type 5 */
2123 case SEC_C_RRM_MEAS_REPORTS: /* Section Type 10 */
2124 case SEC_C_REQUEST_RRM_MEAS: /* Section Type 11 */
2125 proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2126 break;
2127 default:
2128 /* Other section types don't support extensions */
2129 break;
2132 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbc, numPrbc, rb);
2133 proto_item_append_text(sectionHeading, ", Symbols: %2u", numSymbol);
2135 if (numPrbc == 0) {
2136 /* Special case for all PRBs */
2137 numPrbc = pref_data_plane_section_total_rbs;
2138 startPrbc = 0; /* may already be 0... */
2141 else {
2142 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
2143 proto_item_append_text(sectionHeading, ", numSinrPerPrb: %2u", num_sinr_per_prb);
2146 /* Section type specific fields (after 'numSymbol') */
2147 switch (sectionType) {
2148 case SEC_C_UNUSED_RB: /* Section Type 0 - Table 7.4.2-1 */
2149 /* reserved (15 bits) */
2150 proto_tree_add_item(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2, ENC_NA);
2151 offset += 2;
2152 break;
2154 case SEC_C_NORMAL: /* Section Type 1 - Table 7.4.3-1 */
2155 /* beamId */
2156 beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
2157 offset += 2;
2159 proto_item_append_text(sectionHeading, ", BeamId: %d", beamId);
2160 break;
2162 case SEC_C_PRACH: /* Section Type 3 - Table 7.4.5-1 */
2164 /* beamId */
2165 beamId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
2166 offset += 2;
2168 /* freqOffset */
2169 int32_t freqOffset; /* Yes, this is signed, so the implicit cast is intentional. */
2170 proto_item *freq_offset_item = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN, &freqOffset);
2171 freqOffset |= 0xff000000; /* Must sign-extend */
2172 proto_item_set_text(freq_offset_item, "Frequency offset: %d \u0394f", freqOffset);
2173 offset += 3;
2175 /* reserved */
2176 proto_tree_add_item(c_section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
2177 offset += 1;
2179 proto_item_append_text(sectionHeading, ", BeamId: %d, FreqOffset: %d \u0394f", beamId, freqOffset);
2180 break;
2183 case SEC_C_UE_SCHED: /* Section Type 5 - Table 7.4.7-1 */
2184 case SEC_C_RRM_MEAS_REPORTS: /* Section Type 10 - Table 7.4.12-1 */
2185 /* ueId */
2186 ueId_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_NA, &ueId);
2187 offset += 2;
2188 if (ueId == 0x7fff) {
2189 proto_item_append_text(ueId_ti, " (PRBs not scheduled for eAxC ID in transport header)");
2192 proto_item_append_text(sectionHeading, ", UEId: %d", ueId);
2193 break;
2195 case SEC_C_SINR_REPORTING: /* Section Type 9 - SINR Reporting */
2197 /* Hidden filter for bf (DMFS-BF) */
2198 proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2199 PROTO_ITEM_SET_HIDDEN(bf_ti);
2201 unsigned bit_offset = offset*8;
2203 for (unsigned prb=0; prb < numPrbu; prb++) {
2204 /* TODO: create a subtree for each PRB entry with good summary? */
2206 /* Each prb starts byte-aligned */
2207 bit_offset = ((bit_offset+7)/8) * 8;
2209 /* N.B., using width/method from UL U-plane preferences, not certain that this is correct.. */
2211 /* sinrCompParam */
2212 uint32_t exponent = 0; /* N.B. init to silence warnings, but will always be set if read in COMP_BLOCK_FP case */
2213 uint16_t sReSMask;
2214 bit_offset = dissect_udcompparam(tvb, pinfo, c_section_tree, bit_offset/8,
2215 pref_iqCompressionUplink, &exponent, &sReSMask,
2216 true) * 8; /* last param is for_sinr */
2218 /* sinrValues for this PRB. TODO: subtree for each PRB? */
2219 /* TODO: not sure how numSinrPerPrb interacts with rb==1... */
2220 for (unsigned n=0; n < num_sinr_per_prb; n++) {
2221 unsigned sinr_bits = tvb_get_bits(tvb, bit_offset, pref_sample_bit_width_uplink, ENC_BIG_ENDIAN);
2223 /* TODO: using uplink compression settings from preferences. This isn't right.. */
2224 float value = decompress_value(sinr_bits, pref_iqCompressionUplink, pref_sample_bit_width_uplink, exponent);
2225 unsigned sample_len_in_bytes = ((bit_offset%8)+pref_sample_bit_width_uplink+7)/8;
2226 proto_item *val_ti = proto_tree_add_float(c_section_tree, hf_oran_sinr_value, tvb,
2227 bit_offset/8, sample_len_in_bytes, value);
2228 /* Show here which subcarriers share which values (they all divide 12..) */
2229 proto_item_append_text(val_ti, " (PRB=%u, subcarriers %u-%u)",
2230 startPrbu+(prb*(rb+1)),
2231 n*(12/num_sinr_per_prb), (n+1)*(12/num_sinr_per_prb)-1);
2233 bit_offset += pref_sample_bit_width_uplink;
2236 offset = (bit_offset+7)/8;
2237 break;
2239 case SEC_C_REQUEST_RRM_MEAS: /* Section Type 11 - Request RRM Measurements */
2240 /* Reserved (15 bits) */
2241 proto_tree_add_item(c_section_tree, hf_oran_reserved_15bits, tvb, offset, 2, ENC_NA);
2242 offset += 2;
2243 break;
2245 default:
2246 break;
2249 else if (sectionType == SEC_C_CH_INFO) { /* Section Type 6 */
2250 /* ef */
2251 proto_tree_add_item_ret_boolean(c_section_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2252 /* ueId */
2253 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_ueId, tvb, offset, 2, ENC_NA, &ueId);
2254 offset += 2;
2255 /* regularizationFactor */
2256 proto_tree_add_item(c_section_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_NA);
2257 offset += 2;
2258 /* reserved (4 bits) */
2259 proto_tree_add_item(c_section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
2260 /* rb ("Value=0 shall be set") */
2261 uint32_t rb;
2262 proto_item *rb_ti = proto_tree_add_item_ret_uint(c_section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
2263 if (rb != 0) {
2264 proto_item_append_text(rb_ti, " (should be set to 0)");
2265 expert_add_info(pinfo, rb_ti, &ei_oran_st6_rb_shall_be_0);
2267 /* symInc */
2268 proto_tree_add_item(c_section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
2269 /* startPrbc */
2270 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_startPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbc);
2271 offset += 2;
2272 /* numPrbc */
2273 proto_tree_add_item_ret_uint(c_section_tree, hf_oran_numPrbc, tvb, offset, 1, ENC_NA, &numPrbc);
2274 offset += 1;
2276 /* Hidden filter for bf */
2277 proto_item *bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2278 PROTO_ITEM_SET_HIDDEN(bf_ti);
2280 /* ciIsample,ciQsample pairs */
2281 unsigned m;
2282 unsigned prb;
2283 uint32_t bit_offset = offset*8;
2285 /* Antenna count from preference */
2286 unsigned num_trx = pref_num_bf_antennas;
2288 write_channel_section_info(sectionHeading, pinfo,
2289 sectionId, ueId, startPrbc, numPrbc, num_trx);
2291 bool first_prb = true;
2292 uint8_t exponent = 0;
2293 for (prb=startPrbc; prb < startPrbc+numPrbc; prb++) {
2295 /* PRB subtree */
2296 unsigned prb_start_offset = bit_offset;
2297 proto_item *prb_ti = proto_tree_add_string_format(c_section_tree, hf_oran_samples_prb,
2298 tvb, bit_offset/8, 0,
2299 "", "PRB=%u", prb);
2300 proto_tree *prb_tree = proto_item_add_subtree(prb_ti, ett_oran_prb_cisamples);
2302 /* There may be a ciCompParam here.. */
2303 if (first_prb || ci_comp_opt==1) {
2304 bit_offset = dissect_ciCompParam(tvb, prb_tree, pinfo, bit_offset, ci_comp_meth, &exponent);
2306 first_prb = false;
2308 /* Antennas */
2309 for (m=0; m < num_trx; m++) {
2311 unsigned sample_offset = bit_offset / 8;
2312 uint8_t sample_extent = ((bit_offset + (ci_iq_width*2)) / 8) - sample_offset;
2314 /* Create subtree for antenna */
2315 proto_item *sample_ti = proto_tree_add_string_format(prb_tree, hf_oran_ciSample,
2316 tvb, sample_offset, sample_extent,
2317 "", "TRX=%2u: ", m);
2318 proto_tree *sample_tree = proto_item_add_subtree(sample_ti, ett_oran_cisample);
2320 /* I */
2321 /* Get bits, and convert to float. */
2322 uint32_t bits = tvb_get_bits(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2323 float value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent);
2325 /* Add to tree. */
2326 proto_tree_add_float_format_value(sample_tree, hf_oran_ciIsample, tvb, bit_offset/8, (16+7)/8, value, "#%u=%f", m, value);
2327 bit_offset += ci_iq_width;
2328 proto_item_append_text(sample_ti, "I%u=%f ", m, value);
2330 /* Q */
2331 /* Get bits, and convert to float. */
2332 bits = tvb_get_bits(tvb, bit_offset, ci_iq_width, ENC_BIG_ENDIAN);
2333 value = decompress_value(bits, ci_comp_meth, ci_iq_width, exponent);
2335 /* Add to tree. */
2336 proto_tree_add_float_format_value(sample_tree, hf_oran_ciQsample, tvb, bit_offset/8, (16+7)/8, value, "#%u=%f", m, value);
2337 bit_offset += ci_iq_width;
2338 proto_item_append_text(sample_ti, "Q%u=%f ", m, value);
2340 proto_item_set_len(prb_ti, (bit_offset-prb_start_offset)/8);
2342 offset = (bit_offset/8);
2345 bool seen_se10 = false;
2346 uint32_t numPortc = 0;
2347 proto_item *bf_ti = NULL;
2349 /* Section extension commands */
2350 while (extension_flag) {
2352 int extension_start_offset = offset;
2354 /* Prefetch extType so can use specific extension type ett */
2355 uint32_t exttype = tvb_get_uint8(tvb, offset) & 0x7f;
2356 uint32_t exttype_ett_index = exttype;
2357 if (exttype == 0 || exttype > HIGHEST_EXTTYPE) {
2358 /* Just use first one if out of range */
2359 exttype_ett_index = 1;
2362 /* Create subtree for each extension (with summary) */
2363 proto_item *extension_ti = proto_tree_add_string_format(c_section_tree, hf_oran_extension,
2364 tvb, offset, 0, "", "Extension");
2365 proto_tree *extension_tree = proto_item_add_subtree(extension_ti, ett_oran_c_section_extension[exttype_ett_index-1]);
2367 /* ef (i.e. another extension after this one?) */
2368 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_ef, tvb, offset, 1, ENC_BIG_ENDIAN, &extension_flag);
2370 /* extType */
2371 proto_item *exttype_ti;
2372 exttype_ti = proto_tree_add_item(extension_tree, hf_oran_exttype, tvb, offset, 1, ENC_BIG_ENDIAN);
2373 offset++;
2374 proto_item_append_text(sectionHeading, " (ext-%u)", exttype);
2376 proto_item_append_text(extension_ti, " (ext-%u: %s)", exttype, val_to_str_const(exttype, exttype_vals, "Reserved"));
2378 /* Don't tap if out of range. */
2379 if (exttype > 0 && exttype <= HIGHEST_EXTTYPE) {
2380 tap_info->extensions[exttype] = true;
2383 /* Is this SE allowed for this section type? */
2384 if (!se_allowed_in_st(exttype, sectionType)) {
2385 expert_add_info_format(pinfo, extension_tree, &ei_oran_se_on_unsupported_st,
2386 "SE %u (%s) should not appear in ST %u (%s)!",
2387 exttype, val_to_str_const(exttype, exttype_vals, "Reserved"),
2388 sectionType, rval_to_str_const(sectionType, section_types, "Unknown"));
2392 /* extLen (number of 32-bit words) */
2393 uint32_t extlen_len = ((exttype==11)||(exttype==19)||(exttype==20)) ? 2 : 1; /* Extensions 11/19/20 are special */
2394 uint32_t extlen;
2395 proto_item *extlen_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_extlen, tvb,
2396 offset, extlen_len, ENC_BIG_ENDIAN, &extlen);
2397 proto_item_append_text(extlen_ti, " (%u bytes)", extlen*4);
2398 offset += extlen_len;
2399 if (extlen == 0) {
2400 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_zero,
2401 "extlen value of 0 is reserved");
2402 /* Break out to avoid infinitely looping! */
2403 break;
2406 bool ext_unhandled = false;
2408 switch (exttype) {
2410 case 1: /* SE 1: Beamforming Weights */
2412 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
2413 proto_item *comp_meth_ti = NULL;
2415 /* Hidden filter for bf */
2416 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2417 PROTO_ITEM_SET_HIDDEN(bf_ti);
2419 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
2420 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
2421 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
2423 /* bfwCompParam */
2424 uint32_t exponent = 0;
2425 bool compression_method_supported = false;
2426 offset = dissect_bfwCompParam(tvb, extension_tree, pinfo, offset, comp_meth_ti,
2427 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
2429 /* Can't show details of unsupported compression method */
2430 if (!compression_method_supported) {
2431 break;
2434 /* We know:
2435 - iq_width (above)
2436 - numBfWeights (taken from preference)
2437 - remaining bytes in extension
2438 We can therefore derive TRX (number of antennas).
2441 /* I & Q samples
2442 Don't know how many there will be, so just fill available bytes...
2444 unsigned weights_bytes = (extlen*4)-3;
2445 unsigned num_weights_pairs = (weights_bytes*8) / (bfwcomphdr_iq_width*2);
2446 unsigned num_trx = num_weights_pairs;
2447 int bit_offset = offset*8;
2449 for (unsigned n=0; n < num_trx; n++) {
2450 /* Create antenna subtree */
2451 int bfw_offset = bit_offset / 8;
2452 proto_item *bfw_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfw,
2453 tvb, bfw_offset, 0, "", "TRX %3u: (", n);
2454 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
2456 /* I value */
2457 /* Get bits, and convert to float. */
2458 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
2459 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
2460 /* Add to tree. */
2461 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
2462 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
2463 bit_offset += bfwcomphdr_iq_width;
2464 proto_item_append_text(bfw_ti, "I=%f ", value);
2466 /* Leave a gap between I and Q values */
2467 proto_item_append_text(bfw_ti, " ");
2469 /* Q value */
2470 /* Get bits, and convert to float. */
2471 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
2472 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
2473 /* Add to tree. */
2474 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
2475 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
2476 bit_offset += bfwcomphdr_iq_width;
2477 proto_item_append_text(bfw_ti, "Q=%f", value);
2479 proto_item_append_text(bfw_ti, ")");
2480 proto_item_set_len(bfw_ti, (bit_offset+7)/8 - bfw_offset);
2482 /* Need to round to next byte */
2483 offset = (bit_offset+7)/8;
2485 break;
2488 case 2: /* SE 2: Beamforming attributes */
2490 /* Hidden filter for bf */
2491 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2492 PROTO_ITEM_SET_HIDDEN(bf_ti);
2494 /* bfaCompHdr (get widths of fields to follow) */
2495 uint32_t bfAzPtWidth, bfZePtWidth, bfAz3ddWidth, bfZe3ddWidth;
2496 /* subtree */
2497 proto_item *bfa_ti = proto_tree_add_string_format(extension_tree, hf_oran_bfaCompHdr,
2498 tvb, offset, 2, "", "bfaCompHdr");
2499 proto_tree *bfa_tree = proto_item_add_subtree(bfa_ti, ett_oran_bfacomphdr);
2501 /* reserved (2 bits) */
2502 proto_tree_add_item(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2503 /* bfAzPtWidth (3 bits) */
2504 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAzPtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAzPtWidth);
2505 /* bfZePtWidth (3 bits) */
2506 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZePtWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZePtWidth);
2507 offset += 1;
2509 /* reserved (2 bits) */
2510 proto_tree_add_item(bfa_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2511 /* bfAz3ddWidth (3 bits) */
2512 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfAz3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfAz3ddWidth);
2513 /* bfZe3ddWidth (3 bits) */
2514 proto_tree_add_item_ret_uint(bfa_tree, hf_oran_bfZe3ddWidth, tvb, offset, 1, ENC_BIG_ENDIAN, &bfZe3ddWidth);
2515 offset += 1;
2517 unsigned bit_offset = offset*8;
2519 /* bfAzPt */
2520 if (bfAzPtWidth > 0) {
2521 proto_tree_add_bits_item(extension_tree, hf_oran_bfAzPt, tvb, bit_offset, bfAzPtWidth+1, ENC_BIG_ENDIAN);
2522 bit_offset += (bfAzPtWidth+1);
2524 /* bfZePt */
2525 if (bfZePtWidth > 0) {
2526 proto_tree_add_bits_item(extension_tree, hf_oran_bfZePt, tvb, bit_offset, bfZePtWidth+1, ENC_BIG_ENDIAN);
2527 bit_offset += (bfZePtWidth+1);
2529 /* bfAz3dd */
2530 if (bfAz3ddWidth > 0) {
2531 proto_tree_add_bits_item(extension_tree, hf_oran_bfAz3dd, tvb, bit_offset, bfAz3ddWidth+1, ENC_BIG_ENDIAN);
2532 bit_offset += (bfAz3ddWidth+1);
2534 /* bfZe3dd */
2535 if (bfZe3ddWidth > 0) {
2536 proto_tree_add_bits_item(extension_tree, hf_oran_bfZe3dd, tvb, bit_offset, bfZe3ddWidth+1, ENC_BIG_ENDIAN);
2537 bit_offset += (bfZe3ddWidth+1);
2540 /* Pad to next byte (unless last 2 fields already fit in this one) */
2541 if ((bit_offset % 8) > 2) {
2542 offset = (bit_offset+7) / 8;
2544 else {
2545 offset = bit_offset / 8;
2548 /* bfAzSl (3 bits) */
2549 proto_tree_add_item(extension_tree, hf_oran_bfAzSl, tvb, offset, 1, ENC_BIG_ENDIAN);
2550 /* bfZeSl (3 bits) */
2551 proto_tree_add_item(extension_tree, hf_oran_bfZeSl, tvb, offset, 1, ENC_BIG_ENDIAN);
2552 offset += 1;
2553 break;
2556 case 3: /* SE 3: TODO: DL precoding parameters */
2558 /* codebookindex (8 bits) */
2559 /* "This parameter is not used and shall be set to zero." */
2560 proto_tree_add_item(extension_tree, hf_oran_codebook_index, tvb, offset, 1, ENC_BIG_ENDIAN);
2561 offset += 1;
2562 /* layerid */
2563 uint32_t layerid;
2564 proto_tree_add_item_ret_uint(extension_tree, hf_oran_layerid, tvb, offset, 1, ENC_BIG_ENDIAN, &layerid);
2565 /* numLayers */
2566 proto_tree_add_item(extension_tree, hf_oran_numlayers, tvb, offset, 1, ENC_BIG_ENDIAN);
2567 offset += 1;
2569 /* Stop here for non-first data layer */
2570 if (layerid != 0 && layerid != 0xf) {
2571 break;
2574 /* First data layer case */
2575 /* txScheme */
2576 proto_tree_add_item(extension_tree, hf_oran_txscheme, tvb, offset, 1, ENC_BIG_ENDIAN);
2577 /* crsReMask */
2578 proto_tree_add_item(extension_tree, hf_oran_crs_remask, tvb, offset, 2, ENC_BIG_ENDIAN);
2579 offset += 2;
2581 /* crsShift (1 bit) */
2582 proto_tree_add_item(extension_tree, hf_oran_crs_shift, tvb, offset, 1, ENC_BIG_ENDIAN);
2583 /* reserved (3 bits) */
2584 proto_tree_add_item(extension_tree, hf_oran_reserved_bits123, tvb, offset, 1, ENC_BIG_ENDIAN);
2585 /* crsSymNum (4 bits) */
2586 proto_tree_add_item(extension_tree, hf_oran_crs_symnum, tvb, offset, 1, ENC_BIG_ENDIAN);
2587 offset += 1;
2588 /* reserved */
2589 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2590 offset += 1;
2592 /* reserved (1 bit) */
2593 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2594 /* beamIdAP1 (15 bits) */
2595 proto_tree_add_item(extension_tree, hf_oran_beamid_ap1, tvb, offset, 2, ENC_BIG_ENDIAN);
2596 offset += 2;
2597 /* reserved (1 bit) */
2598 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2599 /* beamIdAP2 (15 bits) */
2600 proto_tree_add_item(extension_tree, hf_oran_beamid_ap2, tvb, offset, 2, ENC_BIG_ENDIAN);
2601 offset += 2;
2602 /* reserved (1 bit) */
2603 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2604 /* beamIdAP3 (15 bits) */
2605 proto_tree_add_item(extension_tree, hf_oran_beamid_ap3, tvb, offset, 2, ENC_BIG_ENDIAN);
2606 offset += 2;
2607 break;
2610 case 4: /* SE 4: Modulation compression params (5.4.7.4) */
2612 /* csf */
2613 dissect_csf(extension_tree, tvb, offset*8, ci_iq_width, NULL);
2615 /* modCompScaler */
2616 uint32_t modCompScaler;
2617 proto_item *ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_modcompscaler,
2618 tvb, offset, 2, ENC_BIG_ENDIAN, &modCompScaler);
2619 offset += 2;
2621 /* Work out and show floating point value too. exponent and mantissa are both unsigned */
2622 uint16_t exponent = (modCompScaler >> 11) & 0x000f; /* m.s. 4 bits */
2623 uint16_t mantissa = modCompScaler & 0x07ff; /* l.s. 11 bits */
2624 double value = ((double)mantissa/(1<<11)) * (1.0 / (1 << exponent));
2625 proto_item_append_text(ti, " (%f)", value);
2627 /* TODO: need to store these in per-section data in state that gets looked up by U-Plane */
2628 break;
2631 case 5: /* SE 5: Modulation Compression Additional Parameters (7.7.5) */
2633 /* Applies only to section types 1,3 and 5 */
2634 /* N.B. there may be multiple instances of this SE in the same frame */
2636 /* There may be one or 2 entries, depending upon extlen */
2637 int sets = 1, reserved_bits = 0;
2638 switch (extlen) {
2639 case 2:
2640 sets = 1;
2641 reserved_bits = 20;
2642 break;
2643 case 3:
2644 sets = 2;
2645 reserved_bits = 24;
2646 break;
2647 case 4:
2648 /* sets can be 3 or 4, depending upon whether last 28 bits are 0.. */
2649 if ((tvb_get_ntohl(tvb, offset+10) & 0x0fffffff) == 0) {
2650 sets = 3;
2651 reserved_bits = 28;
2653 else {
2654 sets = 4;
2655 reserved_bits = 0;
2657 break;
2659 default:
2660 /* Malformed error!!! */
2661 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
2662 "For section 5, extlen must be 2, 3 or 4, but %u was dissected",
2663 extlen);
2664 break;
2667 unsigned bit_offset = offset*8;
2669 for (int n=0; n < sets; n++) {
2670 /* Subtree for each set */
2671 unsigned set_start_offset = bit_offset/8;
2672 proto_item *set_ti = proto_tree_add_string(extension_tree, hf_oran_modcomp_param_set,
2673 tvb, set_start_offset, 0, "");
2674 proto_tree *set_tree = proto_item_add_subtree(set_ti, ett_oran_modcomp_param_set);
2676 uint64_t mcScaleReMask, mcScaleOffset;
2677 bool csf;
2679 /* mcScaleReMask (12 bits) */
2680 proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_re_mask, tvb, bit_offset, 12, &mcScaleReMask, ENC_BIG_ENDIAN);
2681 bit_offset += 12;
2682 /* csf (1 bit) */
2683 bit_offset = dissect_csf(set_tree, tvb, bit_offset, ci_iq_width, &csf);
2684 /* mcScaleOffset (15 bits) */
2685 proto_item *ti = proto_tree_add_bits_ret_val(set_tree, hf_oran_mc_scale_offset, tvb, bit_offset, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
2686 uint16_t exponent = (mcScaleOffset >> 11) & 0x000f; /* m.s. 4 bits */
2687 uint16_t mantissa = mcScaleOffset & 0x07ff; /* l.s. 11 bits */
2688 double mcScaleOffset_value = ((double)mantissa/(1<<11)) * (1.0 / (1 << exponent));
2689 proto_item_append_text(ti, " (%f)", mcScaleOffset_value);
2690 bit_offset += 15;
2692 /* Summary */
2693 proto_item_set_len(set_ti, (bit_offset+7)/8 - set_start_offset);
2694 proto_item_append_text(set_ti, " (mcScaleReMask=0x%03x csf=%5s mcScaleOffset=%f)",
2695 (unsigned)mcScaleReMask, tfs_get_true_false(csf), mcScaleOffset_value);
2698 proto_item_append_text(extension_ti, " (%u sets)", sets);
2700 /* Reserved (variable-length) */
2701 if (reserved_bits) {
2702 proto_tree_add_bits_item(extension_tree, hf_oran_reserved, tvb, bit_offset, reserved_bits, ENC_BIG_ENDIAN);
2703 bit_offset += reserved_bits;
2706 offset = bit_offset/8;
2707 break;
2710 case 6: /* SE 6: Non-contiguous PRB allocation in time and frequency domain */
2712 /* Update ext6 recorded info */
2713 ext11_settings.ext6_set = true;
2715 /* repetition */
2716 proto_tree_add_bits_item(extension_tree, hf_oran_repetition, tvb, offset*8, 1, ENC_BIG_ENDIAN);
2717 /* rbgSize (PRBs per bit set in rbgMask) */
2718 uint32_t rbgSize;
2719 proto_item *rbg_size_ti;
2720 rbg_size_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgSize);
2721 if (rbgSize == 0) {
2722 /* N.B. this is only true if "se6-rb-bit-supported" is set... */
2723 expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_rbg_size_reserved,
2724 "rbgSize value of 0 is reserved");
2726 /* rbgMask (28 bits) */
2727 uint32_t rbgMask;
2728 proto_item *rbgmask_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN, &rbgMask);
2729 if (rbgSize == 0) {
2730 proto_item_append_text(rbgmask_ti, " (value ignored since rbgSize is 0)");
2733 /* TODO: if receiver detects non-zero bits outside the valid range, those shall be ignored. */
2734 offset += 4;
2735 /* priority */
2736 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
2737 /* symbolMask */
2738 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
2739 offset += 2;
2741 /* Look up rbg_size enum -> value */
2742 switch (rbgSize) {
2743 case 0:
2744 /* N.B. reserved, but covered above with expert info (would remain 0) */
2745 break;
2746 case 1:
2747 ext11_settings.ext6_rbg_size = 1; break;
2748 case 2:
2749 ext11_settings.ext6_rbg_size = 2; break;
2750 case 3:
2751 ext11_settings.ext6_rbg_size = 3; break;
2752 case 4:
2753 ext11_settings.ext6_rbg_size = 4; break;
2754 case 5:
2755 ext11_settings.ext6_rbg_size = 6; break;
2756 case 6:
2757 ext11_settings.ext6_rbg_size = 8; break;
2758 case 7:
2759 ext11_settings.ext6_rbg_size = 16; break;
2760 /* N.B., encoded in 3 bits, so no other values are possible */
2763 /* Set to looked-up value */
2764 rbgSize = ext11_settings.ext6_rbg_size;
2766 uint32_t lastRbgid = 0;
2767 if (rbgSize != 0) {
2768 /* The O-DU shall not use combinations of startPrbc, numPrbc and rbgSize leading to a value of lastRbgid larger than 27 */
2769 /* i.e., leftmost bit used should not need to go off left end of rbgMask! */
2770 lastRbgid = (uint32_t)ceil((numPrbc + (startPrbc % rbgSize)) / (float)rbgSize) - 1;
2771 if (lastRbgid > 27) {
2772 expert_add_info_format(pinfo, rbg_size_ti, &ei_oran_lastRbdid_out_of_range,
2773 "SE6: rbgSize (%u) not compatible with startPrbc(%u) and numPrbc(%u)",
2774 rbgSize, startPrbc, numPrbc);
2775 break;
2779 /* Record (and count) which bits are set in rbgMask */
2780 bool first_seen = false;
2781 unsigned first_seen_pos=0, last_seen_pos=0;
2782 for (unsigned n=0; n < 28 && ext11_settings.ext6_num_bits_set < 28; n++) {
2783 if ((rbgMask >> n) & 0x01) {
2784 ext11_settings.ext6_bits_set[ext11_settings.ext6_num_bits_set++] = n;
2785 if (!first_seen) {
2786 first_seen = true;
2787 first_seen_pos = n;
2789 last_seen_pos = n;
2793 /* Show how many bits were set in rbgMask */
2794 proto_item_append_text(rbgmask_ti, " (%u bits set)", ext11_settings.ext6_num_bits_set);
2795 /* Also, that is the range of bits */
2796 if (first_seen) {
2797 proto_item_append_text(rbgmask_ti, " (%u bits spread)", last_seen_pos-first_seen_pos+1);
2800 /* Complain if last set bit is beyond lastRbgid */
2801 if (first_seen) {
2802 if (last_seen_pos > lastRbgid) {
2803 expert_add_info_format(pinfo, rbgmask_ti, &ei_oran_rbgMask_beyond_last_rbdid,
2804 "SE6: rbgMask (0x%07x) has bit %u set, but lastRbgId is %u",
2805 rbgMask, last_seen_pos, lastRbgid);
2808 break;
2811 case 7: /* SE 7: eAxC mask */
2812 /* Allow ST0 to address multiple eAxC_ID values for transmission blanking */
2813 proto_tree_add_item(extension_tree, hf_oran_eAxC_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
2814 offset += 2;
2815 break;
2817 case 8: /* SE 8: Regularization factor */
2818 proto_tree_add_item(extension_tree, hf_oran_regularizationFactor, tvb, offset, 2, ENC_BIG_ENDIAN);
2819 offset += 2;
2820 break;
2822 case 9: /* SE 9: Dynamic Spectrum Sharing parameters */
2823 proto_tree_add_item(extension_tree, hf_oran_technology, tvb, offset, 1, ENC_BIG_ENDIAN);
2824 offset += 1;
2825 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
2826 offset += 1;
2827 break;
2829 case 10: /* SE 10: Group configuration of multiple ports */
2831 seen_se10 = true;
2833 /* beamGroupType */
2834 uint32_t beam_group_type = 0;
2835 proto_item *bgt_ti;
2836 bgt_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamGroupType,
2837 tvb, offset, 1, ENC_BIG_ENDIAN, &beam_group_type);
2838 proto_item_append_text(extension_ti, " (%s)", val_to_str_const(beam_group_type, beam_group_type_vals, "Unknown"));
2840 /* numPortc */
2841 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
2842 tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
2843 offset++;
2845 /* Will append all beamId values to extension_ti, regardless of beamGroupType */
2846 unsigned n;
2848 switch (beam_group_type) {
2849 case 0x0: /* common beam */
2850 case 0x1: /* beam matrix indication */
2851 /* Reserved byte */
2852 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
2853 offset++;
2854 break;
2856 case 0x2: /* beam vector listing */
2858 proto_item_append_text(extension_ti, " [ ");
2860 /* Beam listing vector case */
2861 /* Work out how many port beam entries there is room for */
2862 /* Using numPortC as visible in issue 18116 */
2863 for (n=0; n < numPortc; n++) {
2864 /* 1 reserved bit */
2865 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2867 /* port beam ID (or UEID) */
2868 uint32_t id;
2869 proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
2870 tvb, offset, 2, ENC_BIG_ENDIAN, &id);
2871 proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
2872 offset += 2;
2874 proto_item_append_text(extension_ti, "%u ", id);
2877 proto_item_append_text(extension_ti, "]");
2878 break;
2880 case 0x3: /* beamId/ueId listing with associated port-list index */
2882 proto_item_append_text(extension_ti, " [ ");
2884 if (numPortc > 0) {
2885 /* first portListIndex */
2886 uint32_t port_list_index;
2887 proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
2888 offset, 1, ENC_BIG_ENDIAN, &port_list_index);
2889 offset += 1;
2891 for (n=0; n < numPortc-1; n++) {
2892 /* 1 reserved bit */
2893 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
2895 /* port beam ID (or UEID) */
2896 uint32_t id;
2897 proto_item *beamid_or_ueid_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId,
2898 tvb, offset, 2, ENC_BIG_ENDIAN, &id);
2899 proto_item_append_text(beamid_or_ueid_ti, " port #%u beam ID (or UEId) %u", n, id);
2900 offset += 2;
2902 /* portListIndex */
2903 proto_tree_add_item_ret_uint(extension_tree, hf_oran_port_list_index, tvb,
2904 offset, 1, ENC_BIG_ENDIAN, &port_list_index);
2905 offset += 1;
2907 proto_item_append_text(extension_ti, "%u:%u ", port_list_index, id);
2911 proto_item_append_text(extension_ti, "]");
2912 break;
2916 default:
2917 /* Warning for unsupported/reserved value */
2918 expert_add_info(NULL, bgt_ti, &ei_oran_se10_unknown_beamgrouptype);
2919 break;
2921 break;
2924 case 11: /* SE 11: Flexible Weights Extension Type */
2926 /* Hidden filter for bf */
2927 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
2928 PROTO_ITEM_SET_HIDDEN(bf_ti);
2930 /* beamId in section header should be ignored. Guard against appending multiple times.. */
2931 if (beamId_ti && !beamId_ignored) {
2932 proto_item_append_text(beamId_ti, " (ignored)");
2933 beamId_ignored = true;
2936 bool disableBFWs;
2937 uint32_t numBundPrb;
2938 bool rad;
2940 /* disableBFWs */
2941 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
2942 tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
2943 if (disableBFWs) {
2944 proto_item_append_text(extension_ti, " (disableBFWs)");
2947 /* RAD */
2948 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_rad,
2949 tvb, offset, 1, ENC_BIG_ENDIAN, &rad);
2950 /* bundleOffset (6 bits) */
2951 proto_tree_add_item(extension_tree, hf_oran_bundle_offset, tvb,
2952 offset, 1, ENC_BIG_ENDIAN);
2953 offset++;
2955 /* numBundPrb (number of prbs in each bundle) */
2956 proto_item *num_bund_prb_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_bund_prbs,
2957 tvb, offset, 1, ENC_BIG_ENDIAN, &numBundPrb);
2958 offset++;
2959 /* value zero is reserved.. */
2960 if (numBundPrb == 0) {
2961 expert_add_info_format(pinfo, num_bund_prb_ti, &ei_oran_reserved_numBundPrb,
2962 "Reserved value 0 for numBundPrb seen - not valid");
2965 uint32_t num_bundles;
2966 bool orphaned_prbs = false;
2968 if (!disableBFWs) {
2969 /********************************************/
2970 /* Table 7.7.1.1-1 */
2971 /********************************************/
2973 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
2974 proto_item *comp_meth_ti = NULL;
2976 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
2977 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
2978 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
2980 /* Work out number of bundles, but take care not to divide by zero. */
2981 if (numBundPrb == 0) {
2982 break;
2985 /* Work out bundles! */
2986 ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
2987 num_bundles = ext11_settings.num_bundles;
2989 /* Add (complete) bundles */
2990 for (unsigned b=0; b < num_bundles; b++) {
2992 offset = dissect_bfw_bundle(tvb, extension_tree, pinfo, offset,
2993 comp_meth_ti, bfwcomphdr_comp_meth,
2994 (ext11_settings.ext21_set) ?
2995 numPrbc :
2996 pref_num_weights_per_bundle,
2997 bfwcomphdr_iq_width,
2998 b, /* bundle number */
2999 ext11_settings.bundles[b].start,
3000 ext11_settings.bundles[b].end,
3001 ext11_settings.bundles[b].is_orphan);
3002 if (!offset) {
3003 break;
3006 if (num_bundles > 0) {
3007 /* Set flag from last bundle entry */
3008 orphaned_prbs = ext11_settings.bundles[num_bundles-1].is_orphan;
3011 else {
3012 /********************************************/
3013 /* Table 7.7.1.1-2 */
3014 /* No weights in this case */
3015 /********************************************/
3017 /* Work out number of bundles, but take care not to divide by zero. */
3018 if (numBundPrb == 0) {
3019 break;
3022 ext11_work_out_bundles(startPrbc, numPrbc, numBundPrb, &ext11_settings);
3023 num_bundles = ext11_settings.num_bundles;
3025 for (unsigned n=0; n < num_bundles; n++) {
3026 /* contInd */
3027 proto_tree_add_item(extension_tree, hf_oran_cont_ind,
3028 tvb, offset, 1, ENC_BIG_ENDIAN);
3029 /* beamId */
3030 proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_beam_id,
3031 tvb, offset, 2, ENC_BIG_ENDIAN);
3032 if (!ext11_settings.bundles[n].is_orphan) {
3033 proto_item_append_text(ti, " (Bundle %u)", n);
3035 else {
3036 orphaned_prbs = true;
3037 proto_item_append_text(ti, " (Orphaned PRBs)");
3039 offset += 2;
3043 /* Add summary to extension root */
3044 if (orphaned_prbs) {
3045 proto_item_append_text(extension_ti, " (%u bundles + orphaned)", num_bundles);
3047 else {
3048 proto_item_append_text(extension_ti, " (%u bundles)", num_bundles);
3052 break;
3054 case 12: /* SE 12: Non-Contiguous PRB Allocation with Frequency Ranges */
3056 ext11_settings.ext12_set = true;
3058 /* priority */
3059 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3061 /* symbolMask */
3062 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3063 offset += 2;
3065 /* There are now 'R' pairs of (offStartPrb, numPrb) values. Fill extlen bytes with values. If last one is not set,
3066 should be populated with 0s. */
3067 uint32_t extlen_remaining_bytes = (extlen*4) - 4;
3068 uint8_t prb_index;
3070 for (prb_index = 1; extlen_remaining_bytes > 0; prb_index++)
3072 /* Create a subtree for each pair */
3073 proto_item *pair_ti = proto_tree_add_string(extension_tree, hf_oran_off_start_prb_num_prb_pair,
3074 tvb, offset, 2, "");
3075 proto_tree *pair_tree = proto_item_add_subtree(pair_ti, ett_oran_offset_start_prb_num_prb);
3077 /* offStartPrb */
3078 uint32_t off_start_prb;
3079 proto_tree_add_item_ret_uint(pair_tree, hf_oran_off_start_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &off_start_prb);
3080 offset++;
3082 /* numPrb */
3083 uint32_t num_prb;
3084 proto_tree_add_item_ret_uint(pair_tree, hf_oran_num_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_prb);
3085 offset++;
3087 extlen_remaining_bytes -= 2;
3089 /* Last pair may be 0,0 if not used. Check for this */
3090 if ((extlen_remaining_bytes == 0) && (off_start_prb == 0) && (num_prb == 0)) {
3091 proto_item_append_text(pair_ti, " (not used)");
3093 /* Add summary to pair root item, and configure details in ext11_settings */
3094 else {
3095 proto_item_append_text(pair_ti, "(%u) offStartPrb=%3u, numPrb=%u",
3096 prb_index, off_start_prb, num_prb);
3097 if (ext11_settings.ext12_num_pairs < MAX_BFW_EXT12_PAIRS) {
3098 ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs].off_start_prb = off_start_prb;
3099 ext11_settings.ext12_pairs[ext11_settings.ext12_num_pairs++].num_prb = num_prb;
3103 break;
3106 case 13: /* SE 13: PRB Allocation with Frequency Hopping */
3108 /* Will update settings for ext11 */
3109 ext11_settings.ext13_set = true;
3111 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3112 uint8_t allocation_index;
3114 unsigned prev_next_symbol_id = 0, prev_next_start_prbc = 0;
3116 for (allocation_index = 1; extlen_remaining_bytes > 0; allocation_index++)
3118 /* Subtree for allocation */
3119 proto_item *allocation_ti = proto_tree_add_string(extension_tree, hf_oran_prb_allocation,
3120 tvb, offset, 2, "");
3121 proto_tree *allocation_tree = proto_item_add_subtree(allocation_ti, ett_oran_prb_allocation);
3123 /* Reserved (2 bits) */
3124 proto_tree_add_item(allocation_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3126 /* nextSymbolId (4 bits) */
3127 uint32_t next_symbol_id;
3128 proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextSymbolId, tvb, offset, 1, ENC_BIG_ENDIAN, &next_symbol_id);
3130 /* nextStartPrbc (10 bits) */
3131 uint32_t next_start_prbc;
3132 proto_tree_add_item_ret_uint(allocation_tree, hf_oran_nextStartPrbc, tvb, offset, 2, ENC_BIG_ENDIAN, &next_start_prbc);
3133 offset += 2;
3135 /* Add summary to allocation root item */
3136 proto_item_append_text(allocation_ti, "(%u) nextSymbolId=%3u, nextStartPrbc=%u",
3137 allocation_index, next_symbol_id, next_start_prbc);
3139 /* Checking for duplicates (expected if e.g. had only 2 entries but extlen bytes still to fill */
3140 if ((allocation_index > 1) && (next_symbol_id == prev_next_symbol_id) && (next_start_prbc == prev_next_start_prbc)) {
3141 proto_item_append_text(allocation_ti, " (repeated - to fill up extlen)");
3143 else {
3144 /* Add entry for configuring ext11. don't store out of range */
3145 if (ext11_settings.ext13_num_start_prbs < MAX_BFW_EXT13_ALLOCATIONS) {
3146 ext11_settings.ext13_start_prbs[ext11_settings.ext13_num_start_prbs++] = next_start_prbc;
3149 prev_next_symbol_id = next_symbol_id;
3150 prev_next_start_prbc = next_start_prbc;
3152 extlen_remaining_bytes -= 2;
3154 break;
3157 case 14: /* SE 14: Nulling-layer Info. for ueId-based beamforming */
3158 /* Hidden filter for bf (DMRS BF) */
3159 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3160 PROTO_ITEM_SET_HIDDEN(bf_ti);
3162 if (!seen_se10) {
3163 proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
3164 offset += 1;
3165 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3166 offset += 1;
3168 else {
3169 /* Loop over numPortc++1 (from SE 10) nullLayerInd fields */
3170 for (unsigned port=0; port < numPortc+1; port++) {
3171 proto_tree_add_item(extension_tree, hf_oran_nullLayerInd, tvb, offset, 1, ENC_BIG_ENDIAN);
3172 offset += 1;
3175 break;
3177 case 15: /* SE 15: Mixed-numerology Info. for ueId-based beamforming */
3179 /* frameStructure */
3180 offset = dissect_frame_structure(extension_tree, tvb, offset,
3181 subframeId, slotId);
3182 /* freqOffset */
3183 proto_tree_add_item(extension_tree, hf_oran_freqOffset, tvb, offset, 3, ENC_BIG_ENDIAN);
3184 offset += 3;
3185 /* cpLength */
3186 proto_item *cplength_ti = proto_tree_add_item(extension_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
3187 if (sectionType != 0 && sectionType != 3) {
3188 proto_item_append_text(cplength_ti, " (ignored - used only with ST0 and ST3)");
3190 offset += 2;
3191 break;
3194 case 16: /* SE 16: Antenna mapping in UE channel information based UL beamforming */
3196 /* Just filling available bytes with antMask entries.
3197 N.B., if SE 10 also used, could associate each antMask with (beamId or UEId) RX eAxC */
3198 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3199 unsigned num_ant_masks = extlen_remaining_bytes / 8;
3200 for (unsigned n=0; n < num_ant_masks; n++) {
3201 proto_item *ti = proto_tree_add_item(extension_tree, hf_oran_antMask, tvb, offset, 8, ENC_BIG_ENDIAN);
3202 proto_item_append_text(ti, " (RX eAxC #%u)", n+1);
3203 offset += 8;
3205 break;
3208 case 17: /* SE 17: Indication of user port group */
3210 uint32_t extlen_remaining_bytes = (extlen*4) - 2;
3211 uint32_t end_bit = (offset+extlen_remaining_bytes) * 8;
3212 uint32_t ueid_index = 1;
3213 /* TODO: just filling up all available bytes - some may actually be padding.. */
3214 /* "the preceding Section Type and extension messages implicitly provide the number of scheduled users" */
3215 for (uint32_t bit_offset=offset*8; bit_offset < end_bit; bit_offset+=4, ueid_index++) {
3216 proto_item *ti = proto_tree_add_bits_item(extension_tree, hf_oran_num_ueid, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
3217 proto_item_append_text(ti, " (user #%u)", ueid_index);
3219 break;
3222 case 18: /* SE 18: Uplink transmission management */
3223 /* transmissionWindowOffset */
3224 proto_tree_add_item(extension_tree, hf_oran_transmissionWindowOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
3225 offset += 2;
3226 /* reserved (2 bits) */
3227 proto_tree_add_item(extension_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3228 /* transmissionWindowSize (14 bits) */
3229 proto_tree_add_item(extension_tree, hf_oran_transmissionWindowSize, tvb, offset, 2, ENC_BIG_ENDIAN);
3230 offset += 2;
3232 /* reserved (6 bits) */
3233 proto_tree_add_item(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3234 /* toT (2 bits) */
3235 proto_tree_add_item(extension_tree, hf_oran_toT, tvb, offset, 1, ENC_BIG_ENDIAN);
3236 offset += 1;
3237 break;
3239 case 19: /* SE 19: Compact beamforming information for multiple port */
3241 /* beamId in section header should be ignored. Guard against appending multiple times.. */
3242 if (beamId_ti && !beamId_ignored) {
3243 proto_item_append_text(beamId_ti, " (ignored)");
3244 beamId_ignored = true;
3247 /* disableBFWs */
3248 bool disableBFWs;
3249 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_disable_bfws,
3250 tvb, offset, 1, ENC_BIG_ENDIAN, &disableBFWs);
3251 if (disableBFWs) {
3252 proto_item_append_text(extension_ti, " (disableBFWs)");
3254 /* Repetition */
3255 uint64_t repetition;
3256 proto_tree_add_bits_ret_val(extension_tree, hf_oran_repetition, tvb, (offset*8)+1, 1, &repetition, ENC_BIG_ENDIAN);
3257 /* numPortc */
3258 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPortc,
3259 tvb, offset, 1, ENC_BIG_ENDIAN, &numPortc);
3260 offset++;
3262 /* priority */
3263 proto_tree_add_item(extension_tree, hf_oran_noncontig_priority, tvb, offset, 1, ENC_BIG_ENDIAN);
3264 /* symbolMask */
3265 proto_tree_add_item(extension_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3266 offset += 2;
3268 /* bfwCompHdr */
3269 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
3270 proto_item *comp_meth_ti = NULL;
3271 offset = dissect_bfwCompHdr(tvb, extension_tree, offset,
3272 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
3274 if (!repetition) {
3276 /* Add entries for each port */
3277 for (unsigned port=0; port < numPortc; port++) {
3279 /* Create subtree for port entry*/
3280 int port_start_offset = offset;
3281 proto_item *port_ti = proto_tree_add_string_format(extension_tree, hf_oran_ext19_port,
3282 tvb, offset, 0,
3283 "", "Port %u: ", port);
3284 proto_tree *port_tree = proto_item_add_subtree(port_ti, ett_oran_ext19_port);
3286 /* Reserved (4 bits) */
3287 proto_tree_add_item(port_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3288 /* portReMask (12 bits) */
3289 proto_tree_add_item(port_tree, hf_oran_portReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3290 offset += 2;
3292 /* Reserved (2 bits) */
3293 proto_tree_add_item(port_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3294 /* portSymbolMask (14 bits) */
3295 proto_tree_add_item(port_tree, hf_oran_portSymbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3296 offset += 2;
3298 /* Reserved (1 bit) */
3299 proto_tree_add_item(port_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3300 /* beamID (15 bits) */
3301 proto_tree_add_item_ret_uint(port_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
3302 proto_item_append_text(port_ti, " (beamId=%u)", beamId);
3303 offset += 2;
3305 /* No weights present */
3306 if (!disableBFWs) {
3307 /*******************************************************************/
3308 /* Table 7.7.19.1-1 (there is no part -2 for disableBFWs case...), */
3309 /* but for SE 11, bfwCompParam was only present for !disableBFWs */
3310 /*******************************************************************/
3312 /* bfwCompParam */
3313 bool compression_method_supported = false;
3314 uint32_t exponent = 0;
3315 offset = dissect_bfwCompParam(tvb, port_tree, pinfo, offset, comp_meth_ti,
3316 bfwcomphdr_comp_meth, &exponent, &compression_method_supported);
3318 int bit_offset = offset*8;
3319 int bfw_offset;
3321 /* Add weights for each TRX */
3322 for (unsigned b=0; b < pref_num_bf_antennas; b++) {
3324 /* Create BFW subtree */
3325 bfw_offset = bit_offset / 8;
3326 uint8_t bfw_extent = ((bit_offset + (bfwcomphdr_iq_width*2)) / 8) - bfw_offset;
3327 proto_item *bfw_ti = proto_tree_add_string_format(port_tree, hf_oran_bfw,
3328 tvb, bfw_offset, bfw_extent,
3329 "", "TRX %u: (", b);
3330 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
3332 /* I */
3333 /* Get bits, and convert to float. */
3334 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3335 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
3336 /* Add to tree. */
3337 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
3338 (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
3339 bit_offset += bfwcomphdr_iq_width;
3340 proto_item_append_text(bfw_ti, "I%u=%f ", b, value);
3342 /* Q */
3343 /* Get bits, and convert to float. */
3344 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
3345 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
3346 /* Add to tree. */
3347 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
3348 (bfwcomphdr_iq_width+7)/8, value, "#%u=%f", b, value);
3349 bit_offset += bfwcomphdr_iq_width;
3350 proto_item_append_text(bfw_ti, "Q%u=%f)", b, value);
3353 offset = (bit_offset+7)/8;
3355 else {
3356 /* No weights... */
3358 /* Reserved (1 bit) */
3359 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3360 /* beamID (15 bits) */
3361 proto_tree_add_item_ret_uint(extension_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN, &beamId);
3362 proto_item_append_text(port_ti, " (beamId=%u)", beamId);
3363 offset += 2;
3366 /* Set length of this port entry */
3367 proto_item_set_len(port_ti, offset-port_start_offset);
3370 break;
3373 case 20: /* SE 20: Puncturing extension */
3375 /* numPuncPatterns */
3376 uint32_t numPuncPatterns;
3377 proto_tree_add_item_ret_uint(extension_tree, hf_oran_numPuncPatterns, tvb, offset, 1, ENC_BIG_ENDIAN, &numPuncPatterns);
3378 offset += 1;
3380 /* Add each puncturing pattern */
3381 for (uint32_t n=0; n < numPuncPatterns; n++) {
3382 unsigned pattern_start_offset = offset;
3384 /* Subtree for this puncturing pattern */
3385 proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_puncPattern,
3386 tvb, offset, 0,
3387 "", "Puncturing Pattern: %u/%u", n+1, hf_oran_numPuncPatterns);
3388 proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_punc_pattern);
3390 /* SymbolMask (14 bits) */
3391 proto_tree_add_item(pattern_tree, hf_oran_symbolMask_ext20, tvb, offset, 2, ENC_BIG_ENDIAN);
3392 offset += 1;
3393 /* startPuncPrb (10 bits) */
3394 proto_tree_add_item(pattern_tree, hf_oran_startPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN);
3395 offset += 2;
3396 /* numPuncPrb (8 bits) */
3397 proto_tree_add_item(pattern_tree, hf_oran_numPuncPrb, tvb, offset, 1, ENC_BIG_ENDIAN);
3398 offset += 1;
3399 /* puncReMask (12 bits) */
3400 proto_tree_add_item(pattern_tree, hf_oran_puncReMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3401 offset += 1;
3402 /* rb (1 bit) */
3403 proto_item *rb_ti = proto_tree_add_item(pattern_tree, hf_oran_rb, tvb, offset, 1, ENC_BIG_ENDIAN);
3404 /* reserved (1 bit) */
3405 proto_tree_add_item(pattern_tree, hf_oran_reserved_bit5, tvb, offset, 1, ENC_BIG_ENDIAN);
3406 /* multiSDScope (1 bit) */
3407 proto_tree_add_item(pattern_tree, hf_oran_multiSDScope, tvb, offset, 1, ENC_BIG_ENDIAN);
3408 /* rbgIncl (1 bit) */
3409 bool rbgIncl;
3410 proto_tree_add_item_ret_boolean(pattern_tree, hf_oran_RbgIncl, tvb, offset, 1, ENC_BIG_ENDIAN, &rbgIncl);
3411 offset += 1;
3413 if (rbgIncl) {
3414 /* reserved (1 bit) */
3415 proto_tree_add_item(pattern_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3416 /* rbgSize(3 bits) */
3417 proto_tree_add_item(pattern_tree, hf_oran_rbgSize, tvb, offset, 1, ENC_BIG_ENDIAN);
3418 /* rbgMask (28 bits) */
3419 proto_tree_add_item(pattern_tree, hf_oran_rbgMask, tvb, offset, 4, ENC_BIG_ENDIAN);
3420 offset += 4;
3422 proto_item_append_text(rb_ti, " (ignored)");
3425 proto_item_set_len(pattern_ti, offset-pattern_start_offset);
3428 break;
3430 case 21: /* SE 21: Variable PRB group size for channel information */
3432 /* ciPrbGroupSize */
3433 uint32_t ci_prb_group_size;
3434 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);
3435 offset += 1;
3437 switch (ci_prb_group_size) {
3438 case 0:
3439 case 1:
3440 case 255:
3441 /* Reserved value */
3442 expert_add_info_format(pinfo, prb_group_size_ti, &ei_oran_ci_prb_group_size_reserved,
3443 "SE 11 ciPrbGroupSize is reserved value %u - must be 2-254",
3444 ci_prb_group_size);
3446 break;
3447 default:
3448 /* This value affects how SE 11 is interpreted */
3449 ext11_settings.ext21_set = true;
3450 ext11_settings.ext21_ci_prb_group_size = ci_prb_group_size;
3452 if (numPrbc == 0) {
3453 expert_add_info(pinfo, numprbc_ti, &ei_oran_numprbc_ext21_zero);
3455 break;
3458 /* reserved (6 bits) */
3459 proto_tree_add_item(extension_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3461 /* prgSize (2 bits). Interpretation depends upon section type (5 or 6), but also mplane parameters? */
3462 if (sectionType == SEC_C_UE_SCHED) { /* Section Type 5 */
3463 proto_tree_add_item(extension_tree, hf_oran_prg_size_st5, tvb, offset, 1, ENC_BIG_ENDIAN);
3465 else if (sectionType == SEC_C_CH_INFO) { /* Section Type 6 */
3466 proto_tree_add_item(extension_tree, hf_oran_prg_size_st6, tvb, offset, 1, ENC_BIG_ENDIAN);
3468 offset += 1;
3469 break;
3472 case 22: /* SE 22: ACK/NACK request */
3474 uint32_t ack_nack_req_id;
3475 proto_tree_add_item_ret_uint(extension_tree, hf_oran_ack_nack_req_id, tvb, offset, 2,
3476 ENC_BIG_ENDIAN, &ack_nack_req_id);
3477 offset += 2;
3479 if (state) {
3480 if (!PINFO_FD_VISITED(pinfo)) {
3481 /* Add this request into conversation state on first pass */
3482 ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
3483 request_details->request_frame_number = pinfo->num;
3484 request_details->request_frame_time = pinfo->abs_ts;
3485 request_details->requestType = SE22;
3486 /* Insert into flow's tree */
3487 wmem_tree_insert32(state->ack_nack_requests, ack_nack_req_id, request_details);
3489 else {
3490 /* Try to link forward to ST8 response */
3491 ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
3492 ack_nack_req_id);
3493 if (response) {
3494 show_link_to_acknack_response(extension_tree, tvb, pinfo, response);
3498 break;
3501 case 23: /* SE 23: Arbitrary symbol pattern modulation compression parameters */
3503 /* Green common header */
3505 /* numSymPrbPattern (4 bits) */
3506 uint32_t num_sym_prb_pattern;
3507 proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_sym_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sym_prb_pattern);
3508 /* reserved (3 bits) */
3509 proto_tree_add_item(extension_tree, hf_oran_reserved_bits456, tvb, offset, 1, ENC_BIG_ENDIAN);
3510 /* prbMode (1 bit) */
3511 bool prb_mode;
3512 proto_tree_add_item_ret_boolean(extension_tree, hf_oran_prb_mode, tvb, offset, 1, ENC_BIG_ENDIAN, &prb_mode);
3513 offset += 1;
3515 /* reserved (8 bits) */
3516 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3517 offset += 1;
3519 /* Dissect each SymPrbPattern */
3520 for (uint32_t n=0; n < num_sym_prb_pattern; n++) {
3522 /* Subtree */
3523 proto_item *pattern_ti = proto_tree_add_string_format(extension_tree, hf_oran_sym_prb_pattern,
3524 tvb, offset, 1, "",
3525 prb_mode ? "PRB-BLOCK" : "PRB-MASK");
3526 proto_tree *pattern_tree = proto_item_add_subtree(pattern_ti, ett_oran_sym_prb_pattern);
3529 /* Orange part */
3531 /* Reserved (2 bits) */
3532 proto_tree_add_item(pattern_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3533 /* symMask (14 bits) */
3534 proto_tree_add_item(pattern_tree, hf_oran_sym_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3535 offset += 2;
3536 /* numMcScaleOffset (4 bits) */
3537 proto_tree_add_item(pattern_tree, hf_oran_num_mc_scale_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
3539 if (!prb_mode) { /* PRB-MASK */
3540 /* prbPattern (4 bits) */
3541 proto_tree_add_item(pattern_tree, hf_oran_prb_pattern, tvb, offset, 1, ENC_BIG_ENDIAN);
3542 offset += 1;
3543 /* reserved (8 bits) */
3544 proto_tree_add_item(pattern_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3545 offset += 1;
3547 else { /* PRB-BLOCK */
3548 /* prbBlkOffset (8 bits) */
3549 proto_tree_add_item(pattern_tree, hf_oran_prb_block_offset, tvb, offset, 1, ENC_BIG_ENDIAN);
3550 offset += 1;
3551 /* prbBlkSize (4 bits) */
3552 proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
3553 offset += 1;
3556 /* Yellowish part */
3557 if (prb_mode) { /* PRB-BLOCK */
3558 /* prbBlkSize (4 bits) */
3559 proto_tree_add_item(pattern_tree, hf_oran_prb_block_size, tvb, offset, 1, ENC_BIG_ENDIAN);
3561 else {
3562 /* reserved (4 bits) */
3563 proto_tree_add_item(pattern_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3566 /* mcScaleReMask (12 bits) */
3567 uint64_t mcScaleReMask, mcScaleOffset;
3568 proto_tree_add_bits_ret_val(pattern_tree, hf_oran_mc_scale_re_mask, tvb, offset*8 + 4, 12, &mcScaleReMask, ENC_BIG_ENDIAN);
3569 offset += 2;
3570 /* csf */
3571 dissect_csf(pattern_tree, tvb, offset*8, ci_iq_width, NULL);
3572 /* mcScaleOffset (15 bits) */
3573 proto_tree_add_bits_ret_val(pattern_tree, hf_oran_mc_scale_offset, tvb, offset*8 + 1, 15, &mcScaleOffset, ENC_BIG_ENDIAN);
3574 offset += 2;
3576 proto_item_set_end(pattern_ti, tvb, offset);
3578 break;
3581 case 24: /* SE 24: PUSCH DMRS configuration */
3583 /* Hidden filter for bf (DMRS BF) */
3584 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3585 PROTO_ITEM_SET_HIDDEN(bf_ti);
3587 /* alpnPerSym (1 bit) */
3588 proto_tree_add_item(extension_tree, hf_oran_alpn_per_sym, tvb, offset, 1, ENC_BIG_ENDIAN);
3589 /* antDmrsSnr (1 bit) */
3590 proto_tree_add_item(extension_tree, hf_oran_ant_dmrs_snr, tvb, offset, 1, ENC_BIG_ENDIAN);
3591 /* reserved (1 bit) */
3592 proto_tree_add_item(extension_tree, hf_oran_reserved_bit2, tvb, offset, 1, ENC_BIG_ENDIAN);
3593 /* userGroupSize (5 bits) */
3594 uint32_t user_group_size;
3595 proto_item *ugs_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_size, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_size);
3596 if (user_group_size == 0) {
3597 proto_item_append_text(ugs_ti, " (not used)");
3599 else if (user_group_size > 12) {
3600 proto_item_append_text(ugs_ti, " (reserved)");
3602 offset += 1;
3603 /* userGroupId (8 bits) */
3604 uint32_t user_group_id;
3605 proto_tree_add_item_ret_uint(extension_tree, hf_oran_user_group_id, tvb, offset, 1, ENC_BIG_ENDIAN, &user_group_id);
3606 if (user_group_id == 0) {
3607 /* TODO: Value 0 can happen in several cases, described in 7.7.24.7.. */
3609 offset += 1;
3611 /* Dissect each entry (until run out of extlen bytes..). Not sure how this works with padding bytes though... */
3612 /* TODO: how to know when have seen last entry? Zero byte (within last 3 bytes of space) are valid... */
3613 while (offset < (extension_start_offset + extlen*4)) {
3615 /* Subtree */
3616 proto_item *entry_ti = proto_tree_add_string_format(extension_tree, hf_oran_dmrs_entry,
3617 tvb, offset, 0, "",
3618 "Entry");
3619 proto_tree *entry_tree = proto_item_add_subtree(entry_ti, ett_oran_dmrs_entry);
3621 /* entryType (3 bits) */
3622 uint32_t entry_type;
3623 proto_item *entry_type_ti;
3624 entry_type_ti = proto_tree_add_item_ret_uint(entry_tree, hf_oran_entry_type, tvb, offset, 1, ENC_BIG_ENDIAN, &entry_type);
3625 if (entry_type > 3) {
3626 proto_item_append_text(entry_type_ti, " (reserved)");
3629 /* dmrsPortNumber (5 bits). Values 0-11 allowed */
3630 unsigned int dmrs_port_number;
3631 proto_item *dpn_ti = proto_tree_add_item_ret_uint(entry_tree, hf_oran_dmrs_port_number, tvb, offset, 1, ENC_BIG_ENDIAN, &dmrs_port_number);
3632 if (dmrs_port_number > 11) {
3633 proto_item_append_text(dpn_ti, " (12-31 are reserved)");
3635 offset += 1;
3637 /* What follows depends upon entryType */
3638 switch (entry_type) {
3639 case 0:
3640 case 1:
3641 /* No further fields for these */
3642 break;
3644 case 2:
3645 case 3:
3646 /* Type 2/3 are very similar.. */
3648 /* ueIdReset (1 bit) */
3649 proto_tree_add_item(entry_tree, hf_oran_ueid_reset, tvb, offset, 1, ENC_BIG_ENDIAN);
3650 /* reserved (1 bit) */
3651 proto_tree_add_item(entry_tree, hf_oran_reserved_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3652 /* dmrsSymbolMask (14 bits) */
3653 /* TODO: break down into separate mask fields? */
3654 proto_tree_add_item(entry_tree, hf_oran_dmrs_symbol_mask, tvb, offset, 2, ENC_BIG_ENDIAN);
3655 offset += 2;
3657 /* scrambling */
3658 proto_tree_add_item(entry_tree, hf_oran_scrambling, tvb, offset, 2, ENC_BIG_ENDIAN);
3659 offset += 2;
3661 /* nscid (1 bit) */
3662 proto_tree_add_item(entry_tree, hf_oran_nscid, tvb, offset, 1, ENC_BIG_ENDIAN);
3664 /* These 5 bits differ depending upon entry type */
3665 if (entry_type == 2) {
3666 /* dType (1 bit) */
3667 proto_tree_add_item(entry_tree, hf_oran_dtype, tvb, offset, 1, ENC_BIG_ENDIAN);
3668 /* cdmWithoutData (2 bits) */
3669 proto_tree_add_item(entry_tree, hf_oran_cmd_without_data, tvb, offset, 1, ENC_BIG_ENDIAN);
3670 /* lambda (2 bits) */
3671 proto_tree_add_item(entry_tree, hf_oran_lambda, tvb, offset, 1, ENC_BIG_ENDIAN);
3673 else { /* type 3 */
3674 /* reserved (1 bit) */
3675 proto_tree_add_item(entry_tree, hf_oran_reserved_bit1, tvb, offset, 1, ENC_BIG_ENDIAN);
3676 /* lowPaprType (2 bits) */
3677 proto_tree_add_item(entry_tree, hf_oran_low_papr_type, tvb, offset, 1, ENC_BIG_ENDIAN);
3678 /* hoppingMode (2 bits) */
3679 proto_tree_add_item(entry_tree, hf_oran_hopping_mode, tvb, offset, 1, ENC_BIG_ENDIAN);
3682 /* firstPrb (9 bits) */
3683 proto_tree_add_item(entry_tree, hf_oran_first_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
3684 offset += 1;
3685 /* lastPrb (9 bits) */
3686 proto_tree_add_item(entry_tree, hf_oran_last_prb, tvb, offset, 2, ENC_BIG_ENDIAN);
3687 offset += 2;
3688 /* Reserved (16 bits) */
3689 proto_tree_add_item(entry_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
3690 offset += 2;
3691 break;
3693 default:
3694 /* reserved - expert info */
3695 break;
3698 proto_item_append_text(entry_ti, " (type=%u)", entry_type);
3699 proto_item_set_end(entry_ti, tvb, offset);
3701 break;
3704 case 25: /* SE 25: Symbol reordering for DMRS-BF */
3705 /* Just dissect each available block of 7 bytes as the 14 symbols for a layer,
3706 where each layer could be one or apply to all layers. */
3708 /* TODO: should only appear in one section of a message.. */
3709 unsigned layer = 0;
3710 proto_item *layer_ti;
3711 while (offset+7 <= (extension_start_offset + extlen*4)) {
3712 /* Layer subtree */
3713 layer_ti = proto_tree_add_string_format(extension_tree, hf_oran_symbol_reordering_layer,
3714 tvb, offset, 7, "",
3715 "Layer");
3716 proto_tree *layer_tree = proto_item_add_subtree(layer_ti, ett_oran_symbol_reordering_layer);
3718 /* All 14 symbols for a layer (or all layers) */
3719 for (unsigned s=0; s < 14; s++) {
3720 proto_item *sym_ti;
3721 /* txWinForOnAirSymbol */
3722 unsigned int tx_win_for_on_air_symbol;
3723 sym_ti = proto_tree_add_item_ret_uint(layer_tree,
3724 (s % 2) ? hf_oran_tx_win_for_on_air_symbol_r : hf_oran_tx_win_for_on_air_symbol_l,
3725 tvb, offset, 1, ENC_BIG_ENDIAN, &tx_win_for_on_air_symbol);
3726 if (tx_win_for_on_air_symbol == 0x0F) {
3727 /* Ordering not affected */
3728 proto_item_append_text(sym_ti, " (sym %u - no info)", s);
3730 else {
3731 proto_item_append_text(sym_ti, " (sym %u)", s);
3733 if (s % 2) {
3734 offset += 1;
3738 proto_item_append_text(layer_ti, " (layer %u)", ++layer);
3740 /* Set layer subtree label */
3741 if (layer == 1) {
3742 proto_item_append_text(layer_ti, " (all)");
3744 break;
3747 case 26: /* SE 26: Frequency offset feedback */
3748 /* Reserved (8 bits). N.B., added after draft? */
3749 proto_tree_add_item(extension_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3750 offset += 1;
3752 /* Reserved (1 bit) */
3753 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3754 /* numFoFb (7 bits) */
3755 unsigned num_fo_fb;
3756 proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_fo_fb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_fo_fb);
3757 offset += 1;
3759 /* Add each freqOffsetFb value */
3760 for (unsigned n=0; n < num_fo_fb; n++) {
3761 unsigned freq_offset_fb;
3762 /* freqOffsetFb (16 bits) */
3763 proto_item *offset_ti = proto_tree_add_item_ret_uint(extension_tree, hf_oran_freq_offset_fb,
3764 tvb, offset, 2, ENC_BIG_ENDIAN, &freq_offset_fb);
3765 /* Show if maps onto a -ve number */
3766 if ((freq_offset_fb >= 0x8ad0) && (freq_offset_fb <= 0xffff)) {
3767 proto_item_append_text(offset_ti, "(value %d)", -1 - (0xffff-freq_offset_fb));
3769 proto_item_append_text(offset_ti, " [#%u]", n+1);
3770 offset += 2;
3772 break;
3774 case 27: /* SE 27: O-DU controlled dimensionality reduction */
3776 /* Hidden filter for bf (DMRS BF) */
3777 bf_ti = proto_tree_add_item(tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3778 PROTO_ITEM_SET_HIDDEN(bf_ti);
3780 /* beamType (2 bits) */
3781 unsigned beam_type;
3782 proto_tree_add_item_ret_uint(extension_tree, hf_oran_beam_type, tvb, offset, 1, ENC_BIG_ENDIAN, &beam_type);
3783 /* reserved (6 bits) */
3784 proto_tree_add_item(extension_tree, hf_oran_reserved_last_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3785 offset += 1;
3787 /* numElements */
3788 unsigned num_elements;
3789 proto_tree_add_item_ret_uint(extension_tree, hf_oran_num_elements, tvb, offset, 1, ENC_BIG_ENDIAN, &num_elements);
3790 offset += 1;
3792 /* beamId value(s) */
3793 switch (num_elements) {
3794 case 0:
3795 for (unsigned n=0; n < num_elements; n++) {
3796 /* reserved (1 bit) + beamId */
3797 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3798 proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
3799 offset += 2;
3801 break;
3802 case 1:
3803 /* reserved (1 bit) + beamId */
3804 proto_tree_add_item(extension_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
3805 proto_tree_add_item(c_section_tree, hf_oran_beamId, tvb, offset, 2, ENC_BIG_ENDIAN);
3806 offset += 2;
3807 break;
3808 default:
3809 /* Unknown type... */
3810 break;
3812 break;
3815 default:
3816 /* Other/unexpected extension types */
3817 expert_add_info_format(pinfo, exttype_ti, &ei_oran_unhandled_se,
3818 "SE %u (%s) not supported by dissector",
3819 exttype, val_to_str_const(exttype, exttype_vals, "Reserved"));
3820 ext_unhandled = true;
3821 break;
3824 /* Check offset compared with extlen. There should be 0-3 bytes of padding */
3825 int num_padding_bytes = (extension_start_offset + (extlen*4) - offset);
3826 if (!ext_unhandled && ((num_padding_bytes<0) || (num_padding_bytes>3))) {
3827 expert_add_info_format(pinfo, extlen_ti, &ei_oran_extlen_wrong,
3828 "extlen signalled %u bytes (+ 0-3 bytes padding), but %u were dissected",
3829 extlen*4, offset-extension_start_offset);
3832 /* Move offset to beyond signalled length of extension */
3833 offset = extension_start_offset + (extlen*4);
3835 /* Set length of extension header. */
3836 proto_item_set_len(extension_ti, extlen*4);
3838 /* End of section extension handling */
3842 /* RRM measurement reports have measurement reports after extensions */
3843 if (sectionType == SEC_C_RRM_MEAS_REPORTS) /* Section Type 10 */
3845 /* Hidden filter for bf (DMFS-BF) */
3846 bf_ti = proto_tree_add_item(c_section_tree, hf_oran_bf, tvb, 0, 0, ENC_NA);
3847 PROTO_ITEM_SET_HIDDEN(bf_ti);
3849 bool mf;
3850 do {
3851 /* Measurement report subtree */
3852 proto_item *mr_ti = proto_tree_add_item(c_section_tree, hf_oran_measurement_report,
3853 tvb, offset, 0, ENC_ASCII);
3854 proto_tree *mr_tree = proto_item_add_subtree(mr_ti, ett_oran_measurement_report);
3855 unsigned report_start_offset = offset;
3857 /* mf (1 bit) */
3858 proto_tree_add_item_ret_boolean(mr_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
3860 /* measTypeId (7 bits) */
3861 uint32_t meas_type_id;
3862 proto_item *meas_type_id_ti;
3863 meas_type_id_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_type_id, tvb, offset, 1, ENC_BIG_ENDIAN, &meas_type_id);
3864 offset += 1;
3866 /* Common to all measurement types */
3867 unsigned num_elements = 0;
3868 if (meas_type_id == 6) {
3869 /* numElements */
3870 proto_tree_add_item_ret_uint(mr_tree, hf_oran_num_elements, tvb, offset, 1, ENC_BIG_ENDIAN, &num_elements);
3872 else {
3873 /* All other meas ids have a reserved byte */
3874 proto_tree_add_item(mr_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3876 offset += 1;
3878 /* measDataSize (16 bits). N.B. begins at mf field, i.e. 2 bytes before this one */
3879 unsigned meas_data_size;
3880 proto_item *meas_data_size_ti;
3881 meas_data_size_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_data_size, tvb, offset, 2, ENC_BIG_ENDIAN, &meas_data_size);
3882 meas_data_size *= 4;
3883 proto_item_append_text(meas_data_size_ti, " (%u bytes)", meas_data_size);
3884 offset += 2;
3886 /* Summary for measurement report root */
3887 proto_item_append_text(mr_ti, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
3888 /* And section header */
3889 proto_item_append_text(tree, " (%s)", val_to_str_const(meas_type_id, meas_type_id_vals, "unknown"));
3891 switch (meas_type_id) {
3892 case 1:
3894 /* ueTae */
3895 unsigned ue_tae;
3896 proto_item *ue_tae_ti;
3897 ue_tae_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_tae, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_tae);
3898 /* Show if maps onto a -ve number */
3899 if ((ue_tae >= 0x8ad0) && (ue_tae <= 0xffff)) {
3900 proto_item_append_text(ue_tae_ti, "(value %d)", -1 - (0xffff-ue_tae));
3902 offset += 2;
3904 /* Reserved (16 bits) */
3905 proto_tree_add_item(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
3906 offset += 2;
3907 break;
3909 case 2:
3910 /* ueLayerPower entries (how many? for now just use up meas_data_size..) */
3911 for (unsigned n=0; n < (meas_data_size-4)/2; n++) {
3912 unsigned ue_layer_power;
3913 proto_item *ue_layer_power_ti;
3914 ue_layer_power_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_layer_power, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_layer_power);
3915 /* Show if maps onto a -ve number */
3916 if ((ue_layer_power >= 0x8ad0) && (ue_layer_power <= 0xffff)) {
3917 proto_item_append_text(ue_layer_power_ti, "(value %d)", -1 - (0xffff-ue_layer_power));
3919 offset += 2;
3921 /* padding out to 4 bytes */
3922 break;
3923 case 3:
3925 /* ueFreqOffset */
3926 unsigned ue_freq_offset;
3927 proto_item *ue_freq_offset_ti;
3928 ue_freq_offset_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ue_freq_offset, tvb, offset, 2, ENC_BIG_ENDIAN, &ue_freq_offset);
3929 /* Show if maps onto a -ve number */
3930 if ((ue_freq_offset >= 0x8ad0) && (ue_freq_offset <= 0xffff)) {
3931 proto_item_append_text(ue_freq_offset_ti, "(value %d)", -1 - (0xffff-ue_freq_offset));
3933 offset += 2;
3935 /* Reserved (16 bits) */
3936 proto_tree_add_item(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
3937 offset += 2;
3938 break;
3940 case 4:
3941 case 5:
3942 /* reserved (2 bits) */
3943 proto_tree_add_item(mr_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
3944 /* symbolMask (14 bits) */
3945 proto_tree_add_item(mr_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
3946 offset += 2;
3948 /* 2 bytes for each PRB ipnPower */
3949 for (unsigned n=0; n < numPrbc; n++) {
3950 unsigned ipn_power;
3951 proto_item *ipn_power_ti;
3952 /* ipnPower (2 bytes) */
3953 ipn_power_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ipn_power, tvb, offset, 2, ENC_BIG_ENDIAN, &ipn_power);
3954 proto_item_append_text(ipn_power_ti, " (PRB %3d)", startPrbc+n);
3955 /* Show if maps onto a -ve number */
3956 if ((ipn_power >= 0x8ad0) && (ipn_power <= 0xffff)) {
3957 proto_item_append_text(ipn_power_ti, " (value %d)", -1 - (0xffff-ipn_power));
3959 offset += 2;
3961 /* padding out to 4 bytes */
3962 break;
3963 case 6:
3964 /* antDmrsSnrVal entries */
3965 for (unsigned n=0; n < num_elements; n++) {
3966 unsigned snr_value;
3967 proto_item *snr_value_ti;
3968 /* antDmrsSnrVal (2 bytes) */
3969 snr_value_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_ant_dmrs_snr_val, tvb, offset, 2, ENC_BIG_ENDIAN, &snr_value);
3970 proto_item_append_text(snr_value_ti, " (elem %2u)", n+1);
3971 /* Show if maps onto a -ve number */
3972 if ((snr_value >= 0x8ad0) && (snr_value <= 0xffff)) {
3973 proto_item_append_text(snr_value_ti, " (value %d)", -1 - (0xffff-snr_value));
3975 offset += 2;
3977 break;
3979 default:
3980 /* Anything else is not expected */
3981 expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
3982 "measTypeId %u (%s) not supported - only 1-6 are expected",
3983 meas_type_id,
3984 val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
3985 break;
3989 /* Pad out to next 4 bytes */
3990 if ((offset-report_start_offset) % 4) {
3991 offset += (4 - ((offset-report_start_offset) % 4));
3994 /* End of measurement report tree */
3995 proto_item_set_end(mr_ti, tvb, offset);
3996 } while (mf);
3999 /* Request for RRM Measurements has commands after extensions */
4000 if (sectionType == SEC_C_REQUEST_RRM_MEAS) /* Section Type 11 */
4002 bool mf;
4003 do {
4004 /* Measurement report subtree */
4005 proto_item *mr_ti = proto_tree_add_item(c_section_tree, hf_oran_measurement_report,
4006 tvb, offset, 0, ENC_ASCII);
4007 proto_tree *mr_tree = proto_item_add_subtree(mr_ti, ett_oran_measurement_report);
4009 /* mf (1 bit) */
4010 proto_tree_add_item_ret_boolean(mr_tree, hf_oran_mf, tvb, offset, 1, ENC_BIG_ENDIAN, &mf);
4012 /* measTypeId (7 bits) */
4013 uint32_t meas_type_id;
4014 proto_item *meas_type_id_ti;
4015 meas_type_id_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_type_id, tvb, offset, 1, ENC_BIG_ENDIAN, &meas_type_id);
4016 offset += 1;
4018 proto_item *meas_command_ti;
4019 uint32_t meas_command_size;
4021 switch (meas_type_id) {
4022 case 5: /* command for IpN for unallocated PRBs */
4023 /* reserved (1 byte) */
4024 proto_tree_add_item(mr_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4025 offset += 1;
4026 /* measCmdSize. Presumably number of words so in future could skip unrecognised command types.. */
4027 meas_command_ti = proto_tree_add_item_ret_uint(mr_tree, hf_oran_meas_cmd_size, tvb, offset, 2, ENC_BIG_ENDIAN, &meas_command_size);
4028 proto_item_append_text(meas_command_ti, " (%u bytes)", meas_command_size*4);
4029 offset += 2;
4030 /* reserved (2 bits) */
4031 proto_tree_add_item(mr_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4032 /* symbolMask (14 bits) */
4033 proto_tree_add_item(mr_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN);
4034 offset += 2;
4035 /* reserved (16 bits) */
4036 proto_tree_add_item(mr_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4037 offset += 2;
4038 break;
4040 default:
4041 /* Anything else is not expected */
4042 expert_add_info_format(pinfo, meas_type_id_ti, &ei_oran_unexpected_measTypeId,
4043 "measTypeId %u (%s) not supported - only 5 is expected",
4044 meas_type_id,
4045 val_to_str_const(meas_type_id, meas_type_id_vals, "reserved"));
4046 break;
4048 } while (mf);
4051 /* Set extent of overall section */
4052 proto_item_set_len(sectionHeading, offset);
4054 return offset;
4057 /* Dissect udCompHdr (user data compression header, 7.5.2.10) */
4058 /* bit_width and comp_meth are out params */
4059 static int dissect_udcomphdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, unsigned offset,
4060 bool ignore,
4061 unsigned *bit_width, unsigned *comp_meth, proto_item **comp_meth_ti)
4063 /* Subtree */
4064 proto_item *udcomphdr_ti = proto_tree_add_string_format(tree, hf_oran_udCompHdr,
4065 tvb, offset, 1, "",
4066 "udCompHdr");
4067 proto_tree *udcomphdr_tree = proto_item_add_subtree(udcomphdr_ti, ett_oran_udcomphdr);
4069 /* udIqWidth */
4070 uint32_t hdr_iq_width;
4071 proto_item *iq_width_item = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
4072 *bit_width = (hdr_iq_width) ? hdr_iq_width : 16;
4073 proto_item_append_text(iq_width_item, " (%u bits)", *bit_width);
4075 /* udCompMeth */
4076 uint32_t ud_comp_meth;
4077 *comp_meth_ti = proto_tree_add_item_ret_uint(udcomphdr_tree, hf_oran_udCompHdrMeth, tvb, offset, 1, ENC_NA, &ud_comp_meth);
4078 if (comp_meth) {
4079 *comp_meth = ud_comp_meth;
4082 /* Summary */
4083 if (!ignore) {
4084 proto_item_append_text(udcomphdr_ti, " (IqWidth=%u, udCompMeth=%s)",
4085 *bit_width, rval_to_str_const(ud_comp_meth, ud_comp_header_meth, "Unknown"));
4087 else {
4088 proto_item_append_text(udcomphdr_ti, " (ignored)");
4089 if (hdr_iq_width || ud_comp_meth) {
4090 expert_add_info_format(pinfo, udcomphdr_ti, &ei_oran_udpcomphdr_should_be_zero,
4091 "udCompHdr in C-Plane for DL should be 0 - found %02x",
4092 tvb_get_uint8(tvb, offset));
4096 return offset+1;
4099 /* Dissect udCompParam (user data compression parameter, 8.3.3.15) */
4100 /* bit_width and comp_meth are out params */
4101 static int dissect_udcompparam(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
4102 unsigned comp_meth,
4103 uint32_t *exponent, uint16_t *sReSMask,
4104 bool for_sinr)
4106 if (comp_meth == COMP_NONE ||
4107 comp_meth == COMP_MODULATION ||
4108 comp_meth == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) {
4110 /* Not even creating a subtree for udCompMeth 0, 4, 8 */
4111 return offset;
4114 /* Subtree */
4115 unsigned start_offset = offset;
4116 proto_item *udcompparam_ti = proto_tree_add_string_format(tree, hf_oran_udCompParam,
4117 tvb, offset, 1, "",
4118 (for_sinr) ? "sinrCompHdr" : "udCompParam");
4119 proto_tree *udcompparam_tree = proto_item_add_subtree(udcompparam_ti, ett_oran_udcompparam);
4121 /* Show comp_meth as a generated field */
4122 proto_item *meth_ti = proto_tree_add_uint(udcompparam_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, comp_meth);
4123 proto_item_set_generated(meth_ti);
4125 uint32_t param_exponent;
4126 uint64_t param_sresmask;
4128 static int * const sres_mask_flags[] = {
4129 &hf_oran_sReSMask_re12,
4130 &hf_oran_sReSMask_re11,
4131 &hf_oran_sReSMask_re10,
4132 &hf_oran_sReSMask_re9,
4133 &hf_oran_sReSMask_re8,
4134 &hf_oran_sReSMask_re7,
4135 &hf_oran_sReSMask_re6,
4136 &hf_oran_sReSMask_re5,
4137 &hf_oran_sReSMask_re4,
4138 &hf_oran_sReSMask_re3,
4139 &hf_oran_sReSMask_re2,
4140 &hf_oran_sReSMask_re1,
4141 NULL
4144 switch (comp_meth) {
4145 case COMP_BLOCK_FP: /* 1 */
4146 case BFP_AND_SELECTIVE_RE_WITH_MASKS: /* 7 */
4147 /* reserved (4 bits) */
4148 proto_tree_add_item(udcompparam_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
4149 /* exponent (4 bits) */
4150 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
4151 tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
4152 *exponent = param_exponent;
4153 proto_item_append_text(udcompparam_ti, " (Exponent=%u)", param_exponent);
4154 offset += 1;
4155 break;
4157 case COMP_BLOCK_SCALE: /* 2 */
4158 /* Separate into integer and fractional bits? */
4159 proto_tree_add_item(udcompparam_tree, hf_oran_blockScaler,
4160 tvb, offset, 1, ENC_BIG_ENDIAN);
4161 offset++;
4162 break;
4164 case COMP_U_LAW: /* 3 */
4165 /* compBitWidth, compShift */
4166 proto_tree_add_item(udcompparam_tree, hf_oran_compBitWidth,
4167 tvb, offset, 1, ENC_BIG_ENDIAN);
4168 proto_tree_add_item(udcompparam_tree, hf_oran_compShift,
4169 tvb, offset, 1, ENC_BIG_ENDIAN);
4170 offset += 1;
4171 break;
4173 case BFP_AND_SELECTIVE_RE: /* 5 */
4175 /* sReSMask (exponent in middle!) */
4176 proto_item *sresmask_ti;
4177 sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
4178 hf_oran_sReSMask,
4179 ett_oran_sresmask,
4180 sres_mask_flags,
4181 ENC_NA,
4182 &param_sresmask);
4184 /* Get rid of exponent-shaped gap */
4185 param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
4186 unsigned res = 0;
4187 for (unsigned n=0; n < 12; n++) {
4188 if ((param_sresmask >> n) & 0x1) {
4189 res++;
4192 proto_item_append_text(sresmask_ti, " (%2u REs)", res);
4194 /* exponent */
4195 proto_tree_add_item_ret_uint(udcompparam_tree, hf_oran_exponent,
4196 tvb, offset, 1, ENC_BIG_ENDIAN, &param_exponent);
4197 *sReSMask = (uint16_t)param_sresmask;
4198 *exponent = param_exponent;
4200 proto_item_append_text(udcompparam_ti, " (exponent=%u, %u REs)", *exponent, res);
4201 offset += 2;
4202 break;
4205 case MOD_COMPR_AND_SELECTIVE_RE: /* 6 */
4207 /* sReSMask (exponent in middle!) */
4208 proto_item *sresmask_ti;
4210 sresmask_ti = proto_tree_add_bitmask_ret_uint64(udcompparam_tree, tvb, offset,
4211 hf_oran_sReSMask,
4212 ett_oran_sresmask,
4213 sres_mask_flags,
4214 ENC_NA,
4215 &param_sresmask);
4217 /* Get rid of reserved-shaped gap */
4218 param_sresmask = ((param_sresmask >> 4) & 0x0f00) | (param_sresmask & 0xff);
4219 unsigned res = 0;
4220 for (unsigned n=0; n < 12; n++) {
4221 if ((param_sresmask >> n) & 0x1) {
4222 res++;
4225 proto_item_append_text(sresmask_ti, " (%u REs)", res);
4227 /* reserved (4 bits) */
4228 proto_tree_add_item(udcompparam_tree, hf_oran_reserved_last_4bits,
4229 tvb, offset, 1, ENC_BIG_ENDIAN);
4230 *sReSMask = (uint16_t)param_sresmask;
4232 proto_item_append_text(udcompparam_ti, " (%u REs)", res);
4233 offset += 2;
4234 break;
4237 default:
4238 /* reserved (set to all zeros), but how many bytes?? */
4239 break;
4242 proto_item_set_len(udcompparam_ti, offset-start_offset);
4243 return offset;
4247 /* Dissect ciCompHdr (channel information compression header, 7.5.2.15) */
4248 /* bit_width and comp_meth are out params */
4249 static int dissect_cicomphdr(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, unsigned offset,
4250 unsigned *bit_width, unsigned *comp_meth, uint8_t *comp_opt)
4252 /* Subtree */
4253 proto_item *cicomphdr_ti = proto_tree_add_string_format(tree, hf_oran_ciCompHdr,
4254 tvb, offset, 1, "",
4255 "ciCompHdr");
4256 proto_tree *cicomphdr_tree = proto_item_add_subtree(cicomphdr_ti, ett_oran_cicomphdr);
4258 /* ciIqWidth */
4259 uint32_t hdr_iq_width;
4260 proto_item *iq_width_item = proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrIqWidth , tvb, offset, 1, ENC_NA, &hdr_iq_width);
4261 hdr_iq_width = (hdr_iq_width) ? hdr_iq_width : 16;
4262 if (bit_width) {
4263 *bit_width = hdr_iq_width;
4265 proto_item_append_text(iq_width_item, " (%u bits)", hdr_iq_width);
4267 /* ciCompMeth */
4268 uint32_t ci_comp_meth;
4269 proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompHdrMeth, tvb, offset, 1, ENC_NA, &ci_comp_meth);
4270 if (comp_meth) {
4271 *comp_meth = ci_comp_meth;
4274 /* ciCompOpt */
4275 uint32_t opt;
4276 proto_tree_add_item_ret_uint(cicomphdr_tree, hf_oran_ciCompOpt, tvb, offset, 1, ENC_NA, &opt);
4277 *comp_opt = opt;
4278 offset += 1;
4280 /* Summary */
4281 proto_item_append_text(cicomphdr_ti, " (IqWidth=%u, ciCompMeth=%s, ciCompOpt=%s)",
4282 hdr_iq_width,
4283 rval_to_str_const(ci_comp_meth, ud_comp_header_meth, "Unknown"),
4284 (*comp_opt) ? "compression per PRB" : "compression per UE");
4285 return offset;
4288 static void dissect_payload_version(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, unsigned offset)
4290 unsigned version;
4291 proto_item *ti = proto_tree_add_item_ret_uint(tree, hf_oran_payload_version, tvb, offset, 1, ENC_NA, &version);
4292 if (version != 1) {
4293 expert_add_info_format(pinfo, ti, &ei_oran_version_unsupported,
4294 "PayloadVersion %u not supported by dissector (only 1 is known)",
4295 version);
4296 /* TODO: should throw an exception? */
4300 static void show_link_to_acknack_request(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
4301 ack_nack_request_t *request)
4303 /* Request frame */
4304 proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_request_frame,
4305 tvb, 0, 0, request->request_frame_number);
4306 PROTO_ITEM_SET_GENERATED(ti);
4308 /* Work out gap between frames (in ms) */
4309 int seconds_between_packets = (int)
4310 (pinfo->abs_ts.secs - request->request_frame_time.secs);
4311 int nseconds_between_packets =
4312 pinfo->abs_ts.nsecs - request->request_frame_time.nsecs;
4314 int total_gap = (seconds_between_packets*1000) +
4315 ((nseconds_between_packets+500000) / 1000000);
4317 ti = proto_tree_add_uint(tree, hf_oran_acknack_request_time,
4318 tvb, 0, 0, total_gap);
4319 PROTO_ITEM_SET_GENERATED(ti);
4321 /* Type of request */
4322 ti = proto_tree_add_uint(tree, hf_oran_acknack_request_type,
4323 tvb, 0, 0, request->requestType);
4324 PROTO_ITEM_SET_GENERATED(ti);
4327 static void show_link_to_acknack_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
4328 ack_nack_request_t *response)
4330 if (response->response_frame_number == 0) {
4331 /* Requests may not get a response, and can't always tell when to expect one */
4332 return;
4335 /* Response frame */
4336 proto_item *ti = proto_tree_add_uint(tree, hf_oran_acknack_response_frame,
4337 tvb, 0, 0, response->response_frame_number);
4338 PROTO_ITEM_SET_GENERATED(ti);
4340 /* Work out gap between frames (in ms) */
4341 int seconds_between_packets = (int)
4342 (response->response_frame_time.secs - pinfo->abs_ts.secs);
4343 int nseconds_between_packets =
4344 response->response_frame_time.nsecs - pinfo->abs_ts.nsecs;
4346 int total_gap = (seconds_between_packets*1000) +
4347 ((nseconds_between_packets+500000) / 1000000);
4349 ti = proto_tree_add_uint(tree, hf_oran_acknack_response_time,
4350 tvb, 0, 0, total_gap);
4351 PROTO_ITEM_SET_GENERATED(ti);
4356 /* Control plane dissector (section 7). */
4357 static int dissect_oran_c(tvbuff_t *tvb, packet_info *pinfo,
4358 proto_tree *tree, oran_tap_info *tap_info, void *data _U_)
4360 /* Hidden filter for plane */
4361 proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_cplane, tvb, 0, 0, ENC_NA);
4362 PROTO_ITEM_SET_HIDDEN(plane_ti);
4364 /* Set up structures needed to add the protocol subtree and manage it */
4365 unsigned offset = 0;
4367 col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-C");
4368 col_set_str(pinfo->cinfo, COL_INFO, "C-Plane");
4370 tap_info->userplane = false;
4372 /* Create display subtree for the protocol */
4373 proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
4374 proto_item_append_text(protocol_item, "-C");
4375 proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
4377 uint16_t eAxC;
4378 addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_rtcid, &eAxC);
4379 tap_info->eaxc = eAxC;
4381 /* Message identifier */
4382 uint8_t seq_id;
4383 proto_item *seq_id_ti;
4384 offset = addSeqid(tvb, oran_tree, offset, ORAN_C_PLANE, &seq_id, &seq_id_ti);
4386 /* Section common subtree */
4387 int section_tree_offset = offset;
4388 proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_c_section_common,
4389 tvb, offset, 0, "", "C-Plane Section Type ");
4390 proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_c_section_common);
4392 /* Peek ahead at the section type */
4393 uint32_t sectionType = 0;
4394 sectionType = tvb_get_uint8(tvb, offset+5);
4396 uint32_t scs = 0;
4397 proto_item *scs_ti = NULL;
4399 /* dataDirection */
4400 uint32_t direction = 0;
4401 proto_tree_add_item_ret_uint(section_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
4402 tap_info->uplink = (direction==0);
4404 /* Look up any existing conversation state for eAxC+plane */
4405 uint32_t key = make_flow_key(eAxC, ORAN_C_PLANE);
4406 flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
4408 /* Update/report status of conversation */
4409 if (!PINFO_FD_VISITED(pinfo)) {
4411 if (state == NULL) {
4412 /* Allocate new state */
4413 state = wmem_new0(wmem_file_scope(), flow_state_t);
4414 state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
4415 wmem_tree_insert32(flow_states_table, key, state);
4418 /* Check sequence analysis status */
4419 if (state->last_frame_seen[direction] && (seq_id != state->next_expected_sequence_number[direction])) {
4420 /* Store this result */
4421 flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
4422 result->unexpected_seq_number = true;
4423 result->expected_sequence_number = state->next_expected_sequence_number[direction];
4424 result->previous_frame = state->last_frame[direction];
4425 wmem_tree_insert32(flow_results_table, pinfo->num, result);
4427 /* Update conversation info */
4428 state->last_frame[direction] = pinfo->num;
4429 state->last_frame_seen[direction] = true;
4430 state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
4433 /* Show any issues associated with this frame number */
4434 flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
4435 if (result!=NULL && result->unexpected_seq_number) {
4436 expert_add_info_format(pinfo, seq_id_ti, &ei_oran_cplane_unexpected_sequence_number,
4437 "Sequence number %u expected, but got %u",
4438 result->expected_sequence_number, seq_id);
4439 tap_info->missing_sns = (seq_id - result->expected_sequence_number) % 256;
4440 /* TODO: could add previous/next frames (in seqId tree?) ? */
4443 /* payloadVersion */
4444 dissect_payload_version(section_tree, tvb, pinfo, offset);
4446 /* filterIndex */
4447 if (sectionType == SEC_C_SLOT_CONTROL || sectionType == SEC_C_ACK_NACK_FEEDBACK) {
4448 /* scs (for ST4 and ST8) */
4449 scs_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_frameStructure_subcarrier_spacing, tvb, offset, 1, ENC_NA, &scs);
4451 else if (sectionType == SEC_C_RRM_MEAS_REPORTS || sectionType == SEC_C_REQUEST_RRM_MEAS) {
4452 /* reserved (4 bits) */
4453 proto_tree_add_item(section_tree, hf_oran_reserved_last_4bits, tvb, offset, 1, ENC_NA);
4455 else if (sectionType != SEC_C_LAA) {
4456 /* filterIndex (most common case) */
4457 proto_tree_add_item(section_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
4459 offset += 1;
4461 unsigned ref_a_offset = offset;
4462 /* frameId */
4463 uint32_t frameId = 0;
4464 proto_tree_add_item_ret_uint(section_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
4465 offset += 1;
4467 /* subframeId */
4468 uint32_t subframeId = 0;
4469 proto_tree_add_item_ret_uint(section_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
4470 /* slotId */
4471 uint32_t slotId = 0;
4472 proto_tree_add_item_ret_uint(section_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
4473 tap_info->slot = slotId;
4474 offset++;
4476 /* startSymbolId */
4477 uint32_t startSymbolId = 0;
4478 proto_item *ssid_ti = NULL;
4479 if ((sectionType == SEC_C_ACK_NACK_FEEDBACK) || /* Section Type 8 */
4480 (sectionType == SEC_C_SINR_REPORTING)) { /* Section Type 9 */
4481 /* symbolId */
4482 proto_tree_add_item(section_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA);
4484 else if (sectionType != SEC_C_LAA) {
4485 /* startSymbolId is in most section types */
4486 ssid_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_start_symbol_id, tvb, offset, 1, ENC_NA, &startSymbolId);
4487 if (startSymbolId && (sectionType == SEC_C_RRM_MEAS_REPORTS)) {
4488 proto_item_append_text(ssid_ti, " (should be 0 for ST10!)");
4489 expert_add_info_format(pinfo, ssid_ti, &ei_oran_st10_startsymbolid_not_0,
4490 "startSymbolId should be 0 for ST10 - found %u", startSymbolId);
4493 else {
4494 /* reserved (6 bits) */
4495 proto_tree_add_item(section_tree, hf_oran_reserved_last_6bits, tvb, offset, 1, ENC_NA);
4497 offset++;
4499 char id[16];
4500 snprintf(id, 16, "%d-%d-%d", frameId, subframeId, slotId);
4501 proto_item *pi = proto_tree_add_string(section_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
4502 proto_item_set_generated(pi);
4504 uint32_t cmd_scope = 0;
4505 bool st8_ready = false;
4507 /* numberOfSections (or whatever section has instead) */
4508 uint32_t nSections = 0;
4509 if (sectionType == SEC_C_SLOT_CONTROL) { /* Section Type 4 */
4510 /* Slot Control has these fields instead */
4511 /* reserved (4 bits) */
4512 proto_tree_add_item(section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
4513 /* cmdScope (4 bits) */
4514 proto_tree_add_item_ret_uint(section_tree, hf_oran_cmd_scope, tvb, offset, 1, ENC_NA, &cmd_scope);
4516 else if (sectionType == SEC_C_ACK_NACK_FEEDBACK) { /* Section Type 8 */
4517 /* reserved (7 bits) */
4518 proto_tree_add_item(section_tree, hf_oran_reserved_7bits, tvb, offset, 1, ENC_NA);
4519 /* ready (1 bit) */
4520 /* TODO: when set, ready in slotId+1.. */
4521 proto_tree_add_item_ret_boolean(section_tree, hf_oran_ready, tvb, offset, 1, ENC_NA, &st8_ready);
4522 if (!st8_ready) {
4523 /* SCS value is ignored, and may be set to any value by O-RU */
4524 proto_item_append_text(scs_ti, " (ignored)");
4527 else if (sectionType != SEC_C_LAA) {
4528 proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfSections, tvb, offset, 1, ENC_NA, &nSections);
4530 else {
4531 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
4533 offset++;
4535 /* sectionType */
4536 proto_tree_add_item_ret_uint(section_tree, hf_oran_sectionType, tvb, offset, 1, ENC_NA, &sectionType);
4537 offset += 1;
4539 /* Note this section type in stats */
4540 if (sectionType < SEC_C_MAX_INDEX) {
4541 tap_info->section_types[sectionType] = true;
4544 /* Section-specific fields (white entries in Section Type diagrams) */
4545 unsigned bit_width = 0;
4546 int comp_meth = 0;
4547 proto_item *comp_meth_ti;
4548 unsigned ci_comp_method = 0;
4549 uint8_t ci_comp_opt = 0;
4551 uint32_t num_ues = 0;
4552 uint32_t number_of_acks = 0, number_of_nacks = 0;
4554 uint32_t num_sinr_per_prb = 0;
4556 switch (sectionType) {
4557 case SEC_C_UNUSED_RB: /* Section Type 0 */
4558 /* timeOffset */
4559 proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
4560 offset += 2;
4561 /* frameStructure */
4562 offset = dissect_frame_structure(section_tree, tvb, offset,
4563 subframeId, slotId);
4565 /* cpLength */
4566 proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
4567 offset += 2;
4568 /* reserved */
4569 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
4570 offset += 1;
4571 break;
4573 case SEC_C_NORMAL: /* Section Type 1 */
4574 case SEC_C_UE_SCHED: /* Section Type 5 */
4575 /* udCompHdr */
4576 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
4577 (direction==1), /* ignore for DL */
4578 &bit_width, &comp_meth, &comp_meth_ti);
4579 /* reserved */
4580 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
4581 offset += 1;
4582 break;
4584 case SEC_C_SLOT_CONTROL: /* Section Type 4 */
4585 break;
4587 case SEC_C_PRACH: /* Section Type 3 */
4588 /* timeOffset */
4589 proto_tree_add_item(section_tree, hf_oran_timeOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
4590 offset += 2;
4591 /* frameStructure */
4592 offset = dissect_frame_structure(section_tree, tvb, offset,
4593 subframeId, slotId);
4594 /* cpLength */
4595 proto_tree_add_item(section_tree, hf_oran_cpLength, tvb, offset, 2, ENC_BIG_ENDIAN);
4596 offset += 2;
4597 /* udCompHdr */
4598 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset,
4599 (direction==1), /* ignore for DL */
4600 &bit_width, &comp_meth, &comp_meth_ti);
4601 break;
4603 case SEC_C_CH_INFO: /* Section Type 6 */
4604 /* numberOfUEs */
4605 proto_tree_add_item_ret_uint(section_tree, hf_oran_numberOfUEs, tvb, offset, 1, ENC_NA, &num_ues);
4606 offset += 1;
4607 /* ciCompHdr (was reserved) */
4608 offset = dissect_cicomphdr(tvb, pinfo, section_tree, offset, &bit_width, &ci_comp_method, &ci_comp_opt);
4610 /* Number of sections may not be filled in (at all, or correctly), so set to the number of UEs.
4611 The data entries are per-UE... they don't have a sectionID, but they could have section extensions... */
4612 if (nSections == 0 || num_ues > nSections) {
4613 nSections = num_ues;
4615 break;
4617 case SEC_C_RSVD2:
4618 break;
4620 case SEC_C_LAA: /* Section Type 7 */
4621 proto_tree_add_item(section_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4622 offset += 2;
4623 break;
4625 case SEC_C_ACK_NACK_FEEDBACK: /* Section Type 8 */
4626 /* numberOfAcks (1 byte) */
4627 proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_acks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_acks);
4628 offset += 1;
4629 /* numberOfNacks (1 byte) */
4630 proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_nacks, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_nacks);
4631 offset += 1;
4633 /* Show ACKs and NACKs. For both, try to link back to request. */
4634 for (unsigned int n=1; n <= number_of_acks; n++) {
4635 uint32_t ackid;
4636 proto_item *ack_ti;
4637 ack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_ackid, tvb, offset, 2, ENC_BIG_ENDIAN, &ackid);
4638 offset += 2;
4640 /* Look up request table in state (which really should be set by now, but test anyway). */
4641 if (state) {
4642 ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, ackid);
4643 if (request != NULL) {
4644 /* On first pass, update with this response */
4645 if (!PINFO_FD_VISITED(pinfo)) {
4646 request->response_frame_number = pinfo->num;
4647 request->response_frame_time = pinfo->abs_ts;
4650 /* Show request details */
4651 show_link_to_acknack_request(section_tree, tvb, pinfo, request);
4653 else {
4654 /* Request not found */
4655 expert_add_info_format(pinfo, ack_ti, &ei_oran_acknack_no_request,
4656 "Response for ackId=%u received, but no request found",
4657 ackid);
4661 for (unsigned int m=1; m <= number_of_nacks; m++) {
4662 uint32_t nackid;
4663 proto_item *nack_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_nackid, tvb, offset, 2, ENC_BIG_ENDIAN, &nackid);
4664 offset += 2;
4666 expert_add_info_format(pinfo, nack_ti, &ei_oran_st8_nackid,
4667 "Received Nack for ackNackId=%u",
4668 nackid);
4670 /* Look up request table in state. */
4671 if (state) {
4672 ack_nack_request_t *request = wmem_tree_lookup32(state->ack_nack_requests, nackid);
4673 if (request) {
4674 /* On first pass, update with this response */
4675 if (!PINFO_FD_VISITED(pinfo)) {
4676 request->response_frame_number = pinfo->num;
4677 request->response_frame_time = pinfo->abs_ts;
4680 /* Show request details */
4681 show_link_to_acknack_request(section_tree, tvb, pinfo, request);
4683 else {
4684 /* Request not found */
4685 expert_add_info_format(pinfo, nack_ti, &ei_oran_acknack_no_request,
4686 "Response for nackId=%u received, but no request found",
4687 nackid);
4691 break;
4693 case SEC_C_SINR_REPORTING: /* Section Type 9 */
4695 /* numSinrPerPrb (3 bits) */
4696 proto_item *nspp_ti;
4697 nspp_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_num_sinr_per_prb, tvb, offset, 1, ENC_BIG_ENDIAN, &num_sinr_per_prb);
4698 switch (num_sinr_per_prb) {
4699 case 0:
4700 num_sinr_per_prb = 1; break;
4701 case 1:
4702 num_sinr_per_prb = 2; break;
4703 case 2:
4704 num_sinr_per_prb = 3; break;
4705 case 3:
4706 num_sinr_per_prb = 4; break;
4707 case 4:
4708 num_sinr_per_prb = 6; break;
4709 case 5:
4710 num_sinr_per_prb = 12; break;
4712 default:
4713 proto_item_append_text(nspp_ti, " (invalid)");
4714 num_sinr_per_prb = 1;
4715 /* TODO: expert info? */
4718 /* reserved (13 bits) */
4719 proto_tree_add_item(section_tree, hf_oran_reserved_last_5bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4720 offset += 1;
4721 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4722 offset += 1;
4723 break;
4726 case SEC_C_RRM_MEAS_REPORTS:
4727 case SEC_C_REQUEST_RRM_MEAS:
4728 /* reserved (16 bits) */
4729 proto_tree_add_item(section_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4730 offset += 2;
4731 break;
4734 /* Update udCompHdr details in state for UL U-Plane */
4735 if (!PINFO_FD_VISITED(pinfo) && state && direction==0) {
4736 switch (sectionType) {
4737 case SEC_C_NORMAL: /* Section Type 1 */
4738 case SEC_C_PRACH: /* Section Type 3 */
4739 case SEC_C_UE_SCHED: /* Section Type 5 */
4740 state->ul_ud_comp_hdr_set = true;
4741 state->ul_ud_comp_hdr_bit_width = bit_width;
4742 state->ul_ud_comp_hdr_compression = comp_meth;
4743 break;
4744 default:
4745 break;
4750 proto_item_append_text(sectionHeading, "%d, %s, Frame: %d, Subframe: %d, Slot: %d, StartSymbol: %d",
4751 sectionType, val_to_str_const(direction, data_direction_vals, "Unknown"),
4752 frameId, subframeId, slotId, startSymbolId);
4753 write_pdu_label_and_info(protocol_item, NULL, pinfo, ", Type: %2d %s", sectionType,
4754 rval_to_str_const(sectionType, section_types_short, "Unknown"));
4756 /* Set actual length of C-Plane section header */
4757 proto_item_set_len(section_tree, offset - section_tree_offset);
4759 if (sectionType == SEC_C_ACK_NACK_FEEDBACK) {
4760 write_pdu_label_and_info(oran_tree, section_tree, pinfo,
4761 (st8_ready) ? " (Ready)" : " (ACK)");
4765 /* Section type 4 doesn't have normal sections, so deal with here before normal sections */
4766 if (sectionType == SEC_C_SLOT_CONTROL) {
4767 /* numberOfST4Cmds */
4768 uint32_t no_st4_cmds, st4_cmd_len, num_slots, ack_nack_req_id, st4_cmd_type;
4769 proto_item *no_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_number_of_st4_cmds,
4770 tvb, offset, 1, ENC_NA, &no_st4_cmds);
4771 if (no_st4_cmds == 0) {
4772 expert_add_info_format(pinfo, no_ti, &ei_oran_st4_no_cmds,
4773 "Not valid for ST4 to carry no commands");
4775 offset += 1;
4777 /* reserved (1 byte) */
4778 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4779 offset += 1;
4781 /* Loop over commands. Each has 8-byte common header, followed by cmd-specific payload */
4782 proto_item *len_ti;
4783 for (uint32_t n=0; n < no_st4_cmds; n++) {
4784 /* Table 7.4.6-2: Section Type 4 Command common header format */
4785 proto_item *hdr_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd_header,
4786 tvb, offset, 8, "",
4787 "Type 4 Command common header");
4788 proto_tree *hdr_tree = proto_item_add_subtree(hdr_ti, ett_oran_st4_cmd_header);
4790 /* st4CmdType */
4791 proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_type, tvb, offset, 1, ENC_NA, &st4_cmd_type);
4792 offset += 1;
4794 /* st4CmdLen */
4795 len_ti = proto_tree_add_item_ret_uint(hdr_tree, hf_oran_st4_cmd_len, tvb, offset, 2, ENC_NA, &st4_cmd_len);
4796 if (st4_cmd_len == 0) {
4797 /* Meaning of 0 not yet defined (v15.00) */
4798 proto_item_append_text(len_ti, " (reserved)");
4799 expert_add_info(pinfo, len_ti, &ei_oran_st4_zero_len_cmd);
4801 else {
4802 proto_item_append_text(len_ti, " (%u bytes)", st4_cmd_len*4);
4804 offset += 2;
4806 /* numSlots */
4807 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);
4808 if (num_slots == 0) {
4809 proto_item_append_text(slots_ti, " (until changed)");
4811 offset += 1;
4813 /* ackNackReqId */
4814 proto_item *ack_nack_req_id_ti;
4815 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);
4816 offset += 2;
4817 if (ack_nack_req_id == 0) {
4818 proto_item_append_text(ack_nack_req_id_ti, " (no Section type 8 response expected)");
4821 /* reserved (16 bits) */
4822 proto_tree_add_item(hdr_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
4823 offset += 2;
4825 /* Set common header summary */
4826 proto_item_append_text(hdr_ti, " (cmd=%s, len=%u, slots=%u, ackNackReqId=%u)",
4827 rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"),
4828 st4_cmd_len, num_slots, ack_nack_req_id);
4830 col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
4831 rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
4834 /* Subtree for this command body */
4835 proto_item *command_ti = proto_tree_add_string_format(section_tree, hf_oran_st4_cmd,
4836 tvb, offset, 0, "",
4837 "Type 4 Command (%s)", rval_to_str_const(st4_cmd_type, st4_cmd_type_vals, "Unknown"));
4838 proto_tree *command_tree = proto_item_add_subtree(command_ti, ett_oran_st4_cmd);
4840 unsigned command_start_offset = offset;
4842 /* Check fields compatible with chosen command. */
4843 if (st4_cmd_type==1) {
4844 if (num_slots != 0) {
4845 /* "the value of numSlots should be set to zero for this command type" */
4846 expert_add_info_format(pinfo, ssid_ti, &ei_oran_numslots_not_zero,
4847 "numSlots should be zero for ST4 command 1 - found %u",
4848 num_slots);
4852 if (st4_cmd_type==3 || st4_cmd_type==4) {
4853 if (startSymbolId != 0) {
4854 /* "expected reception window for the commands is the symbol zero reception window" */
4855 expert_add_info_format(pinfo, ssid_ti, &ei_oran_start_symbol_id_not_zero,
4856 "startSymbolId should be zero for ST4 commands 3&4 - found %u",
4857 startSymbolId);
4861 /* Add format for this command */
4862 switch (st4_cmd_type) {
4863 case 1: /* TIME_DOMAIN_BEAM_CONFIG */
4865 bool disable_tdbfns;
4866 uint32_t bfwcomphdr_iq_width, bfwcomphdr_comp_meth;
4868 /* reserved (2 bits) */
4869 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4870 /* symbolMask (14 bits) */
4871 uint32_t symbol_mask;
4872 proto_item *symbol_mask_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN, &symbol_mask);
4873 /* 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 */
4874 /* lsb is symbol 0 */
4875 for (unsigned s=0; s < 14; s++) {
4876 if ((startSymbolId & (1 << s)) && (startSymbolId > s)) {
4877 proto_item_append_text(symbol_mask_ti, " (startSymbolId is %u, so some lower symbol bits ignored!)", startSymbolId);
4878 /* TODO: expert info too? */
4879 break;
4882 offset += 2;
4884 /* disableTDBFNs */
4885 proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfns, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfns);
4887 /* tdBeamNum */
4888 proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4889 offset += 2;
4891 /* bfwCompHdr (2 subheaders - bfwIqWidth and bfwCompMeth)*/
4892 offset = dissect_bfwCompHdr(tvb, command_tree, offset,
4893 &bfwcomphdr_iq_width, &bfwcomphdr_comp_meth, &comp_meth_ti);
4894 /* reserved (3 bytes) */
4895 proto_tree_add_bits_item(command_tree, hf_oran_reserved, tvb, offset*8, 24, ENC_BIG_ENDIAN);
4896 offset += 3;
4898 if (disable_tdbfns) {
4899 /* No beamnum information to show so get out. */
4900 break;
4903 /* Read beam entries until reach end of command length */
4904 while ((offset - command_start_offset) < (st4_cmd_len * 4)) {
4906 /* disableTDBFWs */
4907 bool disable_tdbfws;
4908 proto_tree_add_item_ret_boolean(command_tree, hf_oran_disable_tdbfws, tvb, offset, 1, ENC_BIG_ENDIAN, &disable_tdbfws);
4910 /* tdBeamNum */
4911 proto_tree_add_item(command_tree, hf_oran_td_beam_num, tvb, offset, 2, ENC_BIG_ENDIAN);
4912 offset += 2;
4914 /* Showing BFWs? */
4915 if (!disable_tdbfws) {
4917 /* bfwCompParam */
4918 unsigned exponent = 0;
4919 bool supported = false;
4920 offset = dissect_bfwCompParam(tvb, command_tree, pinfo, offset,
4921 comp_meth_ti, bfwcomphdr_comp_meth, &exponent, &supported);
4923 /* Antenna count from preference */
4924 unsigned num_trx = pref_num_bf_antennas;
4925 int bit_offset = offset*8;
4927 for (unsigned trx=0; trx < num_trx; trx++) {
4928 /* Create antenna subtree */
4929 int bfw_offset = bit_offset / 8;
4930 proto_item *bfw_ti = proto_tree_add_string_format(command_tree, hf_oran_bfw,
4931 tvb, bfw_offset, 0, "", "TRX %3u: (", trx);
4932 proto_tree *bfw_tree = proto_item_add_subtree(bfw_ti, ett_oran_bfw);
4934 /* I value */
4935 /* Get bits, and convert to float. */
4936 uint32_t bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4937 float value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
4938 /* Add to tree. */
4939 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_i, tvb, bit_offset/8,
4940 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
4941 bit_offset += bfwcomphdr_iq_width;
4942 proto_item_append_text(bfw_ti, "I=%f ", value);
4944 /* Leave a gap between I and Q values */
4945 proto_item_append_text(bfw_ti, " ");
4947 /* Q value */
4948 /* Get bits, and convert to float. */
4949 bits = tvb_get_bits(tvb, bit_offset, bfwcomphdr_iq_width, ENC_BIG_ENDIAN);
4950 value = decompress_value(bits, bfwcomphdr_comp_meth, bfwcomphdr_iq_width, exponent);
4951 /* Add to tree. */
4952 proto_tree_add_float_format_value(bfw_tree, hf_oran_bfw_q, tvb, bit_offset/8,
4953 (bfwcomphdr_iq_width+7)/8, value, "%f", value);
4954 bit_offset += bfwcomphdr_iq_width;
4955 proto_item_append_text(bfw_ti, "Q=%f", value);
4957 proto_item_append_text(bfw_ti, ")");
4958 proto_item_set_len(bfw_ti, (bit_offset+7)/8 - bfw_offset);
4960 /* Need to round to next byte */
4961 offset = (bit_offset+7)/8;
4964 break;
4966 case 2: /* TDD_CONFIG_PATTERN */
4967 /* reserved (2 bits) */
4968 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4969 /* dirPattern (14 bits) */
4970 proto_tree_add_item(command_tree, hf_oran_dir_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
4971 offset += 2;
4973 /* reserved (2 bits) */
4974 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4975 /* guardPattern (14 bits) */
4976 proto_tree_add_item(command_tree, hf_oran_guard_pattern, tvb, offset, 2, ENC_BIG_ENDIAN);
4977 offset += 2;
4978 break;
4980 case 3: /* TRX_CONTROL */
4982 /* Only allowed cmdScope is ARRAY-COMMAND */
4983 if (cmd_scope != 0) {
4984 expert_add_info(pinfo, command_tree, &ei_oran_trx_control_cmd_scope);
4987 /* reserved (1 bit) */
4988 proto_tree_add_item(command_tree, hf_oran_reserved_1bit, tvb, offset, 1, ENC_BIG_ENDIAN);
4989 /* log2MaskBits (4 bits) */
4990 unsigned log2maskbits;
4991 proto_tree_add_item_ret_uint(command_tree, hf_oran_log2maskbits, tvb, offset, 1, ENC_BIG_ENDIAN, &log2maskbits);
4992 /* sleepMode */
4993 uint32_t sleep_mode;
4994 proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_trx, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
4995 offset += 1;
4997 /* reserved (4 bits) */
4998 proto_tree_add_item(command_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
4999 /* numSlotsExt (20 bits) */
5000 uint32_t num_slots_ext;
5001 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);
5002 if (num_slots==0 && num_slots_ext==0) {
5003 proto_item_append_text(num_slots_ext_ti, " (undefined sleep period)");
5005 else {
5006 /* Time should be rounded up according to SCS */
5007 float total = (float)(num_slots + num_slots_ext);
5008 /* From table 7.5.2.13-3 */
5009 float slot_length_by_scs[16] = { 1000, 500, 250, 125, 62.5, 31.25,
5010 0, 0, 0, 0, 0, 0, /* reserved */
5011 1000, 1000, 1000, 1000 };
5012 float slot_length = slot_length_by_scs[scs];
5013 /* Only using valid SCS. TODO: is this test ok? */
5014 if (slot_length != 0) {
5015 /* Round up to next slot */
5016 total = ((int)(total / slot_length) + 1) * slot_length;
5017 proto_item_append_text(num_slots_ext_ti, " (defined sleep period of %f us)", total);
5020 offset += 3;
5022 /* reserved (2 bits) */
5023 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5025 /* symbolMask (14 bits) */
5026 uint32_t symbol_mask;
5027 proto_item *sm_ti;
5028 sm_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN, &symbol_mask);
5029 if (symbol_mask == 0x0) {
5030 proto_item_append_text(sm_ti, " (wake)");
5031 col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
5033 else if (symbol_mask == 0x3fff) {
5034 proto_item_append_text(sm_ti, " (sleep)");
5035 col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
5037 else {
5038 expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
5039 "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
5040 sleep_mode, symbol_mask);
5042 offset += 2;
5044 /* antMask (16-2048 bits). Size is lookup from log2MaskBits enum.. */
5045 unsigned antmask_length = 2;
5046 if (log2maskbits >= 4) {
5047 antmask_length = (1 << log2maskbits) / 8;
5049 proto_item *ant_mask_ti = proto_tree_add_item(command_tree, hf_oran_antMask_trx_control, tvb, offset, antmask_length, ENC_NA);
5050 /* show count */
5051 unsigned antenna_count = 0;
5052 for (unsigned b=0; b < antmask_length; b++) {
5053 uint8_t byte = tvb_get_uint8(tvb, offset+b);
5054 for (unsigned bit=0; bit < 8; bit++) {
5055 if ((1 << bit) & byte) {
5056 antenna_count++;
5060 proto_item_append_text(ant_mask_ti, " (%u antennas)", antenna_count);
5061 offset += antmask_length;
5063 /* Pad to next 4-byte boundary */
5064 if (offset%4) {
5065 offset += (4-(offset%4));
5067 break;
5070 case 4: /* ASM (advanced sleep mode) */
5071 /* reserved (2+4=6 bits) */
5072 proto_tree_add_item(command_tree, hf_oran_reserved_6bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5073 /* sleepMode (2 bits) */
5074 uint32_t sleep_mode;
5075 proto_tree_add_item_ret_uint(command_tree, hf_oran_sleepmode_asm, tvb, offset, 1, ENC_BIG_ENDIAN, &sleep_mode);
5076 offset += 1;
5078 /* reserved (4 bits) */
5079 proto_tree_add_item(command_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5080 /* numSlotsExt (20 bits) */
5081 proto_tree_add_item(command_tree, hf_oran_num_slots_ext, tvb, offset, 3, ENC_BIG_ENDIAN);
5082 offset += 3;
5084 /* reserved (2 bits) */
5085 proto_tree_add_item(command_tree, hf_oran_reserved_2bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5086 /* symbolMask (14 bits) */
5087 uint32_t symbol_mask;
5088 proto_item *sm_ti;
5089 sm_ti = proto_tree_add_item_ret_uint(command_tree, hf_oran_symbolMask, tvb, offset, 2, ENC_BIG_ENDIAN, &symbol_mask);
5090 if (symbol_mask == 0x0) {
5091 proto_item_append_text(sm_ti, " (wake)");
5092 col_append_str(pinfo->cinfo, COL_INFO, " (wake)");
5094 else if (symbol_mask == 0x3fff) {
5095 proto_item_append_text(sm_ti, " (sleep)");
5096 col_append_str(pinfo->cinfo, COL_INFO, " (sleep)");
5098 else {
5099 expert_add_info_format(pinfo, sm_ti, &ei_oran_bad_symbolmask,
5100 "For non-zero sleepMode (%u), symbolMask should be 0x0 or 0x3fff - found 0x%05x",
5101 sleep_mode, symbol_mask);
5103 offset += 2;
5105 /* reserved (2 bytes) */
5106 proto_tree_add_item(command_tree, hf_oran_reserved_16bits, tvb, offset, 2, ENC_BIG_ENDIAN);
5107 offset += 2;
5108 break;
5110 default:
5111 /* Error! */
5112 expert_add_info_format(pinfo, len_ti, &ei_oran_st4_unknown_cmd,
5113 "Dissected ST4 command (%u) not recognised",
5114 st4_cmd_type);
5115 break;
5118 /* Check apparent size of padding (0-3 bytes ok) */
5119 long padding_remaining = command_start_offset + (st4_cmd_len * 4) - offset;
5120 if (padding_remaining < 0 || padding_remaining > 3) {
5121 expert_add_info_format(pinfo, len_ti, &ei_oran_st4_wrong_len_cmd,
5122 "Dissected ST4 command does not match signalled st4CmdLen - set to %u (%u bytes) but dissected %u bytes",
5123 st4_cmd_len, st4_cmd_len*4, offset-command_start_offset);
5126 /* Advance by signalled length (needs to be aligned on 4-byte boundary) */
5127 offset = command_start_offset + (st4_cmd_len * 4);
5129 /* Set end of command tree */
5130 proto_item_set_end(command_ti, tvb, offset);
5132 if (ack_nack_req_id != 0) {
5133 if (!PINFO_FD_VISITED(pinfo)) {
5134 /* Add this request into conversation state on first pass */
5135 ack_nack_request_t *request_details = wmem_new0(wmem_file_scope(), ack_nack_request_t);
5136 request_details->request_frame_number = pinfo->num;
5137 request_details->request_frame_time = pinfo->abs_ts;
5138 request_details->requestType = ST4Cmd1+st4_cmd_type-1;
5140 wmem_tree_insert32(state->ack_nack_requests,
5141 ack_nack_req_id,
5142 request_details);
5144 else {
5145 /* On later passes, try to link forward to ST8 response */
5146 ack_nack_request_t *response = wmem_tree_lookup32(state->ack_nack_requests,
5147 ack_nack_req_id);
5148 if (response) {
5149 show_link_to_acknack_response(section_tree, tvb, pinfo, response);
5155 /* LAA doesn't have sections either.. */
5156 else if (sectionType == SEC_C_LAA) { /* Section Type 7 */
5157 /* 7.2.5 Table 6.4-6 */
5158 unsigned mcot;
5159 proto_item *mcot_ti;
5161 /* laaMsgType */
5162 uint32_t laa_msg_type;
5163 proto_item *laa_msg_type_ti;
5164 laa_msg_type_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgType, tvb, offset, 1, ENC_NA, &laa_msg_type);
5165 /* laaMsgLen */
5166 uint32_t laa_msg_len;
5167 proto_item *len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_laaMsgLen, tvb, offset, 1, ENC_NA, &laa_msg_len);
5168 proto_item_append_text(len_ti, " (%u bytes)", 4*laa_msg_len);
5169 if (laa_msg_len == 0) {
5170 proto_item_append_text(len_ti, " (reserved)");
5172 offset += 1;
5174 int payload_offset = offset;
5176 /* Payload */
5177 switch (laa_msg_type) {
5178 case 0:
5179 /* LBT_PDSCH_REQ */
5180 /* lbtHandle (16 bits) */
5181 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5182 offset += 2;
5183 /* lbtOffset (10 bits) */
5184 proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
5185 offset += 1;
5186 /* lbtMode (2 bits) */
5187 proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
5188 /* reserved (1 bit) */
5189 proto_tree_add_item(section_tree, hf_oran_reserved_bit4, tvb, offset, 1, ENC_BIG_ENDIAN);
5190 /* lbtDeferFactor (3 bits) */
5191 proto_tree_add_item(section_tree, hf_oran_lbtDeferFactor, tvb, offset, 1, ENC_BIG_ENDIAN);
5192 offset += 1;
5193 /* lbtBackoffCounter (10 bits) */
5194 proto_tree_add_item(section_tree, hf_oran_lbtBackoffCounter, tvb, offset, 2, ENC_BIG_ENDIAN);
5195 offset += 1;
5196 /* MCOT (4 bits) */
5197 mcot_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_MCOT, tvb, offset, 1, ENC_BIG_ENDIAN, &mcot);
5198 if (mcot<1 || mcot>10) {
5199 proto_item_append_text(mcot_ti, " (should be in range 1-10!)");
5200 expert_add_info_format(pinfo, mcot_ti, &ei_oran_mcot_out_of_range,
5201 "MCOT seen with value %u (must be 1-10)", mcot);
5204 /* reserved (10 bits) */
5205 proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+6, 10, ENC_BIG_ENDIAN);
5206 break;
5207 case 1:
5208 /* LBT_DRS_REQ */
5209 /* lbtHandle (16 bits) */
5210 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5211 offset += 2;
5212 /* lbtOffset (10 bits) */
5213 proto_tree_add_item(section_tree, hf_oran_lbtOffset, tvb, offset, 2, ENC_BIG_ENDIAN);
5214 offset += 1;
5215 /* lbtMode (2 bits) */
5216 proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8+2, 2, ENC_BIG_ENDIAN);
5217 /* reserved (28 bits) */
5218 proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+4, 28, ENC_BIG_ENDIAN);
5219 break;
5220 case 2:
5221 /* LBT_PDSCH_RSP */
5222 /* lbtHandle (16 bits) */
5223 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5224 offset += 2;
5225 /* lbtPdschRes (2 bits) */
5226 proto_tree_add_item(section_tree, hf_oran_lbtPdschRes, tvb, offset, 1, ENC_BIG_ENDIAN);
5227 /* inParSF (1 bit) */
5228 proto_tree_add_item(section_tree, hf_oran_initialPartialSF, tvb, offset, 1, ENC_BIG_ENDIAN);
5229 /* sfStatus (1 bit) */
5230 proto_tree_add_item(section_tree, hf_oran_sfStatus, tvb, offset, 1, ENC_BIG_ENDIAN);
5231 /* sfnSf (12 bits) */
5232 proto_tree_add_item(section_tree, hf_oran_sfnSfEnd, tvb, offset, 2, ENC_BIG_ENDIAN);
5233 offset += 2;
5234 /* reserved (24 bits) */
5235 proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8), 24, ENC_BIG_ENDIAN);
5236 break;
5237 case 3:
5238 /* LBT_DRS_RSP */
5239 /* lbtHandle (16 bits) */
5240 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5241 offset += 2;
5242 /* lbtDrsRes (1 bit) */
5243 proto_tree_add_item(section_tree, hf_oran_lbtDrsRes, tvb, offset, 1, ENC_BIG_ENDIAN);
5244 /* reserved (7 bits) */
5245 proto_tree_add_item(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5246 break;
5247 case 4:
5248 /* LBT_Buffer_Error */
5249 /* lbtHandle (16 bits) */
5250 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5251 offset += 2;
5252 /* lbtBufErr (1 bit) */
5253 proto_tree_add_item(section_tree, hf_oran_lbtBufErr, tvb, offset, 1, ENC_BIG_ENDIAN);
5254 /* reserved (7 bits) */
5255 proto_tree_add_item(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5256 break;
5257 case 5:
5258 /* LBT_CWCONFIG_REQ */
5259 /* lbtHandle (16 bits) */
5260 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5261 offset += 2;
5262 /* lbtCWConfig_H (8 bits) */
5263 proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_H, tvb, offset, 1, ENC_BIG_ENDIAN);
5264 offset += 1;
5265 /* lbtCWConfig_T (8 bits) */
5266 proto_tree_add_item(section_tree, hf_oran_lbtCWConfig_T, tvb, offset, 1, ENC_BIG_ENDIAN);
5267 offset += 1;
5268 /* lbtMode (2 bits) */
5269 proto_tree_add_bits_item(section_tree, hf_oran_lbtMode, tvb, offset*8, 2, ENC_BIG_ENDIAN);
5270 /* lbtTrafficClass (3 bits) */
5271 proto_tree_add_item(section_tree, hf_oran_lbtTrafficClass, tvb, offset, 1, ENC_BIG_ENDIAN);
5272 /* reserved (19 bits) */
5273 proto_tree_add_bits_item(section_tree, hf_oran_reserved, tvb, (offset*8)+5, 19, ENC_BIG_ENDIAN);
5274 break;
5275 case 6:
5276 /* LBT_CWCONFIG_RSP */
5277 /* lbtHandle (16 bits) */
5278 proto_tree_add_item(section_tree, hf_oran_lbtHandle, tvb, offset, 2, ENC_BIG_ENDIAN);
5279 offset += 2;
5280 /* lbtCWR_Rst (1 bit) */
5281 proto_tree_add_item(section_tree, hf_oran_lbtCWR_Rst, tvb, offset, 1, ENC_BIG_ENDIAN);
5282 /* reserved (7 bits) */
5283 proto_tree_add_item(section_tree, hf_oran_reserved_last_7bits, tvb, offset, 1, ENC_BIG_ENDIAN);
5284 break;
5286 default:
5287 /* Unhandled! */
5288 expert_add_info_format(pinfo, laa_msg_type_ti, &ei_oran_laa_msg_type_unsupported,
5289 "laaMsgType %u not supported by dissector",
5290 laa_msg_type);
5292 break;
5294 /* For now just skip indicated length of bytes */
5295 offset = payload_offset + 4*(laa_msg_len+1);
5299 /* Dissect each C section */
5300 for (uint32_t i = 0; i < nSections; ++i) {
5301 tvbuff_t *section_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, -1);
5302 offset += dissect_oran_c_section(section_tvb, oran_tree, pinfo, state, sectionType, tap_info,
5303 protocol_item,
5304 subframeId, slotId,
5305 bit_width, ci_comp_method, ci_comp_opt,
5306 num_sinr_per_prb);
5309 /* Expert error if we are short of tvb by > 3 bytes */
5310 if (tvb_reported_length_remaining(tvb, offset) > 3) {
5311 expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
5312 "%u bytes remain at end of frame - should be 0-3",
5313 tvb_reported_length_remaining(tvb, offset));
5316 return tvb_captured_length(tvb);
5319 static int dissect_oran_u_re(tvbuff_t *tvb, proto_tree *tree,
5320 unsigned sample_number, int samples_offset,
5321 unsigned sample_bit_width,
5322 int comp_meth,
5323 uint32_t exponent)
5325 /* I */
5326 unsigned i_bits = tvb_get_bits(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
5327 float i_value = decompress_value(i_bits, comp_meth, sample_bit_width, exponent);
5328 unsigned sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
5329 proto_item *i_ti = proto_tree_add_float(tree, hf_oran_iSample, tvb, samples_offset/8, sample_len_in_bytes, i_value);
5330 proto_item_set_text(i_ti, "iSample: % 0.7f 0x%04x (RE-%2u in the PRB)", i_value, i_bits, sample_number);
5331 samples_offset += sample_bit_width;
5332 /* Q */
5333 unsigned q_bits = tvb_get_bits(tvb, samples_offset, sample_bit_width, ENC_BIG_ENDIAN);
5334 float q_value = decompress_value(q_bits, comp_meth, sample_bit_width, exponent);
5335 sample_len_in_bytes = ((samples_offset%8)+sample_bit_width+7)/8;
5336 proto_item *q_ti = proto_tree_add_float(tree, hf_oran_qSample, tvb, samples_offset/8, sample_len_in_bytes, q_value);
5337 proto_item_set_text(q_ti, "qSample: % 0.7f 0x%04x (RE-%2u in the PRB)", q_value, q_bits, sample_number);
5338 samples_offset += sample_bit_width;
5340 return samples_offset;
5344 static bool udcomplen_appears_present(bool udcomphdr_present, tvbuff_t *tvb, int offset)
5346 if (!udcomplen_heuristic_result_set) {
5347 /* All sections will start the same way */
5348 unsigned int section_bytes_before_field = (udcomphdr_present) ? 6 : 4;
5350 /* Move offset back to the start of the section */
5351 offset -= section_bytes_before_field;
5353 do {
5354 /* This field appears several bytes into the U-plane section */
5355 uint32_t length_remaining = tvb_reported_length_remaining(tvb, offset);
5356 /* Are there enough bytes to still read the length field? */
5357 if (section_bytes_before_field+2 > length_remaining) {
5358 udcomplen_heuristic_result = false;
5359 udcomplen_heuristic_result_set = true;
5360 break;
5363 /* Read the length field */
5364 uint16_t udcomplen = tvb_get_ntohs(tvb, offset+section_bytes_before_field);
5366 /* Is this less than a valid section? Realistic minimal section will be bigger than this..
5367 * Could take into account numPrbU, etc */
5368 if (udcomplen < section_bytes_before_field+2) {
5369 udcomplen_heuristic_result = false;
5370 udcomplen_heuristic_result_set = true;
5371 break;
5374 /* Does this section fit into the frame? */
5375 if (udcomplen > length_remaining) {
5376 udcomplen_heuristic_result = false;
5377 udcomplen_heuristic_result_set = true;
5378 break;
5381 /* Move past this section */
5382 offset += udcomplen;
5384 /* Are we at the end of the frame? */
5385 /* TODO: if frame is less than 60 bytes, there may be > 4 bytes, likely zeros.. */
5386 if (tvb_reported_length_remaining(tvb, offset) < 4) {
5387 udcomplen_heuristic_result = true;
5388 udcomplen_heuristic_result_set = true;
5390 } while (!udcomplen_heuristic_result_set);
5392 return udcomplen_heuristic_result;
5395 static bool at_udcomphdr(tvbuff_t *tvb, int offset)
5397 if (tvb_captured_length_remaining(tvb, offset) < 2) {
5398 return false;
5400 uint8_t first_byte = tvb_get_uint8(tvb, offset);
5401 uint8_t reserved_byte = tvb_get_uint8(tvb, offset+1);
5403 /* - iq width could be anything, though unlikely to be signalled as (say) < 1-3? */
5404 /* - meth should be 0-8 */
5405 /* - reserved byte should be 0 */
5406 return (((first_byte & 0x0f) <= MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS) && (reserved_byte == 0));
5409 static bool udcomphdr_appears_present(flow_state_t *flow, uint32_t direction, tvbuff_t *tvb, int offset)
5411 /* Should really not happen, but guard against this anyway. */
5412 if (flow == NULL) {
5413 /* No state to update. */
5414 return false;
5417 if (direction == DIR_UPLINK) {
5418 if (flow->udcomphdrUplink_heuristic_result_set) {
5419 /* Return cached value */
5420 return flow->udcomphdrUplink_heuristic_result;
5422 else {
5423 /* Work it out, and save answer for next time */
5424 flow->udcomphdrUplink_heuristic_result_set = true;
5425 flow->udcomphdrUplink_heuristic_result = at_udcomphdr(tvb, offset);
5426 return flow->udcomphdrUplink_heuristic_result;
5429 else {
5430 /* Downlink */
5431 if (flow->udcomphdrDownlink_heuristic_result_set) {
5432 /* Return cached value */
5433 return flow->udcomphdrDownlink_heuristic_result;
5435 else {
5436 /* Work it out, and save answer for next time */
5437 flow->udcomphdrDownlink_heuristic_result_set = true;
5438 flow->udcomphdrDownlink_heuristic_result = at_udcomphdr(tvb, offset);
5439 return flow->udcomphdrDownlink_heuristic_result;
5444 /* User plane dissector (section 8) */
5445 static int
5446 dissect_oran_u(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5447 oran_tap_info *tap_info, void *data _U_)
5449 /* Hidden filter for plane */
5450 proto_item *plane_ti = proto_tree_add_item(tree, hf_oran_uplane, tvb, 0, 0, ENC_NA);
5451 PROTO_ITEM_SET_HIDDEN(plane_ti);
5453 /* Set up structures needed to add the protocol subtree and manage it */
5454 int offset = 0;
5456 col_set_str(pinfo->cinfo, COL_PROTOCOL, "O-RAN-FH-U");
5457 col_set_str(pinfo->cinfo, COL_INFO, "U-Plane");
5459 tap_info->userplane = true;
5461 /* Create display subtree for the protocol */
5462 proto_item *protocol_item = proto_tree_add_item(tree, proto_oran, tvb, 0, -1, ENC_NA);
5463 proto_item_append_text(protocol_item, "-U");
5464 proto_tree *oran_tree = proto_item_add_subtree(protocol_item, ett_oran);
5466 /* Transport header */
5467 /* Real-time control data / IQ data transfer message series identifier */
5468 uint16_t eAxC;
5469 addPcOrRtcid(tvb, oran_tree, &offset, hf_oran_ecpri_pcid, &eAxC);
5470 tap_info->eaxc = eAxC;
5472 /* Message identifier */
5473 uint8_t seq_id;
5474 proto_item *seq_id_ti;
5475 offset = addSeqid(tvb, oran_tree, offset, ORAN_U_PLANE, &seq_id, &seq_id_ti);
5477 /* Common header for time reference */
5478 proto_item *timingHeader = proto_tree_add_string_format(oran_tree, hf_oran_timing_header,
5479 tvb, offset, 4, "", "Timing Header (");
5480 proto_tree *timing_header_tree = proto_item_add_subtree(timingHeader, ett_oran_u_timing);
5482 /* dataDirection */
5483 uint32_t direction;
5484 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_data_direction, tvb, offset, 1, ENC_NA, &direction);
5485 tap_info->uplink = (direction==0);
5486 /* payloadVersion */
5487 dissect_payload_version(timing_header_tree, tvb, pinfo, offset);
5488 /* filterIndex */
5489 proto_tree_add_item(timing_header_tree, hf_oran_filter_index, tvb, offset, 1, ENC_NA);
5490 offset += 1;
5492 int ref_a_offset = offset;
5494 /* frameId */
5495 uint32_t frameId = 0;
5496 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_frame_id, tvb, offset, 1, ENC_NA, &frameId);
5497 offset += 1;
5499 /* subframeId */
5500 uint32_t subframeId = 0;
5501 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_subframe_id, tvb, offset, 1, ENC_NA, &subframeId);
5502 /* slotId */
5503 uint32_t slotId = 0;
5504 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_slot_id, tvb, offset, 2, ENC_BIG_ENDIAN, &slotId);
5505 tap_info->slot = slotId;
5506 offset++;
5507 /* symbolId */
5508 uint32_t symbolId = 0;
5509 proto_tree_add_item_ret_uint(timing_header_tree, hf_oran_symbolId, tvb, offset, 1, ENC_NA, &symbolId);
5510 offset++;
5512 char id[16];
5513 snprintf(id, 16, "%d-%d-%d", frameId, subframeId, slotId);
5514 proto_item *pi = proto_tree_add_string(timing_header_tree, hf_oran_refa, tvb, ref_a_offset, 3, id);
5515 proto_item_set_generated(pi);
5517 proto_item_append_text(timingHeader, "%s, Frame: %d, Subframe: %d, Slot: %d, Symbol: %d)",
5518 val_to_str_const(direction, data_direction_vals, "Unknown"), frameId, subframeId, slotId, symbolId);
5520 unsigned sample_bit_width;
5521 int compression;
5522 int includeUdCompHeader;
5524 /* Update/report status of conversation */
5525 uint32_t key = make_flow_key(eAxC, ORAN_U_PLANE);
5526 flow_state_t* state = (flow_state_t*)wmem_tree_lookup32(flow_states_table, key);
5528 if (!PINFO_FD_VISITED(pinfo)) {
5529 /* Create conversation if doesn't exist yet */
5530 if (!state) {
5531 /* Allocate new state */
5532 state = wmem_new0(wmem_file_scope(), flow_state_t);
5533 state->ack_nack_requests = wmem_tree_new(wmem_epan_scope());
5534 wmem_tree_insert32(flow_states_table, key, state);
5537 /* Check sequence analysis status */
5538 if (state->last_frame_seen[direction] && (seq_id != state->next_expected_sequence_number[direction])) {
5539 /* Store this result */
5540 flow_result_t *result = wmem_new0(wmem_file_scope(), flow_result_t);
5541 result->unexpected_seq_number = true;
5542 result->expected_sequence_number = state->next_expected_sequence_number[direction];
5543 result->previous_frame = state->last_frame[direction];
5544 wmem_tree_insert32(flow_results_table, pinfo->num, result);
5546 /* Update sequence analysis state */
5547 state->last_frame[direction] = pinfo->num;
5548 state->last_frame_seen[direction] = true;
5549 state->next_expected_sequence_number[direction] = (seq_id+1) % 256;
5552 /* Show any issues associated with this frame number */
5553 flow_result_t *result = wmem_tree_lookup32(flow_results_table, pinfo->num);
5554 if (result) {
5555 if (result->unexpected_seq_number) {
5556 expert_add_info_format(pinfo, seq_id_ti, &ei_oran_uplane_unexpected_sequence_number,
5557 "Sequence number %u expected, but got %u",
5558 result->expected_sequence_number, seq_id);
5559 tap_info->missing_sns = (seq_id - result->expected_sequence_number) % 256;
5560 /* TODO: could add previous/next frame (in seqId tree?) ? */
5564 /* Look up preferences for samples */
5565 if (direction == DIR_UPLINK) {
5566 sample_bit_width = pref_sample_bit_width_uplink;
5567 compression = pref_iqCompressionUplink;
5568 includeUdCompHeader = pref_includeUdCompHeaderUplink;
5569 } else {
5570 sample_bit_width = pref_sample_bit_width_downlink;
5571 compression = pref_iqCompressionDownlink;
5572 includeUdCompHeader = pref_includeUdCompHeaderDownlink;
5575 /* If uplink, load any udCompHdr settings written by C-Plane */
5576 bool ud_cmp_hdr_cplane = false;
5577 if (state && direction == 0) {
5578 /* Initialise settings from udpCompHdr from C-Plane */
5579 if (state->ul_ud_comp_hdr_set) {
5580 sample_bit_width = state->ul_ud_comp_hdr_bit_width;
5581 compression = state->ul_ud_comp_hdr_compression;
5583 ud_cmp_hdr_cplane = true;
5587 /* Need a valid value (e.g. 9, 14). 0 definitely won't work, as won't progress around loop! */
5588 /* N.B. may yet be overwritten by udCompHdr settings in sections below! */
5589 if (sample_bit_width == 0) {
5590 expert_add_info_format(pinfo, protocol_item, &ei_oran_invalid_sample_bit_width,
5591 "%cL Sample bit width from %s (%u) not valid, so can't decode sections",
5592 (direction == DIR_UPLINK) ? 'U' : 'D',
5593 !ud_cmp_hdr_cplane ? "preference" : "C-Plane",
5594 sample_bit_width);
5595 return offset;
5598 unsigned bytesLeft;
5599 unsigned number_of_sections = 0;
5600 unsigned nBytesPerPrb =0;
5602 /* Add each section (no count, just keep parsing until payload used) */
5603 do {
5604 /* Section subtree */
5605 unsigned section_start_offset = offset;
5606 proto_item *sectionHeading = proto_tree_add_string_format(oran_tree, hf_oran_u_section,
5607 tvb, offset, 0, "", "Section");
5608 proto_tree *section_tree = proto_item_add_subtree(sectionHeading, ett_oran_u_section);
5610 /* Section Header fields (darker green part) */
5612 /* sectionId */
5613 uint32_t sectionId = 0;
5614 proto_item *ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_section_id, tvb, offset, 2, ENC_BIG_ENDIAN, &sectionId);
5615 if (sectionId == 4095) {
5616 proto_item_append_text(ti, " (not default coupling C/U planes using sectionId)");
5618 offset++;
5619 /* rb */
5620 uint32_t rb;
5621 proto_tree_add_item_ret_uint(section_tree, hf_oran_rb, tvb, offset, 1, ENC_NA, &rb);
5622 /* symInc */
5623 proto_tree_add_item(section_tree, hf_oran_symInc, tvb, offset, 1, ENC_NA);
5624 /* startPrbu */
5625 uint32_t startPrbu = 0;
5626 proto_tree_add_item_ret_uint(section_tree, hf_oran_startPrbu, tvb, offset, 2, ENC_BIG_ENDIAN, &startPrbu);
5627 offset += 2;
5629 /* numPrbu */
5630 uint32_t numPrbu = 0;
5631 proto_tree_add_item_ret_uint(section_tree, hf_oran_numPrbu, tvb, offset, 1, ENC_NA, &numPrbu);
5632 offset += 1;
5634 proto_item *ud_comp_meth_item, *ud_comp_len_ti=NULL;
5635 uint32_t ud_comp_len;
5637 /* udCompHdr (if preferences indicate will be present) */
5638 bool included = (includeUdCompHeader==1) ||
5639 (includeUdCompHeader==2 && udcomphdr_appears_present(state, direction, tvb, offset));
5640 if (included) {
5641 /* 7.5.2.10 */
5642 /* Extract these values to inform how wide IQ samples in each PRB will be. */
5643 offset = dissect_udcomphdr(tvb, pinfo, section_tree, offset, false, &sample_bit_width,
5644 &compression, &ud_comp_meth_item);
5646 /* Not part of udCompHdr */
5647 proto_tree_add_item(section_tree, hf_oran_reserved_8bits, tvb, offset, 1, ENC_NA);
5648 offset += 1;
5650 else {
5651 /* No fields to dissect - just showing comp values from prefs */
5652 /* iqWidth */
5653 proto_item *iq_width_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrIqWidth_pref, tvb, 0, 0, sample_bit_width);
5654 proto_item_append_text(iq_width_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
5655 proto_item_set_generated(iq_width_item);
5657 /* udCompMethod */
5658 ud_comp_meth_item = proto_tree_add_uint(section_tree, hf_oran_udCompHdrMeth_pref, tvb, 0, 0, compression);
5659 proto_item_append_text(ud_comp_meth_item, (ud_cmp_hdr_cplane) ? " (from c-plane)" : " (from preferences)");
5660 proto_item_set_generated(ud_comp_meth_item);
5663 /* Not supported! TODO: other places where comp method is looked up (e.g., bfw?) */
5664 switch (compression) {
5665 case COMP_NONE:
5666 case COMP_BLOCK_FP:
5667 case BFP_AND_SELECTIVE_RE:
5668 break;
5669 default:
5670 expert_add_info_format(pinfo, ud_comp_meth_item, &ei_oran_unsupported_compression_method,
5671 "Compression method %u (%s) not supported by dissector",
5672 compression,
5673 rval_to_str_const(compression, ud_comp_header_meth, "reserved"));
5676 /* udCompLen (when supported, methods 5,6,7,8) */
5677 if (compression >= BFP_AND_SELECTIVE_RE) {
5678 bool supported = (pref_support_udcompLen==1) || /* supported */
5679 (pref_support_udcompLen==2 && udcomplen_appears_present(includeUdCompHeader, tvb, offset));
5681 if (supported) {
5682 ud_comp_len_ti = proto_tree_add_item_ret_uint(section_tree, hf_oran_udCompLen, tvb, offset, 2, ENC_NA, &ud_comp_len);
5683 if (ud_comp_len <= 1) {
5684 proto_item_append_text(ud_comp_len_ti, " (reserved)");
5686 /* TODO: report if less than a viable section in frame? */
5687 /* Check that there is this much length left in the frame */
5688 if ((int)ud_comp_len > tvb_reported_length_remaining(tvb, section_start_offset)) {
5689 expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
5690 "udCompLen indicates %u bytes in section, but only %u are left in frame",
5691 ud_comp_len, tvb_reported_length_remaining(tvb, section_start_offset));
5693 /* Actual length of section will be checked below, at the end of the section */
5694 offset += 2;
5698 /* sReSMask1 + sReSMask2 (depends upon compression method) */
5699 uint64_t sresmask1=0, sresmask2=0;
5700 if (compression == BFP_AND_SELECTIVE_RE_WITH_MASKS ||
5701 compression == MOD_COMPR_AND_SELECTIVE_RE_WITH_MASKS)
5703 static int * const sres_mask1_2_flags[] = {
5704 &hf_oran_sReSMask1_2_re12,
5705 &hf_oran_sReSMask1_2_re11,
5706 &hf_oran_sReSMask1_2_re10,
5707 &hf_oran_sReSMask1_2_re9,
5708 &hf_oran_sReSMask_re8,
5709 &hf_oran_sReSMask_re7,
5710 &hf_oran_sReSMask_re6,
5711 &hf_oran_sReSMask_re5,
5712 &hf_oran_sReSMask_re4,
5713 &hf_oran_sReSMask_re3,
5714 &hf_oran_sReSMask_re2,
5715 &hf_oran_sReSMask_re1,
5716 NULL
5719 /* reserved (4 bits) */
5720 proto_tree_add_item(section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
5721 /* sReSMask1 (12 bits) */
5722 proto_item *sresmask_ti;
5723 sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
5724 hf_oran_sReSMask1,
5725 ett_oran_sresmask,
5726 sres_mask1_2_flags,
5727 ENC_NA,
5728 &sresmask1);
5729 offset += 2;
5730 /* Count REs present */
5731 unsigned res = 0;
5732 for (unsigned n=0; n < 12; n++) {
5733 if ((sresmask1 >> n) & 0x1) {
5734 res++;
5737 proto_item_append_text(sresmask_ti, " (%u REs)", res);
5740 /* reserved (4 bits) */
5741 proto_tree_add_item(section_tree, hf_oran_reserved_4bits, tvb, offset, 1, ENC_NA);
5742 /* sReSMask2 (12 bits) */
5743 sresmask_ti = proto_tree_add_bitmask_ret_uint64(section_tree, tvb, offset,
5744 hf_oran_sReSMask2,
5745 ett_oran_sresmask,
5746 sres_mask1_2_flags,
5747 ENC_NA,
5748 &sresmask2);
5749 offset += 2;
5751 if (rb == 1) {
5752 proto_item_append_text(sresmask_ti, " (ignored)");
5753 if (sresmask2 != 0) {
5754 expert_add_info(pinfo, ud_comp_len_ti, &ei_oran_sresmask2_not_zero_with_rb);
5757 else {
5758 /* Count REs present */
5759 res = 0;
5760 for (unsigned n=0; n < 12; n++) {
5761 if ((sresmask2 >> n) & 0x1) {
5762 res++;
5765 proto_item_append_text(sresmask_ti, " (%u REs)", res);
5769 write_section_info(sectionHeading, pinfo, protocol_item, sectionId, startPrbu, numPrbu, rb);
5771 /* TODO: should this use the same pref as c-plane? */
5772 if (numPrbu == 0) {
5773 /* Special case for all PRBs (NR: the total number of PRBs may be > 255) */
5774 numPrbu = pref_data_plane_section_total_rbs;
5775 startPrbu = 0; /* may already be 0... */
5778 /* Add each PRB */
5779 for (unsigned i = 0; i < numPrbu; i++) {
5780 /* Create subtree */
5781 proto_item *prbHeading = proto_tree_add_string_format(section_tree, hf_oran_samples_prb,
5782 tvb, offset, 0,
5783 "", "PRB");
5784 proto_tree *rb_tree = proto_item_add_subtree(prbHeading, ett_oran_u_prb);
5785 uint32_t exponent = 0;
5786 uint16_t sresmask = 0;
5788 /* udCompParam (depends upon compression method) */
5789 int before = offset;
5790 offset = dissect_udcompparam(tvb, pinfo, rb_tree, offset, compression, &exponent, &sresmask, false);
5791 int udcompparam_len = offset-before;
5793 /* Show PRB number in root */
5794 proto_item_append_text(prbHeading, " %3u", startPrbu + i*(1+rb));
5796 /* Work out how many REs / PRB */
5797 unsigned res_per_prb = 12;
5798 uint16_t sresmask_to_use = 0x0fff;
5800 if (compression >= BFP_AND_SELECTIVE_RE) {
5801 /* Work out which mask should be used */
5802 if (compression==BFP_AND_SELECTIVE_RE || compression==MOD_COMPR_AND_SELECTIVE_RE) {
5803 /* Selective RE cases, use value from compModParam */
5804 sresmask_to_use = (uint16_t)sresmask;
5806 else {
5807 /* With masks (in section). Choose between sresmask1 and sresmask2 */
5808 if (rb==1 || (i%1)==0) {
5809 /* Even values */
5810 sresmask_to_use = (uint16_t)sresmask1;
5812 else {
5813 /* Odd values */
5814 sresmask_to_use = (uint16_t)sresmask2;
5818 /* Count REs present using sresmask */
5819 res_per_prb = 0;
5820 /* Use sresmask to pick out which REs are present */
5821 for (unsigned n=0; n<12; n++) {
5822 if (sresmask_to_use & (1<<n)) {
5823 res_per_prb++;
5828 /* N.B. bytes for samples need to be padded out to next byte
5829 (certainly where there aren't 12 REs in PRB..) */
5830 unsigned nBytesForSamples = (sample_bit_width * res_per_prb * 2 + 7) / 8;
5831 nBytesPerPrb = nBytesForSamples + udcompparam_len;
5833 proto_tree_add_item(rb_tree, hf_oran_iq_user_data, tvb, offset, nBytesForSamples, ENC_NA);
5835 /* Optionally trying to show I/Q RE values */
5836 if (pref_showIQSampleValues) {
5837 /* Individual values */
5838 unsigned samples_offset = offset*8;
5839 unsigned samples = 0;
5841 if (compression >= BFP_AND_SELECTIVE_RE) {
5842 /* Use sresmask to pick out which REs are present */
5843 for (unsigned n=1; n<=12; n++) {
5844 if (sresmask_to_use & (1<<(n-1))) {
5845 samples_offset = dissect_oran_u_re(tvb, rb_tree,
5846 n, samples_offset, sample_bit_width, compression, exponent);
5847 samples++;
5851 else {
5852 /* All 12 REs are present */
5853 for (unsigned n=1; n<=12; n++) {
5854 samples_offset = dissect_oran_u_re(tvb, rb_tree,
5855 n, samples_offset, sample_bit_width, compression, exponent);
5856 samples++;
5859 proto_item_append_text(prbHeading, " (%u REs)", samples);
5862 /* Advance past samples */
5863 offset += nBytesForSamples;
5865 /* Set end of prb subtree */
5866 proto_item_set_end(prbHeading, tvb, offset);
5869 /* Set extent of section */
5870 proto_item_set_len(sectionHeading, offset-section_start_offset);
5871 if (ud_comp_len_ti != NULL && ((offset-section_start_offset != ud_comp_len))) {
5872 expert_add_info_format(pinfo, ud_comp_len_ti, &ei_oran_ud_comp_len_wrong_size,
5873 "udCompLen indicates %u bytes in section, but dissected %u instead",
5874 ud_comp_len, offset-section_start_offset);
5877 bytesLeft = tvb_captured_length(tvb) - offset;
5878 number_of_sections++;
5879 } while (bytesLeft >= (4 + nBytesPerPrb)); /* FIXME: bad heuristic */
5881 /* Show number of sections found */
5882 proto_item *ti = proto_tree_add_uint(oran_tree, hf_oran_numberOfSections, tvb, 0, 0, number_of_sections);
5883 proto_item_set_generated(ti);
5885 /* Expert error if we are short of tvb by > 3 bytes */
5886 if (tvb_reported_length_remaining(tvb, offset) > 3) {
5887 expert_add_info_format(pinfo, protocol_item, &ei_oran_frame_length,
5888 "%u bytes remain at end of frame - should be 0-3",
5889 tvb_reported_length_remaining(tvb, offset));
5892 return tvb_captured_length(tvb);
5896 /**********************************************************************/
5897 /* Main dissection function. */
5898 /* N.B. ecpri message type passed in as 'data' arg by eCPRI dissector */
5899 static int
5900 dissect_oran(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
5902 uint32_t ecpri_message_type = *(uint32_t *)data;
5903 int offset = 0;
5905 /* Allocate and zero tap struct */
5906 oran_tap_info *tap_info = wmem_new0(wmem_file_scope(), oran_tap_info);
5908 switch (ecpri_message_type) {
5909 case ECPRI_MT_IQ_DATA:
5910 offset = dissect_oran_u(tvb, pinfo, tree, tap_info, data);
5911 break;
5912 case ECPRI_MT_RT_CTRL_DATA:
5913 offset = dissect_oran_c(tvb, pinfo, tree, tap_info, data);
5914 break;
5915 default:
5916 /* Not dissecting other types - assume these are handled by eCPRI dissector */
5917 return 0;
5920 tap_queue_packet(oran_tap, pinfo, tap_info);
5922 return offset;
5925 static void oran_init_protocol(void)
5927 udcomplen_heuristic_result_set = false;
5928 udcomplen_heuristic_result = false;
5932 /* Register the protocol with Wireshark. */
5933 void
5934 proto_register_oran(void)
5936 static hf_register_info hf[] = {
5938 /* Section 5.1.3.2.7 */
5939 { &hf_oran_du_port_id,
5940 { "DU Port ID", "oran_fh_cus.du_port_id",
5941 FT_UINT16, BASE_DEC,
5942 NULL, 0x0,
5943 "Width set in dissector preference", HFILL }
5946 /* Section 5.1.3.2.7 */
5947 { &hf_oran_bandsector_id,
5948 { "BandSector ID", "oran_fh_cus.bandsector_id",
5949 FT_UINT16, BASE_DEC,
5950 NULL, 0x0,
5951 "Width set in dissector preference", HFILL }
5954 /* Section 5.1.3.2.7 */
5955 { &hf_oran_cc_id,
5956 { "CC ID", "oran_fh_cus.cc_id",
5957 FT_UINT16, BASE_DEC,
5958 NULL, 0x0,
5959 "Width set in dissector preference", HFILL }
5962 /* Section 5.1.3.2.7 */
5963 { &hf_oran_ru_port_id,
5964 { "RU Port ID", "oran_fh_cus.ru_port_id",
5965 FT_UINT16, BASE_DEC,
5966 NULL, 0x0,
5967 "Width set in dissector preference", HFILL }
5970 /* Section 5.1.3.2.8 */
5971 { &hf_oran_sequence_id,
5972 { "Sequence ID", "oran_fh_cus.sequence_id",
5973 FT_UINT8, BASE_DEC,
5974 NULL, 0x0,
5975 "The Sequence ID wraps around individually per eAxC", HFILL }
5978 /* Section 5.1.3.2.8 */
5979 { &hf_oran_e_bit,
5980 { "E Bit", "oran_fh_cus.e_bit",
5981 FT_UINT8, BASE_DEC,
5982 VALS(e_bit), 0x80,
5983 "Indicate the last message of a subsequence (U-Plane only)", HFILL }
5986 /* Section 5.1.3.2.8 */
5987 { &hf_oran_subsequence_id,
5988 { "Subsequence ID", "oran_fh_cus.subsequence_id",
5989 FT_UINT8, BASE_DEC,
5990 NULL, 0x7f,
5991 "The subsequence ID (for eCPRI layer fragmentation)", HFILL }
5994 /* Section 7.5.2.1 */
5995 { &hf_oran_data_direction,
5996 { "Data Direction", "oran_fh_cus.data_direction",
5997 FT_UINT8, BASE_DEC,
5998 VALS(data_direction_vals), 0x80,
5999 "gNB data direction", HFILL }
6002 /* Section 7.5.2.2 */
6003 { &hf_oran_payload_version,
6004 { "Payload Version", "oran_fh_cus.payloadVersion",
6005 FT_UINT8, BASE_DEC,
6006 NULL, 0x70,
6007 "Payload protocol version the following IEs", HFILL}
6010 /* Section 7.5.2.3 */
6011 { &hf_oran_filter_index,
6012 { "Filter Index", "oran_fh_cus.filterIndex",
6013 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6014 RVALS(filter_indices), 0x0f,
6015 "used between IQ data and air interface, both in DL and UL", HFILL}
6018 /* Section 7.5.2.4 */
6019 { &hf_oran_frame_id,
6020 { "Frame ID", "oran_fh_cus.frameId",
6021 FT_UINT8, BASE_DEC,
6022 NULL, 0x0,
6023 "A counter for 10 ms frames (wrapping period 2.56 seconds)", HFILL}
6026 /* Section 7.5.2.5 */
6027 { &hf_oran_subframe_id,
6028 { "Subframe ID", "oran_fh_cus.subframe_id",
6029 FT_UINT8, BASE_DEC,
6030 NULL, 0xf0,
6031 "A counter for 1 ms sub-frames within 10ms frame", HFILL}
6034 /* Section 7.5.2.6 */
6035 { &hf_oran_slot_id,
6036 { "Slot ID", "oran_fh_cus.slotId",
6037 FT_UINT16, BASE_DEC,
6038 NULL, 0x0fc0,
6039 "Slot number within a 1ms sub-frame", HFILL}
6042 /* Generated for convenience */
6043 { &hf_oran_slot_within_frame,
6044 { "Slot within frame", "oran_fh_cus.slot-within-frame",
6045 FT_UINT16, BASE_DEC,
6046 NULL, 0x0,
6047 "Slot within frame, to match DCT logs", HFILL}
6050 /* Section 7.5.2.7 */
6051 { &hf_oran_start_symbol_id,
6052 { "Start Symbol ID", "oran_fh_cus.startSymbolId",
6053 FT_UINT8, BASE_DEC,
6054 NULL, 0x3f,
6055 "The first symbol number within slot affected", HFILL}
6058 /* Section 7.5.2.8 */
6059 { &hf_oran_numberOfSections,
6060 { "Number of Sections", "oran_fh_cus.numberOfSections",
6061 FT_UINT8, BASE_DEC,
6062 NULL, 0x0,
6063 "The number of section IDs included in this C-Plane message", HFILL}
6066 /* Section 7.5.2.9 */
6067 { &hf_oran_sectionType,
6068 { "Section Type", "oran_fh_cus.sectionType",
6069 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6070 RVALS(section_types), 0x0,
6071 "Determines the characteristics of U-plane data", HFILL}
6074 /* Section 7.5.2.10 */
6075 { &hf_oran_udCompHdr,
6076 { "udCompHdr", "oran_fh_cus.udCompHdr",
6077 FT_STRING, BASE_NONE,
6078 NULL, 0x0,
6079 NULL, HFILL}
6082 /* Section 7.5.2.11 */
6083 { &hf_oran_numberOfUEs,
6084 { "Number Of UEs", "oran_fh_cus.numberOfUEs",
6085 FT_UINT8, BASE_DEC,
6086 NULL, 0x0,
6087 "Indicates number of UEs for which channel info is provided", HFILL}
6090 /* Section 7.5.2.12 */
6091 { &hf_oran_timeOffset,
6092 { "Time Offset", "oran_fh_cus.timeOffset",
6093 FT_UINT16, BASE_DEC,
6094 NULL, 0x0,
6095 "from start of the slot to start of CP in samples", HFILL}
6098 /* Section 7.5.2.13 */
6099 { &hf_oran_frameStructure_fft,
6100 { "FFT Size", "oran_fh_cus.frameStructure.fft",
6101 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
6102 RVALS(frame_structure_fft), 0xf0,
6103 "The FFT/iFFT size being used for all IQ data processing related to this message", HFILL }
6106 /* Section 7.5.2.13 */
6107 { &hf_oran_frameStructure_subcarrier_spacing,
6108 { "Subcarrier Spacing", "oran_fh_cus.frameStructure.spacing",
6109 FT_UINT8, BASE_HEX | BASE_RANGE_STRING,
6110 RVALS(subcarrier_spacings), 0x0f,
6111 "The sub carrier spacing as well as the number of slots per 1ms sub-frame",
6112 HFILL }
6115 /* Section 7.5.2.14 */
6116 { &hf_oran_cpLength,
6117 { "cpLength", "oran_fh_cus.cpLength",
6118 FT_UINT16, BASE_DEC,
6119 NULL, 0x0,
6120 "cyclic prefix length", HFILL}
6123 { &hf_oran_timing_header,
6124 { "Timing Header", "oran_fh_cus.timingHeader",
6125 FT_STRING, BASE_NONE,
6126 NULL, 0x0,
6127 NULL, HFILL}
6130 /* Section 7.5.3.1 */
6131 { &hf_oran_section_id,
6132 { "sectionId", "oran_fh_cus.sectionId",
6133 FT_UINT16, BASE_DEC,
6134 NULL, 0xfff0,
6135 "section identifier of data", HFILL}
6138 /* Section 7.5.3.2 */
6139 { &hf_oran_rb,
6140 { "rb", "oran_fh_cus.rb",
6141 FT_UINT8, BASE_DEC,
6142 VALS(rb_vals), 0x08,
6143 "resource block indicator", HFILL}
6146 /* Section 7.5.5.3 */
6147 { &hf_oran_symInc,
6148 { "symInc", "oran_fh_cus.symInc",
6149 FT_UINT8, BASE_DEC,
6150 VALS(sym_inc_vals), 0x04,
6151 "Symbol Number Increment Command", HFILL}
6154 /* Section 7.5.3.4 */
6155 { &hf_oran_startPrbc,
6156 { "startPrbc", "oran_fh_cus.startPrbc",
6157 FT_UINT16, BASE_DEC,
6158 NULL, 0x03ff,
6159 "Starting PRB of Control Plane Section", HFILL}
6162 /* Section 7.5.3.5 */
6163 { &hf_oran_reMask_re1,
6164 { "RE 1", "oran_fh_cus.reMask-RE1",
6165 FT_BOOLEAN, 16,
6166 TFS(&tfs_applicable_not_applicable), 0x8000,
6167 NULL, HFILL}
6169 { &hf_oran_reMask_re2,
6170 { "RE 2", "oran_fh_cus.reMask-RE2",
6171 FT_BOOLEAN, 16,
6172 TFS(&tfs_applicable_not_applicable), 0x4000,
6173 NULL, HFILL}
6175 { &hf_oran_reMask_re3,
6176 { "RE 3", "oran_fh_cus.reMask-RE3",
6177 FT_BOOLEAN, 16,
6178 TFS(&tfs_applicable_not_applicable), 0x2000,
6179 NULL, HFILL}
6181 { &hf_oran_reMask_re4,
6182 { "RE 4", "oran_fh_cus.reMask-RE4",
6183 FT_BOOLEAN, 16,
6184 TFS(&tfs_applicable_not_applicable), 0x1000,
6185 NULL, HFILL}
6187 { &hf_oran_reMask_re5,
6188 { "RE 5", "oran_fh_cus.reMask-RE5",
6189 FT_BOOLEAN, 16,
6190 TFS(&tfs_applicable_not_applicable), 0x0800,
6191 NULL, HFILL}
6193 { &hf_oran_reMask_re6,
6194 { "RE 6", "oran_fh_cus.reMask-RE6",
6195 FT_BOOLEAN, 16,
6196 TFS(&tfs_applicable_not_applicable), 0x0400,
6197 NULL, HFILL}
6199 { &hf_oran_reMask_re7,
6200 { "RE 7", "oran_fh_cus.reMask-RE7",
6201 FT_BOOLEAN, 16,
6202 TFS(&tfs_applicable_not_applicable), 0x0200,
6203 NULL, HFILL}
6205 { &hf_oran_reMask_re8,
6206 { "RE 8", "oran_fh_cus.reMask-RE8",
6207 FT_BOOLEAN, 16,
6208 TFS(&tfs_applicable_not_applicable), 0x0100,
6209 NULL, HFILL}
6211 { &hf_oran_reMask_re9,
6212 { "RE 9", "oran_fh_cus.reMask-RE9",
6213 FT_BOOLEAN, 16,
6214 TFS(&tfs_applicable_not_applicable), 0x0080,
6215 NULL, HFILL}
6217 { &hf_oran_reMask_re10,
6218 { "RE 10", "oran_fh_cus.reMask-RE10",
6219 FT_BOOLEAN, 16,
6220 TFS(&tfs_applicable_not_applicable), 0x0040,
6221 NULL, HFILL}
6223 { &hf_oran_reMask_re11,
6224 { "RE 11", "oran_fh_cus.reMask-RE11",
6225 FT_BOOLEAN, 16,
6226 TFS(&tfs_applicable_not_applicable), 0x0020,
6227 NULL, HFILL}
6229 { &hf_oran_reMask_re12,
6230 { "RE 12", "oran_fh_cus.reMask-RE12",
6231 FT_BOOLEAN, 16,
6232 TFS(&tfs_applicable_not_applicable), 0x0010,
6233 NULL, HFILL}
6235 { &hf_oran_reMask,
6236 { "RE Mask", "oran_fh_cus.reMask",
6237 FT_UINT16, BASE_HEX,
6238 NULL, 0xfff0,
6239 "The Resource Element (RE) mask within a PRB", HFILL}
6242 /* Section 7.5.3.6 */
6243 { &hf_oran_numPrbc,
6244 { "numPrbc", "oran_fh_cus.numPrbc",
6245 FT_UINT8, BASE_DEC,
6246 NULL, 0x0,
6247 "Number of contiguous PRBs per data section description", HFILL}
6250 /* Section 7.5.3.7 */
6251 { &hf_oran_numSymbol,
6252 { "Number of Symbols", "oran_fh_cus.numSymbol",
6253 FT_UINT8, BASE_DEC,
6254 NULL, 0x0f,
6255 "Defines number of symbols to which the section control is applicable", HFILL}
6258 /* Section 7.5.3.8 */
6259 { &hf_oran_ef,
6260 { "Extension Flag", "oran_fh_cus.ef",
6261 FT_BOOLEAN, 8,
6262 NULL, 0x80,
6263 "Indicates if more section extensions follow", HFILL}
6266 /* Section 7.5.3.9 */
6267 { &hf_oran_beamId,
6268 { "Beam ID", "oran_fh_cus.beamId",
6269 FT_UINT16, BASE_DEC,
6270 NULL, 0x7fff,
6271 "Defines the beam pattern to be applied to the U-Plane data", HFILL}
6274 { &hf_oran_extension,
6275 { "Extension", "oran_fh_cus.extension",
6276 FT_STRING, BASE_NONE,
6277 NULL, 0x0,
6278 "Section extension", HFILL}
6281 /* Section 7.6.2.1 */
6282 { &hf_oran_exttype,
6283 { "extType", "oran_fh_cus.extType",
6284 FT_UINT8, BASE_DEC,
6285 VALS(exttype_vals), 0x7f,
6286 "The extension type, which provides additional parameters specific to subject data extension", HFILL}
6289 /* Section 7.6.2.3 */
6290 { &hf_oran_extlen,
6291 { "extLen", "oran_fh_cus.extLen",
6292 FT_UINT16, BASE_DEC,
6293 NULL, 0x0,
6294 "Extension length in 32-bit words", HFILL}
6297 /* Section 7.7.1 */
6298 { &hf_oran_bfw,
6299 { "bfw", "oran_fh_cus.bfw",
6300 FT_STRING, BASE_NONE,
6301 NULL, 0x0,
6302 "Set of weights for a particular antenna", HFILL}
6304 { &hf_oran_bfw_bundle,
6305 { "Bundle", "oran_fh_cus.bfw.bundle",
6306 FT_STRING, BASE_NONE,
6307 NULL, 0x0,
6308 "Bundle of BFWs", HFILL}
6310 { &hf_oran_bfw_bundle_id,
6311 { "Bundle Id", "oran_fh_cus.bfw.bundleId",
6312 FT_UINT32, BASE_DEC,
6313 NULL, 0x0,
6314 NULL, HFILL}
6316 /* Section 7.7.1.4 */
6317 { &hf_oran_bfw_i,
6318 { "bfwI", "oran_fh_cus.bfwI",
6319 FT_FLOAT, BASE_NONE,
6320 NULL, 0x0,
6321 "In-phase", HFILL}
6323 /* Section 7.7.1.5 */
6324 { &hf_oran_bfw_q,
6325 { "bfwQ", "oran_fh_cus.bfwQ",
6326 FT_FLOAT, BASE_NONE,
6327 NULL, 0x0,
6328 "Quadrature", HFILL}
6331 /* Section 7.5.3.10 */
6332 { &hf_oran_ueId,
6333 { "UE ID", "oran_fh_cus.ueId",
6334 FT_UINT16, BASE_DEC,
6335 NULL, 0x7fff,
6336 "logical identifier for set of channel info", HFILL}
6339 /* Section 7.5.3.11 */
6340 { &hf_oran_freqOffset,
6341 { "Frequency Offset", "oran_fh_cus.freqOffset",
6342 FT_UINT24, BASE_DEC,
6343 NULL, 0x0,
6344 "with respect to the carrier center frequency before additional filtering", HFILL}
6347 /* Section 7.5.3.12 */
6348 { &hf_oran_regularizationFactor,
6349 { "Regularization Factor", "oran_fh_cus.regularizationFactor",
6350 FT_INT16, BASE_DEC,
6351 NULL, 0x0,
6352 "Signed value to support MMSE operation within O-RU", HFILL}
6355 /* Section 7.5.3.14 */
6356 { &hf_oran_laaMsgType,
6357 { "LAA Message Type", "oran_fh_cus.laaMsgType",
6358 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6359 RVALS(laaMsgTypes), 0xf0,
6360 NULL, HFILL}
6363 /* Section 7.5.3.15 */
6364 { &hf_oran_laaMsgLen,
6365 { "LAA Message Length", "oran_fh_cus.laaMsgLen",
6366 FT_UINT8, BASE_DEC,
6367 NULL, 0x0f,
6368 "number of 32-bit words in the LAA section", HFILL}
6371 /* Section 7.5.3.16 */
6372 { &hf_oran_lbtHandle,
6373 { "LBT Handle", "oran_fh_cus.lbtHandle",
6374 FT_UINT16, BASE_HEX,
6375 NULL, 0x0,
6376 "label to identify transaction", HFILL}
6379 /* Section 7.5.3.17 */
6380 { &hf_oran_lbtDeferFactor,
6381 { "Defer Factor", "oran_fh_cus.lbtDeferFactor",
6382 FT_UINT8, BASE_DEC,
6383 NULL, 0x07,
6384 "Defer factor in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
6387 /* Section 7.5.3.18 */
6388 { &hf_oran_lbtBackoffCounter,
6389 { "Backoff Counter", "oran_fh_cus.lbtBackoffCounter",
6390 FT_UINT16, BASE_DEC,
6391 NULL, 0xffc0,
6392 "LBT backoff counter in sensing slots as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
6395 /* Section 7.5.3.19 */
6396 { &hf_oran_lbtOffset,
6397 { "LBT Offset", "oran_fh_cus.lbtOffset",
6398 FT_UINT16, BASE_DEC,
6399 NULL, 0xffc0,
6400 "LBT start time in microseconds from the beginning of the subframe scheduled by this message", HFILL}
6403 /* Section 7.5.3.20 */
6404 { &hf_oran_MCOT,
6405 { "Maximum Channel Occupancy Time", "oran_fh_cus.MCOT",
6406 FT_UINT8, BASE_DEC,
6407 NULL, 0x3c,
6408 "LTE TXOP duration in subframes as described in 3GPP TS 36.213 Section 15.1.1", HFILL}
6411 /* Section 7.5.3.21 */
6412 { &hf_oran_lbtMode,
6413 { "LBT Mode", "oran_fh_cus.lbtMode",
6414 FT_UINT8, BASE_DEC,
6415 VALS(lbtMode_vals), 0x0,
6416 NULL, HFILL}
6419 /* Section 7.5.3.22 */
6420 { &hf_oran_lbtPdschRes,
6421 { "lbtPdschRes", "oran_fh_cus.lbtPdschRes",
6422 FT_UINT8, BASE_DEC,
6423 VALS(lbtPdschRes_vals), 0xc0,
6424 "LBT result of SFN/SF", HFILL}
6427 /* Section 7.5.3.23 */
6428 { &hf_oran_sfStatus,
6429 { "sfStatus", "oran_fh_cus.sfStatus",
6430 FT_BOOLEAN, 8,
6431 TFS(&tfs_sfStatus), 0x10,
6432 "Indicates whether the subframe was dropped or transmitted", HFILL}
6435 /* Section 7.5.3.22 */
6436 { &hf_oran_lbtDrsRes,
6437 { "lbtDrsRes", "oran_fh_cus.lbtDrsRes",
6438 FT_BOOLEAN, 8,
6439 TFS(&tfs_fail_success), 0x80,
6440 "Indicates whether the subframe was dropped or transmitted", HFILL}
6443 /* Section 7.5.3.25 */
6444 { &hf_oran_initialPartialSF,
6445 { "Initial partial SF", "oran_fh_cus.initialPartialSF",
6446 FT_BOOLEAN, 8,
6447 TFS(&tfs_partial_full_sf), 0x40,
6448 "Indicates whether the initial SF in the LBT process is full or partial", HFILL}
6451 /* Section 7.5.3.26. */
6452 { &hf_oran_lbtBufErr,
6453 { "lbtBufErr", "oran_fh_cus.lbtBufErr",
6454 FT_BOOLEAN, 8,
6455 TFS(&tfs_lbtBufErr), 0x80,
6456 "LBT buffer error", HFILL}
6459 /* Section 7.5.3.27 */
6460 { &hf_oran_sfnSfEnd,
6461 { "SFN/SF End", "oran_fh_cus.sfnSfEnd",
6462 FT_UINT16, BASE_DEC,
6463 NULL, 0x0fff,
6464 "SFN/SF by which the DRS window must end", HFILL}
6467 /* Section 7.5.3.28 */
6468 { &hf_oran_lbtCWConfig_H,
6469 { "lbtCWConfig_H", "oran_fh_cus.lbtCWConfig_H",
6470 FT_UINT8, BASE_DEC,
6471 NULL, 0x0,
6472 "HARQ parameters for congestion window management", HFILL}
6475 /* Section 7.5.3.29 */
6476 { &hf_oran_lbtCWConfig_T,
6477 { "lbtCWConfig_T", "oran_fh_cus.lbtCWConfig_T",
6478 FT_UINT8, BASE_DEC,
6479 NULL, 0x0,
6480 "TB parameters for congestion window management", HFILL}
6483 /* Section 7.5.3.30 */
6484 { &hf_oran_lbtTrafficClass,
6485 { "lbtTrafficClass", "oran_fh_cus.lbtTrafficClass",
6486 FT_UINT8, BASE_DEC,
6487 VALS(lbtTrafficClass_vals), 0x38,
6488 "Traffic class priority for congestion window management", HFILL}
6491 /* Section 7.5.3.31 */
6492 { &hf_oran_lbtCWR_Rst,
6493 { "lbtCWR_Rst", "oran_fh_cus.lbtCWR_Rst",
6494 FT_BOOLEAN, 8,
6495 TFS(&tfs_fail_success), 0x80,
6496 "notification about packet reception successful or not", HFILL}
6499 /* Reserved fields */
6500 { &hf_oran_reserved,
6501 { "reserved", "oran_fh_cus.reserved",
6502 FT_UINT64, BASE_HEX,
6503 NULL, 0x0,
6504 NULL, HFILL}
6507 { &hf_oran_reserved_1bit,
6508 { "reserved", "oran_fh_cus.reserved",
6509 FT_UINT8, BASE_HEX,
6510 NULL, 0x80,
6511 NULL, HFILL}
6513 { &hf_oran_reserved_2bits,
6514 { "reserved", "oran_fh_cus.reserved",
6515 FT_UINT8, BASE_HEX,
6516 NULL, 0xc0,
6517 NULL, HFILL}
6519 { &hf_oran_reserved_4bits,
6520 { "reserved", "oran_fh_cus.reserved",
6521 FT_UINT8, BASE_HEX,
6522 NULL, 0xf0,
6523 NULL, HFILL}
6525 { &hf_oran_reserved_last_4bits,
6526 { "reserved", "oran_fh_cus.reserved",
6527 FT_UINT8, BASE_HEX,
6528 NULL, 0x0f,
6529 NULL, HFILL}
6531 { &hf_oran_reserved_last_5bits,
6532 { "reserved", "oran_fh_cus.reserved",
6533 FT_UINT8, BASE_HEX,
6534 NULL, 0x1f,
6535 NULL, HFILL}
6537 { &hf_oran_reserved_6bits,
6538 { "reserved", "oran_fh_cus.reserved",
6539 FT_UINT8, BASE_HEX,
6540 NULL, 0xfc,
6541 NULL, HFILL}
6543 { &hf_oran_reserved_last_6bits,
6544 { "reserved", "oran_fh_cus.reserved",
6545 FT_UINT8, BASE_HEX,
6546 NULL, 0x3f,
6547 NULL, HFILL}
6549 { &hf_oran_reserved_7bits,
6550 { "reserved", "oran_fh_cus.reserved",
6551 FT_UINT8, BASE_HEX,
6552 NULL, 0xfe,
6553 NULL, HFILL}
6555 { &hf_oran_reserved_last_7bits,
6556 { "reserved", "oran_fh_cus.reserved",
6557 FT_UINT8, BASE_HEX,
6558 NULL, 0x7f,
6559 NULL, HFILL}
6561 { &hf_oran_reserved_8bits,
6562 { "reserved", "oran_fh_cus.reserved",
6563 FT_UINT8, BASE_HEX,
6564 NULL, 0x0,
6565 NULL, HFILL}
6567 { &hf_oran_reserved_16bits,
6568 { "reserved", "oran_fh_cus.reserved",
6569 FT_UINT16, BASE_HEX,
6570 NULL, 0x0,
6571 NULL, HFILL}
6573 { &hf_oran_reserved_15bits,
6574 { "reserved", "oran_fh_cus.reserved",
6575 FT_UINT16, BASE_HEX,
6576 NULL, 0x7fff,
6577 NULL, HFILL}
6579 { &hf_oran_reserved_bit1,
6580 { "reserved", "oran_fh_cus.reserved",
6581 FT_UINT8, BASE_HEX,
6582 NULL, 0x40,
6583 NULL, HFILL}
6585 { &hf_oran_reserved_bit2,
6586 { "reserved", "oran_fh_cus.reserved",
6587 FT_UINT8, BASE_HEX,
6588 NULL, 0x20,
6589 NULL, HFILL}
6591 { &hf_oran_reserved_bit4,
6592 { "reserved", "oran_fh_cus.reserved",
6593 FT_UINT8, BASE_HEX,
6594 NULL, 0x08,
6595 NULL, HFILL}
6597 { &hf_oran_reserved_bit5,
6598 { "reserved", "oran_fh_cus.reserved",
6599 FT_UINT8, BASE_HEX,
6600 NULL, 0x04,
6601 NULL, HFILL}
6603 { &hf_oran_reserved_bits123,
6604 { "reserved", "oran_fh_cus.reserved",
6605 FT_UINT8, BASE_HEX,
6606 NULL, 0x70,
6607 NULL, HFILL}
6609 { &hf_oran_reserved_bits456,
6610 { "reserved", "oran_fh_cus.reserved",
6611 FT_UINT8, BASE_HEX,
6612 NULL, 0x0e,
6613 NULL, HFILL}
6617 /* 7.7.11.10 */
6618 { &hf_oran_bundle_offset,
6619 { "BundleOffset", "oran_fh_cus.bundleOffset",
6620 FT_UINT8, BASE_DEC,
6621 NULL, 0x3f,
6622 "offset between start of first PRB bundle and startPrbc", HFILL}
6624 /* 7.7.11.9 */
6625 { &hf_oran_cont_ind,
6626 { "contInd", "oran_fh_cus.contInd",
6627 FT_BOOLEAN, 8,
6628 TFS(&continuity_indication_tfs), 0x80,
6629 "PRB region continuity flag", HFILL}
6632 /* 7.7.1.2 bfwCompHdr (beamforming weight compression header) */
6633 { &hf_oran_bfwCompHdr,
6634 { "bfwCompHdr", "oran_fh_cus.bfwCompHdr",
6635 FT_STRING, BASE_NONE,
6636 NULL, 0x0,
6637 "Compression method and IQ bit width for beamforming weights", HFILL}
6639 { &hf_oran_bfwCompHdr_iqWidth,
6640 { "IQ Bit Width", "oran_fh_cus.bfwCompHdr_iqWidth",
6641 FT_UINT8, BASE_HEX,
6642 VALS(bfw_comp_headers_iq_width), 0xf0,
6643 "IQ bit width for the beamforming weights", HFILL}
6645 { &hf_oran_bfwCompHdr_compMeth,
6646 { "Compression Method", "oran_fh_cus.bfwCompHdr_compMeth",
6647 FT_UINT8, BASE_HEX,
6648 VALS(bfw_comp_headers_comp_meth), 0x0f,
6649 "compression method for the beamforming weights", HFILL}
6652 /* 7.5.3.32 */
6653 { &hf_oran_ciCompParam,
6654 { "ciCompParam", "oran_fh_cus.ciCompParam",
6655 FT_STRING, BASE_NONE,
6656 NULL, 0x0,
6657 "channel information compression parameter", HFILL}
6660 /* Table 7.5.3.32-1 */
6661 { &hf_oran_blockScaler,
6662 { "blockScaler", "oran_fh_cus.blockScaler",
6663 FT_UINT8, BASE_HEX,
6664 NULL, 0x0,
6665 "unsigned, 1 integer bit, 7 fractional bits", HFILL}
6667 { &hf_oran_compBitWidth,
6668 { "compBitWidth", "oran_fh_cus.compBitWidth",
6669 FT_UINT8, BASE_DEC,
6670 NULL, 0xf0,
6671 "Length of I bits and length of Q bits after compression over entire PRB", HFILL}
6673 { &hf_oran_compShift,
6674 { "compShift", "oran_fh_cus.compShift",
6675 FT_UINT8, BASE_DEC,
6676 NULL, 0x0f,
6677 "The shift applied to the entire PRB", HFILL}
6680 /* Section 7.7.6.6 */
6681 { &hf_oran_repetition,
6682 { "repetition", "oran_fh_cus.repetition",
6683 FT_BOOLEAN, BASE_NONE,
6684 NULL, 0x0,
6685 "Repetition of a highest priority data section for C-Plane", HFILL}
6687 /* 7.7.20.9 */
6688 { &hf_oran_rbgSize,
6689 { "rbgSize", "oran_fh_cus.rbgSize",
6690 FT_UINT8, BASE_HEX,
6691 VALS(rbg_size_vals), 0x70,
6692 "Number of PRBs of the resource block groups allocated by the bit mask", HFILL}
6694 /* 7.7.20.10 */
6695 { &hf_oran_rbgMask,
6696 { "rbgMask", "oran_fh_cus.rbgMask",
6697 FT_UINT32, BASE_HEX,
6698 NULL, 0x0fffffff,
6699 "Each bit indicates whether a corresponding resource block group is present", HFILL}
6701 /* 7.7.6.5 */
6702 { &hf_oran_noncontig_priority,
6703 { "priority", "oran_fh_cus.priority",
6704 FT_UINT8, BASE_HEX,
6705 VALS(priority_vals), 0xc0,
6706 NULL, HFILL}
6708 /* 7.7.6.4 */
6709 { &hf_oran_symbolMask,
6710 { "symbolMask", "oran_fh_cus.symbolMask",
6711 FT_UINT16, BASE_HEX,
6712 NULL, 0x3fff,
6713 "Each bit indicates whether the rbgMask applies to a given symbol in the slot", HFILL}
6716 /* 7.7.22.2 */
6717 { &hf_oran_ack_nack_req_id,
6718 { "ackNackReqId", "oran_fh_cus.ackNackReqId",
6719 FT_UINT16, BASE_HEX,
6720 NULL, 0x0,
6721 "Indicates the ACK/NACK request ID of a section description", HFILL}
6724 /* Subtree for next 2 items */
6725 { &hf_oran_off_start_prb_num_prb_pair,
6726 { "Pair", "oran_fh_cus.offStartPrb_numPrb",
6727 FT_STRING, BASE_NONE,
6728 NULL, 0x0,
6729 "Pair of offStartPrb and numPrb", HFILL}
6732 /* 7.7.12.4 */
6733 { &hf_oran_off_start_prb,
6734 { "offStartPrb", "oran_fh_cus.offStartPrb",
6735 FT_UINT8, BASE_DEC,
6736 NULL, 0x0,
6737 "Offset of PRB range start", HFILL}
6739 /* 7.7.12.5 */
6740 { &hf_oran_num_prb,
6741 { "numPrb", "oran_fh_cus.numPrb",
6742 FT_UINT8, BASE_DEC,
6743 NULL, 0x0,
6744 "Number of PRBs in PRB range", HFILL}
6747 /* symbolId 8.3.3.7 */
6748 { &hf_oran_symbolId,
6749 { "Symbol Identifier", "oran_fh_cus.symbolId",
6750 FT_UINT8, BASE_DEC,
6751 NULL, 0x3f,
6752 "Identifies a symbol number within a slot", HFILL}
6755 /* startPrbu 8.3.3.11 */
6756 { &hf_oran_startPrbu,
6757 { "startPrbu", "oran_fh_cus.startPrbu",
6758 FT_UINT16, BASE_DEC,
6759 NULL, 0x03ff,
6760 "starting PRB of user plane section", HFILL}
6763 /* numPrbu 8.3.3.12 */
6764 { &hf_oran_numPrbu,
6765 { "numPrbu", "oran_fh_cus.numPrbu",
6766 FT_UINT8, BASE_DEC,
6767 NULL, 0x0,
6768 "number of PRBs per user plane section", HFILL}
6771 /* 7.7.1.3 */
6772 { &hf_oran_bfwCompParam,
6773 { "bfwCompParam", "oran_fh_cus.bfwCompParam",
6774 FT_STRING, BASE_NONE,
6775 NULL, 0x0,
6776 "Beamforming weight compression parameter", HFILL}
6779 /* 6.3.3.13 */
6780 { &hf_oran_udCompHdrMeth,
6781 { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
6782 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6783 RVALS(ud_comp_header_meth), 0x0f,
6784 "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
6786 { &hf_oran_udCompHdrMeth_pref,
6787 { "User Data Compression Method", "oran_fh_cus.udCompHdrMeth",
6788 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6789 RVALS(ud_comp_header_meth), 0x0,
6790 "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
6792 /* 8.3.3.18 */
6793 { &hf_oran_udCompLen,
6794 { "udCompLen", "oran_fh_cus.udCompLen",
6795 FT_UINT16, BASE_DEC,
6796 NULL, 0x0,
6797 "PRB field length in octets", HFILL}
6800 /* 6.3.3.13 */
6801 { &hf_oran_udCompHdrIqWidth,
6802 { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
6803 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6804 RVALS(ud_comp_header_width), 0xf0,
6805 "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
6807 { &hf_oran_udCompHdrIqWidth_pref,
6808 { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
6809 FT_UINT8, BASE_DEC,
6810 NULL, 0x0,
6811 "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
6814 /* Section 8.3.3.15 (not always present - depends upon meth) */
6815 { &hf_oran_udCompParam,
6816 { "User Data Compression Parameter", "oran_fh_cus.udCompParam",
6817 FT_STRING, BASE_NONE,
6818 NULL, 0x0,
6819 "Applies to whatever compression method is specified by the associated sectionID's compMeth value", HFILL}
6821 /* 8.3.3.18 */
6822 { &hf_oran_sReSMask,
6823 { "sReSMask", "oran_fh_cus.sReSMask",
6824 FT_UINT16, BASE_HEX,
6825 NULL, 0xf0ff,
6826 "selective RE sending mask", HFILL}
6829 { &hf_oran_sReSMask_re12,
6830 { "RE-12", "oran_fh_cus.sReSMask-re12",
6831 FT_BOOLEAN, 16,
6832 TFS(&tfs_present_not_present), 0x8000,
6833 NULL, HFILL}
6835 { &hf_oran_sReSMask_re11,
6836 { "RE-11", "oran_fh_cus.sReSMask-re11",
6837 FT_BOOLEAN, 16,
6838 TFS(&tfs_present_not_present), 0x4000,
6839 NULL, HFILL}
6841 { &hf_oran_sReSMask_re10,
6842 { "RE-10", "oran_fh_cus.sReSMask-re10",
6843 FT_BOOLEAN, 16,
6844 TFS(&tfs_present_not_present), 0x2000,
6845 NULL, HFILL}
6847 { &hf_oran_sReSMask_re9,
6848 { "RE-9", "oran_fh_cus.sReSMask-re9",
6849 FT_BOOLEAN, 16,
6850 TFS(&tfs_present_not_present), 0x1000,
6851 NULL, HFILL}
6853 { &hf_oran_sReSMask_re8,
6854 { "RE-8", "oran_fh_cus.sReSMask-re8",
6855 FT_BOOLEAN, 16,
6856 TFS(&tfs_present_not_present), 0x0080,
6857 NULL, HFILL}
6859 { &hf_oran_sReSMask_re7,
6860 { "RE-7", "oran_fh_cus.sReSMask-re7",
6861 FT_BOOLEAN, 16,
6862 TFS(&tfs_present_not_present), 0x0040,
6863 NULL, HFILL}
6865 { &hf_oran_sReSMask_re6,
6866 { "RE-6", "oran_fh_cus.sReSMask-re6",
6867 FT_BOOLEAN, 16,
6868 TFS(&tfs_present_not_present), 0x0020,
6869 NULL, HFILL}
6871 { &hf_oran_sReSMask_re5,
6872 { "RE-5", "oran_fh_cus.sReSMask-re5",
6873 FT_BOOLEAN, 16,
6874 TFS(&tfs_present_not_present), 0x0010,
6875 NULL, HFILL}
6877 { &hf_oran_sReSMask_re4,
6878 { "RE-4", "oran_fh_cus.sReSMask-re4",
6879 FT_BOOLEAN, 16,
6880 TFS(&tfs_present_not_present), 0x0008,
6881 NULL, HFILL}
6883 { &hf_oran_sReSMask_re3,
6884 { "RE-3", "oran_fh_cus.sReSMask-re3",
6885 FT_BOOLEAN, 16,
6886 TFS(&tfs_present_not_present), 0x0004,
6887 NULL, HFILL}
6889 { &hf_oran_sReSMask_re2,
6890 { "RE-2", "oran_fh_cus.sReSMask-re2",
6891 FT_BOOLEAN, 16,
6892 TFS(&tfs_present_not_present), 0x0002,
6893 NULL, HFILL}
6895 { &hf_oran_sReSMask_re1,
6896 { "RE-1", "oran_fh_cus.sReSMask-re1",
6897 FT_BOOLEAN, 16,
6898 TFS(&tfs_present_not_present), 0x0001,
6899 NULL, HFILL}
6902 /* 8.3.3.20 */
6903 { &hf_oran_sReSMask1,
6904 { "sReSMask1", "oran_fh_cus.sReSMask1",
6905 FT_UINT16, BASE_HEX,
6906 NULL, 0x0fff,
6907 "selective RE sending mask 1", HFILL}
6909 /* 8.3.3.21 */
6910 { &hf_oran_sReSMask2,
6911 { "sReSMask2", "oran_fh_cus.sReSMask2",
6912 FT_UINT16, BASE_HEX,
6913 NULL, 0x0fff,
6914 "selective RE sending mask 2", HFILL}
6917 { &hf_oran_sReSMask1_2_re12,
6918 { "RE-12", "oran_fh_cus.sReSMask-re12",
6919 FT_BOOLEAN, 16,
6920 TFS(&tfs_present_not_present), 0x0800,
6921 NULL, HFILL}
6923 { &hf_oran_sReSMask1_2_re11,
6924 { "RE-11", "oran_fh_cus.sReSMask-re11",
6925 FT_BOOLEAN, 16,
6926 TFS(&tfs_present_not_present), 0x0400,
6927 NULL, HFILL}
6929 { &hf_oran_sReSMask1_2_re10,
6930 { "RE-10", "oran_fh_cus.sReSMask-re10",
6931 FT_BOOLEAN, 16,
6932 TFS(&tfs_present_not_present), 0x0200,
6933 NULL, HFILL}
6935 { &hf_oran_sReSMask1_2_re9,
6936 { "RE-9", "oran_fh_cus.sReSMask-re9",
6937 FT_BOOLEAN, 16,
6938 TFS(&tfs_present_not_present), 0x0100,
6939 NULL, HFILL}
6942 /* Section 6.3.3.15 */
6943 { &hf_oran_iSample,
6944 { "iSample", "oran_fh_cus.iSample",
6945 FT_FLOAT, BASE_NONE,
6946 NULL, 0x0,
6947 "In-phase Sample value", HFILL}
6950 /* Section 6.3.3.16 */
6951 { &hf_oran_qSample,
6952 { "qSample", "oran_fh_cus.qSample",
6953 FT_FLOAT, BASE_NONE,
6954 NULL, 0x0,
6955 "Quadrature Sample value", HFILL}
6958 { &hf_oran_exponent,
6959 { "Exponent", "oran_fh_cus.exponent",
6960 FT_UINT8, BASE_DEC,
6961 NULL, 0x0f,
6962 "Exponent applicable to the I & Q mantissas", HFILL }
6965 { &hf_oran_iq_user_data,
6966 { "IQ User Data", "oran_fh_cus.iq_user_data",
6967 FT_BYTES, BASE_NONE,
6968 NULL, 0x0,
6969 "Used for the In-phase and Quadrature sample mantissa", HFILL }
6972 { &hf_oran_c_eAxC_ID,
6973 { "c_eAxC_ID", "oran_fh_cus.c_eaxc_id",
6974 FT_STRING, BASE_NONE,
6975 NULL, 0x0,
6976 "This is a calculated field for the c_eAxC ID, which identifies the message stream", HFILL }
6979 { &hf_oran_refa,
6980 { "RefA", "oran_fh_cus.refa",
6981 FT_STRING, BASE_NONE,
6982 NULL, 0x0,
6983 "This is a calculated field for the RefA ID, which provides a reference in time", HFILL }
6987 /* Section 7.5.2.15 */
6988 { &hf_oran_ciCompHdr,
6989 { "ciCompHdr", "oran_fh_cus.ciCompHdr",
6990 FT_STRING, BASE_NONE,
6991 NULL, 0x0,
6992 NULL, HFILL}
6994 { &hf_oran_ciCompHdrMeth,
6995 { "User Data Compression Method", "oran_fh_cus.ciCompHdrMeth",
6996 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
6997 RVALS(ud_comp_header_meth), 0x0e,
6998 "Defines the compression method for the user data in every section in the C-Plane message", HFILL}
7000 { &hf_oran_ciCompHdrIqWidth,
7001 { "User Data IQ width", "oran_fh_cus.udCompHdrWidth",
7002 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7003 RVALS(ud_comp_header_width), 0xf0,
7004 "Defines the IQ bit width for the user data in every section in the C-Plane message", HFILL}
7006 { &hf_oran_ciCompOpt,
7007 { "ciCompOpt", "oran_fh_cus.ciCompOpt",
7008 FT_UINT8, BASE_DEC,
7009 VALS(ci_comp_opt_vals), 0x01,
7010 NULL, HFILL }
7013 /* 7.7.11.7 */
7014 { &hf_oran_disable_bfws,
7015 { "disableBFWs", "oran_fh_cus.disableBFWs",
7016 FT_BOOLEAN, 8,
7017 NULL, 0x80,
7018 "Indicate if BFWs under section extension are disabled", HFILL }
7020 /* 7.7.11.8 */
7021 { &hf_oran_rad,
7022 { "RAD", "oran_fh_cus.rad",
7023 FT_BOOLEAN, 8,
7024 NULL, 0x40,
7025 "Reset After PRB Discontinuity", HFILL }
7027 /* 7.7.11.4 */
7028 { &hf_oran_num_bund_prbs,
7029 { "numBundPrb", "oran_fh_cus.numBundPrb",
7030 FT_UINT8, BASE_DEC,
7031 NULL, 0x0,
7032 "Number of bundled PRBs per BFWs", HFILL }
7034 { &hf_oran_beam_id,
7035 { "beamId", "oran_fh_cus.beamId",
7036 FT_UINT16, BASE_DEC,
7037 NULL, 0x7fff,
7038 NULL, HFILL }
7040 { &hf_oran_num_weights_per_bundle,
7041 { "Num weights per bundle", "oran_fh_cus.num_weights_per_bundle",
7042 FT_UINT16, BASE_DEC,
7043 NULL, 0x0,
7044 "From dissector preference", HFILL }
7047 { &hf_oran_samples_prb,
7048 {"PRB", "oran_fh_cus.prb",
7049 FT_STRING, BASE_NONE,
7050 NULL, 0x0,
7051 "Grouping of samples for a particular Physical Resource Block", HFILL}
7054 /* 7.5.3.13 */
7055 { &hf_oran_ciSample,
7056 { "ciSample", "oran_fh_cus.ciSample",
7057 FT_STRING, BASE_NONE,
7058 NULL, 0x0,
7059 "Sample (I and Q values)", HFILL}
7061 { &hf_oran_ciIsample,
7062 { "ciIsample", "oran_fh_cus.ciISample",
7063 FT_FLOAT, BASE_NONE,
7064 NULL, 0x0,
7065 "Channel information complex value - I part", HFILL}
7067 { &hf_oran_ciQsample,
7068 { "ciQsample", "oran_fh_cus.ciQSample",
7069 FT_FLOAT, BASE_NONE,
7070 NULL, 0x0,
7071 "Channel information complex value - Q part", HFILL}
7074 /* 7.7.10.2 */
7075 { &hf_oran_beamGroupType,
7076 { "beamGroupType", "oran_fh_cus.beamGroupType",
7077 FT_UINT8, BASE_DEC,
7078 VALS(beam_group_type_vals), 0xc0,
7079 "The type of beam grouping", HFILL }
7081 /* 7.7.10.3 */
7082 { &hf_oran_numPortc,
7083 { "numPortc", "oran_fh_cus.numPortc",
7084 FT_UINT8, BASE_DEC,
7085 NULL, 0x3f,
7086 "The number of eAxC ports", HFILL }
7089 /* 7.7.4.2 (1 bit) */
7090 { &hf_oran_csf,
7091 { "csf", "oran_fh_cus.csf",
7092 FT_BOOLEAN, BASE_NONE,
7093 NULL, 0x0,
7094 "constellation shift flag", HFILL }
7096 /* 7.7.4.3 */
7097 { &hf_oran_modcompscaler,
7098 { "modCompScaler", "oran_fh_cus.modcompscaler",
7099 FT_UINT16, BASE_DEC,
7100 NULL, 0x7fff,
7101 "modulation compression scaler value", HFILL }
7104 /* 7.7.5.1 */
7105 { &hf_oran_modcomp_param_set,
7106 { "Set", "oran_fh_cus.modcomp-param-set",
7107 FT_STRING, BASE_NONE,
7108 NULL, 0x0,
7109 NULL, HFILL }
7112 /* mcScaleReMask 7.7.5.2 (12 bits) */
7113 { &hf_oran_mc_scale_re_mask,
7114 { "mcScaleReMask", "oran_fh_cus.mcscaleremask",
7115 FT_BOOLEAN, BASE_NONE,
7116 NULL, 0x0,
7117 "modulation compression power scale RE mask", HFILL }
7119 /* mcScaleOffset 7.7.5.4 (15 bits) */
7120 { &hf_oran_mc_scale_offset,
7121 { "mcScaleOffset", "oran_fh_cus.mcscaleoffset",
7122 FT_UINT24, BASE_DEC,
7123 NULL, 0x0,
7124 "scaling value for modulation compression", HFILL }
7126 /* eAxCmask (7.7.7.2) */
7127 { &hf_oran_eAxC_mask,
7128 { "eAxC Mask", "oran_fh_cus.eaxcmask",
7129 FT_UINT16, BASE_HEX,
7130 NULL, 0x0,
7131 "Which eAxC_ID values the C-Plane message applies to", HFILL }
7133 /* technology (interface name) 7.7.9.2 */
7134 { &hf_oran_technology,
7135 { "Technology", "oran_fh_cus.technology",
7136 FT_UINT8, BASE_DEC,
7137 VALS(interface_name_vals), 0x0,
7138 "Interface name (that C-PLane section applies to)", HFILL }
7140 /* Exttype 14 (7.7.14.2) */
7141 { &hf_oran_nullLayerInd,
7142 { "nullLayerInd", "oran_fh_cus.nulllayerind",
7143 FT_BOOLEAN, BASE_NONE,
7144 NULL, 0x0,
7145 "Whether corresponding layer is nulling-layer or not", HFILL }
7148 /* Exttype 19 (7.7.19.8) */
7149 { &hf_oran_portReMask,
7150 { "portReMask", "oran_fh_cus.portReMask",
7151 FT_BOOLEAN, 16,
7152 TFS(&tfs_set_notset), 0x0fff,
7153 "RE bitmask per port", HFILL }
7155 /* 7.7.19.9 */
7156 { &hf_oran_portSymbolMask,
7157 { "portSymbolMask", "oran_fh_cus.portSymbolMask",
7158 FT_BOOLEAN, 16,
7159 TFS(&tfs_set_notset), 0x3fff,
7160 "Symbol bitmask port port", HFILL }
7163 { &hf_oran_ext19_port,
7164 {"Port", "oran_fh_cus.ext19.port",
7165 FT_STRING, BASE_NONE,
7166 NULL, 0x0,
7167 "Entry for a given port in ext19", HFILL}
7170 /* Ext 13 */
7171 { &hf_oran_prb_allocation,
7172 {"PRB allocation", "oran_fh_cus.prb-allocation",
7173 FT_STRING, BASE_NONE,
7174 NULL, 0x0,
7175 NULL, HFILL}
7177 /* 7.7.13.2 */
7178 { &hf_oran_nextSymbolId,
7179 { "nextSymbolId", "oran_fh_cus.nextSymbolId",
7180 FT_UINT8, BASE_DEC,
7181 NULL, 0x3c,
7182 "offset of PRB range start", HFILL }
7184 /* 7.7.13.3 */
7185 { &hf_oran_nextStartPrbc,
7186 { "nextStartPrbc", "oran_fh_cus.nextStartPrbc",
7187 FT_UINT16, BASE_DEC,
7188 NULL, 0x03ff,
7189 "number of PRBs in PRB range", HFILL }
7192 /* Puncturing patters as appears in SE 20 */
7193 { &hf_oran_puncPattern,
7194 { "puncPattern", "oran_fh_cus.puncPattern",
7195 FT_STRING, BASE_NONE,
7196 NULL, 0x0,
7197 NULL, HFILL}
7200 /* 7.7.20.2 numPuncPatterns */
7201 { &hf_oran_numPuncPatterns,
7202 { "numPuncPatterns", "oran_fh_cus.numPuncPatterns",
7203 FT_UINT8, BASE_DEC,
7204 NULL, 0x0,
7205 "number of puncturing patterns", HFILL }
7207 /* 7.7.20.3 symbolMask */
7208 { &hf_oran_symbolMask_ext20,
7209 { "symbolMask", "oran_fh_cus.symbolMask",
7210 FT_UINT16, BASE_HEX,
7211 NULL, 0xfffc,
7212 "Bitmask where each bit indicates the symbols associated with the puncturing pattern", HFILL}
7214 /* 7.7.20.4 startPuncPrb */
7215 { &hf_oran_startPuncPrb,
7216 { "startPuncPrb", "oran_fh_cus.startPuncPrb",
7217 FT_UINT16, BASE_DEC,
7218 NULL, 0x03ff,
7219 "starting PRB to which one puncturing pattern applies", HFILL}
7221 /* 7.7.20.5 numPuncPrb */
7222 { &hf_oran_numPuncPrb,
7223 { "numPuncPrb", "oran_fh_cus.numPuncPrb",
7224 FT_UINT24, BASE_DEC,
7225 NULL, 0x03ffff,
7226 "the number of PRBs of the puncturing pattern", HFILL}
7228 /* 7.7.20.6 puncReMask */
7229 { &hf_oran_puncReMask,
7230 { "puncReMask", "oran_fh_cus.puncReMask",
7231 FT_UINT16, BASE_DEC,
7232 NULL, 0xffc0,
7233 "puncturing pattern RE mask", HFILL}
7235 /* 7.7.20.12 multiSDScope */
7236 { &hf_oran_multiSDScope,
7237 { "multiSDScope", "oran_fh_cus.multiSDScope",
7238 FT_BOOLEAN, 8,
7239 TFS(&multi_sd_scope_tfs), 0x02,
7240 "multiple section description scope flag", HFILL}
7242 /* 7.7.20.4 rbgIncl */
7243 { &hf_oran_RbgIncl,
7244 { "rbgIncl", "oran_fh_cus.rbgIncl",
7245 FT_BOOLEAN, 8,
7246 NULL, 0x01,
7247 "rbg included flag", HFILL}
7250 /* 7.7.21.2 ciPrbGroupSize */
7251 { &hf_oran_ci_prb_group_size,
7252 { "ciPrbGroupSize", "oran_fh_cus.ciPrbGroupSize",
7253 FT_UINT8, BASE_DEC,
7254 NULL, 0x0,
7255 "channel information PRB group size", HFILL}
7257 /* 7.21.3 */
7258 { &hf_oran_prg_size_st5,
7259 { "prgSize", "oran_fh_cus.prgSize",
7260 FT_UINT8, BASE_DEC,
7261 VALS(prg_size_st5_vals), 0x03,
7262 "precoding resource block group size", HFILL}
7264 { &hf_oran_prg_size_st6,
7265 { "prgSize", "oran_fh_cus.prgSize",
7266 FT_UINT8, BASE_DEC,
7267 VALS(prg_size_st6_vals), 0x03,
7268 "precoding resource block group size", HFILL}
7271 /* 7.7.17.2 numUeID */
7272 { &hf_oran_num_ueid,
7273 { "numUeID", "oran_fh_cus.numUeID",
7274 FT_UINT8, BASE_DEC,
7275 NULL, 0x0,
7276 "number of ueIDs per user", HFILL}
7279 /* 7.7.16.2 antMask */
7280 { &hf_oran_antMask,
7281 { "antMask", "oran_fh_cus.antMask",
7282 FT_UINT64, BASE_HEX,
7283 NULL, 0xffffffffffffffff,
7284 "indices of antennas to be pre-combined per RX endpoint", HFILL}
7287 /* 7.7.18.2 transmissionWindowOffset */
7288 { &hf_oran_transmissionWindowOffset,
7289 { "transmissionWindowOffset", "oran_fh_cus.transmissionWindowOffset",
7290 FT_UINT16, BASE_DEC,
7291 NULL, 0x0,
7292 "start of the transmission window as an offset to when the transmission window would have been without this parameter, i.e. (Ta3_max - Ta3_min)", HFILL}
7294 /* 7.7.18.3 transmissionWindowSize */
7295 { &hf_oran_transmissionWindowSize,
7296 { "transmissionWindowSize", "oran_fh_cus.transmissionWindowSize",
7297 FT_UINT16, BASE_DEC,
7298 NULL, 0x3fff,
7299 "size of the transmission window in resolution µs", HFILL}
7301 /* 7.7.18.4 toT */
7302 { &hf_oran_toT,
7303 { "toT", "oran_fh_cus.toT",
7304 FT_UINT8, BASE_DEC,
7305 VALS(type_of_transmission_vals), 0x03,
7306 "type of transmission", HFILL}
7309 /* 7.7.2.2 bfaCompHdr */
7310 { &hf_oran_bfaCompHdr,
7311 { "bfaCompHdr", "oran_fh_cus.bfaCompHdr",
7312 FT_STRING, BASE_NONE,
7313 NULL, 0x0,
7314 "beamforming attributes compression header", HFILL}
7316 /* 7.7.2.2-2: bfAzPtWidth */
7317 { &hf_oran_bfAzPtWidth,
7318 { "bfAzPtWidth", "oran_fh_cus.bfAzPtWidth",
7319 FT_UINT8, BASE_DEC,
7320 VALS(bfa_bw_vals), 0x38,
7321 NULL, HFILL}
7323 /* 7.7.2.2-3: bfZePtWidth */
7324 { &hf_oran_bfZePtWidth,
7325 { "bfZePtWidth", "oran_fh_cus.bfZePtWidth",
7326 FT_UINT8, BASE_DEC,
7327 VALS(bfa_bw_vals), 0x07,
7328 NULL, HFILL}
7330 /* 7.7.2.2-4: bfAz3ddWidth */
7331 { &hf_oran_bfAz3ddWidth,
7332 { "bfAz3ddWidth", "oran_fh_cus.bfAz3ddWidth",
7333 FT_UINT8, BASE_DEC,
7334 VALS(bfa_bw_vals), 0x38,
7335 NULL, HFILL}
7337 /* 7.7.2.2-5: bfZe3ddWidth */
7338 { &hf_oran_bfZe3ddWidth,
7339 { "bfZe3ddWidth", "oran_fh_cus.bfZe3ddWidth",
7340 FT_UINT8, BASE_DEC,
7341 VALS(bfa_bw_vals), 0x07,
7342 NULL, HFILL}
7345 /* 7.7.2.3 bfAzPt */
7346 { &hf_oran_bfAzPt,
7347 { "bfAzPt", "oran_fh_cus.bfAzPt",
7348 FT_UINT8, BASE_DEC,
7349 NULL, 0x0,
7350 "beamforming azimuth pointing parameter", HFILL}
7352 /* 7.7.2.4 bfZePt */
7353 { &hf_oran_bfZePt,
7354 { "bfZePt", "oran_fh_cus.bfZePt",
7355 FT_UINT8, BASE_DEC,
7356 NULL, 0x0,
7357 "beamforming zenith pointing parameter", HFILL}
7359 /* 7.7.2.5 bfAz3dd */
7360 { &hf_oran_bfAz3dd,
7361 { "bfAz3dd", "oran_fh_cus.bfAz3dd",
7362 FT_UINT8, BASE_DEC,
7363 NULL, 0x0,
7364 "beamforming azimuth beamwidth parameter", HFILL}
7366 /* 7.7.2.6 bfZe3dd */
7367 { &hf_oran_bfZe3dd,
7368 { "bfZe3dd", "oran_fh_cus.bfZe3dd",
7369 FT_UINT8, BASE_DEC,
7370 NULL, 0x0,
7371 "beamforming zenith beamwidth parameter", HFILL}
7374 /* 7.7.2.7 bfAzSl */
7375 { &hf_oran_bfAzSl,
7376 { "bfAzSl", "oran_fh_cus.bfAzSl",
7377 FT_UINT8, BASE_DEC,
7378 VALS(sidelobe_suppression_vals), 0x38,
7379 "beamforming azimuth sidelobe parameter", HFILL}
7381 /* 7.7.2.8 bfZeSl */
7382 { &hf_oran_bfZeSl,
7383 { "bfZeSl", "oran_fh_cus.bfZeSl",
7384 FT_UINT8, BASE_DEC,
7385 VALS(sidelobe_suppression_vals), 0x07,
7386 "beamforming zenith sidelobe parameter", HFILL}
7389 /* 7.5.2.17 */
7390 { &hf_oran_cmd_scope,
7391 { "cmdScope", "oran_fh_cus.cmdScope",
7392 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7393 RVALS(cmd_scope_vals), 0x0f,
7394 "command scope", HFILL}
7396 /* 7.5.2.18 */
7397 { &hf_oran_number_of_st4_cmds,
7398 { "numberOfST4Cmds", "oran_fh_cus.numberOfST4Cmds",
7399 FT_UINT8, BASE_DEC,
7400 NULL, 0x0,
7401 "Number of Section Type 4 commands", HFILL}
7404 { &hf_oran_st4_cmd_header,
7405 { "Command common header", "oran_fh_cus.st4CmdCommonHeader",
7406 FT_STRING, BASE_NONE,
7407 NULL, 0x0,
7408 NULL, HFILL}
7411 /* 7.5.3.38 */
7412 { &hf_oran_st4_cmd_type,
7413 { "st4CmdType", "oran_fh_cus.st4CmdType",
7414 FT_UINT8, BASE_DEC | BASE_RANGE_STRING,
7415 RVALS(st4_cmd_type_vals), 0x0,
7416 NULL, HFILL}
7418 /* 7.5.3.39 */
7419 { &hf_oran_st4_cmd_len,
7420 { "st4CmdLen", "oran_fh_cus.st4CmdLen",
7421 FT_UINT16, BASE_DEC,
7422 NULL, 0x0,
7423 "Length of command in 32-bit words", HFILL}
7425 /* 7.5.3.40 */
7426 { &hf_oran_st4_cmd_num_slots,
7427 { "numSlots", "oran_fh_cus.st4NumSlots",
7428 FT_UINT8, BASE_DEC,
7429 NULL, 0x0,
7430 "Contiguous slots for which command is applicable", HFILL}
7432 /* 7.5.3.41 */
7433 { &hf_oran_st4_cmd_ack_nack_req_id,
7434 { "ackNackReqId", "oran_fh_cus.ackNackReqId",
7435 FT_UINT16, BASE_DEC,
7436 NULL, 0x0,
7437 "ACK/NACK Request Id", HFILL}
7440 { &hf_oran_st4_cmd,
7441 { "Command", "oran_fh_cus.st4Cmd",
7442 FT_STRING, BASE_NONE,
7443 NULL, 0x0,
7444 NULL, HFILL}
7447 /* 7.5.3.52 */
7448 { &hf_oran_sleepmode_trx,
7449 { "sleepMode", "oran_fh_cus.sleepMode",
7450 FT_UINT8, BASE_HEX,
7451 VALS(sleep_mode_trx_vals), 0x03,
7452 NULL, HFILL}
7454 { &hf_oran_sleepmode_asm,
7455 { "sleepMode", "oran_fh_cus.sleepMode",
7456 FT_UINT8, BASE_HEX,
7457 VALS(sleep_mode_asm_vals), 0x03,
7458 NULL, HFILL}
7461 /* 7.5.3.51 */
7462 { &hf_oran_log2maskbits,
7463 { "log2MaskBits", "oran_fh_cus.log2MaskBits",
7464 FT_UINT8, BASE_HEX,
7465 VALS(log2maskbits_vals), 0x3c,
7466 "Number of bits to appear in antMask", HFILL}
7468 /* 7.5.3.53 */
7469 { &hf_oran_num_slots_ext,
7470 { "numSlotsExt", "oran_fh_cus.numSlotsExt",
7471 FT_UINT24, BASE_HEX,
7472 NULL, 0x0fffff,
7473 NULL, HFILL}
7475 /* 7.5.3.54 */
7476 { &hf_oran_antMask_trx_control,
7477 { "antMask", "oran_fh_cus.trxControl.antMask",
7478 FT_BYTES, BASE_NONE,
7479 NULL, 0x0,
7480 "which antennas should sleep or wake-up", HFILL}
7482 /* 7.5.3.55 */
7483 { &hf_oran_ready,
7484 { "ready", "oran_fh_cus.ready",
7485 FT_BOOLEAN, 8,
7486 TFS(&ready_tfs), 0x01,
7487 "wake-up ready indicator", HFILL}
7489 /* 7.5.3.34 */
7490 { &hf_oran_number_of_acks,
7491 { "numberOfAcks", "oran_fh_cus.numberOfAcks",
7492 FT_UINT8, BASE_DEC,
7493 NULL, 0x0,
7494 "number of ACKs for one eAxC_ID", HFILL}
7496 /* 7.5.3.35 */
7497 { &hf_oran_number_of_nacks,
7498 { "numberOfNacks", "oran_fh_cus.numberOfNacks",
7499 FT_UINT8, BASE_DEC,
7500 NULL, 0x0,
7501 "number of NACKs for one eAxC_ID", HFILL}
7503 /* 7.5.3.36 */
7504 { &hf_oran_ackid,
7505 { "ackId", "oran_fh_cus.ackId",
7506 FT_UINT16, BASE_DEC,
7507 NULL, 0x0,
7508 NULL, HFILL}
7510 /* 7.5.3.37 */
7511 { &hf_oran_nackid,
7512 { "nackId", "oran_fh_cus.nackId",
7513 FT_UINT16, BASE_DEC,
7514 NULL, 0x0,
7515 NULL, HFILL}
7518 /* Links between acknack requests & responses */
7519 { &hf_oran_acknack_request_frame,
7520 { "Request Frame", "oran_fh_cus.ackNackId.request-frame",
7521 FT_FRAMENUM, BASE_NONE,
7522 FRAMENUM_TYPE(FT_FRAMENUM_REQUEST), 0x0,
7523 NULL, HFILL}
7525 { &hf_oran_acknack_request_time,
7526 { "Time since request in ms", "oran_fh_cus.ackNackId.time-since-request",
7527 FT_UINT32, BASE_DEC,
7528 NULL, 0x0,
7529 "Time between request and response", HFILL}
7531 { &hf_oran_acknack_request_type,
7532 { "Request Type", "oran_fh_cus.ackNackId.request-type",
7533 FT_UINT32, BASE_DEC,
7534 VALS(acknack_type_vals), 0x0,
7535 NULL, HFILL}
7537 { &hf_oran_acknack_response_frame,
7538 { "Response Frame", "oran_fh_cus.ackNackId.response-frame",
7539 FT_FRAMENUM, BASE_NONE,
7540 FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE), 0x0,
7541 NULL, HFILL}
7543 { &hf_oran_acknack_response_time,
7544 { "Time to response in ms", "oran_fh_cus.ackNackId.time-to-response",
7545 FT_UINT32, BASE_DEC,
7546 NULL, 0x0,
7547 "Time between request and response", HFILL}
7550 /* 7.5.3.43 */
7551 { &hf_oran_disable_tdbfns,
7552 { "disableTDBFNs", "oran_fh_cus.disableTDBFNs",
7553 FT_BOOLEAN, 8,
7554 TFS(&disable_tdbfns_tfs), 0x80,
7555 NULL, HFILL}
7558 /* 7.5.3.44 */
7559 { &hf_oran_td_beam_group,
7560 { "tdBeamGrp", "oran_fh_cus.tdBeamGrp",
7561 FT_UINT16, BASE_HEX,
7562 NULL, 0x7fff,
7563 "Applies to symbolMask in command header", HFILL}
7565 /* 7.5.3.43 */
7566 { &hf_oran_disable_tdbfws,
7567 { "disableTDBFWs", "oran_fh_cus.disableTDBFWs",
7568 FT_BOOLEAN, 8,
7569 TFS(&beam_numbers_included_tfs), 0x80,
7570 NULL, HFILL}
7573 /* 7.5.3.56 */
7574 { &hf_oran_td_beam_num,
7575 { "tdBeamNum", "oran_fh_cus.tdBeamNum",
7576 FT_UINT16, BASE_HEX,
7577 NULL, 0x7fff,
7578 "time-domain beam number", HFILL}
7581 /* 7.5.3.49 */
7582 { &hf_oran_dir_pattern,
7583 { "dirPattern", "oran_fh_cus.dirPattern",
7584 FT_BOOLEAN, 16,
7585 TFS(&symbol_direction_tfs), 0x3fff,
7586 "symbol data direction (gNB Tx/Rx) pattern", HFILL}
7588 /* 7.5.3.50 */
7589 { &hf_oran_guard_pattern,
7590 { "guardPattern", "oran_fh_cus.guardPattern",
7591 FT_BOOLEAN, 16,
7592 TFS(&symbol_guard_tfs), 0x3fff,
7593 "guard pattern bitmask", HFILL}
7596 /* For convenient filtering */
7597 { &hf_oran_cplane,
7598 { "C-Plane", "oran_fh_cus.c-plane",
7599 FT_NONE, BASE_NONE,
7600 NULL, 0x0,
7601 NULL, HFILL}
7603 { &hf_oran_uplane,
7604 { "U-Plane", "oran_fh_cus.u-plane",
7605 FT_NONE, BASE_NONE,
7606 NULL, 0x0,
7607 NULL, HFILL}
7609 { &hf_oran_bf,
7610 { "BeamForming", "oran_fh_cus.bf",
7611 FT_NONE, BASE_NONE,
7612 NULL, 0x0,
7613 NULL, HFILL}
7617 /* 5.1.3.2.7 */
7618 { &hf_oran_ecpri_pcid,
7619 { "ecpriPcid", "oran_fh_cus.ecpriPcid",
7620 FT_NONE, BASE_NONE,
7621 NULL, 0x0,
7622 "IQ data transfer message series identifier", HFILL}
7624 { &hf_oran_ecpri_rtcid,
7625 { "ecpriRtcid", "oran_fh_cus.ecpriRtcid",
7626 FT_NONE, BASE_NONE,
7627 NULL, 0x0,
7628 "Real time control data identifier", HFILL}
7630 /* 5.1.3.2.8 */
7631 { &hf_oran_ecpri_seqid,
7632 { "ecpriSeqid", "oran_fh_cus.ecpriSeqid",
7633 FT_NONE, BASE_NONE,
7634 NULL, 0x0,
7635 "message identifier", HFILL}
7638 /* 7.7.23.2 */
7639 { &hf_oran_num_sym_prb_pattern,
7640 { "numSymPrbPattern", "oran_fh_cus.numSymPrbPattern",
7641 FT_UINT8, BASE_DEC,
7642 NULL, 0xf0,
7643 "number of symbol and resource block patterns", HFILL}
7645 /* 7.7.23.11 */
7646 { &hf_oran_prb_mode,
7647 { "prbMode", "oran_fh_cus.prbMode",
7648 FT_BOOLEAN, 8,
7649 TFS(&prb_mode_tfs), 0x01,
7650 "PRB Mode", HFILL}
7653 { &hf_oran_sym_prb_pattern,
7654 { "symPrbPattern", "oran_fh_cus.symPrbPattern",
7655 FT_STRING, BASE_NONE,
7656 NULL, 0x0,
7657 NULL, HFILL}
7660 /* 7.7.23.3 */
7661 { &hf_oran_sym_mask,
7662 { "symMask", "oran_fh_cus.symMask",
7663 FT_UINT16, BASE_HEX,
7664 NULL, 0x3fff,
7665 "symbol mask part of symPrbPattern", HFILL}
7667 /* 7.7.23.5 */
7668 {&hf_oran_num_mc_scale_offset,
7669 {"numMcScaleOffset", "oran_fh_cus.numMcScaleOffset",
7670 FT_UINT8, BASE_DEC,
7671 NULL, 0xf0,
7672 "number of modulation compression scaling value per symPrbPattern",
7673 HFILL}
7675 /* 7.7.23.4 */
7676 { &hf_oran_prb_pattern,
7677 { "prbPattern", "oran_fh_cus.prbPattern",
7678 FT_UINT8, BASE_DEC,
7679 NULL, 0x0f,
7680 "resource block pattern part of symPrbPattern", HFILL}
7683 /* 7.7.3.2 */
7684 { &hf_oran_codebook_index,
7685 { "codebookIndex", "oran_fh_cus.codebookIndex",
7686 FT_UINT8, BASE_DEC,
7687 NULL, 0x0,
7688 "precoder codebook used for transmission", HFILL}
7690 /* 7.7.3.3 */
7691 { &hf_oran_layerid,
7692 { "layerID", "oran_fh_cus.layerID",
7693 FT_UINT8, BASE_DEC,
7694 NULL, 0xf0,
7695 "Layer ID for DL transmission", HFILL}
7697 /* 7.7.3.5 */
7698 { &hf_oran_numlayers,
7699 { "numLayers", "oran_fh_cus.numLayers",
7700 FT_UINT8, BASE_DEC,
7701 NULL, 0x0f,
7702 "number of layers for DL transmission", HFILL}
7704 /* 7.7.3.4 */
7705 { &hf_oran_txscheme,
7706 { "txScheme", "oran_fh_cus.txScheme",
7707 FT_UINT8, BASE_DEC,
7708 NULL, 0xf0,
7709 "transmission scheme", HFILL}
7711 /* 7.7.3.6 */
7712 { &hf_oran_crs_remask,
7713 { "crsReMask", "oran_fh_cus.crsReMask",
7714 FT_UINT16, BASE_HEX,
7715 NULL, 0x0fff,
7716 "CRS resource element mask", HFILL}
7718 /* 7.7.3.8 */
7719 { &hf_oran_crs_shift,
7720 { "crsShift", "oran_fh_cus.crsShift",
7721 FT_UINT8, BASE_HEX,
7722 NULL, 0x80,
7723 "CRS resource element mask", HFILL}
7725 /* 7.7.3.7 */
7726 { &hf_oran_crs_symnum,
7727 { "crsSymNum", "oran_fh_cus.crsSymNum",
7728 FT_UINT8, BASE_DEC,
7729 NULL, 0x0f,
7730 "CRS symbol number indication", HFILL}
7732 /* 7.7.3.9 */
7733 { &hf_oran_beamid_ap1,
7734 { "beamIdAP1", "oran_fh_cus.beamIdAP1",
7735 FT_UINT16, BASE_DEC,
7736 NULL, 0x7f,
7737 "beam id to be used for antenna port 1", HFILL}
7739 /* 7.7.3.10 */
7740 { &hf_oran_beamid_ap2,
7741 { "beamIdAP2", "oran_fh_cus.beamIdAP2",
7742 FT_UINT16, BASE_DEC,
7743 NULL, 0x7f,
7744 "beam id to be used for antenna port 2", HFILL}
7746 /* 7.7.3.11 */
7747 { &hf_oran_beamid_ap3,
7748 { "beamIdAP3", "oran_fh_cus.beamIdAP3",
7749 FT_UINT16, BASE_DEC,
7750 NULL, 0x7f,
7751 "beam id to be used for antenna port 3", HFILL}
7754 /* 7.7.10.3a */
7755 { &hf_oran_port_list_index,
7756 { "portListIndex", "oran_fh_cus.portListIndex",
7757 FT_UINT8, BASE_DEC,
7758 NULL, 0x0,
7759 "the index of an eAxC_ID in the port-list", HFILL}
7762 { &hf_oran_alpn_per_sym,
7763 { "alpnPerSym", "oran_fh_cus.alpnPerSym",
7764 FT_UINT8, BASE_HEX,
7765 VALS(alpn_per_sym_vals), 0x80,
7766 NULL, HFILL}
7768 { &hf_oran_ant_dmrs_snr,
7769 { "antDmrsSnr", "oran_fh_cus.antDmrsSnr",
7770 FT_UINT8, BASE_HEX,
7771 VALS(ant_dmrs_snr_vals), 0x40,
7772 NULL, HFILL}
7775 /* 7.7.24.6 */
7776 { &hf_oran_user_group_size,
7777 { "userGroupSize", "oran_fh_cus.userGroupSize",
7778 FT_UINT8, BASE_DEC,
7779 NULL, 0x1f,
7780 "number of UE data layers in the user group identified by userGroupId", HFILL}
7782 /* 7.7.24.7 */
7783 { &hf_oran_user_group_id,
7784 { "userGroupId", "oran_fh_cus.userGroupId",
7785 FT_UINT8, BASE_DEC,
7786 NULL, 0x0,
7787 "number of UE data layers in the user group identified by userGroupId", HFILL}
7789 /* 7.7.24.8 */
7790 { &hf_oran_entry_type,
7791 { "entryType", "oran_fh_cus.entryType",
7792 FT_UINT8, BASE_DEC,
7793 NULL, 0xe0,
7794 "indicates format of the entry", HFILL}
7796 /* 7.7.24.9 */
7797 { &hf_oran_dmrs_port_number,
7798 { "dmrsPortNumber", "oran_fh_cus.dmrsPortNumber",
7799 FT_UINT8, BASE_DEC,
7800 NULL, 0x1f,
7801 "DMRS antenna port number for the associated ueId", HFILL}
7803 /* 7.7.24.10 */
7804 { &hf_oran_ueid_reset,
7805 { "ueidReset", "oran_fh_cus.ueidReset",
7806 FT_BOOLEAN, 8,
7807 TFS(&tfs_ueid_reset), 0x80,
7808 "same UEID as the previous slot", HFILL}
7810 /* 7.7.24.11 */
7811 { &hf_oran_dmrs_symbol_mask,
7812 { "dmrsSymbolMask", "oran_fh_cus.dmrsSymbolMask",
7813 FT_UINT16, BASE_HEX,
7814 NULL, 0x3fff,
7815 "symbols within the slot containing DMRS", HFILL}
7817 /* 7.7.24.12 */
7818 { &hf_oran_scrambling,
7819 { "scrambling", "oran_fh_cus.scrambling",
7820 FT_UINT16, BASE_HEX,
7821 NULL, 0x0,
7822 "used to calculate the seed value required to initialize pseudo-random generator", HFILL}
7824 /* 7.7.24.13 */
7825 { &hf_oran_nscid,
7826 { "nscid", "oran_fh_cus.nscid",
7827 FT_UINT8, BASE_HEX,
7828 NULL, 0x80,
7829 "used to calculate the seed value for pseudo-random generator", HFILL}
7831 /* 7.7.24.14 */
7832 { &hf_oran_dtype,
7833 { "dType", "oran_fh_cus.dType",
7834 FT_UINT8, BASE_HEX,
7835 VALS(dtype_vals), 0x40,
7836 "PUSCH DMRS configuration type", HFILL}
7838 /* 7.7.24.15 */
7839 { &hf_oran_cmd_without_data,
7840 { "cmdWithoutData", "oran_fh_cus.cmdWithoutData",
7841 FT_UINT8, BASE_HEX,
7842 NULL, 0x30,
7843 "number of DMRS CDM groups without data", HFILL}
7845 /* 7.7.24.16 */
7846 { &hf_oran_lambda,
7847 { "lambda", "oran_fh_cus.lambda",
7848 FT_UINT8, BASE_HEX,
7849 NULL, 0x0c,
7850 NULL, HFILL}
7852 /* 7.7.24.19 */
7853 { &hf_oran_first_prb,
7854 { "firstPrb", "oran_fh_cus.firstPrb",
7855 FT_UINT16, BASE_DEC,
7856 NULL, 0x03fe,
7857 NULL, HFILL}
7859 /* 7.7.24.20 */
7860 { &hf_oran_last_prb,
7861 { "lastPrb", "oran_fh_cus.lastPrb",
7862 FT_UINT16, BASE_DEC,
7863 NULL, 0x01ff,
7864 NULL, HFILL}
7867 /* 7.7.24.17 */
7868 /* TODO: add value_string */
7869 { &hf_oran_low_papr_type,
7870 { "lowPaprType", "oran_fh_cus.lowPaprType",
7871 FT_UINT8, BASE_HEX,
7872 VALS(papr_type_vals), 0x30,
7873 NULL, HFILL}
7875 /* 7.7.24.18 */
7876 { &hf_oran_hopping_mode,
7877 { "hoppingMode", "oran_fh_cus.hoppingMode",
7878 FT_UINT8, BASE_HEX,
7879 VALS(hopping_mode_vals), 0x0c,
7880 NULL, HFILL}
7883 { &hf_oran_tx_win_for_on_air_symbol_l,
7884 { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
7885 FT_UINT8, BASE_DEC,
7886 NULL, 0xf0,
7887 NULL, HFILL}
7889 { &hf_oran_tx_win_for_on_air_symbol_r,
7890 { "txWinForOnAirSymbol", "oran_fh_cus.txWinForOnAirSymbol",
7891 FT_UINT8, BASE_DEC,
7892 NULL, 0x0f,
7893 NULL, HFILL}
7895 /* 7.7.26.2 */
7896 { &hf_oran_num_fo_fb,
7897 { "numFoFb", "oran_fh_cus.numFoFb",
7898 FT_UINT8, BASE_DEC,
7899 NULL, 0x7f,
7900 "number of frequency offset feedback", HFILL}
7902 /* 7.7.26.3 */
7903 { &hf_oran_freq_offset_fb,
7904 { "freqOffsetFb", "oran_fh_cus.freqOffsetFb",
7905 FT_UINT16, BASE_HEX_DEC | BASE_RANGE_STRING,
7906 RVALS(freq_offset_fb_values), 0x0,
7907 "UE frequency offset feedback", HFILL}
7910 /* 7.5.2.19 */
7911 { &hf_oran_num_sinr_per_prb,
7912 { "numSinrPerPrb", "oran_fh_cus.numSinrPerPrb",
7913 FT_UINT8, BASE_DEC,
7914 VALS(num_sinr_per_prb_vals), 0xe0,
7915 "number of SINR values per PRB", HFILL}
7918 /* 7.5.3.68 */
7919 { &hf_oran_sinr_value,
7920 { "sinrValue", "oran_fh_cus.sinrValue",
7921 FT_FLOAT, BASE_NONE,
7922 NULL, 0x0,
7923 NULL, HFILL}
7926 { &hf_oran_measurement_report,
7927 { "Measurement Report", "oran_fh_cus.measurement-report",
7928 FT_STRING, BASE_NONE,
7929 NULL, 0x0,
7930 NULL, HFILL}
7932 /* 7.5.3.57 */
7933 { &hf_oran_mf,
7934 { "mf", "oran_fh_cus.mf",
7935 FT_BOOLEAN, 8,
7936 TFS(&measurement_flag_tfs), 0x80,
7937 "measurement flag", HFILL}
7939 /* 7.5.3.59 */
7940 { &hf_oran_meas_data_size,
7941 { "measDataSize", "oran_fh_cus.measDataSize",
7942 FT_UINT16, BASE_DEC,
7943 NULL, 0x0,
7944 "measurement data size (in words)", HFILL}
7947 /* 7.5.3.58 */
7948 { &hf_oran_meas_type_id,
7949 { "measTypeId", "oran_fh_cus.measTypeId",
7950 FT_UINT8, BASE_DEC,
7951 VALS(meas_type_id_vals), 0x7F,
7952 "measurement report type identifier", HFILL}
7954 /* 7.5.3.66 */
7955 { &hf_oran_num_elements,
7956 { "numElements", "oran_fh_cus.numElements",
7957 FT_UINT8, BASE_DEC,
7958 NULL, 0x0,
7959 "measurement report type identifier", HFILL}
7961 /* 7.5.3.60 */
7962 { &hf_oran_ue_tae,
7963 { "ueTae", "oran_fh_cus.ueTae",
7964 FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
7965 RVALS(freq_offset_fb_values), 0x0,
7966 "UE Timing Advance Error", HFILL}
7968 /* 7.5.3.61 */
7969 { &hf_oran_ue_layer_power,
7970 { "ueLayerPower", "oran_fh_cus.ueLayerPower",
7971 FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
7972 RVALS(freq_offset_fb_values), 0x0,
7973 "UE Layer Power", HFILL}
7976 /* 7.5.3.62 */
7977 { &hf_oran_ue_freq_offset,
7978 { "ueFreqOffset", "oran_fh_cus.ueFreqOffset",
7979 FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
7980 RVALS(freq_offset_fb_values), 0x0,
7981 "UE frequency offset", HFILL}
7983 /* 7.5.3.63 */
7984 { &hf_oran_ipn_power,
7985 { "ipnPower", "oran_fh_cus.ipnPower",
7986 FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
7987 RVALS(freq_offset_fb_values), 0x0,
7988 "Interference plus Noise power", HFILL}
7990 /* 7.5.3.64 */
7991 { &hf_oran_ant_dmrs_snr_val,
7992 { "antDmrsSnrVal", "oran_fh_cus.antDmrsSnrVal",
7993 FT_UINT16, BASE_DEC | BASE_RANGE_STRING,
7994 RVALS(freq_offset_fb_values), 0x0,
7995 "antenna DMRS-SNR", HFILL}
7998 /* 7.5.27.2 */
7999 {&hf_oran_beam_type,
8000 {"beamType", "oran_fh_cus.beamType",
8001 FT_UINT16, BASE_DEC,
8002 VALS(beam_type_vals), 0xc0,
8003 NULL,
8004 HFILL}
8006 /* 7.5.3.65 */
8007 {&hf_oran_meas_cmd_size,
8008 {"measCmdSize", "oran_fh_cus.measCmdSize",
8009 FT_UINT16, BASE_DEC,
8010 NULL, 0x0,
8011 "measurement command size in words",
8012 HFILL}
8015 { &hf_oran_symbol_reordering_layer,
8016 { "Layer", "oran_fh_cus.layer",
8017 FT_STRING, BASE_NONE,
8018 NULL, 0x0,
8019 NULL, HFILL}
8021 { &hf_oran_dmrs_entry,
8022 { "Entry", "oran_fh_cus.dmrs-entry",
8023 FT_STRING, BASE_NONE,
8024 NULL, 0x0,
8025 NULL, HFILL}
8028 { &hf_oran_c_section_common,
8029 { "Common Section", "oran_fh_cus.c-plane.section.common",
8030 FT_STRING, BASE_NONE,
8031 NULL, 0x0,
8032 NULL, HFILL}
8034 { &hf_oran_c_section,
8035 { "Section", "oran_fh_cus.c-plane.section",
8036 FT_STRING, BASE_NONE,
8037 NULL, 0x0,
8038 NULL, HFILL}
8040 { &hf_oran_u_section,
8041 { "Section", "oran_fh_cus.u-plane.section",
8042 FT_STRING, BASE_NONE,
8043 NULL, 0x0,
8044 NULL, HFILL}
8048 /* Setup protocol subtree array */
8049 static int *ett[] = {
8050 &ett_oran,
8051 &ett_oran_ecpri_pcid,
8052 &ett_oran_ecpri_rtcid,
8053 &ett_oran_ecpri_seqid,
8054 &ett_oran_section_type,
8055 &ett_oran_u_timing,
8056 &ett_oran_u_section,
8057 &ett_oran_u_prb,
8058 &ett_oran_section,
8059 &ett_oran_iq,
8060 &ett_oran_bfw_bundle,
8061 &ett_oran_bfw,
8062 &ett_oran_offset_start_prb_num_prb,
8063 &ett_oran_prb_cisamples,
8064 &ett_oran_cisample,
8065 &ett_oran_udcomphdr,
8066 &ett_oran_udcompparam,
8067 &ett_oran_cicomphdr,
8068 &ett_oran_cicompparam,
8069 &ett_oran_bfwcomphdr,
8070 &ett_oran_bfwcompparam,
8071 &ett_oran_ext19_port,
8072 &ett_oran_prb_allocation,
8073 &ett_oran_punc_pattern,
8074 &ett_oran_bfacomphdr,
8075 &ett_oran_modcomp_param_set,
8076 &ett_oran_st4_cmd_header,
8077 &ett_oran_st4_cmd,
8078 &ett_oran_sym_prb_pattern,
8079 &ett_oran_measurement_report,
8080 &ett_oran_sresmask,
8081 &ett_oran_c_section_common,
8082 &ett_oran_c_section,
8083 &ett_oran_remask,
8084 &ett_oran_symbol_reordering_layer,
8085 &ett_oran_dmrs_entry
8088 static int *ext_ett[HIGHEST_EXTTYPE];
8089 for (unsigned extno=0; extno<HIGHEST_EXTTYPE; extno++) {
8090 ext_ett[extno] = &ett_oran_c_section_extension[extno];
8093 expert_module_t* expert_oran;
8095 static ei_register_info ei[] = {
8096 { &ei_oran_unsupported_bfw_compression_method, { "oran_fh_cus.unsupported_bfw_compression_method", PI_UNDECODED, PI_WARN, "Unsupported BFW Compression Method", EXPFILL }},
8097 { &ei_oran_invalid_sample_bit_width, { "oran_fh_cus.invalid_sample_bit_width", PI_UNDECODED, PI_ERROR, "Unsupported sample bit width", EXPFILL }},
8098 { &ei_oran_reserved_numBundPrb, { "oran_fh_cus.reserved_numBundPrb", PI_MALFORMED, PI_ERROR, "Reserved value of numBundPrb", EXPFILL }},
8099 { &ei_oran_extlen_wrong, { "oran_fh_cus.extlen_wrong", PI_MALFORMED, PI_ERROR, "extlen doesn't match number of dissected bytes", EXPFILL }},
8100 { &ei_oran_invalid_eaxc_bit_width, { "oran_fh_cus.invalid_exac_bit_width", PI_UNDECODED, PI_ERROR, "Inconsistent eAxC bit width", EXPFILL }},
8101 { &ei_oran_extlen_zero, { "oran_fh_cus.extlen_zero", PI_MALFORMED, PI_ERROR, "extlen - zero is reserved value", EXPFILL }},
8102 { &ei_oran_rbg_size_reserved, { "oran_fh_cus.rbg_size_reserved", PI_MALFORMED, PI_ERROR, "rbgSize - zero is reserved value", EXPFILL }},
8103 { &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 }},
8104 { &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 }},
8105 { &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 }},
8106 { &ei_oran_st8_nackid, { "oran_fh_cus.st8_nackid", PI_SEQUENCE, PI_WARN, "operation for this ackId failed", EXPFILL }},
8107 { &ei_oran_st4_no_cmds, { "oran_fh_cus.st4_nackid", PI_MALFORMED, PI_ERROR, "Not valid to have no commands in ST4", EXPFILL }},
8108 { &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 }},
8109 { &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 }},
8110 { &ei_oran_st4_unknown_cmd, { "oran_fh_cus.st4_unknown_cmd", PI_MALFORMED, PI_ERROR, "ST4 cmd with unknown command code", EXPFILL }},
8111 { &ei_oran_mcot_out_of_range, { "oran_fh_cus.mcot_out_of_range", PI_MALFORMED, PI_ERROR, "MCOT should be 1-10", EXPFILL }},
8112 { &ei_oran_se10_unknown_beamgrouptype, { "oran_fh_cus.se10_unknown_beamgrouptype", PI_MALFORMED, PI_WARN, "SE10 - unknown BeamGroupType value", EXPFILL }},
8113 { &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 }},
8114 { &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 }},
8115 { &ei_oran_unhandled_se, { "oran_fh_cus.se_not_handled", PI_UNDECODED, PI_WARN, "SE not recognised/handled by dissector", EXPFILL }},
8116 { &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 }},
8117 { &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 }},
8118 { &ei_oran_version_unsupported, { "oran_fh_cus.version_unsupported", PI_UNDECODED, PI_WARN, "Protocol version unsupported", EXPFILL }},
8119 { &ei_oran_laa_msg_type_unsupported, { "oran_fh_cus.laa_msg_type_unsupported", PI_UNDECODED, PI_WARN, "laaMsgType unsupported", EXPFILL }},
8120 { &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 }},
8121 { &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 }},
8122 { &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 }},
8123 { &ei_oran_acknack_no_request, { "oran_fh_cus.acknack_no_request", PI_SEQUENCE, PI_WARN, "Have ackNackId response, but no request", EXPFILL }},
8124 { &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 }},
8125 { &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 }},
8126 { &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 }},
8127 { &ei_oran_lastRbdid_out_of_range, { "oran_fh_cus.lastrbdid_out_of_range", PI_MALFORMED, PI_WARN, "SE 6 has bad rbgSize", EXPFILL }},
8128 { &ei_oran_rbgMask_beyond_last_rbdid, { "oran_fh_cus.rbgmask_beyond_lastrbdid", PI_MALFORMED, PI_WARN, "rbgMask has bits set beyond lastRbgId", EXPFILL }},
8129 { &ei_oran_unexpected_measTypeId, { "oran_fh_cus.unexpected_meastypeid", PI_MALFORMED, PI_WARN, "unexpected measTypeId", EXPFILL }},
8130 { &ei_oran_unsupported_compression_method, { "oran_fh_cus.compression_type_unsupported", PI_UNDECODED, PI_WARN, "Unsupported compression type", EXPFILL }},
8131 { &ei_oran_ud_comp_len_wrong_size, { "oran_fh_cus.ud_comp_len_wrong_size", PI_MALFORMED, PI_WARN, "udCompLen does not match length of U-Plane section", EXPFILL }},
8132 { &ei_oran_sresmask2_not_zero_with_rb, { "oran_fh_cus.sresmask2_not_zero", PI_MALFORMED, PI_WARN, "sReSMask2 should be zero when rb set", EXPFILL }},
8133 { &ei_oran_st6_rb_shall_be_0, { "oran_fh_cus.st6_rb_set", PI_MALFORMED, PI_WARN, "rb should not be set for Section Type 6", EXPFILL }},
8134 { &ei_oran_st10_numsymbol_not_14, { "oran_fh_cus.st10_numsymbol_not_14", PI_MALFORMED, PI_WARN, "numSymbol should be 14 for Section Type 10", EXPFILL }},
8135 { &ei_oran_st10_startsymbolid_not_0, { "oran_fh_cus.st10_startsymbolid_not_0", PI_MALFORMED, PI_WARN, "startSymbolId should be 0 for Section Type 10", EXPFILL }}
8138 /* Register the protocol name and description */
8139 proto_oran = proto_register_protocol("O-RAN Fronthaul CUS", "O-RAN FH CUS", "oran_fh_cus");
8141 /* Allow dissector to find be found by name. */
8142 register_dissector("oran_fh_cus", dissect_oran, proto_oran);
8144 /* Register the tap name. */
8145 oran_tap = register_tap("oran-fh-cus");
8147 /* Required function calls to register the header fields and subtrees */
8148 proto_register_field_array(proto_oran, hf, array_length(hf));
8149 proto_register_subtree_array(ett, array_length(ett));
8150 proto_register_subtree_array(ext_ett, array_length(ext_ett));
8153 expert_oran = expert_register_protocol(proto_oran);
8154 expert_register_field_array(expert_oran, ei, array_length(ei));
8156 module_t * oran_module = prefs_register_protocol(proto_oran, NULL);
8158 /* Register bit width/compression preferences separately by direction. */
8159 prefs_register_uint_preference(oran_module, "oran.du_port_id_bits", "DU Port ID bits [a]",
8160 "The bit width of DU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_du_port_id_bits);
8161 prefs_register_uint_preference(oran_module, "oran.bandsector_id_bits", "BandSector ID bits [b]",
8162 "The bit width of BandSector ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_bandsector_id_bits);
8163 prefs_register_uint_preference(oran_module, "oran.cc_id_bits", "CC ID bits [c]",
8164 "The bit width of CC ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_cc_id_bits);
8165 prefs_register_uint_preference(oran_module, "oran.ru_port_id_bits", "RU Port ID bits [d]",
8166 "The bit width of RU Port ID - sum of a,b,c&d (eAxC) must be 16", 10, &pref_ru_port_id_bits);
8168 prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_up", "IQ Bitwidth Uplink",
8169 "The bit width of a sample in the Uplink (if no udcompHdr)", 10, &pref_sample_bit_width_uplink);
8170 prefs_register_enum_preference(oran_module, "oran.ud_comp_up", "Uplink User Data Compression",
8171 "Uplink User Data Compression", &pref_iqCompressionUplink, ul_compression_options, false);
8172 prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_up", "udCompHdr field is present for uplink",
8173 "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
8174 "configuration of the O-RU. This preference instructs the dissector to expect "
8175 "this field to be present in uplink messages",
8176 &pref_includeUdCompHeaderUplink, udcomphdr_present_options, false);
8178 prefs_register_uint_preference(oran_module, "oran.iq_bitwidth_down", "IQ Bitwidth Downlink",
8179 "The bit width of a sample in the Downlink (if no udcompHdr)", 10, &pref_sample_bit_width_downlink);
8180 prefs_register_enum_preference(oran_module, "oran.ud_comp_down", "Downlink User Data Compression",
8181 "Downlink User Data Compression", &pref_iqCompressionDownlink, dl_compression_options, false);
8182 prefs_register_enum_preference(oran_module, "oran.ud_comp_hdr_down", "udCompHdr field is present for downlink",
8183 "The udCompHdr field in U-Plane messages may or may not be present, depending on the "
8184 "configuration of the O-RU. This preference instructs the dissector to expect "
8185 "this field to be present in downlink messages",
8186 &pref_includeUdCompHeaderDownlink, udcomphdr_present_options, false);
8188 prefs_register_uint_preference(oran_module, "oran.rbs_in_uplane_section", "Total RBs in User-Plane data section",
8189 "This is used if numPrbu is signalled as 0", 10, &pref_data_plane_section_total_rbs);
8191 prefs_register_uint_preference(oran_module, "oran.num_weights_per_bundle", "Number of weights per bundle",
8192 "Used in decoding of section extension type 11 (Flexible BF weights)", 10, &pref_num_weights_per_bundle);
8194 prefs_register_uint_preference(oran_module, "oran.num_bf_antennas", "Number of BF Antennas",
8195 "Number of BF Antennas (used for C section type 6)", 10, &pref_num_bf_antennas);
8197 prefs_register_bool_preference(oran_module, "oran.show_iq_samples", "Show IQ Sample values",
8198 "When enabled, for U-Plane frames show each I and Q value in PRB", &pref_showIQSampleValues);
8200 prefs_register_obsolete_preference(oran_module, "oran.num_bf_weights");
8202 prefs_register_enum_preference(oran_module, "oran.support_udcomplen", "udCompLen supported",
8203 "When enabled, U-Plane messages with relevant compression schemes will include udCompLen",
8204 &pref_support_udcompLen, udcomp_support_options, false);
8206 flow_states_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
8207 flow_results_table = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
8209 register_init_routine(&oran_init_protocol);
8212 /* Simpler form of proto_reg_handoff_oran which can be used if there are
8213 * no prefs-dependent registration function calls. */
8214 void
8215 proto_reg_handoff_oran(void)
8220 * Editor modelines - http://www.wireshark.org/tools/modelines.html
8222 * Local Variables:
8223 * c-basic-offset: 4
8224 * tab-width: 8
8225 * indent-tabs-mode: nil
8226 * End:
8228 * ex: set shiftwidth=4 tabstop=8 expandtab:
8229 * :indentSize=4:tabSize=8:noTabs=true: