Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-aeron.c
blobacc49fd147babc8348e10e35c5fe6c6fbb9ad5cf
1 /* packet-aeron.c
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
11 * More info https://github.com/real-logic/aeron/wiki/Transport-Protocol-Specification
14 #include "config.h"
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>
25 * The Aeron protocol is defined at
27 * https://github.com/real-logic/aeron/wiki/Transport-Protocol-Specification
30 void proto_register_aeron(void);
31 void proto_reg_handoff_aeron(void);
33 /* Protocol handle */
34 static int proto_aeron;
36 /* Dissector handles */
37 static dissector_handle_t aeron_dissector_handle;
38 static heur_dissector_list_t aeron_heuristic_subdissector_list;
40 /*----------------------------------------------------------------------------*/
41 /* Preferences. */
42 /*----------------------------------------------------------------------------*/
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;
49 /*----------------------------------------------------------------------------*/
50 /* Aeron position routines. */
51 /*----------------------------------------------------------------------------*/
52 typedef struct
54 uint32_t term_id;
55 uint32_t term_offset;
56 } aeron_pos_t;
58 static int aeron_pos_roundup(int offset)
60 return WS_ROUNDUP_32(offset);
63 static int aeron_pos_compare(const aeron_pos_t * pos1, const aeron_pos_t * pos2)
65 /* Returns:
66 < 0 if pos1 < pos2
67 == 0 if pos1 == pos2
68 > 0 if pos1 > pos2
70 if (pos1->term_id == pos2->term_id)
72 if (pos1->term_offset == pos2->term_offset)
74 return 0;
76 else
78 return ((pos1->term_offset < pos2->term_offset) ? -1 : 1);
81 else
83 return ((pos1->term_id < pos2->term_id) ? -1 : 1);
87 static uint32_t aeron_pos_delta(const aeron_pos_t * pos1, const aeron_pos_t * pos2, uint32_t term_size)
89 const aeron_pos_t * p1;
90 const aeron_pos_t * p2;
91 uint64_t p1_val;
92 uint64_t p2_val;
93 uint64_t delta;
94 int rc;
96 rc = aeron_pos_compare(pos1, pos2);
97 if (rc >= 0)
99 p1 = pos1;
100 p2 = pos2;
102 else
104 p1 = pos2;
105 p2 = pos1;
107 p1_val = ((uint64_t) p1->term_id * term_size) + ((uint64_t) p1->term_offset);
108 p2_val = ((uint64_t) p2->term_id * term_size) + ((uint64_t) p2->term_offset);
109 delta = p1_val - p2_val;
110 return ((uint32_t) (delta & UINT64_C(0x00000000ffffffff)));
113 static bool aeron_pos_add_length(aeron_pos_t * pos, uint32_t length, uint32_t term_length)
115 uint32_t next_term_offset;
116 uint32_t rounded_next_term_offset;
118 next_term_offset = pos->term_offset + length;
119 if (next_term_offset < pos->term_offset)
120 return false; /* overflow */
121 rounded_next_term_offset = aeron_pos_roundup(next_term_offset);
122 if (rounded_next_term_offset < next_term_offset)
123 return false; /* overflow */
124 next_term_offset = rounded_next_term_offset;
126 if (next_term_offset >= term_length)
128 pos->term_offset = 0;
129 pos->term_id++;
131 else
133 pos->term_offset = next_term_offset;
135 return true;
138 /*----------------------------------------------------------------------------*/
139 /* Aeron frame information management. */
140 /*----------------------------------------------------------------------------*/
141 static wmem_tree_t * aeron_frame_info_tree;
143 struct aeron_frame_info_t_stct;
144 typedef struct aeron_frame_info_t_stct aeron_frame_info_t;
146 typedef struct
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;
153 typedef struct
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;
163 typedef struct
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 #define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL 0x00000001
173 #define AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX 0x00000002
174 #define AERON_STREAM_ANALYSIS_FLAGS_PACING_RX 0x00000004
175 #define AERON_STREAM_ANALYSIS_FLAGS_OOO 0x00000008
176 #define AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP 0x00000010
177 #define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE 0x00000020
178 #define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE 0x00000040
179 #define AERON_STREAM_ANALYSIS_FLAGS_OOO_SM 0x00000080
180 #define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM 0x00000100
181 #define AERON_STREAM_ANALYSIS_FLAGS_RX 0x00000200
182 #define AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE 0x00000400
184 #define AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID 0x00000001
186 typedef struct
188 uint32_t previous;
189 uint32_t next;
190 } aeron_frame_link_t;
192 struct aeron_msg_t_stct;
193 typedef struct aeron_msg_t_stct aeron_msg_t;
195 struct aeron_frame_info_t_stct
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;
209 #define AERON_FRAME_INFO_FLAGS_RETRANSMISSION 0x00000001
210 #define AERON_FRAME_INFO_FLAGS_KEEPALIVE 0x00000002
211 #define AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG 0x00000004
213 static wmem_tree_key_t * aeron_frame_info_key_build(uint32_t frame, uint32_t ofs)
215 wmem_tree_key_t * fkey;
216 uint32_t * key;
218 fkey = wmem_alloc_array(wmem_packet_scope(), wmem_tree_key_t, 2);
219 key = wmem_alloc_array(wmem_packet_scope(), 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);
229 static aeron_frame_info_t * aeron_frame_info_lookup(wmem_tree_key_t * key)
231 aeron_frame_info_t * fi;
233 fi = (aeron_frame_info_t *) wmem_tree_lookup32_array(aeron_frame_info_tree, key);
234 return (fi);
237 static aeron_frame_info_t * aeron_frame_info_find(uint32_t frame, uint32_t ofs)
239 wmem_tree_key_t * key = aeron_frame_info_key_build(frame, ofs);
240 return (aeron_frame_info_lookup(key));
243 static aeron_frame_info_t * aeron_frame_info_add(uint32_t frame, uint32_t ofs)
245 aeron_frame_info_t * fi;
246 wmem_tree_key_t * key = aeron_frame_info_key_build(frame, ofs);
248 fi = aeron_frame_info_lookup(key);
249 if (fi == NULL)
251 fi = wmem_new0(wmem_file_scope(), aeron_frame_info_t);
252 fi->frame = frame;
253 fi->ofs = ofs;
254 if (aeron_sequence_analysis && aeron_stream_analysis)
256 fi->rx = wmem_list_new(wmem_file_scope());
258 wmem_tree_insert32_array(aeron_frame_info_tree, key, (void *) fi);
260 return (fi);
263 /*----------------------------------------------------------------------------*/
264 /* Aeron channel ID management. */
265 /*----------------------------------------------------------------------------*/
266 static uint64_t aeron_channel_id = 1;
268 static uint64_t aeron_channel_id_assign(void)
270 return (aeron_channel_id++);
273 static void aeron_channel_id_init(void)
275 aeron_channel_id = 1;
278 /*----------------------------------------------------------------------------*/
279 /* Aeron transport, stream, term, and fragment structures. */
280 /*----------------------------------------------------------------------------*/
281 typedef struct
283 address * addr1;
284 address * addr2;
285 uint16_t port1;
286 uint16_t port2;
287 } aeron_conversation_info_t;
289 struct aeron_transport_t_stct;
290 typedef struct aeron_transport_t_stct aeron_transport_t;
292 struct aeron_stream_t_stct;
293 typedef struct aeron_stream_t_stct aeron_stream_t;
295 struct aeron_term_t_stct;
296 typedef struct aeron_term_t_stct aeron_term_t;
298 struct aeron_fragment_t_stct;
299 typedef struct aeron_fragment_t_stct aeron_fragment_t;
301 struct aeron_transport_t_stct
303 uint64_t channel_id;
304 wmem_map_t * stream; /* Map of all streams (aeron_stream_t) in this transport, keyed by stream ID */
305 aeron_frame_info_t * last_frame;
306 address addr1;
307 address addr2;
308 uint32_t session_id;
309 uint16_t port1;
310 uint16_t port2;
313 struct aeron_stream_rcv_t_stct;
314 typedef struct aeron_stream_rcv_t_stct aeron_stream_rcv_t;
316 struct aeron_stream_rcv_t_stct
318 address addr; /* Receiver's IP address */
319 uint16_t port; /* Receiver's (sending) port */
320 aeron_pos_t completed;
321 uint32_t receiver_window;
324 struct aeron_stream_t_stct
326 aeron_transport_t * transport; /* Parent transport */
327 wmem_map_t * term; /* Map of all terms (aeron_term_t) in this stream, keyed by term ID */
328 wmem_list_t * rcv; /* List of receivers (aeron_stream_rcv_t) */
329 uint32_t rcv_count;
330 aeron_frame_info_t * last_frame;
331 uint32_t stream_id;
332 uint32_t term_length;
333 uint32_t mtu;
334 uint32_t ttl;
335 uint32_t flags;
336 aeron_pos_t high;
338 #define AERON_STREAM_FLAGS_HIGH_VALID 0x1
340 typedef struct
342 aeron_term_t * term; /* Parent term */
343 aeron_frame_info_t * frame_info; /* Frame info (aeron_frame_info_t) in which this NAK occurred */
344 uint32_t term_offset; /* NAK term offset */
345 uint32_t length; /* Length of NAK */
346 } aeron_nak_t;
348 struct aeron_term_t_stct
350 aeron_stream_t * stream; /* Parent stream */
351 wmem_map_t * fragment; /* Map of all fragments (aeron_fragment_t) in this term, keyed by term offset */
352 wmem_tree_t * message; /* Tree of all fragmented messages (aeron_msg_t) in this term, keyed by lowest term offset */
353 wmem_list_t * orphan_fragment;
354 aeron_frame_info_t * last_frame; /* Pointer to last frame seen for this term */
355 wmem_list_t * nak; /* List of all NAKs (aeron_nak_t) in this term */
356 uint32_t term_id;
359 struct aeron_fragment_t_stct
361 aeron_term_t * term; /* Parent term */
362 wmem_list_t * frame; /* List of frames (aeron_frame_info_t) containing this fragment (term offset) */
363 aeron_frame_info_t * first_frame; /* First frame which contains this fragment (term offset) */
364 aeron_frame_info_t * last_frame; /* Last frame which contains this fragment (term offset) */
365 aeron_frame_info_t * first_data_frame; /* First frame which contains this fragment (term offset) as actual data (not as a KA) */
366 uint32_t term_offset;
367 uint32_t length;
368 uint32_t data_length;
369 uint32_t frame_count;
372 /*----------------------------------------------------------------------------*/
373 /* Aeron transport management. */
374 /*----------------------------------------------------------------------------*/
375 static unsigned aeron_uint32_hash_func(const void *key)
377 uint32_t value = *((const uint32_t *) key);
378 return ((unsigned) value);
381 static gboolean aeron_uint32_compare_func(const void *lhs, const void *rhs)
383 uint32_t key1 = *((const uint32_t *) lhs);
384 uint32_t key2 = *((const uint32_t *) rhs);
385 return ((key1 == key2) ? true : false);
388 static aeron_transport_t * aeron_transport_add(const aeron_conversation_info_t * cinfo, uint32_t session_id, uint32_t frame)
390 aeron_transport_t * transport;
391 conversation_t * conv;
392 wmem_map_t * session_map;
394 conv = find_conversation(frame, cinfo->addr1, cinfo->addr2, CONVERSATION_UDP, cinfo->port1, cinfo->port2, 0);
395 if (conv == NULL)
397 conv = conversation_new(frame, cinfo->addr1, cinfo->addr2, CONVERSATION_UDP, cinfo->port1, cinfo->port2, 0);
399 if (frame > conv->last_frame)
401 conv->last_frame = frame;
403 session_map = (wmem_map_t *) conversation_get_proto_data(conv, proto_aeron);
404 if (session_map == NULL)
406 session_map = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
407 conversation_add_proto_data(conv, proto_aeron, (void *) session_map);
409 transport = (aeron_transport_t *) wmem_map_lookup(session_map, (const void *) &session_id);
410 if (transport != NULL)
412 return (transport);
414 transport = wmem_new0(wmem_file_scope(), aeron_transport_t);
415 transport->channel_id = aeron_channel_id_assign();
416 transport->stream = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
417 transport->last_frame = NULL;
418 copy_address_wmem(wmem_file_scope(), &(transport->addr1), cinfo->addr1);
419 copy_address_wmem(wmem_file_scope(), &(transport->addr2), cinfo->addr2);
420 transport->session_id = session_id;
421 transport->port1 = cinfo->port1;
422 transport->port2 = cinfo->port2;
423 wmem_map_insert(session_map, (const void *) &(transport->session_id), (void *) transport);
424 return (transport);
427 static aeron_stream_t * aeron_transport_stream_find(aeron_transport_t * transport, uint32_t stream_id)
429 aeron_stream_t * stream;
431 stream = (aeron_stream_t *) wmem_map_lookup(transport->stream, (const void *) &stream_id);
432 return (stream);
435 static aeron_stream_t * aeron_transport_stream_add(aeron_transport_t * transport, uint32_t stream_id)
437 aeron_stream_t * stream;
439 stream = aeron_transport_stream_find(transport, stream_id);
440 if (stream == NULL)
442 stream = wmem_new0(wmem_file_scope(), aeron_stream_t);
443 stream->transport = transport;
444 stream->term = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
445 stream->rcv = wmem_list_new(wmem_file_scope());
446 stream->rcv_count = 0;
447 stream->last_frame = NULL;
448 stream->stream_id = stream_id;
449 stream->term_length = 0;
450 stream->mtu = 0;
451 stream->ttl = 0;
452 stream->flags = 0;
453 stream->high.term_id = 0;
454 stream->high.term_offset = 0;
455 wmem_map_insert(transport->stream, (const void *) &(stream->stream_id), (void *) stream);
457 return (stream);
460 static void aeron_transport_frame_add(aeron_transport_t * transport, aeron_frame_info_t * finfo, uint32_t flags)
462 if (flags != 0)
464 finfo->flags = flags;
466 if (transport->last_frame != NULL)
468 finfo->transport.previous = transport->last_frame->frame;
469 transport->last_frame->transport.next = finfo->frame;
471 finfo->transport.next = 0;
472 transport->last_frame = finfo;
475 /*----------------------------------------------------------------------------*/
476 /* Aeron stream management. */
477 /*----------------------------------------------------------------------------*/
478 static aeron_term_t * aeron_stream_term_find(aeron_stream_t * stream, uint32_t term_id)
480 aeron_term_t * term;
482 term = (aeron_term_t *) wmem_map_lookup(stream->term, (const void *) &term_id);
483 return (term);
486 static aeron_term_t * aeron_stream_term_add(aeron_stream_t * stream, uint32_t term_id)
488 aeron_term_t * term;
490 term = aeron_stream_term_find(stream, term_id);
491 if (term == NULL)
493 term = wmem_new0(wmem_file_scope(), aeron_term_t);
494 term->stream = stream;
495 term->fragment = wmem_map_new(wmem_file_scope(), aeron_uint32_hash_func, aeron_uint32_compare_func);
496 term->message = wmem_tree_new(wmem_file_scope());
497 term->orphan_fragment = wmem_list_new(wmem_file_scope());
498 term->nak = wmem_list_new(wmem_file_scope());
499 term->term_id = term_id;
500 wmem_map_insert(stream->term, (const void *) &(term->term_id), (void *) term);
502 return (term);
505 static aeron_stream_rcv_t * aeron_stream_rcv_find(aeron_stream_t * stream, const address * addr, uint16_t port)
507 wmem_list_frame_t * lf = wmem_list_head(stream->rcv);
508 aeron_stream_rcv_t * rcv = NULL;
510 while (lf != NULL)
512 aeron_stream_rcv_t * cur = (aeron_stream_rcv_t *) wmem_list_frame_data(lf);
513 if (cur != NULL)
515 if ((cmp_address(&(cur->addr), addr) == 0) && (cur->port == port))
517 rcv = cur;
518 break;
521 lf = wmem_list_frame_next(lf);
523 return (rcv);
526 static aeron_stream_rcv_t * aeron_stream_rcv_add(aeron_stream_t * stream, const address * addr, uint16_t port)
528 aeron_stream_rcv_t * rcv;
530 rcv = aeron_stream_rcv_find(stream, addr, port);
531 if (rcv != NULL)
533 return (rcv);
535 rcv = wmem_new0(wmem_file_scope(), aeron_stream_rcv_t);
536 copy_address_wmem(wmem_file_scope(), &(rcv->addr), addr);
537 rcv->port = port;
538 rcv->completed.term_id = 0;
539 rcv->completed.term_offset = 0;
540 rcv->receiver_window = 0;
541 wmem_list_append(stream->rcv, (void *) rcv);
542 stream->rcv_count++;
543 return (rcv);
546 static void aeron_stream_frame_add(aeron_stream_t * stream, aeron_frame_info_t * finfo, uint32_t flags)
548 if (flags != 0)
550 finfo->flags = flags;
552 if (stream->last_frame != NULL)
554 finfo->stream.previous = stream->last_frame->frame;
555 stream->last_frame->stream.next = finfo->frame;
557 finfo->stream.next = 0;
558 stream->last_frame = finfo;
559 aeron_transport_frame_add(stream->transport, finfo, 0);
562 /*----------------------------------------------------------------------------*/
563 /* Aeron term management. */
564 /*----------------------------------------------------------------------------*/
565 static aeron_fragment_t * aeron_term_fragment_find(aeron_term_t * term, uint32_t term_offset)
567 aeron_fragment_t * fragment;
569 fragment = (aeron_fragment_t *) wmem_map_lookup(term->fragment, (const void *) &term_offset);
570 return (fragment);
573 static aeron_fragment_t * aeron_term_fragment_add(aeron_term_t * term, uint32_t term_offset, uint32_t length, uint32_t data_length)
575 aeron_fragment_t * fragment;
577 fragment = aeron_term_fragment_find(term, term_offset);
578 if (fragment == NULL)
580 fragment = wmem_new0(wmem_file_scope(), aeron_fragment_t);
581 fragment->term = term;
582 fragment->frame = wmem_list_new(wmem_file_scope());
583 fragment->first_frame = NULL;
584 fragment->last_frame = NULL;
585 fragment->first_data_frame = NULL;
586 fragment->term_offset = term_offset;
587 fragment->length = length;
588 fragment->data_length = data_length;
589 fragment->frame_count = 0;
590 wmem_map_insert(term->fragment, (const void *) &(fragment->term_offset), (void *) fragment);
592 return (fragment);
595 static void aeron_term_frame_add(aeron_term_t * term, aeron_frame_info_t * finfo, uint32_t flags)
597 if (flags != 0)
599 finfo->flags = flags;
601 if (term->last_frame != NULL)
603 finfo->term.previous = term->last_frame->frame;
604 term->last_frame->term.next = finfo->frame;
606 finfo->term.next = 0;
607 term->last_frame = finfo;
608 aeron_stream_frame_add(term->stream, finfo, 0);
611 /*----------------------------------------------------------------------------*/
612 /* Aeron fragment management. */
613 /*----------------------------------------------------------------------------*/
614 static void aeron_fragment_frame_add(aeron_fragment_t * fragment, aeron_frame_info_t * finfo, uint32_t flags, uint32_t length)
616 if (flags != 0)
618 finfo->flags = flags;
620 wmem_list_append(fragment->frame, (void *) finfo);
621 fragment->frame_count++;
622 if (fragment->last_frame != NULL)
624 finfo->fragment.previous = fragment->last_frame->frame;
625 fragment->last_frame->fragment.next = finfo->frame;
627 if (fragment->first_frame == NULL)
629 fragment->first_frame = finfo;
631 if (length != 0)
633 if (fragment->first_data_frame == NULL)
635 fragment->first_data_frame = finfo;
638 finfo->fragment.next = 0;
639 fragment->last_frame = finfo;
640 aeron_term_frame_add(fragment->term, finfo, 0);
643 /*----------------------------------------------------------------------------*/
644 /* Utility functions. */
645 /*----------------------------------------------------------------------------*/
646 static bool aeron_is_address_multicast(const address * addr)
648 const uint8_t * addr_data = (const uint8_t *) addr->data;
650 switch (addr->type)
652 case AT_IPv4:
653 if (addr_data && ((addr_data[0] & 0xf0) == 0xe0))
655 return true;
657 break;
658 case AT_IPv6:
659 if (addr_data && (addr_data[0] == 0xff))
661 return true;
663 break;
664 default:
665 break;
667 return false;
670 static char * aeron_format_transport_uri(const aeron_conversation_info_t * cinfo)
672 wmem_strbuf_t * uri;
674 uri = wmem_strbuf_new(wmem_packet_scope(), "aeron:udp?");
675 if (aeron_is_address_multicast(cinfo->addr2))
677 switch (cinfo->addr2->type)
679 case AT_IPv6:
680 wmem_strbuf_append_printf(uri, "group=[%s]:%" PRIu16, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
681 break;
682 case AT_IPv4:
683 default:
684 wmem_strbuf_append_printf(uri, "group=%s:%" PRIu16, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
685 break;
688 else
690 switch (cinfo->addr2->type)
692 case AT_IPv6:
693 wmem_strbuf_append_printf(uri, "remote=[%s]:%" PRIu16, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
694 break;
695 case AT_IPv4:
696 default:
697 wmem_strbuf_append_printf(uri, "remote=%s:%" PRIu16, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
698 break;
701 return (wmem_strbuf_finalize(uri));
704 /*----------------------------------------------------------------------------*/
705 /* Packet definitions. */
706 /*----------------------------------------------------------------------------*/
708 /* Basic frame offsets */
709 #define O_AERON_BASIC_FRAME_LENGTH 0
710 #define O_AERON_BASIC_VERSION 4
711 #define O_AERON_BASIC_FLAGS 5
712 #define O_AERON_BASIC_TYPE 6
714 #define HDR_LENGTH_MIN 12
716 /* Padding frame */
717 #define O_AERON_PAD_FRAME_LENGTH 0
718 #define O_AERON_PAD_VERSION 4
719 #define O_AERON_PAD_FLAGS 5
720 #define O_AERON_PAD_TYPE 6
721 #define O_AERON_PAD_TERM_OFFSET 8
722 #define O_AERON_PAD_SESSION_ID 12
723 #define O_AERON_PAD_STREAM_ID 16
724 #define O_AERON_PAD_TERM_ID 20
725 #define L_AERON_PAD_MIN 24
727 /* Data frame */
728 #define O_AERON_DATA_FRAME_LENGTH 0
729 #define O_AERON_DATA_VERSION 4
730 #define O_AERON_DATA_FLAGS 5
731 #define O_AERON_DATA_TYPE 6
732 #define O_AERON_DATA_TERM_OFFSET 8
733 #define O_AERON_DATA_SESSION_ID 12
734 #define O_AERON_DATA_STREAM_ID 16
735 #define O_AERON_DATA_TERM_ID 20
736 #define O_AERON_DATA_RESERVED_VALUE 24
737 #define O_AERON_DATA_DATA 32
738 #define L_AERON_DATA_MIN 32
740 /* NAK frame */
741 #define O_AERON_NAK_FRAME_LENGTH 0
742 #define O_AERON_NAK_VERSION 4
743 #define O_AERON_NAK_FLAGS 5
744 #define O_AERON_NAK_TYPE 6
745 #define O_AERON_NAK_SESSION_ID 8
746 #define O_AERON_NAK_STREAM_ID 12
747 #define O_AERON_NAK_TERM_ID 16
748 #define O_AERON_NAK_TERM_OFFSET 20
749 #define O_AERON_NAK_LENGTH 24
750 #define L_AERON_NAK 28
752 /* Status message */
753 #define O_AERON_SM_FRAME_LENGTH 0
754 #define O_AERON_SM_VERSION 4
755 #define O_AERON_SM_FLAGS 5
756 #define O_AERON_SM_TYPE 6
757 #define O_AERON_SM_SESSION_ID 8
758 #define O_AERON_SM_STREAM_ID 12
759 #define O_AERON_SM_TERM_ID 16
760 #define O_AERON_SM_COMPLETED_TERM_OFFSET 20
761 #define O_AERON_SM_RECEIVER_WINDOW 24
762 #define O_AERON_SM_RECEIVER_ID 28
763 #define O_AERON_SM_FEEDBACK 36
764 #define L_AERON_SM_MIN 36
766 /* Error header */
767 #define O_AERON_ERR_FRAME_LENGTH 0
768 #define O_AERON_ERR_VERSION 4
769 #define O_AERON_ERR_CODE 5
770 #define O_AERON_ERR_TYPE 6
771 #define O_AERON_ERR_OFFENDING_FRAME_LENGTH 8
772 #define O_AERON_ERR_OFFENDING_HEADER 12
773 #define O_AERON_ERR_TERM_ID 16
774 #define O_AERON_ERR_COMPLETED_TERM_OFFSET 20
775 #define O_AERON_ERR_RECEIVER_WINDOW 24
776 #define O_AERON_ERR_FEEDBACK 28
777 #define L_AERON_ERR_MIN 12
779 /* Heartbeat frame */
780 #define O_AERON_HEAERTBEAT_FRAME_LENGTH 0
781 #define O_AERON_HEAERTBEAT_VERSION 4
782 #define O_AERON_HEAERTBEAT_FLAGS 5
783 #define O_AERON_HEAERTBEAT_TYPE 6
784 #define O_AERON_HEAERTBEAT_TERM_OFFSET 8
785 #define O_AERON_HEAERTBEAT_SESSION_ID 12
786 #define O_AERON_HEAERTBEAT_STREAM_ID 16
787 #define O_AERON_HEAERTBEAT_TERM_ID 20
788 #define L_AERON_HEAERTBEAT_MIN 24
790 /* RTT message */
791 #define O_AERON_RTT_FRAME_LENGTH 0
792 #define O_AERON_RTT_VERSION 4
793 #define O_AERON_RTT_FLAGS 5
794 #define O_AERON_RTT_TYPE 6
795 #define O_AERON_RTT_SESSION_ID 8
796 #define O_AERON_RTT_STREAM_ID 12
797 #define O_AERON_RTT_ECHO_TIMESTAMP 16
798 #define O_AERON_RTT_RECEPTION_DELTA 24
799 #define O_AERON_RTT_RECEIVER_ID 32
800 #define L_AERON_RTT 40
802 /* Setup frame */
803 #define O_AERON_SETUP_FRAME_LENGTH 0
804 #define O_AERON_SETUP_VERSION 4
805 #define O_AERON_SETUP_FLAGS 5
806 #define O_AERON_SETUP_TYPE 6
807 #define O_AERON_SETUP_TERM_OFFSET 8
808 #define O_AERON_SETUP_SESSION_ID 12
809 #define O_AERON_SETUP_STREAM_ID 16
810 #define O_AERON_SETUP_INITIAL_TERM_ID 20
811 #define O_AERON_SETUP_ACTIVE_TERM_ID 24
812 #define O_AERON_SETUP_TERM_LENGTH 28
813 #define O_AERON_SETUP_MTU 32
814 #define O_AERON_SETUP_TTL 36
815 #define L_AERON_SETUP 40
817 #define HDR_TYPE_PAD 0x0000
818 #define HDR_TYPE_DATA 0x0001
819 #define HDR_TYPE_NAK 0x0002
820 #define HDR_TYPE_SM 0x0003
821 #define HDR_TYPE_ERR 0x0004
822 #define HDR_TYPE_SETUP 0x0005
823 #define HDR_TYPE_RTT 0x0006
824 #define HDR_TYPE_RES 0x0007
825 #define HDR_TYPE_EXT 0xFFFF
827 #define DATA_FLAGS_BEGIN 0x80
828 #define DATA_FLAGS_END 0x40
829 #define DATA_FLAGS_EOS 0x20
830 #define DATA_FLAGS_COMPLETE (DATA_FLAGS_BEGIN | DATA_FLAGS_END)
832 #define STATUS_FLAGS_SETUP 0x80
833 #define STATUS_FLAGS_REPLY 0x80
836 /*----------------------------------------------------------------------------*/
837 /* Value translation tables. */
838 /*----------------------------------------------------------------------------*/
840 static const value_string aeron_frame_type[] =
842 { HDR_TYPE_PAD, "Pad" },
843 { HDR_TYPE_DATA, "Data" },
844 { HDR_TYPE_NAK, "NAK" },
845 { HDR_TYPE_SM, "Status" },
846 { HDR_TYPE_ERR, "Error" },
847 { HDR_TYPE_SETUP, "Setup" },
848 { HDR_TYPE_RTT, "RTT" },
849 { HDR_TYPE_RES, "Resolution" },
850 { HDR_TYPE_EXT, "Extension" },
851 { 0x0, NULL }
855 Aeron conversations:
857 UDP unicast:
858 - The URL specifies the subscriber address and UDP port, and the publisher "connects" to the single subscriber.
859 - The publisher sends Pad, Data, and Setup frames to the subscriber address and port.
860 - The subscriber sends NAK and SM frames to the publisher, using as the destination the address and port from
861 which the Setup and Data frames were received
862 - So the conversation is defined by [A(publisher),A(subscriber),P(publisher),P(subscriber),PT_UDP]
864 UDP multicast:
865 - The URL specifies the data multicast group and UDP port, and must be an odd-numbered address. The control multicast
866 group is automatically set to be one greater than the data multicast group, and the same port is used.
867 - The publisher sends Pad, Data, and Setup frames to the data multicast group and port.
868 - The subscriber sends NAK and SM frames to the control multicast group and port.
869 - So the conversation is defined by [ControlGroup,DataGroup,port,port,PT_UDP]
873 static aeron_conversation_info_t * aeron_setup_conversation_info(const packet_info * pinfo, uint16_t type)
875 aeron_conversation_info_t * cinfo;
876 int addr_len = pinfo->dst.len;
878 cinfo = wmem_new0(pinfo->pool, aeron_conversation_info_t);
879 switch (pinfo->dst.type)
881 case AT_IPv4:
883 const uint8_t * dst_addr = (const uint8_t *) pinfo->dst.data;
885 cinfo->addr1 = wmem_new0(pinfo->pool, address);
886 cinfo->addr2 = wmem_new0(pinfo->pool, address);
887 if (aeron_is_address_multicast(&(pinfo->dst)))
889 uint8_t * addr1;
890 uint8_t * addr2;
892 addr1 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
893 addr2 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
894 if ((dst_addr[addr_len - 1] & 0x1) != 0)
896 /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
897 addr1[addr_len - 1]++;
899 else
901 /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
902 addr2[addr_len - 1]--;
904 set_address(cinfo->addr1, AT_IPv4, addr_len, (void *) addr1);
905 set_address(cinfo->addr2, AT_IPv4, addr_len, (void *) addr2);
906 cinfo->port1 = pinfo->destport;
907 cinfo->port2 = cinfo->port1;
909 else
911 switch (type)
913 case HDR_TYPE_PAD:
914 case HDR_TYPE_DATA:
915 case HDR_TYPE_SETUP:
916 case HDR_TYPE_RTT:
917 /* Destination is a receiver */
918 copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->src));
919 cinfo->port1 = pinfo->srcport;
920 copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->dst));
921 cinfo->port2 = pinfo->destport;
922 break;
923 case HDR_TYPE_NAK:
924 case HDR_TYPE_SM:
925 /* Destination is the source */
926 copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->dst));
927 cinfo->port1 = pinfo->destport;
928 copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->src));
929 cinfo->port2 = pinfo->srcport;
930 break;
931 default:
932 break;
936 break;
937 case AT_IPv6:
939 const uint8_t * dst_addr = (const uint8_t *) pinfo->dst.data;
941 cinfo->addr1 = wmem_new0(pinfo->pool, address);
942 cinfo->addr2 = wmem_new0(pinfo->pool, address);
943 if (aeron_is_address_multicast(&(pinfo->dst)))
945 uint8_t * addr1;
946 uint8_t * addr2;
948 addr1 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
949 addr2 = (uint8_t *) wmem_memdup(pinfo->pool, (const void *) dst_addr, (size_t) addr_len);
950 if ((dst_addr[addr_len - 1] & 0x1) != 0)
952 /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
953 addr1[addr_len - 1]++;
955 else
957 /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
958 addr2[addr_len - 1]--;
960 set_address(cinfo->addr1, AT_IPv6, addr_len, (void *) addr1);
961 set_address(cinfo->addr2, AT_IPv6, addr_len, (void *) addr2);
962 cinfo->port1 = pinfo->destport;
963 cinfo->port2 = cinfo->port1;
965 else
967 switch (type)
969 case HDR_TYPE_PAD:
970 case HDR_TYPE_DATA:
971 case HDR_TYPE_SETUP:
972 case HDR_TYPE_RTT:
973 /* Destination is a receiver */
974 copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->src));
975 cinfo->port1 = pinfo->srcport;
976 copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->dst));
977 cinfo->port2 = pinfo->destport;
978 break;
979 case HDR_TYPE_NAK:
980 case HDR_TYPE_SM:
981 /* Destination is the source */
982 copy_address_wmem(pinfo->pool, cinfo->addr1, &(pinfo->dst));
983 cinfo->port1 = pinfo->destport;
984 copy_address_wmem(pinfo->pool, cinfo->addr2, &(pinfo->src));
985 cinfo->port2 = pinfo->srcport;
986 break;
987 default:
988 break;
992 break;
993 default:
994 return (NULL);
996 return (cinfo);
999 /*----------------------------------------------------------------------------*/
1000 /* Handles of all types. */
1001 /*----------------------------------------------------------------------------*/
1003 /* Dissector tree handles */
1004 static int ett_aeron;
1005 static int ett_aeron_pad;
1006 static int ett_aeron_data;
1007 static int ett_aeron_data_flags;
1008 static int ett_aeron_data_reassembly;
1009 static int ett_aeron_nak;
1010 static int ett_aeron_sm;
1011 static int ett_aeron_sm_flags;
1012 static int ett_aeron_rtt;
1013 static int ett_aeron_rtt_flags;
1014 static int ett_aeron_err;
1015 static int ett_aeron_setup;
1016 static int ett_aeron_ext;
1017 static int ett_aeron_sequence_analysis;
1018 static int ett_aeron_sequence_analysis_retransmission_rx;
1019 static int ett_aeron_sequence_analysis_nak_rx;
1020 static int ett_aeron_sequence_analysis_term_offset;
1021 static int ett_aeron_stream_analysis;
1023 /* Dissector field handles */
1024 static int hf_aeron_channel_id;
1025 static int hf_aeron_pad;
1026 static int hf_aeron_pad_frame_length;
1027 static int hf_aeron_pad_version;
1028 static int hf_aeron_pad_flags;
1029 static int hf_aeron_pad_type;
1030 static int hf_aeron_pad_term_offset;
1031 static int hf_aeron_pad_session_id;
1032 static int hf_aeron_pad_stream_id;
1033 static int hf_aeron_pad_term_id;
1034 static int hf_aeron_data;
1035 static int hf_aeron_data_frame_length;
1036 static int hf_aeron_data_version;
1037 static int hf_aeron_data_flags;
1038 static int hf_aeron_data_flags_b;
1039 static int hf_aeron_data_flags_e;
1040 static int hf_aeron_data_flags_s;
1041 static int hf_aeron_data_type;
1042 static int hf_aeron_data_term_offset;
1043 static int hf_aeron_data_next_offset;
1044 static int hf_aeron_data_next_offset_term;
1045 static int hf_aeron_data_next_offset_first_frame;
1046 static int hf_aeron_data_session_id;
1047 static int hf_aeron_data_stream_id;
1048 static int hf_aeron_data_term_id;
1049 static int hf_aeron_data_reserved_value;
1050 static int hf_aeron_data_reassembly;
1051 static int hf_aeron_data_reassembly_fragment;
1052 static int hf_aeron_nak;
1053 static int hf_aeron_nak_frame_length;
1054 static int hf_aeron_nak_version;
1055 static int hf_aeron_nak_flags;
1056 static int hf_aeron_nak_type;
1057 static int hf_aeron_nak_session_id;
1058 static int hf_aeron_nak_stream_id;
1059 static int hf_aeron_nak_term_id;
1060 static int hf_aeron_nak_term_offset;
1061 static int hf_aeron_nak_length;
1062 static int hf_aeron_sm;
1063 static int hf_aeron_sm_frame_length;
1064 static int hf_aeron_sm_version;
1065 static int hf_aeron_sm_flags;
1066 static int hf_aeron_sm_flags_s;
1067 static int hf_aeron_sm_type;
1068 static int hf_aeron_sm_session_id;
1069 static int hf_aeron_sm_stream_id;
1070 static int hf_aeron_sm_consumption_term_id;
1071 static int hf_aeron_sm_consumption_term_offset;
1072 static int hf_aeron_sm_receiver_window;
1073 static int hf_aeron_sm_receiver_id;
1074 static int hf_aeron_sm_feedback;
1075 static int hf_aeron_err;
1076 static int hf_aeron_err_frame_length;
1077 static int hf_aeron_err_version;
1078 static int hf_aeron_err_code;
1079 static int hf_aeron_err_type;
1080 static int hf_aeron_err_off_frame_length;
1081 static int hf_aeron_err_off_hdr;
1082 static int hf_aeron_err_string;
1083 static int hf_aeron_heartbeat;
1084 static int hf_aeron_heartbeat_frame_length;
1085 static int hf_aeron_heartbeat_version;
1086 static int hf_aeron_heartbeat_flags;
1087 static int hf_aeron_heartbeat_flags_b;
1088 static int hf_aeron_heartbeat_flags_e;
1089 static int hf_aeron_heartbeat_type;
1090 static int hf_aeron_heartbeat_term_offset;
1091 static int hf_aeron_heartbeat_session_id;
1092 static int hf_aeron_heartbeat_stream_id;
1093 static int hf_aeron_heartbeat_term_id;
1094 static int hf_aeron_rtt;
1095 static int hf_aeron_rtt_frame_length;
1096 static int hf_aeron_rtt_version;
1097 static int hf_aeron_rtt_flags;
1098 static int hf_aeron_rtt_flags_r;
1099 static int hf_aeron_rtt_type;
1100 static int hf_aeron_rtt_session_id;
1101 static int hf_aeron_rtt_stream_id;
1102 static int hf_aeron_rtt_echo_timestamp;
1103 static int hf_aeron_rtt_reception_delta;
1104 static int hf_aeron_rtt_receiver_id;
1105 static int hf_aeron_setup;
1106 static int hf_aeron_setup_frame_length;
1107 static int hf_aeron_setup_version;
1108 static int hf_aeron_setup_flags;
1109 static int hf_aeron_setup_type;
1110 static int hf_aeron_setup_term_offset;
1111 static int hf_aeron_setup_session_id;
1112 static int hf_aeron_setup_stream_id;
1113 static int hf_aeron_setup_initial_term_id;
1114 static int hf_aeron_setup_active_term_id;
1115 static int hf_aeron_setup_term_length;
1116 static int hf_aeron_setup_mtu;
1117 static int hf_aeron_setup_ttl;
1118 static int hf_aeron_sequence_analysis;
1119 static int hf_aeron_sequence_analysis_channel_prev_frame;
1120 static int hf_aeron_sequence_analysis_channel_next_frame;
1121 static int hf_aeron_sequence_analysis_stream_prev_frame;
1122 static int hf_aeron_sequence_analysis_stream_next_frame;
1123 static int hf_aeron_sequence_analysis_term_prev_frame;
1124 static int hf_aeron_sequence_analysis_term_next_frame;
1125 static int hf_aeron_sequence_analysis_term_offset;
1126 static int hf_aeron_sequence_analysis_term_offset_frame;
1127 static int hf_aeron_sequence_analysis_retransmission;
1128 static int hf_aeron_sequence_analysis_retransmission_rx;
1129 static int hf_aeron_sequence_analysis_retransmission_rx_frame;
1130 static int hf_aeron_sequence_analysis_keepalive;
1131 static int hf_aeron_sequence_analysis_nak_unrecovered;
1132 static int hf_aeron_sequence_analysis_nak_rx;
1133 static int hf_aeron_sequence_analysis_nak_rx_frame;
1134 static int hf_aeron_stream_analysis;
1135 static int hf_aeron_stream_analysis_high_term_id;
1136 static int hf_aeron_stream_analysis_high_term_offset;
1137 static int hf_aeron_stream_analysis_completed_term_id;
1138 static int hf_aeron_stream_analysis_completed_term_offset;
1139 static int hf_aeron_stream_analysis_outstanding_bytes;
1141 /* Expert info handles */
1142 static expert_field ei_aeron_analysis_nak;
1143 static expert_field ei_aeron_analysis_window_full;
1144 static expert_field ei_aeron_analysis_idle_rx;
1145 static expert_field ei_aeron_analysis_pacing_rx;
1146 static expert_field ei_aeron_analysis_ooo;
1147 static expert_field ei_aeron_analysis_ooo_gap;
1148 static expert_field ei_aeron_analysis_keepalive;
1149 static expert_field ei_aeron_analysis_ooo_sm;
1150 static expert_field ei_aeron_analysis_keepalive_sm;
1151 static expert_field ei_aeron_analysis_window_resize;
1152 static expert_field ei_aeron_analysis_rx;
1153 static expert_field ei_aeron_analysis_term_id_change;
1154 static expert_field ei_aeron_analysis_invalid_pad_length;
1155 static expert_field ei_aeron_analysis_invalid_data_length;
1156 static expert_field ei_aeron_analysis_invalid_nak_length;
1157 static expert_field ei_aeron_analysis_invalid_sm_length;
1158 static expert_field ei_aeron_analysis_invalid_rtt_length;
1159 static expert_field ei_aeron_analysis_invalid_err_length;
1160 static expert_field ei_aeron_analysis_invalid_setup_length;
1162 /*----------------------------------------------------------------------------*/
1163 /* Setup packet information */
1164 /*----------------------------------------------------------------------------*/
1165 typedef struct
1167 uint32_t info_flags;
1168 uint32_t stream_id;
1169 uint32_t term_id;
1170 uint32_t term_offset;
1171 uint32_t length;
1172 uint32_t data_length;
1173 uint32_t receiver_window;
1174 uint64_t receiver_id;
1175 uint32_t nak_term_offset;
1176 uint32_t nak_length;
1177 uint16_t type;
1178 uint8_t flags;
1179 } aeron_packet_info_t;
1180 #define AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID 0x00000001
1181 #define AERON_PACKET_INFO_FLAGS_TERM_ID_VALID 0x00000002
1182 #define AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID 0x00000004
1184 static void aeron_frame_nak_rx_add(aeron_frame_info_t * nak_info, aeron_frame_info_t * rx_info, uint32_t term_offset, uint32_t length)
1186 if (nak_info->nak_analysis->unrecovered_length >= length)
1188 wmem_list_frame_t * lf = wmem_list_head(nak_info->nak_analysis->rx);
1189 aeron_rx_info_t * rx = NULL;
1191 while (lf != NULL)
1193 rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1194 if (rx != NULL)
1196 if ((rx->term_offset == term_offset) && (rx->length == length))
1198 /* Already have this RX */
1199 return;
1202 lf = wmem_list_frame_next(lf);
1204 /* This RX frame isn't in the list, so add it */
1205 rx = wmem_new0(wmem_file_scope(), aeron_rx_info_t);
1206 rx->frame_info = rx_info;
1207 rx->term_offset = term_offset;
1208 rx->length = length;
1209 wmem_list_append(nak_info->nak_analysis->rx, (void *) rx);
1210 nak_info->nak_analysis->unrecovered_length -= length;
1211 wmem_list_append(rx_info->rx, (void *) nak_info);
1215 static void aeron_frame_process_rx(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1217 wmem_list_frame_t * lf;
1219 lf = wmem_list_head(term->nak);
1220 while (lf != NULL)
1222 aeron_nak_t * nak = (aeron_nak_t *) wmem_list_frame_data(lf);
1223 if (nak != NULL)
1225 if (nak->frame_info->frame <= finfo->frame)
1227 if ((nak->term_offset <= info->term_offset) && (nak->length >= info->length))
1229 /* This data frame falls entirely within the NAK range */
1230 aeron_frame_nak_rx_add(nak->frame_info, finfo, info->term_offset, info->length);
1234 lf = wmem_list_frame_next(lf);
1238 static void aeron_frame_nak_analysis_setup(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1240 aeron_nak_t * nak = wmem_new0(wmem_file_scope(), aeron_nak_t);
1241 nak->term = term;
1242 nak->frame_info = finfo;
1243 nak->term_offset = info->nak_term_offset;
1244 nak->length = info->nak_length;
1245 wmem_list_append(term->nak, (void *) nak);
1247 finfo->nak_analysis = wmem_new0(wmem_file_scope(), aeron_nak_analysis_t);
1248 finfo->nak_analysis->frame_info = finfo;
1249 finfo->nak_analysis->rx = wmem_list_new(wmem_file_scope());
1250 finfo->nak_analysis->nak_term_offset = info->nak_term_offset;
1251 finfo->nak_analysis->nak_length = info->nak_length;
1252 finfo->nak_analysis->unrecovered_length = info->nak_length;
1255 /* return 0 for success and -1 for error */
1256 static int aeron_frame_stream_analysis_setup(packet_info * pinfo, aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_stream_t * stream, aeron_term_t * term, bool new_term)
1258 aeron_stream_rcv_t * rcv = NULL;
1259 /* dp is the current data position (from this frame). */
1260 aeron_pos_t dp = { 0, 0 };
1262 pdp is the previous (high) data position (from the stream).
1263 pdpv is true if pdp is valid (meaning we previously saw a data message).
1265 aeron_pos_t pdp = stream->high;
1266 bool pdpv = ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0);
1267 /* rp is the current receiver position (from this frame). */
1268 aeron_pos_t rp = { 0, 0 };
1270 prp is the previous (high) receiver completed position (from the stream receiver).
1271 prpv is true if prp is valid (meaning we previously saw a status message).
1273 aeron_pos_t prp = { 0, 0 };
1274 bool prpv = false;
1275 uint32_t cur_receiver_window = 0;
1276 /* Flags to be used when creating the fragment frame entry */
1277 uint32_t frame_flags = 0;
1279 if (info->type == HDR_TYPE_SM)
1281 /* Locate the receiver */
1282 rcv = aeron_stream_rcv_find(stream, &(pinfo->src), pinfo->srcport);
1283 if (rcv == NULL)
1285 rcv = aeron_stream_rcv_add(stream, &(pinfo->src), pinfo->srcport);
1287 else
1289 prpv = true;
1290 prp = rcv->completed;
1291 cur_receiver_window = rcv->receiver_window;
1294 switch (info->type)
1296 case HDR_TYPE_DATA:
1297 case HDR_TYPE_PAD:
1298 dp.term_id = info->term_id;
1299 dp.term_offset = info->term_offset;
1300 if (!aeron_pos_add_length(&dp, info->length, stream->term_length))
1301 return -1;
1302 if (pdpv)
1304 if (dp.term_id > stream->high.term_id)
1306 stream->high.term_id = dp.term_id;
1307 stream->high.term_offset = dp.term_offset;
1309 else if (dp.term_offset > stream->high.term_offset)
1311 stream->high.term_offset = dp.term_offset;
1314 else
1316 stream->flags |= AERON_STREAM_FLAGS_HIGH_VALID;
1317 stream->high.term_id = dp.term_id;
1318 stream->high.term_offset = dp.term_offset;
1320 break;
1321 case HDR_TYPE_SM:
1322 rp.term_id = info->term_id;
1323 rp.term_offset = info->term_offset;
1324 if (prpv)
1326 if (rp.term_id > rcv->completed.term_id)
1328 rcv->completed.term_id = rp.term_id;
1329 rcv->completed.term_offset = rp.term_offset;
1331 else if (rp.term_offset > rcv->completed.term_offset)
1333 rcv->completed.term_offset = rp.term_offset;
1336 else
1338 rcv->completed.term_id = rp.term_id;
1339 rcv->completed.term_offset = rp.term_offset;
1341 rcv->receiver_window = info->receiver_window;
1342 break;
1343 default:
1344 break;
1346 if (aeron_stream_analysis)
1348 if ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0)
1350 finfo->stream_analysis = wmem_new0(wmem_file_scope(), aeron_stream_analysis_t);
1353 if (finfo->stream_analysis != NULL)
1355 switch (info->type)
1357 case HDR_TYPE_DATA:
1358 case HDR_TYPE_SM:
1359 case HDR_TYPE_PAD:
1360 finfo->stream_analysis->high.term_id = stream->high.term_id;
1361 finfo->stream_analysis->high.term_offset = stream->high.term_offset;
1362 if (rcv != NULL)
1364 finfo->stream_analysis->flags2 |= AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID;
1365 finfo->stream_analysis->completed.term_id = rcv->completed.term_id;
1366 finfo->stream_analysis->completed.term_offset = rcv->completed.term_offset;
1367 finfo->stream_analysis->receiver_window = rcv->receiver_window;
1368 finfo->stream_analysis->outstanding_bytes = aeron_pos_delta(&(finfo->stream_analysis->high), &(finfo->stream_analysis->completed), stream->term_length);
1369 if (finfo->stream_analysis->outstanding_bytes >= finfo->stream_analysis->receiver_window)
1371 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL;
1374 else
1376 finfo->stream_analysis->completed.term_id = 0;
1377 finfo->stream_analysis->completed.term_offset = 0;
1378 finfo->stream_analysis->receiver_window = 0;
1379 finfo->stream_analysis->outstanding_bytes = 0;
1381 break;
1382 default:
1383 break;
1385 switch (info->type)
1387 case HDR_TYPE_DATA:
1388 case HDR_TYPE_PAD:
1389 if (pdpv)
1391 /* We have a previous data position. */
1392 int rc = aeron_pos_compare(&dp, &pdp);
1393 if (rc == 0)
1395 /* Data position is the same as previous data position. */
1396 if (info->length == 0)
1398 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE;
1399 frame_flags |= AERON_FRAME_INFO_FLAGS_KEEPALIVE;
1401 else
1403 if (prpv)
1405 /* Previous receiver position is valid */
1406 if (aeron_pos_compare(&dp, &prp) == 0)
1408 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1410 else
1412 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_PACING_RX;
1415 else
1417 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1419 frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1422 else
1424 aeron_pos_t expected_dp;
1425 int erc;
1427 expected_dp.term_id = pdp.term_id;
1428 expected_dp.term_offset = pdp.term_offset;
1429 if (!aeron_pos_add_length(&expected_dp, info->length, stream->term_length))
1430 return -1;
1431 erc = aeron_pos_compare(&expected_dp, &dp);
1432 if (erc > 0)
1434 /* Could be OOO - but for now assume it's a RX */
1435 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_RX;
1436 frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1437 aeron_frame_process_rx(info, finfo, term);
1439 else if (erc < 0)
1441 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP;
1445 if (new_term && (info->term_offset == 0))
1447 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE;
1449 break;
1450 case HDR_TYPE_SM:
1451 if (prpv)
1453 int rc = aeron_pos_compare(&rp, &prp);
1454 if (rc == 0)
1456 /* Completed term ID and term offset stayed the same. */
1457 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM;
1459 else if (rc < 0)
1461 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_SM;
1463 if (cur_receiver_window != finfo->stream_analysis->receiver_window)
1465 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE;
1468 break;
1469 default:
1470 break;
1473 if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1475 aeron_fragment_t * fragment;
1477 fragment = aeron_term_fragment_find(term, info->term_offset);
1478 if (fragment == NULL)
1480 fragment = aeron_term_fragment_add(term, info->term_offset, info->length, info->data_length);
1482 aeron_fragment_frame_add(fragment, finfo, frame_flags, info->length);
1484 else
1486 aeron_term_frame_add(term, finfo, frame_flags);
1489 return 0;
1492 /* return 0 for success and -1 for error */
1493 static int aeron_frame_info_setup(packet_info * pinfo, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo)
1495 if (!transport || !aeron_sequence_analysis || !finfo || PINFO_FD_VISITED(pinfo))
1496 /* XXX - is it an error if transport, aeron_sequence_analysis or finfo are NULL? */
1497 return 0;
1499 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1501 aeron_stream_t * stream;
1503 stream = aeron_transport_stream_find(transport, info->stream_id);
1504 if (stream == NULL)
1506 stream = aeron_transport_stream_add(transport, info->stream_id);
1508 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1510 aeron_term_t * term;
1511 bool new_term = false;
1513 term = aeron_stream_term_find(stream, info->term_id);
1514 if (term == NULL)
1516 term = aeron_stream_term_add(stream, info->term_id);
1517 new_term = true;
1519 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1521 if (aeron_frame_stream_analysis_setup(pinfo, info, finfo, stream, term, new_term) < 0)
1522 return -1;
1524 else
1526 aeron_term_frame_add(term, finfo, 0);
1527 if (info->type == HDR_TYPE_NAK)
1529 aeron_frame_nak_analysis_setup(info, finfo, term);
1533 else
1535 aeron_stream_frame_add(stream, finfo, 0);
1538 else
1540 aeron_transport_frame_add(transport, finfo, 0);
1543 return 0;
1546 static void aeron_sequence_report_frame(tvbuff_t * tvb, proto_tree * tree, aeron_frame_info_t * finfo)
1548 proto_item * item = NULL;
1550 if ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0)
1552 item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" PRIu32 " (RX)", finfo->frame);
1554 else if ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0)
1556 item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" PRIu32 " (KA)", finfo->frame);
1558 else
1560 item = proto_tree_add_uint(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame);
1562 proto_item_set_generated(item);
1565 static void aeron_sequence_report(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo)
1567 if (transport != NULL)
1569 if (aeron_sequence_analysis && (finfo != NULL))
1571 proto_tree * subtree;
1572 proto_item * item;
1574 item = proto_tree_add_item(tree, hf_aeron_sequence_analysis, tvb, 0, 0, ENC_NA);
1575 proto_item_set_generated(item);
1576 subtree = proto_item_add_subtree(item, ett_aeron_sequence_analysis);
1577 if (finfo->transport.previous != 0)
1579 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_prev_frame, tvb, 0, 0, finfo->transport.previous);
1580 proto_item_set_generated(item);
1582 if (finfo->transport.next != 0)
1584 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_next_frame, tvb, 0, 0, finfo->transport.next);
1585 proto_item_set_generated(item);
1587 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1589 aeron_stream_t * stream;
1591 stream = aeron_transport_stream_find(transport, info->stream_id);
1592 if (stream != NULL)
1594 if (finfo->stream.previous != 0)
1596 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_prev_frame, tvb, 0, 0, finfo->stream.previous);
1597 proto_item_set_generated(item);
1599 if (finfo->stream.next != 0)
1601 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_next_frame, tvb, 0, 0, finfo->stream.next);
1602 proto_item_set_generated(item);
1604 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1606 aeron_term_t * term;
1608 term = aeron_stream_term_find(stream, info->term_id);
1609 if (term != NULL)
1611 if (finfo->term.previous != 0)
1613 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_prev_frame, tvb, 0, 0, finfo->term.previous);
1614 proto_item_set_generated(item);
1616 if (finfo->term.next != 0)
1618 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_next_frame, tvb, 0, 0, finfo->term.next);
1619 proto_item_set_generated(item);
1621 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1623 if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1625 aeron_fragment_t * fragment;
1627 fragment = aeron_term_fragment_find(term, info->term_offset);
1628 if (fragment != NULL)
1630 proto_item * fei_item;
1631 bool rx = ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0);
1632 bool ka = ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0);
1634 if (fragment->frame_count > 1)
1636 proto_tree * frame_tree;
1637 proto_item * frame_item;
1638 wmem_list_frame_t * lf;
1640 frame_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_term_offset, tvb, 0, 0, ENC_NA);
1641 proto_item_set_generated(frame_item);
1642 frame_tree = proto_item_add_subtree(frame_item, ett_aeron_sequence_analysis_term_offset);
1643 lf = wmem_list_head(fragment->frame);
1644 while (lf != NULL)
1646 aeron_frame_info_t * frag_frame = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1647 if (frag_frame != NULL)
1649 if (frag_frame->frame != pinfo->num)
1651 aeron_sequence_report_frame(tvb, frame_tree, frag_frame);
1654 lf = wmem_list_frame_next(lf);
1657 fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_retransmission, tvb, 0, 0, rx);
1658 proto_item_set_generated(fei_item);
1659 if (rx)
1661 if (wmem_list_count(finfo->rx) > 0)
1663 proto_tree * rx_tree;
1664 proto_item * rx_item;
1665 wmem_list_frame_t * lf;
1667 rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_retransmission_rx, tvb, 0, 0, ENC_NA);
1668 proto_item_set_generated(rx_item);
1669 rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_retransmission_rx);
1670 lf = wmem_list_head(finfo->rx);
1671 while (lf != NULL)
1673 aeron_frame_info_t * nak = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1674 if (nak != NULL)
1676 rx_item = proto_tree_add_uint(rx_tree, hf_aeron_sequence_analysis_retransmission_rx_frame, tvb, 0, 0, nak->frame);
1677 proto_item_set_generated(rx_item);
1679 lf = wmem_list_frame_next(lf);
1683 fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_keepalive, tvb, 0, 0, ka);
1684 proto_item_set_generated(fei_item);
1688 else if ((info->type == HDR_TYPE_NAK) && (finfo->nak_analysis != NULL))
1690 proto_item * nak_item;
1692 nak_item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_nak_unrecovered, tvb, 0, 0, finfo->nak_analysis->unrecovered_length);
1693 proto_item_set_generated(nak_item);
1694 if (wmem_list_count(finfo->nak_analysis->rx) > 0)
1696 proto_tree * rx_tree;
1697 proto_item * rx_item;
1698 wmem_list_frame_t * lf;
1700 rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_nak_rx, tvb, 0, 0, ENC_NA);
1701 proto_item_set_generated(rx_item);
1702 rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_nak_rx);
1703 lf = wmem_list_head(finfo->nak_analysis->rx);
1704 while (lf != NULL)
1706 aeron_rx_info_t * rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1707 if (rx != NULL)
1709 rx_item = proto_tree_add_uint_format_value(rx_tree, hf_aeron_sequence_analysis_nak_rx_frame, tvb, 0, 0, rx->frame_info->frame,
1710 "%" PRIu32 ", Term offset=%" PRIu32 " (0x%08x), Length=%" PRIu32, rx->frame_info->frame, rx->term_offset, rx->term_offset, rx->length);
1711 proto_item_set_generated(rx_item);
1713 lf = wmem_list_frame_next(lf);
1725 static void aeron_stream_report(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, aeron_transport_t * transport, aeron_frame_info_t * finfo)
1727 if (transport != NULL)
1729 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1731 proto_tree * subtree;
1732 proto_item * item;
1734 item = proto_tree_add_item(tree, hf_aeron_stream_analysis, tvb, 0, 0, ENC_NA);
1735 proto_item_set_generated(item);
1736 subtree = proto_item_add_subtree(item, ett_aeron_stream_analysis);
1737 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_id, tvb, 0, 0, finfo->stream_analysis->high.term_id);
1738 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE) != 0)
1740 expert_add_info(pinfo, item, &ei_aeron_analysis_term_id_change);
1742 proto_item_set_generated(item);
1743 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_offset, tvb, 0, 0, finfo->stream_analysis->high.term_offset);
1744 proto_item_set_generated(item);
1745 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX) != 0)
1747 expert_add_info(pinfo, item, &ei_aeron_analysis_idle_rx);
1749 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_PACING_RX) != 0)
1751 expert_add_info(pinfo, item, &ei_aeron_analysis_pacing_rx);
1753 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO) != 0)
1755 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo);
1757 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP) != 0)
1759 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_gap);
1761 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1763 expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive);
1765 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_RX) != 0)
1767 expert_add_info(pinfo, item, &ei_aeron_analysis_rx);
1769 if ((finfo->stream_analysis->flags2 & AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID) != 0)
1771 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_id, tvb, 0, 0, finfo->stream_analysis->completed.term_id);
1772 proto_item_set_generated(item);
1773 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_offset, tvb, 0, 0, finfo->stream_analysis->completed.term_offset);
1774 proto_item_set_generated(item);
1775 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_SM) != 0)
1777 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_sm);
1779 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1781 expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive_sm);
1783 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_outstanding_bytes, tvb, 0, 0, finfo->stream_analysis->outstanding_bytes);
1784 proto_item_set_generated(item);
1785 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL) != 0)
1787 expert_add_info(pinfo, item, &ei_aeron_analysis_window_full);
1794 static void aeron_next_offset_report(tvbuff_t * tvb, proto_tree * tree, aeron_transport_t * transport, uint32_t stream_id, uint32_t term_id, uint32_t term_offset, uint32_t length)
1796 aeron_stream_t * stream;
1798 stream = aeron_transport_stream_find(transport, stream_id);
1799 if (stream != NULL)
1801 aeron_term_t * term;
1802 if (stream->term_length == 0)
1804 stream->term_length = length;
1806 term = aeron_stream_term_find(stream, term_id);
1807 if (term != NULL)
1809 aeron_fragment_t * fragment = aeron_term_fragment_find(term, term_offset);
1810 if (fragment != NULL)
1812 uint32_t next_offset = term_offset + length;
1813 uint32_t next_offset_term_id = term_id;
1814 aeron_term_t * next_offset_term = NULL;
1815 proto_item * item;
1817 if (next_offset >= stream->term_length)
1819 next_offset = 0;
1820 next_offset_term_id++;
1822 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset, tvb, 0, 0, next_offset);
1823 proto_item_set_generated(item);
1824 if (next_offset_term_id != term_id)
1826 next_offset_term = aeron_stream_term_find(stream, next_offset_term_id);
1827 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_term, tvb, 0, 0, next_offset_term_id);
1828 proto_item_set_generated(item);
1830 else
1832 next_offset_term = term;
1834 if (next_offset_term != NULL)
1836 aeron_fragment_t * next_offset_fragment;
1837 next_offset_fragment = aeron_term_fragment_find(next_offset_term, next_offset);
1838 if (next_offset_fragment != NULL)
1840 if (next_offset_fragment->first_frame != NULL)
1842 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_first_frame, tvb, 0, 0, next_offset_fragment->first_frame->frame);
1843 proto_item_set_generated(item);
1852 static void aeron_info_stream_progress_report(packet_info * pinfo, uint16_t msgtype, uint8_t flags, uint32_t term_id, uint32_t term_offset, aeron_frame_info_t * finfo)
1854 const char * type_string = val_to_str_const((uint32_t) msgtype, aeron_frame_type, "Unknown");
1856 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1858 switch (msgtype)
1860 case HDR_TYPE_PAD:
1861 case HDR_TYPE_DATA:
1862 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1864 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1866 else
1868 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" PRIu32 ")",
1869 type_string, term_id, term_offset);
1871 break;
1872 case HDR_TYPE_SM:
1873 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1875 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1877 else
1879 if (finfo->stream_analysis->high.term_id == finfo->stream_analysis->completed.term_id)
1881 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%" PRIu32 "/%" PRIu32 " [%" PRIu32 "])",
1882 type_string, finfo->stream_analysis->high.term_offset, finfo->stream_analysis->completed.term_offset, finfo->stream_analysis->outstanding_bytes);
1884 else
1886 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" PRIu32 "/0x%08x:%" PRIu32 " [%" PRIu32 "])",
1887 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 break;
1893 else
1895 if ((msgtype == HDR_TYPE_SM) && ((flags & STATUS_FLAGS_SETUP) != 0))
1897 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-SETUP", type_string);
1899 else
1901 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", type_string);
1906 /*----------------------------------------------------------------------------*/
1907 /* Payload reassembly. */
1908 /*----------------------------------------------------------------------------*/
1909 struct aeron_msg_fragment_t_stct;
1910 typedef struct aeron_msg_fragment_t_stct aeron_msg_fragment_t;
1912 struct aeron_msg_t_stct
1914 wmem_list_t * fragment;
1915 aeron_term_t * term;
1916 tvbuff_t * reassembled_data;
1917 uint32_t first_fragment_term_offset;
1918 uint32_t next_expected_term_offset;
1919 uint32_t length; /* Total message payload length */
1920 uint32_t frame_length; /* Total length of all message frames accumulated */
1921 uint32_t fragment_count; /* Number of fragments in this message */
1922 uint32_t contiguous_length; /* Number of contiguous frame bytes accumulated for this message */
1923 uint32_t begin_frame; /* Data frame in which the B flag was set */
1924 uint32_t first_frame; /* Lowest-numbered frame which is part of this message */
1925 uint32_t end_frame; /* Data frame in which the E flag was set */
1926 uint32_t last_frame; /* Highest-numbered frame which is part of this message */
1927 bool complete;
1930 struct aeron_msg_fragment_t_stct
1932 char * data;
1933 uint32_t term_offset; /* Term offset for entire fragment */
1934 uint32_t frame_length; /* Length of entire frame/fragment */
1935 uint32_t data_length; /* Payload length */
1936 uint32_t frame; /* Frame in which the fragment resides */
1937 int frame_offset; /* Offset into the frame for the entire Aeron message */
1938 uint8_t flags; /* Frame data flags */
1941 static void aeron_msg_fragment_add(aeron_msg_t * msg, aeron_msg_fragment_t * fragment)
1943 /* Add the fragment to the message */
1944 wmem_list_append(msg->fragment, (void *) fragment);
1945 /* Update the message */
1946 msg->length += fragment->data_length;
1947 msg->contiguous_length += fragment->data_length;
1948 msg->fragment_count++;
1949 if (msg->first_frame > fragment->frame)
1951 msg->first_frame = fragment->frame;
1953 if (msg->last_frame < fragment->frame)
1955 msg->last_frame = fragment->frame;
1957 msg->next_expected_term_offset += fragment->frame_length;
1958 if ((fragment->flags & DATA_FLAGS_END) == DATA_FLAGS_END)
1960 uint8_t * buf;
1961 wmem_list_frame_t * lf;
1962 size_t ofs = 0;
1963 size_t accum_len = 0;
1964 uint32_t last_frame_offset = 0;
1965 bool last_frame_found = false;
1966 aeron_frame_info_t * finfo = NULL;
1968 msg->complete = true;
1969 msg->end_frame = fragment->frame;
1970 buf = (uint8_t *) wmem_alloc(wmem_file_scope(), (size_t) msg->length);
1971 lf = wmem_list_head(msg->fragment);
1972 while (lf != NULL)
1974 aeron_msg_fragment_t * cur_frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
1975 if (cur_frag != NULL)
1977 if (cur_frag->frame == msg->last_frame)
1979 last_frame_offset = cur_frag->frame_offset;
1980 last_frame_found = true;
1982 memcpy((void *) (buf + ofs), (void *) cur_frag->data, (size_t) cur_frag->data_length);
1983 ofs += (size_t) cur_frag->data_length;
1984 accum_len += (size_t) cur_frag->data_length;
1986 lf = wmem_list_frame_next(lf);
1988 DISSECTOR_ASSERT(accum_len == (size_t) msg->length);
1989 DISSECTOR_ASSERT(last_frame_found == true);
1990 if (last_frame_found)
1992 finfo = aeron_frame_info_find(msg->last_frame, last_frame_offset);
1994 msg->reassembled_data = tvb_new_real_data(buf, msg->length, msg->length);
1995 DISSECTOR_ASSERT(finfo != NULL);
1996 if (finfo != NULL)
1998 finfo->flags |= AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG;
1999 finfo->message = msg;
2004 static bool aeron_msg_process_orphan_fragments_msg_cb(const void *key _U_, void * value, void * userdata)
2006 aeron_msg_t * msg = (aeron_msg_t *) value;
2007 aeron_term_t * term = (aeron_term_t *) userdata;
2008 bool frag_found = false;
2009 wmem_list_frame_t * lf = NULL;
2010 aeron_msg_fragment_t * frag = NULL;
2012 if (msg->complete)
2014 /* This message is complete, no need to check for orphans */
2015 return false;
2017 /* Scan through the orphan fragments */
2018 while (true)
2020 lf = wmem_list_head(term->orphan_fragment);
2021 while (lf != NULL)
2023 frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2024 if (frag != NULL)
2026 if (msg->next_expected_term_offset == frag->term_offset)
2028 /* Found one! Remove it from the orphan list, and add it to the message */
2029 wmem_list_remove_frame(term->orphan_fragment, lf);
2030 aeron_msg_fragment_add(msg, frag);
2031 frag_found = true;
2032 break;
2035 lf = wmem_list_frame_next(lf);
2037 if (!frag_found)
2039 break;
2041 frag_found = false;
2043 return false;
2046 static void aeron_msg_process_orphan_fragments(aeron_term_t * term)
2048 /* If we have no orphan fragments to process, nothing to do. */
2049 if (wmem_list_count(term->orphan_fragment) == 0)
2051 return;
2053 wmem_tree_foreach(term->message, aeron_msg_process_orphan_fragments_msg_cb, (void *) term);
2056 static aeron_msg_fragment_t * aeron_msg_fragment_create(tvbuff_t * tvb, int offset, packet_info * pinfo, aeron_packet_info_t * info)
2058 aeron_msg_fragment_t * frag;
2060 frag = wmem_new0(wmem_file_scope(), aeron_msg_fragment_t);
2061 frag->term_offset = info->term_offset;
2062 frag->frame_length = info->length;
2063 frag->data_length = info->data_length;
2064 frag->frame = pinfo->num;
2065 frag->frame_offset = offset;
2066 frag->data = (char *) tvb_memdup(wmem_file_scope(), tvb, frag->frame_offset + O_AERON_DATA_DATA, (size_t) frag->data_length);
2067 frag->flags = info->flags;
2068 return (frag);
2071 static aeron_msg_fragment_t * aeron_msg_fragment_find(aeron_msg_t * message, aeron_packet_info_t * info)
2073 aeron_msg_fragment_t * frag = NULL;
2074 wmem_list_frame_t * lf;
2076 if (message->next_expected_term_offset < info->term_offset)
2078 return (NULL);
2080 lf = wmem_list_head(message->fragment);
2081 while (lf != NULL)
2083 frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2084 if (frag != NULL)
2086 if (frag->term_offset == info->term_offset)
2088 break;
2091 lf = wmem_list_frame_next(lf);
2093 return (frag);
2096 static aeron_msg_t * aeron_term_msg_find_le(aeron_term_t * term, uint32_t term_offset)
2098 /* Return the last aeron_msg_t with starting_fragment_term_offset <= offset */
2099 aeron_msg_t * msg = (aeron_msg_t *) wmem_tree_lookup32_le(term->message, term_offset);
2100 return (msg);
2103 static aeron_msg_t * aeron_term_msg_add(aeron_term_t * term, packet_info * pinfo, aeron_packet_info_t * info)
2105 aeron_msg_t * pos;
2106 aeron_msg_t * msg;
2108 pos = aeron_term_msg_find_le(term, info->term_offset);
2109 if ((pos != NULL) && (pos->first_fragment_term_offset == info->term_offset))
2111 return (pos);
2113 msg = wmem_new0(wmem_file_scope(), aeron_msg_t);
2114 msg->fragment = wmem_list_new(wmem_file_scope());
2115 msg->term = term;
2116 msg->reassembled_data = NULL;
2117 msg->first_fragment_term_offset = info->term_offset;
2118 msg->next_expected_term_offset = info->term_offset;
2119 msg->length = 0;
2120 msg->frame_length = 0;
2121 msg->fragment_count = 0;
2122 msg->contiguous_length = 0;
2123 msg->begin_frame = pinfo->num;
2124 msg->first_frame = pinfo->num;
2125 msg->end_frame = 0;
2126 msg->last_frame = 0;
2127 msg->complete = false;
2128 wmem_tree_insert32(term->message, msg->first_fragment_term_offset, (void *) msg);
2129 return (msg);
2132 static void aeron_msg_process(tvbuff_t * tvb, int offset, packet_info * pinfo, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo _U_)
2134 if (aeron_reassemble_fragments && (PINFO_FD_VISITED(pinfo) == 0))
2136 if ((info->flags & DATA_FLAGS_COMPLETE) != DATA_FLAGS_COMPLETE)
2138 aeron_stream_t * stream = aeron_transport_stream_find(transport, info->stream_id);
2139 if (stream != NULL)
2141 aeron_term_t * term = aeron_stream_term_find(stream, info->term_id);
2142 if (term != NULL)
2144 aeron_msg_t * msg = NULL;
2145 aeron_msg_fragment_t * frag = NULL;
2147 if ((info->flags & DATA_FLAGS_BEGIN) == DATA_FLAGS_BEGIN)
2149 /* Beginning of a message. First see if this message already exists. */
2150 msg = aeron_term_msg_find_le(term, info->term_offset);
2151 if (msg != NULL)
2153 if (msg->first_fragment_term_offset != info->term_offset)
2156 A message start with a term offset:
2157 1) Between two existing messages for this term, or
2158 2) Less than the first message for this term
2159 Likely this was caused by an RX or out-of-order packet. Need to create a new one.
2161 msg = NULL;
2164 if (msg == NULL)
2166 msg = aeron_term_msg_add(term, pinfo, info);
2169 else
2171 /* End of message, or middle of message. See if we already have a message with a smaller starting term offset */
2172 msg = aeron_term_msg_find_le(term, info->term_offset);
2173 if (msg != NULL)
2175 /* Is this the next expected term offset? */
2176 if (msg->next_expected_term_offset == info->term_offset)
2178 /* Yes - we can add the fragment to the message */
2180 else
2182 /* Do we already have this fragment? */
2183 frag = aeron_msg_fragment_find(msg, info);
2184 if (frag != NULL)
2186 /* Already have it, so nothing to do */
2187 return;
2189 else
2191 /* Not the next fragment, so no known message associated with it. */
2192 msg = NULL;
2197 /* Create the fragment */
2198 frag = aeron_msg_fragment_create(tvb, offset, pinfo, info);
2199 if (msg == NULL)
2201 /* Add the fragment to the list of orphaned fragments */
2202 wmem_list_append(term->orphan_fragment, (void *) frag);
2204 else
2206 /* Add the fragment to the message */
2207 aeron_msg_fragment_add(msg, frag);
2209 /* Process the orphan list */
2210 aeron_msg_process_orphan_fragments(term);
2217 /*----------------------------------------------------------------------------*/
2218 /* Aeron pad message packet dissection functions. */
2219 /*----------------------------------------------------------------------------*/
2220 static int dissect_aeron_pad(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2222 proto_tree * subtree;
2223 proto_item * pad_item;
2224 proto_item * channel_item;
2225 proto_item * frame_length_item;
2226 uint32_t frame_length;
2227 uint32_t pad_length;
2228 aeron_transport_t * transport;
2229 uint32_t session_id;
2230 uint32_t stream_id;
2231 uint32_t term_id;
2232 uint32_t term_offset;
2233 int rounded_length;
2234 aeron_packet_info_t pktinfo;
2236 frame_length = tvb_get_letohl(tvb, offset + O_AERON_PAD_FRAME_LENGTH);
2237 rounded_length = (int) aeron_pos_roundup(frame_length);
2238 if (rounded_length < 0)
2239 return 0;
2240 term_offset = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_OFFSET);
2241 session_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_SESSION_ID);
2242 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2243 stream_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_STREAM_ID);
2244 term_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_ID);
2245 pad_length = frame_length - L_AERON_PAD_MIN;
2246 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2247 pktinfo.stream_id = stream_id;
2248 pktinfo.term_id = term_id;
2249 pktinfo.term_offset = term_offset;
2250 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2251 pktinfo.length = frame_length;
2252 pktinfo.data_length = pad_length;
2253 pktinfo.type = HDR_TYPE_PAD;
2254 pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_PAD_FLAGS);
2255 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2256 return 0;
2258 aeron_info_stream_progress_report(pinfo, HDR_TYPE_PAD, pktinfo.flags, term_id, term_offset, finfo);
2259 pad_item = proto_tree_add_none_format(tree, hf_aeron_pad, tvb, offset, -1, "Pad Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2260 term_id, term_offset, frame_length, rounded_length);
2261 subtree = proto_item_add_subtree(pad_item, ett_aeron_pad);
2262 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2263 proto_item_set_generated(channel_item);
2264 frame_length_item = proto_tree_add_item(subtree, hf_aeron_pad_frame_length, tvb, offset + O_AERON_PAD_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2265 proto_tree_add_item(subtree, hf_aeron_pad_version, tvb, offset + O_AERON_PAD_VERSION, 1, ENC_LITTLE_ENDIAN);
2266 proto_tree_add_item(subtree, hf_aeron_pad_flags, tvb, offset + O_AERON_PAD_FLAGS, 1, ENC_LITTLE_ENDIAN);
2267 proto_tree_add_item(subtree, hf_aeron_pad_type, tvb, offset + O_AERON_PAD_TYPE, 2, ENC_LITTLE_ENDIAN);
2268 proto_tree_add_item(subtree, hf_aeron_pad_term_offset, tvb, offset + O_AERON_PAD_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2269 aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, (uint32_t) rounded_length);
2270 proto_tree_add_item(subtree, hf_aeron_pad_session_id, tvb, offset + O_AERON_PAD_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2271 proto_tree_add_item(subtree, hf_aeron_pad_stream_id, tvb, offset + O_AERON_PAD_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2272 proto_tree_add_item(subtree, hf_aeron_pad_term_id, tvb, offset + O_AERON_PAD_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2273 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2274 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2275 proto_item_set_len(pad_item, rounded_length);
2276 if (frame_length < L_AERON_PAD_MIN)
2278 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_pad_length);
2279 return (-rounded_length);
2281 return (rounded_length);
2284 /*----------------------------------------------------------------------------*/
2285 /* Aeron data message packet dissection functions. */
2286 /*----------------------------------------------------------------------------*/
2287 static void dissect_aeron_reassembled_data(packet_info * pinfo, proto_tree * tree, aeron_frame_info_t * finfo)
2289 proto_item * frag_item;
2290 proto_tree * frag_tree;
2291 aeron_msg_t * msg;
2292 wmem_list_frame_t * lf;
2293 bool first_item = true;
2294 uint32_t msg_ofs = 0;
2296 if (finfo->message == NULL)
2298 return;
2300 msg = finfo->message;
2301 add_new_data_source(pinfo, msg->reassembled_data, "Reassembled Data");
2302 frag_item = proto_tree_add_none_format(tree,
2303 hf_aeron_data_reassembly,
2304 msg->reassembled_data,
2306 tvb_reported_length_remaining(msg->reassembled_data, 0),
2307 "%" PRIu32 " Reassembled Fragments (%" PRIu32 " bytes):",
2308 msg->fragment_count,
2309 msg->length);
2310 frag_tree = proto_item_add_subtree(frag_item, ett_aeron_data_reassembly);
2311 lf = wmem_list_head(msg->fragment);
2312 while (lf != NULL)
2314 aeron_msg_fragment_t * frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2315 if (frag != NULL)
2317 proto_item * pi;
2318 pi = proto_tree_add_uint_format_value(frag_tree,
2319 hf_aeron_data_reassembly_fragment,
2320 msg->reassembled_data,
2321 msg_ofs,
2322 frag->data_length,
2323 frag->frame,
2324 "Frame: %" PRIu32 ", payload: %" PRIu32 "-%" PRIu32 " (%" PRIu32 " bytes)",
2325 frag->frame,
2326 msg_ofs,
2327 (msg_ofs + frag->data_length) - 1,
2328 frag->data_length);
2329 proto_item_set_generated(pi);
2330 if (first_item)
2332 proto_item_append_text(frag_item, " #%" PRIu32 "(%" PRIu32 ")", frag->frame, frag->data_length);
2334 else
2336 proto_item_append_text(frag_item, ", #%" PRIu32 "(%" PRIu32 ")", frag->frame, frag->data_length);
2338 msg_ofs += frag->data_length;
2339 first_item = false;
2341 lf = wmem_list_frame_next(lf);
2343 proto_item_set_generated(frag_item);
2346 static int dissect_aeron_data(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2348 proto_tree * subtree;
2349 proto_item * data_item;
2350 proto_item * channel_item;
2351 proto_item * frame_length_item;
2352 uint32_t frame_length;
2353 static int * const flags[] =
2355 &hf_aeron_data_flags_b,
2356 &hf_aeron_data_flags_e,
2357 &hf_aeron_data_flags_s,
2358 NULL
2360 aeron_transport_t * transport;
2361 uint32_t session_id;
2362 uint32_t stream_id;
2363 uint32_t term_id;
2364 uint32_t term_offset;
2365 uint32_t data_length;
2366 int rounded_length = 0;
2367 aeron_packet_info_t pktinfo;
2368 uint32_t offset_increment = 0;
2370 frame_length = tvb_get_letohl(tvb, offset + O_AERON_DATA_FRAME_LENGTH);
2371 if (frame_length == 0)
2373 rounded_length = O_AERON_DATA_DATA;
2374 data_length = 0;
2375 offset_increment = 0;
2377 else
2379 offset_increment = aeron_pos_roundup(frame_length);
2380 rounded_length = (int) offset_increment;
2381 if (rounded_length < 0)
2382 return 0;
2383 data_length = frame_length - O_AERON_DATA_DATA;
2385 term_offset = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_OFFSET);
2386 session_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_SESSION_ID);
2387 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2388 stream_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_STREAM_ID);
2389 term_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_ID);
2390 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2391 pktinfo.stream_id = stream_id;
2392 pktinfo.term_id = term_id;
2393 pktinfo.term_offset = term_offset;
2394 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2395 pktinfo.length = frame_length;
2396 pktinfo.data_length = data_length;
2397 pktinfo.type = HDR_TYPE_DATA;
2398 pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_DATA_FLAGS);
2399 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2400 return 0;
2402 aeron_info_stream_progress_report(pinfo, HDR_TYPE_DATA, pktinfo.flags, term_id, term_offset, finfo);
2403 data_item = proto_tree_add_none_format(tree, hf_aeron_data, tvb, offset, -1, "Data Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2404 (uint32_t) term_id, term_offset, frame_length, rounded_length);
2405 subtree = proto_item_add_subtree(data_item, ett_aeron_data);
2406 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2407 proto_item_set_generated(channel_item);
2408 frame_length_item = proto_tree_add_item(subtree, hf_aeron_data_frame_length, tvb, offset + O_AERON_DATA_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2409 proto_tree_add_item(subtree, hf_aeron_data_version, tvb, offset + O_AERON_DATA_VERSION, 1, ENC_LITTLE_ENDIAN);
2410 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_DATA_FLAGS, hf_aeron_data_flags, ett_aeron_data_flags, flags, ENC_LITTLE_ENDIAN);
2411 proto_tree_add_item(subtree, hf_aeron_data_type, tvb, offset + O_AERON_DATA_TYPE, 2, ENC_LITTLE_ENDIAN);
2412 proto_tree_add_item(subtree, hf_aeron_data_term_offset, tvb, offset + O_AERON_DATA_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2413 aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, offset_increment);
2414 proto_tree_add_item(subtree, hf_aeron_data_session_id, tvb, offset + O_AERON_DATA_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2415 proto_tree_add_item(subtree, hf_aeron_data_stream_id, tvb, offset + O_AERON_DATA_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2416 proto_tree_add_item(subtree, hf_aeron_data_term_id, tvb, offset + O_AERON_DATA_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2417 proto_tree_add_item(subtree, hf_aeron_data_reserved_value, tvb, offset + O_AERON_DATA_RESERVED_VALUE, 8, ENC_LITTLE_ENDIAN);
2418 if (data_length > 0)
2420 tvbuff_t * data_tvb = NULL;
2421 bool can_call_subdissector = false;
2422 bool dissector_found = false;
2423 heur_dtbl_entry_t * hdtbl_entry;
2425 aeron_msg_process(tvb, offset, pinfo, transport, &pktinfo, finfo);
2426 if ((pktinfo.flags & DATA_FLAGS_COMPLETE) == DATA_FLAGS_COMPLETE)
2428 can_call_subdissector = true;
2430 if (finfo != NULL)
2432 if ((finfo->flags & AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG) != 0)
2434 dissect_aeron_reassembled_data(pinfo, subtree, finfo);
2435 data_tvb = finfo->message->reassembled_data;
2436 can_call_subdissector = true;
2438 else
2440 data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2443 else
2445 data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2447 if (can_call_subdissector && aeron_use_heuristic_subdissectors)
2449 dissector_found = dissector_try_heuristic(aeron_heuristic_subdissector_list, data_tvb, pinfo, subtree, &hdtbl_entry, NULL);
2451 if (!dissector_found)
2453 call_data_dissector(data_tvb, pinfo, subtree);
2456 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2457 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2458 proto_item_set_len(data_item, rounded_length);
2459 if ((frame_length != 0) && (frame_length < L_AERON_DATA_MIN))
2461 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_data_length);
2462 return (-rounded_length);
2464 return (rounded_length);
2467 /*----------------------------------------------------------------------------*/
2468 /* Aeron NAK packet dissection functions. */
2469 /*----------------------------------------------------------------------------*/
2470 static int dissect_aeron_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2472 proto_tree * subtree;
2473 proto_item * nak_item;
2474 proto_item * frame_length_item;
2475 proto_item * channel_item;
2476 proto_item * nak_offset_item;
2477 uint32_t frame_length;
2478 aeron_transport_t * transport;
2479 uint32_t session_id;
2480 uint32_t stream_id;
2481 uint32_t term_id;
2482 uint32_t nak_term_offset;
2483 uint32_t nak_length;
2484 int rounded_length;
2485 aeron_packet_info_t pktinfo;
2487 frame_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_FRAME_LENGTH);
2488 rounded_length = (int)frame_length;
2489 if (rounded_length < 0)
2490 return 0;
2491 session_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_SESSION_ID);
2492 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2493 stream_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_STREAM_ID);
2494 term_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_ID);
2495 nak_term_offset = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_OFFSET);
2496 nak_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_LENGTH);
2497 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2498 pktinfo.stream_id = stream_id;
2499 pktinfo.term_id = term_id;
2500 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2501 pktinfo.nak_term_offset = nak_term_offset;
2502 pktinfo.nak_length = nak_length;
2503 pktinfo.type = HDR_TYPE_NAK;
2504 pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_NAK_FLAGS);
2505 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2506 return 0;
2508 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "NAK");
2509 nak_item = proto_tree_add_none_format(tree, hf_aeron_nak, tvb, offset, -1, "NAK Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32,
2510 term_id, nak_term_offset, nak_length);
2511 subtree = proto_item_add_subtree(nak_item, ett_aeron_nak);
2512 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2513 proto_item_set_generated(channel_item);
2514 frame_length_item = proto_tree_add_item(subtree, hf_aeron_nak_frame_length, tvb, offset + O_AERON_NAK_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2515 proto_tree_add_item(subtree, hf_aeron_nak_version, tvb, offset + O_AERON_NAK_VERSION, 1, ENC_LITTLE_ENDIAN);
2516 proto_tree_add_item(subtree, hf_aeron_nak_flags, tvb, offset + O_AERON_NAK_FLAGS, 1, ENC_LITTLE_ENDIAN);
2517 proto_tree_add_item(subtree, hf_aeron_nak_type, tvb, offset + O_AERON_NAK_TYPE, 2, ENC_LITTLE_ENDIAN);
2518 proto_tree_add_item(subtree, hf_aeron_nak_session_id, tvb, offset + O_AERON_NAK_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2519 proto_tree_add_item(subtree, hf_aeron_nak_stream_id, tvb, offset + O_AERON_NAK_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2520 proto_tree_add_item(subtree, hf_aeron_nak_term_id, tvb, offset + O_AERON_NAK_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2521 nak_offset_item = proto_tree_add_item(subtree, hf_aeron_nak_term_offset, tvb, offset + O_AERON_NAK_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2522 proto_tree_add_item(subtree, hf_aeron_nak_length, tvb, offset + O_AERON_NAK_LENGTH, 4, ENC_LITTLE_ENDIAN);
2523 expert_add_info_format(pinfo, nak_offset_item, &ei_aeron_analysis_nak, "NAK offset %" PRIu32 " length %" PRIu32, nak_term_offset, nak_length);
2524 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2525 proto_item_set_len(nak_item, rounded_length);
2526 if (frame_length != L_AERON_NAK)
2528 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_nak_length);
2529 return (-rounded_length);
2531 return (rounded_length);
2534 /*----------------------------------------------------------------------------*/
2535 /* Aeron status message packet dissection functions. */
2536 /*----------------------------------------------------------------------------*/
2537 static void aeron_window_resize_report(packet_info * pinfo, proto_item * item, aeron_frame_info_t * finfo)
2539 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
2541 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE) != 0)
2543 expert_add_info(pinfo, item, &ei_aeron_analysis_window_resize);
2548 static int dissect_aeron_sm(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2550 proto_tree * subtree;
2551 proto_item * sm_item;
2552 proto_item * frame_length_item;
2553 proto_item * item;
2554 proto_item * rcv_window_item;
2555 uint32_t frame_length;
2556 static int * const flags[] =
2558 &hf_aeron_sm_flags_s,
2559 NULL
2561 uint32_t feedback_length;
2562 aeron_transport_t * transport;
2563 uint32_t session_id;
2564 uint32_t stream_id;
2565 uint32_t term_id;
2566 uint32_t consumption_offset;
2567 uint32_t rcv_window;
2568 uint64_t rcv_id;
2569 int rounded_length;
2570 aeron_packet_info_t pktinfo;
2572 frame_length = tvb_get_letohl(tvb, offset + O_AERON_SM_FRAME_LENGTH);
2573 feedback_length = frame_length - O_AERON_SM_FEEDBACK;
2574 rounded_length = (int) frame_length;
2575 if (rounded_length < 0)
2576 return 0;
2577 session_id = tvb_get_letohl(tvb, offset + O_AERON_SM_SESSION_ID);
2578 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2579 stream_id = tvb_get_letohl(tvb, offset + O_AERON_SM_STREAM_ID);
2580 term_id = tvb_get_letohl(tvb, offset + O_AERON_SM_TERM_ID);
2581 consumption_offset = tvb_get_letohl(tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET);
2582 rcv_window = tvb_get_letohl(tvb, offset + O_AERON_SM_RECEIVER_WINDOW);
2583 rcv_id = tvb_get_letoh64(tvb, offset + O_AERON_SM_RECEIVER_ID);
2584 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2585 pktinfo.stream_id = stream_id;
2586 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID;
2587 pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_SM_FLAGS);
2588 if ((pktinfo.flags & STATUS_FLAGS_SETUP) == 0)
2590 pktinfo.term_id = term_id;
2591 pktinfo.term_offset = consumption_offset;
2592 pktinfo.info_flags |= (AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID);
2593 pktinfo.receiver_window = rcv_window;
2594 pktinfo.receiver_id = rcv_id;
2596 else
2598 pktinfo.term_id = 0;
2599 pktinfo.term_offset = 0;
2600 pktinfo.receiver_window = 0;
2601 pktinfo.receiver_id = 0;
2603 pktinfo.length = 0;
2604 pktinfo.data_length = 0;
2605 pktinfo.type = HDR_TYPE_SM;
2606 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2607 return 0;
2609 aeron_info_stream_progress_report(pinfo, HDR_TYPE_SM, pktinfo.flags, term_id, consumption_offset, finfo);
2610 sm_item = proto_tree_add_none_format(tree, hf_aeron_sm, tvb, offset, -1, "Status Message: Term 0x%x, ConsumptionOfs %" PRIu32 ", RcvWindow %" PRIu32 ", RcvID %" PRIu64,
2611 term_id, consumption_offset, rcv_window, rcv_id);
2612 subtree = proto_item_add_subtree(sm_item, ett_aeron_sm);
2613 item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2614 proto_item_set_generated(item);
2615 frame_length_item = proto_tree_add_item(subtree, hf_aeron_sm_frame_length, tvb, offset + O_AERON_SM_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2616 proto_tree_add_item(subtree, hf_aeron_sm_version, tvb, offset + O_AERON_SM_VERSION, 1, ENC_LITTLE_ENDIAN);
2617 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_SM_FLAGS, hf_aeron_sm_flags, ett_aeron_sm_flags, flags, ENC_LITTLE_ENDIAN);
2618 proto_tree_add_item(subtree, hf_aeron_sm_type, tvb, offset + O_AERON_SM_TYPE, 2, ENC_LITTLE_ENDIAN);
2619 proto_tree_add_item(subtree, hf_aeron_sm_session_id, tvb, offset + O_AERON_SM_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2620 proto_tree_add_item(subtree, hf_aeron_sm_stream_id, tvb, offset + O_AERON_SM_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2621 proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_id, tvb, offset + O_AERON_SM_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2622 proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_offset, tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2623 rcv_window_item = proto_tree_add_item(subtree, hf_aeron_sm_receiver_window, tvb, offset + O_AERON_SM_RECEIVER_WINDOW, 4, ENC_LITTLE_ENDIAN);
2624 aeron_window_resize_report(pinfo, rcv_window_item, finfo);
2625 proto_tree_add_item(subtree, hf_aeron_sm_receiver_id, tvb, offset + O_AERON_SM_RECEIVER_ID, 8, ENC_LITTLE_ENDIAN);
2626 if (feedback_length > 0)
2628 proto_tree_add_item(subtree, hf_aeron_sm_feedback, tvb, offset + O_AERON_SM_FEEDBACK, feedback_length, ENC_NA);
2630 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2631 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2632 proto_item_set_len(sm_item, rounded_length);
2633 if (frame_length < L_AERON_SM_MIN)
2635 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_sm_length);
2636 return (-rounded_length);
2638 return (rounded_length);
2641 /*----------------------------------------------------------------------------*/
2642 /* Aeron error packet dissection functions. */
2643 /*----------------------------------------------------------------------------*/
2644 static int dissect_aeron_err(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree)
2646 proto_tree * subtree;
2647 proto_item * err_item;
2648 proto_item * frame_length_item;
2649 int rounded_length;
2650 uint32_t bad_frame_length;
2651 int string_length;
2652 uint32_t frame_length;
2653 int ofs;
2655 frame_length = tvb_get_letohl(tvb, offset + O_AERON_ERR_FRAME_LENGTH);
2656 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Error");
2657 err_item = proto_tree_add_item(tree, hf_aeron_err, tvb, offset, -1, ENC_NA);
2658 subtree = proto_item_add_subtree(err_item, ett_aeron_err);
2659 frame_length_item = proto_tree_add_item(subtree, hf_aeron_err_frame_length, tvb, offset + O_AERON_ERR_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2660 proto_tree_add_item(subtree, hf_aeron_err_version, tvb, offset + O_AERON_ERR_VERSION, 1, ENC_LITTLE_ENDIAN);
2661 proto_tree_add_item(subtree, hf_aeron_err_code, tvb, offset + O_AERON_ERR_CODE, 1, ENC_LITTLE_ENDIAN);
2662 proto_tree_add_item(subtree, hf_aeron_err_type, tvb, offset + O_AERON_ERR_TYPE, 2, ENC_LITTLE_ENDIAN);
2663 proto_tree_add_item(subtree, hf_aeron_err_off_frame_length, tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2664 bad_frame_length = tvb_get_letohl(tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH);
2665 ofs = offset + O_AERON_ERR_OFFENDING_HEADER;
2666 proto_tree_add_item(subtree, hf_aeron_err_off_hdr, tvb, offset + ofs, bad_frame_length, ENC_NA);
2667 ofs += bad_frame_length;
2668 string_length = frame_length - ofs;
2669 if (string_length > 0)
2671 proto_tree_add_item(subtree, hf_aeron_err_string, tvb, offset + ofs, string_length, ENC_ASCII);
2673 rounded_length = (int) frame_length;
2674 if (rounded_length < 0)
2675 return 0;
2676 proto_item_set_len(err_item, rounded_length);
2677 if (frame_length < L_AERON_ERR_MIN)
2679 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_err_length);
2680 return (-rounded_length);
2682 return (rounded_length);
2685 /*----------------------------------------------------------------------------*/
2686 /* Aeron heartbeat packet dissection functions. (Data frame also) */
2687 /*----------------------------------------------------------------------------*/
2688 static int dissect_aeron_heartbeat(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2690 proto_tree * subtree;
2691 proto_item * data_item;
2692 proto_item * channel_item;
2693 proto_item * frame_length_item;
2694 uint32_t frame_length;
2695 static int * const flags[] =
2697 &hf_aeron_heartbeat_flags_b,
2698 &hf_aeron_heartbeat_flags_e,
2699 NULL
2701 aeron_transport_t * transport;
2702 uint32_t term_offset;
2703 uint32_t session_id;
2704 uint32_t stream_id;
2705 uint32_t term_id;
2707 int rounded_length = 24;
2708 aeron_packet_info_t pktinfo;
2710 frame_length = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_FRAME_LENGTH);
2711 term_offset = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_TERM_OFFSET);
2712 session_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_SESSION_ID);
2713 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2714 stream_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_STREAM_ID);
2715 term_id = tvb_get_letohl(tvb, offset + O_AERON_HEAERTBEAT_TERM_ID);
2716 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2717 pktinfo.stream_id = stream_id;
2718 pktinfo.term_id = term_id;
2719 pktinfo.term_offset = term_offset;
2720 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2721 pktinfo.length = frame_length;
2722 pktinfo.data_length = 0;
2723 pktinfo.type = HDR_TYPE_DATA;
2724 pktinfo.flags = tvb_get_uint8(tvb, offset + O_AERON_HEAERTBEAT_FLAGS);
2725 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2726 return 0;
2728 aeron_info_stream_progress_report(pinfo, HDR_TYPE_DATA, pktinfo.flags, term_id, term_offset, finfo);
2729 data_item = proto_tree_add_none_format(tree, hf_aeron_heartbeat, tvb, offset, -1, "Heartbeat Frame: Term 0x%x, Ofs %" PRIu32 ", Len %" PRIu32 "(%d)",
2730 (uint32_t) term_id, term_offset, frame_length, rounded_length);
2731 subtree = proto_item_add_subtree(data_item, ett_aeron_data);
2732 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2733 proto_item_set_generated(channel_item);
2734 frame_length_item = proto_tree_add_item(subtree, hf_aeron_heartbeat_frame_length, tvb, offset + O_AERON_HEAERTBEAT_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2735 proto_tree_add_item(subtree, hf_aeron_heartbeat_version, tvb, offset + O_AERON_HEAERTBEAT_VERSION, 1, ENC_LITTLE_ENDIAN);
2736 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_HEAERTBEAT_FLAGS, hf_aeron_heartbeat_flags, ett_aeron_data_flags, flags, ENC_LITTLE_ENDIAN);
2737 proto_tree_add_item(subtree, hf_aeron_heartbeat_type, tvb, offset + O_AERON_HEAERTBEAT_TYPE, 2, ENC_LITTLE_ENDIAN);
2738 proto_tree_add_item(subtree, hf_aeron_heartbeat_term_offset, tvb, offset + O_AERON_HEAERTBEAT_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2739 proto_tree_add_item(subtree, hf_aeron_heartbeat_session_id, tvb, offset + O_AERON_HEAERTBEAT_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2740 proto_tree_add_item(subtree, hf_aeron_heartbeat_stream_id, tvb, offset + O_AERON_HEAERTBEAT_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2741 proto_tree_add_item(subtree, hf_aeron_heartbeat_term_id, tvb, offset + O_AERON_HEAERTBEAT_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2743 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2744 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2745 proto_item_set_len(data_item, rounded_length);
2746 if (frame_length != 0)
2748 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_data_length);
2749 return (-rounded_length);
2751 return (rounded_length);
2754 /*----------------------------------------------------------------------------*/
2755 /* Aeron rtt message packet dissection functions. */
2756 /*----------------------------------------------------------------------------*/
2757 static int dissect_aeron_rtt(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2759 proto_tree * subtree;
2760 proto_item * rtt_item;
2761 proto_item * frame_length_item;
2762 proto_item * item;
2763 uint32_t frame_length;
2764 static int * const flags[] =
2766 &hf_aeron_rtt_flags_r,
2767 NULL
2769 aeron_transport_t * transport;
2770 uint32_t session_id;
2771 uint32_t stream_id;
2772 uint64_t rcv_id;
2773 int rounded_length;
2775 frame_length = tvb_get_letohl(tvb, offset + O_AERON_RTT_FRAME_LENGTH);
2776 rounded_length = (int)frame_length;
2777 if (rounded_length < 0)
2778 return 0;
2779 session_id = tvb_get_letohl(tvb, offset + O_AERON_RTT_SESSION_ID);
2780 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2781 stream_id = tvb_get_letohl(tvb, offset + O_AERON_RTT_STREAM_ID);
2782 rcv_id = tvb_get_letoh64(tvb, offset + O_AERON_RTT_RECEIVER_ID);
2784 rtt_item = proto_tree_add_none_format(tree, hf_aeron_rtt, tvb, offset, -1, "RTT Message: Stream ID %" PRIu32 ", RcvID %" PRIu64,
2785 stream_id, rcv_id);
2786 subtree = proto_item_add_subtree(rtt_item, ett_aeron_rtt);
2787 item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2788 proto_item_set_generated(item);
2789 frame_length_item = proto_tree_add_item(subtree, hf_aeron_rtt_frame_length, tvb, offset + O_AERON_RTT_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2790 proto_tree_add_item(subtree, hf_aeron_rtt_version, tvb, offset + O_AERON_RTT_VERSION, 1, ENC_LITTLE_ENDIAN);
2791 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_RTT_FLAGS, hf_aeron_rtt_flags, ett_aeron_rtt_flags, flags, ENC_LITTLE_ENDIAN);
2792 proto_tree_add_item(subtree, hf_aeron_rtt_type, tvb, offset + O_AERON_RTT_TYPE, 2, ENC_LITTLE_ENDIAN);
2793 proto_tree_add_item(subtree, hf_aeron_rtt_session_id, tvb, offset + O_AERON_RTT_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2794 proto_tree_add_item(subtree, hf_aeron_rtt_stream_id, tvb, offset + O_AERON_RTT_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2795 proto_tree_add_item(subtree, hf_aeron_rtt_echo_timestamp, tvb, offset + O_AERON_RTT_ECHO_TIMESTAMP, 8, ENC_LITTLE_ENDIAN);
2796 proto_tree_add_item(subtree, hf_aeron_rtt_reception_delta, tvb, offset + O_AERON_RTT_RECEPTION_DELTA, 8, ENC_LITTLE_ENDIAN);
2797 proto_tree_add_item(subtree, hf_aeron_rtt_receiver_id, tvb, offset + O_AERON_RTT_RECEIVER_ID, 8, ENC_LITTLE_ENDIAN);
2799 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2800 proto_item_set_len(rtt_item, rounded_length);
2801 if (frame_length != L_AERON_RTT)
2803 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_rtt_length);
2804 return (-rounded_length);
2806 return (rounded_length);
2809 /*----------------------------------------------------------------------------*/
2810 /* Aeron setup packet dissection functions. */
2811 /*----------------------------------------------------------------------------*/
2812 static void aeron_set_stream_mtu_ttl_term_length(packet_info * pinfo, aeron_transport_t * transport, uint32_t stream_id, uint32_t mtu, uint32_t ttl, uint32_t term_length)
2814 if (PINFO_FD_VISITED(pinfo) == 0)
2816 aeron_stream_t * stream = aeron_transport_stream_find(transport, stream_id);
2817 if (stream != NULL)
2819 stream->term_length = term_length;
2820 stream->mtu = mtu;
2821 stream->ttl = ttl;
2826 static int dissect_aeron_setup(tvbuff_t * tvb, int offset, packet_info * pinfo, proto_tree * tree, aeron_conversation_info_t * cinfo, aeron_frame_info_t * finfo)
2828 proto_tree * subtree;
2829 proto_item * setup_item;
2830 proto_item * frame_length_item;
2831 uint32_t frame_length;
2832 proto_item * channel_item;
2833 aeron_transport_t * transport;
2834 uint32_t session_id;
2835 uint32_t stream_id;
2836 uint32_t active_term_id;
2837 uint32_t initial_term_id;
2838 uint32_t term_offset;
2839 uint32_t term_length;
2840 uint32_t mtu;
2841 uint32_t ttl;
2842 int rounded_length;
2843 aeron_packet_info_t pktinfo;
2845 frame_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_FRAME_LENGTH);
2846 rounded_length = (int) frame_length;
2847 if (rounded_length < 0)
2848 return 0;
2849 term_offset = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_OFFSET);
2850 session_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_SESSION_ID);
2851 transport = aeron_transport_add(cinfo, session_id, pinfo->num);
2852 stream_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_STREAM_ID);
2853 initial_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID);
2854 active_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID);
2855 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2856 pktinfo.stream_id = stream_id;
2857 pktinfo.term_id = active_term_id;
2858 pktinfo.term_offset = 0;
2859 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2860 pktinfo.length = 0;
2861 pktinfo.data_length = 0;
2862 pktinfo.receiver_window = 0;
2863 pktinfo.type = HDR_TYPE_SETUP;
2864 pktinfo.flags = 0;
2865 if (aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo) < 0)
2866 return 0;
2867 term_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_LENGTH);
2868 mtu = tvb_get_letohl(tvb, offset + O_AERON_SETUP_MTU);
2869 ttl = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TTL);
2870 aeron_set_stream_mtu_ttl_term_length(pinfo, transport, stream_id, mtu, ttl, term_length);
2872 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Setup");
2873 setup_item = proto_tree_add_none_format(tree, hf_aeron_setup, tvb, offset, -1,
2874 "Setup Frame: InitTerm 0x%x, ActiveTerm 0x%x, TermLen %" PRIu32 ", Ofs %" PRIu32 ", MTU %" PRIu32 ", TTL %" PRIu32,
2875 initial_term_id, (uint32_t) active_term_id, term_length, term_offset, mtu, ttl);
2876 subtree = proto_item_add_subtree(setup_item, ett_aeron_setup);
2877 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2878 proto_item_set_generated(channel_item);
2879 frame_length_item = proto_tree_add_item(subtree, hf_aeron_setup_frame_length, tvb, offset + O_AERON_SETUP_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2880 proto_tree_add_item(subtree, hf_aeron_setup_version, tvb, offset + O_AERON_SETUP_VERSION, 1, ENC_LITTLE_ENDIAN);
2881 proto_tree_add_item(subtree, hf_aeron_setup_flags, tvb, offset + O_AERON_SETUP_FLAGS, 1, ENC_LITTLE_ENDIAN);
2882 proto_tree_add_item(subtree, hf_aeron_setup_type, tvb, offset + O_AERON_SETUP_TYPE, 2, ENC_LITTLE_ENDIAN);
2883 proto_tree_add_item(subtree, hf_aeron_setup_term_offset, tvb, offset + O_AERON_SETUP_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2884 proto_tree_add_item(subtree, hf_aeron_setup_session_id, tvb, offset + O_AERON_SETUP_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2885 proto_tree_add_item(subtree, hf_aeron_setup_stream_id, tvb, offset + O_AERON_SETUP_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2886 proto_tree_add_item(subtree, hf_aeron_setup_initial_term_id, tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2887 proto_tree_add_item(subtree, hf_aeron_setup_active_term_id, tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2888 proto_tree_add_item(subtree, hf_aeron_setup_term_length, tvb, offset + O_AERON_SETUP_TERM_LENGTH, 4, ENC_LITTLE_ENDIAN);
2889 proto_tree_add_item(subtree, hf_aeron_setup_mtu, tvb, offset + O_AERON_SETUP_MTU, 4, ENC_LITTLE_ENDIAN);
2890 proto_tree_add_item(subtree, hf_aeron_setup_ttl, tvb, offset + O_AERON_SETUP_TTL, 4, ENC_LITTLE_ENDIAN);
2891 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2892 proto_item_set_len(setup_item, rounded_length);
2893 if (frame_length != L_AERON_SETUP)
2895 expert_add_info(pinfo, frame_length_item, &ei_aeron_analysis_invalid_setup_length);
2896 return (-rounded_length);
2898 return (rounded_length);
2901 /*----------------------------------------------------------------------------*/
2902 /* Aeron packet dissector. */
2903 /*----------------------------------------------------------------------------*/
2904 static int dissect_aeron(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data _U_)
2906 int total_dissected_length = 0;
2907 uint32_t frame_length;
2908 uint8_t frame_flags;
2909 uint16_t frame_type;
2910 proto_tree * aeron_tree;
2911 proto_item * aeron_item;
2912 int dissected_length = 0;
2913 int offset = 0;
2914 int length_remaining;
2915 aeron_conversation_info_t * cinfo;
2917 /* Get enough information to determine the conversation info.
2918 Make sure that we don't throw an exception before we know that
2919 this packet contains our protocol. */
2920 if (tvb_captured_length_remaining(tvb, offset) < 2)
2921 return 0;
2922 frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2923 cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2924 if (!cinfo)
2925 return 0;
2927 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Aeron");
2928 col_clear(pinfo->cinfo, COL_INFO);
2929 col_add_str(pinfo->cinfo, COL_INFO, aeron_format_transport_uri(cinfo));
2930 col_set_fence(pinfo->cinfo, COL_INFO);
2932 length_remaining = tvb_reported_length(tvb);
2933 aeron_item = proto_tree_add_protocol_format(tree, proto_aeron, tvb, offset, -1, "Aeron Protocol");
2934 aeron_tree = proto_item_add_subtree(aeron_item, ett_aeron);
2935 while (length_remaining > 0)
2937 aeron_frame_info_t * finfo = NULL;
2939 /* Make sure superfluous padding is not identified as aeron frame */
2940 if (tvb_skip_uint8(tvb, offset, tvb_captured_length_remaining(tvb, offset), 0) == (int)tvb_captured_length(tvb))
2942 break;
2945 if (aeron_sequence_analysis)
2947 finfo = aeron_frame_info_add(pinfo->num, (uint32_t) offset);
2949 frame_length = tvb_get_letohl(tvb, offset + O_AERON_BASIC_FRAME_LENGTH);
2950 frame_flags = tvb_get_uint8(tvb, offset + O_AERON_BASIC_FLAGS);
2951 frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2952 cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2953 switch (frame_type)
2955 case HDR_TYPE_PAD:
2956 dissected_length = dissect_aeron_pad(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2957 break;
2958 case HDR_TYPE_DATA:
2959 if(frame_length == 0 && frame_flags == DATA_FLAGS_COMPLETE)
2961 dissected_length = dissect_aeron_heartbeat(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2963 else
2965 dissected_length = dissect_aeron_data(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2967 break;
2968 case HDR_TYPE_NAK:
2969 dissected_length = dissect_aeron_nak(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2970 break;
2971 case HDR_TYPE_SM:
2972 dissected_length = dissect_aeron_sm(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2973 break;
2974 case HDR_TYPE_RTT:
2975 dissected_length = dissect_aeron_rtt(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2976 break;
2977 case HDR_TYPE_ERR:
2978 dissected_length = dissect_aeron_err(tvb, offset, pinfo, aeron_tree);
2979 break;
2980 case HDR_TYPE_SETUP:
2981 dissected_length = dissect_aeron_setup(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2982 break;
2983 case HDR_TYPE_RES:
2984 case HDR_TYPE_EXT:
2985 default:
2986 return (total_dissected_length);
2988 if (dissected_length <= 0)
2990 total_dissected_length += -dissected_length;
2991 proto_item_set_len(aeron_item, total_dissected_length);
2992 return (total_dissected_length);
2994 total_dissected_length += dissected_length;
2995 offset += dissected_length;
2996 length_remaining -= dissected_length;
2997 proto_item_set_len(aeron_item, total_dissected_length);
2999 return (total_dissected_length);
3002 static bool test_aeron_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data)
3004 uint8_t ver;
3005 uint16_t packet_type;
3006 int length;
3007 int length_remaining;
3008 int rc;
3010 length_remaining = tvb_captured_length_remaining(tvb, 0);
3011 if (length_remaining < HDR_LENGTH_MIN)
3013 return false;
3015 /* We know we have at least HDR_LENGTH_MIN (12) bytes captured */
3016 ver = tvb_get_uint8(tvb, O_AERON_BASIC_VERSION);
3017 if (ver != 0)
3019 return false;
3021 packet_type = tvb_get_letohs(tvb, O_AERON_BASIC_TYPE);
3022 switch (packet_type)
3024 case HDR_TYPE_PAD:
3025 case HDR_TYPE_DATA:
3026 case HDR_TYPE_NAK:
3027 case HDR_TYPE_SM:
3028 case HDR_TYPE_RTT:
3029 case HDR_TYPE_ERR:
3030 case HDR_TYPE_SETUP:
3031 case HDR_TYPE_RES:
3032 case HDR_TYPE_EXT:
3033 break;
3034 default:
3035 return false;
3037 length = (int) (tvb_get_letohl(tvb, O_AERON_BASIC_FRAME_LENGTH) & 0x7fffffff);
3038 if (!((packet_type == HDR_TYPE_DATA) && (length == 0)))
3040 if (length < HDR_LENGTH_MIN)
3042 return false;
3045 if (packet_type == HDR_TYPE_PAD)
3047 /* Pad frames can't have a zero term offset */
3048 uint32_t term_offset = tvb_get_letohl(tvb, O_AERON_PAD_TERM_OFFSET);
3049 if (term_offset == 0)
3051 return false;
3054 else
3056 if (length > length_remaining)
3058 return false;
3061 rc = dissect_aeron(tvb, pinfo, tree, user_data);
3062 if (rc == 0)
3064 return false;
3066 return true;
3069 /* Register all the bits needed with the filtering engine */
3070 void proto_register_aeron(void)
3072 static hf_register_info hf[] =
3074 { &hf_aeron_channel_id,
3075 { "Channel ID", "aeron.channel_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3076 { &hf_aeron_pad,
3077 { "Pad Frame", "aeron.pad", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3078 { &hf_aeron_pad_frame_length,
3079 { "Frame Length", "aeron.pad.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3080 { &hf_aeron_pad_version,
3081 { "Version", "aeron.pad.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3082 { &hf_aeron_pad_flags,
3083 { "Flags", "aeron.pad.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3084 { &hf_aeron_pad_type,
3085 { "Type", "aeron.pad.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3086 { &hf_aeron_pad_term_offset,
3087 { "Term Offset", "aeron.pad.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3088 { &hf_aeron_pad_session_id,
3089 { "Session ID", "aeron.pad.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3090 { &hf_aeron_pad_stream_id,
3091 { "Stream ID", "aeron.pad.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3092 { &hf_aeron_pad_term_id,
3093 { "Term ID", "aeron.pad.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3094 { &hf_aeron_data,
3095 { "Data Frame", "aeron.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3096 { &hf_aeron_data_frame_length,
3097 { "Frame Length", "aeron.data.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3098 { &hf_aeron_data_version,
3099 { "Version", "aeron.data.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3100 { &hf_aeron_data_flags,
3101 { "Flags", "aeron.data.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3102 { &hf_aeron_data_flags_b,
3103 { "Begin Message", "aeron.data.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_BEGIN, NULL, HFILL } },
3104 { &hf_aeron_data_flags_e,
3105 { "End Message", "aeron.data.flags.e", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_END, NULL, HFILL } },
3106 { &hf_aeron_data_flags_s,
3107 { "End Of Stream", "aeron.data.flags.s", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_EOS, NULL, HFILL } },
3108 { &hf_aeron_data_type,
3109 { "Type", "aeron.data.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3110 { &hf_aeron_data_term_offset,
3111 { "Term Offset", "aeron.data.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3112 { &hf_aeron_data_next_offset,
3113 { "Next Offset", "aeron.data.next_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3114 { &hf_aeron_data_next_offset_term,
3115 { "Next Offset Term", "aeron.data.next_offset_term", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3116 { &hf_aeron_data_next_offset_first_frame,
3117 { "Next Offset First Frame", "aeron.data.next_offset_first_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3118 { &hf_aeron_data_session_id,
3119 { "Session ID", "aeron.data.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3120 { &hf_aeron_data_stream_id,
3121 { "Stream ID", "aeron.data.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3122 { &hf_aeron_data_term_id,
3123 { "Term ID", "aeron.data.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3124 { &hf_aeron_data_reserved_value,
3125 { "Reserved", "aeron.data.reserved_value", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3126 { &hf_aeron_data_reassembly,
3127 { "Reassembled Fragments", "aeron.data.reassembly", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3128 { &hf_aeron_data_reassembly_fragment,
3129 { "Fragment", "aeron.data.reassembly.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3130 { &hf_aeron_nak,
3131 { "NAK Frame", "aeron.nak", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3132 { &hf_aeron_nak_frame_length,
3133 { "Frame Length", "aeron.nak.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3134 { &hf_aeron_nak_version,
3135 { "Version", "aeron.nak.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3136 { &hf_aeron_nak_flags,
3137 { "Flags", "aeron.nak.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3138 { &hf_aeron_nak_type,
3139 { "Type", "aeron.nak.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3140 { &hf_aeron_nak_session_id,
3141 { "Session ID", "aeron.nak.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3142 { &hf_aeron_nak_stream_id,
3143 { "Stream ID", "aeron.nak.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3144 { &hf_aeron_nak_term_id,
3145 { "Term ID", "aeron.nak.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3146 { &hf_aeron_nak_term_offset,
3147 { "Term Offset", "aeron.nak.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3148 { &hf_aeron_nak_length,
3149 { "Length", "aeron.nak.length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3150 { &hf_aeron_sm,
3151 { "Status Message", "aeron.sm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3152 { &hf_aeron_sm_frame_length,
3153 { "Frame Length", "aeron.sm.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3154 { &hf_aeron_sm_version,
3155 { "Version", "aeron.sm.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3156 { &hf_aeron_sm_flags,
3157 { "Flags", "aeron.sm.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3158 { &hf_aeron_sm_flags_s,
3159 { "Setup", "aeron.sm.flags.s", FT_BOOLEAN, 8, TFS(&tfs_set_notset), STATUS_FLAGS_SETUP, NULL, HFILL } },
3160 { &hf_aeron_sm_type,
3161 { "Type", "aeron.sm.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3162 { &hf_aeron_sm_session_id,
3163 { "Session ID", "aeron.sm.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3164 { &hf_aeron_sm_stream_id,
3165 { "Stream ID", "aeron.sm.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3166 { &hf_aeron_sm_consumption_term_id,
3167 { "Consumption Term ID", "aeron.sm.consumption_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3168 { &hf_aeron_sm_consumption_term_offset,
3169 { "Consumption Term Offset", "aeron.sm.consumption_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3170 { &hf_aeron_sm_receiver_window,
3171 { "Receiver Window", "aeron.sm.receiver_window", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3172 { &hf_aeron_sm_receiver_id,
3173 { "Receiver ID", "aeron.sm.receiver_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3174 { &hf_aeron_sm_feedback,
3175 { "Application-specific Feedback", "aeron.sm.feedback", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3176 { &hf_aeron_rtt,
3177 { "RTT Message", "aeron.rtt", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3178 { &hf_aeron_rtt_frame_length,
3179 { "Frame Length", "aeron.rtt.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3180 { &hf_aeron_rtt_version,
3181 { "Version", "aeron.rtt.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3182 { &hf_aeron_rtt_flags,
3183 { "Flags", "aeron.rtt.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3184 { &hf_aeron_rtt_flags_r,
3185 { "Reply", "aeron.rtt.flags.r", FT_BOOLEAN, 8, TFS(&tfs_set_notset), STATUS_FLAGS_REPLY, NULL, HFILL } },
3186 { &hf_aeron_rtt_type,
3187 { "Type", "aeron.rtt.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3188 { &hf_aeron_rtt_session_id,
3189 { "Session ID", "aeron.rtt.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3190 { &hf_aeron_rtt_stream_id,
3191 { "Stream ID", "aeron.rtt.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3192 { &hf_aeron_rtt_echo_timestamp,
3193 { "Echo Timestamp", "aeron.rtt.echo_timestamp", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3194 { &hf_aeron_rtt_reception_delta,
3195 { "Reception Delta", "aeron.rtt.reception_delta", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3196 { &hf_aeron_rtt_receiver_id,
3197 { "Receiver ID", "aeron.rtt.receiver_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3198 { &hf_aeron_err,
3199 { "Error Header", "aeron.err", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3200 { &hf_aeron_err_frame_length,
3201 { "Frame Length", "aeron.err.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3202 { &hf_aeron_err_version,
3203 { "Version", "aeron.err.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3204 { &hf_aeron_err_code,
3205 { "Error Code", "aeron.err.code", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3206 { &hf_aeron_err_type,
3207 { "Type", "aeron.err.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3208 { &hf_aeron_err_off_frame_length,
3209 { "Offending Frame Length", "aeron.err.off_frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3210 { &hf_aeron_err_off_hdr,
3211 { "Offending Header", "aeron.err.off_hdr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3212 { &hf_aeron_err_string,
3213 { "Error String", "aeron.err.string", FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3214 { &hf_aeron_heartbeat,
3215 { "Heart Frame", "aeron.heartbeat", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3216 { &hf_aeron_heartbeat_frame_length,
3217 { "Frame Length", "aeron.heartbeat.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3218 { &hf_aeron_heartbeat_version,
3219 { "Version", "aeron.heartbeat.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3220 { &hf_aeron_heartbeat_flags,
3221 { "Flags", "aeron.heartbeat.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3222 { &hf_aeron_heartbeat_flags_b,
3223 { "Begin Message", "aeron.heartbeat.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_BEGIN, NULL, HFILL } },
3224 { &hf_aeron_heartbeat_flags_e,
3225 { "End Message", "aeron.heartbeat.flags.e", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_END, NULL, HFILL } },
3226 { &hf_aeron_heartbeat_type,
3227 { "Type", "aeron.heartbeat.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3228 { &hf_aeron_heartbeat_term_offset,
3229 { "Term Offset", "aeron.heartbeat.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3230 { &hf_aeron_heartbeat_session_id,
3231 { "Session ID", "aeron.heartbeat.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3232 { &hf_aeron_heartbeat_stream_id,
3233 { "Stream ID", "aeron.heartbeat.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3234 { &hf_aeron_heartbeat_term_id,
3235 { "Term ID", "aeron.heartbeat.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3236 { &hf_aeron_setup,
3237 { "Setup Frame", "aeron.setup", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3238 { &hf_aeron_setup_frame_length,
3239 { "Frame Length", "aeron.setup.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3240 { &hf_aeron_setup_version,
3241 { "Version", "aeron.setup.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3242 { &hf_aeron_setup_flags,
3243 { "Flags", "aeron.setup.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
3244 { &hf_aeron_setup_type,
3245 { "Type", "aeron.setup.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
3246 { &hf_aeron_setup_term_offset,
3247 { "Term Offset", "aeron.setup.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3248 { &hf_aeron_setup_session_id,
3249 { "Session ID", "aeron.setup.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3250 { &hf_aeron_setup_stream_id,
3251 { "Stream ID", "aeron.setup.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3252 { &hf_aeron_setup_initial_term_id,
3253 { "Initial Term ID", "aeron.setup.initial_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3254 { &hf_aeron_setup_active_term_id,
3255 { "Active Term ID", "aeron.setup.active_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3256 { &hf_aeron_setup_term_length,
3257 { "Term Length", "aeron.setup.term_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3258 { &hf_aeron_setup_mtu,
3259 { "MTU", "aeron.setup.mtu", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3260 { &hf_aeron_setup_ttl,
3261 { "TTL", "aeron.setup.ttl", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3262 { &hf_aeron_sequence_analysis,
3263 { "Sequence Analysis", "aeron.sequence_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3264 { &hf_aeron_sequence_analysis_channel_prev_frame,
3265 { "Previous Channel Frame", "aeron.sequence_analysis.prev_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3266 { &hf_aeron_sequence_analysis_channel_next_frame,
3267 { "Next Channel Frame", "aeron.sequence_analysis.next_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3268 { &hf_aeron_sequence_analysis_stream_prev_frame,
3269 { "Previous Stream Frame", "aeron.sequence_analysis.prev_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3270 { &hf_aeron_sequence_analysis_stream_next_frame,
3271 { "Next Stream Frame", "aeron.sequence_analysis.next_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3272 { &hf_aeron_sequence_analysis_term_prev_frame,
3273 { "Previous Term Frame", "aeron.sequence_analysis.prev_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3274 { &hf_aeron_sequence_analysis_term_next_frame,
3275 { "Next Term Frame", "aeron.sequence_analysis.next_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3276 { &hf_aeron_sequence_analysis_term_offset,
3277 { "Offset also in", "aeron.sequence_analysis.term_offset", FT_NONE, BASE_NONE, NULL, 0x0, "Offset also appears in these frames", HFILL } },
3278 { &hf_aeron_sequence_analysis_term_offset_frame,
3279 { "Frame", "aeron.sequence_analysis.term_offset.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3280 { &hf_aeron_sequence_analysis_retransmission,
3281 { "Frame is a retransmission", "aeron.sequence_analysis.retransmission", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3282 { &hf_aeron_sequence_analysis_retransmission_rx,
3283 { "List of NAK frames to which this retransmission applies", "aeron.sequence_analysis.retransmission.rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3284 { &hf_aeron_sequence_analysis_retransmission_rx_frame,
3285 { "Retransmission applies to frame", "aeron.sequence_analysis.retransmission.rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3286 { &hf_aeron_sequence_analysis_nak_unrecovered,
3287 { "Unrecovered Bytes", "aeron.sequence_analysis.nak_unrecovered", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
3288 { &hf_aeron_sequence_analysis_nak_rx,
3289 { "List of RX Frames for this NAK", "aeron.sequence_analysis.nak_rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3290 { &hf_aeron_sequence_analysis_nak_rx_frame,
3291 { "RX Frame for this NAK", "aeron.sequence_analysis.nak_rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3292 { &hf_aeron_sequence_analysis_keepalive,
3293 { "Frame is a keepalive", "aeron.sequence_analysis.keepalive", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3294 { &hf_aeron_stream_analysis,
3295 { "Stream Analysis", "aeron.stream_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
3296 { &hf_aeron_stream_analysis_high_term_id,
3297 { "Highest sent term ID", "aeron.stream_analysis.high_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3298 { &hf_aeron_stream_analysis_high_term_offset,
3299 { "Highest sent term offset", "aeron.stream_analysis.high_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3300 { &hf_aeron_stream_analysis_completed_term_id,
3301 { "Completed term ID", "aeron.stream_analysis.completed_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3302 { &hf_aeron_stream_analysis_completed_term_offset,
3303 { "Completed term offset", "aeron.stream_analysis.completed_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
3304 { &hf_aeron_stream_analysis_outstanding_bytes,
3305 { "Outstanding bytes", "aeron.stream_analysis.outstanding_bytes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }
3307 static int * ett[] =
3309 &ett_aeron,
3310 &ett_aeron_pad,
3311 &ett_aeron_data,
3312 &ett_aeron_data_flags,
3313 &ett_aeron_data_reassembly,
3314 &ett_aeron_nak,
3315 &ett_aeron_sm,
3316 &ett_aeron_sm_flags,
3317 &ett_aeron_rtt,
3318 &ett_aeron_rtt_flags,
3319 &ett_aeron_err,
3320 &ett_aeron_setup,
3321 &ett_aeron_ext,
3322 &ett_aeron_sequence_analysis,
3323 &ett_aeron_sequence_analysis_retransmission_rx,
3324 &ett_aeron_sequence_analysis_nak_rx,
3325 &ett_aeron_sequence_analysis_term_offset,
3326 &ett_aeron_stream_analysis
3328 static ei_register_info ei[] =
3330 { &ei_aeron_analysis_nak, { "aeron.analysis.nak", PI_SEQUENCE, PI_NOTE, "NAK", EXPFILL } },
3331 { &ei_aeron_analysis_window_full, { "aeron.analysis.window_full", PI_SEQUENCE, PI_NOTE, "Receiver window is full", EXPFILL } },
3332 { &ei_aeron_analysis_idle_rx, { "aeron.analysis.idle_rx", PI_SEQUENCE, PI_NOTE, "This frame contains an Idle RX", EXPFILL } },
3333 { &ei_aeron_analysis_pacing_rx, { "aeron.analysis.pacing_rx", PI_SEQUENCE, PI_NOTE, "This frame contains a Pacing RX", EXPFILL } },
3334 { &ei_aeron_analysis_ooo, { "aeron.analysis.ooo", PI_SEQUENCE, PI_NOTE, "This frame contains Out-of-order data", EXPFILL } },
3335 { &ei_aeron_analysis_ooo_gap, { "aeron.analysis.ooo_gap", PI_SEQUENCE, PI_NOTE, "This frame is an Out-of-order gap", EXPFILL } },
3336 { &ei_aeron_analysis_keepalive, { "aeron.analysis.keepalive", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive", EXPFILL } },
3337 { &ei_aeron_analysis_window_resize, { "aeron.analysis.window_resize", PI_SEQUENCE, PI_NOTE, "Receiver window resized", EXPFILL } },
3338 { &ei_aeron_analysis_ooo_sm, { "aeron.analysis.ooo_sm", PI_SEQUENCE, PI_NOTE, "This frame contains an Out-of-order SM", EXPFILL } },
3339 { &ei_aeron_analysis_keepalive_sm, { "aeron.analysis.keepalive_sm", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive SM", EXPFILL } },
3340 { &ei_aeron_analysis_rx, { "aeron.analysis.rx", PI_SEQUENCE, PI_NOTE, "This frame contains a (likely) retransmission", EXPFILL } },
3341 { &ei_aeron_analysis_term_id_change, { "aeron.analysis.term_id_change", PI_SEQUENCE, PI_CHAT, "This frame contains a new term ID", EXPFILL } },
3342 { &ei_aeron_analysis_invalid_pad_length, { "aeron.analysis.invalid_pad_length", PI_MALFORMED, PI_ERROR, "Invalid pad frame length", EXPFILL } },
3343 { &ei_aeron_analysis_invalid_data_length, { "aeron.analysis.invalid_data_length", PI_MALFORMED, PI_ERROR, "Invalid data frame length", EXPFILL } },
3344 { &ei_aeron_analysis_invalid_nak_length, { "aeron.analysis.invalid_nak_length", PI_MALFORMED, PI_ERROR, "Invalid NAK frame length", EXPFILL } },
3345 { &ei_aeron_analysis_invalid_sm_length, { "aeron.analysis.invalid_sm_length", PI_MALFORMED, PI_ERROR, "Invalid SM frame length", EXPFILL } },
3346 { &ei_aeron_analysis_invalid_rtt_length, { "aeron.analysis.invalid_rtt_length", PI_MALFORMED, PI_ERROR, "Invalid RTT frame length", EXPFILL } },
3347 { &ei_aeron_analysis_invalid_err_length, { "aeron.analysis.invalid_err_length", PI_MALFORMED, PI_ERROR, "Invalid error frame length", EXPFILL } },
3348 { &ei_aeron_analysis_invalid_setup_length, { "aeron.analysis.invalid_setup_length", PI_MALFORMED, PI_ERROR, "Invalid setup frame length", EXPFILL } }
3350 module_t * aeron_module;
3351 expert_module_t * expert_aeron;
3353 proto_aeron = proto_register_protocol("Aeron Protocol", "Aeron", "aeron");
3355 proto_register_field_array(proto_aeron, hf, array_length(hf));
3356 proto_register_subtree_array(ett, array_length(ett));
3357 expert_aeron = expert_register_protocol(proto_aeron);
3358 expert_register_field_array(expert_aeron, ei, array_length(ei));
3359 aeron_module = prefs_register_protocol(proto_aeron, NULL);
3360 aeron_heuristic_subdissector_list = register_heur_dissector_list_with_description("aeron_msg_payload", "Aeron Data payload", proto_aeron);
3362 aeron_dissector_handle = register_dissector("aeron", dissect_aeron, proto_aeron);
3364 prefs_register_bool_preference(aeron_module,
3365 "sequence_analysis",
3366 "Analyze transport sequencing",
3367 "Include next/previous frame for channel, stream, and term, and other transport sequence analysis.",
3368 &aeron_sequence_analysis);
3369 prefs_register_bool_preference(aeron_module,
3370 "stream_analysis",
3371 "Analyze stream sequencing",
3372 "Include stream analysis, tracking publisher and subscriber positions. Requires \"Analyze transport sequencing\".",
3373 &aeron_stream_analysis);
3374 prefs_register_bool_preference(aeron_module,
3375 "reassemble_fragments",
3376 "Reassemble fragmented data",
3377 "Reassemble fragmented data messages. Requires \"Analyze transport sequencing\" and \"Analyze stream sequencing\".",
3378 &aeron_reassemble_fragments);
3379 prefs_register_bool_preference(aeron_module,
3380 "use_heuristic_subdissectors",
3381 "Use heuristic sub-dissectors",
3382 "Use a registered heuristic sub-dissector to decode the payload data. Requires \"Analyze transport sequencing\", \"Analyze stream sequencing\", and \"Reassemble fragmented data\".",
3383 &aeron_use_heuristic_subdissectors);
3384 register_init_routine(aeron_channel_id_init);
3385 aeron_frame_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3388 /* The registration hand-off routine */
3389 void proto_reg_handoff_aeron(void)
3391 dissector_add_for_decode_as_with_preference("udp.port", aeron_dissector_handle);
3392 heur_dissector_add("udp", test_aeron_packet, "Aeron over UDP", "aeron_udp", proto_aeron, HEURISTIC_DISABLE);
3396 * Editor modelines - https://www.wireshark.org/tools/modelines.html
3398 * Local variables:
3399 * c-basic-offset: 4
3400 * tab-width: 8
3401 * indent-tabs-mode: nil
3402 * End:
3404 * vi: set shiftwidth=4 tabstop=8 expandtab:
3405 * :indentSize=4:tabSize=8:noTabs=true: