Coverage Report

Created: 2025-08-04 07:15

/src/wireshark/epan/dissectors/packet-aeron.c
Line
Count
Source (jump to first uncovered line)
1
/* packet-aeron.c
2
 *
3
 * Wireshark - Network traffic analyzer
4
 * By Gerald Combs <gerald@wireshark.org>
5
 * Copyright 1998 Gerald Combs
6
 *
7
 * SPDX-License-Identifier: GPL-2.0-or-later
8
 */
9
10
/*
11
 * More info https://github.com/real-logic/aeron/wiki/Transport-Protocol-Specification
12
 */
13
14
#include "config.h"
15
16
#include <epan/packet.h>
17
#include <epan/prefs.h>
18
#include <epan/expert.h>
19
#include <epan/conversation.h>
20
#include <epan/to_str.h>
21
#include <epan/tfs.h>
22
#include <wsutil/ws_roundup.h>
23
24
/*
25
 * The Aeron protocol is defined at
26
 *
27
 *    https://github.com/real-logic/aeron/wiki/Transport-Protocol-Specification
28
 */
29
30
void proto_register_aeron(void);
31
void proto_reg_handoff_aeron(void);
32
33
/* Protocol handle */
34
static int proto_aeron;
35
36
/* Dissector handles */
37
static dissector_handle_t aeron_dissector_handle;
38
static heur_dissector_list_t aeron_heuristic_subdissector_list;
39
40
/*----------------------------------------------------------------------------*/
41
/* Preferences.                                                               */
42
/*----------------------------------------------------------------------------*/
43
44
static bool aeron_sequence_analysis;
45
static bool aeron_stream_analysis;
46
static bool aeron_reassemble_fragments;
47
static bool aeron_use_heuristic_subdissectors;
48
49
/*----------------------------------------------------------------------------*/
50
/* Aeron position routines.                                                   */
51
/*----------------------------------------------------------------------------*/
52
typedef struct
53
{
54
    uint32_t term_id;
55
    uint32_t term_offset;
56
} aeron_pos_t;
57
58
static int aeron_pos_roundup(int offset)
59
0
{
60
0
    return WS_ROUNDUP_32(offset);
61
0
}
62
63
static int aeron_pos_compare(const aeron_pos_t * pos1, const aeron_pos_t * pos2)
64
0
{
65
    /* Returns:
66
        < 0  if pos1 < pos2
67
        == 0 if pos1 == pos2
68
        > 0  if pos1 > pos2
69
    */
70
0
    if (pos1->term_id == pos2->term_id)
71
0
    {
72
0
        if (pos1->term_offset == pos2->term_offset)
73
0
        {
74
0
            return 0;
75
0
        }
76
0
        else
77
0
        {
78
0
            return ((pos1->term_offset < pos2->term_offset) ? -1 : 1);
79
0
        }
80
0
    }
81
0
    else
82
0
    {
83
0
        return ((pos1->term_id < pos2->term_id) ? -1 : 1);
84
0
    }
85
0
}
86
87
static uint32_t aeron_pos_delta(const aeron_pos_t * pos1, const aeron_pos_t * pos2, uint32_t term_size)
88
0
{
89
0
    const aeron_pos_t * p1;
90
0
    const aeron_pos_t * p2;
91
0
    uint64_t p1_val;
92
0
    uint64_t p2_val;
93
0
    uint64_t delta;
94
0
    int rc;
95
96
0
    rc = aeron_pos_compare(pos1, pos2);
97
0
    if (rc >= 0)
98
0
    {
99
0
        p1 = pos1;
100
0
        p2 = pos2;
101
0
    }
102
0
    else
103
0
    {
104
0
        p1 = pos2;
105
0
        p2 = pos1;
106
0
    }
107
0
    p1_val = ((uint64_t) p1->term_id * term_size) + ((uint64_t) p1->term_offset);
108
0
    p2_val = ((uint64_t) p2->term_id * term_size) + ((uint64_t) p2->term_offset);
109
0
    delta = p1_val - p2_val;
110
0
    return ((uint32_t) (delta & UINT64_C(0x00000000ffffffff)));
111
0
}
112
113
static bool aeron_pos_add_length(aeron_pos_t * pos, uint32_t length, uint32_t term_length)
114
0
{
115
0
    uint32_t next_term_offset;
116
0
    uint32_t rounded_next_term_offset;
117
118
0
    next_term_offset = pos->term_offset + length;
119
0
    if (next_term_offset < pos->term_offset)
120
0
        return false;  /* overflow */
121
0
    rounded_next_term_offset = aeron_pos_roundup(next_term_offset);
122
0
    if (rounded_next_term_offset < next_term_offset)
123
0
        return false;  /* overflow */
124
0
    next_term_offset = rounded_next_term_offset;
125
126
0
    if (next_term_offset >= term_length)
127
0
    {
128
0
        pos->term_offset = 0;
129
0
        pos->term_id++;
130
0
    }
131
0
    else
132
0
    {
133
0
        pos->term_offset = next_term_offset;
134
0
    }
135
0
    return true;
136
0
}
137
138
/*----------------------------------------------------------------------------*/
139
/* Aeron frame information management.                                        */
140
/*----------------------------------------------------------------------------*/
141
static wmem_tree_t * aeron_frame_info_tree;
142
143
struct aeron_frame_info_t_stct;
144
typedef struct aeron_frame_info_t_stct aeron_frame_info_t;
145
146
typedef struct
147
{
148
    aeron_frame_info_t * frame_info;        /* Frame (aeron_frame_info_t) containing the RX data */
149
    uint32_t term_offset;                 /* Term offset of RX data */
150
    uint32_t length;                      /* Length of RX data */
151
} aeron_rx_info_t;
152
153
typedef struct
154
{
155
    aeron_frame_info_t * frame_info;        /* Frame (aeron_frame_info_t) in which this NAK occurs */
156
    wmem_list_t * rx;                       /* List of RX frames for this NAK */
157
    uint32_t flags;
158
    uint32_t nak_term_offset;                /* Term offset specified by this NAK */
159
    uint32_t nak_length;                     /* NAK length */
160
    uint32_t unrecovered_length;             /* Number of bytes unrecovered via RX */
161
} aeron_nak_analysis_t;
162
163
typedef struct
164
{
165
    uint32_t flags;
166
    uint32_t flags2;
167
    aeron_pos_t high;
168
    aeron_pos_t completed;
169
    uint32_t receiver_window;
170
    uint32_t outstanding_bytes;
171
} aeron_stream_analysis_t;
172
0
#define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL      0x00000001
173
0
#define AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX          0x00000002
174
0
#define AERON_STREAM_ANALYSIS_FLAGS_PACING_RX        0x00000004
175
0
#define AERON_STREAM_ANALYSIS_FLAGS_OOO              0x00000008
176
0
#define AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP          0x00000010
177
0
#define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE        0x00000020
178
0
#define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE    0x00000040
179
0
#define AERON_STREAM_ANALYSIS_FLAGS_OOO_SM           0x00000080
180
0
#define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM     0x00000100
181
0
#define AERON_STREAM_ANALYSIS_FLAGS_RX               0x00000200
182
0
#define AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE   0x00000400
183
184
0
#define AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID       0x00000001
185
186
typedef struct
187
{
188
    uint32_t previous;
189
    uint32_t next;
190
} aeron_frame_link_t;
191
192
struct aeron_msg_t_stct;
193
typedef struct aeron_msg_t_stct aeron_msg_t;
194
195
struct aeron_frame_info_t_stct
196
{
197
    uint32_t frame;
198
    uint32_t ofs;
199
    aeron_frame_link_t transport;
200
    aeron_frame_link_t stream;
201
    aeron_frame_link_t term;
202
    aeron_frame_link_t fragment;
203
    aeron_stream_analysis_t * stream_analysis;
204
    aeron_nak_analysis_t * nak_analysis;
205
    aeron_msg_t * message;
206
    wmem_list_t * rx;
207
    uint32_t flags;
208
};
209
0
#define AERON_FRAME_INFO_FLAGS_RETRANSMISSION  0x00000001
210
0
#define AERON_FRAME_INFO_FLAGS_KEEPALIVE       0x00000002
211
0
#define AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG 0x00000004
212
213
static wmem_tree_key_t * aeron_frame_info_key_build(wmem_allocator_t* allocator, uint32_t frame, uint32_t ofs)
214
0
{
215
0
    wmem_tree_key_t * fkey;
216
0
    uint32_t * key;
217
218
0
    fkey = wmem_alloc_array(allocator, wmem_tree_key_t, 2);
219
0
    key = wmem_alloc_array(allocator, uint32_t, 2);
220
0
    key[0] = frame;
221
0
    key[1] = ofs;
222
0
    fkey[0].length = 2;
223
0
    fkey[0].key = key;
224
0
    fkey[1].length = 0;
225
0
    fkey[1].key = NULL;
226
0
    return (fkey);
227
0
}
228
229
static aeron_frame_info_t * aeron_frame_info_lookup(wmem_tree_key_t * key)
230
0
{
231
0
    aeron_frame_info_t * fi;
232
233
0
    fi = (aeron_frame_info_t *) wmem_tree_lookup32_array(aeron_frame_info_tree, key);
234
0
    return (fi);
235
0
}
236
237
static aeron_frame_info_t * aeron_frame_info_find(wmem_allocator_t* allocator, uint32_t frame, uint32_t ofs)
238
0
{
239
0
    wmem_tree_key_t * key = aeron_frame_info_key_build(allocator, frame, ofs);
240
0
    return (aeron_frame_info_lookup(key));
241
0
}
242
243
static aeron_frame_info_t * aeron_frame_info_add(wmem_allocator_t* allocator, uint32_t frame, uint32_t ofs)
244
0
{
245
0
    aeron_frame_info_t * fi;
246
0
    wmem_tree_key_t * key = aeron_frame_info_key_build(allocator, frame, ofs);
247
248
0
    fi = aeron_frame_info_lookup(key);
249
0
    if (fi == NULL)
250
0
    {
251
0
        fi = wmem_new0(wmem_file_scope(), aeron_frame_info_t);
252
0
        fi->frame = frame;
253
0
        fi->ofs = ofs;
254
0
        if (aeron_sequence_analysis && aeron_stream_analysis)
255
0
        {
256
0
            fi->rx = wmem_list_new(wmem_file_scope());
257
0
        }
258
0
        wmem_tree_insert32_array(aeron_frame_info_tree, key, (void *) fi);
259
0
    }
260
0
    return (fi);
261
0
}
262
263
/*----------------------------------------------------------------------------*/
264
/* Aeron channel ID management.                                               */
265
/*----------------------------------------------------------------------------*/
266
static uint64_t aeron_channel_id = 1;
267
268
static uint64_t aeron_channel_id_assign(void)
269
0
{
270
0
    return (aeron_channel_id++);
271
0
}
272
273
static void aeron_channel_id_init(void)
274
14
{
275
14
    aeron_channel_id = 1;
276
14
}
277
278
/*----------------------------------------------------------------------------*/
279
/* Aeron transport, stream, term, and fragment structures.                    */
280
/*----------------------------------------------------------------------------*/
281
typedef struct
282
{
283
    address * addr1;
284
    address * addr2;
285
    uint16_t port1;
286
    uint16_t port2;
287
} aeron_conversation_info_t;
288
289
struct aeron_transport_t_stct;
290
typedef struct aeron_transport_t_stct aeron_transport_t;
291
292
struct aeron_stream_t_stct;
293
typedef struct aeron_stream_t_stct aeron_stream_t;
294
295
struct aeron_term_t_stct;
296
typedef struct aeron_term_t_stct aeron_term_t;
297
298
struct aeron_fragment_t_stct;
299
typedef struct aeron_fragment_t_stct aeron_fragment_t;
300
301
struct aeron_transport_t_stct
302
{
303
    uint64_t channel_id;
304
    wmem_map_t * stream;                    /* Map of all streams (aeron_stream_t) in this transport, keyed by stream ID */
305
    aeron_frame_info_t * last_frame;
306
    address addr1;
307
    address addr2;
308
    uint32_t session_id;
309
    uint16_t port1;
310
    uint16_t port2;
311
};
312
313
struct aeron_stream_rcv_t_stct;
314
typedef struct aeron_stream_rcv_t_stct aeron_stream_rcv_t;
315
316
struct aeron_stream_rcv_t_stct
317
{
318
    address addr;                           /* Receiver's IP address */
319
    uint16_t port;                           /* Receiver's (sending) port */
320
    aeron_pos_t completed;
321
    uint32_t receiver_window;
322
};
323
324
struct aeron_stream_t_stct
325
{
326
    aeron_transport_t * transport;          /* Parent transport */
327
    wmem_map_t * term;                      /* Map of all terms (aeron_term_t) in this stream, keyed by term ID */
328
    wmem_list_t * rcv;                      /* List of receivers (aeron_stream_rcv_t) */
329
    uint32_t rcv_count;
330
    aeron_frame_info_t * last_frame;
331
    uint32_t stream_id;
332
    uint32_t term_length;
333
    uint32_t mtu;
334
    uint32_t ttl;
335
    uint32_t flags;
336
    aeron_pos_t high;
337
};
338
0
#define AERON_STREAM_FLAGS_HIGH_VALID 0x1
339
340
typedef struct
341
{
342
    aeron_term_t * term;                    /* Parent term */
343
    aeron_frame_info_t * frame_info;        /* Frame info (aeron_frame_info_t) in which this NAK occurred */
344
    uint32_t term_offset;                    /* NAK term offset */
345
    uint32_t length;                         /* Length of NAK */
346
} aeron_nak_t;
347
348
struct aeron_term_t_stct
349
{
350
    aeron_stream_t * stream;                /* Parent stream */
351
    wmem_map_t * fragment;                  /* Map of all fragments (aeron_fragment_t) in this term, keyed by term offset */
352
    wmem_tree_t * message;                  /* Tree of all fragmented messages (aeron_msg_t) in this term, keyed by lowest term offset */
353
    wmem_list_t * orphan_fragment;
354
    aeron_frame_info_t * last_frame;        /* Pointer to last frame seen for this term */
355
    wmem_list_t * nak;                      /* List of all NAKs (aeron_nak_t) in this term */
356
    uint32_t term_id;
357
};
358
359
struct aeron_fragment_t_stct
360
{
361
    aeron_term_t * term;                    /* Parent term */
362
    wmem_list_t * frame;                    /* List of frames (aeron_frame_info_t) containing this fragment (term offset) */
363
    aeron_frame_info_t * first_frame;       /* First frame which contains this fragment (term offset) */
364
    aeron_frame_info_t * last_frame;        /* Last frame which contains this fragment (term offset) */
365
    aeron_frame_info_t * first_data_frame;  /* First frame which contains this fragment (term offset) as actual data (not as a KA) */
366
    uint32_t term_offset;
367
    uint32_t length;
368
    uint32_t data_length;
369
    uint32_t frame_count;
370
};
371
372
/*----------------------------------------------------------------------------*/
373
/* Aeron transport management.                                                */
374
/*----------------------------------------------------------------------------*/
375
static unsigned aeron_uint32_hash_func(const void *key)
376
0
{
377
0
    uint32_t value = *((const uint32_t *) key);
378
0
    return ((unsigned) value);
379
0
}
380
381
static gboolean aeron_uint32_compare_func(const void *lhs, const void *rhs)
382
0
{
383
0
    uint32_t key1 = *((const uint32_t *) lhs);
384
0
    uint32_t key2 = *((const uint32_t *) rhs);
385
0
    return ((key1 == key2) ? true : false);
386
0
}
387
388
static aeron_transport_t * aeron_transport_add(const aeron_conversation_info_t * cinfo, uint32_t session_id, uint32_t frame)
389
0
{
390
0
    aeron_transport_t * transport;
391
0
    conversation_t * conv;
392
0
    wmem_map_t * session_map;
393
394
0
    conv = find_conversation(frame, cinfo->addr1, cinfo->addr2, CONVERSATION_UDP, cinfo->port1, cinfo->port2, 0);
395
0
    if (conv == NULL)
396
0
    {
397
0
        conv = conversation_new(frame, cinfo->addr1, cinfo->addr2, CONVERSATION_UDP, cinfo->port1, cinfo->port2, 0);
398
0
    }
399
0
    if (frame > conv->last_frame)
400
0
    {
401
0
        conv->last_frame = frame;
402
0
    }
403
0
    session_map = (wmem_map_t *) conversation_get_proto_data(conv, proto_aeron);
404
0
    if (session_map == NULL)
405
0
    {
406
0
        session_map = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
407
0
        conversation_add_proto_data(conv, proto_aeron, (void *) session_map);
408
0
    }
409
0
    transport = (aeron_transport_t *) wmem_map_lookup(session_map, (const void *) &session_id);
410
0
    if (transport != NULL)
411
0
    {
412
0
        return (transport);
413
0
    }
414
0
    transport = wmem_new0(wmem_file_scope(), aeron_transport_t);
415
0
    transport->channel_id = aeron_channel_id_assign();
416
0
    transport->stream = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
417
0
    transport->last_frame = NULL;
418
0
    copy_address_wmem(wmem_file_scope(), &(transport->addr1), cinfo->addr1);
419
0
    copy_address_wmem(wmem_file_scope(), &(transport->addr2), cinfo->addr2);
420
0
    transport->session_id = session_id;
421
0
    transport->port1 = cinfo->port1;
422
0
    transport->port2 = cinfo->port2;
423
0
    wmem_map_insert(session_map, (const void *) &(transport->session_id), (void *) transport);
424
0
    return (transport);
425
0
}
426
427
static aeron_stream_t * aeron_transport_stream_find(aeron_transport_t * transport, uint32_t stream_id)
428
0
{
429
0
    aeron_stream_t * stream;
430
431
0
    stream = (aeron_stream_t *) wmem_map_lookup(transport->stream, (const void *) &stream_id);
432
0
    return (stream);
433
0
}
434
435
static aeron_stream_t * aeron_transport_stream_add(aeron_transport_t * transport, uint32_t stream_id)
436
0
{
437
0
    aeron_stream_t * stream;
438
439
0
    stream = aeron_transport_stream_find(transport, stream_id);
440
0
    if (stream == NULL)
441
0
    {
442
0
        stream = wmem_new0(wmem_file_scope(), aeron_stream_t);
443
0
        stream->transport = transport;
444
0
        stream->term = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
445
0
        stream->rcv = wmem_list_new(wmem_file_scope());
446
0
        stream->rcv_count = 0;
447
0
        stream->last_frame = NULL;
448
0
        stream->stream_id = stream_id;
449
0
        stream->term_length = 0;
450
0
        stream->mtu = 0;
451
0
        stream->ttl = 0;
452
0
        stream->flags = 0;
453
0
        stream->high.term_id = 0;
454
0
        stream->high.term_offset = 0;
455
0
        wmem_map_insert(transport->stream, (const void *) &(stream->stream_id), (void *) stream);
456
0
    }
457
0
    return (stream);
458
0
}
459
460
static void aeron_transport_frame_add(aeron_transport_t * transport, aeron_frame_info_t * finfo, uint32_t flags)
461
0
{
462
0
    if (flags != 0)
463
0
    {
464
0
        finfo->flags = flags;
465
0
    }
466
0
    if (transport->last_frame != NULL)
467
0
    {
468
0
        finfo->transport.previous = transport->last_frame->frame;
469
0
        transport->last_frame->transport.next = finfo->frame;
470
0
    }
471
0
    finfo->transport.next = 0;
472
0
    transport->last_frame = finfo;
473
0
}
474
475
/*----------------------------------------------------------------------------*/
476
/* Aeron stream management.                                                   */
477
/*----------------------------------------------------------------------------*/
478
static aeron_term_t * aeron_stream_term_find(aeron_stream_t * stream, uint32_t term_id)
479
0
{
480
0
    aeron_term_t * term;
481
482
0
    term = (aeron_term_t *) wmem_map_lookup(stream->term, (const void *) &term_id);
483
0
    return (term);
484
0
}
485
486
static aeron_term_t * aeron_stream_term_add(aeron_stream_t * stream, uint32_t term_id)
487
0
{
488
0
    aeron_term_t * term;
489
490
0
    term = aeron_stream_term_find(stream, term_id);
491
0
    if (term == NULL)
492
0
    {
493
0
        term = wmem_new0(wmem_file_scope(), aeron_term_t);
494
0
        term->stream = stream;
495
0
        term->fragment = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
496
0
        term->message = wmem_tree_new(wmem_file_scope());
497
0
        term->orphan_fragment = wmem_list_new(wmem_file_scope());
498
0
        term->nak = wmem_list_new(wmem_file_scope());
499
0
        term->term_id = term_id;
500
0
        wmem_map_insert(stream->term, (const void *) &(term->term_id), (void *) term);
501
0
    }
502
0
    return (term);
503
0
}
504
505
static aeron_stream_rcv_t * aeron_stream_rcv_find(aeron_stream_t * stream, const address * addr, uint16_t port)
506
0
{
507
0
    wmem_list_frame_t * lf = wmem_list_head(stream->rcv);
508
0
    aeron_stream_rcv_t * rcv = NULL;
509
510
0
    while (lf != NULL)
511
0
    {
512
0
        aeron_stream_rcv_t * cur = (aeron_stream_rcv_t *) wmem_list_frame_data(lf);
513
0
        if (cur != NULL)
514
0
        {
515
0
            if ((cmp_address(&(cur->addr), addr) == 0) && (cur->port == port))
516
0
            {
517
0
                rcv = cur;
518
0
                break;
519
0
            }
520
0
        }
521
0
        lf = wmem_list_frame_next(lf);
522
0
    }
523
0
    return (rcv);
524
0
}
525
526
static aeron_stream_rcv_t * aeron_stream_rcv_add(aeron_stream_t * stream, const address * addr, uint16_t port)
527
0
{
528
0
    aeron_stream_rcv_t * rcv;
529
530
0
    rcv = aeron_stream_rcv_find(stream, addr, port);
531
0
    if (rcv != NULL)
532
0
    {
533
0
        return (rcv);
534
0
    }
535
0
    rcv = wmem_new0(wmem_file_scope(), aeron_stream_rcv_t);
536
0
    copy_address_wmem(wmem_file_scope(), &(rcv->addr), addr);
537
0
    rcv->port = port;
538
0
    rcv->completed.term_id = 0;
539
0
    rcv->completed.term_offset = 0;
540
0
    rcv->receiver_window = 0;
541
0
    wmem_list_append(stream->rcv, (void *) rcv);
542
0
    stream->rcv_count++;
543
0
    return (rcv);
544
0
}
545
546
static void aeron_stream_frame_add(aeron_stream_t * stream, aeron_frame_info_t * finfo, uint32_t flags)
547
0
{
548
0
    if (flags != 0)
549
0
    {
550
0
        finfo->flags = flags;
551
0
    }
552
0
    if (stream->last_frame != NULL)
553
0
    {
554
0
        finfo->stream.previous = stream->last_frame->frame;
555
0
        stream->last_frame->stream.next = finfo->frame;
556
0
    }
557
0
    finfo->stream.next = 0;
558
0
    stream->last_frame = finfo;
559
0
    aeron_transport_frame_add(stream->transport, finfo, 0);
560
0
}
561
562
/*----------------------------------------------------------------------------*/
563
/* Aeron term management.                                                     */
564
/*----------------------------------------------------------------------------*/
565
static aeron_fragment_t * aeron_term_fragment_find(aeron_term_t * term, uint32_t term_offset)
566
0
{
567
0
    aeron_fragment_t * fragment;
568
569
0
    fragment = (aeron_fragment_t *) wmem_map_lookup(term->fragment, (const void *) &term_offset);
570
0
    return (fragment);
571
0
}
572
573
static aeron_fragment_t * aeron_term_fragment_add(aeron_term_t * term, uint32_t term_offset, uint32_t length, uint32_t data_length)
574
0
{
575
0
    aeron_fragment_t * fragment;
576
577
0
    fragment = aeron_term_fragment_find(term, term_offset);
578
0
    if (fragment == NULL)
579
0
    {
580
0
        fragment = wmem_new0(wmem_file_scope(), aeron_fragment_t);
581
0
        fragment->term = term;
582
0
        fragment->frame = wmem_list_new(wmem_file_scope());
583
0
        fragment->first_frame = NULL;
584
0
        fragment->last_frame = NULL;
585
0
        fragment->first_data_frame = NULL;
586
0
        fragment->term_offset = term_offset;
587
0
        fragment->length = length;
588
0
        fragment->data_length = data_length;
589
0
        fragment->frame_count = 0;
590
0
        wmem_map_insert(term->fragment, (const void *) &(fragment->term_offset), (void *) fragment);
591
0
    }
592
0
    return (fragment);
593
0
}
594
595
static void aeron_term_frame_add(aeron_term_t * term, aeron_frame_info_t * finfo, uint32_t flags)
596
0
{
597
0
    if (flags != 0)
598
0
    {
599
0
        finfo->flags = flags;
600
0
    }
601
0
    if (term->last_frame != NULL)
602
0
    {
603
0
        finfo->term.previous = term->last_frame->frame;
604
0
        term->last_frame->term.next = finfo->frame;
605
0
    }
606
0
    finfo->term.next = 0;
607
0
    term->last_frame = finfo;
608
0
    aeron_stream_frame_add(term->stream, finfo, 0);
609
0
}
610
611
/*----------------------------------------------------------------------------*/
612
/* Aeron fragment management.                                                 */
613
/*----------------------------------------------------------------------------*/
614
static void aeron_fragment_frame_add(aeron_fragment_t * fragment, aeron_frame_info_t * finfo, uint32_t flags, uint32_t length)
615
0
{
616
0
    if (flags != 0)
617
0
    {
618
0
        finfo->flags = flags;
619
0
    }
620
0
    wmem_list_append(fragment->frame, (void *) finfo);
621
0
    fragment->frame_count++;
622
0
    if (fragment->last_frame != NULL)
623
0
    {
624
0
        finfo->fragment.previous = fragment->last_frame->frame;
625
0
        fragment->last_frame->fragment.next = finfo->frame;
626
0
    }
627
0
    if (fragment->first_frame == NULL)
628
0
    {
629
0
        fragment->first_frame = finfo;
630
0
    }
631
0
    if (length != 0)
632
0
    {
633
0
        if (fragment->first_data_frame == NULL)
634
0
        {
635
0
            fragment->first_data_frame = finfo;
636
0
        }
637
0
    }
638
0
    finfo->fragment.next = 0;
639
0
    fragment->last_frame = finfo;
640
0
    aeron_term_frame_add(fragment->term, finfo, 0);
641
0
}
642
643
/*----------------------------------------------------------------------------*/
644
/* Utility functions.                                                         */
645
/*----------------------------------------------------------------------------*/
646
static bool aeron_is_address_multicast(const address * addr)
647
0
{
648
0
    const uint8_t * addr_data = (const uint8_t *) addr->data;
649
650
0
    switch (addr->type)
651
0
    {
652
0
        case AT_IPv4:
653
0
            if (addr_data && ((addr_data[0] & 0xf0) == 0xe0))
654
0
            {
655
0
                return true;
656
0
            }
657
0
            break;
658
0
        case AT_IPv6:
659
0
            if (addr_data && (addr_data[0] == 0xff))
660
0
            {
661
0
                return true;
662
0
            }
663
0
            break;
664
0
        default:
665
0
            break;
666
0
    }
667
0
    return false;
668
0
}
669
670
static char * aeron_format_transport_uri(wmem_allocator_t* allocator, const aeron_conversation_info_t * cinfo)
671
0
{
672
0
    wmem_strbuf_t * uri;
673
674
0
    uri = wmem_strbuf_new(allocator, "aeron:udp?");
675
0
    if (aeron_is_address_multicast(cinfo->addr2))
676
0
    {
677
0
        switch (cinfo->addr2->type)
678
0
        {
679
0
            case AT_IPv6:
680
0
                wmem_strbuf_append_printf(uri, "group=[%s]:%" PRIu16, address_to_str(allocator, cinfo->addr2), cinfo->port2);
681
0
                break;
682
0
            case AT_IPv4:
683
0
            default:
684
0
                wmem_strbuf_append_printf(uri, "group=%s:%" PRIu16, address_to_str(allocator, cinfo->addr2), cinfo->port2);
685
0
                break;
686
0
        }
687
0
    }
688
0
    else
689
0
    {
690
0
        switch (cinfo->addr2->type)
691
0
        {
692
0
            case AT_IPv6:
693
0
                wmem_strbuf_append_printf(uri, "remote=[%s]:%" PRIu16, address_to_str(allocator, cinfo->addr2), cinfo->port2);
694
0
                break;
695
0
            case AT_IPv4:
696
0
            default:
697
0
                wmem_strbuf_append_printf(uri, "remote=%s:%" PRIu16, address_to_str(allocator, cinfo->addr2), cinfo->port2);
698
0
                break;
699
0
        }
700
0
    }
701
0
    return (wmem_strbuf_finalize(uri));
702
0
}
703
704
/*----------------------------------------------------------------------------*/
705
/* Packet definitions.                                                        */
706
/*----------------------------------------------------------------------------*/
707
708
/* Basic frame offsets */
709
0
#define O_AERON_BASIC_FRAME_LENGTH 0
710
0
#define O_AERON_BASIC_VERSION 4
711
0
#define O_AERON_BASIC_FLAGS 5
712
0
#define O_AERON_BASIC_TYPE 6
713
714
0
#define HDR_LENGTH_MIN 12
715
716
/* Padding frame */
717
0
#define O_AERON_PAD_FRAME_LENGTH 0
718
0
#define O_AERON_PAD_VERSION 4
719
0
#define O_AERON_PAD_FLAGS 5
720
0
#define O_AERON_PAD_TYPE 6
721
0
#define O_AERON_PAD_TERM_OFFSET 8
722
0
#define O_AERON_PAD_SESSION_ID 12
723
0
#define O_AERON_PAD_STREAM_ID 16
724
0
#define O_AERON_PAD_TERM_ID 20
725
0
#define L_AERON_PAD_MIN 24
726
727
/* Data frame */
728
0
#define O_AERON_DATA_FRAME_LENGTH 0
729
0
#define O_AERON_DATA_VERSION 4
730
0
#define O_AERON_DATA_FLAGS 5
731
0
#define O_AERON_DATA_TYPE 6
732
0
#define O_AERON_DATA_TERM_OFFSET 8
733
0
#define O_AERON_DATA_SESSION_ID 12
734
0
#define O_AERON_DATA_STREAM_ID 16
735
0
#define O_AERON_DATA_TERM_ID 20
736
0
#define O_AERON_DATA_RESERVED_VALUE 24
737
0
#define O_AERON_DATA_DATA 32
738
0
#define L_AERON_DATA_MIN 32
739
740
/* NAK frame */
741
0
#define O_AERON_NAK_FRAME_LENGTH 0
742
0
#define O_AERON_NAK_VERSION 4
743
0
#define O_AERON_NAK_FLAGS 5
744
0
#define O_AERON_NAK_TYPE 6
745
0
#define O_AERON_NAK_SESSION_ID 8
746
0
#define O_AERON_NAK_STREAM_ID 12
747
0
#define O_AERON_NAK_TERM_ID 16
748
0
#define O_AERON_NAK_TERM_OFFSET 20
749
0
#define O_AERON_NAK_LENGTH 24
750
0
#define L_AERON_NAK 28
751
752
/* Status message */
753
0
#define O_AERON_SM_FRAME_LENGTH 0
754
0
#define O_AERON_SM_VERSION 4
755
0
#define O_AERON_SM_FLAGS 5
756
0
#define O_AERON_SM_TYPE 6
757
0
#define O_AERON_SM_SESSION_ID 8
758
0
#define O_AERON_SM_STREAM_ID 12
759
0
#define O_AERON_SM_TERM_ID 16
760
0
#define O_AERON_SM_COMPLETED_TERM_OFFSET 20
761
0
#define O_AERON_SM_RECEIVER_WINDOW 24
762
0
#define O_AERON_SM_RECEIVER_ID 28
763
0
#define O_AERON_SM_FEEDBACK 36
764
0
#define L_AERON_SM_MIN 36
765
766
/* Error header */
767
0
#define O_AERON_ERR_FRAME_LENGTH 0
768
0
#define O_AERON_ERR_VERSION 4
769
0
#define O_AERON_ERR_CODE 5
770
0
#define O_AERON_ERR_TYPE 6
771
0
#define O_AERON_ERR_OFFENDING_FRAME_LENGTH 8
772
0
#define O_AERON_ERR_OFFENDING_HEADER 12
773
#define O_AERON_ERR_TERM_ID 16
774
#define O_AERON_ERR_COMPLETED_TERM_OFFSET 20
775
#define O_AERON_ERR_RECEIVER_WINDOW 24
776
#define O_AERON_ERR_FEEDBACK 28
777
0
#define L_AERON_ERR_MIN 12
778
779
/* Heartbeat frame */
780
0
#define O_AERON_HEAERTBEAT_FRAME_LENGTH 0
781
0
#define O_AERON_HEAERTBEAT_VERSION 4
782
0
#define O_AERON_HEAERTBEAT_FLAGS 5
783
0
#define O_AERON_HEAERTBEAT_TYPE 6
784
0
#define O_AERON_HEAERTBEAT_TERM_OFFSET 8
785
0
#define O_AERON_HEAERTBEAT_SESSION_ID 12
786
0
#define O_AERON_HEAERTBEAT_STREAM_ID 16
787
0
#define O_AERON_HEAERTBEAT_TERM_ID 20
788
#define L_AERON_HEAERTBEAT_MIN 24
789
790
/* RTT message */
791
0
#define O_AERON_RTT_FRAME_LENGTH 0
792
0
#define O_AERON_RTT_VERSION 4
793
0
#define O_AERON_RTT_FLAGS 5
794
0
#define O_AERON_RTT_TYPE 6
795
0
#define O_AERON_RTT_SESSION_ID 8
796
0
#define O_AERON_RTT_STREAM_ID 12
797
0
#define O_AERON_RTT_ECHO_TIMESTAMP 16
798
0
#define O_AERON_RTT_RECEPTION_DELTA 24
799
0
#define O_AERON_RTT_RECEIVER_ID 32
800
0
#define L_AERON_RTT 40
801
802
/* Setup frame */
803
0
#define O_AERON_SETUP_FRAME_LENGTH 0
804
0
#define O_AERON_SETUP_VERSION 4
805
0
#define O_AERON_SETUP_FLAGS 5
806
0
#define O_AERON_SETUP_TYPE 6
807
0
#define O_AERON_SETUP_TERM_OFFSET 8
808
0
#define O_AERON_SETUP_SESSION_ID 12
809
0
#define O_AERON_SETUP_STREAM_ID 16
810
0
#define O_AERON_SETUP_INITIAL_TERM_ID 20
811
0
#define O_AERON_SETUP_ACTIVE_TERM_ID 24
812
0
#define O_AERON_SETUP_TERM_LENGTH 28
813
0
#define O_AERON_SETUP_MTU 32
814
0
#define O_AERON_SETUP_TTL 36
815
0
#define L_AERON_SETUP 40
816
817
0
#define HDR_TYPE_PAD 0x0000
818
0
#define HDR_TYPE_DATA 0x0001
819
0
#define HDR_TYPE_NAK 0x0002
820
0
#define HDR_TYPE_SM 0x0003
821
0
#define HDR_TYPE_ERR 0x0004
822
0
#define HDR_TYPE_SETUP 0x0005
823
0
#define HDR_TYPE_RTT 0x0006
824
0
#define HDR_TYPE_RES 0x0007
825
0
#define HDR_TYPE_EXT 0xFFFF
826
827
28
#define DATA_FLAGS_BEGIN 0x80
828
28
#define DATA_FLAGS_END 0x40
829
14
#define DATA_FLAGS_EOS 0x20
830
0
#define DATA_FLAGS_COMPLETE (DATA_FLAGS_BEGIN | DATA_FLAGS_END)
831
832
14
#define STATUS_FLAGS_SETUP 0x80
833
14
#define STATUS_FLAGS_REPLY 0x80
834
835
836
/*----------------------------------------------------------------------------*/
837
/* Value translation tables.                                                  */
838
/*----------------------------------------------------------------------------*/
839
840
static const value_string aeron_frame_type[] =
841
{
842
    { HDR_TYPE_PAD,   "Pad" },
843
    { HDR_TYPE_DATA,  "Data" },
844
    { HDR_TYPE_NAK,   "NAK" },
845
    { HDR_TYPE_SM,    "Status" },
846
    { HDR_TYPE_ERR,   "Error" },
847
    { HDR_TYPE_SETUP, "Setup" },
848
    { HDR_TYPE_RTT,   "RTT" },
849
    { HDR_TYPE_RES,   "Resolution" },
850
    { HDR_TYPE_EXT,   "Extension" },
851
    { 0x0, NULL }
852
};
853
854
/*
855
    Aeron conversations:
856
857
    UDP unicast:
858
    - The URL specifies the subscriber address and UDP port, and the publisher "connects" to the single subscriber.
859
    - The publisher sends Pad, Data, and Setup frames to the subscriber address and port.
860
    - The subscriber sends NAK and SM frames to the publisher, using as the destination the address and port from
861
      which the Setup and Data frames were received
862
    - So the conversation is defined by [A(publisher),A(subscriber),P(publisher),P(subscriber),PT_UDP]
863
864
    UDP multicast:
865
    - The URL specifies the data multicast group and UDP port, and must be an odd-numbered address. The control multicast
866
      group is automatically set to be one greater than the data multicast group, and the same port is used.
867
    - The publisher sends Pad, Data, and Setup frames to the data multicast group and port.
868
    - The subscriber sends NAK and SM frames to the control multicast group and port.
869
    - So the conversation is defined by [ControlGroup,DataGroup,port,port,PT_UDP]
870
871
*/
872
873
static aeron_conversation_info_t * aeron_setup_conversation_info(const packet_info * pinfo, uint16_t type)
874
0
{
875
0
    aeron_conversation_info_t * cinfo;
876
0
    int addr_len = pinfo->dst.len;
877
878
0
    cinfo = wmem_new0(pinfo->pool, aeron_conversation_info_t);
879
0
    switch (pinfo->dst.type)
880
0
    {
881
0
        case AT_IPv4:
882
0
            {
883
0
                const uint8_t * dst_addr = (const uint8_t *) pinfo->dst.data;
884
885
0
                cinfo->addr1 = wmem_new0(pinfo->pool, address);
886
0
                cinfo->addr2 = wmem_new0(pinfo->pool, address);
887
0
                if (aeron_is_address_multicast(&(pinfo->dst)))
888
0
                {
889
0
                    uint8_t * addr1;
890
0
                    uint8_t * addr2;
891
892
0
                    addr1 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
893
0
                    addr2 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
894
0
                    if ((dst_addr[addr_len - 1] & 0x1) != 0)
895
0
                    {
896
                        /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
897
0
                        addr1[addr_len - 1]++;
898
0
                    }
899
0
                    else
900
0
                    {
901
                        /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
902
0
                        addr2[addr_len - 1]--;
903
0
                    }
904
0
                    set_address(cinfo->addr1, AT_IPv4, addr_len, (void *) addr1);
905
0
                    set_address(cinfo->addr2, AT_IPv4, addr_len, (void *) addr2);
906
0
                    cinfo->port1 = pinfo->destport;
907
0
                    cinfo->port2 = cinfo->port1;
908
0
                }
909
0
                else
910
0
                {
911
0
                    switch (type)
912
0
                    {
913
0
                        case HDR_TYPE_PAD:
914
0
                        case HDR_TYPE_DATA:
915
0
                        case HDR_TYPE_SETUP:
916
0
                        case HDR_TYPE_RTT:
917
                            /* Destination is a receiver */
918
0
                            copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->src));
919
0
                            cinfo->port1 = pinfo->srcport;
920
0
                            copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->dst));
921
0
                            cinfo->port2 = pinfo->destport;
922
0
                            break;
923
0
                        case HDR_TYPE_NAK:
924
0
                        case HDR_TYPE_SM:
925
                            /* Destination is the source */
926
0
                            copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->dst));
