1 /* Routines for LTE RLC disassembly
2 *
3 * Martin Mathieson
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "config.h"
13
14 #include <epan/packet.h>
15 #include <epan/exceptions.h>
16 #include <epan/expert.h>
17 #include <epan/prefs.h>
18 #include <epan/tap.h>
19 #include <epan/proto_data.h>
20 #include "packet-mac-lte.h"
21 #include "packet-rlc-lte.h"
22 #include "packet-pdcp-lte.h"
23
24
25 /* Described in:
26 * 3GPP TS 36.322 Evolved Universal Terrestial Radio Access (E-UTRA)
27 * Radio Link Control (RLC) Protocol specification v14.0.0
28 */
29
30 /* TODO:
31 - add intermediate results to segments leading to final reassembly
32 - use multiple active rlc_channel_reassembly_info's per channel
33 - sequence analysis gets confused when we change cells and skip back
34 to SN 0. Maybe add cell-id to context and add to channel/result key?
35 */
36
37 void proto_register_rlc_lte(void);
38 void proto_reg_handoff_rlc_lte(void);
39
40 /********************************/
41 /* Preference settings */
42
43 #define SEQUENCE_ANALYSIS_MAC_ONLY 1
44 #define SEQUENCE_ANALYSIS_RLC_ONLY 2
45
46 /* By default do try to analyse the sequence of messages for AM/UM channels
47 using MAC PDUs */
48 static gint global_rlc_lte_am_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY;
49 static gint global_rlc_lte_um_sequence_analysis = SEQUENCE_ANALYSIS_MAC_ONLY;
50
51 /* By default do call PDCP/RRC dissectors for SDU data */
52 static gboolean global_rlc_lte_call_pdcp_for_srb = TRUE;
53
54 enum pdcp_for_drb { PDCP_drb_off, PDCP_drb_SN_7, PDCP_drb_SN_12, PDCP_drb_SN_signalled, PDCP_drb_SN_15, PDCP_drb_SN_18};
55 static const enum_val_t pdcp_drb_col_vals[] = {
56 {"pdcp-drb-off", "Off", PDCP_drb_off},
57 {"pdcp-drb-sn-7", "7-bit SN", PDCP_drb_SN_7},
58 {"pdcp-drb-sn-12", "12-bit SN", PDCP_drb_SN_12},
59 {"pdcp-drb-sn-15", "15-bit SN", PDCP_drb_SN_15},
60 {"pdcp-drb-sn-18", "18-bit SN", PDCP_drb_SN_18},
61 {"pdcp-drb-sn-signalling", "Use signalled value", PDCP_drb_SN_signalled},
62 {NULL, NULL, -1}
63 };
64 static gint global_rlc_lte_call_pdcp_for_drb = (gint)PDCP_drb_SN_signalled;
65
66 static gboolean global_rlc_lte_call_rrc_for_ccch = TRUE;
67 static gboolean global_rlc_lte_call_rrc_for_mcch = FALSE;
68 static gboolean global_rlc_lte_call_ip_for_mtch = FALSE;
69
70 /* Preference to expect RLC headers without payloads */
71 static gboolean global_rlc_lte_headers_expected = FALSE;
72
73 /* Re-assembly of segments */
74 static gboolean global_rlc_lte_reassembly = TRUE;
75
76 /* Tree storing UE related parameters */
77 #define NO_EXT_LI 0x0
78 #define UL_EXT_LI 0x1
79 #define DL_EXT_LI 0x2
80 typedef struct rlc_ue_parameters {
81 guint32 id;
82 guint8 ext_li_field;
83 guint8 pdcp_sn_bits;
84 } rlc_ue_parameters;
85 static wmem_tree_t *ue_parameters_tree;
86
87 /**************************************************/
88 /* Initialize the protocol and registered fields. */
89 int proto_rlc_lte = -1;
90
91 extern int proto_mac_lte;
92 extern int proto_pdcp_lte;
93
94 static dissector_handle_t pdcp_lte_handle;
95 static dissector_handle_t ip_handle;
96 static dissector_handle_t lte_rrc_mcch;
97 static dissector_handle_t lte_rrc_ul_ccch;
98 static dissector_handle_t lte_rrc_dl_ccch;
99 static dissector_handle_t lte_rrc_bcch_bch;
100 static dissector_handle_t lte_rrc_bcch_dl_sch;
101 static dissector_handle_t lte_rrc_pcch;
102 static dissector_handle_t lte_rrc_ul_ccch_nb;
103 static dissector_handle_t lte_rrc_dl_ccch_nb;
104 static dissector_handle_t lte_rrc_bcch_bch_nb;
105 static dissector_handle_t lte_rrc_bcch_dl_sch_nb;
106 static dissector_handle_t lte_rrc_pcch_nb;
107
108
109 static int rlc_lte_tap = -1;
110
111 /* Decoding context */
112 static int hf_rlc_lte_context = -1;
113 static int hf_rlc_lte_context_mode = -1;
114 static int hf_rlc_lte_context_direction = -1;
115 static int hf_rlc_lte_context_priority = -1;
116 static int hf_rlc_lte_context_ueid = -1;
117 static int hf_rlc_lte_context_channel_type = -1;
118 static int hf_rlc_lte_context_channel_id = -1;
119 static int hf_rlc_lte_context_pdu_length = -1;
120 static int hf_rlc_lte_context_um_sn_length = -1;
121 static int hf_rlc_lte_context_am_sn_length = -1;
122
123 /* Transparent mode fields */
124 static int hf_rlc_lte_tm = -1;
125 static int hf_rlc_lte_tm_data = -1;
126
127 /* Unacknowledged mode fields */
128 static int hf_rlc_lte_um = -1;
129 static int hf_rlc_lte_um_header = -1;
130 static int hf_rlc_lte_um_fi = -1;
131 static int hf_rlc_lte_um_fixed_e = -1;
132 static int hf_rlc_lte_um_sn = -1;
133 static int hf_rlc_lte_um_fixed_reserved = -1;
134 static int hf_rlc_lte_um_data = -1;
135 static int hf_rlc_lte_extension_part = -1;
136
137 /* Extended header (common to UM and AM) */
138 static int hf_rlc_lte_extension_e = -1;
139 static int hf_rlc_lte_extension_li = -1;
140 static int hf_rlc_lte_extension_padding = -1;
141
142
143 /* Acknowledged mode fields */
144 static int hf_rlc_lte_am = -1;
145 static int hf_rlc_lte_am_header = -1;
146 static int hf_rlc_lte_am_data_control = -1;
147 static int hf_rlc_lte_am_rf = -1;
148 static int hf_rlc_lte_am_p = -1;
149 static int hf_rlc_lte_am_fi = -1;
150 static int hf_rlc_lte_am_fixed_e = -1;
151 static int hf_rlc_lte_am_fixed_sn = -1;
152 static int hf_rlc_lte_am_fixed_reserved = -1;
153 static int hf_rlc_lte_am_segment_lsf16 = -1;
154 static int hf_rlc_lte_am_fixed_reserved2 = -1;
155 static int hf_rlc_lte_am_fixed_sn16 = -1;
156 static int hf_rlc_lte_am_segment_lsf = -1;
157 static int hf_rlc_lte_am_segment_so = -1;
158 static int hf_rlc_lte_am_segment_so16 = -1;
159 static int hf_rlc_lte_am_data = -1;
160
161 /* Control fields */
162 static int hf_rlc_lte_am_cpt = -1;
163 static int hf_rlc_lte_am_ack_sn = -1;
164 static int hf_rlc_lte_am_e1 = -1;
165 static int hf_rlc_lte_am_e2 = -1;
166 static int hf_rlc_lte_am_nack_sn = -1;
167 static int hf_rlc_lte_am_nacks = -1;
168 static int hf_rlc_lte_am_so_start = -1;
169 static int hf_rlc_lte_am_so_end = -1;
170
171 static int hf_rlc_lte_predefined_pdu = -1;
172 static int hf_rlc_lte_header_only = -1;
173
174 /* Sequence Analysis */
175 static int hf_rlc_lte_sequence_analysis = -1;
176 static int hf_rlc_lte_sequence_analysis_ok = -1;
177 static int hf_rlc_lte_sequence_analysis_previous_frame = -1;
178 static int hf_rlc_lte_sequence_analysis_next_frame = -1;
179 static int hf_rlc_lte_sequence_analysis_expected_sn = -1;
180 static int hf_rlc_lte_sequence_analysis_framing_info_correct = -1;
181
182 static int hf_rlc_lte_sequence_analysis_mac_retx = -1;
183 static int hf_rlc_lte_sequence_analysis_retx = -1;
184 static int hf_rlc_lte_sequence_analysis_repeated = -1;
185 static int hf_rlc_lte_sequence_analysis_skipped = -1;
186
187 static int hf_rlc_lte_sequence_analysis_repeated_nack = -1;
188 static int hf_rlc_lte_sequence_analysis_repeated_nack_original_frame = -1;
189
190 static int hf_rlc_lte_sequence_analysis_ack_out_of_range = -1;
191 static int hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = -1;
192
193 /* Reassembly */
194 static int hf_rlc_lte_reassembly_source = -1;
195 static int hf_rlc_lte_reassembly_source_number_of_segments = -1;
196 static int hf_rlc_lte_reassembly_source_total_length = -1;
197 static int hf_rlc_lte_reassembly_source_segment = -1;
198 static int hf_rlc_lte_reassembly_source_segment_sn = -1;
199 static int hf_rlc_lte_reassembly_source_segment_framenum = -1;
200 static int hf_rlc_lte_reassembly_source_segment_length = -1;
201
202 /* Subtrees. */
203 static int ett_rlc_lte = -1;
204 static int ett_rlc_lte_context = -1;
205 static int ett_rlc_lte_um_header = -1;
206 static int ett_rlc_lte_am_header = -1;
207 static int ett_rlc_lte_extension_part = -1;
208 static int ett_rlc_lte_sequence_analysis = -1;
209 static int ett_rlc_lte_reassembly_source = -1;
210 static int ett_rlc_lte_reassembly_source_segment = -1;
211
212 static expert_field ei_rlc_lte_context_mode = EI_INIT;
213 static expert_field ei_rlc_lte_am_nack_sn = EI_INIT;
214 static expert_field ei_rlc_lte_am_nack_sn_ahead_ack = EI_INIT;
215 static expert_field ei_rlc_lte_um_sn_repeated = EI_INIT;
216 static expert_field ei_rlc_lte_am_nack_sn_ack_same = EI_INIT;
217 static expert_field ei_rlc_lte_am_cpt = EI_INIT;
218 static expert_field ei_rlc_lte_am_data_no_data = EI_INIT;
219 static expert_field ei_rlc_lte_sequence_analysis_last_segment_complete = EI_INIT;
220 static expert_field ei_rlc_lte_sequence_analysis_mac_retx = EI_INIT;
221 static expert_field ei_rlc_lte_am_nack_sn_partial = EI_INIT;
222 static expert_field ei_rlc_lte_sequence_analysis_repeated_nack = EI_INIT;
223 static expert_field ei_rlc_lte_bytes_after_status_pdu_complete = EI_INIT;
224 static expert_field ei_rlc_lte_sequence_analysis_repeated = EI_INIT;
225 static expert_field ei_rlc_lte_wrong_sequence_number = EI_INIT;
226 static expert_field ei_rlc_lte_sequence_analysis_retx = EI_INIT;
227 static expert_field ei_rlc_lte_am_sn_missing = EI_INIT;
228 static expert_field ei_rlc_lte_um_sn = EI_INIT;
229 static expert_field ei_rlc_lte_header_only = EI_INIT;
230 static expert_field ei_rlc_lte_am_data_no_data_beyond_extensions = EI_INIT;
231 static expert_field ei_rlc_lte_um_sn_missing = EI_INIT;
232 static expert_field ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame = EI_INIT;
233 static expert_field ei_rlc_lte_sequence_analysis_last_segment_not_continued = EI_INIT;
234 static expert_field ei_rlc_lte_reserved_bits_not_zero = EI_INIT;
235 static expert_field ei_rlc_lte_no_per_frame_info = EI_INIT;
236 static expert_field ei_rlc_lte_unknown_udp_framing_tag = EI_INIT;
237 static expert_field ei_rlc_lte_missing_udp_framing_tag = EI_INIT;
238
239 /* Value-strings */
240 static const value_string direction_vals[] =
241 {
242 { DIRECTION_UPLINK, "Uplink"},
243 { DIRECTION_DOWNLINK, "Downlink"},
244 { 0, NULL }
245 };
246
247 static const value_string rlc_mode_short_vals[] =
248 {
249 { RLC_TM_MODE, "TM"},
250 { RLC_UM_MODE, "UM"},
251 { RLC_AM_MODE, "AM"},
252 { RLC_PREDEF, "PREDEFINED"}, /* For data testing */
253 { 0, NULL }
254 };
255
256 static const value_string rlc_mode_vals[] =
257 {
258 { RLC_TM_MODE, "Transparent Mode"},
259 { RLC_UM_MODE, "Unacknowledged Mode"},
260 { RLC_AM_MODE, "Acknowledged Mode"},
261 { 0, NULL }
262 };
263
264 static const value_string rlc_channel_type_vals[] =
265 {
266 { CHANNEL_TYPE_CCCH, "CCCH"},
267 { CHANNEL_TYPE_BCCH_BCH, "BCCH_BCH"},
268 { CHANNEL_TYPE_PCCH, "PCCH"},
269 { CHANNEL_TYPE_SRB, "SRB"},
270 { CHANNEL_TYPE_DRB, "DRB"},
271 { CHANNEL_TYPE_BCCH_DL_SCH, "BCCH_DL_SCH"},
272 { CHANNEL_TYPE_MCCH, "MCCH"},
273 { CHANNEL_TYPE_MTCH, "MTCH"},
274 { 0, NULL }
275 };
276
277 static const value_string framing_info_vals[] =
278 {
279 { 0, "First byte begins a RLC SDU and last byte ends a RLC SDU"},
280 { 1, "First byte begins a RLC SDU and last byte does not end a RLC SDU"},
281 { 2, "First byte does not begin a RLC SDU and last byte ends a RLC SDU"},
282 { 3, "First byte does not begin a RLC SDU and last byte does not end a RLC SDU"},
283 { 0, NULL }
284 };
285
286 static const value_string fixed_extension_vals[] =
287 {
288 { 0, "Data field follows from the octet following the fixed part of the header"},
289 { 1, "A set of E field and LI field follows from the octet following the fixed part of the header"},
290 { 0, NULL }
291 };
292
293 static const value_string extension_extension_vals[] =
294 {
295 { 0, "Data field follows from the octet following the LI field following this E field"},
296 { 1, "A set of E field and LI field follows from the bit following the LI field following this E field"},
297 { 0, NULL }
298 };
299
300 static const value_string data_or_control_vals[] =
301 {
302 { 0, "Control PDU"},
303 { 1, "Data PDU"},
304 { 0, NULL }
305 };
306
307 static const value_string resegmentation_flag_vals[] =
308 {
309 { 0, "AMD PDU"},
310 { 1, "AMD PDU segment"},
311 { 0, NULL }
312 };
313
314 static const value_string polling_bit_vals[] =
315 {
316 { 0, "Status report not requested"},
317 { 1, "Status report is requested"},
318 { 0, NULL }
319 };
320
321 static const value_string lsf_vals[] =
322 {
323 { 0, "Last byte of the AMD PDU segment does not correspond to the last byte of an AMD PDU"},
324 { 1, "Last byte of the AMD PDU segment corresponds to the last byte of an AMD PDU"},
325 { 0, NULL }
326 };
327
328 static const value_string control_pdu_type_vals[] =
329 {
330 { 0, "STATUS PDU"},
331 { 0, NULL }
332 };
333
334 static const value_string am_e1_vals[] =
335 {
336 { 0, "A set of NACK_SN, E1 and E2 does not follow"},
337 { 1, "A set of NACK_SN, E1 and E2 follows"},
338 { 0, NULL }
339 };
340
341 static const value_string am_e2_vals[] =
342 {
343 { 0, "A set of SOstart and SOend does not follow for this NACK_SN"},
344 { 1, "A set of SOstart and SOend follows for this NACK_SN"},
345 { 0, NULL }
346 };
347
348 static const value_string header_only_vals[] =
349 {
350 { 0, "RLC PDU Headers and body present"},
351 { 1, "RLC PDU Headers only"},
352 { 0, NULL }
353 };
354
355
356
357 /**********************************************************************************/
358 /* These are for keeping track of UM/AM extension headers, and the lengths found */
359 /* in them */
360 static guint8 s_number_of_extensions = 0;
361 #define MAX_RLC_SDUS 192
362 static guint16 s_lengths[MAX_RLC_SDUS];
363
364
365 /*********************************************************************/
366 /* UM/AM sequence analysis */
367
368 /* Types for RLC channel hash table */
369 /* This table is maintained during initial dissection of RLC */
370 /* frames, mapping from channel_hash_key -> sequence_analysis_report */
371
372 /* Channel key */
373 typedef struct
374 {
375 guint ueId : 16;
376 guint channelType : 3;
377 guint channelId : 5;
378 guint direction : 1;
379 } channel_hash_key;
380
381
382 /******************************************************************/
383 /* State maintained for AM/UM reassembly */
384
385 typedef struct rlc_segment {
386 guint32 frameNum;
387 guint16 SN;
388 guint8 *data;
389 guint16 length;
390 } rlc_segment;
391
392 typedef struct rlc_channel_reassembly_info
393 {
394 guint16 number_of_segments;
395 #define RLC_MAX_SEGMENTS 100
396 rlc_segment segments[RLC_MAX_SEGMENTS];
397 } rlc_channel_reassembly_info;
398
399
400
401
402 /*******************************************************************/
403 /* Conversation-type status for sequence analysis on channel */
404 typedef struct
405 {
406 guint8 rlcMode;
407
408 /* For UM, we always expect the SN to keep advancing, and these fields
409 keep track of this.
410 For AM, these correspond to new data */
411 guint16 previousSequenceNumber;
412 guint32 previousFrameNum;
413 gboolean previousSegmentIncomplete;
414
415 /* Accumulate info about current segmented SDU */
416 struct rlc_channel_reassembly_info *reassembly_info;
417 } channel_sequence_analysis_status;
418
419 /* The sequence analysis channel hash table */
420 static wmem_map_t *sequence_analysis_channel_hash = NULL;
421
422
423 /* Types for sequence analysis frame report hash table */
424 /* This is a table from framenum -> state_report_in_frame */
425 /* This is necessary because the per-packet info is already being used */
426 /* for context information before the dissector is called */
427
428 /* Info to attach to frame when first read, recording what to show about sequence */
429 typedef enum {
430 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing, ACK_Out_of_Window, SN_Error
431 } sequence_analysis_state;
432
433
434 typedef struct
435 {
436 gboolean sequenceExpectedCorrect;
437 guint16 sequenceExpected;
438 guint32 previousFrameNum;
439 gboolean previousSegmentIncomplete;
440 guint32 nextFrameNum;
441
442 guint16 firstSN;
443 guint16 lastSN;
444
445 /* AM/UM */
446 sequence_analysis_state state;
447 } sequence_analysis_report;
448
449
450 /* The sequence analysis frame report hash table instance itself */
451 static wmem_map_t *sequence_analysis_report_hash = NULL;
452
453
454 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
455 rlc_lte_info *p_rlc_lte_info,
456 gboolean do_persist);
457
458
459
460
461 /* The reassembly result hash table */
462 static wmem_map_t *reassembly_report_hash = NULL;
463
464
465 /* Create a new struct for reassembly */
reassembly_reset(channel_sequence_analysis_status * status)466 static void reassembly_reset(channel_sequence_analysis_status *status)
467 {
468 status->reassembly_info = wmem_new0(wmem_file_scope(), rlc_channel_reassembly_info);
469 }
470
471 /* Hide previous one */
reassembly_destroy(channel_sequence_analysis_status * status)472 static void reassembly_destroy(channel_sequence_analysis_status *status)
473 {
474 /* Just "leak" it. There seems to be no way to free this memory... */
475 status->reassembly_info = NULL;
476 }
477
478 /* Add a new segment to the accumulating segmented SDU */
reassembly_add_segment(channel_sequence_analysis_status * status,guint16 SN,guint32 frame,tvbuff_t * tvb,gint offset,gint length)479 static void reassembly_add_segment(channel_sequence_analysis_status *status,
480 guint16 SN, guint32 frame,
481 tvbuff_t *tvb, gint offset, gint length)
482 {
483 int segment_number = status->reassembly_info->number_of_segments;
484 guint8 *segment_data;
485
486 /* Give up if reach segment limit */
487 if (segment_number >= (RLC_MAX_SEGMENTS-1)) {
488 reassembly_destroy(status);
489 return;
490 }
491
492 segment_data = (guint8 *)tvb_memdup(wmem_file_scope(),tvb, offset, length);
493
494 /* Add new segment */
495 status->reassembly_info->segments[segment_number].frameNum = frame;
496 status->reassembly_info->segments[segment_number].SN = SN;
497 status->reassembly_info->segments[segment_number].data = segment_data;
498 status->reassembly_info->segments[segment_number].length = length;
499
500 status->reassembly_info->number_of_segments++;
501 }
502
503
504 /* Record the current & complete segmented SDU by mapping from this frame number to
505 struct with segment info. */
reassembly_record(channel_sequence_analysis_status * status,packet_info * pinfo,guint16 SN,rlc_lte_info * p_rlc_lte_info)506 static void reassembly_record(channel_sequence_analysis_status *status, packet_info *pinfo,
507 guint16 SN, rlc_lte_info *p_rlc_lte_info)
508 {
509 /* Just store existing info in hash table */
510 wmem_map_insert(reassembly_report_hash,
511 get_report_hash_key(SN, pinfo->num, p_rlc_lte_info, TRUE),
512 status->reassembly_info);
513 }
514
515 /* Create and return a tvb based upon contents of reassembly info */
reassembly_get_reassembled_tvb(rlc_channel_reassembly_info * reassembly_info,tvbuff_t * parent_tvb,packet_info * pinfo)516 static tvbuff_t* reassembly_get_reassembled_tvb(rlc_channel_reassembly_info *reassembly_info,
517 tvbuff_t *parent_tvb, packet_info *pinfo)
518 {
519 gint n;
520 guint combined_length = 0;
521 guint8 *combined_data;
522 guint combined_offset = 0;
523 tvbuff_t *reassembled_tvb;
524
525 /* Allocate buffer big enough to hold re-assembled data */
526 for (n=0; n < reassembly_info->number_of_segments; n++) {
527 combined_length += reassembly_info->segments[n].length;
528 }
529 combined_data = (guint8 *)wmem_alloc(pinfo->pool, combined_length);
530
531 /* Copy data into contiguous buffer */
532 for (n=0; n < reassembly_info->number_of_segments; n++) {
533 guint8 *data = reassembly_info->segments[n].data;
534 int length = reassembly_info->segments[n].length;
535 memcpy(combined_data+combined_offset, data, length);
536 combined_offset += length;
537 }
538
539 /* Create and return tvb with this data */
540 reassembled_tvb = tvb_new_child_real_data(parent_tvb, combined_data, combined_offset, combined_offset);
541 add_new_data_source(pinfo, reassembled_tvb, "Reassembled SDU");
542 return reassembled_tvb;
543 }
544
545 /* Show where the segments came from for a reassembled SDU */
reassembly_show_source(rlc_channel_reassembly_info * reassembly_info,proto_tree * tree,tvbuff_t * tvb,gint offset)546 static void reassembly_show_source(rlc_channel_reassembly_info *reassembly_info,
547 proto_tree *tree, tvbuff_t *tvb, gint offset)
548 {
549 int n;
550 proto_item *source_ti, *ti;
551 proto_tree *source_tree;
552 proto_item *segment_ti;
553 proto_tree *segment_tree;
554 guint total_length=0;
555
556 /* Create root of source info */
557 source_ti = proto_tree_add_item(tree,
558 hf_rlc_lte_reassembly_source,
559 tvb, 0, 0, ENC_ASCII|ENC_NA);
560 source_tree = proto_item_add_subtree(source_ti, ett_rlc_lte_reassembly_source);
561 proto_item_set_generated(source_ti);
562
563 for (n=0; n < reassembly_info->number_of_segments; n++) {
564 total_length += reassembly_info->segments[n].length;
565 }
566 proto_item_append_text(source_ti, " %u segments, %u bytes", reassembly_info->number_of_segments,
567 total_length);
568
569 /* Number of segments */
570 ti = proto_tree_add_uint(source_tree,
571 hf_rlc_lte_reassembly_source_number_of_segments,
572 tvb, 0, 0, reassembly_info->number_of_segments);
573 proto_item_set_generated(ti);
574
575 /* Total length */
576 ti = proto_tree_add_uint(source_tree,
577 hf_rlc_lte_reassembly_source_total_length,
578 tvb, 0, 0, total_length);
579 proto_item_set_generated(ti);
580
581 /* Now add info about each segment in turn */
582 for (n=0; n < reassembly_info->number_of_segments; n++) {
583
584 /* Add next segment as a subtree */
585 rlc_segment *segment = &(reassembly_info->segments[n]);
586 proto_item_append_text(source_ti, " (SN=%u frame=%u len=%u)",
587 segment->SN, segment->frameNum, segment->length);
588
589 /* N.B. assume last segment from passed-in tvb! */
590 segment_ti = proto_tree_add_item(source_tree,
591 hf_rlc_lte_reassembly_source_segment,
592 tvb,
593 (n == reassembly_info->number_of_segments-1) ? offset : 0,
594 (n == reassembly_info->number_of_segments-1) ? segment->length : 0,
595 ENC_NA);
596 segment_tree = proto_item_add_subtree(segment_ti, ett_rlc_lte_reassembly_source_segment);
597 proto_item_append_text(segment_ti, " (SN=%u frame=%u length=%u)",
598 segment->SN, segment->frameNum, segment->length);
599 proto_item_set_generated(segment_ti);
600
601 /* Add details to segment tree */
602 ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_sn,
603 tvb, 0, 0, segment->SN);
604 proto_item_set_generated(ti);
605 ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_framenum,
606 tvb, 0, 0, segment->frameNum);
607 proto_item_set_generated(ti);
608 ti = proto_tree_add_uint(segment_tree, hf_rlc_lte_reassembly_source_segment_length,
609 tvb, 0, 0, segment->length);
610 proto_item_set_generated(ti);
611 }
612 }
613
614
615
616
617 /******************************************************************/
618 /* Conversation-type status for repeated NACK checking on channel */
619 typedef struct
620 {
621 guint16 noOfNACKs;
622 guint16 NACKs[MAX_NACKs];
623 guint32 frameNum;
624 } channel_repeated_nack_status;
625
626 static wmem_map_t *repeated_nack_channel_hash = NULL;
627
628 typedef struct {
629 guint16 noOfNACKsRepeated;
630 guint16 repeatedNACKs[MAX_NACKs];
631 guint32 previousFrameNum;
632 } channel_repeated_nack_report;
633
634 static wmem_map_t *repeated_nack_report_hash = NULL;
635
636
637
638 /********************************************************/
639 /* Forward declarations & functions */
640 static void dissect_rlc_lte_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing);
641
642
643 /* Write the given formatted text to:
644 - the info column
645 - the top-level RLC PDU item
646 - another subtree item (if supplied) */
write_pdu_label_and_info(proto_item * pdu_ti,proto_item * sub_ti,packet_info * pinfo,const char * format,...)647 static void write_pdu_label_and_info(proto_item *pdu_ti, proto_item *sub_ti,
648 packet_info *pinfo, const char *format, ...)
649 {
650 #define MAX_INFO_BUFFER 256
651 static char info_buffer[MAX_INFO_BUFFER];
652
653 va_list ap;
654
655 va_start(ap, format);
656 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
657 va_end(ap);
658
659 /* Add to indicated places */
660 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
661 proto_item_append_text(pdu_ti, "%s", info_buffer);
662 if (sub_ti != NULL) {
663 proto_item_append_text(sub_ti, "%s", info_buffer);
664 }
665 }
666
667 /* Version of function above, where no g_vsnprintf() call needed
668 - the info column
669 - the top-level RLC PDU item
670 - another subtree item (if supplied) */
write_pdu_label_and_info_literal(proto_item * pdu_ti,proto_item * sub_ti,packet_info * pinfo,const char * info_buffer)671 static void write_pdu_label_and_info_literal(proto_item *pdu_ti, proto_item *sub_ti,
672 packet_info *pinfo, const char *info_buffer)
673 {
674 /* Add to indicated places */
675 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
676 proto_item_append_text(pdu_ti, "%s", info_buffer);
677 if (sub_ti != NULL) {
678 proto_item_append_text(sub_ti, "%s", info_buffer);
679 }
680 }
681
682
683
684 /* Dissect extension headers (common to both UM and AM) */
dissect_rlc_lte_extension_header(tvbuff_t * tvb,packet_info * pinfo _U_,proto_tree * tree,int offset,rlc_lte_info * p_rlc_lte_info)685 static int dissect_rlc_lte_extension_header(tvbuff_t *tvb, packet_info *pinfo _U_,
686 proto_tree *tree,
687 int offset,
688 rlc_lte_info *p_rlc_lte_info)
689 {
690 guint8 isOdd;
691 guint64 extension = 1;
692 guint64 length;
693
694 /* Reset this count */
695 s_number_of_extensions = 0;
696
697 while (extension && (s_number_of_extensions < MAX_RLC_SDUS)) {
698 proto_tree *extension_part_tree;
699 proto_item *extension_part_ti;
700
701 /* Extension part subtree */
702 extension_part_ti = proto_tree_add_string_format(tree,
703 hf_rlc_lte_extension_part,
704 tvb, offset, 2,
705 "",
706 "Extension Part");
707 extension_part_tree = proto_item_add_subtree(extension_part_ti,
708 ett_rlc_lte_extension_part);
709
710 if (p_rlc_lte_info->extendedLiField == FALSE) {
711 isOdd = (s_number_of_extensions % 2);
712
713 /* Read next extension */
714 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
715 (offset*8) + ((isOdd) ? 4 : 0),
716 1,
717 &extension, ENC_BIG_ENDIAN);
718
719 /* Read length field */
720 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
721 (offset*8) + ((isOdd) ? 5 : 1),
722 11,
723 &length, ENC_BIG_ENDIAN);
724
725 /* Move on to byte of next extension */
726 if (isOdd) {
727 offset += 2;
728 } else {
729 offset++;
730 }
731 } else {
732 /* Read next extension */
733 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_e, tvb,
734 (offset*8),
735 1,
736 &extension, ENC_BIG_ENDIAN);
737
738 /* Read length field */
739 proto_tree_add_bits_ret_val(extension_part_tree, hf_rlc_lte_extension_li, tvb,
740 (offset*8) + 1,
741 15,
742 &length, ENC_BIG_ENDIAN);
743
744 /* Move on to byte of next extension */
745 offset += 2;
746 }
747
748 proto_item_append_text(extension_part_tree, " (length=%u)", (guint16)length);
749
750 s_lengths[s_number_of_extensions++] = (guint16)length;
751 }
752
753 /* May need to skip padding after last extension part */
754 isOdd = (s_number_of_extensions % 2);
755 if (isOdd && (p_rlc_lte_info->extendedLiField == FALSE)) {
756 proto_tree_add_item(tree, hf_rlc_lte_extension_padding,
757 tvb, offset++, 1, ENC_BIG_ENDIAN);
758 }
759
760 return offset;
761 }
762
763
764 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
765 whether or not the beginning and end are included in this packet */
show_PDU_in_info(packet_info * pinfo,proto_item * top_ti,gint32 length,gboolean first_includes_start,gboolean last_includes_end)766 static void show_PDU_in_info(packet_info *pinfo,
767 proto_item *top_ti,
768 gint32 length,
769 gboolean first_includes_start,
770 gboolean last_includes_end)
771 {
772 /* Reflect this PDU in the info column */
773 if (length > 0) {
774 write_pdu_label_and_info(top_ti, NULL, pinfo,
775 " %s%u-byte%s%s",
776 (first_includes_start) ? "[" : "..",
777 length,
778 (length > 1) ? "s" : "",
779 (last_includes_end) ? "]" : "..");
780 }
781 else {
782 write_pdu_label_and_info(top_ti, NULL, pinfo,
783 " %sunknown-bytes%s",
784 (first_includes_start) ? "[" : "..",
785 (last_includes_end) ? "]" : "..");
786 }
787 }
788
789
790 /* Show an SDU. If configured, pass to PDCP/RRC/IP dissector */
show_PDU_in_tree(packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,rlc_lte_info * rlc_info,gboolean whole_pdu,rlc_channel_reassembly_info * reassembly_info,sequence_analysis_state state)791 static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, gint offset, gint length,
792 rlc_lte_info *rlc_info, gboolean whole_pdu, rlc_channel_reassembly_info *reassembly_info,
793 sequence_analysis_state state)
794 {
795 wmem_tree_key_t key[3];
796 guint32 id;
797 rlc_ue_parameters *params;
798
799 /* Add raw data (according to mode) */
800 proto_item *data_ti = proto_tree_add_item(tree,
801 (rlc_info->rlcMode == RLC_AM_MODE) ?
802 hf_rlc_lte_am_data :
803 hf_rlc_lte_um_data,
804 tvb, offset, length, ENC_NA);
805
806 if (whole_pdu || (reassembly_info != NULL)) {
807 if (((global_rlc_lte_call_pdcp_for_srb) && (rlc_info->channelType == CHANNEL_TYPE_SRB)) ||
808 ((global_rlc_lte_call_pdcp_for_drb != PDCP_drb_off) && (rlc_info->channelType == CHANNEL_TYPE_DRB))) {
809 /* Send whole PDU to PDCP */
810
811 /* TODO: made static to avoid compiler warning... */
812 static tvbuff_t *pdcp_tvb = NULL;
813 struct pdcp_lte_info *p_pdcp_lte_info;
814
815 /* Get tvb for passing to LTE PDCP dissector */
816 if (reassembly_info == NULL) {
817 pdcp_tvb = tvb_new_subset_length(tvb, offset, length);
818 }
819 else {
820 /* Get combined tvb. */
821 pdcp_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
822 reassembly_show_source(reassembly_info, tree, tvb, offset);
823 }
824
825 /* Reuse or allocate struct */
826 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
827 if (p_pdcp_lte_info == NULL) {
828 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
829 /* Store info in packet */
830 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
831 }
832
833 p_pdcp_lte_info->ueid = rlc_info->ueid;
834 if (rlc_info->nbMode == rlc_nb_mode) {
835 p_pdcp_lte_info->channelType = Channel_DCCH_NB;
836 } else {
837 p_pdcp_lte_info->channelType = Channel_DCCH;
838 }
839 p_pdcp_lte_info->channelId = rlc_info->channelId;
840 p_pdcp_lte_info->direction = rlc_info->direction;
841 p_pdcp_lte_info->is_retx = (state != SN_OK);
842
843 /* Set plane and sequence number length */
844 p_pdcp_lte_info->no_header_pdu = FALSE;
845 if (rlc_info->channelType == CHANNEL_TYPE_SRB) {
846 p_pdcp_lte_info->plane = SIGNALING_PLANE;
847 if ((rlc_info->nbMode == rlc_nb_mode) && (rlc_info->channelId == 3)) {
848 p_pdcp_lte_info->no_header_pdu = TRUE;
849 p_pdcp_lte_info->seqnum_length = 0;
850 } else {
851 p_pdcp_lte_info->seqnum_length = 5;
852 }
853 }
854 else {
855 p_pdcp_lte_info->plane = USER_PLANE;
856 switch (global_rlc_lte_call_pdcp_for_drb) {
857 case PDCP_drb_SN_7:
858 p_pdcp_lte_info->seqnum_length = 7;
859 break;
860 case PDCP_drb_SN_12:
861 p_pdcp_lte_info->seqnum_length = 12;
862 break;
863 case PDCP_drb_SN_15:
864 p_pdcp_lte_info->seqnum_length = 15;
865 break;
866 case PDCP_drb_SN_18:
867 p_pdcp_lte_info->seqnum_length = 18;
868 break;
869 case PDCP_drb_SN_signalled:
870 /* Use whatever was signalled (e.g. in RRC) */
871 id = (rlc_info->channelId << 16) | rlc_info->ueid;
872 key[0].length = 1;
873 key[0].key = &id;
874 key[1].length = 1;
875 key[1].key = &pinfo->num;
876 key[2].length = 0;
877 key[2].key = NULL;
878
879 params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
880 if (params && (params->id != id)) {
881 params = NULL;
882 }
883 if (params) {
884 p_pdcp_lte_info->seqnum_length = params->pdcp_sn_bits;
885 } else if (rlc_info->nbMode == rlc_nb_mode) {
886 p_pdcp_lte_info->seqnum_length = 7;
887 } else {
888 p_pdcp_lte_info->seqnum_length = 12;
889 }
890 break;
891
892 default:
893 DISSECTOR_ASSERT(FALSE);
894 break;
895 }
896 }
897
898 TRY {
899 call_dissector_only(pdcp_lte_handle, pdcp_tvb, pinfo, tree, NULL);
900 }
901 CATCH_ALL {
902 }
903 ENDTRY
904
905 proto_item_set_hidden(data_ti);
906 }
907 else if (global_rlc_lte_call_rrc_for_mcch && (rlc_info->channelType == CHANNEL_TYPE_MCCH)) {
908 /* Send whole PDU to RRC */
909 static tvbuff_t *rrc_tvb = NULL;
910
911 /* Get tvb for passing to LTE RRC dissector */
912 if (reassembly_info == NULL) {
913 rrc_tvb = tvb_new_subset_length(tvb, offset, length);
914 }
915 else {
916 /* Get combined tvb. */
917 rrc_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
918 reassembly_show_source(reassembly_info, tree, tvb, offset);
919 }
920
921 TRY {
922 call_dissector_only(lte_rrc_mcch, rrc_tvb, pinfo, tree, NULL);
923 }
924 CATCH_ALL {
925 }
926 ENDTRY
927
928 proto_item_set_hidden(data_ti);
929 }
930 else if (global_rlc_lte_call_ip_for_mtch && (rlc_info->channelType == CHANNEL_TYPE_MTCH)) {
931 /* Send whole PDU to IP */
932 static tvbuff_t *ip_tvb = NULL;
933
934 /* Get tvb for passing to IP dissector */
935 if (reassembly_info == NULL) {
936 ip_tvb = tvb_new_subset_length(tvb, offset, length);
937 }
938 else {
939 /* Get combined tvb. */
940 ip_tvb = reassembly_get_reassembled_tvb(reassembly_info, tvb, pinfo);
941 reassembly_show_source(reassembly_info, tree, tvb, offset);
942 }
943
944 TRY {
945 call_dissector_only(ip_handle, ip_tvb, pinfo, tree, NULL);
946 }
947 CATCH_ALL {
948 }
949 ENDTRY
950
951 proto_item_set_hidden(data_ti);
952 }
953 }
954 }
955
956 /* Hash table functions for RLC channels */
957
958 /* Equal keys */
rlc_channel_equal(gconstpointer v,gconstpointer v2)959 static gint rlc_channel_equal(gconstpointer v, gconstpointer v2)
960 {
961 const channel_hash_key* val1 = (const channel_hash_key *)v;
962 const channel_hash_key* val2 = (const channel_hash_key *)v2;
963
964 /* All fields must match */
965 /* N.B. Currently fits into one word, so could return (*v == *v2)
966 if we're sure they're initialised to 0... */
967 return ((val1->ueId == val2->ueId) &&
968 (val1->channelType == val2->channelType) &&
969 (val1->channelId == val2->channelId) &&
970 (val1->direction == val2->direction));
971 }
972
973 /* Compute a hash value for a given key. */
rlc_channel_hash_func(gconstpointer v)974 static guint rlc_channel_hash_func(gconstpointer v)
975 {
976 const channel_hash_key* val1 = (const channel_hash_key *)v;
977
978 /* TODO: check/reduce multipliers */
979 return ((val1->ueId * 1024) + (val1->channelType*64) + (val1->channelId*2) + val1->direction);
980 }
981
982
983 /*************************************************************************/
984 /* Result hash */
985
986 typedef struct {
987 guint32 frameNumber;
988 guint32 SN : 10;
989 guint32 channelType : 2;
990 guint32 channelId: 5;
991 guint32 direction: 1;
992 } rlc_result_hash_key;
993
994 /* Compare 2 rlc_result_hash_key structs */
rlc_result_hash_equal(gconstpointer v,gconstpointer v2)995 static gint rlc_result_hash_equal(gconstpointer v, gconstpointer v2)
996 {
997 const rlc_result_hash_key *val1 = (const rlc_result_hash_key *)v;
998 const rlc_result_hash_key *val2 = (const rlc_result_hash_key *)v2;
999
1000 /* All fields (and any padding...) must match */
1001 return (memcmp(val1, val2, sizeof(rlc_result_hash_key)) == 0);
1002 }
1003
1004 /* Compute a hash value for a given key. */
rlc_result_hash_func(gconstpointer v)1005 static guint rlc_result_hash_func(gconstpointer v)
1006 {
1007 const rlc_result_hash_key* val1 = (const rlc_result_hash_key *)v;
1008
1009 /* Got rid of multipliers - no evidence that they reduced collisions */
1010 return val1->frameNumber + val1->SN +
1011 val1->channelType +
1012 val1->channelId +
1013 val1->direction;
1014 }
1015
1016 /* Convenience function to get a pointer for the hash_func to work with */
get_report_hash_key(guint16 SN,guint32 frameNumber,rlc_lte_info * p_rlc_lte_info,gboolean do_persist)1017 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
1018 rlc_lte_info *p_rlc_lte_info,
1019 gboolean do_persist)
1020 {
1021 static rlc_result_hash_key key;
1022 rlc_result_hash_key *p_key;
1023
1024 /* Only allocate a struct when will be adding entry */
1025 if (do_persist) {
1026 p_key = wmem_new0(wmem_file_scope(), rlc_result_hash_key);
1027 }
1028 else {
1029 memset(&key, 0, sizeof(rlc_result_hash_key));
1030 p_key = &key;
1031 }
1032
1033 /* Fill in details, and return pointer */
1034 p_key->frameNumber = frameNumber;
1035 p_key->SN = SN;
1036 p_key->channelType = p_rlc_lte_info->channelType;
1037 p_key->channelId = p_rlc_lte_info->channelId;
1038 p_key->direction = p_rlc_lte_info->direction;
1039
1040 return p_key;
1041 }
1042
checkFIconsistency(sequence_analysis_report * p,rlc_lte_info * p_rlc_lte_info,gboolean newSegmentStarted,proto_tree * seqnum_tree,packet_info * pinfo,tvbuff_t * tvb)1043 static void checkFIconsistency(sequence_analysis_report *p,
1044 rlc_lte_info *p_rlc_lte_info,
1045 gboolean newSegmentStarted,
1046 proto_tree *seqnum_tree,
1047 packet_info *pinfo, tvbuff_t *tvb)
1048 {
1049 proto_item *ti;
1050
1051 if (p->previousSegmentIncomplete) {
1052 /* Previous segment was incomplete, so this PDU should continue it */
1053 if (newSegmentStarted) {
1054 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1055 tvb, 0, 0, FALSE);
1056 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_last_segment_not_continued,
1057 "Last segment of previous PDU was not continued for UE %u (%s-%u)",
1058 p_rlc_lte_info->ueid,
1059 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1060 p_rlc_lte_info->channelId);
1061 }
1062 else {
1063 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1064 tvb, 0, 0, TRUE);
1065 proto_item_set_hidden(ti);
1066 }
1067 }
1068 else {
1069 /* Previous segment was complete, so this PDU should start a new one */
1070 if (!newSegmentStarted) {
1071 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1072 tvb, 0, 0, FALSE);
1073 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_last_segment_complete,
1074 "Last segment of previous PDU was complete, but new segment was not started on UE %u (%s-%u)",
1075 p_rlc_lte_info->ueid,
1076 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1077 p_rlc_lte_info->channelId);
1078 }
1079 else {
1080 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_framing_info_correct,
1081 tvb, 0, 0, TRUE);
1082 proto_item_set_hidden(ti);
1083 }
1084 }
1085 proto_item_set_generated(ti);
1086 }
1087
1088 /* Add to the tree values associated with sequence analysis for this frame */
addChannelSequenceInfo(sequence_analysis_report * p,gboolean isControlFrame,rlc_lte_info * p_rlc_lte_info,guint16 sequenceNumber,gboolean newSegmentStarted,rlc_lte_tap_info * tap_info,packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb)1089 static void addChannelSequenceInfo(sequence_analysis_report *p,
1090 gboolean isControlFrame,
1091 rlc_lte_info *p_rlc_lte_info,
1092 guint16 sequenceNumber,
1093 gboolean newSegmentStarted,
1094 rlc_lte_tap_info *tap_info,
1095 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
1096 {
1097 proto_tree *seqnum_tree;
1098 proto_item *seqnum_ti;
1099 proto_item *ti;
1100
1101 /* Create subtree */
1102 seqnum_ti = proto_tree_add_string_format(tree,
1103 hf_rlc_lte_sequence_analysis,
1104 tvb, 0, 0,
1105 "", "Sequence Analysis");
1106 seqnum_tree = proto_item_add_subtree(seqnum_ti,
1107 ett_rlc_lte_sequence_analysis);
1108 proto_item_set_generated(seqnum_ti);
1109
1110 if (p->previousFrameNum != 0) {
1111 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_previous_frame,
1112 tvb, 0, 0, p->previousFrameNum);
1113 proto_item_set_generated(ti);
1114 }
1115
1116 switch (p_rlc_lte_info->rlcMode) {
1117 case RLC_AM_MODE:
1118
1119 /********************************************/
1120 /* AM */
1121 /********************************************/
1122
1123 switch (p->state) {
1124 case SN_OK:
1125 if (isControlFrame) {
1126 return;
1127 }
1128
1129 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1130 tvb, 0, 0, TRUE);
1131 proto_item_set_generated(ti);
1132 proto_item_append_text(seqnum_ti, " - OK");
1133
1134 /* Link to next SN in channel (if known) */
1135 if (p->nextFrameNum != 0) {
1136 proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_next_frame,
1137 tvb, 0, 0, p->nextFrameNum);
1138 }
1139 /* Correct sequence number, so check frame indication bits consistent */
1140 /* Deactivated for now as it gets confused by resegmentation */
1141 /* checkFIconsistency(p, p_rlc_lte_info, newSegmentStarted, seqnum_tree, pinfo, tvb); */
1142 break;
1143
1144 case SN_MAC_Retx:
1145 if (isControlFrame) {
1146 return;
1147 }
1148
1149 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1150 tvb, 0, 0, FALSE);
1151 proto_item_set_generated(ti);
1152 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
1153 tvb, 0, 0, TRUE);
1154 proto_item_set_generated(ti);
1155 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_mac_retx,
1156 "AM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u)",
1157 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1158 p_rlc_lte_info->ueid,
1159 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1160 p_rlc_lte_info->channelId);
1161 proto_item_append_text(seqnum_ti, " - MAC retx of SN %u", p->firstSN);
1162 break;
1163
1164 case SN_Retx:
1165 if (isControlFrame) {
1166 return;
1167 }
1168
1169 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1170 tvb, 0, 0, FALSE);
1171 proto_item_set_generated(ti);
1172 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_retx,
1173 tvb, 0, 0, TRUE);
1174 proto_item_set_generated(ti);
1175 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_retx,
1176 "AM Frame retransmitted for %s on UE %u - most likely in response to NACK (%s-%u)",
1177 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1178 p_rlc_lte_info->ueid,
1179 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1180 p_rlc_lte_info->channelId);
1181 proto_item_append_text(seqnum_ti, " - SN %u retransmitted", p->firstSN);
1182 break;
1183
1184 case SN_Repeated:
1185 if (isControlFrame) {
1186 return;
1187 }
1188
1189 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1190 tvb, 0, 0, FALSE);
1191 proto_item_set_generated(ti);
1192 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
1193 tvb, 0, 0, TRUE);
1194 proto_item_set_generated(ti);
1195 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_repeated,
1196 "AM SN Repeated for %s for UE %u - probably because didn't receive Status PDU? (%s-%u)",
1197 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1198 p_rlc_lte_info->ueid,
1199 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1200 p_rlc_lte_info->channelId);
1201 proto_item_append_text(seqnum_ti, "- SN %u Repeated", p->firstSN);
1202 break;
1203
1204 case SN_Missing:
1205 if (isControlFrame) {
1206 return;
1207 }
1208
1209 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1210 tvb, 0, 0, FALSE);
1211 proto_item_set_generated(ti);
1212 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
1213 tvb, 0, 0, TRUE);
1214 proto_item_set_generated(ti);
1215 if (p->lastSN != p->firstSN) {
1216 expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_sn_missing,
1217 "AM SNs (%u to %u) missing for %s on UE %u (%s-%u)",
1218 p->firstSN, p->lastSN,
1219 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1220 p_rlc_lte_info->ueid,
1221 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1222 p_rlc_lte_info->channelId);
1223 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
1224 p->firstSN, p->lastSN);
1225 if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
1226 tap_info->missingSNs = ((65536 + (guint32)p->lastSN - (guint32)p->firstSN) % 65536) + 1;
1227 } else {
1228 tap_info->missingSNs = ((1024 + p->lastSN - p->firstSN) % 1024) + 1;
1229 }
1230 }
1231 else {
1232 expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_sn_missing,
1233 "AM SN (%u) missing for %s on UE %u (%s-%u)",
1234 p->firstSN,
1235 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1236 p_rlc_lte_info->ueid,
1237 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1238 p_rlc_lte_info->channelId);
1239 proto_item_append_text(seqnum_ti, " - SN missing (%u)", p->firstSN);
1240 tap_info->missingSNs = 1;
1241 }
1242 break;
1243
1244 case ACK_Out_of_Window:
1245 if (!isControlFrame) {
1246 return;
1247 }
1248
1249
1250 /* Not OK */
1251 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1252 tvb, 0, 0, FALSE);
1253 /* Out of range */
1254 proto_item_set_generated(ti);
1255 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ack_out_of_range,
1256 tvb, 0, 0, TRUE);
1257 proto_item_set_generated(ti);
1258
1259 /* Link back to last seen SN in other direction */
1260 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
1261 tvb, 0, 0, p->previousFrameNum);
1262 proto_item_set_generated(ti);
1263
1264 /* Expert error */
1265 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
1266 "AM ACK for SN %u - but last received SN in other direction is %u for UE %u (%s-%u)",
1267 p->firstSN, p->sequenceExpected,
1268 p_rlc_lte_info->ueid,
1269 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1270 p_rlc_lte_info->channelId);
1271 proto_item_append_text(seqnum_ti, "- ACK SN %u Outside Rx Window - last received SN is %u",
1272 p->firstSN, p->sequenceExpected);
1273
1274 break;
1275
1276 default:
1277 return;
1278 }
1279 break;
1280
1281 case RLC_UM_MODE:
1282
1283 /********************************************/
1284 /* UM */
1285 /********************************************/
1286
1287 /* Expected sequence number */
1288 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_expected_sn,
1289 tvb, 0, 0, p->sequenceExpected);
1290 proto_item_set_generated(ti);
1291 if (p->sequenceExpectedCorrect) {
1292 proto_item_set_hidden(ti);
1293 }
1294
1295 if (!p->sequenceExpectedCorrect) {
1296 /* Work out SN wrap (in case needed below) */
1297 guint16 snLimit;
1298 if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1299 snLimit = 32;
1300 }
1301 else {
1302 snLimit = 1024;
1303 }
1304
1305 switch (p->state) {
1306 case SN_Missing:
1307 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1308 tvb, 0, 0, FALSE);
1309 proto_item_set_generated(ti);
1310 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_skipped,
1311 tvb, 0, 0, TRUE);
1312 proto_item_set_generated(ti);
1313 if (p->lastSN != p->firstSN) {
1314 expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_missing,
1315 "UM SNs (%u to %u) missing for %s on UE %u (%s-%u)",
1316 p->firstSN, p->lastSN,
1317 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1318 p_rlc_lte_info->ueid,
1319 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1320 p_rlc_lte_info->channelId);
1321 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
1322 p->firstSN, p->lastSN);
1323 tap_info->missingSNs = ((snLimit + p->lastSN - p->firstSN) % snLimit) + 1;
1324 }
1325 else {
1326 expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_missing,
1327 "UM SN (%u) missing for %s on UE %u (%s-%u)",
1328 p->firstSN,
1329 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1330 p_rlc_lte_info->ueid,
1331 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1332 p_rlc_lte_info->channelId);
1333 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
1334 p->firstSN);
1335 tap_info->missingSNs = 1;
1336 }
1337 break;
1338
1339 case SN_Repeated:
1340 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1341 tvb, 0, 0, FALSE);
1342 proto_item_set_generated(ti);
1343 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated,
1344 tvb, 0, 0, TRUE);
1345 proto_item_set_generated(ti);
1346 expert_add_info_format(pinfo, ti, &ei_rlc_lte_um_sn_repeated,
1347 "UM SN (%u) repeated for %s for UE %u (%s-%u)",
1348 p->firstSN,
1349 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1350 p_rlc_lte_info->ueid,
1351 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1352 p_rlc_lte_info->channelId);
1353 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
1354 p->firstSN);
1355 break;
1356
1357 case SN_MAC_Retx:
1358 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1359 tvb, 0, 0, FALSE);
1360 proto_item_set_generated(ti);
1361 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_mac_retx,
1362 tvb, 0, 0, TRUE);
1363 proto_item_set_generated(ti);
1364 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_mac_retx,
1365 "UM Frame retransmitted for %s on UE %u - due to MAC retx! (%s-%u)",
1366 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1367 p_rlc_lte_info->ueid,
1368 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1369 p_rlc_lte_info->channelId);
1370 break;
1371
1372 default:
1373 /* Incorrect sequence number */
1374 expert_add_info_format(pinfo, ti, &ei_rlc_lte_wrong_sequence_number,
1375 "Wrong Sequence Number for %s on UE %u - got %u, expected %u (%s-%u)",
1376 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1377 p_rlc_lte_info->ueid, sequenceNumber, p->sequenceExpected,
1378 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
1379 p_rlc_lte_info->channelId);
1380
1381 break;
1382 }
1383
1384 }
1385 else {
1386 /* Correct sequence number, so check frame indication bits consistent */
1387 checkFIconsistency(p, p_rlc_lte_info, newSegmentStarted, seqnum_tree, pinfo, tvb);
1388
1389 /* Set OK here! */
1390 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1391 tvb, 0, 0, TRUE);
1392 proto_item_set_generated(ti);
1393 proto_item_append_text(seqnum_ti, " - OK");
1394 }
1395
1396 /* Next channel frame */
1397 if (p->nextFrameNum != 0) {
1398 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_next_frame,
1399 tvb, 0, 0, p->nextFrameNum);
1400 proto_item_set_generated(ti);
1401 }
1402 }
1403 }
1404
1405 /* Update the channel status and set report for this frame */
checkChannelSequenceInfo(packet_info * pinfo,tvbuff_t * tvb,rlc_lte_info * p_rlc_lte_info,gboolean isControlFrame,guint8 number_of_segments,guint16 firstSegmentOffset,guint16 firstSegmentLength,guint16 lastSegmentOffset,guint16 sequenceNumber,gboolean first_includes_start,gboolean last_includes_end,gboolean is_resegmented _U_,rlc_lte_tap_info * tap_info,proto_tree * tree)1406 static sequence_analysis_state checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
1407 rlc_lte_info *p_rlc_lte_info,
1408 gboolean isControlFrame,
1409 guint8 number_of_segments,
1410 guint16 firstSegmentOffset,
1411 guint16 firstSegmentLength,
1412 guint16 lastSegmentOffset,
1413 guint16 sequenceNumber,
1414 gboolean first_includes_start, gboolean last_includes_end,
1415 gboolean is_resegmented _U_,
1416 rlc_lte_tap_info *tap_info,
1417 proto_tree *tree)
1418 {
1419 channel_hash_key channel_key;
1420 channel_hash_key *p_channel_key;
1421 channel_sequence_analysis_status *p_channel_status;
1422 sequence_analysis_report *p_report_in_frame = NULL;
1423 gboolean createdChannel = FALSE;
1424 guint16 expectedSequenceNumber = 0;
1425 guint32 snLimit = 0;
1426
1427 /* If find stat_report_in_frame already, use that and get out */
1428 if (pinfo->fd->visited) {
1429 p_report_in_frame = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1430 get_report_hash_key(sequenceNumber,
1431 pinfo->num,
1432 p_rlc_lte_info,
1433 FALSE));
1434 if (p_report_in_frame != NULL) {
1435 addChannelSequenceInfo(p_report_in_frame, isControlFrame, p_rlc_lte_info,
1436 sequenceNumber, first_includes_start,
1437 tap_info, pinfo, tree, tvb);
1438 return p_report_in_frame->state;
1439 }
1440
1441 /* Don't just give up here... */
1442 }
1443
1444
1445 /**************************************************/
1446 /* Create or find an entry for this channel state */
1447 channel_key.ueId = p_rlc_lte_info->ueid;
1448 channel_key.channelType = p_rlc_lte_info->channelType;
1449 channel_key.channelId = p_rlc_lte_info->channelId;
1450 channel_key.direction = p_rlc_lte_info->direction;
1451
1452 /* Do the table lookup */
1453 p_channel_status = (channel_sequence_analysis_status*)wmem_map_lookup(sequence_analysis_channel_hash, &channel_key);
1454
1455 /* Create table entry if necessary */
1456 if (p_channel_status == NULL) {
1457 createdChannel = TRUE;
1458
1459 /* Allocate a new value and duplicate key contents */
1460 p_channel_status = wmem_new0(wmem_file_scope(), channel_sequence_analysis_status);
1461 p_channel_key = (channel_hash_key *)wmem_memdup(wmem_file_scope(), &channel_key, sizeof(channel_hash_key));
1462
1463 /* Set mode */
1464 p_channel_status->rlcMode = p_rlc_lte_info->rlcMode;
1465
1466 /* Add entry */
1467 wmem_map_insert(sequence_analysis_channel_hash, p_channel_key, p_channel_status);
1468 }
1469
1470 /* Create space for frame state_report */
1471 p_report_in_frame = wmem_new0(wmem_file_scope(), sequence_analysis_report);
1472
1473
1474 /* Deal with according to channel mode */
1475 switch (p_channel_status->rlcMode) {
1476 case RLC_UM_MODE:
1477
1478 if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1479 snLimit = 32;
1480 }
1481 else {
1482 snLimit = 1024;
1483 }
1484
1485 /* Work out expected sequence number */
1486 if (!createdChannel) {
1487 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
1488 }
1489 else {
1490 /* Whatever we got is fine.. */
1491 expectedSequenceNumber = sequenceNumber;
1492 }
1493
1494 if ((sequenceNumber == 0) &&
1495 ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH))) {
1496 /* With eMBMS, SN restarts to 0 at each MCH Scheduling Period so we cannot deduce easily whether
1497 there was a PDU loss or not without analysing the Frame Indicator; assume no loss when seeing 0 */
1498 expectedSequenceNumber = 0;
1499 }
1500
1501 /* Set report for this frame */
1502 /* For UM, sequence number is always expectedSequence number */
1503 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
1504
1505 /* For wrong sequence number... */
1506 if (!p_report_in_frame->sequenceExpectedCorrect) {
1507
1508 /* Don't get confused by MAC (HARQ) retx */
1509 if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
1510 p_report_in_frame->state = SN_MAC_Retx;
1511 p_report_in_frame->firstSN = sequenceNumber;
1512
1513 /* No channel state to update */
1514 break;
1515 }
1516
1517 /* Frames are not missing if we get an earlier sequence number again */
1518 /* TODO: taking time into account would give better idea of whether missing or repeated... */
1519 else if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH) ||
1520 (((snLimit + sequenceNumber - expectedSequenceNumber) % snLimit) < 10)) {
1521 reassembly_destroy(p_channel_status);
1522
1523 p_report_in_frame->state = SN_Missing;
1524 tap_info->missingSNs = (snLimit + sequenceNumber - expectedSequenceNumber) % snLimit;
1525 p_report_in_frame->firstSN = expectedSequenceNumber;
1526 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
1527
1528 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1529 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1530 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1531
1532 /* Update channel status to remember *this* frame */
1533 p_channel_status->previousFrameNum = pinfo->num;
1534 p_channel_status->previousSequenceNumber = sequenceNumber;
1535 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1536 }
1537 else {
1538 /* An SN has been repeated */
1539 p_report_in_frame->state = SN_Repeated;
1540 p_report_in_frame->firstSN = sequenceNumber;
1541
1542 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1543 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1544 }
1545 }
1546 else {
1547 /* SN was OK */
1548 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1549 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1550 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1551
1552 /* Update channel status to remember *this* frame */
1553 p_channel_status->previousFrameNum = pinfo->num;
1554 p_channel_status->previousSequenceNumber = sequenceNumber;
1555 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1556
1557 if (p_channel_status->reassembly_info) {
1558 /* Add next segment to reassembly info */
1559 reassembly_add_segment(p_channel_status, sequenceNumber, pinfo->num,
1560 tvb, firstSegmentOffset, firstSegmentLength);
1561
1562 /* The end of existing reassembly? */
1563 if (!first_includes_start &&
1564 ((number_of_segments > 1) || last_includes_end)) {
1565
1566 reassembly_record(p_channel_status, pinfo, sequenceNumber, p_rlc_lte_info);
1567 reassembly_destroy(p_channel_status);
1568 }
1569 }
1570
1571 /* The start of a new reassembly? */
1572 if (!last_includes_end &&
1573 ((number_of_segments > 1) || first_includes_start)) {
1574
1575 guint16 lastSegmentLength = tvb_reported_length(tvb)-lastSegmentOffset;
1576
1577 if (global_rlc_lte_reassembly) {
1578 reassembly_reset(p_channel_status);
1579 reassembly_add_segment(p_channel_status, sequenceNumber,
1580 pinfo->num,
1581 tvb, lastSegmentOffset, lastSegmentLength);
1582 }
1583 }
1584
1585 if (p_report_in_frame->previousFrameNum != 0) {
1586 /* Get report for previous frame */
1587 sequence_analysis_report *p_previous_report;
1588 if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
1589 snLimit = 32;
1590 }
1591 else {
1592 snLimit = 1024;
1593 }
1594
1595 /* Look up report for previous SN */
1596 p_previous_report = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1597 get_report_hash_key((sequenceNumber+snLimit-1) % snLimit,
1598 p_report_in_frame->previousFrameNum,
1599 p_rlc_lte_info,
1600 FALSE));
1601 /* It really shouldn't be NULL... */
1602 if (p_previous_report != NULL) {
1603 /* Point it forward to this one */
1604 p_previous_report->nextFrameNum = pinfo->num;
1605 }
1606 }
1607 }
1608
1609 break;
1610
1611 case RLC_AM_MODE:
1612
1613 if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
1614 snLimit = 65536;
1615 } else {
1616 snLimit = 1024;
1617 }
1618
1619 /* Work out expected sequence number */
1620 if (!createdChannel) {
1621 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
1622 }
1623 else {
1624 /* Whatever we got is fine.. */
1625 expectedSequenceNumber = sequenceNumber;
1626 }
1627
1628 /* For AM, may be:
1629 - expected Sequence number OR
1630 - previous frame repeated
1631 - old SN being sent (in response to NACK)
1632 - new SN, but with frames missed out
1633 Assume window whose front is at expectedSequenceNumber */
1634
1635 /* First of all, check to see whether frame is judged to be MAC Retx */
1636 if (is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
1637 /* Just report that this is a MAC Retx */
1638 p_report_in_frame->state = SN_MAC_Retx;
1639 p_report_in_frame->firstSN = sequenceNumber;
1640
1641 /* No channel state to update */
1642 break;
1643 }
1644
1645 if (sequenceNumber != expectedSequenceNumber) {
1646 /* Don't trash reassembly info if this looks like a close retx... */
1647 if (((snLimit + sequenceNumber - expectedSequenceNumber) % snLimit) < 50) {
1648 reassembly_destroy(p_channel_status);
1649 }
1650 }
1651
1652 /* Expected? */
1653 if (sequenceNumber == expectedSequenceNumber) {
1654 /* Set report for this frame */
1655 p_report_in_frame->sequenceExpectedCorrect = TRUE;
1656 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1657 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1658 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1659 p_report_in_frame->state = SN_OK;
1660
1661 /* Update channel status */
1662 p_channel_status->previousSequenceNumber = sequenceNumber;
1663 p_channel_status->previousFrameNum = pinfo->num;
1664 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1665
1666
1667 if (p_channel_status->reassembly_info) {
1668
1669 /* Add next segment to reassembly info */
1670 reassembly_add_segment(p_channel_status, sequenceNumber, pinfo->num,
1671 tvb, firstSegmentOffset, firstSegmentLength);
1672
1673 /* The end of existing reassembly? */
1674 if (!first_includes_start &&
1675 ((number_of_segments > 1) || last_includes_end)) {
1676
1677 reassembly_record(p_channel_status, pinfo,
1678 sequenceNumber, p_rlc_lte_info);
1679 reassembly_destroy(p_channel_status);
1680 }
1681 }
1682
1683 /* The start of a new reassembly? */
1684 if (!last_includes_end &&
1685 ((number_of_segments > 1) || first_includes_start)) {
1686
1687 guint16 lastSegmentLength = tvb_reported_length(tvb)-lastSegmentOffset;
1688 if (global_rlc_lte_reassembly) {
1689 reassembly_reset(p_channel_status);
1690 reassembly_add_segment(p_channel_status, sequenceNumber,
1691 pinfo->num,
1692 tvb, lastSegmentOffset, lastSegmentLength);
1693 }
1694 }
1695
1696 if (p_report_in_frame->previousFrameNum != 0) {
1697 /* Get report for previous frame */
1698 sequence_analysis_report *p_previous_report;
1699 p_previous_report = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1700 get_report_hash_key((sequenceNumber+snLimit-1) % snLimit,
1701 p_report_in_frame->previousFrameNum,
1702 p_rlc_lte_info,
1703 FALSE));
1704 /* It really shouldn't be NULL... */
1705 if (p_previous_report != NULL) {
1706 /* Point it forward to this one */
1707 p_previous_report->nextFrameNum = pinfo->num;
1708 }
1709 }
1710
1711 }
1712
1713 /* Previous subframe repeated? */
1714 else if (((sequenceNumber+1) % snLimit) == expectedSequenceNumber) {
1715 p_report_in_frame->state = SN_Repeated;
1716
1717 /* Set report for this frame */
1718 p_report_in_frame->sequenceExpectedCorrect = FALSE;
1719 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1720 p_report_in_frame->firstSN = sequenceNumber;
1721 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1722 p_report_in_frame->previousSegmentIncomplete = p_channel_status->previousSegmentIncomplete;
1723
1724
1725 /* Really should be nothing to update... */
1726 p_channel_status->previousSequenceNumber = sequenceNumber;
1727 p_channel_status->previousFrameNum = pinfo->num;
1728 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1729 }
1730
1731 else {
1732 /* Need to work out if new (with skips, or likely a retx (due to NACK)) */
1733 gint delta = (snLimit + expectedSequenceNumber - sequenceNumber) % snLimit;
1734
1735 /* Rx window is 512/32768, so check to see if this is a retx */
1736 if (delta < (gint)(snLimit>>1)) {
1737 /* Probably a retx due to receiving NACK */
1738 p_report_in_frame->state = SN_Retx;
1739
1740 p_report_in_frame->firstSN = sequenceNumber;
1741 /* Don't update anything in channel state */
1742 }
1743
1744 else {
1745 /* Ahead of expected SN. Assume frames have been missed */
1746 p_report_in_frame->state = SN_Missing;
1747
1748 p_report_in_frame->firstSN = expectedSequenceNumber;
1749 p_report_in_frame->lastSN = (snLimit + sequenceNumber-1) % snLimit;
1750
1751 /* Update channel state - forget about missed SNs */
1752 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1753 p_channel_status->previousSequenceNumber = sequenceNumber;
1754 p_channel_status->previousFrameNum = pinfo->num;
1755 p_channel_status->previousSegmentIncomplete = !last_includes_end;
1756 }
1757 }
1758 break;
1759
1760 default:
1761 /* Shouldn't get here! */
1762 return SN_Error;
1763 }
1764
1765 /* Associate with this frame number */
1766 wmem_map_insert(sequence_analysis_report_hash,
1767 get_report_hash_key(sequenceNumber, pinfo->num, p_rlc_lte_info, TRUE),
1768 p_report_in_frame);
1769
1770 /* Add state report for this frame into tree */
1771 addChannelSequenceInfo(p_report_in_frame, isControlFrame, p_rlc_lte_info, sequenceNumber,
1772 first_includes_start, tap_info, pinfo, tree, tvb);
1773
1774 return p_report_in_frame->state;
1775 }
1776
1777
1778 /* Add to the tree values associated with sequence analysis for this frame */
addChannelRepeatedNACKInfo(channel_repeated_nack_report * p,rlc_lte_info * p_rlc_lte_info,packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb)1779 static void addChannelRepeatedNACKInfo(channel_repeated_nack_report *p,
1780 rlc_lte_info *p_rlc_lte_info,
1781 packet_info *pinfo, proto_tree *tree,
1782 tvbuff_t *tvb)
1783 {
1784 proto_tree *seqnum_tree;
1785 proto_item *seqnum_ti;
1786 proto_item *ti;
1787 gint n;
1788
1789 /* Create subtree */
1790 seqnum_ti = proto_tree_add_string_format(tree,
1791 hf_rlc_lte_sequence_analysis,
1792 tvb, 0, 0,
1793 "", "Sequence Analysis");
1794 seqnum_tree = proto_item_add_subtree(seqnum_ti,
1795 ett_rlc_lte_sequence_analysis);
1796 proto_item_set_generated(seqnum_ti);
1797
1798 /* OK = FALSE */
1799 ti = proto_tree_add_boolean(seqnum_tree, hf_rlc_lte_sequence_analysis_ok,
1800 tvb, 0, 0, FALSE);
1801 proto_item_set_generated(ti);
1802
1803 /* Add each repeated NACK as item & expert info */
1804 for (n=0; n < p->noOfNACKsRepeated; n++) {
1805
1806 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated_nack,
1807 tvb, 0, 0, p->repeatedNACKs[n]);
1808 proto_item_set_generated(ti);
1809
1810 expert_add_info_format(pinfo, ti, &ei_rlc_lte_sequence_analysis_repeated_nack,
1811 "Same SN (%u) NACKd for %s on UE %u in successive Status PDUs",
1812 p->repeatedNACKs[n],
1813 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
1814 p_rlc_lte_info->ueid);
1815 }
1816
1817 /* Link back to previous status report */
1818 ti = proto_tree_add_uint(seqnum_tree, hf_rlc_lte_sequence_analysis_repeated_nack_original_frame,
1819 tvb, 0, 0, p->previousFrameNum);
1820 proto_item_set_generated(ti);
1821
1822 /* Append count to sequence analysis root */
1823 proto_item_append_text(seqnum_ti, " - %u SNs repeated from previous Status PDU",
1824 p->noOfNACKsRepeated);
1825 }
1826
1827
1828 /* Update the channel repeated NACK status and set report for this frame */
checkChannelRepeatedNACKInfo(packet_info * pinfo,rlc_lte_info * p_rlc_lte_info,rlc_lte_tap_info * tap_info,proto_tree * tree,tvbuff_t * tvb)1829 static void checkChannelRepeatedNACKInfo(packet_info *pinfo,
1830 rlc_lte_info *p_rlc_lte_info,
1831 rlc_lte_tap_info *tap_info,
1832 proto_tree *tree,
1833 tvbuff_t *tvb)
1834 {
1835 channel_hash_key channel_key;
1836 channel_hash_key *p_channel_key;
1837 channel_repeated_nack_status *p_channel_status;
1838 channel_repeated_nack_report *p_report_in_frame = NULL;
1839
1840 guint16 noOfNACKsRepeated = 0;
1841 guint16 repeatedNACKs[MAX_NACKs];
1842 gint n, i, j;
1843
1844 /* If find state_report_in_frame already, use that and get out */
1845 if (pinfo->fd->visited) {
1846 p_report_in_frame = (channel_repeated_nack_report*)wmem_map_lookup(repeated_nack_report_hash,
1847 get_report_hash_key(0, pinfo->num,
1848 p_rlc_lte_info, FALSE));
1849 if (p_report_in_frame != NULL) {
1850 addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1851 pinfo, tree, tvb);
1852 return;
1853 }
1854 else {
1855 /* Give up - we must have tried already... */
1856 return;
1857 }
1858 }
1859
1860
1861 /**************************************************/
1862 /* Create or find an entry for this channel state */
1863 channel_key.ueId = p_rlc_lte_info->ueid;
1864 channel_key.channelType = p_rlc_lte_info->channelType;
1865 channel_key.channelId = p_rlc_lte_info->channelId;
1866 channel_key.direction = p_rlc_lte_info->direction;
1867 memset(repeatedNACKs, 0, sizeof(repeatedNACKs));
1868
1869 /* Do the table lookup */
1870 p_channel_status = (channel_repeated_nack_status*)wmem_map_lookup(repeated_nack_channel_hash, &channel_key);
1871
1872 /* Create table entry if necessary */
1873 if (p_channel_status == NULL) {
1874
1875 /* Allocate a new key and value */
1876 p_channel_key = wmem_new(wmem_file_scope(), channel_hash_key);
1877 p_channel_status = wmem_new0(wmem_file_scope(), channel_repeated_nack_status);
1878
1879 /* Copy key contents */
1880 memcpy(p_channel_key, &channel_key, sizeof(channel_hash_key));
1881
1882 /* Add entry to table */
1883 wmem_map_insert(repeated_nack_channel_hash, p_channel_key, p_channel_status);
1884 }
1885
1886 /* Compare NACKs in channel status with NACKs in tap_info.
1887 Note any that are repeated */
1888 for (i=0; i < p_channel_status->noOfNACKs; i++) {
1889 for (j=0; j < MIN(tap_info->noOfNACKs, MAX_NACKs); j++) {
1890 if (tap_info->NACKs[j] == p_channel_status->NACKs[i]) {
1891 /* Don't add the same repeated NACK twice! */
1892 if ((noOfNACKsRepeated == 0) ||
1893 (repeatedNACKs[noOfNACKsRepeated-1] != p_channel_status->NACKs[i])) {
1894
1895 repeatedNACKs[noOfNACKsRepeated++] = p_channel_status->NACKs[i];
1896 }
1897 }
1898 }
1899 }
1900
1901 /* Copy NACKs from tap_info into channel status for next time! */
1902 p_channel_status->noOfNACKs = 0;
1903 for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1904 p_channel_status->NACKs[p_channel_status->noOfNACKs++] = tap_info->NACKs[n];
1905 }
1906
1907 if (noOfNACKsRepeated >= 1) {
1908 /* Create space for frame state_report */
1909 p_report_in_frame = wmem_new(wmem_file_scope(), channel_repeated_nack_report);
1910
1911 /* Copy in found duplicates */
1912 for (n=0; n < MIN(tap_info->noOfNACKs, MAX_NACKs); n++) {
1913 p_report_in_frame->repeatedNACKs[n] = repeatedNACKs[n];
1914 }
1915 p_report_in_frame->noOfNACKsRepeated = noOfNACKsRepeated;
1916
1917 p_report_in_frame->previousFrameNum = p_channel_status->frameNum;
1918
1919 /* Associate with this frame number */
1920 wmem_map_insert(repeated_nack_report_hash,
1921 get_report_hash_key(0, pinfo->num,
1922 p_rlc_lte_info, TRUE),
1923 p_report_in_frame);
1924
1925 /* Add state report for this frame into tree */
1926 addChannelRepeatedNACKInfo(p_report_in_frame, p_rlc_lte_info,
1927 pinfo, tree, tvb);
1928 }
1929
1930 /* Save frame number for next comparison */
1931 p_channel_status->frameNum = pinfo->num;
1932 }
1933
1934 /* Check that the ACK is consistent with data the expected sequence number
1935 in the other direction */
checkChannelACKWindow(guint16 ack_sn,packet_info * pinfo,rlc_lte_info * p_rlc_lte_info,rlc_lte_tap_info * tap_info,proto_tree * tree,tvbuff_t * tvb)1936 static void checkChannelACKWindow(guint16 ack_sn,
1937 packet_info *pinfo,
1938 rlc_lte_info *p_rlc_lte_info,
1939 rlc_lte_tap_info *tap_info,
1940 proto_tree *tree,
1941 tvbuff_t *tvb)
1942 {
1943 channel_hash_key channel_key;
1944 channel_sequence_analysis_status *p_channel_status;
1945 sequence_analysis_report *p_report_in_frame = NULL;
1946 guint32 snLimit;
1947
1948 /* If find stat_report_in_frame already, use that and get out */
1949 if (pinfo->fd->visited) {
1950 p_report_in_frame = (sequence_analysis_report*)wmem_map_lookup(sequence_analysis_report_hash,
1951 get_report_hash_key(0, pinfo->num,
1952 p_rlc_lte_info,
1953 FALSE));
1954 if (p_report_in_frame != NULL) {
1955 /* Add any info to tree */
1956 addChannelSequenceInfo(p_report_in_frame, TRUE, p_rlc_lte_info,
1957 0, FALSE,
1958 tap_info, pinfo, tree, tvb);
1959 return;
1960 }
1961 else {
1962 /* Give up - we must have tried already... */
1963 return;
1964 }
1965 }
1966
1967 /*******************************************************************/
1968 /* Find an entry for this channel state (in the opposite direction */
1969 channel_key.ueId = p_rlc_lte_info->ueid;
1970 channel_key.channelType = p_rlc_lte_info->channelType;
1971 channel_key.channelId = p_rlc_lte_info->channelId;
1972 channel_key.direction =
1973 (p_rlc_lte_info->direction == DIRECTION_UPLINK) ? DIRECTION_DOWNLINK : DIRECTION_UPLINK;
1974
1975 /* Do the table lookup */
1976 p_channel_status = (channel_sequence_analysis_status*)wmem_map_lookup(sequence_analysis_channel_hash, &channel_key);
1977
1978 /* Create table entry if necessary */
1979 if (p_channel_status == NULL) {
1980 return;
1981 }
1982
1983 /* Is it in the rx window? This test will catch if it's ahead, but we don't
1984 really know what the back of the tx window is... */
1985 snLimit = (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) ? 65536 : 1024;
1986 if (((snLimit + (guint32)p_channel_status->previousSequenceNumber+1 - ack_sn) % snLimit) > (snLimit>>1)) {
1987
1988 /* Set result */
1989 p_report_in_frame = wmem_new0(wmem_file_scope(), sequence_analysis_report);
1990 p_report_in_frame->state = ACK_Out_of_Window;
1991 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1992 p_report_in_frame->sequenceExpected = p_channel_status->previousSequenceNumber;
1993 p_report_in_frame->firstSN = ack_sn;
1994
1995 /* Associate with this frame number */
1996 wmem_map_insert(sequence_analysis_report_hash,
1997 get_report_hash_key(0, pinfo->num,
1998 p_rlc_lte_info, TRUE),
1999 p_report_in_frame);
2000
2001 /* Add state report for this frame into tree */
2002 addChannelSequenceInfo(p_report_in_frame, TRUE, p_rlc_lte_info, 0,
2003 FALSE, tap_info, pinfo, tree, tvb);
2004 }
2005 }
2006
2007
2008
2009
2010 /***************************************************/
2011 /* Transparent mode PDU. Call RRC if configured to */
dissect_rlc_lte_tm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_lte_info * p_rlc_lte_info,proto_item * top_ti)2012 static void dissect_rlc_lte_tm(tvbuff_t *tvb, packet_info *pinfo,
2013 proto_tree *tree,
2014 int offset,
2015 rlc_lte_info *p_rlc_lte_info,
2016 proto_item *top_ti)
2017 {
2018 proto_item *raw_tm_ti;
2019 proto_item *tm_ti;
2020
2021 /* Create hidden TM root */
2022 tm_ti = proto_tree_add_string_format(tree, hf_rlc_lte_tm,
2023 tvb, offset, 0, "", "TM");
2024 proto_item_set_hidden(tm_ti);
2025
2026 /* Remaining bytes are all data */
2027 raw_tm_ti = proto_tree_add_item(tree, hf_rlc_lte_tm_data, tvb, offset, -1, ENC_NA);
2028 if (!global_rlc_lte_call_rrc_for_ccch) {
2029 write_pdu_label_and_info(top_ti, NULL, pinfo,
2030 " [%u-bytes]", tvb_reported_length_remaining(tvb, offset));
2031 }
2032
2033 if (global_rlc_lte_call_rrc_for_ccch) {
2034 tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
2035 volatile dissector_handle_t protocol_handle;
2036
2037 switch (p_rlc_lte_info->channelType) {
2038 case CHANNEL_TYPE_CCCH:
2039 if (p_rlc_lte_info->direction == DIRECTION_UPLINK) {
2040 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2041 lte_rrc_ul_ccch_nb : lte_rrc_ul_ccch;
2042 }
2043 else {
2044 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2045 lte_rrc_dl_ccch_nb : lte_rrc_dl_ccch;
2046 }
2047 break;
2048
2049 case CHANNEL_TYPE_BCCH_BCH:
2050 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2051 lte_rrc_bcch_bch_nb : lte_rrc_bcch_bch;
2052 break;
2053 case CHANNEL_TYPE_BCCH_DL_SCH:
2054 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2055 lte_rrc_bcch_dl_sch_nb : lte_rrc_bcch_dl_sch;
2056 break;
2057 case CHANNEL_TYPE_PCCH:
2058 protocol_handle = (p_rlc_lte_info->nbMode == rlc_nb_mode) ?
2059 lte_rrc_pcch_nb : lte_rrc_pcch;
2060 break;
2061
2062 case CHANNEL_TYPE_SRB:
2063 case CHANNEL_TYPE_DRB:
2064 case CHANNEL_TYPE_MCCH:
2065 case CHANNEL_TYPE_MTCH:
2066
2067 default:
2068 /* Shouldn't happen, just return... */
2069 return;
2070 }
2071
2072 /* Hide raw view of bytes */
2073 proto_item_set_hidden(raw_tm_ti);
2074
2075 /* Call it (catch exceptions) */
2076 TRY {
2077 call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
2078 }
2079 CATCH_ALL {
2080 }
2081 ENDTRY
2082 }
2083 }
2084
2085
2086
2087 /***************************************************/
2088 /* Unacknowledged mode PDU */
dissect_rlc_lte_um(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_lte_info * p_rlc_lte_info,proto_item * top_ti,rlc_lte_tap_info * tap_info)2089 static void dissect_rlc_lte_um(tvbuff_t *tvb, packet_info *pinfo,
2090 proto_tree *tree,
2091 int offset,
2092 rlc_lte_info *p_rlc_lte_info,
2093 proto_item *top_ti,
2094 rlc_lte_tap_info *tap_info)
2095 {
2096 guint64 framing_info;
2097 gboolean first_includes_start;
2098 gboolean last_includes_end;
2099 guint64 fixed_extension;
2100 guint64 sn;
2101 gint start_offset = offset;
2102 proto_item *um_ti;
2103 proto_tree *um_header_tree;
2104 proto_item *um_header_ti;
2105 gboolean is_truncated = FALSE;
2106 proto_item *truncated_ti;
2107 rlc_channel_reassembly_info *reassembly_info = NULL;
2108 sequence_analysis_state seq_anal_state = SN_OK;
2109
2110 /* Hidden UM root */
2111 um_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um,
2112 tvb, offset, 0, "", "UM");
2113 proto_item_set_hidden(um_ti);
2114
2115 /* Add UM header subtree */
2116 um_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_um_header,
2117 tvb, offset, 0,
2118 "", "UM header");
2119 um_header_tree = proto_item_add_subtree(um_header_ti,
2120 ett_rlc_lte_um_header);
2121
2122
2123 /*******************************/
2124 /* Fixed UM header */
2125 if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_5_BITS) {
2126 /* Framing info (2 bits) */
2127 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
2128 tvb, offset*8, 2,
2129 &framing_info, ENC_BIG_ENDIAN);
2130
2131 /* Extension (1 bit) */
2132 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
2133 (offset*8) + 2, 1,
2134 &fixed_extension, ENC_BIG_ENDIAN);
2135
2136 /* Sequence Number (5 bit) */
2137 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
2138 (offset*8) + 3, 5,
2139 &sn, ENC_BIG_ENDIAN);
2140 offset++;
2141 }
2142 else if (p_rlc_lte_info->sequenceNumberLength == UM_SN_LENGTH_10_BITS) {
2143 guint8 reserved;
2144 proto_item *ti;
2145
2146 /* Check 3 Reserved bits */
2147 reserved = (tvb_get_guint8(tvb, offset) & 0xe0) >> 5;
2148 ti = proto_tree_add_item(um_header_tree, hf_rlc_lte_um_fixed_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2149 if (reserved != 0) {
2150 expert_add_info_format(pinfo, ti, &ei_rlc_lte_reserved_bits_not_zero,
2151 "RLC UM Fixed header Reserved bits not zero (found 0x%x)", reserved);
2152 }
2153
2154 /* Framing info (2 bits) */
2155 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fi,
2156 tvb, (offset*8)+3, 2,
2157 &framing_info, ENC_BIG_ENDIAN);
2158
2159 /* Extension (1 bit) */
2160 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_fixed_e, tvb,
2161 (offset*8) + 5, 1,
2162 &fixed_extension, ENC_BIG_ENDIAN);
2163
2164 /* Sequence Number (10 bits) */
2165 proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_lte_um_sn, tvb,
2166 (offset*8) + 6, 10,
2167 &sn, ENC_BIG_ENDIAN);
2168 offset += 2;
2169 }
2170 else {
2171 /* Invalid length of sequence number */
2172 proto_tree_add_expert_format(um_header_tree, pinfo, &ei_rlc_lte_um_sn, tvb, 0, 0,
2173 "Invalid sequence number length (%u bits)",
2174 p_rlc_lte_info->sequenceNumberLength);
2175 return;
2176 }
2177
2178 tap_info->sequenceNumber = (guint16)sn;
2179
2180 /* Show SN in info column */
2181 if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_MCCH) || (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH)) {
2182 write_pdu_label_and_info(top_ti, um_header_ti, pinfo, " sn=%-4u", (guint16)sn);
2183 }
2184 else {
2185 write_pdu_label_and_info(top_ti, um_header_ti, pinfo, " sn=%-4u", (guint16)sn);
2186 }
2187
2188 proto_item_set_len(um_header_ti, offset-start_offset);
2189
2190
2191 /*************************************/
2192 /* UM header extension */
2193 if (fixed_extension) {
2194 offset = dissect_rlc_lte_extension_header(tvb, pinfo, um_header_tree, offset, p_rlc_lte_info);
2195 }
2196
2197 /* Extract these 2 flags from framing_info */
2198 first_includes_start = ((guint8)framing_info & 0x02) == 0;
2199 last_includes_end = ((guint8)framing_info & 0x01) == 0;
2200
2201 if (global_rlc_lte_headers_expected) {
2202 /* There might not be any data, if only headers (plus control data) were logged */
2203 is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
2204 truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
2205 is_truncated);
2206 if (is_truncated) {
2207 int n;
2208 proto_item_set_generated(truncated_ti);
2209 expert_add_info(pinfo, truncated_ti, &ei_rlc_lte_header_only);
2210
2211 /* Show in the info column how long the data would be */
2212 for (n=0; n < s_number_of_extensions; n++) {
2213 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2214 (n==0) ? first_includes_start : TRUE,
2215 TRUE);
2216 offset += s_lengths[n];
2217 }
2218 /* Last one */
2219 show_PDU_in_info(pinfo, top_ti, p_rlc_lte_info->pduLength - offset,
2220 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2221 last_includes_end);
2222 }
2223 else {
2224 proto_item_set_hidden(truncated_ti);
2225 }
2226 }
2227
2228 /* Show number of extensions in header root */
2229 if (s_number_of_extensions > 0) {
2230 proto_item_append_text(um_header_ti, " (%u extensions)", s_number_of_extensions);
2231 }
2232
2233 /* Call sequence analysis function now */
2234 if (((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2235 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2236 ((global_rlc_lte_um_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2237 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2238
2239 guint16 lastSegmentOffset = offset;
2240 if (s_number_of_extensions >= 1) {
2241 int n;
2242 lastSegmentOffset = offset;
2243 for (n=0; n < s_number_of_extensions; n++) {
2244 lastSegmentOffset += s_lengths[n];
2245 }
2246 }
2247
2248 seq_anal_state = checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info,
2249 FALSE,
2250 s_number_of_extensions+1,
2251 offset,
2252 s_number_of_extensions ?
2253 s_lengths[0] :
2254 p_rlc_lte_info->pduLength - offset,
2255 lastSegmentOffset,
2256 (guint16)sn, first_includes_start, last_includes_end,
2257 FALSE, /* UM doesn't re-segment */
2258 tap_info, um_header_tree);
2259 }
2260
2261 if (is_truncated) {
2262 return;
2263 }
2264
2265 /*************************************/
2266 /* Data */
2267
2268 reassembly_info = (rlc_channel_reassembly_info *)wmem_map_lookup(reassembly_report_hash,
2269 get_report_hash_key((guint16)sn, pinfo->num,
2270 p_rlc_lte_info, FALSE));
2271
2272 if (s_number_of_extensions > 0) {
2273 /* Show each data segment separately */
2274 int n;
2275 for (n=0; n < s_number_of_extensions; n++) {
2276 show_PDU_in_tree(pinfo, tree, tvb, offset, s_lengths[n], p_rlc_lte_info,
2277 (n==0) ? first_includes_start : TRUE,
2278 (n==0) ? reassembly_info : NULL,
2279 seq_anal_state);
2280 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2281 (n==0) ? first_includes_start : TRUE,
2282 TRUE);
2283 /* Make sure we don't lose the summary of this SDU */
2284 col_append_str(pinfo->cinfo, COL_INFO, " | ");
2285 col_set_fence(pinfo->cinfo, COL_INFO);
2286
2287 tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
2288 offset += s_lengths[n];
2289 }
2290 }
2291
2292 /* Final data element */
2293 show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), p_rlc_lte_info,
2294 ((s_number_of_extensions == 0) ? first_includes_start : TRUE) && last_includes_end,
2295 (s_number_of_extensions == 0) ? reassembly_info : NULL,
2296 seq_anal_state);
2297 show_PDU_in_info(pinfo, top_ti, (guint16)tvb_reported_length_remaining(tvb, offset),
2298 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2299 last_includes_end);
2300 }
2301
2302
2303
2304 /* Dissect an AM STATUS PDU */
dissect_rlc_lte_am_status_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * status_ti,int offset,proto_item * top_ti,rlc_lte_info * p_rlc_lte_info,rlc_lte_tap_info * tap_info)2305 static void dissect_rlc_lte_am_status_pdu(tvbuff_t *tvb,
2306 packet_info *pinfo,
2307 proto_tree *tree,
2308 proto_item *status_ti,
2309 int offset,
2310 proto_item *top_ti,
2311 rlc_lte_info *p_rlc_lte_info,
2312 rlc_lte_tap_info *tap_info)
2313 {
2314 guint8 cpt, sn_size, so_size;
2315 guint32 sn_limit;
2316 guint64 ack_sn, nack_sn;
2317 guint16 nack_count = 0, so_end_of_pdu;
2318 guint64 e1 = 0, e2 = 0;
2319 guint64 so_start, so_end;
2320 int bit_offset = offset * 8;
2321 proto_item *ti;
2322
2323 /****************************************************************/
2324 /* Part of RLC control PDU header */
2325
2326 /* Control PDU Type (CPT) */
2327 cpt = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
2328 ti = proto_tree_add_item(tree, hf_rlc_lte_am_cpt, tvb, offset, 1, ENC_BIG_ENDIAN);
2329 if (cpt != 0) {
2330 /* Protest and stop - only know about STATUS PDUs */
2331 expert_add_info_format(pinfo, ti, &ei_rlc_lte_am_cpt,
2332 "RLC Control frame type %u not handled", cpt);
2333 return;
2334 }
2335
2336 if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2337 sn_size = 16;
2338 sn_limit = 65536;
2339 so_size = 16;
2340 so_end_of_pdu = 0xffff;
2341 } else {
2342 sn_size = 10;
2343 sn_limit = 1024;
2344 so_size = 15;
2345 so_end_of_pdu = 0x7fff;
2346 }
2347
2348 /* The Status PDU itself starts 4 bits into the byte */
2349 bit_offset += 4;
2350
2351 /* ACK SN */
2352 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_ack_sn, tvb,
2353 bit_offset, sn_size, &ack_sn, ENC_BIG_ENDIAN);
2354 bit_offset += sn_size;
2355 write_pdu_label_and_info(top_ti, status_ti, pinfo, " ACK_SN=%-4u", (guint16)ack_sn);
2356
2357 tap_info->ACKNo = (guint16)ack_sn;
2358
2359 /* E1 */
2360 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
2361 bit_offset, 1, &e1, ENC_BIG_ENDIAN);
2362
2363 /* Skip another bit to byte-align the next bit... */
2364 bit_offset++;
2365
2366 /* Optional, extra fields */
2367 do {
2368 if (e1) {
2369 proto_item *nack_ti;
2370
2371 /****************************/
2372 /* Read NACK_SN, E1, E2 */
2373
2374 /* NACK_SN */
2375 nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_nack_sn, tvb,
2376 bit_offset, sn_size, &nack_sn, ENC_BIG_ENDIAN);
2377 bit_offset += sn_size;
2378 write_pdu_label_and_info(top_ti, NULL, pinfo, " NACK_SN=%-4u", (guint16)nack_sn);
2379
2380 /* We shouldn't NACK the ACK_SN! */
2381 if (nack_sn == ack_sn) {
2382 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_ack_same,
2383 "Status PDU shouldn't ACK and NACK the same sequence number (%" G_GINT64_MODIFIER "u)",
2384 ack_sn);
2385 }
2386
2387 /* NACK should always be 'behind' the ACK */
2388 if ((sn_limit + ack_sn - nack_sn) % sn_limit > (sn_limit>>1)) {
2389 expert_add_info(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_ahead_ack);
2390 }
2391
2392 /* Copy into struct, but don't exceed buffer */
2393 if (nack_count < MAX_NACKs) {
2394 tap_info->NACKs[nack_count++] = (guint16)nack_sn;
2395 }
2396 else {
2397 /* Let it get bigger than the array for accurate stats... */
2398 nack_count++;
2399 }
2400
2401 /* E1 */
2402 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e1, tvb,
2403 bit_offset, 1, &e1, ENC_BIG_ENDIAN);
2404 bit_offset++;
2405
2406 /* E2 */
2407 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_e2, tvb,
2408 bit_offset, 1, &e2, ENC_BIG_ENDIAN);
2409
2410 /* Report as expert info */
2411 if (e2) {
2412 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn_partial,
2413 "Status PDU reports NACK (partial) on %s for UE %u",
2414 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
2415 p_rlc_lte_info->ueid);
2416 }
2417 else {
2418 expert_add_info_format(pinfo, nack_ti, &ei_rlc_lte_am_nack_sn,
2419 "Status PDU reports NACK on %s for UE %u",
2420 val_to_str_const(p_rlc_lte_info->direction, direction_vals, "Unknown"),
2421 p_rlc_lte_info->ueid);
2422 }
2423
2424 bit_offset++;
2425 }
2426
2427 if (e2) {
2428 /* Read SOstart, SOend */
2429 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_start, tvb,
2430 bit_offset, so_size, &so_start, ENC_BIG_ENDIAN);
2431 bit_offset += so_size;
2432
2433 proto_tree_add_bits_ret_val(tree, hf_rlc_lte_am_so_end, tvb,
2434 bit_offset, so_size, &so_end, ENC_BIG_ENDIAN);
2435 bit_offset += so_size;
2436
2437
2438 if ((guint16)so_end == so_end_of_pdu) {
2439 write_pdu_label_and_info(top_ti, NULL, pinfo,
2440 " (SOstart=%u SOend=<END-OF_PDU>)",
2441 (guint16)so_start);
2442 }
2443 else {
2444 write_pdu_label_and_info(top_ti, NULL, pinfo,
2445 " (SOstart=%u SOend=%u)",
2446 (guint16)so_start, (guint16)so_end);
2447 }
2448
2449 /* Reset this flag here */
2450 e2 = 0;
2451 }
2452 } while (e1);
2453
2454 if (nack_count > 0) {
2455 proto_item *count_ti = proto_tree_add_uint(tree, hf_rlc_lte_am_nacks, tvb, 0, 1, nack_count);
2456 proto_item_set_generated(count_ti);
2457 proto_item_append_text(status_ti, " (%u NACKs)", nack_count);
2458 tap_info->noOfNACKs = nack_count;
2459 }
2460
2461 /* Check that we've reached the end of the PDU. If not, show malformed */
2462 offset = (bit_offset+7) / 8;
2463 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2464 expert_add_info_format(pinfo, status_ti, &ei_rlc_lte_bytes_after_status_pdu_complete,
2465 "%cL %u bytes remaining after Status PDU complete",
2466 (p_rlc_lte_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
2467 tvb_reported_length_remaining(tvb, offset));
2468 }
2469
2470 /* Set selected length of control tree */
2471 proto_item_set_len(status_ti, offset);
2472
2473 /* Repeated NACK analysis & check ACK-SN is in range */
2474 if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2475 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2476 ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2477 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2478
2479 if (!is_mac_lte_frame_retx(pinfo, p_rlc_lte_info->direction)) {
2480 checkChannelRepeatedNACKInfo(pinfo, p_rlc_lte_info, tap_info, tree, tvb);
2481 checkChannelACKWindow((guint16)ack_sn, pinfo, p_rlc_lte_info, tap_info, tree, tvb);
2482 }
2483 }
2484 }
2485
2486
2487 /***************************************************/
2488 /* Acknowledged mode PDU */
dissect_rlc_lte_am(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_lte_info * p_rlc_lte_info,proto_item * top_ti,rlc_lte_tap_info * tap_info)2489 static void dissect_rlc_lte_am(tvbuff_t *tvb, packet_info *pinfo,
2490 proto_tree *tree,
2491 int offset,
2492 rlc_lte_info *p_rlc_lte_info,
2493 proto_item *top_ti,
2494 rlc_lte_tap_info *tap_info)
2495 {
2496 guint8 is_data;
2497 guint8 is_resegmented;
2498 guint8 polling;
2499 guint8 fixed_extension;
2500 guint8 framing_info;
2501 gboolean first_includes_start;
2502 gboolean last_includes_end;
2503 proto_item *am_ti;
2504 proto_tree *am_header_tree;
2505 proto_item *am_header_ti;
2506 gint start_offset = offset;
2507 guint16 sn;
2508 gboolean is_truncated = FALSE;
2509 proto_item *truncated_ti;
2510 rlc_channel_reassembly_info *reassembly_info = NULL;
2511 sequence_analysis_state seq_anal_state = SN_OK;
2512 guint32 id;
2513 wmem_tree_key_t key[3];
2514 rlc_ue_parameters *params;
2515
2516 /* Hidden AM root */
2517 am_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am,
2518 tvb, offset, 0, "", "AM");
2519 proto_item_set_hidden(am_ti);
2520
2521 /* Add AM header subtree */
2522 am_header_ti = proto_tree_add_string_format(tree, hf_rlc_lte_am_header,
2523 tvb, offset, 0,
2524 "", "AM Header ");
2525 am_header_tree = proto_item_add_subtree(am_header_ti,
2526 ett_rlc_lte_am_header);
2527
2528 /* First bit is Data/Control flag */
2529 is_data = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
2530 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
2531 tap_info->isControlPDU = !is_data;
2532
2533 if (!is_data) {
2534 /**********************/
2535 /* Status PDU */
2536 write_pdu_label_and_info_literal(top_ti, NULL, pinfo, " [CONTROL]");
2537
2538 /* Control PDUs are a completely separate format */
2539 dissect_rlc_lte_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti,
2540 offset, top_ti,
2541 p_rlc_lte_info, tap_info);
2542 return;
2543 }
2544
2545 /******************************/
2546 /* Data PDU fixed header */
2547
2548 /* Re-segmentation Flag (RF) field */
2549 is_resegmented = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
2550 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_rf, tvb, offset, 1, ENC_BIG_ENDIAN);
2551 tap_info->isResegmented = is_resegmented;
2552
2553 write_pdu_label_and_info_literal(top_ti, NULL, pinfo,
2554 (is_resegmented) ? " [DATA-SEGMENT]" : " [DATA]");
2555
2556 /* Polling bit */
2557 polling = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
2558 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_p, tvb, offset, 1, ENC_BIG_ENDIAN);
2559
2560 write_pdu_label_and_info_literal(top_ti, NULL, pinfo, (polling) ? " (P) " : " ");
2561 if (polling) {
2562 proto_item_append_text(am_header_ti, " (P) ");
2563 }
2564
2565 /* Framing Info */
2566 framing_info = (tvb_get_guint8(tvb, offset) & 0x18) >> 3;
2567 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fi, tvb, offset, 1, ENC_BIG_ENDIAN);
2568
2569 /* Extension bit */
2570 fixed_extension = (tvb_get_guint8(tvb, offset) & 0x04) >> 2;
2571 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_e, tvb, offset, 1, ENC_BIG_ENDIAN);
2572
2573 /* Sequence Number */
2574 if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2575 guint8 reserved;
2576
2577 if (is_resegmented) {
2578 /* Last Segment Field (LSF) */
2579 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf16, tvb, offset, 1, ENC_BIG_ENDIAN);
2580 /* Reserved (R1) */
2581 am_ti = proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_reserved2, tvb, offset, 1, ENC_BIG_ENDIAN);
2582 reserved = tvb_get_guint8(tvb, offset) & 0x01;
2583 } else {
2584 /* Reserved (R1) */
2585 am_ti = proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
2586 reserved = tvb_get_guint8(tvb, offset) & 0x03;
2587 }
2588 if (reserved != 0) {
2589 expert_add_info_format(pinfo, am_ti, &ei_rlc_lte_reserved_bits_not_zero,
2590 "RLC AM Fixed header Reserved bits not zero (found 0x%x)", reserved);
2591 }
2592 offset += 1;
2593 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn16, tvb, offset, 2, ENC_BIG_ENDIAN);
2594 sn = tvb_get_ntohs(tvb, offset);
2595 offset += 2;
2596 } else {
2597 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_fixed_sn, tvb, offset, 2, ENC_BIG_ENDIAN);
2598 sn = tvb_get_ntohs(tvb, offset) & 0x03ff;
2599 offset += 2;
2600 }
2601 tap_info->sequenceNumber = sn;
2602
2603 write_pdu_label_and_info(top_ti, am_header_ti, pinfo, "sn=%-4u", sn);
2604
2605 /***************************************/
2606 /* Dissect extra segment header fields */
2607 if (is_resegmented) {
2608 guint16 segmentOffset;
2609
2610 if (p_rlc_lte_info->sequenceNumberLength == AM_SN_LENGTH_16_BITS) {
2611 /* SO */
2612 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so16, tvb, offset, 2, ENC_BIG_ENDIAN);
2613 segmentOffset = tvb_get_ntohs(tvb, offset);
2614 } else {
2615 /* Last Segment Field (LSF) */
2616 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_lsf, tvb, offset, 1, ENC_BIG_ENDIAN);
2617
2618 /* SO */
2619 proto_tree_add_item(am_header_tree, hf_rlc_lte_am_segment_so, tvb, offset, 2, ENC_BIG_ENDIAN);
2620 segmentOffset = tvb_get_ntohs(tvb, offset) & 0x7fff;
2621 }
2622 write_pdu_label_and_info(top_ti, am_header_ti, pinfo, " SO=%u ", segmentOffset);
2623 offset += 2;
2624 }
2625
2626 /*************************************/
2627 /* AM header extension */
2628 if (fixed_extension) {
2629 if (!PINFO_FD_VISITED(pinfo)) {
2630 id = (p_rlc_lte_info->channelId << 16) | p_rlc_lte_info->ueid;
2631 key[0].length = 1;
2632 key[0].key = &id;
2633 key[1].length = 1;
2634 key[1].key = &pinfo->num;
2635 key[2].length = 0;
2636 key[2].key = NULL;
2637 params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
2638 if (params && (params->id == id)) {
2639 p_rlc_lte_info->extendedLiField = (p_rlc_lte_info->direction == DIRECTION_UPLINK) ?
2640 (params->ext_li_field & UL_EXT_LI): (params->ext_li_field & DL_EXT_LI);
2641 }
2642 }
2643 offset = dissect_rlc_lte_extension_header(tvb, pinfo, am_header_tree, offset, p_rlc_lte_info);
2644 }
2645
2646 /* Header is now complete */
2647 proto_item_set_len(am_header_ti, offset-start_offset);
2648
2649 /* Show number of extensions in header root */
2650 if (s_number_of_extensions > 0) {
2651 proto_item_append_text(am_header_ti, " (%u extensions)", s_number_of_extensions);
2652 }
2653
2654 /* Extract these 2 flags from framing_info */
2655 first_includes_start = (framing_info & 0x02) == 0;
2656 last_includes_end = (framing_info & 0x01) == 0;
2657
2658 /* There might not be any data, if only headers (plus control data) were logged */
2659 if (global_rlc_lte_headers_expected) {
2660 is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
2661 truncated_ti = proto_tree_add_uint(tree, hf_rlc_lte_header_only, tvb, 0, 0,
2662 is_truncated);
2663 if (is_truncated) {
2664 int n;
2665 proto_item_set_generated(truncated_ti);
2666 expert_add_info(pinfo, truncated_ti, &ei_rlc_lte_header_only);
2667 /* Show in the info column how long the data would be */
2668 for (n=0; n < s_number_of_extensions; n++) {
2669 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2670 (n==0) ? first_includes_start : TRUE,
2671 TRUE);
2672 offset += s_lengths[n];
2673 }
2674 /* Last one */
2675 show_PDU_in_info(pinfo, top_ti, p_rlc_lte_info->pduLength - offset,
2676 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2677 last_includes_end);
2678 }
2679 else {
2680 proto_item_set_hidden(truncated_ti);
2681 }
2682 }
2683
2684 /* Call sequence analysis function now */
2685 if (((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_MAC_ONLY) &&
2686 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL)) ||
2687 ((global_rlc_lte_am_sequence_analysis == SEQUENCE_ANALYSIS_RLC_ONLY) &&
2688 (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) == NULL))) {
2689
2690 guint16 firstSegmentLength;
2691 guint16 lastSegmentOffset = offset;
2692 if (s_number_of_extensions >= 1) {
2693 int n;
2694 for (n=0; n < s_number_of_extensions; n++) {
2695 lastSegmentOffset += s_lengths[n];
2696 }
2697
2698 firstSegmentLength = s_lengths[0];
2699 }
2700 else {
2701 firstSegmentLength = tvb_reported_length_remaining(tvb, offset);
2702 }
2703
2704 seq_anal_state = checkChannelSequenceInfo(pinfo, tvb, p_rlc_lte_info, FALSE,
2705 s_number_of_extensions+1,
2706 offset, firstSegmentLength,
2707 lastSegmentOffset,
2708 (guint16)sn,
2709 first_includes_start, last_includes_end,
2710 is_resegmented, tap_info, tree);
2711 }
2712
2713 if (is_truncated) {
2714 return;
2715 }
2716
2717 /*************************************/
2718 /* Data */
2719
2720 if (!first_includes_start) {
2721 reassembly_info = (rlc_channel_reassembly_info *)wmem_map_lookup(reassembly_report_hash,
2722 get_report_hash_key((guint16)sn,
2723 pinfo->num,
2724 p_rlc_lte_info,
2725 FALSE));
2726 }
2727
2728 if (s_number_of_extensions > 0) {
2729 /* Show each data segment separately */
2730 int n;
2731 for (n=0; n < s_number_of_extensions; n++) {
2732 show_PDU_in_tree(pinfo, tree, tvb, offset, s_lengths[n], p_rlc_lte_info,
2733 (n==0) ? first_includes_start : TRUE,
2734 (n==0) ? reassembly_info : NULL,
2735 seq_anal_state);
2736 show_PDU_in_info(pinfo, top_ti, s_lengths[n],
2737 (n==0) ? first_includes_start : TRUE,
2738 TRUE);
2739 /* Make sure we don't lose the summary of this SDU */
2740 col_append_str(pinfo->cinfo, COL_INFO, " | ");
2741 col_set_fence(pinfo->cinfo, COL_INFO);
2742
2743 tvb_ensure_bytes_exist(tvb, offset, s_lengths[n]);
2744 offset += s_lengths[n];
2745 }
2746 }
2747
2748 /* Final data element */
2749 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2750 show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), p_rlc_lte_info,
2751 ((s_number_of_extensions == 0) ? first_includes_start : TRUE) && last_includes_end,
2752 (s_number_of_extensions == 0) ? reassembly_info : NULL,
2753 seq_anal_state);
2754 show_PDU_in_info(pinfo, top_ti, (guint16)tvb_reported_length_remaining(tvb, offset),
2755 (s_number_of_extensions == 0) ? first_includes_start : TRUE,
2756 last_includes_end);
2757 }
2758 else {
2759 /* Report that expected data was missing (unless we know it might happen) */
2760 if (!global_rlc_lte_headers_expected) {
2761 if (s_number_of_extensions > 0) {
2762 expert_add_info(pinfo, am_header_ti, &ei_rlc_lte_am_data_no_data_beyond_extensions);
2763 }
2764 else {
2765 expert_add_info(pinfo, am_header_ti, &ei_rlc_lte_am_data_no_data);
2766 }
2767 }
2768 }
2769 }
2770
report_heur_error(proto_tree * tree,packet_info * pinfo,expert_field * eiindex,tvbuff_t * tvb,gint start,gint length)2771 static void report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
2772 tvbuff_t *tvb, gint start, gint length)
2773 {
2774 proto_item *ti;
2775 proto_tree *subtree;
2776
2777 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
2778 col_clear(pinfo->cinfo, COL_INFO);
2779 ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, 0, -1, ENC_NA);
2780 subtree = proto_item_add_subtree(ti, ett_rlc_lte);
2781 proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
2782 }
2783
2784 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
dissect_rlc_lte_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2785 static gboolean dissect_rlc_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
2786 proto_tree *tree, void *data _U_)
2787 {
2788 gint offset = 0;
2789 struct rlc_lte_info *p_rlc_lte_info;
2790 tvbuff_t *rlc_tvb;
2791 guint8 tag = 0;
2792 gboolean seqNumLengthTagPresent = FALSE;
2793
2794 /* Needs to be at least as long as:
2795 - the signature string
2796 - fixed header bytes
2797 - tag for data
2798 - at least one byte of RLC PDU payload */
2799 if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(RLC_LTE_START_STRING)+1+2)) {
2800 return FALSE;
2801 }
2802
2803 /* OK, compare with signature string */
2804 if (tvb_strneql(tvb, offset, RLC_LTE_START_STRING, (gint)strlen(RLC_LTE_START_STRING)) != 0) {
2805 return FALSE;
2806 }
2807 offset += (gint)strlen(RLC_LTE_START_STRING);
2808
2809
2810 /* If redissecting, use previous info struct (if available) */
2811 p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2812 if (p_rlc_lte_info == NULL) {
2813 /* Allocate new info struct for this frame */
2814 p_rlc_lte_info = wmem_new0(wmem_file_scope(), struct rlc_lte_info);
2815
2816 /* Read fixed fields */
2817 p_rlc_lte_info->rlcMode = tvb_get_guint8(tvb, offset++);
2818 if (p_rlc_lte_info->rlcMode == RLC_AM_MODE) {
2819 p_rlc_lte_info->sequenceNumberLength = AM_SN_LENGTH_10_BITS;
2820 }
2821
2822 /* Read optional fields */
2823 while (tag != RLC_LTE_PAYLOAD_TAG) {
2824 /* Process next tag */
2825 tag = tvb_get_guint8(tvb, offset++);
2826 switch (tag) {
2827 case RLC_LTE_SN_LENGTH_TAG:
2828 p_rlc_lte_info->sequenceNumberLength = tvb_get_guint8(tvb, offset);
2829 offset++;
2830 seqNumLengthTagPresent = TRUE;
2831 break;
2832 case RLC_LTE_DIRECTION_TAG:
2833 p_rlc_lte_info->direction = tvb_get_guint8(tvb, offset);
2834 offset++;
2835 break;
2836 case RLC_LTE_PRIORITY_TAG:
2837 p_rlc_lte_info->priority = tvb_get_guint8(tvb, offset);
2838 offset++;
2839 break;
2840 case RLC_LTE_UEID_TAG:
2841 p_rlc_lte_info->ueid = tvb_get_ntohs(tvb, offset);
2842 offset += 2;
2843 break;
2844 case RLC_LTE_CHANNEL_TYPE_TAG:
2845 p_rlc_lte_info->channelType = tvb_get_ntohs(tvb, offset);
2846 offset += 2;
2847 break;
2848 case RLC_LTE_CHANNEL_ID_TAG:
2849 p_rlc_lte_info->channelId = tvb_get_ntohs(tvb, offset);
2850 offset += 2;
2851 break;
2852 case RLC_LTE_EXT_LI_FIELD_TAG:
2853 p_rlc_lte_info->extendedLiField = TRUE;
2854 break;
2855 case RLC_LTE_NB_MODE_TAG:
2856 p_rlc_lte_info->nbMode =
2857 (rlc_lte_nb_mode)tvb_get_guint8(tvb, offset);
2858 offset++;
2859 break;
2860
2861 case RLC_LTE_PAYLOAD_TAG:
2862 /* Have reached data, so set payload length and get out of loop */
2863 p_rlc_lte_info->pduLength = tvb_reported_length_remaining(tvb, offset);
2864 continue;
2865
2866 default:
2867 /* It must be a recognised tag */
2868 report_heur_error(tree, pinfo, &ei_rlc_lte_unknown_udp_framing_tag, tvb, offset-1, 1);
2869 wmem_free(wmem_file_scope(), p_rlc_lte_info);
2870 return TRUE;
2871 }
2872 }
2873
2874 if ((p_rlc_lte_info->rlcMode == RLC_UM_MODE) && (seqNumLengthTagPresent == FALSE)) {
2875 /* Conditional field is not present */
2876 report_heur_error(tree, pinfo, &ei_rlc_lte_missing_udp_framing_tag, tvb, 0, offset);
2877 wmem_free(wmem_file_scope(), p_rlc_lte_info);
2878 return TRUE;
2879 }
2880
2881 /* Store info in packet */
2882 p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0, p_rlc_lte_info);
2883 }
2884 else {
2885 offset = tvb_reported_length(tvb) - p_rlc_lte_info->pduLength;
2886 }
2887
2888 /**************************************/
2889 /* OK, now dissect as RLC LTE */
2890
2891 /* Create tvb that starts at actual RLC PDU */
2892 rlc_tvb = tvb_new_subset_remaining(tvb, offset);
2893 dissect_rlc_lte_common(rlc_tvb, pinfo, tree, TRUE);
2894 return TRUE;
2895 }
2896
2897
2898
2899 /*****************************/
2900 /* Main dissection function. */
2901 /*****************************/
2902
dissect_rlc_lte(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2903 static int dissect_rlc_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
2904 {
2905 dissect_rlc_lte_common(tvb, pinfo, tree, FALSE);
2906 return tvb_captured_length(tvb);
2907 }
2908
dissect_rlc_lte_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gboolean is_udp_framing)2909 static void dissect_rlc_lte_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing)
2910 {
2911 proto_tree *rlc_lte_tree;
2912 proto_tree *context_tree;
2913 proto_item *top_ti;
2914 proto_item *context_ti;
2915 proto_item *ti;
2916 proto_item *mode_ti;
2917 gint offset = 0;
2918 struct rlc_lte_info *p_rlc_lte_info;
2919
2920 /* Allocate and Zero tap struct */
2921 rlc_lte_tap_info *tap_info = wmem_new0(pinfo->pool, rlc_lte_tap_info);
2922
2923 /* Set protocol name */
2924 col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-LTE");
2925
2926 /* Create protocol tree. */
2927 top_ti = proto_tree_add_item(tree, proto_rlc_lte, tvb, offset, -1, ENC_NA);
2928 rlc_lte_tree = proto_item_add_subtree(top_ti, ett_rlc_lte);
2929
2930
2931 /* Look for packet info! */
2932 p_rlc_lte_info = (rlc_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0);
2933
2934 /* Can't dissect anything without it... */
2935 if (p_rlc_lte_info == NULL) {
2936 proto_tree_add_expert(rlc_lte_tree, pinfo, &ei_rlc_lte_no_per_frame_info, tvb, offset, -1);
2937 return;
2938 }
2939
2940 /* Clear info column when using UDP framing */
2941 if (is_udp_framing) {
2942 col_clear(pinfo->cinfo, COL_INFO);
2943 }
2944
2945 /*****************************************/
2946 /* Show context information */
2947
2948 /* Create context root */
2949 context_ti = proto_tree_add_string_format(rlc_lte_tree, hf_rlc_lte_context,
2950 tvb, offset, 0, "", "Context");
2951 context_tree = proto_item_add_subtree(context_ti, ett_rlc_lte_context);
2952 proto_item_set_generated(context_ti);
2953
2954 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_direction,
2955 tvb, 0, 0, p_rlc_lte_info->direction);
2956 proto_item_set_generated(ti);
2957
2958 mode_ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_mode,
2959 tvb, 0, 0, p_rlc_lte_info->rlcMode);
2960 proto_item_set_generated(mode_ti);
2961
2962 if (p_rlc_lte_info->ueid != 0) {
2963 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_ueid,
2964 tvb, 0, 0, p_rlc_lte_info->ueid);
2965 proto_item_set_generated(ti);
2966 }
2967
2968 if ((p_rlc_lte_info->priority >= 1) && (p_rlc_lte_info->priority <=16)) {
2969 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_priority,
2970 tvb, 0, 0, p_rlc_lte_info->priority);
2971 proto_item_set_generated(ti);
2972 }
2973
2974 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_type,
2975 tvb, 0, 0, p_rlc_lte_info->channelType);
2976 proto_item_set_generated(ti);
2977
2978 if ((p_rlc_lte_info->channelType == CHANNEL_TYPE_SRB) ||
2979 (p_rlc_lte_info->channelType == CHANNEL_TYPE_DRB) ||
2980 (p_rlc_lte_info->channelType == CHANNEL_TYPE_MTCH)) {
2981 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_channel_id,
2982 tvb, 0, 0, p_rlc_lte_info->channelId);
2983 proto_item_set_generated(ti);
2984 }
2985
2986 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_pdu_length,
2987 tvb, 0, 0, p_rlc_lte_info->pduLength);
2988 proto_item_set_generated(ti);
2989
2990 if (p_rlc_lte_info->rlcMode == RLC_UM_MODE) {
2991 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_um_sn_length,
2992 tvb, 0, 0, p_rlc_lte_info->sequenceNumberLength);
2993 proto_item_set_generated(ti);
2994 }
2995
2996 if (p_rlc_lte_info->rlcMode == RLC_AM_MODE) {
2997 ti = proto_tree_add_uint(context_tree, hf_rlc_lte_context_am_sn_length,
2998 tvb, 0, 0, p_rlc_lte_info->sequenceNumberLength ?
2999 p_rlc_lte_info->sequenceNumberLength : 10);
3000 proto_item_set_generated(ti);
3001 }
3002
3003 /* Append highlights to top-level item */
3004 if (p_rlc_lte_info->ueid != 0) {
3005 proto_item_append_text(top_ti, " UEId=%u", p_rlc_lte_info->ueid);
3006 col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%-4u ", p_rlc_lte_info->ueid);
3007 }
3008
3009 /* Append context highlights to info column */
3010 write_pdu_label_and_info(top_ti, NULL, pinfo,
3011 " [%s] [%s] ",
3012 (p_rlc_lte_info->direction == 0) ? "UL" : "DL",
3013 val_to_str_const(p_rlc_lte_info->rlcMode, rlc_mode_short_vals, "Unknown"));
3014
3015 if (p_rlc_lte_info->channelId == 0) {
3016 write_pdu_label_and_info(top_ti, NULL, pinfo, "%s ",
3017 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"));
3018 }
3019 else {
3020 write_pdu_label_and_info(top_ti, NULL, pinfo, "%s:%-2u",
3021 val_to_str_const(p_rlc_lte_info->channelType, rlc_channel_type_vals, "Unknown"),
3022 p_rlc_lte_info->channelId);
3023 }
3024
3025 /* Set context-info parts of tap struct */
3026 tap_info->rlcMode = p_rlc_lte_info->rlcMode;
3027 tap_info->direction = p_rlc_lte_info->direction;
3028 tap_info->priority = p_rlc_lte_info->priority;
3029 tap_info->ueid = p_rlc_lte_info->ueid;
3030 tap_info->channelType = p_rlc_lte_info->channelType;
3031 tap_info->channelId = p_rlc_lte_info->channelId;
3032 tap_info->pduLength = p_rlc_lte_info->pduLength;
3033 tap_info->sequenceNumberLength = p_rlc_lte_info->sequenceNumberLength;
3034 tap_info->loggedInMACFrame = (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_lte, 0) != NULL);
3035
3036 tap_info->rlc_lte_time = pinfo->abs_ts;
3037
3038 /* Reset this count */
3039 s_number_of_extensions = 0;
3040
3041 /* Dissect the RLC PDU itself. Format depends upon mode... */
3042 switch (p_rlc_lte_info->rlcMode) {
3043
3044 case RLC_TM_MODE:
3045 dissect_rlc_lte_tm(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti);
3046 break;
3047
3048 case RLC_UM_MODE:
3049 dissect_rlc_lte_um(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
3050 tap_info);
3051 break;
3052
3053 case RLC_AM_MODE:
3054 dissect_rlc_lte_am(tvb, pinfo, rlc_lte_tree, offset, p_rlc_lte_info, top_ti,
3055 tap_info);
3056 break;
3057
3058 case RLC_PREDEF:
3059 /* Predefined data (i.e. not containing a valid RLC header */
3060 proto_tree_add_item(rlc_lte_tree, hf_rlc_lte_predefined_pdu, tvb, offset, -1, ENC_NA);
3061 write_pdu_label_and_info(top_ti, NULL, pinfo, " [%u-bytes]",
3062 tvb_reported_length_remaining(tvb, offset));
3063 break;
3064
3065 default:
3066 /* Error - unrecognised mode */
3067 expert_add_info_format(pinfo, mode_ti, &ei_rlc_lte_context_mode,
3068 "Unrecognised RLC Mode set (%u)", p_rlc_lte_info->rlcMode);
3069 break;
3070 }
3071
3072 /* Queue tap info */
3073 tap_queue_packet(rlc_lte_tap, pinfo, tap_info);
3074 }
3075
3076
3077
3078 /* Configure number of PDCP SN bits to use for DRB channels */
set_rlc_lte_drb_pdcp_seqnum_length(packet_info * pinfo,guint16 ueid,guint8 drbid,guint8 userplane_seqnum_length)3079 void set_rlc_lte_drb_pdcp_seqnum_length(packet_info *pinfo, guint16 ueid, guint8 drbid,
3080 guint8 userplane_seqnum_length)
3081 {
3082 wmem_tree_key_t key[3];
3083 guint32 id;
3084 rlc_ue_parameters *params;
3085
3086 if (PINFO_FD_VISITED(pinfo)) {
3087 return;
3088 }
3089
3090 id = (drbid << 16) | ueid;
3091 key[0].length = 1;
3092 key[0].key = &id;
3093 key[1].length = 1;
3094 key[1].key = &pinfo->num;
3095 key[2].length = 0;
3096 key[2].key = NULL;
3097
3098 params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
3099 if (params && (params->id != id)) {
3100 params = NULL;
3101 }
3102 if (params == NULL) {
3103 params = (rlc_ue_parameters *)wmem_new(wmem_file_scope(), rlc_ue_parameters);
3104 params->id = id;
3105 params->ext_li_field = NO_EXT_LI;
3106 wmem_tree_insert32_array(ue_parameters_tree, key, (void *)params);
3107 }
3108 params->pdcp_sn_bits = userplane_seqnum_length;
3109 }
3110
3111 /*Configure LI field for AM DRB channels */
set_rlc_lte_drb_li_field(packet_info * pinfo,guint16 ueid,guint8 drbid,gboolean ul_ext_li_field,gboolean dl_ext_li_field)3112 void set_rlc_lte_drb_li_field(packet_info *pinfo, guint16 ueid, guint8 drbid,
3113 gboolean ul_ext_li_field, gboolean dl_ext_li_field)
3114 {
3115 wmem_tree_key_t key[3];
3116 guint32 id;
3117 rlc_ue_parameters *params;
3118
3119 if (PINFO_FD_VISITED(pinfo)) {
3120 return;
3121 }
3122
3123 id = (drbid << 16) | ueid;
3124 key[0].length = 1;
3125 key[0].key = &id;
3126 key[1].length = 1;
3127 key[1].key = &pinfo->num;
3128 key[2].length = 0;
3129 key[2].key = NULL;
3130
3131 params = (rlc_ue_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
3132 if (params && (params->id != id)) {
3133 params = NULL;
3134 }
3135 if (params == NULL) {
3136 params = (rlc_ue_parameters *)wmem_new(wmem_file_scope(), rlc_ue_parameters);
3137 params->id = id;
3138 params->pdcp_sn_bits = 12;
3139 wmem_tree_insert32_array(ue_parameters_tree, key, (void *)params);
3140 }
3141 params->ext_li_field = ul_ext_li_field ? UL_EXT_LI : NO_EXT_LI;
3142 params->ext_li_field |= dl_ext_li_field ? DL_EXT_LI : NO_EXT_LI;
3143 }
3144
proto_register_rlc_lte(void)3145 void proto_register_rlc_lte(void)
3146 {
3147 static hf_register_info hf[] =
3148 {
3149 /**********************************/
3150 /* Items for decoding context */
3151 { &hf_rlc_lte_context,
3152 { "Context",
3153 "rlc-lte.context", FT_STRING, BASE_NONE, NULL, 0x0,
3154 NULL, HFILL
3155 }
3156 },
3157 { &hf_rlc_lte_context_mode,
3158 { "RLC Mode",
3159 "rlc-lte.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
3160 NULL, HFILL
3161 }
3162 },
3163 { &hf_rlc_lte_context_direction,
3164 { "Direction",
3165 "rlc-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3166 "Direction of message", HFILL
3167 }
3168 },
3169 { &hf_rlc_lte_context_priority,
3170 { "Priority",
3171 "rlc-lte.priority", FT_UINT8, BASE_DEC, 0, 0x0,
3172 NULL, HFILL
3173 }
3174 },
3175 { &hf_rlc_lte_context_ueid,
3176 { "UEId",
3177 "rlc-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
3178 "User Equipment Identifier associated with message", HFILL
3179 }
3180 },
3181 { &hf_rlc_lte_context_channel_type,
3182 { "Channel Type",
3183 "rlc-lte.channel-type", FT_UINT16, BASE_DEC, VALS(rlc_channel_type_vals), 0x0,
3184 "Channel Type associated with message", HFILL
3185 }
3186 },
3187 { &hf_rlc_lte_context_channel_id,
3188 { "Channel ID",
3189 "rlc-lte.channel-id", FT_UINT16, BASE_DEC, 0, 0x0,
3190 "Channel ID associated with message", HFILL
3191 }
3192 },
3193 { &hf_rlc_lte_context_pdu_length,
3194 { "PDU Length",
3195 "rlc-lte.pdu-length", FT_UINT16, BASE_DEC, 0, 0x0,
3196 "Length of PDU (in bytes)", HFILL
3197 }
3198 },
3199 { &hf_rlc_lte_context_um_sn_length,
3200 { "UM Sequence number length",
3201 "rlc-lte.um-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
3202 "Length of UM sequence number in bits", HFILL
3203 }
3204 },
3205 { &hf_rlc_lte_context_am_sn_length,
3206 { "AM Sequence number length",
3207 "rlc-lte.am-seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
3208 "Length of AM sequence number in bits", HFILL
3209 }
3210 },
3211
3212 /* Transparent mode fields */
3213 { &hf_rlc_lte_tm,
3214 { "TM",
3215 "rlc-lte.tm", FT_STRING, BASE_NONE, NULL, 0x0,
3216 "Transparent Mode", HFILL
3217 }
3218 },
3219 { &hf_rlc_lte_tm_data,
3220 { "TM Data",
3221 "rlc-lte.tm.data", FT_BYTES, BASE_NONE, 0, 0x0,
3222 "Transparent Mode Data", HFILL
3223 }
3224 },
3225
3226 /* Unacknowledged mode fields */
3227 { &hf_rlc_lte_um,
3228 { "UM",
3229 "rlc-lte.um", FT_STRING, BASE_NONE, NULL, 0x0,
3230 "Unacknowledged Mode", HFILL
3231 }
3232 },
3233 { &hf_rlc_lte_um_header,
3234 { "UM Header",
3235 "rlc-lte.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
3236 "Unacknowledged Mode Header", HFILL
3237 }
3238 },
3239 { &hf_rlc_lte_um_fi,
3240 { "Framing Info",
3241 "rlc-lte.um.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x0,
3242 NULL, HFILL
3243 }
3244 },
3245 { &hf_rlc_lte_um_fixed_e,
3246 { "Extension",
3247 "rlc-lte.um.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x0,
3248 "Extension in fixed part of UM header", HFILL
3249 }
3250 },
3251 { &hf_rlc_lte_um_sn,
3252 { "Sequence number",
3253 "rlc-lte.um.sn", FT_UINT8, BASE_DEC, 0, 0x0,
3254 "Unacknowledged Mode Sequence Number", HFILL
3255 }
3256 },
3257 { &hf_rlc_lte_um_fixed_reserved,
3258 { "Reserved",
3259 "rlc-lte.um.reserved", FT_UINT8, BASE_DEC, 0, 0xe0,
3260 "Unacknowledged Mode Fixed header reserved bits", HFILL
3261 }
3262 },
3263 { &hf_rlc_lte_um_data,
3264 { "UM Data",
3265 "rlc-lte.um.data", FT_BYTES, BASE_NONE, 0, 0x0,
3266 "Unacknowledged Mode Data", HFILL
3267 }
3268 },
3269 { &hf_rlc_lte_extension_part,
3270 { "Extension Part",
3271 "rlc-lte.extension-part", FT_STRING, BASE_NONE, 0, 0x0,
3272 NULL, HFILL
3273 }
3274 },
3275 { &hf_rlc_lte_extension_e,
3276 { "Extension",
3277 "rlc-lte.extension.e", FT_UINT8, BASE_HEX, VALS(extension_extension_vals), 0x0,
3278 "Extension in extended part of the header", HFILL
3279 }
3280 },
3281 { &hf_rlc_lte_extension_li,
3282 { "Length Indicator",
3283 "rlc-lte.extension.li", FT_UINT16, BASE_DEC, 0, 0x0,
3284 NULL, HFILL
3285 }
3286 },
3287 { &hf_rlc_lte_extension_padding,
3288 { "Padding",
3289 "rlc-lte.extension.padding", FT_UINT8, BASE_HEX, 0, 0x0f,
3290 "Extension header padding", HFILL
3291 }
3292 },
3293
3294 /* Acknowledged mode fields */
3295 { &hf_rlc_lte_am,
3296 { "AM",
3297 "rlc-lte.am", FT_STRING, BASE_NONE, NULL, 0x0,
3298 "Acknowledged Mode", HFILL
3299 }
3300 },
3301 { &hf_rlc_lte_am_header,
3302 { "AM Header",
3303 "rlc-lte.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
3304 "Acknowledged Mode Header", HFILL
3305 }
3306 },
3307 { &hf_rlc_lte_am_data_control,
3308 { "Frame type",
3309 "rlc-lte.am.frame-type", FT_UINT8, BASE_HEX, VALS(data_or_control_vals), 0x80,
3310 "AM Frame Type (Control or Data)", HFILL
3311 }
3312 },
3313 { &hf_rlc_lte_am_rf,
3314 { "Re-segmentation Flag",
3315 "rlc-lte.am.rf", FT_UINT8, BASE_HEX, VALS(resegmentation_flag_vals), 0x40,
3316 "AM Re-segmentation Flag", HFILL
3317 }
3318 },
3319 { &hf_rlc_lte_am_p,
3320 { "Polling Bit",
3321 "rlc-lte.am.p", FT_UINT8, BASE_HEX, VALS(polling_bit_vals), 0x20,
3322 NULL, HFILL
3323 }
3324 },
3325 { &hf_rlc_lte_am_fi,
3326 { "Framing Info",
3327 "rlc-lte.am.fi", FT_UINT8, BASE_HEX, VALS(framing_info_vals), 0x18,
3328 "AM Framing Info", HFILL
3329 }
3330 },
3331 { &hf_rlc_lte_am_fixed_e,
3332 { "Extension",
3333 "rlc-lte.am.fixed.e", FT_UINT8, BASE_HEX, VALS(fixed_extension_vals), 0x04,
3334 "Fixed Extension Bit", HFILL
3335 }
3336 },
3337 { &hf_rlc_lte_am_fixed_sn,
3338 { "Sequence Number",
3339 "rlc-lte.am.fixed.sn", FT_UINT16, BASE_DEC, 0, 0x03ff,
3340 "AM Fixed Sequence Number", HFILL
3341 }
3342 },
3343 { &hf_rlc_lte_am_fixed_reserved,
3344 { "Reserved",
3345 "rlc-lte.am.reserved", FT_UINT8, BASE_DEC, 0, 0x03,
3346 "Acknowledged Mode Fixed header reserved bits", HFILL
3347 }
3348 },
3349 { &hf_rlc_lte_am_segment_lsf16,
3350 { "Last Segment Flag",
3351 "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x02,
3352 NULL, HFILL
3353 }
3354 },
3355 { &hf_rlc_lte_am_fixed_reserved2,
3356 { "Reserved",
3357 "rlc-lte.am.reserved", FT_UINT8, BASE_DEC, 0, 0x01,
3358 "Acknowledged Mode Fixed header reserved bit", HFILL
3359 }
3360 },
3361 { &hf_rlc_lte_am_fixed_sn16,
3362 { "Sequence Number",
3363 "rlc-lte.am.fixed.sn", FT_UINT16, BASE_DEC, 0, 0xffff,
3364 "AM Fixed Sequence Number", HFILL
3365 }
3366 },
3367 { &hf_rlc_lte_am_segment_lsf,
3368 { "Last Segment Flag",
3369 "rlc-lte.am.segment.lsf", FT_UINT8, BASE_HEX, VALS(lsf_vals), 0x80,
3370 NULL, HFILL
3371 }
3372 },
3373 { &hf_rlc_lte_am_segment_so,
3374 { "Segment Offset",
3375 "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0x7fff,
3376 NULL, HFILL
3377 }
3378 },
3379 { &hf_rlc_lte_am_segment_so16,
3380 { "Segment Offset",
3381 "rlc-lte.am.segment.offset", FT_UINT16, BASE_DEC, 0, 0xffff,
3382 NULL, HFILL
3383 }
3384 },
3385 { &hf_rlc_lte_am_data,
3386 { "AM Data",
3387 "rlc-lte.am.data", FT_BYTES, BASE_NONE, 0, 0x0,
3388 "Acknowledged Mode Data", HFILL
3389 }
3390 },
3391
3392 { &hf_rlc_lte_am_cpt,
3393 { "Control PDU Type",
3394 "rlc-lte.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
3395 "AM Control PDU Type", HFILL
3396 }
3397 },
3398 { &hf_rlc_lte_am_ack_sn,
3399 { "ACK Sequence Number",
3400 "rlc-lte.am.ack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3401 "Sequence Number we expect to receive next", HFILL
3402 }
3403 },
3404 { &hf_rlc_lte_am_e1,
3405 { "Extension bit 1",
3406 "rlc-lte.am.e1", FT_UINT8, BASE_HEX, VALS(am_e1_vals), 0x0,
3407 NULL, HFILL
3408 }
3409 },
3410 { &hf_rlc_lte_am_e2,
3411 { "Extension bit 2",
3412 "rlc-lte.am.e2", FT_UINT8, BASE_HEX, VALS(am_e2_vals), 0x0,
3413 NULL, HFILL
3414 }
3415 },
3416 { &hf_rlc_lte_am_nacks,
3417 { "Number of NACKs",
3418 "rlc-lte.am.nacks", FT_UINT16, BASE_DEC, 0, 0x0,
3419 "Number of NACKs in this status PDU", HFILL
3420 }
3421 },
3422 { &hf_rlc_lte_am_nack_sn,
3423 { "NACK Sequence Number",
3424 "rlc-lte.am.nack-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3425 "Negative Acknowledgement Sequence Number", HFILL
3426 }
3427 },
3428 { &hf_rlc_lte_am_so_start,
3429 { "SO Start",
3430 "rlc-lte.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
3431 "Segment Offset Start byte index", HFILL
3432 }
3433 },
3434 { &hf_rlc_lte_am_so_end,
3435 { "SO End",
3436 "rlc-lte.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
3437 "Segment Offset End byte index", HFILL
3438 }
3439 },
3440
3441 { &hf_rlc_lte_predefined_pdu,
3442 { "Predefined data",
3443 "rlc-lte.predefined-data", FT_BYTES, BASE_NONE, 0, 0x0,
3444 "Predefined test data", HFILL
3445 }
3446 },
3447
3448 /* Sequence analysis fields */
3449 { &hf_rlc_lte_sequence_analysis,
3450 { "Sequence Analysis",
3451 "rlc-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
3452 NULL, HFILL
3453 }
3454 },
3455 { &hf_rlc_lte_sequence_analysis_ok,
3456 { "OK",
3457 "rlc-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3458 NULL, HFILL
3459 }
3460 },
3461 { &hf_rlc_lte_sequence_analysis_previous_frame,
3462 { "Previous frame for channel",
3463 "rlc-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3464 NULL, HFILL
3465 }
3466 },
3467 { &hf_rlc_lte_sequence_analysis_next_frame,
3468 { "Next frame for channel",
3469 "rlc-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3470 NULL, HFILL
3471 }
3472 },
3473 { &hf_rlc_lte_sequence_analysis_expected_sn,
3474 { "Expected SN",
3475 "rlc-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
3476 NULL, HFILL
3477 }
3478 },
3479 { &hf_rlc_lte_sequence_analysis_framing_info_correct,
3480 { "Frame info continued correctly",
3481 "rlc-lte.sequence-analysis.framing-info-correct", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3482 NULL, HFILL
3483 }
3484 },
3485 { &hf_rlc_lte_sequence_analysis_mac_retx,
3486 { "Frame retransmitted by MAC",
3487 "rlc-lte.sequence-analysis.mac-retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3488 NULL, HFILL
3489 }
3490 },
3491 { &hf_rlc_lte_sequence_analysis_retx,
3492 { "Retransmitted frame",
3493 "rlc-lte.sequence-analysis.retx", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3494 NULL, HFILL
3495 }
3496 },
3497 { &hf_rlc_lte_sequence_analysis_skipped,
3498 { "Skipped frames",
3499 "rlc-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3500 NULL, HFILL
3501 }
3502 },
3503 { &hf_rlc_lte_sequence_analysis_repeated,
3504 { "Repeated frame",
3505 "rlc-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3506 NULL, HFILL
3507 }
3508 },
3509 { &hf_rlc_lte_sequence_analysis_repeated_nack,
3510 { "Repeated NACK",
3511 "rlc-lte.sequence-analysis.repeated-nack", FT_UINT16, BASE_DEC, 0, 0x0,
3512 NULL, HFILL
3513 }
3514 },
3515 { &hf_rlc_lte_sequence_analysis_repeated_nack_original_frame,
3516 { "Frame with previous status PDU",
3517 "rlc-lte.sequence-analysis.repeated-nack.original-frame", FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK), 0x0,
3518 NULL, HFILL
3519 }
3520 },
3521
3522 { &hf_rlc_lte_sequence_analysis_ack_out_of_range,
3523 { "Out of range ACK",
3524 "rlc-lte.sequence-analysis.ack-out-of-range", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3525 NULL, HFILL
3526 }
3527 },
3528 { &hf_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame,
3529 { "Frame with most recent SN",
3530 "rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3531 NULL, HFILL
3532 }
3533 },
3534
3535 /* Reassembly fields */
3536 { &hf_rlc_lte_reassembly_source,
3537 { "Reassembly Source",
3538 "rlc-lte.reassembly-info", FT_STRING, BASE_NONE, 0, 0x0,
3539 NULL, HFILL
3540 }
3541 },
3542 { &hf_rlc_lte_reassembly_source_number_of_segments,
3543 { "Number of segments",
3544 "rlc-lte.reassembly-info.number-of-segments", FT_UINT16, BASE_DEC, 0, 0x0,
3545 NULL, HFILL
3546 }
3547 },
3548 { &hf_rlc_lte_reassembly_source_total_length,
3549 { "Total length",
3550 "rlc-lte.reassembly-info.total-length", FT_UINT16, BASE_DEC, 0, 0x0,
3551 NULL, HFILL
3552 }
3553 },
3554 { &hf_rlc_lte_reassembly_source_segment,
3555 { "Segment",
3556 "rlc-lte.reassembly-info.segment", FT_NONE, BASE_NONE, 0, 0x0,
3557 NULL, HFILL
3558 }
3559 },
3560 { &hf_rlc_lte_reassembly_source_segment_sn,
3561 { "SN",
3562 "rlc-lte.reassembly-info.segment.sn", FT_UINT16, BASE_DEC, 0, 0x0,
3563 NULL, HFILL
3564 }
3565 },
3566 { &hf_rlc_lte_reassembly_source_segment_framenum,
3567 { "Frame",
3568 "rlc-lte.reassembly-info.segment.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3569 NULL, HFILL
3570 }
3571 },
3572 { &hf_rlc_lte_reassembly_source_segment_length,
3573 { "Length",
3574 "rlc-lte.reassembly-info.segment.length", FT_UINT32, BASE_DEC, 0, 0x0,
3575 NULL, HFILL
3576 }
3577 },
3578
3579 { &hf_rlc_lte_header_only,
3580 { "RLC PDU Header only",
3581 "rlc-lte.header-only", FT_UINT8, BASE_DEC, VALS(header_only_vals), 0x0,
3582 NULL, HFILL
3583 }
3584 },
3585 };
3586
3587 static gint *ett[] =
3588 {
3589 &ett_rlc_lte,
3590 &ett_rlc_lte_context,
3591 &ett_rlc_lte_um_header,
3592 &ett_rlc_lte_am_header,
3593 &ett_rlc_lte_extension_part,
3594 &ett_rlc_lte_sequence_analysis,
3595 &ett_rlc_lte_reassembly_source,
3596 &ett_rlc_lte_reassembly_source_segment
3597 };
3598
3599 static ei_register_info ei[] = {
3600 { &ei_rlc_lte_sequence_analysis_last_segment_not_continued, { "rlc-lte.sequence-analysis.last-segment-not-continued", PI_SEQUENCE, PI_WARN, "Last segment of previous PDU was not continued for UE", EXPFILL }},
3601 { &ei_rlc_lte_sequence_analysis_last_segment_complete, { "rlc-lte.sequence-analysis.last-segment-complete", PI_SEQUENCE, PI_WARN, "Last segment of previous PDU was complete, but new segment was not started on UE", EXPFILL }},
3602 { &ei_rlc_lte_sequence_analysis_mac_retx, { "rlc-lte.sequence-analysis.mac-retx.expert", PI_SEQUENCE, PI_WARN, "AM Frame retransmitted due to MAC retx!", EXPFILL }},
3603 { &ei_rlc_lte_sequence_analysis_retx, { "rlc-lte.sequence-analysis.retx.expert", PI_SEQUENCE, PI_WARN, "AM Frame retransmitted most likely in response to NACK", EXPFILL }},
3604 { &ei_rlc_lte_sequence_analysis_repeated, { "rlc-lte.sequence-analysis.repeated-frame.expert", PI_SEQUENCE, PI_WARN, "AM SN Repeated - probably because didn't receive Status PDU?", EXPFILL }},
3605 { &ei_rlc_lte_am_sn_missing, { "rlc-lte.sequence-analysis.am-sn.missing", PI_SEQUENCE, PI_WARN, "AM SNs missing", EXPFILL }},
3606 { &ei_rlc_lte_sequence_analysis_ack_out_of_range_opposite_frame, { "rlc-lte.sequence-analysis.ack-out-of-range.last-sn-frame.expert", PI_SEQUENCE, PI_ERROR, "AM ACK for SN - but last received SN in other direction is X", EXPFILL }},
3607 { &ei_rlc_lte_um_sn_missing, { "rlc-lte.sequence-analysis.um-sn.missing", PI_SEQUENCE, PI_WARN, "UM SNs missing", EXPFILL }},
3608 { &ei_rlc_lte_um_sn_repeated, { "rlc-lte.sequence-analysis.um-sn.repeated", PI_SEQUENCE, PI_WARN, "UM SN repeated", EXPFILL }},
3609 { &ei_rlc_lte_wrong_sequence_number, { "rlc-lte.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
3610 { &ei_rlc_lte_sequence_analysis_repeated_nack, { "rlc-lte.sequence-analysis.repeated-nack.expert", PI_SEQUENCE, PI_ERROR, "Same SN NACKd on successive Status PDUs", EXPFILL }},
3611 { &ei_rlc_lte_reserved_bits_not_zero, { "rlc-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
3612 { &ei_rlc_lte_um_sn, { "rlc-lte.um.sn.invalid", PI_MALFORMED, PI_ERROR, "Invalid sequence number length", EXPFILL }},
3613 { &ei_rlc_lte_header_only, { "rlc-lte.header-only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
3614 { &ei_rlc_lte_am_cpt, { "rlc-lte.am.cpt.invalid", PI_MALFORMED, PI_ERROR, "RLC Control frame type not handled", EXPFILL }},
3615 { &ei_rlc_lte_am_nack_sn_ack_same, { "rlc-lte.am.nack-sn.ack-same", PI_MALFORMED, PI_ERROR, "Status PDU shouldn't ACK and NACK the same sequence number", EXPFILL }},
3616 { &ei_rlc_lte_am_nack_sn_ahead_ack, { "rlc-lte.am.nack-sn.ahead-ack", PI_MALFORMED, PI_ERROR, "NACK must not be ahead of ACK in status PDU", EXPFILL }},
3617 { &ei_rlc_lte_am_nack_sn_partial, { "rlc-lte.am.nack-sn.partial", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK (partial)", EXPFILL }},
3618 { &ei_rlc_lte_am_nack_sn, { "rlc-lte.am.nack-sn.expert", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK", EXPFILL }},
3619 { &ei_rlc_lte_bytes_after_status_pdu_complete, { "rlc-lte.bytes-after-status-pdu-complete", PI_MALFORMED, PI_ERROR, "bytes remaining after Status PDU complete", EXPFILL }},
3620 { &ei_rlc_lte_am_data_no_data_beyond_extensions, { "rlc-lte.am-data.no-data-beyond-extensions", PI_MALFORMED, PI_ERROR, "AM data PDU doesn't contain any data beyond extensions", EXPFILL }},
3621 { &ei_rlc_lte_am_data_no_data, { "rlc-lte.am-data.no-data", PI_MALFORMED, PI_ERROR, "AM data PDU doesn't contain any data", EXPFILL }},
3622 { &ei_rlc_lte_context_mode, { "rlc-lte.mode.invalid", PI_MALFORMED, PI_ERROR, "Unrecognised RLC Mode set", EXPFILL }},
3623 { &ei_rlc_lte_no_per_frame_info, { "rlc-lte.no_per_frame_info", PI_UNDECODED, PI_ERROR, "Can't dissect LTE RLC frame because no per-frame info was attached!", EXPFILL }},
3624 { &ei_rlc_lte_unknown_udp_framing_tag, { "rlc-lte.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3625 { &ei_rlc_lte_missing_udp_framing_tag, { "rlc-lte.missing-udp-framing-tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3626 };
3627
3628 static const enum_val_t sequence_analysis_vals[] = {
3629 {"no-analysis", "No-Analysis", FALSE},
3630 {"mac-only", "Only-MAC-frames", SEQUENCE_ANALYSIS_MAC_ONLY},
3631 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
3632 {NULL, NULL, -1}
3633 };
3634
3635 module_t *rlc_lte_module;
3636 expert_module_t* expert_rlc_lte;
3637
3638 /* Register protocol. */
3639 proto_rlc_lte = proto_register_protocol("RLC-LTE", "RLC-LTE", "rlc-lte");
3640 proto_register_field_array(proto_rlc_lte, hf, array_length(hf));
3641 proto_register_subtree_array(ett, array_length(ett));
3642 expert_rlc_lte = expert_register_protocol(proto_rlc_lte);
3643 expert_register_field_array(expert_rlc_lte, ei, array_length(ei));
3644
3645 /* Allow other dissectors to find this one by name. */
3646 register_dissector("rlc-lte", dissect_rlc_lte, proto_rlc_lte);
3647
3648 /* Register the tap name */
3649 rlc_lte_tap = register_tap("rlc-lte");
3650
3651 /* Preferences */
3652 rlc_lte_module = prefs_register_protocol(proto_rlc_lte, NULL);
3653
3654 prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis_am",
3655 "Do sequence analysis for AM channels",
3656 "Attempt to keep track of PDUs for AM channels, and point out problems",
3657 &global_rlc_lte_am_sequence_analysis, sequence_analysis_vals, FALSE);
3658
3659 prefs_register_enum_preference(rlc_lte_module, "do_sequence_analysis",
3660 "Do sequence analysis for UM channels",
3661 "Attempt to keep track of PDUs for UM channels, and point out problems",
3662 &global_rlc_lte_um_sequence_analysis, sequence_analysis_vals, FALSE);
3663
3664 prefs_register_bool_preference(rlc_lte_module, "call_pdcp_for_srb",
3665 "Call PDCP dissector for SRB PDUs",
3666 "Call PDCP dissector for signalling PDUs. Note that without reassembly, it can"
3667 "only be called for complete PDUs (i.e. not segmented over RLC)",
3668 &global_rlc_lte_call_pdcp_for_srb);
3669
3670 prefs_register_enum_preference(rlc_lte_module, "call_pdcp_for_drb",
3671 "Call PDCP dissector for DRB PDUs",
3672 "Call PDCP dissector for user-plane PDUs. Note that without reassembly, it can"
3673 "only be called for complete PDUs (i.e. not segmented over RLC)",
3674 &global_rlc_lte_call_pdcp_for_drb, pdcp_drb_col_vals, FALSE);
3675
3676
3677 prefs_register_bool_preference(rlc_lte_module, "call_rrc_for_ccch",
3678 "Call RRC dissector for CCCH PDUs",
3679 "Call RRC dissector for CCCH PDUs",
3680 &global_rlc_lte_call_rrc_for_ccch);
3681
3682 prefs_register_bool_preference(rlc_lte_module, "call_rrc_for_mcch",
3683 "Call RRC dissector for MCCH PDUs",
3684 "Call RRC dissector for MCCH PDUs Note that without reassembly, it can"
3685 "only be called for complete PDUs (i.e. not segmented over RLC)",
3686 &global_rlc_lte_call_rrc_for_mcch);
3687
3688 prefs_register_bool_preference(rlc_lte_module, "call_ip_for_mtch",
3689 "Call IP dissector for MTCH PDUs",
3690 "Call ip dissector for MTCH PDUs Note that without reassembly, it can"
3691 "only be called for complete PDUs (i.e. not segmented over RLC)",
3692 &global_rlc_lte_call_ip_for_mtch);
3693
3694 prefs_register_obsolete_preference(rlc_lte_module, "heuristic_rlc_lte_over_udp");
3695
3696 prefs_register_bool_preference(rlc_lte_module, "header_only_mode",
3697 "May see RLC headers only",
3698 "When enabled, if data is not present, don't report as an error, but instead "
3699 "add expert info to indicate that headers were omitted",
3700 &global_rlc_lte_headers_expected);
3701
3702 prefs_register_bool_preference(rlc_lte_module, "reassembly",
3703 "Attempt SDU reassembly",
3704 "When enabled, attempts to re-assemble upper-layer SDUs that are split over "
3705 "more than one RLC PDU. Note: does not currently support out-of-order or "
3706 "re-segmentation. N.B. sequence analysis must also be turned on in order "
3707 "for reassembly to work",
3708 &global_rlc_lte_reassembly);
3709
3710 ue_parameters_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3711
3712 sequence_analysis_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_channel_hash_func, rlc_channel_equal);
3713 sequence_analysis_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3714 repeated_nack_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_channel_hash_func, rlc_channel_equal);
3715 repeated_nack_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3716 reassembly_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), rlc_result_hash_func, rlc_result_hash_equal);
3717 }
3718
proto_reg_handoff_rlc_lte(void)3719 void proto_reg_handoff_rlc_lte(void)
3720 {
3721 /* Add as a heuristic UDP dissector */
3722 heur_dissector_add("udp", dissect_rlc_lte_heur, "RLC-LTE over UDP", "rlc_lte_udp", proto_rlc_lte, HEURISTIC_DISABLE);
3723
3724 pdcp_lte_handle = find_dissector_add_dependency("pdcp-lte", proto_rlc_lte);
3725 ip_handle = find_dissector_add_dependency("ip", proto_rlc_lte);
3726 lte_rrc_mcch = find_dissector_add_dependency("lte_rrc.mcch", proto_rlc_lte);
3727 lte_rrc_ul_ccch = find_dissector_add_dependency("lte_rrc.ul_ccch", proto_rlc_lte);
3728 lte_rrc_dl_ccch = find_dissector_add_dependency("lte_rrc.dl_dcch", proto_rlc_lte);
3729 lte_rrc_bcch_bch = find_dissector_add_dependency("lte_rrc.bcch_bch", proto_rlc_lte);
3730 lte_rrc_bcch_dl_sch = find_dissector_add_dependency("lte_rrc.bcch_dl_sch", proto_rlc_lte);
3731 lte_rrc_pcch = find_dissector_add_dependency("lte_rrc.pcch", proto_rlc_lte);
3732 lte_rrc_ul_ccch_nb = find_dissector_add_dependency("lte_rrc.ul_ccch.nb", proto_rlc_lte);
3733 lte_rrc_dl_ccch_nb = find_dissector_add_dependency("lte_rrc.dl_ccch.nb", proto_rlc_lte);
3734 lte_rrc_bcch_bch_nb = find_dissector_add_dependency("lte_rrc.bcch_bch.nb", proto_rlc_lte);
3735 lte_rrc_bcch_dl_sch_nb = find_dissector_add_dependency("lte_rrc.bcch_dl_sch.nb", proto_rlc_lte);
3736 lte_rrc_pcch_nb = find_dissector_add_dependency("lte_rrc.pcch.nb", proto_rlc_lte);
3737 }
3738
3739 /*
3740 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3741 *
3742 * Local variables:
3743 * c-basic-offset: 4
3744 * tab-width: 8
3745 * indent-tabs-mode: nil
3746 * End:
3747 *
3748 * vi: set shiftwidth=4 tabstop=8 expandtab:
3749 * :indentSize=4:tabSize=8:noTabs=true:
3750 */
3751