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