927
0
                            cinfo->port1 = pinfo->destport;
928
0
                            copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->src));
929
0
                            cinfo->port2 = pinfo->srcport;
930
0
                            break;
931
0
                        default:
932
0
                            break;
933
0
                    }
934
0
                }
935
0
            }
936
0
            break;
937
0
        case AT_IPv6:
938
0
            {
939
0
                const uint8_t * dst_addr = (const uint8_t *) pinfo->dst.data;
940
941
0
                cinfo->addr1 = wmem_new0(pinfo->pool, address);
942
0
                cinfo->addr2 = wmem_new0(pinfo->pool, address);
943
0
                if (aeron_is_address_multicast(&(pinfo->dst)))
944
0
                {
945
0
                    uint8_t * addr1;
946
0
                    uint8_t * addr2;
947
948
0
                    addr1 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
949
0
                    addr2 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
950
0
                    if ((dst_addr[addr_len - 1] & 0x1) != 0)
951
0
                    {
952
                        /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
953
0
                        addr1[addr_len - 1]++;
954
0
                    }
955
0
                    else
956
0
                    {
957
                        /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
958
0
                        addr2[addr_len - 1]--;
959
0
                    }
960
0
                    set_address(cinfo->addr1, AT_IPv6, addr_len, (void *) addr1);
961
0
                    set_address(cinfo->addr2, AT_IPv6, addr_len, (void *) addr2);
962
0
                    cinfo->port1 = pinfo->destport;
963
0
                    cinfo->port2 = cinfo->port1;
964
0
                }
965
0
                else
966
0
                {
967
0
                    switch (type)
968
0
                    {
969
0
                        case HDR_TYPE_PAD:
970
0
                        case HDR_TYPE_DATA:
971
0
                        case HDR_TYPE_SETUP:
972
0
                        case HDR_TYPE_RTT:
973
                            /* Destination is a receiver */
974
0
                            copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->src));
975
0
                            cinfo->port1 = pinfo->srcport;
976
0
                            copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->dst));
