3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #ifdef HAVE_ARPA_INET_H
24 #include <arpa/inet.h>
29 #include <epan/packet.h>
30 #include <epan/prefs.h>
31 #include <epan/expert.h>
34 #include <epan/conversation.h>
35 #include <epan/to_str.h>
36 #ifndef HAVE_INET_ATON
37 #include <wsutil/inet_aton.h>
39 #include <wsutil/pint.h>
41 /* The Aeron protocol is defined at https://github.com/real-logic/Aeron/wiki/Protocol-Specification */
43 void proto_register_aeron(void);
44 void proto_reg_handoff_aeron(void);
47 static int proto_aeron = -1;
49 /* Dissector handles */
50 static dissector_handle_t aeron_dissector_handle;
51 static dissector_handle_t aeron_data_dissector_handle;
52 static heur_dissector_list_t aeron_heuristic_subdissector_list;
54 /*----------------------------------------------------------------------------*/
56 /*----------------------------------------------------------------------------*/
58 static gboolean aeron_sequence_analysis = FALSE;
59 static gboolean aeron_stream_analysis = FALSE;
60 static gboolean aeron_reassemble_fragments = FALSE;
61 static gboolean aeron_use_heuristic_subdissectors = FALSE;
63 /*----------------------------------------------------------------------------*/
64 /* Aeron position routines. */
65 /*----------------------------------------------------------------------------*/
72 static int aeron_pos_roundup(int offset)
74 return ((offset+7) & 0xfffffff8);
77 static int aeron_pos_compare(const aeron_pos_t * pos1, const aeron_pos_t * pos2)
84 if (pos1->term_id == pos2->term_id)
86 if (pos1->term_offset == pos2->term_offset)
92 return ((pos1->term_offset < pos2->term_offset) ? -1 : 1);
97 return ((pos1->term_id < pos2->term_id) ? -1 : 1);
101 static guint32 aeron_pos_delta(const aeron_pos_t * pos1, const aeron_pos_t * pos2, guint32 term_size)
103 const aeron_pos_t * p1;
104 const aeron_pos_t * p2;
110 rc = aeron_pos_compare(pos1, pos2);
121 p1_val = (guint64) (p1->term_id * term_size) + ((guint64) p1->term_offset);
122 p2_val = (guint64) (p2->term_id * term_size) + ((guint64) p2->term_offset);
123 delta = p1_val - p2_val;
124 return ((guint32) (delta & G_GUINT64_CONSTANT(0x00000000ffffffff)));
127 static void aeron_pos_add_length(aeron_pos_t * pos, guint32 length, guint32 term_length)
129 guint32 next_term_offset = aeron_pos_roundup(pos->term_offset + length);
131 if (next_term_offset >= term_length)
133 pos->term_offset = 0;
138 pos->term_offset = next_term_offset;
142 /*----------------------------------------------------------------------------*/
143 /* Aeron frame information management. */
144 /*----------------------------------------------------------------------------*/
145 static wmem_tree_t * aeron_frame_info_tree = NULL;
147 struct aeron_frame_info_t_stct;
148 typedef struct aeron_frame_info_t_stct aeron_frame_info_t;
152 aeron_frame_info_t * frame_info; /* Frame (aeron_frame_info_t) containing the RX data */
153 guint32 term_offset; /* Term offset of RX data */
154 guint32 length; /* Length of RX data */
159 aeron_frame_info_t * frame_info; /* Frame (aeron_frame_info_t) in which this NAK occurs */
160 wmem_list_t * rx; /* List of RX frames for this NAK */
162 guint32 nak_term_offset; /* Term offset specified by this NAK */
163 guint32 nak_length; /* NAK length */
164 guint32 unrecovered_length; /* Number of bytes unrecovered via RX */
165 } aeron_nak_analysis_t;
172 aeron_pos_t completed;
173 guint32 receiver_window;
174 guint32 outstanding_bytes;
175 } aeron_stream_analysis_t;
176 #define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL 0x00000001
177 #define AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX 0x00000002
178 #define AERON_STREAM_ANALYSIS_FLAGS_PACING_RX 0x00000004
179 #define AERON_STREAM_ANALYSIS_FLAGS_OOO 0x00000008
180 #define AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP 0x00000010
181 #define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE 0x00000020
182 #define AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE 0x00000040
183 #define AERON_STREAM_ANALYSIS_FLAGS_OOO_SM 0x00000080
184 #define AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM 0x00000100
185 #define AERON_STREAM_ANALYSIS_FLAGS_RX 0x00000200
186 #define AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE 0x00000400
188 #define AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID 0x00000001
194 } aeron_frame_link_t;
196 struct aeron_msg_t_stct;
197 typedef struct aeron_msg_t_stct aeron_msg_t;
199 struct aeron_frame_info_t_stct
203 aeron_frame_link_t transport;
204 aeron_frame_link_t stream;
205 aeron_frame_link_t term;
206 aeron_frame_link_t fragment;
207 aeron_stream_analysis_t * stream_analysis;
208 aeron_nak_analysis_t * nak_analysis;
209 aeron_msg_t * message;
213 #define AERON_FRAME_INFO_FLAGS_RETRANSMISSION 0x00000001
214 #define AERON_FRAME_INFO_FLAGS_KEEPALIVE 0x00000002
215 #define AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG 0x00000004
217 static wmem_tree_key_t * aeron_frame_info_key_build(guint32 frame, guint32 ofs)
219 wmem_tree_key_t * fkey;
222 fkey = wmem_alloc_array(wmem_packet_scope(), wmem_tree_key_t, 2);
223 key = wmem_alloc_array(wmem_packet_scope(), guint32, 2);
233 static aeron_frame_info_t * aeron_frame_info_lookup(wmem_tree_key_t * key)
235 aeron_frame_info_t * fi = NULL;
237 fi = (aeron_frame_info_t *) wmem_tree_lookup32_array(aeron_frame_info_tree, key);
241 static aeron_frame_info_t * aeron_frame_info_find(guint32 frame, guint32 ofs)
243 wmem_tree_key_t * key = aeron_frame_info_key_build(frame, ofs);
244 return (aeron_frame_info_lookup(key));
247 static aeron_frame_info_t * aeron_frame_info_add(guint32 frame, guint32 ofs)
249 aeron_frame_info_t * fi = NULL;
250 wmem_tree_key_t * key = aeron_frame_info_key_build(frame, ofs);
252 fi = aeron_frame_info_lookup(key);
255 fi = wmem_new0(wmem_file_scope(), aeron_frame_info_t);
258 if (aeron_sequence_analysis && aeron_stream_analysis)
260 fi->rx = wmem_list_new(wmem_file_scope());
262 wmem_tree_insert32_array(aeron_frame_info_tree, key, (void *) fi);
267 /*----------------------------------------------------------------------------*/
268 /* Aeron channel ID management. */
269 /*----------------------------------------------------------------------------*/
270 static guint64 aeron_channel_id = 1;
272 static guint64 aeron_channel_id_assign(void)
274 return (aeron_channel_id++);
277 static void aeron_channel_id_init(void)
279 aeron_channel_id = 1;
282 /*----------------------------------------------------------------------------*/
283 /* Aeron transport, stream, term, and fragment structures. */
284 /*----------------------------------------------------------------------------*/
292 } aeron_conversation_info_t;
294 struct aeron_transport_t_stct;
295 typedef struct aeron_transport_t_stct aeron_transport_t;
297 struct aeron_stream_t_stct;
298 typedef struct aeron_stream_t_stct aeron_stream_t;
300 struct aeron_term_t_stct;
301 typedef struct aeron_term_t_stct aeron_term_t;
303 struct aeron_fragment_t_stct;
304 typedef struct aeron_fragment_t_stct aeron_fragment_t;
306 struct aeron_transport_t_stct
309 wmem_map_t * stream; /* Map of all streams (aeron_stream_t) in this transport, keyed by stream ID */
310 aeron_frame_info_t * last_frame;
318 struct aeron_stream_rcv_t_stct;
319 typedef struct aeron_stream_rcv_t_stct aeron_stream_rcv_t;
321 struct aeron_stream_rcv_t_stct
323 address addr; /* Receiver's IP address */
324 guint16 port; /* Receiver's (sending) port */
325 aeron_pos_t completed;
326 guint32 receiver_window;
329 struct aeron_stream_t_stct
331 aeron_transport_t * transport; /* Parent transport */
332 wmem_map_t * term; /* Map of all terms (aeron_term_t) in this stream, keyed by term ID */
333 wmem_list_t * rcv; /* List of receivers (aeron_stream_rcv_t) */
335 aeron_frame_info_t * last_frame;
342 #define AERON_STREAM_FLAGS_HIGH_VALID 0x1
346 aeron_term_t * term; /* Parent term */
347 aeron_frame_info_t * frame_info; /* Frame info (aeron_frame_info_t) in which this NAK occurred */
348 guint32 term_offset; /* NAK term offset */
349 guint32 length; /* Length of NAK */
352 struct aeron_term_t_stct
354 aeron_stream_t * stream; /* Parent stream */
355 wmem_map_t * fragment; /* Map of all fragments (aeron_fragment_t) in this term, keyed by term offset */
356 wmem_tree_t * message; /* Tree of all fragmented messages (aeron_msg_t) in this term, keyed by lowest term offset */
357 wmem_list_t * orphan_fragment;
358 aeron_frame_info_t * last_frame; /* Pointer to last frame seen for this term */
359 wmem_list_t * nak; /* List of all NAKs (aeron_nak_t) in this term */
363 struct aeron_fragment_t_stct
365 aeron_term_t * term; /* Parent term */
366 wmem_list_t * frame; /* List of frames (aeron_frame_info_t) containing this fragment (term offset) */
367 aeron_frame_info_t * first_frame; /* First frame which contains this fragment (term offset) */
368 aeron_frame_info_t * last_frame; /* Last frame which contains this fragment (term offset) */
369 aeron_frame_info_t * first_data_frame; /* First frame which contains this fragment (term offset) as actual data (not as a KA) */
376 /*----------------------------------------------------------------------------*/
377 /* Aeron transport management. */
378 /*----------------------------------------------------------------------------*/
379 static guint aeron_guint32_hash_func(gconstpointer key)
381 guint32 value = *((const guint32 *) key);
382 return ((guint) value);
385 static gboolean aeron_guint32_compare_func(gconstpointer lhs, gconstpointer rhs)
387 guint32 key1 = *((const guint32 *) lhs);
388 guint32 key2 = *((const guint32 *) rhs);
389 return ((key1 == key2) ? TRUE : FALSE);
392 static aeron_transport_t * aeron_transport_add(const aeron_conversation_info_t * cinfo, guint32 session_id, guint32 frame)
394 aeron_transport_t * transport;
395 conversation_t * conv = NULL;
396 wmem_map_t * session_map = NULL;
398 conv = find_conversation(frame, cinfo->addr1, cinfo->addr2, cinfo->ptype, cinfo->port1, cinfo->port2, 0);
401 conv = conversation_new(frame, cinfo->addr1, cinfo->addr2, cinfo->ptype, cinfo->port1, cinfo->port2, 0);
403 if (frame > conv->last_frame)
405 conv->last_frame = frame;
407 session_map = (wmem_map_t *) conversation_get_proto_data(conv, proto_aeron);
408 if (session_map == NULL)
410 session_map = wmem_map_new(wmem_file_scope(), aeron_guint32_hash_func, aeron_guint32_compare_func);
411 conversation_add_proto_data(conv, proto_aeron, (void *) session_map);
413 transport = (aeron_transport_t *) wmem_map_lookup(session_map, (const void *) &session_id);
414 if (transport != NULL)
418 transport = wmem_new0(wmem_file_scope(), aeron_transport_t);
419 transport->channel_id = aeron_channel_id_assign();
420 transport->stream = wmem_map_new(wmem_file_scope(), aeron_guint32_hash_func, aeron_guint32_compare_func);
421 transport->last_frame = NULL;
422 WMEM_COPY_ADDRESS(wmem_file_scope(), &(transport->addr1), cinfo->addr1);
423 WMEM_COPY_ADDRESS(wmem_file_scope(), &(transport->addr2), cinfo->addr2);
424 transport->session_id = session_id;
425 transport->port1 = cinfo->port1;
426 transport->port2 = cinfo->port2;
427 wmem_map_insert(session_map, (const void *) &(transport->session_id), (void *) transport);
431 static aeron_stream_t * aeron_transport_stream_find(aeron_transport_t * transport, guint32 stream_id)
433 aeron_stream_t * stream = NULL;
435 stream = (aeron_stream_t *) wmem_map_lookup(transport->stream, (const void *) &stream_id);
439 static aeron_stream_t * aeron_transport_stream_add(aeron_transport_t * transport, guint32 stream_id)
441 aeron_stream_t * stream = NULL;
443 stream = aeron_transport_stream_find(transport, stream_id);
446 stream = wmem_new0(wmem_file_scope(), aeron_stream_t);
447 stream->transport = transport;
448 stream->term = wmem_map_new(wmem_file_scope(), aeron_guint32_hash_func, aeron_guint32_compare_func);
449 stream->rcv = wmem_list_new(wmem_file_scope());
450 stream->rcv_count = 0;
451 stream->last_frame = NULL;
452 stream->stream_id = stream_id;
453 stream->term_length = 0;
456 stream->high.term_id = 0;
457 stream->high.term_offset = 0;
458 wmem_map_insert(transport->stream, (const void *) &(stream->stream_id), (void *) stream);
463 static void aeron_transport_frame_add(aeron_transport_t * transport, aeron_frame_info_t * finfo, guint32 flags)
467 finfo->flags = flags;
469 if (transport->last_frame != NULL)
471 finfo->transport.previous = transport->last_frame->frame;
472 transport->last_frame->transport.next = finfo->frame;
474 finfo->transport.next = 0;
475 transport->last_frame = finfo;
478 /*----------------------------------------------------------------------------*/
479 /* Aeron stream management. */
480 /*----------------------------------------------------------------------------*/
481 static aeron_term_t * aeron_stream_term_find(aeron_stream_t * stream, guint32 term_id)
483 aeron_term_t * term = NULL;
485 term = (aeron_term_t *) wmem_map_lookup(stream->term, (const void *) &term_id);
489 static aeron_term_t * aeron_stream_term_add(aeron_stream_t * stream, guint32 term_id)
491 aeron_term_t * term = NULL;
493 term = aeron_stream_term_find(stream, term_id);
496 term = wmem_new0(wmem_file_scope(), aeron_term_t);
497 term->stream = stream;
498 term->fragment = wmem_map_new(wmem_file_scope(), aeron_guint32_hash_func, aeron_guint32_compare_func);
499 term->message = wmem_tree_new(wmem_file_scope());
500 term->orphan_fragment = wmem_list_new(wmem_file_scope());
501 term->nak = wmem_list_new(wmem_file_scope());
502 term->term_id = term_id;
503 wmem_map_insert(stream->term, (const void *) &(term->term_id), (void *) term);
508 static aeron_stream_rcv_t * aeron_stream_rcv_find(aeron_stream_t * stream, const address * addr, guint16 port)
510 wmem_list_frame_t * lf = wmem_list_head(stream->rcv);
511 aeron_stream_rcv_t * rcv = NULL;
515 aeron_stream_rcv_t * cur = (aeron_stream_rcv_t *) wmem_list_frame_data(lf);
518 if ((cmp_address(&(cur->addr), addr) == 0) && (cur->port == port))
524 lf = wmem_list_frame_next(lf);
529 static aeron_stream_rcv_t * aeron_stream_rcv_add(aeron_stream_t * stream, const address * addr, guint16 port)
531 aeron_stream_rcv_t * rcv = NULL;
533 rcv = aeron_stream_rcv_find(stream, addr, port);
538 rcv = wmem_new0(wmem_file_scope(), aeron_stream_rcv_t);
539 WMEM_COPY_ADDRESS(wmem_file_scope(), &(rcv->addr), addr);
541 rcv->completed.term_id = 0;
542 rcv->completed.term_offset = 0;
543 rcv->receiver_window = 0;
544 wmem_list_append(stream->rcv, (void *) rcv);
549 static void aeron_stream_frame_add(aeron_stream_t * stream, aeron_frame_info_t * finfo, guint32 flags)
553 finfo->flags = flags;
555 if (stream->last_frame != NULL)
557 finfo->stream.previous = stream->last_frame->frame;
558 stream->last_frame->stream.next = finfo->frame;
560 finfo->stream.next = 0;
561 stream->last_frame = finfo;
562 aeron_transport_frame_add(stream->transport, finfo, 0);
565 /*----------------------------------------------------------------------------*/
566 /* Aeron term management. */
567 /*----------------------------------------------------------------------------*/
568 static aeron_fragment_t * aeron_term_fragment_find(aeron_term_t * term, guint32 term_offset)
570 aeron_fragment_t * fragment = NULL;
572 fragment = (aeron_fragment_t *) wmem_map_lookup(term->fragment, (const void *) &term_offset);
576 static aeron_fragment_t * aeron_term_fragment_add(aeron_term_t * term, guint32 term_offset, guint32 length, guint32 data_length)
578 aeron_fragment_t * fragment = NULL;
580 fragment = aeron_term_fragment_find(term, term_offset);
581 if (fragment == NULL)
583 fragment = wmem_new0(wmem_file_scope(), aeron_fragment_t);
584 fragment->term = term;
585 fragment->frame = wmem_list_new(wmem_file_scope());
586 fragment->first_frame = NULL;
587 fragment->last_frame = NULL;
588 fragment->first_data_frame = NULL;
589 fragment->term_offset = term_offset;
590 fragment->length = length;
591 fragment->data_length = data_length;
592 fragment->frame_count = 0;
593 wmem_map_insert(term->fragment, (const void *) &(fragment->term_offset), (void *) fragment);
598 static void aeron_term_frame_add(aeron_term_t * term, aeron_frame_info_t * finfo, guint32 flags)
602 finfo->flags = flags;
604 if (term->last_frame != NULL)
606 finfo->term.previous = term->last_frame->frame;
607 term->last_frame->term.next = finfo->frame;
609 finfo->term.next = 0;
610 term->last_frame = finfo;
611 aeron_stream_frame_add(term->stream, finfo, 0);
614 /*----------------------------------------------------------------------------*/
615 /* Aeron fragment management. */
616 /*----------------------------------------------------------------------------*/
617 static void aeron_fragment_frame_add(aeron_fragment_t * fragment, aeron_frame_info_t * finfo, guint32 flags, guint32 length)
621 finfo->flags = flags;
623 wmem_list_append(fragment->frame, (void *) finfo);
624 fragment->frame_count++;
625 if (fragment->last_frame != NULL)
627 finfo->fragment.previous = fragment->last_frame->frame;
628 fragment->last_frame->fragment.next = finfo->frame;
630 if (fragment->first_frame == NULL)
632 fragment->first_frame = finfo;
636 if (fragment->first_data_frame == NULL)
638 fragment->first_data_frame = finfo;
641 finfo->fragment.next = 0;
642 fragment->last_frame = finfo;
643 aeron_term_frame_add(fragment->term, finfo, 0);
646 /*----------------------------------------------------------------------------*/
647 /* Utilioty functions. */
648 /*----------------------------------------------------------------------------*/
649 static gboolean aeron_is_address_multicast(const address * addr)
651 guint8 * addr_data = (guint8 *) addr->data;
656 if ((addr_data[0] & 0xf0) == 0xe0)
662 if (addr_data[0] == 0xff)
673 static char * aeron_format_transport_uri(const aeron_conversation_info_t * cinfo)
675 wmem_strbuf_t * uri = NULL;
677 uri = wmem_strbuf_new(wmem_packet_scope(), "aeron:");
678 switch (cinfo->ptype)
681 wmem_strbuf_append(uri, "udp");
684 wmem_strbuf_append(uri, "unknown");
687 wmem_strbuf_append_c(uri, '?');
688 if (aeron_is_address_multicast(cinfo->addr2))
690 switch (cinfo->addr2->type)
693 wmem_strbuf_append_printf(uri, "group=[%s]:%" G_GUINT16_FORMAT, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
697 wmem_strbuf_append_printf(uri, "group=%s:%" G_GUINT16_FORMAT, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
703 switch (cinfo->addr2->type)
706 wmem_strbuf_append_printf(uri, "remote=[%s]:%" G_GUINT16_FORMAT, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
710 wmem_strbuf_append_printf(uri, "remote=%s:%" G_GUINT16_FORMAT, address_to_str(wmem_packet_scope(), cinfo->addr2), cinfo->port2);
714 return (wmem_strbuf_finalize(uri));
717 /*----------------------------------------------------------------------------*/
718 /* Packet definitions. */
719 /*----------------------------------------------------------------------------*/
721 /* Basic frame offsets */
722 #define O_AERON_BASIC_FRAME_LENGTH 0
723 #define O_AERON_BASIC_VERSION 4
724 #define O_AERON_BASIC_FLAGS 5
725 #define O_AERON_BASIC_TYPE 6
727 #define HDR_LENGTH_MIN 12
730 #define O_AERON_PAD_FRAME_LENGTH 0
731 #define O_AERON_PAD_VERSION 4
732 #define O_AERON_PAD_FLAGS 5
733 #define O_AERON_PAD_TYPE 6
734 #define O_AERON_PAD_TERM_OFFSET 8
735 #define O_AERON_PAD_SESSION_ID 12
736 #define O_AERON_PAD_STREAM_ID 16
737 #define O_AERON_PAD_TERM_ID 20
738 #define L_AERON_PAD 24
741 #define O_AERON_DATA_FRAME_LENGTH 0
742 #define O_AERON_DATA_VERSION 4
743 #define O_AERON_DATA_FLAGS 5
744 #define O_AERON_DATA_TYPE 6
745 #define O_AERON_DATA_TERM_OFFSET 8
746 #define O_AERON_DATA_SESSION_ID 12
747 #define O_AERON_DATA_STREAM_ID 16
748 #define O_AERON_DATA_TERM_ID 20
749 #define O_AERON_DATA_DATA 24
750 #define L_AERON_DATA 24
753 #define O_AERON_NAK_FRAME_LENGTH 0
754 #define O_AERON_NAK_VERSION 4
755 #define O_AERON_NAK_FLAGS 5
756 #define O_AERON_NAK_TYPE 6
757 #define O_AERON_NAK_SESSION_ID 8
758 #define O_AERON_NAK_STREAM_ID 12
759 #define O_AERON_NAK_TERM_ID 16
760 #define O_AERON_NAK_TERM_OFFSET 20
761 #define O_AERON_NAK_LENGTH 24
764 #define O_AERON_SM_FRAME_LENGTH 0
765 #define O_AERON_SM_VERSION 4
766 #define O_AERON_SM_FLAGS 5
767 #define O_AERON_SM_TYPE 6
768 #define O_AERON_SM_SESSION_ID 8
769 #define O_AERON_SM_STREAM_ID 12
770 #define O_AERON_SM_TERM_ID 16
771 #define O_AERON_SM_COMPLETED_TERM_OFFSET 20
772 #define O_AERON_SM_RECEIVER_WINDOW 24
773 #define O_AERON_SM_FEEDBACK 28
776 #define O_AERON_ERR_FRAME_LENGTH 0
777 #define O_AERON_ERR_VERSION 4
778 #define O_AERON_ERR_CODE 5
779 #define O_AERON_ERR_TYPE 6
780 #define O_AERON_ERR_OFFENDING_FRAME_LENGTH 8
781 #define O_AERON_ERR_OFFENDING_HEADER 12
782 #define O_AERON_ERR_TERM_ID 16
783 #define O_AERON_ERR_COMPLETED_TERM_OFFSET 20
784 #define O_AERON_ERR_RECEIVER_WINDOW 24
785 #define O_AERON_ERR_FEEDBACK 28
788 #define O_AERON_SETUP_FRAME_LENGTH 0
789 #define O_AERON_SETUP_VERSION 4
790 #define O_AERON_SETUP_FLAGS 5
791 #define O_AERON_SETUP_TYPE 6
792 #define O_AERON_SETUP_TERM_OFFSET 8
793 #define O_AERON_SETUP_SESSION_ID 12
794 #define O_AERON_SETUP_STREAM_ID 16
795 #define O_AERON_SETUP_INITIAL_TERM_ID 20
796 #define O_AERON_SETUP_ACTIVE_TERM_ID 24
797 #define O_AERON_SETUP_TERM_LENGTH 28
798 #define O_AERON_SETUP_MTU 32
800 #define HDR_TYPE_PAD 0x0000
801 #define HDR_TYPE_DATA 0x0001
802 #define HDR_TYPE_NAK 0x0002
803 #define HDR_TYPE_SM 0x0003
804 #define HDR_TYPE_ERR 0x0004
805 #define HDR_TYPE_SETUP 0x0005
806 #define HDR_TYPE_EXT 0xFFFF
808 #define DATA_FLAGS_BEGIN 0x80
809 #define DATA_FLAGS_END 0x40
810 #define DATA_FLAGS_COMPLETE (DATA_FLAGS_BEGIN | DATA_FLAGS_END)
812 #define STATUS_FLAGS_SETUP 0x80
814 /*----------------------------------------------------------------------------*/
815 /* Value translation tables. */
816 /*----------------------------------------------------------------------------*/
818 static const value_string aeron_frame_type[] =
820 { HDR_TYPE_PAD, "Pad" },
821 { HDR_TYPE_DATA, "Data" },
822 { HDR_TYPE_NAK, "NAK" },
823 { HDR_TYPE_SM, "Status" },
824 { HDR_TYPE_ERR, "Error" },
825 { HDR_TYPE_SETUP, "Setup" },
826 { HDR_TYPE_EXT, "Extension" },
834 - The URL specifies the subscriber address and UDP port, and the publisher "connects" to the single subscriber.
835 - The publisher sends Pad, Data, and Setup frames to the subscriber address and port.
836 - The subscriber sends NAK and SM frames to the publisher, using as the destination the address and port from
837 which the Setup and Data frames were received
838 - So the conversation is defined by [A(publisher),A(subscriber),P(publisher),P(subscriber),PT_UDP]
841 - The URL specifies the data multicast group and UDP port, and must be an odd-numbered address. The control multicast
842 group is automatically set to be one greater than the data multicast group, and the same port is used.
843 - The publisher sends Pad, Data, and Setup frames to the data multicast group and port.
844 - The subscriber sends NAK and SM frames to the control multicast group and port.
845 - So the conversation is defined by [ControlGroup,DataGroup,port,port,PT_UDP]
849 static aeron_conversation_info_t * aeron_setup_conversation_info(const packet_info * pinfo, guint16 type)
851 aeron_conversation_info_t * cinfo;
852 int addr_len = pinfo->dst.len;
854 cinfo = wmem_new0(wmem_packet_scope(), aeron_conversation_info_t);
855 cinfo->ptype = pinfo->ptype;
856 switch (pinfo->dst.type)
860 guint8 * dst_addr = (guint8 *) pinfo->dst.data;
862 cinfo->addr1 = wmem_new0(wmem_packet_scope(), address);
863 cinfo->addr2 = wmem_new0(wmem_packet_scope(), address);
864 if (aeron_is_address_multicast(&(pinfo->dst)))
866 guint8 * addr1 = NULL;
867 guint8 * addr2 = NULL;
869 addr1 = (guint8 *) wmem_alloc(wmem_packet_scope(), (size_t) addr_len);
870 addr2 = (guint8 *) wmem_alloc(wmem_packet_scope(), (size_t) addr_len);
871 memcpy((void *) addr1, (void *) dst_addr, (size_t) addr_len);
872 memcpy((void *) addr2, (void *) dst_addr, (size_t) addr_len);
873 if ((dst_addr[addr_len - 1] & 0x1) != 0)
875 /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
876 addr1[addr_len - 1]++;
880 /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
881 addr2[addr_len - 1]--;
883 SET_ADDRESS(cinfo->addr1, AT_IPv4, addr_len, (void *) addr1);
884 SET_ADDRESS(cinfo->addr2, AT_IPv4, addr_len, (void *) addr2);
885 cinfo->port1 = pinfo->destport;
886 cinfo->port2 = cinfo->port1;
895 /* Destination is a receiver */
896 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr1, &(pinfo->src));
897 cinfo->port1 = pinfo->srcport;
898 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr2, &(pinfo->dst));
899 cinfo->port2 = pinfo->destport;
903 /* Destination is the source */
904 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr1, &(pinfo->dst));
905 cinfo->port1 = pinfo->destport;
906 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr2, &(pinfo->src));
907 cinfo->port2 = pinfo->srcport;
917 guint8 * dst_addr = (guint8 *) pinfo->dst.data;
919 cinfo->addr1 = wmem_new0(wmem_packet_scope(), address);
920 cinfo->addr2 = wmem_new0(wmem_packet_scope(), address);
921 if (aeron_is_address_multicast(&(pinfo->dst)))
923 guint8 * addr1 = NULL;
924 guint8 * addr2 = NULL;
926 addr1 = (guint8 *) wmem_alloc(wmem_packet_scope(), (size_t) addr_len);
927 addr2 = (guint8 *) wmem_alloc(wmem_packet_scope(), (size_t) addr_len);
928 memcpy((void *) addr1, (void *) dst_addr, (size_t) addr_len);
929 memcpy((void *) addr2, (void *) dst_addr, (size_t) addr_len);
930 if ((dst_addr[addr_len - 1] & 0x1) != 0)
932 /* Address is odd, so it's the data group (in addr2). Increment the last byte of addr1 for the control group. */
933 addr1[addr_len - 1]++;
937 /* Address is even, so it's the control group (in addr1). Decrement the last byte of addr2 for the data group. */
938 addr2[addr_len - 1]--;
940 SET_ADDRESS(cinfo->addr1, AT_IPv6, addr_len, (void *) addr1);
941 SET_ADDRESS(cinfo->addr2, AT_IPv6, addr_len, (void *) addr2);
942 cinfo->port1 = pinfo->destport;
943 cinfo->port2 = cinfo->port1;
952 /* Destination is a receiver */
953 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr1, &(pinfo->src));
954 cinfo->port1 = pinfo->srcport;
955 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr2, &(pinfo->dst));
956 cinfo->port2 = pinfo->destport;
960 /* Destination is the source */
961 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr1, &(pinfo->dst));
962 cinfo->port1 = pinfo->destport;
963 WMEM_COPY_ADDRESS(wmem_packet_scope(), cinfo->addr2, &(pinfo->src));
964 cinfo->port2 = pinfo->srcport;
978 /*----------------------------------------------------------------------------*/
979 /* Handles of all types. */
980 /*----------------------------------------------------------------------------*/
982 /* Dissector tree handles */
983 static gint ett_aeron = -1;
984 static gint ett_aeron_pad = -1;
985 static gint ett_aeron_data = -1;
986 static gint ett_aeron_data_flags = -1;
987 static gint ett_aeron_data_reassembly = -1;
988 static gint ett_aeron_nak = -1;
989 static gint ett_aeron_sm = -1;
990 static gint ett_aeron_sm_flags = -1;
991 static gint ett_aeron_err = -1;
992 static gint ett_aeron_setup = -1;
993 static gint ett_aeron_ext = -1;
994 static gint ett_aeron_sequence_analysis = -1;
995 static gint ett_aeron_sequence_analysis_retransmission_rx = -1;
996 static gint ett_aeron_sequence_analysis_nak_rx = -1;
997 static gint ett_aeron_sequence_analysis_term_offset = -1;
998 static gint ett_aeron_stream_analysis = -1;
1000 /* Dissector field handles */
1001 static int hf_aeron_channel_id = -1;
1002 static int hf_aeron_pad = -1;
1003 static int hf_aeron_pad_frame_length = -1;
1004 static int hf_aeron_pad_version = -1;
1005 static int hf_aeron_pad_flags = -1;
1006 static int hf_aeron_pad_type = -1;
1007 static int hf_aeron_pad_term_offset = -1;
1008 static int hf_aeron_pad_session_id = -1;
1009 static int hf_aeron_pad_stream_id = -1;
1010 static int hf_aeron_pad_term_id = -1;
1011 static int hf_aeron_data = -1;
1012 static int hf_aeron_data_frame_length = -1;
1013 static int hf_aeron_data_version = -1;
1014 static int hf_aeron_data_flags = -1;
1015 static int hf_aeron_data_flags_b = -1;
1016 static int hf_aeron_data_flags_e = -1;
1017 static int hf_aeron_data_type = -1;
1018 static int hf_aeron_data_term_offset = -1;
1019 static int hf_aeron_data_next_offset = -1;
1020 static int hf_aeron_data_next_offset_term = -1;
1021 static int hf_aeron_data_next_offset_first_frame = -1;
1022 static int hf_aeron_data_session_id = -1;
1023 static int hf_aeron_data_stream_id = -1;
1024 static int hf_aeron_data_term_id = -1;
1025 static int hf_aeron_data_reassembly = -1;
1026 static int hf_aeron_data_reassembly_fragment = -1;
1027 static int hf_aeron_nak = -1;
1028 static int hf_aeron_nak_frame_length = -1;
1029 static int hf_aeron_nak_version = -1;
1030 static int hf_aeron_nak_flags = -1;
1031 static int hf_aeron_nak_type = -1;
1032 static int hf_aeron_nak_session_id = -1;
1033 static int hf_aeron_nak_stream_id = -1;
1034 static int hf_aeron_nak_term_id = -1;
1035 static int hf_aeron_nak_term_offset = -1;
1036 static int hf_aeron_nak_length = -1;
1037 static int hf_aeron_sm = -1;
1038 static int hf_aeron_sm_frame_length = -1;
1039 static int hf_aeron_sm_version = -1;
1040 static int hf_aeron_sm_flags = -1;
1041 static int hf_aeron_sm_flags_s = -1;
1042 static int hf_aeron_sm_type = -1;
1043 static int hf_aeron_sm_session_id = -1;
1044 static int hf_aeron_sm_stream_id = -1;
1045 static int hf_aeron_sm_consumption_term_id = -1;
1046 static int hf_aeron_sm_consumption_term_offset = -1;
1047 static int hf_aeron_sm_receiver_window = -1;
1048 static int hf_aeron_sm_feedback = -1;
1049 static int hf_aeron_err = -1;
1050 static int hf_aeron_err_frame_length = -1;
1051 static int hf_aeron_err_version = -1;
1052 static int hf_aeron_err_code = -1;
1053 static int hf_aeron_err_type = -1;
1054 static int hf_aeron_err_off_frame_length = -1;
1055 static int hf_aeron_err_off_hdr = -1;
1056 static int hf_aeron_err_string = -1;
1057 static int hf_aeron_setup = -1;
1058 static int hf_aeron_setup_frame_length = -1;
1059 static int hf_aeron_setup_version = -1;
1060 static int hf_aeron_setup_flags = -1;
1061 static int hf_aeron_setup_type = -1;
1062 static int hf_aeron_setup_term_offset = -1;
1063 static int hf_aeron_setup_session_id = -1;
1064 static int hf_aeron_setup_stream_id = -1;
1065 static int hf_aeron_setup_initial_term_id = -1;
1066 static int hf_aeron_setup_active_term_id = -1;
1067 static int hf_aeron_setup_term_length = -1;
1068 static int hf_aeron_setup_mtu = -1;
1069 static int hf_aeron_sequence_analysis = -1;
1070 static int hf_aeron_sequence_analysis_channel_prev_frame = -1;
1071 static int hf_aeron_sequence_analysis_channel_next_frame = -1;
1072 static int hf_aeron_sequence_analysis_stream_prev_frame = -1;
1073 static int hf_aeron_sequence_analysis_stream_next_frame = -1;
1074 static int hf_aeron_sequence_analysis_term_prev_frame = -1;
1075 static int hf_aeron_sequence_analysis_term_next_frame = -1;
1076 static int hf_aeron_sequence_analysis_term_offset = -1;
1077 static int hf_aeron_sequence_analysis_term_offset_frame = -1;
1078 static int hf_aeron_sequence_analysis_retransmission = -1;
1079 static int hf_aeron_sequence_analysis_retransmission_rx = -1;
1080 static int hf_aeron_sequence_analysis_retransmission_rx_frame = -1;
1081 static int hf_aeron_sequence_analysis_keepalive = -1;
1082 static int hf_aeron_sequence_analysis_nak_unrecovered = -1;
1083 static int hf_aeron_sequence_analysis_nak_rx = -1;
1084 static int hf_aeron_sequence_analysis_nak_rx_frame = -1;
1085 static int hf_aeron_stream_analysis = -1;
1086 static int hf_aeron_stream_analysis_high_term_id = -1;
1087 static int hf_aeron_stream_analysis_high_term_offset = -1;
1088 static int hf_aeron_stream_analysis_completed_term_id = -1;
1089 static int hf_aeron_stream_analysis_completed_term_offset = -1;
1090 static int hf_aeron_stream_analysis_outstanding_bytes = -1;
1092 /* Expert info handles */
1093 static expert_field ei_aeron_analysis_nak = EI_INIT;
1094 static expert_field ei_aeron_analysis_window_full = EI_INIT;
1095 static expert_field ei_aeron_analysis_idle_rx = EI_INIT;
1096 static expert_field ei_aeron_analysis_pacing_rx = EI_INIT;
1097 static expert_field ei_aeron_analysis_ooo = EI_INIT;
1098 static expert_field ei_aeron_analysis_ooo_gap = EI_INIT;
1099 static expert_field ei_aeron_analysis_keepalive = EI_INIT;
1100 static expert_field ei_aeron_analysis_ooo_sm = EI_INIT;
1101 static expert_field ei_aeron_analysis_keepalive_sm = EI_INIT;
1102 static expert_field ei_aeron_analysis_window_resize = EI_INIT;
1103 static expert_field ei_aeron_analysis_rx = EI_INIT;
1104 static expert_field ei_aeron_analysis_term_id_change = EI_INIT;
1106 /*----------------------------------------------------------------------------*/
1107 /* Setup packet information */
1108 /*----------------------------------------------------------------------------*/
1114 guint32 term_offset;
1116 guint32 data_length;
1117 guint32 receiver_window;
1118 guint32 nak_term_offset;
1122 } aeron_packet_info_t;
1123 #define AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID 0x00000001
1124 #define AERON_PACKET_INFO_FLAGS_TERM_ID_VALID 0x00000002
1125 #define AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID 0x00000004
1127 static void aeron_frame_nak_rx_add(aeron_frame_info_t * nak_info, aeron_frame_info_t * rx_info, guint32 term_offset, guint32 length)
1129 if (nak_info->nak_analysis->unrecovered_length >= length)
1131 wmem_list_frame_t * lf = wmem_list_head(nak_info->nak_analysis->rx);
1132 aeron_rx_info_t * rx = NULL;
1136 rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1139 if ((rx->term_offset == term_offset) && (rx->length == length))
1141 /* Already have this RX */
1145 lf = wmem_list_frame_next(lf);
1147 /* This RX frame isn't in the list, so add it */
1148 rx = wmem_new0(wmem_file_scope(), aeron_rx_info_t);
1149 rx->frame_info = rx_info;
1150 rx->term_offset = term_offset;
1151 rx->length = length;
1152 wmem_list_append(nak_info->nak_analysis->rx, (void *) rx);
1153 nak_info->nak_analysis->unrecovered_length -= length;
1154 wmem_list_append(rx_info->rx, (void *) nak_info);
1158 static void aeron_frame_process_rx(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1160 wmem_list_frame_t * lf = NULL;
1162 lf = wmem_list_head(term->nak);
1165 aeron_nak_t * nak = (aeron_nak_t *) wmem_list_frame_data(lf);
1168 if (nak->frame_info->frame <= finfo->frame)
1170 if ((nak->term_offset <= info->term_offset) && (nak->length >= info->length))
1172 /* This data frame falls entirely within the NAK range */
1173 aeron_frame_nak_rx_add(nak->frame_info, finfo, info->term_offset, info->length);
1177 lf = wmem_list_frame_next(lf);
1181 static void aeron_frame_nak_analysis_setup(aeron_packet_info_t * info, aeron_frame_info_t * finfo, aeron_term_t * term)
1183 aeron_nak_t * nak = wmem_new0(wmem_file_scope(), aeron_nak_t);
1185 nak->frame_info = finfo;
1186 nak->term_offset = info->nak_term_offset;
1187 nak->length = info->nak_length;
1188 wmem_list_append(term->nak, (void *) nak);
1190 finfo->nak_analysis = wmem_new0(wmem_file_scope(), aeron_nak_analysis_t);
1191 finfo->nak_analysis->frame_info = finfo;
1192 finfo->nak_analysis->rx = wmem_list_new(wmem_file_scope());
1193 finfo->nak_analysis->nak_term_offset = info->nak_term_offset;
1194 finfo->nak_analysis->nak_length = info->nak_length;
1195 finfo->nak_analysis->unrecovered_length = info->nak_length;
1198 static void 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, gboolean new_term)
1200 aeron_stream_rcv_t * rcv = NULL;
1201 /* dp is the current data position (from this frame). */
1202 aeron_pos_t dp = { 0, 0 };
1204 pdp is the previous (high) data position (from the stream).
1205 pdpv is TRUE if pdp is valid (meaning we previously saw a data message).
1207 aeron_pos_t pdp = stream->high;
1208 gboolean pdpv = ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0);
1209 /* rp is the current receiver position (from this frame). */
1210 aeron_pos_t rp = { 0, 0 };
1212 prp is the previous (high) receiver completed position (from the stream receiver).
1213 prpv is TRUE if prp is valid (meaning we previously saw a status message).
1215 aeron_pos_t prp = { 0, 0 };
1216 gboolean prpv = FALSE;
1217 guint32 cur_receiver_window = 0;
1218 /* Flags to be used when creating the fragment frame entry */
1219 guint32 frame_flags = 0;
1221 if (info->type == HDR_TYPE_SM)
1223 /* Locate the receiver */
1224 rcv = aeron_stream_rcv_find(stream, &(pinfo->src), pinfo->srcport);
1227 rcv = aeron_stream_rcv_add(stream, &(pinfo->src), pinfo->srcport);
1232 prp = rcv->completed;
1233 cur_receiver_window = rcv->receiver_window;
1240 dp.term_id = info->term_id;
1241 dp.term_offset = info->term_offset;
1242 aeron_pos_add_length(&dp, info->length, stream->term_length);
1245 if (dp.term_id > stream->high.term_id)
1247 stream->high.term_id = dp.term_id;
1248 stream->high.term_offset = dp.term_offset;
1250 else if (dp.term_offset > stream->high.term_offset)
1252 stream->high.term_offset = dp.term_offset;
1257 stream->flags |= AERON_STREAM_FLAGS_HIGH_VALID;
1258 stream->high.term_id = dp.term_id;
1259 stream->high.term_offset = dp.term_offset;
1263 rp.term_id = info->term_id;
1264 rp.term_offset = info->term_offset;
1267 if (rp.term_id > rcv->completed.term_id)
1269 rcv->completed.term_id = rp.term_id;
1270 rcv->completed.term_offset = rp.term_offset;
1272 else if (rp.term_offset > rcv->completed.term_offset)
1274 rcv->completed.term_offset = rp.term_offset;
1279 rcv->completed.term_id = rp.term_id;
1280 rcv->completed.term_offset = rp.term_offset;
1282 rcv->receiver_window = info->receiver_window;
1287 if (aeron_stream_analysis)
1289 if ((stream->flags & AERON_STREAM_FLAGS_HIGH_VALID) != 0)
1291 finfo->stream_analysis = wmem_new0(wmem_file_scope(), aeron_stream_analysis_t);
1294 if (finfo->stream_analysis != NULL)
1301 finfo->stream_analysis->high.term_id = stream->high.term_id;
1302 finfo->stream_analysis->high.term_offset = stream->high.term_offset;
1305 finfo->stream_analysis->flags2 |= AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID;
1306 finfo->stream_analysis->completed.term_id = rcv->completed.term_id;
1307 finfo->stream_analysis->completed.term_offset = rcv->completed.term_offset;
1308 finfo->stream_analysis->receiver_window = rcv->receiver_window;
1309 finfo->stream_analysis->outstanding_bytes = aeron_pos_delta(&(finfo->stream_analysis->high), &(finfo->stream_analysis->completed), stream->term_length);
1310 if (finfo->stream_analysis->outstanding_bytes >= finfo->stream_analysis->receiver_window)
1312 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL;
1317 finfo->stream_analysis->completed.term_id = 0;
1318 finfo->stream_analysis->completed.term_offset = 0;
1319 finfo->stream_analysis->receiver_window = 0;
1320 finfo->stream_analysis->outstanding_bytes = 0;
1332 /* We have a previous data position. */
1333 int rc = aeron_pos_compare(&dp, &pdp);
1336 /* Data position is the same as previous data position. */
1337 if (info->length == 0)
1339 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE;
1340 frame_flags |= AERON_FRAME_INFO_FLAGS_KEEPALIVE;
1346 /* Previous receiver position is valid */
1347 if (aeron_pos_compare(&dp, &prp) == 0)
1349 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1353 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_PACING_RX;
1358 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX;
1360 frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1365 aeron_pos_t expected_dp;
1368 expected_dp.term_id = pdp.term_id;
1369 expected_dp.term_offset = pdp.term_offset;
1370 aeron_pos_add_length(&expected_dp, info->length, stream->term_length);
1371 erc = aeron_pos_compare(&expected_dp, &dp);
1374 /* Could be OOO - but for now assume it's a RX */
1375 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_RX;
1376 frame_flags |= AERON_FRAME_INFO_FLAGS_RETRANSMISSION;
1377 aeron_frame_process_rx(info, finfo, term);
1381 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP;
1385 if (new_term && (info->term_offset == 0))
1387 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE;
1393 int rc = aeron_pos_compare(&rp, &prp);
1396 /* Completed term ID and term offset stayed the same. */
1397 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM;
1401 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_OOO_SM;
1403 if (cur_receiver_window != finfo->stream_analysis->receiver_window)
1405 finfo->stream_analysis->flags |= AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE;
1413 if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1415 aeron_fragment_t * fragment = NULL;
1417 fragment = aeron_term_fragment_find(term, info->term_offset);
1418 if (fragment == NULL)
1420 fragment = aeron_term_fragment_add(term, info->term_offset, info->length, info->data_length);
1422 aeron_fragment_frame_add(fragment, finfo, frame_flags, info->length);
1426 aeron_term_frame_add(term, finfo, frame_flags);
1430 static void aeron_frame_info_setup(packet_info * pinfo, aeron_transport_t * transport, aeron_packet_info_t * info, aeron_frame_info_t * finfo)
1432 if (transport != NULL)
1434 if (aeron_sequence_analysis && (finfo != NULL))
1436 if (PINFO_FD_VISITED(pinfo) == 0)
1438 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1440 aeron_stream_t * stream = NULL;
1442 stream = aeron_transport_stream_find(transport, info->stream_id);
1445 stream = aeron_transport_stream_add(transport, info->stream_id);
1447 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1449 aeron_term_t * term = NULL;
1450 gboolean new_term = FALSE;
1452 term = aeron_stream_term_find(stream, info->term_id);
1455 term = aeron_stream_term_add(stream, info->term_id);
1458 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1460 aeron_frame_stream_analysis_setup(pinfo, info, finfo, stream, term, new_term);
1464 aeron_term_frame_add(term, finfo, 0);
1465 if (info->type == HDR_TYPE_NAK)
1467 aeron_frame_nak_analysis_setup(info, finfo, term);
1473 aeron_stream_frame_add(stream, finfo, 0);
1478 aeron_transport_frame_add(transport, finfo, 0);
1485 static void aeron_sequence_report_frame(tvbuff_t * tvb, proto_tree * tree, aeron_frame_info_t * finfo)
1487 proto_item * item = NULL;
1489 if ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0)
1491 item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" G_GUINT32_FORMAT " (RX)", finfo->frame);
1493 else if ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0)
1495 item = proto_tree_add_uint_format_value(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame, "%" G_GUINT32_FORMAT " (KA)", finfo->frame);
1499 item = proto_tree_add_uint(tree, hf_aeron_sequence_analysis_term_offset_frame, tvb, 0, 0, finfo->frame);
1501 PROTO_ITEM_SET_GENERATED(item);
1504 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)
1506 if (transport != NULL)
1508 if (aeron_sequence_analysis && (finfo != NULL))
1510 proto_tree * subtree = NULL;
1511 proto_item * item = NULL;
1513 item = proto_tree_add_item(tree, hf_aeron_sequence_analysis, tvb, 0, 0, ENC_NA);
1514 PROTO_ITEM_SET_GENERATED(item);
1515 subtree = proto_item_add_subtree(item, ett_aeron_sequence_analysis);
1516 if (finfo->transport.previous != 0)
1518 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_prev_frame, tvb, 0, 0, finfo->transport.previous);
1519 PROTO_ITEM_SET_GENERATED(item);
1521 if (finfo->transport.next != 0)
1523 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_channel_next_frame, tvb, 0, 0, finfo->transport.next);
1524 PROTO_ITEM_SET_GENERATED(item);
1526 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID) != 0)
1528 aeron_stream_t * stream = NULL;
1530 stream = aeron_transport_stream_find(transport, info->stream_id);
1533 if (finfo->stream.previous != 0)
1535 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_prev_frame, tvb, 0, 0, finfo->stream.previous);
1536 PROTO_ITEM_SET_GENERATED(item);
1538 if (finfo->stream.next != 0)
1540 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_stream_next_frame, tvb, 0, 0, finfo->stream.next);
1541 PROTO_ITEM_SET_GENERATED(item);
1543 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_ID_VALID) != 0)
1545 aeron_term_t * term = NULL;
1547 term = aeron_stream_term_find(stream, info->term_id);
1550 if (finfo->term.previous != 0)
1552 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_prev_frame, tvb, 0, 0, finfo->term.previous);
1553 PROTO_ITEM_SET_GENERATED(item);
1555 if (finfo->term.next != 0)
1557 item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_term_next_frame, tvb, 0, 0, finfo->term.next);
1558 PROTO_ITEM_SET_GENERATED(item);
1560 if ((info->info_flags & AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID) != 0)
1562 if ((info->type == HDR_TYPE_DATA) || (info->type == HDR_TYPE_PAD))
1564 aeron_fragment_t * fragment = NULL;
1566 fragment = aeron_term_fragment_find(term, info->term_offset);
1567 if (fragment != NULL)
1569 proto_item * fei_item = NULL;
1570 gboolean rx = ((finfo->flags & AERON_FRAME_INFO_FLAGS_RETRANSMISSION) != 0);
1571 gboolean ka = ((finfo->flags & AERON_FRAME_INFO_FLAGS_KEEPALIVE) != 0);
1573 if (fragment->frame_count > 1)
1575 proto_tree * frame_tree = NULL;
1576 proto_item * frame_item = NULL;
1577 wmem_list_frame_t * lf = NULL;
1579 frame_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_term_offset, tvb, 0, 0, ENC_NA);
1580 PROTO_ITEM_SET_GENERATED(frame_item);
1581 frame_tree = proto_item_add_subtree(frame_item, ett_aeron_sequence_analysis_term_offset);
1582 lf = wmem_list_head(fragment->frame);
1585 aeron_frame_info_t * frag_frame = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1586 if (frag_frame != NULL)
1588 if (frag_frame->frame != pinfo->fd->num)
1590 aeron_sequence_report_frame(tvb, frame_tree, frag_frame);
1593 lf = wmem_list_frame_next(lf);
1596 fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_retransmission, tvb, 0, 0, rx);
1597 PROTO_ITEM_SET_GENERATED(fei_item);
1600 if (wmem_list_count(finfo->rx) > 0)
1602 proto_tree * rx_tree = NULL;
1603 proto_item * rx_item = NULL;
1604 wmem_list_frame_t * lf = NULL;
1606 rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_retransmission_rx, tvb, 0, 0, ENC_NA);
1607 PROTO_ITEM_SET_GENERATED(rx_item);
1608 rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_retransmission_rx);
1609 lf = wmem_list_head(finfo->rx);
1612 aeron_frame_info_t * nak = (aeron_frame_info_t *) wmem_list_frame_data(lf);
1615 rx_item = proto_tree_add_uint(rx_tree, hf_aeron_sequence_analysis_retransmission_rx_frame, tvb, 0, 0, nak->frame);
1616 PROTO_ITEM_SET_GENERATED(rx_item);
1618 lf = wmem_list_frame_next(lf);
1622 fei_item = proto_tree_add_boolean(subtree, hf_aeron_sequence_analysis_keepalive, tvb, 0, 0, ka);
1623 PROTO_ITEM_SET_GENERATED(fei_item);
1627 else if ((info->type == HDR_TYPE_NAK) && (finfo->nak_analysis != NULL))
1629 proto_item * nak_item = NULL;
1631 nak_item = proto_tree_add_uint(subtree, hf_aeron_sequence_analysis_nak_unrecovered, tvb, 0, 0, finfo->nak_analysis->unrecovered_length);
1632 PROTO_ITEM_SET_GENERATED(nak_item);
1633 if (wmem_list_count(finfo->nak_analysis->rx) > 0)
1635 proto_tree * rx_tree = NULL;
1636 proto_item * rx_item = NULL;
1637 wmem_list_frame_t * lf = NULL;
1639 rx_item = proto_tree_add_item(subtree, hf_aeron_sequence_analysis_nak_rx, tvb, 0, 0, ENC_NA);
1640 PROTO_ITEM_SET_GENERATED(rx_item);
1641 rx_tree = proto_item_add_subtree(rx_item, ett_aeron_sequence_analysis_nak_rx);
1642 lf = wmem_list_head(finfo->nak_analysis->rx);
1645 aeron_rx_info_t * rx = (aeron_rx_info_t *) wmem_list_frame_data(lf);
1648 rx_item = proto_tree_add_uint_format_value(rx_tree, hf_aeron_sequence_analysis_nak_rx_frame, tvb, 0, 0, rx->frame_info->frame,
1649 "%" G_GUINT32_FORMAT ", Term offset=%" G_GUINT32_FORMAT " (0x%08x), Length=%" G_GUINT32_FORMAT, rx->frame_info->frame, rx->term_offset, rx->term_offset, rx->length);
1650 PROTO_ITEM_SET_GENERATED(rx_item);
1652 lf = wmem_list_frame_next(lf);
1664 static void aeron_stream_report(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, aeron_transport_t * transport, aeron_frame_info_t * finfo)
1666 if (transport != NULL)
1668 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1670 proto_tree * subtree = NULL;
1671 proto_item * item = NULL;
1673 item = proto_tree_add_item(tree, hf_aeron_stream_analysis, tvb, 0, 0, ENC_NA);
1674 PROTO_ITEM_SET_GENERATED(item);
1675 subtree = proto_item_add_subtree(item, ett_aeron_stream_analysis);
1676 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_id, tvb, 0, 0, finfo->stream_analysis->high.term_id);
1677 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_TERM_ID_CHANGE) != 0)
1679 expert_add_info(pinfo, item, &ei_aeron_analysis_term_id_change);
1681 PROTO_ITEM_SET_GENERATED(item);
1682 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_high_term_offset, tvb, 0, 0, finfo->stream_analysis->high.term_offset);
1683 PROTO_ITEM_SET_GENERATED(item);
1684 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_IDLE_RX) != 0)
1686 expert_add_info(pinfo, item, &ei_aeron_analysis_idle_rx);
1688 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_PACING_RX) != 0)
1690 expert_add_info(pinfo, item, &ei_aeron_analysis_pacing_rx);
1692 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO) != 0)
1694 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo);
1696 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_GAP) != 0)
1698 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_gap);
1700 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1702 expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive);
1704 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_RX) != 0)
1706 expert_add_info(pinfo, item, &ei_aeron_analysis_rx);
1708 if ((finfo->stream_analysis->flags2 & AERON_STREAM_ANALYSIS_FLAGS2_RCV_VALID) != 0)
1710 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_id, tvb, 0, 0, finfo->stream_analysis->completed.term_id);
1711 PROTO_ITEM_SET_GENERATED(item);
1712 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_completed_term_offset, tvb, 0, 0, finfo->stream_analysis->completed.term_offset);
1713 PROTO_ITEM_SET_GENERATED(item);
1714 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_OOO_SM) != 0)
1716 expert_add_info(pinfo, item, &ei_aeron_analysis_ooo_sm);
1718 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1720 expert_add_info(pinfo, item, &ei_aeron_analysis_keepalive_sm);
1722 item = proto_tree_add_uint(subtree, hf_aeron_stream_analysis_outstanding_bytes, tvb, 0, 0, finfo->stream_analysis->outstanding_bytes);
1723 PROTO_ITEM_SET_GENERATED(item);
1724 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_FULL) != 0)
1726 expert_add_info(pinfo, item, &ei_aeron_analysis_window_full);
1733 static void aeron_next_offset_report(tvbuff_t * tvb, proto_tree * tree, aeron_transport_t * transport, guint32 stream_id, guint32 term_id, guint32 term_offset, guint32 length)
1735 aeron_stream_t * stream = NULL;
1736 proto_item * item = NULL;
1738 stream = aeron_transport_stream_find(transport, stream_id);
1741 aeron_term_t * term = NULL;
1742 if (stream->term_length == 0)
1744 stream->term_length = length;
1746 term = aeron_stream_term_find(stream, term_id);
1749 aeron_fragment_t * fragment = aeron_term_fragment_find(term, term_offset);
1750 if (fragment != NULL)
1752 guint32 next_offset = term_offset + length;
1753 guint32 next_offset_term_id = term_id;
1754 guint32 next_offset_first_frame = 0;
1755 aeron_fragment_t * next_offset_fragment = NULL;
1756 aeron_term_t * next_offset_term = NULL;
1758 if (next_offset >= stream->term_length)
1761 next_offset_term_id++;
1763 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset, tvb, 0, 0, next_offset);
1764 PROTO_ITEM_SET_GENERATED(item);
1765 if (next_offset_term_id != term_id)
1767 next_offset_term = aeron_stream_term_find(stream, next_offset_term_id);
1768 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_term, tvb, 0, 0, next_offset_term_id);
1769 PROTO_ITEM_SET_GENERATED(item);
1773 next_offset_term = term;
1775 if (next_offset_term != NULL)
1777 next_offset_fragment = aeron_term_fragment_find(next_offset_term, next_offset);
1778 if (next_offset_fragment != NULL)
1780 if (next_offset_fragment->first_frame != NULL)
1782 next_offset_first_frame = next_offset_fragment->first_frame->frame;
1783 item = proto_tree_add_uint(tree, hf_aeron_data_next_offset_first_frame, tvb, 0, 0, next_offset_first_frame);
1784 PROTO_ITEM_SET_GENERATED(item);
1793 static void aeron_info_stream_progress_report(packet_info * pinfo, guint16 msgtype, guint8 flags, guint32 term_id, guint32 term_offset, aeron_frame_info_t * finfo)
1795 const gchar * type_string = val_to_str_const((guint32) msgtype, aeron_frame_type, "Unknown");
1797 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
1803 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE) != 0)
1805 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1809 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" G_GUINT32_FORMAT ")",
1810 type_string, term_id, term_offset);
1814 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_KEEPALIVE_SM) != 0)
1816 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-KA", type_string);
1820 if (finfo->stream_analysis->high.term_id == finfo->stream_analysis->completed.term_id)
1822 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (%" G_GUINT32_FORMAT "/%" G_GUINT32_FORMAT " [%" G_GUINT32_FORMAT "])",
1823 type_string, finfo->stream_analysis->high.term_offset, finfo->stream_analysis->completed.term_offset, finfo->stream_analysis->outstanding_bytes);
1827 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s (0x%08x:%" G_GUINT32_FORMAT "/0x%08x:%" G_GUINT32_FORMAT " [%" G_GUINT32_FORMAT "])",
1828 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);
1836 if ((msgtype == HDR_TYPE_SM) && ((flags & STATUS_FLAGS_SETUP) != 0))
1838 col_append_sep_fstr(pinfo->cinfo, COL_INFO, ", ", "%s-SETUP", type_string);
1842 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", type_string);
1847 /*----------------------------------------------------------------------------*/
1848 /* Payload reassembly. */
1849 /*----------------------------------------------------------------------------*/
1850 struct aeron_msg_fragment_t_stct;
1851 typedef struct aeron_msg_fragment_t_stct aeron_msg_fragment_t;
1853 struct aeron_msg_t_stct
1855 wmem_list_t * fragment;
1856 aeron_term_t * term;
1857 tvbuff_t * reassembled_data;
1858 guint32 first_fragment_term_offset;
1859 guint32 next_expected_term_offset;
1860 guint32 length; /* Total message payload length */
1861 guint32 frame_length; /* Total length of all message frames accumulated */
1862 guint32 fragment_count; /* Number of fragments in this message */
1863 guint32 contiguous_length; /* Number of contiguous frame bytes accumulated for this message */
1864 guint32 begin_frame; /* Data frame in which the B flag was set */
1865 guint32 first_frame; /* Lowest-numbered frame which is part of this message */
1866 guint32 end_frame; /* Data frame in which the E flag was set */
1867 guint32 last_frame; /* Highest-numbered frame which is part of this message */
1871 struct aeron_msg_fragment_t_stct
1874 guint32 term_offset; /* Term offset for entire fragment */
1875 guint32 frame_length; /* Length of entire frame/fragment */
1876 guint32 data_length; /* Payload length */
1877 guint32 frame; /* Frame in which the fragment resides */
1878 gint frame_offset; /* Offset into the frame for the entire Aeron message */
1879 guint8 flags; /* Frame data flags */
1882 static void aeron_msg_fragment_add(aeron_msg_t * msg, aeron_msg_fragment_t * fragment)
1884 /* Add the fragment to the message */
1885 wmem_list_append(msg->fragment, (void *) fragment);
1886 /* Update the message */
1887 msg->length += fragment->data_length;
1888 msg->contiguous_length += fragment->data_length;
1889 msg->fragment_count++;
1890 if (msg->first_frame > fragment->frame)
1892 msg->first_frame = fragment->frame;
1894 if (msg->last_frame < fragment->frame)
1896 msg->last_frame = fragment->frame;
1898 msg->next_expected_term_offset += fragment->frame_length;
1899 if ((fragment->flags & DATA_FLAGS_END) == DATA_FLAGS_END)
1902 wmem_list_frame_t * lf = NULL;
1904 size_t accum_len = 0;
1905 guint32 last_frame_offset = 0;
1906 gboolean last_frame_found = FALSE;
1907 aeron_frame_info_t * finfo = NULL;
1909 msg->complete = TRUE;
1910 msg->end_frame = fragment->frame;
1911 buf = (gchar *) wmem_alloc(wmem_file_scope(), (size_t) msg->length);
1912 lf = wmem_list_head(msg->fragment);
1915 aeron_msg_fragment_t * cur_frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
1916 if (cur_frag != NULL)
1918 if (cur_frag->frame == msg->last_frame)
1920 last_frame_offset = cur_frag->frame_offset;
1921 last_frame_found = TRUE;
1923 memcpy((void *) (buf + ofs), (void *) cur_frag->data, (size_t) cur_frag->data_length);
1924 ofs += (size_t) cur_frag->data_length;
1925 accum_len += (size_t) cur_frag->data_length;
1927 lf = wmem_list_frame_next(lf);
1929 DISSECTOR_ASSERT(accum_len == (size_t) msg->length);
1930 DISSECTOR_ASSERT(last_frame_found == TRUE);
1931 if (last_frame_found)
1933 finfo = aeron_frame_info_find(msg->last_frame, last_frame_offset);
1935 msg->reassembled_data = tvb_new_real_data(buf, msg->length, msg->length);
1936 DISSECTOR_ASSERT(finfo != NULL);
1939 finfo->flags |= AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG;
1940 finfo->message = msg;
1945 static gboolean aeron_msg_process_orphan_fragments_msg_cb(void * value, void * userdata)
1947 aeron_msg_t * msg = (aeron_msg_t *) value;
1948 aeron_term_t * term = (aeron_term_t *) userdata;
1949 gboolean frag_found = FALSE;
1950 wmem_list_frame_t * lf = NULL;
1951 aeron_msg_fragment_t * frag = NULL;
1955 /* This message is complete, no need to check for orphans */
1958 /* Scan through the orphan fragments */
1961 lf = wmem_list_head(term->orphan_fragment);
1964 frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
1967 if (msg->next_expected_term_offset == frag->term_offset)
1969 /* Found one! Remove it from the orphan list, and add it to the message */
1970 wmem_list_remove_frame(term->orphan_fragment, lf);
1971 aeron_msg_fragment_add(msg, frag);
1976 lf = wmem_list_frame_next(lf);
1987 static void aeron_msg_process_orphan_fragments(aeron_term_t * term)
1989 /* If we have no orphan fragments to process, nothing to do. */
1990 if (wmem_list_count(term->orphan_fragment) == 0)
1994 wmem_tree_foreach(term->message, aeron_msg_process_orphan_fragments_msg_cb, (void *) term);
1997 static aeron_msg_fragment_t * aeron_msg_fragment_create(tvbuff_t * tvb, int offset, packet_info * pinfo, aeron_packet_info_t * info)
1999 aeron_msg_fragment_t * frag = NULL;
2001 frag = wmem_new0(wmem_file_scope(), aeron_msg_fragment_t);
2002 frag->term_offset = info->term_offset;
2003 frag->frame_length = info->length;
2004 frag->data_length = info->data_length;
2005 frag->frame = pinfo->fd->num;
2006 frag->frame_offset = offset;
2007 frag->data = (gchar *) tvb_memdup(wmem_file_scope(), tvb, frag->frame_offset + O_AERON_DATA_DATA, (size_t) frag->data_length);
2008 frag->flags = info->flags;
2012 static aeron_msg_fragment_t * aeron_msg_fragment_find(aeron_msg_t * message, aeron_packet_info_t * info)
2014 aeron_msg_fragment_t * frag = NULL;
2015 wmem_list_frame_t * lf = NULL;
2017 if (message->next_expected_term_offset < info->term_offset)
2021 lf = wmem_list_head(message->fragment);
2024 frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2027 if (frag->term_offset == info->term_offset)
2032 lf = wmem_list_frame_next(lf);
2037 static aeron_msg_t * aeron_term_msg_find_le(aeron_term_t * term, guint32 term_offset)
2039 /* Return the last aeron_msg_t with starting_fragment_term_offset <= offset */
2040 aeron_msg_t * msg = (aeron_msg_t *) wmem_tree_lookup32_le(term->message, term_offset);
2044 static aeron_msg_t * aeron_term_msg_add(aeron_term_t * term, packet_info * pinfo, aeron_packet_info_t * info)
2046 aeron_msg_t * pos = NULL;
2047 aeron_msg_t * msg = NULL;
2049 pos = aeron_term_msg_find_le(term, info->term_offset);
2050 if ((pos != NULL) && (pos->first_fragment_term_offset == info->term_offset))
2054 msg = wmem_new0(wmem_file_scope(), aeron_msg_t);
2055 msg->fragment = wmem_list_new(wmem_file_scope());
2057 msg->reassembled_data = NULL;
2058 msg->first_fragment_term_offset = info->term_offset;
2059 msg->next_expected_term_offset = info->term_offset;
2061 msg->frame_length = 0;
2062 msg->fragment_count = 0;
2063 msg->contiguous_length = 0;
2064 msg->begin_frame = pinfo->fd->num;
2065 msg->first_frame = pinfo->fd->num;
2067 msg->last_frame = 0;
2068 msg->complete = FALSE;
2069 wmem_tree_insert32(term->message, msg->first_fragment_term_offset, (void *) msg);
2073 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_)
2075 if (aeron_reassemble_fragments && (PINFO_FD_VISITED(pinfo) == 0))
2077 if ((info->flags & DATA_FLAGS_COMPLETE) != DATA_FLAGS_COMPLETE)
2079 aeron_stream_t * stream = aeron_transport_stream_find(transport, info->stream_id);
2082 aeron_term_t * term = aeron_stream_term_find(stream, info->term_id);
2085 aeron_msg_t * msg = NULL;
2086 aeron_msg_fragment_t * frag = NULL;
2088 if ((info->flags & DATA_FLAGS_BEGIN) == DATA_FLAGS_BEGIN)
2090 /* Beginning of a message. First see if this message already exists. */
2091 msg = aeron_term_msg_find_le(term, info->term_offset);
2094 if (msg->first_fragment_term_offset != info->term_offset)
2097 A message start with a term offset:
2098 1) Between two existing messages for this term, or
2099 2) Less than the first message for this term
2100 Likely this was caused by an RX or out-of-order packet. Need to create a new one.
2107 msg = aeron_term_msg_add(term, pinfo, info);
2112 /* End of message, or middle of message. See if we already have a message with a smaller starting term offset */
2113 msg = aeron_term_msg_find_le(term, info->term_offset);
2116 /* Is this the next expexted term offset? */
2117 if (msg->next_expected_term_offset == info->term_offset)
2119 /* Yes - we can add the fragment to the message */
2123 /* Do we already have this fragment? */
2124 frag = aeron_msg_fragment_find(msg, info);
2127 /* Already have it, so nothing to do */
2132 /* Not the next fragment, so no known message associated with it. */
2138 /* Create the fragment */
2139 frag = aeron_msg_fragment_create(tvb, offset, pinfo, info);
2142 /* Add the fragment to the list of orphaned fragments */
2143 wmem_list_append(term->orphan_fragment, (void *) frag);
2147 /* Add the fragment to the message */
2148 aeron_msg_fragment_add(msg, frag);
2150 /* Process the orphan list */
2151 aeron_msg_process_orphan_fragments(term);
2158 /*----------------------------------------------------------------------------*/
2159 /* Aeron pad message packet dissection functions. */
2160 /*----------------------------------------------------------------------------*/
2161 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)
2163 proto_tree * subtree = NULL;
2164 proto_item * item = NULL;
2165 proto_item * channel_item = NULL;
2166 guint32 frame_length;
2168 aeron_transport_t * transport;
2172 guint32 term_offset;
2173 int rounded_length = 0;
2174 aeron_packet_info_t pktinfo;
2176 frame_length = tvb_get_letohl(tvb, offset + O_AERON_PAD_FRAME_LENGTH);
2177 rounded_length = (int) aeron_pos_roundup(frame_length);
2178 term_offset = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_OFFSET);
2179 session_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_SESSION_ID);
2180 transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
2181 stream_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_STREAM_ID);
2182 term_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_ID);
2183 pad_length = frame_length - L_AERON_PAD;
2184 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2185 pktinfo.stream_id = stream_id;
2186 pktinfo.term_id = term_id;
2187 pktinfo.term_offset = term_offset;
2188 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2189 pktinfo.length = frame_length;
2190 pktinfo.data_length = pad_length;
2191 pktinfo.type = HDR_TYPE_PAD;
2192 pktinfo.flags = tvb_get_guint8(tvb, offset + O_AERON_PAD_FLAGS);
2193 aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo);
2195 aeron_info_stream_progress_report(pinfo, HDR_TYPE_PAD, pktinfo.flags, term_id, term_offset, finfo);
2196 item = proto_tree_add_none_format(tree, hf_aeron_pad, tvb, offset, -1, "Pad Frame: Term 0x%x, Ofs %" G_GUINT32_FORMAT ", Len %" G_GUINT32_FORMAT "(%d)",
2197 term_id, term_offset, frame_length, rounded_length);
2198 subtree = proto_item_add_subtree(item, ett_aeron_pad);
2199 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2200 PROTO_ITEM_SET_GENERATED(channel_item);
2201 proto_tree_add_item(subtree, hf_aeron_pad_frame_length, tvb, offset + O_AERON_PAD_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2202 proto_tree_add_item(subtree, hf_aeron_pad_version, tvb, offset + O_AERON_PAD_VERSION, 1, ENC_LITTLE_ENDIAN);
2203 proto_tree_add_item(subtree, hf_aeron_pad_flags, tvb, offset + O_AERON_PAD_FLAGS, 1, ENC_LITTLE_ENDIAN);
2204 proto_tree_add_item(subtree, hf_aeron_pad_type, tvb, offset + O_AERON_PAD_TYPE, 2, ENC_LITTLE_ENDIAN);
2205 proto_tree_add_item(subtree, hf_aeron_pad_term_offset, tvb, offset + O_AERON_PAD_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2206 aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, (guint32) rounded_length);
2207 proto_tree_add_item(subtree, hf_aeron_pad_session_id, tvb, offset + O_AERON_PAD_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2208 proto_tree_add_item(subtree, hf_aeron_pad_stream_id, tvb, offset + O_AERON_PAD_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2209 proto_tree_add_item(subtree, hf_aeron_pad_term_id, tvb, offset + O_AERON_PAD_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2210 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2211 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2212 proto_item_set_len(item, L_AERON_PAD);
2213 return (L_AERON_PAD);
2216 /*----------------------------------------------------------------------------*/
2217 /* Aeron data message packet dissection functions. */
2218 /*----------------------------------------------------------------------------*/
2219 static void dissect_aeron_reassembled_data(packet_info * pinfo, proto_tree * tree, aeron_frame_info_t * finfo)
2221 proto_item * frag_item = NULL;
2222 proto_tree * frag_tree = NULL;
2223 proto_item * pi = NULL;
2224 aeron_msg_t * msg = NULL;
2225 wmem_list_frame_t * lf = NULL;
2226 gboolean first_item = TRUE;
2227 guint32 msg_ofs = 0;
2229 if (finfo->message == NULL)
2233 msg = finfo->message;
2234 add_new_data_source(pinfo, msg->reassembled_data, "Reassembled Data");
2235 frag_item = proto_tree_add_none_format(tree,
2236 hf_aeron_data_reassembly,
2237 msg->reassembled_data,
2239 tvb_reported_length_remaining(msg->reassembled_data, 0),
2240 "%" G_GUINT32_FORMAT " Reassembled Fragments (%" G_GUINT32_FORMAT " bytes):",
2241 msg->fragment_count,
2243 frag_tree = proto_item_add_subtree(frag_item, ett_aeron_data_reassembly);
2244 lf = wmem_list_head(msg->fragment);
2247 aeron_msg_fragment_t * frag = (aeron_msg_fragment_t *) wmem_list_frame_data(lf);
2250 pi = proto_tree_add_uint_format_value(frag_tree,
2251 hf_aeron_data_reassembly_fragment,
2252 msg->reassembled_data,
2256 "Frame: %" G_GUINT32_FORMAT ", payload: %" G_GUINT32_FORMAT "-%" G_GUINT32_FORMAT " (%" G_GUINT32_FORMAT " bytes)",
2259 (msg_ofs + frag->data_length) - 1,
2261 PROTO_ITEM_SET_GENERATED(pi);
2264 proto_item_append_text(frag_item, " #%" G_GUINT32_FORMAT "(%" G_GUINT32_FORMAT ")", frag->frame, frag->data_length);
2268 proto_item_append_text(frag_item, ", #%" G_GUINT32_FORMAT "(%" G_GUINT32_FORMAT ")", frag->frame, frag->data_length);
2270 msg_ofs += frag->data_length;
2273 lf = wmem_list_frame_next(lf);
2275 PROTO_ITEM_SET_GENERATED(frag_item);
2278 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)
2280 proto_tree * subtree = NULL;
2281 proto_item * item = NULL;
2282 guint32 frame_length;
2283 static const int * flags[] =
2285 &hf_aeron_data_flags_b,
2286 &hf_aeron_data_flags_e,
2289 aeron_transport_t * transport;
2293 guint32 term_offset;
2294 guint32 data_length;
2295 int rounded_length = 0;
2296 aeron_packet_info_t pktinfo;
2297 guint32 offset_increment = 0;
2299 frame_length = tvb_get_letohl(tvb, offset + O_AERON_DATA_FRAME_LENGTH);
2300 if (frame_length == 0)
2302 rounded_length = O_AERON_DATA_DATA;
2304 offset_increment = 0;
2308 offset_increment = aeron_pos_roundup(frame_length);
2309 rounded_length = (int) offset_increment;
2310 data_length = frame_length - O_AERON_DATA_DATA;
2312 term_offset = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_OFFSET);
2313 session_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_SESSION_ID);
2314 transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
2315 stream_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_STREAM_ID);
2316 term_id = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_ID);
2317 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2318 pktinfo.stream_id = stream_id;
2319 pktinfo.term_id = term_id;
2320 pktinfo.term_offset = term_offset;
2321 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID;
2322 pktinfo.length = frame_length;
2323 pktinfo.data_length = data_length;
2324 pktinfo.type = HDR_TYPE_DATA;
2325 pktinfo.flags = tvb_get_guint8(tvb, offset + O_AERON_DATA_FLAGS);
2326 aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo);
2328 aeron_info_stream_progress_report(pinfo, HDR_TYPE_DATA, pktinfo.flags, term_id, term_offset, finfo);
2329 item = proto_tree_add_none_format(tree, hf_aeron_data, tvb, offset, -1, "Data Frame: Term 0x%x, Ofs %" G_GUINT32_FORMAT ", Len %" G_GUINT32_FORMAT "(%d)",
2330 (guint32) term_id, term_offset, frame_length, rounded_length);
2331 subtree = proto_item_add_subtree(item, ett_aeron_data);
2332 item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2333 PROTO_ITEM_SET_GENERATED(item);
2334 proto_tree_add_item(subtree, hf_aeron_data_frame_length, tvb, offset + O_AERON_DATA_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2335 proto_tree_add_item(subtree, hf_aeron_data_version, tvb, offset + O_AERON_DATA_VERSION, 1, ENC_LITTLE_ENDIAN);
2336 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_DATA_FLAGS, hf_aeron_data_flags, ett_aeron_data_flags, flags, ENC_LITTLE_ENDIAN);
2337 proto_tree_add_item(subtree, hf_aeron_data_type, tvb, offset + O_AERON_DATA_TYPE, 2, ENC_LITTLE_ENDIAN);
2338 proto_tree_add_item(subtree, hf_aeron_data_term_offset, tvb, offset + O_AERON_DATA_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2339 aeron_next_offset_report(tvb, subtree, transport, stream_id, term_id, term_offset, offset_increment);
2340 proto_tree_add_item(subtree, hf_aeron_data_session_id, tvb, offset + O_AERON_DATA_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2341 proto_tree_add_item(subtree, hf_aeron_data_stream_id, tvb, offset + O_AERON_DATA_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2342 proto_tree_add_item(subtree, hf_aeron_data_term_id, tvb, offset + O_AERON_DATA_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2343 if (data_length > 0)
2345 tvbuff_t * data_tvb = NULL;
2346 gboolean can_call_subdissector = FALSE;
2347 gboolean dissector_found = FALSE;
2348 heur_dtbl_entry_t * hdtbl_entry;
2350 aeron_msg_process(tvb, offset, pinfo, transport, &pktinfo, finfo);
2351 if ((pktinfo.flags & DATA_FLAGS_COMPLETE) == DATA_FLAGS_COMPLETE)
2353 can_call_subdissector = TRUE;
2357 if ((finfo->flags & AERON_FRAME_INFO_FLAGS_REASSEMBLED_MSG) != 0)
2359 dissect_aeron_reassembled_data(pinfo, subtree, finfo);
2360 data_tvb = finfo->message->reassembled_data;
2361 can_call_subdissector = TRUE;
2365 data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2370 data_tvb = tvb_new_subset_length(tvb, offset + O_AERON_DATA_DATA, data_length);
2372 if (can_call_subdissector && aeron_use_heuristic_subdissectors)
2374 dissector_found = dissector_try_heuristic(aeron_heuristic_subdissector_list, data_tvb, pinfo, subtree, &hdtbl_entry, NULL);
2376 if (!dissector_found)
2378 call_dissector(aeron_data_dissector_handle, data_tvb, pinfo, subtree);
2381 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2382 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2383 proto_item_set_len(item, rounded_length);
2384 return (rounded_length);
2387 /*----------------------------------------------------------------------------*/
2388 /* Aeron NAK packet dissection functions. */
2389 /*----------------------------------------------------------------------------*/
2390 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)
2392 proto_tree * subtree = NULL;
2393 proto_item * item = NULL;
2394 proto_item * channel_item = NULL;
2395 proto_item * nak_item = NULL;
2396 guint32 frame_length;
2397 aeron_transport_t * transport;
2401 guint32 nak_term_offset;
2403 int rounded_length = 0;
2404 aeron_packet_info_t pktinfo;
2406 frame_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_FRAME_LENGTH);
2407 rounded_length = (int) aeron_pos_roundup(frame_length);
2408 session_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_SESSION_ID);
2409 transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
2410 stream_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_STREAM_ID);
2411 term_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_ID);
2412 nak_term_offset = tvb_get_letohl(tvb, offset + O_AERON_NAK_TERM_OFFSET);
2413 nak_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_LENGTH);
2414 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2415 pktinfo.stream_id = stream_id;
2416 pktinfo.term_id = term_id;
2417 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2418 pktinfo.nak_term_offset = nak_term_offset;
2419 pktinfo.nak_length = nak_length;
2420 pktinfo.type = HDR_TYPE_NAK;
2421 pktinfo.flags = tvb_get_guint8(tvb, offset + O_AERON_NAK_FLAGS);
2422 aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo);
2424 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "NAK");
2425 item = proto_tree_add_none_format(tree, hf_aeron_nak, tvb, offset, -1, "NAK Frame: Term 0x%x, Ofs %" G_GUINT32_FORMAT ", Len %" G_GUINT32_FORMAT,
2426 term_id, nak_term_offset, nak_length);
2427 subtree = proto_item_add_subtree(item, ett_aeron_nak);
2428 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2429 PROTO_ITEM_SET_GENERATED(channel_item);
2430 proto_tree_add_item(subtree, hf_aeron_nak_frame_length, tvb, offset + O_AERON_NAK_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2431 proto_tree_add_item(subtree, hf_aeron_nak_version, tvb, offset + O_AERON_NAK_VERSION, 1, ENC_LITTLE_ENDIAN);
2432 proto_tree_add_item(subtree, hf_aeron_nak_flags, tvb, offset + O_AERON_NAK_FLAGS, 1, ENC_LITTLE_ENDIAN);
2433 proto_tree_add_item(subtree, hf_aeron_nak_type, tvb, offset + O_AERON_NAK_TYPE, 2, ENC_LITTLE_ENDIAN);
2434 proto_tree_add_item(subtree, hf_aeron_nak_session_id, tvb, offset + O_AERON_NAK_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2435 proto_tree_add_item(subtree, hf_aeron_nak_stream_id, tvb, offset + O_AERON_NAK_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2436 proto_tree_add_item(subtree, hf_aeron_nak_term_id, tvb, offset + O_AERON_NAK_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2437 nak_item = proto_tree_add_item(subtree, hf_aeron_nak_term_offset, tvb, offset + O_AERON_NAK_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2438 proto_tree_add_item(subtree, hf_aeron_nak_length, tvb, offset + O_AERON_NAK_LENGTH, 4, ENC_LITTLE_ENDIAN);
2439 expert_add_info_format(pinfo, nak_item, &ei_aeron_analysis_nak, "NAK offset %" G_GUINT32_FORMAT " length %" G_GUINT32_FORMAT, nak_term_offset, nak_length);
2440 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2441 proto_item_set_len(item, rounded_length);
2442 return (rounded_length);
2445 /*----------------------------------------------------------------------------*/
2446 /* Aeron status message packet dissection functions. */
2447 /*----------------------------------------------------------------------------*/
2448 static void aeron_window_resize_report(packet_info * pinfo, proto_item * item, aeron_frame_info_t * finfo)
2450 if (aeron_sequence_analysis && aeron_stream_analysis && (finfo != NULL) && (finfo->stream_analysis != NULL))
2452 if ((finfo->stream_analysis->flags & AERON_STREAM_ANALYSIS_FLAGS_WINDOW_RESIZE) != 0)
2454 expert_add_info(pinfo, item, &ei_aeron_analysis_window_resize);
2459 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)
2461 proto_tree * subtree = NULL;
2462 proto_item * item = NULL;
2463 proto_item * channel_item = NULL;
2464 guint32 frame_length;
2465 static const int * flags[] =
2467 &hf_aeron_sm_flags_s,
2470 guint32 feedback_length;
2471 aeron_transport_t * transport;
2475 guint32 consumption_offset;
2477 int rounded_length = 0;
2478 aeron_packet_info_t pktinfo;
2480 frame_length = tvb_get_letohl(tvb, offset + O_AERON_SM_FRAME_LENGTH);
2481 feedback_length = frame_length - O_AERON_SM_FEEDBACK;
2482 rounded_length = (int) aeron_pos_roundup(frame_length);
2483 session_id = tvb_get_letohl(tvb, offset + O_AERON_SM_SESSION_ID);
2484 transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
2485 stream_id = tvb_get_letohl(tvb, offset + O_AERON_SM_STREAM_ID);
2486 term_id = tvb_get_letohl(tvb, offset + O_AERON_SM_TERM_ID);
2487 consumption_offset = tvb_get_letohl(tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET);
2488 rcv_window = tvb_get_letohl(tvb, offset + O_AERON_SM_RECEIVER_WINDOW);
2489 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2490 pktinfo.stream_id = stream_id;
2491 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID;
2492 pktinfo.flags = tvb_get_guint8(tvb, offset + O_AERON_SM_FLAGS);
2493 if ((pktinfo.flags & STATUS_FLAGS_SETUP) == 0)
2495 pktinfo.term_id = term_id;
2496 pktinfo.term_offset = consumption_offset;
2497 pktinfo.info_flags |= (AERON_PACKET_INFO_FLAGS_TERM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_OFFSET_VALID);
2498 pktinfo.receiver_window = rcv_window;
2502 pktinfo.term_id = 0;
2503 pktinfo.term_offset = 0;
2504 pktinfo.receiver_window = 0;
2507 pktinfo.data_length = 0;
2508 pktinfo.type = HDR_TYPE_SM;
2509 aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo);
2511 aeron_info_stream_progress_report(pinfo, HDR_TYPE_SM, pktinfo.flags, term_id, consumption_offset, finfo);
2512 item = proto_tree_add_none_format(tree, hf_aeron_sm, tvb, offset, -1, "Status Message: Term 0x%x, ConsumptionOfs %" G_GUINT32_FORMAT ", RcvWindow %" G_GUINT32_FORMAT,
2513 term_id, consumption_offset, rcv_window);
2514 subtree = proto_item_add_subtree(item, ett_aeron_sm);
2515 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2516 PROTO_ITEM_SET_GENERATED(channel_item);
2517 proto_tree_add_item(subtree, hf_aeron_sm_frame_length, tvb, offset + O_AERON_SM_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2518 proto_tree_add_item(subtree, hf_aeron_sm_version, tvb, offset + O_AERON_SM_VERSION, 1, ENC_LITTLE_ENDIAN);
2519 proto_tree_add_bitmask(subtree, tvb, offset + O_AERON_SM_FLAGS, hf_aeron_sm_flags, ett_aeron_sm_flags, flags, ENC_LITTLE_ENDIAN);
2520 proto_tree_add_item(subtree, hf_aeron_sm_type, tvb, offset + O_AERON_SM_TYPE, 2, ENC_LITTLE_ENDIAN);
2521 proto_tree_add_item(subtree, hf_aeron_sm_session_id, tvb, offset + O_AERON_SM_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2522 proto_tree_add_item(subtree, hf_aeron_sm_stream_id, tvb, offset + O_AERON_SM_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2523 proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_id, tvb, offset + O_AERON_SM_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2524 proto_tree_add_item(subtree, hf_aeron_sm_consumption_term_offset, tvb, offset + O_AERON_SM_COMPLETED_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2525 item = proto_tree_add_item(subtree, hf_aeron_sm_receiver_window, tvb, offset + O_AERON_SM_RECEIVER_WINDOW, 4, ENC_LITTLE_ENDIAN);
2526 aeron_window_resize_report(pinfo, item, finfo);
2527 if (feedback_length > 0)
2529 proto_tree_add_item(subtree, hf_aeron_sm_feedback, tvb, offset + O_AERON_SM_FEEDBACK, feedback_length, ENC_NA);
2531 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2532 aeron_stream_report(tvb, pinfo, subtree, transport, finfo);
2533 proto_item_set_len(item, rounded_length);
2534 return (rounded_length);
2537 /*----------------------------------------------------------------------------*/
2538 /* Aeron error packet dissection functions. */
2539 /*----------------------------------------------------------------------------*/
2540 static int dissect_aeron_err(tvbuff_t * tvb, int offset, packet_info * pinfo _U_, proto_tree * tree)
2542 proto_tree * subtree = NULL;
2543 proto_item * item = NULL;
2545 guint32 bad_frame_length;
2546 gint string_length = 0;
2549 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Error");
2550 item = proto_tree_add_item(tree, hf_aeron_err, tvb, offset, -1, ENC_NA);
2551 subtree = proto_item_add_subtree(item, ett_aeron_err);
2552 proto_tree_add_item(subtree, hf_aeron_err_frame_length, tvb, offset + O_AERON_ERR_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2553 proto_tree_add_item(subtree, hf_aeron_err_version, tvb, offset + O_AERON_ERR_VERSION, 1, ENC_LITTLE_ENDIAN);
2554 proto_tree_add_item(subtree, hf_aeron_err_code, tvb, offset + O_AERON_ERR_CODE, 1, ENC_LITTLE_ENDIAN);
2555 proto_tree_add_item(subtree, hf_aeron_err_type, tvb, offset + O_AERON_ERR_TYPE, 2, ENC_LITTLE_ENDIAN);
2556 length = tvb_get_letohl(tvb, offset + O_AERON_ERR_FRAME_LENGTH);
2557 proto_tree_add_item(subtree, hf_aeron_err_off_frame_length, tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2558 bad_frame_length = tvb_get_letohl(tvb, offset + O_AERON_ERR_OFFENDING_FRAME_LENGTH);
2559 ofs = offset + O_AERON_ERR_OFFENDING_HEADER;
2560 proto_tree_add_item(subtree, hf_aeron_err_off_hdr, tvb, offset + ofs, bad_frame_length, ENC_NA);
2561 ofs += bad_frame_length;
2562 string_length = length - ofs;
2563 if (string_length > 0)
2565 proto_tree_add_item(subtree, hf_aeron_err_string, tvb, offset + ofs, string_length, ENC_ASCII|ENC_NA);
2567 length = aeron_pos_roundup(length);
2568 proto_item_set_len(item, (int) length);
2569 return ((int) length);
2572 /*----------------------------------------------------------------------------*/
2573 /* Aeron setup packet dissection functions. */
2574 /*----------------------------------------------------------------------------*/
2575 static void aeron_set_stream_mtu_term_length(packet_info * pinfo, aeron_transport_t * transport, guint32 stream_id, guint32 mtu, guint32 term_length)
2577 if (PINFO_FD_VISITED(pinfo) == 0)
2579 aeron_stream_t * stream = aeron_transport_stream_find(transport, stream_id);
2582 stream->term_length = term_length;
2588 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)
2590 proto_tree * subtree = NULL;
2591 proto_item * item = NULL;
2592 guint32 frame_length;
2593 proto_item * channel_item = NULL;
2594 aeron_transport_t * transport;
2597 guint32 active_term_id;
2598 guint32 initial_term_id;
2599 guint32 term_offset;
2600 guint32 term_length;
2603 aeron_packet_info_t pktinfo;
2605 frame_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_FRAME_LENGTH);
2606 rounded_length = (int) aeron_pos_roundup(frame_length);
2607 term_offset = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_OFFSET);
2608 session_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_SESSION_ID);
2609 transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
2610 stream_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_STREAM_ID);
2611 initial_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID);
2612 active_term_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID);
2613 memset((void *) &pktinfo, 0, sizeof(aeron_packet_info_t));
2614 pktinfo.stream_id = stream_id;
2615 pktinfo.term_id = active_term_id;
2616 pktinfo.term_offset = 0;
2617 pktinfo.info_flags = AERON_PACKET_INFO_FLAGS_STREAM_ID_VALID | AERON_PACKET_INFO_FLAGS_TERM_ID_VALID;
2619 pktinfo.data_length = 0;
2620 pktinfo.receiver_window = 0;
2621 pktinfo.type = HDR_TYPE_SETUP;
2623 aeron_frame_info_setup(pinfo, transport, &pktinfo, finfo);
2624 term_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_LENGTH);
2625 mtu = tvb_get_letohl(tvb, offset + O_AERON_SETUP_MTU);
2626 aeron_set_stream_mtu_term_length(pinfo, transport, stream_id, mtu, term_length);
2628 col_append_sep_str(pinfo->cinfo, COL_INFO, ", ", "Setup");
2629 item = proto_tree_add_none_format(tree, hf_aeron_setup, tvb, offset, -1, "Setup Frame: InitTerm 0x%x, ActiveTerm 0x%x, TermLen %" G_GUINT32_FORMAT ", Ofs %" G_GUINT32_FORMAT ", MTU %" G_GUINT32_FORMAT,
2630 initial_term_id, (guint32) active_term_id, term_length, term_offset, mtu);
2631 subtree = proto_item_add_subtree(item, ett_aeron_setup);
2632 channel_item = proto_tree_add_uint64(subtree, hf_aeron_channel_id, tvb, 0, 0, transport->channel_id);
2633 PROTO_ITEM_SET_GENERATED(channel_item);
2634 proto_tree_add_item(subtree, hf_aeron_setup_frame_length, tvb, offset + O_AERON_SETUP_FRAME_LENGTH, 4, ENC_LITTLE_ENDIAN);
2635 proto_tree_add_item(subtree, hf_aeron_setup_version, tvb, offset + O_AERON_SETUP_VERSION, 1, ENC_LITTLE_ENDIAN);
2636 proto_tree_add_item(subtree, hf_aeron_setup_flags, tvb, offset + O_AERON_SETUP_FLAGS, 1, ENC_LITTLE_ENDIAN);
2637 proto_tree_add_item(subtree, hf_aeron_setup_type, tvb, offset + O_AERON_SETUP_TYPE, 2, ENC_LITTLE_ENDIAN);
2638 proto_tree_add_item(subtree, hf_aeron_setup_term_offset, tvb, offset + O_AERON_SETUP_TERM_OFFSET, 4, ENC_LITTLE_ENDIAN);
2639 proto_tree_add_item(subtree, hf_aeron_setup_session_id, tvb, offset + O_AERON_SETUP_SESSION_ID, 4, ENC_LITTLE_ENDIAN);
2640 proto_tree_add_item(subtree, hf_aeron_setup_stream_id, tvb, offset + O_AERON_SETUP_STREAM_ID, 4, ENC_LITTLE_ENDIAN);
2641 proto_tree_add_item(subtree, hf_aeron_setup_initial_term_id, tvb, offset + O_AERON_SETUP_INITIAL_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2642 proto_tree_add_item(subtree, hf_aeron_setup_active_term_id, tvb, offset + O_AERON_SETUP_ACTIVE_TERM_ID, 4, ENC_LITTLE_ENDIAN);
2643 proto_tree_add_item(subtree, hf_aeron_setup_term_length, tvb, offset + O_AERON_SETUP_TERM_LENGTH, 4, ENC_LITTLE_ENDIAN);
2644 proto_tree_add_item(subtree, hf_aeron_setup_mtu, tvb, offset + O_AERON_SETUP_MTU, 4, ENC_LITTLE_ENDIAN);
2645 aeron_sequence_report(tvb, pinfo, subtree, transport, &pktinfo, finfo);
2646 proto_item_set_len(item, rounded_length);
2647 return (rounded_length);
2650 /*----------------------------------------------------------------------------*/
2651 /* Aeron packet dissector. */
2652 /*----------------------------------------------------------------------------*/
2653 static int dissect_aeron(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data _U_)
2655 int total_dissected_length = 0;
2657 proto_tree * aeron_tree = NULL;
2658 proto_item * aeron_item;
2659 int dissected_length = 0;
2661 int length_remaining = 0;
2662 aeron_conversation_info_t * cinfo = NULL;
2664 /* Get enough information to determine the conversation info */
2665 frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2666 cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2671 col_add_str(pinfo->cinfo, COL_PROTOCOL, "Aeron");
2672 col_clear(pinfo->cinfo, COL_INFO);
2673 col_add_str(pinfo->cinfo, COL_INFO, aeron_format_transport_uri(cinfo));
2674 col_set_fence(pinfo->cinfo, COL_INFO);
2676 length_remaining = tvb_reported_length(tvb);
2677 aeron_item = proto_tree_add_protocol_format(tree, proto_aeron, tvb, offset, -1, "Aeron Protocol");
2678 aeron_tree = proto_item_add_subtree(aeron_item, ett_aeron);
2679 while (length_remaining > 0)
2681 aeron_frame_info_t * finfo = NULL;
2683 if (aeron_sequence_analysis)
2685 finfo = aeron_frame_info_add(pinfo->fd->num, (guint32) offset);
2687 frame_type = tvb_get_letohs(tvb, offset + O_AERON_BASIC_TYPE);
2688 cinfo = aeron_setup_conversation_info(pinfo, frame_type);
2692 dissected_length = dissect_aeron_pad(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2695 dissected_length = dissect_aeron_data(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2698 dissected_length = dissect_aeron_nak(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2701 dissected_length = dissect_aeron_sm(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2704 dissected_length = dissect_aeron_err(tvb, offset, pinfo, aeron_tree);
2706 case HDR_TYPE_SETUP:
2707 dissected_length = dissect_aeron_setup(tvb, offset, pinfo, aeron_tree, cinfo, finfo);
2711 return (total_dissected_length);
2713 if (length_remaining - dissected_length >= length_remaining) {
2714 return (total_dissected_length);
2716 total_dissected_length += dissected_length;
2717 offset += dissected_length;
2718 length_remaining -= dissected_length;
2719 proto_item_set_len(aeron_item, dissected_length);
2721 return (total_dissected_length);
2724 static gboolean test_aeron_packet(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * user_data)
2727 guint16 packet_type = 0;
2729 gint length_remaining;
2732 length_remaining = tvb_captured_length_remaining(tvb, 0);
2733 if (length_remaining < HDR_LENGTH_MIN)
2737 /* We know we have at least HDR_LENGTH_MIN (12) bytes captured */
2738 ver = tvb_get_guint8(tvb, O_AERON_BASIC_VERSION);
2743 packet_type = tvb_get_letohs(tvb, O_AERON_BASIC_TYPE);
2744 switch (packet_type)
2751 case HDR_TYPE_SETUP:
2757 length = (gint) (tvb_get_letohl(tvb, O_AERON_BASIC_FRAME_LENGTH) & 0x7fffffff);
2758 if (!((packet_type == HDR_TYPE_DATA) && (length == 0)))
2760 if (length < HDR_LENGTH_MIN)
2765 if (packet_type == HDR_TYPE_PAD)
2767 /* Pad frames can't have a zero term offset */
2768 guint32 term_offset = tvb_get_letohl(tvb, O_AERON_PAD_TERM_OFFSET);
2769 if (term_offset == 0)
2776 if (length > length_remaining)
2781 rc = dissect_aeron(tvb, pinfo, tree, user_data);
2789 static void aeron_init(void)
2791 aeron_channel_id_init();
2794 /* Register all the bits needed with the filtering engine */
2795 void proto_register_aeron(void)
2797 static hf_register_info hf[] =
2799 { &hf_aeron_channel_id,
2800 { "Channel ID", "aeron.channel_id", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2802 { "Pad Frame", "aeron.pad", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2803 { &hf_aeron_pad_frame_length,
2804 { "Frame Length", "aeron.pad.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2805 { &hf_aeron_pad_version,
2806 { "Version", "aeron.pad.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2807 { &hf_aeron_pad_flags,
2808 { "Flags", "aeron.pad.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2809 { &hf_aeron_pad_type,
2810 { "Type", "aeron.pad.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2811 { &hf_aeron_pad_term_offset,
2812 { "Term Offset", "aeron.pad.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2813 { &hf_aeron_pad_session_id,
2814 { "Session ID", "aeron.pad.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2815 { &hf_aeron_pad_stream_id,
2816 { "Stream ID", "aeron.pad.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2817 { &hf_aeron_pad_term_id,
2818 { "Term ID", "aeron.pad.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2820 { "Data Frame", "aeron.data", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2821 { &hf_aeron_data_frame_length,
2822 { "Frame Length", "aeron.data.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2823 { &hf_aeron_data_version,
2824 { "Version", "aeron.data.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2825 { &hf_aeron_data_flags,
2826 { "Flags", "aeron.data.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2827 { &hf_aeron_data_flags_b,
2828 { "Begin Message", "aeron.data.flags.b", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_BEGIN, NULL, HFILL } },
2829 { &hf_aeron_data_flags_e,
2830 { "End Message", "aeron.data.flags.e", FT_BOOLEAN, 8, TFS(&tfs_set_notset), DATA_FLAGS_END, NULL, HFILL } },
2831 { &hf_aeron_data_type,
2832 { "Type", "aeron.data.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2833 { &hf_aeron_data_term_offset,
2834 { "Term Offset", "aeron.data.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2835 { &hf_aeron_data_next_offset,
2836 { "Next Offset", "aeron.data.next_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2837 { &hf_aeron_data_next_offset_term,
2838 { "Next Offset Term", "aeron.data.next_offset_term", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2839 { &hf_aeron_data_next_offset_first_frame,
2840 { "Next Offset First Frame", "aeron.data.next_offset_first_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2841 { &hf_aeron_data_session_id,
2842 { "Session ID", "aeron.data.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2843 { &hf_aeron_data_stream_id,
2844 { "Stream ID", "aeron.data.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2845 { &hf_aeron_data_term_id,
2846 { "Term ID", "aeron.data.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2847 { &hf_aeron_data_reassembly,
2848 { "Reassembled Fragments", "aeron.data.reassembly", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2849 { &hf_aeron_data_reassembly_fragment,
2850 { "Fragment", "aeron.data.reassembly.fragment", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2852 { "NAK Frame", "aeron.nak", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2853 { &hf_aeron_nak_frame_length,
2854 { "Frame Length", "aeron.nak.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2855 { &hf_aeron_nak_version,
2856 { "Version", "aeron.nak.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2857 { &hf_aeron_nak_flags,
2858 { "Flags", "aeron.nak.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2859 { &hf_aeron_nak_type,
2860 { "Type", "aeron.nak.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2861 { &hf_aeron_nak_session_id,
2862 { "Session ID", "aeron.nak.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2863 { &hf_aeron_nak_stream_id,
2864 { "Stream ID", "aeron.nak.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2865 { &hf_aeron_nak_term_id,
2866 { "Term ID", "aeron.nak.term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2867 { &hf_aeron_nak_term_offset,
2868 { "Term Offset", "aeron.nak.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2869 { &hf_aeron_nak_length,
2870 { "Length", "aeron.nak.length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2872 { "Status Message", "aeron.sm", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2873 { &hf_aeron_sm_frame_length,
2874 { "Frame Length", "aeron.sm.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2875 { &hf_aeron_sm_version,
2876 { "Version", "aeron.sm.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2877 { &hf_aeron_sm_flags,
2878 { "Flags", "aeron.sm.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2879 { &hf_aeron_sm_flags_s,
2880 { "Setup", "aeron.sm.flags.s", FT_BOOLEAN, 8, TFS(&tfs_set_notset), STATUS_FLAGS_SETUP, NULL, HFILL } },
2881 { &hf_aeron_sm_type,
2882 { "Type", "aeron.sm.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2883 { &hf_aeron_sm_session_id,
2884 { "Session ID", "aeron.sm.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2885 { &hf_aeron_sm_stream_id,
2886 { "Stream ID", "aeron.sm.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2887 { &hf_aeron_sm_consumption_term_id,
2888 { "Consumption Term ID", "aeron.sm.consumption_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2889 { &hf_aeron_sm_consumption_term_offset,
2890 { "Consumption Term Offset", "aeron.sm.consumption_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2891 { &hf_aeron_sm_receiver_window,
2892 { "Receiver Window", "aeron.sm.receiver_window", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2893 { &hf_aeron_sm_feedback,
2894 { "Application-specific Feedback", "aeron.sm.feedback", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2896 { "Error Header", "aeron.err", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2897 { &hf_aeron_err_frame_length,
2898 { "Frame Length", "aeron.err.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2899 { &hf_aeron_err_version,
2900 { "Version", "aeron.err.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2901 { &hf_aeron_err_code,
2902 { "Error Code", "aeron.err.code", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2903 { &hf_aeron_err_type,
2904 { "Type", "aeron.err.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2905 { &hf_aeron_err_off_frame_length,
2906 { "Offending Frame Length", "aeron.err.off_frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2907 { &hf_aeron_err_off_hdr,
2908 { "Offending Header", "aeron.err.off_hdr", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2909 { &hf_aeron_err_string,
2910 { "Error String", "aeron.err.string", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2912 { "Setup Frame", "aeron.setup", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2913 { &hf_aeron_setup_frame_length,
2914 { "Frame Length", "aeron.setup.frame_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2915 { &hf_aeron_setup_version,
2916 { "Version", "aeron.setup.version", FT_UINT8, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2917 { &hf_aeron_setup_flags,
2918 { "Flags", "aeron.setup.flags", FT_UINT8, BASE_HEX, NULL, 0x0, NULL, HFILL } },
2919 { &hf_aeron_setup_type,
2920 { "Type", "aeron.setup.type", FT_UINT16, BASE_DEC_HEX, VALS(aeron_frame_type), 0x0, NULL, HFILL } },
2921 { &hf_aeron_setup_term_offset,
2922 { "Term Offset", "aeron.setup.term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2923 { &hf_aeron_setup_session_id,
2924 { "Session ID", "aeron.setup.session_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2925 { &hf_aeron_setup_stream_id,
2926 { "Stream ID", "aeron.setup.stream_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2927 { &hf_aeron_setup_initial_term_id,
2928 { "Initial Term ID", "aeron.setup.initial_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2929 { &hf_aeron_setup_active_term_id,
2930 { "Active Term ID", "aeron.setup.active_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2931 { &hf_aeron_setup_term_length,
2932 { "Term Length", "aeron.setup.term_length", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2933 { &hf_aeron_setup_mtu,
2934 { "MTU", "aeron.setup.mtu", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2935 { &hf_aeron_sequence_analysis,
2936 { "Sequence Analysis", "aeron.sequence_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2937 { &hf_aeron_sequence_analysis_channel_prev_frame,
2938 { "Previous Channel Frame", "aeron.sequence_analysis.prev_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2939 { &hf_aeron_sequence_analysis_channel_next_frame,
2940 { "Next Channel Frame", "aeron.sequence_analysis.next_channel_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2941 { &hf_aeron_sequence_analysis_stream_prev_frame,
2942 { "Previous Stream Frame", "aeron.sequence_analysis.prev_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2943 { &hf_aeron_sequence_analysis_stream_next_frame,
2944 { "Next Stream Frame", "aeron.sequence_analysis.next_stream_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2945 { &hf_aeron_sequence_analysis_term_prev_frame,
2946 { "Previous Term Frame", "aeron.sequence_analysis.prev_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2947 { &hf_aeron_sequence_analysis_term_next_frame,
2948 { "Next Term Frame", "aeron.sequence_analysis.next_term_frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2949 { &hf_aeron_sequence_analysis_term_offset,
2950 { "Offset also in", "aeron.sequence_analysis.term_offset", FT_NONE, BASE_NONE, NULL, 0x0, "Offset also appears in these frames", HFILL } },
2951 { &hf_aeron_sequence_analysis_term_offset_frame,
2952 { "Frame", "aeron.sequence_analysis.term_offset.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2953 { &hf_aeron_sequence_analysis_retransmission,
2954 { "Frame is a retransmission", "aeron.sequence_analysis.retransmission", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2955 { &hf_aeron_sequence_analysis_retransmission_rx,
2956 { "List of NAK frames to which this retransmission applies", "aeron.sequence_analysis.retransmission.rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2957 { &hf_aeron_sequence_analysis_retransmission_rx_frame,
2958 { "Retransmission applies to frame", "aeron.sequence_analysis.retransmission.rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2959 { &hf_aeron_sequence_analysis_nak_unrecovered,
2960 { "Unrecovered Bytes", "aeron.sequence_analysis.nak_unrecovered", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } },
2961 { &hf_aeron_sequence_analysis_nak_rx,
2962 { "List of RX Frames for this NAK", "aeron.sequence_analysis.nak_rx", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2963 { &hf_aeron_sequence_analysis_nak_rx_frame,
2964 { "RX Frame for this NAK", "aeron.sequence_analysis.nak_rx.frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2965 { &hf_aeron_sequence_analysis_keepalive,
2966 { "Frame is a keepalive", "aeron.sequence_analysis.keepalive", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2967 { &hf_aeron_stream_analysis,
2968 { "Stream Analysis", "aeron.stream_analysis", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL } },
2969 { &hf_aeron_stream_analysis_high_term_id,
2970 { "Highest sent term ID", "aeron.stream_analysis.high_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2971 { &hf_aeron_stream_analysis_high_term_offset,
2972 { "Highest sent term offset", "aeron.stream_analysis.high_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2973 { &hf_aeron_stream_analysis_completed_term_id,
2974 { "Completed term ID", "aeron.stream_analysis.completed_term_id", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2975 { &hf_aeron_stream_analysis_completed_term_offset,
2976 { "Completed term offset", "aeron.stream_analysis.completed_term_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL } },
2977 { &hf_aeron_stream_analysis_outstanding_bytes,
2978 { "Outstanding bytes", "aeron.stream_analysis.outstanding_bytes", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL } }
2980 static gint * ett[] =
2985 &ett_aeron_data_flags,
2986 &ett_aeron_data_reassembly,
2989 &ett_aeron_sm_flags,
2993 &ett_aeron_sequence_analysis,
2994 &ett_aeron_sequence_analysis_retransmission_rx,
2995 &ett_aeron_sequence_analysis_nak_rx,
2996 &ett_aeron_sequence_analysis_term_offset,
2997 &ett_aeron_stream_analysis
2999 static ei_register_info ei[] =
3001 { &ei_aeron_analysis_nak, { "aeron.analysis.nak", PI_SEQUENCE, PI_NOTE, "NAK", EXPFILL } },
3002 { &ei_aeron_analysis_window_full, { "aeron.analysis.window_full", PI_SEQUENCE, PI_NOTE, "Receiver window is full", EXPFILL } },
3003 { &ei_aeron_analysis_idle_rx, { "aeron.analysis.idle_rx", PI_SEQUENCE, PI_NOTE, "This frame contains an Idle RX", EXPFILL } },
3004 { &ei_aeron_analysis_pacing_rx, { "aeron.analysis.pacing_rx", PI_SEQUENCE, PI_NOTE, "This frame contains a Pacing RX", EXPFILL } },
3005 { &ei_aeron_analysis_ooo, { "aeron.analysis.ooo", PI_SEQUENCE, PI_NOTE, "This frame contains Out-of-order data", EXPFILL } },
3006 { &ei_aeron_analysis_ooo_gap, { "aeron.analysis.ooo_gap", PI_SEQUENCE, PI_NOTE, "This frame is an Out-of-order gap", EXPFILL } },
3007 { &ei_aeron_analysis_keepalive, { "aeron.analysis.keepalive", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive", EXPFILL } },
3008 { &ei_aeron_analysis_window_resize, { "aeron.analysis.window_resize", PI_SEQUENCE, PI_NOTE, "Receiver window resized", EXPFILL } },
3009 { &ei_aeron_analysis_ooo_sm, { "aeron.analysis.ooo_sm", PI_SEQUENCE, PI_NOTE, "This frame contains an Out-of-order SM", EXPFILL } },
3010 { &ei_aeron_analysis_keepalive_sm, { "aeron.analysis.keepalive_sm", PI_SEQUENCE, PI_NOTE, "This frame contains a Keepalive SM", EXPFILL } },
3011 { &ei_aeron_analysis_rx, { "aeron.analysis.rx", PI_SEQUENCE, PI_NOTE, "This frame contains a (likely) retransmission", EXPFILL } },
3012 { &ei_aeron_analysis_term_id_change, { "aeron.analysis.term_id_change", PI_SEQUENCE, PI_CHAT, "This frame contains a new term ID", EXPFILL } }
3014 module_t * aeron_module;
3015 expert_module_t * expert_aeron;
3017 proto_aeron = proto_register_protocol("Aeron Protocol", "Aeron", "aeron");
3019 proto_register_field_array(proto_aeron, hf, array_length(hf));
3020 proto_register_subtree_array(ett, array_length(ett));
3021 expert_aeron = expert_register_protocol(proto_aeron);
3022 expert_register_field_array(expert_aeron, ei, array_length(ei));
3023 aeron_module = prefs_register_protocol(proto_aeron, proto_reg_handoff_aeron);
3024 aeron_heuristic_subdissector_list = register_heur_dissector_list("aeron_msg_payload");
3026 prefs_register_bool_preference(aeron_module,
3027 "sequence_analysis",
3028 "Analyze transport sequencing",
3029 "Include next/previous frame for channel, stream, and term, and other transport sequence analysis.",
3030 &aeron_sequence_analysis);
3031 prefs_register_bool_preference(aeron_module,
3033 "Analyze stream sequencing",
3034 "Include stream analysis, tracking publisher and subscriber positions. Requires \"Analyze transport sequencing\".",
3035 &aeron_stream_analysis);
3036 prefs_register_bool_preference(aeron_module,
3037 "reassemble_fragments",
3038 "Reassemble fragmented data",
3039 "Reassemble fragmented data messages. Requires \"Analyze transport sequencing\" and \"Analyze stream sequencing\".",
3040 &aeron_reassemble_fragments);
3041 prefs_register_bool_preference(aeron_module,
3042 "use_heuristic_subdissectors",
3043 "Use heuristic sub-dissectors",
3044 "Use a registered heuristic sub-dissector to decode the payload data. Requires \"Analyze transport sequencing\", \"Analyze stream sequencing\", and \"Reassemble fragmented data\".",
3045 &aeron_use_heuristic_subdissectors);
3046 register_init_routine(aeron_init);
3047 aeron_frame_info_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
3050 /* The registration hand-off routine */
3051 void proto_reg_handoff_aeron(void)
3053 aeron_dissector_handle = new_create_dissector_handle(dissect_aeron, proto_aeron);
3054 dissector_add_for_decode_as("udp.port", aeron_dissector_handle);
3055 heur_dissector_add("udp", test_aeron_packet, proto_aeron);
3056 aeron_data_dissector_handle = find_dissector("data");
3060 * Editor modelines - http://www.wireshark.org/tools/modelines.html
3065 * indent-tabs-mode: nil
3068 * vi: set shiftwidth=4 tabstop=8 expandtab:
3069 * :indentSize=4:tabSize=8:noTabs=true: