diff options
Diffstat (limited to 'epan/dissectors/packet-drbd.c')
-rw-r--r-- | epan/dissectors/packet-drbd.c | 554 |
1 files changed, 348 insertions, 206 deletions
diff --git a/epan/dissectors/packet-drbd.c b/epan/dissectors/packet-drbd.c index d89ec51a..9483bea8 100644 --- a/epan/dissectors/packet-drbd.c +++ b/epan/dissectors/packet-drbd.c @@ -19,10 +19,12 @@ #include <config.h> #include <epan/packet.h> -#include <epan/prefs.h> +#include <epan/exceptions.h> +#include <epan/unit_strings.h> #include "packet-tcp.h" #include <wsutil/str_util.h> +#include <wsutil/array.h> /* Known as SHARED_SECRET_MAX in the DRBD sources */ #define DRBD_STRING_MAX 64 @@ -113,6 +115,11 @@ enum drbd_packet { P_OV_DAGTAG_REQ = 0x4f, P_OV_DAGTAG_REPLY = 0x50, + P_WRITE_ACK_IN_SYNC = 0x51, + P_RS_NEG_ACK = 0x52, + P_OV_RESULT_ID = 0x53, + P_RS_DEALLOCATED_ID = 0x54, + P_INITIAL_META = 0xfff1, P_INITIAL_DATA = 0xfff2, @@ -120,23 +127,23 @@ enum drbd_packet { }; typedef struct { - guint32 tid; - gint32 initiator_node_id; + uint32_t tid; + int32_t initiator_node_id; } drbd_twopc_key; typedef struct { - guint32 prepare_frame; + uint32_t prepare_frame; enum drbd_packet command; } drbd_twopc_val; -static guint drbd_twopc_key_hash(gconstpointer k) +static unsigned drbd_twopc_key_hash(const void *k) { const drbd_twopc_key *key = (const drbd_twopc_key *) k; return key->tid; } -static gint drbd_twopc_key_equal(gconstpointer k1, gconstpointer k2) +static int drbd_twopc_key_equal(const void *k1, const void *k2) { const drbd_twopc_key *key1 = (const drbd_twopc_key*) k1; const drbd_twopc_key *key2 = (const drbd_twopc_key*) k2; @@ -240,6 +247,11 @@ static const value_string packet_names[] = { { P_OV_DAGTAG_REQ, "P_OV_DAGTAG_REQ" }, { P_OV_DAGTAG_REPLY, "P_OV_DAGTAG_REPLY" }, + { P_WRITE_ACK_IN_SYNC, "P_WRITE_ACK_IN_SYNC" }, + { P_RS_NEG_ACK, "P_RS_NEG_ACK" }, + { P_OV_RESULT_ID, "P_OV_RESULT_ID" }, + { P_RS_DEALLOCATED_ID, "P_RS_DEALLOCATED_ID" }, + { P_INITIAL_META, "P_INITIAL_META" }, { P_INITIAL_DATA, "P_INITIAL_DATA" }, @@ -387,6 +399,17 @@ static const value_string disk_state_names[] = { #define DP_WSAME 512 #define DP_ZEROES 1024 +#define OV_RESULT_SKIP 4710 +#define OV_RESULT_IN_SYNC 4711 +#define OV_RESULT_OUT_OF_SYNC 4712 + +static const val64_string ov_result_codes[] = { + { OV_RESULT_SKIP, "SKIP" }, + { OV_RESULT_IN_SYNC, "IN_SYNC" }, + { OV_RESULT_OUT_OF_SYNC, "OUT_OF_SYNC" }, + { 0, NULL } +}; + #define DRBD_STREAM_DATA 0 #define DRBD_STREAM_CONTROL 1 @@ -429,6 +452,7 @@ static void decode_payload_data_wsame(tvbuff_t *tvb, proto_tree *tree, drbd_conv static void decode_payload_rs_deallocated(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); static void decode_payload_block_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); +static void decode_payload_ov_result(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); static void decode_payload_barrier_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); static void decode_payload_confirm_stable(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); static void decode_payload_rq_s_reply(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data); @@ -476,6 +500,7 @@ static const value_payload_decoder payload_decoders[] = { { P_TRIM, NULL, decode_payload_data_size }, { P_ZEROES, NULL, decode_payload_data_size }, { P_RS_DEALLOCATED, NULL, decode_payload_rs_deallocated }, + { P_RS_DEALLOCATED_ID, NULL, decode_payload_block_ack }, { P_WSAME, NULL, decode_payload_data_wsame }, { P_DISCONNECT, NULL, NULL }, { P_RS_DAGTAG_REQ, NULL, decode_payload_dagtag_data_request }, @@ -488,12 +513,15 @@ static const value_payload_decoder payload_decoders[] = { { P_PING_ACK, NULL, NULL }, { P_RECV_ACK, NULL, decode_payload_block_ack }, { P_WRITE_ACK, NULL, decode_payload_block_ack }, - { P_RS_WRITE_ACK, NULL, decode_payload_block_ack }, + { P_WRITE_ACK_IN_SYNC, NULL, decode_payload_block_ack }, { P_SUPERSEDED, NULL, decode_payload_block_ack }, { P_NEG_ACK, NULL, decode_payload_block_ack }, { P_NEG_DREPLY, NULL, decode_payload_block_ack }, { P_NEG_RS_DREPLY, NULL, decode_payload_block_ack }, + { P_RS_WRITE_ACK, NULL, decode_payload_block_ack }, + { P_RS_NEG_ACK, NULL, decode_payload_block_ack }, { P_OV_RESULT, NULL, decode_payload_block_ack }, + { P_OV_RESULT_ID, NULL, decode_payload_ov_result }, { P_BARRIER_ACK, NULL, decode_payload_barrier_ack }, { P_CONFIRM_STABLE, NULL, decode_payload_confirm_stable }, { P_STATE_CHG_REPLY, NULL, decode_payload_rq_s_reply }, @@ -515,133 +543,140 @@ void proto_register_drbd(void); void proto_reg_handoff_drbd(void); static dissector_handle_t drbd_handle; - -static int proto_drbd = -1; - -static int hf_drbd_command = -1; -static int hf_drbd_length = -1; -static int hf_drbd_volume = -1; -static int hf_drbd_auth_challenge_nonce = -1; -static int hf_drbd_auth_response_hash = -1; -static int hf_drbd_sector = -1; -static int hf_drbd_block_id = -1; -static int hf_drbd_seq_num = -1; -static int hf_drbd_dp_flags = -1; -static int hf_drbd_data = -1; -static int hf_drbd_size = -1; -static int hf_drbd_protocol_min = -1; -static int hf_drbd_feature_flags = -1; -static int hf_drbd_protocol_max = -1; -static int hf_drbd_sender_node_id = -1; -static int hf_drbd_receiver_node_id = -1; -static int hf_drbd_barrier = -1; -static int hf_drbd_set_size = -1; -static int hf_drbd_oldest_block_id = -1; -static int hf_drbd_youngest_block_id = -1; -static int hf_drbd_resync_rate = -1; -static int hf_drbd_verify_alg = -1; -static int hf_drbd_csums_alg = -1; -static int hf_drbd_c_plan_ahead = -1; -static int hf_drbd_c_delay_target = -1; -static int hf_drbd_c_fill_target = -1; -static int hf_drbd_c_max_rate = -1; -static int hf_drbd_protocol = -1; -static int hf_drbd_after_sb_0p = -1; -static int hf_drbd_after_sb_1p = -1; -static int hf_drbd_after_sb_2p = -1; -static int hf_drbd_conn_flags = -1; -static int hf_drbd_two_primaries = -1; -static int hf_drbd_integrity_alg = -1; -static int hf_drbd_current_uuid = -1; -static int hf_drbd_bitmap_uuid = -1; -static int hf_drbd_history_uuid_list = -1; -static int hf_drbd_history_uuid = -1; -static int hf_drbd_dirty_bits = -1; -static int hf_drbd_uuid_flags = -1; -static int hf_drbd_node_mask = -1; -static int hf_drbd_bitmap_uuids_mask = -1; -static int hf_drbd_uuid = -1; -static int hf_drbd_weak_nodes = -1; -static int hf_drbd_physical_block_size = -1; -static int hf_drbd_logical_block_size = -1; -static int hf_drbd_alignment_offset = -1; -static int hf_drbd_io_min = -1; -static int hf_drbd_io_opt = -1; -static int hf_drbd_discard_enabled = -1; -static int hf_drbd_discard_zeroes_data = -1; -static int hf_drbd_write_same_capable = -1; -static int hf_drbd_d_size = -1; -static int hf_drbd_u_size = -1; -static int hf_drbd_c_size = -1; -static int hf_drbd_max_bio_size = -1; -static int hf_drbd_queue_order_type = -1; -static int hf_drbd_dds_flags = -1; -static int hf_drbd_state = -1; -static int hf_drbd_retcode = -1; -static int hf_drbd_twopc_prepare_in = -1; -static int hf_drbd_tid = -1; -static int hf_drbd_twopc_flags = -1; -static int hf_drbd_initiator_node_id = -1; -static int hf_drbd_target_node_id = -1; -static int hf_drbd_nodes_to_reach = -1; -static int hf_drbd_primary_nodes = -1; -static int hf_drbd_user_size = -1; -static int hf_drbd_diskful_primary_nodes = -1; -static int hf_drbd_exposed_size = -1; -static int hf_drbd_reachable_nodes = -1; -static int hf_drbd_max_possible_size = -1; -static int hf_drbd_offset = -1; -static int hf_drbd_dagtag = -1; -static int hf_drbd_dagtag_node_id = -1; -static int hf_drbd_new_rx_descs_data = -1; -static int hf_drbd_new_rx_descs_control = -1; -static int hf_drbd_rx_desc_stolen_from = -1; - -static int hf_drbd_state_role = -1; -static int hf_drbd_state_peer = -1; -static int hf_drbd_state_conn = -1; -static int hf_drbd_state_disk = -1; -static int hf_drbd_state_pdsk = -1; -static int hf_drbd_state_susp = -1; -static int hf_drbd_state_aftr_isp = -1; -static int hf_drbd_state_peer_isp = -1; -static int hf_drbd_state_user_isp = -1; -static int hf_drbd_state_susp_nod = -1; -static int hf_drbd_state_susp_fen = -1; -static int hf_drbd_state_quorum = -1; - -static int hf_drbd_twopc_flag_has_reachable = -1; - -static int hf_drbd_uuid_flag_discard_my_data = -1; -static int hf_drbd_uuid_flag_crashed_primary = -1; -static int hf_drbd_uuid_flag_inconsistent = -1; -static int hf_drbd_uuid_flag_skip_initial_sync = -1; -static int hf_drbd_uuid_flag_new_datagen = -1; -static int hf_drbd_uuid_flag_stable = -1; -static int hf_drbd_uuid_flag_got_stable = -1; -static int hf_drbd_uuid_flag_resync = -1; -static int hf_drbd_uuid_flag_reconnect = -1; -static int hf_drbd_uuid_flag_diskless_primary = -1; -static int hf_drbd_uuid_flag_primary_lost_quorum = -1; - -static int hf_drbd_dp_hardbarrier = -1; -static int hf_drbd_dp_rw_sync = -1; -static int hf_drbd_dp_may_set_in_sync = -1; -static int hf_drbd_dp_unplug = -1; -static int hf_drbd_dp_fua = -1; -static int hf_drbd_dp_flush = -1; -static int hf_drbd_dp_discard = -1; -static int hf_drbd_dp_send_receive_ack = -1; -static int hf_drbd_dp_send_write_ack = -1; -static int hf_drbd_dp_wsame = -1; -static int hf_drbd_dp_zeroes = -1; - -static gint ett_drbd = -1; -static gint ett_drbd_state = -1; -static gint ett_drbd_twopc_flags = -1; -static gint ett_drbd_uuid_flags = -1; -static gint ett_drbd_history_uuids = -1; -static gint ett_drbd_data_flags = -1; +static dissector_handle_t drbd_lb_tcp_handle; + +static int proto_drbd; +static int proto_drbd_lb_tcp; + +static int hf_drbd_command; +static int hf_drbd_length; +static int hf_drbd_volume; +static int hf_drbd_auth_challenge_nonce; +static int hf_drbd_auth_response_hash; +static int hf_drbd_sector; +static int hf_drbd_block_id; +static int hf_drbd_seq_num; +static int hf_drbd_ov_result; +static int hf_drbd_dp_flags; +static int hf_drbd_data; +static int hf_drbd_size; +static int hf_drbd_protocol_min; +static int hf_drbd_feature_flags; +static int hf_drbd_protocol_max; +static int hf_drbd_sender_node_id; +static int hf_drbd_receiver_node_id; +static int hf_drbd_barrier; +static int hf_drbd_set_size; +static int hf_drbd_oldest_block_id; +static int hf_drbd_youngest_block_id; +static int hf_drbd_resync_rate; +static int hf_drbd_verify_alg; +static int hf_drbd_csums_alg; +static int hf_drbd_c_plan_ahead; +static int hf_drbd_c_delay_target; +static int hf_drbd_c_fill_target; +static int hf_drbd_c_max_rate; +static int hf_drbd_protocol; +static int hf_drbd_after_sb_0p; +static int hf_drbd_after_sb_1p; +static int hf_drbd_after_sb_2p; +static int hf_drbd_conn_flags; +static int hf_drbd_two_primaries; +static int hf_drbd_integrity_alg; +static int hf_drbd_current_uuid; +static int hf_drbd_bitmap_uuid; +static int hf_drbd_history_uuid_list; +static int hf_drbd_history_uuid; +static int hf_drbd_dirty_bits; +static int hf_drbd_uuid_flags; +static int hf_drbd_node_mask; +static int hf_drbd_bitmap_uuids_mask; +static int hf_drbd_uuid; +static int hf_drbd_weak_nodes; +static int hf_drbd_physical_block_size; +static int hf_drbd_logical_block_size; +static int hf_drbd_alignment_offset; +static int hf_drbd_io_min; +static int hf_drbd_io_opt; +static int hf_drbd_discard_enabled; +static int hf_drbd_discard_zeroes_data; +static int hf_drbd_write_same_capable; +static int hf_drbd_d_size; +static int hf_drbd_u_size; +static int hf_drbd_c_size; +static int hf_drbd_max_bio_size; +static int hf_drbd_queue_order_type; +static int hf_drbd_dds_flags; +static int hf_drbd_state; +static int hf_drbd_retcode; +static int hf_drbd_twopc_prepare_in; +static int hf_drbd_tid; +static int hf_drbd_twopc_flags; +static int hf_drbd_initiator_node_id; +static int hf_drbd_target_node_id; +static int hf_drbd_nodes_to_reach; +static int hf_drbd_primary_nodes; +static int hf_drbd_user_size; +static int hf_drbd_diskful_primary_nodes; +static int hf_drbd_exposed_size; +static int hf_drbd_reachable_nodes; +static int hf_drbd_max_possible_size; +static int hf_drbd_offset; +static int hf_drbd_dagtag; +static int hf_drbd_dagtag_node_id; +static int hf_drbd_new_rx_descs_data; +static int hf_drbd_new_rx_descs_control; +static int hf_drbd_rx_desc_stolen_from; + +static int hf_drbd_state_role; +static int hf_drbd_state_peer; +static int hf_drbd_state_conn; +static int hf_drbd_state_disk; +static int hf_drbd_state_pdsk; +static int hf_drbd_state_susp; +static int hf_drbd_state_aftr_isp; +static int hf_drbd_state_peer_isp; +static int hf_drbd_state_user_isp; +static int hf_drbd_state_susp_nod; +static int hf_drbd_state_susp_fen; +static int hf_drbd_state_quorum; + +static int hf_drbd_twopc_flag_has_reachable; + +static int hf_drbd_uuid_flag_discard_my_data; +static int hf_drbd_uuid_flag_crashed_primary; +static int hf_drbd_uuid_flag_inconsistent; +static int hf_drbd_uuid_flag_skip_initial_sync; +static int hf_drbd_uuid_flag_new_datagen; +static int hf_drbd_uuid_flag_stable; +static int hf_drbd_uuid_flag_got_stable; +static int hf_drbd_uuid_flag_resync; +static int hf_drbd_uuid_flag_reconnect; +static int hf_drbd_uuid_flag_diskless_primary; +static int hf_drbd_uuid_flag_primary_lost_quorum; + +static int hf_drbd_dp_hardbarrier; +static int hf_drbd_dp_rw_sync; +static int hf_drbd_dp_may_set_in_sync; +static int hf_drbd_dp_unplug; +static int hf_drbd_dp_fua; +static int hf_drbd_dp_flush; +static int hf_drbd_dp_discard; +static int hf_drbd_dp_send_receive_ack; +static int hf_drbd_dp_send_write_ack; +static int hf_drbd_dp_wsame; +static int hf_drbd_dp_zeroes; + +static int hf_drbd_lb_tcp_seq; +static int hf_drbd_lb_tcp_length; + +static int ett_drbd; +static int ett_drbd_lb_tcp; +static int ett_drbd_state; +static int ett_drbd_twopc_flags; +static int ett_drbd_uuid_flags; +static int ett_drbd_history_uuids; +static int ett_drbd_data_flags; static int * const state_fields[] = { &hf_drbd_state_role, @@ -696,8 +731,8 @@ static int * const data_flag_fields[] = { #define CHALLENGE_LEN 64 -static gboolean is_bit_set_64(guint64 value, int bit) { - return !!(value & (G_GUINT64_CONSTANT(1) << bit)); +static bool is_bit_set_64(uint64_t value, int bit) { + return !!(value & (UINT64_C(1) << bit)); } /* @@ -713,10 +748,10 @@ static gboolean is_bit_set_64(guint64 value, int bit) { #define DRBD_MAGIC_100 0x8620ec20 #define DRBD_TRANSPORT_RDMA_MAGIC 0x5257494E -static guint get_drbd_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) +static unsigned read_drbd_packet_len(tvbuff_t *tvb, int offset) { - guint32 magic32; - guint16 magic16; + uint32_t magic32; + uint16_t magic16; magic32 = tvb_get_ntohl(tvb, offset); @@ -734,6 +769,27 @@ static guint get_drbd_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, return 0; } +static unsigned get_drbd_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_) +{ + unsigned drbd_len = read_drbd_packet_len(tvb, offset); + + if (tvb_reported_length_remaining(tvb, offset) >= DRBD_FRAME_HEADER_100_LEN && !drbd_len) { + /* We have enough data to recognize any header, but none matched. + * Either there is data corruption or this is actually an lb-tcp + * stream. It is possible that the capture is missing the first lb-tcp + * header. In that case, the stream will be misidentified as normal + * DRBD on TCP. + * + * Reset the dissector and throw some exception so that a new dissector + * is chosen by the heuristic. */ + conversation_t *conversation = find_or_create_conversation(pinfo); + conversation_set_dissector(conversation, NULL); + THROW(ReportedBoundsError); + } + + return drbd_len; +} + static int dissect_drbd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) { dissect_drbd_message(tvb, pinfo, tree); @@ -743,56 +799,123 @@ static int dissect_drbd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, static int dissect_drbd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) { col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD"); - tcp_dissect_pdus(tvb, pinfo, tree, TRUE, DRBD_FRAME_HEADER_80_LEN, + tcp_dissect_pdus(tvb, pinfo, tree, true, DRBD_FRAME_HEADER_80_LEN, get_drbd_pdu_len, dissect_drbd_pdu, data); return tvb_reported_length(tvb); } -static gboolean test_drbd_header(tvbuff_t *tvb) +static unsigned get_drbd_lb_tcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) { - guint reported_length = tvb_reported_length(tvb); - if (reported_length < DRBD_FRAME_HEADER_80_LEN || tvb_captured_length(tvb) < 4) { - return FALSE; + return 8 + tvb_get_ntohl(tvb, offset + 4); +} + +static int dissect_drbd_lb_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) +{ + proto_tree *lb_tcp_tree; + proto_item *lb_tcp_ti; + + lb_tcp_ti = proto_tree_add_item(tree, proto_drbd_lb_tcp, tvb, 0, -1, ENC_NA); + proto_item_set_text(lb_tcp_ti, "DRBD [lb-tcp]"); + lb_tcp_tree = proto_item_add_subtree(lb_tcp_ti, ett_drbd_lb_tcp); + + proto_tree_add_item(lb_tcp_tree, hf_drbd_lb_tcp_seq, tvb, 0, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(lb_tcp_tree, hf_drbd_lb_tcp_length, tvb, 4, 4, ENC_BIG_ENDIAN); + + unsigned offset = 8; + while (tvb_captured_length(tvb) >= offset + DRBD_FRAME_HEADER_80_LEN) { + unsigned length = read_drbd_packet_len(tvb, offset); + + /* Was a header recognized? */ + if (length == 0) { + const char *info_text = col_get_text(pinfo->cinfo, COL_INFO); + + col_clear(pinfo->cinfo, COL_INFO); + if (!info_text || !info_text[0]) + col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport); + col_append_str(pinfo->cinfo, COL_INFO, " [lb-tcp Payload]"); + col_set_fence(pinfo->cinfo, COL_INFO); + + break; + } + + dissect_drbd_message(tvb_new_subset_length(tvb, offset, length), pinfo, tree); + + offset += length; } - gboolean match = FALSE; - guint32 magic32 = tvb_get_ntohl(tvb, 0); + return tvb_reported_length(tvb); +} + +static int dissect_drbd_lb_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) +{ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD lb-tcp"); + tcp_dissect_pdus(tvb, pinfo, tree, true, 8, + get_drbd_lb_tcp_pdu_len, dissect_drbd_lb_tcp_pdu, data); + return tvb_reported_length(tvb); +} + +static bool test_drbd_header(tvbuff_t *tvb, int offset) +{ + int reported_length = tvb_reported_length(tvb); + int captured_length = tvb_captured_length(tvb); + + if (reported_length < offset + DRBD_FRAME_HEADER_80_LEN || captured_length < offset + 4) + return false; + + uint32_t magic32 = tvb_get_ntohl(tvb, offset); if (magic32 == DRBD_MAGIC) - match = TRUE; - else if (reported_length >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) - match = TRUE; + return true; + else if (reported_length >= offset + DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) + return true; else { - guint16 magic16 = tvb_get_ntohs(tvb, 0); + uint16_t magic16 = tvb_get_ntohs(tvb, offset); if (magic16 == DRBD_MAGIC_BIG) - match = TRUE; + return true; } - return match; + return false; } -static gboolean test_drbd_rdma_control_header(tvbuff_t *tvb) +static bool test_drbd_rdma_control_header(tvbuff_t *tvb) { - guint reported_length = tvb_reported_length(tvb); + unsigned reported_length = tvb_reported_length(tvb); if (reported_length < DRBD_TRANSPORT_RDMA_PACKET_LEN || tvb_captured_length(tvb) < 4) { - return FALSE; + return false; } - guint32 magic32 = tvb_get_ntohl(tvb, 0); + uint32_t magic32 = tvb_get_ntohl(tvb, 0); return magic32 == DRBD_TRANSPORT_RDMA_MAGIC; } -static gboolean test_drbd_protocol(tvbuff_t *tvb, packet_info *pinfo, +static bool test_drbd_protocol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - if (!test_drbd_header(tvb)) - return FALSE; + if (!test_drbd_header(tvb, 0)) + return false; conversation_t *conversation = find_or_create_conversation(pinfo); conversation_set_dissector(conversation, drbd_handle); dissect_drbd(tvb, pinfo, tree, data); - return TRUE; + return true; +} + +static bool test_drbd_lb_tcp_protocol(tvbuff_t *tvb, packet_info *pinfo, + proto_tree *tree, void *data _U_) +{ + /* DRBD packets may be split between lb-tcp wrapper packets. As a result, + * there may be lb-tcp packets that do not contain any DRBD header. + * However, we have no other way to identify lb-tcp packets, so look for a + * DRBD header anyway. This is a best-effort solution. */ + if (!test_drbd_header(tvb, 8)) + return false; + + conversation_t *conversation = find_or_create_conversation(pinfo); + conversation_set_dissector(conversation, drbd_lb_tcp_handle); + dissect_drbd_lb_tcp(tvb, pinfo, tree, data); + + return true; } /* @@ -816,7 +939,7 @@ static conversation_t *find_drbd_conversation(packet_info *pinfo) { address* addr_a; address* addr_b; - guint32 port_a = MIN(pinfo->srcport, pinfo->destport); + uint32_t port_a = MIN(pinfo->srcport, pinfo->destport); if (cmp_address(&pinfo->src, &pinfo->dst) < 0) { addr_a = &pinfo->src; @@ -841,10 +964,10 @@ static conversation_t *find_drbd_conversation(packet_info *pinfo) /** * Returns buffer containing the payload. */ -static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, guint16 *command) +static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, uint16_t *command) { - guint32 magic32; - guint16 magic16; + uint32_t magic32; + uint16_t magic16; magic32 = tvb_get_ntohl(tvb, 0); @@ -881,7 +1004,7 @@ static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, guint16 *command) return NULL; } -static const value_payload_decoder *find_payload_decoder(guint16 command) +static const value_payload_decoder *find_payload_decoder(uint16_t command) { for (unsigned int i = 0; i < array_length(payload_decoders); i++) { if (payload_decoders[i].value == command) { @@ -896,7 +1019,7 @@ static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree * { proto_tree *drbd_tree; proto_item *ti; - guint16 command = -1; + uint16_t command = -1; col_clear(pinfo->cinfo, COL_INFO); @@ -909,14 +1032,11 @@ static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree * return; /* Indicate what kind of message this is. */ - const gchar *packet_name = val_to_str(command, packet_names, "Unknown (0x%02x)"); - const gchar *info_text = col_get_text(pinfo->cinfo, COL_INFO); - if (!info_text || !info_text[0]) { + const char *packet_name = val_to_str(command, packet_names, "Unknown (0x%02x)"); + const char *info_text = col_get_text(pinfo->cinfo, COL_INFO); + if (!info_text || !info_text[0]) col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport); - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name); - } else { - col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name); - } + col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name); col_set_fence(pinfo->cinfo, COL_INFO); conversation_t *conv = find_drbd_conversation(pinfo); @@ -941,9 +1061,9 @@ static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree * (*payload_decoder->tree_fn) (payload_tvb, drbd_tree, conv_data); } -static void drbd_ib_append_col_info(packet_info *pinfo, const gchar *packet_name) +static void drbd_ib_append_col_info(packet_info *pinfo, const char *packet_name) { - const gchar *info_text; + const char *info_text; col_clear(pinfo->cinfo, COL_INFO); info_text = col_get_text(pinfo->cinfo, COL_INFO); @@ -958,7 +1078,7 @@ static void dissect_drbd_ib_message(tvbuff_t *tvb, packet_info *pinfo, proto_tre { proto_tree *drbd_tree; proto_item *ti; - guint16 command = -1; + uint16_t command = -1; ti = proto_tree_add_item(tree, proto_drbd, tvb, 0, -1, ENC_NA); drbd_tree = proto_item_add_subtree(ti, ett_drbd); @@ -969,7 +1089,7 @@ static void dissect_drbd_ib_message(tvbuff_t *tvb, packet_info *pinfo, proto_tre return; /* Indicate what kind of message this is. */ - const gchar *packet_name = val_to_str(command, packet_names, "Unknown (0x%02x)"); + const char *packet_name = val_to_str(command, packet_names, "Unknown (0x%02x)"); drbd_ib_append_col_info(pinfo, packet_name); if (tree == NULL) @@ -1002,20 +1122,20 @@ static void dissect_drbd_ib_control_message(tvbuff_t *tvb, packet_info *pinfo, p proto_tree_add_item(drbd_tree, hf_drbd_rx_desc_stolen_from, tvb, 12, 4, ENC_BIG_ENDIAN); } -static gboolean dissect_drbd_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) +static bool dissect_drbd_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { - if (!test_drbd_header(tvb) && !test_drbd_rdma_control_header(tvb)) - return FALSE; + if (!test_drbd_header(tvb, 0) && !test_drbd_rdma_control_header(tvb)) + return false; col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD RDMA"); while (1) { - guint length; - gboolean is_control_packet = test_drbd_rdma_control_header(tvb); + unsigned length; + bool is_control_packet = test_drbd_rdma_control_header(tvb); if (is_control_packet) length = DRBD_TRANSPORT_RDMA_PACKET_LEN; else - length = get_drbd_pdu_len(pinfo, tvb, 0, data); + length = read_drbd_packet_len(tvb, 0); /* Was a header recognized? */ if (length == 0) @@ -1036,17 +1156,17 @@ static gboolean dissect_drbd_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *t tvb = tvb_new_subset_remaining(tvb, length); } - return TRUE; + return true; } static void insert_twopc(tvbuff_t *tvb, packet_info *pinfo, drbd_conv *conv_data, enum drbd_packet command) { - guint32 flags = tvb_get_ntohl(tvb, 4); + uint32_t flags = tvb_get_ntohl(tvb, 4); drbd_twopc_key *key = wmem_new0(wmem_file_scope(), drbd_twopc_key); key->tid = tvb_get_ntohl(tvb, 0); if (flags & TWOPC_HAS_FLAGS) - key->initiator_node_id = tvb_get_gint8(tvb, 10); + key->initiator_node_id = tvb_get_int8(tvb, 10); else key->initiator_node_id = tvb_get_ntohil(tvb, 4); @@ -1098,7 +1218,7 @@ static void decode_payload_data(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv { decode_data_common(tvb, tree); - guint nbytes = tvb_reported_length_remaining(tvb, 24); + unsigned nbytes = tvb_reported_length_remaining(tvb, 24); proto_tree_add_uint(tree, hf_drbd_size, tvb, 0, 0, nbytes); /* For infiniband the data is not in this tvb, so we do not show the data field. */ @@ -1131,8 +1251,8 @@ static void decode_payload_dagtag_data_request(tvbuff_t *tvb, proto_tree *tree, static void decode_payload_sync_param(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) { - guint length = tvb_reported_length(tvb); - guint offset = 0; + unsigned length = tvb_reported_length(tvb); + unsigned offset = 0; proto_tree_add_item(tree, hf_drbd_resync_rate, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; @@ -1197,7 +1317,7 @@ static void decode_payload_state(tvbuff_t *tvb, proto_tree *tree, drbd_conv *con } /* Filter fields leaving only those with bitmask overlapping with the given mask. */ -static void mask_fields(guint32 mask, int * const fields[], int * masked_fields[]) +static void mask_fields(uint32_t mask, int * const fields[], int * masked_fields[]) { int masked_i = 0; @@ -1213,9 +1333,9 @@ static void mask_fields(guint32 mask, int * const fields[], int * masked_fields[ masked_fields[masked_i] = NULL; } -static void decode_state_change(tvbuff_t *tvb, proto_tree *tree, gint offset) +static void decode_state_change(tvbuff_t *tvb, proto_tree *tree, int offset) { - guint32 state_mask = tvb_get_ntohl(tvb, offset); + uint32_t state_mask = tvb_get_ntohl(tvb, offset); int * masked_state_fields[array_length(state_fields)]; mask_fields(state_mask, state_fields, masked_state_fields); @@ -1249,12 +1369,12 @@ static void decode_payload_out_of_sync(tvbuff_t *tvb, proto_tree *tree, drbd_con } /* Return the twopc flags, if present. */ -static guint32 decode_twopc_request_common(tvbuff_t *tvb, proto_tree *tree, drbd_twopc_key *key) +static uint32_t decode_twopc_request_common(tvbuff_t *tvb, proto_tree *tree, drbd_twopc_key *key) { proto_tree_add_item_ret_uint(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN, key ? &key->tid : NULL); - guint32 flags = tvb_get_ntohl(tvb, 4); + uint32_t flags = tvb_get_ntohl(tvb, 4); if (flags & TWOPC_HAS_FLAGS) { proto_tree_add_bitmask(tree, tvb, 4, hf_drbd_twopc_flags, ett_drbd_twopc_flags, twopc_flag_fields, ENC_BIG_ENDIAN); proto_tree_add_item_ret_int(tree, hf_drbd_initiator_node_id, tvb, 10, 1, ENC_BIG_ENDIAN, @@ -1273,7 +1393,7 @@ static guint32 decode_twopc_request_common(tvbuff_t *tvb, proto_tree *tree, drbd static void decode_payload_twopc_prepare(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) { - guint32 flags = decode_twopc_request_common(tvb, tree, NULL); + uint32_t flags = decode_twopc_request_common(tvb, tree, NULL); if (!(flags & TWOPC_HAS_FLAGS)) proto_tree_add_item(tree, hf_drbd_primary_nodes, tvb, 20, 8, ENC_BIG_ENDIAN); @@ -1292,7 +1412,7 @@ static void decode_payload_twopc_prep_rsz(tvbuff_t *tvb, proto_tree *tree, drbd_ static void decode_payload_twopc_commit(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data) { drbd_twopc_key key; - guint32 flags = decode_twopc_request_common(tvb, tree, &key); + uint32_t flags = decode_twopc_request_common(tvb, tree, &key); if (!conv_data) return; @@ -1329,13 +1449,13 @@ static void decode_payload_uuids110(tvbuff_t *tvb, proto_tree *tree, drbd_conv * proto_tree_add_bitmask(tree, tvb, 16, hf_drbd_uuid_flags, ett_drbd_uuid_flags, uuid_flag_fields, ENC_BIG_ENDIAN); proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 24, 8, ENC_BIG_ENDIAN); - guint64 bitmap_uuids_mask; + uint64_t bitmap_uuids_mask; proto_tree_add_item_ret_uint64(tree, hf_drbd_bitmap_uuids_mask, tvb, 32, 8, ENC_BIG_ENDIAN, &bitmap_uuids_mask); - guint offset = 40; + unsigned offset = 40; for (int i = 0; i < 64; i++) { if (is_bit_set_64(bitmap_uuids_mask, i)) { - guint64 bitmap_uuid = tvb_get_ntoh64(tvb, offset); + uint64_t bitmap_uuid = tvb_get_ntoh64(tvb, offset); proto_tree_add_uint64_format(tree, hf_drbd_bitmap_uuid, tvb, offset, 8, bitmap_uuid, "Bitmap UUID for node %d: 0x%016" PRIx64, i, bitmap_uuid); offset += 8; @@ -1344,7 +1464,7 @@ static void decode_payload_uuids110(tvbuff_t *tvb, proto_tree *tree, drbd_conv * proto_item *history_uuids = proto_tree_add_item(tree, hf_drbd_history_uuid_list, tvb, offset, -1, ENC_NA); proto_tree *history_tree = proto_item_add_subtree(history_uuids, ett_drbd_history_uuids); - guint total_length = tvb_reported_length(tvb); + unsigned total_length = tvb_reported_length(tvb); while (offset < total_length) { proto_tree_add_item(history_tree, hf_drbd_history_uuid, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; @@ -1374,7 +1494,7 @@ static void decode_payload_data_wsame(tvbuff_t *tvb, proto_tree *tree, drbd_conv decode_data_common(tvb, tree); proto_tree_add_item(tree, hf_drbd_size, tvb, 24, 4, ENC_BIG_ENDIAN); - guint nbytes = tvb_reported_length_remaining(tvb, 28); + unsigned nbytes = tvb_reported_length_remaining(tvb, 28); /* For infiniband the data is not in this tvb, so we do not show the data field. */ if (tvb_captured_length(tvb) >= 28 + nbytes) { proto_tree_add_bytes_format(tree, hf_drbd_data, tvb, 28, @@ -1396,6 +1516,15 @@ static void decode_payload_block_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 20, 4, ENC_BIG_ENDIAN); } +static void decode_payload_ov_result(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) +{ + proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); + proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 20, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(tree, hf_drbd_ov_result, tvb, 24, 8, ENC_BIG_ENDIAN); +} + static void decode_payload_barrier_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) { proto_tree_add_item(tree, hf_drbd_barrier, tvb, 0, 4, ENC_LITTLE_ENDIAN); @@ -1457,7 +1586,7 @@ static void decode_payload_twopc_reply(tvbuff_t *tvb, proto_tree *tree, drbd_con } } -static void format_node_mask(gchar *s, guint64 value) +static void format_node_mask(char *s, uint64_t value) { if (!value) { (void) g_strlcpy(s, "<none>", ITEM_LABEL_LENGTH); @@ -1467,7 +1596,7 @@ static void format_node_mask(gchar *s, guint64 value) int written = 0; int run_start = -1; for (int i = 0; i < 64 && written < ITEM_LABEL_LENGTH; i++) { - gboolean is_set = is_bit_set_64(value, i); + bool is_set = is_bit_set_64(value, i); int run_end; if (!is_set) { @@ -1510,6 +1639,7 @@ void proto_register_drbd(void) { &hf_drbd_sector, { "Sector", "drbd.sector", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_block_id, { "Block ID", "drbd.block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_seq_num, { "Sequence number", "drbd.seq_num", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_drbd_ov_result, { "Online verify result", "drbd.ov_result", FT_UINT64, BASE_DEC|BASE_VAL64_STRING, VALS64(ov_result_codes), 0x0, NULL, HFILL }}, { &hf_drbd_dp_flags, { "Data flags", "drbd.dp_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_data, { "Data", "drbd.data", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_size, { "Size", "drbd.size", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, @@ -1522,13 +1652,13 @@ void proto_register_drbd(void) { &hf_drbd_set_size, { "set_size", "drbd.set_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_oldest_block_id, { "oldest_block_id", "drbd.oldest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_youngest_block_id, { "youngest_block_id", "drbd.youngest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, - { &hf_drbd_resync_rate, { "resync_rate", "drbd.resync_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_kibps, 0x0, NULL, HFILL }}, + { &hf_drbd_resync_rate, { "resync_rate", "drbd.resync_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_kibps), 0x0, NULL, HFILL }}, { &hf_drbd_verify_alg, { "verify_alg", "drbd.verify_alg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_csums_alg, { "csums_alg", "drbd.csums_alg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_c_plan_ahead, { "c_plan_ahead", "drbd.c_plan_ahead", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_c_delay_target, { "c_delay_target", "drbd.c_delay_target", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_c_fill_target, { "c_fill_target", "drbd.c_fill_target", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, - { &hf_drbd_c_max_rate, { "c_max_rate", "drbd.c_max_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, &units_kibps, 0x0, NULL, HFILL }}, + { &hf_drbd_c_max_rate, { "c_max_rate", "drbd.c_max_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_kibps), 0x0, NULL, HFILL }}, { &hf_drbd_protocol, { "protocol", "drbd.protocol", FT_UINT32, BASE_HEX, VALS(protocol_names), 0x0, NULL, HFILL }}, { &hf_drbd_after_sb_0p, { "after_sb_0p", "drbd.after_sb_0p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_drbd_after_sb_1p, { "after_sb_1p", "drbd.after_sb_1p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, @@ -1621,8 +1751,14 @@ void proto_register_drbd(void) { &hf_drbd_dp_zeroes, { "zeroes", "drbd.dp_flag.zeroes", FT_BOOLEAN, 32, NULL, DP_ZEROES, NULL, HFILL }}, }; - static gint *ett[] = { + static hf_register_info hf_lb_tcp[] = { + { &hf_drbd_lb_tcp_seq, { "lb-tcp sequence number", "drbd_lb_tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, + { &hf_drbd_lb_tcp_length, { "lb-tcp length", "drbd_lb_tcp.length", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, + }; + + static int *ett[] = { &ett_drbd, + &ett_drbd_lb_tcp, &ett_drbd_state, &ett_drbd_twopc_flags, &ett_drbd_uuid_flags, @@ -1632,15 +1768,21 @@ void proto_register_drbd(void) proto_drbd = proto_register_protocol("DRBD Protocol", "DRBD", "drbd"); proto_register_field_array(proto_drbd, hf, array_length(hf)); + + proto_drbd_lb_tcp = proto_register_protocol("DRBD Load-Balanced Protocol", "DRBD lb-tcp", "drbd_lb_tcp"); + proto_register_field_array(proto_drbd_lb_tcp, hf_lb_tcp, array_length(hf_lb_tcp)); + proto_register_subtree_array(ett, array_length(ett)); drbd_handle = register_dissector("drbd", dissect_drbd, proto_drbd); + drbd_lb_tcp_handle = register_dissector("drbd_lb_tcp", dissect_drbd_lb_tcp, proto_drbd_lb_tcp); } void proto_reg_handoff_drbd(void) { heur_dissector_add("tcp", test_drbd_protocol, "DRBD over TCP", "drbd_tcp", proto_drbd, HEURISTIC_DISABLE); heur_dissector_add("infiniband.payload", dissect_drbd_ib, "DRBD over RDMA", "drbd_rdma", proto_drbd, HEURISTIC_DISABLE); + heur_dissector_add("tcp", test_drbd_lb_tcp_protocol, "DRBD Load-Balanced over TCP", "drbd_lb_tcp", proto_drbd_lb_tcp, HEURISTIC_DISABLE); } /* |