977
0
                            cinfo->port2 = pinfo->destport;
978
0
                            break;
979
0
                        case HDR_TYPE_NAK:
980
0
                        case HDR_TYPE_SM:
981
                            /* Destination is the source */
982
0
                            copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->dst));
983
0
                            cinfo->port1 = pinfo->destport;
984
0
                            copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->src));
985
0
                            cinfo->port2 = pinfo->srcport;
986
0
                            break;
987
0
                        default:
988
0
                            break;
989
0
                    }
990
0
                }
991
0
            }
992
0
            break;
993
0
        default:
994
0
            return (NULL);
995
0
    }
996
0
    return (cinfo);
997
0
}
998
999
/*----------------------------------------------------------------------------*/
1000
/* Handles of all types.                                                      */
1001
/*----------------------------------------------------------------------------*/
1002
1003
/* Dissector tree handles */
1004
static int ett_aeron;
1005
static int ett_aeron_pad;
1006
static int ett_aeron_data;
1007
static int ett_aeron_data_flags;
1008
static int ett_aeron_data_reassembly;
1009
static int ett_aeron_nak;
1010
static int ett_aeron_sm;
1011
static int ett_aeron_sm_flags;
1012
static int ett_aeron_rtt;
1013
static int ett_aeron_rtt_flags;
1014
static int ett_aeron_err;
1015
static int ett_aeron_setup;
1016
static int ett_aeron_ext;
1017
static int ett_aeron_sequence_analysis;
1018
static int ett_aeron_sequence_analysis_retransmission_rx;
1019
static int ett_aeron_sequence_analysis_nak_rx;
1020
static int ett_aeron_sequence_analysis_term_offset;
1021
static int ett_aeron_stream_analysis;
1022
1023
/* Dissector field handles */
1024
static int hf_aeron_channel_id;
1025
static int hf_aeron_pad;
1026
static int hf_aeron_pad_frame_length;
1027
static int hf_aeron_pad_version;
1028
static int hf_aeron_pad_flags;
1029
static int hf_aeron_pad_type;
1030
static int hf_aeron_pad_term_offset;
1031
static int hf_aeron_pad_session_id;
1032
static int hf_aeron_pad_stream_id;
1033
static int hf_aeron_pad_term_id;
1034
static int hf_aeron_data;
1035
static int hf_aeron_data_frame_length;
1036
static int hf_aeron_data_version;
1037
static int hf_aeron_data_flags;
1038
static int hf_aeron_data_flags_b;
1039
static int hf_aeron_data_flags_e;
1040
static int hf_aeron_data_flags_s;
1041
static int hf_aeron_data_type;
1042
static int hf_aeron_data_term_offset;
1043
static int hf_aeron_data_next_offset;
1044
static int hf_aeron_data_next_offset_term;
1045
static int hf_aeron_data_next_offset_first_frame;
1046
static int hf_aeron_data_session_id;
1047
static int hf_aeron_data_stream_id;
1048
static int hf_aeron_data_term_id;
1049
static int hf_aeron_data_reserved_value;
1050
static int hf_aeron_data_reassembly;
1051
static int hf_aeron_data_reassembly_fragment;
1052
static int hf_aeron_nak;
1053
static int hf_aeron_nak_frame_length;
1054
static int hf_aeron_nak_version;
1055
static int hf_aeron_nak_flags;
1056
static int hf_aeron_nak_type;
1057
static int hf_aeron_nak_session_id;
1058
static int hf_aeron_nak_stream_id;
1059
static int hf_aeron_nak_term_id;
1060
static int hf_aeron_nak_term_offset;
1061
static int hf_aeron_nak_length;
1062
static int hf_aeron_sm;
1063
static int hf_aeron_sm_frame_length;
1064
static int hf_aeron_sm_version;
1065
static int hf_aeron_sm_flags;
1066
static int hf_aeron_sm_flags_s;
1067
static int hf_aeron_sm_type;
1068
static int hf_aeron_sm_session_id;
1069
static int hf_aeron_sm_stream_id;
1070
static int hf_aeron_sm_consumption_term_id;
1071
static int hf_aeron_sm_consumption_term_offset;
1072
static int hf_aeron_sm_receiver_window;
1073
static int hf_aeron_sm_receiver_id;
1074
static int hf_aeron_sm_feedback;
1075
static int hf_aeron_err;
1076
static int hf_aeron_err_frame_length;
1077
static int hf_aeron_err_version;
1078
static int hf_aeron_err_code;
1079
static int hf_aeron_err_type;
1080
static int hf_aeron_err_off_frame_length;
1081
static int hf_aeron_err_off_hdr;
1082
static int hf_aeron_err_string;
1083
static int hf_aeron_heartbeat;
1084
static int hf_aeron_heartbeat_frame_length;
1085
static int hf_aeron_heartbeat_version;
1086
static int hf_aeron_heartbeat_flags;
1087
static int hf_aeron_heartbeat_flags_b;
1088
static int hf_aeron_heartbeat_flags_e;
1089
static int hf_aeron_heartbeat_type;
1090
static int hf_aeron_heartbeat_term_offset;
1091
static int hf_aeron_heartbeat_session_id;
1092
static int hf_aeron_heartbeat_stream_id;
1093
static int hf_aeron_heartbeat_term_id;
1094
static int hf_aeron_rtt;
1095
static int hf_aeron_rtt_frame_length;
1096
static int hf_aeron_rtt_version;
1097
static int hf_aeron_rtt_flags;
1098
static int hf_aeron_rtt_flags_r;
1099
static int hf_aeron_rtt_type;
1100
static int hf_aeron_rtt_session_id;
1101
static int hf_aeron_rtt_stream_id;
1102
static int hf_aeron_rtt_echo_timestamp;
1103
static int hf_aeron_rtt_reception_delta;
1104
static int hf_aeron_rtt_receiver_id;
1105
static int hf_aeron_setup;
1106
static int hf_aeron_setup_frame_length;
1107
static int hf_aeron_setup_version;
1108
static int hf_aeron_setup_flags;
1109
static int hf_aeron_setup_type;
1110
static int hf_aeron_setup_term_offset;
1111
static int hf_aeron_setup_session_id;
1112
static int hf_aeron_setup_stream_id;
1113
static int hf_aeron_setup_initial_term_id;
1114
static int hf_aeron_setup_active_term_id;
1115
static int hf_aeron_setup_term_length;
1116
static int hf_aeron_setup_mtu;
1117
static int hf_aeron_setup_ttl;
1118
static int hf_aeron_sequence_analysis;
1119
static int hf_aeron_sequence_analysis_channel_prev_frame;
1120
static int hf_aeron_sequence_analysis_channel_next_frame;
1121
static int hf_aeron_sequence_analysis_stream_prev_frame;
1122
static int hf_aeron_sequence_analysis_stream_next_frame;
1123
static int hf_aeron_sequence_analysis_term_prev_frame;
1124
static int hf_aeron_sequence_analysis_term_next_frame;
1125
static int hf_aeron_sequence_analysis_term_offset;
1126
static int hf_aeron_sequence_analysis_term_offset_frame;
1127
static int hf_aeron_sequence_analysis_retransmission;
1128
static int hf_aeron_sequence_analysis_retransmission_rx;
1129
static int hf_aeron_sequence_analysis_retransmission_rx_frame;
1130
static int hf_aeron_sequence_analysis_keepalive;
1131
static int hf_aeron_sequence_analysis_nak_unrecovered;
1132
static int hf_aeron_sequence_analysis_nak_rx;
1133
static int hf_aeron_sequence_analysis_nak_rx_frame;
1134
static int hf_aeron_stream_analysis;
1135
static int hf_aeron_stream_analysis_high_term_id;
1136
static int hf_aeron_stream_analysis_high_term_offset;
1137
static int hf_aeron_stream_analysis_completed_term_id;
1138
static int hf_aeron_stream_analysis_completed_term_offset;
1139
static int hf_aeron_stream_analysis_outstanding_bytes;
1140
1141
/* Expert info handles */
1142
static expert_field ei_aeron_analysis_nak;
1143
static expert_field ei_aeron_analysis_window_full;
1144
static expert_field ei_aeron_analysis_idle_rx;
1145
static expert_field ei_aeron_analysis_pacing_rx;
1146
static expert_field ei_aeron_analysis_ooo;
1147
static expert_field ei_aeron_analysis_ooo_gap;
1148
static expert_field ei_aeron_analysis_keepalive;
1149
static expert_field ei_aeron_analysis_ooo_sm;
1150
static expert_field ei_aeron_analysis_keepalive_sm;
1151
static expert_field ei_aeron_analysis_window_resize;
1152
static expert_field ei_aeron_analysis_rx;
1153
static expert_field ei_aeron_analysis_term_id_change;
1154
static expert_field ei_aeron_analysis_invalid_pad_length;
1155
static expert_field ei_aeron_analysis_invalid_data_length;
1156
static expert_field ei_aeron_analysis_invalid_nak_length;
1157
static expert_field ei_aeron_analysis_invalid_sm_length;
1158
static expert_field ei_aeron_analysis_invalid_rtt_length;
1159
static expert_field ei_aeron_analysis_invalid_err_length;
1160
static expert_field ei_aeron_analysis_invalid_setup_length;
1161
1162
/*----------------------------------------------------------------------------*/
1163
/* Setup packet information                                                   */
1164
/*----------------------------------------------------------------------------*/
1165
typedef struct
1166
{
1167
    uint32_t info_flags;
1168
    uint32_t stream_id;
1169
    uint32_t term_id;
1170
    uint32_t term_offset;
1171
    uint32_t length;
1172
    uint32_t data_length;
1173
    uint32_t receiver_window;
1174
    uint64_t receiver_id;
1175
    uint32_t nak_term_offset;
1176
    uint32_t nak_length;
1177
    uint16_t type;
1178
    uint8_t flags;
1179
} aeron_packet_info_t;
1180
0
#define AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID   0x00000001
1181
0
#define AERON_PACKET_INFO_FLAGS_TERM_ID_VALID     0x00000002
1182
0
#define AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID 0x00000004
1183
1184
static void aeron_frame_nak_rx_add(aeron_frame_info_t * nak_info, aeron_frame_info_t * rx_info, uint32_t term_offset, uint32_t length)
1185
0
{
1186
0
    if (nak_info->nak_analysis->unrecovered_length >= length)
1187
0
    {
1188
0
        wmem_list_frame_t * lf = wmem_list_head(nak_info->nak_analysis->rx);
1189
0
        aeron_rx_info_t * rx = NULL;
1190
1191
0
        while (lf != NULL)
1192
0
        {
1193
0
            rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1194
0
            if (rx != NULL)
1195
0
            {
1196
0
                if ((rx->term_offset == term_offset) && (rx->length == length))
1197
0
                {
1198
                    /* Already have this RX */
1199
0
                    return;
1200
0
                }
1201
0
            }
1202
0
            lf = wmem_list_frame_next(lf);
1203
0
        }
1204
        /* This RX frame isn't in the list, so add it */
1205
0
        rx = wmem_new0(wmem_file_scope(), aeron_rx_info_t);
1206
0
        rx->frame_info = rx_info;
1207
0
        rx->term_offset = term_offset;
1208
0
        rx->length = length;
1209
0
        wmem_list_append(nak_info->nak_analysis->rx, (void *) rx);
1210
0
        nak_info->nak_analysis->unrecovered_length -= length;
1211
0
        wmem_list_append(rx_info->rx, (void *) nak_info);
1212
0
    }
1213
0
}
1214
1215
static void aeron_frame_process_rx(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1216
0
{
1217
0
    wmem_list_frame_t * lf;
1218
1219
0
    lf = wmem_list_head(term->nak);
1220
0
    while (lf != NULL)
1221
0
    {
1222
0
        aeron_nak_t * nak = (aeron_nak_t *) wmem_list_frame_data(lf);
1223
0
        if (nak != NULL)
1224
0
        {
1225
0
            if (nak->frame_info->frame <= finfo->frame)
1226
0
            {
1227
0
                if ((nak->term_offset <= info->term_offset) && (nak->length >= info->length))
1228
0
                {
1229
                    /* This data frame falls entirely within the NAK range */
1230
0
                    aeron_frame_nak_rx_add(nak->frame_info, finfo, info->term_offset, info->length);
1231
0
                }
1232
0
            }
1233
0
        }
1234
0
        lf = wmem_list_frame_next(lf);
1235
0
    }
1236
0
}
1237
1238
static void aeron_frame_nak_analysis_setup(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1239
0
{
1240
0
    aeron_nak_t * nak = wmem_new0(wmem_file_scope(), aeron_nak_t);
1241
0
    nak->term = term;
1242
0
    nak->frame_info = finfo;
1243
0
    nak->term_offset = info->nak_term_offset;
1244
0
    nak->length = info->nak_length;
1245
0
    wmem_list_append(term->nak, (void *) nak);
1246
1247
0
    finfo->nak_analysis = wmem_new0(wmem_file_scope(), aeron_nak_analysis_t);
1248
0
    finfo->nak_analysis->frame_info = finfo;
1249
0
    finfo->nak_analysis->rx = wmem_list_new(wmem_file_scope());
1250
0
    finfo->nak_analysis->nak_term_offset = info->nak_term_offset;
1251
0
    finfo->nak_analysis->nak_length = info->nak_length;
1252
0
    finfo->nak_analysis->unrecovered_length = info->nak_length;
1253
0
}
1254
1255
/* return 0 for success and -1 for error */
1256
static int aeron_frame_stream_analysis_setup(packet_info * pinfo, aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_stream_t * stream, aeron_term_t * term, bool new_term)
1257
0
{
1258
0
    aeron_stream_rcv_t * rcv = NULL;
1259
    /*  dp is the current data position (from this frame). */
1260
0
    aeron_pos_t dp = { 0, 0 };
1261
    /*
1262
        pdp is the previous (high) data position (from the stream).
1263
        pdpv is true if pdp is valid (meaning we previously saw a data message).
1264
    */
1265
0
    aeron_pos_t pdp = stream->high;
1266
0
    bool pdpv = ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0);
1267
    /*  rp is the current receiver position (from this frame). */
1268
0
    aeron_pos_t rp = { 0, 0 };
1269
    /*
1270
        prp is the previous (high) receiver completed position (from the stream receiver).
1271
        prpv is true if prp is valid (meaning we previously saw a status message).
1272
    */
1273
0
    aeron_pos_t prp = { 0, 0 };
1274
0
    bool prpv = false;
1275
0
    uint32_t cur_receiver_window = 0;
1276
    /* Flags to be used when creating the fragment frame entry */
1277
0
    uint32_t frame_flags = 0;
1278
1279
0
    if (info->type == HDR_TYPE_SM)
1280
0
    {
1281
        /* Locate the receiver */
1282
0
        rcv = aeron_stream_rcv_find(stream, &(pinfo->src), pinfo->srcport);
1283
0
        if (rcv == NULL)
1284
0
        {
1285
0
            rcv = aeron_stream_rcv_add(stream, &(pinfo->src), pinfo->srcport);
1286
0
        }
1287
0
        else
1288
0
        {
1289
0
            prpv = true;
1290
0
            prp = rcv->completed;
1291
0
            cur_receiver_window = rcv->receiver_window;
1292
0
        }
1293
0
    }
1294
0
    switch (info->type)
1295
0
    {
1296
0
        case HDR_TYPE_DATA:
1297
0
        case HDR_TYPE_PAD:
1298
0
            dp.term_id = info->term_id;
1299
0
            dp.term_offset = info->term_offset;
1300
0
            if (!aeron_pos_add_length(&dp, info->length, stream->term_length))
1301
0
                return -1;
1302
0
            if (pdpv)
1303
0
            {
1304
0
                if (dp.term_id > stream->high.term_id)
1305
0
                {
1306
0
                    stream->high.term_id = dp.term_id;
1307
0
                    stream->high.term_offset = dp.term_offset;
1308
0
                }
1309
0
                else if (dp.term_offset > stream->high.term_offset)
1310
0
                {
1311
0
                    stream->high.term_offset = dp.term_offset;
1312
0
                }
1313
0
            }
1314
0
            else
1315
0
            {
1316
0
                stream->flags |= AERON_STREAM_FLAGS_HIGH_VALID;
1317
0
                stream->high.term_id = dp.term_id;
1318
0
                stream->high.term_offset = dp.term_offset;
1319
0
            }
1320
0
            break;
1321
0
        case HDR_TYPE_SM:
1322
0
            rp.term_id = info->term_id;
1323
0
            rp.term_offset = info->term_offset;
1324
0
            if (prpv)
1325
0
            {
1326
0
                if (rp.term_id > rcv->completed.term_id)
1327
0
                {
1328
0
                    rcv->completed.term_id = rp.term_id;
1329
0
                    rcv->completed.term_offset = rp.term_offset;
1330
0
                }
1331
0
                else if (rp.term_offset > rcv->completed.term_offset)
1332
0
                {
1333
0
                    rcv->completed.term_offset = rp.term_offset;
1334
0
                }
1335
0
            }
1336
0
            else
1337
0
            {
1338
0
                rcv->completed.term_id = rp.term_id;
1339
0
                rcv->completed.term_offset = rp.term_offset;
1340
0
            }
1341
0
            rcv->receiver_window = info->receiver_window;
1342
0
            break;
1343
0
        default:
1344
0
            break;
1345
0
    }
1346
0
    if (aeron_stream_analysis)
1347
0
    {
1348
0
        if ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0)
1349
0
        {
1350
0
            finfo->stream_analysis = wmem_new0(wmem_file_scope(), aeron_stream_analysis_t);
1351
0
        }
1352
0
    }
1353
0
    if (finfo->stream_analysis != NULL)
1354
0
    {
1355
0
        switch (info->type)
1356
0
        {
1357
0
            case HDR_TYPE_DATA:
1358
0
            case HDR_TYPE_SM:
1359
0
            case HDR_TYPE_PAD:
1360
0
                finfo->stream_analysis->high.term_id = stream->high.term_id;
1361
0
                finfo->stream_analysis->high.term_offset = stream->high.term_offset;
1362
0
                if (rcv != NULL)
1363
0
                {
1364
0
                    finfo->stream_analysis->flags2 |= AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID;
1365
0
                    finfo->stream_analysis->completed.term_id = rcv->completed.term_id;
1366
0
                    finfo->stream_analysis->completed.term_offset = rcv->completed.term_offset;
1367
0
                    finfo->stream_analysis->receiver_window = rcv->receiver_window;
1368
0
                    finfo->stream_analysis->outstanding_bytes = aeron_pos_delta(&(finfo->stream_analysis->high), &(finfo->stream_analysis->completed), stream->term_length);
1369
0
                    if (finfo->stream_analysis->outstanding_bytes >= finfo->stream_analysis->receiver_window)
1370
0
                    {
1371
0
                        finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL;
1372
0
                    }
1373
0
                }
1374
0
                else
1375
0
                {
1376
0
                    finfo->stream_analysis->completed.term_id = 0;
1377
0
                    finfo->stream_analysis->completed.term_offset = 0;
1378
0
                    finfo->stream_analysis->receiver_window = 0;
1379
0
                    finfo->stream_analysis->outstanding_bytes = 0;
1380
0
                }
1381
0
                break;
1382
0
            default:
1383
0
                break;
1384
0
        }
1385
0
        switch (info->type)
1386
0
        {
1387
0
            case HDR_TYPE_DATA:
1388
0
            case HDR_TYPE_PAD:
1389
0
                if (pdpv)
1390
0
                {
1391
                    /* We have a previous data position. */
1392
0
                    int rc = aeron_pos_compare(&dp, &pdp);
1393
0
                    if (rc == 0)
1394
0
                    {
1395
                        /* Data position is the same as previous data position. */
1396
0
                        if (info->length == 0)
1397
0
                        {
1398
0
                            finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE;
1399
0
                            frame_flags |= AERON_FRAME_INFO_FLAGS_KEEPALIVE;
1400
0
                        }
1401
0
                        else
1402
0
                        {
1403
0
                            if (prpv)
1404
0
                            {
1405
                                /* Previous receiver position is valid */
1406
0
                                if (aeron_pos_compare(&dp, &prp) == 0)
1407
0
                                {
1408
0
                                    finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1409
0
                                }
1410
0
                                else
1411
0
                                {
1412
0
                                    finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_PACING_RX;
1413
0
                                }
1414
0
                            }
1415
0
                            else
1416
0
                            {
1417
0
                                finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1418
0
                            }
1419
0
                            frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1420
0
                        }
1421
0
                    }
1422
0
                    else
1423
0
                    {
1424
0
                        aeron_pos_t expected_dp;
1425
0
                        int erc;
1426
1427
0
                        expected_dp.term_id = pdp.term_id;
1428
0
                        expected_dp.term_offset = pdp.term_offset;
1429
0
                        if (!aeron_pos_add_length(&expected_dp, info->length, stream->term_length))
1430
0
                            return -1;
1431
0
                        erc = aeron_pos_compare(&expected_dp, &dp);
1432
0
                        if (erc > 0)
1433
0
                        {
1434
                            /* Could be OOO - but for now assume it's a RX */
1435
0
                            finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_RX;
1436
0
                            frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1437
0
                            aeron_frame_process_rx(info, finfo, term);
1438
0
                        }
1439
0
                        else if (erc < 0)
1440
0
                        {
1441
0
                            finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP;
1442
0
                        }
1443
0
                    }
1444
0
                }
1445
0
                if (new_term && (info->term_offset == 0))
1446
0
                {
1447
0
                    finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE;
1448
0
                }
1449
0
                break;
1450
0
            case HDR_TYPE_SM:
1451
0
                if (prpv)
1452
0
                {
1453
0
                    int rc = aeron_pos_compare(&rp, &prp);
1454
0
                    if (rc == 0)
1455
0
                    {
1456
                        /* Completed term ID and term offset stayed the same. */
1457
0
                       finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM;
1458
0
                    }
1459
0
                    else if (rc < 0)
1460
0
                    {
1461
0
                        finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_SM;
1462
0
                    }
1463
0
                    if (cur_receiver_window != finfo->stream_analysis->receiver_window)
1464
0
                    {
1465
0
                        finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE;
1466
0
                    }
1467
0
                }
1468
0
                break;
1469
0
            default:
1470
0
                break;
1471
0
        }
1472
0
    }
1473
0
    if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1474
0
    {
1475
0
        aeron_fragment_t * fragment;
1476
1477
0
        fragment = aeron_term_fragment_find(term, info->term_offset);
1478
0
        if (fragment == NULL)
1479
0
        {
1480
0
            fragment = aeron_term_fragment_add(term, info->term_offset, info->length, info->data_length);
1481
0
        }
1482
0
        aeron_fragment_frame_add(fragment, finfo, frame_flags, info->length);
1483
0
    }
1484
0
    else
1485
0
    {
1486
0
        aeron_term_frame_add(term, finfo, frame_flags);
1487
0
    }
1488
1489
0
    return 0;
1490
0
}
1491
1492
/* return 0 for success and -1 for error */
1493
static int aeron_frame_info_setup(packet_info * pinfo, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo)
1494
0
{
1495
0
    if (!transport || !aeron_sequence_analysis || !finfo || PINFO_FD_VISITED(pinfo))
1496
        /* XXX - is it an error if transport, aeron_sequence_analysis or finfo are NULL? */
1497
0
        return 0;
1498
1499
0
    if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1500
0
    {
1501
0
        aeron_stream_t * stream;
1502
1503
0
        stream = aeron_transport_stream_find(transport, info->stream_id);
1504
0
        if (stream == NULL)
1505
0
        {
1506
0
            stream = aeron_transport_stream_add(transport, info->stream_id);
1507
0
        }
1508
0
        if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1509
0
        {
1510
0
            aeron_term_t * term;
1511
0
            bool new_term = false;
1512
1513
0
            term = aeron_stream_term_find(stream, info->term_id);
1514
0
            if (term == NULL)
1515
0
            {
1516
0
                term = aeron_stream_term_add(stream, info->term_id);
1517
0
                new_term = true;
1518
0
            }
1519
0
            if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1520
0
            {
1521
0
                if (aeron_frame_stream_analysis_setup(pinfo, info, finfo, stream, term, new_term) < 0)
1522
0
                    return -1;
1523
0
            }
1524
0
            else
1525
0
            {
1526
0
                aeron_term_frame_add(term, finfo, 0);
1527
0
                if (info->type == HDR_TYPE_NAK)
1528
0
                {
1529
0
                    aeron_frame_nak_analysis_setup(info, finfo, term);
1530
0
                }
1531
0
            }
1532
0
        }
1533
0
        else
1534
0
        {
1535
0
            aeron_stream_frame_add(stream, finfo, 0);
1536
0
        }
1537
0
    }
1538
0
    else
1539
0
    {
1540
0
        aeron_transport_frame_add(transport, finfo, 0);
1541
0
    }
1542
1543
0
    return 0;
1544
0
}
1545
1546
static void aeron_sequence_report_frame(tvbuff_t * tvb, proto_tree * tree, aeron_frame_info_t * finfo)
1547
0
{
1548
0
    proto_item * item = NULL;
1549
1550
0
    if ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0)
