2 * Routines for DRBD dissection
3 * By Joel Colledge <joel.colledge@linbit.com>
4 * Copyright 2019, LINBIT Information Technologies GmbH
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 * Wireshark dissector for DRBD - Distributed Replicated Block Device.
15 * The DRBD Linux kernel module sources can be found at https://github.com/LINBIT/drbd
16 * More information about Linbit and DRBD can be found at https://www.linbit.com/
21 #include <epan/packet.h>
22 #include <epan/exceptions.h>
23 #include <epan/unit_strings.h>
24 #include "packet-tcp.h"
26 #include <wsutil/str_util.h>
27 #include <wsutil/array.h>
29 /* Known as SHARED_SECRET_MAX in the DRBD sources */
30 #define DRBD_STRING_MAX 64
35 P_RS_DATA_REPLY
= 0x02,
38 P_BECOME_SYNC_TARGET
= 0x05,
39 P_BECOME_SYNC_SOURCE
= 0x06,
40 P_UNPLUG_REMOTE
= 0x07,
41 P_DATA_REQUEST
= 0x08,
42 P_RS_DATA_REQUEST
= 0x09,
49 P_AUTH_CHALLENGE
= 0x10,
50 P_AUTH_RESPONSE
= 0x11,
51 P_STATE_CHG_REQ
= 0x12,
57 P_RS_WRITE_ACK
= 0x17,
61 P_NEG_RS_DREPLY
= 0x1b,
63 P_STATE_CHG_REPLY
= 0x1d,
68 P_CSUM_RS_REQUEST
= 0x21,
69 P_RS_IS_IN_SYNC
= 0x22,
70 P_SYNC_PARAM89
= 0x23,
71 P_COMPRESSED_BITMAP
= 0x24,
76 P_CONN_ST_CHG_REQ
= 0x2a,
77 P_CONN_ST_CHG_REPLY
= 0x2b,
79 P_PROTOCOL_UPDATE
= 0x2d,
80 P_TWOPC_PREPARE
= 0x2e,
88 P_RS_DEALLOCATED
= 0x33,
91 P_TWOPC_PREP_RSZ
= 0x35,
95 P_PEERS_IN_SYNC
= 0x41,
99 P_CURRENT_UUID
= 0x44,
103 P_TWOPC_COMMIT
= 0x47,
104 P_TWOPC_RETRY
= 0x48,
106 P_CONFIRM_STABLE
= 0x49,
108 P_RS_CANCEL_AHEAD
= 0x4a,
112 P_RS_DAGTAG_REQ
= 0x4c,
113 P_RS_CSUM_DAGTAG_REQ
= 0x4d,
114 P_RS_THIN_DAGTAG_REQ
= 0x4e,
115 P_OV_DAGTAG_REQ
= 0x4f,
116 P_OV_DAGTAG_REPLY
= 0x50,
118 P_WRITE_ACK_IN_SYNC
= 0x51,
120 P_OV_RESULT_ID
= 0x53,
121 P_RS_DEALLOCATED_ID
= 0x54,
123 P_INITIAL_META
= 0xfff1,
124 P_INITIAL_DATA
= 0xfff2,
126 P_CONNECTION_FEATURES
= 0xfffe
131 int32_t initiator_node_id
;
135 uint32_t prepare_frame
;
136 enum drbd_packet command
;
139 static unsigned drbd_twopc_key_hash(const void *k
)
141 const drbd_twopc_key
*key
= (const drbd_twopc_key
*) k
;
146 static int drbd_twopc_key_equal(const void *k1
, const void *k2
)
148 const drbd_twopc_key
*key1
= (const drbd_twopc_key
*) k1
;
149 const drbd_twopc_key
*key2
= (const drbd_twopc_key
*) k2
;
151 return key1
->tid
== key2
->tid
&& key1
->initiator_node_id
== key2
->initiator_node_id
;
158 typedef struct value_payload_decoder
{
160 void (*state_reader_fn
)(tvbuff_t
*, packet_info
*, drbd_conv
*);
161 void (*tree_fn
)(tvbuff_t
*, proto_tree
*, drbd_conv
*);
162 } value_payload_decoder
;
164 static const value_string packet_names
[] = {
165 { P_DATA
, "P_DATA" },
166 { P_DATA_REPLY
, "P_DATA_REPLY" },
167 { P_RS_DATA_REPLY
, "P_RS_DATA_REPLY" },
168 { P_BARRIER
, "P_BARRIER" },
169 { P_BITMAP
, "P_BITMAP" },
170 { P_BECOME_SYNC_TARGET
, "P_BECOME_SYNC_TARGET" },
171 { P_BECOME_SYNC_SOURCE
, "P_BECOME_SYNC_SOURCE" },
172 { P_UNPLUG_REMOTE
, "P_UNPLUG_REMOTE" },
173 { P_DATA_REQUEST
, "P_DATA_REQUEST" },
174 { P_RS_DATA_REQUEST
, "P_RS_DATA_REQUEST" },
175 { P_SYNC_PARAM
, "P_SYNC_PARAM" },
176 { P_PROTOCOL
, "P_PROTOCOL" },
177 { P_UUIDS
, "P_UUIDS" },
178 { P_SIZES
, "P_SIZES" },
179 { P_STATE
, "P_STATE" },
180 { P_SYNC_UUID
, "P_SYNC_UUID" },
181 { P_AUTH_CHALLENGE
, "P_AUTH_CHALLENGE" },
182 { P_AUTH_RESPONSE
, "P_AUTH_RESPONSE" },
183 { P_STATE_CHG_REQ
, "P_STATE_CHG_REQ" },
185 { P_PING
, "P_PING" },
186 { P_PING_ACK
, "P_PING_ACK" },
187 { P_RECV_ACK
, "P_RECV_ACK" },
188 { P_WRITE_ACK
, "P_WRITE_ACK" },
189 { P_RS_WRITE_ACK
, "P_RS_WRITE_ACK" },
190 { P_SUPERSEDED
, "P_SUPERSEDED" },
191 { P_NEG_ACK
, "P_NEG_ACK" },
192 { P_NEG_DREPLY
, "P_NEG_DREPLY" },
193 { P_NEG_RS_DREPLY
, "P_NEG_RS_DREPLY" },
194 { P_BARRIER_ACK
, "P_BARRIER_ACK" },
195 { P_STATE_CHG_REPLY
, "P_STATE_CHG_REPLY" },
197 { P_OV_REQUEST
, "P_OV_REQUEST" },
198 { P_OV_REPLY
, "P_OV_REPLY" },
199 { P_OV_RESULT
, "P_OV_RESULT" },
200 { P_CSUM_RS_REQUEST
, "P_CSUM_RS_REQUEST" },
201 { P_RS_IS_IN_SYNC
, "P_RS_IS_IN_SYNC" },
202 { P_SYNC_PARAM89
, "P_SYNC_PARAM89" },
203 { P_COMPRESSED_BITMAP
, "P_COMPRESSED_BITMAP" },
205 { P_DELAY_PROBE
, "P_DELAY_PROBE" },
206 { P_OUT_OF_SYNC
, "P_OUT_OF_SYNC" },
207 { P_RS_CANCEL
, "P_RS_CANCEL" },
208 { P_CONN_ST_CHG_REQ
, "P_CONN_ST_CHG_REQ" },
209 { P_CONN_ST_CHG_REPLY
, "P_CONN_ST_CHG_REPLY" },
210 { P_RETRY_WRITE
, "P_RETRY_WRITE" },
211 { P_PROTOCOL_UPDATE
, "P_PROTOCOL_UPDATE" },
212 { P_TWOPC_PREPARE
, "P_TWOPC_PREPARE" },
213 { P_TWOPC_ABORT
, "P_TWOPC_ABORT" },
215 { P_DAGTAG
, "P_DAGTAG" },
217 { P_TRIM
, "P_TRIM" },
219 { P_RS_THIN_REQ
, "P_RS_THIN_REQ" },
220 { P_RS_DEALLOCATED
, "P_RS_DEALLOCATED" },
222 { P_WSAME
, "P_WSAME" },
223 { P_TWOPC_PREP_RSZ
, "P_TWOPC_PREP_RSZ" },
224 { P_ZEROES
, "P_ZEROES" },
226 { P_PEER_ACK
, "P_PEER_ACK" },
227 { P_PEERS_IN_SYNC
, "P_PEERS_IN_SYNC" },
229 { P_UUIDS110
, "P_UUIDS110" },
230 { P_PEER_DAGTAG
, "P_PEER_DAGTAG" },
231 { P_CURRENT_UUID
, "P_CURRENT_UUID" },
233 { P_TWOPC_YES
, "P_TWOPC_YES" },
234 { P_TWOPC_NO
, "P_TWOPC_NO" },
235 { P_TWOPC_COMMIT
, "P_TWOPC_COMMIT" },
236 { P_TWOPC_RETRY
, "P_TWOPC_RETRY" },
238 { P_CONFIRM_STABLE
, "P_CONFIRM_STABLE" },
240 { P_RS_CANCEL_AHEAD
, "P_RS_CANCEL_AHEAD" },
242 { P_DISCONNECT
, "P_DISCONNECT" },
244 { P_RS_DAGTAG_REQ
, "P_RS_DAGTAG_REQ" },
245 { P_RS_CSUM_DAGTAG_REQ
, "P_RS_CSUM_DAGTAG_REQ" },
246 { P_RS_THIN_DAGTAG_REQ
, "P_RS_THIN_DAGTAG_REQ" },
247 { P_OV_DAGTAG_REQ
, "P_OV_DAGTAG_REQ" },
248 { P_OV_DAGTAG_REPLY
, "P_OV_DAGTAG_REPLY" },
250 { P_WRITE_ACK_IN_SYNC
, "P_WRITE_ACK_IN_SYNC" },
251 { P_RS_NEG_ACK
, "P_RS_NEG_ACK" },
252 { P_OV_RESULT_ID
, "P_OV_RESULT_ID" },
253 { P_RS_DEALLOCATED_ID
, "P_RS_DEALLOCATED_ID" },
255 { P_INITIAL_META
, "P_INITIAL_META" },
256 { P_INITIAL_DATA
, "P_INITIAL_DATA" },
258 { P_CONNECTION_FEATURES
, "P_CONNECTION_FEATURES" },
262 #define DRBD_PROT_A 1
263 #define DRBD_PROT_B 2
264 #define DRBD_PROT_C 3
266 static const value_string protocol_names
[] = {
267 { DRBD_PROT_A
, "A" },
268 { DRBD_PROT_B
, "B" },
269 { DRBD_PROT_C
, "C" },
273 #define DRBD_ROLE_UNKNOWN 0
274 #define DRBD_ROLE_PRIMARY 1
275 #define DRBD_ROLE_SECONDARY 2
277 static const value_string role_names
[] = {
278 { DRBD_ROLE_UNKNOWN
, "UNKNOWN" },
279 { DRBD_ROLE_PRIMARY
, "PRIMARY" },
280 { DRBD_ROLE_SECONDARY
, "SECONDARY" },
284 #define DRBD_CONNECTION_STATE_C_STANDALONE 0
285 #define DRBD_CONNECTION_STATE_C_DISCONNECTING 1
286 #define DRBD_CONNECTION_STATE_C_UNCONNECTED 2
287 #define DRBD_CONNECTION_STATE_C_TIMEOUT 3
288 #define DRBD_CONNECTION_STATE_C_BROKEN_PIPE 4
289 #define DRBD_CONNECTION_STATE_C_NETWORK_FAILURE 5
290 #define DRBD_CONNECTION_STATE_C_PROTOCOL_ERROR 6
291 #define DRBD_CONNECTION_STATE_C_TEAR_DOWN 7
292 #define DRBD_CONNECTION_STATE_C_CONNECTING 8
293 #define DRBD_CONNECTION_STATE_C_CONNECTED 9
294 #define DRBD_CONNECTION_STATE_L_ESTABLISHED 10
295 #define DRBD_CONNECTION_STATE_L_STARTING_SYNC_S 11
296 #define DRBD_CONNECTION_STATE_L_STARTING_SYNC_T 12
297 #define DRBD_CONNECTION_STATE_L_WF_BITMAP_S 13
298 #define DRBD_CONNECTION_STATE_L_WF_BITMAP_T 14
299 #define DRBD_CONNECTION_STATE_L_WF_SYNC_UUID 15
300 #define DRBD_CONNECTION_STATE_L_SYNC_SOURCE 16
301 #define DRBD_CONNECTION_STATE_L_SYNC_TARGET 17
302 #define DRBD_CONNECTION_STATE_L_VERIFY_S 18
303 #define DRBD_CONNECTION_STATE_L_VERIFY_T 19
304 #define DRBD_CONNECTION_STATE_L_PAUSED_SYNC_S 20
305 #define DRBD_CONNECTION_STATE_L_PAUSED_SYNC_T 21
306 #define DRBD_CONNECTION_STATE_L_AHEAD 22
307 #define DRBD_CONNECTION_STATE_L_BEHIND 23
309 static const value_string connection_state_names
[] = {
310 { DRBD_CONNECTION_STATE_C_STANDALONE
, "C_STANDALONE" },
311 { DRBD_CONNECTION_STATE_C_DISCONNECTING
, "C_DISCONNECTING" },
312 { DRBD_CONNECTION_STATE_C_UNCONNECTED
, "C_UNCONNECTED" },
313 { DRBD_CONNECTION_STATE_C_TIMEOUT
, "C_TIMEOUT" },
314 { DRBD_CONNECTION_STATE_C_BROKEN_PIPE
, "C_BROKEN_PIPE" },
315 { DRBD_CONNECTION_STATE_C_NETWORK_FAILURE
, "C_NETWORK_FAILURE" },
316 { DRBD_CONNECTION_STATE_C_PROTOCOL_ERROR
, "C_PROTOCOL_ERROR" },
317 { DRBD_CONNECTION_STATE_C_TEAR_DOWN
, "C_TEAR_DOWN" },
318 { DRBD_CONNECTION_STATE_C_CONNECTING
, "C_CONNECTING" },
319 { DRBD_CONNECTION_STATE_C_CONNECTED
, "C_CONNECTED" },
320 { DRBD_CONNECTION_STATE_L_ESTABLISHED
, "L_ESTABLISHED" },
321 { DRBD_CONNECTION_STATE_L_STARTING_SYNC_S
, "L_STARTING_SYNC_S" },
322 { DRBD_CONNECTION_STATE_L_STARTING_SYNC_T
, "L_STARTING_SYNC_T" },
323 { DRBD_CONNECTION_STATE_L_WF_BITMAP_S
, "L_WF_BITMAP_S" },
324 { DRBD_CONNECTION_STATE_L_WF_BITMAP_T
, "L_WF_BITMAP_T" },
325 { DRBD_CONNECTION_STATE_L_WF_SYNC_UUID
, "L_WF_SYNC_UUID" },
326 { DRBD_CONNECTION_STATE_L_SYNC_SOURCE
, "L_SYNC_SOURCE" },
327 { DRBD_CONNECTION_STATE_L_SYNC_TARGET
, "L_SYNC_TARGET" },
328 { DRBD_CONNECTION_STATE_L_VERIFY_S
, "L_VERIFY_S" },
329 { DRBD_CONNECTION_STATE_L_VERIFY_T
, "L_VERIFY_T" },
330 { DRBD_CONNECTION_STATE_L_PAUSED_SYNC_S
, "L_PAUSED_SYNC_S" },
331 { DRBD_CONNECTION_STATE_L_PAUSED_SYNC_T
, "L_PAUSED_SYNC_T" },
332 { DRBD_CONNECTION_STATE_L_AHEAD
, "L_AHEAD" },
333 { DRBD_CONNECTION_STATE_L_BEHIND
, "L_BEHIND" },
337 #define DRBD_DISK_STATE_DISKLESS 0
338 #define DRBD_DISK_STATE_ATTACHING 1
339 #define DRBD_DISK_STATE_DETACHING 2
340 #define DRBD_DISK_STATE_FAILED 3
341 #define DRBD_DISK_STATE_NEGOTIATING 4
342 #define DRBD_DISK_STATE_INCONSISTENT 5
343 #define DRBD_DISK_STATE_OUTDATED 6
344 #define DRBD_DISK_STATE_UNKNOWN 7
345 #define DRBD_DISK_STATE_CONSISTENT 8
346 #define DRBD_DISK_STATE_UP_TO_DATE 9
348 static const value_string disk_state_names
[] = {
349 { DRBD_DISK_STATE_DISKLESS
, "D_DISKLESS" },
350 { DRBD_DISK_STATE_ATTACHING
, "D_ATTACHING" },
351 { DRBD_DISK_STATE_DETACHING
, "D_DETACHING" },
352 { DRBD_DISK_STATE_FAILED
, "D_FAILED" },
353 { DRBD_DISK_STATE_NEGOTIATING
, "D_NEGOTIATING" },
354 { DRBD_DISK_STATE_INCONSISTENT
, "D_INCONSISTENT" },
355 { DRBD_DISK_STATE_OUTDATED
, "D_OUTDATED" },
356 { DRBD_DISK_STATE_UNKNOWN
, "D_UNKNOWN" },
357 { DRBD_DISK_STATE_CONSISTENT
, "D_CONSISTENT" },
358 { DRBD_DISK_STATE_UP_TO_DATE
, "D_UP_TO_DATE" },
362 #define STATE_ROLE (0x3 << 0) /* 3/4 primary/secondary/unknown */
363 #define STATE_PEER (0x3 << 2) /* 3/4 primary/secondary/unknown */
364 #define STATE_CONN (0x1f << 4) /* 17/32 cstates */
365 #define STATE_DISK (0xf << 9) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */
366 #define STATE_PDSK (0xf << 13) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */
367 #define STATE_SUSP (0x1 << 17) /* 2/2 IO suspended no/yes (by user) */
368 #define STATE_AFTR_ISP (0x1 << 18) /* isp .. imposed sync pause */
369 #define STATE_PEER_ISP (0x1 << 19)
370 #define STATE_USER_ISP (0x1 << 20)
371 #define STATE_SUSP_NOD (0x1 << 21) /* IO suspended because no data */
372 #define STATE_SUSP_FEN (0x1 << 22) /* IO suspended because fence peer handler runs*/
373 #define STATE_QUORUM (0x1 << 23)
375 #define TWOPC_HAS_FLAGS 0x80000000 /* For packet dissectors */
376 #define TWOPC_HAS_REACHABLE 0x40000000 /* The reachable_nodes field is valid */
378 #define UUID_FLAG_DISCARD_MY_DATA 1
379 #define UUID_FLAG_CRASHED_PRIMARY 2
380 #define UUID_FLAG_INCONSISTENT 4
381 #define UUID_FLAG_SKIP_INITIAL_SYNC 8
382 #define UUID_FLAG_NEW_DATAGEN 16
383 #define UUID_FLAG_STABLE 32
384 #define UUID_FLAG_GOT_STABLE 64
385 #define UUID_FLAG_RESYNC 128
386 #define UUID_FLAG_RECONNECT 256
387 #define UUID_FLAG_DISKLESS_PRIMARY 512
388 #define UUID_FLAG_PRIMARY_LOST_QUORUM 1024
390 #define DP_HARDBARRIER 1
392 #define DP_MAY_SET_IN_SYNC 4
396 #define DP_DISCARD 64
397 #define DP_SEND_RECEIVE_ACK 128
398 #define DP_SEND_WRITE_ACK 256
400 #define DP_ZEROES 1024
402 #define OV_RESULT_SKIP 4710
403 #define OV_RESULT_IN_SYNC 4711
404 #define OV_RESULT_OUT_OF_SYNC 4712
406 static const val64_string ov_result_codes
[] = {
407 { OV_RESULT_SKIP
, "SKIP" },
408 { OV_RESULT_IN_SYNC
, "IN_SYNC" },
409 { OV_RESULT_OUT_OF_SYNC
, "OUT_OF_SYNC" },
413 #define DRBD_STREAM_DATA 0
414 #define DRBD_STREAM_CONTROL 1
416 static const value_string stream_names
[] = {
417 { DRBD_STREAM_DATA
, "Data" },
418 { DRBD_STREAM_CONTROL
, "Control" },
422 static void dissect_drbd_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
);
424 static void read_state_twopc_prepare(tvbuff_t
*tvb
, packet_info
*pinfo
, drbd_conv
*conv_data
);
425 static void read_state_twopc_prep_rsz(tvbuff_t
*tvb
, packet_info
*pinfo
, drbd_conv
*conv_data
);
427 static void decode_payload_connection_features(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
428 static void decode_payload_auth_challenge(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
429 static void decode_payload_auth_response(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
430 static void decode_payload_data(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
431 static void decode_payload_barrier(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
432 static void decode_payload_dagtag_data_request(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
433 static void decode_payload_data_request(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
434 static void decode_payload_sync_param(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
435 static void decode_payload_protocol(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
436 static void decode_payload_uuids(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
437 static void decode_payload_sizes(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
438 static void decode_payload_state(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
439 static void decode_payload_req_state(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
440 static void decode_payload_sync_uuid(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
441 static void decode_payload_skip(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
442 static void decode_payload_out_of_sync(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
443 static void decode_payload_twopc_prepare(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
444 static void decode_payload_twopc_prep_rsz(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
445 static void decode_payload_twopc_commit(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
446 static void decode_payload_dagtag(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
447 static void decode_payload_uuids110(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
448 static void decode_payload_peer_dagtag(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
449 static void decode_payload_current_uuid(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
450 static void decode_payload_data_size(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
451 static void decode_payload_data_wsame(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
452 static void decode_payload_rs_deallocated(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
454 static void decode_payload_block_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
455 static void decode_payload_ov_result(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
456 static void decode_payload_barrier_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
457 static void decode_payload_confirm_stable(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
458 static void decode_payload_rq_s_reply(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
459 static void decode_payload_peer_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
460 static void decode_payload_peers_in_sync(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
461 static void decode_payload_twopc_reply(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
);
463 static const value_payload_decoder payload_decoders
[] = {
464 { P_CONNECTION_FEATURES
, NULL
, decode_payload_connection_features
},
465 { P_AUTH_CHALLENGE
, NULL
, decode_payload_auth_challenge
},
466 { P_AUTH_RESPONSE
, NULL
, decode_payload_auth_response
},
467 { P_DATA
, NULL
, decode_payload_data
},
468 { P_DATA_REPLY
, NULL
, decode_payload_data
},
469 { P_RS_DATA_REPLY
, NULL
, decode_payload_data
},
470 { P_BARRIER
, NULL
, decode_payload_barrier
},
471 { P_BITMAP
, NULL
, NULL
}, /* TODO: decode additional data */
472 { P_COMPRESSED_BITMAP
, NULL
, NULL
}, /* TODO: decode additional data */
473 { P_UNPLUG_REMOTE
, NULL
, NULL
},
474 { P_DATA_REQUEST
, NULL
, decode_payload_data_request
},
475 { P_RS_DATA_REQUEST
, NULL
, decode_payload_data_request
},
476 { P_SYNC_PARAM
, NULL
, decode_payload_sync_param
},
477 { P_SYNC_PARAM89
, NULL
, decode_payload_sync_param
},
478 { P_PROTOCOL
, NULL
, decode_payload_protocol
},
479 { P_UUIDS
, NULL
, decode_payload_uuids
},
480 { P_SIZES
, NULL
, decode_payload_sizes
},
481 { P_STATE
, NULL
, decode_payload_state
},
482 { P_STATE_CHG_REQ
, NULL
, decode_payload_req_state
},
483 { P_SYNC_UUID
, NULL
, decode_payload_sync_uuid
},
484 { P_OV_REQUEST
, NULL
, decode_payload_data_request
},
485 { P_OV_REPLY
, NULL
, decode_payload_data_request
}, /* TODO: decode additional data */
486 { P_CSUM_RS_REQUEST
, NULL
, decode_payload_data_request
}, /* TODO: decode additional data */
487 { P_RS_THIN_REQ
, NULL
, decode_payload_data_request
},
488 { P_DELAY_PROBE
, NULL
, decode_payload_skip
},
489 { P_OUT_OF_SYNC
, NULL
, decode_payload_out_of_sync
},
490 { P_CONN_ST_CHG_REQ
, NULL
, decode_payload_req_state
},
491 { P_PROTOCOL_UPDATE
, NULL
, decode_payload_protocol
}, /* TODO: decode additional data */
492 { P_TWOPC_PREPARE
, read_state_twopc_prepare
, decode_payload_twopc_prepare
},
493 { P_TWOPC_PREP_RSZ
, read_state_twopc_prep_rsz
, decode_payload_twopc_prep_rsz
},
494 { P_TWOPC_ABORT
, NULL
, decode_payload_twopc_commit
},
495 { P_DAGTAG
, NULL
, decode_payload_dagtag
},
496 { P_UUIDS110
, NULL
, decode_payload_uuids110
},
497 { P_PEER_DAGTAG
, NULL
, decode_payload_peer_dagtag
},
498 { P_CURRENT_UUID
, NULL
, decode_payload_current_uuid
},
499 { P_TWOPC_COMMIT
, NULL
, decode_payload_twopc_commit
},
500 { P_TRIM
, NULL
, decode_payload_data_size
},
501 { P_ZEROES
, NULL
, decode_payload_data_size
},
502 { P_RS_DEALLOCATED
, NULL
, decode_payload_rs_deallocated
},
503 { P_RS_DEALLOCATED_ID
, NULL
, decode_payload_block_ack
},
504 { P_WSAME
, NULL
, decode_payload_data_wsame
},
505 { P_DISCONNECT
, NULL
, NULL
},
506 { P_RS_DAGTAG_REQ
, NULL
, decode_payload_dagtag_data_request
},
507 { P_RS_CSUM_DAGTAG_REQ
, NULL
, decode_payload_dagtag_data_request
},
508 { P_RS_THIN_DAGTAG_REQ
, NULL
, decode_payload_dagtag_data_request
},
509 { P_OV_DAGTAG_REQ
, NULL
, decode_payload_dagtag_data_request
},
510 { P_OV_DAGTAG_REPLY
, NULL
, decode_payload_dagtag_data_request
},
512 { P_PING
, NULL
, NULL
},
513 { P_PING_ACK
, NULL
, NULL
},
514 { P_RECV_ACK
, NULL
, decode_payload_block_ack
},
515 { P_WRITE_ACK
, NULL
, decode_payload_block_ack
},
516 { P_WRITE_ACK_IN_SYNC
, NULL
, decode_payload_block_ack
},
517 { P_SUPERSEDED
, NULL
, decode_payload_block_ack
},
518 { P_NEG_ACK
, NULL
, decode_payload_block_ack
},
519 { P_NEG_DREPLY
, NULL
, decode_payload_block_ack
},
520 { P_NEG_RS_DREPLY
, NULL
, decode_payload_block_ack
},
521 { P_RS_WRITE_ACK
, NULL
, decode_payload_block_ack
},
522 { P_RS_NEG_ACK
, NULL
, decode_payload_block_ack
},
523 { P_OV_RESULT
, NULL
, decode_payload_block_ack
},
524 { P_OV_RESULT_ID
, NULL
, decode_payload_ov_result
},
525 { P_BARRIER_ACK
, NULL
, decode_payload_barrier_ack
},
526 { P_CONFIRM_STABLE
, NULL
, decode_payload_confirm_stable
},
527 { P_STATE_CHG_REPLY
, NULL
, decode_payload_rq_s_reply
},
528 { P_RS_IS_IN_SYNC
, NULL
, decode_payload_block_ack
},
529 { P_DELAY_PROBE
, NULL
, decode_payload_skip
},
530 { P_RS_CANCEL
, NULL
, decode_payload_block_ack
},
531 { P_RS_CANCEL_AHEAD
, NULL
, decode_payload_block_ack
},
532 { P_CONN_ST_CHG_REPLY
, NULL
, decode_payload_rq_s_reply
},
533 { P_RETRY_WRITE
, NULL
, decode_payload_block_ack
},
534 { P_PEER_ACK
, NULL
, decode_payload_peer_ack
},
535 { P_PEERS_IN_SYNC
, NULL
, decode_payload_peers_in_sync
},
536 { P_TWOPC_YES
, NULL
, decode_payload_twopc_reply
},
537 { P_TWOPC_NO
, NULL
, decode_payload_twopc_reply
},
538 { P_TWOPC_RETRY
, NULL
, decode_payload_twopc_reply
},
542 void proto_register_drbd(void);
543 void proto_reg_handoff_drbd(void);
545 static dissector_handle_t drbd_handle
;
546 static dissector_handle_t drbd_lb_tcp_handle
;
548 static int proto_drbd
;
549 static int proto_drbd_lb_tcp
;
551 static int hf_drbd_command
;
552 static int hf_drbd_length
;
553 static int hf_drbd_volume
;
554 static int hf_drbd_auth_challenge_nonce
;
555 static int hf_drbd_auth_response_hash
;
556 static int hf_drbd_sector
;
557 static int hf_drbd_block_id
;
558 static int hf_drbd_seq_num
;
559 static int hf_drbd_ov_result
;
560 static int hf_drbd_dp_flags
;
561 static int hf_drbd_data
;
562 static int hf_drbd_size
;
563 static int hf_drbd_protocol_min
;
564 static int hf_drbd_feature_flags
;
565 static int hf_drbd_protocol_max
;
566 static int hf_drbd_sender_node_id
;
567 static int hf_drbd_receiver_node_id
;
568 static int hf_drbd_barrier
;
569 static int hf_drbd_set_size
;
570 static int hf_drbd_oldest_block_id
;
571 static int hf_drbd_youngest_block_id
;
572 static int hf_drbd_resync_rate
;
573 static int hf_drbd_verify_alg
;
574 static int hf_drbd_csums_alg
;
575 static int hf_drbd_c_plan_ahead
;
576 static int hf_drbd_c_delay_target
;
577 static int hf_drbd_c_fill_target
;
578 static int hf_drbd_c_max_rate
;
579 static int hf_drbd_protocol
;
580 static int hf_drbd_after_sb_0p
;
581 static int hf_drbd_after_sb_1p
;
582 static int hf_drbd_after_sb_2p
;
583 static int hf_drbd_conn_flags
;
584 static int hf_drbd_two_primaries
;
585 static int hf_drbd_integrity_alg
;
586 static int hf_drbd_current_uuid
;
587 static int hf_drbd_bitmap_uuid
;
588 static int hf_drbd_history_uuid_list
;
589 static int hf_drbd_history_uuid
;
590 static int hf_drbd_dirty_bits
;
591 static int hf_drbd_uuid_flags
;
592 static int hf_drbd_node_mask
;
593 static int hf_drbd_bitmap_uuids_mask
;
594 static int hf_drbd_uuid
;
595 static int hf_drbd_weak_nodes
;
596 static int hf_drbd_physical_block_size
;
597 static int hf_drbd_logical_block_size
;
598 static int hf_drbd_alignment_offset
;
599 static int hf_drbd_io_min
;
600 static int hf_drbd_io_opt
;
601 static int hf_drbd_discard_enabled
;
602 static int hf_drbd_discard_zeroes_data
;
603 static int hf_drbd_write_same_capable
;
604 static int hf_drbd_d_size
;
605 static int hf_drbd_u_size
;
606 static int hf_drbd_c_size
;
607 static int hf_drbd_max_bio_size
;
608 static int hf_drbd_queue_order_type
;
609 static int hf_drbd_dds_flags
;
610 static int hf_drbd_state
;
611 static int hf_drbd_retcode
;
612 static int hf_drbd_twopc_prepare_in
;
613 static int hf_drbd_tid
;
614 static int hf_drbd_twopc_flags
;
615 static int hf_drbd_initiator_node_id
;
616 static int hf_drbd_target_node_id
;
617 static int hf_drbd_nodes_to_reach
;
618 static int hf_drbd_primary_nodes
;
619 static int hf_drbd_user_size
;
620 static int hf_drbd_diskful_primary_nodes
;
621 static int hf_drbd_exposed_size
;
622 static int hf_drbd_reachable_nodes
;
623 static int hf_drbd_max_possible_size
;
624 static int hf_drbd_offset
;
625 static int hf_drbd_dagtag
;
626 static int hf_drbd_dagtag_node_id
;
627 static int hf_drbd_new_rx_descs_data
;
628 static int hf_drbd_new_rx_descs_control
;
629 static int hf_drbd_rx_desc_stolen_from
;
631 static int hf_drbd_state_role
;
632 static int hf_drbd_state_peer
;
633 static int hf_drbd_state_conn
;
634 static int hf_drbd_state_disk
;
635 static int hf_drbd_state_pdsk
;
636 static int hf_drbd_state_susp
;
637 static int hf_drbd_state_aftr_isp
;
638 static int hf_drbd_state_peer_isp
;
639 static int hf_drbd_state_user_isp
;
640 static int hf_drbd_state_susp_nod
;
641 static int hf_drbd_state_susp_fen
;
642 static int hf_drbd_state_quorum
;
644 static int hf_drbd_twopc_flag_has_reachable
;
646 static int hf_drbd_uuid_flag_discard_my_data
;
647 static int hf_drbd_uuid_flag_crashed_primary
;
648 static int hf_drbd_uuid_flag_inconsistent
;
649 static int hf_drbd_uuid_flag_skip_initial_sync
;
650 static int hf_drbd_uuid_flag_new_datagen
;
651 static int hf_drbd_uuid_flag_stable
;
652 static int hf_drbd_uuid_flag_got_stable
;
653 static int hf_drbd_uuid_flag_resync
;
654 static int hf_drbd_uuid_flag_reconnect
;
655 static int hf_drbd_uuid_flag_diskless_primary
;
656 static int hf_drbd_uuid_flag_primary_lost_quorum
;
658 static int hf_drbd_dp_hardbarrier
;
659 static int hf_drbd_dp_rw_sync
;
660 static int hf_drbd_dp_may_set_in_sync
;
661 static int hf_drbd_dp_unplug
;
662 static int hf_drbd_dp_fua
;
663 static int hf_drbd_dp_flush
;
664 static int hf_drbd_dp_discard
;
665 static int hf_drbd_dp_send_receive_ack
;
666 static int hf_drbd_dp_send_write_ack
;
667 static int hf_drbd_dp_wsame
;
668 static int hf_drbd_dp_zeroes
;
670 static int hf_drbd_lb_tcp_seq
;
671 static int hf_drbd_lb_tcp_length
;
674 static int ett_drbd_lb_tcp
;
675 static int ett_drbd_state
;
676 static int ett_drbd_twopc_flags
;
677 static int ett_drbd_uuid_flags
;
678 static int ett_drbd_history_uuids
;
679 static int ett_drbd_data_flags
;
681 static int * const state_fields
[] = {
688 &hf_drbd_state_aftr_isp
,
689 &hf_drbd_state_peer_isp
,
690 &hf_drbd_state_user_isp
,
691 &hf_drbd_state_susp_nod
,
692 &hf_drbd_state_susp_fen
,
693 &hf_drbd_state_quorum
,
697 static int * const twopc_flag_fields
[] = {
698 &hf_drbd_twopc_flag_has_reachable
,
702 static int * const uuid_flag_fields
[] = {
703 &hf_drbd_uuid_flag_discard_my_data
,
704 &hf_drbd_uuid_flag_crashed_primary
,
705 &hf_drbd_uuid_flag_inconsistent
,
706 &hf_drbd_uuid_flag_skip_initial_sync
,
707 &hf_drbd_uuid_flag_new_datagen
,
708 &hf_drbd_uuid_flag_stable
,
709 &hf_drbd_uuid_flag_got_stable
,
710 &hf_drbd_uuid_flag_resync
,
711 &hf_drbd_uuid_flag_reconnect
,
712 &hf_drbd_uuid_flag_diskless_primary
,
713 &hf_drbd_uuid_flag_primary_lost_quorum
,
717 static int * const data_flag_fields
[] = {
718 &hf_drbd_dp_hardbarrier
,
720 &hf_drbd_dp_may_set_in_sync
,
725 &hf_drbd_dp_send_receive_ack
,
726 &hf_drbd_dp_send_write_ack
,
732 #define CHALLENGE_LEN 64
734 static bool is_bit_set_64(uint64_t value
, int bit
) {
735 return !!(value
& (UINT64_C(1) << bit
));
739 * Length of the frame header.
741 #define DRBD_FRAME_HEADER_80_LEN 8
742 #define DRBD_FRAME_HEADER_95_LEN 8
743 #define DRBD_FRAME_HEADER_100_LEN 16
744 #define DRBD_TRANSPORT_RDMA_PACKET_LEN 16
746 #define DRBD_MAGIC 0x83740267
747 #define DRBD_MAGIC_BIG 0x835a
748 #define DRBD_MAGIC_100 0x8620ec20
749 #define DRBD_TRANSPORT_RDMA_MAGIC 0x5257494E
751 static unsigned read_drbd_packet_len(tvbuff_t
*tvb
, int offset
)
756 magic32
= tvb_get_ntohl(tvb
, offset
);
758 if (magic32
== DRBD_MAGIC
)
759 return DRBD_FRAME_HEADER_80_LEN
+ tvb_get_ntohs(tvb
, offset
+ 6);
761 if (tvb_reported_length_remaining(tvb
, offset
) >= DRBD_FRAME_HEADER_100_LEN
&& magic32
== DRBD_MAGIC_100
)
762 return DRBD_FRAME_HEADER_100_LEN
+ tvb_get_ntohl(tvb
, offset
+ 8);
764 magic16
= tvb_get_ntohs(tvb
, offset
);
766 if (magic16
== DRBD_MAGIC_BIG
)
767 return DRBD_FRAME_HEADER_95_LEN
+ tvb_get_ntohl(tvb
, offset
+ 4);
772 static unsigned get_drbd_pdu_len(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
774 unsigned drbd_len
= read_drbd_packet_len(tvb
, offset
);
776 if (tvb_reported_length_remaining(tvb
, offset
) >= DRBD_FRAME_HEADER_100_LEN
&& !drbd_len
) {
777 /* We have enough data to recognize any header, but none matched.
778 * Either there is data corruption or this is actually an lb-tcp
779 * stream. It is possible that the capture is missing the first lb-tcp
780 * header. In that case, the stream will be misidentified as normal
783 * Reset the dissector and throw some exception so that a new dissector
784 * is chosen by the heuristic. */
785 conversation_t
*conversation
= find_or_create_conversation(pinfo
);
786 conversation_set_dissector(conversation
, NULL
);
787 THROW(ReportedBoundsError
);
793 static int dissect_drbd_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
795 dissect_drbd_message(tvb
, pinfo
, tree
);
796 return tvb_reported_length(tvb
);
799 static int dissect_drbd(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
801 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DRBD");
802 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, DRBD_FRAME_HEADER_80_LEN
,
803 get_drbd_pdu_len
, dissect_drbd_pdu
, data
);
804 return tvb_reported_length(tvb
);
807 static unsigned get_drbd_lb_tcp_pdu_len(packet_info
*pinfo _U_
, tvbuff_t
*tvb
, int offset
, void *data _U_
)
809 return 8 + tvb_get_ntohl(tvb
, offset
+ 4);
812 static int dissect_drbd_lb_tcp_pdu(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data _U_
)
814 proto_tree
*lb_tcp_tree
;
815 proto_item
*lb_tcp_ti
;
817 lb_tcp_ti
= proto_tree_add_item(tree
, proto_drbd_lb_tcp
, tvb
, 0, -1, ENC_NA
);
818 proto_item_set_text(lb_tcp_ti
, "DRBD [lb-tcp]");
819 lb_tcp_tree
= proto_item_add_subtree(lb_tcp_ti
, ett_drbd_lb_tcp
);
821 proto_tree_add_item(lb_tcp_tree
, hf_drbd_lb_tcp_seq
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
822 proto_tree_add_item(lb_tcp_tree
, hf_drbd_lb_tcp_length
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
825 while (tvb_captured_length(tvb
) >= offset
+ DRBD_FRAME_HEADER_80_LEN
) {
826 unsigned length
= read_drbd_packet_len(tvb
, offset
);
828 /* Was a header recognized? */
830 const char *info_text
= col_get_text(pinfo
->cinfo
, COL_INFO
);
832 col_clear(pinfo
->cinfo
, COL_INFO
);
833 if (!info_text
|| !info_text
[0])
834 col_append_ports(pinfo
->cinfo
, COL_INFO
, PT_TCP
, pinfo
->srcport
, pinfo
->destport
);
835 col_append_str(pinfo
->cinfo
, COL_INFO
, " [lb-tcp Payload]");
836 col_set_fence(pinfo
->cinfo
, COL_INFO
);
841 dissect_drbd_message(tvb_new_subset_length(tvb
, offset
, length
), pinfo
, tree
);
846 return tvb_reported_length(tvb
);
849 static int dissect_drbd_lb_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
851 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DRBD lb-tcp");
852 tcp_dissect_pdus(tvb
, pinfo
, tree
, true, 8,
853 get_drbd_lb_tcp_pdu_len
, dissect_drbd_lb_tcp_pdu
, data
);
854 return tvb_reported_length(tvb
);
857 static bool test_drbd_header(tvbuff_t
*tvb
, int offset
)
859 int reported_length
= tvb_reported_length(tvb
);
860 int captured_length
= tvb_captured_length(tvb
);
862 if (reported_length
< offset
+ DRBD_FRAME_HEADER_80_LEN
|| captured_length
< offset
+ 4)
865 uint32_t magic32
= tvb_get_ntohl(tvb
, offset
);
867 if (magic32
== DRBD_MAGIC
)
869 else if (reported_length
>= offset
+ DRBD_FRAME_HEADER_100_LEN
&& magic32
== DRBD_MAGIC_100
)
872 uint16_t magic16
= tvb_get_ntohs(tvb
, offset
);
873 if (magic16
== DRBD_MAGIC_BIG
)
880 static bool test_drbd_rdma_control_header(tvbuff_t
*tvb
)
882 unsigned reported_length
= tvb_reported_length(tvb
);
883 if (reported_length
< DRBD_TRANSPORT_RDMA_PACKET_LEN
|| tvb_captured_length(tvb
) < 4) {
887 uint32_t magic32
= tvb_get_ntohl(tvb
, 0);
888 return magic32
== DRBD_TRANSPORT_RDMA_MAGIC
;
891 static bool test_drbd_protocol(tvbuff_t
*tvb
, packet_info
*pinfo
,
892 proto_tree
*tree
, void *data _U_
)
894 if (!test_drbd_header(tvb
, 0))
897 conversation_t
*conversation
= find_or_create_conversation(pinfo
);
898 conversation_set_dissector(conversation
, drbd_handle
);
899 dissect_drbd(tvb
, pinfo
, tree
, data
);
904 static bool test_drbd_lb_tcp_protocol(tvbuff_t
*tvb
, packet_info
*pinfo
,
905 proto_tree
*tree
, void *data _U_
)
907 /* DRBD packets may be split between lb-tcp wrapper packets. As a result,
908 * there may be lb-tcp packets that do not contain any DRBD header.
909 * However, we have no other way to identify lb-tcp packets, so look for a
910 * DRBD header anyway. This is a best-effort solution. */
911 if (!test_drbd_header(tvb
, 8))
914 conversation_t
*conversation
= find_or_create_conversation(pinfo
);
915 conversation_set_dissector(conversation
, drbd_lb_tcp_handle
);
916 dissect_drbd_lb_tcp(tvb
, pinfo
, tree
, data
);
922 * A DRBD connection consists of 2 TCP connections. We need information from
923 * one to correctly interpret the other. However, it is impossible to determine
924 * definitely just from a packet trace which TCP connections belong together.
925 * Fortunately, there is an essentially universal convention that the
926 * connections have a statically allocated port number in common. One
927 * connection uses it on one node, the other connection uses the same port
928 * number but on the other node. The other port numbers are dynamically
929 * allocated and thus greater.
931 * For example, the connections use:
932 * 1. Port 7000 on node A, port 44444 on node B
933 * 2. Port 55555 on node A, port 7000 on node B
935 * Hence we can associate one conversation_t to the DRBD connection by keying
936 * it on the lower port number and the two addresses in a consistent order.
938 static conversation_t
*find_drbd_conversation(packet_info
*pinfo
)
942 uint32_t port_a
= MIN(pinfo
->srcport
, pinfo
->destport
);
944 if (cmp_address(&pinfo
->src
, &pinfo
->dst
) < 0) {
945 addr_a
= &pinfo
->src
;
946 addr_b
= &pinfo
->dst
;
948 addr_a
= &pinfo
->dst
;
949 addr_b
= &pinfo
->src
;
952 conversation_t
*conv
= find_conversation(pinfo
->num
, addr_a
, addr_b
, CONVERSATION_TCP
, port_a
, 0, NO_PORT_B
);
955 /* CONVERSATION_TEMPLATE prevents the port information being added once
956 * a wildcard search matches. */
957 conv
= conversation_new(pinfo
->num
, addr_a
, addr_b
, CONVERSATION_TCP
, port_a
, 0,
958 NO_PORT2
|CONVERSATION_TEMPLATE
);
965 * Returns buffer containing the payload.
967 static tvbuff_t
*decode_header(tvbuff_t
*tvb
, proto_tree
*pt
, uint16_t *command
)
972 magic32
= tvb_get_ntohl(tvb
, 0);
974 if (magic32
== DRBD_MAGIC
) {
975 *command
= tvb_get_ntohs(tvb
, 4);
977 proto_tree_add_item(pt
, hf_drbd_command
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
978 proto_tree_add_item(pt
, hf_drbd_length
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
980 return tvb_new_subset_remaining(tvb
, DRBD_FRAME_HEADER_80_LEN
);
983 if (tvb_reported_length(tvb
) >= DRBD_FRAME_HEADER_100_LEN
&& magic32
== DRBD_MAGIC_100
) {
984 *command
= tvb_get_ntohs(tvb
, 6);
986 proto_tree_add_item(pt
, hf_drbd_volume
, tvb
, 4, 2, ENC_BIG_ENDIAN
);
987 proto_tree_add_item(pt
, hf_drbd_command
, tvb
, 6, 2, ENC_BIG_ENDIAN
);
988 proto_tree_add_item(pt
, hf_drbd_length
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
990 return tvb_new_subset_remaining(tvb
, DRBD_FRAME_HEADER_100_LEN
);
993 magic16
= tvb_get_ntohs(tvb
, 0);
995 if (magic16
== DRBD_MAGIC_BIG
) {
996 *command
= tvb_get_ntohs(tvb
, 2);
998 proto_tree_add_item(pt
, hf_drbd_command
, tvb
, 2, 2, ENC_BIG_ENDIAN
);
999 proto_tree_add_item(pt
, hf_drbd_length
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1001 return tvb_new_subset_remaining(tvb
, DRBD_FRAME_HEADER_95_LEN
);
1007 static const value_payload_decoder
*find_payload_decoder(uint16_t command
)
1009 for (unsigned int i
= 0; i
< array_length(payload_decoders
); i
++) {
1010 if (payload_decoders
[i
].value
== command
) {
1011 return &payload_decoders
[i
];
1018 static void dissect_drbd_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1020 proto_tree
*drbd_tree
;
1022 uint16_t command
= -1;
1024 col_clear(pinfo
->cinfo
, COL_INFO
);
1026 ti
= proto_tree_add_item(tree
, proto_drbd
, tvb
, 0, -1, ENC_NA
);
1027 drbd_tree
= proto_item_add_subtree(ti
, ett_drbd
);
1029 tvbuff_t
*payload_tvb
= decode_header(tvb
, drbd_tree
, &command
);
1034 /* Indicate what kind of message this is. */
1035 const char *packet_name
= val_to_str(command
, packet_names
, "Unknown (0x%02x)");
1036 const char *info_text
= col_get_text(pinfo
->cinfo
, COL_INFO
);
1037 if (!info_text
|| !info_text
[0])
1038 col_append_ports(pinfo
->cinfo
, COL_INFO
, PT_TCP
, pinfo
->srcport
, pinfo
->destport
);
1039 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [%s]", packet_name
);
1040 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1042 conversation_t
*conv
= find_drbd_conversation(pinfo
);
1043 drbd_conv
*conv_data
= (drbd_conv
*)conversation_get_proto_data(conv
, proto_drbd
);
1045 conv_data
= wmem_new0(wmem_file_scope(), drbd_conv
);
1046 conv_data
->twopc
= wmem_map_new(wmem_file_scope(), drbd_twopc_key_hash
, drbd_twopc_key_equal
);
1047 conversation_add_proto_data(conv
, proto_drbd
, conv_data
);
1050 const value_payload_decoder
*payload_decoder
= find_payload_decoder(command
);
1052 if (!PINFO_FD_VISITED(pinfo
) && payload_decoder
&& payload_decoder
->state_reader_fn
)
1053 (*payload_decoder
->state_reader_fn
) (payload_tvb
, pinfo
, conv_data
);
1058 proto_item_set_text(ti
, "DRBD [%s]", packet_name
);
1060 if (payload_decoder
&& payload_decoder
->tree_fn
)
1061 (*payload_decoder
->tree_fn
) (payload_tvb
, drbd_tree
, conv_data
);
1064 static void drbd_ib_append_col_info(packet_info
*pinfo
, const char *packet_name
)
1066 const char *info_text
;
1068 col_clear(pinfo
->cinfo
, COL_INFO
);
1069 info_text
= col_get_text(pinfo
->cinfo
, COL_INFO
);
1070 if (!info_text
|| !info_text
[0])
1071 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "QP=0x%06x [%s]", pinfo
->destport
, packet_name
);
1073 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " [%s]", packet_name
);
1074 col_set_fence(pinfo
->cinfo
, COL_INFO
);
1077 static void dissect_drbd_ib_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1079 proto_tree
*drbd_tree
;
1081 uint16_t command
= -1;
1083 ti
= proto_tree_add_item(tree
, proto_drbd
, tvb
, 0, -1, ENC_NA
);
1084 drbd_tree
= proto_item_add_subtree(ti
, ett_drbd
);
1086 tvbuff_t
*payload_tvb
= decode_header(tvb
, drbd_tree
, &command
);
1091 /* Indicate what kind of message this is. */
1092 const char *packet_name
= val_to_str(command
, packet_names
, "Unknown (0x%02x)");
1093 drbd_ib_append_col_info(pinfo
, packet_name
);
1098 proto_item_set_text(ti
, "DRBD [%s]", packet_name
);
1100 const value_payload_decoder
*payload_decoder
= find_payload_decoder(command
);
1102 if (payload_decoder
&& payload_decoder
->tree_fn
)
1103 (*payload_decoder
->tree_fn
) (payload_tvb
, drbd_tree
, NULL
);
1106 static void dissect_drbd_ib_control_message(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
1108 proto_tree
*drbd_tree
;
1111 drbd_ib_append_col_info(pinfo
, "RDMA Flow Control");
1116 ti
= proto_tree_add_item(tree
, proto_drbd
, tvb
, 0, -1, ENC_NA
);
1117 proto_item_set_text(ti
, "DRBD [RDMA Flow Control]");
1118 drbd_tree
= proto_item_add_subtree(ti
, ett_drbd
);
1120 proto_tree_add_item(drbd_tree
, hf_drbd_new_rx_descs_data
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1121 proto_tree_add_item(drbd_tree
, hf_drbd_new_rx_descs_control
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1122 proto_tree_add_item(drbd_tree
, hf_drbd_rx_desc_stolen_from
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1125 static bool dissect_drbd_ib(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
1127 if (!test_drbd_header(tvb
, 0) && !test_drbd_rdma_control_header(tvb
))
1130 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "DRBD RDMA");
1133 bool is_control_packet
= test_drbd_rdma_control_header(tvb
);
1135 if (is_control_packet
)
1136 length
= DRBD_TRANSPORT_RDMA_PACKET_LEN
;
1138 length
= read_drbd_packet_len(tvb
, 0);
1140 /* Was a header recognized? */
1144 tvbuff_t
*packet_tvb
= tvb_new_subset_length(tvb
, 0, length
);
1146 if (is_control_packet
)
1147 dissect_drbd_ib_control_message(packet_tvb
, pinfo
, tree
);
1149 dissect_drbd_ib_message(packet_tvb
, pinfo
, tree
);
1151 /* Is there enough data for another DRBD packet? */
1152 if (tvb_reported_length(tvb
) < length
+ DRBD_FRAME_HEADER_80_LEN
)
1155 /* Move to the next DRBD packet. */
1156 tvb
= tvb_new_subset_remaining(tvb
, length
);
1162 static void insert_twopc(tvbuff_t
*tvb
, packet_info
*pinfo
, drbd_conv
*conv_data
, enum drbd_packet command
)
1164 uint32_t flags
= tvb_get_ntohl(tvb
, 4);
1166 drbd_twopc_key
*key
= wmem_new0(wmem_file_scope(), drbd_twopc_key
);
1167 key
->tid
= tvb_get_ntohl(tvb
, 0);
1168 if (flags
& TWOPC_HAS_FLAGS
)
1169 key
->initiator_node_id
= tvb_get_int8(tvb
, 10);
1171 key
->initiator_node_id
= tvb_get_ntohil(tvb
, 4);
1173 drbd_twopc_val
*val
= wmem_new0(wmem_file_scope(), drbd_twopc_val
);
1174 val
->prepare_frame
= pinfo
->num
;
1175 val
->command
= command
;
1177 wmem_map_insert(conv_data
->twopc
, key
, val
);
1180 static void read_state_twopc_prepare(tvbuff_t
*tvb
, packet_info
*pinfo
, drbd_conv
*conv_data
)
1182 insert_twopc(tvb
, pinfo
, conv_data
, P_TWOPC_PREPARE
);
1185 static void read_state_twopc_prep_rsz(tvbuff_t
*tvb
, packet_info
*pinfo
, drbd_conv
*conv_data
)
1187 insert_twopc(tvb
, pinfo
, conv_data
, P_TWOPC_PREP_RSZ
);
1190 static void decode_payload_connection_features(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1192 proto_tree_add_item(tree
, hf_drbd_protocol_min
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1193 proto_tree_add_item(tree
, hf_drbd_feature_flags
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1194 proto_tree_add_item(tree
, hf_drbd_protocol_max
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1195 proto_tree_add_item(tree
, hf_drbd_sender_node_id
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1196 proto_tree_add_item(tree
, hf_drbd_receiver_node_id
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1199 static void decode_payload_auth_challenge(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1201 proto_tree_add_bytes_format(tree
, hf_drbd_auth_challenge_nonce
, tvb
, 0, CHALLENGE_LEN
, NULL
, "Nonce");
1204 static void decode_payload_auth_response(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1206 proto_tree_add_bytes_format(tree
, hf_drbd_auth_response_hash
, tvb
, 0, -1, NULL
, "Hash");
1209 static void decode_data_common(tvbuff_t
*tvb
, proto_tree
*tree
)
1211 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1212 proto_tree_add_item(tree
, hf_drbd_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1213 proto_tree_add_item(tree
, hf_drbd_seq_num
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1214 proto_tree_add_bitmask(tree
, tvb
, 20, hf_drbd_dp_flags
, ett_drbd_data_flags
, data_flag_fields
, ENC_BIG_ENDIAN
);
1217 static void decode_payload_data(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1219 decode_data_common(tvb
, tree
);
1221 unsigned nbytes
= tvb_reported_length_remaining(tvb
, 24);
1222 proto_tree_add_uint(tree
, hf_drbd_size
, tvb
, 0, 0, nbytes
);
1224 /* For infiniband the data is not in this tvb, so we do not show the data field. */
1225 if (tvb_captured_length(tvb
) >= 24 + nbytes
) {
1226 proto_tree_add_bytes_format(tree
, hf_drbd_data
, tvb
, 24,
1227 nbytes
, NULL
, "Data (%u byte%s)", nbytes
, plurality(nbytes
, "", "s"));
1231 static void decode_payload_barrier(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1233 proto_tree_add_item(tree
, hf_drbd_barrier
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
1236 static void decode_payload_data_request(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1238 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1239 proto_tree_add_item(tree
, hf_drbd_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1240 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1243 static void decode_payload_dagtag_data_request(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1245 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1246 proto_tree_add_item(tree
, hf_drbd_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1247 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1248 proto_tree_add_item(tree
, hf_drbd_dagtag_node_id
, tvb
, 20, 4, ENC_BIG_ENDIAN
);
1249 proto_tree_add_item(tree
, hf_drbd_dagtag
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1252 static void decode_payload_sync_param(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1254 unsigned length
= tvb_reported_length(tvb
);
1255 unsigned offset
= 0;
1257 proto_tree_add_item(tree
, hf_drbd_resync_rate
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1259 proto_tree_add_item(tree
, hf_drbd_verify_alg
, tvb
, offset
, DRBD_STRING_MAX
, ENC_ASCII
| ENC_NA
);
1260 offset
+= DRBD_STRING_MAX
;
1262 if (length
>= offset
+ DRBD_STRING_MAX
) {
1263 proto_tree_add_item(tree
, hf_drbd_csums_alg
, tvb
, offset
, DRBD_STRING_MAX
, ENC_ASCII
| ENC_NA
);
1264 offset
+= DRBD_STRING_MAX
;
1267 if (length
>= offset
+ 16) {
1268 proto_tree_add_item(tree
, hf_drbd_c_plan_ahead
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
1269 proto_tree_add_item(tree
, hf_drbd_c_delay_target
, tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
1270 proto_tree_add_item(tree
, hf_drbd_c_fill_target
, tvb
, offset
+ 8, 4, ENC_BIG_ENDIAN
);
1271 proto_tree_add_item(tree
, hf_drbd_c_max_rate
, tvb
, offset
+ 12, 4, ENC_BIG_ENDIAN
);
1275 static void decode_payload_protocol(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1277 proto_tree_add_item(tree
, hf_drbd_protocol
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1278 proto_tree_add_item(tree
, hf_drbd_after_sb_0p
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1279 proto_tree_add_item(tree
, hf_drbd_after_sb_1p
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1280 proto_tree_add_item(tree
, hf_drbd_after_sb_2p
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1281 proto_tree_add_item(tree
, hf_drbd_conn_flags
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1282 proto_tree_add_item(tree
, hf_drbd_two_primaries
, tvb
, 20, 4, ENC_BIG_ENDIAN
);
1283 proto_tree_add_item(tree
, hf_drbd_integrity_alg
, tvb
, 24, -1, ENC_ASCII
| ENC_NA
);
1286 static void decode_payload_uuids(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1288 proto_tree_add_item(tree
, hf_drbd_current_uuid
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1289 proto_tree_add_item(tree
, hf_drbd_bitmap_uuid
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1290 proto_tree_add_item(tree
, hf_drbd_history_uuid
, tvb
, 16, 8, ENC_BIG_ENDIAN
);
1291 proto_tree_add_item(tree
, hf_drbd_history_uuid
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1292 proto_tree_add_item(tree
, hf_drbd_dirty_bits
, tvb
, 32, 8, ENC_BIG_ENDIAN
);
1293 proto_tree_add_bitmask(tree
, tvb
, 40, hf_drbd_uuid_flags
, ett_drbd_uuid_flags
, uuid_flag_fields
, ENC_BIG_ENDIAN
);
1296 static void decode_payload_sizes(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1298 proto_tree_add_item(tree
, hf_drbd_d_size
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1299 proto_tree_add_item(tree
, hf_drbd_u_size
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1300 proto_tree_add_item(tree
, hf_drbd_c_size
, tvb
, 16, 8, ENC_BIG_ENDIAN
);
1301 proto_tree_add_item(tree
, hf_drbd_max_bio_size
, tvb
, 24, 4, ENC_BIG_ENDIAN
);
1302 proto_tree_add_item(tree
, hf_drbd_queue_order_type
, tvb
, 28, 2, ENC_BIG_ENDIAN
);
1303 proto_tree_add_item(tree
, hf_drbd_dds_flags
, tvb
, 30, 2, ENC_BIG_ENDIAN
);
1304 proto_tree_add_item(tree
, hf_drbd_physical_block_size
, tvb
, 32, 4, ENC_BIG_ENDIAN
);
1305 proto_tree_add_item(tree
, hf_drbd_logical_block_size
, tvb
, 36, 4, ENC_BIG_ENDIAN
);
1306 proto_tree_add_item(tree
, hf_drbd_alignment_offset
, tvb
, 40, 4, ENC_BIG_ENDIAN
);
1307 proto_tree_add_item(tree
, hf_drbd_io_min
, tvb
, 44, 4, ENC_BIG_ENDIAN
);
1308 proto_tree_add_item(tree
, hf_drbd_io_opt
, tvb
, 48, 4, ENC_BIG_ENDIAN
);
1309 proto_tree_add_item(tree
, hf_drbd_discard_enabled
, tvb
, 52, 1, ENC_BIG_ENDIAN
);
1310 proto_tree_add_item(tree
, hf_drbd_discard_zeroes_data
, tvb
, 53, 1, ENC_BIG_ENDIAN
);
1311 proto_tree_add_item(tree
, hf_drbd_write_same_capable
, tvb
, 54, 1, ENC_BIG_ENDIAN
);
1314 static void decode_payload_state(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1316 proto_tree_add_bitmask(tree
, tvb
, 0, hf_drbd_state
, ett_drbd_state
, state_fields
, ENC_BIG_ENDIAN
);
1319 /* Filter fields leaving only those with bitmask overlapping with the given mask. */
1320 static void mask_fields(uint32_t mask
, int * const fields
[], int * masked_fields
[])
1324 for (int fields_i
= 0; fields
[fields_i
]; fields_i
++) {
1325 header_field_info
*hf
= proto_registrar_get_nth(*fields
[fields_i
]);
1327 if (hf
&& mask
& hf
->bitmask
) {
1328 masked_fields
[masked_i
] = fields
[fields_i
];
1333 masked_fields
[masked_i
] = NULL
;
1336 static void decode_state_change(tvbuff_t
*tvb
, proto_tree
*tree
, int offset
)
1338 uint32_t state_mask
= tvb_get_ntohl(tvb
, offset
);
1339 int * masked_state_fields
[array_length(state_fields
)];
1340 mask_fields(state_mask
, state_fields
, masked_state_fields
);
1342 if (masked_state_fields
[0]) {
1343 proto_tree_add_bitmask(tree
, tvb
, offset
+ 4, hf_drbd_state
, ett_drbd_state
, masked_state_fields
, ENC_BIG_ENDIAN
);
1345 proto_tree_add_item(tree
, hf_drbd_state
, tvb
, offset
+ 4, 4, ENC_BIG_ENDIAN
);
1349 static void decode_payload_req_state(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1351 decode_state_change(tvb
, tree
, 0);
1354 static void decode_payload_sync_uuid(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1356 proto_tree_add_item(tree
, hf_drbd_uuid
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1359 static void decode_payload_skip(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1361 proto_tree_add_item(tree
, hf_drbd_seq_num
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1362 proto_tree_add_item(tree
, hf_drbd_offset
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1365 static void decode_payload_out_of_sync(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1367 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1368 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1371 /* Return the twopc flags, if present. */
1372 static uint32_t decode_twopc_request_common(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_twopc_key
*key
)
1374 proto_tree_add_item_ret_uint(tree
, hf_drbd_tid
, tvb
, 0, 4, ENC_BIG_ENDIAN
,
1375 key
? &key
->tid
: NULL
);
1377 uint32_t flags
= tvb_get_ntohl(tvb
, 4);
1378 if (flags
& TWOPC_HAS_FLAGS
) {
1379 proto_tree_add_bitmask(tree
, tvb
, 4, hf_drbd_twopc_flags
, ett_drbd_twopc_flags
, twopc_flag_fields
, ENC_BIG_ENDIAN
);
1380 proto_tree_add_item_ret_int(tree
, hf_drbd_initiator_node_id
, tvb
, 10, 1, ENC_BIG_ENDIAN
,
1381 key
? &key
->initiator_node_id
: NULL
);
1382 proto_tree_add_item(tree
, hf_drbd_target_node_id
, tvb
, 11, 1, ENC_BIG_ENDIAN
);
1385 proto_tree_add_item_ret_int(tree
, hf_drbd_initiator_node_id
, tvb
, 4, 4, ENC_BIG_ENDIAN
,
1386 key
? &key
->initiator_node_id
: NULL
);
1387 proto_tree_add_item(tree
, hf_drbd_target_node_id
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1390 proto_tree_add_item(tree
, hf_drbd_nodes_to_reach
, tvb
, 12, 8, ENC_BIG_ENDIAN
);
1394 static void decode_payload_twopc_prepare(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1396 uint32_t flags
= decode_twopc_request_common(tvb
, tree
, NULL
);
1398 if (!(flags
& TWOPC_HAS_FLAGS
))
1399 proto_tree_add_item(tree
, hf_drbd_primary_nodes
, tvb
, 20, 8, ENC_BIG_ENDIAN
);
1401 decode_state_change(tvb
, tree
, 28);
1404 static void decode_payload_twopc_prep_rsz(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1406 decode_twopc_request_common(tvb
, tree
, NULL
);
1408 proto_tree_add_item(tree
, hf_drbd_user_size
, tvb
, 20, 8, ENC_BIG_ENDIAN
);
1409 proto_tree_add_item(tree
, hf_drbd_dds_flags
, tvb
, 28, 2, ENC_BIG_ENDIAN
);
1412 static void decode_payload_twopc_commit(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
)
1415 uint32_t flags
= decode_twopc_request_common(tvb
, tree
, &key
);
1420 drbd_twopc_val
*val
= wmem_map_lookup(conv_data
->twopc
, &key
);
1424 proto_item
*it
= proto_tree_add_uint(tree
, hf_drbd_twopc_prepare_in
,
1425 tvb
, 0, 0, val
->prepare_frame
);
1426 proto_item_set_generated(it
);
1428 if (val
->command
== P_TWOPC_PREPARE
) {
1429 proto_tree_add_item(tree
, hf_drbd_primary_nodes
, tvb
, 20, 8, ENC_BIG_ENDIAN
);
1430 if (!(flags
& TWOPC_HAS_FLAGS
))
1431 decode_state_change(tvb
, tree
, 28);
1432 else if (flags
& TWOPC_HAS_REACHABLE
)
1433 proto_tree_add_item(tree
, hf_drbd_reachable_nodes
, tvb
, 28, 8, ENC_BIG_ENDIAN
);
1434 } else if (val
->command
== P_TWOPC_PREP_RSZ
) {
1435 proto_tree_add_item(tree
, hf_drbd_diskful_primary_nodes
, tvb
, 20, 8, ENC_BIG_ENDIAN
);
1436 proto_tree_add_item(tree
, hf_drbd_exposed_size
, tvb
, 28, 8, ENC_BIG_ENDIAN
);
1440 static void decode_payload_dagtag(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1442 proto_tree_add_item(tree
, hf_drbd_dagtag
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1445 static void decode_payload_uuids110(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1447 proto_tree_add_item(tree
, hf_drbd_current_uuid
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1448 proto_tree_add_item(tree
, hf_drbd_dirty_bits
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1449 proto_tree_add_bitmask(tree
, tvb
, 16, hf_drbd_uuid_flags
, ett_drbd_uuid_flags
, uuid_flag_fields
, ENC_BIG_ENDIAN
);
1450 proto_tree_add_item(tree
, hf_drbd_node_mask
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1452 uint64_t bitmap_uuids_mask
;
1453 proto_tree_add_item_ret_uint64(tree
, hf_drbd_bitmap_uuids_mask
, tvb
, 32, 8, ENC_BIG_ENDIAN
, &bitmap_uuids_mask
);
1455 unsigned offset
= 40;
1456 for (int i
= 0; i
< 64; i
++) {
1457 if (is_bit_set_64(bitmap_uuids_mask
, i
)) {
1458 uint64_t bitmap_uuid
= tvb_get_ntoh64(tvb
, offset
);
1459 proto_tree_add_uint64_format(tree
, hf_drbd_bitmap_uuid
, tvb
, offset
, 8, bitmap_uuid
,
1460 "Bitmap UUID for node %d: 0x%016" PRIx64
, i
, bitmap_uuid
);
1465 proto_item
*history_uuids
= proto_tree_add_item(tree
, hf_drbd_history_uuid_list
, tvb
, offset
, -1, ENC_NA
);
1466 proto_tree
*history_tree
= proto_item_add_subtree(history_uuids
, ett_drbd_history_uuids
);
1467 unsigned total_length
= tvb_reported_length(tvb
);
1468 while (offset
< total_length
) {
1469 proto_tree_add_item(history_tree
, hf_drbd_history_uuid
, tvb
, offset
, 8, ENC_BIG_ENDIAN
);
1474 static void decode_payload_peer_dagtag(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1476 proto_tree_add_item(tree
, hf_drbd_dagtag
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1477 proto_tree_add_item(tree
, hf_drbd_dagtag_node_id
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1480 static void decode_payload_current_uuid(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1482 proto_tree_add_item(tree
, hf_drbd_uuid
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1483 proto_tree_add_item(tree
, hf_drbd_weak_nodes
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1486 static void decode_payload_data_size(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1488 decode_data_common(tvb
, tree
);
1489 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 24, 4, ENC_BIG_ENDIAN
);
1492 static void decode_payload_data_wsame(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1494 decode_data_common(tvb
, tree
);
1495 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 24, 4, ENC_BIG_ENDIAN
);
1497 unsigned nbytes
= tvb_reported_length_remaining(tvb
, 28);
1498 /* For infiniband the data is not in this tvb, so we do not show the data field. */
1499 if (tvb_captured_length(tvb
) >= 28 + nbytes
) {
1500 proto_tree_add_bytes_format(tree
, hf_drbd_data
, tvb
, 28,
1501 nbytes
, NULL
, "Data (%u byte%s)", nbytes
, plurality(nbytes
, "", "s"));
1505 static void decode_payload_rs_deallocated(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1507 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1508 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1511 static void decode_payload_block_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1513 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1514 proto_tree_add_item(tree
, hf_drbd_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1515 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1516 proto_tree_add_item(tree
, hf_drbd_seq_num
, tvb
, 20, 4, ENC_BIG_ENDIAN
);
1519 static void decode_payload_ov_result(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1521 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1522 proto_tree_add_item(tree
, hf_drbd_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1523 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1524 proto_tree_add_item(tree
, hf_drbd_seq_num
, tvb
, 20, 4, ENC_BIG_ENDIAN
);
1525 proto_tree_add_item(tree
, hf_drbd_ov_result
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1528 static void decode_payload_barrier_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1530 proto_tree_add_item(tree
, hf_drbd_barrier
, tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
1531 proto_tree_add_item(tree
, hf_drbd_set_size
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1534 static void decode_payload_confirm_stable(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1536 proto_tree_add_item(tree
, hf_drbd_oldest_block_id
, tvb
, 0, 8, ENC_LITTLE_ENDIAN
);
1537 proto_tree_add_item(tree
, hf_drbd_youngest_block_id
, tvb
, 8, 8, ENC_LITTLE_ENDIAN
);
1538 proto_tree_add_item(tree
, hf_drbd_set_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1541 static void decode_payload_rq_s_reply(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1543 proto_tree_add_item(tree
, hf_drbd_retcode
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1546 static void decode_payload_peer_ack(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1548 proto_tree_add_item(tree
, hf_drbd_node_mask
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1549 proto_tree_add_item(tree
, hf_drbd_dagtag
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1552 static void decode_payload_peers_in_sync(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data _U_
)
1554 proto_tree_add_item(tree
, hf_drbd_sector
, tvb
, 0, 8, ENC_BIG_ENDIAN
);
1555 proto_tree_add_item(tree
, hf_drbd_node_mask
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1556 proto_tree_add_item(tree
, hf_drbd_size
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1559 static void decode_payload_twopc_reply(tvbuff_t
*tvb
, proto_tree
*tree
, drbd_conv
*conv_data
)
1563 proto_tree_add_item_ret_uint(tree
, hf_drbd_tid
, tvb
, 0, 4, ENC_BIG_ENDIAN
,
1565 proto_tree_add_item_ret_int(tree
, hf_drbd_initiator_node_id
, tvb
, 4, 4, ENC_BIG_ENDIAN
,
1566 &key
.initiator_node_id
);
1567 proto_tree_add_item(tree
, hf_drbd_reachable_nodes
, tvb
, 8, 8, ENC_BIG_ENDIAN
);
1572 drbd_twopc_val
*val
= wmem_map_lookup(conv_data
->twopc
, &key
);
1576 proto_item
*it
= proto_tree_add_uint(tree
, hf_drbd_twopc_prepare_in
,
1577 tvb
, 0, 0, val
->prepare_frame
);
1578 proto_item_set_generated(it
);
1580 if (val
->command
== P_TWOPC_PREPARE
) {
1581 proto_tree_add_item(tree
, hf_drbd_primary_nodes
, tvb
, 16, 8, ENC_BIG_ENDIAN
);
1582 proto_tree_add_item(tree
, hf_drbd_weak_nodes
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1583 } else if (val
->command
== P_TWOPC_PREP_RSZ
) {
1584 proto_tree_add_item(tree
, hf_drbd_diskful_primary_nodes
, tvb
, 16, 8, ENC_BIG_ENDIAN
);
1585 proto_tree_add_item(tree
, hf_drbd_max_possible_size
, tvb
, 24, 8, ENC_BIG_ENDIAN
);
1589 static void format_node_mask(char *s
, uint64_t value
)
1592 (void) g_strlcpy(s
, "<none>", ITEM_LABEL_LENGTH
);
1598 for (int i
= 0; i
< 64 && written
< ITEM_LABEL_LENGTH
; i
++) {
1599 bool is_set
= is_bit_set_64(value
, i
);
1604 } else if (i
== 63) {
1605 if (run_start
== -1)
1612 if (run_start
!= -1 && run_end
!= -1) {
1613 int run_length
= run_end
- run_start
;
1614 const char *sep
= written
? ", " : "";
1616 if (run_length
== 1)
1617 written
+= snprintf(s
+ written
, ITEM_LABEL_LENGTH
- written
, "%s%d", sep
, run_start
);
1618 else if (run_length
== 2)
1619 written
+= snprintf(s
+ written
, ITEM_LABEL_LENGTH
- written
, "%s%d, %d", sep
, run_start
, run_start
+ 1);
1621 written
+= snprintf(s
+ written
, ITEM_LABEL_LENGTH
- written
, "%s%d - %d", sep
, run_start
, run_end
- 1);
1626 else if (run_start
== -1)
1631 void proto_register_drbd(void)
1633 static hf_register_info hf
[] = {
1634 { &hf_drbd_command
, { "Command", "drbd.command", FT_UINT16
, BASE_HEX
, VALS(packet_names
), 0x0, NULL
, HFILL
}},
1635 { &hf_drbd_length
, { "Payload length", "drbd.length", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1636 { &hf_drbd_volume
, { "Volume", "drbd.volume", FT_INT16
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1637 { &hf_drbd_auth_challenge_nonce
, { "Nonce", "drbd.auth_nonce", FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x0, NULL
, HFILL
}},
1638 { &hf_drbd_auth_response_hash
, { "Hash", "drbd.auth_hash", FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x0, NULL
, HFILL
}},
1639 { &hf_drbd_sector
, { "Sector", "drbd.sector", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1640 { &hf_drbd_block_id
, { "Block ID", "drbd.block_id", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1641 { &hf_drbd_seq_num
, { "Sequence number", "drbd.seq_num", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1642 { &hf_drbd_ov_result
, { "Online verify result", "drbd.ov_result", FT_UINT64
, BASE_DEC
|BASE_VAL64_STRING
, VALS64(ov_result_codes
), 0x0, NULL
, HFILL
}},
1643 { &hf_drbd_dp_flags
, { "Data flags", "drbd.dp_flags", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1644 { &hf_drbd_data
, { "Data", "drbd.data", FT_BYTES
, BASE_NO_DISPLAY_VALUE
, NULL
, 0x0, NULL
, HFILL
}},
1645 { &hf_drbd_size
, { "Size", "drbd.size", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1646 { &hf_drbd_protocol_min
, { "protocol_min", "drbd.protocol_min", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1647 { &hf_drbd_feature_flags
, { "feature_flags", "drbd.feature_flags", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1648 { &hf_drbd_protocol_max
, { "protocol_max", "drbd.protocol_max", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1649 { &hf_drbd_sender_node_id
, { "sender_node_id", "drbd.sender_node_id", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1650 { &hf_drbd_receiver_node_id
, { "receiver_node_id", "drbd.receiver_node_id", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1651 { &hf_drbd_barrier
, { "barrier", "drbd.barrier", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1652 { &hf_drbd_set_size
, { "set_size", "drbd.set_size", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1653 { &hf_drbd_oldest_block_id
, { "oldest_block_id", "drbd.oldest_block_id", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1654 { &hf_drbd_youngest_block_id
, { "youngest_block_id", "drbd.youngest_block_id", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1655 { &hf_drbd_resync_rate
, { "resync_rate", "drbd.resync_rate", FT_UINT32
, BASE_DEC
|BASE_UNIT_STRING
, UNS(&units_kibps
), 0x0, NULL
, HFILL
}},
1656 { &hf_drbd_verify_alg
, { "verify_alg", "drbd.verify_alg", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1657 { &hf_drbd_csums_alg
, { "csums_alg", "drbd.csums_alg", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1658 { &hf_drbd_c_plan_ahead
, { "c_plan_ahead", "drbd.c_plan_ahead", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1659 { &hf_drbd_c_delay_target
, { "c_delay_target", "drbd.c_delay_target", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1660 { &hf_drbd_c_fill_target
, { "c_fill_target", "drbd.c_fill_target", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1661 { &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
}},
1662 { &hf_drbd_protocol
, { "protocol", "drbd.protocol", FT_UINT32
, BASE_HEX
, VALS(protocol_names
), 0x0, NULL
, HFILL
}},
1663 { &hf_drbd_after_sb_0p
, { "after_sb_0p", "drbd.after_sb_0p", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1664 { &hf_drbd_after_sb_1p
, { "after_sb_1p", "drbd.after_sb_1p", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1665 { &hf_drbd_after_sb_2p
, { "after_sb_2p", "drbd.after_sb_2p", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1666 { &hf_drbd_conn_flags
, { "conn_flags", "drbd.conn_flags", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1667 { &hf_drbd_two_primaries
, { "two_primaries", "drbd.two_primaries", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1668 { &hf_drbd_integrity_alg
, { "integrity_alg", "drbd.integrity_alg", FT_STRINGZ
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1669 { &hf_drbd_current_uuid
, { "Current UUID", "drbd.current_uuid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1670 { &hf_drbd_bitmap_uuid
, { "Bitmap UUID", "drbd.bitmap_uuid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1671 { &hf_drbd_history_uuid_list
, { "History UUIDs", "drbd.history_uuids", FT_NONE
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1672 { &hf_drbd_history_uuid
, { "History UUID", "drbd.history_uuid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1673 { &hf_drbd_dirty_bits
, { "Dirty bits", "drbd.dirty_bits", FT_UINT64
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1674 { &hf_drbd_uuid_flags
, { "UUID flags", "drbd.uuid_flags", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1675 { &hf_drbd_node_mask
, { "Nodes", "drbd.node_mask", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1676 { &hf_drbd_bitmap_uuids_mask
, { "Bitmap UUID nodes", "drbd.bitmap_uuids_mask", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1677 { &hf_drbd_uuid
, { "uuid", "drbd.uuid", FT_UINT64
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1678 { &hf_drbd_weak_nodes
, { "weak_nodes", "drbd.weak_nodes", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1679 { &hf_drbd_physical_block_size
, { "physical_block_size", "drbd.physical_block_size", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1680 { &hf_drbd_logical_block_size
, { "logical_block_size", "drbd.logical_block_size", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1681 { &hf_drbd_alignment_offset
, { "alignment_offset", "drbd.alignment_offset", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1682 { &hf_drbd_io_min
, { "io_min", "drbd.io_min", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1683 { &hf_drbd_io_opt
, { "io_opt", "drbd.io_opt", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1684 { &hf_drbd_discard_enabled
, { "discard_enabled", "drbd.discard_enabled", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1685 { &hf_drbd_discard_zeroes_data
, { "discard_zeroes_data", "drbd.discard_zeroes_data", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1686 { &hf_drbd_write_same_capable
, { "write_same_capable", "drbd.write_same_capable", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0, NULL
, HFILL
}},
1687 { &hf_drbd_d_size
, { "d_size", "drbd.d_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1688 { &hf_drbd_u_size
, { "u_size", "drbd.u_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1689 { &hf_drbd_c_size
, { "c_size", "drbd.c_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1690 { &hf_drbd_max_bio_size
, { "max_bio_size", "drbd.max_bio_size", FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1691 { &hf_drbd_queue_order_type
, { "queue_order_type", "drbd.queue_order_type", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1692 { &hf_drbd_dds_flags
, { "dds_flags", "drbd.dds_flags", FT_UINT16
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1693 { &hf_drbd_state
, { "state", "drbd.state", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1694 { &hf_drbd_retcode
, { "retcode", "drbd.retcode", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1695 { &hf_drbd_twopc_prepare_in
, { "Two-phase commit prepare in", "drbd.twopc_prepare_in", FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0, NULL
, HFILL
}},
1696 { &hf_drbd_tid
, { "tid", "drbd.tid", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1697 { &hf_drbd_twopc_flags
, { "twopc_flags", "drbd.twopc_flags", FT_UINT32
, BASE_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1698 { &hf_drbd_initiator_node_id
, { "initiator_node_id", "drbd.initiator_node_id", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1699 { &hf_drbd_target_node_id
, { "target_node_id", "drbd.target_node_id", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1700 { &hf_drbd_nodes_to_reach
, { "nodes_to_reach", "drbd.nodes_to_reach", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1701 { &hf_drbd_primary_nodes
, { "primary_nodes", "drbd.primary_nodes", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1702 { &hf_drbd_user_size
, { "user_size", "drbd.user_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1703 { &hf_drbd_diskful_primary_nodes
, { "diskful_primary_nodes", "drbd.diskful_primary_nodes", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1704 { &hf_drbd_exposed_size
, { "exposed_size", "drbd.exposed_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1705 { &hf_drbd_reachable_nodes
, { "reachable_nodes", "drbd.reachable_nodes", FT_UINT64
, BASE_CUSTOM
, CF_FUNC(format_node_mask
), 0x0, NULL
, HFILL
}},
1706 { &hf_drbd_max_possible_size
, { "max_possible_size", "drbd.max_possible_size", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1707 { &hf_drbd_offset
, { "offset", "drbd.offset", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1708 { &hf_drbd_dagtag
, { "dagtag", "drbd.dagtag", FT_UINT64
, BASE_DEC_HEX
, NULL
, 0x0, NULL
, HFILL
}},
1709 { &hf_drbd_dagtag_node_id
, { "dagtag_node_id", "drbd.dagtag_node_id", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1710 { &hf_drbd_new_rx_descs_data
, { "New descriptors received (data)", "drbd.new_rx_descs_data", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1711 { &hf_drbd_new_rx_descs_control
, { "New descriptors received (control)", "drbd.new_rx_descs_control", FT_INT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1712 { &hf_drbd_rx_desc_stolen_from
, { "Descriptor stolen from", "drbd.rx_desc_stolen_from", FT_INT32
, BASE_DEC
, VALS(stream_names
), 0x0, NULL
, HFILL
}},
1714 { &hf_drbd_state_role
, { "role", "drbd.state.role", FT_UINT32
, BASE_DEC
, VALS(role_names
), STATE_ROLE
, NULL
, HFILL
}},
1715 { &hf_drbd_state_peer
, { "peer", "drbd.state.peer", FT_UINT32
, BASE_DEC
, VALS(role_names
), STATE_PEER
, NULL
, HFILL
}},
1716 { &hf_drbd_state_conn
, { "conn", "drbd.state.conn", FT_UINT32
, BASE_DEC
, VALS(connection_state_names
), STATE_CONN
, NULL
, HFILL
}},
1717 { &hf_drbd_state_disk
, { "disk", "drbd.state.disk", FT_UINT32
, BASE_DEC
, VALS(disk_state_names
), STATE_DISK
, NULL
, HFILL
}},
1718 { &hf_drbd_state_pdsk
, { "pdsk", "drbd.state.pdsk", FT_UINT32
, BASE_DEC
, VALS(disk_state_names
), STATE_PDSK
, NULL
, HFILL
}},
1719 { &hf_drbd_state_susp
, { "susp", "drbd.state.susp", FT_BOOLEAN
, 32, NULL
, STATE_SUSP
, NULL
, HFILL
}},
1720 { &hf_drbd_state_aftr_isp
, { "aftr_isp", "drbd.state.aftr_isp", FT_BOOLEAN
, 32, NULL
, STATE_AFTR_ISP
, NULL
, HFILL
}},
1721 { &hf_drbd_state_peer_isp
, { "peer_isp", "drbd.state.peer_isp", FT_BOOLEAN
, 32, NULL
, STATE_PEER_ISP
, NULL
, HFILL
}},
1722 { &hf_drbd_state_user_isp
, { "user_isp", "drbd.state.user_isp", FT_BOOLEAN
, 32, NULL
, STATE_USER_ISP
, NULL
, HFILL
}},
1723 { &hf_drbd_state_susp_nod
, { "susp_nod", "drbd.state.susp_nod", FT_BOOLEAN
, 32, NULL
, STATE_SUSP_NOD
, NULL
, HFILL
}},
1724 { &hf_drbd_state_susp_fen
, { "susp_fen", "drbd.state.susp_fen", FT_BOOLEAN
, 32, NULL
, STATE_SUSP_FEN
, NULL
, HFILL
}},
1725 { &hf_drbd_state_quorum
, { "quorum", "drbd.state.quorum", FT_BOOLEAN
, 32, NULL
, STATE_QUORUM
, NULL
, HFILL
}},
1727 { &hf_drbd_twopc_flag_has_reachable
, { "has_reachable", "drbd.twopc_flags.has_reachable", FT_BOOLEAN
, 32, NULL
, TWOPC_HAS_REACHABLE
, NULL
, HFILL
}},
1729 { &hf_drbd_uuid_flag_discard_my_data
, { "discard_my_data", "drbd.uuid_flag.discard_my_data", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_DISCARD_MY_DATA
, NULL
, HFILL
}},
1730 { &hf_drbd_uuid_flag_crashed_primary
, { "crashed_primary", "drbd.uuid_flag.crashed_primary", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_CRASHED_PRIMARY
, NULL
, HFILL
}},
1731 { &hf_drbd_uuid_flag_inconsistent
, { "inconsistent", "drbd.uuid_flag.inconsistent", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_INCONSISTENT
, NULL
, HFILL
}},
1732 { &hf_drbd_uuid_flag_skip_initial_sync
, { "skip_initial_sync", "drbd.uuid_flag.skip_initial_sync", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_SKIP_INITIAL_SYNC
, NULL
, HFILL
}},
1733 { &hf_drbd_uuid_flag_new_datagen
, { "new_datagen", "drbd.uuid_flag.new_datagen", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_NEW_DATAGEN
, NULL
, HFILL
}},
1734 { &hf_drbd_uuid_flag_stable
, { "stable", "drbd.uuid_flag.stable", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_STABLE
, NULL
, HFILL
}},
1735 { &hf_drbd_uuid_flag_got_stable
, { "got_stable", "drbd.uuid_flag.got_stable", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_GOT_STABLE
, NULL
, HFILL
}},
1736 { &hf_drbd_uuid_flag_resync
, { "resync", "drbd.uuid_flag.resync", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_RESYNC
, NULL
, HFILL
}},
1737 { &hf_drbd_uuid_flag_reconnect
, { "reconnect", "drbd.uuid_flag.reconnect", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_RECONNECT
, NULL
, HFILL
}},
1738 { &hf_drbd_uuid_flag_diskless_primary
, { "diskless_primary", "drbd.uuid_flag.diskless_primary", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_DISKLESS_PRIMARY
, NULL
, HFILL
}},
1739 { &hf_drbd_uuid_flag_primary_lost_quorum
, { "primary_lost_quorum", "drbd.uuid_flag.primary_lost_quorum", FT_BOOLEAN
, 64, NULL
, UUID_FLAG_PRIMARY_LOST_QUORUM
, NULL
, HFILL
}},
1741 { &hf_drbd_dp_hardbarrier
, { "hardbarrier", "drbd.dp_flag.hardbarrier", FT_BOOLEAN
, 32, NULL
, DP_HARDBARRIER
, NULL
, HFILL
}},
1742 { &hf_drbd_dp_rw_sync
, { "rw_sync", "drbd.dp_flag.rw_sync", FT_BOOLEAN
, 32, NULL
, DP_RW_SYNC
, NULL
, HFILL
}},
1743 { &hf_drbd_dp_may_set_in_sync
, { "may_set_in_sync", "drbd.dp_flag.may_set_in_sync", FT_BOOLEAN
, 32, NULL
, DP_MAY_SET_IN_SYNC
, NULL
, HFILL
}},
1744 { &hf_drbd_dp_unplug
, { "unplug", "drbd.dp_flag.unplug", FT_BOOLEAN
, 32, NULL
, DP_UNPLUG
, NULL
, HFILL
}},
1745 { &hf_drbd_dp_fua
, { "fua", "drbd.dp_flag.fua", FT_BOOLEAN
, 32, NULL
, DP_FUA
, NULL
, HFILL
}},
1746 { &hf_drbd_dp_flush
, { "flush", "drbd.dp_flag.flush", FT_BOOLEAN
, 32, NULL
, DP_FLUSH
, NULL
, HFILL
}},
1747 { &hf_drbd_dp_discard
, { "discard", "drbd.dp_flag.discard", FT_BOOLEAN
, 32, NULL
, DP_DISCARD
, NULL
, HFILL
}},
1748 { &hf_drbd_dp_send_receive_ack
, { "send_receive_ack", "drbd.dp_flag.send_receive_ack", FT_BOOLEAN
, 32, NULL
, DP_SEND_RECEIVE_ACK
, NULL
, HFILL
}},
1749 { &hf_drbd_dp_send_write_ack
, { "send_write_ack", "drbd.dp_flag.send_write_ack", FT_BOOLEAN
, 32, NULL
, DP_SEND_WRITE_ACK
, NULL
, HFILL
}},
1750 { &hf_drbd_dp_wsame
, { "wsame", "drbd.dp_flag.wsame", FT_BOOLEAN
, 32, NULL
, DP_WSAME
, NULL
, HFILL
}},
1751 { &hf_drbd_dp_zeroes
, { "zeroes", "drbd.dp_flag.zeroes", FT_BOOLEAN
, 32, NULL
, DP_ZEROES
, NULL
, HFILL
}},
1754 static hf_register_info hf_lb_tcp
[] = {
1755 { &hf_drbd_lb_tcp_seq
, { "lb-tcp sequence number", "drbd_lb_tcp.seq", FT_UINT32
, BASE_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1756 { &hf_drbd_lb_tcp_length
, { "lb-tcp length", "drbd_lb_tcp.length", FT_UINT32
, BASE_HEX_DEC
, NULL
, 0x0, NULL
, HFILL
}},
1759 static int *ett
[] = {
1763 &ett_drbd_twopc_flags
,
1764 &ett_drbd_uuid_flags
,
1765 &ett_drbd_history_uuids
,
1766 &ett_drbd_data_flags
,
1769 proto_drbd
= proto_register_protocol("DRBD Protocol", "DRBD", "drbd");
1770 proto_register_field_array(proto_drbd
, hf
, array_length(hf
));
1772 proto_drbd_lb_tcp
= proto_register_protocol("DRBD Load-Balanced Protocol", "DRBD lb-tcp", "drbd_lb_tcp");
1773 proto_register_field_array(proto_drbd_lb_tcp
, hf_lb_tcp
, array_length(hf_lb_tcp
));
1775 proto_register_subtree_array(ett
, array_length(ett
));
1777 drbd_handle
= register_dissector("drbd", dissect_drbd
, proto_drbd
);
1778 drbd_lb_tcp_handle
= register_dissector("drbd_lb_tcp", dissect_drbd_lb_tcp
, proto_drbd_lb_tcp
);
1781 void proto_reg_handoff_drbd(void)
1783 heur_dissector_add("tcp", test_drbd_protocol
, "DRBD over TCP", "drbd_tcp", proto_drbd
, HEURISTIC_DISABLE
);
1784 heur_dissector_add("infiniband.payload", dissect_drbd_ib
, "DRBD over RDMA", "drbd_rdma", proto_drbd
, HEURISTIC_DISABLE
);
1785 heur_dissector_add("tcp", test_drbd_lb_tcp_protocol
, "DRBD Load-Balanced over TCP", "drbd_lb_tcp", proto_drbd_lb_tcp
, HEURISTIC_DISABLE
);
1789 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1794 * indent-tabs-mode: nil
1797 * vi: set shiftwidth=4 tabstop=8 expandtab:
1798 * :indentSize=4:tabSize=8:noTabs=true: