Coverage Report

Created: 2026-08-14 06:45

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