1551
0
    {
1552
0
        item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" PRIu32 " (RX)", finfo->frame);
1553
0
    }
1554
0
    else if ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0)
1555
0
    {
1556
0
        item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" PRIu32 " (KA)", finfo->frame);
1557
0
    }
1558
0
    else
1559
0
    {
1560
0
        item = proto_tree_add_uint(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame);
1561
0
    }
1562
0
    proto_item_set_generated(item);
1563
0
}
1564
1565
static void aeron_sequence_report(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo)
1566
0
{
1567
0
    if (transport != NULL)
1568
0
    {
1569
0
        if (aeron_sequence_analysis && (finfo != NULL))
1570
0
        {
1571
0
            proto_tree * subtree;
1572
0
            proto_item * item;
1573
1574
0
            item = proto_tree_add_item(tree, hf_aeron_sequence_analysis, tvb, 0, 0, ENC_NA);
1575
0
            proto_item_set_generated(item);
1576
0
            subtree = proto_item_add_subtree(item, ett_aeron_sequence_analysis);
1577
0
            if (finfo->transport.previous != 0)
1578
0
            {
1579
0
                item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_prev_frame, tvb, 0, 0, finfo->transport.previous);
1580
0
                proto_item_set_generated(item);
1581
0
            }
1582
0
            if (finfo->transport.next != 0)
1583
0
            {
1584
0
                item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_next_frame, tvb, 0, 0, finfo->transport.next);
1585
0
                proto_item_set_generated(item);
1586
0
            }
1587
0
            if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1588
0
            {
1589
0
                aeron_stream_t * stream;
1590
1591
0
                stream = aeron_transport_stream_find(transport, info->stream_id);
1592
0
                if (stream != NULL)
1593
0
                {
1594
0
                    if (finfo->stream.previous != 0)
1595
0
                    {
1596
0
                        item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_prev_frame, tvb, 0, 0, finfo->stream.previous);
1597
0
                        proto_item_set_generated(item);
1598
0
                    }
1599
0
                    if (finfo->stream.next != 0)
1600
0
                    {
1601
0
                        item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_next_frame, tvb, 0, 0, finfo->stream.next);
1602
0
                        proto_item_set_generated(item);
1603
0
                    }
1604
0
                    if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1605
0
                    {
1606
0
                        aeron_term_t * term;
1607
1608
0
                        term = aeron_stream_term_find(stream, info->term_id);
1609
0
                        if (term != NULL)
1610
0
                        {
1611
0
                            if (finfo->term.previous != 0)
1612
0
                            {
1613
0
                                item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_prev_frame, tvb, 0, 0, finfo->term.previous);
1614
0
                                proto_item_set_generated(item);
1615
0
                            }
1616
0
                            if (finfo->term.next != 0)
1617
0
                            {
1618
0
                                item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_next_frame, tvb, 0, 0, finfo->term.next);
1619
0
                                proto_item_set_generated(item);
1620
0
                            }
1621
0
                            if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1622
0
                            {
1623
0
                                if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1624
0
                                {
1625
0
                                    aeron_fragment_t * fragment;
1626
1627
0
                                    fragment = aeron_term_fragment_find(term, info->term_offset);
1628
0
                                    if (fragment != NULL)
1629
0
                                    {
1630
0
                                        proto_item * fei_item;
1631
0
                                        bool rx = ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0);
1632
0
                                        bool ka = ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0);
1633
1634
0
                                        if (fragment->frame_count > 1)
1635
0
                                        {
1636
0
                                            proto_tree * frame_tree;
1637
0
                                            proto_item * frame_item;
1638
0
                                            wmem_list_frame_t * lf;
1639
1640
0
                                            frame_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_term_offset, tvb, 0, 0, ENC_NA);
1641
0
                                            proto_item_set_generated(frame_item);
1642
0
                                            frame_tree = proto_item_add_subtree(frame_item, ett_aeron_sequence_analysis_term_offset);
1643
0
                                            lf = wmem_list_head(fragment->frame);
1644
0
                                            while (lf != NULL)
1645
0
                                            {
1646
0
                                                aeron_frame_info_t * frag_frame = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1647
0
                                                if (frag_frame != NULL)
1648
0
                                                {
1649
0
                                                    if (frag_frame->frame != pinfo->num)
1650
0
                                                    {
1651
0
                                                        aeron_sequence_report_frame(tvb, frame_tree, frag_frame);
1652
0
                                                    }
1653
0
                                                }
1654
0
                                                lf = wmem_list_frame_next(lf);
1655
0
                                            }
1656
0
                                        }
1657
0
                                        fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_retransmission, tvb, 0, 0, rx);
1658
0
                                        proto_item_set_generated(fei_item);
1659
0
                                        if (rx)
1660
0
                                        {
1661
0
                                            if (wmem_list_count(finfo->rx) > 0)
1662
0
                                            {
1663
0
                                                proto_tree * rx_tree;
1664
0
                                                proto_item * rx_item;
1665
0
                                                wmem_list_frame_t * lf;
1666
1667
0
                                                rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_retransmission_rx, tvb, 0, 0, ENC_NA);
1668
0
                                                proto_item_set_generated(rx_item);
1669
0
                                                rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_retransmission_rx);
1670
0
                                                lf = wmem_list_head(finfo->rx);
1671
0
                                                while (lf != NULL)
1672
0
                                                {
1673
0
                                                    aeron_frame_info_t * nak = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1674
0
                                                    if (nak != NULL)
1675
0
                                                    {
1676
0
                                                        rx_item = proto_tree_add_uint(rx_tree, hf_aeron_sequence_analysis_retransmission_rx_frame, tvb, 0, 0, nak->frame);
1677
0
                                                        proto_item_set_generated(rx_item);
1678
0
                                                    }
1679
0
                                                    lf = wmem_list_frame_next(lf);
1680
0
                                                }
1681
0
                                            }
1682
0
                                        }
1683
0
                                        fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_keepalive, tvb, 0, 0, ka);
1684
0
                                        proto_item_set_generated(fei_item);
1685
0
                                    }
1686
0
                                }
1687
0
                            }
1688
0
                            else if ((info->type == HDR_TYPE_NAK) && (finfo->nak_analysis != NULL))
1689
0
                            {
1690
0
                                proto_item * nak_item;
1691
1692
0
                                nak_item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_nak_unrecovered, tvb, 0, 0, finfo->nak_analysis->unrecovered_length);
1693
0
                                proto_item_set_generated(nak_item);
1694
0
                                if (wmem_list_count(finfo->nak_analysis->rx) > 0)
1695
0
                                {
1696
0
                                    proto_tree * rx_tree;
1697
0
                                    proto_item * rx_item;
1698
0
                                    wmem_list_frame_t * lf;
1699
1700
0
                                    rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_nak_rx, tvb, 0, 0, ENC_NA);
1701
0
                                    proto_item_set_generated(rx_item);
1702
0
                                    rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_nak_rx);
1703
0
                                    lf = wmem_list_head(finfo->nak_analysis->rx);
1704
0
                                    while (lf != NULL)
1705
0
                                    {
1706
0
                                        aeron_rx_info_t * rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1707
0
                                        if (rx != NULL)
1708
0
                                        {
1709
0
                                            rx_item = proto_tree_add_uint_format_value(rx_tree, hf_aeron_sequence_analysis_nak_rx_frame, tvb, 0, 0, rx->frame_info->frame,
1710
0
                                                "%" PRIu32 ", Term offset=%" PRIu32 " (0x%08x), Length=%" PRIu32, rx->frame_info->frame, rx->term_offset, rx->term_offset, rx->length);
1711
0
                                            proto_item_set_generated(rx_item);
1712
0
                                        }
1713
0
                                        lf = wmem_list_frame_next(lf);
1714
0
                                    }
1715
0
                                }
1716
0
                            }
1717
0
                        }
1718
0
                    }
1719
0
                }
1720
0
            }
1721
0
        }
1722
0
    }
1723
0
}
1724
1725
static void aeron_stream_report(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, aeron_transport_t * transport, aeron_frame_info_t * finfo)
1726
0
{
1727
0
    if (transport != NULL)
1728
0
    {
1729
0
        if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1730
0
        {
1731
0
            proto_tree * subtree;
1732
0
            proto_item * item;
1733
1734
0
            item = proto_tree_add_item(tree, hf_aeron_stream_analysis, tvb, 0, 0, ENC_NA);
1735
0
            proto_item_set_generated(item);
1736
0
            subtree = proto_item_add_subtree(item, ett_aeron_stream_analysis);
1737
0
            item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_id, tvb, 0, 0, finfo->stream_analysis->high.term_id);
1738
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE) != 0)
1739
0
            {
1740
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_term_id_change);
1741
0
            }
1742
0
            proto_item_set_generated(item);
1743
0
            item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_offset, tvb, 0, 0, finfo->stream_analysis->high.term_offset);
1744
0
            proto_item_set_generated(item);
1745
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX) != 0)
1746
0
            {
1747
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_idle_rx);
1748
0
            }
1749
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_PACING_RX) != 0)
1750
0
            {
1751
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_pacing_rx);
1752
0
            }
1753
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO) != 0)
1754
0
            {
1755
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_ooo);
1756
0
            }
1757
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP) != 0)
1758
0
            {
1759
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_gap);
1760
0
            }
1761
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1762
0
            {
1763
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive);
1764
0
            }
1765
0
            if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_RX) != 0)
1766
0
            {
1767
0
                expert_add_info(pinfo, item, &ei_aeron_analysis_rx);
1768
0
            }
1769
0
            if ((finfo->stream_analysis->flags2 & AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID) != 0)
1770
0
            {
1771
0
                item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_id, tvb, 0, 0, finfo->stream_analysis->completed.term_id);
1772
0
                proto_item_set_generated(item);
1773
0
                item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_offset, tvb, 0, 0, finfo->stream_analysis->completed.term_offset);
1774
0
                proto_item_set_generated(item);
1775
0
                if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_SM) != 0)
1776
0
                {
1777
0
                    expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_sm);
1778
0
                }
1779
0
                if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1780
0
                {
1781
0
                    expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive_sm);
1782
0
                }
1783
0
                item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_outstanding_bytes, tvb, 0, 0, finfo->stream_analysis->outstanding_bytes);
1784
0
                proto_item_set_generated(item);
1785
0
                if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL) != 0)
1786
0
                {
1787
0
                    expert_add_info(pinfo, item, &ei_aeron_analysis_window_full);
1788
0
                }
1789
0
            }
1790
0
        }
1791
0
    }
1792
0
}
1793
1794
static void aeron_next_offset_report(tvbuff_t * tvb, proto_tree * tree, aeron_transport_t * transport, uint32_t stream_id, uint32_t term_id, uint32_t term_offset, uint32_t length)
1795
0
{
1796
0
    aeron_stream_t * stream;
1797
1798
0
    stream = aeron_transport_stream_find(transport, stream_id);
1799
0
    if (stream != NULL)
1800
0
    {
1801
0
        aeron_term_t * term;
1802
0
        if (stream->term_length == 0)
1803
0
        {
1804
0
            stream->term_length = length;
1805
0
        }
1806
0
        term = aeron_stream_term_find(stream, term_id);
1807
0
        if (term != NULL)
1808
0
        {
1809
0
            aeron_fragment_t * fragment = aeron_term_fragment_find(term, term_offset);
1810
0
            if (fragment != NULL)
1811
0
            {
1812
0
                uint32_t next_offset = term_offset + length;
1813
0
                uint32_t next_offset_term_id = term_id;
1814
0
                aeron_term_t * next_offset_term = NULL;
1815
0
                proto_item * item;
1816
1817
0
                if (next_offset >= stream->term_length)
1818
0
                {
1819
0
                    next_offset = 0;
1820
0
                    next_offset_term_id++;
1821
0
                }
1822
0
                item = proto_tree_add_uint(tree, hf_aeron_data_next_offset, tvb, 0, 0, next_offset);
1823
0
                proto_item_set_generated(item);
1824
0
                if (next_offset_term_id != term_id)
1825
0
                {
1826
0
                    next_offset_term = aeron_stream_term_find(stream, next_offset_term_id);
1827
0
                    item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_term, tvb, 0, 0, next_offset_term_id);
1828
0
                    proto_item_set_generated(item);
1829
0
                }
1830
0
                else
1831
0
                {
1832
0
                    next_offset_term = term;
1833
0
                }
1834
0
                if (next_offset_term != NULL)
1835
0
                {
1836
0
                    aeron_fragment_t * next_offset_fragment;
1837
0
                    next_offset_fragment = aeron_term_fragment_find(next_offset_term, next_offset);
1838
0
                    if (next_offset_fragment != NULL)
1839
0
                    {
1840
0
                        if (next_offset_fragment->first_frame != NULL)
1841
0
                        {
1842
0
                            item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_first_frame, tvb, 0, 0, next_offset_fragment->first_frame->frame);
1843
0
                            proto_item_set_generated(item);
1844
0
                        }
1845
0
                    }
1846
0
                }
1847
0
            }
1848
0
        }
1849
0
    }
1850
0
}
1851
1852
static void aeron_info_stream_progress_report(packet_info * pinfo, uint16_t msgtype, uint8_t flags, uint32_t term_id, uint32_t term_offset, aeron_frame_info_t * finfo)
1853
0
{
1854
0
    const char * type_string = val_to_str_const((uint32_t) msgtype, aeron_frame_type, "Unknown");
1855
1856
0
    if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1857
0
    {
1858
0
        switch (msgtype)
1859
0
        {
1860
0
            case HDR_TYPE_PAD:
1861
0
            case HDR_TYPE_DATA:
1862
0
                if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1863
0
                {
1864
0
                    col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1865
0
                }
1866
0
                else
1867
0
                {
1868
0
                    col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" PRIu32 ")",
1869
0
                        type_string, term_id, term_offset);
1870
0
                }
1871
0
                break;
1872
0
            case HDR_TYPE_SM:
1873
0
                if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1874
0
                {
1875
0
                    col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1876
0
                }
1877
0
                else
1878
0
                {
1879
0
                    if (finfo->stream_analysis->high.term_id == finfo->stream_analysis->completed.term_id)
1880
0
                    {
1881
0
                        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%" PRIu32 "/%" PRIu32 " [%" PRIu32 "])",
1882
0
                            type_string, finfo->stream_analysis->high.term_offset, finfo->stream_analysis->completed.term_offset, finfo->stream_analysis->outstanding_bytes);
1883
0
                    }
1884
0
                    else
1885
0
                    {
1886
0
                        col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" PRIu32 "/0x%08x:%" PRIu32 " [%" PRIu32 "])",
1887
0
                            type_string, finfo->stream_analysis->high.term_id, finfo->stream_analysis->high.term_offset, finfo->stream_analysis->completed.term_id, finfo->stream_analysis->completed.term_offset, finfo->stream_analysis->outstanding_bytes);
1888
0
                    }
