1 /* Routines for NR RLC disassembly
2  *
3  * Pascal Quantin
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/proto_data.h>
19 #include <epan/reassemble.h>
20 
21 #include "packet-rlc-nr.h"
22 #include "packet-pdcp-nr.h"
23 
24 
25 /* Described in:
26  * 3GPP TS 38.322 NR; Radio Link Control (RLC) protocol specification v15.0.0
27  */
28 
29 /* TODO:
30 - add sequence analysis
31 - take configuration of reordering timer, and stop reassembly if timeout exceeded?
32 - add tap info
33 - call more upper layer dissectors once they appear
34 */
35 
36 void proto_register_rlc_nr(void);
37 void proto_reg_handoff_rlc_nr(void);
38 
39 /********************************/
40 /* Preference settings          */
41 
42 /* By default do call PDCP/RRC dissectors for SDU data */
43 static gboolean global_rlc_nr_call_pdcp_for_srb = TRUE;
44 
45 enum pdcp_for_drb { PDCP_drb_off, PDCP_drb_SN_12, PDCP_drb_SN_18, PDCP_drb_SN_signalled};
46 static const enum_val_t pdcp_drb_col_vals[] = {
47     {"pdcp-drb-off",           "Off",                 PDCP_drb_off},
48     {"pdcp-drb-sn-12",         "12-bit SN",           PDCP_drb_SN_12},
49     {"pdcp-drb-sn-18",         "18-bit SN",           PDCP_drb_SN_18},
50     {"pdcp-drb-sn-signalling", "Use signalled value", PDCP_drb_SN_signalled},
51     {NULL, NULL, -1}
52 };
53 /* Separate config for UL/DL */
54 static gint global_rlc_nr_call_pdcp_for_ul_drb = (gint)PDCP_drb_off;
55 static gint global_rlc_nr_call_pdcp_for_dl_drb = (gint)PDCP_drb_off;
56 
57 
58 static gboolean global_rlc_nr_call_rrc_for_ccch = TRUE;
59 
60 /* Preference to expect RLC headers without payloads */
61 static gboolean global_rlc_nr_headers_expected = FALSE;
62 
63 /* Attempt reassembly. */
64 static gboolean global_rlc_nr_reassemble_um_pdus = FALSE;
65 static gboolean global_rlc_nr_reassemble_am_pdus = TRUE;
66 
67 /* Tree storing UE related parameters (ueid, drbid) -> pdcp_bearer_parameters */
68 static wmem_tree_t *ue_parameters_tree;
69 
70 
71 /**************************************************/
72 /* Initialize the protocol and registered fields. */
73 int proto_rlc_nr = -1;
74 
75 extern int proto_pdcp_nr;
76 
77 static dissector_handle_t pdcp_nr_handle;
78 static dissector_handle_t nr_rrc_bcch_bch;
79 static dissector_handle_t nr_rrc_bcch_dl_sch;
80 static dissector_handle_t nr_rrc_pcch;
81 static dissector_handle_t nr_rrc_ul_ccch;
82 static dissector_handle_t nr_rrc_ul_ccch1;
83 static dissector_handle_t nr_rrc_dl_ccch;
84 
85 
86 /* Decoding context */
87 static int hf_rlc_nr_context = -1;
88 static int hf_rlc_nr_context_mode = -1;
89 static int hf_rlc_nr_context_direction = -1;
90 static int hf_rlc_nr_context_ueid = -1;
91 static int hf_rlc_nr_context_bearer_type = -1;
92 static int hf_rlc_nr_context_bearer_id = -1;
93 static int hf_rlc_nr_context_pdu_length = -1;
94 static int hf_rlc_nr_context_sn_length = -1;
95 
96 /* Transparent mode fields */
97 static int hf_rlc_nr_tm = -1;
98 static int hf_rlc_nr_tm_data = -1;
99 
100 /* Unacknowledged mode fields */
101 static int hf_rlc_nr_um = -1;
102 static int hf_rlc_nr_um_header = -1;
103 static int hf_rlc_nr_um_si = -1;
104 static int hf_rlc_nr_um_reserved = -1;
105 static int hf_rlc_nr_um_sn6 = -1;
106 static int hf_rlc_nr_um_sn12 = -1;
107 static int hf_rlc_nr_um_so = -1;
108 static int hf_rlc_nr_um_data = -1;
109 
110 /* Acknowledged mode fields */
111 static int hf_rlc_nr_am = -1;
112 static int hf_rlc_nr_am_header = -1;
113 static int hf_rlc_nr_am_data_control = -1;
114 static int hf_rlc_nr_am_p = -1;
115 static int hf_rlc_nr_am_si = -1;
116 static int hf_rlc_nr_am_sn12 = -1;
117 static int hf_rlc_nr_am_sn18 = -1;
118 static int hf_rlc_nr_am_reserved = -1;
119 static int hf_rlc_nr_am_so = -1;
120 static int hf_rlc_nr_am_data = -1;
121 
122 /* Control fields */
123 static int hf_rlc_nr_am_cpt = -1;
124 static int hf_rlc_nr_am_ack_sn = -1;
125 static int hf_rlc_nr_am_e1 = -1;
126 static int hf_rlc_nr_am_e2 = -1;
127 static int hf_rlc_nr_am_e3 = -1;
128 static int hf_rlc_nr_am_nack_sn = -1;
129 static int hf_rlc_nr_am_so_start = -1;
130 static int hf_rlc_nr_am_so_end = -1;
131 static int hf_rlc_nr_am_nack_range = -1;
132 static int hf_rlc_nr_am_nacks = -1;
133 
134 static int hf_rlc_nr_header_only = -1;
135 
136 static int hf_rlc_nr_fragments = -1;
137 static int hf_rlc_nr_fragment = -1;
138 static int hf_rlc_nr_fragment_overlap = -1;
139 static int hf_rlc_nr_fragment_overlap_conflict = -1;
140 static int hf_rlc_nr_fragment_multiple_tails = -1;
141 static int hf_rlc_nr_fragment_too_long_fragment = -1;
142 static int hf_rlc_nr_fragment_error = -1;
143 static int hf_rlc_nr_fragment_count = -1;
144 static int hf_rlc_nr_reassembled_in = -1;
145 static int hf_rlc_nr_reassembled_length = -1;
146 static int hf_rlc_nr_reassembled_data = -1;
147 
148 
149 
150 /* Subtrees. */
151 static int ett_rlc_nr = -1;
152 static int ett_rlc_nr_context = -1;
153 static int ett_rlc_nr_um_header = -1;
154 static int ett_rlc_nr_am_header = -1;
155 static int ett_rlc_nr_fragments = -1;
156 static int ett_rlc_nr_fragment = -1;
157 
158 
159 static const fragment_items rlc_nr_frag_items = {
160   &ett_rlc_nr_fragment,
161   &ett_rlc_nr_fragments,
162   &hf_rlc_nr_fragments,
163   &hf_rlc_nr_fragment,
164   &hf_rlc_nr_fragment_overlap,
165   &hf_rlc_nr_fragment_overlap_conflict,
166   &hf_rlc_nr_fragment_multiple_tails,
167   &hf_rlc_nr_fragment_too_long_fragment,
168   &hf_rlc_nr_fragment_error,
169   &hf_rlc_nr_fragment_count,
170   &hf_rlc_nr_reassembled_in,
171   &hf_rlc_nr_reassembled_length,
172   &hf_rlc_nr_reassembled_data,
173   "RLC PDU fragments"
174 };
175 
176 
177 static expert_field ei_rlc_nr_context_mode = EI_INIT;
178 static expert_field ei_rlc_nr_am_nack_sn = EI_INIT;
179 static expert_field ei_rlc_nr_am_nack_sn_ahead_ack = EI_INIT;
180 static expert_field ei_rlc_nr_am_nack_sn_ack_same = EI_INIT;
181 static expert_field ei_rlc_nr_am_nack_range = EI_INIT;
182 static expert_field ei_rlc_nr_am_cpt = EI_INIT;
183 static expert_field ei_rlc_nr_um_data_no_data = EI_INIT;
184 static expert_field ei_rlc_nr_am_data_no_data = EI_INIT;
185 static expert_field ei_rlc_nr_am_nack_sn_partial = EI_INIT;
186 static expert_field ei_rlc_nr_bytes_after_status_pdu_complete = EI_INIT;
187 static expert_field ei_rlc_nr_um_sn = EI_INIT;
188 static expert_field ei_rlc_nr_am_sn = EI_INIT;
189 static expert_field ei_rlc_nr_header_only = EI_INIT;
190 static expert_field ei_rlc_nr_reserved_bits_not_zero = EI_INIT;
191 static expert_field ei_rlc_nr_no_per_frame_info = EI_INIT;
192 static expert_field ei_rlc_nr_unknown_udp_framing_tag = EI_INIT;
193 
194 /* Value-strings */
195 static const value_string direction_vals[] =
196 {
197     { DIRECTION_UPLINK,   "Uplink" },
198     { DIRECTION_DOWNLINK, "Downlink" },
199     { 0, NULL }
200 };
201 
202 static const value_string rlc_mode_short_vals[] =
203 {
204     { RLC_TM_MODE, "TM" },
205     { RLC_UM_MODE, "UM" },
206     { RLC_AM_MODE, "AM" },
207     { 0, NULL }
208 };
209 
210 static const value_string rlc_mode_vals[] =
211 {
212     { RLC_TM_MODE, "Transparent Mode" },
213     { RLC_UM_MODE, "Unacknowledged Mode" },
214     { RLC_AM_MODE, "Acknowledged Mode" },
215     { 0, NULL }
216 };
217 
218 static const value_string rlc_bearer_type_vals[] =
219 {
220     { BEARER_TYPE_CCCH,        "CCCH" },
221     { BEARER_TYPE_BCCH_BCH,    "BCCH BCH" },
222     { BEARER_TYPE_PCCH,        "PCCH" },
223     { BEARER_TYPE_SRB,         "SRB" },
224     { BEARER_TYPE_DRB,         "DRB" },
225     { BEARER_TYPE_BCCH_DL_SCH, "BCCH DL-SCH" },
226     { 0, NULL }
227 };
228 
229 static const value_string seg_info_vals[] =
230 {
231     { 0, "Data field contains all bytes of an RLC SDU" },
232     { 1, "Data field contains the first segment of an RLC SDU" },
233     { 2, "Data field contains the last segment of an RLC SDU" },
234     { 3, "Data field contains neither the first nor last segment of an RLC SDU" },
235     { 0, NULL }
236 };
237 
238 static const true_false_string data_or_control_vals =
239 {
240     "Data PDU",
241     "Control PDU"
242 };
243 
244 static const true_false_string polling_bit_vals =
245 {
246     "Status report is requested",
247     "Status report not requested"
248 };
249 
250 static const value_string control_pdu_type_vals[] =
251 {
252     { 0, "STATUS PDU" },
253     { 0, NULL }
254 };
255 
256 static const true_false_string am_e1_vals =
257 {
258     "A set of NACK_SN, E1, E2 and E3 follows",
259     "A set of NACK_SN, E1, E2 and E3 does not follow"
260 };
261 
262 static const true_false_string am_e2_vals =
263 {
264     "A set of SOstart and SOend follows for this NACK_SN",
265     "A set of SOstart and SOend does not follow for this NACK_SN"
266 };
267 
268 static const true_false_string am_e3_vals =
269 {
270     "NACK range field follows for this NACK_SN",
271     "NACK range field does not follow for this NACK_SN"
272 };
273 
274 static const true_false_string header_only_vals =
275 {
276     "RLC PDU Headers only",
277     "RLC PDU Headers and body present"
278 };
279 
280 /* Reassembly state */
281 static reassembly_table pdu_reassembly_table;
282 
pdu_hash(gconstpointer k _U_)283 static guint pdu_hash(gconstpointer k _U_)
284 {
285     return GPOINTER_TO_UINT(k);
286 }
287 
pdu_equal(gconstpointer k1,gconstpointer k2)288 static gint pdu_equal(gconstpointer k1, gconstpointer k2)
289 {
290     return k1 == k2;
291 }
292 
pdu_temporary_key(const packet_info * pinfo _U_,const guint32 id _U_,const void * data _U_)293 static gpointer pdu_temporary_key(const packet_info *pinfo _U_, const guint32 id _U_, const void *data _U_)
294 {
295     return (gpointer)data;
296 }
297 
pdu_persistent_key(const packet_info * pinfo _U_,const guint32 id _U_,const void * data)298 static gpointer pdu_persistent_key(const packet_info *pinfo _U_, const guint32 id _U_,
299                                          const void *data)
300 {
301     return (gpointer)data;
302 }
303 
pdu_free_temporary_key(gpointer ptr _U_)304 static void pdu_free_temporary_key(gpointer ptr _U_)
305 {
306 }
307 
pdu_free_persistent_key(gpointer ptr _U_)308 static void pdu_free_persistent_key(gpointer ptr _U_)
309 {
310 }
311 
312 static reassembly_table_functions pdu_reassembly_table_functions =
313 {
314     pdu_hash,
315     pdu_equal,
316     pdu_temporary_key,
317     pdu_persistent_key,
318     pdu_free_temporary_key,
319     pdu_free_persistent_key
320 };
321 
322 
323 /********************************************************/
324 /* Forward declarations & functions                     */
325 static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing);
326 
327 
328 /* Write the given formatted text to:
329    - the info column
330    - the top-level RLC PDU item
331    - another subtree item (if supplied) */
write_pdu_label_and_info(proto_item * pdu_ti,proto_item * sub_ti,packet_info * pinfo,const char * format,...)332 static void write_pdu_label_and_info(proto_item *pdu_ti, proto_item *sub_ti,
333                                      packet_info *pinfo, const char *format, ...)
334 {
335     #define MAX_INFO_BUFFER 256
336     static char info_buffer[MAX_INFO_BUFFER];
337 
338     va_list ap;
339 
340     va_start(ap, format);
341     g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
342     va_end(ap);
343 
344     /* Add to indicated places */
345     col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
346     proto_item_append_text(pdu_ti, "%s", info_buffer);
347     if (sub_ti != NULL) {
348         proto_item_append_text(sub_ti, "%s", info_buffer);
349     }
350 }
351 
352 /* Version of function above, where no g_vsnprintf() call needed
353    - the info column
354    - the top-level RLC PDU item
355    - 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)356 static void write_pdu_label_and_info_literal(proto_item *pdu_ti, proto_item *sub_ti,
357                                              packet_info *pinfo, const char *info_buffer)
358 {
359     /* Add to indicated places */
360     col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
361     proto_item_append_text(pdu_ti, "%s", info_buffer);
362     if (sub_ti != NULL) {
363         proto_item_append_text(sub_ti, "%s", info_buffer);
364     }
365 }
366 
367 /* Show in the info column how many bytes are in the UM/AM PDU, and indicate
368    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,guint8 seg_info)369 static void show_PDU_in_info(packet_info *pinfo,
370                              proto_item *top_ti,
371                              gint32 length,
372                              guint8 seg_info)
373 {
374     /* Reflect this PDU in the info column */
375     if (length > 0) {
376         write_pdu_label_and_info(top_ti, NULL, pinfo,
377                                  "  %s%u-byte%s%s",
378                                  (seg_info & 0x02) ? ".." : "[",
379                                  length,
380                                  (length > 1) ? "s" : "",
381                                  (seg_info & 0x01) ? ".." : "]");
382     } else {
383         write_pdu_label_and_info(top_ti, NULL, pinfo,
384                                  "  %sunknown-bytes%s",
385                                  (seg_info & 0x02) ? ".." : "[",
386                                  (seg_info & 0x01) ? ".." : "]");
387     }
388 }
389 
390 
391 /* Show an SDU. If configured, pass to PDCP/RRC dissector */
show_PDU_in_tree(packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb,gint offset,gint length,rlc_nr_info * rlc_info,guint32 seg_info,gboolean is_reassembled)392 static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, gint offset, gint length,
393                              rlc_nr_info *rlc_info, guint32 seg_info, gboolean is_reassembled)
394 {
395     wmem_tree_key_t key[2];
396     guint32 id;
397     pdcp_bearer_parameters *params;
398 
399     /* Add raw data (according to mode) */
400     if (!is_reassembled) {
401         proto_tree_add_item(tree, (rlc_info->rlcMode == RLC_AM_MODE) ?
402                             hf_rlc_nr_am_data : hf_rlc_nr_um_data,
403                             tvb, offset, length, ENC_NA);
404     }
405 
406     if ((seg_info == 0) || is_reassembled) {  /* i.e. contains whole SDU */
407         if ((global_rlc_nr_call_pdcp_for_srb && (rlc_info->bearerType == BEARER_TYPE_SRB)) ||
408             ((rlc_info->bearerType == BEARER_TYPE_DRB) &&
409                  (((rlc_info->direction == PDCP_NR_DIRECTION_UPLINK) &&   (global_rlc_nr_call_pdcp_for_ul_drb != PDCP_drb_off)) ||
410                   ((rlc_info->direction == PDCP_NR_DIRECTION_DOWNLINK) && (global_rlc_nr_call_pdcp_for_dl_drb != PDCP_drb_off)))))
411         {
412 
413             /* Get whole PDU into tvb */
414             tvbuff_t *pdcp_tvb = tvb_new_subset_length(tvb, offset, length);
415 
416             /* Reuse or allocate struct */
417             struct pdcp_nr_info *p_pdcp_nr_info;
418             p_pdcp_nr_info = (pdcp_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0);
419             if (p_pdcp_nr_info == NULL) {
420                 p_pdcp_nr_info = wmem_new0(wmem_file_scope(), pdcp_nr_info);
421                 /* Store info in packet */
422                 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0, p_pdcp_nr_info);
423             }
424 
425             /* Fill in struct params. */
426             p_pdcp_nr_info->direction = rlc_info->direction;
427             p_pdcp_nr_info->ueid = rlc_info->ueid;
428 
429             gint seqnum_len;
430 
431             switch (rlc_info->bearerType) {
432                 case BEARER_TYPE_SRB:
433                     p_pdcp_nr_info->plane = NR_SIGNALING_PLANE;
434                     p_pdcp_nr_info->bearerType = Bearer_DCCH;
435                     p_pdcp_nr_info->seqnum_length = 12;
436                     break;
437 
438                 case BEARER_TYPE_DRB:
439                     p_pdcp_nr_info->plane = NR_USER_PLANE;
440                     p_pdcp_nr_info->bearerType = Bearer_DCCH;
441 
442                     seqnum_len = (rlc_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
443                                        global_rlc_nr_call_pdcp_for_ul_drb :
444                                        global_rlc_nr_call_pdcp_for_dl_drb;
445                     switch (seqnum_len) {
446                         case PDCP_drb_SN_12:
447                             p_pdcp_nr_info->seqnum_length = 12;
448                             break;
449                         case PDCP_drb_SN_18:
450                             p_pdcp_nr_info->seqnum_length = 18;
451                             break;
452                         case PDCP_drb_SN_signalled:
453                             /* Use whatever was signalled (i.e. in RRC) */
454                             id = (rlc_info->bearerId << 16) | rlc_info->ueid;
455                             key[0].length = 1;
456                             key[0].key = &id;
457                             key[1].length = 0;
458                             key[1].key = NULL;
459 
460                             /* Look up configured params for this PDCP DRB. */
461                             params = (pdcp_bearer_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
462                             if (params && (params->id != id)) {
463                                 params = NULL;
464                             }
465                             if (params) {
466                                 if (p_pdcp_nr_info->direction == DIRECTION_UPLINK) {
467                                     p_pdcp_nr_info->seqnum_length = params->pdcp_sn_bits_ul;
468                                     if (params->pdcp_sdap_ul) {
469                                         p_pdcp_nr_info->sdap_header &= PDCP_NR_UL_SDAP_HEADER_PRESENT;
470                                     }
471                                 }
472                                 else {
473                                     p_pdcp_nr_info->seqnum_length = params->pdcp_sn_bits_dl;
474                                     if (params->pdcp_sdap_dl) {
475                                         p_pdcp_nr_info->sdap_header &= PDCP_NR_DL_SDAP_HEADER_PRESENT;
476                                     }
477                                 }
478                                 p_pdcp_nr_info->maci_present = params->pdcp_integrity;
479                                 p_pdcp_nr_info->ciphering_disabled = params->pdcp_ciphering_disabled;
480                             }
481                             break;
482 
483                     }
484                     break;
485 
486                 default:
487                     /* Shouldn't get here */
488                     return;
489             }
490             p_pdcp_nr_info->bearerId = rlc_info->bearerId;
491 
492             /* Assume no SDAP present */
493             p_pdcp_nr_info->sdap_header = 0;
494             p_pdcp_nr_info->rohc.rohc_compression = FALSE;
495             p_pdcp_nr_info->is_retx = FALSE;
496             p_pdcp_nr_info->pdu_length = length;
497 
498             TRY {
499                 call_dissector_only(pdcp_nr_handle, pdcp_tvb, pinfo, tree, NULL);
500             }
501             CATCH_ALL {
502             }
503             ENDTRY
504         }
505     }
506 }
507 
508 /***************************************************/
509 /* Transparent mode PDU. Call RRC if configured to */
dissect_rlc_nr_tm(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_nr_info * p_rlc_nr_info,proto_item * top_ti)510 static void dissect_rlc_nr_tm(tvbuff_t *tvb, packet_info *pinfo,
511                               proto_tree *tree,
512                               int offset,
513                               rlc_nr_info *p_rlc_nr_info,
514                               proto_item *top_ti)
515 {
516     proto_item *raw_tm_ti;
517     proto_item *tm_ti;
518 
519     /* Create hidden TM root */
520     tm_ti = proto_tree_add_string_format(tree, hf_rlc_nr_tm,
521                                          tvb, offset, 0, "", "TM");
522     proto_item_set_hidden(tm_ti);
523 
524     /* Remaining bytes are all data */
525     raw_tm_ti = proto_tree_add_item(tree, hf_rlc_nr_tm_data, tvb, offset, -1, ENC_NA);
526     if (!global_rlc_nr_call_rrc_for_ccch) {
527         write_pdu_label_and_info(top_ti, NULL, pinfo,
528                                  "                               [%u-bytes]", tvb_reported_length_remaining(tvb, offset));
529     }
530 
531     if (global_rlc_nr_call_rrc_for_ccch) {
532         tvbuff_t *rrc_tvb = tvb_new_subset_remaining(tvb, offset);
533         volatile dissector_handle_t protocol_handle;
534 
535         switch (p_rlc_nr_info->bearerType) {
536         case BEARER_TYPE_BCCH_BCH:
537             protocol_handle = nr_rrc_bcch_bch;
538             break;
539         case BEARER_TYPE_BCCH_DL_SCH:
540             protocol_handle = nr_rrc_bcch_dl_sch;
541             break;
542         case BEARER_TYPE_PCCH:
543             protocol_handle = nr_rrc_pcch;
544             break;
545         case BEARER_TYPE_CCCH:
546             if (p_rlc_nr_info->direction == DIRECTION_UPLINK) {
547                 protocol_handle = (tvb_reported_length(rrc_tvb) == 8) ?
548                                     nr_rrc_ul_ccch1 : nr_rrc_ul_ccch;
549             } else {
550                 protocol_handle = nr_rrc_dl_ccch;
551             }
552             break;
553         case BEARER_TYPE_SRB:
554         case BEARER_TYPE_DRB:
555         default:
556                 /* Shouldn't happen, just return... */
557                 return;
558         }
559 
560         /* Hide raw view of bytes */
561         proto_item_set_hidden(raw_tm_ti);
562 
563         /* Call it (catch exceptions) */
564         TRY {
565             call_dissector_only(protocol_handle, rrc_tvb, pinfo, tree, NULL);
566         }
567         CATCH_ALL {
568         }
569         ENDTRY
570     }
571 }
572 
573 
574 
575 /***************************************************/
576 /* Unacknowledged mode PDU                         */
dissect_rlc_nr_um(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_nr_info * p_rlc_nr_info,proto_item * top_ti)577 static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo,
578                                proto_tree *tree,
579                                int offset,
580                                rlc_nr_info *p_rlc_nr_info,
581                                proto_item *top_ti)
582 {
583     guint32 seg_info, sn;
584     guint64 reserved;
585     proto_item *um_ti;
586     proto_tree *um_header_tree;
587     proto_item *um_header_ti;
588     gboolean is_truncated = FALSE;
589     proto_item *truncated_ti;
590     proto_item *reserved_ti;
591     int start_offset = offset;
592     guint32 so = 0;
593 
594     /* Hidden UM root */
595     um_ti = proto_tree_add_string_format(tree, hf_rlc_nr_um,
596                                          tvb, offset, 0, "", "UM");
597     proto_item_set_hidden(um_ti);
598 
599     /* Add UM header subtree */
600     um_header_ti = proto_tree_add_string_format(tree, hf_rlc_nr_um_header,
601                                                 tvb, offset, 0,
602                                                 "", "UM header");
603     um_header_tree = proto_item_add_subtree(um_header_ti,
604                                             ett_rlc_nr_um_header);
605 
606     /* Segmentation Info */
607     proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_si, tvb, offset, 1, ENC_BIG_ENDIAN, &seg_info);
608     if (seg_info == 0) {
609         /* Have all bytes of SDU, so no SN. */
610         reserved_ti = proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_nr_um_reserved,
611                                                   tvb, (offset<<3)+2, 6, &reserved, ENC_BIG_ENDIAN);
612         offset++;
613         if (reserved) {
614             expert_add_info(pinfo, reserved_ti, &ei_rlc_nr_reserved_bits_not_zero);
615         }
616         write_pdu_label_and_info(top_ti, um_header_ti, pinfo, "                             ");
617     } else {
618         /* Add sequence number */
619         if (p_rlc_nr_info->sequenceNumberLength == UM_SN_LENGTH_6_BITS) {
620             proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_sn6, tvb, offset, 1, ENC_BIG_ENDIAN, &sn);
621             offset++;
622         } else if (p_rlc_nr_info->sequenceNumberLength == UM_SN_LENGTH_12_BITS) {
623             reserved_ti = proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_nr_um_reserved, tvb,
624                                                       (offset<<3)+2, 2, &reserved, ENC_BIG_ENDIAN);
625             if (reserved) {
626                 expert_add_info(pinfo, reserved_ti, &ei_rlc_nr_reserved_bits_not_zero);
627             }
628             proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_sn12, tvb, offset, 2, ENC_BIG_ENDIAN, &sn);
629             offset += 2;
630         } else {
631             /* Invalid length of sequence number */
632             proto_tree_add_expert_format(um_header_tree, pinfo, &ei_rlc_nr_um_sn, tvb, 0, 0,
633                                          "Invalid sequence number length (%u bits)",
634                                          p_rlc_nr_info->sequenceNumberLength);
635             return;
636         }
637         if (seg_info >= 2) {
638             /* Segment offset */
639             proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_so, tvb, offset, 2, ENC_BIG_ENDIAN, &so);
640             offset += 2;
641             write_pdu_label_and_info(top_ti, um_header_ti, pinfo, "            SN=%-6u SO=%-4u", sn, so);
642         } else {
643             /* Seg info is 1, so start of SDU - no SO */
644             write_pdu_label_and_info(top_ti, um_header_ti, pinfo, "            SN=%-6u        ", sn);
645         }
646     }
647     /* End of header */
648     proto_item_set_len(um_header_ti, offset-start_offset);
649 
650     if (global_rlc_nr_headers_expected) {
651         /* There might not be any data, if only headers (plus control data) were logged */
652         is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
653         truncated_ti = proto_tree_add_boolean(tree, hf_rlc_nr_header_only, tvb, 0, 0,
654                                               is_truncated);
655         if (is_truncated) {
656             proto_item_set_generated(truncated_ti);
657             expert_add_info(pinfo, truncated_ti, &ei_rlc_nr_header_only);
658             show_PDU_in_info(pinfo, top_ti, p_rlc_nr_info->pduLength - offset, seg_info);
659             return;
660         } else {
661             proto_item_set_hidden(truncated_ti);
662         }
663     }
664 
665     /* Data */
666 
667     /* Handle any reassembly. */
668     tvbuff_t *next_tvb = NULL;
669     if (global_rlc_nr_reassemble_um_pdus && seg_info && tvb_reported_length_remaining(tvb, offset) > 0) {
670         // Set fragmented flag.
671         gboolean save_fragmented = pinfo->fragmented;
672         pinfo->fragmented = TRUE;
673         fragment_head *fh;
674         gboolean more_frags = seg_info & 0x01;
675         /* TODO: This should be unique enough, but is there a way to get frame number of first frame in reassembly table? */
676         guint32 id = p_rlc_nr_info->direction +       /* 1 bit */
677                     (p_rlc_nr_info->ueid<<1) +        /* 7 bits */
678                     (p_rlc_nr_info->bearerId<<8) +    /* 5 bits */
679                     (sn<<13);                         /* Leave 19 bits for SN - overlaps with other fields but room to overflow into msb */
680 
681         fh = fragment_add(&pdu_reassembly_table, tvb, offset, pinfo,
682                           id,                                         /* id */
683                           GUINT_TO_POINTER(id),                       /* data */
684                           so,                                         /* frag_offset */
685                           tvb_reported_length_remaining(tvb, offset), /* frag_data_len */
686                           more_frags                                  /* more_frags */
687                           );
688 
689         gboolean update_col_info = TRUE;
690         next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled RLC SDU",
691                                             fh, &rlc_nr_frag_items,
692                                             &update_col_info, tree);
693         pinfo->fragmented = save_fragmented;
694     }
695 
696     if (tvb_reported_length_remaining(tvb, offset) > 0) {
697         show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
698                          p_rlc_nr_info, seg_info, FALSE);
699         show_PDU_in_info(pinfo, top_ti, tvb_reported_length_remaining(tvb, offset), seg_info);
700 
701         /* Also add any reassembled PDU */
702         if (next_tvb) {
703             add_new_data_source(pinfo, next_tvb, "Reassembled RLC-NR PDU");
704             show_PDU_in_tree(pinfo, tree, next_tvb, 0, tvb_captured_length(next_tvb),
705                              p_rlc_nr_info, seg_info, TRUE);
706         }
707     } else if (!global_rlc_nr_headers_expected) {
708         /* Report that expected data was missing (unless we know it might happen) */
709         expert_add_info(pinfo, um_header_ti, &ei_rlc_nr_um_data_no_data);
710     }
711 }
712 
713 
714 
715 /* Dissect an AM STATUS PDU */
dissect_rlc_nr_am_status_pdu(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,proto_item * status_ti,int offset,proto_item * top_ti,rlc_nr_info * p_rlc_nr_info)716 static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb,
717                                          packet_info *pinfo,
718                                          proto_tree *tree,
719                                          proto_item *status_ti,
720                                          int offset,
721                                          proto_item *top_ti,
722                                          rlc_nr_info *p_rlc_nr_info)
723 {
724     guint8     sn_size, reserved_bits1, reserved_bits2;
725     guint32    cpt, sn_limit, nack_count = 0;
726     guint64    ack_sn, nack_sn;
727     guint64    e1, e2, e3, reserved;
728     guint32    so_start, so_end, nack_range;
729     int        bit_offset = offset << 3;
730     proto_item *ti;
731 
732     /****************************************************************/
733     /* Part of RLC control PDU header                               */
734 
735     /* Control PDU Type (CPT) */
736     ti = proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_cpt, tvb, offset, 1, ENC_BIG_ENDIAN, &cpt);
737     if (cpt != 0) {
738         /* Protest and stop - only know about STATUS PDUs */
739         expert_add_info_format(pinfo, ti, &ei_rlc_nr_am_cpt,
740                                "RLC Control frame type %u not handled", cpt);
741         return;
742     }
743 
744     if (p_rlc_nr_info->sequenceNumberLength == AM_SN_LENGTH_12_BITS) {
745         sn_size = 12;
746         sn_limit = 4096;
747         reserved_bits1 = 7;
748         reserved_bits2 = 1;
749     } else if (p_rlc_nr_info->sequenceNumberLength == AM_SN_LENGTH_18_BITS) {
750         sn_size = 18;
751         sn_limit = 262044;
752         reserved_bits1 = 1;
753         reserved_bits2 = 3;
754     } else {
755         proto_tree_add_expert_format(tree, pinfo, &ei_rlc_nr_am_sn, tvb, 0, 0,
756                                      "Invalid sequence number length (%u bits)",
757                                      p_rlc_nr_info->sequenceNumberLength);
758         return;
759     }
760 
761     /* The Status PDU itself starts 4 bits into the byte */
762     bit_offset += 4;
763 
764     /* ACK SN */
765     proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_ack_sn, tvb,
766                                 bit_offset, sn_size, &ack_sn, ENC_BIG_ENDIAN);
767     bit_offset += sn_size;
768     write_pdu_label_and_info(top_ti, status_ti, pinfo, "  ACK_SN=%-6u", (guint32)ack_sn);
769 
770     /* E1 */
771     proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e1, tvb,
772                                 bit_offset, 1, &e1, ENC_BIG_ENDIAN);
773     bit_offset++;
774 
775     /* Reserved bits */
776     ti = proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_reserved, tvb, bit_offset,
777                                      reserved_bits1, &reserved, ENC_BIG_ENDIAN);
778     bit_offset += reserved_bits1;
779     if (reserved) {
780         expert_add_info(pinfo, ti, &ei_rlc_nr_reserved_bits_not_zero);
781     }
782 
783     /* Optional, extra fields */
784     while (e1) {
785         proto_item *nack_ti;
786 
787         /****************************/
788         /* Read NACK_SN, E1, E2, E3 */
789 
790         /* NACK_SN */
791         nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_nack_sn, tvb,
792                                               bit_offset, sn_size, &nack_sn, ENC_BIG_ENDIAN);
793         bit_offset += sn_size;
794         write_pdu_label_and_info(top_ti, NULL, pinfo, "  NACK_SN=%-6u", (guint32)nack_sn);
795 
796         /* We shouldn't NACK the ACK_SN! */
797         if (nack_sn == ack_sn) {
798             expert_add_info_format(pinfo, nack_ti, &ei_rlc_nr_am_nack_sn_ack_same,
799                                    "Status PDU shouldn't ACK and NACK the same sequence number (%" G_GINT64_MODIFIER "u)",
800                                    ack_sn);
801         }
802 
803         /* NACK should always be 'behind' the ACK */
804         if ((sn_limit + ack_sn - nack_sn) % sn_limit > (sn_limit>>1)) {
805             expert_add_info(pinfo, nack_ti, &ei_rlc_nr_am_nack_sn_ahead_ack);
806         }
807 
808         nack_count++;
809 
810         /* E1 */
811         proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e1, tvb,
812                                     bit_offset, 1, &e1, ENC_BIG_ENDIAN);
813         bit_offset++;
814 
815         /* E2 */
816         proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e2, tvb,
817                                     bit_offset, 1, &e2, ENC_BIG_ENDIAN);
818         bit_offset++;
819 
820         /* Report as expert info */
821         if (e2) {
822             expert_add_info_format(pinfo, nack_ti, &ei_rlc_nr_am_nack_sn_partial,
823                                    "Status PDU reports NACK (partial) on %s for UE %u",
824                                    val_to_str_const(p_rlc_nr_info->direction, direction_vals, "Unknown"),
825                                    p_rlc_nr_info->ueid);
826         } else {
827             expert_add_info_format(pinfo, nack_ti, &ei_rlc_nr_am_nack_sn,
828                                    "Status PDU reports NACK on %s for UE %u",
829                                    val_to_str_const(p_rlc_nr_info->direction, direction_vals, "Unknown"),
830                                    p_rlc_nr_info->ueid);
831         }
832 
833         /* E3 */
834         proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e3, tvb,
835                                     bit_offset, 1, &e3, ENC_BIG_ENDIAN);
836         bit_offset++;
837 
838         /* Reserved bits */
839         ti = proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_reserved, tvb, bit_offset,
840                                          reserved_bits2, &reserved, ENC_BIG_ENDIAN);
841         bit_offset += reserved_bits2;
842         if (reserved) {
843             expert_add_info(pinfo, ti, &ei_rlc_nr_reserved_bits_not_zero);
844         }
845 
846         if (e2) {
847             /* Read SOstart, SOend */
848             proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_so_start, tvb,
849                                          bit_offset>>3, 2, ENC_BIG_ENDIAN, &so_start);
850             bit_offset += 16;
851 
852             proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_so_end, tvb,
853                                          bit_offset>>3, 2, ENC_BIG_ENDIAN, &so_end);
854             bit_offset += 16;
855 
856 
857             if (so_end == 0xffff) {
858                 write_pdu_label_and_info(top_ti, NULL, pinfo,
859                                          " (SOstart=%u SOend=<END-OF_SDU>)",
860                                          so_start);
861             } else {
862                 write_pdu_label_and_info(top_ti, NULL, pinfo,
863                                          " (SOstart=%u SOend=%u)",
864                                          so_start, so_end);
865             }
866         }
867 
868         if (e3) {
869             proto_item *nack_range_ti;
870 
871             /* Read NACK range */
872             nack_range_ti = proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_nack_range, tvb,
873                                                          bit_offset>>3, 1, ENC_BIG_ENDIAN, &nack_range);
874             bit_offset += 8;
875             if (nack_range == 0) {
876                 expert_add_info(pinfo, nack_range_ti, &ei_rlc_nr_am_nack_range);
877             } else {
878                 nack_count += nack_range-1;
879             }
880 
881             write_pdu_label_and_info(top_ti, NULL, pinfo," NACK range=%u", nack_range);
882         }
883     }
884 
885     if (nack_count > 0) {
886         proto_item *count_ti = proto_tree_add_uint(tree, hf_rlc_nr_am_nacks, tvb, 0, 1, nack_count);
887         proto_item_set_generated(count_ti);
888         proto_item_append_text(status_ti, "  (%u NACKs)", nack_count);
889     }
890 
891     /* Check that we've reached the end of the PDU. If not, show malformed */
892     offset = (bit_offset+7) / 8;
893     if (tvb_reported_length_remaining(tvb, offset) > 0) {
894         expert_add_info_format(pinfo, status_ti, &ei_rlc_nr_bytes_after_status_pdu_complete,
895                                "%cL %u bytes remaining after Status PDU complete",
896                                (p_rlc_nr_info->direction == DIRECTION_UPLINK) ? 'U' : 'D',
897                                tvb_reported_length_remaining(tvb, offset));
898     }
899 
900     /* Set selected length of control tree */
901     proto_item_set_len(status_ti, offset);
902 }
903 
904 
905 /***************************************************/
906 /* Acknowledged mode PDU                           */
dissect_rlc_nr_am(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,int offset,rlc_nr_info * p_rlc_nr_info,proto_item * top_ti)907 static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo,
908                               proto_tree *tree,
909                               int offset,
910                               rlc_nr_info *p_rlc_nr_info,
911                               proto_item *top_ti)
912 {
913     gboolean dc, polling;
914     guint32 seg_info, sn;
915     guint64 reserved;
916     proto_item *am_ti;
917     proto_tree *am_header_tree;
918     proto_item *am_header_ti;
919     gint   start_offset = offset;
920     gboolean is_truncated = FALSE;
921     proto_item *truncated_ti;
922     proto_item *reserved_ti;
923     guint32 so = 0;
924 
925     /* Hidden AM root */
926     am_ti = proto_tree_add_string_format(tree, hf_rlc_nr_am,
927                                          tvb, offset, 0, "", "AM");
928     proto_item_set_hidden(am_ti);
929 
930     /* Add AM header subtree */
931     am_header_ti = proto_tree_add_string_format(tree, hf_rlc_nr_am_header,
932                                                 tvb, offset, 0,
933                                                 "", "AM Header ");
934     am_header_tree = proto_item_add_subtree(am_header_ti,
935                                             ett_rlc_nr_am_header);
936 
937     /* First bit is Data/Control flag */
938     proto_tree_add_item_ret_boolean(am_header_tree, hf_rlc_nr_am_data_control,
939                                     tvb, offset, 1, ENC_BIG_ENDIAN, &dc);
940 
941     if (dc == 0) {
942         /**********************/
943         /* Status PDU         */
944         write_pdu_label_and_info_literal(top_ti, NULL, pinfo, " [CONTROL]");
945 
946         /* Control PDUs are a completely separate format  */
947         dissect_rlc_nr_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti,
948                                      offset, top_ti, p_rlc_nr_info);
949         return;
950     }
951 
952     /**********************/
953     /* Data PDU           */
954     write_pdu_label_and_info_literal(top_ti, NULL, pinfo, " [DATA]");
955 
956     /* Polling bit */
957     proto_tree_add_item_ret_boolean(am_header_tree, hf_rlc_nr_am_p, tvb,
958                                     offset, 1, ENC_BIG_ENDIAN, &polling);
959 
960     write_pdu_label_and_info_literal(top_ti, NULL, pinfo, (polling) ? " (P) " : "     ");
961     if (polling) {
962         proto_item_append_text(am_header_ti, " (P) ");
963     }
964 
965     /* Segmentation Info */
966     proto_tree_add_item_ret_uint(am_header_tree, hf_rlc_nr_am_si, tvb,
967                                  offset, 1, ENC_BIG_ENDIAN, &seg_info);
968 
969     /* Sequence Number */
970     if (p_rlc_nr_info->sequenceNumberLength == AM_SN_LENGTH_12_BITS) {
971         proto_tree_add_item_ret_uint(am_header_tree, hf_rlc_nr_am_sn12, tvb,
972                                      offset, 2, ENC_BIG_ENDIAN, &sn);
973         offset += 2;
974     } else if (p_rlc_nr_info->sequenceNumberLength == AM_SN_LENGTH_18_BITS) {
975         reserved_ti = proto_tree_add_bits_ret_val(am_header_tree, hf_rlc_nr_am_reserved, tvb,
976                                                   (offset<<3)+4, 2, &reserved, ENC_BIG_ENDIAN);
977         if (reserved) {
978             expert_add_info(pinfo, reserved_ti, &ei_rlc_nr_reserved_bits_not_zero);
979         }
980         proto_tree_add_item_ret_uint(am_header_tree, hf_rlc_nr_am_sn18, tvb,
981                                      offset, 3, ENC_BIG_ENDIAN, &sn);
982         offset += 3;
983     } else {
984         /* Invalid length of sequence number */
985         proto_tree_add_expert_format(am_header_tree, pinfo, &ei_rlc_nr_am_sn, tvb, 0, 0,
986                                      "Invalid sequence number length (%u bits)",
987                                      p_rlc_nr_info->sequenceNumberLength);
988         return;
989     }
990 
991     /* Segment Offset */
992     if (seg_info >= 2) {
993         proto_tree_add_item_ret_uint(am_header_tree, hf_rlc_nr_am_so, tvb,
994                                      offset, 2, ENC_BIG_ENDIAN, &so);
995         offset += 2;
996         write_pdu_label_and_info(top_ti, am_header_ti, pinfo, "SN=%-6u SO=%-4u",sn, so);
997     } else {
998         write_pdu_label_and_info(top_ti, am_header_ti, pinfo, "SN=%-6u        ", sn);
999     }
1000 
1001     /* Header is now complete */
1002     proto_item_set_len(am_header_ti, offset-start_offset);
1003 
1004     /* There might not be any data, if only headers (plus control data) were logged */
1005     if (global_rlc_nr_headers_expected) {
1006         is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0);
1007         truncated_ti = proto_tree_add_boolean(tree, hf_rlc_nr_header_only, tvb, 0, 0,
1008                                               is_truncated);
1009         if (is_truncated) {
1010             proto_item_set_generated(truncated_ti);
1011             expert_add_info(pinfo, truncated_ti, &ei_rlc_nr_header_only);
1012             show_PDU_in_info(pinfo, top_ti, p_rlc_nr_info->pduLength - offset, seg_info);
1013             return;
1014         } else {
1015             proto_item_set_hidden(truncated_ti);
1016         }
1017     }
1018 
1019     /* Data */
1020 
1021     /* Handle any reassembly. */
1022     tvbuff_t *next_tvb = NULL;
1023     if (global_rlc_nr_reassemble_am_pdus && seg_info && tvb_reported_length_remaining(tvb, offset) > 0) {
1024         // Set fragmented flag.
1025         gboolean save_fragmented = pinfo->fragmented;
1026         pinfo->fragmented = TRUE;
1027         fragment_head *fh;
1028         gboolean more_frags = seg_info & 0x01;
1029         /* TODO: This should be unique enough, but is there a way to get frame number of first frame in reassembly table? */
1030         guint32 id = p_rlc_nr_info->direction +       /* 1 bit */
1031                     (p_rlc_nr_info->ueid<<1) +        /* 7 bits */
1032                     (p_rlc_nr_info->bearerId<<8) +    /* 5 bits */
1033                     (sn<<13);                         /* Leave 19 bits for SN - overlaps with other fields but room to overflow into msb */
1034 
1035         fh = fragment_add(&pdu_reassembly_table, tvb, offset, pinfo,
1036                           id,                                         /* id */
1037                           GUINT_TO_POINTER(id),                       /* data */
1038                           so,                                         /* frag_offset */
1039                           tvb_reported_length_remaining(tvb, offset), /* frag_data_len */
1040                           more_frags                                  /* more_frags */
1041                           );
1042 
1043         gboolean update_col_info = TRUE;
1044         next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled RLC SDU",
1045                                             fh, &rlc_nr_frag_items,
1046                                             &update_col_info, tree);
1047         pinfo->fragmented = save_fragmented;
1048     }
1049 
1050 
1051     if (tvb_reported_length_remaining(tvb, offset) > 0) {
1052         show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
1053                          p_rlc_nr_info, seg_info, FALSE);
1054         show_PDU_in_info(pinfo, top_ti, tvb_reported_length_remaining(tvb, offset), seg_info);
1055 
1056         /* Also add any reassembled PDU */
1057         if (next_tvb) {
1058             add_new_data_source(pinfo, next_tvb, "Reassembled RLC-NR PDU");
1059             show_PDU_in_tree(pinfo, tree, next_tvb, 0, tvb_captured_length(next_tvb),
1060                              p_rlc_nr_info, seg_info, TRUE);
1061         }
1062     } else if (!global_rlc_nr_headers_expected) {
1063         /* Report that expected data was missing (unless we know it might happen) */
1064         expert_add_info(pinfo, am_header_ti, &ei_rlc_nr_am_data_no_data);
1065     }
1066 }
1067 
1068 
1069 /* Heuristic dissector looks for supported framing protocol (see header file for details) */
dissect_rlc_nr_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1070 static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo,
1071                                     proto_tree *tree, void *data _U_)
1072 {
1073     gint        offset = 0;
1074     rlc_nr_info *p_rlc_nr_info;
1075     tvbuff_t    *rlc_tvb;
1076     guint8      tag;
1077 
1078     /* Do this again on re-dissection to re-discover offset of actual PDU */
1079 
1080     /* Needs to be at least as long as:
1081        - the signature string
1082        - fixed header bytes
1083        - tag for data
1084        - at least one byte of RLC PDU payload */
1085     if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(RLC_NR_START_STRING)+2+2)) {
1086         return FALSE;
1087     }
1088 
1089     /* OK, compare with signature string */
1090     if (tvb_strneql(tvb, offset, RLC_NR_START_STRING, (gint)strlen(RLC_NR_START_STRING)) != 0) {
1091         return FALSE;
1092     }
1093     offset += (gint)strlen(RLC_NR_START_STRING);
1094 
1095 
1096     /* If redissecting, use previous info struct (if available) */
1097     p_rlc_nr_info = (rlc_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0);
1098     if (p_rlc_nr_info == NULL) {
1099         /* Allocate new info struct for this frame */
1100         p_rlc_nr_info = wmem_new0(wmem_file_scope(), struct rlc_nr_info);
1101 
1102         /* Read fixed fields */
1103         p_rlc_nr_info->rlcMode = tvb_get_guint8(tvb, offset++);
1104         p_rlc_nr_info->sequenceNumberLength = tvb_get_guint8(tvb, offset++);
1105 
1106         /* Read optional fields */
1107         do {
1108             /* Process next tag */
1109             tag = tvb_get_guint8(tvb, offset++);
1110             switch (tag) {
1111                 case RLC_NR_DIRECTION_TAG:
1112                     p_rlc_nr_info->direction = tvb_get_guint8(tvb, offset);
1113                     offset++;
1114                     break;
1115                 case RLC_NR_UEID_TAG:
1116                     p_rlc_nr_info->ueid = tvb_get_ntohs(tvb, offset);
1117                     offset += 2;
1118                     break;
1119                 case RLC_NR_BEARER_TYPE_TAG:
1120                     p_rlc_nr_info->bearerType = tvb_get_guint8(tvb, offset);
1121                     offset++;
1122                     break;
1123                 case RLC_NR_BEARER_ID_TAG:
1124                     p_rlc_nr_info->bearerId = tvb_get_guint8(tvb, offset);
1125                     offset++;
1126                     break;
1127                 case RLC_NR_PAYLOAD_TAG:
1128                     /* Have reached data, so set payload length and get out of loop */
1129                     p_rlc_nr_info->pduLength = tvb_reported_length_remaining(tvb, offset);
1130                     break;
1131                 default:
1132                     /* It must be a recognised tag */
1133                     {
1134                         proto_item *ti;
1135                         proto_tree *subtree;
1136 
1137                         col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-NR");
1138                         col_clear(pinfo->cinfo, COL_INFO);
1139                         ti = proto_tree_add_item(tree, proto_rlc_nr, tvb, offset, tvb_reported_length(tvb), ENC_NA);
1140                         subtree = proto_item_add_subtree(ti, ett_rlc_nr);
1141                         proto_tree_add_expert(subtree, pinfo, &ei_rlc_nr_unknown_udp_framing_tag,
1142                                               tvb, offset-1, 1);
1143                     }
1144                     wmem_free(wmem_file_scope(), p_rlc_nr_info);
1145                     return TRUE;
1146             }
1147         } while (tag != RLC_NR_PAYLOAD_TAG);
1148 
1149         /* Store info in packet */
1150         p_add_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0, p_rlc_nr_info);
1151     } else {
1152         offset = tvb_reported_length(tvb) - p_rlc_nr_info->pduLength;
1153     }
1154 
1155     /**************************************/
1156     /* OK, now dissect as RLC NR          */
1157 
1158     /* Create tvb that starts at actual RLC PDU */
1159     rlc_tvb = tvb_new_subset_remaining(tvb, offset);
1160     dissect_rlc_nr_common(rlc_tvb, pinfo, tree, TRUE);
1161     return TRUE;
1162 }
1163 
1164 /*****************************/
1165 /* Main dissection function. */
1166 /*****************************/
1167 
dissect_rlc_nr(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1168 static int dissect_rlc_nr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1169 {
1170     dissect_rlc_nr_common(tvb, pinfo, tree, FALSE);
1171     return tvb_captured_length(tvb);
1172 }
1173 
dissect_rlc_nr_common(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,gboolean is_udp_framing)1174 static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing)
1175 {
1176     proto_tree             *rlc_nr_tree;
1177     proto_tree             *context_tree;
1178     proto_item             *top_ti;
1179     proto_item             *context_ti;
1180     proto_item             *ti;
1181     proto_item             *mode_ti;
1182     gint                   offset = 0;
1183     struct rlc_nr_info     *p_rlc_nr_info;
1184 
1185     /* Set protocol name */
1186     col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-NR");
1187 
1188     /* Create protocol tree. */
1189     top_ti = proto_tree_add_item(tree, proto_rlc_nr, tvb, offset, -1, ENC_NA);
1190     rlc_nr_tree = proto_item_add_subtree(top_ti, ett_rlc_nr);
1191 
1192 
1193     /* Look for packet info! */
1194     p_rlc_nr_info = (rlc_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0);
1195 
1196     /* Can't dissect anything without it... */
1197     if (p_rlc_nr_info == NULL) {
1198         proto_tree_add_expert(rlc_nr_tree, pinfo, &ei_rlc_nr_no_per_frame_info, tvb, offset, -1);
1199         return;
1200     }
1201 
1202     /* Clear info column when using UDP framing */
1203     if (is_udp_framing) {
1204         col_clear(pinfo->cinfo, COL_INFO);
1205     }
1206 
1207     /*****************************************/
1208     /* Show context information              */
1209 
1210     /* Create context root */
1211     context_ti = proto_tree_add_string_format(rlc_nr_tree, hf_rlc_nr_context,
1212                                               tvb, offset, 0, "", "Context");
1213     context_tree = proto_item_add_subtree(context_ti, ett_rlc_nr_context);
1214     proto_item_set_generated(context_ti);
1215 
1216     ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_direction,
1217                              tvb, 0, 0, p_rlc_nr_info->direction);
1218     proto_item_set_generated(ti);
1219 
1220     mode_ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_mode,
1221                                   tvb, 0, 0, p_rlc_nr_info->rlcMode);
1222     proto_item_set_generated(mode_ti);
1223 
1224     if (p_rlc_nr_info->ueid != 0) {
1225         ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_ueid,
1226                                  tvb, 0, 0, p_rlc_nr_info->ueid);
1227         proto_item_set_generated(ti);
1228     }
1229 
1230     ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_bearer_type,
1231                              tvb, 0, 0, p_rlc_nr_info->bearerType);
1232     proto_item_set_generated(ti);
1233 
1234     if ((p_rlc_nr_info->bearerType == BEARER_TYPE_SRB) ||
1235         (p_rlc_nr_info->bearerType == BEARER_TYPE_DRB)) {
1236         ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_bearer_id,
1237                                  tvb, 0, 0, p_rlc_nr_info->bearerId);
1238         proto_item_set_generated(ti);
1239     }
1240 
1241     ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_pdu_length,
1242                              tvb, 0, 0, p_rlc_nr_info->pduLength);
1243     proto_item_set_generated(ti);
1244 
1245     if (p_rlc_nr_info->rlcMode != RLC_TM_MODE) {
1246         ti = proto_tree_add_uint(context_tree, hf_rlc_nr_context_sn_length,
1247                                  tvb, 0, 0, p_rlc_nr_info->sequenceNumberLength);
1248         proto_item_set_generated(ti);
1249     }
1250 
1251     /* Append highlights to top-level item */
1252     if (p_rlc_nr_info->ueid != 0) {
1253         proto_item_append_text(top_ti, "   UEId=%u", p_rlc_nr_info->ueid);
1254         col_append_fstr(pinfo->cinfo, COL_INFO, "UEId=%-4u ", p_rlc_nr_info->ueid);
1255     }
1256 
1257     /* Append context highlights to info column */
1258     write_pdu_label_and_info(top_ti, NULL, pinfo,
1259                              " [%s] [%s] ",
1260                              (p_rlc_nr_info->direction == 0) ? "UL" : "DL",
1261                              val_to_str_const(p_rlc_nr_info->rlcMode, rlc_mode_short_vals, "Unknown"));
1262 
1263     if (p_rlc_nr_info->bearerId == 0) {
1264         write_pdu_label_and_info(top_ti, NULL, pinfo, "%s   ",
1265                                  val_to_str_const(p_rlc_nr_info->bearerType, rlc_bearer_type_vals, "Unknown"));
1266     } else {
1267         write_pdu_label_and_info(top_ti, NULL, pinfo, "%s:%-2u",
1268                                  val_to_str_const(p_rlc_nr_info->bearerType, rlc_bearer_type_vals, "Unknown"),
1269                                  p_rlc_nr_info->bearerId);
1270     }
1271 
1272     /* Dissect the RLC PDU itself. Format depends upon mode... */
1273     switch (p_rlc_nr_info->rlcMode) {
1274 
1275         case RLC_TM_MODE:
1276             dissect_rlc_nr_tm(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti);
1277             break;
1278 
1279         case RLC_UM_MODE:
1280             dissect_rlc_nr_um(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti);
1281             break;
1282 
1283         case RLC_AM_MODE:
1284             dissect_rlc_nr_am(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti);
1285             break;
1286 
1287         default:
1288             /* Error - unrecognised mode */
1289             expert_add_info_format(pinfo, mode_ti, &ei_rlc_nr_context_mode,
1290                                    "Unrecognised RLC Mode set (%u)", p_rlc_nr_info->rlcMode);
1291             break;
1292     }
1293 }
1294 
1295 
1296 /* Configure DRB PDCP channel properties. */
set_rlc_nr_drb_pdcp_mapping(packet_info * pinfo,nr_drb_rlc_pdcp_mapping_t * drb_mapping)1297 void set_rlc_nr_drb_pdcp_mapping(packet_info *pinfo,
1298                                  nr_drb_rlc_pdcp_mapping_t *drb_mapping)
1299 {
1300     wmem_tree_key_t key[2];
1301     guint32 id;
1302     pdcp_bearer_parameters *params;
1303 
1304     if (PINFO_FD_VISITED(pinfo)) {
1305         return;
1306     }
1307 
1308     id = (drb_mapping->drbid << 16) | drb_mapping->ueid;
1309     key[0].length = 1;
1310     key[0].key = &id;
1311     key[1].length = 0;
1312     key[1].key = NULL;
1313 
1314     /* Look up entry for this UEId/drbid */
1315     params = (pdcp_bearer_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
1316     if (params && (params->id != id)) {
1317         params = NULL;
1318     }
1319     if (params == NULL) {
1320         /* Not found so create new entry */
1321         params = (pdcp_bearer_parameters *)wmem_new(wmem_file_scope(), pdcp_bearer_parameters);
1322         params->id = id;
1323         wmem_tree_insert32_array(ue_parameters_tree, key, (void *)params);
1324     }
1325 
1326     /* Populate params */
1327     params->pdcp_sn_bits_ul = drb_mapping->pdcpUlSnLength;
1328     params->pdcp_sn_bits_dl = drb_mapping->pdcpDlSnLength;
1329     params->pdcp_sdap_ul = drb_mapping->pdcpUlSdap;
1330     params->pdcp_sdap_dl = drb_mapping->pdcpDlSdap;
1331     params->pdcp_integrity = drb_mapping->pdcpIntegrityProtection;
1332     params->pdcp_ciphering_disabled = drb_mapping->pdcpCipheringDisabled;
1333 }
1334 
get_rlc_nr_drb_pdcp_mapping(guint16 ue_id,guint8 drb_id)1335 pdcp_bearer_parameters* get_rlc_nr_drb_pdcp_mapping(guint16 ue_id, guint8 drb_id)
1336 {
1337     wmem_tree_key_t key[2];
1338     guint32 id;
1339     pdcp_bearer_parameters *params;
1340 
1341     id = (drb_id << 16) | ue_id;
1342     key[0].length = 1;
1343     key[0].key = &id;
1344     key[1].length = 0;
1345     key[1].key = NULL;
1346 
1347     /* Look up configured params for this PDCP DRB. */
1348     params = (pdcp_bearer_parameters *)wmem_tree_lookup32_array_le(ue_parameters_tree, key);
1349     if (params && (params->id != id)) {
1350         params = NULL;
1351     }
1352 
1353     return params;
1354 }
1355 
1356 
proto_register_rlc_nr(void)1357 void proto_register_rlc_nr(void)
1358 {
1359     static hf_register_info hf[] =
1360     {
1361         /**********************************/
1362         /* Items for decoding context     */
1363         { &hf_rlc_nr_context,
1364             { "Context",
1365               "rlc-nr.context", FT_STRING, BASE_NONE, NULL, 0x0,
1366               NULL, HFILL
1367             }
1368         },
1369         { &hf_rlc_nr_context_mode,
1370             { "RLC Mode",
1371               "rlc-nr.mode", FT_UINT8, BASE_DEC, VALS(rlc_mode_vals), 0x0,
1372               NULL, HFILL
1373             }
1374         },
1375         { &hf_rlc_nr_context_direction,
1376             { "Direction",
1377               "rlc-nr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
1378               "Direction of message", HFILL
1379             }
1380         },
1381         { &hf_rlc_nr_context_ueid,
1382             { "UEId",
1383               "rlc-nr.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
1384               "User Equipment Identifier associated with message", HFILL
1385             }
1386         },
1387         { &hf_rlc_nr_context_bearer_type,
1388             { "Bearer Type",
1389               "rlc-nr.bearer-type", FT_UINT16, BASE_DEC, VALS(rlc_bearer_type_vals), 0x0,
1390               "Bearer Type associated with message", HFILL
1391             }
1392         },
1393         { &hf_rlc_nr_context_bearer_id,
1394             { "Bearer Id",
1395               "rlc-nr.bearer-id", FT_UINT16, BASE_DEC, 0, 0x0,
1396               "Bearer ID associated with message", HFILL
1397             }
1398         },
1399         { &hf_rlc_nr_context_pdu_length,
1400             { "PDU Length",
1401               "rlc-nr.pdu-length", FT_UINT16, BASE_DEC, 0, 0x0,
1402               "Length of PDU (in bytes)", HFILL
1403             }
1404         },
1405         { &hf_rlc_nr_context_sn_length,
1406             { "Sequence Number length",
1407               "rlc-nr.seqnum-length", FT_UINT8, BASE_DEC, 0, 0x0,
1408               "Length of sequence number in bits", HFILL
1409             }
1410         },
1411 
1412         /* Transparent mode fields */
1413         { &hf_rlc_nr_tm,
1414             { "TM",
1415               "rlc-nr.tm", FT_STRING, BASE_NONE, NULL, 0x0,
1416               "Transparent Mode", HFILL
1417             }
1418         },
1419         { &hf_rlc_nr_tm_data,
1420             { "TM Data",
1421               "rlc-nr.tm.data", FT_BYTES, BASE_NONE, 0, 0x0,
1422               "Transparent Mode Data", HFILL
1423             }
1424         },
1425 
1426         /* Unacknowledged mode fields */
1427         { &hf_rlc_nr_um,
1428             { "UM",
1429               "rlc-nr.um", FT_STRING, BASE_NONE, NULL, 0x0,
1430               "Unacknowledged Mode", HFILL
1431             }
1432         },
1433         { &hf_rlc_nr_um_header,
1434             { "UM Header",
1435               "rlc-nr.um.header", FT_STRING, BASE_NONE, NULL, 0x0,
1436               "Unacknowledged Mode Header", HFILL
1437             }
1438         },
1439         { &hf_rlc_nr_um_si,
1440             { "Segmentation Info",
1441               "rlc-nr.um.si", FT_UINT8, BASE_HEX, VALS(seg_info_vals), 0xc0,
1442               NULL, HFILL
1443             }
1444         },
1445         { &hf_rlc_nr_um_reserved,
1446             { "Reserved",
1447               "rlc-nr.um.reserved", FT_UINT8, BASE_HEX, 0, 0x0,
1448               NULL, HFILL
1449             }
1450         },
1451         { &hf_rlc_nr_um_sn6,
1452             { "Sequence Number",
1453               "rlc-nr.um.sn", FT_UINT8, BASE_DEC, 0, 0x3f,
1454               NULL, HFILL
1455             }
1456         },
1457         { &hf_rlc_nr_um_sn12,
1458             { "Sequence Number",
1459               "rlc-nr.um.sn", FT_UINT16, BASE_DEC, 0, 0x0fff,
1460               NULL, HFILL
1461             }
1462         },
1463         { &hf_rlc_nr_um_so,
1464             { "Segment Offset",
1465               "rlc-nr.um.so", FT_UINT16, BASE_DEC, 0, 0x0,
1466               NULL, HFILL
1467             }
1468         },
1469         { &hf_rlc_nr_um_data,
1470             { "UM Data",
1471               "rlc-nr.um.data", FT_BYTES, BASE_NONE, 0, 0x0,
1472               "Unacknowledged Mode Data", HFILL
1473             }
1474         },
1475 
1476         /* Acknowledged mode fields */
1477         { &hf_rlc_nr_am,
1478             { "AM",
1479               "rlc-nr.am", FT_STRING, BASE_NONE, NULL, 0x0,
1480               "Acknowledged Mode", HFILL
1481             }
1482         },
1483         { &hf_rlc_nr_am_header,
1484             { "AM Header",
1485               "rlc-nr.am.header", FT_STRING, BASE_NONE, NULL, 0x0,
1486               "Acknowledged Mode Header", HFILL
1487             }
1488         },
1489         { &hf_rlc_nr_am_data_control,
1490             { "Data/Control",
1491               "rlc-nr.am.dc", FT_BOOLEAN, 8, TFS(&data_or_control_vals), 0x80,
1492               NULL, HFILL
1493             }
1494         },
1495         { &hf_rlc_nr_am_p,
1496             { "Polling Bit",
1497               "rlc-nr.am.p", FT_BOOLEAN, 8, TFS(&polling_bit_vals), 0x40,
1498               NULL, HFILL
1499             }
1500         },
1501         { &hf_rlc_nr_am_si,
1502             { "Segmentation Info",
1503               "rlc-nr.am.si", FT_UINT8, BASE_HEX, VALS(seg_info_vals), 0x30,
1504               NULL, HFILL
1505             }
1506         },
1507         { &hf_rlc_nr_am_sn12,
1508             { "Sequence Number",
1509               "rlc-nr.am.sn", FT_UINT16, BASE_DEC, 0, 0x0fff,
1510               NULL, HFILL
1511             }
1512         },
1513         { &hf_rlc_nr_am_sn18,
1514             { "Sequence Number",
1515               "rlc-nr.am.sn", FT_UINT24, BASE_DEC, 0, 0x03ffff,
1516               NULL, HFILL
1517             }
1518         },
1519         { &hf_rlc_nr_am_reserved,
1520             { "Reserved",
1521               "rlc-nr.am.reserved", FT_UINT8, BASE_HEX, 0, 0x0,
1522               NULL, HFILL
1523             }
1524         },
1525         { &hf_rlc_nr_am_so,
1526             { "Segment Offset",
1527               "rlc-nr.am.so", FT_UINT16, BASE_DEC, 0, 0x0,
1528               NULL, HFILL
1529             }
1530         },
1531         { &hf_rlc_nr_am_data,
1532             { "AM Data",
1533               "rlc-nr.am.data", FT_BYTES, BASE_NONE, 0, 0x0,
1534               "Acknowledged Mode Data", HFILL
1535             }
1536         },
1537 
1538         { &hf_rlc_nr_am_cpt,
1539             { "Control PDU Type",
1540               "rlc-nr.am.cpt", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
1541               "AM Control PDU Type", HFILL
1542             }
1543         },
1544         { &hf_rlc_nr_am_ack_sn,
1545             { "ACK Sequence Number",
1546               "rlc-nr.am.ack-sn", FT_UINT24, BASE_DEC, 0, 0x0,
1547               "Sequence Number we expect to receive next", HFILL
1548             }
1549         },
1550         { &hf_rlc_nr_am_e1,
1551             { "Extension bit 1",
1552               "rlc-nr.am.e1", FT_BOOLEAN, BASE_NONE, TFS(&am_e1_vals), 0x0,
1553               NULL, HFILL
1554             }
1555         },
1556         { &hf_rlc_nr_am_e2,
1557             { "Extension bit 2",
1558               "rlc-nr.am.e2", FT_BOOLEAN, BASE_NONE, TFS(&am_e2_vals), 0x0,
1559               NULL, HFILL
1560             }
1561         },
1562         { &hf_rlc_nr_am_e3,
1563             { "Extension bit 3",
1564               "rlc-nr.am.e3", FT_BOOLEAN, BASE_NONE, TFS(&am_e3_vals), 0x0,
1565               NULL, HFILL
1566             }
1567         },
1568         { &hf_rlc_nr_am_nacks,
1569             { "Number of NACKs",
1570               "rlc-nr.am.nacks", FT_UINT32, BASE_DEC, 0, 0x0,
1571               "Number of NACKs in this status PDU", HFILL
1572             }
1573         },
1574         { &hf_rlc_nr_am_nack_sn,
1575             { "NACK Sequence Number",
1576               "rlc-nr.am.nack-sn", FT_UINT24, BASE_DEC, 0, 0x0,
1577               "Negative Acknowledgement Sequence Number", HFILL
1578             }
1579         },
1580         { &hf_rlc_nr_am_so_start,
1581             { "SO start",
1582               "rlc-nr.am.so-start", FT_UINT16, BASE_DEC, 0, 0x0,
1583               "Segment Offset Start byte index", HFILL
1584             }
1585         },
1586         { &hf_rlc_nr_am_so_end,
1587             { "SO end",
1588               "rlc-nr.am.so-end", FT_UINT16, BASE_DEC, 0, 0x0,
1589               "Segment Offset End byte index", HFILL
1590             }
1591         },
1592         { &hf_rlc_nr_am_nack_range,
1593             { "NACK range",
1594               "rlc-nr.am.nack-range", FT_UINT16, BASE_DEC, 0, 0x0,
1595               "Number of consecutively lost RLC SDUs starting from and including NACK_SN", HFILL
1596             }
1597         },
1598 
1599         { &hf_rlc_nr_header_only,
1600             { "RLC PDU Header only",
1601               "rlc-nr.header-only", FT_BOOLEAN, BASE_NONE, TFS(&header_only_vals), 0x0,
1602               NULL, HFILL
1603             }
1604         },
1605 
1606         { &hf_rlc_nr_fragment,
1607           { "RLC-NR fragment",
1608             "rlc-nr.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1609             NULL, HFILL }
1610         },
1611         { &hf_rlc_nr_fragments,
1612           { "RLC-NR fragments",
1613             "rlc-nr.fragments", FT_BYTES, BASE_NONE, NULL, 0x0,
1614             NULL, HFILL }
1615         },
1616         { &hf_rlc_nr_fragment_overlap,
1617           { "Fragment overlap",
1618             "rlc-nr.fragment.overlap", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1619             "Fragment overlaps with other fragments", HFILL }
1620         },
1621         { &hf_rlc_nr_fragment_overlap_conflict,
1622           { "Conflicting data in fragment overlap",
1623             "rlc-nr.fragment.overlap.conflict",
1624             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1625             "Overlapping fragments contained conflicting data", HFILL }
1626         },
1627         { &hf_rlc_nr_fragment_multiple_tails,
1628           { "Multiple tail fragments found",
1629             "rlc-nr.fragment.multipletails",
1630             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1631             "Several tails were found when defragmenting the packet", HFILL }
1632         },
1633         { &hf_rlc_nr_fragment_too_long_fragment,
1634           { "Fragment too long",
1635             "rlc-nr.fragment.toolongfragment",
1636             FT_BOOLEAN, BASE_NONE, NULL, 0x0,
1637             "Fragment contained data past end of packet", HFILL }
1638         },
1639         { &hf_rlc_nr_fragment_error,
1640           { "Defragmentation error",
1641             "rlc-nr.fragment.error",
1642             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1643             "Defragmentation error due to illegal fragments", HFILL }
1644         },
1645         { &hf_rlc_nr_fragment_count,
1646           { "Fragment count",
1647             "rlc-nr.fragment.count",
1648             FT_UINT32, BASE_DEC, NULL, 0x0,
1649             NULL, HFILL }
1650         },
1651         { &hf_rlc_nr_reassembled_in,
1652           { "Reassembled RLC-NR in frame",
1653             "rlc-nr.reassembled_in",
1654             FT_FRAMENUM, BASE_NONE, NULL, 0x0,
1655             "This RLC-NR packet is reassembled in this frame", HFILL }
1656         },
1657         { &hf_rlc_nr_reassembled_length,
1658           { "Reassembled RLC-NR length",
1659             "rlc-nr.reassembled.length",
1660             FT_UINT32, BASE_DEC, NULL, 0x0,
1661             "The total length of the reassembled payload", HFILL }
1662         },
1663         { &hf_rlc_nr_reassembled_data,
1664           { "Reassembled payload",
1665             "rlc-nr.reassembled.data",
1666             FT_BYTES, BASE_NONE, NULL, 0x0,
1667             "The reassembled payload", HFILL }
1668         },
1669 
1670     };
1671 
1672     static gint *ett[] =
1673     {
1674         &ett_rlc_nr,
1675         &ett_rlc_nr_context,
1676         &ett_rlc_nr_um_header,
1677         &ett_rlc_nr_am_header,
1678         &ett_rlc_nr_fragment,
1679         &ett_rlc_nr_fragments
1680     };
1681 
1682     static ei_register_info ei[] = {
1683         { &ei_rlc_nr_reserved_bits_not_zero, { "rlc-nr.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
1684         { &ei_rlc_nr_um_sn, { "rlc-nr.um.sn.invalid", PI_MALFORMED, PI_ERROR, "Invalid sequence number length", EXPFILL }},
1685         { &ei_rlc_nr_am_sn, { "rlc-nr.am.sn.invalid", PI_MALFORMED, PI_ERROR, "Invalid sequence number length", EXPFILL }},
1686         { &ei_rlc_nr_header_only, { "rlc-nr.header-only.expert", PI_SEQUENCE, PI_NOTE, "RLC PDU SDUs have been omitted", EXPFILL }},
1687         { &ei_rlc_nr_am_cpt, { "rlc-nr.am.cpt.invalid", PI_MALFORMED, PI_ERROR, "RLC Control frame type not handled", EXPFILL }},
1688         { &ei_rlc_nr_am_nack_sn_ack_same, { "rlc-nr.am.nack-sn.ack-same", PI_MALFORMED, PI_ERROR, "Status PDU shouldn't ACK and NACK the same sequence number", EXPFILL }},
1689         { &ei_rlc_nr_am_nack_range, { "rlc-nr.am.nack-sn.nack-range", PI_MALFORMED, PI_ERROR, "Status PDU should not contain a NACK range with value 0", EXPFILL }},
1690         { &ei_rlc_nr_am_nack_sn_ahead_ack, { "rlc-nr.am.nack-sn.ahead-ack", PI_MALFORMED, PI_ERROR, "NACK must not be ahead of ACK in status PDU", EXPFILL }},
1691         { &ei_rlc_nr_am_nack_sn_partial, { "rlc-nr.am.nack-sn.partial", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK (partial)", EXPFILL }},
1692         { &ei_rlc_nr_am_nack_sn, { "rlc-nr.am.nack-sn.expert", PI_SEQUENCE, PI_WARN, "Status PDU reports NACK", EXPFILL }},
1693         { &ei_rlc_nr_bytes_after_status_pdu_complete, { "rlc-nr.bytes-after-status-pdu-complete", PI_MALFORMED, PI_ERROR, "bytes remaining after Status PDU complete", EXPFILL }},
1694         { &ei_rlc_nr_um_data_no_data, { "rlc-nr.um-data.no-data", PI_MALFORMED, PI_ERROR, "UM data PDU doesn't contain any data", EXPFILL }},
1695         { &ei_rlc_nr_am_data_no_data, { "rlc-nr.am-data.no-data", PI_MALFORMED, PI_ERROR, "AM data PDU doesn't contain any data", EXPFILL }},
1696         { &ei_rlc_nr_context_mode, { "rlc-nr.mode.invalid", PI_MALFORMED, PI_ERROR, "Unrecognised RLC Mode set", EXPFILL }},
1697         { &ei_rlc_nr_no_per_frame_info, { "rlc-nr.no-per-frame-info", PI_UNDECODED, PI_ERROR, "Can't dissect NR RLC frame because no per-frame info was attached!", EXPFILL }},
1698         { &ei_rlc_nr_unknown_udp_framing_tag, { "rlc-nr.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }}
1699     };
1700 
1701     module_t *rlc_nr_module;
1702     expert_module_t* expert_rlc_nr;
1703 
1704     /* Register protocol. */
1705     proto_rlc_nr = proto_register_protocol("RLC-NR", "RLC-NR", "rlc-nr");
1706     proto_register_field_array(proto_rlc_nr, hf, array_length(hf));
1707     proto_register_subtree_array(ett, array_length(ett));
1708     expert_rlc_nr = expert_register_protocol(proto_rlc_nr);
1709     expert_register_field_array(expert_rlc_nr, ei, array_length(ei));
1710 
1711     /* Allow other dissectors to find this one by name. */
1712     register_dissector("rlc-nr", dissect_rlc_nr, proto_rlc_nr);
1713 
1714     /* Preferences */
1715     rlc_nr_module = prefs_register_protocol(proto_rlc_nr, NULL);
1716 
1717     prefs_register_bool_preference(rlc_nr_module, "call_pdcp_for_srb",
1718         "Call PDCP dissector for SRB PDUs",
1719         "Call PDCP dissector for signalling PDUs.  Note that without reassembly, it can"
1720         "only be called for complete PDUs (i.e. not segmented over RLC)",
1721         &global_rlc_nr_call_pdcp_for_srb);
1722 
1723     prefs_register_enum_preference(rlc_nr_module, "call_pdcp_for_ul_drb",
1724         "Call PDCP dissector for UL DRB PDUs",
1725         "Call PDCP dissector for UL user-plane PDUs.  Note that without reassembly, it can"
1726         "only be called for complete PDUs (i.e. not segmented over RLC)",
1727         &global_rlc_nr_call_pdcp_for_ul_drb, pdcp_drb_col_vals, FALSE);
1728 
1729     prefs_register_enum_preference(rlc_nr_module, "call_pdcp_for_dl_drb",
1730         "Call PDCP dissector for DL DRB PDUs",
1731         "Call PDCP dissector for DL user-plane PDUs.  Note that without reassembly, it can"
1732         "only be called for complete PDUs (i.e. not segmented over RLC)",
1733         &global_rlc_nr_call_pdcp_for_dl_drb, pdcp_drb_col_vals, FALSE);
1734 
1735     prefs_register_bool_preference(rlc_nr_module, "call_rrc_for_ccch",
1736         "Call RRC dissector for CCCH PDUs",
1737         "Call RRC dissector for CCCH PDUs",
1738         &global_rlc_nr_call_rrc_for_ccch);
1739 
1740     prefs_register_bool_preference(rlc_nr_module, "header_only_mode",
1741         "May see RLC headers only",
1742         "When enabled, if data is not present, don't report as an error, but instead "
1743         "add expert info to indicate that headers were omitted",
1744         &global_rlc_nr_headers_expected);
1745 
1746     prefs_register_bool_preference(rlc_nr_module, "reassemble_am_frames",
1747         "Try to reassemble AM frames",
1748         "N.B. This should be considered experimental/incomplete, in that it doesn't try to discard reassembled state "
1749         "when reestablishment happens, or in certain packet-loss cases",
1750         &global_rlc_nr_reassemble_am_pdus);
1751 
1752     prefs_register_bool_preference(rlc_nr_module, "reassemble_um_frames",
1753         "Try to reassemble UM frames",
1754         "N.B. This should be considered experimental/incomplete, in that it doesn't try to discard reassembled state "
1755         "when reestablishment happens, or in certain packet-loss cases",
1756         &global_rlc_nr_reassemble_um_pdus);
1757 
1758     ue_parameters_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
1759 
1760     /* Register reassembly table. */
1761     reassembly_table_register(&pdu_reassembly_table, &pdu_reassembly_table_functions);
1762 }
1763 
proto_reg_handoff_rlc_nr(void)1764 void proto_reg_handoff_rlc_nr(void)
1765 {
1766     /* Add as a heuristic UDP dissector */
1767     heur_dissector_add("udp", dissect_rlc_nr_heur, "RLC-NR over UDP", "rlc_nr_udp", proto_rlc_nr, HEURISTIC_DISABLE);
1768 
1769     pdcp_nr_handle = find_dissector("pdcp-nr");
1770     nr_rrc_bcch_bch = find_dissector_add_dependency("nr-rrc.bcch.bch", proto_rlc_nr);
1771     nr_rrc_bcch_dl_sch = find_dissector_add_dependency("nr-rrc.bcch.dl.sch", proto_rlc_nr);
1772     nr_rrc_pcch = find_dissector_add_dependency("nr-rrc.pcch", proto_pdcp_nr);
1773     nr_rrc_ul_ccch = find_dissector_add_dependency("nr-rrc.ul.ccch", proto_rlc_nr);
1774     nr_rrc_ul_ccch1 = find_dissector_add_dependency("nr-rrc.ul.ccch1", proto_rlc_nr);
1775     nr_rrc_dl_ccch = find_dissector_add_dependency("nr-rrc.dl.ccch", proto_rlc_nr);
1776 }
1777 
1778 /*
1779  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1780  *
1781  * Local variables:
1782  * c-basic-offset: 4
1783  * tab-width: 8
1784  * indent-tabs-mode: nil
1785  * End:
1786  *
1787  * vi: set shiftwidth=4 tabstop=8 expandtab:
1788  * :indentSize=4:tabSize=8:noTabs=true:
1789  */
1790