From Pascal Quantin:
[obnox/wireshark/wip.git] / epan / dissectors / packet-pdcp-lte.c
1 /* Routines for LTE PDCP/ROHC
2  *
3  * Martin Mathieson
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <string.h>
31
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/expert.h>
35 #include <epan/addr_resolv.h>
36
37 #include "packet-pdcp-lte.h"
38
39 /* Described in:
40  * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
41  *                Packet Data Convergence Protocol (PDCP) specification
42  *
43  * RFC 3095       RObust Header Compression (ROHC):
44  *                Framework and four profiles: RTP, UDP, ESP, and uncompressed
45  */
46
47
48 /* TODO:
49    - Update to latest version of 36.323
50    - Complete ROHC support for RTP and extend to other profiles (including ROHCv2)
51    - Support for decryption
52    - Verify MAC authentication bytes
53 */
54
55
56 /* Initialize the protocol and registered fields. */
57 int proto_pdcp_lte = -1;
58
59 extern int proto_rlc_lte;
60
61 /* Configuration (info known outside of PDU) */
62 static int hf_pdcp_lte_configuration = -1;
63 static int hf_pdcp_lte_direction = -1;
64 static int hf_pdcp_lte_ueid = -1;
65 static int hf_pdcp_lte_channel_type = -1;
66 static int hf_pdcp_lte_channel_id = -1;
67 static int hf_pdcp_lte_rohc = -1;
68 static int hf_pdcp_lte_rohc_compression = -1;
69 static int hf_pdcp_lte_rohc_mode = -1;
70 static int hf_pdcp_lte_rohc_rnd = -1;
71 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
72 static int hf_pdcp_lte_rohc_profile = -1;
73 static int hf_pdcp_lte_no_header_pdu = -1;
74 static int hf_pdcp_lte_plane = -1;
75 static int hf_pdcp_lte_seqnum_length = -1;
76 static int hf_pdcp_lte_cid_inclusion_info = -1;
77 static int hf_pdcp_lte_large_cid_present = -1;
78
79 /* PDCP header fields */
80 static int hf_pdcp_lte_seq_num_5 = -1;
81 static int hf_pdcp_lte_seq_num_7 = -1;
82 static int hf_pdcp_lte_reserved3 = -1;
83 static int hf_pdcp_lte_seq_num_12 = -1;
84 static int hf_pdcp_lte_signalling_data = -1;
85 static int hf_pdcp_lte_mac = -1;
86 static int hf_pdcp_lte_data_control = -1;
87 static int hf_pdcp_lte_user_plane_data = -1;
88 static int hf_pdcp_lte_control_pdu_type = -1;
89 static int hf_pdcp_lte_fms = -1;
90 static int hf_pdcp_lte_bitmap = -1;
91 static int hf_pdcp_lte_bitmap_not_received = -1;
92
93 /* Robust Header Compression Fields */
94 static int hf_pdcp_lte_rohc_padding = -1;
95 static int hf_pdcp_lte_rohc_r_0_crc = -1;
96 static int hf_pdcp_lte_rohc_feedback = -1;
97
98 static int hf_pdcp_lte_rohc_type0_t = -1;
99 static int hf_pdcp_lte_rohc_type1_t = -1;
100 static int hf_pdcp_lte_rohc_type2_t = -1;
101
102 static int hf_pdcp_lte_rohc_d = -1;
103 static int hf_pdcp_lte_rohc_ir_crc = -1;
104
105 static int hf_pdcp_lte_rohc_static_ipv4 = -1;
106 static int hf_pdcp_lte_rohc_ip_version = -1;
107 static int hf_pdcp_lte_rohc_ip_protocol = -1;
108 static int hf_pdcp_lte_rohc_ip_src = -1;
109 static int hf_pdcp_lte_rohc_ip_dst = -1;
110
111 static int hf_pdcp_lte_rohc_static_udp = -1;
112 static int hf_pdcp_lte_rohc_static_udp_src_port = -1;
113 static int hf_pdcp_lte_rohc_static_udp_dst_port = -1;
114
115 static int hf_pdcp_lte_rohc_static_rtp = -1;
116 static int hf_pdcp_lte_rohc_static_rtp_ssrc = -1;
117
118 static int hf_pdcp_lte_rohc_dynamic_ipv4 = -1;
119 static int hf_pdcp_lte_rohc_dynamic_ipv4_tos = -1;
120 static int hf_pdcp_lte_rohc_dynamic_ipv4_ttl = -1;
121 static int hf_pdcp_lte_rohc_dynamic_ipv4_id = -1;
122 static int hf_pdcp_lte_rohc_dynamic_ipv4_df = -1;
123 static int hf_pdcp_lte_rohc_dynamic_ipv4_rnd = -1;
124 static int hf_pdcp_lte_rohc_dynamic_ipv4_nbo = -1;
125
126 static int hf_pdcp_lte_rohc_dynamic_udp = -1;
127 static int hf_pdcp_lte_rohc_dynamic_udp_checksum = -1;
128 static int hf_pdcp_lte_rohc_dynamic_udp_seqnum = -1;
129
130 static int hf_pdcp_lte_rohc_dynamic_rtp = -1;
131 static int hf_pdcp_lte_rohc_dynamic_rtp_rx = -1;
132 static int hf_pdcp_lte_rohc_dynamic_rtp_cc = -1;
133 static int hf_pdcp_lte_rohc_dynamic_rtp_seqnum = -1;
134 static int hf_pdcp_lte_rohc_dynamic_rtp_timestamp = -1;
135 static int hf_pdcp_lte_rohc_dynamic_rtp_reserved3 = -1;
136 static int hf_pdcp_lte_rohc_dynamic_rtp_x = -1;
137 static int hf_pdcp_lte_rohc_dynamic_rtp_mode = -1;
138 static int hf_pdcp_lte_rohc_dynamic_rtp_tis = -1;
139 static int hf_pdcp_lte_rohc_dynamic_rtp_tss = -1;
140 static int hf_pdcp_lte_rohc_dynamic_rtp_ts_stride = -1;
141
142 static int hf_pdcp_lte_rohc_ts = -1;
143 static int hf_pdcp_lte_rohc_m = -1;
144 static int hf_pdcp_lte_rohc_uor2_sn = -1;
145 static int hf_pdcp_lte_rohc_uor2_x = -1;
146
147 static int hf_pdcp_lte_rohc_add_cid = -1;
148 static int hf_pdcp_lte_rohc_large_cid = -1;
149
150 static int hf_pdcp_lte_rohc_uo0_sn = -1;
151 static int hf_pdcp_lte_rohc_uo0_crc = -1;
152
153 static int hf_pdcp_lte_rohc_r0_sn = -1;
154 static int hf_pdcp_lte_rohc_r0_crc_sn = -1;
155 static int hf_pdcp_lte_rohc_r0_crc_crc = -1;
156
157 static int hf_pdcp_lte_rohc_feedback_code = -1;
158 static int hf_pdcp_lte_rohc_feedback_size = -1;
159 static int hf_pdcp_lte_rohc_feedback_feedback1 = -1;
160 static int hf_pdcp_lte_rohc_feedback_feedback2 = -1;
161 static int hf_pdcp_lte_rohc_feedback_ack_type = -1;
162 static int hf_pdcp_lte_rohc_feedback_mode = -1;
163 static int hf_pdcp_lte_rohc_feedback_sn = -1;
164 static int hf_pdcp_lte_rohc_feedback_option = -1;
165 static int hf_pdcp_lte_rohc_feedback_length = -1;
166 static int hf_pdcp_lte_rohc_feedback_crc = -1;
167 static int hf_pdcp_lte_rohc_feedback_option_sn = -1;
168 static int hf_pdcp_lte_rohc_feedback_option_clock = -1;
169
170 static int hf_pdcp_lte_rohc_ip_id = -1;
171 static int hf_pdcp_lte_rohc_udp_checksum = -1;
172 static int hf_pdcp_lte_rohc_payload = -1;
173
174 /* Sequence Analysis */
175 static int hf_pdcp_lte_sequence_analysis = -1;
176 static int hf_pdcp_lte_sequence_analysis_ok = -1;
177 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
178 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
179
180 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
181 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
182
183
184
185
186 /* Protocol subtree. */
187 static int ett_pdcp = -1;
188 static int ett_pdcp_configuration = -1;
189 static int ett_pdcp_packet = -1;
190 static int ett_pdcp_lte_sequence_analysis = -1;
191 static int ett_pdcp_rohc = -1;
192 static int ett_pdcp_rohc_static_ipv4 = -1;
193 static int ett_pdcp_rohc_static_udp = -1;
194 static int ett_pdcp_rohc_static_rtp = -1;
195 static int ett_pdcp_rohc_dynamic_ipv4 = -1;
196 static int ett_pdcp_rohc_dynamic_udp = -1;
197 static int ett_pdcp_rohc_dynamic_rtp = -1;
198 static int ett_pdcp_rohc_report_bitmap = -1;
199
200
201 static const value_string direction_vals[] =
202 {
203     { DIRECTION_UPLINK,      "Uplink"},
204     { DIRECTION_DOWNLINK,    "Downlink"},
205     { 0, NULL }
206 };
207
208
209 static const value_string pdcp_plane_vals[] = {
210     { SIGNALING_PLANE,    "Signalling" },
211     { USER_PLANE,         "User" },
212     { 0,   NULL }
213 };
214
215 static const value_string logical_channel_vals[] = {
216     { Channel_DCCH,  "DCCH"},
217     { Channel_BCCH,  "BCCH"},
218     { Channel_CCCH,  "CCCH"},
219     { Channel_PCCH,  "PCCH"},
220     { 0,             NULL}
221 };
222
223 static const value_string rohc_mode_vals[] = {
224     { UNIDIRECTIONAL,            "Unidirectional" },
225     { OPTIMISTIC_BIDIRECTIONAL,  "Optimistic Bidirectional" },
226     { RELIABLE_BIDIRECTIONAL,    "Reliable Bidirectional" },
227     { 0,   NULL }
228 };
229
230
231 /* TODO: add more */
232 static const value_string rohc_profile_vals[] = {
233     { 0,   "Uncompressed" },
234     { 1,   "RTP" },
235     { 2,   "UDP" },
236     { 3,   "ESP/IP" },
237     { 0,   NULL }
238 };
239
240 static const value_string pdu_type_vals[] = {
241     { 0,   "Control PDU" },
242     { 1,   "Data PDU" },
243     { 0,   NULL }
244 };
245
246 static const value_string feedback_ack_vals[] = {
247     { 0,   "ACK" },
248     { 1,   "NACK" },
249     { 2,   "STATIC-NACK" },
250     { 0,   NULL }
251 };
252
253 static const value_string feedback_option_vals[] = {
254     { 1,   "CRC" },
255     { 2,   "REJECT" },
256     { 3,   "SN-Not-Valid" },
257     { 4,   "SN" },
258     { 5,   "Clock" },
259     { 6,   "Jitter" },
260     { 7,   "Loss" },
261     { 0,   NULL }
262 };
263
264 static const value_string control_pdu_type_vals[] = {
265     { 0,   "PDCP Status report" },
266     { 1,   "Header Compression Feedback Information" },
267     { 0,   NULL }
268 };
269
270 static const value_string t_vals[] = {
271     { 0,   "ID message format" },
272     { 1,   "TS message format" },
273     { 0,   NULL }
274 };
275
276 static const value_string ip_protocol_vals[] = {
277     { 6,   "TCP" },
278     { 17,  "UDP" },
279     { 0,   NULL }
280 };
281
282
283 static dissector_handle_t ip_handle;
284
285
286 /* Preference variables */
287 static gboolean global_pdcp_show_feedback_option_tag_length = FALSE;
288 static gboolean global_pdcp_dissect_user_plane_as_ip = FALSE;
289 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = FALSE;
290 static gboolean global_pdcp_check_sequence_numbers = FALSE;
291 static gboolean global_pdcp_dissect_rohc = FALSE;
292
293
294 /**************************************************/
295 /* Sequence number analysis                       */
296
297 /* Channel key */
298 typedef struct
299 {
300     guint16            ueId;
301     LogicalChannelType channelType;
302     guint16            channelId;
303     guint8             direction;
304 } pdcp_channel_hash_key;
305
306 /* Channel state */
307 typedef struct
308 {
309     guint16  previousSequenceNumber;
310     guint32  previousFrameNum;
311 } pdcp_channel_status;
312
313 /* The sequence analysis channel hash table.
314    Maps key -> status */
315 static GHashTable *pdcp_sequence_analysis_channel_hash = NULL;
316
317 /* Equal keys */
318 static gint pdcp_channel_equal(gconstpointer v, gconstpointer v2)
319 {
320     const pdcp_channel_hash_key* val1 = v;
321     const pdcp_channel_hash_key* val2 = v2;
322
323     /* All fields must match */
324     return (memcmp(val1, val2, sizeof(pdcp_channel_hash_key)) == 0);
325 }
326
327 /* Compute a hash value for a given key. */
328 static guint pdcp_channel_hash_func(gconstpointer v)
329 {
330     const pdcp_channel_hash_key* val1 = v;
331
332     /* TODO: use multipliers */
333     return val1->ueId + val1->channelType + val1->channelId + val1->direction;
334 }
335
336 /* Hash table functions for frame reports */
337
338 /* TODO: copied from packet-rlc-lte.c.  extern, or add to lib? */
339 /* Equal keys */
340 static gint pdcp_frame_equal(gconstpointer v, gconstpointer v2)
341 {
342     return (v == v2);
343 }
344
345 /* Compute a hash value for a given key. */
346 static guint pdcp_frame_hash_func(gconstpointer v)
347 {
348     return GPOINTER_TO_UINT(v);
349 }
350
351
352 /* Info to attach to frame when first read, recording what to show about sequence */
353 typedef struct
354 {
355     gboolean  sequenceExpectedCorrect;
356     guint16   sequenceExpected;
357     guint32   previousFrameNum;
358
359     guint16   firstSN;
360     guint16   lastSN;
361
362     enum { SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing} state;
363 } pdcp_sequence_report_in_frame;
364
365 /* The sequence analysis frame report hash table instance itself   */
366 static GHashTable *pdcp_lte_frame_sequence_analysis_report_hash = NULL;
367
368
369 /* Add to the tree values associated with sequence analysis for this frame */
370 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
371                                    pdcp_lte_info *p_pdcp_lte_info,
372                                    guint16   sequenceNumber,
373                                    packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb)
374 {
375     proto_tree *seqnum_tree;
376     proto_item *seqnum_ti;
377     proto_item *ti;
378     guint16 snLimit;
379
380     /* Create subtree */
381     seqnum_ti = proto_tree_add_string_format(tree,
382                                              hf_pdcp_lte_sequence_analysis,
383                                              tvb, 0, 0,
384                                              "", "Sequence Analysis");
385     seqnum_tree = proto_item_add_subtree(seqnum_ti,
386                                          ett_pdcp_lte_sequence_analysis);
387     PROTO_ITEM_SET_GENERATED(seqnum_ti);
388
389
390     /* Previous channel frame */
391     if (p->previousFrameNum != 0) {
392         proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
393                             tvb, 0, 0, p->previousFrameNum);
394     }
395
396     /* Expected sequence number */
397     ti = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
398                             tvb, 0, 0, p->sequenceExpected);
399     PROTO_ITEM_SET_GENERATED(ti);
400
401     /* Work out SN wrap (in case needed below) */
402     switch (p_pdcp_lte_info->seqnum_length) {
403         case PDCP_SN_LENGTH_5_BITS:
404             snLimit = 32;
405             break;
406         case PDCP_SN_LENGTH_7_BITS:
407             snLimit = 128;
408             break;
409         case PDCP_SN_LENGTH_12_BITS:
410             snLimit = 4096;
411             break;
412         default:
413             DISSECTOR_ASSERT_NOT_REACHED();
414             break;
415     }
416
417     switch (p->state) {
418         case SN_OK:
419             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
420                                         tvb, 0, 0, TRUE);
421             PROTO_ITEM_SET_GENERATED(ti);
422             proto_item_append_text(seqnum_ti, " - OK");
423             break;
424
425         case SN_Missing:
426             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
427                                         tvb, 0, 0, FALSE);
428             PROTO_ITEM_SET_GENERATED(ti);
429             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
430                                         tvb, 0, 0, TRUE);
431             PROTO_ITEM_SET_GENERATED(ti);
432             if (p->lastSN != p->firstSN) {
433                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
434                                        "PDCP SNs (%u to %u) missing for %s on UE %u",
435                                        p->firstSN, p->lastSN,
436                                        val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
437                                        p_pdcp_lte_info->ueid);
438                 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
439                                        p->firstSN, p->lastSN);
440             }
441             else {
442                 expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
443                                        "PDCP SN (%u) missing for %s on UE %u",
444                                        p->firstSN,
445                                        val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
446                                        p_pdcp_lte_info->ueid);
447                 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
448                                        p->firstSN);
449             }
450             break;
451
452         case SN_Repeated:
453             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
454                                         tvb, 0, 0, FALSE);
455             PROTO_ITEM_SET_GENERATED(ti);
456             ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
457                                         tvb, 0, 0, TRUE);
458             PROTO_ITEM_SET_GENERATED(ti);
459             expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
460                                    "PDCP SN (%u) repeated for %s for UE %u",
461                                    p->firstSN,
462                                    val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
463                                    p_pdcp_lte_info->ueid);
464             proto_item_append_text(seqnum_ti, "- SN %u Repeated",
465                                    p->firstSN);
466             break;
467
468         default:
469             /* Incorrect sequence number */
470             expert_add_info_format(pinfo, ti, PI_SEQUENCE, PI_WARN,
471                                    "Wrong Sequence Number for %s on UE %u - got %u, expected %u",
472                                    val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
473                                    p_pdcp_lte_info->ueid, sequenceNumber, p->sequenceExpected);
474             break;
475     }
476 }
477
478
479 /* Update the channel status and set report for this frame */
480 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
481                                      pdcp_lte_info *p_pdcp_lte_info,
482                                      guint16 sequenceNumber,
483                                      proto_tree *tree)
484 {
485     pdcp_channel_hash_key          channel_key;
486     pdcp_channel_hash_key          *p_channel_key;
487     pdcp_channel_status            *p_channel_status;
488     pdcp_sequence_report_in_frame  *p_report_in_frame = NULL;
489     gboolean               createdChannel = FALSE;
490     guint16                expectedSequenceNumber = 0;
491     guint16                snLimit = 0;
492
493     /* If find stat_report_in_frame already, use that and get out */
494     if (pinfo->fd->flags.visited) {
495         p_report_in_frame = (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_frame_sequence_analysis_report_hash,
496                                                                                 &pinfo->fd->num);
497         if (p_report_in_frame != NULL) {
498             addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
499                                    sequenceNumber,
500                                    pinfo, tree, tvb);
501             return;
502         }
503         else {
504             /* Give up - we must have tried already... */
505             return;
506         }
507     }
508
509
510     /**************************************************/
511     /* Create or find an entry for this channel state */
512     memset(&channel_key, 0, sizeof(channel_key));
513     channel_key.ueId = p_pdcp_lte_info->ueid;
514     channel_key.channelType = p_pdcp_lte_info->channelType;
515     channel_key.channelId = p_pdcp_lte_info->channelId;
516     channel_key.direction = p_pdcp_lte_info->direction;
517
518     /* Do the table lookup */
519     p_channel_status = (pdcp_channel_status*)g_hash_table_lookup(pdcp_sequence_analysis_channel_hash, &channel_key);
520
521     /* Create table entry if necessary */
522     if (p_channel_status == NULL) {
523         createdChannel = TRUE;
524
525         /* Allocate a new key and value */
526         p_channel_key = se_alloc(sizeof(pdcp_channel_hash_key));
527         p_channel_status = se_alloc0(sizeof(pdcp_channel_status));
528
529         /* Copy key contents */
530         memcpy(p_channel_key, &channel_key, sizeof(pdcp_channel_hash_key));
531
532         /* Add entry */
533         g_hash_table_insert(pdcp_sequence_analysis_channel_hash, p_channel_key, p_channel_status);
534     }
535
536     /* Create space for frame state_report */
537     p_report_in_frame = se_alloc(sizeof(pdcp_sequence_report_in_frame));
538
539     switch (p_pdcp_lte_info->seqnum_length) {
540         case PDCP_SN_LENGTH_5_BITS:
541             snLimit = 32;
542             break;
543         case PDCP_SN_LENGTH_7_BITS:
544             snLimit = 128;
545             break;
546         case PDCP_SN_LENGTH_12_BITS:
547             snLimit = 4096;
548             break;
549         default:
550             DISSECTOR_ASSERT_NOT_REACHED();
551             break;
552     }
553
554     /* Work out expected sequence number */
555     if (!createdChannel) {
556         expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
557     }
558
559     /* Set report for this frame */
560     /* For PDCP, sequence number is always expectedSequence number */
561     p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
562
563     /* For wrong sequence number... */
564     if (!p_report_in_frame->sequenceExpectedCorrect) {
565
566         /* Frames are not missing if we get an earlier sequence number again */
567         if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
568             p_report_in_frame->state = SN_Missing;
569             p_report_in_frame->firstSN = expectedSequenceNumber;
570             p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
571
572             p_report_in_frame->sequenceExpected = expectedSequenceNumber;
573             p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
574
575             /* Update channel status to remember *this* frame */
576             p_channel_status->previousFrameNum = pinfo->fd->num;
577             p_channel_status->previousSequenceNumber = sequenceNumber;
578         }
579         else {
580             /* An SN has been repeated */
581             p_report_in_frame->state = SN_Repeated;
582             p_report_in_frame->firstSN = sequenceNumber;
583
584             p_report_in_frame->sequenceExpected = expectedSequenceNumber;
585             p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
586         }
587     }
588     else {
589         /* SN was OK */
590         p_report_in_frame->state = SN_OK;
591         p_report_in_frame->sequenceExpected = expectedSequenceNumber;
592         p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
593
594         /* Update channel status to remember *this* frame */
595         p_channel_status->previousFrameNum = pinfo->fd->num;
596         p_channel_status->previousSequenceNumber = sequenceNumber;
597     }
598
599     /* Associate with this frame number */
600     g_hash_table_insert(pdcp_lte_frame_sequence_analysis_report_hash, &pinfo->fd->num, p_report_in_frame);
601
602     /* Add state report for this frame into tree */
603     addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
604                            pinfo, tree, tvb);
605 }
606
607
608
609 /***************************************************************/
610
611
612 /* Dissect a Large-CID field.
613    Return following offset */
614 static int dissect_large_cid(proto_tree *tree,
615                              tvbuff_t *tvb,
616                              int offset)
617 {
618     guint8 first_octet = tvb_get_guint8(tvb, offset);
619
620     if ((first_octet & 0x80) == 0) {
621         /* One byte */
622         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 1,
623                             first_octet);
624         return offset+1;
625     }
626     else {
627         /* Two bytes */
628         guint16 bytes = tvb_get_ntohs(tvb, offset) & 0x7fff;
629         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_large_cid, tvb, offset, 2,
630                             bytes);
631         return offset+2;
632     }
633
634 }
635
636 static int dissect_pdcp_dynamic_chain(proto_tree *tree,
637                                       proto_item *root_item _U_,
638                                       tvbuff_t *tvb,
639                                       int offset,
640                                       struct pdcp_lte_info *p_pdcp_info,
641                                       packet_info *pinfo)
642 {
643     /* IPv4 dynamic */
644     if (p_pdcp_info->rohc_ip_version == 4) {
645         proto_tree *dynamic_ipv4_tree;
646         proto_item *root_ti;
647         int tree_start_offset = offset;
648         guint8 tos, ttl, id, rnd, nbo;
649
650         /* Create dynamic IPv4 subtree */
651         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_ipv4, tvb, offset, -1, FALSE);
652         dynamic_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_ipv4);
653
654         /* ToS */
655         tos = tvb_get_guint8(tvb, offset);
656         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_tos, tvb, offset, 1, FALSE);
657         offset++;
658
659         /* TTL */
660         ttl = tvb_get_guint8(tvb, offset);
661         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_ttl, tvb, offset, 1, FALSE);
662         offset++;
663
664         /* IP-ID */
665         id = tvb_get_guint8(tvb, offset);
666         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_id, tvb, offset, 1, FALSE);
667         offset++;
668
669         /* IP flags */
670         rnd = (tvb_get_guint8(tvb, offset) & 0x40) >> 6;
671         nbo = (tvb_get_guint8(tvb, offset) & 0x20) >> 5;
672         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_df, tvb, offset, 1, FALSE);
673         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_rnd, tvb, offset, 1, FALSE);
674         proto_tree_add_item(dynamic_ipv4_tree, hf_pdcp_lte_rohc_dynamic_ipv4_nbo, tvb, offset, 1, FALSE);
675
676         /* TODO: general extension header list... */
677         offset += 3;
678
679         /* Set proper length for subtree */
680         proto_item_set_len(root_ti, offset-tree_start_offset);
681
682         /* Add summary to root item */
683         proto_item_append_text(root_ti, " (ToS=%u, TTL=%u, ID=%u, RND=%u, NBO=%u)",
684                                tos, ttl, id, rnd, nbo);
685     }
686
687     /* UDP dynamic */
688     if ((p_pdcp_info->profile == 1) ||
689         (p_pdcp_info->profile == 2)) {
690
691         proto_tree *dynamic_udp_tree;
692         proto_item *root_ti;
693         unsigned short checksum;
694
695         /* Create dynamic UDP subtree */
696         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_udp, tvb, offset, 2, FALSE);
697         dynamic_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_udp);
698
699         /* 16-bit checksum */
700         checksum = tvb_get_ntohs(tvb, offset);
701         proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_checksum, tvb, offset, 2, FALSE);
702         offset +=2;
703
704         if (p_pdcp_info->profile == 2) {
705             guint16 seqnum;
706
707             seqnum = tvb_get_ntohs(tvb, offset);
708             proto_tree_add_item(dynamic_udp_tree, hf_pdcp_lte_rohc_dynamic_udp_seqnum, tvb, offset, 2, FALSE);
709             offset +=2;
710
711             /* Add summary to root item */
712             proto_item_append_text(root_ti, " (checksum = %04x, seqnum = %u)", checksum, seqnum);
713         }
714         else {
715             /* Add summary to root item */
716             proto_item_append_text(root_ti, " (checksum = %04x)", checksum);
717         }
718     }
719
720     /* RTP dynamic */
721     if (p_pdcp_info->profile == 1) {
722         proto_tree *dynamic_rtp_tree;
723         proto_item *root_ti;
724         int tree_start_offset = offset;
725         guint8     rx;
726         guint8     contributing_csrcs;
727         guint16    sequence_number;
728         guint32    timestamp;
729         guint8     tis=0, tss=0;
730         guint64    ts_stride=0;
731
732         /* Create dynamic RTP subtree */
733         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_dynamic_rtp, tvb, offset, -1, FALSE);
734         dynamic_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_dynamic_rtp);
735
736         /* TODO: */
737         /* V | P | RX | CC */
738         rx = tvb_get_guint8(tvb, offset) & 0x10;
739         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_rx, tvb, offset, 1, FALSE);
740         contributing_csrcs = tvb_get_guint8(tvb, offset) & 0x0f;
741         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_cc, tvb, offset, 1, FALSE);
742         offset += 1;
743
744         /* TODO: */
745         /* M | PT */
746         offset += 1;
747
748         /* Sequence number */
749         sequence_number = tvb_get_ntohs(tvb, offset);
750         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_seqnum, tvb, offset, 2, FALSE);
751         offset += 2;
752
753         /* Timestamp (4 octets) */
754         timestamp = tvb_get_ntohl(tvb, offset);
755         proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_timestamp, tvb, offset, 4, FALSE);
756         offset += 4;
757
758         /* TODO: CSRC list */
759         /*offset += (4 * contributing_csrcs); */
760         offset++;
761
762         /* TODO: Reserved | X | Mode | TIS | TIS */
763         if (rx) {
764             guint8 this_byte = tvb_get_guint8(tvb, offset);
765             proto_item *reserved_ti = proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
766                                                           tvb, offset, 1, FALSE);
767
768             /* Check reserved bits are 0 */
769             if ((this_byte & 0xe0) != 0) {
770                 expert_add_info_format(pinfo, reserved_ti, PI_MALFORMED, PI_ERROR,
771                                        "Reserved bits have value 0x%x - should be 0x0",
772                                        (this_byte & 0xe0));
773             }
774             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_x, tvb, offset, 1, FALSE);
775             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_mode, tvb, offset, 1, FALSE);
776             tss = (this_byte & 0x02);
777             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tss, tvb, offset, 1, FALSE);
778             tis = (this_byte & 0x01);
779             proto_tree_add_item(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_tis, tvb, offset, 1, FALSE);
780             offset++;
781         }
782
783         /* TODO: the length of these fields can be learned by looked at the leading bits, see
784            RFC 3095, "4.5.6.  Self-describing variable-length values" */
785         /* TODO: TS-Stride (1-4 bytes) */
786         if (tis) {
787             /* Assume encoded in two bytes for now... */
788             proto_tree_add_bits_ret_val(dynamic_rtp_tree, hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
789                                         tvb, offset*8 + 2, 14, &ts_stride, FALSE);
790             offset += 2;
791         }
792
793         /* TODO: Time-stride (1-4 bytes) */
794         if (tss) {
795         }
796
797         /* Set proper length for subtree */
798         proto_item_set_len(root_ti, offset-tree_start_offset);
799
800         /* Add summary to root item */
801         proto_item_append_text(root_ti, " (seqnum = %u, timestamp = %u)",
802                                sequence_number, timestamp);
803     }
804
805     return offset;
806 }
807
808
809
810 static int dissect_pdcp_irdyn_packet(proto_tree *tree _U_,
811                                      proto_item *root_item,
812                                      tvbuff_t *tvb _U_,
813                                      int offset,
814                                      struct pdcp_lte_info *p_pdcp_info _U_,
815                                      packet_info *pinfo)
816 {
817     col_append_str(pinfo->cinfo, COL_INFO, " IRDYN");
818     proto_item_append_text(root_item, " (IRDYN)");
819
820     /* Large CID */
821     if (p_pdcp_info->large_cid_present) {
822         offset = dissect_large_cid(tree, tvb, offset);
823     }
824
825     /* Profile */
826     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
827     offset++;
828
829     /* 8-bit CRC */
830     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
831     offset++;
832
833     /* Dissect dynamic chain */
834     offset = dissect_pdcp_dynamic_chain(tree,
835                                         root_item,
836                                         tvb,
837                                         offset,
838                                         p_pdcp_info,
839                                         pinfo);
840     return offset;
841 }
842
843
844 static int dissect_pdcp_ir_packet(proto_tree *tree,
845                                   proto_item *root_item,
846                                   tvbuff_t *tvb,
847                                   int offset,
848                                   struct pdcp_lte_info *p_pdcp_info,
849                                   packet_info *pinfo)
850 {
851     unsigned char dynamic_chain_present;
852
853     col_append_str(pinfo->cinfo, COL_INFO, " IR");
854     proto_item_append_text(root_item, " (IR)");
855
856     /* Is dynamic chain present? */
857     dynamic_chain_present = tvb_get_guint8(tvb, offset) & 0x1;
858     proto_tree_add_item(tree, hf_pdcp_lte_rohc_d, tvb, offset, 1, FALSE);
859     offset++;
860
861     /* Large CID */
862     if (p_pdcp_info->large_cid_present) {
863         offset = dissect_large_cid(tree, tvb, offset);
864     }
865
866     /* Profile */
867     proto_tree_add_item(tree, hf_pdcp_lte_rohc_profile, tvb, offset, 1, FALSE);
868     offset++;
869
870     /* 8-bit CRC */
871     proto_tree_add_item(tree, hf_pdcp_lte_rohc_ir_crc, tvb, offset, 1, FALSE);
872     offset++;
873
874     /* IPv4 static part */
875     if (p_pdcp_info->rohc_ip_version == 4) {
876         proto_tree *static_ipv4_tree;
877         proto_item *root_ti;
878         int tree_start_offset = offset;
879         guint8  protocol;
880         guint32 source, dest;
881
882         /* Create static IPv4 subtree */
883         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_ipv4, tvb, offset, -1, FALSE);
884         static_ipv4_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_ipv4);
885
886         /* IP version (must be 4) */
887         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_version, tvb, offset, 1, FALSE);
888         offset++;
889
890         /* Protocol */
891         protocol = tvb_get_guint8(tvb, offset);
892         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_protocol, tvb, offset, 1, FALSE);
893         offset++;
894
895         /* Source address */
896         source = tvb_get_ipv4(tvb, offset);
897         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_src, tvb, offset, 4, FALSE);
898         offset += 4;
899
900         /* Dest address */
901         dest = tvb_get_ipv4(tvb, offset);
902         proto_tree_add_item(static_ipv4_tree, hf_pdcp_lte_rohc_ip_dst, tvb, offset, 4, FALSE);
903         offset += 4;
904
905         /* Set proper length for subtree */
906         proto_item_set_len(root_ti, offset-tree_start_offset);
907
908         /* Add summary to root item */
909         proto_item_append_text(root_ti, " (prot=%s: %s -> %s)",
910                                val_to_str(protocol, ip_protocol_vals, "Unknown"),
911                                (char*)get_hostname(source),
912                                (char*)get_hostname(dest));
913     }
914
915     /* UDP static part. TODO: also check protocol from last part!? */
916     if ((p_pdcp_info->profile == 1) ||
917         (p_pdcp_info->profile == 2)) {
918
919         proto_tree *static_udp_tree;
920         proto_item *root_ti;
921         int tree_start_offset = offset;
922         unsigned short source_port, dest_port;
923
924         /* Create static UDP subtree */
925         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_udp, tvb, offset, -1, FALSE);
926         static_udp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_udp);
927
928         /* Source port */
929         source_port = tvb_get_ntohs(tvb, offset);
930         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
931         offset += 2;
932
933         /* Dest port */
934         dest_port = tvb_get_ntohs(tvb, offset);
935         proto_tree_add_item(static_udp_tree, hf_pdcp_lte_rohc_static_udp_src_port, tvb, offset, 2, FALSE);
936         offset += 2;
937
938         /* Set proper length for subtree */
939         proto_item_set_len(root_ti, offset-tree_start_offset);
940
941         /* Add summary to root item */
942         proto_item_append_text(root_ti, " (%u -> %u)", source_port, dest_port);
943     }
944
945     /* RTP static */
946     if (p_pdcp_info->profile == 1) {
947         proto_tree *static_rtp_tree;
948         proto_item *root_ti;
949         guint32    ssrc;
950
951         /* Create static RTP subtree */
952         root_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_static_rtp, tvb, offset, 4, FALSE);
953         static_rtp_tree = proto_item_add_subtree(root_ti, ett_pdcp_rohc_static_rtp);
954
955         /* SSRC */
956         ssrc = tvb_get_ntohl(tvb, offset);
957         proto_tree_add_item(static_rtp_tree, hf_pdcp_lte_rohc_static_rtp_ssrc, tvb, offset, 4, FALSE);
958         offset += 4;
959
960         /* Add summary to root item */
961         proto_item_append_text(root_ti, " (SSRC=%u)", ssrc);
962     }
963
964
965     /* Dynamic chain */
966     if (dynamic_chain_present) {
967         offset = dissect_pdcp_dynamic_chain(tree,
968                                             root_item,
969                                             tvb,
970                                             offset,
971                                             p_pdcp_info,
972                                             pinfo);
973     }
974
975     return offset;
976 }
977
978
979
980 static int dissect_pdcp_feedback_feedback1(proto_tree *tree,
981                                            proto_item *item,
982                                            tvbuff_t *tvb,
983                                            int offset,
984                                            struct pdcp_lte_info *p_pdcp_info _U_,
985                                            packet_info *pinfo)
986 {
987     guint8 sn;
988
989     proto_item_append_text(item, " (type 1)");
990
991     /* TODO: profile-specific */
992     sn = tvb_get_guint8(tvb, offset);
993     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback1, tvb, offset, 1, FALSE);
994     offset++;
995
996     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
997
998     return offset;
999 }
1000
1001 /* Includes Large-CID, if present */
1002 static int dissect_pdcp_feedback_feedback2(proto_tree *tree,
1003                                            proto_item *item,
1004                                            tvbuff_t *tvb,
1005                                            int offset,
1006                                            int size,
1007                                            struct pdcp_lte_info *p_pdcp_info _U_,
1008                                            packet_info *pinfo _U_)
1009 {
1010     proto_item *ti;
1011     guint8  ack_type;
1012     guint8  mode;
1013     guint8  first_octet;
1014     guint16 sn;
1015     const char * full_mode_name;
1016     int size_remaining;
1017
1018     proto_item_append_text(item, " (type 2)");
1019
1020     /* Large CID */
1021     if (p_pdcp_info->large_cid_present) {
1022         offset = dissect_large_cid(tree, tvb, offset);
1023     }
1024
1025     /* Feedback2 hidden filter */
1026     ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_feedback2, tvb, offset, -1, FALSE);
1027     PROTO_ITEM_SET_HIDDEN(ti);
1028
1029     /* Ack-type */
1030     first_octet = tvb_get_guint8(tvb, offset);
1031     ack_type = (first_octet & 0xc0) >> 6;
1032     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_ack_type, tvb, offset, 1, FALSE);
1033
1034     /* TODO: expert info on NACK? */
1035
1036     /* Mode */
1037     mode = (first_octet & 0x30) >> 4;
1038     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_mode, tvb, offset, 1, FALSE);
1039
1040     /* Show ACK-TYPE(Mode) in info column */
1041     full_mode_name = val_to_str(mode, rohc_mode_vals, "Error");
1042
1043     col_append_fstr(pinfo->cinfo, COL_INFO, " %s(%c)",
1044                     val_to_str(ack_type, feedback_ack_vals, "Unknown"),
1045                     full_mode_name[0]);
1046
1047     /* 11 bits of SN */
1048     proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_sn, tvb, offset, 2, FALSE);
1049     sn = tvb_get_ntohs(tvb, offset) & 0x7ff;
1050     offset += 2;
1051
1052     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1053
1054     /* Loop over any remaining feedback options */
1055     size_remaining = size - 2;
1056
1057     while (tvb_length_remaining(tvb, offset) > 0) {
1058         guint8 option = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
1059         guint8 length = tvb_get_guint8(tvb, offset) & 0x0f;
1060         guint8 one_byte_value;
1061
1062         /* Preference setting controls showing option and lengths */
1063         if (global_pdcp_show_feedback_option_tag_length) {
1064             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option, tvb, offset, 1, FALSE);
1065             proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_length, tvb, offset, 1, FALSE);
1066         }
1067         offset++;
1068         size_remaining--;
1069
1070         /* TODO: switch including missing option types */
1071         switch (option) {
1072             case 1:
1073                 /* CRC */
1074                 one_byte_value = tvb_get_guint8(tvb, offset);
1075                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_crc, tvb, offset, 1, FALSE);
1076                 col_append_fstr(pinfo->cinfo, COL_INFO, " CRC=%u ", one_byte_value);
1077                 break;
1078             case 2:
1079                 /* REJECT: TODO */
1080                 break;
1081             case 3:
1082                 /* SN-Not-Valid: TODO */
1083                 break;
1084             case 4:
1085                 /* SN */
1086                 one_byte_value = tvb_get_guint8(tvb, offset);
1087                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_sn, tvb, offset, 1, FALSE);
1088                 col_append_fstr(pinfo->cinfo, COL_INFO, " SN=%u ", one_byte_value);
1089                 break;
1090             case 5:
1091                 /* Clock */
1092                 one_byte_value = tvb_get_guint8(tvb, offset);
1093                 proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback_option_clock, tvb, offset, 1, FALSE);
1094                 col_append_fstr(pinfo->cinfo, COL_INFO, " Clock=%u ", one_byte_value);
1095                 break;
1096             case 6:
1097                 /* Jitter: TODO */
1098                 break;
1099             case 7:
1100                 /* Loss: TODO */
1101                 break;
1102
1103             default:
1104                 /* TODO: unhandled option */
1105                 break;
1106         }
1107
1108         /* Skip length */
1109         offset += length;
1110         size_remaining -= length;
1111     }
1112
1113     return offset;
1114 }
1115
1116
1117 /* Dissect a feedback packet.
1118    Return following offset */
1119 static int dissect_pdcp_feedback_packet(proto_tree *tree,
1120                                         proto_item *root_item,
1121                                         tvbuff_t *tvb,
1122                                         int offset,
1123                                         struct pdcp_lte_info *p_pdcp_info,
1124                                         packet_info *pinfo)
1125 {
1126     guint8 code;
1127     guint8 size;
1128     proto_item *ti;
1129     proto_item *feedback_ti;
1130     proto_tree *feedback_tree;
1131
1132     col_append_str(pinfo->cinfo, COL_INFO, " Feedback");
1133     proto_item_append_text(root_item, " (Feedback)");
1134
1135     /* Create feedback tree root */
1136     feedback_ti = proto_tree_add_item(tree, hf_pdcp_lte_rohc_feedback, tvb, offset, -1, FALSE);
1137     feedback_tree = proto_item_add_subtree(feedback_ti, ett_pdcp_packet);
1138
1139     /* Code */
1140     code = tvb_get_guint8(tvb, offset) & 0x07;
1141     ti = proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_code, tvb, offset, 1, FALSE);
1142     offset++;
1143
1144     /* Optional length field */
1145     if (code != 0) {
1146         proto_item_append_text(ti, " (length of feedback data)");
1147         size = code;
1148     }
1149     else {
1150         proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_feedback_size, tvb, offset, 1, FALSE);
1151         size = tvb_get_guint8(tvb, offset);
1152         offset++;
1153     }
1154
1155     /* Work out feedback type */
1156     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
1157          !p_pdcp_info->large_cid_present) {
1158
1159         /* Small CID */
1160         if (size == 1) {
1161             offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
1162         }
1163         else if ((size > 1) && ((tvb_get_guint8(tvb, offset) & 0xc0) == 0xc0)) {
1164             /* Add-CID here! */
1165             proto_tree_add_item(feedback_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
1166             offset++;
1167
1168             if (size == 2) {
1169                 offset = dissect_pdcp_feedback_feedback1(feedback_tree, feedback_ti, tvb, offset, p_pdcp_info, pinfo);
1170             }
1171             else {
1172                 offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1173             }
1174         }
1175         else {
1176             offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1177         }
1178     }
1179     else {
1180         offset = dissect_pdcp_feedback_feedback2(feedback_tree, feedback_ti, tvb, offset, size, p_pdcp_info, pinfo);
1181     }
1182
1183     return offset;
1184 }
1185
1186
1187 /* Dissect R-0 packet.
1188    Return following offset */
1189 static int dissect_pdcp_r_0_packet(proto_tree *tree,
1190                                    proto_item *root_item,
1191                                    tvbuff_t *tvb,
1192                                    int offset,
1193                                    struct pdcp_lte_info *p_pdcp_info _U_,
1194                                    packet_info *pinfo)
1195 {
1196     guint8 sn;
1197
1198     col_append_str(pinfo->cinfo, COL_INFO, " R-0");
1199     proto_item_append_text(root_item, " (R-0)");
1200
1201     /* 6 bits of sn */
1202     sn = tvb_get_guint8(tvb, offset) & 0x3f;
1203     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_sn, tvb, offset, 1, FALSE);
1204     offset++;
1205
1206     /* Large CID */
1207     if (p_pdcp_info->large_cid_present) {
1208         offset = dissect_large_cid(tree, tvb, offset);
1209     }
1210
1211     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1212
1213     return offset;
1214 }
1215
1216
1217 /* Dissect R-0-CRC packet.
1218    Return following offset */
1219 static int dissect_pdcp_r_0_crc_packet(proto_tree *tree,
1220                                        proto_item *root_item,
1221                                        tvbuff_t *tvb,
1222                                        int offset,
1223                                        struct pdcp_lte_info *p_pdcp_info,
1224                                        packet_info *pinfo)
1225 {
1226     guint8 sn;
1227
1228     col_append_str(pinfo->cinfo, COL_INFO, " R-0-CRC");
1229     proto_item_append_text(root_item, " (R-0-CRC)");
1230
1231     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r_0_crc, tvb, offset, -1, FALSE);
1232
1233     /* 7 bits of sn */
1234     /* TODO: wrong!  Large-cid may be in-between!!!! */
1235     sn = tvb_get_guint8(tvb, offset) & 0x3f;
1236     offset++;
1237
1238     /* Large CID */
1239     if (p_pdcp_info->large_cid_present) {
1240         offset = dissect_large_cid(tree, tvb, offset);
1241     }
1242
1243     /* Conclude SN */
1244     sn = (sn << 1) + ((tvb_get_guint8(tvb, offset) & 0x80) >> 7);
1245     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_r0_crc_sn, tvb, offset, 1, sn);
1246
1247     /* 7 bit CRC */
1248     proto_tree_add_item(tree, hf_pdcp_lte_rohc_r0_crc_crc, tvb, offset, 1, FALSE);
1249     offset++;
1250
1251     /* Show SN in info column */
1252     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1253
1254     return offset;
1255 }
1256
1257
1258 /* Dissect UO-0-CRC packet.
1259    Return following offset */
1260 static int dissect_pdcp_uo_0_packet(proto_tree *tree,
1261                                     proto_item *root_item,
1262                                     tvbuff_t *tvb,
1263                                     int offset,
1264                                     struct pdcp_lte_info *p_pdcp_info,
1265                                     packet_info *pinfo)
1266 {
1267     guint8 sn;
1268
1269     col_append_str(pinfo->cinfo, COL_INFO, " U0-0");
1270     proto_item_append_text(root_item, " (UO-0)");
1271
1272     /* SN */
1273     sn = (tvb_get_guint8(tvb, offset) & 0x78) >> 3;
1274     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_sn, tvb, offset, 1, FALSE);
1275
1276     /* CRC (3 bits) */
1277     proto_tree_add_item(tree, hf_pdcp_lte_rohc_uo0_crc, tvb, offset, 1, FALSE);
1278
1279     offset++;
1280
1281     /* Large CID */
1282     if (p_pdcp_info->large_cid_present) {
1283         offset = dissect_large_cid(tree, tvb, offset);
1284     }
1285
1286     /* Show SN in info column */
1287     col_append_fstr(pinfo->cinfo, COL_INFO, " (sn=%u)", sn);
1288
1289     return offset;
1290 }
1291
1292
1293 /* Dissect R-1 packet.
1294    Return following offset */
1295 static int  dissect_pdcp_r_1_packet(proto_tree *tree,
1296                                     proto_item *root_item,
1297                                     tvbuff_t *tvb,
1298                                     int offset,
1299                                     struct pdcp_lte_info *p_pdcp_info,
1300                                     packet_info *pinfo)
1301 {
1302     col_append_str(pinfo->cinfo, COL_INFO, " R-1");
1303     proto_item_append_text(root_item, " (R-1)");
1304
1305     /* TODO: octet before large-cid */
1306     offset++;
1307
1308     /* Large CID */
1309     if (p_pdcp_info->large_cid_present) {
1310         offset = dissect_large_cid(tree, tvb, offset);
1311     }
1312
1313     if (p_pdcp_info->profile == 1) {
1314         /* TODO: */
1315     }
1316     else if (p_pdcp_info->profile == 2) {
1317         /* TODO: */
1318     }
1319
1320     return offset;
1321 }
1322
1323
1324 /* Dissect R-1-TS or R-1-ID packet.
1325    Return following offset */
1326 static int  dissect_pdcp_r_1_ts_or_id_packet(proto_tree *tree,
1327                                              proto_item *root_item,
1328                                              tvbuff_t *tvb,
1329                                              int offset,
1330                                              struct pdcp_lte_info *p_pdcp_info,
1331                                              packet_info *pinfo)
1332 {
1333     unsigned char T;
1334
1335     /* TODO: octet before large-cid */
1336     offset++;
1337
1338     /* Large CID */
1339     if (p_pdcp_info->large_cid_present) {
1340         offset = dissect_large_cid(tree, tvb, offset);
1341     }
1342
1343     /* T determines frame type */
1344     T = tvb_get_guint8(tvb, ++offset) >> 7;
1345     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type1_t, tvb, offset, 1, FALSE);
1346     if (T) {
1347         col_append_str(pinfo->cinfo, COL_INFO, " R-1-TS");
1348         proto_item_append_text(root_item, " (R-1-TS)");
1349     }
1350     else {
1351         col_append_str(pinfo->cinfo, COL_INFO, " R-1-ID");
1352         proto_item_append_text(root_item, " (R-1-ID)");
1353     }
1354
1355     if (p_pdcp_info->profile == 1) {
1356         /* TODO: */
1357     }
1358     else if (p_pdcp_info->profile == 2) {
1359         /* TODO: */
1360     }
1361
1362     return offset;
1363 }
1364
1365
1366 /* Dissect UO-1 packet.
1367    Return following offset */
1368 static int  dissect_pdcp_uo_1_packet(proto_tree *tree,
1369                                      proto_item *root_item,
1370                                      tvbuff_t *tvb,
1371                                      int offset,
1372                                      struct pdcp_lte_info *p_pdcp_info,
1373                                      packet_info *pinfo)
1374 {
1375     col_append_str(pinfo->cinfo, COL_INFO, " UO-1");
1376     proto_item_append_text(root_item, " (UO-1)");
1377
1378     /* TODO: octet before large-cid */
1379     offset++;
1380
1381     /* Large CID */
1382     if (p_pdcp_info->large_cid_present) {
1383         offset = dissect_large_cid(tree, tvb, offset);
1384     }
1385
1386     if (p_pdcp_info->profile == 1) {
1387         /* TODO: */
1388     }
1389     else if (p_pdcp_info->profile == 2) {
1390         /* TODO: */
1391     }
1392
1393     return offset;
1394 }
1395
1396
1397 /* Dissect UO-1-TS or UO-1-ID packet.
1398    Return following offset */
1399 static int  dissect_pdcp_uo_1_ts_or_id_packet(proto_tree *tree,
1400                                               proto_item *root_item,
1401                                               tvbuff_t *tvb,
1402                                               int offset,
1403                                               struct pdcp_lte_info *p_pdcp_info,
1404                                               packet_info *pinfo)
1405 {
1406     unsigned char T;
1407
1408     /* TODO: octet before large-cid */
1409     offset++;
1410
1411     /* Large CID */
1412     if (p_pdcp_info->large_cid_present) {
1413         offset = dissect_large_cid(tree, tvb, offset);
1414     }
1415
1416     /* T determines frame type */
1417     T = tvb_get_guint8(tvb, ++offset) >> 5;
1418     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type0_t, tvb, offset, 1, FALSE);
1419     if (T) {
1420         col_append_str(pinfo->cinfo, COL_INFO, " UO-1-TS");
1421         proto_item_append_text(root_item, " (UO-1-TS)");
1422     }
1423     else {
1424         col_append_str(pinfo->cinfo, COL_INFO, " UO-1-ID");
1425         proto_item_append_text(root_item, " (UO-1-ID)");
1426     }
1427
1428     if (p_pdcp_info->profile == 1) {
1429         /* TODO: */
1430     }
1431     else if (p_pdcp_info->profile == 2) {
1432         /* TODO: */
1433     }
1434
1435     return offset;
1436 }
1437
1438
1439
1440
1441
1442 /* Dissect UOR-2 packet.
1443    Return following offset */
1444 static int  dissect_pdcp_uor_2_packet(proto_tree *tree,
1445                                       proto_item *root_item,
1446                                       tvbuff_t *tvb,
1447                                       int offset,
1448                                       struct pdcp_lte_info *p_pdcp_info,
1449                                       packet_info *pinfo)
1450 {
1451     guint8 ts;
1452
1453     col_append_str(pinfo->cinfo, COL_INFO, " U0R-2");
1454     proto_item_append_text(root_item, " (UOR-2)");
1455
1456     /* TS straddles CID */
1457     ts = tvb_get_guint8(tvb, offset) & 0x1f;
1458     offset++;
1459
1460     /* Large CID */
1461     if (p_pdcp_info->large_cid_present) {
1462         offset = dissect_large_cid(tree, tvb, offset);
1463     }
1464
1465     /* Last bit of TS is here */
1466     ts = (ts << 1) | (tvb_get_guint8(tvb, offset) >> 7);
1467     proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1468
1469     if (p_pdcp_info->profile == 1) {
1470         /* M */
1471         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, FALSE);
1472
1473         /* SN (6 bits) */
1474         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_sn, tvb, offset, 1, FALSE);
1475         offset++;
1476
1477         /* X (one bit) */
1478         proto_tree_add_item(tree, hf_pdcp_lte_rohc_uor2_x, tvb, offset, 1, FALSE);
1479
1480         /* TODO: CRC */
1481         offset++;
1482     }
1483     else if (p_pdcp_info->profile == 2) {
1484         /* TODO: */
1485         offset += 2;
1486     }
1487
1488     return offset;
1489 }
1490
1491
1492 /* Dissect UOR-2-TS or UOR-2-ID packet.
1493    Return following offset */
1494 static int  dissect_pdcp_uor_2_ts_or_id_packet(proto_tree *tree,
1495                                                proto_item *root_item,
1496                                                tvbuff_t *tvb,
1497                                                int offset,
1498                                                struct pdcp_lte_info *p_pdcp_info,
1499                                                packet_info *pinfo)
1500 {
1501     unsigned char T;
1502
1503     /* TODO: octet before large-cid.
1504        TODO: can't decode this until we know what T is,
1505              but T is after large-cid... */
1506     offset++;
1507
1508     /* T determines frame type */
1509     T = tvb_get_guint8(tvb, offset) >> 7;
1510     proto_tree_add_item(tree, hf_pdcp_lte_rohc_type2_t, tvb, offset, 1, FALSE);
1511
1512     if (T) {
1513         col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-TS");
1514         proto_item_append_text(root_item, " (UOR-2-TS)");
1515     }
1516     else {
1517         col_append_str(pinfo->cinfo, COL_INFO, " U0R-2-ID");
1518         proto_item_append_text(root_item, " (UOR-2-ID)");
1519     }
1520
1521
1522     if (T) {
1523         /* UOR-2-TS format */
1524
1525         /* TS */
1526         guint8 ts = tvb_get_guint8(tvb, offset) & 0x1f;
1527         proto_tree_add_uint(tree, hf_pdcp_lte_rohc_ts, tvb, offset, 1, ts);
1528         offset++;
1529
1530         /* Large CID */
1531         if (p_pdcp_info->large_cid_present) {
1532             offset = dissect_large_cid(tree, tvb, offset);
1533         }
1534
1535         /* m */
1536         proto_tree_add_item(tree, hf_pdcp_lte_rohc_m, tvb, offset, 1, ts);
1537
1538         /* TODO: */
1539     }
1540     else {
1541         /* TODO: UOR-2-ID format */
1542
1543         /* IP-ID */
1544
1545         /* Large CID */
1546         if (p_pdcp_info->large_cid_present) {
1547             offset = dissect_large_cid(tree, tvb, offset);
1548         }
1549
1550         /* TODO: */
1551     }
1552
1553     if (p_pdcp_info->profile == 1) {
1554         /* TODO: */
1555     }
1556     else if (p_pdcp_info->profile == 2) {
1557         /* TODO: */
1558     }
1559
1560     return offset;
1561 }
1562
1563
1564
1565
1566 /* Show in the tree the config info attached to this frame, as generated fields */
1567 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1568                              pdcp_lte_info *p_pdcp_info)
1569 {
1570     proto_item *ti;
1571     proto_tree *configuration_tree;
1572     proto_item *configuration_ti = proto_tree_add_item(tree,
1573                                                        hf_pdcp_lte_configuration,
1574                                                        tvb, 0, 0, FALSE);
1575     configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1576
1577     /* Direction */
1578     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1579                              p_pdcp_info->direction);
1580     PROTO_ITEM_SET_GENERATED(ti);
1581
1582     /* Plane */
1583     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1584                              p_pdcp_info->plane);
1585     PROTO_ITEM_SET_GENERATED(ti);
1586
1587     /* UEId */
1588     if (p_pdcp_info->ueid != 0) {
1589         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
1590                                  p_pdcp_info->ueid);
1591         PROTO_ITEM_SET_GENERATED(ti);
1592     }
1593
1594     /* Channel type */
1595     ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
1596                              p_pdcp_info->channelType);
1597     PROTO_ITEM_SET_GENERATED(ti);
1598     if (p_pdcp_info->channelId != 0) {
1599         /* Channel type */
1600         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
1601                                  p_pdcp_info->channelId);
1602         PROTO_ITEM_SET_GENERATED(ti);
1603     }
1604
1605
1606     /* User-plane-specific fields */
1607     if (p_pdcp_info->plane == USER_PLANE) {
1608
1609         /* No Header PDU */
1610         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1611                                  p_pdcp_info->no_header_pdu);
1612         PROTO_ITEM_SET_GENERATED(ti);
1613
1614         if (!p_pdcp_info->no_header_pdu) {
1615
1616             /* Seqnum length */
1617             ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1618                                      p_pdcp_info->seqnum_length);
1619             PROTO_ITEM_SET_GENERATED(ti);
1620         }
1621     }
1622
1623     /* ROHC compression */
1624     ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1625                                 p_pdcp_info->rohc_compression);
1626     PROTO_ITEM_SET_GENERATED(ti);
1627
1628     /* ROHC-specific settings */
1629     if (p_pdcp_info->rohc_compression) {
1630
1631         /* Show ROHC mode */
1632         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1633                                  p_pdcp_info->mode);
1634         PROTO_ITEM_SET_GENERATED(ti);
1635
1636         /* Show RND */
1637         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1638                                  p_pdcp_info->rnd);
1639         PROTO_ITEM_SET_GENERATED(ti);
1640
1641         /* UDP Checksum */
1642         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1643                                  p_pdcp_info->udp_checkum_present);
1644         PROTO_ITEM_SET_GENERATED(ti);
1645
1646         /* ROHC profile */
1647         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1648                                  p_pdcp_info->profile);
1649         PROTO_ITEM_SET_GENERATED(ti);
1650
1651         /* CID Inclusion Info */
1652         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1653                                  p_pdcp_info->cid_inclusion_info);
1654         PROTO_ITEM_SET_GENERATED(ti);
1655
1656         /* Large CID */
1657         ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1658                                  p_pdcp_info->large_cid_present);
1659         PROTO_ITEM_SET_GENERATED(ti);
1660     }
1661
1662     /* Append summary to configuration root */
1663     proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1664                            val_to_str(p_pdcp_info->direction, direction_vals, "Unknown"),
1665                            val_to_str(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1666
1667     if (p_pdcp_info->rohc_compression) {
1668         const char *mode = val_to_str(p_pdcp_info->mode, rohc_mode_vals, "Error");
1669         proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1670                                mode[0],
1671                                val_to_str(p_pdcp_info->profile, rohc_profile_vals, "Unknown"));
1672     }
1673     proto_item_append_text(configuration_ti, ")");
1674     PROTO_ITEM_SET_GENERATED(configuration_ti);
1675
1676     /* Show plane in info column */
1677     col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1678                     val_to_str(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1679
1680 }
1681
1682
1683 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1684 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info  *p_pdcp_info)
1685 {
1686     dissector_handle_t rrc_handle = 0;
1687
1688     switch (p_pdcp_info->channelType)
1689     {
1690         case Channel_CCCH:
1691             if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1692                 rrc_handle = find_dissector("lte_rrc.ul_ccch");
1693             }
1694             else {
1695                 rrc_handle = find_dissector("lte_rrc.dl_ccch");
1696             }
1697             break;
1698         case Channel_PCCH:
1699             rrc_handle = find_dissector("lte-rrc.pcch");
1700             break;
1701         case Channel_BCCH:
1702             switch (p_pdcp_info->BCCHTransport) {
1703                 case BCH_TRANSPORT:
1704                     rrc_handle = find_dissector("lte-rrc.bcch.bch");
1705                     break;
1706                 case DLSCH_TRANSPORT:
1707                     rrc_handle = find_dissector("lte-rrc.bcch.dl.sch");
1708                     break;
1709             }
1710             break;
1711         case Channel_DCCH:
1712             if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1713                 rrc_handle = find_dissector("lte_rrc.ul_dcch");
1714             }
1715             else {
1716                 rrc_handle = find_dissector("lte_rrc.dl_dcch");
1717             }
1718             break;
1719
1720
1721         default:
1722             break;
1723     }
1724
1725     return rrc_handle;
1726 }
1727
1728
1729 /* Forwad declarations */
1730 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1731
1732 /* Heuristic dissection */
1733 static gboolean global_pdcp_lte_heur = FALSE;
1734
1735 /* Heuristic dissector looks for supported framing protocol (see wiki page)  */
1736 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1737                                      proto_tree *tree)
1738 {
1739     gint                 offset = 0;
1740     struct pdcp_lte_info *p_pdcp_lte_info;
1741     tvbuff_t             *pdcp_tvb;
1742     guint8               tag = 0;
1743     gboolean             infoAlreadySet = FALSE;
1744     gboolean             seqnumLengthTagPresent = FALSE;
1745
1746     /* This is a heuristic dissector, which means we get all the UDP
1747      * traffic not sent to a known dissector and not claimed by
1748      * a heuristic dissector called before us!
1749      */
1750
1751     if (!global_pdcp_lte_heur) {
1752         return FALSE;
1753     }
1754
1755     /* Do this again on re-dissection to re-discover offset of actual PDU */
1756
1757     /* Needs to be at least as long as:
1758        - the signature string
1759        - fixed header bytes
1760        - tag for data
1761        - at least one byte of PDCP PDU payload */
1762     if ((size_t)tvb_length_remaining(tvb, offset) < (strlen(PDCP_LTE_START_STRING)+3+2)) {
1763         return FALSE;
1764     }
1765
1766     /* OK, compare with signature string */
1767     if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1768         return FALSE;
1769     }
1770     offset += (gint)strlen(PDCP_LTE_START_STRING);
1771
1772
1773     /* If redissecting, use previous info struct (if available) */
1774     p_pdcp_lte_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1775     if (p_pdcp_lte_info == NULL) {
1776         /* Allocate new info struct for this frame */
1777         p_pdcp_lte_info = se_alloc0(sizeof(struct pdcp_lte_info));
1778         infoAlreadySet = FALSE;
1779     }
1780     else {
1781         infoAlreadySet = TRUE;
1782     }
1783
1784
1785     /* Read fixed fields */
1786     p_pdcp_lte_info->no_header_pdu = tvb_get_guint8(tvb, offset++);
1787     p_pdcp_lte_info->plane = tvb_get_guint8(tvb, offset++);
1788     p_pdcp_lte_info->rohc_compression = tvb_get_guint8(tvb, offset++);
1789
1790     /* Read optional fields */
1791     while (tag != PDCP_LTE_PAYLOAD_TAG) {
1792         /* Process next tag */
1793         tag = tvb_get_guint8(tvb, offset++);
1794         switch (tag) {
1795             case PDCP_LTE_SEQNUM_LENGTH_TAG:
1796                 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1797                 offset++;
1798                 seqnumLengthTagPresent = TRUE;
1799                 break;
1800             case PDCP_LTE_DIRECTION_TAG:
1801                 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1802                 offset++;
1803                 break;
1804             case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1805                 p_pdcp_lte_info->channelType = tvb_get_guint8(tvb, offset);
1806                 offset++;
1807                 break;
1808             case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1809                 p_pdcp_lte_info->BCCHTransport = tvb_get_guint8(tvb, offset);
1810                 offset++;
1811                 break;
1812             case PDCP_LTE_ROHC_IP_VERSION_TAG:
1813                 p_pdcp_lte_info->rohc_ip_version = tvb_get_ntohs(tvb, offset);
1814                 offset += 2;
1815                 break;
1816             case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1817                 p_pdcp_lte_info->cid_inclusion_info = tvb_get_guint8(tvb, offset);
1818                 offset++;
1819                 break;
1820             case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1821                 p_pdcp_lte_info->large_cid_present = tvb_get_guint8(tvb, offset);
1822                 offset++;
1823                 break;
1824             case PDCP_LTE_ROHC_MODE_TAG:
1825                 p_pdcp_lte_info->mode = tvb_get_guint8(tvb, offset);
1826                 offset++;
1827                 break;
1828             case PDCP_LTE_ROHC_RND_TAG:
1829                 p_pdcp_lte_info->rnd = tvb_get_guint8(tvb, offset);
1830                 offset++;
1831                 break;
1832             case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1833                 p_pdcp_lte_info->udp_checkum_present = tvb_get_guint8(tvb, offset);
1834                 offset++;
1835                 break;
1836             case PDCP_LTE_ROHC_PROFILE_TAG:
1837                 p_pdcp_lte_info->profile = tvb_get_ntohs(tvb, offset);
1838                 offset += 2;
1839                 break;
1840
1841             case PDCP_LTE_PAYLOAD_TAG:
1842                 /* Have reached data, so get out of loop */
1843                 continue;
1844
1845             default:
1846                 /* It must be a recognised tag */
1847                 return FALSE;
1848         }
1849     }
1850
1851     if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1852         /* Conditional field is not present */
1853         return FALSE;
1854     }
1855
1856     if (!infoAlreadySet) {
1857         /* Store info in packet */
1858         p_add_proto_data(pinfo->fd, proto_pdcp_lte, p_pdcp_lte_info);
1859     }
1860
1861     /**************************************/
1862     /* OK, now dissect as PDCP LTE        */
1863
1864     /* Create tvb that starts at actual PDCP PDU */
1865     pdcp_tvb = tvb_new_subset(tvb, offset, -1, tvb_reported_length(tvb)-offset);
1866     dissect_pdcp_lte(pdcp_tvb, pinfo, tree);
1867     return TRUE;
1868 }
1869
1870
1871 /******************************/
1872 /* Main dissection function.  */
1873 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1874 {
1875     const char         *mode;
1876     proto_tree         *pdcp_tree = NULL;
1877     proto_item         *root_ti = NULL;
1878     proto_tree         *rohc_tree = NULL;
1879     proto_item         *rohc_ti = NULL;
1880     gint               offset = 0;
1881     gint               rohc_offset;
1882     struct pdcp_lte_info  *p_pdcp_info;
1883     guint8             base_header_byte;
1884     gboolean           udp_checksum_needed = TRUE;
1885     gboolean           ip_id_needed = TRUE;
1886
1887     /* Append this protocol name rather than replace. */
1888     col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1889
1890     /* Create pdcp tree. */
1891     if (tree) {
1892         root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, FALSE);
1893         pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1894     }
1895
1896
1897     /* Look for attached packet info! */
1898     p_pdcp_info = p_get_proto_data(pinfo->fd, proto_pdcp_lte);
1899     /* Can't dissect anything without it... */
1900     if (p_pdcp_info == NULL) {
1901         return;
1902     }
1903
1904
1905     /* Set mode string */
1906     mode = val_to_str(p_pdcp_info->mode, rohc_mode_vals, "Error");
1907
1908     /* Show configuration (attached packet) info in tree */
1909     if (pdcp_tree) {
1910         show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1911     }
1912
1913     /* Show ROHC mode */
1914     if (p_pdcp_info->rohc_compression) {
1915         col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1916     }
1917
1918
1919     /* Handle PDCP header (if present) */
1920     if (!p_pdcp_info->no_header_pdu) {
1921
1922         /* TODO: shouldn't need to initialise this one!! */
1923         guint16  seqnum = 0;
1924         gboolean seqnum_set = FALSE;
1925
1926         /*****************************/
1927         /* Signalling plane messages */
1928         if (p_pdcp_info->plane == SIGNALING_PLANE) {
1929             guint32 mac;
1930             guint32 data_length;
1931
1932             /* 5-bit sequence number */
1933             seqnum = tvb_get_guint8(tvb, offset) & 0x1f;
1934             seqnum_set = TRUE;
1935             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, FALSE);
1936             col_append_fstr(pinfo->cinfo, COL_INFO, " sn=%-2u ", seqnum);
1937             offset++;
1938
1939
1940             /* RRC data is all but last 4 bytes.
1941                Call lte-rrc dissector (according to direction and channel type) */
1942             if (global_pdcp_dissect_signalling_plane_as_rrc) {
1943                 /* Get appropriate dissector handle */
1944                 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1945
1946                 if (rrc_handle != 0) {
1947                     /* Call RRC dissector if have one */
1948                     tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
1949                                                            tvb_length_remaining(tvb, offset) - 4,
1950                                                            tvb_length_remaining(tvb, offset) - 4);
1951                     call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
1952                 }
1953                 else {
1954                      /* Just show data */
1955                         proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1956                                             tvb_length_remaining(tvb, offset) - 4, FALSE);
1957                 }
1958             }
1959             else {
1960                 /* Just show as unparsed data */
1961                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
1962                                     tvb_length_remaining(tvb, offset) - 4, FALSE);
1963             }
1964
1965             data_length = tvb_length_remaining(tvb, offset) - 4;
1966             offset += data_length;
1967
1968             /* Last 4 bytes are MAC */
1969             mac = tvb_get_ntohl(tvb, offset);
1970             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, tvb, offset, 4, FALSE);
1971             offset += 4;
1972
1973             col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
1974                             mac, data_length);
1975
1976         }
1977         else if (p_pdcp_info->plane == USER_PLANE) {
1978
1979             /**********************************/
1980             /* User-plane messages            */
1981             gboolean pdu_type = (tvb_get_guint8(tvb, offset) & 0x80) >> 7;
1982
1983             /* Data/Control flag */
1984             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, FALSE);
1985
1986             if (pdu_type == 1) {
1987                 /*****************************/
1988                 /* Use-plane Data            */
1989
1990                 /* Number of sequence number bits depends upon config */
1991                 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_7_BITS) {
1992                     seqnum = tvb_get_guint8(tvb, offset) & 0x7f;
1993                     seqnum_set = TRUE;
1994                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, FALSE);
1995                     offset++;
1996                 }
1997                 else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
1998                     proto_item *ti;
1999                     guint8 reserved_value;
2000
2001                     /* 3 reserved bits */
2002                     ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, FALSE);
2003                     reserved_value = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
2004
2005                     /* Complain if not 0 */
2006                     if (reserved_value != 0) {
2007                         expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
2008                                                "Reserved bits have value 0x%x - should be 0x0",
2009                                                reserved_value);
2010                     }
2011
2012                     /* 12-bit sequence number */
2013                     seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
2014                     seqnum_set = TRUE;
2015                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, FALSE);
2016                     offset += 2;
2017                 }
2018                 else {
2019                     /* Not a recognised data format!!!!! */
2020                     return;
2021                 }
2022
2023                 col_append_fstr(pinfo->cinfo, COL_INFO, " sn=%-4u ", seqnum);
2024             }
2025             else {
2026                 /*******************************/
2027                 /* User-plane Control messages */
2028                 guint8 control_pdu_type = (tvb_get_guint8(tvb, offset) & 0x70) >> 4;
2029                 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, FALSE);
2030
2031                 switch (control_pdu_type) {
2032                     case 0:    /* PDCP status report */
2033                         {
2034                             guint16 fms;
2035                             guint   not_received = 0;
2036                             guint   sn;
2037                             proto_tree *bitmap_tree;
2038                             proto_item *bitmap_ti = NULL;
2039
2040                             /* First-Missing-Sequence SN */
2041                             fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
2042                             sn = (fms + 1) % 4096;
2043                             proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
2044                                                 offset, 2, FALSE);
2045                             offset += 2;
2046
2047                             /* Bitmap tree */
2048                             if (tvb_length_remaining(tvb, offset) > 0) {
2049                                 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
2050                                                                 offset, -1, FALSE);
2051                                 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_rohc_report_bitmap);
2052
2053
2054                                 /* For each byte... */
2055                                 for ( ; tvb_length_remaining(tvb, offset); offset++) {
2056                                     guint bit_offset = 0;
2057                                     /* .. look for error (0) in each bit */
2058                                     for ( ; bit_offset < 8; bit_offset++) {
2059                                         if ((tvb_get_guint8(tvb, offset) >> (7-bit_offset) & 0x1) == 0) {
2060                                             proto_tree_add_boolean_format_value(bitmap_tree, hf_pdcp_lte_bitmap_not_received, tvb, offset, 1, TRUE,
2061                                                                                 " (SN=%u)", sn);
2062                                             not_received++;
2063                                         }
2064                                         sn = (sn + 1) % 4096;
2065                                     }
2066                                 }
2067                             }
2068
2069                             if (bitmap_ti != NULL) {
2070                                 proto_item_append_text(bitmap_ti, " (not-received=%u)", not_received);
2071                             }
2072                             col_append_fstr(pinfo->cinfo, COL_INFO,
2073                                            " Status Report (fms=%u) not-received=%u",
2074                                            fms, not_received);
2075                         }
2076                         return;
2077
2078                     case 1:     /* ROHC Feedback */
2079                         offset++;
2080                         break;  /* Drop-through to dissect feedback */
2081
2082                     default:    /* Reserved */
2083                         return;
2084                 }
2085             }
2086         }
2087         else {
2088             /* Invalid plane setting...! */
2089             col_append_fstr(pinfo->cinfo, COL_INFO, " - INVALID PLANE (%u)",
2090                             p_pdcp_info->plane);
2091             return;
2092         }
2093
2094         /* For now, only do sequence analysis if RLC wasn't present in the frame */
2095         /* This can be fixed once RLC does re-assembly... */
2096         if (global_pdcp_check_sequence_numbers && seqnum_set &&
2097              (p_get_proto_data(pinfo->fd, proto_rlc_lte) == NULL)) {
2098
2099             checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
2100                                      (guint16)seqnum, pdcp_tree);
2101         }
2102
2103     }
2104     else {
2105         /* Show that its a no-header PDU */
2106         col_append_str(pinfo->cinfo, COL_INFO, " No-Header ");
2107     }
2108
2109
2110     /* If not compressed with ROHC, show as user-plane data */
2111     if (!p_pdcp_info->rohc_compression) {
2112         if (tvb_length_remaining(tvb, offset) > 0) {
2113             if (p_pdcp_info->plane == USER_PLANE) {
2114                 if (global_pdcp_dissect_user_plane_as_ip) {
2115                     tvbuff_t *payload_tvb = tvb_new_subset_remaining(tvb, offset);
2116                     call_dissector_only(ip_handle, payload_tvb, pinfo, pdcp_tree);
2117                 }
2118                 else {
2119                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, tvb, offset, -1, FALSE);
2120                 }
2121             }
2122             else {
2123                 if (global_pdcp_dissect_signalling_plane_as_rrc) {
2124                     /* Get appropriate dissector handle */
2125                     dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
2126
2127                     if (rrc_handle != 0) {
2128                         /* Call RRC dissector if have one */
2129                         tvbuff_t *payload_tvb = tvb_new_subset(tvb, offset,
2130                                                                tvb_length_remaining(tvb, offset),
2131                                                                tvb_length_remaining(tvb, offset));
2132                         call_dissector_only(rrc_handle, payload_tvb, pinfo, pdcp_tree);
2133                     }
2134                     else {
2135                          /* Just show data */
2136                          proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset,
2137                                              tvb_length_remaining(tvb, offset), FALSE);
2138                     }
2139                 }
2140                 else {
2141                     proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, tvb, offset, -1, FALSE);
2142                 }
2143             }
2144
2145             col_append_fstr(pinfo->cinfo, COL_INFO, "(%u bytes data)",
2146                             tvb_length_remaining(tvb, offset));
2147         }
2148         return;
2149     }
2150
2151
2152     /***************************/
2153     /* ROHC packets            */
2154     /***************************/
2155
2156     col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2157                     val_to_str(p_pdcp_info->profile, rohc_profile_vals, "Unkown"));
2158
2159     /* Only attempt ROHC if configured to */
2160     if (!global_pdcp_dissect_rohc) {
2161         return;
2162     }
2163
2164     /* Create pdcp tree. */
2165     if (pdcp_tree) {
2166         rohc_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_rohc, tvb, offset, -1, FALSE);
2167         rohc_tree = proto_item_add_subtree(rohc_ti, ett_pdcp_rohc);
2168     }
2169
2170     rohc_offset = offset;
2171
2172     /* Skip any leading padding octets (11100000) */
2173     while (tvb_get_guint8(tvb, offset) == 0xe0) {
2174         offset++;
2175     }
2176     if (offset > rohc_offset) {
2177         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_padding, tvb, rohc_offset,
2178                             offset-rohc_offset, FALSE);
2179     }
2180
2181     /* Add-CID octet */
2182     if ((p_pdcp_info->cid_inclusion_info == CID_IN_ROHC_PACKET) &&
2183         !p_pdcp_info->large_cid_present)
2184     {
2185         if (((tvb_get_guint8(tvb, offset) >> 4) & 0x0f) == 0x0e) {
2186             proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 1, FALSE);
2187             offset++;
2188         }
2189         else {
2190             /* Assume CID value of 0 if field absent */
2191             proto_item *ti = proto_tree_add_uint(rohc_tree, hf_pdcp_lte_rohc_add_cid, tvb, offset, 0, 0);
2192             PROTO_ITEM_SET_GENERATED(ti);
2193         }
2194     }
2195
2196     /* Now look at first octet of base header and identify packet type */
2197     base_header_byte = tvb_get_guint8(tvb, offset);
2198
2199     /* IR (1111110) */
2200     if ((base_header_byte & 0xfe) == 0xfc) {
2201         offset = dissect_pdcp_ir_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2202         udp_checksum_needed = FALSE;
2203         ip_id_needed = FALSE;
2204     }
2205
2206     /* IRDYN (11111000) */
2207     else if (base_header_byte == 0xf8) {
2208         offset = dissect_pdcp_irdyn_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2209         udp_checksum_needed = FALSE;
2210         ip_id_needed = FALSE;
2211     }
2212
2213     /* Feedback (begins with 11110) */
2214     else if (((base_header_byte & 0xf8) >> 3) == 0x1e) {
2215         offset = dissect_pdcp_feedback_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2216         return;
2217     }
2218
2219     /* Packet type 0 (0) */
2220     else if ((base_header_byte & 0x80) == 0) {
2221
2222         /* TODO: decide type based upon:
2223            - mode
2224            - 2nd bit
2225            - length remaining (taking into account large-cid) */
2226
2227         /* R-0 begins with 00 */
2228         if (((base_header_byte & 0xc0) == 0) &&
2229              (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
2230
2231             offset = dissect_pdcp_r_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2232         }
2233
2234         /* R-0-CRC begins with 01 */
2235         else if ((((base_header_byte & 0x40) >> 6) == 1) &&
2236                   (p_pdcp_info->mode == RELIABLE_BIDIRECTIONAL)) {
2237
2238             offset = dissect_pdcp_r_0_crc_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2239         }
2240
2241         else {
2242             offset = dissect_pdcp_uo_0_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2243         }
2244     }
2245
2246     /* Packet type 1 (10) */
2247     else if (((base_header_byte & 0xc0) >> 6) == 2) {
2248
2249         switch (p_pdcp_info->mode) {
2250
2251             case RELIABLE_BIDIRECTIONAL:
2252                  /* R-1 if !(ipv4 && rand) */
2253                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
2254                       (!p_pdcp_info->rnd))) {
2255                     offset = dissect_pdcp_r_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2256                     return;
2257                  }
2258                 else {
2259                     /* Whether its R-1-ID or R-1-TS depends upon T bit */
2260                     dissect_pdcp_r_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2261                     return;
2262                 }
2263                 break;
2264
2265             case UNIDIRECTIONAL:
2266             case OPTIMISTIC_BIDIRECTIONAL:
2267                  /* UO-1 if !(ipv4 && rand) */
2268                  if (!((p_pdcp_info->rohc_ip_version == 4) &&
2269                       (!p_pdcp_info->rnd))) {
2270                     offset = dissect_pdcp_uo_1_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2271                     return;
2272                  }
2273                 else {
2274                     /* Whether its UO-1-ID or UO-1-TS depends upon T bit */
2275                     dissect_pdcp_uo_1_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2276                     return;
2277                 }
2278
2279                 return;
2280
2281         }
2282     }
2283
2284     /* Packet type 2 (110) */
2285     else if (((base_header_byte & 0xe0) >> 5) == 6) {
2286
2287         /* UOR-2 if !(ipv4 && rand) */
2288         if (!((p_pdcp_info->rohc_ip_version == 4) &&
2289               (!p_pdcp_info->rnd))) {
2290
2291             offset = dissect_pdcp_uor_2_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2292         }
2293         else {
2294             /* Whether its UOR-2-ID or UOR-2-TS depends upon T bit */
2295             dissect_pdcp_uor_2_ts_or_id_packet(rohc_tree, rohc_ti, tvb, offset, p_pdcp_info, pinfo);
2296             return;
2297         }
2298     }
2299
2300     /* Segment (1111111) */
2301     else if ((base_header_byte & 0xfe) == 0xfe) {
2302         /* TODO: */
2303         return;
2304     }
2305
2306
2307     /* Fields beyond base header */
2308
2309     /* These 2 fields not present for IR, IR-DYN frames */
2310
2311     /* IP-ID */
2312     if (p_pdcp_info->rnd && ip_id_needed) {
2313         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_ip_id, tvb, offset, 2, FALSE);
2314         offset += 2;
2315     }
2316
2317     /* UDP Checksum */
2318     if (p_pdcp_info->udp_checkum_present && udp_checksum_needed) {
2319         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_udp_checksum, tvb, offset, 2, FALSE);
2320         offset += 2;
2321     }
2322
2323     /* Payload */
2324     if (tvb_reported_length_remaining(tvb, offset) > 0) {
2325         proto_tree_add_item(rohc_tree, hf_pdcp_lte_rohc_payload, tvb, offset, -1, FALSE);
2326     }
2327 }
2328
2329 /* Initializes the hash table and the mem_chunk area each time a new
2330  * file is loaded or re-loaded in wireshark */
2331 static void
2332 pdcp_lte_init_protocol(void)
2333 {
2334     /* Destroy any existing hashes. */
2335     if (pdcp_sequence_analysis_channel_hash) {
2336         g_hash_table_destroy(pdcp_sequence_analysis_channel_hash);
2337     }
2338     if (pdcp_lte_frame_sequence_analysis_report_hash) {
2339         g_hash_table_destroy(pdcp_lte_frame_sequence_analysis_report_hash);
2340     }
2341
2342
2343     /* Now create them over */
2344     pdcp_sequence_analysis_channel_hash = g_hash_table_new(pdcp_channel_hash_func, pdcp_channel_equal);
2345     pdcp_lte_frame_sequence_analysis_report_hash = g_hash_table_new(pdcp_frame_hash_func, pdcp_frame_equal);
2346 }
2347
2348
2349
2350 void proto_register_pdcp(void)
2351 {
2352     static hf_register_info hf[] =
2353     {
2354         { &hf_pdcp_lte_configuration,
2355             { "Configuration",
2356               "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2357               "Configuration info passed into dissector", HFILL
2358             }
2359         },
2360
2361         { &hf_pdcp_lte_rohc_compression,
2362             { "ROHC Compression",
2363               "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2364               NULL, HFILL
2365             }
2366         },
2367         { &hf_pdcp_lte_rohc_mode,
2368             { "ROHC Mode",
2369               "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2370               NULL, HFILL
2371             }
2372         },
2373         { &hf_pdcp_lte_rohc_rnd,
2374             { "RND",  /* TODO: true/false vals? */
2375               "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
2376               "RND of outer ip header", HFILL
2377             }
2378         },
2379         { &hf_pdcp_lte_rohc_udp_checksum_present,
2380             { "UDP Checksum",  /* TODO: true/false vals? */
2381               "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2382               "UDP Checksum present", HFILL
2383             }
2384         },
2385         { &hf_pdcp_lte_direction,
2386             { "Direction",
2387               "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2388               "Direction of message", HFILL
2389             }
2390         },
2391         { &hf_pdcp_lte_ueid,
2392             { "UE",
2393               "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2394               "UE Identifier", HFILL
2395             }
2396         },
2397         { &hf_pdcp_lte_channel_type,
2398             { "Channel type",
2399               "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
2400               NULL, HFILL
2401             }
2402         },
2403         { &hf_pdcp_lte_channel_id,
2404             { "Channel Id",
2405               "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
2406               NULL, HFILL
2407             }
2408         },
2409         { &hf_pdcp_lte_rohc_profile,
2410             { "ROHC profile",
2411               "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2412               "ROHC Mode", HFILL
2413             }
2414         },
2415         { &hf_pdcp_lte_no_header_pdu,
2416             { "No Header PDU",
2417               "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
2418               NULL, HFILL
2419             }
2420         },
2421         { &hf_pdcp_lte_plane,
2422             { "Plane",
2423               "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2424               NULL, HFILL
2425             }
2426         },
2427         { &hf_pdcp_lte_seqnum_length,
2428             { "Seqnum length",
2429               "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2430               "Sequence Number Length", HFILL
2431             }
2432         },
2433
2434
2435         { &hf_pdcp_lte_cid_inclusion_info,
2436             { "CID Inclusion Info",
2437               "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
2438               NULL, HFILL
2439             }
2440         },
2441         { &hf_pdcp_lte_large_cid_present,
2442             { "Large CID Present",
2443               "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2444               NULL, HFILL
2445             }
2446         },
2447
2448         { &hf_pdcp_lte_seq_num_5,
2449             { "Seq Num",
2450               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
2451               "PDCP Seq num", HFILL
2452             }
2453         },
2454         { &hf_pdcp_lte_seq_num_7,
2455             { "Seq Num",
2456               "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
2457               "PDCP Seq num", HFILL
2458             }
2459         },
2460         { &hf_pdcp_lte_reserved3,
2461             { "Reserved",
2462               "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2463               "3 reserved bits", HFILL
2464             }
2465         },
2466         { &hf_pdcp_lte_seq_num_12,
2467             { "Seq Num",
2468               "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2469               "PDCP Seq num", HFILL
2470             }
2471         },
2472         { &hf_pdcp_lte_signalling_data,
2473             { "Signalling Data",
2474               "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2475               NULL, HFILL
2476             }
2477         },
2478         { &hf_pdcp_lte_mac,
2479             { "MAC",
2480               "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
2481               NULL, HFILL
2482             }
2483         },
2484         { &hf_pdcp_lte_data_control,
2485             { "PDU Type",
2486               "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
2487               NULL, HFILL
2488             }
2489         },
2490         { &hf_pdcp_lte_user_plane_data,
2491             { "User-Plane Data",
2492               "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2493               NULL, HFILL
2494             }
2495         },
2496         { &hf_pdcp_lte_control_pdu_type,
2497             { "Control PDU Type",
2498               "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2499               NULL, HFILL
2500             }
2501         },
2502         { &hf_pdcp_lte_fms,
2503             { "First Missing Sequence Number",
2504               "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2505               "First Missing PDCP Sequence Number", HFILL
2506             }
2507         },
2508         { &hf_pdcp_lte_bitmap,
2509             { "Bitmap",
2510               "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2511               "Status report bitmap (0=error, 1=OK)", HFILL
2512             }
2513         },
2514         { &hf_pdcp_lte_bitmap_not_received,
2515             { "Not Received",
2516               "pdcp-lte.bitmap.error", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2517               "Status report PDU error", HFILL
2518             }
2519         },
2520
2521
2522         { &hf_pdcp_lte_sequence_analysis,
2523             { "Sequence Analysis",
2524               "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2525               NULL, HFILL
2526             }
2527         },
2528         { &hf_pdcp_lte_sequence_analysis_ok,
2529             { "OK",
2530               "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2531               NULL, HFILL
2532             }
2533         },
2534         { &hf_pdcp_lte_sequence_analysis_previous_frame,
2535             { "Previous frame for channel",
2536               "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2537               NULL, HFILL
2538             }
2539         },
2540         { &hf_pdcp_lte_sequence_analysis_expected_sn,
2541             { "Expected SN",
2542               "pdcp-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2543               NULL, HFILL
2544             }
2545         },
2546         { &hf_pdcp_lte_sequence_analysis_skipped,
2547             { "Skipped frames",
2548               "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2549               NULL, HFILL
2550             }
2551         },
2552         { &hf_pdcp_lte_sequence_analysis_repeated,
2553             { "Repeated frame",
2554               "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2555               NULL, HFILL
2556             }
2557         },
2558
2559         { &hf_pdcp_lte_rohc,
2560             { "ROHC Message",
2561               "pdcp-lte.rohc", FT_NONE, BASE_NONE, NULL, 0,
2562               NULL, HFILL
2563             }
2564         },
2565
2566         { &hf_pdcp_lte_rohc_padding,
2567             { "Padding",
2568               "pdcp-lte.rohc.padding", FT_NONE, BASE_NONE, NULL, 0,
2569               "ROHC Padding", HFILL
2570             }
2571         },
2572         { &hf_pdcp_lte_rohc_r_0_crc,
2573             { "R-0-CRC Packet",
2574               "pdcp-lte.r-0-crc", FT_NONE, BASE_NONE, NULL, 0,
2575               NULL, HFILL
2576             }
2577         },
2578         { &hf_pdcp_lte_rohc_feedback,
2579             { "Feedback",
2580               "pdcp-lte.rohc.feedback", FT_NONE, BASE_NONE, NULL, 0,
2581               "Feedback Packet", HFILL
2582             }
2583         },
2584         { &hf_pdcp_lte_rohc_type0_t,
2585             { "T",
2586               "pdcp-lte.rohc.t0.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x20,
2587               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2588             }
2589         },
2590         { &hf_pdcp_lte_rohc_type1_t,
2591             { "T",
2592               "pdcp-lte.rohc.t1.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2593               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2594             }
2595         },
2596         { &hf_pdcp_lte_rohc_type2_t,
2597             { "T",
2598               "pdcp-lte.rohc.t2.t", FT_UINT8, BASE_HEX, VALS(t_vals), 0x80,
2599               "Indicates whether frame type is TS (1) or ID (0)", HFILL
2600             }
2601         },
2602         { &hf_pdcp_lte_rohc_d,
2603             { "D",
2604               "pdcp-lte.rohc.d", FT_UINT8, BASE_HEX, NULL, 0x01,
2605               "Indicates whether Dynamic chain is present", HFILL
2606             }
2607         },
2608         { &hf_pdcp_lte_rohc_ir_crc,
2609             { "CRC",
2610               "pdcp-lte.rohc.ir.crc", FT_UINT8, BASE_HEX, NULL, 0x0,
2611               "8-bit CRC", HFILL
2612             }
2613         },
2614
2615         { &hf_pdcp_lte_rohc_static_ipv4,
2616             { "Static IPv4 chain",
2617               "pdcp-lte.rohc.static.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2618               NULL, HFILL
2619             }
2620         },
2621         { &hf_pdcp_lte_rohc_ip_version,
2622             { "IP Version",
2623               "pdcp-lte.rohc.ip-version", FT_UINT8, BASE_HEX, NULL, 0xf0,
2624               NULL, HFILL
2625             }
2626         },
2627         /* TODO: create/use value_string */
2628         { &hf_pdcp_lte_rohc_ip_protocol,
2629             { "IP Protocol",
2630               "pdcp-lte.rohc.ip-protocol", FT_UINT8, BASE_DEC, VALS(ip_protocol_vals), 0x0,
2631               NULL, HFILL
2632             }
2633         },
2634         { &hf_pdcp_lte_rohc_ip_src,
2635             { "IP Source address",
2636               "pdcp-lte.rohc.ip-src", FT_IPv4, BASE_NONE, NULL, 0x0,
2637               NULL, HFILL
2638             }
2639         },
2640         { &hf_pdcp_lte_rohc_ip_dst,
2641             { "IP Destination address",
2642               "pdcp-lte.rohc.ip-dst", FT_IPv4, BASE_NONE, NULL, 0x0,
2643               NULL, HFILL
2644             }
2645         },
2646
2647         { &hf_pdcp_lte_rohc_static_udp,
2648             { "Static UDP chain",
2649               "pdcp-lte.rohc.static.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2650               NULL, HFILL
2651             }
2652         },
2653         { &hf_pdcp_lte_rohc_static_udp_src_port,
2654             { "Static UDP source port",
2655               "pdcp-lte.rohc.static.udp.src-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2656               NULL, HFILL
2657             }
2658         },
2659         { &hf_pdcp_lte_rohc_static_udp_dst_port,
2660             { "Static UDP destination port",
2661               "pdcp-lte.rohc.static.udp.dst-port", FT_UINT16, BASE_DEC, NULL, 0x0,
2662               NULL, HFILL
2663             }
2664         },
2665         { &hf_pdcp_lte_rohc_static_rtp,
2666             { "Static RTP chain",
2667               "pdcp-lte.rohc.static.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2668               NULL, HFILL
2669             }
2670         },
2671         { &hf_pdcp_lte_rohc_static_rtp_ssrc,
2672             { "SSRC",
2673               "pdcp-lte.rohc.static.rtp.ssrc", FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
2674               "Static RTP chain SSRC", HFILL
2675             }
2676         },
2677
2678         { &hf_pdcp_lte_rohc_dynamic_ipv4,
2679             { "Dynamic IPv4 chain",
2680               "pdcp-lte.rohc.dynamic.ipv4", FT_NONE, BASE_NONE, NULL, 0x0,
2681               NULL, HFILL
2682             }
2683         },
2684         { &hf_pdcp_lte_rohc_dynamic_ipv4_tos,
2685             { "ToS",
2686               "pdcp-lte.rohc.ip.tos", FT_UINT8, BASE_HEX, NULL, 0x0,
2687               "IP Type of Service", HFILL
2688             }
2689         },
2690         { &hf_pdcp_lte_rohc_dynamic_ipv4_ttl,
2691             { "TTL",
2692               "pdcp-lte.rohc.ip.ttl", FT_UINT8, BASE_HEX, NULL, 0x0,
2693               "IP Time To Live", HFILL
2694             }
2695         },
2696         { &hf_pdcp_lte_rohc_dynamic_ipv4_id,
2697             { "IP-ID",
2698               "pdcp-lte.rohc.ip.id", FT_UINT8, BASE_HEX, NULL, 0x0,
2699               "IP ID", HFILL
2700             }
2701         },
2702         { &hf_pdcp_lte_rohc_dynamic_ipv4_df,
2703             { "Don't Fragment",
2704               "pdcp-lte.rohc.ip.df", FT_UINT8, BASE_HEX, NULL, 0x80,
2705               "IP Don't Fragment flag", HFILL
2706             }
2707         },
2708         { &hf_pdcp_lte_rohc_dynamic_ipv4_rnd,
2709             { "Random IP-ID field",
2710               "pdcp-lte.rohc.ip.rnd", FT_UINT8, BASE_HEX, NULL, 0x40,
2711               NULL, HFILL
2712             }
2713         },
2714         { &hf_pdcp_lte_rohc_dynamic_ipv4_nbo,
2715             { "Network Byte Order IP-ID field",
2716               "pdcp-lte.rohc.ip.nbo", FT_UINT8, BASE_HEX, NULL, 0x20,
2717               NULL, HFILL
2718             }
2719         },
2720         { &hf_pdcp_lte_rohc_dynamic_udp,
2721             { "Dynamic UDP chain",
2722               "pdcp-lte.rohc.dynamic.udp", FT_NONE, BASE_NONE, NULL, 0x0,
2723               NULL, HFILL
2724             }
2725         },
2726         { &hf_pdcp_lte_rohc_dynamic_udp_checksum,
2727             { "UDP Checksum",
2728               "pdcp-lte.rohc.dynamic.udp.checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2729               NULL, HFILL
2730             }
2731         },
2732         { &hf_pdcp_lte_rohc_dynamic_udp_seqnum,
2733             { "UDP Sequence Number",
2734               "pdcp-lte.rohc.dynamic.udp.seqnum", FT_UINT16, BASE_HEX, NULL, 0x0,
2735               NULL, HFILL
2736             }
2737         },
2738
2739         { &hf_pdcp_lte_rohc_dynamic_rtp,
2740             { "Dynamic RTP chain",
2741               "pdcp-lte.rohc.dynamic.rtp", FT_NONE, BASE_NONE, NULL, 0x0,
2742               NULL, HFILL
2743             }
2744         },
2745         { &hf_pdcp_lte_rohc_dynamic_rtp_rx,
2746             { "RX",
2747               "pdcp-lte.rohc.dynamic.rtp.rx", FT_UINT8, BASE_DEC, NULL, 0x10,
2748               NULL, HFILL
2749             }
2750         },
2751         { &hf_pdcp_lte_rohc_dynamic_rtp_cc,
2752             { "Contributing CSRCs",
2753               "pdcp-lte.rohc.dynamic.rtp.cc", FT_UINT8, BASE_DEC, NULL, 0x0f,
2754               "Dynamic RTP chain CCs", HFILL
2755             }
2756         },
2757         { &hf_pdcp_lte_rohc_dynamic_rtp_seqnum,
2758             { "RTP Sequence Number",
2759               "pdcp-lte.rohc.dynamic.rtp.seqnum", FT_UINT16, BASE_DEC, NULL, 0x0,
2760               "Dynamic RTP chain Sequence Number", HFILL
2761             }
2762         },
2763         { &hf_pdcp_lte_rohc_dynamic_rtp_timestamp,
2764             { "RTP Timestamp",
2765               "pdcp-lte.rohc.dynamic.rtp.timestamp", FT_UINT32, BASE_DEC, NULL, 0x0,
2766               "Dynamic RTP chain Timestamp", HFILL
2767             }
2768         },
2769         { &hf_pdcp_lte_rohc_dynamic_rtp_reserved3,
2770             { "Reserved",
2771               "pdcp-lte.rohc.dynamic.rtp.reserved3", FT_UINT8, BASE_HEX, NULL, 0xc0,
2772               "Reserved bits", HFILL
2773             }
2774         },
2775         { &hf_pdcp_lte_rohc_dynamic_rtp_x,
2776             { "X",
2777               "pdcp-lte.rohc.dynamic.rtp.x", FT_UINT8, BASE_DEC, NULL, 0x10,
2778               NULL, HFILL
2779             }
2780         },
2781         { &hf_pdcp_lte_rohc_dynamic_rtp_mode,
2782             { "Mode",
2783               "pdcp-lte.rohc.dynamic.rtp.mode", FT_UINT8, BASE_HEX, VALS(rohc_mode_vals), 0x0c,
2784               NULL, HFILL
2785             }
2786         },
2787         { &hf_pdcp_lte_rohc_dynamic_rtp_tis,
2788             { "TIS",
2789               "pdcp-lte.rohc.dynamic.rtp.tis", FT_UINT8, BASE_HEX, NULL, 0x02,
2790               "Dynamic RTP chain TIS (indicates time_stride present)", HFILL
2791             }
2792         },
2793         { &hf_pdcp_lte_rohc_dynamic_rtp_tss,
2794             { "TSS",
2795               "pdcp-lte.rohc.dynamic.rtp.tss", FT_UINT8, BASE_HEX, NULL, 0x01,
2796               "Dynamic RTP chain TSS (indicates TS_stride present)", HFILL
2797             }
2798         },
2799         { &hf_pdcp_lte_rohc_dynamic_rtp_ts_stride,
2800             { "TS Stride",
2801               "pdcp-lte.rohc.dynamic.rtp.ts-stride", FT_UINT32, BASE_DEC, NULL, 0x0,
2802               "Dynamic RTP chain TS Stride", HFILL
2803             }
2804         },
2805         { &hf_pdcp_lte_rohc_ts,
2806             { "TS",
2807               "pdcp-lte.rohc.ts", FT_UINT8, BASE_DEC, NULL, 0x0,
2808               NULL, HFILL
2809             }
2810         },
2811         { &hf_pdcp_lte_rohc_m,
2812             { "M",
2813               "pdcp-lte.rohc.m", FT_UINT8, BASE_DEC, NULL, 0x40,
2814               NULL, HFILL
2815             }
2816         },
2817         { &hf_pdcp_lte_rohc_uor2_sn,
2818             { "SN",
2819               "pdcp-lte.rohc.uor2.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2820               NULL, HFILL
2821             }
2822         },
2823         { &hf_pdcp_lte_rohc_uor2_x,
2824             { "X",
2825               "pdcp-lte.rohc.uor2.x", FT_UINT8, BASE_DEC, NULL, 0x80,
2826               NULL, HFILL
2827             }
2828         },
2829
2830         { &hf_pdcp_lte_rohc_add_cid,
2831             { "Add-CID",
2832               "pdcp-lte.rohc.add-cid", FT_UINT8, BASE_DEC, NULL, 0x0f,
2833               NULL, HFILL
2834             }
2835         },
2836         { &hf_pdcp_lte_rohc_large_cid,
2837             { "Large-CID",
2838               "pdcp-lte.rohc.large-cid", FT_UINT16, BASE_DEC, NULL, 0x07ff,
2839               NULL, HFILL
2840             }
2841         },
2842         { &hf_pdcp_lte_rohc_uo0_sn,
2843             { "SN",
2844               "pdcp-lte.rohc.uo0.sn", FT_UINT8, BASE_DEC, NULL, 0x78,
2845               NULL, HFILL
2846             }
2847         },
2848         { &hf_pdcp_lte_rohc_uo0_crc,
2849             { "CRC",
2850               "pdcp-lte.rohc.uo0.crc", FT_UINT8, BASE_DEC, NULL, 0x07,
2851               "3-bit CRC", HFILL
2852             }
2853         },
2854         { &hf_pdcp_lte_rohc_r0_sn,
2855             { "SN",
2856               "pdcp-lte.rohc.r0.sn", FT_UINT8, BASE_DEC, NULL, 0x3f,
2857               NULL, HFILL
2858             }
2859         },
2860         { &hf_pdcp_lte_rohc_r0_crc_sn,
2861             { "SN",
2862               "pdcp-lte.rohc.r0-crc.sn", FT_UINT16, BASE_DEC, NULL, 0x0,
2863               NULL, HFILL
2864             }
2865         },
2866         { &hf_pdcp_lte_rohc_r0_crc_crc,
2867             { "CRC7",
2868               "pdcp-lte.rohc.r0-crc.crc", FT_UINT8, BASE_DEC, NULL, 0x7f,
2869               "CRC 7", HFILL
2870             }
2871         },
2872         { &hf_pdcp_lte_rohc_feedback_code,
2873             { "Code",
2874               "pdcp-lte.rohc.feedback-code", FT_UINT8, BASE_DEC, NULL, 0x07,
2875               "Feedback options length (if > 0)", HFILL
2876             }
2877         },
2878         { &hf_pdcp_lte_rohc_feedback_size,
2879             { "Size",
2880               "pdcp-lte.rohc.feedback-size", FT_UINT8, BASE_DEC, NULL, 0x0,
2881               "Feedback options length", HFILL
2882             }
2883         },
2884         { &hf_pdcp_lte_rohc_feedback_feedback1,
2885             { "FEEDBACK-1 (SN)",
2886               "pdcp-lte.rohc.feedback.feedback1", FT_UINT8, BASE_DEC, NULL, 0x0,
2887               "Feedback-1", HFILL
2888             }
2889         },
2890         { &hf_pdcp_lte_rohc_feedback_feedback2,
2891             { "FEEDBACK-2",
2892               "pdcp-lte.rohc.feedback.feedback2", FT_NONE, BASE_NONE, NULL, 0x0,
2893               NULL, HFILL
2894             }
2895         },
2896
2897         { &hf_pdcp_lte_rohc_feedback_ack_type,
2898             { "Acktype",
2899               "pdcp-lte.rohc.feedback-acktype", FT_UINT8, BASE_DEC, VALS(feedback_ack_vals), 0xc0,
2900               "Feedback-2 ack type", HFILL
2901             }
2902         },
2903         { &hf_pdcp_lte_rohc_feedback_mode,
2904             { "mode",
2905               "pdcp-lte.rohc.feedback-mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x30,
2906               "Feedback mode", HFILL
2907             }
2908         },
2909         { &hf_pdcp_lte_rohc_feedback_sn,
2910             { "SN",
2911               "pdcp-lte.rohc.feedback-sn", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2912               "Feedback sequence number", HFILL
2913             }
2914         },
2915
2916         { &hf_pdcp_lte_rohc_feedback_option,
2917             { "Option",
2918               "pdcp-lte.rohc.feedback-option", FT_UINT8, BASE_DEC, VALS(feedback_option_vals), 0xf0,
2919               "Feedback option", HFILL
2920             }
2921         },
2922         { &hf_pdcp_lte_rohc_feedback_length,
2923             { "Length",
2924               "pdcp-lte.rohc.feedback-length", FT_UINT8, BASE_DEC, NULL, 0x0f,
2925               "Feedback length", HFILL
2926             }
2927         },
2928         { &hf_pdcp_lte_rohc_feedback_crc,
2929             { "CRC",
2930               "pdcp-lte.rohc.feedback-crc", FT_UINT8, BASE_HEX_DEC, NULL, 0x0,
2931               "Feedback CRC", HFILL
2932             }
2933         },
2934         { &hf_pdcp_lte_rohc_feedback_option_sn,
2935             { "SN",
2936               "pdcp-lte.rohc.feedback-option-sn", FT_UINT8, BASE_DEC, NULL, 0x0,
2937               "Feedback Option SN", HFILL
2938             }
2939         },
2940         { &hf_pdcp_lte_rohc_feedback_option_clock,
2941             { "Clock",
2942               "pdcp-lte.rohc.feedback-option-clock", FT_UINT8, BASE_DEC, NULL, 0x0,
2943               "Feedback Option Clock", HFILL
2944             }
2945         },
2946
2947         { &hf_pdcp_lte_rohc_ip_id,
2948             { "IP-ID",
2949               "pdcp-lte.rohc.ip-id", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2950               NULL, HFILL
2951             }
2952         },
2953         { &hf_pdcp_lte_rohc_udp_checksum,
2954             { "UDP Checksum",
2955               "pdcp-lte.rohc.udp-checksum", FT_UINT16, BASE_HEX_DEC, NULL, 0x0,
2956               NULL, HFILL
2957             }
2958         },
2959         { &hf_pdcp_lte_rohc_payload,
2960             { "Payload",
2961               "pdcp-lte.rohc.payload", FT_BYTES, BASE_NONE, NULL, 0x0,
2962               NULL, HFILL
2963             }
2964         },
2965
2966     };
2967
2968     static gint *ett[] =
2969     {
2970         &ett_pdcp,
2971         &ett_pdcp_configuration,
2972         &ett_pdcp_packet,
2973         &ett_pdcp_lte_sequence_analysis,
2974         &ett_pdcp_rohc,
2975         &ett_pdcp_rohc_static_ipv4,
2976         &ett_pdcp_rohc_static_udp,
2977         &ett_pdcp_rohc_static_rtp,
2978         &ett_pdcp_rohc_dynamic_ipv4,
2979         &ett_pdcp_rohc_dynamic_udp,
2980         &ett_pdcp_rohc_dynamic_rtp,
2981         &ett_pdcp_rohc_report_bitmap
2982     };
2983
2984     module_t *pdcp_lte_module;
2985
2986     /* Register protocol. */
2987     proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
2988     proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
2989     proto_register_subtree_array(ett, array_length(ett));
2990
2991     /* Allow other dissectors to find this one by name. */
2992     register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
2993
2994     pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
2995
2996     /* Dissect uncompressed user-plane data as IP */
2997     prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
2998         "Show uncompressed User-Plane data as IP",
2999         "Show uncompressed User-Plane data as IP",
3000         &global_pdcp_dissect_user_plane_as_ip);
3001
3002     /* Dissect unciphered signalling data as RRC */
3003     prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
3004         "Show unciphered Signalling-Plane data as RRC",
3005         "Show unciphered Signalling-Plane data as RRC",
3006         &global_pdcp_dissect_signalling_plane_as_rrc);
3007
3008     /* Check for missing sequence numbers */
3009     prefs_register_bool_preference(pdcp_lte_module, "check_sequence_numbers",
3010         "Do sequence number analysis",
3011         "Do sequence number analysis",
3012         &global_pdcp_check_sequence_numbers);
3013
3014     /* Attempt to dissect ROHC headers */
3015     prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
3016         "Attempt to decode ROHC data",
3017         "Attempt to decode ROHC data",
3018         &global_pdcp_dissect_rohc);
3019
3020     prefs_register_bool_preference(pdcp_lte_module, "show_feedback_option_tag_length",
3021         "Show ROHC feedback option tag & length",
3022         "Show ROHC feedback option tag & length",
3023         &global_pdcp_show_feedback_option_tag_length);
3024
3025     prefs_register_bool_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp",
3026         "Try Heuristic LTE-PDCP over UDP framing",
3027         "When enabled, use heuristic dissector to find PDCP-LTE frames sent with "
3028         "UDP framing",
3029         &global_pdcp_lte_heur);
3030
3031     register_init_routine(&pdcp_lte_init_protocol);
3032 }
3033
3034 void proto_reg_handoff_pdcp_lte(void)
3035 {
3036     dissector_handle_t pdcp_lte_handle;
3037
3038     pdcp_lte_handle = find_dissector("pdcp-lte");
3039     /* Add as a heuristic UDP dissector */
3040     heur_dissector_add("udp", dissect_pdcp_lte_heur, proto_pdcp_lte);
3041
3042     ip_handle = find_dissector("ip");
3043 }
3044