1889
0
                }
1890
0
                break;
1891
0
        }
1892
0
    }
1893
0
    else
1894
0
    {
1895
0
        if ((msgtype == HDR_TYPE_SM) && ((flags & STATUS_FLAGS_SETUP) != 0))
1896
0
        {
1897
0
            col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-SETUP", type_string);
1898
0
        }
1899
0
        else
1900
0
        {
1901
0
            col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", type_string);
1902
0
        }
1903
0
    }
1904
0
}
1905
1906
/*----------------------------------------------------------------------------*/
1907
/* Payload reassembly.                                                        */
1908
/*----------------------------------------------------------------------------*/
1909
struct aeron_msg_fragment_t_stct;
1910
typedef struct aeron_msg_fragment_t_stct aeron_msg_fragment_t;
1911
1912
struct aeron_msg_t_stct
1913
{
1914
    wmem_list_t * fragment;
1915
    aeron_term_t * term;
1916
    tvbuff_t * reassembled_data;
1917
    uint32_t first_fragment_term_offset;
1918
    uint32_t next_expected_term_offset;
1919
    uint32_t length;                 /* Total message payload length */
1920
    uint32_t frame_length;           /* Total length of all message frames accumulated */
1921
    uint32_t fragment_count;         /* Number of fragments in this message */
1922
    uint32_t contiguous_length;      /* Number of contiguous frame bytes accumulated for this message */
1923
    uint32_t begin_frame;            /* Data frame in which the B flag was set */
1924
    uint32_t first_frame;            /* Lowest-numbered frame which is part of this message */
1925
    uint32_t end_frame;              /* Data frame in which the E flag was set */
1926
    uint32_t last_frame;             /* Highest-numbered frame which is part of this message */
1927
    bool complete;
1928
};
1929
1930
struct aeron_msg_fragment_t_stct
1931
{
1932
    char * data;
1933
    uint32_t term_offset;            /* Term offset for entire fragment */
1934
    uint32_t frame_length;           /* Length of entire frame/fragment */
1935
    uint32_t data_length;            /* Payload length */
1936
    uint32_t frame;                  /* Frame in which the fragment resides */
1937
    int frame_offset;              /* Offset into the frame for the entire Aeron message */
1938
    uint8_t flags;                   /* Frame data flags */
1939
};
1940
1941
static void aeron_msg_fragment_add(aeron_msg_t * msg, aeron_msg_fragment_t * fragment)
1942
0
{
1943
    /* Add the fragment to the message */
1944
0
    wmem_list_append(msg->fragment, (void *) fragment);
1945
    /* Update the message */
1946
0
    msg->length += fragment->data_length;
1947
0
    msg->contiguous_length += fragment->data_length;
1948
0
    msg->fragment_count++;
1949
0
    if (msg->first_frame > fragment->frame)
1950
0
    {
1951
0
        msg->first_frame = fragment->frame;
1952
0
    }
1953
0
    if (msg->last_frame < fragment->frame)
1954
0
    {
1955
0
        msg->last_frame = fragment->frame;
1956
0
    }
1957
0
    msg->next_expected_term_offset += fragment->frame_length;
1958
0
    if ((fragment->flags & DATA_FLAGS_END) == DATA_FLAGS_END)
1959
0
    {
1960
0
        uint8_t * buf;
1961
0
        wmem_list_frame_t * lf;
1962
0
        size_t ofs = 0;
1963
0
        size_t accum_len = 0;
1964
0
        uint32_t last_frame_offset = 0;
1965
0
        bool last_frame_found = false;
1966
0
        aeron_frame_info_t * finfo = NULL;
1967
1968
0
        msg->complete = true;
1969
0
        msg->end_frame = fragment->frame;
1970
0
        buf = (uint8_t *) wmem_alloc(wmem_file_scope(), (size_t) msg->length);
1971
0
        lf = wmem_list_head(msg->fragment);
1972
0
        while (lf != NULL)
1973
0
        {
1974
0
            aeron_msg_fragment_t * cur_frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
1975
0
            if (cur_frag != NULL)
1976
0
            {
1977
0
                if (cur_frag->frame == msg->last_frame)
1978
0
                {
1979
0
                    last_frame_offset = cur_frag->frame_offset;
1980
0
                    last_frame_found = true;
1981
0
                }
1982
0
                memcpy((void *) (buf + ofs), (void *) cur_frag->data, (size_t) cur_frag->data_length);
1983
0
                ofs += (size_t) cur_frag->data_length;
1984
0
                accum_len += (size_t) cur_frag->data_length;
1985
0
            }
1986
0
            lf = wmem_list_frame_next(lf);
1987
0
        }
1988
0
        DISSECTOR_ASSERT(accum_len == (size_t) msg->length);
1989
0
        DISSECTOR_ASSERT(last_frame_found == true);
1990
0
        if (last_frame_found)
1991
0
        {
1992
0
            finfo = aeron_frame_info_find(wmem_packet_scope(), msg->last_frame, last_frame_offset);
1993
0
        }
1994
0
        msg->reassembled_data = tvb_new_real_data(buf, msg->length, msg->length);
1995
0
        DISSECTOR_ASSERT(finfo != NULL);
1996
0
        if (finfo != NULL)
1997
0
        {
1998
0
            finfo->flags |= AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG;
1999
0
            finfo->message = msg;
2000
0
        }
2001
0
    }
2002
0
}
2003
2004
static bool aeron_msg_process_orphan_fragments_msg_cb(const void *key _U_, void * value, void * userdata)
2005
0
{
2006
0
    aeron_msg_t * msg = (aeron_msg_t *) value;
2007
0
    aeron_term_t * term = (aeron_term_t *) userdata;
2008
0
    bool frag_found = false;
2009
0
    wmem_list_frame_t * lf = NULL;
2010
0
    aeron_msg_fragment_t * frag = NULL;
2011
2012
0
    if (msg->complete)
2013
0
    {
2014
        /* This message is complete, no need to check for orphans */
2015
0
        return false;
2016
0
    }
2017
    /* Scan through the orphan fragments */
2018
0
    while (true)
2019
0
    {
2020
0
        lf = wmem_list_head(term->orphan_fragment);
2021
0
        while (lf != NULL)
2022
0
        {
2023
0
            frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2024
0
            if (frag != NULL)
2025
0
            {
2026
0
                if (msg->next_expected_term_offset == frag->term_offset)
2027
0
                {
2028
                    /* Found one! Remove it from the orphan list, and add it to the message */
2029
0
                    wmem_list_remove_frame(term->orphan_fragment, lf);
2030
0
                    aeron_msg_fragment_add(msg, frag);
2031
0
                    frag_found = true;
2032
0
                    break;
2033
0
                }
2034
0
            }
2035
0
            lf = wmem_list_frame_next(lf);
2036
0
        }
2037
0
        if (!frag_found)
2038
0
        {
2039
0
            break;
2040
0
        }
2041
0
        frag_found = false;
2042
0
    }
2043
0
    return false;
2044
0
}
2045
2046
static void aeron_msg_process_orphan_fragments(aeron_term_t * term)
2047
0
{
2048
    /* If we have no orphan fragments to process, nothing to do. */
2049
0
    if (wmem_list_count(term->orphan_fragment) == 0)
2050
0
    {
2051
0
        return;
2052
0
    }
2053
0
    wmem_tree_foreach(term->message, aeron_msg_process_orphan_fragments_msg_cb, (void *) term);
2054
0
}
2055
2056
static aeron_msg_fragment_t * aeron_msg_fragment_create(tvbuff_t * tvb, int offset, packet_info * pinfo, aeron_packet_info_t * info)
2057
0
{
2058
0
    aeron_msg_fragment_t * frag;
2059
2060
0
    frag = wmem_new0(wmem_file_scope(), aeron_msg_fragment_t);
2061
0
    frag->term_offset = info->term_offset;
2062
0
    frag->frame_length = info->length;
2063
0
    frag->data_length = info->data_length;
2064
0
    frag->frame = pinfo->num;
2065
0
    frag->frame_offset = offset;
2066
0
    frag->data = (char *) tvb_memdup(wmem_file_scope(), tvb, frag->frame_offset + O_AERON_DATA_DATA, (size_t) frag->data_length);
2067
0
    frag->flags = info->flags;
2068
0
    return (frag);
2069
0
}
2070
2071
static aeron_msg_fragment_t * aeron_msg_fragment_find(aeron_msg_t * message, aeron_packet_info_t * info)
2072
0
{
2073
0
    aeron_msg_fragment_t * frag = NULL;
2074
0
    wmem_list_frame_t * lf;
2075
2076
0
    if (message->next_expected_term_offset < info->term_offset)
2077
0
    {
2078
0
        return (NULL);
2079
0
    }
2080
0
    lf = wmem_list_head(message->fragment);
2081
0
    while (lf != NULL)
2082
0
    {
2083
0
        frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2084
0
        if (frag != NULL)
2085
0
        {
2086
0
            if (frag->term_offset == info->term_offset)
2087
0
            {
2088
0
                break;
2089
0
            }
2090
0
        }
2091
0
        lf = wmem_list_frame_next(lf);
2092
0
    }
2093
0
    return (frag);
2094
0
}
2095
2096
static aeron_msg_t * aeron_term_msg_find_le(aeron_term_t * term, uint32_t term_offset)
2097
0
{
2098
    /* Return the last aeron_msg_t with starting_fragment_term_offset <= offset */
2099
0
    aeron_msg_t * msg = (aeron_msg_t *) wmem_tree_lookup32_le(term->message, term_offset);
2100
0
    return (msg);
2101
0
}
2102
2103
static aeron_msg_t * aeron_term_msg_add(aeron_term_t * term, packet_info * pinfo, aeron_packet_info_t * info)
2104
0
{
2105
0
    aeron_msg_t * pos;
2106
0
    aeron_msg_t * msg;
2107
2108
0
    pos = aeron_term_msg_find_le(term, info->term_offset);
2109
0
    if ((pos != NULL) && (pos->first_fragment_term_offset == info->term_offset))
2110
0
    {
2111
0
        return (pos);
2112
0
    }
2113
0
    msg = wmem_new0(wmem_file_scope(), aeron_msg_t);
2114
0
    msg->fragment = wmem_list_new(wmem_file_scope());
2115
0
    msg->term = term;
2116
0
    msg->reassembled_data = NULL;
2117
0
    msg->first_fragment_term_offset = info->term_offset;
2118
0
    msg->next_expected_term_offset = info->term_offset;
2119
0
    msg->length = 0;
2120
0
    msg->frame_length = 0;
2121
0
    msg->fragment_count = 0;
2122
0
    msg->contiguous_length = 0;
2123
0
    msg->begin_frame = pinfo->num;
2124
0
    msg->first_frame = pinfo->num;
2125
0
    msg->end_frame = 0;
2126
0
    msg->last_frame = 0;
2127
0
    msg->complete = false;
2128
0
    wmem_tree_insert32(term->message, msg->first_fragment_term_offset, (void *) msg);
2129
0
    return (msg);
2130
0
}
2131
2132
static void aeron_msg_process(tvbuff_t * tvb, int offset, packet_info * pinfo, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo _U_)
2133
0
{
2134
0
    if (aeron_reassemble_fragments && (PINFO_FD_VISITED(pinfo) == 0))
2135
0
    {
2136
0
        if ((info->flags & DATA_FLAGS_COMPLETE) != DATA_FLAGS_COMPLETE)
2137
0
        {
2138
0
            aeron_stream_t * stream = aeron_transport_stream_find(transport, info->stream_id);
2139
0
            if (stream != NULL)
2140
0
            {
2141
0
                aeron_term_t * term = aeron_stream_term_find(stream, info->term_id);
2142
0
                if (term != NULL)
2143
0
                {
2144
0
                    aeron_msg_t * msg = NULL;
2145
0
                    aeron_msg_fragment_t * frag = NULL;
2146
2147
0
                    if ((info->flags & DATA_FLAGS_BEGIN) == DATA_FLAGS_BEGIN)
2148
0
                    {
2149
                        /* Beginning of a message. First see if this message already exists. */
2150
0
                        msg = aeron_term_msg_find_le(term, info->term_offset);
2151
0
                        if (msg != NULL)
2152
0
                        {
2153
0
                            if (msg->first_fragment_term_offset != info->term_offset)
2154
0
                            {
2155
                                /*
2156
                                    A message start with a term offset:
2157
                                        1) Between two existing messages for this term, or
2158
                                        2) Less than the first message for this term
2159
                                    Likely this was caused by an RX or out-of-order packet. Need to create a new one.
2160
                                */
2161
0
                                msg = NULL;
2162
0
                            }
2163
0
                        }
2164
0
                        if (msg == NULL)
2165
0
                        {
2166
0
                            msg = aeron_term_msg_add(term, pinfo, info);
2167
0
                        }
2168
0
                    }
2169
0
                    else
2170
0
                    {
2171
                        /* End of message, or middle of message. See if we already have a message with a smaller starting term offset */
2172
0
                        msg = aeron_term_msg_find_le(term, info->term_offset);
2173
0
                        if (msg != NULL)
2174
0
                        {
2175
                            /* Is this the next expected term offset? */
2176
0
                            if (msg->next_expected_term_offset == info->term_offset)
2177
0
                            {
2178
                                /* Yes - we can add the fragment to the message */
2179
0
                            }
2180
0
                            else
2181
0
                            {
2182
                                /* Do we already have this fragment? */
2183
0
                                frag = aeron_msg_fragment_find(msg, info);
2184
0
                                if (frag != NULL)
2185
0
                                {
2186
                                    /* Already have it, so nothing to do */
2187
0
                                    return;
2188
0
                                }
2189
0
                                else
2190
0
                                {
2191
                                    /* Not the next fragment, so no known message associated with it. */
2192
0
                                    msg = NULL;
2193
0
                                }
2194
0
                            }
2195
0
                        }
2196
0
                    }
2197
                    /* Create the fragment */
2198
0
                    frag = aeron_msg_fragment_create(tvb, offset, pinfo, info);
2199
0
                    if (msg == NULL)
2200
0
                    {
2201
                        /* Add the fragment to the list of orphaned fragments */
2202
0
                        wmem_list_append(term->orphan_fragment, (void *) frag);
2203
0
                    }
2204
0
                    else
2205
0
                    {
2206
                        /* Add the fragment to the message */
2207
0
                        aeron_msg_fragment_add(msg, frag);
2208
0
                    }
2209
                    /* Process the orphan list */
2210
0
                    aeron_msg_process_orphan_fragments(term);
2211
0
                }
2212
0
            }
2213
0
        }
2214
0
    }
2215
0
}
2216
2217
/*----------------------------------------------------------------------------*/
2218
/* Aeron pad message packet dissection functions.                             */
2219
/*----------------------------------------------------------------------------*/
2220
static int dissect_aeron_pad(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2221
0
{
2222
0
    proto_tree * subtree;
2223
0
    proto_item * pad_item;
2224
0
    proto_item * channel_item;
2225
0
    proto_item * frame_length_item;
2226
0
    uint32_t frame_length;
2227
0
    uint32_t pad_length;
2228
0
    aeron_transport_t * transport;
2229
0
    uint32_t session_id;
2230
0
    uint32_t stream_id;
2231
0
    uint32_t term_id;
2232
0
    uint32_t term_offset;
2233
0
    int rounded_length;
2234
0
    aeron_packet_info_t pktinfo;
2235
2236
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_PAD_FRAME_LENGTH);
2237
0
    rounded_length = (int) aeron_pos_roundup(frame_length);
2238
0
    if (rounded_length < 0)
2239
0
        return 0;
2240
0
    term_offset = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_OFFSET);
2241
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_SESSION_ID);
2242
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2243
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_STREAM_ID);
2244
0
    term_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_ID);
2245
0
    pad_length = frame_length - L_AERON_PAD_MIN;
2246
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2247
0
    pktinfo.stream_id = stream_id;
2248
0
    pktinfo.term_id = term_id;
2249
0
    pktinfo.term_offset = term_offset;
2250
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2251
0
    pktinfo.length = frame_length;
2252
0
    pktinfo.data_length = pad_length;
2253
0
    pktinfo.type = HDR_TYPE_PAD;
2254
0
    pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_PAD_FLAGS);
2255
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2256
0
        return 0;
2257
2258
0
    aeron_info_stream_progress_report(pinfo, HDR_TYPE_PAD, pktinfo.flags, term_id, term_offset, finfo);
2259
0
    pad_item = proto_tree_add_none_format(tree, hf_aeron_pad, tvb, offset, -1, "Pad Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2260
0
        term_id, term_offset, frame_length, rounded_length);
2261
0
    subtree = proto_item_add_subtree(pad_item, ett_aeron_pad);
2262
0
    channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2263
0
    proto_item_set_generated(channel_item);
2264
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_pad_frame_length, tvb, offset + O_AERON_PAD_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2265
0
    proto_tree_add_item(subtree, hf_aeron_pad_version, tvb, offset + O_AERON_PAD_VERSION, 1, ENC_LITTLE_ENDIAN);
2266
0
    proto_tree_add_item(subtree, hf_aeron_pad_flags, tvb, offset + O_AERON_PAD_FLAGS, 1, ENC_LITTLE_ENDIAN);
2267
0
    proto_tree_add_item(subtree, hf_aeron_pad_type, tvb, offset + O_AERON_PAD_TYPE, 2, ENC_LITTLE_ENDIAN);
2268
0
    proto_tree_add_item(subtree, hf_aeron_pad_term_offset, tvb, offset + O_AERON_PAD_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2269
0
    aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, (uint32_t) rounded_length);
2270
0
    proto_tree_add_item(subtree, hf_aeron_pad_session_id, tvb, offset + O_AERON_PAD_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2271
0
    proto_tree_add_item(subtree, hf_aeron_pad_stream_id, tvb, offset + O_AERON_PAD_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2272
0
    proto_tree_add_item(subtree, hf_aeron_pad_term_id, tvb, offset + O_AERON_PAD_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2273
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2274
0
    aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2275
0
    proto_item_set_len(pad_item, rounded_length);
2276
0
    if (frame_length < L_AERON_PAD_MIN)
2277
0
    {
2278
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_pad_length);
2279
0
        return (-rounded_length);
2280
0
    }
2281
0
    return (rounded_length);
2282
0
}
2283
2284
/*----------------------------------------------------------------------------*/
2285
/* Aeron data message packet dissection functions.                            */
2286
/*----------------------------------------------------------------------------*/
2287
static void dissect_aeron_reassembled_data(packet_info * pinfo, proto_tree * tree, aeron_frame_info_t * finfo)
2288
0
{
2289
0
    proto_item * frag_item;
2290
0
    proto_tree * frag_tree;
2291
0
    aeron_msg_t * msg;
2292
0
    wmem_list_frame_t * lf;
2293
0
    bool first_item = true;
2294
0
    uint32_t msg_ofs = 0;
2295
2296
0
    if (finfo->message == NULL)
2297
0
    {
2298
0
        return;
2299
0
    }
2300
0
    msg = finfo->message;
2301
0
    add_new_data_source(pinfo, msg->reassembled_data, "Reassembled Data");
2302
0
    frag_item = proto_tree_add_none_format(tree,
2303
0
        hf_aeron_data_reassembly,
2304
0
        msg->reassembled_data,
2305
0
        0,
2306
0
        tvb_reported_length_remaining(msg->reassembled_data, 0),
2307
0
        "%" PRIu32 " Reassembled Fragments (%" PRIu32 " bytes):",
2308
0
        msg->fragment_count,
2309
0
        msg->length);
2310
0
    frag_tree = proto_item_add_subtree(frag_item, ett_aeron_data_reassembly);
2311
0
    lf = wmem_list_head(msg->fragment);
2312
0
    while (lf != NULL)
2313
0
    {
2314
0
        aeron_msg_fragment_t * frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2315
0
        if (frag != NULL)
2316
0
        {
2317
0
            proto_item * pi;
2318
0
            pi = proto_tree_add_uint_format_value(frag_tree,
2319
0
                hf_aeron_data_reassembly_fragment,
2320
0
                msg->reassembled_data,
2321
0
                msg_ofs,
2322
0
                frag->data_length,
2323
0
                frag->frame,
2324
0
                "Frame: %" PRIu32 ", payload: %" PRIu32 "-%" PRIu32 " (%" PRIu32 " bytes)",
2325
0
                frag->frame,
2326
0
                msg_ofs,
2327
0
                (msg_ofs + frag->data_length) - 1,
2328
0
                frag->data_length);
2329
0
            proto_item_set_generated(pi);
2330
0
            if (first_item)
2331
0
            {
2332
0
                proto_item_append_text(frag_item, " #%" PRIu32 "(%" PRIu32 ")", frag->frame, frag->data_length);
2333
0
            }
2334
0
            else
2335
0
            {
2336
0
                proto_item_append_text(frag_item, ", #%" PRIu32 "(%" PRIu32 ")", frag->frame, frag->data_length);
2337
0
            }
2338
0
            msg_ofs += frag->data_length;
2339
0
            first_item = false;
2340
0
        }
2341
0
        lf = wmem_list_frame_next(lf);
2342
0
    }
2343
0
    proto_item_set_generated(frag_item);
2344
0
}
2345
2346
static int dissect_aeron_data(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2347
0
{
2348
0
    proto_tree * subtree;
2349
0
    proto_item * data_item;
2350
0
    proto_item * channel_item;
2351
0
    proto_item * frame_length_item;
2352
0
    uint32_t frame_length;
2353
0
    static int * const flags[] =
2354
0
    {
2355
0
        &hf_aeron_data_flags_b,
2356
0
        &hf_aeron_data_flags_e,
2357
0
        &hf_aeron_data_flags_s,
2358
0
        NULL
2359
0
    };
2360
0
    aeron_transport_t * transport;
2361
0
    uint32_t session_id;
2362
0
    uint32_t stream_id;
2363
0
    uint32_t term_id;
2364
0
    uint32_t term_offset;
2365
0
    uint32_t data_length;
2366
0
    int rounded_length = 0;
2367
0
    aeron_packet_info_t pktinfo;
2368
0
    uint32_t offset_increment = 0;
2369
2370
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_DATA_FRAME_LENGTH);
2371
0
    if (frame_length == 0)
2372
0
    {
2373
0
        rounded_length = O_AERON_DATA_DATA;
2374
0
        data_length = 0;
2375
0
        offset_increment = 0;
2376
0
    }
2377
0
    else
2378
0
    {
2379
0
        offset_increment = aeron_pos_roundup(frame_length);
2380
0
        rounded_length = (int) offset_increment;
2381
0
        if (rounded_length < 0)
2382
0
            return 0;
2383
0
        data_length = frame_length - O_AERON_DATA_DATA;
2384
0
    }
2385
0
    term_offset = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_OFFSET);
2386
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_SESSION_ID);
2387
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2388
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_STREAM_ID);
2389
0
    term_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_ID);
