Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-drbd.c
blob9483bea846503df9d3433026c8a176f15cbfbbf1
1 /* packet-drbd.c
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/
19 #include <config.h>
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
32 enum drbd_packet {
33 P_DATA = 0x00,
34 P_DATA_REPLY = 0x01,
35 P_RS_DATA_REPLY = 0x02,
36 P_BARRIER = 0x03,
37 P_BITMAP = 0x04,
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,
43 P_SYNC_PARAM = 0x0a,
44 P_PROTOCOL = 0x0b,
45 P_UUIDS = 0x0c,
46 P_SIZES = 0x0d,
47 P_STATE = 0x0e,
48 P_SYNC_UUID = 0x0f,
49 P_AUTH_CHALLENGE = 0x10,
50 P_AUTH_RESPONSE = 0x11,
51 P_STATE_CHG_REQ = 0x12,
53 P_PING = 0x13,
54 P_PING_ACK = 0x14,
55 P_RECV_ACK = 0x15,
56 P_WRITE_ACK = 0x16,
57 P_RS_WRITE_ACK = 0x17,
58 P_SUPERSEDED = 0x18,
59 P_NEG_ACK = 0x19,
60 P_NEG_DREPLY = 0x1a,
61 P_NEG_RS_DREPLY = 0x1b,
62 P_BARRIER_ACK = 0x1c,
63 P_STATE_CHG_REPLY = 0x1d,
65 P_OV_REQUEST = 0x1e,
66 P_OV_REPLY = 0x1f,
67 P_OV_RESULT = 0x20,
68 P_CSUM_RS_REQUEST = 0x21,
69 P_RS_IS_IN_SYNC = 0x22,
70 P_SYNC_PARAM89 = 0x23,
71 P_COMPRESSED_BITMAP = 0x24,
73 P_DELAY_PROBE = 0x27,
74 P_OUT_OF_SYNC = 0x28,
75 P_RS_CANCEL = 0x29,
76 P_CONN_ST_CHG_REQ = 0x2a,
77 P_CONN_ST_CHG_REPLY = 0x2b,
78 P_RETRY_WRITE = 0x2c,
79 P_PROTOCOL_UPDATE = 0x2d,
80 P_TWOPC_PREPARE = 0x2e,
81 P_TWOPC_ABORT = 0x2f,
83 P_DAGTAG = 0x30,
85 P_TRIM = 0x31,
87 P_RS_THIN_REQ = 0x32,
88 P_RS_DEALLOCATED = 0x33,
90 P_WSAME = 0x34,
91 P_TWOPC_PREP_RSZ = 0x35,
92 P_ZEROES = 0x36,
94 P_PEER_ACK = 0x40,
95 P_PEERS_IN_SYNC = 0x41,
97 P_UUIDS110 = 0x42,
98 P_PEER_DAGTAG = 0x43,
99 P_CURRENT_UUID = 0x44,
101 P_TWOPC_YES = 0x45,
102 P_TWOPC_NO = 0x46,
103 P_TWOPC_COMMIT = 0x47,
104 P_TWOPC_RETRY = 0x48,
106 P_CONFIRM_STABLE = 0x49,
108 P_RS_CANCEL_AHEAD = 0x4a,
110 P_DISCONNECT = 0x4b,
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,
119 P_RS_NEG_ACK = 0x52,
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
129 typedef struct {
130 uint32_t tid;
131 int32_t initiator_node_id;
132 } drbd_twopc_key;
134 typedef struct {
135 uint32_t prepare_frame;
136 enum drbd_packet command;
137 } drbd_twopc_val;
139 static unsigned drbd_twopc_key_hash(const void *k)
141 const drbd_twopc_key *key = (const drbd_twopc_key *) k;
143 return key->tid;
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;
154 typedef struct {
155 wmem_map_t *twopc;
156 } drbd_conv;
158 typedef struct value_payload_decoder {
159 int value;
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" },
259 { 0, NULL }
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" },
270 { 0, NULL }
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" },
281 { 0, NULL }
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" },
334 { 0, NULL }
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" },
359 { 0, NULL }
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
391 #define DP_RW_SYNC 2
392 #define DP_MAY_SET_IN_SYNC 4
393 #define DP_UNPLUG 8
394 #define DP_FUA 16
395 #define DP_FLUSH 32
396 #define DP_DISCARD 64
397 #define DP_SEND_RECEIVE_ACK 128
398 #define DP_SEND_WRITE_ACK 256
399 #define DP_WSAME 512
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" },
410 { 0, NULL }
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" },
419 { 0, NULL }
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;
673 static int ett_drbd;
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[] = {
682 &hf_drbd_state_role,
683 &hf_drbd_state_peer,
684 &hf_drbd_state_conn,
685 &hf_drbd_state_disk,
686 &hf_drbd_state_pdsk,
687 &hf_drbd_state_susp,
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,
694 NULL
697 static int * const twopc_flag_fields[] = {
698 &hf_drbd_twopc_flag_has_reachable,
699 NULL
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,
714 NULL
717 static int * const data_flag_fields[] = {
718 &hf_drbd_dp_hardbarrier,
719 &hf_drbd_dp_rw_sync,
720 &hf_drbd_dp_may_set_in_sync,
721 &hf_drbd_dp_unplug,
722 &hf_drbd_dp_fua,
723 &hf_drbd_dp_flush,
724 &hf_drbd_dp_discard,
725 &hf_drbd_dp_send_receive_ack,
726 &hf_drbd_dp_send_write_ack,
727 &hf_drbd_dp_wsame,
728 &hf_drbd_dp_zeroes,
729 NULL
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)
753 uint32_t magic32;
754 uint16_t magic16;
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);
769 return 0;
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
781 * DRBD on TCP.
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);
790 return drbd_len;
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);
824 unsigned offset = 8;
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? */
829 if (length == 0) {
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);
838 break;
841 dissect_drbd_message(tvb_new_subset_length(tvb, offset, length), pinfo, tree);
843 offset += length;
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)
863 return false;
865 uint32_t magic32 = tvb_get_ntohl(tvb, offset);
867 if (magic32 == DRBD_MAGIC)
868 return true;
869 else if (reported_length >= offset + DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100)
870 return true;
871 else {
872 uint16_t magic16 = tvb_get_ntohs(tvb, offset);
873 if (magic16 == DRBD_MAGIC_BIG)
874 return true;
877 return false;
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) {
884 return false;
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))
895 return false;
897 conversation_t *conversation = find_or_create_conversation(pinfo);
898 conversation_set_dissector(conversation, drbd_handle);
899 dissect_drbd(tvb, pinfo, tree, data);
901 return true;
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))
912 return false;
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);
918 return true;
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)
940 address* addr_a;
941 address* addr_b;
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;
947 } else {
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);
953 if (!conv)
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);
961 return conv;
965 * Returns buffer containing the payload.
967 static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, uint16_t *command)
969 uint32_t magic32;
970 uint16_t magic16;
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);
1004 return NULL;
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];
1015 return NULL;
1018 static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1020 proto_tree *drbd_tree;
1021 proto_item *ti;
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);
1031 if (!payload_tvb)
1032 return;
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);
1044 if (!conv_data) {
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);
1055 if (tree == NULL)
1056 return;
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);
1072 else
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;
1080 proto_item *ti;
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);
1088 if (!payload_tvb)
1089 return;
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);
1095 if (tree == NULL)
1096 return;
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;
1109 proto_item *ti;
1111 drbd_ib_append_col_info(pinfo, "RDMA Flow Control");
1113 if (tree == NULL)
1114 return;
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))
1128 return false;
1130 col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD RDMA");
1131 while (1) {
1132 unsigned length;
1133 bool is_control_packet = test_drbd_rdma_control_header(tvb);
1135 if (is_control_packet)
1136 length = DRBD_TRANSPORT_RDMA_PACKET_LEN;
1137 else
1138 length = read_drbd_packet_len(tvb, 0);
1140 /* Was a header recognized? */
1141 if (length == 0)
1142 break;
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);
1148 else
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)
1153 break;
1155 /* Move to the next DRBD packet. */
1156 tvb = tvb_new_subset_remaining(tvb, length);
1159 return true;
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);
1170 else
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);
1258 offset += 4;
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[])
1322 int masked_i = 0;
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];
1329 masked_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);
1344 } else {
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);
1383 } else {
1384 flags = 0;
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);
1391 return flags;
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)
1414 drbd_twopc_key key;
1415 uint32_t flags = decode_twopc_request_common(tvb, tree, &key);
1417 if (!conv_data)
1418 return;
1420 drbd_twopc_val *val = wmem_map_lookup(conv_data->twopc, &key);
1421 if (!val)
1422 return;
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);
1461 offset += 8;
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);
1470 offset += 8;
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)
1561 drbd_twopc_key key;
1563 proto_tree_add_item_ret_uint(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN,
1564 &key.tid);
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);
1569 if (!conv_data)
1570 return;
1572 drbd_twopc_val *val = wmem_map_lookup(conv_data->twopc, &key);
1573 if (!val)
1574 return;
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)
1591 if (!value) {
1592 (void) g_strlcpy(s, "<none>", ITEM_LABEL_LENGTH);
1593 return;
1596 int written = 0;
1597 int run_start = -1;
1598 for (int i = 0; i < 64 && written < ITEM_LABEL_LENGTH; i++) {
1599 bool is_set = is_bit_set_64(value, i);
1601 int run_end;
1602 if (!is_set) {
1603 run_end = i;
1604 } else if (i == 63) {
1605 if (run_start == -1)
1606 run_start = i;
1607 run_end = 64;
1608 } else {
1609 run_end = -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);
1620 else
1621 written += snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d - %d", sep, run_start, run_end - 1);
1624 if (!is_set)
1625 run_start = -1;
1626 else if (run_start == -1)
1627 run_start = i;
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[] = {
1760 &ett_drbd,
1761 &ett_drbd_lb_tcp,
1762 &ett_drbd_state,
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
1791 * Local variables:
1792 * c-basic-offset: 4
1793 * tab-width: 8
1794 * indent-tabs-mode: nil
1795 * End:
1797 * vi: set shiftwidth=4 tabstop=8 expandtab:
1798 * :indentSize=4:tabSize=8:noTabs=true: