diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:53 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-09-19 04:14:53 +0000 |
commit | a86c5f7cae7ec9a3398300555a0b644689d946a1 (patch) | |
tree | 39fe4b107c71174fd1e8a8ceb9a4d2aa14116248 /epan/dissectors/packet-rlc-nr.c | |
parent | Releasing progress-linux version 4.2.6-1~progress7.99u1. (diff) | |
download | wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.tar.xz wireshark-a86c5f7cae7ec9a3398300555a0b644689d946a1.zip |
Merging upstream version 4.4.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dissectors/packet-rlc-nr.c')
-rw-r--r-- | epan/dissectors/packet-rlc-nr.c | 429 |
1 files changed, 244 insertions, 185 deletions
diff --git a/epan/dissectors/packet-rlc-nr.c b/epan/dissectors/packet-rlc-nr.c index 89ddc9fd..55c3e83a 100644 --- a/epan/dissectors/packet-rlc-nr.c +++ b/epan/dissectors/packet-rlc-nr.c @@ -15,10 +15,12 @@ #include <epan/exceptions.h> #include <epan/expert.h> #include <epan/prefs.h> +#include <epan/tap.h> #include <epan/proto_data.h> #include <epan/reassemble.h> #include "packet-rlc-nr.h" +#include "packet-rlc-3gpp-common.h" #include "packet-pdcp-nr.h" @@ -39,7 +41,7 @@ void proto_reg_handoff_rlc_nr(void); /* Preference settings */ /* By default do call PDCP/RRC dissectors for SDU data */ -static gboolean global_rlc_nr_call_pdcp_for_srb = TRUE; +static bool global_rlc_nr_call_pdcp_for_srb = true; enum pdcp_for_drb { PDCP_drb_off, PDCP_drb_SN_12, PDCP_drb_SN_18, PDCP_drb_SN_signalled}; static const enum_val_t pdcp_drb_col_vals[] = { @@ -50,18 +52,18 @@ static const enum_val_t pdcp_drb_col_vals[] = { {NULL, NULL, -1} }; /* Separate config for UL/DL */ -static gint global_rlc_nr_call_pdcp_for_ul_drb = (gint)PDCP_drb_off; -static gint global_rlc_nr_call_pdcp_for_dl_drb = (gint)PDCP_drb_off; +static int global_rlc_nr_call_pdcp_for_ul_drb = (int)PDCP_drb_off; +static int global_rlc_nr_call_pdcp_for_dl_drb = (int)PDCP_drb_off; -static gboolean global_rlc_nr_call_rrc_for_ccch = TRUE; +static bool global_rlc_nr_call_rrc_for_ccch = true; /* Preference to expect RLC headers without payloads */ -static gboolean global_rlc_nr_headers_expected = FALSE; +static bool global_rlc_nr_headers_expected; /* Attempt reassembly. */ -static gboolean global_rlc_nr_reassemble_um_pdus = FALSE; -static gboolean global_rlc_nr_reassemble_am_pdus = TRUE; +static bool global_rlc_nr_reassemble_um_pdus; +static bool global_rlc_nr_reassemble_am_pdus = true; /* Tree storing UE related parameters (ueid, drbid) -> pdcp_bearer_parameters */ static wmem_tree_t *ue_parameters_tree; @@ -76,8 +78,9 @@ static wmem_tree_t *reassembly_start_table_stored; /**************************************************/ /* Initialize the protocol and registered fields. */ -int proto_rlc_nr = -1; +int proto_rlc_nr; +extern int proto_mac_nr; extern int proto_pdcp_nr; static dissector_handle_t pdcp_nr_handle; @@ -89,77 +92,79 @@ static dissector_handle_t nr_rrc_ul_ccch1; static dissector_handle_t nr_rrc_dl_ccch; +static int rlc_nr_tap = -1; + /* Decoding context */ -static int hf_rlc_nr_context = -1; -static int hf_rlc_nr_context_mode = -1; -static int hf_rlc_nr_context_direction = -1; -static int hf_rlc_nr_context_ueid = -1; -static int hf_rlc_nr_context_bearer_type = -1; -static int hf_rlc_nr_context_bearer_id = -1; -static int hf_rlc_nr_context_pdu_length = -1; -static int hf_rlc_nr_context_sn_length = -1; +static int hf_rlc_nr_context; +static int hf_rlc_nr_context_mode; +static int hf_rlc_nr_context_direction; +static int hf_rlc_nr_context_ueid; +static int hf_rlc_nr_context_bearer_type; +static int hf_rlc_nr_context_bearer_id; +static int hf_rlc_nr_context_pdu_length; +static int hf_rlc_nr_context_sn_length; /* Transparent mode fields */ -static int hf_rlc_nr_tm = -1; -static int hf_rlc_nr_tm_data = -1; +static int hf_rlc_nr_tm; +static int hf_rlc_nr_tm_data; /* Unacknowledged mode fields */ -static int hf_rlc_nr_um = -1; -static int hf_rlc_nr_um_header = -1; -static int hf_rlc_nr_um_si = -1; -static int hf_rlc_nr_um_reserved = -1; -static int hf_rlc_nr_um_sn6 = -1; -static int hf_rlc_nr_um_sn12 = -1; -static int hf_rlc_nr_um_so = -1; -static int hf_rlc_nr_um_data = -1; +static int hf_rlc_nr_um; +static int hf_rlc_nr_um_header; +static int hf_rlc_nr_um_si; +static int hf_rlc_nr_um_reserved; +static int hf_rlc_nr_um_sn6; +static int hf_rlc_nr_um_sn12; +static int hf_rlc_nr_um_so; +static int hf_rlc_nr_um_data; /* Acknowledged mode fields */ -static int hf_rlc_nr_am = -1; -static int hf_rlc_nr_am_header = -1; -static int hf_rlc_nr_am_data_control = -1; -static int hf_rlc_nr_am_p = -1; -static int hf_rlc_nr_am_si = -1; -static int hf_rlc_nr_am_sn12 = -1; -static int hf_rlc_nr_am_sn18 = -1; -static int hf_rlc_nr_am_reserved = -1; -static int hf_rlc_nr_am_so = -1; -static int hf_rlc_nr_am_data = -1; +static int hf_rlc_nr_am; +static int hf_rlc_nr_am_header; +static int hf_rlc_nr_am_data_control; +static int hf_rlc_nr_am_p; +static int hf_rlc_nr_am_si; +static int hf_rlc_nr_am_sn12; +static int hf_rlc_nr_am_sn18; +static int hf_rlc_nr_am_reserved; +static int hf_rlc_nr_am_so; +static int hf_rlc_nr_am_data; /* Control fields */ -static int hf_rlc_nr_am_cpt = -1; -static int hf_rlc_nr_am_ack_sn = -1; -static int hf_rlc_nr_am_e1 = -1; -static int hf_rlc_nr_am_e2 = -1; -static int hf_rlc_nr_am_e3 = -1; -static int hf_rlc_nr_am_nack_sn = -1; -static int hf_rlc_nr_am_so_start = -1; -static int hf_rlc_nr_am_so_end = -1; -static int hf_rlc_nr_am_nack_range = -1; -static int hf_rlc_nr_am_nacks = -1; - -static int hf_rlc_nr_header_only = -1; - -static int hf_rlc_nr_fragments = -1; -static int hf_rlc_nr_fragment = -1; -static int hf_rlc_nr_fragment_overlap = -1; -static int hf_rlc_nr_fragment_overlap_conflict = -1; -static int hf_rlc_nr_fragment_multiple_tails = -1; -static int hf_rlc_nr_fragment_too_long_fragment = -1; -static int hf_rlc_nr_fragment_error = -1; -static int hf_rlc_nr_fragment_count = -1; -static int hf_rlc_nr_reassembled_in = -1; -static int hf_rlc_nr_reassembled_length = -1; -static int hf_rlc_nr_reassembled_data = -1; +static int hf_rlc_nr_am_cpt; +static int hf_rlc_nr_am_ack_sn; +static int hf_rlc_nr_am_e1; +static int hf_rlc_nr_am_e2; +static int hf_rlc_nr_am_e3; +static int hf_rlc_nr_am_nack_sn; +static int hf_rlc_nr_am_so_start; +static int hf_rlc_nr_am_so_end; +static int hf_rlc_nr_am_nack_range; +static int hf_rlc_nr_am_nacks; + +static int hf_rlc_nr_header_only; + +static int hf_rlc_nr_fragments; +static int hf_rlc_nr_fragment; +static int hf_rlc_nr_fragment_overlap; +static int hf_rlc_nr_fragment_overlap_conflict; +static int hf_rlc_nr_fragment_multiple_tails; +static int hf_rlc_nr_fragment_too_long_fragment; +static int hf_rlc_nr_fragment_error; +static int hf_rlc_nr_fragment_count; +static int hf_rlc_nr_reassembled_in; +static int hf_rlc_nr_reassembled_length; +static int hf_rlc_nr_reassembled_data; /* Subtrees. */ -static int ett_rlc_nr = -1; -static int ett_rlc_nr_context = -1; -static int ett_rlc_nr_um_header = -1; -static int ett_rlc_nr_am_header = -1; -static int ett_rlc_nr_fragments = -1; -static int ett_rlc_nr_fragment = -1; +static int ett_rlc_nr; +static int ett_rlc_nr_context; +static int ett_rlc_nr_um_header; +static int ett_rlc_nr_am_header; +static int ett_rlc_nr_fragments; +static int ett_rlc_nr_fragment; static const fragment_items rlc_nr_frag_items = { @@ -180,22 +185,22 @@ static const fragment_items rlc_nr_frag_items = { }; -static expert_field ei_rlc_nr_context_mode = EI_INIT; -static expert_field ei_rlc_nr_am_nack_sn = EI_INIT; -static expert_field ei_rlc_nr_am_nack_sn_ahead_ack = EI_INIT; -static expert_field ei_rlc_nr_am_nack_sn_ack_same = EI_INIT; -static expert_field ei_rlc_nr_am_nack_range = EI_INIT; -static expert_field ei_rlc_nr_am_cpt = EI_INIT; -static expert_field ei_rlc_nr_um_data_no_data = EI_INIT; -static expert_field ei_rlc_nr_am_data_no_data = EI_INIT; -static expert_field ei_rlc_nr_am_nack_sn_partial = EI_INIT; -static expert_field ei_rlc_nr_bytes_after_status_pdu_complete = EI_INIT; -static expert_field ei_rlc_nr_um_sn = EI_INIT; -static expert_field ei_rlc_nr_am_sn = EI_INIT; -static expert_field ei_rlc_nr_header_only = EI_INIT; -static expert_field ei_rlc_nr_reserved_bits_not_zero = EI_INIT; -static expert_field ei_rlc_nr_no_per_frame_info = EI_INIT; -static expert_field ei_rlc_nr_unknown_udp_framing_tag = EI_INIT; +static expert_field ei_rlc_nr_context_mode; +static expert_field ei_rlc_nr_am_nack_sn; +static expert_field ei_rlc_nr_am_nack_sn_ahead_ack; +static expert_field ei_rlc_nr_am_nack_sn_ack_same; +static expert_field ei_rlc_nr_am_nack_range; +static expert_field ei_rlc_nr_am_cpt; +static expert_field ei_rlc_nr_um_data_no_data; +static expert_field ei_rlc_nr_am_data_no_data; +static expert_field ei_rlc_nr_am_nack_sn_partial; +static expert_field ei_rlc_nr_bytes_after_status_pdu_complete; +static expert_field ei_rlc_nr_um_sn; +static expert_field ei_rlc_nr_am_sn; +static expert_field ei_rlc_nr_header_only; +static expert_field ei_rlc_nr_reserved_bits_not_zero; +static expert_field ei_rlc_nr_no_per_frame_info; +static expert_field ei_rlc_nr_unknown_udp_framing_tag; /* Value-strings */ static const value_string direction_vals[] = @@ -241,12 +246,6 @@ static const value_string seg_info_vals[] = { 0, NULL } }; -static const true_false_string data_or_control_vals = -{ - "Data PDU", - "Control PDU" -}; - static const true_false_string polling_bit_vals = { "Status report is requested", @@ -286,32 +285,32 @@ static const true_false_string header_only_vals = /* Reassembly state */ static reassembly_table pdu_reassembly_table; -static guint pdu_hash(gconstpointer k) +static unsigned pdu_hash(const void *k) { return GPOINTER_TO_UINT(k); } -static gint pdu_equal(gconstpointer k1, gconstpointer k2) +static int pdu_equal(const void *k1, const void *k2) { return k1 == k2; } -static gpointer pdu_temporary_key(const packet_info *pinfo _U_, const guint32 id _U_, const void *data) +static void *pdu_temporary_key(const packet_info *pinfo _U_, const uint32_t id _U_, const void *data) { - return (gpointer)data; + return (void *)data; } -static gpointer pdu_persistent_key(const packet_info *pinfo _U_, const guint32 id _U_, +static void *pdu_persistent_key(const packet_info *pinfo _U_, const uint32_t id _U_, const void *data) { - return (gpointer)data; + return (void *)data; } -static void pdu_free_temporary_key(gpointer ptr _U_) +static void pdu_free_temporary_key(void *ptr _U_) { } -static void pdu_free_persistent_key(gpointer ptr _U_) +static void pdu_free_persistent_key(void *ptr _U_) { } @@ -328,7 +327,7 @@ static reassembly_table_functions pdu_reassembly_table_functions = /********************************************************/ /* Forward declarations & functions */ -static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing); +static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool is_udp_framing); /* Write the given formatted text to: @@ -375,7 +374,7 @@ static void write_pdu_label_and_info_literal(proto_item *pdu_ti, proto_item *sub /* Show in the info column how many bytes are in the UM/AM PDU, and indicate whether or not the beginning and end are included in this packet */ static void show_PDU_in_info(packet_info *pinfo, proto_item *top_ti, - gint32 length, guint8 seg_info) + int32_t length, uint8_t seg_info) { /* Reflect this PDU in the info column */ if (length > 0) { @@ -395,11 +394,11 @@ static void show_PDU_in_info(packet_info *pinfo, proto_item *top_ti, /* Show an SDU. If configured, pass to PDCP/RRC dissector */ -static void 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) +static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset, int length, + rlc_nr_info *rlc_info, uint32_t seg_info, bool is_reassembled) { wmem_tree_key_t key[2]; - guint32 id; + uint32_t id; pdcp_bearer_parameters *params; /* Add raw data (according to mode) */ @@ -432,7 +431,7 @@ static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb p_pdcp_nr_info->direction = rlc_info->direction; p_pdcp_nr_info->ueid = rlc_info->ueid; - gint seqnum_len; + int seqnum_len; switch (rlc_info->bearerType) { case BEARER_TYPE_SRB: @@ -495,8 +494,8 @@ static void show_PDU_in_tree(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb } p_pdcp_nr_info->bearerId = rlc_info->bearerId; - p_pdcp_nr_info->rohc.rohc_compression = FALSE; - p_pdcp_nr_info->is_retx = FALSE; + p_pdcp_nr_info->rohc.rohc_compression = false; + p_pdcp_nr_info->is_retx = false; p_pdcp_nr_info->pdu_length = length; TRY { @@ -576,21 +575,21 @@ static void dissect_rlc_nr_tm(tvbuff_t *tvb, packet_info *pinfo, /* Look up / set the frame thought to be the start segment of this RLC PDU. */ /* N.B. this algorithm will not be correct in all cases, but is good enough to be useful.. */ -static guint32 get_reassembly_start_frame(packet_info *pinfo, guint32 seg_info, - rlc_nr_info *p_rlc_nr_info, guint32 sn) +static uint32_t get_reassembly_start_frame(packet_info *pinfo, uint32_t seg_info, + rlc_nr_info *p_rlc_nr_info, uint32_t sn) { - guint32 frame_id = 0; + uint32_t frame_id = 0; - guint32 key_values[] = { p_rlc_nr_info->ueid, + uint32_t key_values[] = { p_rlc_nr_info->ueid, p_rlc_nr_info->direction, p_rlc_nr_info->bearerType, p_rlc_nr_info->bearerId, sn, - pinfo->num /* N.B. only used for subsquent/_stored table */ + pinfo->num }; /* Is this the first segment of SN? */ - gboolean first_segment = (seg_info & 0x2) == 0; + bool first_segment = (seg_info & 0x2) == 0; /* Set Key. */ wmem_tree_key_t key[2]; @@ -599,13 +598,13 @@ static guint32 get_reassembly_start_frame(packet_info *pinfo, guint32 seg_info, key[1].length = 0; key[1].key = NULL; - guint32 *p_frame_id = NULL; + uint32_t *p_frame_id = NULL; if (!PINFO_FD_VISITED(pinfo)) { /* On first pass, maintain reassembly_start_table. */ /* Look for existing entry. */ - p_frame_id = (guint32*)wmem_tree_lookup32_array(reassembly_start_table, key); + p_frame_id = (uint32_t*)wmem_tree_lookup32_array(reassembly_start_table, key); if (first_segment) { @@ -629,7 +628,7 @@ static guint32 get_reassembly_start_frame(packet_info *pinfo, guint32 seg_info, else { /* For subsequent passes, use stored value */ key[0].length = 6; /* i.e. include this framenum in key */ - p_frame_id = (guint32*)wmem_tree_lookup32_array(reassembly_start_table_stored, key); + p_frame_id = (uint32_t*)wmem_tree_lookup32_array(reassembly_start_table_stored, key); if (p_frame_id) { /* Use found value */ frame_id = GPOINTER_TO_UINT(p_frame_id); @@ -641,10 +640,10 @@ static guint32 get_reassembly_start_frame(packet_info *pinfo, guint32 seg_info, /* On first pass - if this SN is complete, don't try to add any more fragments to it */ static void reassembly_frame_complete(packet_info *pinfo, - rlc_nr_info *p_rlc_nr_info, guint32 sn) + rlc_nr_info *p_rlc_nr_info, uint32_t sn) { if (!PINFO_FD_VISITED(pinfo)) { - guint32 key_values[] = { p_rlc_nr_info->ueid, + uint32_t key_values[] = { p_rlc_nr_info->ueid, p_rlc_nr_info->direction, p_rlc_nr_info->bearerType, p_rlc_nr_info->bearerId, @@ -668,17 +667,18 @@ static void reassembly_frame_complete(packet_info *pinfo, /* Unacknowledged mode PDU */ static void 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) + rlc_nr_info *p_rlc_nr_info, proto_item *top_ti, + rlc_3gpp_tap_info *tap_info) { - guint32 seg_info, sn; - guint64 reserved; + uint32_t seg_info, sn; + uint64_t reserved; proto_item *um_ti; proto_tree *um_header_tree; proto_item *um_header_ti; proto_item *truncated_ti; proto_item *reserved_ti; int start_offset = offset; - guint32 so = 0; + uint32_t so = 0; /* Hidden UM root */ um_ti = proto_tree_add_string_format(tree, hf_rlc_nr_um, @@ -706,16 +706,20 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, } else { /* Add sequence number */ if (p_rlc_nr_info->sequenceNumberLength == UM_SN_LENGTH_6_BITS) { + /* SN */ proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_sn6, tvb, offset, 1, ENC_BIG_ENDIAN, &sn); offset++; + tap_info->sequenceNumberGiven = true; } else if (p_rlc_nr_info->sequenceNumberLength == UM_SN_LENGTH_12_BITS) { reserved_ti = proto_tree_add_bits_ret_val(um_header_tree, hf_rlc_nr_um_reserved, tvb, (offset<<3)+2, 2, &reserved, ENC_BIG_ENDIAN); if (reserved) { expert_add_info(pinfo, reserved_ti, &ei_rlc_nr_reserved_bits_not_zero); } + /* SN */ proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_sn12, tvb, offset, 2, ENC_BIG_ENDIAN, &sn); offset += 2; + tap_info->sequenceNumberGiven = true; } else { /* Invalid length of sequence number */ proto_tree_add_expert_format(um_header_tree, pinfo, &ei_rlc_nr_um_sn, tvb, 0, 0, @@ -723,6 +727,9 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, p_rlc_nr_info->sequenceNumberLength); return; } + + tap_info->sequenceNumber = sn; + if (seg_info >= 2) { /* Segment offset */ proto_tree_add_item_ret_uint(um_header_tree, hf_rlc_nr_um_so, tvb, offset, 2, ENC_BIG_ENDIAN, &so); @@ -738,7 +745,7 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, if (global_rlc_nr_headers_expected) { /* There might not be any data, if only headers (plus control data) were logged */ - gboolean is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0); + bool is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0); truncated_ti = proto_tree_add_boolean(tree, hf_rlc_nr_header_only, tvb, 0, 0, is_truncated); if (is_truncated) { @@ -757,11 +764,11 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, tvbuff_t *next_tvb = NULL; if (global_rlc_nr_reassemble_um_pdus && seg_info && tvb_reported_length_remaining(tvb, offset) > 0) { /* Set fragmented flag. */ - gboolean save_fragmented = pinfo->fragmented; - pinfo->fragmented = TRUE; + bool save_fragmented = pinfo->fragmented; + pinfo->fragmented = true; fragment_head *fh; - gboolean more_frags = seg_info & 0x01; - guint32 id = get_reassembly_start_frame(pinfo, seg_info, p_rlc_nr_info, sn); /* Leave 19 bits for SN - overlaps with other fields but room to overflow into msb */ + bool more_frags = seg_info & 0x01; + uint32_t id = get_reassembly_start_frame(pinfo, seg_info, p_rlc_nr_info, sn); /* Leave 19 bits for SN - overlaps with other fields but room to overflow into msb */ if (id != 0) { fh = fragment_add(&pdu_reassembly_table, tvb, offset, pinfo, id, /* id */ @@ -771,7 +778,7 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, more_frags /* more_frags */ ); - gboolean update_col_info = TRUE; + bool update_col_info = true; next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled RLC SDU", fh, &rlc_nr_frag_items, &update_col_info, tree); @@ -781,14 +788,14 @@ static void dissect_rlc_nr_um(tvbuff_t *tvb, packet_info *pinfo, if (tvb_reported_length_remaining(tvb, offset) > 0) { show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), - p_rlc_nr_info, seg_info, FALSE); + p_rlc_nr_info, seg_info, false); show_PDU_in_info(pinfo, top_ti, tvb_reported_length_remaining(tvb, offset), seg_info); /* Also add any reassembled PDU */ if (next_tvb) { add_new_data_source(pinfo, next_tvb, "Reassembled RLC-NR PDU"); show_PDU_in_tree(pinfo, tree, next_tvb, 0, tvb_captured_length(next_tvb), - p_rlc_nr_info, seg_info, TRUE); + p_rlc_nr_info, seg_info, true); /* Note that PDU is now completed (so won't try to add to it) */ reassembly_frame_complete(pinfo, p_rlc_nr_info, sn); @@ -808,13 +815,14 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, proto_item *status_ti, int offset, proto_item *top_ti, - rlc_nr_info *p_rlc_nr_info) + rlc_nr_info *p_rlc_nr_info, + rlc_3gpp_tap_info *tap_info) { - guint8 sn_size, reserved_bits1, reserved_bits2; - guint32 cpt, sn_limit, nack_count = 0; - guint64 ack_sn, nack_sn; - guint64 e1, e2, e3, reserved; - guint32 so_start, so_end, nack_range; + uint8_t sn_size, reserved_bits1, reserved_bits2; + uint32_t cpt, sn_limit, nack_count = 0; + uint64_t ack_sn, nack_sn; + uint64_t e1, e2, e3, reserved; + uint32_t so_start, so_end, nack_range; int bit_offset = offset << 3; proto_item *ti; @@ -854,7 +862,8 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_ack_sn, tvb, bit_offset, sn_size, &ack_sn, ENC_BIG_ENDIAN); bit_offset += sn_size; - write_pdu_label_and_info(top_ti, status_ti, pinfo, " ACK_SN=%-6u", (guint32)ack_sn); + write_pdu_label_and_info(top_ti, status_ti, pinfo, " ACK_SN=%-6u", (uint32_t)ack_sn); + tap_info->ACKNo = (uint32_t)ack_sn; /* E1 */ proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e1, tvb, @@ -880,7 +889,7 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, nack_ti = proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_nack_sn, tvb, bit_offset, sn_size, &nack_sn, ENC_BIG_ENDIAN); bit_offset += sn_size; - write_pdu_label_and_info(top_ti, NULL, pinfo, " NACK_SN=%-6u", (guint32)nack_sn); + write_pdu_label_and_info(top_ti, NULL, pinfo, " NACK_SN=%-6u", (uint32_t)nack_sn); /* We shouldn't NACK the ACK_SN! */ if (nack_sn == ack_sn) { @@ -894,7 +903,15 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, expert_add_info(pinfo, nack_ti, &ei_rlc_nr_am_nack_sn_ahead_ack); } - nack_count++; + /* Copy single NACK into tap struct, but don't exceed buffer */ + if (nack_count < MAX_NACKs) { + tap_info->NACKs[nack_count++] = (uint32_t)nack_sn; + } + else { + /* Let it get bigger than the array for accurate stats... */ + nack_count++; + } + /* E1 */ proto_tree_add_bits_ret_val(tree, hf_rlc_nr_am_e1, tvb, @@ -938,6 +955,7 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, bit_offset>>3, 2, ENC_BIG_ENDIAN, &so_start); bit_offset += 16; + /* N.B., if E3 is set, this refers to a byte offset within the last PDU of the range.. */ proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_so_end, tvb, bit_offset>>3, 2, ENC_BIG_ENDIAN, &so_end); bit_offset += 16; @@ -955,20 +973,30 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, } if (e3) { + /* NACK range */ proto_item *nack_range_ti; - - /* Read NACK range */ nack_range_ti = proto_tree_add_item_ret_uint(tree, hf_rlc_nr_am_nack_range, tvb, bit_offset>>3, 1, ENC_BIG_ENDIAN, &nack_range); bit_offset += 8; if (nack_range == 0) { + /* It is the number of PDUs not received, so 0 does not make sense */ expert_add_info(pinfo, nack_range_ti, &ei_rlc_nr_am_nack_range); - } else { - nack_count += nack_range-1; + return; } - proto_item_append_text(nack_range_ti, " (SNs %" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT " missing)", nack_sn, nack_sn+nack_range-1); + proto_item_append_text(nack_range_ti, " (SNs %" PRIu64 "-%" PRIu64 " missing)", + nack_sn, nack_sn+nack_range-1); write_pdu_label_and_info(top_ti, NULL, pinfo," NACK range=%u", nack_range); + + /* Copy NACK SNs into tap_info */ + for (unsigned nack=0; nack < nack_range-1; nack++) { + if (nack_count+nack < MAX_NACKs) { + /* Guard against wrapping the SN range */ + tap_info->NACKs[nack_count+nack] = (uint32_t)((nack_sn+nack+1) % sn_limit); + } + } + /* Let it get bigger than the array for accurate stats. Take care not to double-count nack-sn itself. */ + nack_count += (nack_range-1); } } @@ -976,6 +1004,7 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, proto_item *count_ti = proto_tree_add_uint(tree, hf_rlc_nr_am_nacks, tvb, 0, 1, nack_count); proto_item_set_generated(count_ti); proto_item_append_text(status_ti, " (%u NACKs)", nack_count); + tap_info->noOfNACKs = nack_count; } /* Check that we've reached the end of the PDU. If not, show malformed */ @@ -996,18 +1025,19 @@ static void dissect_rlc_nr_am_status_pdu(tvbuff_t *tvb, /* Acknowledged mode PDU */ static void 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) + rlc_nr_info *p_rlc_nr_info, proto_item *top_ti, + rlc_3gpp_tap_info *tap_info _U_) { - gboolean dc, polling; - guint32 seg_info, sn; - guint64 reserved; + bool dc, polling; + uint32_t seg_info, sn; + uint64_t reserved; proto_item *am_ti; proto_tree *am_header_tree; proto_item *am_header_ti; - gint start_offset = offset; + int start_offset = offset; proto_item *truncated_ti; proto_item *reserved_ti; - guint32 so = 0; + uint32_t so = 0; /* Hidden AM root */ am_ti = proto_tree_add_string_format(tree, hf_rlc_nr_am, @@ -1024,6 +1054,7 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, /* First bit is Data/Control flag */ proto_tree_add_item_ret_boolean(am_header_tree, hf_rlc_nr_am_data_control, tvb, offset, 1, ENC_BIG_ENDIAN, &dc); + tap_info->isControlPDU = !dc; if (dc == 0) { /**********************/ @@ -1032,7 +1063,8 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, /* Control PDUs are a completely separate format */ dissect_rlc_nr_am_status_pdu(tvb, pinfo, am_header_tree, am_header_ti, - offset, top_ti, p_rlc_nr_info); + offset, top_ti, + p_rlc_nr_info, tap_info); return; } @@ -1075,6 +1107,9 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, return; } + tap_info->sequenceNumberGiven = true; + tap_info->sequenceNumber = sn; + /* Segment Offset */ if (seg_info >= 2) { proto_tree_add_item_ret_uint(am_header_tree, hf_rlc_nr_am_so, tvb, @@ -1090,7 +1125,7 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, /* There might not be any data, if only headers (plus control data) were logged */ if (global_rlc_nr_headers_expected) { - gboolean is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0); + bool is_truncated = (tvb_captured_length_remaining(tvb, offset) == 0); truncated_ti = proto_tree_add_boolean(tree, hf_rlc_nr_header_only, tvb, 0, 0, is_truncated); if (is_truncated) { @@ -1109,11 +1144,11 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, tvbuff_t *next_tvb = NULL; if (global_rlc_nr_reassemble_am_pdus && seg_info && tvb_reported_length_remaining(tvb, offset) > 0) { /* Set fragmented flag. */ - gboolean save_fragmented = pinfo->fragmented; - pinfo->fragmented = TRUE; + bool save_fragmented = pinfo->fragmented; + pinfo->fragmented = true; fragment_head *fh; - gboolean more_frags = seg_info & 0x01; - guint32 id = get_reassembly_start_frame(pinfo, seg_info, p_rlc_nr_info, sn); + bool more_frags = seg_info & 0x01; + uint32_t id = get_reassembly_start_frame(pinfo, seg_info, p_rlc_nr_info, sn); if (id != 0) { fh = fragment_add(&pdu_reassembly_table, tvb, offset, pinfo, id, /* id */ @@ -1123,7 +1158,7 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, more_frags /* more_frags */ ); - gboolean update_col_info = TRUE; + bool update_col_info = true; next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled RLC SDU", fh, &rlc_nr_frag_items, &update_col_info, tree); @@ -1134,14 +1169,14 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, if (tvb_reported_length_remaining(tvb, offset) > 0) { show_PDU_in_tree(pinfo, tree, tvb, offset, tvb_reported_length_remaining(tvb, offset), - p_rlc_nr_info, seg_info, FALSE); + p_rlc_nr_info, seg_info, false); show_PDU_in_info(pinfo, top_ti, tvb_reported_length_remaining(tvb, offset), seg_info); /* Also add any reassembled PDU */ if (next_tvb) { add_new_data_source(pinfo, next_tvb, "Reassembled RLC-NR PDU"); show_PDU_in_tree(pinfo, tree, next_tvb, 0, tvb_captured_length(next_tvb), - p_rlc_nr_info, seg_info, TRUE); + p_rlc_nr_info, seg_info, true); } } else if (!global_rlc_nr_headers_expected) { /* Report that expected data was missing (unless we know it might happen) */ @@ -1151,13 +1186,13 @@ static void dissect_rlc_nr_am(tvbuff_t *tvb, packet_info *pinfo, /* Heuristic dissector looks for supported framing protocol (see header file for details) */ -static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, +static bool dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - gint offset = 0; + int offset = 0; rlc_nr_info *p_rlc_nr_info; tvbuff_t *rlc_tvb; - guint8 tag; + uint8_t tag; /* Do this again on re-dissection to re-discover offset of actual PDU */ @@ -1166,15 +1201,15 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, - fixed header bytes - tag for data - at least one byte of RLC PDU payload */ - if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(RLC_NR_START_STRING)+2+2)) { - return FALSE; + if (tvb_captured_length_remaining(tvb, offset) < (int)(strlen(RLC_NR_START_STRING)+2+2)) { + return false; } /* OK, compare with signature string */ - if (tvb_strneql(tvb, offset, RLC_NR_START_STRING, (gint)strlen(RLC_NR_START_STRING)) != 0) { - return FALSE; + if (tvb_strneql(tvb, offset, RLC_NR_START_STRING, (int)strlen(RLC_NR_START_STRING)) != 0) { + return false; } - offset += (gint)strlen(RLC_NR_START_STRING); + offset += (int)strlen(RLC_NR_START_STRING); /* If redissecting, use previous info struct (if available) */ @@ -1184,16 +1219,16 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, p_rlc_nr_info = wmem_new0(wmem_file_scope(), struct rlc_nr_info); /* Read fixed fields */ - p_rlc_nr_info->rlcMode = tvb_get_guint8(tvb, offset++); - p_rlc_nr_info->sequenceNumberLength = tvb_get_guint8(tvb, offset++); + p_rlc_nr_info->rlcMode = tvb_get_uint8(tvb, offset++); + p_rlc_nr_info->sequenceNumberLength = tvb_get_uint8(tvb, offset++); /* Read optional fields */ do { /* Process next tag */ - tag = tvb_get_guint8(tvb, offset++); + tag = tvb_get_uint8(tvb, offset++); switch (tag) { case RLC_NR_DIRECTION_TAG: - p_rlc_nr_info->direction = tvb_get_guint8(tvb, offset); + p_rlc_nr_info->direction = tvb_get_uint8(tvb, offset); offset++; break; case RLC_NR_UEID_TAG: @@ -1201,11 +1236,11 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, offset += 2; break; case RLC_NR_BEARER_TYPE_TAG: - p_rlc_nr_info->bearerType = tvb_get_guint8(tvb, offset); + p_rlc_nr_info->bearerType = tvb_get_uint8(tvb, offset); offset++; break; case RLC_NR_BEARER_ID_TAG: - p_rlc_nr_info->bearerId = tvb_get_guint8(tvb, offset); + p_rlc_nr_info->bearerId = tvb_get_uint8(tvb, offset); offset++; break; case RLC_NR_PAYLOAD_TAG: @@ -1226,7 +1261,7 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, tvb, offset-1, 1); } wmem_free(wmem_file_scope(), p_rlc_nr_info); - return TRUE; + return true; } } while (tag != RLC_NR_PAYLOAD_TAG); @@ -1241,8 +1276,8 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, /* Create tvb that starts at actual RLC PDU */ rlc_tvb = tvb_new_subset_remaining(tvb, offset); - dissect_rlc_nr_common(rlc_tvb, pinfo, tree, TRUE /* udp framing */); - return TRUE; + dissect_rlc_nr_common(rlc_tvb, pinfo, tree, true /* udp framing */); + return true; } /*****************************/ @@ -1251,11 +1286,11 @@ static gboolean dissect_rlc_nr_heur(tvbuff_t *tvb, packet_info *pinfo, static int dissect_rlc_nr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { - dissect_rlc_nr_common(tvb, pinfo, tree, FALSE /* not udp framing */); + dissect_rlc_nr_common(tvb, pinfo, tree, false /* not udp framing */); return tvb_captured_length(tvb); } -static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gboolean is_udp_framing) +static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, bool is_udp_framing) { proto_tree *rlc_nr_tree; proto_tree *context_tree; @@ -1263,9 +1298,13 @@ static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree proto_item *context_ti; proto_item *ti; proto_item *mode_ti; - gint offset = 0; + int offset = 0; struct rlc_nr_info *p_rlc_nr_info; + /* Allocate and Zero tap struct */ + rlc_3gpp_tap_info *tap_info = wmem_new0(pinfo->pool, rlc_3gpp_tap_info); + tap_info->rat = RLC_RAT_NR; + /* Set protocol name */ col_set_str(pinfo->cinfo, COL_PROTOCOL, "RLC-NR"); @@ -1353,6 +1392,20 @@ static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree p_rlc_nr_info->bearerId); } + /* Set context-info parts of tap struct */ + tap_info->rlcMode = p_rlc_nr_info->rlcMode; + tap_info->direction = p_rlc_nr_info->direction; + /* TODO: p_rlc_nr_info does not have priority. */ + tap_info->ueid = p_rlc_nr_info->ueid; + tap_info->channelType = p_rlc_nr_info->bearerType; + tap_info->channelId = p_rlc_nr_info->bearerId; + tap_info->pduLength = p_rlc_nr_info->pduLength; + tap_info->sequenceNumberLength = p_rlc_nr_info->sequenceNumberLength; + tap_info->loggedInMACFrame = (p_get_proto_data(wmem_file_scope(), pinfo, proto_mac_nr, 0) != NULL); + + tap_info->rlc_time = pinfo->abs_ts; + + /* Dissect the RLC PDU itself. Format depends upon mode... */ switch (p_rlc_nr_info->rlcMode) { @@ -1361,11 +1414,11 @@ static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree break; case RLC_UM_MODE: - dissect_rlc_nr_um(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti); + dissect_rlc_nr_um(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti, tap_info); break; case RLC_AM_MODE: - dissect_rlc_nr_am(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti); + dissect_rlc_nr_am(tvb, pinfo, rlc_nr_tree, offset, p_rlc_nr_info, top_ti, tap_info); break; default: @@ -1374,6 +1427,9 @@ static void dissect_rlc_nr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree "Unrecognised RLC Mode set (%u)", p_rlc_nr_info->rlcMode); break; } + + /* Queue tap info */ + tap_queue_packet(rlc_nr_tap, pinfo, tap_info); } @@ -1382,7 +1438,7 @@ void set_rlc_nr_drb_pdcp_mapping(packet_info *pinfo, nr_drb_rlc_pdcp_mapping_t *drb_mapping) { wmem_tree_key_t key[2]; - guint32 id; + uint32_t id; pdcp_bearer_parameters *params; if (PINFO_FD_VISITED(pinfo)) { @@ -1416,10 +1472,10 @@ void set_rlc_nr_drb_pdcp_mapping(packet_info *pinfo, params->pdcp_ciphering_disabled = drb_mapping->pdcpCipheringDisabled; } -pdcp_bearer_parameters* get_rlc_nr_drb_pdcp_mapping(guint16 ue_id, guint8 drb_id) +pdcp_bearer_parameters* get_rlc_nr_drb_pdcp_mapping(uint16_t ue_id, uint8_t drb_id) { wmem_tree_key_t key[2]; - guint32 id; + uint32_t id; pdcp_bearer_parameters *params; id = (drb_id << 16) | ue_id; @@ -1572,7 +1628,7 @@ void proto_register_rlc_nr(void) }, { &hf_rlc_nr_am_data_control, { "Data/Control", - "rlc-nr.am.dc", FT_BOOLEAN, 8, TFS(&data_or_control_vals), 0x80, + "rlc-nr.am.dc", FT_BOOLEAN, 8, TFS(&tfs_data_pdu_control_pdu), 0x80, NULL, HFILL } }, @@ -1751,7 +1807,7 @@ void proto_register_rlc_nr(void) } }; - static gint *ett[] = + static int *ett[] = { &ett_rlc_nr, &ett_rlc_nr_context, @@ -1793,6 +1849,9 @@ void proto_register_rlc_nr(void) /* Allow other dissectors to find this one by name. */ register_dissector("rlc-nr", dissect_rlc_nr, proto_rlc_nr); + /* Register the tap name */ + rlc_nr_tap = register_tap("rlc-3gpp"); + /* Preferences */ rlc_nr_module = prefs_register_protocol(proto_rlc_nr, NULL); @@ -1806,13 +1865,13 @@ void proto_register_rlc_nr(void) "Call PDCP dissector for UL DRB PDUs", "Call PDCP dissector for UL user-plane PDUs. Note that without reassembly, it can" "only be called for complete PDUs (i.e. not segmented over RLC)", - &global_rlc_nr_call_pdcp_for_ul_drb, pdcp_drb_col_vals, FALSE); + &global_rlc_nr_call_pdcp_for_ul_drb, pdcp_drb_col_vals, false); prefs_register_enum_preference(rlc_nr_module, "call_pdcp_for_dl_drb", "Call PDCP dissector for DL DRB PDUs", "Call PDCP dissector for DL user-plane PDUs. Note that without reassembly, it can" "only be called for complete PDUs (i.e. not segmented over RLC)", - &global_rlc_nr_call_pdcp_for_dl_drb, pdcp_drb_col_vals, FALSE); + &global_rlc_nr_call_pdcp_for_dl_drb, pdcp_drb_col_vals, false); prefs_register_bool_preference(rlc_nr_module, "call_rrc_for_ccch", "Call RRC dissector for CCCH PDUs", |