2390
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2391
0
    pktinfo.stream_id = stream_id;
2392
0
    pktinfo.term_id = term_id;
2393
0
    pktinfo.term_offset = term_offset;
2394
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2395
0
    pktinfo.length = frame_length;
2396
0
    pktinfo.data_length = data_length;
2397
0
    pktinfo.type = HDR_TYPE_DATA;
2398
0
    pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_DATA_FLAGS);
2399
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2400
0
        return 0;
2401
2402
0
    aeron_info_stream_progress_report(pinfo, HDR_TYPE_DATA, pktinfo.flags, term_id, term_offset, finfo);
2403
0
    data_item = proto_tree_add_none_format(tree, hf_aeron_data, tvb, offset, -1, "Data Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2404
0
        (uint32_t) term_id, term_offset, frame_length, rounded_length);
2405
0
    subtree = proto_item_add_subtree(data_item, ett_aeron_data);
2406
0
    channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2407
0
    proto_item_set_generated(channel_item);
2408
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_data_frame_length, tvb, offset + O_AERON_DATA_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2409
0
    proto_tree_add_item(subtree, hf_aeron_data_version, tvb, offset + O_AERON_DATA_VERSION, 1, ENC_LITTLE_ENDIAN);
2410
0
    proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_DATA_FLAGS, hf_aeron_data_flags, ett_aeron_data_flags, flags, ENC_LITTLE_ENDIAN);
2411
0
    proto_tree_add_item(subtree, hf_aeron_data_type, tvb, offset + O_AERON_DATA_TYPE, 2, ENC_LITTLE_ENDIAN);
2412
0
    proto_tree_add_item(subtree, hf_aeron_data_term_offset, tvb, offset + O_AERON_DATA_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2413
0
    aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, offset_increment);
2414
0
    proto_tree_add_item(subtree, hf_aeron_data_session_id, tvb, offset + O_AERON_DATA_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2415
0
    proto_tree_add_item(subtree, hf_aeron_data_stream_id, tvb, offset + O_AERON_DATA_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2416
0
    proto_tree_add_item(subtree, hf_aeron_data_term_id, tvb, offset + O_AERON_DATA_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2417
0
    proto_tree_add_item(subtree, hf_aeron_data_reserved_value, tvb, offset + O_AERON_DATA_RESERVED_VALUE, 8, ENC_LITTLE_ENDIAN);
2418
0
    if (data_length > 0)
2419
0
    {
2420
0
        tvbuff_t * data_tvb = NULL;
2421
0
        bool can_call_subdissector = false;
2422
0
        bool dissector_found = false;
2423
0
        heur_dtbl_entry_t * hdtbl_entry;
2424
2425
0
        aeron_msg_process(tvb, offset, pinfo, transport, &pktinfo, finfo);
2426
0
        if ((pktinfo.flags & DATA_FLAGS_COMPLETE) == DATA_FLAGS_COMPLETE)
2427
0
        {
2428
0
            can_call_subdissector = true;
2429
0
        }
2430
0
        if (finfo != NULL)
2431
0
        {
2432
0
            if ((finfo->flags & AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG) != 0)
2433
0
            {
2434
0
                dissect_aeron_reassembled_data(pinfo, subtree, finfo);
2435
0
                data_tvb = finfo->message->reassembled_data;
2436
0
                can_call_subdissector = true;
2437
0
            }
2438
0
            else
2439
0
            {
2440
0
                data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2441
0
            }
2442
0
        }
2443
0
        else
2444
0
        {
2445
0
            data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2446
0
        }
2447
0
        if (can_call_subdissector && aeron_use_heuristic_subdissectors)
2448
0
        {
2449
0
            dissector_found = dissector_try_heuristic(aeron_heuristic_subdissector_list, data_tvb, pinfo, subtree, &hdtbl_entry, NULL);
2450
0
        }
2451
0
        if (!dissector_found)
2452
0
        {
2453
0
            call_data_dissector(data_tvb, pinfo, subtree);
2454
0
        }
2455
0
    }
2456
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2457
0
    aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2458
0
    proto_item_set_len(data_item, rounded_length);
2459
0
    if ((frame_length != 0) && (frame_length < L_AERON_DATA_MIN))
2460
0
    {
2461
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_data_length);
2462
0
        return (-rounded_length);
2463
0
    }
2464
0
    return (rounded_length);
2465
0
}
2466
2467
/*----------------------------------------------------------------------------*/
2468
/* Aeron NAK packet dissection functions.                                     */
2469
/*----------------------------------------------------------------------------*/
2470
static int dissect_aeron_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2471
0
{
2472
0
    proto_tree * subtree;
2473
0
    proto_item * nak_item;
2474
0
    proto_item * frame_length_item;
2475
0
    proto_item * channel_item;
2476
0
    proto_item * nak_offset_item;
2477
0
    uint32_t frame_length;
2478
0
    aeron_transport_t * transport;
2479
0
    uint32_t session_id;
2480
0
    uint32_t stream_id;
2481
0
    uint32_t term_id;
2482
0
    uint32_t nak_term_offset;
2483
0
    uint32_t nak_length;
2484
0
    int rounded_length;
2485
0
    aeron_packet_info_t pktinfo;
2486
2487
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_FRAME_LENGTH);
2488
0
    rounded_length = (int)frame_length;
2489
0
    if (rounded_length < 0)
2490
0
        return 0;
2491
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_SESSION_ID);
2492
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2493
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_STREAM_ID);
2494
0
    term_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_ID);
2495
0
    nak_term_offset = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_OFFSET);
2496
0
    nak_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_LENGTH);
2497
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2498
0
    pktinfo.stream_id = stream_id;
2499
0
    pktinfo.term_id = term_id;
2500
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2501
0
    pktinfo.nak_term_offset = nak_term_offset;
2502
0
    pktinfo.nak_length = nak_length;
2503
0
    pktinfo.type = HDR_TYPE_NAK;
2504
0
    pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_NAK_FLAGS);
2505
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2506
0
        return 0;
2507
2508
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "NAK");
2509
0
    nak_item = proto_tree_add_none_format(tree, hf_aeron_nak, tvb, offset, -1, "NAK Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32,
2510
0
        term_id, nak_term_offset, nak_length);
2511
0
    subtree = proto_item_add_subtree(nak_item, ett_aeron_nak);
2512
0
    channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2513
0
    proto_item_set_generated(channel_item);
2514
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_nak_frame_length, tvb, offset + O_AERON_NAK_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2515
0
    proto_tree_add_item(subtree, hf_aeron_nak_version, tvb, offset + O_AERON_NAK_VERSION, 1, ENC_LITTLE_ENDIAN);
2516
0
    proto_tree_add_item(subtree, hf_aeron_nak_flags, tvb, offset + O_AERON_NAK_FLAGS, 1, ENC_LITTLE_ENDIAN);
2517
0
    proto_tree_add_item(subtree, hf_aeron_nak_type, tvb, offset + O_AERON_NAK_TYPE, 2, ENC_LITTLE_ENDIAN);
2518
0
    proto_tree_add_item(subtree, hf_aeron_nak_session_id, tvb, offset + O_AERON_NAK_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2519
0
    proto_tree_add_item(subtree, hf_aeron_nak_stream_id, tvb, offset + O_AERON_NAK_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2520
0
    proto_tree_add_item(subtree, hf_aeron_nak_term_id, tvb, offset + O_AERON_NAK_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2521
0
    nak_offset_item = proto_tree_add_item(subtree, hf_aeron_nak_term_offset, tvb, offset + O_AERON_NAK_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2522
0
    proto_tree_add_item(subtree, hf_aeron_nak_length, tvb, offset + O_AERON_NAK_LENGTH, 4, ENC_LITTLE_ENDIAN);
2523
0
    expert_add_info_format(pinfo, nak_offset_item, &ei_aeron_analysis_nak, "NAK offset %" PRIu32 " length %" PRIu32, nak_term_offset, nak_length);
2524
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2525
0
    proto_item_set_len(nak_item, rounded_length);
2526
0
    if (frame_length != L_AERON_NAK)
2527
0
    {
2528
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_nak_length);
2529
0
        return (-rounded_length);
2530
0
    }
2531
0
    return (rounded_length);
2532
0
}
2533
2534
/*----------------------------------------------------------------------------*/
2535
/* Aeron status message packet dissection functions.                          */
2536
/*----------------------------------------------------------------------------*/
2537
static void aeron_window_resize_report(packet_info * pinfo, proto_item * item, aeron_frame_info_t * finfo)
2538
0
{
2539
0
    if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
2540
0
    {
2541
0
        if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE) != 0)
2542
0
        {
2543
0
            expert_add_info(pinfo, item, &ei_aeron_analysis_window_resize);
2544
0
        }
2545
0
    }
2546
0
}
2547
2548
static int dissect_aeron_sm(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2549
0
{
2550
0
    proto_tree * subtree;
2551
0
    proto_item * sm_item;
2552
0
    proto_item * frame_length_item;
2553
0
    proto_item * item;
2554
0
    proto_item * rcv_window_item;
2555
0
    uint32_t frame_length;
2556
0
    static int * const flags[] =
2557
0
    {
2558
0
        &hf_aeron_sm_flags_s,
2559
0
        NULL
2560
0
    };
2561
0
    uint32_t feedback_length;
2562
0
    aeron_transport_t * transport;
2563
0
    uint32_t session_id;
2564
0
    uint32_t stream_id;
2565
0
    uint32_t term_id;
2566
0
    uint32_t consumption_offset;
2567
0
    uint32_t rcv_window;
2568
0
    uint64_t rcv_id;
2569
0
    int rounded_length;
2570
0
    aeron_packet_info_t pktinfo;
2571
2572
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_SM_FRAME_LENGTH);
2573
0
    feedback_length = frame_length - O_AERON_SM_FEEDBACK;
2574
0
    rounded_length = (int) frame_length;
2575
0
    if (rounded_length < 0)
2576
0
        return 0;
2577
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_SM_SESSION_ID);
2578
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2579
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_SM_STREAM_ID);
2580
0
    term_id = tvb_get_letohl(tvb, offset + O_AERON_SM_TERM_ID);
2581
0
    consumption_offset = tvb_get_letohl(tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET);
2582
0
    rcv_window = tvb_get_letohl(tvb, offset + O_AERON_SM_RECEIVER_WINDOW);
2583
0
    rcv_id = tvb_get_letoh64(tvb, offset + O_AERON_SM_RECEIVER_ID);
2584
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2585
0
    pktinfo.stream_id = stream_id;
2586
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID;
2587
0
    pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_SM_FLAGS);
2588
0
    if ((pktinfo.flags & STATUS_FLAGS_SETUP) == 0)
2589
0
    {
2590
0
        pktinfo.term_id = term_id;
2591
0
        pktinfo.term_offset = consumption_offset;
2592
0
        pktinfo.info_flags |= (AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID);
2593
0
        pktinfo.receiver_window = rcv_window;
2594
0
        pktinfo.receiver_id = rcv_id;
2595
0
    }
2596
0
    else
2597
0
    {
2598
0
        pktinfo.term_id = 0;
2599
0
        pktinfo.term_offset = 0;
2600
0
        pktinfo.receiver_window = 0;
2601
0
        pktinfo.receiver_id = 0;
2602
0
    }
2603
0
    pktinfo.length = 0;
2604
0
    pktinfo.data_length = 0;
2605
0
    pktinfo.type = HDR_TYPE_SM;
2606
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2607
0
        return 0;
2608
2609
0
    aeron_info_stream_progress_report(pinfo, HDR_TYPE_SM, pktinfo.flags, term_id, consumption_offset, finfo);
2610
0
    sm_item = proto_tree_add_none_format(tree, hf_aeron_sm, tvb, offset, -1, "Status Message: Term 0x%x, ConsumptionOfs %" PRIu32 ", RcvWindow %" PRIu32 ", RcvID %" PRIu64,
2611
0
        term_id, consumption_offset, rcv_window, rcv_id);
2612
0
    subtree = proto_item_add_subtree(sm_item, ett_aeron_sm);
2613
0
    item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2614
0
    proto_item_set_generated(item);
2615
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_sm_frame_length, tvb, offset + O_AERON_SM_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2616
0
    proto_tree_add_item(subtree, hf_aeron_sm_version, tvb, offset + O_AERON_SM_VERSION, 1, ENC_LITTLE_ENDIAN);
2617
0
    proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_SM_FLAGS, hf_aeron_sm_flags, ett_aeron_sm_flags, flags, ENC_LITTLE_ENDIAN);
2618
0
    proto_tree_add_item(subtree, hf_aeron_sm_type, tvb, offset + O_AERON_SM_TYPE, 2, ENC_LITTLE_ENDIAN);
2619
0
    proto_tree_add_item(subtree, hf_aeron_sm_session_id, tvb, offset + O_AERON_SM_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2620
0
    proto_tree_add_item(subtree, hf_aeron_sm_stream_id, tvb, offset + O_AERON_SM_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2621
0
    proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_id, tvb, offset + O_AERON_SM_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2622
0
    proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_offset, tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2623
0
    rcv_window_item = proto_tree_add_item(subtree, hf_aeron_sm_receiver_window, tvb, offset + O_AERON_SM_RECEIVER_WINDOW, 4, ENC_LITTLE_ENDIAN);
2624
0
    aeron_window_resize_report(pinfo, rcv_window_item, finfo);
2625
0
    proto_tree_add_item(subtree, hf_aeron_sm_receiver_id, tvb, offset + O_AERON_SM_RECEIVER_ID, 8, ENC_LITTLE_ENDIAN);
2626
0
    if (feedback_length > 0)
2627
0
    {
2628
0
        proto_tree_add_item(subtree, hf_aeron_sm_feedback, tvb, offset + O_AERON_SM_FEEDBACK, feedback_length, ENC_NA);
2629
0
    }
2630
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2631
0
    aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2632
0
    proto_item_set_len(sm_item, rounded_length);
2633
0
    if (frame_length < L_AERON_SM_MIN)
2634
0
    {
2635
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_sm_length);
2636
0
        return (-rounded_length);
2637
0
    }
2638
0
    return (rounded_length);
2639
0
}
2640
2641
/*----------------------------------------------------------------------------*/
2642
/* Aeron error packet dissection functions.                                   */
2643
/*----------------------------------------------------------------------------*/
2644
static int dissect_aeron_err(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree)
2645
0
{
2646
0
    proto_tree * subtree;
2647
0
    proto_item * err_item;
2648
0
    proto_item * frame_length_item;
2649
0
    int rounded_length;
2650
0
    uint32_t bad_frame_length;
2651
0
    int string_length;
2652
0
    uint32_t frame_length;
2653
0
    int ofs;
2654
2655
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_ERR_FRAME_LENGTH);
2656
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Error");
2657
0
    err_item = proto_tree_add_item(tree, hf_aeron_err, tvb, offset, -1, ENC_NA);
2658
0
    subtree = proto_item_add_subtree(err_item, ett_aeron_err);
2659
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_err_frame_length, tvb, offset + O_AERON_ERR_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2660
0
    proto_tree_add_item(subtree, hf_aeron_err_version, tvb, offset + O_AERON_ERR_VERSION, 1, ENC_LITTLE_ENDIAN);
2661
0
    proto_tree_add_item(subtree, hf_aeron_err_code, tvb, offset + O_AERON_ERR_CODE, 1, ENC_LITTLE_ENDIAN);
2662
0
    proto_tree_add_item(subtree, hf_aeron_err_type, tvb, offset + O_AERON_ERR_TYPE, 2, ENC_LITTLE_ENDIAN);
2663
0
    proto_tree_add_item(subtree, hf_aeron_err_off_frame_length, tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2664
0
    bad_frame_length = tvb_get_letohl(tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH);
2665
0
    ofs = offset + O_AERON_ERR_OFFENDING_HEADER;
2666
0
    proto_tree_add_item(subtree, hf_aeron_err_off_hdr, tvb, offset + ofs, bad_frame_length, ENC_NA);
2667
0
    ofs += bad_frame_length;
2668
0
    string_length = frame_length - ofs;
2669
0
    if (string_length > 0)
2670
0
    {
2671
0
        proto_tree_add_item(subtree, hf_aeron_err_string, tvb, offset + ofs, string_length, ENC_ASCII);
2672
0
    }
2673
0
    rounded_length = (int) frame_length;
2674
0
    if (rounded_length < 0)
2675
0
        return 0;
2676
0
    proto_item_set_len(err_item, rounded_length);
2677
0
    if (frame_length < L_AERON_ERR_MIN)
2678
0
    {
2679
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_err_length);
2680
0
        return (-rounded_length);
2681
0
    }
2682
0
    return (rounded_length);
2683
0
}
2684
2685
/*----------------------------------------------------------------------------*/
2686
/* Aeron heartbeat packet dissection functions. (Data frame also)             */
2687
/*----------------------------------------------------------------------------*/
2688
static int dissect_aeron_heartbeat(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2689
0
{
2690
0
    proto_tree * subtree;
2691
0
    proto_item * data_item;
2692
0
    proto_item * channel_item;
2693
0
    proto_item * frame_length_item;
2694
0
    uint32_t frame_length;
2695
0
    static int * const flags[] =
2696
0
    {
2697
0
        &hf_aeron_heartbeat_flags_b,
2698
0
        &hf_aeron_heartbeat_flags_e,
2699
0
        NULL
2700
0
    };
2701
0
    aeron_transport_t * transport;
2702
0
    uint32_t term_offset;
2703
0
    uint32_t session_id;
2704
0
    uint32_t stream_id;
2705
0
    uint32_t term_id;
2706
2707
0
    int rounded_length = 24;
2708
0
    aeron_packet_info_t pktinfo;
2709
2710
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_FRAME_LENGTH);
2711
0
    term_offset = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_TERM_OFFSET);
2712
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_SESSION_ID);
2713
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2714
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_STREAM_ID);
2715
0
    term_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_TERM_ID);
2716
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2717
0
    pktinfo.stream_id = stream_id;
2718
0
    pktinfo.term_id = term_id;
2719
0
    pktinfo.term_offset = term_offset;
2720
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2721
0
    pktinfo.length = frame_length;
2722
0
    pktinfo.data_length = 0;
2723
0
    pktinfo.type = HDR_TYPE_DATA;
