/src/wireshark/epan/dissectors/packet-umts_fp.c
Line | Count | Source |
1 | | /* packet-umts_fp.c |
2 | | * Routines for UMTS FP disassembly |
3 | | * |
4 | | * Martin Mathieson |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | |
15 | | #include <epan/packet.h> |
16 | | #include <epan/expert.h> |
17 | | #include <epan/prefs.h> |
18 | | #include <epan/conversation.h> |
19 | | #include <epan/proto_data.h> |
20 | | #include <epan/tfs.h> |
21 | | |
22 | | #include <wsutil/array.h> |
23 | | #include <wsutil/crc7.h> /* For FP data header and control frame CRC. */ |
24 | | #include <wsutil/crc16-plain.h> /* For FP Payload CRC. */ |
25 | | #include <wsutil/crc11.h> /* For FP EDCH header CRC. */ |
26 | | #include <wsutil/pint.h> |
27 | | #include <wsutil/ws_roundup.h> |
28 | | |
29 | | #include "packet-umts_fp.h" |
30 | | #include "packet-nbap.h" |
31 | | #include "packet-rrc.h" |
32 | | |
33 | | /* The Frame Protocol (FP) is described in: |
34 | | * 3GPP TS 25.427 (for dedicated channels) |
35 | | * 3GPP TS 25.435 (for common/shared channels) |
36 | | * |
37 | | * TODO: |
38 | | * - IUR interface-specific formats |
39 | | * - do CRC verification before further parsing |
40 | | * - Set the logical channel properly for non multiplexed, channels |
41 | | * for channels that doesn't have the C/T field! This should be based |
42 | | * on the RRC message RadioBearerSetup. |
43 | | * - E-DCH T2 heuristic dissector |
44 | | */ |
45 | | void proto_register_fp(void); |
46 | | void proto_reg_handoff_fp(void); |
47 | | |
48 | | /* Initialize the protocol and registered fields. */ |
49 | | |
50 | | static int proto_fp; |
51 | | static int proto_umts_mac; |
52 | | static int proto_umts_rlc; |
53 | | |
54 | | static int hf_fp_release; |
55 | | static int hf_fp_release_version; |
56 | | static int hf_fp_release_year; |
57 | | static int hf_fp_release_month; |
58 | | static int hf_fp_channel_type; |
59 | | static int hf_fp_division; |
60 | | static int hf_fp_direction; |
61 | | static int hf_fp_ddi_config; |
62 | | static int hf_fp_ddi_config_ddi; |
63 | | static int hf_fp_ddi_config_macd_pdu_size; |
64 | | |
65 | | static int hf_fp_header_crc; |
66 | | static int hf_fp_ft; |
67 | | static int hf_fp_cfn; |
68 | | static int hf_fp_pch_cfn; |
69 | | static int hf_fp_pch_toa; |
70 | | static int hf_fp_cfn_control; |
71 | | static int hf_fp_toa; |
72 | | static int hf_fp_tfi; |
73 | | static int hf_fp_usch_tfi; |
74 | | static int hf_fp_cpch_tfi; |
75 | | static int hf_fp_propagation_delay; |
76 | | static int hf_fp_tb; |
77 | | static int hf_fp_chan_zero_tbs; |
78 | | static int hf_fp_received_sync_ul_timing_deviation; |
79 | | static int hf_fp_pch_pi; |
80 | | static int hf_fp_pch_tfi; |
81 | | static int hf_fp_fach_tfi; |
82 | | static int hf_fp_transmit_power_level; |
83 | | static int hf_fp_paging_indication_bitmap; |
84 | | static int hf_fp_relevant_paging_indication_bitmap; |
85 | | static int hf_fp_pdsch_set_id; |
86 | | static int hf_fp_rx_timing_deviation; |
87 | | static int hf_fp_dch_e_rucch_flag; |
88 | | static int hf_fp_dch_control_frame_type; |
89 | | static int hf_fp_dch_rx_timing_deviation; |
90 | | static int hf_fp_quality_estimate; |
91 | | static int hf_fp_payload_crc; |
92 | | static int hf_fp_payload_crc_status; |
93 | | static int hf_fp_edch_header_crc; |
94 | | static int hf_fp_edch_fsn; |
95 | | static int hf_fp_edch_subframe; |
96 | | static int hf_fp_edch_number_of_subframes; |
97 | | static int hf_fp_edch_harq_retransmissions; |
98 | | static int hf_fp_edch_subframe_number; |
99 | | static int hf_fp_edch_number_of_mac_es_pdus; |
100 | | static int hf_fp_edch_ddi; |
101 | | static int hf_fp_edch_subframe_header; |
102 | | static int hf_fp_edch_number_of_mac_d_pdus; |
103 | | static int hf_fp_edch_pdu_padding; |
104 | | static int hf_fp_edch_tsn; |
105 | | static int hf_fp_edch_mac_es_pdu; |
106 | | |
107 | | static int hf_fp_edch_user_buffer_size; |
108 | | static int hf_fp_edch_no_macid_sdus; |
109 | | static int hf_fp_edch_number_of_mac_is_pdus; |
110 | | static int hf_fp_edch_mac_is_pdu; |
111 | | |
112 | | static int hf_fp_edch_e_rnti; |
113 | | static int hf_fp_edch_macis_descriptors; |
114 | | static int hf_fp_edch_macis_lchid; |
115 | | static int hf_fp_edch_macis_length; |
116 | | static int hf_fp_edch_macis_flag; |
117 | | static int hf_fp_edch_entity; |
118 | | |
119 | | static int hf_fp_frame_seq_nr; |
120 | | static int hf_fp_hsdsch_pdu_block_header; |
121 | | /* static int hf_fp_hsdsch_pdu_block; */ |
122 | | static int hf_fp_flush; |
123 | | static int hf_fp_fsn_drt_reset; |
124 | | static int hf_fp_drt_indicator; |
125 | | static int hf_fp_fach_indicator; |
126 | | static int hf_fp_total_pdu_blocks; |
127 | | static int hf_fp_drt; |
128 | | static int hf_fp_hrnti; |
129 | | static int hf_fp_rach_measurement_result; |
130 | | static int hf_fp_lchid; |
131 | | static int hf_fp_pdu_length_in_block; |
132 | | static int hf_fp_pdus_in_block; |
133 | | static int hf_fp_cmch_pi; |
134 | | static int hf_fp_user_buffer_size; |
135 | | static int hf_fp_hsdsch_credits; |
136 | | static int hf_fp_hsdsch_max_macd_pdu_len; |
137 | | static int hf_fp_hsdsch_max_macdc_pdu_len; |
138 | | static int hf_fp_hsdsch_interval; |
139 | | static int hf_fp_hsdsch_calculated_rate; |
140 | | static int hf_fp_hsdsch_unlimited_rate; |
141 | | static int hf_fp_hsdsch_repetition_period; |
142 | | static int hf_fp_hsdsch_data_padding; |
143 | | static int hf_fp_hsdsch_new_ie_flags; |
144 | | static int hf_fp_hsdsch_new_ie_flag[8]; |
145 | | static int hf_fp_hsdsch_drt; |
146 | | static int hf_fp_hsdsch_entity; |
147 | | static int hf_fp_hsdsch_physical_layer_category; |
148 | | static int hf_fp_timing_advance; |
149 | | static int hf_fp_num_of_pdu; |
150 | | static int hf_fp_mac_d_pdu_len; |
151 | | static int hf_fp_mac_d_pdu; |
152 | | static int hf_fp_data; |
153 | | static int hf_fp_crcis; |
154 | | static int hf_fp_crci[8]; |
155 | | static int hf_fp_common_control_frame_type; |
156 | | static int hf_fp_t1; |
157 | | static int hf_fp_t2; |
158 | | static int hf_fp_t3; |
159 | | static int hf_fp_ul_sir_target; |
160 | | static int hf_fp_pusch_set_id; |
161 | | static int hf_fp_activation_cfn; |
162 | | static int hf_fp_duration; |
163 | | static int hf_fp_power_offset; |
164 | | static int hf_fp_code_number; |
165 | | static int hf_fp_spreading_factor; |
166 | | static int hf_fp_mc_info; |
167 | | |
168 | | static int hf_fp_rach_new_ie_flags; |
169 | | static int hf_fp_rach_new_ie_flag_unused[7]; |
170 | | static int hf_fp_rach_ext_propagation_delay_present; |
171 | | static int hf_fp_rach_cell_portion_id_present; |
172 | | static int hf_fp_rach_angle_of_arrival_present; |
173 | | static int hf_fp_rach_ext_rx_sync_ul_timing_deviation_present; |
174 | | static int hf_fp_rach_ext_rx_timing_deviation_present; |
175 | | |
176 | | static int hf_fp_cell_portion_id; |
177 | | static int hf_fp_ext_propagation_delay; |
178 | | static int hf_fp_angle_of_arrival; |
179 | | static int hf_fp_ext_received_sync_ul_timing_deviation; |
180 | | |
181 | | static int hf_fp_radio_interface_parameter_update_flag[5]; |
182 | | static int hf_fp_dpc_mode; |
183 | | static int hf_fp_tpc_po; |
184 | | static int hf_fp_multiple_rl_set_indicator; |
185 | | static int hf_fp_max_ue_tx_pow; |
186 | | static int hf_fp_congestion_status; |
187 | | static int hf_fp_e_rucch_present; |
188 | | static int hf_fp_extended_bits_present; |
189 | | static int hf_fp_extended_bits; |
190 | | static int hf_fp_spare_extension; |
191 | | static int hf_fp_ul_setup_frame; |
192 | | static int hf_fp_dl_setup_frame; |
193 | | static int hf_fp_relevant_pi_frame; |
194 | | |
195 | | /* Subtrees. */ |
196 | | static int ett_fp; |
197 | | static int ett_fp_release; |
198 | | static int ett_fp_data; |
199 | | static int ett_fp_crcis; |
200 | | static int ett_fp_ddi_config; |
201 | | static int ett_fp_edch_subframe_header; |
202 | | static int ett_fp_edch_subframe; |
203 | | static int ett_fp_edch_maces; |
204 | | static int ett_fp_edch_macis_descriptors; |
205 | | static int ett_fp_hsdsch_new_ie_flags; |
206 | | static int ett_fp_rach_new_ie_flags; |
207 | | static int ett_fp_hsdsch_pdu_block_header; |
208 | | static int ett_fp_pch_relevant_pi; |
209 | | |
210 | | static expert_field ei_fp_hsdsch_common_experimental_support; |
211 | | static expert_field ei_fp_hsdsch_common_t3_not_implemented; |
212 | | static expert_field ei_fp_channel_type_unknown; |
213 | | static expert_field ei_fp_ddi_not_defined; |
214 | | static expert_field ei_fp_stop_hsdpa_transmission; |
215 | | static expert_field ei_fp_hsdsch_entity_not_specified; |
216 | | static expert_field ei_fp_expecting_tdd; |
217 | | static expert_field ei_fp_bad_payload_checksum; |
218 | | static expert_field ei_fp_e_rnti_t2_edch_frames; |
219 | | static expert_field ei_fp_crci_no_subdissector; |
220 | | static expert_field ei_fp_timing_adjustment_reported; |
221 | | static expert_field ei_fp_mac_is_sdus_miscount; |
222 | | static expert_field ei_fp_maybe_srb; |
223 | | static expert_field ei_fp_transport_channel_type_unknown; |
224 | | static expert_field ei_fp_pch_lost_relevant_pi_frame; |
225 | | static expert_field ei_fp_unable_to_locate_ddi_entry; |
226 | | static expert_field ei_fp_e_rnti_first_entry; |
227 | | static expert_field ei_fp_bad_header_checksum; |
228 | | static expert_field ei_fp_crci_error_bit_set_for_tb; |
229 | | static expert_field ei_fp_spare_extension; |
230 | | static expert_field ei_fp_no_per_frame_info; |
231 | | static expert_field ei_fp_no_per_conv_channel_info; |
232 | | static expert_field ei_fp_invalid_frame_count; |
233 | | static expert_field ei_fp_invalid_ddi_count; |
234 | | |
235 | | static dissector_handle_t rlc_bcch_handle; |
236 | | static dissector_handle_t mac_fdd_dch_handle; |
237 | | static dissector_handle_t mac_fdd_rach_handle; |
238 | | static dissector_handle_t mac_fdd_fach_handle; |
239 | | static dissector_handle_t mac_fdd_pch_handle; |
240 | | static dissector_handle_t mac_fdd_edch_handle; |
241 | | static dissector_handle_t mac_fdd_edch_type2_handle; |
242 | | static dissector_handle_t mac_fdd_hsdsch_handle; |
243 | | static dissector_handle_t fp_handle; |
244 | | static dissector_handle_t fp_aal2_handle; |
245 | | |
246 | | |
247 | | static proto_tree *top_level_tree; |
248 | | |
249 | | /* Variables used for preferences */ |
250 | | static bool preferences_call_mac_dissectors = true; |
251 | | static bool preferences_show_release_info = true; |
252 | | static bool preferences_payload_checksum = true; |
253 | | static bool preferences_header_checksum = true; |
254 | | static bool preferences_track_paging_indications = true; |
255 | | |
256 | | /* E-DCH (T1) channel header information */ |
257 | | struct edch_t1_subframe_info |
258 | | { |
259 | | uint8_t subframe_number; |
260 | | uint8_t number_of_mac_es_pdus; |
261 | | uint8_t ddi[64]; |
262 | | uint16_t number_of_mac_d_pdus[64]; |
263 | | }; |
264 | | |
265 | | /* E-DCH (T2) channel header information */ |
266 | | struct edch_t2_subframe_info |
267 | | { |
268 | | uint8_t subframe_number; |
269 | | uint8_t number_of_mac_is_pdus; |
270 | | uint8_t number_of_mac_is_sdus[16]; |
271 | | uint8_t mac_is_lchid[16][16]; |
272 | | uint16_t mac_is_length[16][16]; |
273 | | }; |
274 | | |
275 | | |
276 | | static const value_string channel_type_vals[] = |
277 | | { |
278 | | { CHANNEL_RACH_FDD, "RACH_FDD" }, |
279 | | { CHANNEL_RACH_TDD, "RACH_TDD" }, |
280 | | { CHANNEL_FACH_FDD, "FACH_FDD" }, |
281 | | { CHANNEL_FACH_TDD, "FACH_TDD" }, |
282 | | { CHANNEL_DSCH_FDD, "DSCH_FDD" }, |
283 | | { CHANNEL_DSCH_TDD, "DSCH_TDD" }, |
284 | | { CHANNEL_USCH_TDD_384, "USCH_TDD_384" }, |
285 | | { CHANNEL_USCH_TDD_128, "USCH_TDD_128" }, |
286 | | { CHANNEL_PCH, "PCH" }, |
287 | | { CHANNEL_CPCH, "CPCH" }, |
288 | | { CHANNEL_BCH, "BCH" }, |
289 | | { CHANNEL_DCH, "DCH" }, |
290 | | { CHANNEL_HSDSCH, "HSDSCH" }, |
291 | | { CHANNEL_IUR_CPCHF, "IUR CPCHF" }, |
292 | | { CHANNEL_IUR_FACH, "IUR FACH" }, |
293 | | { CHANNEL_IUR_DSCH, "IUR DSCH" }, |
294 | | { CHANNEL_EDCH, "EDCH" }, |
295 | | { CHANNEL_RACH_TDD_128, "RACH_TDD_128" }, |
296 | | { CHANNEL_HSDSCH_COMMON, "HSDSCH-COMMON" }, |
297 | | { CHANNEL_HSDSCH_COMMON_T3, "HSDSCH-COMMON-T3" }, |
298 | | { CHANNEL_EDCH_COMMON, "EDCH-COMMON"}, |
299 | | { 0, NULL } |
300 | | }; |
301 | | |
302 | | static const value_string division_vals[] = |
303 | | { |
304 | | { Division_FDD, "FDD"}, |
305 | | { Division_TDD_384, "TDD-384"}, |
306 | | { Division_TDD_128, "TDD-128"}, |
307 | | { Division_TDD_768, "TDD-768"}, |
308 | | { 0, NULL } |
309 | | }; |
310 | | |
311 | | /* Frame Type (ft) values */ |
312 | | #define FT_DATA 0 |
313 | 0 | #define FT_CONTROL 1 |
314 | | |
315 | | static const value_string frame_type_vals[] = { |
316 | | { FT_DATA, "Data" }, |
317 | | { FT_CONTROL, "Control" }, |
318 | | { 0, NULL } |
319 | | }; |
320 | | |
321 | | static const value_string crci_vals[] = { |
322 | | { 0, "Correct" }, |
323 | | { 1, "Not correct" }, |
324 | | { 0, NULL } |
325 | | }; |
326 | | |
327 | | static const value_string paging_indication_vals[] = { |
328 | | { 0, "no PI-bitmap in payload" }, |
329 | | { 1, "PI-bitmap in payload" }, |
330 | | { 0, NULL } |
331 | | }; |
332 | | |
333 | | static const value_string spreading_factor_vals[] = { |
334 | | { 0, "4"}, |
335 | | { 1, "8"}, |
336 | | { 2, "16"}, |
337 | | { 3, "32"}, |
338 | | { 4, "64"}, |
339 | | { 5, "128"}, |
340 | | { 6, "256"}, |
341 | | { 0, NULL } |
342 | | }; |
343 | | |
344 | | static const value_string congestion_status_vals[] = { |
345 | | { 0, "No TNL congestion"}, |
346 | | { 1, "Reserved for future use"}, |
347 | | { 2, "TNL congestion - detected by delay build-up"}, |
348 | | { 3, "TNL congestion - detected by frame loss"}, |
349 | | { 0, NULL } |
350 | | }; |
351 | | |
352 | | static const value_string e_rucch_flag_vals[] = { |
353 | | { 0, "Conventional E-RUCCH reception" }, |
354 | | { 1, "TA Request reception" }, |
355 | | { 0, NULL } |
356 | | }; |
357 | | |
358 | | static const value_string hsdshc_mac_entity_vals[] = { |
359 | | { entity_not_specified, "Unspecified (assume MAC-hs)" }, |
360 | | { hs, "MAC-hs" }, |
361 | | { ehs, "MAC-ehs" }, |
362 | | { 0, NULL } |
363 | | }; |
364 | | |
365 | | static const value_string edch_mac_entity_vals[] = { |
366 | | { 0, "MAC-e/es" }, |
367 | | { 1, "MAC-i/is" }, |
368 | | { 0, NULL } |
369 | | }; |
370 | | |
371 | | static const value_string lchid_vals[] = { |
372 | | { 0, "Logical Channel 1" }, |
373 | | { 1, "Logical Channel 2" }, |
374 | | { 2, "Logical Channel 3" }, |
375 | | { 3, "Logical Channel 4" }, |
376 | | { 4, "Logical Channel 5" }, |
377 | | { 5, "Logical Channel 6" }, |
378 | | { 6, "Logical Channel 7" }, |
379 | | { 7, "Logical Channel 8" }, |
380 | | { 8, "Logical Channel 9" }, |
381 | | { 9, "Logical Channel 10" }, |
382 | | { 10, "Logical Channel 11" }, |
383 | | { 11, "Logical Channel 12" }, |
384 | | { 12, "Logical Channel 13" }, |
385 | | { 13, "Logical Channel 14" }, |
386 | | { 14, "CCCH (SRB0)" }, |
387 | | { 15, "E-RNTI being included (FDD only)" }, |
388 | | { 0, NULL } |
389 | | }; |
390 | | |
391 | | /* Dedicated control types */ |
392 | 0 | #define DCH_OUTER_LOOP_POWER_CONTROL 1 |
393 | 0 | #define DCH_TIMING_ADJUSTMENT 2 |
394 | 0 | #define DCH_DL_SYNCHRONISATION 3 |
395 | 0 | #define DCH_UL_SYNCHRONISATION 4 |
396 | | |
397 | 0 | #define DCH_DL_NODE_SYNCHRONISATION 6 |
398 | 0 | #define DCH_UL_NODE_SYNCHRONISATION 7 |
399 | 0 | #define DCH_RX_TIMING_DEVIATION 8 |
400 | 0 | #define DCH_RADIO_INTERFACE_PARAMETER_UPDATE 9 |
401 | 0 | #define DCH_TIMING_ADVANCE 10 |
402 | 0 | #define DCH_TNL_CONGESTION_INDICATION 11 |
403 | | |
404 | | static const value_string dch_control_frame_type_vals[] = { |
405 | | { DCH_OUTER_LOOP_POWER_CONTROL, "OUTER LOOP POWER CONTROL" }, |
406 | | { DCH_TIMING_ADJUSTMENT, "TIMING ADJUSTMENT" }, |
407 | | { DCH_DL_SYNCHRONISATION, "DL SYNCHRONISATION" }, |
408 | | { DCH_UL_SYNCHRONISATION, "UL SYNCHRONISATION" }, |
409 | | { 5, "Reserved Value" }, |
410 | | { DCH_DL_NODE_SYNCHRONISATION, "DL NODE SYNCHRONISATION" }, |
411 | | { DCH_UL_NODE_SYNCHRONISATION, "UL NODE SYNCHRONISATION" }, |
412 | | { DCH_RX_TIMING_DEVIATION, "RX TIMING DEVIATION" }, |
413 | | { DCH_RADIO_INTERFACE_PARAMETER_UPDATE, "RADIO INTERFACE PARAMETER UPDATE" }, |
414 | | { DCH_TIMING_ADVANCE, "TIMING ADVANCE" }, |
415 | | { DCH_TNL_CONGESTION_INDICATION, "TNL CONGESTION INDICATION" }, |
416 | | { 0, NULL } |
417 | | }; |
418 | | |
419 | | |
420 | | /* Common channel control types */ |
421 | 0 | #define COMMON_OUTER_LOOP_POWER_CONTROL 1 |
422 | 0 | #define COMMON_TIMING_ADJUSTMENT 2 |
423 | 0 | #define COMMON_DL_SYNCHRONISATION 3 |
424 | 0 | #define COMMON_UL_SYNCHRONISATION 4 |
425 | | |
426 | 0 | #define COMMON_DL_NODE_SYNCHRONISATION 6 |
427 | 0 | #define COMMON_UL_NODE_SYNCHRONISATION 7 |
428 | 0 | #define COMMON_DYNAMIC_PUSCH_ASSIGNMENT 8 |
429 | 0 | #define COMMON_TIMING_ADVANCE 9 |
430 | 0 | #define COMMON_HS_DSCH_Capacity_Request 10 |
431 | 0 | #define COMMON_HS_DSCH_Capacity_Allocation 11 |
432 | 0 | #define COMMON_HS_DSCH_Capacity_Allocation_Type_2 12 |
433 | | |
434 | | static const value_string common_control_frame_type_vals[] = { |
435 | | { COMMON_OUTER_LOOP_POWER_CONTROL, "OUTER LOOP POWER CONTROL" }, |
436 | | { COMMON_TIMING_ADJUSTMENT, "TIMING ADJUSTMENT" }, |
437 | | { COMMON_DL_SYNCHRONISATION, "DL SYNCHRONISATION" }, |
438 | | { COMMON_UL_SYNCHRONISATION, "UL SYNCHRONISATION" }, |
439 | | { 5, "Reserved Value" }, |
440 | | { COMMON_DL_NODE_SYNCHRONISATION, "DL NODE SYNCHRONISATION" }, |
441 | | { COMMON_UL_NODE_SYNCHRONISATION, "UL NODE SYNCHRONISATION" }, |
442 | | { COMMON_DYNAMIC_PUSCH_ASSIGNMENT, "DYNAMIC PUSCH ASSIGNMENT" }, |
443 | | { COMMON_TIMING_ADVANCE, "TIMING ADVANCE" }, |
444 | | { COMMON_HS_DSCH_Capacity_Request, "HS-DSCH Capacity Request" }, |
445 | | { COMMON_HS_DSCH_Capacity_Allocation, "HS-DSCH Capacity Allocation" }, |
446 | | { COMMON_HS_DSCH_Capacity_Allocation_Type_2, "HS-DSCH Capacity Allocation Type 2" }, |
447 | | { 0, NULL } |
448 | | }; |
449 | | |
450 | | /* 0 to 7*/ |
451 | | static const uint8_t hsdsch_macdflow_id_rlc_map[] = { |
452 | | RLC_UM, /*0 SRB */ |
453 | | RLC_AM, /*1 Interactive PS*/ |
454 | | RLC_AM, /*2 Interactive PS*/ |
455 | | RLC_UNKNOWN_MODE, /*3 ???*/ |
456 | | RLC_AM, /*4 Streaming PS*/ |
457 | | RLC_UNKNOWN_MODE, |
458 | | RLC_UNKNOWN_MODE, |
459 | | RLC_UNKNOWN_MODE |
460 | | }; |
461 | | |
462 | | /* Mapping hsdsch MACd-FlowId to MAC_CONTENT, basically flowid = 1 (0) => SRB*/ |
463 | | /* 1 to 8*/ |
464 | | static const uint8_t hsdsch_macdflow_id_mac_content_map[] = { |
465 | | MAC_CONTENT_DCCH, /*1 SRB */ |
466 | | MAC_CONTENT_PS_DTCH, /*2 Interactive PS*/ |
467 | | MAC_CONTENT_PS_DTCH, /*3 Interactive PS*/ |
468 | | RLC_UNKNOWN_MODE, /*4 ???*/ |
469 | | MAC_CONTENT_PS_DTCH, /*5 Streaming PS*/ |
470 | | RLC_UNKNOWN_MODE, |
471 | | RLC_UNKNOWN_MODE, |
472 | | RLC_UNKNOWN_MODE |
473 | | }; |
474 | | |
475 | | /* Make fake logical channel id's based on MACdFlow-ID's, |
476 | | * XXXX Bug 12121 expanded the number of entries to 8(+2), |
477 | | * not at all sure what the proper value should be 0xfF? |
478 | | */ |
479 | | static const uint8_t fake_lchid_macd_flow[] = {1,9,14,11,0,12,0,0}; |
480 | | |
481 | | /* Dissect message parts */ |
482 | | static int dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
483 | | unsigned offset, struct fp_info *p_fp_info, |
484 | | dissector_handle_t *data_handle, |
485 | | void *data); |
486 | | |
487 | | static int dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
488 | | unsigned offset, uint16_t length, uint16_t number_of_pdus, struct fp_info *p_fp_info, |
489 | | void *data); |
490 | | static int dissect_macd_pdu_data_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
491 | | unsigned offset, uint16_t length, uint16_t number_of_pdus, struct fp_info * fpi, |
492 | | void *data); |
493 | | |
494 | | static int dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
495 | | fp_info *p_fp_info, unsigned offset); |
496 | | static void dissect_spare_extension_and_crc(tvbuff_t *tvb, packet_info *pinfo, |
497 | | proto_tree *tree, uint8_t dch_crc_present, |
498 | | unsigned offset, unsigned header_length); |
499 | | /* Dissect common control messages */ |
500 | | static int dissect_common_outer_loop_power_control(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, |
501 | | unsigned offset, struct fp_info *p_fp_info); |
502 | | static int dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, |
503 | | unsigned offset, struct fp_info *p_fp_info); |
504 | | static int dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree, |
505 | | tvbuff_t *tvb, unsigned offset); |
506 | | static int dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree, |
507 | | tvbuff_t *tvb, unsigned offset); |
508 | | static int dissect_common_dl_synchronisation(packet_info *pinfo, proto_tree *tree, |
509 | | tvbuff_t *tvb, unsigned offset, |
510 | | struct fp_info *p_fp_info); |
511 | | static int dissect_common_ul_synchronisation(packet_info *pinfo, proto_tree *tree, |
512 | | tvbuff_t *tvb, unsigned offset, |
513 | | struct fp_info *p_fp_info); |
514 | | static int dissect_common_timing_advance(packet_info *pinfo, proto_tree *tree, |
515 | | tvbuff_t *tvb, unsigned offset); |
516 | | static int dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree, |
517 | | tvbuff_t *tvb, unsigned offset); |
518 | | static int dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree, |
519 | | tvbuff_t *tvb, unsigned offset, |
520 | | struct fp_info *p_fp_info); |
521 | | static int dissect_hsdpa_capacity_allocation_type_2(packet_info *pinfo, proto_tree *tree, |
522 | | tvbuff_t *tvb, unsigned offset); |
523 | | static void dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
524 | | unsigned offset, struct fp_info *p_fp_info); |
525 | | static int dissect_common_dynamic_pusch_assignment(packet_info *pinfo, proto_tree *tree, |
526 | | tvbuff_t *tvb, unsigned offset); |
527 | | |
528 | | /* Dissect common channel types */ |
529 | | static void dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
530 | | unsigned offset, struct fp_info *p_fp_info, |
531 | | void *data); |
532 | | static void dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
533 | | unsigned offset, struct fp_info *p_fp_info, |
534 | | void *data); |
535 | | static void dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
536 | | unsigned offset, struct fp_info *p_fp_info); |
537 | | static void dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
538 | | unsigned offset, struct fp_info *p_fp_info); |
539 | | static void dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
540 | | unsigned offset, struct fp_info *p_fp_info, |
541 | | void *data); |
542 | | static void dissect_cpch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
543 | | unsigned offset, struct fp_info *p_fp_info); |
544 | | static void dissect_bch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
545 | | unsigned offset, struct fp_info *p_fp_info); |
546 | | static void dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
547 | | unsigned offset, struct fp_info *p_fp_info); |
548 | | static void dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
549 | | unsigned offset, struct fp_info *p_fp_info, |
550 | | void *data); |
551 | | static void dissect_hsdsch_type_2_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
552 | | unsigned offset, struct fp_info *p_fp_info, |
553 | | void *data); |
554 | | static void dissect_hsdsch_common_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
555 | | unsigned offset, |
556 | | struct fp_info *p_fp_info, |
557 | | void *data); |
558 | | |
559 | | /* Dissect DCH control messages */ |
560 | | static int dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo, |
561 | | tvbuff_t *tvb, unsigned offset); |
562 | | static int dissect_dch_rx_timing_deviation(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, unsigned offset, |
563 | | struct fp_info *p_fp_info); |
564 | | static int dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo, |
565 | | tvbuff_t *tvb, unsigned offset); |
566 | | static int dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo, |
567 | | tvbuff_t *tvb, unsigned offset); |
568 | | static int dissect_dch_outer_loop_power_control(proto_tree *tree, packet_info *pinfo, |
569 | | tvbuff_t *tvb, unsigned offset); |
570 | | static int dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo, |
571 | | tvbuff_t *tvb, unsigned offset); |
572 | | static int dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo, |
573 | | tvbuff_t *tvb, unsigned offset); |
574 | | static int dissect_dch_radio_interface_parameter_update(proto_tree *tree, packet_info *pinfo, |
575 | | tvbuff_t *tvb, unsigned offset); |
576 | | static int dissect_dch_timing_advance(proto_tree *tree, packet_info *pinfo, |
577 | | tvbuff_t *tvb, unsigned offset, struct fp_info *p_fp_info); |
578 | | static int dissect_dch_tnl_congestion_indication(proto_tree *tree, packet_info *pinfo, |
579 | | tvbuff_t *tvb, unsigned offset); |
580 | | |
581 | | |
582 | | static void dissect_dch_control_frame(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, |
583 | | unsigned offset, struct fp_info *p_fp_info); |
584 | | |
585 | | |
586 | | /* Dissect a DCH channel */ |
587 | | static void dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
588 | | unsigned offset, struct fp_info *p_fp_info, |
589 | | void *data); |
590 | | |
591 | | /* Dissect dedicated channels */ |
592 | | static void dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
593 | | unsigned offset, struct fp_info *p_fp_info, |
594 | | bool is_common, |
595 | | void *data); |
596 | | |
597 | | static void dissect_e_dch_t2_or_common_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
598 | | unsigned offset, struct fp_info *p_fp_info, |
599 | | int number_of_subframes, |
600 | | bool is_common, |
601 | | uint16_t header_crc, |
602 | | proto_item * header_crc_pi, |
603 | | void *data); |
604 | | |
605 | | /* Main dissection function */ |
606 | | static int dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data); |
607 | | |
608 | | /* |
609 | | * CRNC sends data downlink on uplink parameters. |
610 | | */ |
611 | | void |
612 | | set_umts_fp_conv_data(conversation_t *conversation, umts_fp_conversation_info_t *umts_fp_conversation_info) |
613 | 0 | { |
614 | |
|
615 | 0 | if (conversation == NULL) { |
616 | 0 | return; |
617 | 0 | } |
618 | | |
619 | 0 | conversation_add_proto_data(conversation, proto_fp, umts_fp_conversation_info); |
620 | 0 | } |
621 | | |
622 | | |
623 | | static int |
624 | | get_tb_count(struct fp_info *p_fp_info) |
625 | 0 | { |
626 | 0 | int chan, tb_count = 0; |
627 | 0 | for (chan = 0; chan < p_fp_info->num_chans; chan++) { |
628 | 0 | tb_count += p_fp_info->chan_num_tbs[chan]; |
629 | 0 | } |
630 | 0 | return tb_count; |
631 | 0 | } |
632 | | |
633 | | static bool verify_control_frame_crc(tvbuff_t * tvb, packet_info * pinfo, proto_item * pi, uint16_t frame_crc) |
634 | 0 | { |
635 | 0 | uint8_t crc = 0; |
636 | 0 | uint8_t * data = NULL; |
637 | | /* Get data. */ |
638 | 0 | data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, 0, tvb_reported_length(tvb)); |
639 | | /* Include only FT flag bit in CRC calculation. */ |
640 | 0 | data[0] = data[0] & 1; |
641 | | /* Calculate crc7 sum. */ |
642 | 0 | crc = crc7update(0, data, tvb_reported_length(tvb)); |
643 | 0 | crc = crc7finalize(crc); /* finalize crc */ |
644 | 0 | if (frame_crc == crc) { |
645 | 0 | proto_item_append_text(pi, " [correct]"); |
646 | 0 | return true; |
647 | 0 | } else { |
648 | 0 | proto_item_append_text(pi, " [incorrect, should be 0x%x]", crc); |
649 | 0 | expert_add_info(pinfo, pi, &ei_fp_bad_header_checksum); |
650 | 0 | return false; |
651 | 0 | } |
652 | 0 | } |
653 | | static bool verify_header_crc(tvbuff_t * tvb, packet_info * pinfo, proto_item * pi, uint16_t header_crc, unsigned header_length) |
654 | 0 | { |
655 | 0 | uint8_t crc = 0; |
656 | 0 | uint8_t * data = NULL; |
657 | | /* Get data of header with first byte removed. */ |
658 | 0 | data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, 1, header_length-1); |
659 | | /* Calculate crc7 sum. */ |
660 | 0 | crc = crc7update(0, data, header_length-1); |
661 | 0 | crc = crc7finalize(crc); /* finalize crc */ |
662 | 0 | if (header_crc == crc) { |
663 | 0 | proto_item_append_text(pi, " [correct]"); |
664 | 0 | return true; |
665 | 0 | } else { |
666 | 0 | proto_item_append_text(pi, " [incorrect, should be 0x%x]", crc); |
667 | 0 | expert_add_info(pinfo, pi, &ei_fp_bad_header_checksum); |
668 | 0 | return false; |
669 | 0 | } |
670 | 0 | } |
671 | | static bool verify_header_crc_edch(tvbuff_t * tvb, packet_info * pinfo, proto_item * pi, uint16_t header_crc, unsigned header_length) |
672 | 0 | { |
673 | 0 | uint16_t crc = 0; |
674 | 0 | uint8_t * data = NULL; |
675 | | /* First create new subset of header with first byte removed. */ |
676 | 0 | tvbuff_t * headtvb = tvb_new_subset_length(tvb, 1, header_length-1); |
677 | | /* Get data of header with first byte removed. */ |
678 | 0 | data = (uint8_t *)tvb_memdup(pinfo->pool, headtvb, 0, header_length-1); |
679 | | /* Remove first 4 bits of the remaining data which are Header CRC cont. */ |
680 | 0 | data[0] = data[0] & 0x0f; |
681 | 0 | crc = crc11_307_noreflect_noxor(data, header_length-1); |
682 | 0 | if (header_crc == crc) { |
683 | 0 | proto_item_append_text(pi, " [correct]"); |
684 | 0 | return true; |
685 | 0 | } else { |
686 | 0 | proto_item_append_text(pi, " [incorrect, should be 0x%x]", crc); |
687 | 0 | expert_add_info(pinfo, pi, &ei_fp_bad_header_checksum); |
688 | 0 | return false; |
689 | 0 | } |
690 | 0 | } |
691 | | |
692 | | /* Dissect the TBs of a UL data frame*/ |
693 | | static int |
694 | | dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
695 | | unsigned offset, struct fp_info *p_fp_info, |
696 | | dissector_handle_t *data_handle, void *data) |
697 | 0 | { |
698 | 0 | int chan, num_tbs = 0; |
699 | 0 | unsigned bit_offset = 0; |
700 | 0 | unsigned crci_bit_offset = (offset+1)<<3; /* Current offset + Quality estimate of 1 byte at the end*/ |
701 | 0 | unsigned data_bits = 0; |
702 | 0 | uint8_t crci_bit = 0; |
703 | 0 | proto_item *tree_ti = NULL; |
704 | 0 | proto_tree *data_tree = NULL; |
705 | 0 | bool dissected = false; |
706 | | |
707 | | /* Add data subtree */ |
708 | 0 | tree_ti = proto_tree_add_item(tree, hf_fp_data, tvb, offset, -1, ENC_NA); |
709 | 0 | proto_item_set_text(tree_ti, "TB data for %u chans", p_fp_info->num_chans); |
710 | 0 | data_tree = proto_item_add_subtree(tree_ti, ett_fp_data); |
711 | |
|
712 | 0 | if (p_fp_info->num_chans >= MAX_FP_CHANS) { |
713 | 0 | expert_add_info_format(pinfo, data_tree, &ei_fp_invalid_frame_count, "Invalid Number of channels (max is %u)", MAX_FP_CHANS); |
714 | 0 | return offset; |
715 | 0 | } |
716 | | |
717 | | /* Calculate offset to CRCI bits */ |
718 | | |
719 | 0 | if (p_fp_info->is_uplink) { |
720 | 0 | for (chan=0; chan < p_fp_info->num_chans; chan++) { |
721 | 0 | int n; |
722 | 0 | for (n=0; n < p_fp_info->chan_num_tbs[chan]; n++) { |
723 | | /* Advance bit offset */ |
724 | 0 | crci_bit_offset += p_fp_info->chan_tf_size[chan]; |
725 | | /* Pad out to next byte */ |
726 | 0 | crci_bit_offset = WS_ROUNDUP_8(crci_bit_offset); |
727 | 0 | } |
728 | 0 | } |
729 | 0 | } |
730 | | /* Now for the TB data */ |
731 | 0 | for (chan=0; chan < p_fp_info->num_chans; chan++) { |
732 | 0 | int n; |
733 | 0 | p_fp_info->cur_chan = chan; /*Set current channel?*/ |
734 | | /* Clearly show channels with no TBs */ |
735 | 0 | if (p_fp_info->chan_num_tbs[chan] == 0) { |
736 | 0 | proto_item *no_tb_ti = proto_tree_add_uint(data_tree, hf_fp_chan_zero_tbs, tvb, |
737 | 0 | offset+(bit_offset/8), |
738 | 0 | 0, chan+1); |
739 | 0 | proto_item_append_text(no_tb_ti, " (of size %d)", |
740 | 0 | p_fp_info->chan_tf_size[chan]); |
741 | 0 | proto_item_set_generated(no_tb_ti); |
742 | 0 | } |
743 | | |
744 | | /* Show TBs from non-empty channels */ |
745 | 0 | for (n=0; n < p_fp_info->chan_num_tbs[chan]; n++) { |
746 | |
|
747 | 0 | proto_item *ti; |
748 | 0 | p_fp_info->cur_tb = chan; /*Set current transport block?*/ |
749 | 0 | if (data_tree) { |
750 | 0 | ti = proto_tree_add_item(data_tree, hf_fp_tb, tvb, |
751 | 0 | offset + (bit_offset/8), |
752 | 0 | ((bit_offset % 8) + p_fp_info->chan_tf_size[chan] + 7) / 8, |
753 | 0 | ENC_NA); |
754 | 0 | proto_item_set_text(ti, "TB (chan %u, tb %u, %u bits)", |
755 | 0 | chan+1, n+1, p_fp_info->chan_tf_size[chan]); |
756 | 0 | } |
757 | |
|
758 | 0 | if (preferences_call_mac_dissectors && data_handle && |
759 | 0 | (p_fp_info->chan_tf_size[chan] > 0)) { |
760 | 0 | tvbuff_t *next_tvb; |
761 | 0 | proto_item *item; |
762 | | /* If this is DL we should not care about crci bits (since they don't exists)*/ |
763 | 0 | if (p_fp_info->is_uplink) { |
764 | | |
765 | |
|
766 | 0 | if ( p_fp_info->channel == CHANNEL_RACH_FDD) { /*In RACH we don't have any QE field, hence go back 8 bits.*/ |
767 | 0 | crci_bit = tvb_get_bits8(tvb, crci_bit_offset+n-8, 1); |
768 | 0 | item = proto_tree_add_item(data_tree, hf_fp_crci[n%8], tvb, (crci_bit_offset+n-8)/8, 1, ENC_BIG_ENDIAN); |
769 | 0 | proto_item_set_generated(item); |
770 | 0 | } else { |
771 | 0 | crci_bit = tvb_get_bits8(tvb, crci_bit_offset+n, 1); |
772 | 0 | item = proto_tree_add_item(data_tree, hf_fp_crci[n%8], tvb, (crci_bit_offset+n)/8, 1, ENC_BIG_ENDIAN); |
773 | 0 | proto_item_set_generated(item); |
774 | 0 | } |
775 | 0 | } |
776 | |
|
777 | 0 | if (crci_bit == 0 || !p_fp_info->is_uplink) { |
778 | 0 | next_tvb = tvb_new_subset_length(tvb, offset + bit_offset/8, |
779 | 0 | ((bit_offset % 8) + p_fp_info->chan_tf_size[chan] + 7) / 8); |
780 | | |
781 | | |
782 | | /****************/ |
783 | | /* TODO: maybe this decision can be based only on info available in fp_info */ |
784 | 0 | call_dissector_with_data(*data_handle, next_tvb, pinfo, top_level_tree, data); |
785 | 0 | dissected = true; |
786 | 0 | } else { |
787 | 0 | proto_tree_add_expert(tree, pinfo, &ei_fp_crci_no_subdissector, tvb, offset + bit_offset/8, |
788 | 0 | ((bit_offset % 8) + p_fp_info->chan_tf_size[chan] + 7) / 8); |
789 | 0 | } |
790 | |
|
791 | 0 | } |
792 | 0 | num_tbs++; |
793 | | |
794 | | /* Advance bit offset */ |
795 | 0 | bit_offset += p_fp_info->chan_tf_size[chan]; |
796 | 0 | data_bits += p_fp_info->chan_tf_size[chan]; |
797 | | |
798 | | /* Pad out to next byte */ |
799 | 0 | bit_offset = WS_ROUNDUP_8(bit_offset); |
800 | 0 | } |
801 | 0 | } |
802 | |
|
803 | 0 | if (dissected == false) { |
804 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "(%u bits in %u tbs)", |
805 | 0 | data_bits, num_tbs); |
806 | 0 | } |
807 | | |
808 | | /* Data tree should cover entire length */ |
809 | 0 | if (data_tree) { |
810 | 0 | proto_item_set_len(tree_ti, bit_offset/8); |
811 | 0 | proto_item_append_text(tree_ti, " (%u bits in %u tbs)", data_bits, num_tbs); |
812 | 0 | } |
813 | | |
814 | | /* Move offset past TBs (we know it's already padded out to next byte) */ |
815 | 0 | offset += (bit_offset / 8); |
816 | |
|
817 | 0 | return offset; |
818 | 0 | } |
819 | | |
820 | | |
821 | | /* Dissect the MAC-d PDUs of an HS-DSCH (type 1) frame. |
822 | | Length is in bits, and payload is offset by 4 bits of padding */ |
823 | | static int |
824 | | dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
825 | | unsigned offset, uint16_t length, uint16_t number_of_pdus, |
826 | | struct fp_info *p_fp_info, void *data) |
827 | 0 | { |
828 | 0 | int pdu; |
829 | 0 | unsigned bit_offset = 0; |
830 | 0 | proto_item *pdus_ti = NULL; |
831 | 0 | proto_tree *data_tree = NULL; |
832 | 0 | bool dissected = false; |
833 | | |
834 | | /* Add data subtree */ |
835 | 0 | pdus_ti = proto_tree_add_item(tree, hf_fp_data, tvb, offset, -1, ENC_NA); |
836 | 0 | proto_item_set_text(pdus_ti, "%u MAC-d PDUs of %u bits", number_of_pdus, length); |
837 | 0 | data_tree = proto_item_add_subtree(pdus_ti, ett_fp_data); |
838 | 0 | if (number_of_pdus >= MAX_MAC_FRAMES) { |
839 | 0 | expert_add_info_format(pinfo, data_tree, &ei_fp_invalid_frame_count, "Invalid number_of_pdus (max is %u)", MAX_MAC_FRAMES); |
840 | 0 | return offset; |
841 | 0 | } |
842 | | |
843 | | /* Now for the PDUs */ |
844 | 0 | for (pdu=0; pdu < number_of_pdus; pdu++) { |
845 | 0 | proto_item *pdu_ti; |
846 | |
|
847 | 0 | if (data_tree) { |
848 | | /* Show 4 bits padding at start of PDU */ |
849 | 0 | proto_tree_add_item(data_tree, hf_fp_hsdsch_data_padding, tvb, offset+(bit_offset/8), 1, ENC_BIG_ENDIAN); |
850 | |
|
851 | 0 | } |
852 | 0 | bit_offset += 4; |
853 | | |
854 | | /* Data bytes! */ |
855 | 0 | if (data_tree) { |
856 | 0 | pdu_ti = proto_tree_add_item(data_tree, hf_fp_mac_d_pdu, tvb, |
857 | 0 | offset + (bit_offset/8), |
858 | 0 | ((bit_offset % 8) + length + 7) / 8, |
859 | 0 | ENC_NA); |
860 | 0 | proto_item_set_text(pdu_ti, "MAC-d PDU (PDU %u)", pdu+1); |
861 | 0 | } |
862 | |
|
863 | 0 | p_fp_info->cur_tb = pdu; /*Set TB (PDU) index correctly*/ |
864 | 0 | if (preferences_call_mac_dissectors) { |
865 | 0 | tvbuff_t *next_tvb; |
866 | 0 | next_tvb = tvb_new_subset_length(tvb, offset + bit_offset/8, |
867 | 0 | ((bit_offset % 8) + length + 7)/8); |
868 | 0 | call_dissector_with_data(mac_fdd_hsdsch_handle, next_tvb, pinfo, top_level_tree, data); |
869 | 0 | dissected = true; |
870 | 0 | } |
871 | | |
872 | | /* Advance bit offset */ |
873 | 0 | bit_offset += length; |
874 | | |
875 | | /* Pad out to next byte */ |
876 | 0 | bit_offset = WS_ROUNDUP_8(bit_offset); |
877 | 0 | } |
878 | | |
879 | | /* Data tree should cover entire length */ |
880 | 0 | proto_item_set_len(pdus_ti, bit_offset/8); |
881 | | |
882 | | /* Move offset past PDUs (we know it's already padded out to next byte) */ |
883 | 0 | offset += (bit_offset / 8); |
884 | | |
885 | | /* Show summary in info column */ |
886 | 0 | if (dissected == false) { |
887 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %u PDUs of %u bits", |
888 | 0 | number_of_pdus, length); |
889 | 0 | } |
890 | |
|
891 | 0 | return offset; |
892 | 0 | } |
893 | | |
894 | | |
895 | | /* Dissect the MAC-d PDUs of an HS-DSCH (type 2) frame. |
896 | | Length is in bytes, and payload is byte-aligned (no padding) */ |
897 | | static int |
898 | | dissect_macd_pdu_data_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
899 | | unsigned offset, uint16_t length, uint16_t number_of_pdus, |
900 | | struct fp_info *fpi, void *data) |
901 | 0 | { |
902 | 0 | int pdu; |
903 | 0 | proto_item *pdus_ti = NULL; |
904 | 0 | proto_tree *data_tree = NULL; |
905 | 0 | unsigned first_offset = offset; |
906 | 0 | bool dissected = false; |
907 | | |
908 | | /* Add data subtree */ |
909 | 0 | pdus_ti = proto_tree_add_item(tree, hf_fp_data, tvb, offset, -1, ENC_NA); |
910 | 0 | proto_item_set_text(pdus_ti, "%u MAC-d PDUs of %u bytes", number_of_pdus, length); |
911 | 0 | data_tree = proto_item_add_subtree(pdus_ti, ett_fp_data); |
912 | |
|
913 | 0 | if (number_of_pdus >= MAX_MAC_FRAMES) { |
914 | 0 | expert_add_info_format(pinfo, data_tree, &ei_fp_invalid_frame_count, "Invalid number_of_pdus (max is %u)", MAX_MAC_FRAMES); |
915 | 0 | return offset; |
916 | 0 | } |
917 | | |
918 | | /* Now for the PDUs */ |
919 | 0 | for (pdu=0; pdu < number_of_pdus; pdu++) { |
920 | 0 | proto_item *pdu_ti; |
921 | | |
922 | | /* Data bytes! */ |
923 | 0 | if (data_tree) { |
924 | 0 | pdu_ti = proto_tree_add_item(data_tree, hf_fp_mac_d_pdu, tvb, |
925 | 0 | offset, length, ENC_NA); |
926 | 0 | proto_item_set_text(pdu_ti, "MAC-d PDU (PDU %u)", pdu+1); |
927 | |
|
928 | 0 | } |
929 | |
|
930 | 0 | if (preferences_call_mac_dissectors) { |
931 | |
|
932 | 0 | tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, length); |
933 | |
|
934 | 0 | fpi->cur_tb = pdu; /*Set proper pdu index for MAC and higher layers*/ |
935 | 0 | call_dissector_with_data(mac_fdd_hsdsch_handle, next_tvb, pinfo, top_level_tree, data); |
936 | 0 | dissected = true; |
937 | 0 | } |
938 | | |
939 | | /* Advance offset */ |
940 | 0 | offset += length; |
941 | 0 | } |
942 | | |
943 | | /* Data tree should cover entire length */ |
944 | 0 | proto_item_set_len(pdus_ti, offset-first_offset); |
945 | | |
946 | | /* Show summary in info column */ |
947 | 0 | if (!dissected) { |
948 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %u PDUs of %u bits", |
949 | 0 | number_of_pdus, length*8); |
950 | 0 | } |
951 | |
|
952 | 0 | return offset; |
953 | 0 | } |
954 | | |
955 | | /* Dissect CRCI bits (uplink) */ |
956 | | static int |
957 | | dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
958 | | fp_info *p_fp_info, unsigned offset) |
959 | 0 | { |
960 | 0 | int n, num_tbs; |
961 | 0 | proto_item *ti = NULL; |
962 | 0 | proto_tree *crcis_tree = NULL; |
963 | 0 | unsigned errors = 0; |
964 | |
|
965 | 0 | num_tbs = get_tb_count(p_fp_info); |
966 | | |
967 | | |
968 | | /* Add CRCIs subtree */ |
969 | 0 | if (tree) { |
970 | 0 | ti = proto_tree_add_item(tree, hf_fp_crcis, tvb, offset, (num_tbs+7)/8, ENC_NA); |
971 | 0 | proto_item_set_text(ti, "CRCI bits for %u tbs", num_tbs); |
972 | 0 | crcis_tree = proto_item_add_subtree(ti, ett_fp_crcis); |
973 | 0 | } |
974 | | |
975 | | /* CRCIs */ |
976 | 0 | for (n=0; n < num_tbs; n++) { |
977 | 0 | int bit = (tvb_get_uint8(tvb, offset+(n/8)) >> (7-(n%8))) & 0x01; |
978 | 0 | proto_tree_add_item(crcis_tree, hf_fp_crci[n%8], tvb, offset+(n/8), |
979 | 0 | 1, ENC_BIG_ENDIAN); |
980 | |
|
981 | 0 | if (bit == 1) { |
982 | 0 | errors++; |
983 | 0 | expert_add_info(pinfo, ti, &ei_fp_crci_error_bit_set_for_tb); |
984 | 0 | } |
985 | 0 | } |
986 | |
|
987 | 0 | if (tree) { |
988 | | /* Highlight range of bytes covered by indicator bits */ |
989 | 0 | proto_item_set_len(ti, (num_tbs+7) / 8); |
990 | | |
991 | | /* Show error count in root text */ |
992 | 0 | proto_item_append_text(ti, " (%u errors)", errors); |
993 | 0 | } |
994 | |
|
995 | 0 | offset += ((num_tbs+7) / 8); |
996 | 0 | return offset; |
997 | 0 | } |
998 | | |
999 | | |
1000 | | static void |
1001 | | dissect_spare_extension_and_crc(tvbuff_t *tvb, packet_info *pinfo, |
1002 | | proto_tree *tree, uint8_t dch_crc_present, |
1003 | | unsigned offset, unsigned header_length) |
1004 | 0 | { |
1005 | 0 | int crc_size = 0; |
1006 | 0 | int remain = tvb_reported_length_remaining(tvb, offset); |
1007 | | |
1008 | | /* Payload CRC (optional) */ |
1009 | 0 | if ((dch_crc_present == 1) || ((dch_crc_present == 2) && (remain >= 2))) { |
1010 | 0 | crc_size = 2; |
1011 | 0 | } |
1012 | |
|
1013 | 0 | if (remain > crc_size) { |
1014 | 0 | proto_item *ti; |
1015 | 0 | ti = proto_tree_add_item(tree, hf_fp_spare_extension, tvb, |
1016 | 0 | offset, remain-crc_size, ENC_NA); |
1017 | 0 | proto_item_append_text(ti, " (%u octets)", remain-crc_size); |
1018 | 0 | expert_add_info_format(pinfo, ti, &ei_fp_spare_extension, "Spare Extension present (%u bytes)", remain-crc_size); |
1019 | 0 | offset += remain-crc_size; |
1020 | 0 | } |
1021 | |
|
1022 | 0 | if (crc_size) { |
1023 | 0 | unsigned flags = PROTO_CHECKSUM_NO_FLAGS; |
1024 | 0 | uint16_t calc_crc = 0; |
1025 | 0 | if (preferences_payload_checksum) { |
1026 | 0 | flags = PROTO_CHECKSUM_VERIFY; |
1027 | 0 | if ((unsigned)offset > header_length) { |
1028 | 0 | uint8_t * data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, header_length, offset-header_length); |
1029 | 0 | calc_crc = crc16_8005_noreflect_noxor(data, offset-header_length); |
1030 | 0 | } |
1031 | 0 | } |
1032 | 0 | if ((unsigned)offset == header_length && remain == 0) { |
1033 | | /* 3GPP TS 25.427 and TS 25.435: "The Payload CRC IE may |
1034 | | * only be present if the frame contains payload" (even |
1035 | | * if defined as present at the setup of the transport bearer.) |
1036 | | * If there's room for the CRC and no payload, assume zero, |
1037 | | * otherwise, assume it's absent. |
1038 | | */ |
1039 | 0 | flags = PROTO_CHECKSUM_NOT_PRESENT; |
1040 | 0 | } |
1041 | 0 | proto_tree_add_checksum(tree, tvb, offset, |
1042 | 0 | hf_fp_payload_crc, hf_fp_payload_crc_status, |
1043 | 0 | &ei_fp_bad_payload_checksum, pinfo, calc_crc, |
1044 | 0 | ENC_BIG_ENDIAN, flags); |
1045 | 0 | } |
1046 | 0 | } |
1047 | | |
1048 | | /***********************************************************/ |
1049 | | /* Common control message types */ |
1050 | | |
1051 | | static int |
1052 | | dissect_common_outer_loop_power_control(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, |
1053 | | unsigned offset, struct fp_info *p_fp_info _U_) |
1054 | 0 | { |
1055 | 0 | return dissect_dch_outer_loop_power_control(tree, pinfo, tvb, offset); |
1056 | 0 | } |
1057 | | |
1058 | | |
1059 | | static int |
1060 | | dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, |
1061 | | unsigned offset, struct fp_info *p_fp_info) |
1062 | 0 | { |
1063 | 0 | int32_t toa; |
1064 | 0 | proto_item *toa_ti; |
1065 | |
|
1066 | 0 | if (p_fp_info->channel != CHANNEL_PCH) { |
1067 | 0 | uint32_t cfn; |
1068 | | |
1069 | | /* CFN control */ |
1070 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1071 | 0 | offset++; |
1072 | | |
1073 | | /* ToA */ |
1074 | 0 | toa = tvb_get_ntohis(tvb, offset); |
1075 | 0 | toa_ti = proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, ENC_BIG_ENDIAN); |
1076 | 0 | offset += 2; |
1077 | |
|
1078 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u, ToA=%d", cfn, toa); |
1079 | 0 | } |
1080 | 0 | else { |
1081 | 0 | uint32_t cfn; |
1082 | | |
1083 | | /* PCH CFN is 12 bits */ |
1084 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_pch_cfn, tvb, offset, 2, ENC_BIG_ENDIAN, &cfn); |
1085 | 0 | offset += 2; |
1086 | | |
1087 | | /* 4 bits of padding follow... */ |
1088 | | |
1089 | | /* 20 bits of ToA (followed by 4 padding bits) */ |
1090 | 0 | toa = ((int)(tvb_get_ntoh24(tvb, offset) << 8)) / 4096; |
1091 | 0 | toa_ti = proto_tree_add_int(tree, hf_fp_pch_toa, tvb, offset, 3, toa); |
1092 | 0 | offset += 3; |
1093 | |
|
1094 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u, ToA=%d", cfn, toa); |
1095 | 0 | } |
1096 | |
|
1097 | 0 | expert_add_info_format(pinfo, toa_ti, &ei_fp_timing_adjustment_reported, "Timing adjustment reported (%.3f ms)", ((float)(toa) / 8)); |
1098 | |
|
1099 | 0 | return offset; |
1100 | 0 | } |
1101 | | |
1102 | | static int |
1103 | | dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree, |
1104 | | tvbuff_t *tvb, unsigned offset) |
1105 | 0 | { |
1106 | | /* T1 (3 bytes) */ |
1107 | 0 | uint32_t encoded = tvb_get_ntoh24(tvb, offset); |
1108 | 0 | float t1 = encoded * (float)0.125; |
1109 | 0 | proto_tree_add_float_format_value(tree, hf_fp_t1, tvb, offset, 3, t1, "%.3f ms (%u)", t1, encoded); |
1110 | 0 | offset += 3; |
1111 | |
|
1112 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " T1=%.3f", t1); |
1113 | |
|
1114 | 0 | return offset; |
1115 | 0 | } |
1116 | | |
1117 | | static int |
1118 | | dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree, |
1119 | | tvbuff_t *tvb, unsigned offset) |
1120 | 0 | { |
1121 | 0 | uint32_t encoded; |
1122 | 0 | float t1, t2, t3; |
1123 | | |
1124 | | /* T1 (3 bytes) */ |
1125 | 0 | encoded = tvb_get_ntoh24(tvb, offset); |
1126 | 0 | t1 = encoded * (float)0.125; |
1127 | 0 | proto_tree_add_float_format_value(tree, hf_fp_t1, tvb, offset, 3, t1, "%.3f ms (%u)", t1, encoded); |
1128 | 0 | offset += 3; |
1129 | | |
1130 | | /* T2 (3 bytes) */ |
1131 | 0 | encoded = tvb_get_ntoh24(tvb, offset); |
1132 | 0 | t2 = encoded * (float)0.125; |
1133 | 0 | proto_tree_add_float_format_value(tree, hf_fp_t2, tvb, offset, 3, t2, "%.3f ms (%u)", t2, encoded); |
1134 | 0 | offset += 3; |
1135 | | |
1136 | | /* T3 (3 bytes) */ |
1137 | 0 | encoded = tvb_get_ntoh24(tvb, offset); |
1138 | 0 | t3 = encoded * (float)0.125; |
1139 | 0 | proto_tree_add_float_format_value(tree, hf_fp_t3, tvb, offset, 3, t3, "%.3f ms (%u)", t3, encoded); |
1140 | 0 | offset += 3; |
1141 | |
|
1142 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " T1=%.3f T2=%.3f, T3=%.3f", |
1143 | 0 | t1, t2, t3); |
1144 | |
|
1145 | 0 | return offset; |
1146 | 0 | } |
1147 | | |
1148 | | static int |
1149 | | dissect_common_dl_synchronisation(packet_info *pinfo, proto_tree *tree, |
1150 | | tvbuff_t *tvb, unsigned offset, struct fp_info *p_fp_info) |
1151 | 0 | { |
1152 | 0 | uint32_t cfn; |
1153 | |
|
1154 | 0 | if (p_fp_info->channel != CHANNEL_PCH) { |
1155 | | /* CFN control */ |
1156 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1157 | 0 | offset++; |
1158 | 0 | } |
1159 | 0 | else { |
1160 | | /* PCH CFN is 12 bits */ |
1161 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_pch_cfn, tvb, offset, 2, ENC_BIG_ENDIAN, &cfn); |
1162 | | |
1163 | | /* 4 bits of padding follow... */ |
1164 | 0 | offset += 2; |
1165 | 0 | } |
1166 | |
|
1167 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u", cfn); |
1168 | |
|
1169 | 0 | return offset; |
1170 | 0 | } |
1171 | | |
1172 | | static int |
1173 | | dissect_common_ul_synchronisation(packet_info *pinfo, proto_tree *tree, |
1174 | | tvbuff_t *tvb, unsigned offset, struct fp_info *p_fp_info) |
1175 | 0 | { |
1176 | 0 | return dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info); |
1177 | 0 | } |
1178 | | |
1179 | | static int |
1180 | | dissect_common_timing_advance(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, unsigned offset) |
1181 | 0 | { |
1182 | 0 | uint32_t cfn; |
1183 | 0 | uint16_t timing_advance; |
1184 | | |
1185 | | /* CFN control */ |
1186 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1187 | 0 | offset++; |
1188 | | |
1189 | | /* Timing Advance */ |
1190 | 0 | timing_advance = (tvb_get_uint8(tvb, offset) & 0x3f) * 4; |
1191 | 0 | proto_tree_add_uint(tree, hf_fp_timing_advance, tvb, offset, 1, timing_advance); |
1192 | 0 | offset++; |
1193 | |
|
1194 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, TA = %u", |
1195 | 0 | cfn, timing_advance); |
1196 | |
|
1197 | 0 | return offset; |
1198 | 0 | } |
1199 | | |
1200 | | static int |
1201 | | dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree, |
1202 | | tvbuff_t *tvb, unsigned offset) |
1203 | 0 | { |
1204 | 0 | uint8_t priority; |
1205 | 0 | uint16_t user_buffer_size; |
1206 | | |
1207 | | /* CmCH-PI */ |
1208 | 0 | proto_tree_add_item_ret_uint8(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN, &priority); |
1209 | 0 | offset++; |
1210 | | |
1211 | | /* User buffer size */ |
1212 | 0 | proto_tree_add_item_ret_uint16(tree, hf_fp_user_buffer_size, tvb, offset, 2, ENC_BIG_ENDIAN, &user_buffer_size); |
1213 | 0 | offset += 2; |
1214 | |
|
1215 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CmCH-PI=%u User-Buffer-Size=%u", |
1216 | 0 | priority, user_buffer_size); |
1217 | |
|
1218 | 0 | return offset; |
1219 | 0 | } |
1220 | | |
1221 | | static int |
1222 | | dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree, |
1223 | | tvbuff_t *tvb, unsigned offset, |
1224 | | struct fp_info *p_fp_info) |
1225 | 0 | { |
1226 | 0 | proto_item *ti; |
1227 | 0 | proto_item *rate_ti; |
1228 | 0 | uint16_t max_pdu_length; |
1229 | 0 | uint8_t repetition_period; |
1230 | 0 | uint8_t interval; |
1231 | 0 | uint64_t credits; |
1232 | | |
1233 | | /* Congestion status (introduced sometime during R6...) */ |
1234 | 0 | if ((p_fp_info->release == 6) || (p_fp_info->release == 7)) { |
1235 | 0 | proto_tree_add_bits_item(tree, hf_fp_congestion_status, tvb, |
1236 | 0 | offset*8 + 2, 2, ENC_BIG_ENDIAN); |
1237 | 0 | } |
1238 | | |
1239 | | /* CmCH-PI */ |
1240 | 0 | proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1241 | 0 | offset++; |
1242 | | |
1243 | | /* Max MAC-d PDU length (13 bits) */ |
1244 | 0 | max_pdu_length = tvb_get_ntohs(tvb, offset) >> 3; |
1245 | 0 | proto_tree_add_item(tree, hf_fp_hsdsch_max_macd_pdu_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
1246 | 0 | offset++; |
1247 | | |
1248 | | /* HS-DSCH credits (11 bits) */ |
1249 | 0 | ti = proto_tree_add_bits_ret_val(tree, hf_fp_hsdsch_credits, tvb, |
1250 | 0 | offset*8 + 5, 11, &credits, ENC_BIG_ENDIAN); |
1251 | 0 | offset += 2; |
1252 | | |
1253 | | /* Interesting values */ |
1254 | 0 | if (credits == 0) { |
1255 | 0 | proto_item_append_text(ti, " (stop transmission)"); |
1256 | 0 | expert_add_info(pinfo, ti, &ei_fp_stop_hsdpa_transmission); |
1257 | 0 | } |
1258 | 0 | if (credits == 2047) { |
1259 | 0 | proto_item_append_text(ti, " (unlimited)"); |
1260 | 0 | } |
1261 | | |
1262 | | /* HS-DSCH Interval */ |
1263 | 0 | interval = tvb_get_uint8(tvb, offset); |
1264 | 0 | ti = proto_tree_add_uint(tree, hf_fp_hsdsch_interval, tvb, offset, 1, interval*10); |
1265 | 0 | offset++; |
1266 | 0 | if (interval == 0) { |
1267 | 0 | proto_item_append_text(ti, " (none of the credits shall be used)"); |
1268 | 0 | } |
1269 | | |
1270 | | /* HS-DSCH Repetition period */ |
1271 | 0 | ti = proto_tree_add_item_ret_uint8(tree, hf_fp_hsdsch_repetition_period, tvb, offset, 1, ENC_BIG_ENDIAN, &repetition_period); |
1272 | 0 | offset++; |
1273 | 0 | if (repetition_period == 0) { |
1274 | 0 | proto_item_append_text(ti, " (unlimited repetition period)"); |
1275 | 0 | } |
1276 | | |
1277 | | /* Calculated and show effective rate enabled */ |
1278 | 0 | if (credits == 2047) { |
1279 | 0 | rate_ti = proto_tree_add_item(tree, hf_fp_hsdsch_unlimited_rate, tvb, 0, 0, ENC_NA); |
1280 | 0 | proto_item_set_generated(rate_ti); |
1281 | 0 | } |
1282 | 0 | else { |
1283 | 0 | if (interval != 0) { |
1284 | | /* Cast on credits is safe, since we know it won't exceed 10^11 */ |
1285 | 0 | rate_ti = proto_tree_add_uint(tree, hf_fp_hsdsch_calculated_rate, tvb, 0, 0, |
1286 | 0 | (uint16_t)credits * max_pdu_length * (1000 / (interval*10))); |
1287 | 0 | proto_item_set_generated(rate_ti); |
1288 | 0 | } |
1289 | 0 | } |
1290 | |
|
1291 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, |
1292 | 0 | " Max-PDU-len=%u Credits=%u Interval=%u Rep-Period=%u", |
1293 | 0 | max_pdu_length, (uint16_t)credits, interval, repetition_period); |
1294 | |
|
1295 | 0 | return offset; |
1296 | 0 | } |
1297 | | |
1298 | | static int |
1299 | | dissect_hsdpa_capacity_allocation_type_2(packet_info *pinfo, proto_tree *tree, |
1300 | | tvbuff_t *tvb, unsigned offset) |
1301 | 0 | { |
1302 | 0 | proto_item *ti; |
1303 | 0 | proto_item *rate_ti; |
1304 | 0 | uint16_t max_pdu_length; |
1305 | 0 | uint8_t repetition_period; |
1306 | 0 | uint8_t interval; |
1307 | 0 | uint16_t credits; |
1308 | | |
1309 | | /* Congestion status */ |
1310 | 0 | proto_tree_add_bits_item(tree, hf_fp_congestion_status, tvb, |
1311 | 0 | offset*8 + 2, 2, ENC_BIG_ENDIAN); |
1312 | | |
1313 | | /* CmCH-PI */ |
1314 | 0 | proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1315 | 0 | offset++; |
1316 | | |
1317 | | /* 5 spare bits follow here */ |
1318 | | |
1319 | | /* Max MAC-d/c PDU length (11 bits) */ |
1320 | 0 | max_pdu_length = tvb_get_ntohs(tvb, offset) & 0x7ff; |
1321 | 0 | proto_tree_add_item(tree, hf_fp_hsdsch_max_macdc_pdu_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
1322 | 0 | offset += 2; |
1323 | | |
1324 | | /* HS-DSCH credits (16 bits) */ |
1325 | 0 | credits = (tvb_get_ntohs(tvb, offset)); |
1326 | 0 | ti = proto_tree_add_uint(tree, hf_fp_hsdsch_credits, tvb, |
1327 | 0 | offset, 2, credits); |
1328 | 0 | offset += 2; |
1329 | | |
1330 | | /* Interesting values */ |
1331 | 0 | if (credits == 0) { |
1332 | 0 | proto_item_append_text(ti, " (stop transmission)"); |
1333 | 0 | expert_add_info(pinfo, ti, &ei_fp_stop_hsdpa_transmission); |
1334 | 0 | } |
1335 | 0 | if (credits == 65535) { |
1336 | 0 | proto_item_append_text(ti, " (unlimited)"); |
1337 | 0 | } |
1338 | | |
1339 | | /* HS-DSCH Interval */ |
1340 | 0 | interval = tvb_get_uint8(tvb, offset); |
1341 | 0 | ti = proto_tree_add_uint(tree, hf_fp_hsdsch_interval, tvb, offset, 1, interval*10); |
1342 | 0 | offset++; |
1343 | 0 | if (interval == 0) { |
1344 | 0 | proto_item_append_text(ti, " (none of the credits shall be used)"); |
1345 | 0 | } |
1346 | | |
1347 | | /* HS-DSCH Repetition period */ |
1348 | 0 | ti = proto_tree_add_item_ret_uint8(tree, hf_fp_hsdsch_repetition_period, tvb, offset, 1, ENC_BIG_ENDIAN, &repetition_period); |
1349 | 0 | offset++; |
1350 | 0 | if (repetition_period == 0) { |
1351 | 0 | proto_item_append_text(ti, " (unlimited repetition period)"); |
1352 | 0 | } |
1353 | | |
1354 | | /* Calculated and show effective rate enabled */ |
1355 | 0 | if (credits == 65535) { |
1356 | 0 | rate_ti = proto_tree_add_item(tree, hf_fp_hsdsch_unlimited_rate, tvb, 0, 0, ENC_NA); |
1357 | 0 | proto_item_set_generated(rate_ti); |
1358 | 0 | } |
1359 | 0 | else { |
1360 | 0 | if (interval != 0) { |
1361 | 0 | rate_ti = proto_tree_add_uint(tree, hf_fp_hsdsch_calculated_rate, tvb, 0, 0, |
1362 | 0 | credits * max_pdu_length * (1000 / (interval*10))); |
1363 | 0 | proto_item_set_generated(rate_ti); |
1364 | 0 | } |
1365 | 0 | } |
1366 | |
|
1367 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, |
1368 | 0 | " Max-PDU-len=%u Credits=%u Interval=%u Rep-Period=%u", |
1369 | 0 | max_pdu_length, credits, interval, repetition_period); |
1370 | |
|
1371 | 0 | return offset; |
1372 | 0 | } |
1373 | | |
1374 | | |
1375 | | |
1376 | | static int |
1377 | | dissect_common_dynamic_pusch_assignment(packet_info *pinfo, proto_tree *tree, |
1378 | | tvbuff_t *tvb, unsigned offset) |
1379 | 0 | { |
1380 | 0 | uint8_t pusch_set_id; |
1381 | 0 | uint8_t activation_cfn; |
1382 | 0 | uint8_t duration; |
1383 | | |
1384 | | /* PUSCH Set Id */ |
1385 | 0 | proto_tree_add_item_ret_uint8(tree, hf_fp_pusch_set_id, tvb, offset, 1, ENC_BIG_ENDIAN, &pusch_set_id); |
1386 | 0 | offset++; |
1387 | | |
1388 | | /* Activation CFN */ |
1389 | 0 | proto_tree_add_item_ret_uint8(tree, hf_fp_activation_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &activation_cfn); |
1390 | 0 | offset++; |
1391 | | |
1392 | | /* Duration */ |
1393 | 0 | duration = tvb_get_uint8(tvb, offset) * 10; |
1394 | 0 | proto_tree_add_uint(tree, hf_fp_duration, tvb, offset, 1, duration); |
1395 | 0 | offset++; |
1396 | |
|
1397 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, |
1398 | 0 | " PUSCH Set Id=%u Activation CFN=%u Duration=%u", |
1399 | 0 | pusch_set_id, activation_cfn, duration); |
1400 | |
|
1401 | 0 | return offset; |
1402 | 0 | } |
1403 | | |
1404 | | |
1405 | | |
1406 | | |
1407 | | |
1408 | | /* Dissect the control part of a common channel message */ |
1409 | | static void |
1410 | | dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1411 | | unsigned offset, struct fp_info *p_fp_info) |
1412 | 0 | { |
1413 | | /* Common control frame type */ |
1414 | 0 | uint8_t control_frame_type = tvb_get_uint8(tvb, offset); |
1415 | 0 | proto_tree_add_item(tree, hf_fp_common_control_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
1416 | 0 | offset++; |
1417 | |
|
1418 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
1419 | 0 | val_to_str_const(control_frame_type, common_control_frame_type_vals, "Unknown")); |
1420 | | |
1421 | | /* Frame-type specific dissection */ |
1422 | 0 | switch (control_frame_type) { |
1423 | 0 | case COMMON_OUTER_LOOP_POWER_CONTROL: |
1424 | 0 | /*offset =*/ dissect_common_outer_loop_power_control(pinfo, tree, tvb, offset, p_fp_info); |
1425 | 0 | break; |
1426 | 0 | case COMMON_TIMING_ADJUSTMENT: |
1427 | 0 | /*offset =*/ dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info); |
1428 | 0 | break; |
1429 | 0 | case COMMON_DL_SYNCHRONISATION: |
1430 | 0 | /*offset =*/ dissect_common_dl_synchronisation(pinfo, tree, tvb, offset, p_fp_info); |
1431 | 0 | break; |
1432 | 0 | case COMMON_UL_SYNCHRONISATION: |
1433 | 0 | /*offset =*/ dissect_common_ul_synchronisation(pinfo, tree, tvb, offset, p_fp_info); |
1434 | 0 | break; |
1435 | 0 | case COMMON_DL_NODE_SYNCHRONISATION: |
1436 | 0 | /*offset =*/ dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset); |
1437 | 0 | break; |
1438 | 0 | case COMMON_UL_NODE_SYNCHRONISATION: |
1439 | 0 | /*offset =*/ dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset); |
1440 | 0 | break; |
1441 | 0 | case COMMON_DYNAMIC_PUSCH_ASSIGNMENT: |
1442 | 0 | /*offset =*/ dissect_common_dynamic_pusch_assignment(pinfo, tree, tvb, offset); |
1443 | 0 | break; |
1444 | 0 | case COMMON_TIMING_ADVANCE: |
1445 | 0 | /*offset =*/ dissect_common_timing_advance(pinfo, tree, tvb, offset); |
1446 | 0 | break; |
1447 | 0 | case COMMON_HS_DSCH_Capacity_Request: |
1448 | 0 | /*offset =*/ dissect_hsdpa_capacity_request(pinfo, tree, tvb, offset); |
1449 | 0 | break; |
1450 | 0 | case COMMON_HS_DSCH_Capacity_Allocation: |
1451 | 0 | /*offset =*/ dissect_hsdpa_capacity_allocation(pinfo, tree, tvb, offset, p_fp_info); |
1452 | 0 | break; |
1453 | 0 | case COMMON_HS_DSCH_Capacity_Allocation_Type_2: |
1454 | 0 | /*offset =*/ dissect_hsdpa_capacity_allocation_type_2(pinfo, tree, tvb, offset); |
1455 | 0 | break; |
1456 | | |
1457 | 0 | default: |
1458 | 0 | break; |
1459 | 0 | } |
1460 | | |
1461 | | /* There is no Spare Extension nor payload crc in common control!? */ |
1462 | | /* dissect_spare_extension_and_crc(tvb, pinfo, tree, 0, offset); |
1463 | | */ |
1464 | 0 | } |
1465 | | |
1466 | | |
1467 | | |
1468 | | /**************************/ |
1469 | | /* Dissect a RACH channel */ |
1470 | | static void |
1471 | | dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1472 | | unsigned offset, struct fp_info *p_fp_info, void *data) |
1473 | 0 | { |
1474 | 0 | uint32_t ft; |
1475 | 0 | uint32_t header_crc = 0; |
1476 | 0 | proto_item * header_crc_pi = NULL; |
1477 | 0 | unsigned header_length; |
1478 | | |
1479 | | /* Header CRC */ |
1480 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
1481 | | |
1482 | | /* Frame Type */ |
1483 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
1484 | 0 | offset++; |
1485 | |
|
1486 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
1487 | |
|
1488 | 0 | if (ft == FT_CONTROL) { |
1489 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
1490 | | /* For control frame the header CRC is actually frame CRC covering all |
1491 | | * bytes except the first */ |
1492 | 0 | if (preferences_header_checksum) { |
1493 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
1494 | 0 | } |
1495 | 0 | } |
1496 | 0 | else { |
1497 | 0 | uint8_t cfn; |
1498 | 0 | uint32_t encoded; |
1499 | 0 | uint32_t propagation_delay = 0; |
1500 | 0 | proto_item *propagation_delay_ti = NULL; |
1501 | 0 | uint32_t received_sync_ul_timing_deviation = 0; |
1502 | 0 | proto_item *received_sync_ul_timing_deviation_ti = NULL; |
1503 | 0 | proto_item *rx_timing_deviation_ti = NULL; |
1504 | 0 | uint16_t rx_timing_deviation = 0; |
1505 | | |
1506 | | /* DATA */ |
1507 | | |
1508 | | /* CFN */ |
1509 | 0 | proto_tree_add_item_ret_uint8(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1510 | 0 | offset++; |
1511 | |
|
1512 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
1513 | | |
1514 | | /* TFI */ |
1515 | 0 | proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1516 | 0 | offset++; |
1517 | |
|
1518 | 0 | if (p_fp_info->channel == CHANNEL_RACH_FDD) { |
1519 | | /* Propagation delay */ |
1520 | 0 | encoded = tvb_get_uint8(tvb, offset); |
1521 | 0 | propagation_delay = encoded * 3; |
1522 | 0 | propagation_delay_ti = proto_tree_add_uint_format_value(tree, hf_fp_propagation_delay, tvb, offset, 1, |
1523 | 0 | propagation_delay, "%u chips (%u)", |
1524 | 0 | propagation_delay, encoded); |
1525 | 0 | offset++; |
1526 | 0 | } |
1527 | | |
1528 | | /* Should be TDD 3.84 or 7.68 */ |
1529 | 0 | if (p_fp_info->channel == CHANNEL_RACH_TDD) { |
1530 | | /* Rx Timing Deviation */ |
1531 | 0 | rx_timing_deviation_ti = proto_tree_add_item_ret_uint16(tree, hf_fp_rx_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN, &rx_timing_deviation); |
1532 | 0 | offset++; |
1533 | 0 | } |
1534 | |
|
1535 | 0 | if (p_fp_info->channel == CHANNEL_RACH_TDD_128) { |
1536 | | /* Received SYNC UL Timing Deviation */ |
1537 | 0 | received_sync_ul_timing_deviation_ti = |
1538 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_received_sync_ul_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN, &received_sync_ul_timing_deviation); |
1539 | 0 | offset++; |
1540 | 0 | } |
1541 | |
|
1542 | 0 | header_length = offset; |
1543 | | |
1544 | | /* TB data */ |
1545 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &mac_fdd_rach_handle, data); |
1546 | | |
1547 | | /* CRCIs */ |
1548 | 0 | offset = dissect_crci_bits(tvb, pinfo, tree, p_fp_info, offset); |
1549 | | |
1550 | | /* Info introduced in R6 */ |
1551 | | /* only check if it looks as if they are present */ |
1552 | 0 | if (((p_fp_info->release == 6) || (p_fp_info->release == 7)) && |
1553 | 0 | (tvb_reported_length_remaining(tvb, offset) > 2)) |
1554 | 0 | { |
1555 | 0 | int n; |
1556 | 0 | uint8_t flags; |
1557 | | /* uint8_t flag_bytes = 0; */ |
1558 | |
|
1559 | 0 | bool cell_portion_id_present = false; |
1560 | 0 | bool ext_propagation_delay_present = false; |
1561 | 0 | bool angle_of_arrival_present = false; |
1562 | 0 | bool ext_rx_sync_ul_timing_deviation_present = false; |
1563 | 0 | bool ext_rx_timing_deviation_present = false; |
1564 | | |
1565 | | /* New IE flags (assume mandatory for now) */ |
1566 | 0 | do { |
1567 | 0 | proto_item *new_ie_flags_ti; |
1568 | 0 | proto_tree *new_ie_flags_tree; |
1569 | 0 | unsigned ies_found = 0; |
1570 | | |
1571 | | /* Add new IE flags subtree */ |
1572 | 0 | new_ie_flags_ti = proto_tree_add_string_format(tree, hf_fp_rach_new_ie_flags, tvb, offset, 1, |
1573 | 0 | "", "New IE flags"); |
1574 | 0 | new_ie_flags_tree = proto_item_add_subtree(new_ie_flags_ti, ett_fp_rach_new_ie_flags); |
1575 | | |
1576 | | /* Read next byte */ |
1577 | 0 | flags = tvb_get_uint8(tvb, offset); |
1578 | | /* flag_bytes++ */ |
1579 | | |
1580 | | /* Dissect individual bits */ |
1581 | 0 | for (n=0; n < 8; n++) { |
1582 | 0 | switch (n) { |
1583 | 0 | case 6: |
1584 | 0 | switch (p_fp_info->division) { |
1585 | 0 | case Division_FDD: |
1586 | | /* Ext propagation delay */ |
1587 | 0 | ext_propagation_delay_present = true; |
1588 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_ext_propagation_delay_present, |
1589 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1590 | 0 | break; |
1591 | 0 | case Division_TDD_128: |
1592 | | /* Ext Rx Sync UL Timing */ |
1593 | 0 | ext_rx_sync_ul_timing_deviation_present = true; |
1594 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_ext_rx_sync_ul_timing_deviation_present, |
1595 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1596 | |
|
1597 | 0 | break; |
1598 | 0 | default: |
1599 | | /* Not defined */ |
1600 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_new_ie_flag_unused[6], |
1601 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1602 | 0 | break; |
1603 | 0 | } |
1604 | 0 | break; |
1605 | 0 | case 7: |
1606 | 0 | switch (p_fp_info->division) { |
1607 | 0 | case Division_FDD: |
1608 | | /* Cell Portion ID */ |
1609 | 0 | cell_portion_id_present = true; |
1610 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_cell_portion_id_present, |
1611 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1612 | 0 | break; |
1613 | 0 | case Division_TDD_128: |
1614 | | /* AOA */ |
1615 | 0 | angle_of_arrival_present = true; |
1616 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_angle_of_arrival_present, |
1617 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1618 | 0 | break; |
1619 | 0 | case Division_TDD_384: |
1620 | 0 | case Division_TDD_768: |
1621 | | /* Extended Rx Timing Deviation */ |
1622 | 0 | ext_rx_timing_deviation_present = true; |
1623 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_ext_rx_timing_deviation_present, |
1624 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1625 | 0 | break; |
1626 | 0 | } |
1627 | 0 | break; |
1628 | | |
1629 | 0 | default: |
1630 | | /* No defined meanings */ |
1631 | | /* Visual Studio Code Analyzer wrongly thinks n can be 7 here. It can't */ |
1632 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_new_ie_flag_unused[n], |
1633 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1634 | 0 | break; |
1635 | 0 | } |
1636 | 0 | if ((flags >> (7-n)) & 0x01) { |
1637 | 0 | ies_found++; |
1638 | 0 | } |
1639 | 0 | } |
1640 | 0 | offset++; |
1641 | |
|
1642 | 0 | proto_item_append_text(new_ie_flags_ti, " (%u IEs found)", ies_found); |
1643 | | |
1644 | | /* Last bit set will indicate another flags byte follows... */ |
1645 | 0 | } while (0); /*((flags & 0x01) && (flag_bytes < 31));*/ |
1646 | | |
1647 | | /* Cell Portion ID */ |
1648 | 0 | if (cell_portion_id_present) { |
1649 | 0 | proto_tree_add_item(tree, hf_fp_cell_portion_id, tvb, offset, 1, ENC_BIG_ENDIAN); |
1650 | 0 | offset++; |
1651 | 0 | } |
1652 | | |
1653 | | /* Ext Rx Timing Deviation */ |
1654 | 0 | if (ext_rx_timing_deviation_present) { |
1655 | 0 | uint8_t extra_bits; |
1656 | 0 | unsigned bits_to_extend; |
1657 | 0 | switch (p_fp_info->division) { |
1658 | 0 | case Division_TDD_384: |
1659 | 0 | bits_to_extend = 1; |
1660 | 0 | break; |
1661 | 0 | case Division_TDD_768: |
1662 | 0 | bits_to_extend = 2; |
1663 | 0 | break; |
1664 | | |
1665 | 0 | default: |
1666 | | /* TODO: report unexpected division type */ |
1667 | 0 | bits_to_extend = 1; |
1668 | 0 | break; |
1669 | 0 | } |
1670 | 0 | extra_bits = tvb_get_uint8(tvb, offset) & |
1671 | 0 | ((bits_to_extend == 1) ? 0x01 : 0x03); |
1672 | 0 | rx_timing_deviation = (extra_bits << 8) | (rx_timing_deviation); |
1673 | 0 | proto_item_append_text(rx_timing_deviation_ti, |
1674 | 0 | " (extended to 0x%x)", |
1675 | 0 | rx_timing_deviation); |
1676 | 0 | proto_tree_add_bits_item(tree, hf_fp_extended_bits, tvb, |
1677 | 0 | offset*8 + (8-bits_to_extend), bits_to_extend, ENC_BIG_ENDIAN); |
1678 | 0 | offset++; |
1679 | 0 | } |
1680 | | |
1681 | | /* Ext propagation delay. */ |
1682 | 0 | if (ext_propagation_delay_present) { |
1683 | 0 | uint16_t extra_bits = tvb_get_ntohs(tvb, offset) & 0x03ff; |
1684 | 0 | proto_tree_add_item(tree, hf_fp_ext_propagation_delay, tvb, offset, 2, ENC_BIG_ENDIAN); |
1685 | | |
1686 | | /* Adding 10 bits to original 8 */ |
1687 | 0 | proto_item_append_text(propagation_delay_ti, " (extended to %u)", |
1688 | 0 | ((extra_bits << 8) | propagation_delay) * 3); |
1689 | 0 | offset += 2; |
1690 | 0 | } |
1691 | | |
1692 | | /* Angle of Arrival (AOA) */ |
1693 | 0 | if (angle_of_arrival_present) { |
1694 | 0 | proto_tree_add_item(tree, hf_fp_angle_of_arrival, tvb, offset, 2, ENC_BIG_ENDIAN); |
1695 | 0 | offset += 2; |
1696 | 0 | } |
1697 | | |
1698 | | /* Ext. Rx Sync UL Timing Deviation */ |
1699 | 0 | if (ext_rx_sync_ul_timing_deviation_present) { |
1700 | 0 | uint16_t extra_bits; |
1701 | | |
1702 | | /* Ext received Sync UL Timing Deviation */ |
1703 | 0 | extra_bits = tvb_get_ntohs(tvb, offset) & 0x1fff; |
1704 | 0 | proto_tree_add_item(tree, hf_fp_ext_received_sync_ul_timing_deviation, tvb, offset, 2, ENC_BIG_ENDIAN); |
1705 | | |
1706 | | /* Adding 13 bits to original 8 */ |
1707 | 0 | proto_item_append_text(received_sync_ul_timing_deviation_ti, " (extended to %u)", |
1708 | 0 | (extra_bits << 8) | received_sync_ul_timing_deviation); |
1709 | 0 | offset += 2; |
1710 | 0 | } |
1711 | 0 | } |
1712 | 0 | if (preferences_header_checksum) { |
1713 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
1714 | 0 | } |
1715 | | /* Spare Extension and Payload CRC */ |
1716 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
1717 | 0 | } |
1718 | 0 | } |
1719 | | |
1720 | | |
1721 | | /**************************/ |
1722 | | /* Dissect a FACH channel */ |
1723 | | static void |
1724 | | dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1725 | | unsigned offset, struct fp_info *p_fp_info, void *data) |
1726 | 0 | { |
1727 | 0 | uint32_t ft; |
1728 | 0 | uint32_t header_crc = 0; |
1729 | 0 | proto_item * header_crc_pi = NULL; |
1730 | 0 | unsigned header_length; |
1731 | | |
1732 | | /* Header CRC */ |
1733 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
1734 | | |
1735 | | /* Frame Type */ |
1736 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
1737 | 0 | offset++; |
1738 | |
|
1739 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
1740 | |
|
1741 | 0 | if (ft == FT_CONTROL) { |
1742 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
1743 | | /* For control frame the header CRC is actually frame CRC covering all |
1744 | | * bytes except the first */ |
1745 | 0 | if (preferences_header_checksum) { |
1746 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
1747 | 0 | } |
1748 | 0 | } |
1749 | 0 | else { |
1750 | 0 | uint8_t cfn; |
1751 | | /* DATA */ |
1752 | | |
1753 | | /* CFN */ |
1754 | 0 | proto_tree_add_item_ret_uint8(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1755 | 0 | offset++; |
1756 | |
|
1757 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
1758 | | |
1759 | | /* TFI */ |
1760 | 0 | proto_tree_add_item(tree, hf_fp_fach_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1761 | 0 | offset++; |
1762 | | |
1763 | | /* Transmit power level */ |
1764 | 0 | proto_tree_add_float(tree, hf_fp_transmit_power_level, tvb, offset, 1, |
1765 | 0 | (float)(int)(tvb_get_uint8(tvb, offset)) / 10); |
1766 | 0 | offset++; |
1767 | 0 | header_length = offset; |
1768 | | |
1769 | | /* TB data */ |
1770 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &mac_fdd_fach_handle, data); |
1771 | | |
1772 | | /* New IE flags (if it looks as though they are present) */ |
1773 | 0 | if ((p_fp_info->release == 7) && |
1774 | 0 | (tvb_reported_length_remaining(tvb, offset) > 2)) { |
1775 | |
|
1776 | 0 | uint8_t flags = tvb_get_uint8(tvb, offset); |
1777 | 0 | uint8_t aoa_present = flags & 0x01; |
1778 | 0 | offset++; |
1779 | |
|
1780 | 0 | if (aoa_present) { |
1781 | 0 | proto_tree_add_item(tree, hf_fp_angle_of_arrival, tvb, offset, 2, ENC_BIG_ENDIAN); |
1782 | 0 | offset += 2; |
1783 | 0 | } |
1784 | 0 | } |
1785 | 0 | if (preferences_header_checksum) { |
1786 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
1787 | 0 | } |
1788 | | /* Spare Extension and Payload CRC */ |
1789 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
1790 | 0 | } |
1791 | 0 | } |
1792 | | |
1793 | | |
1794 | | /**************************/ |
1795 | | /* Dissect a DSCH channel */ |
1796 | | static void |
1797 | | dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1798 | | unsigned offset, struct fp_info *p_fp_info) |
1799 | 0 | { |
1800 | 0 | uint32_t ft; |
1801 | | |
1802 | | /* Header CRC */ |
1803 | 0 | proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN); |
1804 | | |
1805 | | /* Frame Type */ |
1806 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
1807 | 0 | offset++; |
1808 | |
|
1809 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
1810 | |
|
1811 | 0 | if (ft == FT_CONTROL) { |
1812 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
1813 | 0 | } |
1814 | 0 | else { |
1815 | 0 | uint32_t cfn; |
1816 | 0 | unsigned header_length = 0; |
1817 | | |
1818 | | /* DATA */ |
1819 | | |
1820 | | /* CFN */ |
1821 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1822 | 0 | offset++; |
1823 | |
|
1824 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
1825 | | |
1826 | | /* TFI */ |
1827 | 0 | proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1828 | 0 | offset++; |
1829 | | |
1830 | | |
1831 | | /* Other fields depend upon release & FDD/TDD settings */ |
1832 | 0 | if (((p_fp_info->release == 99) || (p_fp_info->release == 4)) && |
1833 | 0 | (p_fp_info->channel == CHANNEL_DSCH_FDD)) { |
1834 | | |
1835 | | /* Power offset */ |
1836 | 0 | proto_tree_add_float(tree, hf_fp_power_offset, tvb, offset, 1, |
1837 | 0 | (float)(-32.0) + |
1838 | 0 | ((float)(int)(tvb_get_uint8(tvb, offset)) * (float)(0.25))); |
1839 | 0 | offset++; |
1840 | | |
1841 | | /* Code number */ |
1842 | 0 | proto_tree_add_item(tree, hf_fp_code_number, tvb, offset, 1, ENC_BIG_ENDIAN); |
1843 | 0 | offset++; |
1844 | | |
1845 | | /* Spreading Factor (3 bits) */ |
1846 | 0 | proto_tree_add_item(tree, hf_fp_spreading_factor, tvb, offset, 1, ENC_BIG_ENDIAN); |
1847 | | |
1848 | | /* MC info (4 bits)*/ |
1849 | 0 | proto_tree_add_item(tree, hf_fp_mc_info, tvb, offset, 1, ENC_BIG_ENDIAN); |
1850 | | |
1851 | | /* Last bit of this byte is spare */ |
1852 | 0 | offset++; |
1853 | 0 | } |
1854 | 0 | else { |
1855 | | /* Normal case */ |
1856 | | |
1857 | | /* PDSCH Set Id */ |
1858 | 0 | proto_tree_add_item(tree, hf_fp_pdsch_set_id, tvb, offset, 1, ENC_BIG_ENDIAN); |
1859 | 0 | offset++; |
1860 | | |
1861 | | /* Transmit power level */ |
1862 | 0 | proto_tree_add_float(tree, hf_fp_transmit_power_level, tvb, offset, 1, |
1863 | 0 | (float)(int)(tvb_get_uint8(tvb, offset)) / 10); |
1864 | 0 | offset++; |
1865 | 0 | } |
1866 | 0 | header_length = offset; |
1867 | | /* TB data */ |
1868 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, NULL, NULL); |
1869 | | |
1870 | | /* Spare Extension and Payload CRC */ |
1871 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
1872 | 0 | } |
1873 | 0 | } |
1874 | | |
1875 | | |
1876 | | /**************************/ |
1877 | | /* Dissect a USCH channel */ |
1878 | | static void |
1879 | | dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1880 | | unsigned offset, struct fp_info *p_fp_info) |
1881 | 0 | { |
1882 | 0 | uint32_t ft; |
1883 | | |
1884 | | /* Header CRC */ |
1885 | 0 | proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN); |
1886 | | |
1887 | | /* Frame Type */ |
1888 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
1889 | 0 | offset++; |
1890 | |
|
1891 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
1892 | |
|
1893 | 0 | if (ft == FT_CONTROL) { |
1894 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
1895 | 0 | } |
1896 | 0 | else { |
1897 | 0 | unsigned cfn; |
1898 | 0 | uint16_t rx_timing_deviation; |
1899 | 0 | proto_item *rx_timing_deviation_ti; |
1900 | 0 | unsigned header_length = 0; |
1901 | | |
1902 | | /* DATA */ |
1903 | | |
1904 | | /* CFN */ |
1905 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
1906 | 0 | offset++; |
1907 | |
|
1908 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
1909 | | |
1910 | | /* TFI */ |
1911 | 0 | proto_tree_add_item(tree, hf_fp_usch_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1912 | 0 | offset++; |
1913 | | |
1914 | | /* Rx Timing Deviation */ |
1915 | 0 | rx_timing_deviation = tvb_get_uint8(tvb, offset); |
1916 | 0 | rx_timing_deviation_ti = proto_tree_add_item(tree, hf_fp_rx_timing_deviation, |
1917 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
1918 | 0 | offset++; |
1919 | 0 | header_length = offset; |
1920 | | /* TB data */ |
1921 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, NULL, NULL); |
1922 | | |
1923 | | /* QE */ |
1924 | 0 | proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, ENC_BIG_ENDIAN); |
1925 | 0 | offset++; |
1926 | | |
1927 | | /* CRCIs */ |
1928 | 0 | offset = dissect_crci_bits(tvb, pinfo, tree, p_fp_info, offset); |
1929 | | |
1930 | | /* New IEs */ |
1931 | 0 | if ((p_fp_info->release == 7) && |
1932 | 0 | (tvb_reported_length_remaining(tvb, offset) > 2)) { |
1933 | |
|
1934 | 0 | uint8_t flags = tvb_get_uint8(tvb, offset); |
1935 | 0 | uint8_t bits_extended = flags & 0x01; |
1936 | 0 | offset++; |
1937 | |
|
1938 | 0 | if (bits_extended) { |
1939 | 0 | uint8_t extra_bits = tvb_get_uint8(tvb, offset) & 0x03; |
1940 | 0 | proto_item_append_text(rx_timing_deviation_ti, |
1941 | 0 | " (extended to %u)", |
1942 | 0 | (rx_timing_deviation << 2) | extra_bits); |
1943 | 0 | } |
1944 | 0 | offset++; |
1945 | 0 | } |
1946 | | |
1947 | | /* Spare Extension and Payload CRC */ |
1948 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
1949 | 0 | } |
1950 | 0 | } |
1951 | | |
1952 | | |
1953 | | |
1954 | | /**************************/ |
1955 | | /* Dissect a PCH channel */ |
1956 | | static void |
1957 | | dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
1958 | | unsigned offset, struct fp_info *p_fp_info, void *data) |
1959 | 0 | { |
1960 | 0 | uint32_t ft; |
1961 | 0 | uint16_t pch_cfn; |
1962 | 0 | uint32_t tfi; |
1963 | 0 | bool paging_indication; |
1964 | 0 | uint32_t header_crc = 0; |
1965 | 0 | proto_item * header_crc_pi = NULL; |
1966 | | |
1967 | | /* Header CRC */ |
1968 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
1969 | | |
1970 | | /* Frame Type */ |
1971 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
1972 | 0 | offset++; |
1973 | |
|
1974 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
1975 | |
|
1976 | 0 | if (ft == FT_CONTROL) { |
1977 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
1978 | | /* For control frame the header CRC is actually frame CRC covering all |
1979 | | * bytes except the first */ |
1980 | 0 | if (preferences_header_checksum) { |
1981 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
1982 | 0 | } |
1983 | 0 | } |
1984 | 0 | else { |
1985 | 0 | unsigned header_length = 0; |
1986 | | /* DATA */ |
1987 | | |
1988 | | /* 12-bit CFN value */ |
1989 | 0 | proto_tree_add_item_ret_uint16(tree, hf_fp_pch_cfn, tvb, offset, 2, ENC_BIG_ENDIAN, &pch_cfn); |
1990 | 0 | offset++; |
1991 | |
|
1992 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%04u ", pch_cfn); |
1993 | | |
1994 | | /* Paging indication */ |
1995 | 0 | proto_tree_add_item(tree, hf_fp_pch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
1996 | 0 | paging_indication = tvb_get_uint8(tvb, offset) & 0x01; |
1997 | 0 | offset++; |
1998 | | |
1999 | | /* 5-bit TFI */ |
2000 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_pch_tfi, tvb, offset, 1, ENC_BIG_ENDIAN, &tfi); |
2001 | 0 | offset++; |
2002 | 0 | header_length = offset; |
2003 | | /* Optional paging indications */ |
2004 | 0 | if (paging_indication) { |
2005 | 0 | proto_item *ti; |
2006 | 0 | ti = proto_tree_add_item(tree, hf_fp_paging_indication_bitmap, tvb, |
2007 | 0 | offset, |
2008 | 0 | (p_fp_info->paging_indications+7) / 8, |
2009 | 0 | ENC_NA); |
2010 | 0 | proto_item_append_text(ti, " (%u bits)", p_fp_info->paging_indications); |
2011 | |
|
2012 | 0 | if(preferences_track_paging_indications && !PINFO_FD_VISITED(pinfo)){ |
2013 | 0 | paging_indications_info_t* current_pi_info; |
2014 | 0 | current_pi_info = wmem_new0(wmem_file_scope(), paging_indications_info_t); |
2015 | 0 | current_pi_info->frame_number = pinfo->num; |
2016 | 0 | current_pi_info->paging_indications_bitmap = (uint8_t*)tvb_memdup(wmem_file_scope(), tvb, offset, (p_fp_info->paging_indications+7) / 8); |
2017 | 0 | p_fp_info->current_paging_indications = current_pi_info; |
2018 | 0 | } |
2019 | |
|
2020 | 0 | offset += ((p_fp_info->paging_indications+7) / 8); |
2021 | 0 | } |
2022 | 0 | if(preferences_track_paging_indications) { |
2023 | 0 | if(p_fp_info->relevant_paging_indications) { |
2024 | | /*If tracking PI is enabled and PI info (from the last packet) is attached, show on tree*/ |
2025 | 0 | proto_item *ti; |
2026 | 0 | proto_tree *relevant_pi_tree; |
2027 | |
|
2028 | 0 | tvbuff_t *pi_tvb; |
2029 | 0 | pi_tvb = tvb_new_child_real_data(tvb, |
2030 | 0 | p_fp_info->relevant_paging_indications->paging_indications_bitmap, |
2031 | 0 | (p_fp_info->paging_indications+7) / 8, |
2032 | 0 | (p_fp_info->paging_indications+7) / 8); |
2033 | 0 | add_new_data_source(pinfo, pi_tvb, "Relevant Paging Indication"); |
2034 | 0 | ti = proto_tree_add_item(tree, hf_fp_relevant_paging_indication_bitmap, pi_tvb, |
2035 | 0 | 0, |
2036 | 0 | (p_fp_info->paging_indications+7) / 8, |
2037 | 0 | ENC_NA); |
2038 | 0 | proto_item_append_text(ti, " (%u bits)", p_fp_info->paging_indications); |
2039 | 0 | proto_item_set_generated(ti); |
2040 | 0 | relevant_pi_tree = proto_item_add_subtree(ti, ett_fp_pch_relevant_pi); |
2041 | 0 | ti = proto_tree_add_uint(relevant_pi_tree, hf_fp_relevant_pi_frame, |
2042 | 0 | tvb, 0, 0, p_fp_info->relevant_paging_indications->frame_number); |
2043 | 0 | proto_item_set_generated(ti); |
2044 | 0 | } |
2045 | 0 | else { |
2046 | | /* PI info not attached. Check if this frame has any Transport Blocks (i.e. RRC payloads) */ |
2047 | 0 | if(tfi > 0) |
2048 | 0 | { |
2049 | | /* This frame has RRC payload(s) but the PI info is missing, report to the user*/ |
2050 | 0 | proto_tree_add_expert_remaining(tree, pinfo, &ei_fp_pch_lost_relevant_pi_frame, tvb, offset); |
2051 | 0 | } |
2052 | 0 | } |
2053 | 0 | } |
2054 | | |
2055 | | /* TB data */ |
2056 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &mac_fdd_pch_handle, data); |
2057 | |
|
2058 | 0 | if (preferences_header_checksum) { |
2059 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
2060 | 0 | } |
2061 | | /* Spare Extension and Payload CRC */ |
2062 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
2063 | 0 | } |
2064 | 0 | } |
2065 | | |
2066 | | |
2067 | | /**************************/ |
2068 | | /* Dissect a CPCH channel */ |
2069 | | static void |
2070 | | dissect_cpch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2071 | | unsigned offset, struct fp_info *p_fp_info) |
2072 | 0 | { |
2073 | 0 | uint32_t ft; |
2074 | | |
2075 | | /* Header CRC */ |
2076 | 0 | proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN); |
2077 | | |
2078 | | /* Frame Type */ |
2079 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
2080 | 0 | offset++; |
2081 | |
|
2082 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
2083 | |
|
2084 | 0 | if (ft == FT_CONTROL) { |
2085 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
2086 | 0 | } |
2087 | 0 | else { |
2088 | 0 | unsigned cfn; |
2089 | 0 | uint32_t encoded; |
2090 | 0 | unsigned header_length = 0; |
2091 | 0 | uint32_t propagation_delay = 0; |
2092 | | |
2093 | | /* DATA */ |
2094 | | |
2095 | | /* CFN */ |
2096 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2097 | 0 | offset++; |
2098 | |
|
2099 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
2100 | | |
2101 | | /* TFI */ |
2102 | 0 | proto_tree_add_item(tree, hf_fp_cpch_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
2103 | 0 | offset++; |
2104 | | |
2105 | | /* Propagation delay */ |
2106 | 0 | encoded = tvb_get_uint8(tvb, offset); |
2107 | 0 | propagation_delay = encoded * 3; |
2108 | 0 | proto_tree_add_uint_format_value(tree, hf_fp_propagation_delay, tvb, offset, 1, |
2109 | 0 | propagation_delay, "Propagation Delay: %u chips (%u)", |
2110 | 0 | propagation_delay, encoded); |
2111 | 0 | offset++; |
2112 | 0 | header_length = offset; /* XXX this might be wrong */ |
2113 | | /* TB data */ |
2114 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, NULL, NULL); |
2115 | | |
2116 | | /* CRCIs */ |
2117 | 0 | offset = dissect_crci_bits(tvb, pinfo, tree, p_fp_info, offset); |
2118 | | |
2119 | | /* Spare Extension and Payload CRC */ |
2120 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
2121 | 0 | } |
2122 | 0 | } |
2123 | | |
2124 | | |
2125 | | /**************************/ |
2126 | | /* Dissect a BCH channel */ |
2127 | | static void |
2128 | | dissect_bch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2129 | | unsigned offset, struct fp_info *p_fp_info) |
2130 | 0 | { |
2131 | 0 | uint32_t ft; |
2132 | | |
2133 | | /* Header CRC */ |
2134 | 0 | proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN); |
2135 | | |
2136 | | /* Frame Type */ |
2137 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
2138 | 0 | offset++; |
2139 | |
|
2140 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
2141 | |
|
2142 | 0 | if (ft == FT_CONTROL) { |
2143 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
2144 | 0 | } |
2145 | 0 | } |
2146 | | |
2147 | | |
2148 | | /********************************/ |
2149 | | /* Dissect an IUR DSCH channel */ |
2150 | | static void |
2151 | | dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2152 | | unsigned offset, struct fp_info *p_fp_info) |
2153 | 0 | { |
2154 | 0 | uint32_t ft; |
2155 | | |
2156 | | /* Header CRC */ |
2157 | 0 | proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN); |
2158 | | |
2159 | | /* Frame Type */ |
2160 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
2161 | 0 | offset++; |
2162 | |
|
2163 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
2164 | |
|
2165 | 0 | if (ft == FT_CONTROL) { |
2166 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
2167 | 0 | } |
2168 | 0 | else { |
2169 | | /* TODO: DATA */ |
2170 | 0 | } |
2171 | 0 | } |
2172 | | |
2173 | | |
2174 | | |
2175 | | |
2176 | | /************************/ |
2177 | | /* DCH control messages */ |
2178 | | |
2179 | | static int |
2180 | | dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2181 | 0 | { |
2182 | 0 | uint32_t cfn; |
2183 | 0 | int16_t toa; |
2184 | 0 | proto_item *toa_ti; |
2185 | | |
2186 | | /* CFN control */ |
2187 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2188 | 0 | offset++; |
2189 | | |
2190 | | /* ToA */ |
2191 | 0 | toa = tvb_get_ntohs(tvb, offset); |
2192 | 0 | toa_ti = proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, ENC_BIG_ENDIAN); |
2193 | 0 | offset += 2; |
2194 | |
|
2195 | 0 | expert_add_info_format(pinfo, toa_ti, &ei_fp_timing_adjustment_reported, "Timing adjustment reported (%.3f ms)", ((float)(toa) / 8)); |
2196 | |
|
2197 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, |
2198 | 0 | " CFN = %u, ToA = %d", cfn, toa); |
2199 | |
|
2200 | 0 | return offset; |
2201 | 0 | } |
2202 | | |
2203 | | static int |
2204 | | dissect_dch_rx_timing_deviation(packet_info *pinfo, proto_tree *tree, |
2205 | | tvbuff_t *tvb, unsigned offset, |
2206 | | struct fp_info *p_fp_info) |
2207 | 0 | { |
2208 | 0 | uint16_t timing_deviation; |
2209 | 0 | int timing_deviation_chips; |
2210 | 0 | proto_item *timing_deviation_ti; |
2211 | | |
2212 | | /* CFN control */ |
2213 | 0 | proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN); |
2214 | 0 | offset++; |
2215 | | |
2216 | | /* Rx Timing Deviation */ |
2217 | 0 | timing_deviation_ti = proto_tree_add_item_ret_uint16(tree, hf_fp_dch_rx_timing_deviation, tvb, offset, 1, ENC_BIG_ENDIAN, &timing_deviation); |
2218 | 0 | offset++; |
2219 | | |
2220 | | /* May be extended in R7, but in this case there are at least 2 bytes remaining */ |
2221 | 0 | if ((p_fp_info->release == 7) && |
2222 | 0 | (tvb_reported_length_remaining(tvb, offset) >= 2)) { |
2223 | | |
2224 | | /* New IE flags */ |
2225 | 0 | uint64_t extended_bits_present; |
2226 | 0 | uint64_t e_rucch_present; |
2227 | | |
2228 | | /* Read flags */ |
2229 | 0 | proto_tree_add_bits_ret_val(tree, hf_fp_e_rucch_present, tvb, |
2230 | 0 | offset*8 + 6, 1, &e_rucch_present, ENC_BIG_ENDIAN); |
2231 | 0 | proto_tree_add_bits_ret_val(tree, hf_fp_extended_bits_present, tvb, |
2232 | 0 | offset*8 + 7, 1, &extended_bits_present, ENC_BIG_ENDIAN); |
2233 | 0 | offset++; |
2234 | | |
2235 | | /* Optional E-RUCCH */ |
2236 | 0 | if (e_rucch_present) { |
2237 | | |
2238 | | /* Value of bit_offset depends upon division type */ |
2239 | 0 | int bit_offset; |
2240 | |
|
2241 | 0 | switch (p_fp_info->division) { |
2242 | 0 | case Division_TDD_384: |
2243 | 0 | bit_offset = 6; |
2244 | 0 | break; |
2245 | 0 | case Division_TDD_768: |
2246 | 0 | bit_offset = 5; |
2247 | 0 | break; |
2248 | 0 | default: |
2249 | 0 | { |
2250 | 0 | proto_tree_add_expert(tree, pinfo, &ei_fp_expecting_tdd, tvb, 0, 0); |
2251 | 0 | bit_offset = 6; |
2252 | 0 | } |
2253 | 0 | } |
2254 | | |
2255 | 0 | proto_tree_add_item(tree, hf_fp_dch_e_rucch_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
2256 | 0 | proto_tree_add_bits_item(tree, hf_fp_dch_e_rucch_flag, tvb, |
2257 | 0 | offset*8 + bit_offset, 1, ENC_BIG_ENDIAN); |
2258 | 0 | } |
2259 | | |
2260 | | /* Timing deviation may be extended by another: |
2261 | | - 1 bits (3.84 TDD) OR |
2262 | | - 2 bits (7.68 TDD) |
2263 | | */ |
2264 | 0 | if (extended_bits_present) { |
2265 | 0 | uint8_t extra_bits; |
2266 | 0 | unsigned bits_to_extend; |
2267 | 0 | switch (p_fp_info->division) { |
2268 | 0 | case Division_TDD_384: |
2269 | 0 | bits_to_extend = 1; |
2270 | 0 | break; |
2271 | 0 | case Division_TDD_768: |
2272 | 0 | bits_to_extend = 2; |
2273 | 0 | break; |
2274 | | |
2275 | 0 | default: |
2276 | | /* TODO: report unexpected division type */ |
2277 | 0 | bits_to_extend = 1; |
2278 | 0 | break; |
2279 | 0 | } |
2280 | 0 | extra_bits = tvb_get_uint8(tvb, offset) & |
2281 | 0 | ((bits_to_extend == 1) ? 0x01 : 0x03); |
2282 | 0 | timing_deviation = (extra_bits << 8) | (timing_deviation); |
2283 | 0 | proto_item_append_text(timing_deviation_ti, |
2284 | 0 | " (extended to 0x%x)", |
2285 | 0 | timing_deviation); |
2286 | 0 | proto_tree_add_bits_item(tree, hf_fp_extended_bits, tvb, |
2287 | 0 | offset*8 + (8-bits_to_extend), bits_to_extend, ENC_BIG_ENDIAN); |
2288 | 0 | offset++; |
2289 | 0 | } |
2290 | 0 | } |
2291 | | |
2292 | 0 | timing_deviation_chips = (timing_deviation*4) - 1024; |
2293 | 0 | proto_item_append_text(timing_deviation_ti, " (%d chips)", |
2294 | 0 | timing_deviation_chips); |
2295 | |
|
2296 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " deviation = %u (%d chips)", |
2297 | 0 | timing_deviation, timing_deviation_chips); |
2298 | |
|
2299 | 0 | return offset; |
2300 | 0 | } |
2301 | | |
2302 | | static int |
2303 | | dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2304 | 0 | { |
2305 | 0 | uint32_t cfn; |
2306 | | |
2307 | | /* CFN control */ |
2308 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2309 | 0 | offset++; |
2310 | |
|
2311 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u", cfn); |
2312 | |
|
2313 | 0 | return offset; |
2314 | 0 | } |
2315 | | |
2316 | | static int |
2317 | | dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2318 | 0 | { |
2319 | 0 | uint32_t cfn; |
2320 | 0 | int16_t toa; |
2321 | | |
2322 | | /* CFN control */ |
2323 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2324 | 0 | offset++; |
2325 | | |
2326 | | /* ToA */ |
2327 | 0 | toa = tvb_get_ntohs(tvb, offset); |
2328 | 0 | proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, ENC_BIG_ENDIAN); |
2329 | 0 | offset += 2; |
2330 | |
|
2331 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, ToA = %d", |
2332 | 0 | cfn, toa); |
2333 | |
|
2334 | 0 | return offset; |
2335 | 0 | } |
2336 | | |
2337 | | static int |
2338 | | dissect_dch_outer_loop_power_control(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2339 | 0 | { |
2340 | | /* UL SIR target */ |
2341 | 0 | uint8_t encoded = tvb_get_uint8(tvb, offset); |
2342 | 0 | float target = (float)-8.2 + ((float)0.1 * (float)(int)(encoded)); |
2343 | 0 | proto_tree_add_float_format_value(tree, hf_fp_ul_sir_target, tvb, offset, 1, target, "%.1f dB (%u)", target, encoded); |
2344 | 0 | offset++; |
2345 | |
|
2346 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " UL SIR Target = %.1f", target); |
2347 | |
|
2348 | 0 | return offset; |
2349 | 0 | } |
2350 | | |
2351 | | static int |
2352 | | dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2353 | 0 | { |
2354 | 0 | return dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset); |
2355 | 0 | } |
2356 | | |
2357 | | static int |
2358 | | dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2359 | 0 | { |
2360 | 0 | return dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset); |
2361 | 0 | } |
2362 | | |
2363 | | static int |
2364 | | dissect_dch_radio_interface_parameter_update(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, unsigned offset) |
2365 | 0 | { |
2366 | 0 | float tpc_po; |
2367 | 0 | int8_t max_tx_pwr; |
2368 | 0 | int n; |
2369 | 0 | uint8_t encoded; |
2370 | | |
2371 | | /* Show defined flags in these 2 bytes */ |
2372 | 0 | for (n=4; n >= 0; n--) { |
2373 | 0 | proto_tree_add_item(tree, hf_fp_radio_interface_parameter_update_flag[n], tvb, offset, 2, ENC_BIG_ENDIAN); |
2374 | 0 | } |
2375 | 0 | offset += 2; |
2376 | | |
2377 | | /* CFN */ |
2378 | 0 | proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN); |
2379 | 0 | offset++; |
2380 | | |
2381 | | /* DPC mode */ |
2382 | 0 | proto_tree_add_item(tree, hf_fp_dpc_mode, tvb, offset, 1, ENC_BIG_ENDIAN); |
2383 | | |
2384 | | /* TPC PO */ |
2385 | 0 | encoded = tvb_get_uint8(tvb, offset) & 0x1f; |
2386 | 0 | tpc_po = (float)encoded * 0.25f; |
2387 | 0 | proto_tree_add_float_format_value(tree, hf_fp_tpc_po, tvb, offset, 1, tpc_po, |
2388 | 0 | "%.2f dB (%u)", tpc_po, encoded); |
2389 | 0 | offset++; |
2390 | | |
2391 | | /* Multiple RL sets indicator */ |
2392 | 0 | proto_tree_add_item(tree, hf_fp_multiple_rl_set_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); |
2393 | 0 | offset += 2; |
2394 | | |
2395 | | /* Maximum UE TX Power */ |
2396 | 0 | encoded = tvb_get_uint8(tvb, offset) & 0x7f; |
2397 | 0 | max_tx_pwr = -55 + encoded; |
2398 | 0 | proto_tree_add_int_format(tree, hf_fp_max_ue_tx_pow, tvb, offset, 1, max_tx_pwr, |
2399 | 0 | "%d dBm (%u)", max_tx_pwr, encoded); |
2400 | 0 | offset++; |
2401 | |
|
2402 | 0 | return offset; |
2403 | 0 | } |
2404 | | |
2405 | | static int |
2406 | | dissect_dch_timing_advance(proto_tree *tree, packet_info *pinfo, |
2407 | | tvbuff_t *tvb, unsigned offset, struct fp_info *p_fp_info) |
2408 | 0 | { |
2409 | 0 | uint32_t cfn; |
2410 | 0 | uint16_t timing_advance; |
2411 | 0 | proto_item *timing_advance_ti; |
2412 | | |
2413 | | /* CFN control */ |
2414 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn_control, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2415 | 0 | offset++; |
2416 | | |
2417 | | /* Timing Advance */ |
2418 | 0 | timing_advance = (tvb_get_uint8(tvb, offset) & 0x3f) * 4; |
2419 | 0 | timing_advance_ti = proto_tree_add_uint(tree, hf_fp_timing_advance, tvb, offset, 1, timing_advance); |
2420 | 0 | offset++; |
2421 | |
|
2422 | 0 | if ((p_fp_info->release == 7) && |
2423 | 0 | (tvb_reported_length_remaining(tvb, offset) > 0)) { |
2424 | | |
2425 | | /* New IE flags */ |
2426 | 0 | uint8_t flags = tvb_get_uint8(tvb, offset); |
2427 | 0 | uint8_t extended_bits = flags & 0x01; |
2428 | 0 | offset++; |
2429 | |
|
2430 | 0 | if (extended_bits) { |
2431 | 0 | uint8_t extra_bit = tvb_get_uint8(tvb, offset) & 0x01; |
2432 | 0 | proto_item_append_text(timing_advance_ti, " (extended to %u)", |
2433 | 0 | (timing_advance << 1) | extra_bit); |
2434 | 0 | } |
2435 | 0 | offset++; |
2436 | 0 | } |
2437 | |
|
2438 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, TA = %u", |
2439 | 0 | cfn, timing_advance); |
2440 | |
|
2441 | 0 | return offset; |
2442 | 0 | } |
2443 | | |
2444 | | static int |
2445 | | dissect_dch_tnl_congestion_indication(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, unsigned offset) |
2446 | 0 | { |
2447 | 0 | uint64_t status; |
2448 | | |
2449 | | /* Congestion status */ |
2450 | 0 | proto_tree_add_bits_ret_val(tree, hf_fp_congestion_status, tvb, |
2451 | 0 | offset*8 + 6, 2, &status, ENC_BIG_ENDIAN); |
2452 | 0 | offset++; |
2453 | |
|
2454 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " status = %s", |
2455 | 0 | val_to_str_const((uint16_t)status, congestion_status_vals, "unknown")); |
2456 | |
|
2457 | 0 | return offset; |
2458 | 0 | } |
2459 | | |
2460 | | |
2461 | | |
2462 | | |
2463 | | /* DCH control frame */ |
2464 | | static void |
2465 | | dissect_dch_control_frame(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, |
2466 | | unsigned offset, struct fp_info *p_fp_info) |
2467 | 0 | { |
2468 | | /* Control frame type */ |
2469 | 0 | uint8_t control_frame_type = tvb_get_uint8(tvb, offset); |
2470 | 0 | proto_tree_add_item(tree, hf_fp_dch_control_frame_type, tvb, offset, 1, ENC_BIG_ENDIAN); |
2471 | 0 | offset++; |
2472 | |
|
2473 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
2474 | 0 | val_to_str_const(control_frame_type, |
2475 | 0 | dch_control_frame_type_vals, "Unknown")); |
2476 | |
|
2477 | 0 | switch (control_frame_type) { |
2478 | 0 | case DCH_TIMING_ADJUSTMENT: |
2479 | 0 | /*offset =*/ dissect_dch_timing_adjustment(tree, pinfo, tvb, offset); |
2480 | 0 | break; |
2481 | 0 | case DCH_RX_TIMING_DEVIATION: |
2482 | 0 | /*offset =*/ dissect_dch_rx_timing_deviation(pinfo, tree, tvb, offset, p_fp_info); |
2483 | 0 | break; |
2484 | 0 | case DCH_DL_SYNCHRONISATION: |
2485 | 0 | /*offset =*/ dissect_dch_dl_synchronisation(tree, pinfo, tvb, offset); |
2486 | 0 | break; |
2487 | 0 | case DCH_UL_SYNCHRONISATION: |
2488 | 0 | /*offset =*/ dissect_dch_ul_synchronisation(tree, pinfo, tvb, offset); |
2489 | 0 | break; |
2490 | 0 | case DCH_OUTER_LOOP_POWER_CONTROL: |
2491 | 0 | /*offset =*/ dissect_dch_outer_loop_power_control(tree, pinfo, tvb, offset); |
2492 | 0 | break; |
2493 | 0 | case DCH_DL_NODE_SYNCHRONISATION: |
2494 | 0 | /*offset =*/ dissect_dch_dl_node_synchronisation(tree, pinfo, tvb, offset); |
2495 | 0 | break; |
2496 | 0 | case DCH_UL_NODE_SYNCHRONISATION: |
2497 | 0 | /*offset =*/ dissect_dch_ul_node_synchronisation(tree, pinfo, tvb, offset); |
2498 | 0 | break; |
2499 | 0 | case DCH_RADIO_INTERFACE_PARAMETER_UPDATE: |
2500 | 0 | /*offset =*/ dissect_dch_radio_interface_parameter_update(tree, pinfo, tvb, offset); |
2501 | 0 | break; |
2502 | 0 | case DCH_TIMING_ADVANCE: |
2503 | 0 | /*offset =*/ dissect_dch_timing_advance(tree, pinfo, tvb, offset, p_fp_info); |
2504 | 0 | break; |
2505 | 0 | case DCH_TNL_CONGESTION_INDICATION: |
2506 | 0 | /*offset =*/ dissect_dch_tnl_congestion_indication(tree, pinfo, tvb, offset); |
2507 | 0 | break; |
2508 | 0 | } |
2509 | | |
2510 | | /* Spare Extension */ |
2511 | | /* dissect_spare_extension_and_crc(tvb, pinfo, tree, 0, offset); |
2512 | | */ |
2513 | 0 | } |
2514 | | |
2515 | | /*******************************/ |
2516 | | /* Dissect a DCH channel */ |
2517 | | static void |
2518 | | dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2519 | | unsigned offset, struct fp_info *p_fp_info, void *data) |
2520 | 0 | { |
2521 | 0 | uint32_t ft; |
2522 | 0 | uint32_t cfn; |
2523 | 0 | unsigned header_length; |
2524 | 0 | uint32_t header_crc = 0; |
2525 | 0 | proto_item * header_crc_pi = NULL; |
2526 | | |
2527 | | /* Header CRC */ |
2528 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
2529 | | |
2530 | | /* Frame Type */ |
2531 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
2532 | 0 | offset++; |
2533 | |
|
2534 | 0 | col_append_str(pinfo->cinfo, COL_INFO, |
2535 | 0 | (ft == FT_CONTROL )? " [Control] " : |
2536 | 0 | ((p_fp_info->is_uplink) ? " [ULData] " : |
2537 | 0 | " [DLData] " )); |
2538 | |
|
2539 | 0 | if (ft == FT_CONTROL) { |
2540 | | /* DCH control frame */ |
2541 | 0 | dissect_dch_control_frame(tree, pinfo, tvb, offset, p_fp_info); |
2542 | | /* For control frame the header CRC is actually frame CRC covering all |
2543 | | * bytes except the first */ |
2544 | 0 | if (preferences_header_checksum) { |
2545 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
2546 | 0 | } |
2547 | 0 | } else { |
2548 | | /************************/ |
2549 | | /* DCH data here */ |
2550 | 0 | int chan; |
2551 | | /* CFN */ |
2552 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2553 | 0 | offset++; |
2554 | |
|
2555 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn); |
2556 | | |
2557 | | /* One TFI for each channel */ |
2558 | 0 | for (chan=0; chan < p_fp_info->num_chans; chan++) { |
2559 | 0 | proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, ENC_BIG_ENDIAN); |
2560 | 0 | offset++; |
2561 | 0 | } |
2562 | 0 | header_length = offset; |
2563 | | /* Dissect TB data */ |
2564 | 0 | offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &mac_fdd_dch_handle, data); |
2565 | | |
2566 | | /* QE and CRCI bits (uplink only) */ |
2567 | 0 | if (p_fp_info->is_uplink) { |
2568 | 0 | proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, ENC_BIG_ENDIAN); |
2569 | 0 | offset++; |
2570 | 0 | offset = dissect_crci_bits(tvb, pinfo, tree, p_fp_info, offset); |
2571 | 0 | } |
2572 | |
|
2573 | 0 | if (preferences_header_checksum) { |
2574 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
2575 | 0 | } |
2576 | | /* Spare extension and payload CRC (optional) */ |
2577 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, |
2578 | 0 | p_fp_info->dch_crc_present, offset, header_length); |
2579 | 0 | } |
2580 | 0 | } |
2581 | | |
2582 | | /**********************************/ |
2583 | | /* Dissect an E-DCH channel */ |
2584 | | static void |
2585 | | dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2586 | | unsigned offset, struct fp_info *p_fp_info, |
2587 | | bool is_common, |
2588 | | void *data) |
2589 | 0 | { |
2590 | 0 | uint32_t ft; |
2591 | 0 | uint8_t number_of_subframes; |
2592 | 0 | uint32_t cfn; |
2593 | 0 | int n; |
2594 | 0 | struct edch_t1_subframe_info subframes[16]; |
2595 | 0 | uint32_t header_crc = 0; |
2596 | 0 | proto_item * header_crc_pi = NULL; |
2597 | 0 | proto_item * item; |
2598 | 0 | unsigned header_length; |
2599 | 0 | rlc_info * rlcinf; |
2600 | |
|
2601 | 0 | if (p_fp_info->edch_type == 1) { |
2602 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " (T2)"); |
2603 | 0 | } |
2604 | | |
2605 | | /* Header CRC */ |
2606 | | /* the bitmask doesn't properly handle this delicate case, do manually */ |
2607 | 0 | header_crc = (tvb_get_bits8(tvb, offset*8, 7) << 4) + tvb_get_bits8(tvb, offset*8+8, 4); |
2608 | | |
2609 | | /* Frame Type */ |
2610 | 0 | ft = tvb_get_uint8(tvb, offset) & 0x01; |
2611 | |
|
2612 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
2613 | |
|
2614 | 0 | if (ft == FT_CONTROL) { |
2615 | | /* DCH control frame */ |
2616 | | |
2617 | | /* For control frame the header CRC is actually frame CRC covering all |
2618 | | * bytes except the first */ |
2619 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
2620 | 0 | proto_tree_add_item(tree, hf_fp_ft, tvb, 0, 1, ENC_BIG_ENDIAN); |
2621 | 0 | offset++; |
2622 | 0 | if (preferences_header_checksum) { |
2623 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
2624 | 0 | } |
2625 | 0 | dissect_dch_control_frame(tree, pinfo, tvb, offset, p_fp_info); |
2626 | 0 | } |
2627 | 0 | else { |
2628 | | /********************************/ |
2629 | | /* E-DCH data here */ |
2630 | 0 | unsigned bit_offset; |
2631 | 0 | unsigned total_pdus = 0; |
2632 | 0 | unsigned total_bits = 0; |
2633 | 0 | bool dissected = false; |
2634 | |
|
2635 | 0 | rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0); |
2636 | 0 | if (!rlcinf) { |
2637 | 0 | rlcinf = wmem_new0(pinfo->pool, rlc_info); |
2638 | 0 | } |
2639 | |
|
2640 | 0 | header_crc_pi = proto_tree_add_uint_format(tree, hf_fp_edch_header_crc, tvb, |
2641 | 0 | offset, 2, header_crc, |
2642 | 0 | "%u%u%u%u %u%u%u. %u%u%u%u .... = E-DCH Header CRC: 0x%x", |
2643 | 0 | (header_crc >> 10) & 1, |
2644 | 0 | (header_crc >> 9) & 1, |
2645 | 0 | (header_crc >> 8) & 1, |
2646 | 0 | (header_crc >> 7) & 1, |
2647 | 0 | (header_crc >> 6) & 1, |
2648 | 0 | (header_crc >> 5) & 1, |
2649 | 0 | (header_crc >> 4) & 1, |
2650 | 0 | (header_crc >> 3) & 1, |
2651 | 0 | (header_crc >> 2) & 1, |
2652 | 0 | (header_crc >> 1) & 1, |
2653 | 0 | (header_crc >> 0) & 1, header_crc); |
2654 | 0 | proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN); |
2655 | 0 | offset++; |
2656 | | /* FSN */ |
2657 | 0 | proto_tree_add_item(tree, hf_fp_edch_fsn, tvb, offset, 1, ENC_BIG_ENDIAN); |
2658 | 0 | offset++; |
2659 | | |
2660 | | /* Number of subframes. |
2661 | | This was 3 bits in early releases, is 4 bits offset by 1 in later releases */ |
2662 | 0 | if ((p_fp_info->release >= 6) && |
2663 | 0 | ((p_fp_info->release_year > 2005) || |
2664 | 0 | ((p_fp_info->release_year == 2005) && (p_fp_info->release_month >= 9)))) { |
2665 | | |
2666 | | /* Use 4 bits plus offset of 1 */ |
2667 | 0 | number_of_subframes = (tvb_get_uint8(tvb, offset) & 0x0f) + 1; |
2668 | 0 | } |
2669 | 0 | else { |
2670 | | /* Use 3 bits only */ |
2671 | 0 | number_of_subframes = (tvb_get_uint8(tvb, offset) & 0x07); |
2672 | 0 | } |
2673 | 0 | proto_tree_add_uint(tree, hf_fp_edch_number_of_subframes, tvb, offset, 1, |
2674 | 0 | number_of_subframes); |
2675 | |
|
2676 | 0 | offset++; |
2677 | | |
2678 | | /* CFN */ |
2679 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_cfn, tvb, offset, 1, ENC_BIG_ENDIAN, &cfn); |
2680 | 0 | offset++; |
2681 | | |
2682 | | /* Remainder of T2 or common data frames differ here... */ |
2683 | 0 | if (p_fp_info->edch_type == 1) { |
2684 | 0 | dissect_e_dch_t2_or_common_channel_info(tvb, pinfo, tree, offset, p_fp_info, |
2685 | 0 | number_of_subframes, |
2686 | 0 | is_common, header_crc, |
2687 | 0 | header_crc_pi, data); |
2688 | 0 | return; |
2689 | 0 | } |
2690 | | |
2691 | | /* EDCH subframe header list */ |
2692 | 0 | for (n=0; n < number_of_subframes; n++) { |
2693 | 0 | int i; |
2694 | 0 | int start_offset = offset; |
2695 | 0 | proto_item *subframe_header_ti; |
2696 | 0 | proto_tree *subframe_header_tree; |
2697 | | |
2698 | | /* Add subframe header subtree */ |
2699 | 0 | subframe_header_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe_header, tvb, offset, 0, |
2700 | 0 | "", "Subframe"); |
2701 | 0 | subframe_header_tree = proto_item_add_subtree(subframe_header_ti, ett_fp_edch_subframe_header); |
2702 | | |
2703 | | /* Number of HARQ Retransmissions */ |
2704 | 0 | proto_tree_add_item(subframe_header_tree, hf_fp_edch_harq_retransmissions, tvb, |
2705 | 0 | offset, 1, ENC_BIG_ENDIAN); |
2706 | | |
2707 | | /* Subframe number */ |
2708 | 0 | subframes[n].subframe_number = (tvb_get_uint8(tvb, offset) & 0x07); |
2709 | 0 | proto_tree_add_bits_item(subframe_header_tree, hf_fp_edch_subframe_number, tvb, |
2710 | 0 | offset*8+5, 3, ENC_BIG_ENDIAN); |
2711 | 0 | offset++; |
2712 | | |
2713 | | /* Number of MAC-es PDUs */ |
2714 | 0 | subframes[n].number_of_mac_es_pdus = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
2715 | 0 | proto_tree_add_item(subframe_header_tree, hf_fp_edch_number_of_mac_es_pdus, |
2716 | 0 | tvb, offset, 1, ENC_BIG_ENDIAN); |
2717 | 0 | bit_offset = 4; |
2718 | |
|
2719 | 0 | proto_item_append_text(subframe_header_ti, " %u header (%u MAC-es PDUs)", |
2720 | 0 | subframes[n].subframe_number, |
2721 | 0 | subframes[n].number_of_mac_es_pdus); |
2722 | | |
2723 | | /* Details of each MAC-es PDU */ |
2724 | 0 | for (i=0; i < subframes[n].number_of_mac_es_pdus; i++) { |
2725 | 0 | uint64_t ddi; |
2726 | 0 | uint64_t n_pdus; /*Size of the PDU*/ |
2727 | 0 | int no_ddi_entries = MIN(p_fp_info->no_ddi_entries, MAX_EDCH_DDIS); |
2728 | |
|
2729 | 0 | proto_item *ddi_ti; |
2730 | 0 | int ddi_size = -1; |
2731 | 0 | int p; |
2732 | | |
2733 | | /* DDI (6 bits) */ |
2734 | 0 | ddi_ti = proto_tree_add_bits_ret_val(subframe_header_tree, hf_fp_edch_ddi, tvb, |
2735 | 0 | offset*8 + bit_offset, 6, &ddi, ENC_BIG_ENDIAN); |
2736 | |
|
2737 | 0 | rlcinf->rbid[i] = (uint8_t)ddi; |
2738 | | /********************************/ |
2739 | | /* Look up data in higher layers*/ |
2740 | | /* Look up the size from this DDI value */ |
2741 | 0 | for (p=0; p < no_ddi_entries; p++) { |
2742 | 0 | if (ddi == p_fp_info->edch_ddi[p]) { |
2743 | 0 | ddi_size = p_fp_info->edch_macd_pdu_size[p]; |
2744 | |
|
2745 | 0 | break; |
2746 | 0 | } |
2747 | 0 | } |
2748 | |
|
2749 | 0 | if (ddi_size == -1) { |
2750 | 0 | expert_add_info_format(pinfo, ddi_ti, &ei_fp_ddi_not_defined, "DDI %u not defined for this UE!", (unsigned)ddi); |
2751 | 0 | return; |
2752 | 0 | } |
2753 | 0 | else { |
2754 | 0 | proto_item_append_text(ddi_ti, " (%d bits)", ddi_size); |
2755 | 0 | } |
2756 | | |
2757 | 0 | subframes[n].ddi[i] = (uint8_t)ddi; |
2758 | 0 | bit_offset += 6; |
2759 | | |
2760 | | /* Number of MAC-d PDUs (6 bits) */ |
2761 | 0 | item = proto_tree_add_bits_ret_val(subframe_header_tree, hf_fp_edch_number_of_mac_d_pdus, tvb, |
2762 | 0 | offset*8 + bit_offset, 6, &n_pdus, ENC_BIG_ENDIAN); |
2763 | 0 | if (n_pdus > MAX_MAC_FRAMES) { |
2764 | 0 | expert_add_info_format(pinfo, item, &ei_fp_invalid_frame_count, "Invalid number of PDUs (max is %u)", MAX_MAC_FRAMES); |
2765 | 0 | return; |
2766 | 0 | } |
2767 | | |
2768 | 0 | subframes[n].number_of_mac_d_pdus[i] = (uint8_t)n_pdus; |
2769 | 0 | bit_offset += 6; |
2770 | 0 | } |
2771 | | |
2772 | 0 | offset += ((bit_offset+7)/8); |
2773 | | |
2774 | | /* Tree should cover entire subframe header */ |
2775 | 0 | proto_item_set_len(subframe_header_ti, offset - start_offset); |
2776 | 0 | } |
2777 | 0 | header_length = offset; |
2778 | | /* EDCH subframes */ |
2779 | 0 | for (n=0; n < number_of_subframes; n++) { |
2780 | 0 | int i; |
2781 | 0 | proto_item *subframe_ti; |
2782 | 0 | proto_tree *subframe_tree; |
2783 | 0 | unsigned bits_in_subframe = 0; |
2784 | 0 | unsigned mac_d_pdus_in_subframe = 0; |
2785 | 0 | unsigned lchid=0; /*Logical channel id*/ |
2786 | 0 | uint32_t user_identity; |
2787 | 0 | umts_mac_info *macinf; |
2788 | 0 | bit_offset = 0; |
2789 | |
|
2790 | 0 | macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0); |
2791 | 0 | if (!macinf) { |
2792 | 0 | macinf = wmem_new0(pinfo->pool, umts_mac_info); |
2793 | 0 | } |
2794 | | /* Add subframe subtree */ |
2795 | 0 | subframe_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe, tvb, offset, 0, |
2796 | 0 | "", "Subframe %u data", subframes[n].subframe_number); |
2797 | 0 | subframe_tree = proto_item_add_subtree(subframe_ti, ett_fp_edch_subframe); |
2798 | |
|
2799 | 0 | for (i=0; i < subframes[n].number_of_mac_es_pdus; i++) { |
2800 | 0 | int m; |
2801 | 0 | uint16_t size = 0; |
2802 | | /* uint8_t tsn; */ |
2803 | 0 | unsigned send_size; |
2804 | 0 | proto_item *ti; |
2805 | 0 | int macd_idx; |
2806 | 0 | proto_tree *maces_tree = NULL; |
2807 | 0 | int no_ddi_entries = MIN(p_fp_info->no_ddi_entries, MAX_EDCH_DDIS); |
2808 | | |
2809 | | /* Look up mac-d pdu size and logicalchannel id for this DDI */ |
2810 | 0 | for (m=0; m < no_ddi_entries; m++) { |
2811 | 0 | if (subframes[n].ddi[i] == p_fp_info->edch_ddi[m]) { |
2812 | 0 | size = p_fp_info->edch_macd_pdu_size[m]; |
2813 | 0 | lchid = p_fp_info->edch_lchId[m]; |
2814 | 0 | break; |
2815 | 0 | } |
2816 | 0 | } |
2817 | |
|
2818 | 0 | if (m == no_ddi_entries) { |
2819 | | /* Not found. Oops */ |
2820 | 0 | expert_add_info(pinfo, NULL, &ei_fp_unable_to_locate_ddi_entry); |
2821 | 0 | return; |
2822 | 0 | } |
2823 | | |
2824 | | /* Send MAC-dd PDUs together as one MAC-es PDU */ |
2825 | 0 | send_size = size * subframes[n].number_of_mac_d_pdus[i]; |
2826 | | |
2827 | | /* 2 bits spare */ |
2828 | 0 | proto_tree_add_item(subframe_tree, hf_fp_edch_pdu_padding, tvb, |
2829 | 0 | offset + (bit_offset/8), |
2830 | 0 | 1, ENC_BIG_ENDIAN); |
2831 | 0 | bit_offset += 2; |
2832 | | |
2833 | | /* TSN */ |
2834 | | /* tsn = (tvb_get_uint8(tvb, offset + (bit_offset/8)) & 0x3f); */ |
2835 | 0 | proto_tree_add_item(subframe_tree, hf_fp_edch_tsn, tvb, |
2836 | 0 | offset + (bit_offset/8), |
2837 | 0 | 1, ENC_BIG_ENDIAN); |
2838 | 0 | bit_offset += 6; |
2839 | | |
2840 | | /* PDU */ |
2841 | 0 | if (subframe_tree) { |
2842 | 0 | ti = proto_tree_add_item(subframe_tree, hf_fp_edch_mac_es_pdu, tvb, |
2843 | 0 | offset + (bit_offset/8), |
2844 | 0 | ((bit_offset % 8) + send_size + 7) / 8, |
2845 | 0 | ENC_NA); |
2846 | 0 | proto_item_append_text(ti, " (%u * %u = %u bits, PDU %d)", |
2847 | 0 | size, subframes[n].number_of_mac_d_pdus[i], |
2848 | 0 | send_size, n); |
2849 | 0 | maces_tree = proto_item_add_subtree(ti, ett_fp_edch_maces); |
2850 | 0 | } |
2851 | | /* Determine the UE ID to use in RLC */ |
2852 | 0 | user_identity = p_fp_info->com_context_id; |
2853 | 0 | if(p_fp_info->urnti) { |
2854 | 0 | user_identity = p_fp_info->urnti; |
2855 | 0 | } |
2856 | 0 | for (macd_idx = 0; macd_idx < subframes[n].number_of_mac_d_pdus[i]; macd_idx++) { |
2857 | |
|
2858 | 0 | if (preferences_call_mac_dissectors) { |
2859 | | /* Should no longer happen ??*/ |
2860 | 0 | if (macd_idx >= MAX_MAC_FRAMES) { |
2861 | 0 | expert_add_info_format(pinfo, subframe_tree, &ei_fp_invalid_frame_count, "Invalid frame count (max is %u)", MAX_MAC_FRAMES); |
2862 | 0 | return; |
2863 | 0 | } |
2864 | | |
2865 | 0 | tvbuff_t *next_tvb; |
2866 | | /* create new TVB and pass further on */ |
2867 | 0 | next_tvb = tvb_new_subset_length(tvb, offset + bit_offset/8, |
2868 | 0 | ((bit_offset % 8) + size + 7) / 8); |
2869 | | |
2870 | | /*Set up information needed for MAC and lower layers*/ |
2871 | 0 | macinf->content[macd_idx] = lchId_type_table[lchid]; /*Set the proper Content type for the mac layer.*/ |
2872 | 0 | macinf->lchid[macd_idx] = lchid; |
2873 | 0 | rlcinf->mode[macd_idx] = lchId_rlc_map[lchid]; /* Set RLC mode by lchid to RLC_MODE map in nbap.h */ |
2874 | | |
2875 | | /* Set UE ID to U-RNTI or NBAP Communication Context*/ |
2876 | 0 | rlcinf->ueid[macd_idx] = user_identity; |
2877 | 0 | rlcinf->rbid[macd_idx] = lchid; |
2878 | 0 | rlcinf->li_size[macd_idx] = RLC_LI_7BITS; |
2879 | |
|
2880 | 0 | rlcinf->ciphered[macd_idx] = false; |
2881 | 0 | rlcinf->deciphered[macd_idx] = false; |
2882 | 0 | p_fp_info->cur_tb = macd_idx; /*Set the transport block index */ |
2883 | |
|
2884 | 0 | call_dissector_with_data(mac_fdd_edch_handle, next_tvb, pinfo, top_level_tree, data); |
2885 | 0 | dissected = true; |
2886 | 0 | } |
2887 | 0 | else { |
2888 | | /* Just add as a MAC-d PDU */ |
2889 | 0 | proto_tree_add_item(maces_tree, hf_fp_mac_d_pdu, tvb, |
2890 | 0 | offset + (bit_offset/8), |
2891 | 0 | ((bit_offset % 8) + size + 7) / 8, |
2892 | 0 | ENC_NA); |
2893 | 0 | } |
2894 | 0 | bit_offset += size; |
2895 | 0 | } |
2896 | | |
2897 | 0 | bits_in_subframe += send_size; |
2898 | 0 | mac_d_pdus_in_subframe += subframes[n].number_of_mac_d_pdus[i]; |
2899 | | |
2900 | | /* Pad out to next byte */ |
2901 | 0 | bit_offset = WS_ROUNDUP_8(bit_offset); |
2902 | 0 | } |
2903 | | |
2904 | 0 | if (tree) { |
2905 | | /* Tree should cover entire subframe */ |
2906 | 0 | proto_item_set_len(subframe_ti, bit_offset/8); |
2907 | | /* Append summary info to subframe label */ |
2908 | 0 | proto_item_append_text(subframe_ti, " (%u bits in %u MAC-d PDUs)", |
2909 | 0 | bits_in_subframe, mac_d_pdus_in_subframe); |
2910 | 0 | } |
2911 | 0 | total_pdus += mac_d_pdus_in_subframe; |
2912 | 0 | total_bits += bits_in_subframe; |
2913 | |
|
2914 | 0 | offset += (bit_offset/8); |
2915 | 0 | } |
2916 | | |
2917 | | /* Report number of subframes in info column |
2918 | | * do this only if no other dissector was called */ |
2919 | 0 | if (dissected == false) { |
2920 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, |
2921 | 0 | " CFN = %03u (%u bits in %u pdus in %u subframes)", |
2922 | 0 | cfn, total_bits, total_pdus, number_of_subframes); |
2923 | 0 | } |
2924 | | /* Add data summary to info column */ |
2925 | | /*col_append_fstr(pinfo->cinfo, COL_INFO, " (%u bytes in %u SDUs in %u MAC-is PDUs in %u subframes)", |
2926 | | total_bytes, macis_sdus_found, macis_pdus, number_of_subframes);*/ |
2927 | 0 | if (preferences_header_checksum) { |
2928 | 0 | verify_header_crc_edch(tvb, pinfo, header_crc_pi, header_crc, header_length); |
2929 | 0 | } |
2930 | | /* Spare extension and payload CRC (optional) */ |
2931 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, |
2932 | 0 | p_fp_info->dch_crc_present, offset, header_length); |
2933 | 0 | } |
2934 | 0 | } |
2935 | | |
2936 | | /* Dissect the remainder of the T2 or common frame that differs from T1 */ |
2937 | | static void |
2938 | | dissect_e_dch_t2_or_common_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
2939 | | unsigned offset, struct fp_info *p_fp_info, |
2940 | | int number_of_subframes, |
2941 | | bool is_common, |
2942 | | uint16_t header_crc, |
2943 | | proto_item * header_crc_pi, |
2944 | | void *data) |
2945 | 0 | { |
2946 | 0 | int n; |
2947 | 0 | int pdu_no; |
2948 | 0 | uint64_t total_macis_sdus; |
2949 | 0 | uint16_t macis_sdus_found = 0; |
2950 | | /* uint16_t macis_pdus = 0; */ |
2951 | 0 | bool F = true; /* We want to continue loop if get E-RNTI indication... */ |
2952 | 0 | int bit_offset; |
2953 | 0 | proto_item *subframe_macis_descriptors_ti = NULL; |
2954 | 0 | static struct edch_t2_subframe_info subframes[16]; |
2955 | 0 | unsigned header_length = 0; |
2956 | | /* User Buffer size */ |
2957 | 0 | proto_tree_add_bits_item(tree, hf_fp_edch_user_buffer_size, tvb, offset*8, |
2958 | 0 | 18, ENC_BIG_ENDIAN); |
2959 | 0 | offset += 2; |
2960 | | |
2961 | | /* Spare is in-between... */ |
2962 | | |
2963 | | /* Total number of MAC-is SDUs */ |
2964 | 0 | proto_tree_add_bits_ret_val(tree, hf_fp_edch_no_macid_sdus, tvb, offset*8+4, |
2965 | 0 | 12, &total_macis_sdus, ENC_BIG_ENDIAN); |
2966 | 0 | offset += 2; |
2967 | |
|
2968 | 0 | if (is_common) { |
2969 | | /* E-RNTI */ |
2970 | 0 | proto_tree_add_item(tree, hf_fp_edch_e_rnti, tvb, offset, 2, ENC_BIG_ENDIAN); |
2971 | 0 | offset += 2; |
2972 | 0 | } |
2973 | |
|
2974 | 0 | bit_offset = offset*8; |
2975 | | /* EDCH subframe header list */ |
2976 | 0 | for (n=0; n < number_of_subframes; n++) { |
2977 | 0 | uint64_t subframe_number; |
2978 | 0 | uint64_t no_of_macis_pdus; |
2979 | 0 | proto_item *subframe_header_ti; |
2980 | 0 | proto_tree *subframe_header_tree; |
2981 | | |
2982 | | /* Add subframe header subtree */ |
2983 | 0 | subframe_header_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe_header, tvb, offset, 0, |
2984 | 0 | "", "Subframe"); |
2985 | 0 | subframe_header_tree = proto_item_add_subtree(subframe_header_ti, ett_fp_edch_subframe_header); |
2986 | | |
2987 | | /* Spare bit */ |
2988 | 0 | bit_offset++; |
2989 | |
|
2990 | 0 | if (!is_common) { |
2991 | | /* Number of HARQ Retransmissions */ |
2992 | 0 | proto_tree_add_item(subframe_header_tree, hf_fp_edch_harq_retransmissions, tvb, |
2993 | 0 | bit_offset/8, 1, ENC_BIG_ENDIAN); |
2994 | 0 | bit_offset += 4; |
2995 | 0 | } |
2996 | | |
2997 | | /* Subframe number */ |
2998 | 0 | proto_tree_add_bits_ret_val(subframe_header_tree, hf_fp_edch_subframe_number, tvb, |
2999 | 0 | bit_offset, 3, &subframe_number, ENC_BIG_ENDIAN); |
3000 | 0 | subframes[n].subframe_number = (uint8_t)subframe_number; |
3001 | 0 | bit_offset += 3; |
3002 | | |
3003 | | /* Number of MAC-is PDUs */ |
3004 | 0 | proto_tree_add_bits_ret_val(subframe_header_tree, hf_fp_edch_number_of_mac_is_pdus, tvb, |
3005 | 0 | bit_offset, 4, &no_of_macis_pdus, ENC_BIG_ENDIAN); |
3006 | 0 | bit_offset += 4; |
3007 | 0 | subframes[n].number_of_mac_is_pdus = (uint8_t)no_of_macis_pdus; |
3008 | | /* macis_pdus += subframes[n].number_of_mac_is_pdus; */ |
3009 | | |
3010 | | /* Next 4 bits are spare for T2*/ |
3011 | 0 | if (!is_common) { |
3012 | 0 | bit_offset += 4; |
3013 | 0 | } |
3014 | | |
3015 | | /* Show summary in root */ |
3016 | 0 | proto_item_append_text(subframe_header_ti, " (SFN %u, %u MAC-is PDUs)", |
3017 | 0 | subframes[n].subframe_number, subframes[n].number_of_mac_is_pdus); |
3018 | 0 | proto_item_set_len(subframe_header_ti, is_common ? 1 : 2); |
3019 | 0 | } |
3020 | 0 | offset = bit_offset / 8; |
3021 | | |
3022 | | |
3023 | | /* MAC-is PDU descriptors for each subframe follow */ |
3024 | 0 | for (n=0; n < number_of_subframes; n++) { |
3025 | 0 | proto_tree *subframe_macis_descriptors_tree; |
3026 | | |
3027 | | /* Add subframe header subtree */ |
3028 | 0 | subframe_macis_descriptors_ti = proto_tree_add_string_format(tree, hf_fp_edch_macis_descriptors, tvb, offset, 0, |
3029 | 0 | "", "MAC-is descriptors (SFN %u)", subframes[n].subframe_number); |
3030 | 0 | proto_item_set_len(subframe_macis_descriptors_ti, subframes[n].number_of_mac_is_pdus*2); |
3031 | 0 | subframe_macis_descriptors_tree = proto_item_add_subtree(subframe_macis_descriptors_ti, |
3032 | 0 | ett_fp_edch_macis_descriptors); |
3033 | | |
3034 | | /* Find a sequence of descriptors for each MAC-is PDU in this subframe */ |
3035 | 0 | for (pdu_no=0; pdu_no < subframes[n].number_of_mac_is_pdus && pdu_no < 16; pdu_no++) { |
3036 | 0 | proto_item *f_ti = NULL; |
3037 | |
|
3038 | 0 | subframes[n].number_of_mac_is_sdus[pdu_no] = 0; |
3039 | |
|
3040 | 0 | do { |
3041 | 0 | if (subframes[n].number_of_mac_is_sdus[pdu_no] == 16) { |
3042 | 0 | expert_add_info_format(pinfo, f_ti, &ei_fp_mac_is_sdus_miscount, "Found too many (%u) MAC-is SDUs - max tracked is 16", macis_sdus_found); |
3043 | 0 | break; |
3044 | 0 | } |
3045 | | |
3046 | | /* Check we haven't gone past the limit */ |
3047 | 0 | if (macis_sdus_found++ > total_macis_sdus) { |
3048 | 0 | expert_add_info_format(pinfo, f_ti, &ei_fp_mac_is_sdus_miscount, "Found too many (%u) MAC-is SDUs - header said there were %u", macis_sdus_found, (uint16_t)total_macis_sdus); |
3049 | 0 | } |
3050 | | |
3051 | | /* LCH-ID */ |
3052 | 0 | subframes[n].mac_is_lchid[pdu_no][subframes[n].number_of_mac_is_sdus[pdu_no]] = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
3053 | 0 | proto_tree_add_item(subframe_macis_descriptors_tree, hf_fp_edch_macis_lchid, tvb, offset, 1, ENC_BIG_ENDIAN); |
3054 | 0 | if (subframes[n].mac_is_lchid[pdu_no][subframes[n].number_of_mac_is_sdus[pdu_no]] == 15) { |
3055 | 0 | proto_item *ti; |
3056 | | |
3057 | | /* 4 bits of spare */ |
3058 | 0 | offset++; |
3059 | | |
3060 | | /* E-RNTI */ |
3061 | 0 | ti = proto_tree_add_item(tree, hf_fp_edch_e_rnti, tvb, offset, 2, ENC_BIG_ENDIAN); |
3062 | 0 | offset += 2; |
3063 | | |
3064 | | /* This is only allowed if: |
3065 | | - it's the common case AND |
3066 | | - it's the first descriptor */ |
3067 | 0 | if (!is_common) { |
3068 | 0 | expert_add_info(pinfo, ti, &ei_fp_e_rnti_t2_edch_frames); |
3069 | 0 | } |
3070 | 0 | if (subframes[n].number_of_mac_is_sdus[pdu_no] > 0) { |
3071 | 0 | expert_add_info(pinfo, ti, &ei_fp_e_rnti_first_entry); |
3072 | 0 | } |
3073 | 0 | continue; |
3074 | 0 | } |
3075 | | |
3076 | | /* Length */ |
3077 | 0 | subframes[n].mac_is_length[pdu_no][subframes[n].number_of_mac_is_sdus[pdu_no]] = (tvb_get_ntohs(tvb, offset) & 0x0ffe) >> 1; |
3078 | 0 | proto_tree_add_item(subframe_macis_descriptors_tree, hf_fp_edch_macis_length, tvb, offset, 2, ENC_BIG_ENDIAN); |
3079 | 0 | offset++; |
3080 | | |
3081 | | /* Flag */ |
3082 | 0 | F = tvb_get_uint8(tvb, offset) & 0x01; |
3083 | 0 | f_ti = proto_tree_add_item(subframe_macis_descriptors_tree, hf_fp_edch_macis_flag, tvb, offset, 1, ENC_BIG_ENDIAN); |
3084 | |
|
3085 | 0 | subframes[n].number_of_mac_is_sdus[pdu_no]++; |
3086 | 0 | offset++; |
3087 | 0 | } while (F == 0); |
3088 | 0 | } |
3089 | 0 | } |
3090 | | |
3091 | | /* Check overall count of MAC-is SDUs */ |
3092 | 0 | if (macis_sdus_found != total_macis_sdus) { |
3093 | 0 | expert_add_info_format(pinfo, subframe_macis_descriptors_ti, &ei_fp_mac_is_sdus_miscount, "Frame contains %u MAC-is SDUs - header said there would be %u!", macis_sdus_found, (uint16_t)total_macis_sdus); |
3094 | 0 | } |
3095 | 0 | header_length = offset; |
3096 | | /* Now PDUs */ |
3097 | 0 | for (n=0; n < number_of_subframes; n++) { |
3098 | | |
3099 | | /* MAC-is PDU */ |
3100 | 0 | for (pdu_no=0; pdu_no < subframes[n].number_of_mac_is_pdus; pdu_no++) { |
3101 | 0 | int i; |
3102 | 0 | unsigned length = 0; |
3103 | 0 | umts_mac_is_info * mac_is_info = wmem_new(wmem_file_scope(), umts_mac_is_info); |
3104 | |
|
3105 | 0 | mac_is_info->number_of_mac_is_sdus = subframes[n].number_of_mac_is_sdus[pdu_no]; |
3106 | 0 | DISSECTOR_ASSERT(subframes[n].number_of_mac_is_sdus[pdu_no] <= MAX_MAC_FRAMES); |
3107 | 0 | for (i = 0; i < subframes[n].number_of_mac_is_sdus[pdu_no]; i++) { |
3108 | 0 | mac_is_info->sdulength[i] = subframes[n].mac_is_length[pdu_no][i]; |
3109 | 0 | mac_is_info->lchid[i] = subframes[n].mac_is_lchid[pdu_no][i]; |
3110 | 0 | length += subframes[n].mac_is_length[pdu_no][i]; |
3111 | 0 | } |
3112 | | |
3113 | | /* Call MAC for this PDU if configured to */ |
3114 | 0 | if (preferences_call_mac_dissectors && data) { |
3115 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, mac_is_info); |
3116 | 0 | call_dissector_with_data(mac_fdd_edch_type2_handle, tvb_new_subset_remaining(tvb, offset), pinfo, top_level_tree, data); |
3117 | 0 | } |
3118 | 0 | else { |
3119 | | /* Still show data if not decoding as MAC PDU */ |
3120 | 0 | proto_tree_add_item(tree, hf_fp_edch_mac_is_pdu, tvb, offset, length, ENC_NA); |
3121 | 0 | } |
3122 | | |
3123 | | /* get_mac_tsn_size in packet-umts_mac.h, gets the global_mac_tsn_size preference in umts_mac.c */ |
3124 | 0 | if (get_mac_tsn_size() == MAC_TSN_14BITS) { |
3125 | 0 | offset += length + 2; /* Plus 2 bytes for TSN 14 bits and SS 2 bit. */ |
3126 | 0 | } else { |
3127 | 0 | offset += length + 1; /* Plus 1 byte for TSN 6 bits and SS 2 bit. */ |
3128 | 0 | } |
3129 | 0 | } |
3130 | 0 | } |
3131 | 0 | if (preferences_header_checksum) { |
3132 | 0 | verify_header_crc_edch(tvb, pinfo, header_crc_pi, header_crc, header_length); |
3133 | 0 | } |
3134 | | /* Spare extension and payload CRC (optional) */ |
3135 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, |
3136 | 0 | p_fp_info->dch_crc_present, offset, header_length); |
3137 | 0 | } |
3138 | | |
3139 | | |
3140 | | |
3141 | | /**********************************************************/ |
3142 | | /* Dissect an HSDSCH channel */ |
3143 | | /* The data format corresponds to the format */ |
3144 | | /* described in R5 and R6, and frame type 1 in Release 7. */ |
3145 | | static void |
3146 | | dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
3147 | | unsigned offset, struct fp_info *p_fp_info, void *data) |
3148 | 0 | { |
3149 | 0 | uint32_t ft; |
3150 | 0 | unsigned header_length; |
3151 | 0 | uint32_t header_crc = 0; |
3152 | 0 | proto_item * header_crc_pi = NULL; |
3153 | | |
3154 | | /* Header CRC */ |
3155 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
3156 | | |
3157 | | /* Frame Type */ |
3158 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
3159 | 0 | offset++; |
3160 | |
|
3161 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
3162 | |
|
3163 | 0 | if (ft == FT_CONTROL) { |
3164 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
3165 | | /* For control frame the header CRC is actually frame CRC covering all |
3166 | | * bytes except the first */ |
3167 | 0 | if (preferences_header_checksum) { |
3168 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
3169 | 0 | } |
3170 | 0 | } |
3171 | 0 | else { |
3172 | 0 | uint8_t number_of_pdus; |
3173 | 0 | uint16_t pdu_length; |
3174 | 0 | uint16_t user_buffer_size; |
3175 | 0 | int i; |
3176 | 0 | umts_mac_info *macinf; |
3177 | 0 | rlc_info *rlcinf; |
3178 | 0 | uint32_t user_identity; |
3179 | 0 | proto_item *item; |
3180 | |
|
3181 | 0 | rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0); |
3182 | 0 | if (!rlcinf) { |
3183 | 0 | rlcinf = wmem_new0(pinfo->pool, rlc_info); |
3184 | 0 | } |
3185 | 0 | macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0); |
3186 | 0 | if (!macinf) { |
3187 | 0 | macinf = wmem_new0(pinfo->pool, umts_mac_info); |
3188 | 0 | } |
3189 | | |
3190 | | /**************************************/ |
3191 | | /* HS-DCH data here (type 1 in R7) */ |
3192 | | |
3193 | | /* Frame Seq Nr */ |
3194 | 0 | if ((p_fp_info->release == 6) || |
3195 | 0 | (p_fp_info->release == 7)) { |
3196 | |
|
3197 | 0 | uint8_t frame_seq_no = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
3198 | 0 | proto_tree_add_item(tree, hf_fp_frame_seq_nr, tvb, offset, 1, ENC_BIG_ENDIAN); |
3199 | |
|
3200 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " seqno=%u", frame_seq_no); |
3201 | 0 | } |
3202 | | |
3203 | | /* CmCH-PI */ |
3204 | 0 | proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
3205 | 0 | offset++; |
3206 | | |
3207 | | /* MAC-d PDU Length (13 bits) */ |
3208 | 0 | pdu_length = (tvb_get_ntohs(tvb, offset) >> 3); |
3209 | 0 | proto_tree_add_item(tree, hf_fp_mac_d_pdu_len, tvb, offset, 2, ENC_BIG_ENDIAN); |
3210 | 0 | offset += 2; |
3211 | 0 | macinf->pdu_len = pdu_length; |
3212 | |
|
3213 | 0 | if ((p_fp_info->release == 6) || |
3214 | 0 | (p_fp_info->release == 7)) { |
3215 | | |
3216 | | /* Flush bit */ |
3217 | 0 | proto_tree_add_item(tree, hf_fp_flush, tvb, offset-1, 1, ENC_BIG_ENDIAN); |
3218 | | |
3219 | | /* FSN/DRT reset bit */ |
3220 | 0 | proto_tree_add_item(tree, hf_fp_fsn_drt_reset, tvb, offset-1, 1, ENC_BIG_ENDIAN); |
3221 | 0 | } |
3222 | | |
3223 | | /* Num of PDUs */ |
3224 | 0 | item = proto_tree_add_item_ret_uint8(tree, hf_fp_num_of_pdu, tvb, offset, 1, ENC_BIG_ENDIAN, &number_of_pdus); |
3225 | 0 | offset++; |
3226 | 0 | if (number_of_pdus > MAX_MAC_FRAMES) { |
3227 | 0 | expert_add_info_format(pinfo, item, &ei_fp_invalid_frame_count, "Invalid number of PDUs (max is %u)", MAX_MAC_FRAMES); |
3228 | 0 | return; |
3229 | 0 | } |
3230 | | |
3231 | | /* User buffer size */ |
3232 | 0 | proto_tree_add_item_ret_uint16(tree, hf_fp_user_buffer_size, tvb, offset, 2, ENC_BIG_ENDIAN, &user_buffer_size); |
3233 | 0 | offset += 2; |
3234 | |
|
3235 | 0 | header_length = offset; |
3236 | | |
3237 | | |
3238 | | /* Determine the UE ID to use in RLC */ |
3239 | 0 | user_identity = p_fp_info->com_context_id; |
3240 | 0 | if(p_fp_info->urnti) { |
3241 | 0 | user_identity = p_fp_info->urnti; |
3242 | 0 | } |
3243 | | /************************/ |
3244 | | /*Configure the pdus*/ |
3245 | 0 | for (i=0;i<number_of_pdus && i<MIN(MAX_MAC_FRAMES, MAX_RLC_CHANS); i++) { |
3246 | 0 | macinf->content[i] = hsdsch_macdflow_id_mac_content_map[p_fp_info->hsdsch_macflowd_id]; /*MAC_CONTENT_PS_DTCH;*/ |
3247 | 0 | macinf->lchid[i] = fake_lchid_macd_flow[p_fp_info->hsdsch_macflowd_id];/*Faked logical channel id 255 used as a mark if it doesn't exist...*/ |
3248 | 0 | macinf->fake_chid[i] = true; /**/ |
3249 | 0 | macinf->macdflow_id[i] = p_fp_info->hsdsch_macflowd_id; /*Save the flow ID (+1 to make it human readable (it's zero indexed!))*/ |
3250 | | |
3251 | | /*Check if this is multiplexed (signaled by RRC)*/ |
3252 | 0 | if (p_fp_info->hsdhsch_macfdlow_is_mux[p_fp_info->hsdsch_macflowd_id] ) { |
3253 | 0 | macinf->ctmux[i] = true; |
3254 | 0 | } else if (p_fp_info->hsdsch_macflowd_id == 0) { /*MACd-flow = 0 is often SRB */ |
3255 | 0 | expert_add_info(pinfo, NULL, &ei_fp_maybe_srb); |
3256 | 0 | } else { |
3257 | 0 | macinf->ctmux[i] = false; /*Either it's multiplexed and not signalled or it's not MUX*/ |
3258 | 0 | } |
3259 | | |
3260 | | /* Figure out RLC mode */ |
3261 | 0 | if(p_fp_info->hsdsch_rlc_mode != FP_RLC_MODE_UNKNOWN) { |
3262 | | /* We know the RLC mode, possibly reported from NBAP */ |
3263 | 0 | rlcinf->mode[i] = (enum rlc_mode)(p_fp_info->hsdsch_rlc_mode - 1); |
3264 | 0 | } |
3265 | 0 | else { |
3266 | | /* Guess the mode by the MACd-flow-ID, basically MACd-flow-ID = 0 then it's SRB0 == UM else AM */ |
3267 | | /* This logic might be incorrect sometimes */ |
3268 | 0 | rlcinf->mode[i] = hsdsch_macdflow_id_rlc_map[p_fp_info->hsdsch_macflowd_id]; |
3269 | 0 | } |
3270 | |
|
3271 | 0 | rlcinf->ueid[i] = user_identity; |
3272 | 0 | rlcinf->li_size[i] = RLC_LI_7BITS; |
3273 | 0 | rlcinf->deciphered[i] = false; |
3274 | 0 | rlcinf->ciphered[i] = false; |
3275 | 0 | rlcinf->rbid[i] = macinf->lchid[i]; |
3276 | |
|
3277 | | #if 0 |
3278 | | /*When a flow has been reconfigured rlc needs to be reset. |
3279 | | * This needs more work though since we must figure out when the re-configuration becomes |
3280 | | * active based on the CFN value |
3281 | | * */ |
3282 | | /*Indicate we need to reset stream*/ |
3283 | | if (p_fp_info->reset_frag) { |
3284 | | rlc_reset_channel(rlcinf->mode[i], macinf->lchid[i], p_fp_info->is_uplink, rlcinf->ueid[i] ); |
3285 | | p_fp_info->reset_frag = false; |
3286 | | |
3287 | | } |
3288 | | #endif |
3289 | 0 | } |
3290 | |
|
3291 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " %ux%u-bit PDUs User-Buffer-Size=%u", |
3292 | 0 | number_of_pdus, pdu_length, user_buffer_size); |
3293 | | |
3294 | | /* MAC-d PDUs */ |
3295 | 0 | offset = dissect_macd_pdu_data(tvb, pinfo, tree, offset, pdu_length, |
3296 | 0 | number_of_pdus, p_fp_info, data); |
3297 | | |
3298 | | /* Extra IEs (if there is room for them) */ |
3299 | 0 | if (((p_fp_info->release == 6) || |
3300 | 0 | (p_fp_info->release == 7)) && |
3301 | 0 | (tvb_reported_length_remaining(tvb, offset) > 2)) { |
3302 | |
|
3303 | 0 | int n; |
3304 | 0 | uint8_t flags; |
3305 | | /* uint8_t flag_bytes = 0; */ |
3306 | | |
3307 | | /* New IE flags */ |
3308 | 0 | do { |
3309 | 0 | proto_item *new_ie_flags_ti; |
3310 | 0 | proto_tree *new_ie_flags_tree; |
3311 | 0 | unsigned ies_found = 0; |
3312 | | |
3313 | | /* Add new IE flags subtree */ |
3314 | 0 | new_ie_flags_ti = proto_tree_add_string_format(tree, hf_fp_hsdsch_new_ie_flags, tvb, offset, 1, |
3315 | 0 | "", "New IE flags"); |
3316 | 0 | new_ie_flags_tree = proto_item_add_subtree(new_ie_flags_ti, ett_fp_hsdsch_new_ie_flags); |
3317 | | |
3318 | | /* Read next byte */ |
3319 | 0 | flags = tvb_get_uint8(tvb, offset); |
3320 | | /* flag_bytes++; */ |
3321 | | |
3322 | | /* Dissect individual bits */ |
3323 | 0 | for (n=0; n < 8; n++) { |
3324 | 0 | proto_tree_add_item(new_ie_flags_tree, hf_fp_hsdsch_new_ie_flag[n], tvb, offset, 1, ENC_BIG_ENDIAN); |
3325 | 0 | if ((flags >> (7-n)) & 0x01) { |
3326 | 0 | ies_found++; |
3327 | 0 | } |
3328 | 0 | } |
3329 | 0 | offset++; |
3330 | |
|
3331 | 0 | proto_item_append_text(new_ie_flags_ti, " (%u IEs found)", ies_found); |
3332 | | |
3333 | | /* Last bit set will indicate another flags byte follows... */ |
3334 | 0 | } while (0); /*((flags & 0x01) && (flag_bytes < 31));*/ |
3335 | |
|
3336 | 0 | if (1) /*(flags & 0x8) */ { |
3337 | | /* DRT is shown as mandatory in the diagram (3GPP TS 25.435 V6.3.0), |
3338 | | but the description below it states that |
3339 | | it should depend upon the first bit. The detailed description of |
3340 | | New IE flags doesn't agree, so treat as mandatory for now... */ |
3341 | 0 | proto_tree_add_item(tree, hf_fp_hsdsch_drt, tvb, offset, 2, ENC_BIG_ENDIAN); |
3342 | 0 | offset += 2; |
3343 | 0 | } |
3344 | 0 | } |
3345 | 0 | if (preferences_header_checksum) { |
3346 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
3347 | 0 | } |
3348 | | /* Spare Extension and Payload CRC */ |
3349 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
3350 | 0 | } |
3351 | 0 | } |
3352 | | |
3353 | | |
3354 | | /******************************************/ |
3355 | | /* Dissect an HSDSCH type 2 channel */ |
3356 | | /* (introduced in Release 7) */ |
3357 | | /* N.B. there is currently no support for */ |
3358 | | /* frame type 3 (IuR only?) */ |
3359 | | static void |
3360 | | dissect_hsdsch_type_2_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
3361 | | unsigned offset, struct fp_info *p_fp_info, |
3362 | | void *data) |
3363 | 0 | { |
3364 | 0 | uint32_t ft; |
3365 | 0 | uint32_t header_crc = 0; |
3366 | 0 | proto_item * header_crc_pi = NULL; |
3367 | 0 | uint16_t header_length; |
3368 | | |
3369 | | /* Header CRC */ |
3370 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
3371 | | |
3372 | | /* Frame Type */ |
3373 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
3374 | 0 | offset++; |
3375 | |
|
3376 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
3377 | |
|
3378 | 0 | if (ft == FT_CONTROL) { |
3379 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
3380 | | /* For control frame the header CRC is actually frame CRC covering all |
3381 | | * bytes except the first */ |
3382 | 0 | if (preferences_header_checksum) { |
3383 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
3384 | 0 | } |
3385 | 0 | } |
3386 | 0 | else { |
3387 | 0 | uint8_t number_of_pdu_blocks; |
3388 | 0 | bool drt_present = false; |
3389 | 0 | bool fach_present = false; |
3390 | 0 | uint16_t user_buffer_size; |
3391 | 0 | int n; |
3392 | 0 | unsigned j; |
3393 | 0 | uint64_t lchid_val; |
3394 | |
|
3395 | 0 | #define MAX_PDU_BLOCKS 31 |
3396 | 0 | uint64_t lchid_field[MAX_PDU_BLOCKS]; |
3397 | 0 | uint64_t pdu_length[MAX_PDU_BLOCKS]; |
3398 | 0 | uint64_t no_of_pdus[MAX_PDU_BLOCKS]; |
3399 | |
|
3400 | 0 | umts_mac_info *macinf; |
3401 | 0 | rlc_info *rlcinf; |
3402 | 0 | uint32_t user_identity; |
3403 | |
|
3404 | 0 | rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0); |
3405 | 0 | if (!rlcinf) { |
3406 | 0 | rlcinf = wmem_new0(pinfo->pool, rlc_info); |
3407 | 0 | } |
3408 | 0 | macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0); |
3409 | 0 | if (!macinf) { |
3410 | 0 | macinf = wmem_new0(pinfo->pool, umts_mac_info); |
3411 | 0 | } |
3412 | | |
3413 | | /********************************/ |
3414 | | /* HS-DCH type 2 data here */ |
3415 | |
|
3416 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "(ehs)"); |
3417 | | |
3418 | | /* Frame Seq Nr (4 bits) */ |
3419 | 0 | if ((p_fp_info->release == 6) || |
3420 | 0 | (p_fp_info->release == 7)) { |
3421 | |
|
3422 | 0 | uint8_t frame_seq_no = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
3423 | 0 | proto_tree_add_item(tree, hf_fp_frame_seq_nr, tvb, offset, 1, ENC_BIG_ENDIAN); |
3424 | |
|
3425 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " seqno=%u", frame_seq_no); |
3426 | 0 | } |
3427 | | |
3428 | | /* CmCH-PI (4 bits) */ |
3429 | 0 | proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
3430 | 0 | offset++; |
3431 | | |
3432 | | /* Total number of PDU blocks (5 bits) */ |
3433 | 0 | number_of_pdu_blocks = (tvb_get_uint8(tvb, offset) >> 3); |
3434 | 0 | proto_tree_add_item(tree, hf_fp_total_pdu_blocks, tvb, offset, 1, ENC_BIG_ENDIAN); |
3435 | |
|
3436 | 0 | if (p_fp_info->release == 7) { |
3437 | | /* Flush bit */ |
3438 | 0 | proto_tree_add_item(tree, hf_fp_flush, tvb, offset, 1, ENC_BIG_ENDIAN); |
3439 | | |
3440 | | /* FSN/DRT reset bit */ |
3441 | 0 | proto_tree_add_item(tree, hf_fp_fsn_drt_reset, tvb, offset, 1, ENC_BIG_ENDIAN); |
3442 | | |
3443 | | /* DRT Indicator */ |
3444 | 0 | drt_present = tvb_get_uint8(tvb, offset) & 0x01; |
3445 | 0 | proto_tree_add_item(tree, hf_fp_drt_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); |
3446 | 0 | } |
3447 | 0 | offset++; |
3448 | | |
3449 | | /* FACH Indicator flag */ |
3450 | 0 | fach_present = (tvb_get_uint8(tvb, offset) & 0x80) >> 7; |
3451 | 0 | proto_tree_add_item(tree, hf_fp_fach_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); |
3452 | 0 | offset++; |
3453 | | |
3454 | | /* User buffer size */ |
3455 | 0 | proto_tree_add_item_ret_uint16(tree, hf_fp_user_buffer_size, tvb, offset, 2, ENC_BIG_ENDIAN, &user_buffer_size); |
3456 | 0 | offset += 2; |
3457 | |
|
3458 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " User-Buffer-Size=%u", user_buffer_size); |
3459 | | |
3460 | | |
3461 | | |
3462 | | /********************************************************************/ |
3463 | | /* Now read number_of_pdu_blocks header entries */ |
3464 | 0 | for (n=0; n < number_of_pdu_blocks; n++) { |
3465 | 0 | proto_item *pdu_block_header_ti; |
3466 | 0 | proto_tree *pdu_block_header_tree; |
3467 | 0 | int block_header_start_offset = offset; |
3468 | | |
3469 | | /* Add PDU block header subtree */ |
3470 | 0 | pdu_block_header_ti = proto_tree_add_string_format(tree, hf_fp_hsdsch_pdu_block_header, |
3471 | 0 | tvb, offset, 0, |
3472 | 0 | "", |
3473 | 0 | "PDU Block Header"); |
3474 | 0 | pdu_block_header_tree = proto_item_add_subtree(pdu_block_header_ti, |
3475 | 0 | ett_fp_hsdsch_pdu_block_header); |
3476 | | |
3477 | | /* MAC-d/c PDU length in this block (11 bits) */ |
3478 | 0 | proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_pdu_length_in_block, tvb, |
3479 | 0 | (offset*8) + ((n % 2) ? 4 : 0), 11, |
3480 | 0 | &pdu_length[n], ENC_BIG_ENDIAN); |
3481 | 0 | if ((n % 2) == 0) |
3482 | 0 | offset++; |
3483 | 0 | else |
3484 | 0 | offset += 2; |
3485 | | |
3486 | | |
3487 | | /* # PDUs in this block (4 bits) */ |
3488 | 0 | proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_pdus_in_block, tvb, |
3489 | 0 | (offset*8) + ((n % 2) ? 0 : 4), 4, |
3490 | 0 | &no_of_pdus[n], ENC_BIG_ENDIAN); |
3491 | 0 | if ((n % 2) == 0) { |
3492 | 0 | offset++; |
3493 | 0 | } |
3494 | | |
3495 | | /* Logical channel ID in block (4 bits) */ |
3496 | 0 | proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_lchid, tvb, |
3497 | 0 | (offset*8) + ((n % 2) ? 4 : 0), 4, |
3498 | 0 | &lchid_field[n], ENC_BIG_ENDIAN); |
3499 | 0 | if ((n % 2) == 1) { |
3500 | 0 | offset++; |
3501 | 0 | } |
3502 | 0 | else { |
3503 | 0 | if (n == (number_of_pdu_blocks-1)) { |
3504 | | /* Byte is padded out for last block */ |
3505 | 0 | offset++; |
3506 | 0 | } |
3507 | 0 | } |
3508 | | |
3509 | | /* Append summary to header tree root */ |
3510 | 0 | proto_item_append_text(pdu_block_header_ti, |
3511 | 0 | " (lch:%u, %u pdus of %u bytes)", |
3512 | 0 | (uint16_t)lchid_field[n], |
3513 | 0 | (uint16_t)no_of_pdus[n], |
3514 | 0 | (uint16_t)pdu_length[n]); |
3515 | | |
3516 | | /* Set length of header tree item */ |
3517 | 0 | if (((n % 2) == 0) && (n < (number_of_pdu_blocks-1))) { |
3518 | 0 | proto_item_set_len(pdu_block_header_ti, |
3519 | 0 | offset - block_header_start_offset+1); |
3520 | 0 | } |
3521 | 0 | else { |
3522 | 0 | proto_item_set_len(pdu_block_header_ti, |
3523 | 0 | offset - block_header_start_offset); |
3524 | 0 | } |
3525 | 0 | } |
3526 | |
|
3527 | 0 | header_length = offset; |
3528 | | |
3529 | | /**********************************************/ |
3530 | | /* Optional fields indicated by earlier flags */ |
3531 | 0 | if (drt_present) { |
3532 | | /* DRT */ |
3533 | 0 | proto_tree_add_item(tree, hf_fp_drt, tvb, offset, 2, ENC_BIG_ENDIAN); |
3534 | 0 | offset += 2; |
3535 | 0 | } |
3536 | |
|
3537 | 0 | if (fach_present) { |
3538 | | /* H-RNTI: */ |
3539 | 0 | proto_tree_add_item(tree, hf_fp_hrnti, tvb, offset, 2, ENC_BIG_ENDIAN); |
3540 | 0 | offset += 2; |
3541 | | |
3542 | | /* RACH Measurement Result */ |
3543 | 0 | proto_tree_add_item(tree, hf_fp_rach_measurement_result, tvb, offset, 2, ENC_BIG_ENDIAN); |
3544 | 0 | offset++; |
3545 | 0 | } |
3546 | | |
3547 | | |
3548 | | /* Determine the UE ID to use in RLC */ |
3549 | 0 | user_identity = p_fp_info->com_context_id; |
3550 | 0 | if(p_fp_info->urnti) { |
3551 | 0 | user_identity = p_fp_info->urnti; |
3552 | 0 | } |
3553 | | /********************************************************************/ |
3554 | | /* Now read the MAC-d/c PDUs for each block using info from headers */ |
3555 | 0 | for (n=0; n < number_of_pdu_blocks; n++) { |
3556 | 0 | for (j=0;j<no_of_pdus[n];j++) { |
3557 | | |
3558 | | /*Configure (signal to lower layers) the PDU!*/ |
3559 | 0 | if (lchid_field[n] != 0x0f) { |
3560 | 0 | lchid_val = lchid_field[n] + 1; /* Add 1 since 'LCHID' field is zero indexed. ie field value = 0 => Actual L-CHID = 1*/ |
3561 | 0 | macinf->content[j] = lchId_type_table[lchid_val]; |
3562 | 0 | macinf->lchid[j] = (uint8_t)lchid_val; |
3563 | 0 | macinf->macdflow_id[j] = p_fp_info->hsdsch_macflowd_id; |
3564 | | /*Figure out RLC_MODE based on MACd-flow-ID, basically MACd-flow-ID = 0 then it's SRB0 == UM else AM*/ |
3565 | 0 | rlcinf->mode[j] = lchId_rlc_map[lchid_val]; |
3566 | |
|
3567 | 0 | macinf->ctmux[n] = false; |
3568 | |
|
3569 | 0 | rlcinf->li_size[j] = RLC_LI_7BITS; |
3570 | 0 | rlcinf->ciphered[j] = false; |
3571 | 0 | rlcinf->deciphered[j] = false; |
3572 | 0 | rlcinf->rbid[j] = (uint8_t)lchid_val; |
3573 | |
|
3574 | 0 | rlcinf->ueid[j] = user_identity; |
3575 | 0 | } |
3576 | 0 | else { |
3577 | | /* LCHID field is 15. This value indicates BCCH or PCCH mapped on HS-DSCH*/ |
3578 | | /* The dissector does not handle this case yet, so we are filling zeroes and default values below*/ |
3579 | 0 | macinf->content[j] = MAC_CONTENT_UNKNOWN; |
3580 | 0 | macinf->lchid[j] = 0; /* LCHID field doesn't reflect a real ID in this case*/ |
3581 | 0 | macinf->macdflow_id[j] = 0; |
3582 | 0 | macinf->ctmux[j] = false; |
3583 | |
|
3584 | 0 | rlcinf->mode[j] = RLC_TM; /* PCCH and BCCH should be using RLC TM? */ |
3585 | 0 | rlcinf->li_size[j] = RLC_LI_7BITS; |
3586 | 0 | rlcinf->ciphered[j] = false; |
3587 | 0 | rlcinf->deciphered[j] = false; |
3588 | 0 | rlcinf->rbid[j] = 0; |
3589 | 0 | rlcinf->ueid[j] = 0; |
3590 | 0 | } |
3591 | 0 | } |
3592 | | |
3593 | | /* Add PDU block header subtree */ |
3594 | 0 | offset = dissect_macd_pdu_data_type_2(tvb, pinfo, tree, offset, |
3595 | 0 | (uint16_t)pdu_length[n], |
3596 | 0 | (uint16_t)no_of_pdus[n], |
3597 | 0 | p_fp_info, data); |
3598 | 0 | } |
3599 | 0 | if (preferences_header_checksum) { |
3600 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
3601 | 0 | } |
3602 | | /* Spare Extension and Payload CRC */ |
3603 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
3604 | 0 | } |
3605 | 0 | } |
3606 | | /** |
3607 | | * Dissect and CONFIGURE hsdsch_common channel. |
3608 | | * |
3609 | | * This will dissect hsdsch common channels of type 2, so this is |
3610 | | * very similar to regular type two (ehs) the difference being how |
3611 | | * the configuration is done. NOTE: VERY EXPERIMENTAL. |
3612 | | * |
3613 | | * @param tvb the tv buffer of the current data |
3614 | | * @param pinfo the packet info of the current data |
3615 | | * @param tree the tree to append this item to |
3616 | | * @param offset the offset in the tvb |
3617 | | * @param p_fp_info FP-packet information |
3618 | | */ |
3619 | | static |
3620 | | void dissect_hsdsch_common_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, |
3621 | | unsigned offset, struct fp_info *p_fp_info, |
3622 | | void *data) |
3623 | 0 | { |
3624 | 0 | uint32_t ft; |
3625 | 0 | uint32_t header_crc = 0; |
3626 | 0 | proto_item * header_crc_pi = NULL; |
3627 | 0 | unsigned header_length; |
3628 | | |
3629 | | /* Header CRC */ |
3630 | 0 | header_crc_pi = proto_tree_add_item_ret_uint(tree, hf_fp_header_crc, tvb, offset, 1, ENC_BIG_ENDIAN, &header_crc); |
3631 | | |
3632 | | /* Frame Type */ |
3633 | 0 | proto_tree_add_item_ret_uint(tree, hf_fp_ft, tvb, offset, 1, ENC_BIG_ENDIAN, &ft); |
3634 | 0 | offset++; |
3635 | |
|
3636 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s] ", val_to_str_const(ft, frame_type_vals, "Unknown")); |
3637 | |
|
3638 | 0 | if (ft == FT_CONTROL) { |
3639 | 0 | dissect_common_control(tvb, pinfo, tree, offset, p_fp_info); |
3640 | | /* For control frame the header CRC is actually frame CRC covering all |
3641 | | * bytes except the first */ |
3642 | 0 | if (preferences_header_checksum) { |
3643 | 0 | verify_control_frame_crc(tvb, pinfo, header_crc_pi, (uint16_t)header_crc); |
3644 | 0 | } |
3645 | 0 | } |
3646 | 0 | else { |
3647 | 0 | uint8_t number_of_pdu_blocks; |
3648 | 0 | bool drt_present = false; |
3649 | 0 | bool fach_present = false; |
3650 | 0 | uint16_t user_buffer_size; |
3651 | 0 | int n; |
3652 | 0 | unsigned j; |
3653 | |
|
3654 | 0 | #define MAX_PDU_BLOCKS 31 |
3655 | 0 | uint64_t lchid[MAX_PDU_BLOCKS]; |
3656 | 0 | uint64_t pdu_length[MAX_PDU_BLOCKS]; |
3657 | 0 | uint64_t no_of_pdus[MAX_PDU_BLOCKS]; |
3658 | 0 | uint8_t newieflags = 0; |
3659 | |
|
3660 | 0 | umts_mac_info *macinf; |
3661 | 0 | rlc_info *rlcinf; |
3662 | |
|
3663 | 0 | rlcinf = (rlc_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0); |
3664 | 0 | if (!rlcinf) { |
3665 | 0 | rlcinf = wmem_new0(pinfo->pool, rlc_info); |
3666 | 0 | } |
3667 | 0 | macinf = (umts_mac_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0); |
3668 | 0 | if (!macinf) { |
3669 | 0 | macinf = wmem_new0(pinfo->pool, umts_mac_info); |
3670 | 0 | } |
3671 | | /********************************/ |
3672 | | /* HS-DCH type 2 data here */ |
3673 | |
|
3674 | 0 | col_append_str(pinfo->cinfo, COL_INFO, "(ehs)"); |
3675 | | |
3676 | | /* Frame Seq Nr (4 bits) */ |
3677 | 0 | if ((p_fp_info->release == 6) || |
3678 | 0 | (p_fp_info->release == 7)) { |
3679 | |
|
3680 | 0 | uint8_t frame_seq_no = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
3681 | 0 | proto_tree_add_item(tree, hf_fp_frame_seq_nr, tvb, offset, 1, ENC_BIG_ENDIAN); |
3682 | |
|
3683 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " seqno=%u", frame_seq_no); |
3684 | 0 | } |
3685 | | |
3686 | | /* CmCH-PI (4 bits) */ |
3687 | 0 | proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, ENC_BIG_ENDIAN); |
3688 | 0 | offset++; |
3689 | | |
3690 | | /* Total number of PDU blocks (5 bits) */ |
3691 | 0 | number_of_pdu_blocks = (tvb_get_uint8(tvb, offset) >> 3); |
3692 | 0 | proto_tree_add_item(tree, hf_fp_total_pdu_blocks, tvb, offset, 1, ENC_BIG_ENDIAN); |
3693 | |
|
3694 | 0 | if (p_fp_info->release == 7) { |
3695 | | /* Flush bit */ |
3696 | 0 | proto_tree_add_item(tree, hf_fp_flush, tvb, offset, 1, ENC_BIG_ENDIAN); |
3697 | | |
3698 | | /* FSN/DRT reset bit */ |
3699 | 0 | proto_tree_add_item(tree, hf_fp_fsn_drt_reset, tvb, offset, 1, ENC_BIG_ENDIAN); |
3700 | | |
3701 | | /* DRT Indicator */ |
3702 | 0 | drt_present = tvb_get_uint8(tvb, offset) & 0x01; |
3703 | 0 | proto_tree_add_item(tree, hf_fp_drt_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); |
3704 | 0 | } |
3705 | 0 | offset++; |
3706 | | |
3707 | | /* FACH Indicator flag */ |
3708 | 0 | fach_present = (tvb_get_uint8(tvb, offset) & 0x80) >> 7; |
3709 | 0 | proto_tree_add_item(tree, hf_fp_fach_indicator, tvb, offset, 1, ENC_BIG_ENDIAN); |
3710 | 0 | offset++; |
3711 | | |
3712 | | /* User buffer size */ |
3713 | 0 | proto_tree_add_item_ret_uint16(tree, hf_fp_user_buffer_size, tvb, offset, 2, ENC_BIG_ENDIAN, &user_buffer_size); |
3714 | 0 | offset += 2; |
3715 | |
|
3716 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " User-Buffer-Size=%u", user_buffer_size); |
3717 | | |
3718 | | |
3719 | | /********************************************************************/ |
3720 | | /* Now read number_of_pdu_blocks header entries */ |
3721 | 0 | for (n=0; n < number_of_pdu_blocks; n++) { |
3722 | 0 | proto_item *pdu_block_header_ti; |
3723 | 0 | proto_item *item; |
3724 | 0 | proto_tree *pdu_block_header_tree; |
3725 | 0 | int block_header_start_offset = offset; |
3726 | | |
3727 | | /* Add PDU block header subtree */ |
3728 | 0 | pdu_block_header_ti = proto_tree_add_string_format(tree, hf_fp_hsdsch_pdu_block_header, |
3729 | 0 | tvb, offset, 0, |
3730 | 0 | "", |
3731 | 0 | "PDU Block Header"); |
3732 | 0 | pdu_block_header_tree = proto_item_add_subtree(pdu_block_header_ti, |
3733 | 0 | ett_fp_hsdsch_pdu_block_header); |
3734 | | |
3735 | | /* MAC-d/c PDU length in this block (11 bits) */ |
3736 | 0 | proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_pdu_length_in_block, tvb, |
3737 | 0 | (offset*8) + ((n % 2) ? 4 : 0), 11, |
3738 | 0 | &pdu_length[n], ENC_BIG_ENDIAN); |
3739 | 0 | if ((n % 2) == 0) |
3740 | 0 | offset++; |
3741 | 0 | else |
3742 | 0 | offset += 2; |
3743 | | |
3744 | | |
3745 | | /* # PDUs in this block (4 bits) */ |
3746 | 0 | item = proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_pdus_in_block, tvb, |
3747 | 0 | (offset*8) + ((n % 2) ? 0 : 4), 4, |
3748 | 0 | &no_of_pdus[n], ENC_BIG_ENDIAN); |
3749 | 0 | if ((n % 2) == 0) { |
3750 | 0 | offset++; |
3751 | 0 | } |
3752 | 0 | if (no_of_pdus[n] > MAX_MAC_FRAMES) { |
3753 | 0 | expert_add_info_format(pinfo, item, &ei_fp_invalid_frame_count, "Invalid number of PDUs (max is %u)", MAX_MAC_FRAMES); |
3754 | 0 | return; |
3755 | 0 | } |
3756 | | |
3757 | | /* Logical channel ID in block (4 bits) */ |
3758 | 0 | proto_tree_add_bits_ret_val(pdu_block_header_tree, hf_fp_lchid, tvb, |
3759 | 0 | (offset*8) + ((n % 2) ? 4 : 0), 4, |
3760 | 0 | &lchid[n], ENC_BIG_ENDIAN); |
3761 | 0 | if ((n % 2) == 1) { |
3762 | 0 | offset++; |
3763 | 0 | } |
3764 | 0 | else { |
3765 | 0 | if (n == (number_of_pdu_blocks-1)) { |
3766 | | /* Byte is padded out for last block */ |
3767 | 0 | offset++; |
3768 | 0 | } |
3769 | 0 | } |
3770 | | |
3771 | | /* Append summary to header tree root */ |
3772 | 0 | proto_item_append_text(pdu_block_header_ti, |
3773 | 0 | " (lch:%u, %u pdus of %u bytes)", |
3774 | 0 | (uint16_t)lchid[n], |
3775 | 0 | (uint16_t)no_of_pdus[n], |
3776 | 0 | (uint16_t)pdu_length[n]); |
3777 | | |
3778 | | /* Set length of header tree item */ |
3779 | 0 | if (((n % 2) == 0) && (n < (number_of_pdu_blocks-1))) { |
3780 | 0 | proto_item_set_len(pdu_block_header_ti, |
3781 | 0 | offset - block_header_start_offset+1); |
3782 | 0 | } |
3783 | 0 | else { |
3784 | 0 | proto_item_set_len(pdu_block_header_ti, |
3785 | 0 | offset - block_header_start_offset); |
3786 | 0 | } |
3787 | 0 | } |
3788 | | |
3789 | 0 | header_length = offset; |
3790 | | |
3791 | | /**********************************************/ |
3792 | | /* Optional fields indicated by earlier flags */ |
3793 | 0 | if (drt_present) { |
3794 | | /* DRT */ |
3795 | 0 | proto_tree_add_item(tree, hf_fp_drt, tvb, offset, 2, ENC_BIG_ENDIAN); |
3796 | 0 | offset += 2; |
3797 | 0 | } |
3798 | |
|
3799 | 0 | if (fach_present) { |
3800 | | /* H-RNTI: */ |
3801 | 0 | proto_tree_add_item(tree, hf_fp_hrnti, tvb, offset, 2, ENC_BIG_ENDIAN); |
3802 | 0 | offset += 2; |
3803 | | |
3804 | | /* RACH Measurement Result */ |
3805 | 0 | proto_tree_add_item(tree, hf_fp_rach_measurement_result, tvb, offset, 1, ENC_BIG_ENDIAN); |
3806 | 0 | offset++; |
3807 | 0 | } |
3808 | | |
3809 | | /********************************************************************/ |
3810 | | /* Now read the MAC-d/c PDUs for each block using info from headers */ |
3811 | 0 | for (n=0; n < number_of_pdu_blocks; n++) { |
3812 | 0 | tvbuff_t *next_tvb; |
3813 | 0 | for (j=0; j<no_of_pdus[n]; j++) { |
3814 | | /* If all bits are set, then this is BCCH or PCCH according to: 25.435 paragraph: 6.2.7.31 */ |
3815 | 0 | if (lchid[n] == 0xF) { |
3816 | | /* In the very few test cases I've seen, this seems to be |
3817 | | * BCCH with transparent MAC layer. Therefore skip right to |
3818 | | * rlc_bcch and hope for the best. */ |
3819 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, (int)pdu_length[n]); |
3820 | 0 | call_dissector_with_data(rlc_bcch_handle, next_tvb, pinfo, top_level_tree, data); |
3821 | 0 | offset += (int)pdu_length[n]; |
3822 | 0 | } else { /* Else go for CCCH UM, this seems to work. */ |
3823 | 0 | p_fp_info->hsdsch_entity = ehs; /* HSDSCH type 2 */ |
3824 | 0 | if (j >= MAX_MAC_FRAMES) { |
3825 | | /* Should not happen as we check no_of_pdus[n]*/ |
3826 | 0 | expert_add_info_format(pinfo, tree, &ei_fp_invalid_frame_count, "Invalid frame count (max is %u)", MAX_MAC_FRAMES); |
3827 | 0 | return; |
3828 | 0 | } |
3829 | 0 | p_fp_info->cur_tb = j; /* set cur_tb for MAC and RRC */ |
3830 | 0 | macinf->content[j] = MAC_CONTENT_CCCH; |
3831 | 0 | macinf->lchid[j] = (uint8_t)lchid[n]+1; /*Add 1 since it is zero indexed? */ |
3832 | 0 | macinf->macdflow_id[j] = p_fp_info->hsdsch_macflowd_id; |
3833 | 0 | macinf->ctmux[j] = false; |
3834 | |
|
3835 | 0 | rlcinf->li_size[j] = RLC_LI_7BITS; |
3836 | 0 | rlcinf->ciphered[j] = false; |
3837 | 0 | rlcinf->deciphered[j] = false; |
3838 | 0 | rlcinf->rbid[j] = (uint8_t)lchid[n]+1; |
3839 | 0 | rlcinf->ueid[j] = p_fp_info->channel; /*We need to fake "UE ID"*/ |
3840 | |
|
3841 | 0 | next_tvb = tvb_new_subset_length(tvb, offset, (int)pdu_length[n]); |
3842 | 0 | call_dissector_with_data(mac_fdd_hsdsch_handle, next_tvb, pinfo, top_level_tree, data); |
3843 | |
|
3844 | 0 | offset += (int)pdu_length[n]; |
3845 | 0 | } |
3846 | 0 | } |
3847 | 0 | } |
3848 | | |
3849 | | /* New IE Flags */ |
3850 | 0 | newieflags = tvb_get_uint8(tvb, offset); |
3851 | | /* If newieflags == 0000 0010 then this indicates that there is a |
3852 | | * HS-DSCH physical layer category and no other New IE flags. */ |
3853 | 0 | if (newieflags == 2) { |
3854 | | /* HS-DSCH physical layer category presence bit. */ |
3855 | 0 | proto_tree_add_uint(tree, hf_fp_hsdsch_new_ie_flag[6], tvb, offset, 1, newieflags); |
3856 | 0 | offset++; |
3857 | | /* HS-DSCH physical layer category. */ |
3858 | 0 | proto_tree_add_bits_item(tree, hf_fp_hsdsch_physical_layer_category, tvb, offset*8, 6, ENC_BIG_ENDIAN); |
3859 | 0 | offset++; |
3860 | 0 | } |
3861 | 0 | if (preferences_header_checksum) { |
3862 | 0 | verify_header_crc(tvb, pinfo, header_crc_pi, header_crc, header_length); |
3863 | 0 | } |
3864 | | /* Spare Extension and Payload CRC */ |
3865 | 0 | dissect_spare_extension_and_crc(tvb, pinfo, tree, 1, offset, header_length); |
3866 | 0 | } |
3867 | 0 | } |
3868 | | /* Validates the header CRC in a Control FP frame */ |
3869 | | /* Should only be used in heuristic dissectors! */ |
3870 | | static bool |
3871 | | check_control_frame_crc_for_heur(wmem_allocator_t* allocator, tvbuff_t * tvb) |
3872 | 0 | { |
3873 | 0 | uint8_t crc = 0; |
3874 | 0 | uint8_t calc_crc = 0; |
3875 | 0 | uint8_t * data = NULL; |
3876 | 0 | unsigned reported_length = tvb_reported_length(tvb); |
3877 | |
|
3878 | 0 | if (reported_length == 0 || reported_length > tvb_captured_length(tvb)) |
3879 | 0 | return false; |
3880 | | |
3881 | 0 | crc = tvb_get_uint8(tvb, 0) >> 1; |
3882 | | /* Get data. */ |
3883 | 0 | data = (uint8_t *)tvb_memdup(allocator, tvb, 0, tvb_reported_length(tvb)); |
3884 | | /* Include only FT flag bit in CRC calculation. */ |
3885 | 0 | data[0] = data[0] & 1; |
3886 | 0 | calc_crc = crc7update(0, data, tvb_reported_length(tvb)); |
3887 | 0 | calc_crc = crc7finalize(calc_crc); |
3888 | |
|
3889 | 0 | return calc_crc == crc; |
3890 | 0 | } |
3891 | | /* Validates the header CRC in a Data FP frame */ |
3892 | | /* Should only be used in heuristic dissectors! */ |
3893 | | static bool |
3894 | | check_header_crc_for_heur(tvbuff_t *tvb, uint16_t header_length) |
3895 | 0 | { |
3896 | 0 | uint8_t crc = 0; |
3897 | 0 | uint8_t calc_crc = 0; |
3898 | 0 | const uint8_t * data = NULL; |
3899 | |
|
3900 | 0 | if (header_length > tvb_captured_length(tvb)) |
3901 | 0 | return false; |
3902 | | |
3903 | 0 | crc = tvb_get_uint8(tvb, 0) >> 1; |
3904 | | /* Get data of header excluding the first byte */ |
3905 | 0 | data = tvb_get_ptr(tvb, 1, header_length - 1); |
3906 | |
|
3907 | 0 | calc_crc = crc7update(0, data, header_length - 1); |
3908 | 0 | calc_crc = crc7finalize(calc_crc); |
3909 | |
|
3910 | 0 | return calc_crc == crc; |
3911 | 0 | } |
3912 | | /* Validates the payload CRC in a Data FP frame */ |
3913 | | /* Should only be used in heuristic dissectors! */ |
3914 | | static bool |
3915 | | check_payload_crc_for_heur(tvbuff_t *tvb, uint16_t header_length) |
3916 | 0 | { |
3917 | 0 | uint16_t reported_length; |
3918 | 0 | uint16_t crc_index; |
3919 | 0 | uint16_t crc = 0; |
3920 | 0 | uint16_t calc_crc = 0; |
3921 | 0 | uint16_t payload_index; |
3922 | 0 | uint16_t payload_length; |
3923 | 0 | const uint8_t *data = NULL; |
3924 | |
|
3925 | 0 | reported_length = tvb_reported_length(tvb); |
3926 | 0 | if (reported_length < 2 || reported_length > tvb_captured_length(tvb)) { |
3927 | 0 | return false; |
3928 | 0 | } |
3929 | | /* Payload CRC is in the last 2 bytes of the packet */ |
3930 | 0 | crc_index = reported_length - 2; |
3931 | 0 | crc = tvb_get_bits16(tvb, crc_index * 8, 16, ENC_BIG_ENDIAN); |
3932 | |
|
3933 | 0 | payload_index = header_length; /* payload first index is the same as the header length */ |
3934 | 0 | payload_length = (reported_length - payload_index) - 2; |
3935 | 0 | data = tvb_get_ptr(tvb, payload_index, payload_length); |
3936 | 0 | calc_crc = crc16_8005_noreflect_noxor(data, payload_length); |
3937 | |
|
3938 | 0 | return calc_crc == crc; |
3939 | 0 | } |
3940 | | /* Validates the header CRC in a E-DCH Data FP frame */ |
3941 | | /* Should only be used in heuristic dissectors! */ |
3942 | | static bool |
3943 | | check_edch_header_crc_for_heur(wmem_allocator_t* allocator, tvbuff_t *tvb, uint16_t header_length) |
3944 | 0 | { |
3945 | 0 | uint16_t crc = 0; |
3946 | 0 | uint16_t calc_crc = 0; |
3947 | 0 | uint8_t * data = NULL; |
3948 | |
|
3949 | 0 | if (header_length > tvb_captured_length(tvb)) |
3950 | 0 | return false; |
3951 | | |
3952 | 0 | crc = (tvb_get_bits8(tvb, 0, 7) << 4) + tvb_get_bits8(tvb, 8, 4); |
3953 | | /* Get data of header excluding the first byte */ |
3954 | 0 | data = (uint8_t *)tvb_memdup(allocator, tvb, 1, header_length-1); |
3955 | | /*Zero the part in the second byte which contains part of the CRC*/ |
3956 | 0 | data[0] = data[0] & 0x0f; |
3957 | |
|
3958 | 0 | calc_crc = crc11_307_noreflect_noxor(data, header_length-1); |
3959 | |
|
3960 | 0 | return calc_crc == crc; |
3961 | 0 | } |
3962 | | /* Generates a unique 32bit identifier based on the frame's metadata */ |
3963 | | /* This ID is used in the RLC dissector for reassembly */ |
3964 | | /* Should only be used in heuristic dissectors! */ |
3965 | | static uint32_t |
3966 | | generate_ue_id_for_heur(packet_info *pinfo) |
3967 | 0 | { |
3968 | 0 | if (pinfo->ptype == PT_UDP && pinfo->src.type == AT_IPv4 && pinfo->dst.type == AT_IPv4) { |
3969 | | /* This logic assumes FP is delivered over IP/UDP*/ |
3970 | | /* Will return the same ID even if the address and ports are reversed */ |
3971 | | |
3972 | | /* srcXor: [ ------- Source Address ------- ] (4 bytes)*/ |
3973 | | /* XOR */ |
3974 | | /* [ Source Port ][ Source Port ] (4 bytes)*/ |
3975 | 0 | int srcXor = pntohu32(pinfo->src.data) ^ ((pinfo->srcport << 16) | (pinfo->srcport)); |
3976 | | |
3977 | | /* dstXor: [ ---- Destination Address ---- ] (4 bytes)*/ |
3978 | | /* XOR */ |
3979 | | /* [ - Dest Port - ][ - Dest Port - ] (4 bytes)*/ |
3980 | 0 | int dstXor = pntohu32(pinfo->dst.data) ^ ((pinfo->destport << 16) | (pinfo->destport)); |
3981 | 0 | return srcXor ^ dstXor; |
3982 | 0 | } |
3983 | 0 | else { |
3984 | | /* Fallback - When IP and/or UDP are missing for whatever reason */ |
3985 | | /* Using the frame number of the first heuristicly dissected frame as the UE ID should be unique enough */ |
3986 | | /* The bitwise NOT operator is used to prevent low UE ID values which are likely to collide */ |
3987 | | /* with legitimate UE IDs derived from C-RNTIs in FACH/RACH */ |
3988 | 0 | return ~(pinfo->num); |
3989 | 0 | } |
3990 | 0 | } |
3991 | | /* Fills common PCH information in a 'fp conversation info' object */ |
3992 | | /* Should only be used in heuristic dissectors! */ |
3993 | | static void |
3994 | | fill_pch_conversation_info_for_heur(umts_fp_conversation_info_t* umts_fp_conversation_info ,packet_info *pinfo) |
3995 | 0 | { |
3996 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
3997 | 0 | umts_fp_conversation_info->division = Division_FDD; |
3998 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
3999 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4000 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4001 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4002 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4003 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
4004 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
4005 | 0 | umts_fp_conversation_info->channel = CHANNEL_PCH; |
4006 | 0 | umts_fp_conversation_info->num_dch_in_flow = 1; |
4007 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1; |
4008 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1; |
4009 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)wmem_new0(wmem_file_scope(), fp_pch_channel_info_t); |
4010 | 0 | } |
4011 | | /* Attaches conversation info to both the downlink and uplink 'conversations' (streams) */ |
4012 | | /* (Required since only one of them is checked in every dissected FP packet) */ |
4013 | | /* Should only be used in heuristic dissectors! */ |
4014 | | static void |
4015 | | set_both_sides_umts_fp_conv_data(packet_info *pinfo, umts_fp_conversation_info_t *umts_fp_conversation_info) |
4016 | 0 | { |
4017 | 0 | conversation_t *packet_direction_conv; |
4018 | 0 | conversation_t *other_direction_conv; |
4019 | |
|
4020 | 0 | if (pinfo == NULL) { |
4021 | 0 | return; |
4022 | 0 | } |
4023 | | |
4024 | | /* Finding or creating conversation for the way the packet is heading */ |
4025 | 0 | packet_direction_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4026 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4027 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4028 | |
|
4029 | 0 | if (packet_direction_conv == NULL) { |
4030 | | /* Conversation does not exist yet, creating one now. */ |
4031 | 0 | packet_direction_conv = conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4032 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4033 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR2); |
4034 | 0 | } |
4035 | 0 | conversation_add_proto_data(packet_direction_conv, proto_fp, umts_fp_conversation_info); |
4036 | | |
4037 | | /* Finding or creating conversation for the other side */ |
4038 | 0 | other_direction_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_src, &pinfo->net_dst, |
4039 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4040 | 0 | pinfo->srcport, pinfo->destport, NO_ADDR_B); |
4041 | |
|
4042 | 0 | if (other_direction_conv == NULL) { |
4043 | | /* Conversation does not exist yet, creating one now. */ |
4044 | 0 | other_direction_conv = conversation_new(pinfo->num, &pinfo->net_src, &pinfo->net_dst, |
4045 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4046 | 0 | pinfo->srcport, pinfo->destport, NO_ADDR2); |
4047 | 0 | } |
4048 | 0 | conversation_add_proto_data(other_direction_conv, proto_fp, umts_fp_conversation_info); |
4049 | |
|
4050 | 0 | } |
4051 | | static bool |
4052 | | heur_dissect_fp_dcch_over_dch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4053 | 0 | { |
4054 | 0 | conversation_t *p_conv; |
4055 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4056 | 0 | struct fp_info *p_fp_info; |
4057 | 0 | uint32_t captured_length; |
4058 | 0 | uint32_t reported_length; |
4059 | 0 | uint8_t frame_type; |
4060 | 0 | uint8_t tfi; |
4061 | 0 | uint8_t pch_collisions_byte; |
4062 | | |
4063 | | /* Trying to find existing conversation */ |
4064 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4065 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4066 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4067 | |
|
4068 | 0 | if (p_conv != NULL) { |
4069 | | /* Checking if the conversation was already framed */ |
4070 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4071 | 0 | if (umts_fp_conversation_info) { |
4072 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_DCH) { |
4073 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4074 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4075 | 0 | return true; |
4076 | 0 | } |
4077 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4078 | | /* This conversation was successfully framed as ANOTHER type */ |
4079 | 0 | return false; |
4080 | 0 | } |
4081 | 0 | } |
4082 | 0 | } |
4083 | | |
4084 | | /* Making sure FP info isn't already attached */ |
4085 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4086 | 0 | if (p_fp_info) { |
4087 | 0 | return false; |
4088 | 0 | } |
4089 | | |
4090 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4091 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4092 | 0 | return false; |
4093 | 0 | } |
4094 | | |
4095 | | /* Making sure we have at least enough bytes for header (3) + footer (2) */ |
4096 | 0 | captured_length = tvb_captured_length(tvb); |
4097 | 0 | if (captured_length < 5) { |
4098 | 0 | return false; |
4099 | 0 | } |
4100 | 0 | reported_length = tvb_reported_length(tvb); |
4101 | |
|
4102 | 0 | tfi = tvb_get_uint8(tvb, 2) & 0x1f; |
4103 | | |
4104 | | /* Checking if this is a DCH frame with 0 TBs*/ |
4105 | 0 | if (tfi == 0x00) |
4106 | 0 | { |
4107 | 0 | if (reported_length != 5 /* DL */ && reported_length != 7 /* UL */) { |
4108 | 0 | return false; |
4109 | 0 | } |
4110 | 0 | if (!check_header_crc_for_heur(tvb, 3)) { |
4111 | 0 | return false; |
4112 | 0 | } |
4113 | 0 | if (!check_payload_crc_for_heur(tvb, 3)) { |
4114 | 0 | return false; |
4115 | 0 | } |
4116 | | /* All checks passed - This is an unknown DCH FP frame. */ |
4117 | | /* To allow dissection of this frame after umts_fp_conversation_info will be added in a later frame */ |
4118 | | /* the conversation must be created here if it doesn't exist yet*/ |
4119 | 0 | if (p_conv == NULL) { |
4120 | 0 | conversation_new(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4121 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4122 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR2); |
4123 | 0 | } |
4124 | 0 | return false; |
4125 | 0 | } |
4126 | | |
4127 | | /* Checking this is a DCH frame with 1 TB */ |
4128 | 0 | if (tfi != 0x01) { |
4129 | 0 | return false; |
4130 | 0 | } |
4131 | | |
4132 | | /* Expecting specific lengths: 24 for downlink frames, 26 for uplink frames */ |
4133 | | /* This is the common Transport Format of DCCH over DCH ( See 3GPP TR 25.944 / 4.1.1.3.1.1 ) */ |
4134 | 0 | if (reported_length != 24 /* DL */ && reported_length != 26 /* UL */) { |
4135 | 0 | return false; |
4136 | 0 | } |
4137 | | |
4138 | 0 | if (!check_header_crc_for_heur(tvb, 3)) { |
4139 | 0 | return false; |
4140 | 0 | } |
4141 | 0 | if (!check_payload_crc_for_heur(tvb, 3)) { |
4142 | 0 | return false; |
4143 | 0 | } |
4144 | | |
4145 | | /* Checking if the 4th byte in the frame is zeroed. In this case the CRC checks aren't */ |
4146 | | /* deterministic enough to guarantee this is a DCH since this packet could also be a PCH frame */ |
4147 | | /* with PI Bitmap of 18 bytes + 0 TBs (Both CRCs will match for both formats) */ |
4148 | 0 | pch_collisions_byte = tvb_get_uint8(tvb, 3); |
4149 | 0 | if (pch_collisions_byte == 0) { |
4150 | 0 | return false; |
4151 | 0 | } |
4152 | | |
4153 | 0 | if(!umts_fp_conversation_info) { |
4154 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4155 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4156 | 0 | } |
4157 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
4158 | 0 | umts_fp_conversation_info->division = Division_FDD; |
4159 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
4160 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4161 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4162 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4163 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4164 | 0 | if (reported_length == 24) { /* Downlink */ |
4165 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
4166 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
4167 | 0 | } |
4168 | 0 | else { /* Uplink*/ |
4169 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->dst); |
4170 | 0 | umts_fp_conversation_info->crnc_port = pinfo->destport; |
4171 | 0 | } |
4172 | 0 | umts_fp_conversation_info->channel = CHANNEL_DCH; |
4173 | 0 | umts_fp_conversation_info->num_dch_in_flow = 1; |
4174 | 0 | umts_fp_conversation_info->dch_ids_in_flow_list[0] = 31; |
4175 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1; |
4176 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1; |
4177 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = 148; |
4178 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_ul_chans = 1; |
4179 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_num_tbs[1] = 1; |
4180 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_tf_size[1] = 148; |
4181 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4182 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4183 | 0 | return true; |
4184 | 0 | } |
4185 | | static bool |
4186 | | heur_dissect_fp_fach1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4187 | 0 | { |
4188 | 0 | conversation_t *p_conv; |
4189 | 0 | fp_fach_channel_info_t* fp_fach_channel_info; |
4190 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4191 | 0 | struct fp_info *p_fp_info; |
4192 | 0 | uint32_t captured_length; |
4193 | 0 | uint32_t reported_length; |
4194 | 0 | uint8_t frame_type; |
4195 | 0 | uint8_t tfi; |
4196 | 0 | uint8_t tctf; |
4197 | | |
4198 | | /* Finding or creating conversation */ |
4199 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4200 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4201 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4202 | |
|
4203 | 0 | if (p_conv != NULL) { |
4204 | | /* Checking if the conversation was already framed */ |
4205 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4206 | 0 | if (umts_fp_conversation_info) { |
4207 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_FACH_FDD) { |
4208 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4209 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4210 | 0 | return true; |
4211 | 0 | } |
4212 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4213 | | /* This conversation was successfully framed as ANOTHER type */ |
4214 | 0 | return false; |
4215 | 0 | } |
4216 | 0 | } |
4217 | 0 | } |
4218 | | /* Making sure we have at least enough bytes for header (4) + footer (2) */ |
4219 | 0 | captured_length = tvb_captured_length(tvb); |
4220 | 0 | if(captured_length < 6) { |
4221 | 0 | return false; |
4222 | 0 | } |
4223 | | |
4224 | | /* Expecting specific lengths: 51 for frames with 1 TB */ |
4225 | | /* This is a common Transport Format of FACH ( See 3GPP TR 25.944 / 4.1.1.2 'FACH1' ) */ |
4226 | 0 | reported_length = tvb_reported_length(tvb); |
4227 | 0 | if (reported_length != 51) { |
4228 | 0 | return false; |
4229 | 0 | } |
4230 | | |
4231 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4232 | | |
4233 | | /* Making sure FP info isn't already attached */ |
4234 | 0 | if (p_fp_info) { |
4235 | 0 | return false; |
4236 | 0 | } |
4237 | | |
4238 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4239 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4240 | | /* We can't tell the FP type and content of control frames */ |
4241 | 0 | return false; |
4242 | 0 | } |
4243 | | |
4244 | 0 | tfi = tvb_get_uint8(tvb, 2) & 0x1f; |
4245 | 0 | if (tfi != 0x01) { |
4246 | 0 | return false; |
4247 | 0 | } |
4248 | | |
4249 | 0 | tctf = tvb_get_uint8(tvb, 4); |
4250 | | /* Asserting the TCTF field contains a valid (non reserved) value according to TS 25.321 Table 9.2.1-2 */ |
4251 | 0 | if (tctf != 0x40 && /* CCCH */ |
4252 | 0 | tctf != 0x50 && /* MCCH */ |
4253 | 0 | tctf != 0x5F && /* MSCH */ |
4254 | 0 | tctf != 0x80 && /* CTCH */ |
4255 | 0 | (tctf >> 4) != 0x06 && /* MTCH */ |
4256 | 0 | (tctf >> 6) != 0x00 && /* BCCH */ |
4257 | 0 | (tctf >> 6) != 0x03) { /* DCCH or DTCH over FACH */ |
4258 | 0 | return false; |
4259 | 0 | } |
4260 | | |
4261 | 0 | if (!check_header_crc_for_heur(tvb, 4)) { |
4262 | 0 | return false; |
4263 | 0 | } |
4264 | 0 | if (!check_payload_crc_for_heur(tvb, 4)) { |
4265 | 0 | return false; |
4266 | 0 | } |
4267 | | |
4268 | 0 | if(!umts_fp_conversation_info) { |
4269 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4270 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4271 | 0 | } |
4272 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
4273 | 0 | umts_fp_conversation_info->division = Division_FDD; |
4274 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
4275 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4276 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4277 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4278 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4279 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
4280 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
4281 | 0 | umts_fp_conversation_info->channel = CHANNEL_FACH_FDD; |
4282 | 0 | umts_fp_conversation_info->num_dch_in_flow = 1; |
4283 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1; |
4284 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1; |
4285 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = 360; |
4286 | | /* Adding the 'channel specific info' for FACH */ |
4287 | 0 | fp_fach_channel_info = wmem_new0(wmem_file_scope(), fp_fach_channel_info_t); |
4288 | 0 | fp_fach_channel_info->crnti_to_urnti_map = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
4289 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_fach_channel_info; |
4290 | |
|
4291 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4292 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4293 | 0 | return true; |
4294 | 0 | } |
4295 | | static bool |
4296 | | heur_dissect_fp_fach2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4297 | 0 | { |
4298 | 0 | conversation_t *p_conv; |
4299 | 0 | fp_fach_channel_info_t* fp_fach_channel_info; |
4300 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4301 | 0 | struct fp_info *p_fp_info; |
4302 | 0 | uint32_t captured_length; |
4303 | 0 | uint32_t reported_length; |
4304 | 0 | uint8_t frame_type; |
4305 | 0 | uint8_t tfi; |
4306 | 0 | uint8_t tctf; |
4307 | | |
4308 | | /* Finding or creating conversation */ |
4309 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4310 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4311 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4312 | |
|
4313 | 0 | if (p_conv != NULL) { |
4314 | | /* Checking if the conversation was already framed */ |
4315 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4316 | 0 | if (umts_fp_conversation_info) { |
4317 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_FACH_FDD) { |
4318 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4319 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4320 | 0 | return true; |
4321 | 0 | } |
4322 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4323 | | /* This conversation was successfully framed as ANOTHER type */ |
4324 | 0 | return false; |
4325 | 0 | } |
4326 | 0 | } |
4327 | 0 | } |
4328 | | /* Making sure we have at least enough bytes for header (4) + footer (2) */ |
4329 | 0 | captured_length = tvb_captured_length(tvb); |
4330 | 0 | if(captured_length < 6) { |
4331 | 0 | return false; |
4332 | 0 | } |
4333 | | |
4334 | | /* Expecting specific lengths: 27 for frames with 1 TB, 48 for frames with 2 TBs */ |
4335 | | /* This is a common Transport Format of FACH ( See 3GPP TR 25.944 / 4.1.1.2 'FACH2' ) */ |
4336 | 0 | reported_length = tvb_reported_length(tvb); |
4337 | 0 | if (reported_length != 27 && reported_length != 48) { |
4338 | 0 | return false; |
4339 | 0 | } |
4340 | | |
4341 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4342 | | |
4343 | | /* Making sure FP info isn't already attached */ |
4344 | 0 | if (p_fp_info) { |
4345 | 0 | return false; |
4346 | 0 | } |
4347 | | |
4348 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4349 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4350 | | /* We can't tell the FP type and content of control frames */ |
4351 | 0 | return false; |
4352 | 0 | } |
4353 | | |
4354 | 0 | tfi = tvb_get_uint8(tvb, 2) & 0x1f; |
4355 | 0 | if (reported_length == 27 && tfi != 0x01) { |
4356 | 0 | return false; |
4357 | 0 | } |
4358 | 0 | if (reported_length == 48 && tfi != 0x02) { |
4359 | 0 | return false; |
4360 | 0 | } |
4361 | | |
4362 | 0 | tctf = tvb_get_uint8(tvb, 4); |
4363 | | /* Asserting the TCTF field contains a valid (non reserved) value according to TS 25.321 Table 9.2.1-2 */ |
4364 | 0 | if (tctf != 0x40 && /* CCCH */ |
4365 | 0 | tctf != 0x50 && /* MCCH */ |
4366 | 0 | tctf != 0x5F && /* MSCH */ |
4367 | 0 | tctf != 0x80 && /* CTCH */ |
4368 | 0 | (tctf >> 4) != 0x06 && /* MTCH */ |
4369 | 0 | (tctf >> 6) != 0x00 && /* BCCH */ |
4370 | 0 | (tctf >> 6) != 0x03) { /* DCCH or DTCH over FACH */ |
4371 | 0 | return false; |
4372 | 0 | } |
4373 | | |
4374 | 0 | if (!check_header_crc_for_heur(tvb, 4)) { |
4375 | 0 | return false; |
4376 | 0 | } |
4377 | 0 | if (!check_payload_crc_for_heur(tvb, 4)) { |
4378 | 0 | return false; |
4379 | 0 | } |
4380 | | |
4381 | 0 | if(!umts_fp_conversation_info) { |
4382 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4383 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4384 | 0 | } |
4385 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
4386 | 0 | umts_fp_conversation_info->division = Division_FDD; |
4387 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
4388 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4389 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4390 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4391 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4392 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
4393 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
4394 | 0 | umts_fp_conversation_info->channel = CHANNEL_FACH_FDD; |
4395 | 0 | umts_fp_conversation_info->num_dch_in_flow = 1; |
4396 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_dl_chans = 1; |
4397 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[1] = 1; |
4398 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = 168; |
4399 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_num_tbs[2] = 2; |
4400 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[2] = 168; |
4401 | | /* Adding the 'channel specific info' for FACH */ |
4402 | 0 | fp_fach_channel_info = wmem_new0(wmem_file_scope(), fp_fach_channel_info_t); |
4403 | 0 | fp_fach_channel_info->crnti_to_urnti_map = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
4404 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_fach_channel_info; |
4405 | |
|
4406 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4407 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4408 | 0 | return true; |
4409 | 0 | } |
4410 | | static bool |
4411 | | heur_dissect_fp_rach(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4412 | 0 | { |
4413 | 0 | conversation_t *p_conv; |
4414 | 0 | fp_rach_channel_info_t* fp_rach_channel_info; |
4415 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4416 | 0 | struct fp_info *p_fp_info; |
4417 | 0 | uint32_t captured_length; |
4418 | 0 | uint32_t reported_length; |
4419 | 0 | uint8_t frame_type; |
4420 | 0 | uint8_t tfi; |
4421 | 0 | uint8_t tctf; |
4422 | | |
4423 | | /* Finding or creating conversation */ |
4424 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4425 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4426 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4427 | |
|
4428 | 0 | if (p_conv != NULL) { |
4429 | | /* Checking if the conversation was already framed */ |
4430 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4431 | 0 | if (umts_fp_conversation_info) { |
4432 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_RACH_FDD) { |
4433 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4434 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4435 | 0 | return true; |
4436 | 0 | } |
4437 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4438 | | /* This conversation was successfully framed as ANOTHER type */ |
4439 | 0 | return false; |
4440 | 0 | } |
4441 | 0 | } |
4442 | 0 | } |
4443 | | |
4444 | | /* Making sure we have at least enough bytes for header (4) + footer (2) */ |
4445 | 0 | captured_length = tvb_captured_length(tvb); |
4446 | 0 | if(captured_length < 6) { |
4447 | 0 | return false; |
4448 | 0 | } |
4449 | | |
4450 | | /* Expecting specific lengths: rach frames are either 28 or 52 bytes long */ |
4451 | | /* This is the common Transport Formats of RACH ( See 3GPP TR 25.944 / 4.1.2.1 ) */ |
4452 | 0 | reported_length = tvb_reported_length(tvb); |
4453 | 0 | if (reported_length != 28 && reported_length != 52) { |
4454 | 0 | return false; |
4455 | 0 | } |
4456 | | |
4457 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4458 | | |
4459 | | /* Making sure FP info isn't already attached */ |
4460 | 0 | if (p_fp_info) { |
4461 | 0 | return false; |
4462 | 0 | } |
4463 | | |
4464 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4465 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4466 | | /* We can't tell the FP type and content of control frames */ |
4467 | 0 | return false; |
4468 | 0 | } |
4469 | | |
4470 | 0 | tfi = tvb_get_uint8(tvb, 2) & 0x1f; |
4471 | 0 | if (reported_length == 28 && tfi != 0x00) { |
4472 | 0 | return false; |
4473 | 0 | } |
4474 | 0 | if (reported_length == 52 && tfi != 0x01) { |
4475 | 0 | return false; |
4476 | 0 | } |
4477 | | |
4478 | 0 | tctf = tvb_get_uint8(tvb, 4) >> 6; |
4479 | | /* Asserting the TCTF field contains a valid (non reserved) value according to TS 25.321 Table 9.2.1-4 */ |
4480 | 0 | if (tctf != 0x00 && /* CCCH */ |
4481 | 0 | tctf != 0x01) /* DCCH over RACH */ |
4482 | 0 | { |
4483 | 0 | return false; |
4484 | 0 | } |
4485 | | |
4486 | 0 | if (!check_header_crc_for_heur(tvb, 4)) { |
4487 | 0 | return false; |
4488 | 0 | } |
4489 | 0 | if (!check_payload_crc_for_heur(tvb, 4)) { |
4490 | 0 | return false; |
4491 | 0 | } |
4492 | | |
4493 | 0 | if(!umts_fp_conversation_info) { |
4494 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4495 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4496 | 0 | } |
4497 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
4498 | 0 | umts_fp_conversation_info->division = Division_FDD; |
4499 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
4500 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4501 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4502 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4503 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4504 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->dst); |
4505 | 0 | umts_fp_conversation_info->crnc_port = pinfo->destport; |
4506 | 0 | umts_fp_conversation_info->channel = CHANNEL_RACH_FDD; |
4507 | 0 | umts_fp_conversation_info->num_dch_in_flow = 1; |
4508 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].num_ul_chans = 0; |
4509 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_num_tbs[0] = 1; |
4510 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_num_tbs[1] = 1; |
4511 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_tf_size[0] = 168; |
4512 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].ul_chan_tf_size[1] = 360; |
4513 | | |
4514 | | /* Adding the 'channel specific info' for RACH */ |
4515 | 0 | fp_rach_channel_info = wmem_new0(wmem_file_scope(), fp_rach_channel_info_t); |
4516 | 0 | fp_rach_channel_info->crnti_to_urnti_map = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope()); |
4517 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_rach_channel_info; |
4518 | |
|
4519 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4520 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4521 | 0 | return true; |
4522 | 0 | } |
4523 | | static bool |
4524 | | heur_dissect_fp_pch(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4525 | 0 | { |
4526 | 0 | conversation_t *p_conv; |
4527 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4528 | 0 | fp_pch_channel_info_t* fp_pch_channel_info = NULL; |
4529 | 0 | struct fp_info *p_fp_info; |
4530 | 0 | bool conversation_initialized = false; |
4531 | 0 | uint32_t captured_length; |
4532 | 0 | uint32_t reported_length; |
4533 | 0 | uint8_t frame_type; |
4534 | 0 | uint8_t reserved_bits; |
4535 | 0 | uint8_t tfi; |
4536 | 0 | uint8_t pi_byte_length; |
4537 | 0 | uint16_t tb_byte_length; |
4538 | 0 | bool pi_present; |
4539 | 0 | bool tb_size_found; |
4540 | 0 | bool pi_length_found; |
4541 | 0 | uint8_t cfn_lowest_bits; |
4542 | 0 | uint8_t dch_collisions_byte; |
4543 | | |
4544 | | /* To correctly dissect a PCH stream 2 parameters are required: PI Bitmap length & TB length */ |
4545 | | /* Both are optional in each packet and having them both in a packet without knowing any of them */ |
4546 | | /* is not helpful.*/ |
4547 | | /* Hence gathering the info from 2 different frames is required. */ |
4548 | | |
4549 | | /* Finding or creating conversation */ |
4550 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4551 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4552 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4553 | |
|
4554 | 0 | if (p_conv != NULL) { |
4555 | | /* Checking if the conversation was already framed */ |
4556 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4557 | 0 | if (umts_fp_conversation_info) { |
4558 | 0 | fp_pch_channel_info = (fp_pch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; |
4559 | | /* Making sure this conversation type is "PCH" and the PCH channel info is present */ |
4560 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_PCH && fp_pch_channel_info != NULL) { |
4561 | 0 | conversation_initialized = true; |
4562 | 0 | pi_length_found = fp_pch_channel_info->paging_indications != 0; |
4563 | 0 | tb_size_found = umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] != 0; |
4564 | 0 | if (pi_length_found && tb_size_found) { |
4565 | | /* Stream already framed - contains both PI length and TB size */ |
4566 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4567 | 0 | return true; |
4568 | 0 | } |
4569 | 0 | } |
4570 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4571 | | /* This conversation was successfully framed as ANOTHER type */ |
4572 | 0 | return false; |
4573 | 0 | } |
4574 | 0 | else { |
4575 | | /* FP conversation info attached and the channel type is UNKNOWN - might be PCH */ |
4576 | 0 | tb_size_found = false; |
4577 | 0 | pi_length_found = false; |
4578 | 0 | } |
4579 | 0 | } |
4580 | 0 | else { |
4581 | | /* FP conversation info not attached - no PCH info is known */ |
4582 | 0 | tb_size_found = false; |
4583 | 0 | pi_length_found = false; |
4584 | 0 | } |
4585 | 0 | } |
4586 | 0 | else { |
4587 | | /* A conversation does not exist yet - no PCH info is known */ |
4588 | 0 | tb_size_found = false; |
4589 | 0 | pi_length_found = false; |
4590 | 0 | } |
4591 | | |
4592 | | /* Making sure we have at least enough bytes for header (4) + footer (2) */ |
4593 | 0 | captured_length = tvb_captured_length(tvb); |
4594 | 0 | if(captured_length < 6) { |
4595 | 0 | return false; |
4596 | 0 | } |
4597 | | |
4598 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4599 | | /* Making sure FP info isn't already attached */ |
4600 | 0 | if (p_fp_info) { |
4601 | 0 | return false; |
4602 | 0 | } |
4603 | | |
4604 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4605 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4606 | | /* We can't tell the FP type and content of control frames */ |
4607 | 0 | return false; |
4608 | 0 | } |
4609 | | |
4610 | | /* Checking bits after CFN and before PI indicator are zeroed */ |
4611 | 0 | reserved_bits = tvb_get_uint8(tvb, 2) & 0x0E; |
4612 | 0 | if (reserved_bits != 0x00) { |
4613 | 0 | return false; |
4614 | 0 | } |
4615 | | |
4616 | 0 | tfi = tvb_get_uint8(tvb, 3) & 0x1f; |
4617 | 0 | if (tfi != 0x00 && tfi != 0x01) { |
4618 | 0 | return false; |
4619 | 0 | } |
4620 | | |
4621 | 0 | if (!check_header_crc_for_heur(tvb, 4)) { |
4622 | 0 | return false; |
4623 | 0 | } |
4624 | 0 | if (!check_payload_crc_for_heur(tvb, 4)) { |
4625 | 0 | return false; |
4626 | 0 | } |
4627 | | |
4628 | 0 | reported_length = tvb_reported_length(tvb); |
4629 | 0 | pi_present = tvb_get_uint8(tvb, 2) & 0x01; /* Rightmost bit in the 3rd byte */ |
4630 | 0 | if (pi_present) { |
4631 | 0 | if (tfi == 0x00 && !pi_length_found) { |
4632 | | /* PI Bitmap present and No TB. Can calculate PI bitmap length */ |
4633 | 0 | uint8_t pi_bit_length; |
4634 | 0 | pi_byte_length = reported_length - 6; /* Removing header length (4) and footer length (2)*/ |
4635 | 0 | switch (pi_byte_length) |
4636 | 0 | { |
4637 | 0 | case 3: /* 18 bits bitmap + padding */ |
4638 | 0 | pi_bit_length = 18; |
4639 | 0 | break; |
4640 | 0 | case 5: /* 36 bits bitmap + padding */ |
4641 | 0 | pi_bit_length = 36; |
4642 | 0 | break; |
4643 | 0 | case 9: /* 72 bits bitmap */ |
4644 | 0 | pi_bit_length = 72; |
4645 | 0 | break; |
4646 | 0 | case 18: /* 144 bits bitmap */ |
4647 | 0 | pi_bit_length = 144; |
4648 | 0 | break; |
4649 | 0 | default: |
4650 | 0 | return false; |
4651 | 0 | } |
4652 | | |
4653 | 0 | if (pi_bit_length == 144 && !tb_size_found) { |
4654 | | /* Nothing has confirmed yet that this channel is a PCH since */ |
4655 | | /* both 'tb_size_found' and 'pi_length_found' are false. */ |
4656 | | /* Checking if the 4 LSB bits of the CFN (the 4 leftmost bits in the 3rd byte) aren't zeroed. */ |
4657 | | /* if they aren't this is probably PCH because those are reserved in DCH */ |
4658 | 0 | cfn_lowest_bits = tvb_get_uint8(tvb, 2) & 0xF0; |
4659 | 0 | if(cfn_lowest_bits == 0) { |
4660 | | /* Checking if the 4th byte in the frame is zeroed. In this case the CRC checks aren't */ |
4661 | | /* deterministic enough to guarantee this is a PCH since this packet could also be a DCH frame */ |
4662 | | /* with MAC's C/T is 0 and 4 leftmost bits of RLC are 0 */ |
4663 | 0 | dch_collisions_byte = tvb_get_uint8(tvb, 3); |
4664 | 0 | if (dch_collisions_byte == 0) { |
4665 | 0 | return false; |
4666 | 0 | } |
4667 | 0 | } |
4668 | 0 | } |
4669 | | |
4670 | 0 | if (!umts_fp_conversation_info) { |
4671 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4672 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4673 | 0 | } |
4674 | 0 | if(!conversation_initialized) { |
4675 | 0 | fill_pch_conversation_info_for_heur(umts_fp_conversation_info, pinfo); |
4676 | 0 | fp_pch_channel_info = (fp_pch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; |
4677 | 0 | } |
4678 | 0 | fp_pch_channel_info->paging_indications = pi_bit_length; |
4679 | 0 | pi_length_found = true; |
4680 | 0 | } |
4681 | 0 | else if (tfi == 0x01 && !tb_size_found && pi_length_found) { |
4682 | | /* TB present and PI bitmap length is known. Can calculate TB length.*/ |
4683 | 0 | pi_byte_length = (fp_pch_channel_info->paging_indications + 7) / 8; |
4684 | 0 | if (!umts_fp_conversation_info) { |
4685 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4686 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4687 | 0 | } |
4688 | 0 | if(!conversation_initialized) { |
4689 | 0 | fill_pch_conversation_info_for_heur(umts_fp_conversation_info, pinfo); |
4690 | 0 | } |
4691 | 0 | tb_byte_length = (reported_length - (pi_byte_length + 6)); /* Removing header length (4), footer length (2) and PI bitmap length*/ |
4692 | | /* Possible TB lengths for PCH is 10 or 30 bytes ( See 3GPP TR 25.944 / 4.1.1.2 ) */ |
4693 | 0 | if (tb_byte_length == 10 || tb_byte_length == 30) { |
4694 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = tb_byte_length * 8; |
4695 | 0 | tb_size_found = true; |
4696 | 0 | } |
4697 | 0 | } |
4698 | | /* TODO: It should be possible to figure both PI & TB sizes if both are present in a frame and neither is known */ |
4699 | | /* Since the total size of the frame should be unique */ |
4700 | | /* e.g. 19 bytes = header (4) + PI 18bits (3) + TB (10) + footer (2)*/ |
4701 | | /* 21 bytes = header (4) + PI 36bits (5) + TB (10) + footer (2)*/ |
4702 | | /* etc... */ |
4703 | | /* This could mostly help dissect 'busy' PCHs where most of the frames have both PI & TB*/ |
4704 | 0 | } |
4705 | 0 | else { |
4706 | 0 | if (tfi == 0x01 && !tb_size_found) { |
4707 | | /* TB present and PI bitmap is missing. Can calculate TB length.*/ |
4708 | 0 | if (!umts_fp_conversation_info) { |
4709 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4710 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4711 | 0 | } |
4712 | 0 | if(!conversation_initialized) { |
4713 | 0 | fill_pch_conversation_info_for_heur(umts_fp_conversation_info, pinfo); |
4714 | 0 | } |
4715 | 0 | tb_byte_length = (reported_length - 6); /* Removing header length (4), footer length (2) */ |
4716 | | /* Possible TB lengths for PCH is 10 or 30 bytes ( See 3GPP TR 25.944 / 4.1.1.2 ) */ |
4717 | 0 | if (tb_byte_length == 10 || tb_byte_length == 30) { |
4718 | 0 | umts_fp_conversation_info->fp_dch_channel_info[0].dl_chan_tf_size[1] = tb_byte_length * 8; |
4719 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4720 | 0 | tb_size_found = true; |
4721 | 0 | } |
4722 | 0 | } |
4723 | 0 | } |
4724 | | |
4725 | 0 | if (pi_length_found && tb_size_found) { |
4726 | | /* Stream completely framed! */ |
4727 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4728 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4729 | 0 | return true; |
4730 | 0 | } |
4731 | 0 | else { |
4732 | | /* Some data still missing */ |
4733 | 0 | return false; |
4734 | 0 | } |
4735 | 0 | } |
4736 | | static bool |
4737 | | heur_dissect_fp_hsdsch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4738 | 0 | { |
4739 | 0 | conversation_t *p_conv; |
4740 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4741 | 0 | fp_hsdsch_channel_info_t* fp_hsdsch_channel_info; |
4742 | 0 | struct fp_info *p_fp_info; |
4743 | 0 | uint32_t captured_length; |
4744 | 0 | uint32_t reported_length; |
4745 | 0 | uint8_t frame_type; |
4746 | 0 | uint16_t mac_d_pdu_length; |
4747 | 0 | uint16_t num_of_pdus; |
4748 | 0 | uint32_t expected_total_size; |
4749 | 0 | uint32_t next_pdu_index; |
4750 | 0 | uint16_t index_step; |
4751 | 0 | uint8_t pre_pdu_padding; |
4752 | | |
4753 | | /* Trying to find existing conversation */ |
4754 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4755 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4756 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4757 | |
|
4758 | 0 | if (p_conv != NULL) { |
4759 | | /* Checking if the conversation was already framed */ |
4760 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4761 | 0 | if (umts_fp_conversation_info) { |
4762 | 0 | fp_hsdsch_channel_info = (fp_hsdsch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; |
4763 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_HSDSCH && fp_hsdsch_channel_info->hsdsch_entity == hs) { |
4764 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4765 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4766 | 0 | return true; |
4767 | 0 | } |
4768 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4769 | | /* This conversation was successfully framed as ANOTHER type */ |
4770 | 0 | return false; |
4771 | 0 | } |
4772 | 0 | } |
4773 | 0 | } |
4774 | | |
4775 | | /* Making sure FP info isn't already attached */ |
4776 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4777 | 0 | if (p_fp_info) { |
4778 | 0 | return false; |
4779 | 0 | } |
4780 | | |
4781 | 0 | captured_length = tvb_reported_length(tvb); |
4782 | | /* Lengths limit: header size (7) + at least 1 PDU Block (2) + CRC Payload size (2)*/ |
4783 | 0 | if (captured_length < 11) { |
4784 | 0 | return false; |
4785 | 0 | } |
4786 | | |
4787 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4788 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4789 | 0 | return false; |
4790 | 0 | } |
4791 | | |
4792 | | /* Lengths limit: Smallest HS-DSCH type 1 data frame is 55 bytes (1 PDU of 336 bits) */ |
4793 | 0 | reported_length = tvb_reported_length(tvb); |
4794 | 0 | if (reported_length < 55) { |
4795 | 0 | return false; |
4796 | 0 | } |
4797 | | |
4798 | 0 | mac_d_pdu_length = tvb_get_uint16(tvb, 2, ENC_NA) >> 3; |
4799 | | /* Only valid PDU lengths are 336 or 656 */ |
4800 | 0 | if (mac_d_pdu_length != 336 && mac_d_pdu_length != 656) { |
4801 | 0 | return false; |
4802 | 0 | } |
4803 | | |
4804 | 0 | num_of_pdus = tvb_get_uint8(tvb, 4); |
4805 | | /* PDUs count shouldn't be 0*/ |
4806 | 0 | if (num_of_pdus == 0) { |
4807 | 0 | return false; |
4808 | 0 | } |
4809 | | /* Maximum PDUs count constraint: 32 PDUs * 336 bits or 17 PDUs * 656 bits */ |
4810 | 0 | if ((mac_d_pdu_length == 336 && num_of_pdus > 32) || (mac_d_pdu_length == 656 && num_of_pdus > 17)) { |
4811 | 0 | return false; |
4812 | 0 | } |
4813 | | |
4814 | | /* Making sure the expected packet size is smaller/equals to the entire packet's size */ |
4815 | 0 | expected_total_size = (num_of_pdus * mac_d_pdu_length / 8) + 7 /*Header length*/ + 2 /*Footer length*/; |
4816 | 0 | if (expected_total_size > captured_length || expected_total_size > reported_length) { |
4817 | 0 | return false; |
4818 | 0 | } |
4819 | | |
4820 | | /* Iterating through the PDUs making sure the padding nibble is present in all of them */ |
4821 | 0 | next_pdu_index = 7; |
4822 | 0 | index_step = mac_d_pdu_length / 8; |
4823 | 0 | for (int i = 0; i < num_of_pdus; i++) |
4824 | 0 | { |
4825 | 0 | pre_pdu_padding = tvb_get_uint8(tvb, next_pdu_index) >> 4; |
4826 | 0 | if (pre_pdu_padding != 0x00) |
4827 | 0 | { |
4828 | | /* One of the padding nibbles is not zeroed */ |
4829 | 0 | return false; |
4830 | 0 | } |
4831 | 0 | next_pdu_index += index_step; |
4832 | 0 | } |
4833 | | |
4834 | 0 | if (!check_header_crc_for_heur(tvb, 7)) { |
4835 | 0 | return false; |
4836 | 0 | } |
4837 | 0 | if (!check_payload_crc_for_heur(tvb, 7)) { |
4838 | 0 | return false; |
4839 | 0 | } |
4840 | | |
4841 | 0 | if(!umts_fp_conversation_info) { |
4842 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
4843 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
4844 | 0 | } |
4845 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
4846 | 0 | umts_fp_conversation_info->division = Division_FDD; |
4847 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
4848 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
4849 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
4850 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
4851 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
4852 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
4853 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
4854 | 0 | umts_fp_conversation_info->channel = CHANNEL_HSDSCH; |
4855 | 0 | fp_hsdsch_channel_info = wmem_new0(wmem_file_scope(), fp_hsdsch_channel_info_t); |
4856 | 0 | fp_hsdsch_channel_info->hsdsch_entity = hs; |
4857 | 0 | fp_hsdsch_channel_info->hsdsch_macdflow_id = 0; |
4858 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_hsdsch_channel_info; |
4859 | |
|
4860 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
4861 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4862 | 0 | return true; |
4863 | 0 | } |
4864 | | static bool |
4865 | | heur_dissect_fp_hsdsch_type_2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
4866 | 0 | { |
4867 | 0 | conversation_t *p_conv; |
4868 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
4869 | 0 | fp_hsdsch_channel_info_t* fp_hsdsch_channel_info; |
4870 | 0 | struct fp_info *p_fp_info; |
4871 | 0 | uint32_t captured_length; |
4872 | 0 | uint32_t reported_length; |
4873 | 0 | uint8_t frame_type; |
4874 | 0 | uint8_t reserved_fach_ind_bits; |
4875 | 0 | uint8_t pdu_block_header_reserved_bit; |
4876 | 0 | uint8_t pdu_block_headers_count; |
4877 | 0 | uint16_t next_pdu_block_header_index; |
4878 | 0 | uint16_t pdu_block_header_pdu_length; |
4879 | 0 | uint8_t pdu_block_header_pdus_count; |
4880 | 0 | uint8_t pdu_block_header_lchid; |
4881 | 0 | uint32_t total_header_length; |
4882 | 0 | uint32_t expected_payload_length; |
4883 | | |
4884 | | /* Trying to find existing conversation */ |
4885 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
4886 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
4887 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
4888 | |
|
4889 | 0 | if (p_conv != NULL) { |
4890 | | /* Checking if the conversation was already framed */ |
4891 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
4892 | 0 | if (umts_fp_conversation_info) { |
4893 | 0 | fp_hsdsch_channel_info = (fp_hsdsch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; |
4894 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_HSDSCH && fp_hsdsch_channel_info->hsdsch_entity == ehs) { |
4895 | 0 | conversation_set_dissector(p_conv, fp_handle); |
4896 | 0 | dissect_fp(tvb, pinfo, tree, data); |
4897 | 0 | return true; |
4898 | 0 | } |
4899 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
4900 | | /* This conversation was successfully framed as ANOTHER type */ |
4901 | 0 | return false; |
4902 | 0 | } |
4903 | 0 | } |
4904 | 0 | } |
4905 | | |
4906 | | /* Making sure FP info isn't already attached */ |
4907 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
4908 | 0 | if (p_fp_info) { |
4909 | 0 | return false; |
4910 | 0 | } |
4911 | | |
4912 | 0 | captured_length = tvb_captured_length(tvb); |
4913 | 0 | reported_length = tvb_reported_length(tvb); |
4914 | | /* Lengths limit: header size + at least 1 PDU Block Header + CRC Payload size */ |
4915 | 0 | if (captured_length < 11) { |
4916 | 0 | return false; |
4917 | 0 | } |
4918 | | |
4919 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
4920 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
4921 | 0 | return false; |
4922 | 0 | } |
4923 | | |
4924 | 0 | pdu_block_header_reserved_bit = (tvb_get_uint8(tvb, 7) & 0x10) >> 4; |
4925 | 0 | if (pdu_block_header_reserved_bit == 0x1) { |
4926 | 0 | return false; |
4927 | 0 | } |
4928 | | |
4929 | | /* Expecting at least 1 PDU Block Header */ |
4930 | 0 | pdu_block_headers_count = tvb_get_uint8(tvb, 2) >> 3; |
4931 | 0 | if (pdu_block_headers_count == 0) { |
4932 | 0 | return false; |
4933 | 0 | } |
4934 | | |
4935 | | /* Getting 3 rightmost bits in the FACH Indicator's byte, which are reserved and should be 0 */ |
4936 | 0 | reserved_fach_ind_bits = tvb_get_uint8(tvb, 3) & 0x03; |
4937 | 0 | if (reserved_fach_ind_bits != 0x00) { |
4938 | 0 | return false; |
4939 | 0 | } |
4940 | | |
4941 | | /* Iterating through the block headers looking for invalid fields and */ |
4942 | | /* calculating the expected total packet length */ |
4943 | 0 | total_header_length = 6; |
4944 | 0 | expected_payload_length = 0; |
4945 | 0 | for (int i = 0; i < pdu_block_headers_count; i++) |
4946 | 0 | { |
4947 | | /* Making sure the next index is not out of range */ |
4948 | 0 | if (((uint32_t)(8 + (i * 3))) >= captured_length) { |
4949 | 0 | return false; |
4950 | 0 | } |
4951 | | |
4952 | | /* Getting blocks length and count from the i-th header */ |
4953 | 0 | if (i % 2 == 0) { |
4954 | 0 | next_pdu_block_header_index = (i * 25) / 10; |
4955 | 0 | } |
4956 | 0 | else { |
4957 | 0 | next_pdu_block_header_index = (((i-1) * 25) / 10) + 2; |
4958 | 0 | } |
4959 | 0 | pdu_block_header_pdu_length = tvb_get_uint16(tvb, 6 + next_pdu_block_header_index, ENC_NA) >> 5; |
4960 | 0 | pdu_block_header_pdus_count = tvb_get_uint8(tvb, 7 + next_pdu_block_header_index) & 0x0F; |
4961 | 0 | pdu_block_header_lchid = tvb_get_uint8(tvb, 8 + next_pdu_block_header_index) >> 4; |
4962 | | |
4963 | | |
4964 | | /* Making sure PDUs' Length isn't zeroed*/ |
4965 | 0 | if (pdu_block_header_pdu_length == 0) { |
4966 | 0 | return false; |
4967 | 0 | } |
4968 | | /* Making sure PDUs Count isn't zeroed */ |
4969 | 0 | if (pdu_block_header_pdus_count == 0) { |
4970 | 0 | return false; |
4971 | 0 | } |
4972 | | |
4973 | | /* Adding this header's length to expected length*/ |
4974 | 0 | if (i % 2 == 0) { |
4975 | 0 | total_header_length += 3; |
4976 | 0 | } |
4977 | 0 | else { |
4978 | 0 | total_header_length += 2; |
4979 | 0 | } |
4980 | | /* Adding this header's payload's size to expected length*/ |
4981 | 0 | expected_payload_length += (pdu_block_header_pdu_length * pdu_block_header_pdus_count); |
4982 | | |
4983 | | /* Checking padding after lchid */ |
4984 | 0 | if ((tvb_get_uint8(tvb, 8 + (i * 3)) & 0x0F) != 0x00) { |
4985 | 0 | return false; |
4986 | 0 | } |
4987 | | /* Checking lchid for reserved value 0x0F*/ |
4988 | | |
4989 | 0 | if (pdu_block_header_lchid == 0x0F) { |
4990 | 0 | return false; |
4991 | 0 | } |
4992 | 0 | } |
4993 | | /* Adding Payload CRC'slength to payload length*/ |
4994 | 0 | expected_payload_length += 2; |
4995 | | /* Calculated expected packet size must not exceed captured length or reported length*/ |
4996 | 0 | if ((total_header_length + expected_payload_length) > captured_length || (total_header_length + expected_payload_length) > reported_length) { |
4997 | 0 | return false; |
4998 | 0 | } |
4999 | | |
5000 | 0 | if (!check_header_crc_for_heur(tvb, total_header_length)) { |
5001 | 0 | return false; |
5002 | 0 | } |
5003 | 0 | if (!check_payload_crc_for_heur(tvb, total_header_length)) { |
5004 | 0 | return false; |
5005 | 0 | } |
5006 | | |
5007 | 0 | if(!umts_fp_conversation_info) { |
5008 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
5009 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
5010 | 0 | } |
5011 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
5012 | 0 | umts_fp_conversation_info->division = Division_FDD; |
5013 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
5014 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
5015 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
5016 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
5017 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
5018 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
5019 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
5020 | 0 | umts_fp_conversation_info->channel = CHANNEL_HSDSCH; |
5021 | 0 | fp_hsdsch_channel_info = wmem_new0(wmem_file_scope(), fp_hsdsch_channel_info_t); |
5022 | 0 | fp_hsdsch_channel_info->hsdsch_entity = ehs; |
5023 | 0 | fp_hsdsch_channel_info->hsdsch_macdflow_id = 1; |
5024 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_hsdsch_channel_info; |
5025 | |
|
5026 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
5027 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5028 | 0 | return true; |
5029 | 0 | } |
5030 | | |
5031 | | static bool |
5032 | | heur_dissect_fp_edch_type_1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
5033 | 0 | { |
5034 | 0 | conversation_t *p_conv; |
5035 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
5036 | 0 | fp_edch_channel_info_t* fp_edch_channel_info; |
5037 | 0 | struct fp_info *p_fp_info; |
5038 | 0 | uint32_t captured_length; |
5039 | 0 | uint8_t frame_type; |
5040 | 0 | uint8_t num_sub_frames_byte; |
5041 | 0 | uint8_t number_of_subframes; |
5042 | 0 | uint8_t number_of_mac_es_pdus; |
5043 | 0 | uint32_t subframe_number; |
5044 | 0 | uint32_t total_sub_headers_len; |
5045 | 0 | uint32_t total_header_length; |
5046 | 0 | uint32_t payload_length; |
5047 | 0 | uint32_t total_mac_pdus_count; |
5048 | 0 | uint32_t macd_pdu_bit_size; |
5049 | 0 | uint32_t bit_offset; |
5050 | 0 | uint32_t offset; |
5051 | 0 | uint32_t i = 0; |
5052 | 0 | uint32_t n = 0; |
5053 | | |
5054 | | /* Trying to find existing conversation */ |
5055 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
5056 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
5057 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
5058 | |
|
5059 | 0 | if (p_conv != NULL) { |
5060 | | /* Checking if the conversation was already framed */ |
5061 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
5062 | 0 | if (umts_fp_conversation_info) { |
5063 | 0 | fp_edch_channel_info = (fp_edch_channel_info_t*)umts_fp_conversation_info->channel_specific_info; |
5064 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_EDCH && fp_edch_channel_info->edch_type == 0) { |
5065 | 0 | conversation_set_dissector(p_conv, fp_handle); |
5066 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5067 | 0 | return true; |
5068 | 0 | } |
5069 | 0 | else if (umts_fp_conversation_info->channel != CHANNEL_UNKNOWN){ |
5070 | | /* This conversation was successfully framed as ANOTHER type */ |
5071 | 0 | return false; |
5072 | 0 | } |
5073 | 0 | } |
5074 | 0 | } |
5075 | | |
5076 | | /* Making sure FP info isn't already attached */ |
5077 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
5078 | 0 | if (p_fp_info) { |
5079 | 0 | return false; |
5080 | 0 | } |
5081 | | |
5082 | 0 | captured_length = tvb_reported_length(tvb); |
5083 | | /* Lengths limit: header size + at least 1 Subframe Header + CRC Payload size */ |
5084 | 0 | if (captured_length < 9) { |
5085 | 0 | return false; |
5086 | 0 | } |
5087 | | |
5088 | 0 | frame_type = tvb_get_uint8(tvb, 0) & 0x01; |
5089 | 0 | if (frame_type == 1) { /* is 'control' frame type*/ |
5090 | 0 | return false; |
5091 | 0 | } |
5092 | | |
5093 | 0 | num_sub_frames_byte = tvb_get_uint8(tvb, 2); |
5094 | | /* Checking 4 leftmost bits in the 'Number of Subframes' byte, which are reserved and should be 0 */ |
5095 | 0 | if (num_sub_frames_byte & 0xf0) { |
5096 | 0 | return false; |
5097 | 0 | } |
5098 | | |
5099 | | /* Values {11-16} are reserved */ |
5100 | 0 | number_of_subframes = (num_sub_frames_byte & 0x0f) + 1; |
5101 | 0 | if (number_of_subframes >= 11) { |
5102 | 0 | return false; |
5103 | 0 | } |
5104 | | |
5105 | | /* Iterating through the block headers looking for invalid fields */ |
5106 | 0 | total_header_length = 4; |
5107 | 0 | offset = 4; |
5108 | 0 | total_mac_pdus_count = 0; |
5109 | | /* EDCH subframe header list */ |
5110 | 0 | for (n=0; n < number_of_subframes; n++) { |
5111 | | |
5112 | | /* Making sure the next index is not out of range */ |
5113 | 0 | if (((uint32_t)(offset + 3)) >= captured_length) { |
5114 | 0 | return false; |
5115 | 0 | } |
5116 | | |
5117 | | /* Subframe number */ |
5118 | 0 | subframe_number = (tvb_get_uint8(tvb, offset) & 0x07); |
5119 | 0 | if (subframe_number > 4) { |
5120 | 0 | return false; |
5121 | 0 | } |
5122 | 0 | offset++; |
5123 | | |
5124 | | /* Number of MAC-es PDUs */ |
5125 | 0 | number_of_mac_es_pdus = (tvb_get_uint8(tvb, offset) & 0xf0) >> 4; |
5126 | 0 | if (number_of_mac_es_pdus == 0) { |
5127 | 0 | return false; |
5128 | 0 | } |
5129 | 0 | bit_offset = 4; |
5130 | | |
5131 | | /* Making sure enough bytes are present for all sub-header */ |
5132 | 0 | total_sub_headers_len = ((int)((((1.5 + (number_of_mac_es_pdus * 1.5))*8+7)/8))); |
5133 | 0 | if ((offset + total_sub_headers_len) >= captured_length) { |
5134 | 0 | return false; |
5135 | 0 | } |
5136 | | /* Details of each MAC-es PDU */ |
5137 | 0 | for (i=0; i < number_of_mac_es_pdus; i++) { |
5138 | 0 | uint32_t n_pdus; /*Size of the PDU*/ |
5139 | | |
5140 | | /* DDI (6 bits) */ |
5141 | 0 | bit_offset += 6; |
5142 | | |
5143 | | /* Number of MAC-d PDUs (6 bits) */ |
5144 | 0 | n_pdus = tvb_get_bits8( tvb, offset*8 + bit_offset, 6); |
5145 | 0 | total_mac_pdus_count += n_pdus; |
5146 | 0 | bit_offset += 6; |
5147 | 0 | } |
5148 | |
|
5149 | 0 | total_header_length += total_sub_headers_len; |
5150 | 0 | offset += ((bit_offset+7)/8); |
5151 | 0 | } |
5152 | | |
5153 | | /* Figure MAC bit size */ |
5154 | 0 | payload_length = captured_length - total_header_length - 3; /* Removing 3 bytes for Payload CRC and TSN */ |
5155 | 0 | if (payload_length == (total_mac_pdus_count * 42)) { |
5156 | 0 | macd_pdu_bit_size = 336; |
5157 | 0 | } |
5158 | 0 | else if (payload_length == (total_mac_pdus_count * 18)) { |
5159 | 0 | macd_pdu_bit_size = 144; |
5160 | 0 | } |
5161 | 0 | else { |
5162 | | /* Unexpected payload length or DDIs combination */ |
5163 | 0 | return false; |
5164 | 0 | } |
5165 | | |
5166 | 0 | if (!check_edch_header_crc_for_heur(pinfo->pool, tvb, total_header_length)) { |
5167 | 0 | return false; |
5168 | 0 | } |
5169 | 0 | if (!check_payload_crc_for_heur(tvb, total_header_length)) { |
5170 | 0 | return false; |
5171 | 0 | } |
5172 | | |
5173 | 0 | if(!umts_fp_conversation_info) { |
5174 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
5175 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
5176 | 0 | } |
5177 | 0 | umts_fp_conversation_info->iface_type = IuB_Interface; |
5178 | 0 | umts_fp_conversation_info->division = Division_FDD; |
5179 | 0 | umts_fp_conversation_info->dl_frame_number = pinfo->num; |
5180 | 0 | umts_fp_conversation_info->ul_frame_number = pinfo->num; |
5181 | 0 | umts_fp_conversation_info->dch_crc_present = 1; |
5182 | 0 | umts_fp_conversation_info->com_context_id = generate_ue_id_for_heur(pinfo); |
5183 | 0 | umts_fp_conversation_info->rlc_mode = FP_RLC_AM; |
5184 | 0 | copy_address_wmem(wmem_file_scope(), &(umts_fp_conversation_info->crnc_address), &pinfo->src); |
5185 | 0 | umts_fp_conversation_info->crnc_port = pinfo->srcport; |
5186 | 0 | umts_fp_conversation_info->channel = CHANNEL_EDCH; |
5187 | 0 | fp_edch_channel_info = wmem_new0(wmem_file_scope(), fp_edch_channel_info_t); |
5188 | 0 | fp_edch_channel_info->no_ddi_entries = 0x0f; |
5189 | 0 | for(i = 0;i<0x0f;i++) { |
5190 | 0 | fp_edch_channel_info->edch_ddi[i] = i; |
5191 | 0 | fp_edch_channel_info->edch_macd_pdu_size[i] = macd_pdu_bit_size; |
5192 | 0 | fp_edch_channel_info->edch_lchId[i] = 9; |
5193 | 0 | } |
5194 | 0 | fp_edch_channel_info->edch_type = 0; /* Type 1 */ |
5195 | 0 | umts_fp_conversation_info->channel_specific_info = (void*)fp_edch_channel_info; |
5196 | |
|
5197 | 0 | conversation_set_dissector(find_or_create_conversation(pinfo), fp_handle); |
5198 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5199 | 0 | return true; |
5200 | 0 | } |
5201 | | /* This method can frame UDP streams containing FP packets but dissection of those packets will */ |
5202 | | /* fail since the FP conversation info is never attached */ |
5203 | | /* Useful for DCH streams containing CS data and don't have their own heuristic method */ |
5204 | | static bool |
5205 | | heur_dissect_fp_unknown_format(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
5206 | 0 | { |
5207 | 0 | conversation_t *p_conv; |
5208 | 0 | umts_fp_conversation_info_t* umts_fp_conversation_info = NULL; |
5209 | 0 | struct fp_info *p_fp_info; |
5210 | 0 | uint32_t length; |
5211 | 0 | uint8_t frame_type; |
5212 | 0 | uint32_t ft; |
5213 | | |
5214 | | /* Trying to find existing conversation */ |
5215 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
5216 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
5217 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
5218 | | |
5219 | | /* Check if FP Conversation Info is attached */ |
5220 | 0 | if (p_conv != NULL) { |
5221 | 0 | umts_fp_conversation_info = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
5222 | 0 | if (umts_fp_conversation_info) { |
5223 | 0 | if (umts_fp_conversation_info->channel == CHANNEL_UNKNOWN) { |
5224 | | /* This stream was framed using a previous control frame, we can call FP dissector without further tests*/ |
5225 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5226 | 0 | return true; |
5227 | 0 | } |
5228 | 0 | else { |
5229 | 0 | return false; |
5230 | 0 | } |
5231 | 0 | } |
5232 | 0 | } |
5233 | | |
5234 | 0 | p_fp_info = (fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
5235 | | |
5236 | | /* Check if per-frame FP Info is attached*/ |
5237 | 0 | if(p_fp_info) { |
5238 | | /* if FP info is present, check that it really is an ethernet link */ |
5239 | 0 | if (p_fp_info->link_type != FP_Link_Ethernet) { |
5240 | 0 | return false; |
5241 | 0 | } |
5242 | | |
5243 | | /* discriminate 'lower' UDP layer from 'user data' UDP layer |
5244 | | * (i.e. if an FP over UDP packet contains a user UDP packet */ |
5245 | 0 | if (p_fp_info->srcport != pinfo->srcport || |
5246 | 0 | p_fp_info->destport != pinfo->destport) |
5247 | 0 | return false; |
5248 | | |
5249 | | /* assume this is FP */ |
5250 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5251 | 0 | return true; |
5252 | 0 | } |
5253 | | |
5254 | | /* Both per-frame FP info and conversation FP info are missing */ |
5255 | | /* Try to frame control frames using header CRC */ |
5256 | 0 | ft = (tvb_get_uint8(tvb, 0) & 0x01); |
5257 | 0 | if(ft != FT_CONTROL) { |
5258 | | /* This is a Data frame, can't tell if it's FP. */ |
5259 | 0 | return false; |
5260 | 0 | } |
5261 | | |
5262 | 0 | length = tvb_captured_length(tvb); |
5263 | | /* Length limit: control frames header is 2 bytes */ |
5264 | 0 | if (length < 2) { |
5265 | 0 | return false; |
5266 | 0 | } |
5267 | | |
5268 | | /* Check 'Frame Type' */ |
5269 | 0 | frame_type = tvb_get_uint8(tvb, 1); |
5270 | | /* 0x00 is unused for both dedicated & common FP */ |
5271 | 0 | if( frame_type == 0x00 ) { |
5272 | 0 | return false; |
5273 | 0 | } |
5274 | | /* Max frame types are: */ |
5275 | | /* For common channels: 0x0E */ |
5276 | | /* For dedicated channels: 0x0B */ |
5277 | | /* The left nibble is zeroed in both cases */ |
5278 | 0 | if( (frame_type & 0xF0) != 0x00) { |
5279 | 0 | return false; |
5280 | 0 | } |
5281 | | |
5282 | | /* Checking Header CRC*/ |
5283 | 0 | if (!check_control_frame_crc_for_heur(pinfo->pool, tvb)) { |
5284 | | /* The CRC is incorrect */ |
5285 | 0 | return false; |
5286 | 0 | } |
5287 | | |
5288 | | /* The CRC is correct! */ |
5289 | | /* Attaching 'FP Conversation Info' to the UDP conversation so other */ |
5290 | | /* packets (both Control AND Data) will be marked as FP */ |
5291 | 0 | umts_fp_conversation_info = wmem_new0(wmem_file_scope(), umts_fp_conversation_info_t); |
5292 | 0 | umts_fp_conversation_info->channel = CHANNEL_UNKNOWN; |
5293 | 0 | set_both_sides_umts_fp_conv_data(pinfo, umts_fp_conversation_info); |
5294 | | /* Call FP Dissector for the current frame */ |
5295 | 0 | dissect_fp(tvb, pinfo, tree, data); |
5296 | 0 | return true; |
5297 | 0 | } |
5298 | | |
5299 | | /* This method wraps the heuristic dissectors of all supported channels */ |
5300 | | static bool |
5301 | | heur_dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
5302 | 0 | { |
5303 | 0 | bool match; |
5304 | |
|
5305 | 0 | match = heur_dissect_fp_dcch_over_dch(tvb, pinfo, tree, data); |
5306 | 0 | if(match) |
5307 | 0 | return true; |
5308 | 0 | match = heur_dissect_fp_fach1(tvb, pinfo, tree, data); |
5309 | 0 | if(match) |
5310 | 0 | return true; |
5311 | 0 | match = heur_dissect_fp_fach2(tvb, pinfo, tree, data); |
5312 | 0 | if(match) |
5313 | 0 | return true; |
5314 | 0 | match = heur_dissect_fp_rach(tvb, pinfo, tree, data); |
5315 | 0 | if(match) |
5316 | 0 | return true; |
5317 | 0 | match = heur_dissect_fp_pch(tvb, pinfo, tree, data); |
5318 | 0 | if(match) |
5319 | 0 | return true; |
5320 | 0 | match = heur_dissect_fp_hsdsch_type_1(tvb, pinfo, tree, data); |
5321 | 0 | if(match) |
5322 | 0 | return true; |
5323 | 0 | match = heur_dissect_fp_hsdsch_type_2(tvb, pinfo, tree, data); |
5324 | 0 | if(match) |
5325 | 0 | return true; |
5326 | 0 | match = heur_dissect_fp_edch_type_1(tvb, pinfo, tree, data); |
5327 | 0 | if(match) |
5328 | 0 | return true; |
5329 | | /* NOTE: Add new heuristic dissectors BEFORE the 'unknown format' dissector */ |
5330 | | /* since it might 'swallow' packets if the UDP stream is framed as 'CHANNEL_UNKNOWN' */ |
5331 | 0 | match = heur_dissect_fp_unknown_format(tvb, pinfo, tree, data); |
5332 | 0 | if(match) |
5333 | 0 | return true; |
5334 | | |
5335 | 0 | return false; |
5336 | 0 | } |
5337 | | |
5338 | | static uint8_t fakes =5; /*[] ={1,5,8};*/ |
5339 | | static uint8_t fake_map[256]; |
5340 | | |
5341 | | /* |
5342 | | * TODO: This need to be fixed! |
5343 | | * Basically you would want the actual RRC messages, that sooner or later maps |
5344 | | * transport channel id's to logical id's or RAB IDs |
5345 | | * to set the proper logical channel/RAB ID, but for now we make synthetic ones. |
5346 | | * */ |
5347 | | |
5348 | | static uint8_t |
5349 | | make_fake_lchid(packet_info *pinfo _U_, int trchld) |
5350 | 0 | { |
5351 | 0 | if ( fake_map[trchld] == 0) { |
5352 | 0 | fake_map[trchld] = fakes; |
5353 | 0 | fakes++; |
5354 | 0 | } |
5355 | 0 | return fake_map[trchld]; |
5356 | 0 | } |
5357 | | |
5358 | | /* Tries to resolve the U-RNTI of a channel user based on info in the fp conv info */ |
5359 | | static void fp_conv_resolve_urnti(umts_fp_conversation_info_t *p_conv_data) |
5360 | 0 | { |
5361 | | /* Trying to resolve the U-RNTI of the user if missing */ |
5362 | | /* Resolving based on the 'C-RNC Communication Context' field found in NBAP */ |
5363 | 0 | if (!p_conv_data->urnti && p_conv_data->com_context_id != 0) { |
5364 | 0 | uint32_t * mapped_urnti = (uint32_t *)(wmem_tree_lookup32(nbap_crncc_urnti_map,p_conv_data->com_context_id)); |
5365 | 0 | if (mapped_urnti != 0) { |
5366 | 0 | p_conv_data->urnti = GPOINTER_TO_UINT(mapped_urnti); |
5367 | 0 | } |
5368 | 0 | } |
5369 | 0 | } |
5370 | | |
5371 | | /* Figures the best "UE ID" to use in RLC reassembly logic */ |
5372 | | static uint32_t get_ue_id_from_conv(umts_fp_conversation_info_t *p_conv_data) |
5373 | 0 | { |
5374 | 0 | uint32_t user_identity; |
5375 | | /* Choosing RLC 'UE ID': */ |
5376 | | /* 1. Preferring the U-RNTI if attached */ |
5377 | | /* 2. Fallback - Using the 'C-RNC Communication Context' used in NBAP for this user */ |
5378 | 0 | user_identity = p_conv_data->com_context_id; |
5379 | 0 | if(p_conv_data->urnti) { |
5380 | 0 | user_identity = p_conv_data->urnti; |
5381 | 0 | } |
5382 | 0 | return user_identity; |
5383 | 0 | } |
5384 | | |
5385 | | static fp_info * |
5386 | | fp_set_per_packet_inf_from_conv(conversation_t *p_conv, |
5387 | | umts_fp_conversation_info_t *p_conv_data, |
5388 | | tvbuff_t *tvb, packet_info *pinfo, |
5389 | | proto_tree *tree _U_) |
5390 | 0 | { |
5391 | 0 | fp_info *fpi; |
5392 | 0 | uint8_t tfi, c_t, lchid; |
5393 | 0 | int offset = 0, i=0, j=0, num_tbs, chan, tb_size, tb_bit_off; |
5394 | 0 | uint32_t ft; |
5395 | 0 | bool is_known_dcch_tf,is_stndalone_ps_rab_tf,is_muxed_cs_ps_tf; |
5396 | 0 | umts_mac_info *macinf; |
5397 | 0 | rlc_info *rlcinf; |
5398 | 0 | uint8_t fake_lchid=0; |
5399 | 0 | int *cur_val=NULL; |
5400 | 0 | fp_hsdsch_channel_info_t* fp_hsdsch_channel_info = NULL; |
5401 | 0 | fp_edch_channel_info_t* fp_edch_channel_info = NULL; |
5402 | 0 | fp_pch_channel_info_t *fp_pch_channel_info = NULL; |
5403 | 0 | fp_fach_channel_info_t* fp_fach_channel_info = NULL; |
5404 | 0 | fp_rach_channel_info_t* fp_rach_channel_info = NULL; |
5405 | 0 | bool info_missing = false; |
5406 | |
|
5407 | 0 | fpi = wmem_new0(wmem_file_scope(), fp_info); |
5408 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_fp, 0, fpi); |
5409 | |
|
5410 | 0 | fpi->iface_type = p_conv_data->iface_type; |
5411 | 0 | fpi->division = p_conv_data->division; |
5412 | 0 | fpi->release = 7; /* Set values greater then the checks performed */ |
5413 | 0 | fpi->release_year = 2006; |
5414 | 0 | fpi->release_month = 12; |
5415 | 0 | fpi->channel = p_conv_data->channel; |
5416 | 0 | fpi->dch_crc_present = p_conv_data->dch_crc_present; |
5417 | 0 | fpi->link_type = FP_Link_Ethernet; |
5418 | |
|
5419 | | #if 0 |
5420 | | /*Only do this the first run, signals that we need to reset the RLC fragtable*/ |
5421 | | if (!PINFO_FD_VISITED(pinfo) && p_conv_data->reset_frag ) { |
5422 | | fpi->reset_frag = p_conv_data->reset_frag; |
5423 | | p_conv_data->reset_frag = false; |
5424 | | } |
5425 | | #endif |
5426 | | /* remember 'lower' UDP layer port information so we can later |
5427 | | * differentiate 'lower' UDP layer from 'user data' UDP layer */ |
5428 | 0 | fpi->srcport = pinfo->srcport; |
5429 | 0 | fpi->destport = pinfo->destport; |
5430 | |
|
5431 | 0 | fpi->com_context_id = p_conv_data->com_context_id; |
5432 | 0 | if(!p_conv_data->urnti) { |
5433 | 0 | fp_conv_resolve_urnti(p_conv_data); |
5434 | 0 | } |
5435 | 0 | fpi->urnti = p_conv_data->urnti; |
5436 | |
|
5437 | 0 | if (pinfo->link_dir == P2P_DIR_UL) { |
5438 | 0 | fpi->is_uplink = true; |
5439 | 0 | } else { |
5440 | 0 | fpi->is_uplink = false; |
5441 | 0 | } |
5442 | |
|
5443 | 0 | ft = tvb_get_uint8(tvb, offset) & 0x01; |
5444 | |
|
5445 | 0 | switch (fpi->channel) { |
5446 | 0 | case CHANNEL_HSDSCH: /* HS-DSCH - High Speed Downlink Shared Channel */ |
5447 | 0 | fp_hsdsch_channel_info = (fp_hsdsch_channel_info_t*)p_conv_data->channel_specific_info; |
5448 | 0 | if(fp_hsdsch_channel_info == NULL) { |
5449 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_fp_no_per_conv_channel_info, tvb, offset, |
5450 | 0 | "Can't dissect HS-DSCH FP stream because no per-conversation channel info was attached!"); |
5451 | 0 | info_missing = true; |
5452 | 0 | break; |
5453 | 0 | } |
5454 | 0 | fpi->hsdsch_entity = fp_hsdsch_channel_info->hsdsch_entity; |
5455 | 0 | fpi->hsdsch_rlc_mode = p_conv_data->rlc_mode; |
5456 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5457 | 0 | fpi->hsdsch_macflowd_id = fp_hsdsch_channel_info->hsdsch_macdflow_id; |
5458 | 0 | macinf->content[0] = hsdsch_macdflow_id_mac_content_map[fp_hsdsch_channel_info->hsdsch_macdflow_id]; |
5459 | 0 | macinf->lchid[0] = fp_hsdsch_channel_info->hsdsch_macdflow_id; |
5460 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5461 | |
|
5462 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5463 | | |
5464 | | /*Figure out RLC_MODE based on MACd-flow-ID, basically MACd-flow-ID = 0 then it's SRB0 == UM else AM*/ |
5465 | 0 | rlcinf->mode[0] = hsdsch_macdflow_id_rlc_map[fp_hsdsch_channel_info->hsdsch_macdflow_id]; |
5466 | |
|
5467 | 0 | if (fpi->hsdsch_entity == hs) { |
5468 | 0 | for (i=0; i<MAX_NUM_HSDHSCH_MACDFLOW; i++) { |
5469 | | /*Figure out if this channel is multiplexed (signaled from RRC)*/ |
5470 | 0 | if ((cur_val=(int *)g_tree_lookup(hsdsch_muxed_flows, GINT_TO_POINTER((int)fp_hsdsch_channel_info->hrnti))) != NULL) { |
5471 | 0 | j = 1 << i; |
5472 | 0 | fpi->hsdhsch_macfdlow_is_mux[i] = j & *cur_val; |
5473 | 0 | } else { |
5474 | 0 | fpi->hsdhsch_macfdlow_is_mux[i] = false; |
5475 | 0 | } |
5476 | |
|
5477 | 0 | } |
5478 | 0 | } |
5479 | 0 | rlcinf->ueid[0] = get_ue_id_from_conv(p_conv_data); |
5480 | 0 | rlcinf->li_size[0] = RLC_LI_7BITS; |
5481 | 0 | rlcinf->ciphered[0] = false; |
5482 | 0 | rlcinf->deciphered[0] = false; |
5483 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5484 | |
|
5485 | 0 | return fpi; |
5486 | | |
5487 | 0 | case CHANNEL_EDCH: |
5488 | 0 | fp_edch_channel_info = (fp_edch_channel_info_t*)p_conv_data->channel_specific_info; |
5489 | 0 | if(fp_edch_channel_info == NULL) { |
5490 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_fp_no_per_conv_channel_info, tvb, offset, |
5491 | 0 | "Can't dissect E-DCH FP stream because no per-conversation channel info was attached!"); |
5492 | 0 | info_missing = true; |
5493 | 0 | break; |
5494 | 0 | } |
5495 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5496 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5497 | 0 | fpi->no_ddi_entries = MIN(fp_edch_channel_info->no_ddi_entries, MAX_EDCH_DDIS); |
5498 | 0 | for (i=0; i<fpi->no_ddi_entries; i++) { |
5499 | 0 | fpi->edch_ddi[i] = fp_edch_channel_info->edch_ddi[i]; /*Set the DDI value*/ |
5500 | 0 | fpi->edch_macd_pdu_size[i] = fp_edch_channel_info->edch_macd_pdu_size[i]; /*Set the PDU size*/ |
5501 | 0 | fpi->edch_lchId[i] = fp_edch_channel_info->edch_lchId[i]; /*Set the channel id for this entry*/ |
5502 | 0 | } |
5503 | 0 | fpi->edch_type = fp_edch_channel_info->edch_type; |
5504 | |
|
5505 | 0 | rlcinf->ueid[0] = get_ue_id_from_conv(p_conv_data); |
5506 | 0 | rlcinf->li_size[0] = RLC_LI_7BITS; |
5507 | 0 | rlcinf->ciphered[0] = false; |
5508 | 0 | rlcinf->deciphered[0] = false; |
5509 | |
|
5510 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5511 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5512 | |
|
5513 | 0 | return fpi; |
5514 | | |
5515 | 0 | case CHANNEL_PCH: |
5516 | 0 | fp_pch_channel_info = (fp_pch_channel_info_t*)p_conv_data->channel_specific_info; |
5517 | 0 | if(fp_pch_channel_info == NULL) { |
5518 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_fp_no_per_conv_channel_info, tvb, offset, |
5519 | 0 | "Can't dissect PCH FP stream because no per-conversation channel info was attached!"); |
5520 | 0 | info_missing = true; |
5521 | 0 | break; |
5522 | 0 | } |
5523 | 0 | fpi->paging_indications = fp_pch_channel_info->paging_indications; |
5524 | 0 | fpi->num_chans = p_conv_data->num_dch_in_flow; |
5525 | |
|
5526 | 0 | if (ft == FT_CONTROL) { |
5527 | | /* control frame, we're done */ |
5528 | 0 | return fpi; |
5529 | 0 | } |
5530 | | /* Inserting Paging Indication Info extracted from the previous packet */ |
5531 | 0 | fpi->relevant_paging_indications = fp_pch_channel_info->last_paging_indication_info; |
5532 | 0 | fp_pch_channel_info->last_paging_indication_info = NULL; |
5533 | | |
5534 | | /* Set offset to TFI */ |
5535 | 0 | offset = 3; |
5536 | 0 | break; |
5537 | 0 | case CHANNEL_DCH: |
5538 | 0 | fpi->num_chans = p_conv_data->num_dch_in_flow; |
5539 | 0 | if (ft == FT_CONTROL) { |
5540 | | /* control frame, we're done */ |
5541 | 0 | return fpi; |
5542 | 0 | } |
5543 | | |
5544 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5545 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5546 | 0 | offset = 2; /* Set offset to TFI */ |
5547 | 0 | fakes = 5; /* Reset fake counter */ |
5548 | 0 | for (chan=0; chan < fpi->num_chans; chan++) { /* Iterate over the DCH channels in the flow (each given a TFI) */ |
5549 | | /* TFI is 5 bits according to 3GPP TS 25.427, paragraph 6.2.4.4 */ |
5550 | 0 | tfi = tvb_get_bits8(tvb, 3+offset*8, 5); |
5551 | | |
5552 | | /* Figure out the number of TBs and size */ |
5553 | 0 | num_tbs = (fpi->is_uplink) ? |
5554 | 0 | p_conv_data->fp_dch_channel_info[chan].ul_chan_num_tbs[tfi] : |
5555 | 0 | p_conv_data->fp_dch_channel_info[chan].dl_chan_num_tbs[tfi]; |
5556 | 0 | tb_size = (fpi->is_uplink) ? |
5557 | 0 | p_conv_data->fp_dch_channel_info[chan].ul_chan_tf_size[tfi] : |
5558 | 0 | p_conv_data->fp_dch_channel_info[chan].dl_chan_tf_size[tfi]; |
5559 | |
|
5560 | 0 | tb_bit_off = (2 + p_conv_data->num_dch_in_flow) * 8; /*Point to the C/T of first TB*/ |
5561 | | /* Iterate over the Transport Blocks */ |
5562 | | /* Set configuration for each individual block */ |
5563 | 0 | for (j=0; j < num_tbs && j+chan < MAX_MAC_FRAMES; j++) { |
5564 | | /* Set transport channel id (useful for debugging) */ |
5565 | 0 | macinf->trchid[j+chan] = p_conv_data->dch_ids_in_flow_list[chan]; |
5566 | | |
5567 | | /* Checking for the common Transport Format of 3.4 kbps SRBs for DCCH ( See 3GPP TR 25.944 / 4.1.1.3.1.1 ) */ |
5568 | 0 | is_known_dcch_tf = (tfi == 1 && num_tbs == 1 && tb_size == 148); |
5569 | | /* Checking for Transport Format of interactive or background PS RAB ( See 3GPP TS 34.108 / 6.10.2.4.1.23 -> 6.10.2.4.1.35 ) */ |
5570 | 0 | is_stndalone_ps_rab_tf = tb_size == 336; |
5571 | | /* Checking for Transport Format of muxed CS & PS RABs ( See 3GPP TS 34.108 / 6.10.2.4.1.38 -> 6.10.2.4.1.51 ) */ |
5572 | 0 | is_muxed_cs_ps_tf = (p_conv_data->dch_ids_in_flow_list[chan] == 24 && tb_size == 340); |
5573 | |
|
5574 | 0 | if (is_known_dcch_tf || is_muxed_cs_ps_tf) { |
5575 | | /* Channel is multiplexed (ie. C/T field present) */ |
5576 | 0 | macinf->ctmux[j+chan] = true; |
5577 | | |
5578 | | /* Peek at C/T, different RLC params for different logical channels */ |
5579 | | /* C/T is 4 bits according to 3GPP TS 25.321, paragraph 9.2.1, from MAC header (not FP) */ |
5580 | 0 | c_t = tvb_get_bits8(tvb, tb_bit_off, 4); |
5581 | 0 | lchid = (c_t + 1) % 0xf; /* C/T field represents the Logical Channel ID but it is zero-based */ |
5582 | 0 | macinf->lchid[j+chan] = lchid; |
5583 | 0 | macinf->content[j+chan] = lchId_type_table[lchid]; /* Base MAC content on logical channel id (Table is in packet-nbap.h) */ |
5584 | 0 | rlcinf->mode[j+chan] = lchId_rlc_map[lchid]; /* Base RLC mode on logical channel id */ |
5585 | 0 | } |
5586 | 0 | else if (is_stndalone_ps_rab_tf) { |
5587 | | /* Channel isn't multiplexed (ie. C/T field not present) */ |
5588 | 0 | macinf->ctmux[j+chan] = false; |
5589 | | |
5590 | | /* Using a fake 'interactive PS' DTCH logical channel id */ |
5591 | | /* TODO: Once proper lchid is always set, this has to be changed */ |
5592 | 0 | macinf->fake_chid[j+chan] = true; |
5593 | 0 | macinf->lchid[j+chan] = 11; |
5594 | 0 | macinf->content[j+chan] = MAC_CONTENT_PS_DTCH; |
5595 | 0 | rlcinf->mode[j+chan] = RLC_AM; |
5596 | 0 | } |
5597 | 0 | else { |
5598 | | /* Unfamiliar DCH format, faking LCHID */ |
5599 | | /* Assuming the channel isn't multiplexed (ie. C/T field not present) */ |
5600 | 0 | macinf->ctmux[j+chan] = false; |
5601 | | |
5602 | | /* TODO: This stuff has to be reworked! */ |
5603 | | /* Generates a fake logical channel id for non multiplexed channel */ |
5604 | 0 | fake_lchid = make_fake_lchid(pinfo, p_conv_data->dch_ids_in_flow_list[chan]); |
5605 | 0 | macinf->content[j+chan] = lchId_type_table[fake_lchid]; |
5606 | 0 | rlcinf->mode[j+chan] = lchId_rlc_map[fake_lchid]; |
5607 | | |
5608 | | /************************/ |
5609 | | /* TODO: Once proper lchid is always set, this has to be removed */ |
5610 | 0 | macinf->fake_chid[j+chan] = true; |
5611 | 0 | macinf->lchid[j+chan] = fake_lchid; |
5612 | | /************************/ |
5613 | 0 | } |
5614 | | |
5615 | | /* Set RLC data */ |
5616 | 0 | rlcinf->ueid[j + chan] = get_ue_id_from_conv(p_conv_data); |
5617 | 0 | rlcinf->li_size[j+chan] = RLC_LI_7BITS; |
5618 | 0 | rlcinf->ciphered[j+chan] = false; |
5619 | 0 | rlcinf->deciphered[j+chan] = false; |
5620 | 0 | rlcinf->rbid[j+chan] = macinf->lchid[j+chan]; |
5621 | | |
5622 | | /*Step over this TB and it's C/T field.*/ |
5623 | 0 | tb_bit_off += tb_size+4; |
5624 | 0 | } |
5625 | |
|
5626 | 0 | offset++; |
5627 | 0 | } |
5628 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5629 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5630 | | /* Set offset to point to first TFI */ |
5631 | 0 | offset = 2; |
5632 | 0 | break; |
5633 | 0 | case CHANNEL_FACH_FDD: |
5634 | 0 | fp_fach_channel_info = (fp_fach_channel_info_t*)p_conv_data->channel_specific_info; |
5635 | 0 | if(fp_fach_channel_info == NULL) { |
5636 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_fp_no_per_conv_channel_info, tvb, offset, |
5637 | 0 | "Can't dissect FACH FP stream because no per-conversation channel info was attached!"); |
5638 | 0 | info_missing = true; |
5639 | 0 | break; |
5640 | 0 | } |
5641 | 0 | fpi->num_chans = p_conv_data->num_dch_in_flow; |
5642 | 0 | if (ft == FT_CONTROL) { |
5643 | | /* control frame, we're done */ |
5644 | 0 | return fpi; |
5645 | 0 | } |
5646 | | /* Set offset to TFI */ |
5647 | 0 | offset = 2; |
5648 | | /* Set MAC data */ |
5649 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5650 | 0 | macinf->ctmux[0] = 1; |
5651 | 0 | macinf->content[0] = MAC_CONTENT_DCCH; |
5652 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5653 | | /* Set RLC data */ |
5654 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5655 | | /* For RLC reassembly to work we need to fake a "UE ID" as an identifier of this stream.*/ |
5656 | | /* Using the (UDP) conversation's ID and the prefix of 0xFFF */ |
5657 | 0 | rlcinf->ueid[0] = (p_conv->conv_index | 0xFFF00000); |
5658 | 0 | rlcinf->mode[0] = RLC_AM; |
5659 | 0 | rlcinf->li_size[0] = RLC_LI_7BITS; |
5660 | 0 | rlcinf->ciphered[0] = false; |
5661 | 0 | rlcinf->deciphered[0] = false; |
5662 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5663 | 0 | break; |
5664 | | |
5665 | 0 | case CHANNEL_RACH_FDD: |
5666 | 0 | fp_rach_channel_info = (fp_rach_channel_info_t*)p_conv_data->channel_specific_info; |
5667 | 0 | if(fp_rach_channel_info == NULL) { |
5668 | 0 | proto_tree_add_expert_format_remaining(tree, pinfo, &ei_fp_no_per_conv_channel_info, tvb, offset, |
5669 | 0 | "Can't dissect RACH FP stream because no per-conversation channel info was attached!"); |
5670 | 0 | info_missing = true; |
5671 | 0 | break; |
5672 | 0 | } |
5673 | 0 | fpi->num_chans = p_conv_data->num_dch_in_flow; |
5674 | 0 | if (ft == FT_CONTROL) { |
5675 | | /* control frame, we're done */ |
5676 | 0 | return fpi; |
5677 | 0 | } |
5678 | | /* Set offset to TFI */ |
5679 | 0 | offset = 2; |
5680 | | /* set MAC & RLC data */ |
5681 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5682 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5683 | 0 | for ( chan = 0; chan < fpi->num_chans; chan++ ) { |
5684 | 0 | macinf->ctmux[chan] = 1; |
5685 | 0 | macinf->content[chan] = MAC_CONTENT_DCCH; |
5686 | | /* RLC dissector's reassembly requires a non-zero stream identifier ('UE ID') to work */ |
5687 | | /* For DCCH: MAC dissector will override this with C-RNTI/U-RNTI */ |
5688 | | /* For CCCH: RLC's mode is TM and the dissector does not reassemble at all - showing 0 in the UI to indicate that */ |
5689 | 0 | rlcinf->ueid[chan] = 0; |
5690 | 0 | } |
5691 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5692 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5693 | 0 | break; |
5694 | 0 | case CHANNEL_HSDSCH_COMMON: |
5695 | 0 | rlcinf = wmem_new0(wmem_file_scope(), rlc_info); |
5696 | 0 | macinf = wmem_new0(wmem_file_scope(), umts_mac_info); |
5697 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_mac, 0, macinf); |
5698 | 0 | p_add_proto_data(wmem_file_scope(), pinfo, proto_umts_rlc, 0, rlcinf); |
5699 | 0 | break; |
5700 | 0 | default: |
5701 | 0 | expert_add_info(pinfo, NULL, &ei_fp_transport_channel_type_unknown); |
5702 | 0 | info_missing = true; |
5703 | 0 | break; |
5704 | 0 | } |
5705 | | |
5706 | 0 | if(info_missing) { |
5707 | | /* Some information was missing in the conversation struct and the FP info isn't complete */ |
5708 | 0 | p_remove_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
5709 | 0 | wmem_free(wmem_file_scope(), fpi); |
5710 | 0 | return NULL; |
5711 | 0 | } |
5712 | | |
5713 | | /* Peek at the packet as the per packet info seems not to take the tfi into account */ |
5714 | 0 | for (i=0; i<fpi->num_chans; i++) { |
5715 | | /*TFI is 5 bits according to 3GPP TS 25.427, paragraph 6.2.4.4*/ |
5716 | 0 | tfi = tvb_get_uint8(tvb, offset) & 0x1f; |
5717 | 0 | if (pinfo->link_dir == P2P_DIR_UL) { |
5718 | 0 | fpi->chan_tf_size[i] = p_conv_data->fp_dch_channel_info[i].ul_chan_tf_size[tfi]; |
5719 | 0 | fpi->chan_num_tbs[i] = p_conv_data->fp_dch_channel_info[i].ul_chan_num_tbs[tfi]; |
5720 | 0 | } else { |
5721 | 0 | fpi->chan_tf_size[i] = p_conv_data->fp_dch_channel_info[i].dl_chan_tf_size[tfi]; |
5722 | 0 | fpi->chan_num_tbs[i] = p_conv_data->fp_dch_channel_info[i].dl_chan_num_tbs[tfi]; |
5723 | 0 | } |
5724 | 0 | offset++; |
5725 | 0 | } |
5726 | | |
5727 | |
|
5728 | 0 | return fpi; |
5729 | 0 | } |
5730 | | |
5731 | | /* Updates the conversation info of a PCH stream based on information parsed in the current frame*/ |
5732 | | static void |
5733 | | update_pch_conversation_info(umts_fp_conversation_info_t *p_conv_data, packet_info *pinfo, struct fp_info *p_fp_info) |
5734 | 0 | { |
5735 | 0 | fp_pch_channel_info_t* fp_pch_channel_info; |
5736 | | /* The channel type MUST be set to PCH */ |
5737 | 0 | DISSECTOR_ASSERT(p_conv_data); |
5738 | 0 | DISSECTOR_ASSERT(p_conv_data->channel == CHANNEL_PCH); |
5739 | |
|
5740 | 0 | fp_pch_channel_info = (fp_pch_channel_info_t*)p_conv_data->channel_specific_info; |
5741 | 0 | if(p_fp_info->current_paging_indications && !PINFO_FD_VISITED(pinfo)) |
5742 | 0 | { |
5743 | | /* Saving the PI info for the next packet to find */ |
5744 | 0 | fp_pch_channel_info->last_paging_indication_info = p_fp_info->current_paging_indications; |
5745 | | /* Resetting this field so we don't add it again to the conversation next time the packet is parsed */ |
5746 | 0 | p_fp_info->current_paging_indications = NULL; |
5747 | 0 | } |
5748 | 0 | } |
5749 | | |
5750 | | /*****************************/ |
5751 | | /* Main dissection function. */ |
5752 | | static int |
5753 | | dissect_fp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
5754 | 0 | { |
5755 | 0 | proto_tree *fp_tree; |
5756 | 0 | proto_item *ti; |
5757 | 0 | int offset = 0; |
5758 | 0 | struct fp_info *p_fp_info; |
5759 | 0 | conversation_t *p_conv = NULL; |
5760 | 0 | umts_fp_conversation_info_t *p_conv_data = NULL; |
5761 | | |
5762 | | /* Append this protocol name rather than replace. */ |
5763 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "FP"); |
5764 | | |
5765 | | /* Create fp tree. */ |
5766 | 0 | ti = proto_tree_add_item(tree, proto_fp, tvb, offset, -1, ENC_NA); |
5767 | 0 | fp_tree = proto_item_add_subtree(ti, ett_fp); |
5768 | |
|
5769 | 0 | top_level_tree = tree; |
5770 | | |
5771 | | /* Look for packet info! */ |
5772 | 0 | p_fp_info = (struct fp_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_fp, 0); |
5773 | | |
5774 | | /* Check if we have conversation info */ |
5775 | | /* Trying to find exact match - with both RNC's address & port and Node B's address & port */ |
5776 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
5777 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
5778 | 0 | pinfo->destport, pinfo->srcport, 0); |
5779 | 0 | if (p_conv) { |
5780 | 0 | p_conv_data = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
5781 | 0 | } |
5782 | 0 | if (!p_conv || !p_conv_data) { |
5783 | | /* Didn't find exact conversation match */ |
5784 | | /* Try to find a partial match with just the source/destination included */ |
5785 | 0 | p_conv = (conversation_t *)find_conversation(pinfo->num, &pinfo->net_dst, &pinfo->net_src, |
5786 | 0 | conversation_pt_to_conversation_type(pinfo->ptype), |
5787 | 0 | pinfo->destport, pinfo->srcport, NO_ADDR_B); |
5788 | 0 | if (p_conv) { |
5789 | 0 | p_conv_data = (umts_fp_conversation_info_t *)conversation_get_proto_data(p_conv, proto_fp); |
5790 | 0 | } |
5791 | 0 | } |
5792 | |
|
5793 | 0 | if (p_conv_data) { |
5794 | | /*Figure out the direction of the link*/ |
5795 | 0 | if (addresses_equal(&(pinfo->net_dst), (&p_conv_data->crnc_address))) { |
5796 | | /* Node B -> CRNC*/ |
5797 | 0 | pinfo->link_dir=P2P_DIR_UL; |
5798 | |
|
5799 | 0 | proto_item *item= proto_tree_add_uint(fp_tree, hf_fp_ul_setup_frame, |
5800 | 0 | tvb, 0, 0, p_conv_data->ul_frame_number); |
5801 | 0 | proto_item_set_generated(item); |
5802 | 0 | } |
5803 | 0 | else { |
5804 | | /* CRNC -> Node B */ |
5805 | 0 | pinfo->link_dir=P2P_DIR_DL; |
5806 | | |
5807 | | /* Maybe the frame number should be stored in the proper location already in nbap?, in ul_frame_number*/ |
5808 | 0 | proto_item *item= proto_tree_add_uint(fp_tree, hf_fp_dl_setup_frame, |
5809 | 0 | tvb, 0, 0, p_conv_data->ul_frame_number); |
5810 | 0 | proto_item_set_generated(item); |
5811 | 0 | } |
5812 | 0 | if (p_fp_info == NULL) { |
5813 | 0 | p_fp_info = fp_set_per_packet_inf_from_conv(p_conv, p_conv_data, tvb, pinfo, fp_tree); |
5814 | 0 | } |
5815 | 0 | } |
5816 | |
|
5817 | 0 | if (pinfo->p2p_dir == P2P_DIR_UNKNOWN) { |
5818 | 0 | if (pinfo->link_dir == P2P_DIR_UL) { |
5819 | 0 | pinfo->p2p_dir = P2P_DIR_RECV; |
5820 | 0 | } else { |
5821 | 0 | pinfo->p2p_dir = P2P_DIR_SENT; |
5822 | 0 | } |
5823 | 0 | } |
5824 | | |
5825 | | /* Can't dissect anything without it... */ |
5826 | 0 | if (p_fp_info == NULL) { |
5827 | 0 | proto_tree_add_expert_remaining(fp_tree, pinfo, &ei_fp_no_per_frame_info, tvb, offset); |
5828 | 0 | return 1; |
5829 | 0 | } |
5830 | | |
5831 | | /* Show release information */ |
5832 | 0 | if (preferences_show_release_info) { |
5833 | 0 | proto_item *release_ti; |
5834 | 0 | proto_tree *release_tree; |
5835 | 0 | proto_item *temp_ti; |
5836 | |
|
5837 | 0 | release_ti = proto_tree_add_item(fp_tree, hf_fp_release, tvb, 0, 0, ENC_NA); |
5838 | 0 | proto_item_set_generated(release_ti); |
5839 | 0 | proto_item_append_text(release_ti, " R%u (%d/%d)", |
5840 | 0 | p_fp_info->release, p_fp_info->release_year, p_fp_info->release_month); |
5841 | 0 | release_tree = proto_item_add_subtree(release_ti, ett_fp_release); |
5842 | |
|
5843 | 0 | temp_ti = proto_tree_add_uint(release_tree, hf_fp_release_version, tvb, 0, 0, p_fp_info->release); |
5844 | 0 | proto_item_set_generated(temp_ti); |
5845 | |
|
5846 | 0 | temp_ti = proto_tree_add_uint(release_tree, hf_fp_release_year, tvb, 0, 0, p_fp_info->release_year); |
5847 | 0 | proto_item_set_generated(temp_ti); |
5848 | |
|
5849 | 0 | temp_ti = proto_tree_add_uint(release_tree, hf_fp_release_month, tvb, 0, 0, p_fp_info->release_month); |
5850 | 0 | proto_item_set_generated(temp_ti); |
5851 | 0 | } |
5852 | | |
5853 | | /* Show channel type in info column, tree */ |
5854 | 0 | col_set_str(pinfo->cinfo, COL_INFO, |
5855 | 0 | val_to_str_const(p_fp_info->channel, |
5856 | 0 | channel_type_vals, |
5857 | 0 | "Unknown channel type")); |
5858 | 0 | if (p_conv_data) { |
5859 | 0 | int i; |
5860 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "(%u", p_conv_data->dch_ids_in_flow_list[0]); |
5861 | 0 | for (i=1; i < p_conv_data->num_dch_in_flow; i++) { |
5862 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, ",%u", p_conv_data->dch_ids_in_flow_list[i]); |
5863 | 0 | } |
5864 | 0 | col_append_str(pinfo->cinfo, COL_INFO, ") "); |
5865 | 0 | } |
5866 | 0 | proto_item_append_text(ti, " (%s)", |
5867 | 0 | val_to_str_const(p_fp_info->channel, |
5868 | 0 | channel_type_vals, |
5869 | 0 | "Unknown channel type")); |
5870 | | |
5871 | | /* Add channel type as a generated field */ |
5872 | 0 | ti = proto_tree_add_uint(fp_tree, hf_fp_channel_type, tvb, 0, 0, p_fp_info->channel); |
5873 | 0 | proto_item_set_generated(ti); |
5874 | | |
5875 | | /* Add division type as a generated field */ |
5876 | 0 | if (p_fp_info->release == 7) { |
5877 | 0 | ti = proto_tree_add_uint(fp_tree, hf_fp_division, tvb, 0, 0, p_fp_info->division); |
5878 | 0 | proto_item_set_generated(ti); |
5879 | 0 | } |
5880 | | |
5881 | | /* Add link direction as a generated field */ |
5882 | 0 | ti = proto_tree_add_boolean(fp_tree, hf_fp_direction, tvb, 0, 0, p_fp_info->is_uplink); |
5883 | 0 | proto_item_set_generated(ti); |
5884 | | |
5885 | | /* Don't currently handle IuR-specific formats, but it's useful to even see |
5886 | | the channel type and direction */ |
5887 | 0 | if (p_fp_info->iface_type == IuR_Interface) { |
5888 | 0 | return 1; |
5889 | 0 | } |
5890 | | |
5891 | | /* Show DDI config info */ |
5892 | 0 | if (p_fp_info->no_ddi_entries > 0) { |
5893 | 0 | int n; |
5894 | 0 | proto_item *ddi_config_ti; |
5895 | 0 | proto_tree *ddi_config_tree; |
5896 | 0 | int no_ddi_entries = MIN(p_fp_info->no_ddi_entries, MAX_EDCH_DDIS); |
5897 | |
|
5898 | 0 | ddi_config_ti = proto_tree_add_string_format(fp_tree, hf_fp_ddi_config, tvb, offset, 0, |
5899 | 0 | "", "DDI Config ("); |
5900 | 0 | proto_item_set_generated(ddi_config_ti); |
5901 | 0 | ddi_config_tree = proto_item_add_subtree(ddi_config_ti, ett_fp_ddi_config); |
5902 | | |
5903 | | /* Add each entry */ |
5904 | 0 | for (n=0; n < no_ddi_entries; n++) { |
5905 | 0 | proto_item_append_text(ddi_config_ti, "%s%u->%ubits", |
5906 | 0 | (n == 0) ? "" : " ", |
5907 | 0 | p_fp_info->edch_ddi[n], p_fp_info->edch_macd_pdu_size[n]); |
5908 | 0 | ti = proto_tree_add_uint(ddi_config_tree, hf_fp_ddi_config_ddi, tvb, 0, 0, |
5909 | 0 | p_fp_info->edch_ddi[n]); |
5910 | 0 | proto_item_set_generated(ti); |
5911 | 0 | ti = proto_tree_add_uint(ddi_config_tree, hf_fp_ddi_config_macd_pdu_size, tvb, 0, 0, |
5912 | 0 | p_fp_info->edch_macd_pdu_size[n]); |
5913 | 0 | proto_item_set_generated(ti); |
5914 | |
|
5915 | 0 | } |
5916 | 0 | proto_item_append_text(ddi_config_ti, ")"); |
5917 | 0 | if (p_fp_info->no_ddi_entries > MAX_EDCH_DDIS) { |
5918 | 0 | expert_add_info_format(pinfo, ddi_config_ti, &ei_fp_invalid_ddi_count, "Invalid Number of E-DCH DDIs (max is %u)", MAX_EDCH_DDIS); |
5919 | 0 | } |
5920 | 0 | } |
5921 | | |
5922 | | /*************************************/ |
5923 | | /* Dissect according to channel type */ |
5924 | 0 | switch (p_fp_info->channel) { |
5925 | 0 | case CHANNEL_RACH_TDD: |
5926 | 0 | case CHANNEL_RACH_TDD_128: |
5927 | 0 | case CHANNEL_RACH_FDD: |
5928 | 0 | dissect_rach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, |
5929 | 0 | data); |
5930 | 0 | break; |
5931 | 0 | case CHANNEL_DCH: |
5932 | 0 | dissect_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, |
5933 | 0 | data); |
5934 | 0 | break; |
5935 | 0 | case CHANNEL_FACH_FDD: |
5936 | 0 | case CHANNEL_FACH_TDD: |
5937 | 0 | dissect_fach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, |
5938 | 0 | data); |
5939 | 0 | break; |
5940 | 0 | case CHANNEL_DSCH_FDD: |
5941 | 0 | case CHANNEL_DSCH_TDD: |
5942 | 0 | dissect_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info); |
5943 | 0 | break; |
5944 | 0 | case CHANNEL_USCH_TDD_128: |
5945 | 0 | case CHANNEL_USCH_TDD_384: |
5946 | 0 | dissect_usch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info); |
5947 | 0 | break; |
5948 | 0 | case CHANNEL_PCH: |
5949 | 0 | dissect_pch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, |
5950 | 0 | data); |
5951 | 0 | update_pch_conversation_info(p_conv_data, pinfo, p_fp_info); |
5952 | 0 | break; |
5953 | 0 | case CHANNEL_CPCH: |
5954 | 0 | dissect_cpch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info); |
5955 | 0 | break; |
5956 | 0 | case CHANNEL_BCH: |
5957 | 0 | dissect_bch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info); |
5958 | 0 | break; |
5959 | 0 | case CHANNEL_HSDSCH: |
5960 | | /* Show configured MAC HS-DSCH entity in use */ |
5961 | 0 | if (fp_tree) |
5962 | 0 | { |
5963 | 0 | proto_item *entity_ti; |
5964 | 0 | entity_ti = proto_tree_add_uint(fp_tree, hf_fp_hsdsch_entity, |
5965 | 0 | tvb, 0, 0, |
5966 | 0 | p_fp_info->hsdsch_entity); |
5967 | 0 | proto_item_set_generated(entity_ti); |
5968 | 0 | } |
5969 | 0 | switch (p_fp_info->hsdsch_entity) { |
5970 | 0 | case entity_not_specified: |
5971 | 0 | case hs: |
5972 | | /* This is the pre-R7 default */ |
5973 | 0 | dissect_hsdsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, data); |
5974 | 0 | break; |
5975 | 0 | case ehs: |
5976 | 0 | dissect_hsdsch_type_2_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, data); |
5977 | 0 | break; |
5978 | 0 | default: |
5979 | | /* Report Error */ |
5980 | 0 | expert_add_info(pinfo, NULL, &ei_fp_hsdsch_entity_not_specified); |
5981 | 0 | break; |
5982 | 0 | } |
5983 | 0 | break; |
5984 | 0 | case CHANNEL_HSDSCH_COMMON: |
5985 | 0 | expert_add_info(pinfo, NULL, &ei_fp_hsdsch_common_experimental_support); |
5986 | | /*if (false)*/ |
5987 | 0 | dissect_hsdsch_common_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, data); |
5988 | |
|
5989 | 0 | break; |
5990 | 0 | case CHANNEL_HSDSCH_COMMON_T3: |
5991 | 0 | expert_add_info(pinfo, NULL, &ei_fp_hsdsch_common_t3_not_implemented); |
5992 | | |
5993 | | /* TODO: */ |
5994 | 0 | break; |
5995 | 0 | case CHANNEL_IUR_CPCHF: |
5996 | | /* TODO: */ |
5997 | 0 | break; |
5998 | 0 | case CHANNEL_IUR_FACH: |
5999 | | /* TODO: */ |
6000 | 0 | break; |
6001 | 0 | case CHANNEL_IUR_DSCH: |
6002 | 0 | dissect_iur_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info); |
6003 | 0 | break; |
6004 | 0 | case CHANNEL_EDCH: |
6005 | 0 | case CHANNEL_EDCH_COMMON: |
6006 | | /* Show configured MAC E-DCH entity in use */ |
6007 | 0 | if (fp_tree) |
6008 | 0 | { |
6009 | 0 | proto_item *entity_ti; |
6010 | 0 | entity_ti = proto_tree_add_uint(fp_tree, hf_fp_edch_entity, |
6011 | 0 | tvb, 0, 0, |
6012 | 0 | p_fp_info->edch_type); |
6013 | 0 | proto_item_set_generated(entity_ti); |
6014 | 0 | } |
6015 | 0 | dissect_e_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info, |
6016 | 0 | p_fp_info->channel == CHANNEL_EDCH_COMMON, |
6017 | 0 | data); |
6018 | 0 | break; |
6019 | | |
6020 | 0 | default: |
6021 | 0 | expert_add_info(pinfo, NULL, &ei_fp_channel_type_unknown); |
6022 | 0 | break; |
6023 | 0 | } |
6024 | 0 | return tvb_captured_length(tvb); |
6025 | 0 | } |
6026 | | |
6027 | | static int |
6028 | | dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
6029 | 0 | { |
6030 | 0 | return dissect_fp_common(tvb, pinfo, tree, NULL); |
6031 | 0 | } |
6032 | | |
6033 | | static int |
6034 | | dissect_fp_aal2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) |
6035 | 0 | { |
6036 | 0 | return dissect_fp_common(tvb, pinfo, tree, data); |
6037 | 0 | } |
6038 | | |
6039 | | void proto_register_fp(void) |
6040 | 16 | { |
6041 | 16 | static hf_register_info hf[] = |
6042 | 16 | { |
6043 | 16 | { &hf_fp_release, |
6044 | 16 | { "Release", |
6045 | 16 | "fp.release", FT_NONE, BASE_NONE, NULL, 0x0, |
6046 | 16 | "Release information", HFILL |
6047 | 16 | } |
6048 | 16 | }, |
6049 | 16 | { &hf_fp_release_version, |
6050 | 16 | { "Release Version", |
6051 | 16 | "fp.release.version", FT_UINT8, BASE_DEC, NULL, 0x0, |
6052 | 16 | "3GPP Release number", HFILL |
6053 | 16 | } |
6054 | 16 | }, |
6055 | 16 | { &hf_fp_release_year, |
6056 | 16 | { "Release year", |
6057 | 16 | "fp.release.year", FT_UINT16, BASE_DEC, NULL, 0x0, |
6058 | 16 | NULL, HFILL |
6059 | 16 | } |
6060 | 16 | }, |
6061 | 16 | { &hf_fp_release_month, |
6062 | 16 | { "Release month", |
6063 | 16 | "fp.release.month", FT_UINT8, BASE_DEC, NULL, 0x0, |
6064 | 16 | NULL, HFILL |
6065 | 16 | } |
6066 | 16 | }, |
6067 | 16 | { &hf_fp_channel_type, |
6068 | 16 | { "Channel Type", |
6069 | 16 | "fp.channel-type", FT_UINT8, BASE_HEX, VALS(channel_type_vals), 0x0, |
6070 | 16 | NULL, HFILL |
6071 | 16 | } |
6072 | 16 | }, |
6073 | 16 | { &hf_fp_division, |
6074 | 16 | { "Division", |
6075 | 16 | "fp.division", FT_UINT8, BASE_HEX, VALS(division_vals), 0x0, |
6076 | 16 | "Radio division type", HFILL |
6077 | 16 | } |
6078 | 16 | }, |
6079 | 16 | { &hf_fp_direction, |
6080 | 16 | { "Direction", |
6081 | 16 | "fp.direction", FT_BOOLEAN, BASE_NONE, TFS(&tfs_uplink_downlink), 0x0, |
6082 | 16 | "Link direction", HFILL |
6083 | 16 | } |
6084 | 16 | }, |
6085 | 16 | { &hf_fp_ddi_config, |
6086 | 16 | { "DDI Config", |
6087 | 16 | "fp.ddi-config", FT_STRING, BASE_NONE, NULL, 0x0, |
6088 | 16 | "DDI Config (for E-DCH)", HFILL |
6089 | 16 | } |
6090 | 16 | }, |
6091 | 16 | { &hf_fp_ddi_config_ddi, |
6092 | 16 | { "DDI", |
6093 | 16 | "fp.ddi-config.ddi", FT_UINT8, BASE_DEC, NULL, 0x0, |
6094 | 16 | NULL, HFILL |
6095 | 16 | } |
6096 | 16 | }, |
6097 | 16 | { &hf_fp_ddi_config_macd_pdu_size, |
6098 | 16 | { "MACd PDU Size", |
6099 | 16 | "fp.ddi-config.macd-pdu-size", FT_UINT16, BASE_DEC, NULL, 0x0, |
6100 | 16 | NULL, HFILL |
6101 | 16 | } |
6102 | 16 | }, |
6103 | | |
6104 | | |
6105 | 16 | { &hf_fp_header_crc, |
6106 | 16 | { "Header CRC", |
6107 | 16 | "fp.header-crc", FT_UINT8, BASE_HEX, NULL, 0xfe, |
6108 | 16 | NULL, HFILL |
6109 | 16 | } |
6110 | 16 | }, |
6111 | 16 | { &hf_fp_ft, |
6112 | 16 | { "Frame Type", |
6113 | 16 | "fp.ft", FT_UINT8, BASE_HEX, VALS(frame_type_vals), 0x01, |
6114 | 16 | NULL, HFILL |
6115 | 16 | } |
6116 | 16 | }, |
6117 | 16 | { &hf_fp_cfn, |
6118 | 16 | { "CFN", |
6119 | 16 | "fp.cfn", FT_UINT8, BASE_DEC, NULL, 0x0, |
6120 | 16 | "Connection Frame Number", HFILL |
6121 | 16 | } |
6122 | 16 | }, |
6123 | 16 | { &hf_fp_pch_cfn, |
6124 | 16 | { "CFN (PCH)", |
6125 | 16 | "fp.pch.cfn", FT_UINT16, BASE_DEC, NULL, 0xfff0, |
6126 | 16 | "PCH Connection Frame Number", HFILL |
6127 | 16 | } |
6128 | 16 | }, |
6129 | 16 | { &hf_fp_pch_toa, |
6130 | 16 | { "ToA (PCH)", |
6131 | 16 | "fp.pch.toa", FT_INT24, BASE_DEC, NULL, 0x0, |
6132 | 16 | "PCH Time of Arrival", HFILL |
6133 | 16 | } |
6134 | 16 | }, |
6135 | 16 | { &hf_fp_cfn_control, |
6136 | 16 | { "CFN control", |
6137 | 16 | "fp.cfn-control", FT_UINT8, BASE_DEC, NULL, 0x0, |
6138 | 16 | "Connection Frame Number Control", HFILL |
6139 | 16 | } |
6140 | 16 | }, |
6141 | 16 | { &hf_fp_toa, |
6142 | 16 | { "ToA", |
6143 | 16 | "fp.toa", FT_INT16, BASE_DEC, NULL, 0x0, |
6144 | 16 | "Time of arrival (units are 125 microseconds)", HFILL |
6145 | 16 | } |
6146 | 16 | }, |
6147 | 16 | { &hf_fp_tb, |
6148 | 16 | { "TB", |
6149 | 16 | "fp.tb", FT_BYTES, BASE_NONE, NULL, 0x0, |
6150 | 16 | "Transport Block", HFILL |
6151 | 16 | } |
6152 | 16 | }, |
6153 | 16 | { &hf_fp_chan_zero_tbs, |
6154 | 16 | { "No TBs for channel", |
6155 | 16 | "fp.channel-with-zero-tbs", FT_UINT32, BASE_DEC, NULL, 0x0, |
6156 | 16 | "Channel with 0 TBs", HFILL |
6157 | 16 | } |
6158 | 16 | }, |
6159 | 16 | { &hf_fp_tfi, |
6160 | 16 | { "TFI", |
6161 | 16 | "fp.tfi", FT_UINT8, BASE_DEC, NULL, 0x0, |
6162 | 16 | "Transport Format Indicator", HFILL |
6163 | 16 | } |
6164 | 16 | }, |
6165 | 16 | { &hf_fp_usch_tfi, |
6166 | 16 | { "TFI", |
6167 | 16 | "fp.usch.tfi", FT_UINT8, BASE_DEC, NULL, 0x1f, |
6168 | 16 | "USCH Transport Format Indicator", HFILL |
6169 | 16 | } |
6170 | 16 | }, |
6171 | 16 | { &hf_fp_cpch_tfi, |
6172 | 16 | { "TFI", |
6173 | 16 | "fp.cpch.tfi", FT_UINT8, BASE_DEC, NULL, 0x1f, |
6174 | 16 | "CPCH Transport Format Indicator", HFILL |
6175 | 16 | } |
6176 | 16 | }, |
6177 | 16 | { &hf_fp_propagation_delay, |
6178 | 16 | { "Propagation Delay", |
6179 | 16 | "fp.propagation-delay", FT_UINT8, BASE_DEC, NULL, 0x0, |
6180 | 16 | NULL, HFILL |
6181 | 16 | } |
6182 | 16 | }, |
6183 | 16 | { &hf_fp_dch_control_frame_type, |
6184 | 16 | { "Control Frame Type", |
6185 | 16 | "fp.dch.control.frame-type", FT_UINT8, BASE_HEX, VALS(dch_control_frame_type_vals), 0x0, |
6186 | 16 | "DCH Control Frame Type", HFILL |
6187 | 16 | } |
6188 | 16 | }, |
6189 | 16 | { &hf_fp_dch_rx_timing_deviation, |
6190 | 16 | { "Rx Timing Deviation", |
6191 | 16 | "fp.dch.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0, |
6192 | 16 | "DCH Rx Timing Deviation", HFILL |
6193 | 16 | } |
6194 | 16 | }, |
6195 | 16 | { &hf_fp_quality_estimate, |
6196 | 16 | { "Quality Estimate", |
6197 | 16 | "fp.dch.quality-estimate", FT_UINT8, BASE_DEC, 0, 0x0, |
6198 | 16 | NULL, HFILL |
6199 | 16 | } |
6200 | 16 | }, |
6201 | 16 | { &hf_fp_payload_crc, |
6202 | 16 | { "Payload CRC", |
6203 | 16 | "fp.payload-crc", FT_UINT16, BASE_HEX, 0, 0x0, |
6204 | 16 | NULL, HFILL |
6205 | 16 | } |
6206 | 16 | }, |
6207 | 16 | { &hf_fp_payload_crc_status, |
6208 | 16 | { "Payload CRC Status", |
6209 | 16 | "fp.payload-crc.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, |
6210 | 16 | NULL, HFILL |
6211 | 16 | } |
6212 | 16 | }, |
6213 | 16 | { &hf_fp_common_control_frame_type, |
6214 | 16 | { "Control Frame Type", |
6215 | 16 | "fp.common.control.frame-type", FT_UINT8, BASE_HEX, VALS(common_control_frame_type_vals), 0x0, |
6216 | 16 | "Common Control Frame Type", HFILL |
6217 | 16 | } |
6218 | 16 | }, |
6219 | 16 | { &hf_fp_crci[0], |
6220 | 16 | { "CRCI", |
6221 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x80, |
6222 | 16 | "CRC correctness indicator", HFILL |
6223 | 16 | } |
6224 | 16 | }, |
6225 | 16 | { &hf_fp_crci[1], |
6226 | 16 | { "CRCI", |
6227 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x40, |
6228 | 16 | "CRC correctness indicator", HFILL |
6229 | 16 | } |
6230 | 16 | }, |
6231 | 16 | { &hf_fp_crci[2], |
6232 | 16 | { "CRCI", |
6233 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x20, |
6234 | 16 | "CRC correctness indicator", HFILL |
6235 | 16 | } |
6236 | 16 | }, |
6237 | 16 | { &hf_fp_crci[3], |
6238 | 16 | { "CRCI", |
6239 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x10, |
6240 | 16 | "CRC correctness indicator", HFILL |
6241 | 16 | } |
6242 | 16 | }, |
6243 | 16 | { &hf_fp_crci[4], |
6244 | 16 | { "CRCI", |
6245 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x08, |
6246 | 16 | "CRC correctness indicator", HFILL |
6247 | 16 | } |
6248 | 16 | }, |
6249 | 16 | { &hf_fp_crci[5], |
6250 | 16 | { "CRCI", |
6251 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x04, |
6252 | 16 | "CRC correctness indicator", HFILL |
6253 | 16 | } |
6254 | 16 | }, |
6255 | 16 | { &hf_fp_crci[6], |
6256 | 16 | { "CRCI", |
6257 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x02, |
6258 | 16 | "CRC correctness indicator", HFILL |
6259 | 16 | } |
6260 | 16 | }, |
6261 | 16 | { &hf_fp_crci[7], |
6262 | 16 | { "CRCI", |
6263 | 16 | "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x01, |
6264 | 16 | "CRC correctness indicator", HFILL |
6265 | 16 | } |
6266 | 16 | }, |
6267 | 16 | { &hf_fp_received_sync_ul_timing_deviation, |
6268 | 16 | { "Received SYNC UL Timing Deviation", |
6269 | 16 | "fp.rx-sync-ul-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0, |
6270 | 16 | NULL, HFILL |
6271 | 16 | } |
6272 | 16 | }, |
6273 | 16 | { &hf_fp_pch_pi, |
6274 | 16 | { "Paging Indication", |
6275 | 16 | "fp.pch.pi", FT_UINT8, BASE_DEC, VALS(paging_indication_vals), 0x01, |
6276 | 16 | "Indicates if the PI Bitmap is present", HFILL |
6277 | 16 | } |
6278 | 16 | }, |
6279 | 16 | { &hf_fp_pch_tfi, |
6280 | 16 | { "TFI", |
6281 | 16 | "fp.pch.tfi", FT_UINT8, BASE_DEC, 0, 0x1f, |
6282 | 16 | "PCH Transport Format Indicator", HFILL |
6283 | 16 | } |
6284 | 16 | }, |
6285 | 16 | { &hf_fp_fach_tfi, |
6286 | 16 | { "TFI", |
6287 | 16 | "fp.fach.tfi", FT_UINT8, BASE_DEC, 0, 0x1f, |
6288 | 16 | "FACH Transport Format Indicator", HFILL |
6289 | 16 | } |
6290 | 16 | }, |
6291 | 16 | { &hf_fp_transmit_power_level, |
6292 | 16 | { "Transmit Power Level", |
6293 | 16 | "fp.transmit-power-level", FT_FLOAT, BASE_NONE, 0, 0x0, |
6294 | 16 | "Transmit Power Level (dB)", HFILL |
6295 | 16 | } |
6296 | 16 | }, |
6297 | 16 | { &hf_fp_pdsch_set_id, |
6298 | 16 | { "PDSCH Set Id", |
6299 | 16 | "fp.pdsch-set-id", FT_UINT8, BASE_DEC, 0, 0x0, |
6300 | 16 | "A pointer to the PDSCH Set which shall be used to transmit", HFILL |
6301 | 16 | } |
6302 | 16 | }, |
6303 | 16 | { &hf_fp_paging_indication_bitmap, |
6304 | 16 | { "Paging Indications bitmap", |
6305 | 16 | "fp.pch.pi-bitmap", FT_BYTES , BASE_NONE, NULL, 0x0, |
6306 | 16 | "Paging Indication bitmap", HFILL |
6307 | 16 | } |
6308 | 16 | }, |
6309 | 16 | { &hf_fp_relevant_paging_indication_bitmap, |
6310 | 16 | { "Relevant Paging Indications bitmap", |
6311 | 16 | "fp.pch.relevant-pi-bitmap", FT_BYTES , BASE_NONE, NULL, 0x0, |
6312 | 16 | "The Paging Indication bitmap used to inform users about the current frame", HFILL |
6313 | 16 | } |
6314 | 16 | }, |
6315 | 16 | { &hf_fp_rx_timing_deviation, |
6316 | 16 | { "Rx Timing Deviation", |
6317 | 16 | "fp.common.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0, |
6318 | 16 | "Common Rx Timing Deviation", HFILL |
6319 | 16 | } |
6320 | 16 | }, |
6321 | 16 | { &hf_fp_dch_e_rucch_flag, |
6322 | 16 | { "E-RUCCH Flag", |
6323 | 16 | "fp.common.control.e-rucch-flag", FT_UINT8, BASE_DEC, VALS(e_rucch_flag_vals), 0x0, |
6324 | 16 | NULL, HFILL |
6325 | 16 | } |
6326 | 16 | }, |
6327 | 16 | { &hf_fp_edch_header_crc, |
6328 | 16 | { "E-DCH Header CRC", |
6329 | 16 | "fp.edch.header-crc", FT_UINT16, BASE_HEX, 0, 0, |
6330 | 16 | NULL, HFILL |
6331 | 16 | } |
6332 | 16 | }, |
6333 | 16 | { &hf_fp_edch_fsn, |
6334 | 16 | { "FSN", |
6335 | 16 | "fp.edch.fsn", FT_UINT8, BASE_DEC, 0, 0x0f, |
6336 | 16 | "E-DCH Frame Sequence Number", HFILL |
6337 | 16 | } |
6338 | 16 | }, |
6339 | 16 | { &hf_fp_edch_number_of_subframes, |
6340 | 16 | { "No of subframes", |
6341 | 16 | "fp.edch.no-of-subframes", FT_UINT8, BASE_DEC, 0, 0x0f, |
6342 | 16 | "E-DCH Number of subframes", HFILL |
6343 | 16 | } |
6344 | 16 | }, |
6345 | 16 | { &hf_fp_edch_harq_retransmissions, |
6346 | 16 | { "No of HARQ Retransmissions", |
6347 | 16 | "fp.edch.no-of-harq-retransmissions", FT_UINT8, BASE_DEC, 0, 0x78, |
6348 | 16 | "E-DCH Number of HARQ retransmissions", HFILL |
6349 | 16 | } |
6350 | 16 | }, |
6351 | 16 | { &hf_fp_edch_subframe_number, |
6352 | 16 | { "Subframe number", |
6353 | 16 | "fp.edch.subframe-number", FT_UINT8, BASE_DEC, 0, 0x0, |
6354 | 16 | "E-DCH Subframe number", HFILL |
6355 | 16 | } |
6356 | 16 | }, |
6357 | 16 | { &hf_fp_edch_number_of_mac_es_pdus, |
6358 | 16 | { "Number of Mac-es PDUs", |
6359 | 16 | "fp.edch.number-of-mac-es-pdus", FT_UINT8, BASE_DEC, 0, 0xf0, |
6360 | 16 | NULL, HFILL |
6361 | 16 | } |
6362 | 16 | }, |
6363 | 16 | { &hf_fp_edch_ddi, |
6364 | 16 | { "DDI", |
6365 | 16 | "fp.edch.ddi", FT_UINT8, BASE_DEC, 0, 0x0, |
6366 | 16 | "E-DCH Data Description Indicator", HFILL |
6367 | 16 | } |
6368 | 16 | }, |
6369 | 16 | { &hf_fp_edch_subframe, |
6370 | 16 | { "Subframe", |
6371 | 16 | "fp.edch.subframe", FT_STRING, BASE_NONE, NULL, 0x0, |
6372 | 16 | "EDCH Subframe", HFILL |
6373 | 16 | } |
6374 | 16 | }, |
6375 | 16 | { &hf_fp_edch_subframe_header, |
6376 | 16 | { "Subframe header", |
6377 | 16 | "fp.edch.subframe-header", FT_STRING, BASE_NONE, NULL, 0x0, |
6378 | 16 | "EDCH Subframe header", HFILL |
6379 | 16 | } |
6380 | 16 | }, |
6381 | 16 | { &hf_fp_edch_number_of_mac_d_pdus, |
6382 | 16 | { "Number of Mac-d PDUs", |
6383 | 16 | "fp.edch.number-of-mac-d-pdus", FT_UINT8, BASE_DEC, 0, 0x0, |
6384 | 16 | NULL, HFILL |
6385 | 16 | } |
6386 | 16 | }, |
6387 | 16 | { &hf_fp_edch_pdu_padding, |
6388 | 16 | { "Padding", |
6389 | 16 | "fp.edch-data-padding", FT_UINT8, BASE_DEC, 0, 0xc0, |
6390 | 16 | "E-DCH padding before PDU", HFILL |
6391 | 16 | } |
6392 | 16 | }, |
6393 | 16 | { &hf_fp_edch_tsn, |
6394 | 16 | { "TSN", |
6395 | 16 | "fp.edch-tsn", FT_UINT8, BASE_DEC, 0, 0x3f, |
6396 | 16 | "E-DCH Transmission Sequence Number", HFILL |
6397 | 16 | } |
6398 | 16 | }, |
6399 | 16 | { &hf_fp_edch_mac_es_pdu, |
6400 | 16 | { "MAC-es PDU", |
6401 | 16 | "fp.edch.mac-es-pdu", FT_NONE, BASE_NONE, NULL, 0x0, |
6402 | 16 | NULL, HFILL |
6403 | 16 | } |
6404 | 16 | }, |
6405 | | |
6406 | 16 | { &hf_fp_edch_user_buffer_size, |
6407 | 16 | { "User Buffer Size", |
6408 | 16 | "fp.edch.user-buffer-size", FT_UINT24, BASE_DEC, NULL, 0x0, |
6409 | 16 | NULL, HFILL |
6410 | 16 | } |
6411 | 16 | }, |
6412 | 16 | { &hf_fp_edch_no_macid_sdus, |
6413 | 16 | { "No of MAC-is SDUs", |
6414 | 16 | "fp.edch.no-macis-sdus", FT_UINT16, BASE_DEC, NULL, 0x0, |
6415 | 16 | NULL, HFILL |
6416 | 16 | } |
6417 | 16 | }, |
6418 | 16 | { &hf_fp_edch_number_of_mac_is_pdus, |
6419 | 16 | { "Number of Mac-is PDUs", |
6420 | 16 | "fp.edch.number-of-mac-is-pdus", FT_UINT8, BASE_DEC, 0, 0x0, |
6421 | 16 | NULL, HFILL |
6422 | 16 | } |
6423 | 16 | }, |
6424 | 16 | { &hf_fp_edch_mac_is_pdu, |
6425 | 16 | { "Mac-is PDU", |
6426 | 16 | "fp.edch.mac-is-pdu", FT_BYTES, BASE_NONE, 0, 0x0, |
6427 | 16 | NULL, HFILL |
6428 | 16 | } |
6429 | 16 | }, |
6430 | 16 | { &hf_fp_edch_e_rnti, |
6431 | 16 | { "E-RNTI", |
6432 | 16 | "fp.edch.e-rnti", FT_UINT16, BASE_DEC, 0, 0x0, |
6433 | 16 | NULL, HFILL |
6434 | 16 | } |
6435 | 16 | }, |
6436 | | |
6437 | 16 | { &hf_fp_edch_macis_descriptors, |
6438 | 16 | { "MAC-is Descriptors", |
6439 | 16 | "fp.edch.mac-is.descriptors", FT_STRING, BASE_NONE, NULL, 0x0, |
6440 | 16 | NULL, HFILL |
6441 | 16 | } |
6442 | 16 | }, |
6443 | 16 | { &hf_fp_edch_macis_lchid, |
6444 | 16 | { "LCH-ID", |
6445 | 16 | "fp.edch.mac-is.lchid", FT_UINT8, BASE_HEX, VALS(lchid_vals), 0xf0, |
6446 | 16 | NULL, HFILL |
6447 | 16 | } |
6448 | 16 | }, |
6449 | 16 | { &hf_fp_edch_macis_length, |
6450 | 16 | { "Length", |
6451 | 16 | "fp.edch.mac-is.length", FT_UINT16, BASE_DEC, 0, 0x0ffe, |
6452 | 16 | NULL, HFILL |
6453 | 16 | } |
6454 | 16 | }, |
6455 | 16 | { &hf_fp_edch_macis_flag, |
6456 | 16 | { "Flag", |
6457 | 16 | "fp.edch.mac-is.flag", FT_UINT8, BASE_HEX, 0, 0x01, |
6458 | 16 | "Indicates if another entry follows", HFILL |
6459 | 16 | } |
6460 | 16 | }, |
6461 | 16 | { &hf_fp_edch_entity, |
6462 | 16 | { "E-DCH Entity", |
6463 | 16 | "fp.edch.entity", FT_UINT8, BASE_DEC, VALS(edch_mac_entity_vals), 0x0, |
6464 | 16 | "Type of MAC entity for this E-DCH channel", HFILL |
6465 | 16 | } |
6466 | 16 | }, |
6467 | 16 | { &hf_fp_frame_seq_nr, |
6468 | 16 | { "Frame Seq Nr", |
6469 | 16 | "fp.frame-seq-nr", FT_UINT8, BASE_DEC, 0, 0xf0, |
6470 | 16 | "Frame Sequence Number", HFILL |
6471 | 16 | } |
6472 | 16 | }, |
6473 | 16 | { &hf_fp_hsdsch_pdu_block_header, |
6474 | 16 | { "PDU block header", |
6475 | 16 | "fp.hsdsch.pdu-block-header", FT_STRING, BASE_NONE, NULL, 0x0, |
6476 | 16 | "HS-DSCH type 2 PDU block header", HFILL |
6477 | 16 | } |
6478 | 16 | }, |
6479 | | #if 0 |
6480 | | { &hf_fp_hsdsch_pdu_block, |
6481 | | { "PDU block", |
6482 | | "fp.hsdsch.pdu-block", FT_STRING, BASE_NONE, NULL, 0x0, |
6483 | | "HS-DSCH type 2 PDU block data", HFILL |
6484 | | } |
6485 | | }, |
6486 | | #endif |
6487 | 16 | { &hf_fp_flush, |
6488 | 16 | { "Flush", |
6489 | 16 | "fp.flush", FT_UINT8, BASE_DEC, 0, 0x04, |
6490 | 16 | "Whether all PDUs for this priority queue should be removed", HFILL |
6491 | 16 | } |
6492 | 16 | }, |
6493 | 16 | { &hf_fp_fsn_drt_reset, |
6494 | 16 | { "FSN-DRT reset", |
6495 | 16 | "fp.fsn-drt-reset", FT_UINT8, BASE_DEC, 0, 0x02, |
6496 | 16 | "FSN/DRT Reset Flag", HFILL |
6497 | 16 | } |
6498 | 16 | }, |
6499 | 16 | { &hf_fp_drt_indicator, |
6500 | 16 | { "DRT Indicator", |
6501 | 16 | "fp.drt-indicator", FT_UINT8, BASE_DEC, 0, 0x01, |
6502 | 16 | NULL, HFILL |
6503 | 16 | } |
6504 | 16 | }, |
6505 | 16 | { &hf_fp_fach_indicator, |
6506 | 16 | { "FACH Indicator", |
6507 | 16 | "fp.fach-indicator", FT_UINT8, BASE_DEC, 0, 0x80, |
6508 | 16 | NULL, HFILL |
6509 | 16 | } |
6510 | 16 | }, |
6511 | 16 | { &hf_fp_total_pdu_blocks, |
6512 | 16 | { "PDU Blocks", |
6513 | 16 | "fp.pdu_blocks", FT_UINT8, BASE_DEC, 0, 0xf8, |
6514 | 16 | "Total number of PDU blocks", HFILL |
6515 | 16 | } |
6516 | 16 | }, |
6517 | 16 | { &hf_fp_drt, |
6518 | 16 | { "DelayRefTime", |
6519 | 16 | "fp.drt", FT_UINT16, BASE_DEC, 0, 0x0, |
6520 | 16 | NULL, HFILL |
6521 | 16 | } |
6522 | 16 | }, |
6523 | 16 | { &hf_fp_hrnti, |
6524 | 16 | { "HRNTI", |
6525 | 16 | "fp.hrnti", FT_UINT16, BASE_DEC, 0, 0x0, |
6526 | 16 | NULL, HFILL |
6527 | 16 | } |
6528 | 16 | }, |
6529 | 16 | { &hf_fp_rach_measurement_result, |
6530 | 16 | { "RACH Measurement Result", |
6531 | 16 | "fp.rach-measurement-result", FT_UINT16, BASE_DEC, 0, 0x0, |
6532 | 16 | NULL, HFILL |
6533 | 16 | } |
6534 | 16 | }, |
6535 | 16 | { &hf_fp_lchid, |
6536 | 16 | { "Logical Channel ID", |
6537 | 16 | "fp.lchid", FT_UINT8, BASE_DEC, NULL, 0x0, |
6538 | 16 | NULL, HFILL |
6539 | 16 | } |
6540 | 16 | }, |
6541 | 16 | { &hf_fp_pdu_length_in_block, |
6542 | 16 | { "PDU length in block", |
6543 | 16 | "fp.pdu-length-in-block", FT_UINT8, BASE_DEC, 0, 0x0, |
6544 | 16 | "Length of each PDU in this block in bytes", HFILL |
6545 | 16 | } |
6546 | 16 | }, |
6547 | 16 | { &hf_fp_pdus_in_block, |
6548 | 16 | { "PDUs in block", |
6549 | 16 | "fp.no-pdus-in-block", FT_UINT8, BASE_DEC, 0, 0x0, |
6550 | 16 | "Number of PDUs in block", HFILL |
6551 | 16 | } |
6552 | 16 | }, |
6553 | 16 | { &hf_fp_cmch_pi, |
6554 | 16 | { "CmCH-PI", |
6555 | 16 | "fp.cmch-pi", FT_UINT8, BASE_DEC, 0, 0x0f, |
6556 | 16 | "Common Transport Channel Priority Indicator", HFILL |
6557 | 16 | } |
6558 | 16 | }, |
6559 | 16 | { &hf_fp_user_buffer_size, |
6560 | 16 | { "User buffer size", |
6561 | 16 | "fp.user-buffer-size", FT_UINT16, BASE_DEC, 0, 0x0, |
6562 | 16 | "User buffer size in octets", HFILL |
6563 | 16 | } |
6564 | 16 | }, |
6565 | 16 | { &hf_fp_hsdsch_credits, |
6566 | 16 | { "HS-DSCH Credits", |
6567 | 16 | "fp.hsdsch-credits", FT_UINT16, BASE_DEC, 0, 0x0, |
6568 | 16 | NULL, HFILL |
6569 | 16 | } |
6570 | 16 | }, |
6571 | 16 | { &hf_fp_hsdsch_max_macd_pdu_len, |
6572 | 16 | { "Max MAC-d PDU Length", |
6573 | 16 | "fp.hsdsch.max-macd-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8, |
6574 | 16 | "Maximum MAC-d PDU Length in bits", HFILL |
6575 | 16 | } |
6576 | 16 | }, |
6577 | 16 | { &hf_fp_hsdsch_max_macdc_pdu_len, |
6578 | 16 | { "Max MAC-d/c PDU Length", |
6579 | 16 | "fp.hsdsch.max-macdc-pdu-len", FT_UINT16, BASE_DEC, 0, 0x07ff, |
6580 | 16 | "Maximum MAC-d/c PDU Length in bits", HFILL |
6581 | 16 | } |
6582 | 16 | }, |
6583 | 16 | { &hf_fp_hsdsch_interval, |
6584 | 16 | { "HS-DSCH Interval in milliseconds", |
6585 | 16 | "fp.hsdsch-interval", FT_UINT8, BASE_DEC, 0, 0x0, |
6586 | 16 | NULL, HFILL |
6587 | 16 | } |
6588 | 16 | }, |
6589 | 16 | { &hf_fp_hsdsch_calculated_rate, |
6590 | 16 | { "Calculated rate allocation (bps)", |
6591 | 16 | "fp.hsdsch-calculated-rate", FT_UINT32, BASE_DEC, 0, 0x0, |
6592 | 16 | "Calculated rate RNC is allowed to send in bps", HFILL |
6593 | 16 | } |
6594 | 16 | }, |
6595 | 16 | { &hf_fp_hsdsch_unlimited_rate, |
6596 | 16 | { "Unlimited rate", |
6597 | 16 | "fp.hsdsch-unlimited-rate", FT_NONE, BASE_NONE, 0, 0x0, |
6598 | 16 | "No restriction on rate at which date may be sent", HFILL |
6599 | 16 | } |
6600 | 16 | }, |
6601 | 16 | { &hf_fp_hsdsch_repetition_period, |
6602 | 16 | { "HS-DSCH Repetition Period", |
6603 | 16 | "fp.hsdsch-repetition-period", FT_UINT8, BASE_DEC, 0, 0x0, |
6604 | 16 | "HS-DSCH Repetition Period in milliseconds", HFILL |
6605 | 16 | } |
6606 | 16 | }, |
6607 | 16 | { &hf_fp_hsdsch_data_padding, |
6608 | 16 | { "Padding", |
6609 | 16 | "fp.hsdsch-data-padding", FT_UINT8, BASE_DEC, 0, 0xf0, |
6610 | 16 | "HS-DSCH Repetition Period in milliseconds", HFILL |
6611 | 16 | } |
6612 | 16 | }, |
6613 | 16 | { &hf_fp_hsdsch_new_ie_flags, |
6614 | 16 | { "New IEs flags", |
6615 | 16 | "fp.hsdsch.new-ie-flags", FT_STRING, BASE_NONE, 0, 0x0, |
6616 | 16 | NULL, HFILL |
6617 | 16 | } |
6618 | 16 | }, |
6619 | 16 | { &hf_fp_hsdsch_new_ie_flag[0], |
6620 | 16 | { "DRT IE present", |
6621 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x80, |
6622 | 16 | NULL, HFILL |
6623 | 16 | } |
6624 | 16 | }, |
6625 | 16 | { &hf_fp_hsdsch_new_ie_flag[1], |
6626 | 16 | { "New IE present", |
6627 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x40, |
6628 | 16 | NULL, HFILL |
6629 | 16 | } |
6630 | 16 | }, |
6631 | 16 | { &hf_fp_hsdsch_new_ie_flag[2], |
6632 | 16 | { "New IE present", |
6633 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x20, |
6634 | 16 | NULL, HFILL |
6635 | 16 | } |
6636 | 16 | }, |
6637 | 16 | { &hf_fp_hsdsch_new_ie_flag[3], |
6638 | 16 | { "New IE present", |
6639 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x10, |
6640 | 16 | NULL, HFILL |
6641 | 16 | } |
6642 | 16 | }, |
6643 | 16 | { &hf_fp_hsdsch_new_ie_flag[4], |
6644 | 16 | { "New IE present", |
6645 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x08, |
6646 | 16 | NULL, HFILL |
6647 | 16 | } |
6648 | 16 | }, |
6649 | 16 | { &hf_fp_hsdsch_new_ie_flag[5], |
6650 | 16 | { "New IE present", |
6651 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x04, |
6652 | 16 | NULL, HFILL |
6653 | 16 | } |
6654 | 16 | }, |
6655 | 16 | { &hf_fp_hsdsch_new_ie_flag[6], |
6656 | 16 | { "HS-DSCH physical layer category present", |
6657 | 16 | "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x02, |
6658 | 16 | NULL, HFILL |
6659 | 16 | } |
6660 | 16 | }, |
6661 | 16 | { &hf_fp_hsdsch_new_ie_flag[7], |
6662 | 16 | { "Another new IE flags byte", |
6663 | 16 | "fp.hsdsch.new-ie-flags-byte", FT_UINT8, BASE_DEC, 0, 0x01, |
6664 | 16 | "Another new IE flagsbyte", HFILL |
6665 | 16 | } |
6666 | 16 | }, |
6667 | 16 | { &hf_fp_hsdsch_drt, |
6668 | 16 | { "DRT", |
6669 | 16 | "fp.hsdsch.drt", FT_UINT16, BASE_DEC, 0, 0x0, |
6670 | 16 | "Delay Reference Time", HFILL |
6671 | 16 | } |
6672 | 16 | }, |
6673 | 16 | { &hf_fp_hsdsch_entity, |
6674 | 16 | { "HS-DSCH Entity", |
6675 | 16 | "fp.hsdsch.entity", FT_UINT8, BASE_DEC, VALS(hsdshc_mac_entity_vals), 0x0, |
6676 | 16 | "Type of MAC entity for this HS-DSCH channel", HFILL |
6677 | 16 | } |
6678 | 16 | }, |
6679 | 16 | { &hf_fp_timing_advance, |
6680 | 16 | { "Timing advance", |
6681 | 16 | "fp.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f, |
6682 | 16 | "Timing advance in chips", HFILL |
6683 | 16 | } |
6684 | 16 | }, |
6685 | 16 | { &hf_fp_num_of_pdu, |
6686 | 16 | { "Number of PDUs", |
6687 | 16 | "fp.hsdsch.num-of-pdu", FT_UINT8, BASE_DEC, 0, 0x0, |
6688 | 16 | "Number of PDUs in the payload", HFILL |
6689 | 16 | } |
6690 | 16 | }, |
6691 | 16 | { &hf_fp_mac_d_pdu_len, |
6692 | 16 | { "MAC-d PDU Length", |
6693 | 16 | "fp.hsdsch.mac-d-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8, |
6694 | 16 | "MAC-d PDU Length in bits", HFILL |
6695 | 16 | } |
6696 | 16 | }, |
6697 | 16 | { &hf_fp_mac_d_pdu, |
6698 | 16 | { "MAC-d PDU", |
6699 | 16 | "fp.mac-d-pdu", FT_BYTES, BASE_NONE, NULL, 0x0, |
6700 | 16 | NULL, HFILL |
6701 | 16 | } |
6702 | 16 | }, |
6703 | 16 | { &hf_fp_data, |
6704 | 16 | { "Data", |
6705 | 16 | "fp.data", FT_BYTES, BASE_NONE, NULL, 0x0, |
6706 | 16 | NULL, HFILL |
6707 | 16 | } |
6708 | 16 | }, |
6709 | 16 | { &hf_fp_crcis, |
6710 | 16 | { "CRCIs", |
6711 | 16 | "fp.crcis", FT_BYTES, BASE_NONE, NULL, 0x0, |
6712 | 16 | "CRC Indicators for uplink TBs", HFILL |
6713 | 16 | } |
6714 | 16 | }, |
6715 | 16 | { &hf_fp_t1, |
6716 | 16 | { "T1", |
6717 | 16 | "fp.t1", FT_FLOAT, BASE_NONE, NULL, 0x0, |
6718 | 16 | "RNC frame number indicating time it sends frame", HFILL |
6719 | 16 | } |
6720 | 16 | }, |
6721 | 16 | { &hf_fp_t2, |
6722 | 16 | { "T2", |
6723 | 16 | "fp.t2", FT_FLOAT, BASE_NONE, NULL, 0x0, |
6724 | 16 | "NodeB frame number indicating time it received DL Sync", HFILL |
6725 | 16 | } |
6726 | 16 | }, |
6727 | 16 | { &hf_fp_t3, |
6728 | 16 | { "T3", |
6729 | 16 | "fp.t3", FT_FLOAT, BASE_NONE, NULL, 0x0, |
6730 | 16 | "NodeB frame number indicating time it sends frame", HFILL |
6731 | 16 | } |
6732 | 16 | }, |
6733 | 16 | { &hf_fp_ul_sir_target, |
6734 | 16 | { "UL_SIR_TARGET", |
6735 | 16 | "fp.ul-sir-target", FT_FLOAT, BASE_NONE, 0, 0x0, |
6736 | 16 | "Value (in dB) of the SIR target to be used by the UL inner loop power control", HFILL |
6737 | 16 | } |
6738 | 16 | }, |
6739 | 16 | { &hf_fp_pusch_set_id, |
6740 | 16 | { "PUSCH Set Id", |
6741 | 16 | "fp.pusch-set-id", FT_UINT8, BASE_DEC, NULL, 0x0, |
6742 | 16 | "Identifies PUSCH Set from those configured in NodeB", HFILL |
6743 | 16 | } |
6744 | 16 | }, |
6745 | 16 | { &hf_fp_activation_cfn, |
6746 | 16 | { "Activation CFN", |
6747 | 16 | "fp.activation-cfn", FT_UINT8, BASE_DEC, NULL, 0x0, |
6748 | 16 | "Activation Connection Frame Number", HFILL |
6749 | 16 | } |
6750 | 16 | }, |
6751 | 16 | { &hf_fp_duration, |
6752 | 16 | { "Duration (ms)", |
6753 | 16 | "fp.pusch-duration", FT_UINT8, BASE_DEC, NULL, 0x0, |
6754 | 16 | "Duration of the activation period of the PUSCH Set", HFILL |
6755 | 16 | } |
6756 | 16 | }, |
6757 | 16 | { &hf_fp_power_offset, |
6758 | 16 | { "Power offset", |
6759 | 16 | "fp.power-offset", FT_FLOAT, BASE_NONE, NULL, 0x0, |
6760 | 16 | "Power offset (in dB)", HFILL |
6761 | 16 | } |
6762 | 16 | }, |
6763 | 16 | { &hf_fp_code_number, |
6764 | 16 | { "Code number", |
6765 | 16 | "fp.code-number", FT_UINT8, BASE_DEC, NULL, 0x0, |
6766 | 16 | NULL, HFILL |
6767 | 16 | } |
6768 | 16 | }, |
6769 | 16 | { &hf_fp_spreading_factor, |
6770 | 16 | { "Spreading factor", |
6771 | 16 | "fp.spreading-factor", FT_UINT8, BASE_DEC, VALS(spreading_factor_vals), 0xf0, |
6772 | 16 | NULL, HFILL |
6773 | 16 | } |
6774 | 16 | }, |
6775 | 16 | { &hf_fp_mc_info, |
6776 | 16 | { "MC info", |
6777 | 16 | "fp.mc-info", FT_UINT8, BASE_DEC, NULL, 0x0e, |
6778 | 16 | NULL, HFILL |
6779 | 16 | } |
6780 | 16 | }, |
6781 | 16 | { &hf_fp_rach_new_ie_flags, |
6782 | 16 | { "New IEs flags", |
6783 | 16 | "fp.rach.new-ie-flags", FT_STRING, BASE_NONE, 0, 0x0, |
6784 | 16 | NULL, HFILL |
6785 | 16 | } |
6786 | 16 | }, |
6787 | 16 | { &hf_fp_rach_new_ie_flag_unused[0], |
6788 | 16 | { "New IE present", |
6789 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x80, |
6790 | 16 | NULL, HFILL |
6791 | 16 | } |
6792 | 16 | }, |
6793 | 16 | { &hf_fp_rach_new_ie_flag_unused[1], |
6794 | 16 | { "New IE present", |
6795 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x40, |
6796 | 16 | NULL, HFILL |
6797 | 16 | } |
6798 | 16 | }, |
6799 | 16 | { &hf_fp_rach_new_ie_flag_unused[2], |
6800 | 16 | { "New IE present", |
6801 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x20, |
6802 | 16 | "New IE present (unused)", HFILL |
6803 | 16 | } |
6804 | 16 | }, |
6805 | 16 | { &hf_fp_rach_new_ie_flag_unused[3], |
6806 | 16 | { "New IE present", |
6807 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x10, |
6808 | 16 | "New IE present (unused)", HFILL |
6809 | 16 | } |
6810 | 16 | }, |
6811 | 16 | { &hf_fp_rach_new_ie_flag_unused[4], |
6812 | 16 | { "New IE present", |
6813 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x08, |
6814 | 16 | "New IE present (unused)", HFILL |
6815 | 16 | } |
6816 | 16 | }, |
6817 | 16 | { &hf_fp_rach_new_ie_flag_unused[5], |
6818 | 16 | { "New IE present", |
6819 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x04, |
6820 | 16 | "New IE present (unused)", HFILL |
6821 | 16 | } |
6822 | 16 | }, |
6823 | 16 | { &hf_fp_rach_new_ie_flag_unused[6], |
6824 | 16 | { "New IE present", |
6825 | 16 | "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x02, |
6826 | 16 | "New IE present (unused)", HFILL |
6827 | 16 | } |
6828 | 16 | }, |
6829 | 16 | { &hf_fp_rach_cell_portion_id_present, |
6830 | 16 | { "Cell portion ID present", |
6831 | 16 | "fp.rach.cell-portion-id-present", FT_UINT8, BASE_DEC, 0, 0x01, |
6832 | 16 | NULL, HFILL |
6833 | 16 | } |
6834 | 16 | }, |
6835 | 16 | { &hf_fp_rach_angle_of_arrival_present, |
6836 | 16 | { "Angle of arrival present", |
6837 | 16 | "fp.rach.angle-of-arrival-present", FT_UINT8, BASE_DEC, 0, 0x01, |
6838 | 16 | NULL, HFILL |
6839 | 16 | } |
6840 | 16 | }, |
6841 | 16 | { &hf_fp_rach_ext_propagation_delay_present, |
6842 | 16 | { "Ext Propagation Delay Present", |
6843 | 16 | "fp.rach.ext-propagation-delay-present", FT_UINT8, BASE_DEC, 0, 0x02, |
6844 | 16 | NULL, HFILL |
6845 | 16 | } |
6846 | 16 | }, |
6847 | 16 | { &hf_fp_rach_ext_rx_sync_ul_timing_deviation_present, |
6848 | 16 | { "Ext Received Sync UL Timing Deviation present", |
6849 | 16 | "fp.rach.ext-rx-sync-ul-timing-deviation-present", FT_UINT8, BASE_DEC, 0, 0x02, |
6850 | 16 | NULL, HFILL |
6851 | 16 | } |
6852 | 16 | }, |
6853 | 16 | { &hf_fp_rach_ext_rx_timing_deviation_present, |
6854 | 16 | { "Ext Rx Timing Deviation present", |
6855 | 16 | "fp.rach.ext-rx-timing-deviation-present", FT_UINT8, BASE_DEC, 0, 0x01, |
6856 | 16 | NULL, HFILL |
6857 | 16 | } |
6858 | 16 | }, |
6859 | 16 | { &hf_fp_cell_portion_id, |
6860 | 16 | { "Cell Portion ID", |
6861 | 16 | "fp.cell-portion-id", FT_UINT8, BASE_DEC, NULL, 0x3f, |
6862 | 16 | NULL, HFILL |
6863 | 16 | } |
6864 | 16 | }, |
6865 | 16 | { &hf_fp_ext_propagation_delay, |
6866 | 16 | { "Ext Propagation Delay", |
6867 | 16 | "fp.ext-propagation-delay", FT_UINT16, BASE_DEC, NULL, 0x03ff, |
6868 | 16 | NULL, HFILL |
6869 | 16 | } |
6870 | 16 | }, |
6871 | 16 | { &hf_fp_angle_of_arrival, |
6872 | 16 | { "Angle of Arrival", |
6873 | 16 | "fp.angle-of-arrival", FT_UINT16, BASE_DEC, NULL, 0x03ff, |
6874 | 16 | NULL, HFILL |
6875 | 16 | } |
6876 | 16 | }, |
6877 | 16 | { &hf_fp_ext_received_sync_ul_timing_deviation, |
6878 | 16 | { "Ext Received SYNC UL Timing Deviation", |
6879 | 16 | "fp.ext-received-sync-ul-timing-deviation", FT_UINT16, BASE_DEC, NULL, 0x1fff, |
6880 | 16 | NULL, HFILL |
6881 | 16 | } |
6882 | 16 | }, |
6883 | | |
6884 | | |
6885 | 16 | { &hf_fp_radio_interface_parameter_update_flag[0], |
6886 | 16 | { "CFN valid", |
6887 | 16 | "fp.radio-interface-param.cfn-valid", FT_UINT16, BASE_DEC, 0, 0x0001, |
6888 | 16 | NULL, HFILL |
6889 | 16 | } |
6890 | 16 | }, |
6891 | 16 | { &hf_fp_radio_interface_parameter_update_flag[1], |
6892 | 16 | { "TPC PO valid", |
6893 | 16 | "fp.radio-interface-param.tpc-po-valid", FT_UINT16, BASE_DEC, 0, 0x0002, |
6894 | 16 | NULL, HFILL |
6895 | 16 | } |
6896 | 16 | }, |
6897 | 16 | { &hf_fp_radio_interface_parameter_update_flag[2], |
6898 | 16 | { "DPC mode valid", |
6899 | 16 | "fp.radio-interface-param.dpc-mode-valid", FT_UINT16, BASE_DEC, 0, 0x0004, |
6900 | 16 | NULL, HFILL |
6901 | 16 | } |
6902 | 16 | }, |
6903 | 16 | { &hf_fp_radio_interface_parameter_update_flag[3], |
6904 | 16 | { "RL sets indicator valid", |
6905 | 16 | "fp.radio-interface_param.rl-sets-indicator-valid", FT_UINT16, BASE_DEC, 0, 0x0020, |
6906 | 16 | NULL, HFILL |
6907 | 16 | } |
6908 | 16 | }, |
6909 | 16 | { &hf_fp_radio_interface_parameter_update_flag[4], |
6910 | 16 | { "Maximum UE TX Power valid", |
6911 | 16 | "fp.radio-interface-param.max-ue-tx-pow-valid", FT_UINT16, BASE_DEC, 0, 0x0040, |
6912 | 16 | "MAX UE TX POW valid", HFILL |
6913 | 16 | } |
6914 | 16 | }, |
6915 | 16 | { &hf_fp_dpc_mode, |
6916 | 16 | { "DPC Mode", |
6917 | 16 | "fp.dpc-mode", FT_UINT8, BASE_DEC, NULL, 0x20, |
6918 | 16 | "DPC Mode to be applied in the uplink", HFILL |
6919 | 16 | } |
6920 | 16 | }, |
6921 | 16 | { &hf_fp_tpc_po, |
6922 | 16 | { "TPC Power Offset", |
6923 | 16 | "fp.tpc-po", FT_FLOAT, BASE_NONE, NULL, 0x0, |
6924 | 16 | NULL, HFILL |
6925 | 16 | } |
6926 | 16 | }, |
6927 | 16 | { &hf_fp_multiple_rl_set_indicator, |
6928 | 16 | { "Multiple RL sets indicator", |
6929 | 16 | "fp.multiple-rl-sets-indicator", FT_UINT8, BASE_DEC, NULL, 0x80, |
6930 | 16 | NULL, HFILL |
6931 | 16 | } |
6932 | 16 | }, |
6933 | 16 | { &hf_fp_max_ue_tx_pow, |
6934 | 16 | { "Maximum UE TX Power", |
6935 | 16 | "fp.max-ue-tx-pow", FT_INT8, BASE_DEC, NULL, 0x0, |
6936 | 16 | "Max UE TX POW (dBm)", HFILL |
6937 | 16 | } |
6938 | 16 | }, |
6939 | 16 | { &hf_fp_congestion_status, |
6940 | 16 | { "Congestion Status", |
6941 | 16 | "fp.congestion-status", FT_UINT8, BASE_DEC, VALS(congestion_status_vals), 0x0, |
6942 | 16 | NULL, HFILL |
6943 | 16 | } |
6944 | 16 | }, |
6945 | 16 | { &hf_fp_e_rucch_present, |
6946 | 16 | { "E-RUCCH Present", |
6947 | 16 | "fp.erucch-present", FT_UINT8, BASE_DEC, NULL, 0x0, |
6948 | 16 | NULL, HFILL |
6949 | 16 | } |
6950 | 16 | }, |
6951 | 16 | { &hf_fp_extended_bits_present, |
6952 | 16 | { "Extended Bits Present", |
6953 | 16 | "fp.extended-bits-present", FT_UINT8, BASE_DEC, NULL, 0x0, |
6954 | 16 | NULL, HFILL |
6955 | 16 | } |
6956 | 16 | }, |
6957 | 16 | { &hf_fp_extended_bits, |
6958 | 16 | { "Extended Bits", |
6959 | 16 | "fp.extended-bits", FT_UINT8, BASE_HEX, NULL, 0x0, |
6960 | 16 | NULL, HFILL |
6961 | 16 | } |
6962 | 16 | }, |
6963 | 16 | { &hf_fp_spare_extension, |
6964 | 16 | { "Spare Extension", |
6965 | 16 | "fp.spare-extension", FT_NONE, BASE_NONE, NULL, 0x0, |
6966 | 16 | NULL, HFILL |
6967 | 16 | } |
6968 | 16 | }, |
6969 | 16 | { &hf_fp_ul_setup_frame, |
6970 | 16 | { "UL setup frame", |
6971 | 16 | "fp.ul.setup_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
6972 | 16 | NULL, HFILL |
6973 | 16 | } |
6974 | 16 | }, |
6975 | 16 | { &hf_fp_dl_setup_frame, |
6976 | 16 | { "DL setup frame", |
6977 | 16 | "fp.dl.setup_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
6978 | 16 | NULL, HFILL |
6979 | 16 | } |
6980 | 16 | }, |
6981 | 16 | { &hf_fp_relevant_pi_frame, |
6982 | 16 | { "Paging Indications frame number", |
6983 | 16 | "fp.pch.relevant-pi-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, |
6984 | 16 | "The frame where this Paging Indication bitmap was found", |
6985 | 16 | HFILL |
6986 | 16 | } |
6987 | 16 | }, |
6988 | 16 | { &hf_fp_hsdsch_physical_layer_category, |
6989 | 16 | { "HS-DSCH physical layer category", |
6990 | 16 | "fp.hsdsch.physical_layer_category", FT_UINT8, BASE_DEC, NULL, 0x0, |
6991 | 16 | NULL, HFILL |
6992 | 16 | } |
6993 | 16 | } |
6994 | 16 | }; |
6995 | | |
6996 | | |
6997 | 16 | static int *ett[] = |
6998 | 16 | { |
6999 | 16 | &ett_fp, |
7000 | 16 | &ett_fp_data, |
7001 | 16 | &ett_fp_crcis, |
7002 | 16 | &ett_fp_ddi_config, |
7003 | 16 | &ett_fp_edch_subframe_header, |
7004 | 16 | &ett_fp_edch_subframe, |
7005 | 16 | &ett_fp_edch_maces, |
7006 | 16 | &ett_fp_edch_macis_descriptors, |
7007 | 16 | &ett_fp_hsdsch_new_ie_flags, |
7008 | 16 | &ett_fp_rach_new_ie_flags, |
7009 | 16 | &ett_fp_hsdsch_pdu_block_header, |
7010 | 16 | &ett_fp_pch_relevant_pi, |
7011 | 16 | &ett_fp_release |
7012 | 16 | }; |
7013 | | |
7014 | 16 | static ei_register_info ei[] = { |
7015 | 16 | { &ei_fp_bad_header_checksum, { "fp.header.bad_checksum", PI_CHECKSUM, PI_WARN, "Bad header checksum", EXPFILL }}, |
7016 | 16 | { &ei_fp_crci_no_subdissector, { "fp.crci.no_subdissector", PI_UNDECODED, PI_NOTE, "Not sent to subdissectors as CRCI is set", EXPFILL }}, |
7017 | 16 | { &ei_fp_crci_error_bit_set_for_tb, { "fp.crci.error_bit_set_for_tb", PI_CHECKSUM, PI_WARN, "CRCI error bit set for TB", EXPFILL }}, |
7018 | 16 | { &ei_fp_spare_extension, { "fp.spare-extension.expert", PI_UNDECODED, PI_WARN, "Spare Extension present", EXPFILL }}, |
7019 | 16 | { &ei_fp_bad_payload_checksum, { "fp.payload-crc.bad", PI_CHECKSUM, PI_WARN, "Bad payload checksum", EXPFILL }}, |
7020 | 16 | { &ei_fp_stop_hsdpa_transmission, { "fp.stop_hsdpa_transmission", PI_RESPONSE_CODE, PI_NOTE, "Stop HSDPA transmission", EXPFILL }}, |
7021 | 16 | { &ei_fp_timing_adjustment_reported, { "fp.timing_adjustment_reported", PI_SEQUENCE, PI_WARN, "Timing adjustment reported", EXPFILL }}, |
7022 | 16 | { &ei_fp_expecting_tdd, { "fp.expecting_tdd", PI_MALFORMED, PI_NOTE, "Error: expecting TDD-384 or TDD-768", EXPFILL }}, |
7023 | 16 | { &ei_fp_ddi_not_defined, { "fp.ddi_not_defined", PI_MALFORMED, PI_ERROR, "DDI not defined for this UE!", EXPFILL }}, |
7024 | 16 | { &ei_fp_unable_to_locate_ddi_entry, { "fp.unable_to_locate_ddi_entry", PI_UNDECODED, PI_ERROR, "Unable to locate DDI entry.", EXPFILL }}, |
7025 | 16 | { &ei_fp_mac_is_sdus_miscount, { "fp.mac_is_sdus.miscount", PI_MALFORMED, PI_ERROR, "Found too many MAC-is SDUs", EXPFILL }}, |
7026 | 16 | { &ei_fp_e_rnti_t2_edch_frames, { "fp.e_rnti.t2_edch_frames", PI_MALFORMED, PI_ERROR, "E-RNTI not supposed to appear for T2 EDCH frames", EXPFILL }}, |
7027 | 16 | { &ei_fp_e_rnti_first_entry, { "fp.e_rnti.first_entry", PI_MALFORMED, PI_ERROR, "E-RNTI must be first entry among descriptors", EXPFILL }}, |
7028 | 16 | { &ei_fp_maybe_srb, { "fp.maybe_srb", PI_PROTOCOL, PI_NOTE, "Found MACd-Flow = 0 and not MUX detected. (This might be SRB)", EXPFILL }}, |
7029 | 16 | { &ei_fp_transport_channel_type_unknown, { "fp.transport_channel_type.unknown", PI_UNDECODED, PI_WARN, "Unknown transport channel type", EXPFILL }}, |
7030 | 16 | { &ei_fp_pch_lost_relevant_pi_frame, { "fp.pch_lost_relevant_pi_frame", PI_SEQUENCE, PI_WARN, "Previous PCH frame containing PI bitmap not captured (common at capture start)", EXPFILL }}, |
7031 | 16 | { &ei_fp_hsdsch_entity_not_specified, { "fp.hsdsch_entity_not_specified", PI_MALFORMED, PI_ERROR, "HSDSCH Entity not specified", EXPFILL }}, |
7032 | 16 | { &ei_fp_hsdsch_common_experimental_support, { "fp.hsdsch_common.experimental_support", PI_DEBUG, PI_WARN, "HSDSCH COMMON - Experimental support!", EXPFILL }}, |
7033 | 16 | { &ei_fp_hsdsch_common_t3_not_implemented, { "fp.hsdsch_common_t3.not_implemented", PI_DEBUG, PI_ERROR, "HSDSCH COMMON T3 - Not implemented!", EXPFILL }}, |
7034 | 16 | { &ei_fp_channel_type_unknown, { "fp.channel_type.unknown", PI_MALFORMED, PI_ERROR, "Unknown channel type", EXPFILL }}, |
7035 | 16 | { &ei_fp_no_per_frame_info, { "fp.no_per_frame_info", PI_UNDECODED, PI_ERROR, "Can't dissect FP frame because no per-frame info was attached!", EXPFILL }}, |
7036 | 16 | { &ei_fp_no_per_conv_channel_info, { "fp.no_per_conv_channel_info", PI_UNDECODED, PI_ERROR, "Can't dissect this FP stream because no per-conversation channel info was attached!", EXPFILL }}, |
7037 | 16 | { &ei_fp_invalid_frame_count, { "fp.invalid_frame_count", PI_MALFORMED, PI_ERROR, "Invalid frame count", EXPFILL }}, |
7038 | 16 | { &ei_fp_invalid_ddi_count, { "fp.invalid_ddi_count", PI_MALFORMED, PI_ERROR, "Invalid E-DCH DDI count", EXPFILL }}, |
7039 | 16 | }; |
7040 | | |
7041 | 16 | module_t *fp_module; |
7042 | 16 | expert_module_t *expert_fp; |
7043 | | |
7044 | | /* Register protocol. */ |
7045 | 16 | proto_fp = proto_register_protocol("FP", "FP", "fp"); |
7046 | 16 | proto_register_field_array(proto_fp, hf, array_length(hf)); |
7047 | 16 | proto_register_subtree_array(ett, array_length(ett)); |
7048 | 16 | expert_fp = expert_register_protocol(proto_fp); |
7049 | 16 | expert_register_field_array(expert_fp, ei, array_length(ei)); |
7050 | | |
7051 | | /* Allow other dissectors to find this one by name. */ |
7052 | 16 | fp_handle = register_dissector("fp", dissect_fp, proto_fp); |
7053 | 16 | fp_aal2_handle = register_dissector("fp.aal2", dissect_fp_aal2, proto_fp); |
7054 | | |
7055 | | /* Preferences */ |
7056 | 16 | fp_module = prefs_register_protocol(proto_fp, NULL); |
7057 | | |
7058 | | /* Determines whether release information should be displayed */ |
7059 | 16 | prefs_register_bool_preference(fp_module, "show_release_info", |
7060 | 16 | "Show reported release info", |
7061 | 16 | "Show reported release info", |
7062 | 16 | &preferences_show_release_info); |
7063 | | |
7064 | | /* Determines whether MAC dissector should be called for payloads */ |
7065 | 16 | prefs_register_bool_preference(fp_module, "call_mac", |
7066 | 16 | "Call MAC dissector for payloads", |
7067 | 16 | "Call MAC dissector for payloads", |
7068 | 16 | &preferences_call_mac_dissectors); |
7069 | | /* Determines whether or not to validate FP payload checksums */ |
7070 | 16 | prefs_register_bool_preference(fp_module, "payload_checksum", |
7071 | 16 | "Validate FP payload checksums", |
7072 | 16 | "Validate FP payload checksums", |
7073 | 16 | &preferences_payload_checksum); |
7074 | | /* Determines whether or not to validate FP header checksums */ |
7075 | 16 | prefs_register_bool_preference(fp_module, "header_checksum", |
7076 | 16 | "Validate FP header checksums", |
7077 | 16 | "Validate FP header checksums", |
7078 | 16 | &preferences_header_checksum); |
7079 | | /* Determines whether or not to track Paging Indications between PCH frames*/ |
7080 | 16 | prefs_register_bool_preference(fp_module, "track_paging_indications", |
7081 | 16 | "Track Paging Indications in PCH channels", |
7082 | 16 | "For each PCH data frame, Try to show the paging indications bitmap found in the previous frame", |
7083 | 16 | &preferences_track_paging_indications); |
7084 | 16 | prefs_register_obsolete_preference(fp_module, "udp_heur"); |
7085 | 16 | prefs_register_obsolete_preference(fp_module, "epandchannelconfigurationtable"); |
7086 | | |
7087 | 16 | } |
7088 | | |
7089 | | |
7090 | | void proto_reg_handoff_fp(void) |
7091 | 16 | { |
7092 | 16 | proto_umts_mac = proto_get_id_by_filter_name("mac"); |
7093 | 16 | proto_umts_rlc = proto_get_id_by_filter_name("rlc"); |
7094 | | |
7095 | 16 | rlc_bcch_handle = find_dissector_add_dependency("rlc.bcch", proto_fp); |
7096 | 16 | mac_fdd_rach_handle = find_dissector_add_dependency("mac.fdd.rach", proto_fp); |
7097 | 16 | mac_fdd_fach_handle = find_dissector_add_dependency("mac.fdd.fach", proto_fp); |
7098 | 16 | mac_fdd_pch_handle = find_dissector_add_dependency("mac.fdd.pch", proto_fp); |
7099 | 16 | mac_fdd_dch_handle = find_dissector_add_dependency("mac.fdd.dch", proto_fp); |
7100 | 16 | mac_fdd_edch_handle = find_dissector_add_dependency("mac.fdd.edch", proto_fp); |
7101 | 16 | mac_fdd_edch_type2_handle = find_dissector_add_dependency("mac.fdd.edch.type2", proto_fp); |
7102 | 16 | mac_fdd_hsdsch_handle = find_dissector_add_dependency("mac.fdd.hsdsch", proto_fp); |
7103 | | |
7104 | 16 | heur_dissector_add("udp", heur_dissect_fp, "FP over UDP", "fp_udp", proto_fp, HEURISTIC_DISABLE); |
7105 | 16 | heur_dissector_add("fp_mux", heur_dissect_fp, "FP over FP Mux", "fp_fp_mux", proto_fp, HEURISTIC_ENABLE); |
7106 | | |
7107 | 16 | dissector_add_uint("atm.aal2.type", TRAF_UMTS_FP, fp_aal2_handle); |
7108 | 16 | } |
7109 | | |
7110 | | /* |
7111 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
7112 | | * |
7113 | | * Local variables: |
7114 | | * c-basic-offset: 4 |
7115 | | * tab-width: 8 |
7116 | | * indent-tabs-mode: nil |
7117 | | * End: |
7118 | | * |
7119 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
7120 | | * :indentSize=4:tabSize=8:noTabs=true: |
7121 | | */ |