2724
0
    pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_HEAERTBEAT_FLAGS);
2725
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2726
0
        return 0;
2727
2728
0
    aeron_info_stream_progress_report(pinfo, HDR_TYPE_DATA, pktinfo.flags, term_id, term_offset, finfo);
2729
0
    data_item = proto_tree_add_none_format(tree, hf_aeron_heartbeat, tvb, offset, -1, "Heartbeat Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2730
0
        (uint32_t) term_id, term_offset, frame_length, rounded_length);
2731
0
    subtree = proto_item_add_subtree(data_item, ett_aeron_data);
2732
0
    channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2733
0
    proto_item_set_generated(channel_item);
2734
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_heartbeat_frame_length, tvb, offset + O_AERON_HEAERTBEAT_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2735
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_version, tvb, offset + O_AERON_HEAERTBEAT_VERSION, 1, ENC_LITTLE_ENDIAN);
2736
0
    proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_HEAERTBEAT_FLAGS, hf_aeron_heartbeat_flags, ett_aeron_data_flags, flags, ENC_LITTLE_ENDIAN);
2737
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_type, tvb, offset + O_AERON_HEAERTBEAT_TYPE, 2, ENC_LITTLE_ENDIAN);
2738
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_term_offset, tvb, offset + O_AERON_HEAERTBEAT_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2739
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_session_id, tvb, offset + O_AERON_HEAERTBEAT_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2740
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_stream_id, tvb, offset + O_AERON_HEAERTBEAT_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2741
0
    proto_tree_add_item(subtree, hf_aeron_heartbeat_term_id, tvb, offset + O_AERON_HEAERTBEAT_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2742
2743
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2744
0
    aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2745
0
    proto_item_set_len(data_item, rounded_length);
2746
0
    if (frame_length != 0)
2747
0
    {
2748
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_data_length);
2749
0
        return (-rounded_length);
2750
0
    }
2751
0
    return (rounded_length);
2752
0
}
2753
2754
/*----------------------------------------------------------------------------*/
2755
/* Aeron rtt message packet dissection functions.                          */
2756
/*----------------------------------------------------------------------------*/
2757
static int dissect_aeron_rtt(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2758
0
{
2759
0
    proto_tree * subtree;
2760
0
    proto_item * rtt_item;
2761
0
    proto_item * frame_length_item;
2762
0
    proto_item * item;
2763
0
    uint32_t frame_length;
2764
0
    static int * const flags[] =
2765
0
    {
2766
0
        &hf_aeron_rtt_flags_r,
2767
0
        NULL
2768
0
    };
2769
0
    aeron_transport_t * transport;
2770
0
    uint32_t session_id;
2771
0
    uint32_t stream_id;
2772
0
    uint64_t rcv_id;
2773
0
    int rounded_length;
2774
2775
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_RTT_FRAME_LENGTH);
2776
0
    rounded_length = (int)frame_length;
2777
0
    if (rounded_length < 0)
2778
0
        return 0;
2779
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_RTT_SESSION_ID);
2780
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2781
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_RTT_STREAM_ID);
2782
0
    rcv_id = tvb_get_letoh64(tvb, offset + O_AERON_RTT_RECEIVER_ID);
2783
2784
0
    rtt_item = proto_tree_add_none_format(tree, hf_aeron_rtt, tvb, offset, -1, "RTT Message: Stream ID %" PRIu32 ", RcvID %" PRIu64,
2785
0
        stream_id, rcv_id);
2786
0
    subtree = proto_item_add_subtree(rtt_item, ett_aeron_rtt);
2787
0
    item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2788
0
    proto_item_set_generated(item);
2789
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_rtt_frame_length, tvb, offset + O_AERON_RTT_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2790
0
    proto_tree_add_item(subtree, hf_aeron_rtt_version, tvb, offset + O_AERON_RTT_VERSION, 1, ENC_LITTLE_ENDIAN);
2791
0
    proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_RTT_FLAGS, hf_aeron_rtt_flags, ett_aeron_rtt_flags, flags, ENC_LITTLE_ENDIAN);
2792
0
    proto_tree_add_item(subtree, hf_aeron_rtt_type, tvb, offset + O_AERON_RTT_TYPE, 2, ENC_LITTLE_ENDIAN);
2793
0
    proto_tree_add_item(subtree, hf_aeron_rtt_session_id, tvb, offset + O_AERON_RTT_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2794
0
    proto_tree_add_item(subtree, hf_aeron_rtt_stream_id, tvb, offset + O_AERON_RTT_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2795
0
    proto_tree_add_item(subtree, hf_aeron_rtt_echo_timestamp, tvb, offset + O_AERON_RTT_ECHO_TIMESTAMP, 8, ENC_LITTLE_ENDIAN);
2796
0
    proto_tree_add_item(subtree, hf_aeron_rtt_reception_delta, tvb, offset + O_AERON_RTT_RECEPTION_DELTA, 8, ENC_LITTLE_ENDIAN);
2797
0
    proto_tree_add_item(subtree, hf_aeron_rtt_receiver_id, tvb, offset + O_AERON_RTT_RECEIVER_ID, 8, ENC_LITTLE_ENDIAN);
2798
2799
0
    aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2800
0
    proto_item_set_len(rtt_item, rounded_length);
2801
0
    if (frame_length != L_AERON_RTT)
2802
0
    {
2803
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_rtt_length);
2804
0
        return (-rounded_length);
2805
0
    }
2806
0
    return (rounded_length);
2807
0
}
2808
2809
/*----------------------------------------------------------------------------*/
2810
/* Aeron setup packet dissection functions.                                   */
2811
/*----------------------------------------------------------------------------*/
2812
static void aeron_set_stream_mtu_ttl_term_length(packet_info * pinfo, aeron_transport_t * transport, uint32_t stream_id, uint32_t mtu, uint32_t ttl, uint32_t term_length)
2813
0
{
2814
0
    if (PINFO_FD_VISITED(pinfo) == 0)
2815
0
    {
2816
0
        aeron_stream_t * stream = aeron_transport_stream_find(transport, stream_id);
2817
0
        if (stream != NULL)
2818
0
        {
2819
0
            stream->term_length = term_length;
2820
0
            stream->mtu = mtu;
2821
0
            stream->ttl = ttl;
2822
0
        }
2823
0
    }
2824
0
}
2825
2826
static int dissect_aeron_setup(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2827
0
{
2828
0
    proto_tree * subtree;
2829
0
    proto_item * setup_item;
2830
0
    proto_item * frame_length_item;
2831
0
    uint32_t frame_length;
2832
0
    proto_item * channel_item;
2833
0
    aeron_transport_t * transport;
2834
0
    uint32_t session_id;
2835
0
    uint32_t stream_id;
2836
0
    uint32_t active_term_id;
2837
0
    uint32_t initial_term_id;
2838
0
    uint32_t term_offset;
2839
0
    uint32_t term_length;
2840
0
    uint32_t mtu;
2841
0
    uint32_t ttl;
2842
0
    int rounded_length;
2843
0
    aeron_packet_info_t pktinfo;
2844
2845
0
    frame_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_FRAME_LENGTH);
2846
0
    rounded_length = (int) frame_length;
2847
0
    if (rounded_length < 0)
2848
0
        return 0;
2849
0
    term_offset = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_OFFSET);
2850
0
    session_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_SESSION_ID);
2851
0
    transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2852
0
    stream_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_STREAM_ID);
2853
0
    initial_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID);
2854
0
    active_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID);
2855
0
    memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2856
0
    pktinfo.stream_id = stream_id;
2857
0
    pktinfo.term_id = active_term_id;
2858
0
    pktinfo.term_offset = 0;
2859
0
    pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2860
0
    pktinfo.length = 0;
2861
0
    pktinfo.data_length = 0;
2862
0
    pktinfo.receiver_window = 0;
2863
0
    pktinfo.type = HDR_TYPE_SETUP;
2864
0
    pktinfo.flags = 0;
2865
0
    if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2866
0
        return 0;
2867
0
    term_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_LENGTH);
2868
0
    mtu = tvb_get_letohl(tvb, offset + O_AERON_SETUP_MTU);
2869
0
    ttl = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TTL);
2870
0
    aeron_set_stream_mtu_ttl_term_length(pinfo, transport, stream_id, mtu, ttl, term_length);
2871
2872
0
    col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Setup");
2873
0
    setup_item = proto_tree_add_none_format(tree, hf_aeron_setup, tvb, offset, -1,
2874
0
        "Setup Frame: InitTerm 0x%x, ActiveTerm 0x%x, TermLen %" PRIu32 ", Ofs %" PRIu32 ", MTU %" PRIu32 ", TTL %" PRIu32,
2875
0
        initial_term_id, (uint32_t) active_term_id, term_length, term_offset, mtu, ttl);
2876
0
    subtree = proto_item_add_subtree(setup_item, ett_aeron_setup);
2877
0
    channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2878
0
    proto_item_set_generated(channel_item);
2879
0
    frame_length_item = proto_tree_add_item(subtree, hf_aeron_setup_frame_length, tvb, offset + O_AERON_SETUP_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2880
0
    proto_tree_add_item(subtree, hf_aeron_setup_version, tvb, offset + O_AERON_SETUP_VERSION, 1, ENC_LITTLE_ENDIAN);
2881
0
    proto_tree_add_item(subtree, hf_aeron_setup_flags, tvb, offset + O_AERON_SETUP_FLAGS, 1, ENC_LITTLE_ENDIAN);
2882
0
    proto_tree_add_item(subtree, hf_aeron_setup_type, tvb, offset + O_AERON_SETUP_TYPE, 2, ENC_LITTLE_ENDIAN);
2883
0
    proto_tree_add_item(subtree, hf_aeron_setup_term_offset, tvb, offset + O_AERON_SETUP_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2884
0
    proto_tree_add_item(subtree, hf_aeron_setup_session_id, tvb, offset + O_AERON_SETUP_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2885
0
    proto_tree_add_item(subtree, hf_aeron_setup_stream_id, tvb, offset + O_AERON_SETUP_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2886
0
    proto_tree_add_item(subtree, hf_aeron_setup_initial_term_id, tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2887
0
    proto_tree_add_item(subtree, hf_aeron_setup_active_term_id, tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2888
0
    proto_tree_add_item(subtree, hf_aeron_setup_term_length, tvb, offset + O_AERON_SETUP_TERM_LENGTH, 4, ENC_LITTLE_ENDIAN);
2889
0
    proto_tree_add_item(subtree, hf_aeron_setup_mtu, tvb, offset + O_AERON_SETUP_MTU, 4, ENC_LITTLE_ENDIAN);
2890
0
    proto_tree_add_item(subtree, hf_aeron_setup_ttl, tvb, offset + O_AERON_SETUP_TTL, 4, ENC_LITTLE_ENDIAN);
2891
0
    aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2892
0
    proto_item_set_len(setup_item, rounded_length);
2893
0
    if (frame_length != L_AERON_SETUP)
2894
0
    {
2895
0
        expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_setup_length);
2896
0
        return (-rounded_length);
2897
0
    }
2898
0
    return (rounded_length);
2899
0
}
2900
2901
/*----------------------------------------------------------------------------*/
2902
/* Aeron packet dissector.                                                    */
2903
/*----------------------------------------------------------------------------*/
2904
static int dissect_aeron(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data _U_)
2905
0
{
2906
0
    int total_dissected_length = 0;
2907
0
    uint32_t frame_length;
2908
0
    uint8_t frame_flags;
2909
0
    uint16_t frame_type;
2910
0
    proto_tree * aeron_tree;
2911
0
    proto_item * aeron_item;
2912
0
    int dissected_length = 0;
2913
0
    int offset = 0;
2914
0
    int length_remaining;
2915
0
    aeron_conversation_info_t * cinfo;
2916
2917
    /* Get enough information to determine the conversation info.
2918
       Make sure that we don't throw an exception before we know that
2919
       this packet contains our protocol. */
2920
0
    if (tvb_captured_length_remaining(tvb, offset) < 2)
2921
0
        return 0;
2922
0
    frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2923
0
    cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2924
0
    if (!cinfo)
2925
0
        return 0;
2926
2927
0
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Aeron");
2928
0
    col_clear(pinfo->cinfo, COL_INFO);
2929
0
    col_add_str(pinfo->cinfo, COL_INFO, aeron_format_transport_uri(pinfo->pool, cinfo));
2930
0
    col_set_fence(pinfo->cinfo, COL_INFO);
2931
2932
0
    length_remaining = tvb_reported_length(tvb);
2933
0
    aeron_item = proto_tree_add_protocol_format(tree, proto_aeron, tvb, offset, -1, "Aeron Protocol");
2934
0
    aeron_tree = proto_item_add_subtree(aeron_item, ett_aeron);
2935
0
    while (length_remaining > 0)
2936
0
    {
2937
0
        aeron_frame_info_t * finfo = NULL;
2938
2939
        /* Make sure superfluous padding is not identified as aeron frame */
2940
0
        if (tvb_skip_uint8(tvb, offset, tvb_captured_length_remaining(tvb, offset), 0) == (int)tvb_captured_length(tvb))
2941
0
        {
2942
0
            break;
2943
0
        }
2944
2945
0
        if (aeron_sequence_analysis)
2946
0
        {
2947
0
            finfo = aeron_frame_info_add(pinfo->pool, pinfo->num, (uint32_t) offset);
2948
0
        }
2949
0
        frame_length = tvb_get_letohl(tvb, offset + O_AERON_BASIC_FRAME_LENGTH);
2950
0
        frame_flags = tvb_get_uint8(tvb, offset + O_AERON_BASIC_FLAGS);
2951
0
        frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2952
0
        cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2953
0
        switch (frame_type)
2954
0
        {
2955
0
            case HDR_TYPE_PAD:
2956
0
                dissected_length = dissect_aeron_pad(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2957
0
                break;
2958
0
            case HDR_TYPE_DATA:
2959
0
                if(frame_length == 0 && frame_flags == DATA_FLAGS_COMPLETE)
2960
0
                {
2961
0
                    dissected_length = dissect_aeron_heartbeat(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2962
0
                }
2963
0
                else
2964
0
                {
2965
0
                    dissected_length = dissect_aeron_data(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2966
0
                }
2967
0
                break;
2968
0
            case HDR_TYPE_NAK:
2969
0
                dissected_length = dissect_aeron_nak(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2970
0
                break;
2971
0
            case HDR_TYPE_SM:
2972
0
                dissected_length = dissect_aeron_sm(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2973
0
                break;
2974
0
            case HDR_TYPE_RTT:
2975
0
                dissected_length = dissect_aeron_rtt(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2976
0
                break;
2977
0
            case HDR_TYPE_ERR:
2978
0
                dissected_length = dissect_aeron_err(tvb, offset, pinfo, aeron_tree);
2979
0
                break;
2980
0
            case HDR_TYPE_SETUP:
2981
0
                dissected_length = dissect_aeron_setup(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2982
0
                break;
2983
0
            case HDR_TYPE_RES:
2984
0
            case HDR_TYPE_EXT:
2985
0
            default:
2986
0
                return (total_dissected_length);
2987
0
        }
2988
0
        if (dissected_length <= 0)
2989
0
        {
2990
0
            total_dissected_length += -dissected_length;
2991
0
            proto_item_set_len(aeron_item, total_dissected_length);
2992
0
            return (total_dissected_length);
2993
0
        }
2994
0
        total_dissected_length += dissected_length;
2995
0
        offset += dissected_length;
2996
0
        length_remaining -= dissected_length;
2997
0
        proto_item_set_len(aeron_item, total_dissected_length);
2998
0
    }
2999
0
    return (total_dissected_length);
3000
0
}
3001
3002
static bool test_aeron_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data)
3003
0
{
3004
0
    uint8_t ver;
3005
0
    uint16_t packet_type;
3006
0
    int length;
3007
0
    int length_remaining;
3008
0
    int rc;
3009
3010
0
    length_remaining = tvb_captured_length_remaining(tvb, 0);
3011
0
    if (length_remaining < HDR_LENGTH_MIN)
3012
0
    {
3013
0
        return false;
3014
0
    }
3015
    /* We know we have at least HDR_LENGTH_MIN (12) bytes captured */
3016
0
    ver = tvb_get_uint8(tvb, O_AERON_BASIC_VERSION);
3017
0
    if (ver != 0)
3018
0
    {
3019
0
        return false;
3020
0
    }
3021
0
    packet_type = tvb_get_letohs(tvb, O_AERON_BASIC_TYPE);
3022
0
    switch (packet_type)
3023
0
    {
3024
0
        case HDR_TYPE_PAD:
3025
0
        case HDR_TYPE_DATA:
3026
0
        case HDR_TYPE_NAK:
3027
0
        case HDR_TYPE_SM:
3028
0
        case HDR_TYPE_RTT:
3029
0
        case HDR_TYPE_ERR:
3030
0
        case HDR_TYPE_SETUP:
3031
0
        case HDR_TYPE_RES:
3032
0
        case HDR_TYPE_EXT:
3033
0
            break;
3034
0
        default:
3035
0
            return false;
3036
0
    }
3037
0
    length = (int) (tvb_get_letohl(tvb, O_AERON_BASIC_FRAME_LENGTH) & 0x7fffffff);
3038
0
    if (!((packet_type == HDR_TYPE_DATA) && (length == 0)))
3039
0
    {
3040
0
        if (length < HDR_LENGTH_MIN)
3041
0
        {
3042
0
            return false;
3043
0
        }
3044
0
    }
3045
0
    if (packet_type == HDR_TYPE_PAD)
3046
0
    {
3047
        /* Pad frames can't have a zero term offset */
3048
0
        uint32_t term_offset = tvb_get_letohl(tvb, O_AERON_PAD_TERM_OFFSET);
3049
0
        if (term_offset == 0)
3050
0
        {
3051
0
            return false;
3052
0
        }
3053
0
    }
3054
0
    else
3055
0
    {
3056
0
        if (length > length_remaining)
3057
0
        {
3058
0
            return false;
3059
0
        }
3060
0
    }
3061
0
    rc = dissect_aeron(tvb, pinfo, tree, user_data);
3062
0
    if (rc == 0)
3063
0
    {
3064
0
        return false;
3065
0
    }
3066
0
    return true;
3067
0
}
3068
3069
/* Register all the bits needed with the filtering engine */
3070
void proto_register_aeron(void)
3071
14
{
3072
14
    static hf_register_info hf[] =
3073
14
    {
3074
14
        { &hf_aeron_channel_id,
3075
14
            { "Channel ID", "aeron.channel_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3076
14
        { &hf_aeron_pad,
3077
14
            { "Pad Frame", "aeron.pad", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3078
14
        { &hf_aeron_pad_frame_length,
3079
14
            { "Frame Length", "aeron.pad.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3080
14
        { &hf_aeron_pad_version,
3081
14
            { "Version", "aeron.pad.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3082
14
        { &hf_aeron_pad_flags,
3083
14
            { "Flags", "aeron.pad.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3084
14
        { &hf_aeron_pad_type,
3085
14
            { "Type", "aeron.pad.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3086
14
        { &hf_aeron_pad_term_offset,
3087
14
            { "Term Offset", "aeron.pad.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3088
14
        { &hf_aeron_pad_session_id,
3089
14
            { "Session ID", "aeron.pad.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3090
14
        { &hf_aeron_pad_stream_id,
3091
14
            { "Stream ID", "aeron.pad.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3092
14
        { &hf_aeron_pad_term_id,
3093
14
            { "Term ID", "aeron.pad.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3094
14
        { &hf_aeron_data,
3095
14
            { "Data Frame", "aeron.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3096
14
        { &hf_aeron_data_frame_length,
3097
14
            { "Frame Length", "aeron.data.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3098
14
        { &hf_aeron_data_version,
3099
14
            { "Version", "aeron.data.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3100
14
        { &hf_aeron_data_flags,
3101
14
            { "Flags", "aeron.data.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3102
14
        { &hf_aeron_data_flags_b,
3103
14
            { "Begin Message", "aeron.data.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_BEGIN, NULL, HFILL } },
3104
14
        { &hf_aeron_data_flags_e,
3105
14
            { "End Message", "aeron.data.flags.e", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_END, NULL, HFILL } },
3106
14
        { &hf_aeron_data_flags_s,
3107
14
            { "End Of Stream", "aeron.data.flags.s", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_EOS, NULL, HFILL } },
3108
14
        { &hf_aeron_data_type,
3109
14
            { "Type", "aeron.data.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3110
14
        { &hf_aeron_data_term_offset,
3111
14
            { "Term Offset", "aeron.data.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3112
14
        { &hf_aeron_data_next_offset,
3113
14
            { "Next Offset", "aeron.data.next_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3114
14
        { &hf_aeron_data_next_offset_term,
3115
14
            { "Next Offset Term", "aeron.data.next_offset_term", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3116
14
        { &hf_aeron_data_next_offset_first_frame,
3117
14
            { "Next Offset First Frame", "aeron.data.next_offset_first_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3118
14
        { &hf_aeron_data_session_id,
3119
14
            { "Session ID", "aeron.data.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3120
14
        { &hf_aeron_data_stream_id,
3121
14
            { "Stream ID", "aeron.data.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3122
14
        { &hf_aeron_data_term_id,
3123
14
            { "Term ID", "aeron.data.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3124
14
        { &hf_aeron_data_reserved_value,
3125
14
            { "Reserved", "aeron.data.reserved_value", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3126
14
        { &hf_aeron_data_reassembly,
3127
14
            { "Reassembled Fragments", "aeron.data.reassembly", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3128
14
        { &hf_aeron_data_reassembly_fragment,
3129
14
            { "Fragment", "aeron.data.reassembly.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3130
14
        { &hf_aeron_nak,
3131
14
            { "NAK Frame", "aeron.nak", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3132
14
        { &hf_aeron_nak_frame_length,
3133
14
            { "Frame Length", "aeron.nak.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3134
14
        { &hf_aeron_nak_version,
3135
14
            { "Version", "aeron.nak.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3136
14
        { &hf_aeron_nak_flags,
3137
14
            { "Flags", "aeron.nak.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3138
14
        { &hf_aeron_nak_type,
3139
14
            { "Type", "aeron.nak.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3140
14
        { &hf_aeron_nak_session_id,
3141
14
            { "Session ID", "aeron.nak.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3142
14
        { &hf_aeron_nak_stream_id,
3143
14
            { "Stream ID", "aeron.nak.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3144
14
        { &hf_aeron_nak_term_id,
3145
14
            { "Term ID", "aeron.nak.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3146
14
        { &hf_aeron_nak_term_offset,
3147
14
            { "Term Offset", "aeron.nak.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3148
14
        { &hf_aeron_nak_length,
3149
14
            { "Length", "aeron.nak.length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3150
14
        { &hf_aeron_sm,
3151
14
            { "Status Message", "aeron.sm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3152
14
        { &hf_aeron_sm_frame_length,
3153
14
            { "Frame Length", "aeron.sm.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3154
14
        { &hf_aeron_sm_version,
3155
14
            { "Version", "aeron.sm.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3156
14
        { &hf_aeron_sm_flags,
3157
14
            { "Flags", "aeron.sm.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3158
14
        { &hf_aeron_sm_flags_s,
3159
14
            { "Setup", "aeron.sm.flags.s", FT_BOOLEAN, 8, TFS(&tfs_set_notset), STATUS_FLAGS_SETUP, NULL, HFILL } },
3160
14
        { &hf_aeron_sm_type,
3161
14
            { "Type", "aeron.sm.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3162
14
        { &hf_aeron_sm_session_id,
3163
14
            { "Session ID", "aeron.sm.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3164
14
        { &hf_aeron_sm_stream_id,
3165
14
            { "Stream ID", "aeron.sm.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3166
14
        { &hf_aeron_sm_consumption_term_id,
3167
14
            { "Consumption Term ID", "aeron.sm.consumption_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3168
14
        { &hf_aeron_sm_consumption_term_offset,
3169
14
            { "Consumption Term Offset", "aeron.sm.consumption_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3170
14
        { &hf_aeron_sm_receiver_window,
3171
14
            { "Receiver Window", "aeron.sm.receiver_window", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3172
14
        { &hf_aeron_sm_receiver_id,
3173
14
            { "Receiver ID", "aeron.sm.receiver_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3174
14
        { &hf_aeron_sm_feedback,
3175
14
            { "Application-specific Feedback", "aeron.sm.feedback", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3176
14
        { &hf_aeron_rtt,
3177
14
            { "RTT Message", "aeron.rtt", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3178
14
        { &hf_aeron_rtt_frame_length,
3179
14
            { "Frame Length", "aeron.rtt.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3180
14
        { &hf_aeron_rtt_version,
3181
14
            { "Version", "aeron.rtt.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3182
14
        { &hf_aeron_rtt_flags,
3183
14
            { "Flags", "aeron.rtt.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3184
14
        { &hf_aeron_rtt_flags_r,
3185
14
            { "Reply", "aeron.rtt.flags.r", FT_BOOLEAN, 8, TFS(&tfs_set_notset), STATUS_FLAGS_REPLY, NULL, HFILL } },
3186
14
        { &hf_aeron_rtt_type,
3187
14
            { "Type", "aeron.rtt.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3188
14
        { &hf_aeron_rtt_session_id,
3189
14
            { "Session ID", "aeron.rtt.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3190
14
        { &hf_aeron_rtt_stream_id,
3191
14
            { "Stream ID", "aeron.rtt.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3192
14
        { &hf_aeron_rtt_echo_timestamp,
3193
14
            { "Echo Timestamp", "aeron.rtt.echo_timestamp", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3194
14
        { &hf_aeron_rtt_reception_delta,
3195
14
            { "Reception Delta", "aeron.rtt.reception_delta", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3196
14
        { &hf_aeron_rtt_receiver_id,
3197
14
            { "Receiver ID", "aeron.rtt.receiver_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3198
14
        { &hf_aeron_err,
3199
14
            { "Error Header", "aeron.err", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3200
14
        { &hf_aeron_err_frame_length,
3201
14
            { "Frame Length", "aeron.err.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3202
14
        { &hf_aeron_err_version,
3203
14
            { "Version", "aeron.err.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3204
14
        { &hf_aeron_err_code,
3205
14
            { "Error Code", "aeron.err.code", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3206
14
        { &hf_aeron_err_type,
3207
14
            { "Type", "aeron.err.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3208
14
        { &hf_aeron_err_off_frame_length,
3209
14
            { "Offending Frame Length", "aeron.err.off_frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3210
14
        { &hf_aeron_err_off_hdr,
3211
14
            { "Offending Header", "aeron.err.off_hdr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3212
14
        { &hf_aeron_err_string,
3213
14
            { "Error String", "aeron.err.string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3214
14
        { &hf_aeron_heartbeat,
3215
14
            { "Heart Frame", "aeron.heartbeat", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3216
14
        { &hf_aeron_heartbeat_frame_length,
3217
14
            { "Frame Length", "aeron.heartbeat.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3218
14
        { &hf_aeron_heartbeat_version,
3219
14
            { "Version", "aeron.heartbeat.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3220
14
        { &hf_aeron_heartbeat_flags,
3221
14
            { "Flags", "aeron.heartbeat.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3222
14
        { &hf_aeron_heartbeat_flags_b,
3223
14
            { "Begin Message", "aeron.heartbeat.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_BEGIN, NULL, HFILL } },
3224
14
        { &hf_aeron_heartbeat_flags_e,
3225
14
            { "End Message", "aeron.heartbeat.flags.e", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_END, NULL, HFILL } },
3226
14
        { &hf_aeron_heartbeat_type,
3227
14
            { "Type", "aeron.heartbeat.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3228
14
        { &hf_aeron_heartbeat_term_offset,
3229
14
            { "Term Offset", "aeron.heartbeat.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3230
14
        { &hf_aeron_heartbeat_session_id,
3231
14
            { "Session ID", "aeron.heartbeat.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3232
14
        { &hf_aeron_heartbeat_stream_id,
3233
14
            { "Stream ID", "aeron.heartbeat.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3234
14
        { &hf_aeron_heartbeat_term_id,
3235
14
            { "Term ID", "aeron.heartbeat.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3236
14
        { &hf_aeron_setup,
3237
14
            { "Setup Frame", "aeron.setup", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3238
14
        { &hf_aeron_setup_frame_length,
3239
14
            { "Frame Length", "aeron.setup.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3240
14
        { &hf_aeron_setup_version,
3241
14
            { "Version", "aeron.setup.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3242
14
        { &hf_aeron_setup_flags,
3243
14
            { "Flags", "aeron.setup.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3244
14
        { &hf_aeron_setup_type,
3245
14
            { "Type", "aeron.setup.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3246
14
        { &hf_aeron_setup_term_offset,
3247
14
            { "Term Offset", "aeron.setup.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3248
14
        { &hf_aeron_setup_session_id,
3249
14
            { "Session ID", "aeron.setup.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3250
14
        { &hf_aeron_setup_stream_id,
3251
14
            { "Stream ID", "aeron.setup.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3252
14
        { &hf_aeron_setup_initial_term_id,
3253
14
            { "Initial Term ID", "aeron.setup.initial_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3254
14
        { &hf_aeron_setup_active_term_id,
3255
14
            { "Active Term ID", "aeron.setup.active_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3256
14
        { &hf_aeron_setup_term_length,
3257
14
            { "Term Length", "aeron.setup.term_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3258
14
        { &hf_aeron_setup_mtu,
3259
14
            { "MTU", "aeron.setup.mtu", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3260
14
        { &hf_aeron_setup_ttl,
3261
14
            { "TTL", "aeron.setup.ttl", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3262
14
        { &hf_aeron_sequence_analysis,
3263
14
            { "Sequence Analysis", "aeron.sequence_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3264
14
        { &hf_aeron_sequence_analysis_channel_prev_frame,
3265
14
            { "Previous Channel Frame", "aeron.sequence_analysis.prev_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3266
14
        { &hf_aeron_sequence_analysis_channel_next_frame,
3267
14
            { "Next Channel Frame", "aeron.sequence_analysis.next_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3268
14
        { &hf_aeron_sequence_analysis_stream_prev_frame,
3269
14
            { "Previous Stream Frame", "aeron.sequence_analysis.prev_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3270
14
        { &hf_aeron_sequence_analysis_stream_next_frame,
3271
14
            { "Next Stream Frame", "aeron.sequence_analysis.next_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3272
14
        { &hf_aeron_sequence_analysis_term_prev_frame,
3273
14
            { "Previous Term Frame", "aeron.sequence_analysis.prev_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3274
14
        { &hf_aeron_sequence_analysis_term_next_frame,
3275
14
            { "Next Term Frame", "aeron.sequence_analysis.next_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3276
14
        { &hf_aeron_sequence_analysis_term_offset,
3277
14
            { "Offset also in", "aeron.sequence_analysis.term_offset", FT_NONE, BASE_NONE, NULL, 0x0, "Offset also appears in these frames", HFILL } },
3278
14
        { &hf_aeron_sequence_analysis_term_offset_frame,
3279
14
            { "Frame", "aeron.sequence_analysis.term_offset.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3280
14
        { &hf_aeron_sequence_analysis_retransmission,
3281
14
            { "Frame is a retransmission", "aeron.sequence_analysis.retransmission", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3282
14
        { &hf_aeron_sequence_analysis_retransmission_rx,
3283
14
            { "List of NAK frames to which this retransmission applies", "aeron.sequence_analysis.retransmission.rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3284
14
        { &hf_aeron_sequence_analysis_retransmission_rx_frame,
3285
14
            { "Retransmission applies to frame", "aeron.sequence_analysis.retransmission.rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3286
14
        { &hf_aeron_sequence_analysis_nak_unrecovered,
3287
14
            { "Unrecovered Bytes", "aeron.sequence_analysis.nak_unrecovered", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3288
14
        { &hf_aeron_sequence_analysis_nak_rx,
3289
14
            { "List of RX Frames for this NAK", "aeron.sequence_analysis.nak_rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3290
14
        { &hf_aeron_sequence_analysis_nak_rx_frame,
3291
14
            { "RX Frame for this NAK", "aeron.sequence_analysis.nak_rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3292
14
        { &hf_aeron_sequence_analysis_keepalive,
3293
14
            { "Frame is a keepalive", "aeron.sequence_analysis.keepalive", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3294
14
        { &hf_aeron_stream_analysis,
3295
14
            { "Stream Analysis", "aeron.stream_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3296
14
        { &hf_aeron_stream_analysis_high_term_id,
3297
14
            { "Highest sent term ID", "aeron.stream_analysis.high_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3298
14
        { &hf_aeron_stream_analysis_high_term_offset,
3299
14
            { "Highest sent term offset", "aeron.stream_analysis.high_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3300
14
        { &hf_aeron_stream_analysis_completed_term_id,
3301
14
            { "Completed term ID", "aeron.stream_analysis.completed_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3302
14
        { &hf_aeron_stream_analysis_completed_term_offset,
3303
14
            { "Completed term offset", "aeron.stream_analysis.completed_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3304
14
        { &hf_aeron_stream_analysis_outstanding_bytes,
3305
14
            { "Outstanding bytes", "aeron.stream_analysis.outstanding_bytes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }
3306
14
    };
3307
14
    static int * ett[] =
3308
14
    {
3309
14
        &ett_aeron,
3310
14
        &ett_aeron_pad,
3311
14
        &ett_aeron_data,
3312
14
        &ett_aeron_data_flags,
3313
14
        &ett_aeron_data_reassembly,
3314
14
        &ett_aeron_nak,
3315
14
        &ett_aeron_sm,
3316
14
        &ett_aeron_sm_flags,
3317
14
        &ett_aeron_rtt,
3318
14
        &ett_aeron_rtt_flags,
3319
14
        &ett_aeron_err,
3320
14
        &ett_aeron_setup,
3321
14
        &ett_aeron_ext,
3322
14
        &ett_aeron_sequence_analysis,
3323
14
        &ett_aeron_sequence_analysis_retransmission_rx,
3324
14
        &ett_aeron_sequence_analysis_nak_rx,
3325
14
        &ett_aeron_sequence_analysis_term_offset,
3326
14
        &ett_aeron_stream_analysis
3327
14
    };
3328
14
    static ei_register_info ei[] =
3329
14
    {
3330
14
        { &ei_aeron_analysis_nak, { "aeron.analysis.nak", PI_SEQUENCE, PI_NOTE, "NAK", EXPFILL } },
3331
14
        { &ei_aeron_analysis_window_full, { "aeron.analysis.window_full", PI_SEQUENCE, PI_NOTE, "Receiver window is full", EXPFILL } },
3332
14
        { &ei_aeron_analysis_idle_rx, { "aeron.analysis.idle_rx", PI_SEQUENCE, PI_NOTE, "This frame contains an Idle RX", EXPFILL } },
3333
14
        { &ei_aeron_analysis_pacing_rx, { "aeron.analysis.pacing_rx", PI_SEQUENCE, PI_NOTE, "This frame contains a Pacing RX", EXPFILL } },
3334
14
        { &ei_aeron_analysis_ooo, { "aeron.analysis.ooo", PI_SEQUENCE, PI_NOTE, "This frame contains Out-of-order data", EXPFILL } },
3335
14
        { &ei_aeron_analysis_ooo_gap, { "aeron.analysis.ooo_gap", PI_SEQUENCE, PI_NOTE, "This frame is an Out-of-order gap", EXPFILL } },
3336
14
        { &ei_aeron_analysis_keepalive, { "aeron.analysis.keepalive", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive", EXPFILL } },
3337
14
        { &ei_aeron_analysis_window_resize, { "aeron.analysis.window_resize", PI_SEQUENCE, PI_NOTE, "Receiver window resized", EXPFILL } },
3338
14
        { &ei_aeron_analysis_ooo_sm, { "aeron.analysis.ooo_sm", PI_SEQUENCE, PI_NOTE, "This frame contains an Out-of-order SM", EXPFILL } },
3339
14
        { &ei_aeron_analysis_keepalive_sm, { "aeron.analysis.keepalive_sm", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive SM", EXPFILL } },
3340
14
        { &ei_aeron_analysis_rx, { "aeron.analysis.rx", PI_SEQUENCE, PI_NOTE, "This frame contains a (likely) retransmission", EXPFILL } },
3341
14
        { &ei_aeron_analysis_term_id_change, { "aeron.analysis.term_id_change", PI_SEQUENCE, PI_CHAT, "This frame contains a new term ID", EXPFILL } },
3342
14
        { &ei_aeron_analysis_invalid_pad_length, { "aeron.analysis.invalid_pad_length", PI_MALFORMED, PI_ERROR, "Invalid pad frame length", EXPFILL } },
3343
14
        { &ei_aeron_analysis_invalid_data_length, { "aeron.analysis.invalid_data_length", PI_MALFORMED, PI_ERROR, "Invalid data frame length", EXPFILL } },
3344
14
        { &ei_aeron_analysis_invalid_nak_length, { "aeron.analysis.invalid_nak_length", PI_MALFORMED, PI_ERROR, "Invalid NAK frame length", EXPFILL } },
3345
14
        { &ei_aeron_analysis_invalid_sm_length, { "aeron.analysis.invalid_sm_length", PI_MALFORMED, PI_ERROR, "Invalid SM frame length", EXPFILL } },
3346
14
        { &ei_aeron_analysis_invalid_rtt_length, { "aeron.analysis.invalid_rtt_length", PI_MALFORMED, PI_ERROR, "Invalid RTT frame length", EXPFILL } },
3347
14
        { &ei_aeron_analysis_invalid_err_length, { "aeron.analysis.invalid_err_length", PI_MALFORMED, PI_ERROR, "Invalid error frame length", EXPFILL } },
3348
14
        { &ei_aeron_analysis_invalid_setup_length, { "aeron.analysis.invalid_setup_length", PI_MALFORMED, PI_ERROR, "Invalid setup frame length", EXPFILL } }
3349
14
    };
3350
14
    module_t * aeron_module;
3351
14
    expert_module_t * expert_aeron;
3352
3353
14
    proto_aeron = proto_register_protocol("Aeron Protocol", "Aeron", "aeron");
3354
3355
14
    proto_register_field_array(proto_aeron, hf, array_length(hf));
3356
14
    proto_register_subtree_array(ett, array_length(ett));
3357
14
    expert_aeron = expert_register_protocol(proto_aeron);
3358
14
    expert_register_field_array(expert_aeron, ei, array_length(ei));
3359
14
    aeron_module = prefs_register_protocol(proto_aeron, NULL);
3360
14
    aeron_heuristic_subdissector_list = register_heur_dissector_list_with_description("aeron_msg_payload", "Aeron Data payload", proto_aeron);
3361
3362
14
    aeron_dissector_handle = register_dissector("aeron", dissect_aeron, proto_aeron);
3363
3364
14
    prefs_register_bool_preference(aeron_module,
3365
14
        "sequence_analysis",
3366
14
        "Analyze transport sequencing",
3367
14
        "Include next/previous frame for channel, stream, and term, and other transport sequence analysis.",
3368
14
        &aeron_sequence_analysis);
3369
14
    prefs_register_bool_preference(aeron_module,
3370
14
        "stream_analysis",
3371
14
        "Analyze stream sequencing",
3372
14
        "Include stream analysis, tracking publisher and subscriber positions. Requires \"Analyze transport sequencing\".",
3373
14
        &aeron_stream_analysis);
3374
14
    prefs_register_bool_preference(aeron_module,
3375
14
        "reassemble_fragments",
3376
14
        "Reassemble fragmented data",
3377
14
        "Reassemble fragmented data messages. Requires \"Analyze transport sequencing\" and \"Analyze stream sequencing\".",
3378
14
        &aeron_reassemble_fragments);
3379
14
    prefs_register_bool_preference(aeron_module,
3380
14
        "use_heuristic_subdissectors",
3381
14
        "Use heuristic sub-dissectors",
3382
14
        "Use a registered heuristic sub-dissector to decode the payload data. Requires \"Analyze transport sequencing\", \"Analyze stream sequencing\", and \"Reassemble fragmented data\".",
3383
14
        &aeron_use_heuristic_subdissectors);
3384
14
    register_init_routine(aeron_channel_id_init);
3385
14
    aeron_frame_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3386
14
}
3387
3388
/* The registration hand-off routine */
3389
void proto_reg_handoff_aeron(void)
3390
14
{
3391
14
    dissector_add_for_decode_as_with_preference("udp.port", aeron_dissector_handle);
3392
14
    heur_dissector_add("udp", test_aeron_packet, "Aeron over UDP", "aeron_udp", proto_aeron, HEURISTIC_DISABLE);
3393
14
}
3394
3395
/*
3396
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3397
 *
3398
 * Local variables:
3399
 * c-basic-offset: 4
3400
 * tab-width: 8
3401
 * indent-tabs-mode: nil
3402
 * End:
3403
 *
3404
 * vi: set shiftwidth=4 tabstop=8 expandtab:
3405
 * :indentSize=4:tabSize=8:noTabs=true:
3406
 */