/src/wireshark/epan/dissectors/packet-drbd.c
Line | Count | Source |
1 | | /* packet-drbd.c |
2 | | * Routines for DRBD dissection |
3 | | * By Joel Colledge <joel.colledge@linbit.com> |
4 | | * Copyright 2019, LINBIT Information Technologies GmbH |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | */ |
12 | | |
13 | | /* |
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/ |
17 | | */ |
18 | | |
19 | | #include <config.h> |
20 | | |
21 | | #include <epan/packet.h> |
22 | | #include <epan/exceptions.h> |
23 | | #include <epan/unit_strings.h> |
24 | | #include "packet-tcp.h" |
25 | | |
26 | | #include <wsutil/str_util.h> |
27 | | #include <wsutil/array.h> |
28 | | |
29 | | /* Known as SHARED_SECRET_MAX in the DRBD sources */ |
30 | 0 | #define DRBD_STRING_MAX 64 |
31 | | |
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, |
52 | | |
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, |
64 | | |
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, |
72 | | |
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, |
82 | | |
83 | | P_DAGTAG = 0x30, |
84 | | |
85 | | P_TRIM = 0x31, |
86 | | |
87 | | P_RS_THIN_REQ = 0x32, |
88 | | P_RS_DEALLOCATED = 0x33, |
89 | | |
90 | | P_WSAME = 0x34, |
91 | | P_TWOPC_PREP_RSZ = 0x35, |
92 | | P_ZEROES = 0x36, |
93 | | |
94 | | P_PEER_ACK = 0x40, |
95 | | P_PEERS_IN_SYNC = 0x41, |
96 | | |
97 | | P_UUIDS110 = 0x42, |
98 | | P_PEER_DAGTAG = 0x43, |
99 | | P_CURRENT_UUID = 0x44, |
100 | | |
101 | | P_TWOPC_YES = 0x45, |
102 | | P_TWOPC_NO = 0x46, |
103 | | P_TWOPC_COMMIT = 0x47, |
104 | | P_TWOPC_RETRY = 0x48, |
105 | | |
106 | | P_CONFIRM_STABLE = 0x49, |
107 | | |
108 | | P_RS_CANCEL_AHEAD = 0x4a, |
109 | | |
110 | | P_DISCONNECT = 0x4b, |
111 | | |
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, |
117 | | |
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, |
122 | | |
123 | | P_INITIAL_META = 0xfff1, |
124 | | P_INITIAL_DATA = 0xfff2, |
125 | | |
126 | | P_CONNECTION_FEATURES = 0xfffe |
127 | | }; |
128 | | |
129 | | typedef struct { |
130 | | uint32_t tid; |
131 | | int32_t initiator_node_id; |
132 | | } drbd_twopc_key; |
133 | | |
134 | | typedef struct { |
135 | | uint32_t prepare_frame; |
136 | | enum drbd_packet command; |
137 | | } drbd_twopc_val; |
138 | | |
139 | | static unsigned drbd_twopc_key_hash(const void *k) |
140 | 0 | { |
141 | 0 | const drbd_twopc_key *key = (const drbd_twopc_key *) k; |
142 | |
|
143 | 0 | return key->tid; |
144 | 0 | } |
145 | | |
146 | | static int drbd_twopc_key_equal(const void *k1, const void *k2) |
147 | 0 | { |
148 | 0 | const drbd_twopc_key *key1 = (const drbd_twopc_key*) k1; |
149 | 0 | const drbd_twopc_key *key2 = (const drbd_twopc_key*) k2; |
150 | |
|
151 | 0 | return key1->tid == key2->tid && key1->initiator_node_id == key2->initiator_node_id; |
152 | 0 | } |
153 | | |
154 | | typedef struct { |
155 | | wmem_map_t *twopc; |
156 | | } drbd_conv; |
157 | | |
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; |
163 | | |
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" }, |
184 | | |
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" }, |
196 | | |
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" }, |
204 | | |
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" }, |
214 | | |
215 | | { P_DAGTAG, "P_DAGTAG" }, |
216 | | |
217 | | { P_TRIM, "P_TRIM" }, |
218 | | |
219 | | { P_RS_THIN_REQ, "P_RS_THIN_REQ" }, |
220 | | { P_RS_DEALLOCATED, "P_RS_DEALLOCATED" }, |
221 | | |
222 | | { P_WSAME, "P_WSAME" }, |
223 | | { P_TWOPC_PREP_RSZ, "P_TWOPC_PREP_RSZ" }, |
224 | | { P_ZEROES, "P_ZEROES" }, |
225 | | |
226 | | { P_PEER_ACK, "P_PEER_ACK" }, |
227 | | { P_PEERS_IN_SYNC, "P_PEERS_IN_SYNC" }, |
228 | | |
229 | | { P_UUIDS110, "P_UUIDS110" }, |
230 | | { P_PEER_DAGTAG, "P_PEER_DAGTAG" }, |
231 | | { P_CURRENT_UUID, "P_CURRENT_UUID" }, |
232 | | |
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" }, |
237 | | |
238 | | { P_CONFIRM_STABLE, "P_CONFIRM_STABLE" }, |
239 | | |
240 | | { P_RS_CANCEL_AHEAD, "P_RS_CANCEL_AHEAD" }, |
241 | | |
242 | | { P_DISCONNECT, "P_DISCONNECT" }, |
243 | | |
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" }, |
249 | | |
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" }, |
254 | | |
255 | | { P_INITIAL_META, "P_INITIAL_META" }, |
256 | | { P_INITIAL_DATA, "P_INITIAL_DATA" }, |
257 | | |
258 | | { P_CONNECTION_FEATURES, "P_CONNECTION_FEATURES" }, |
259 | | { 0, NULL } |
260 | | }; |
261 | | |
262 | | #define DRBD_PROT_A 1 |
263 | | #define DRBD_PROT_B 2 |
264 | | #define DRBD_PROT_C 3 |
265 | | |
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 } |
271 | | }; |
272 | | |
273 | | #define DRBD_ROLE_UNKNOWN 0 |
274 | | #define DRBD_ROLE_PRIMARY 1 |
275 | | #define DRBD_ROLE_SECONDARY 2 |
276 | | |
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 } |
282 | | }; |
283 | | |
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 |
308 | | |
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 } |
335 | | }; |
336 | | |
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 |
347 | | |
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 } |
360 | | }; |
361 | | |
362 | 14 | #define STATE_ROLE (0x3 << 0) /* 3/4 primary/secondary/unknown */ |
363 | 14 | #define STATE_PEER (0x3 << 2) /* 3/4 primary/secondary/unknown */ |
364 | 14 | #define STATE_CONN (0x1f << 4) /* 17/32 cstates */ |
365 | 14 | #define STATE_DISK (0xf << 9) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ |
366 | 14 | #define STATE_PDSK (0xf << 13) /* 8/16 from D_DISKLESS to D_UP_TO_DATE */ |
367 | 14 | #define STATE_SUSP (0x1 << 17) /* 2/2 IO suspended no/yes (by user) */ |
368 | 14 | #define STATE_AFTR_ISP (0x1 << 18) /* isp .. imposed sync pause */ |
369 | 14 | #define STATE_PEER_ISP (0x1 << 19) |
370 | 14 | #define STATE_USER_ISP (0x1 << 20) |
371 | 14 | #define STATE_SUSP_NOD (0x1 << 21) /* IO suspended because no data */ |
372 | 14 | #define STATE_SUSP_FEN (0x1 << 22) /* IO suspended because fence peer handler runs*/ |
373 | 14 | #define STATE_QUORUM (0x1 << 23) |
374 | | |
375 | 0 | #define TWOPC_HAS_FLAGS 0x80000000 /* For packet dissectors */ |
376 | 14 | #define TWOPC_HAS_REACHABLE 0x40000000 /* The reachable_nodes field is valid */ |
377 | | |
378 | 14 | #define UUID_FLAG_DISCARD_MY_DATA 1 |
379 | 14 | #define UUID_FLAG_CRASHED_PRIMARY 2 |
380 | 14 | #define UUID_FLAG_INCONSISTENT 4 |
381 | 14 | #define UUID_FLAG_SKIP_INITIAL_SYNC 8 |
382 | 14 | #define UUID_FLAG_NEW_DATAGEN 16 |
383 | 14 | #define UUID_FLAG_STABLE 32 |
384 | 14 | #define UUID_FLAG_GOT_STABLE 64 |
385 | 14 | #define UUID_FLAG_RESYNC 128 |
386 | 14 | #define UUID_FLAG_RECONNECT 256 |
387 | 14 | #define UUID_FLAG_DISKLESS_PRIMARY 512 |
388 | 14 | #define UUID_FLAG_PRIMARY_LOST_QUORUM 1024 |
389 | | |
390 | 14 | #define DP_HARDBARRIER 1 |
391 | 14 | #define DP_RW_SYNC 2 |
392 | 14 | #define DP_MAY_SET_IN_SYNC 4 |
393 | 14 | #define DP_UNPLUG 8 |
394 | 14 | #define DP_FUA 16 |
395 | 14 | #define DP_FLUSH 32 |
396 | 14 | #define DP_DISCARD 64 |
397 | 14 | #define DP_SEND_RECEIVE_ACK 128 |
398 | 14 | #define DP_SEND_WRITE_ACK 256 |
399 | 14 | #define DP_WSAME 512 |
400 | 14 | #define DP_ZEROES 1024 |
401 | | |
402 | | #define OV_RESULT_SKIP 4710 |
403 | | #define OV_RESULT_IN_SYNC 4711 |
404 | | #define OV_RESULT_OUT_OF_SYNC 4712 |
405 | | |
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 } |
411 | | }; |
412 | | |
413 | | #define DRBD_STREAM_DATA 0 |
414 | | #define DRBD_STREAM_CONTROL 1 |
415 | | |
416 | | static const value_string stream_names[] = { |
417 | | { DRBD_STREAM_DATA, "Data" }, |
418 | | { DRBD_STREAM_CONTROL, "Control" }, |
419 | | { 0, NULL } |
420 | | }; |
421 | | |
422 | | static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); |
423 | | |
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); |
426 | | |
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); |
453 | | |
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); |
462 | | |
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 }, |
511 | | |
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 }, |
539 | | }; |
540 | | |
541 | | |
542 | | void proto_register_drbd(void); |
543 | | void proto_reg_handoff_drbd(void); |
544 | | |
545 | | static dissector_handle_t drbd_handle; |
546 | | static dissector_handle_t drbd_lb_tcp_handle; |
547 | | |
548 | | static int proto_drbd; |
549 | | static int proto_drbd_lb_tcp; |
550 | | |
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; |
630 | | |
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; |
643 | | |
644 | | static int hf_drbd_twopc_flag_has_reachable; |
645 | | |
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; |
657 | | |
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; |
669 | | |
670 | | static int hf_drbd_lb_tcp_seq; |
671 | | static int hf_drbd_lb_tcp_length; |
672 | | |
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; |
680 | | |
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 |
695 | | }; |
696 | | |
697 | | static int * const twopc_flag_fields[] = { |
698 | | &hf_drbd_twopc_flag_has_reachable, |
699 | | NULL |
700 | | }; |
701 | | |
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 |
715 | | }; |
716 | | |
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 |
730 | | }; |
731 | | |
732 | 0 | #define CHALLENGE_LEN 64 |
733 | | |
734 | 0 | static bool is_bit_set_64(uint64_t value, int bit) { |
735 | 0 | return !!(value & (UINT64_C(1) << bit)); |
736 | 0 | } |
737 | | |
738 | | /* |
739 | | * Length of the frame header. |
740 | | */ |
741 | 0 | #define DRBD_FRAME_HEADER_80_LEN 8 |
742 | 0 | #define DRBD_FRAME_HEADER_95_LEN 8 |
743 | 0 | #define DRBD_FRAME_HEADER_100_LEN 16 |
744 | 0 | #define DRBD_TRANSPORT_RDMA_PACKET_LEN 16 |
745 | | |
746 | 0 | #define DRBD_MAGIC 0x83740267 |
747 | 0 | #define DRBD_MAGIC_BIG 0x835a |
748 | 0 | #define DRBD_MAGIC_100 0x8620ec20 |
749 | 0 | #define DRBD_TRANSPORT_RDMA_MAGIC 0x5257494E |
750 | | |
751 | | static unsigned read_drbd_packet_len(tvbuff_t *tvb, int offset) |
752 | 0 | { |
753 | 0 | uint32_t magic32; |
754 | 0 | uint16_t magic16; |
755 | |
|
756 | 0 | magic32 = tvb_get_ntohl(tvb, offset); |
757 | |
|
758 | 0 | if (magic32 == DRBD_MAGIC) |
759 | 0 | return DRBD_FRAME_HEADER_80_LEN + tvb_get_ntohs(tvb, offset + 6); |
760 | | |
761 | 0 | if (tvb_reported_length_remaining(tvb, offset) >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) |
762 | 0 | return DRBD_FRAME_HEADER_100_LEN + tvb_get_ntohl(tvb, offset + 8); |
763 | | |
764 | 0 | magic16 = tvb_get_ntohs(tvb, offset); |
765 | |
|
766 | 0 | if (magic16 == DRBD_MAGIC_BIG) |
767 | 0 | return DRBD_FRAME_HEADER_95_LEN + tvb_get_ntohl(tvb, offset + 4); |
768 | | |
769 | 0 | return 0; |
770 | 0 | } |
771 | | |
772 | | static unsigned get_drbd_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset, void *data _U_) |
773 | 0 | { |
774 | 0 | unsigned drbd_len = read_drbd_packet_len(tvb, offset); |
775 | |
|
776 | 0 | 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. |
782 | | * |
783 | | * Reset the dissector and throw some exception so that a new dissector |
784 | | * is chosen by the heuristic. */ |
785 | 0 | conversation_t *conversation = find_or_create_conversation(pinfo); |
786 | 0 | conversation_set_dissector(conversation, NULL); |
787 | 0 | THROW(ReportedBoundsError); |
788 | 0 | } |
789 | |
|
790 | 0 | return drbd_len; |
791 | 0 | } |
792 | | |
793 | | static int dissect_drbd_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
794 | 0 | { |
795 | 0 | dissect_drbd_message(tvb, pinfo, tree); |
796 | 0 | return tvb_reported_length(tvb); |
797 | 0 | } |
798 | | |
799 | | static int dissect_drbd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
800 | 0 | { |
801 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD"); |
802 | 0 | tcp_dissect_pdus(tvb, pinfo, tree, true, DRBD_FRAME_HEADER_80_LEN, |
803 | 0 | get_drbd_pdu_len, dissect_drbd_pdu, data); |
804 | 0 | return tvb_reported_length(tvb); |
805 | 0 | } |
806 | | |
807 | | static unsigned get_drbd_lb_tcp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset, void *data _U_) |
808 | 0 | { |
809 | 0 | return 8 + tvb_get_ntohl(tvb, offset + 4); |
810 | 0 | } |
811 | | |
812 | | static int dissect_drbd_lb_tcp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) |
813 | 0 | { |
814 | 0 | proto_tree *lb_tcp_tree; |
815 | 0 | proto_item *lb_tcp_ti; |
816 | |
|
817 | 0 | lb_tcp_ti = proto_tree_add_item(tree, proto_drbd_lb_tcp, tvb, 0, -1, ENC_NA); |
818 | 0 | proto_item_set_text(lb_tcp_ti, "DRBD [lb-tcp]"); |
819 | 0 | lb_tcp_tree = proto_item_add_subtree(lb_tcp_ti, ett_drbd_lb_tcp); |
820 | |
|
821 | 0 | proto_tree_add_item(lb_tcp_tree, hf_drbd_lb_tcp_seq, tvb, 0, 4, ENC_BIG_ENDIAN); |
822 | 0 | proto_tree_add_item(lb_tcp_tree, hf_drbd_lb_tcp_length, tvb, 4, 4, ENC_BIG_ENDIAN); |
823 | |
|
824 | 0 | unsigned offset = 8; |
825 | 0 | while (tvb_captured_length(tvb) >= offset + DRBD_FRAME_HEADER_80_LEN) { |
826 | 0 | unsigned length = read_drbd_packet_len(tvb, offset); |
827 | | |
828 | | /* Was a header recognized? */ |
829 | 0 | if (length == 0) { |
830 | 0 | const char *info_text = col_get_text(pinfo->cinfo, COL_INFO); |
831 | |
|
832 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
833 | 0 | if (!info_text || !info_text[0]) |
834 | 0 | col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport); |
835 | 0 | col_append_str(pinfo->cinfo, COL_INFO, " [lb-tcp Payload]"); |
836 | 0 | col_set_fence(pinfo->cinfo, COL_INFO); |
837 | |
|
838 | 0 | break; |
839 | 0 | } |
840 | | |
841 | 0 | dissect_drbd_message(tvb_new_subset_length(tvb, offset, length), pinfo, tree); |
842 | |
|
843 | 0 | offset += length; |
844 | 0 | } |
845 | |
|
846 | 0 | return tvb_reported_length(tvb); |
847 | 0 | } |
848 | | |
849 | | static int dissect_drbd_lb_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data) |
850 | 0 | { |
851 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD lb-tcp"); |
852 | 0 | tcp_dissect_pdus(tvb, pinfo, tree, true, 8, |
853 | 0 | get_drbd_lb_tcp_pdu_len, dissect_drbd_lb_tcp_pdu, data); |
854 | 0 | return tvb_reported_length(tvb); |
855 | 0 | } |
856 | | |
857 | | static bool test_drbd_header(tvbuff_t *tvb, int offset) |
858 | 0 | { |
859 | 0 | int reported_length = tvb_reported_length(tvb); |
860 | 0 | int captured_length = tvb_captured_length(tvb); |
861 | |
|
862 | 0 | if (reported_length < offset + DRBD_FRAME_HEADER_80_LEN || captured_length < offset + 4) |
863 | 0 | return false; |
864 | | |
865 | 0 | uint32_t magic32 = tvb_get_ntohl(tvb, offset); |
866 | |
|
867 | 0 | if (magic32 == DRBD_MAGIC) |
868 | 0 | return true; |
869 | 0 | else if (reported_length >= offset + DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) |
870 | 0 | return true; |
871 | 0 | else { |
872 | 0 | uint16_t magic16 = tvb_get_ntohs(tvb, offset); |
873 | 0 | if (magic16 == DRBD_MAGIC_BIG) |
874 | 0 | return true; |
875 | 0 | } |
876 | | |
877 | 0 | return false; |
878 | 0 | } |
879 | | |
880 | | static bool test_drbd_rdma_control_header(tvbuff_t *tvb) |
881 | 0 | { |
882 | 0 | unsigned reported_length = tvb_reported_length(tvb); |
883 | 0 | if (reported_length < DRBD_TRANSPORT_RDMA_PACKET_LEN || tvb_captured_length(tvb) < 4) { |
884 | 0 | return false; |
885 | 0 | } |
886 | | |
887 | 0 | uint32_t magic32 = tvb_get_ntohl(tvb, 0); |
888 | 0 | return magic32 == DRBD_TRANSPORT_RDMA_MAGIC; |
889 | 0 | } |
890 | | |
891 | | static bool test_drbd_protocol(tvbuff_t *tvb, packet_info *pinfo, |
892 | | proto_tree *tree, void *data _U_) |
893 | 0 | { |
894 | 0 | if (!test_drbd_header(tvb, 0)) |
895 | 0 | return false; |
896 | | |
897 | 0 | conversation_t *conversation = find_or_create_conversation(pinfo); |
898 | 0 | conversation_set_dissector(conversation, drbd_handle); |
899 | 0 | dissect_drbd(tvb, pinfo, tree, data); |
900 | |
|
901 | 0 | return true; |
902 | 0 | } |
903 | | |
904 | | static bool test_drbd_lb_tcp_protocol(tvbuff_t *tvb, packet_info *pinfo, |
905 | | proto_tree *tree, void *data _U_) |
906 | 0 | { |
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 | 0 | if (!test_drbd_header(tvb, 8)) |
912 | 0 | return false; |
913 | | |
914 | 0 | conversation_t *conversation = find_or_create_conversation(pinfo); |
915 | 0 | conversation_set_dissector(conversation, drbd_lb_tcp_handle); |
916 | 0 | dissect_drbd_lb_tcp(tvb, pinfo, tree, data); |
917 | |
|
918 | 0 | return true; |
919 | 0 | } |
920 | | |
921 | | /* |
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. |
930 | | * |
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 |
934 | | * |
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. |
937 | | */ |
938 | | static conversation_t *find_drbd_conversation(packet_info *pinfo) |
939 | 0 | { |
940 | 0 | address* addr_a; |
941 | 0 | address* addr_b; |
942 | 0 | uint32_t port_a = MIN(pinfo->srcport, pinfo->destport); |
943 | |
|
944 | 0 | if (cmp_address(&pinfo->src, &pinfo->dst) < 0) { |
945 | 0 | addr_a = &pinfo->src; |
946 | 0 | addr_b = &pinfo->dst; |
947 | 0 | } else { |
948 | 0 | addr_a = &pinfo->dst; |
949 | 0 | addr_b = &pinfo->src; |
950 | 0 | } |
951 | |
|
952 | 0 | conversation_t *conv = find_conversation(pinfo->num, addr_a, addr_b, CONVERSATION_TCP, port_a, 0, NO_PORT_B); |
953 | 0 | if (!conv) |
954 | 0 | { |
955 | | /* CONVERSATION_TEMPLATE prevents the port information being added once |
956 | | * a wildcard search matches. */ |
957 | 0 | conv = conversation_new(pinfo->num, addr_a, addr_b, CONVERSATION_TCP, port_a, 0, |
958 | 0 | NO_PORT2|CONVERSATION_TEMPLATE); |
959 | 0 | } |
960 | |
|
961 | 0 | return conv; |
962 | 0 | } |
963 | | |
964 | | /** |
965 | | * Returns buffer containing the payload. |
966 | | */ |
967 | | static tvbuff_t *decode_header(tvbuff_t *tvb, proto_tree *pt, uint16_t *command) |
968 | 0 | { |
969 | 0 | uint32_t magic32; |
970 | 0 | uint16_t magic16; |
971 | |
|
972 | 0 | magic32 = tvb_get_ntohl(tvb, 0); |
973 | |
|
974 | 0 | if (magic32 == DRBD_MAGIC) { |
975 | 0 | *command = tvb_get_ntohs(tvb, 4); |
976 | |
|
977 | 0 | proto_tree_add_item(pt, hf_drbd_command, tvb, 4, 2, ENC_BIG_ENDIAN); |
978 | 0 | proto_tree_add_item(pt, hf_drbd_length, tvb, 6, 2, ENC_BIG_ENDIAN); |
979 | |
|
980 | 0 | return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_80_LEN); |
981 | 0 | } |
982 | | |
983 | 0 | if (tvb_reported_length(tvb) >= DRBD_FRAME_HEADER_100_LEN && magic32 == DRBD_MAGIC_100) { |
984 | 0 | *command = tvb_get_ntohs(tvb, 6); |
985 | |
|
986 | 0 | proto_tree_add_item(pt, hf_drbd_volume, tvb, 4, 2, ENC_BIG_ENDIAN); |
987 | 0 | proto_tree_add_item(pt, hf_drbd_command, tvb, 6, 2, ENC_BIG_ENDIAN); |
988 | 0 | proto_tree_add_item(pt, hf_drbd_length, tvb, 8, 4, ENC_BIG_ENDIAN); |
989 | |
|
990 | 0 | return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_100_LEN); |
991 | 0 | } |
992 | | |
993 | 0 | magic16 = tvb_get_ntohs(tvb, 0); |
994 | |
|
995 | 0 | if (magic16 == DRBD_MAGIC_BIG) { |
996 | 0 | *command = tvb_get_ntohs(tvb, 2); |
997 | |
|
998 | 0 | proto_tree_add_item(pt, hf_drbd_command, tvb, 2, 2, ENC_BIG_ENDIAN); |
999 | 0 | proto_tree_add_item(pt, hf_drbd_length, tvb, 4, 4, ENC_BIG_ENDIAN); |
1000 | |
|
1001 | 0 | return tvb_new_subset_remaining(tvb, DRBD_FRAME_HEADER_95_LEN); |
1002 | 0 | } |
1003 | | |
1004 | 0 | return NULL; |
1005 | 0 | } |
1006 | | |
1007 | | static const value_payload_decoder *find_payload_decoder(uint16_t command) |
1008 | 0 | { |
1009 | 0 | for (unsigned int i = 0; i < array_length(payload_decoders); i++) { |
1010 | 0 | if (payload_decoders[i].value == command) { |
1011 | 0 | return &payload_decoders[i]; |
1012 | 0 | } |
1013 | 0 | } |
1014 | | |
1015 | 0 | return NULL; |
1016 | 0 | } |
1017 | | |
1018 | | static void dissect_drbd_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
1019 | 0 | { |
1020 | 0 | proto_tree *drbd_tree; |
1021 | 0 | proto_item *ti; |
1022 | 0 | uint16_t command = -1; |
1023 | |
|
1024 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1025 | |
|
1026 | 0 | ti = proto_tree_add_item(tree, proto_drbd, tvb, 0, -1, ENC_NA); |
1027 | 0 | drbd_tree = proto_item_add_subtree(ti, ett_drbd); |
1028 | |
|
1029 | 0 | tvbuff_t *payload_tvb = decode_header(tvb, drbd_tree, &command); |
1030 | |
|
1031 | 0 | if (!payload_tvb) |
1032 | 0 | return; |
1033 | | |
1034 | | /* Indicate what kind of message this is. */ |
1035 | 0 | const char *packet_name = val_to_str(pinfo->pool, command, packet_names, "Unknown (0x%02x)"); |
1036 | 0 | const char *info_text = col_get_text(pinfo->cinfo, COL_INFO); |
1037 | 0 | if (!info_text || !info_text[0]) |
1038 | 0 | col_append_ports(pinfo->cinfo, COL_INFO, PT_TCP, pinfo->srcport, pinfo->destport); |
1039 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name); |
1040 | 0 | col_set_fence(pinfo->cinfo, COL_INFO); |
1041 | |
|
1042 | 0 | conversation_t *conv = find_drbd_conversation(pinfo); |
1043 | 0 | drbd_conv *conv_data = (drbd_conv *)conversation_get_proto_data(conv, proto_drbd); |
1044 | 0 | if (!conv_data) { |
1045 | 0 | conv_data = wmem_new0(wmem_file_scope(), drbd_conv); |
1046 | 0 | conv_data->twopc = wmem_map_new(wmem_file_scope(), drbd_twopc_key_hash, drbd_twopc_key_equal); |
1047 | 0 | conversation_add_proto_data(conv, proto_drbd, conv_data); |
1048 | 0 | } |
1049 | |
|
1050 | 0 | const value_payload_decoder *payload_decoder = find_payload_decoder(command); |
1051 | |
|
1052 | 0 | if (!PINFO_FD_VISITED(pinfo) && payload_decoder && payload_decoder->state_reader_fn) |
1053 | 0 | (*payload_decoder->state_reader_fn) (payload_tvb, pinfo, conv_data); |
1054 | |
|
1055 | 0 | if (tree == NULL) |
1056 | 0 | return; |
1057 | | |
1058 | 0 | proto_item_set_text(ti, "DRBD [%s]", packet_name); |
1059 | |
|
1060 | 0 | if (payload_decoder && payload_decoder->tree_fn) |
1061 | 0 | (*payload_decoder->tree_fn) (payload_tvb, drbd_tree, conv_data); |
1062 | 0 | } |
1063 | | |
1064 | | static void drbd_ib_append_col_info(packet_info *pinfo, const char *packet_name) |
1065 | 0 | { |
1066 | 0 | const char *info_text; |
1067 | |
|
1068 | 0 | col_clear(pinfo->cinfo, COL_INFO); |
1069 | 0 | info_text = col_get_text(pinfo->cinfo, COL_INFO); |
1070 | 0 | if (!info_text || !info_text[0]) |
1071 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, "QP=0x%06x [%s]", pinfo->destport, packet_name); |
1072 | 0 | else |
1073 | 0 | col_append_fstr(pinfo->cinfo, COL_INFO, " [%s]", packet_name); |
1074 | 0 | col_set_fence(pinfo->cinfo, COL_INFO); |
1075 | 0 | } |
1076 | | |
1077 | | static void dissect_drbd_ib_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
1078 | 0 | { |
1079 | 0 | proto_tree *drbd_tree; |
1080 | 0 | proto_item *ti; |
1081 | 0 | uint16_t command = -1; |
1082 | |
|
1083 | 0 | ti = proto_tree_add_item(tree, proto_drbd, tvb, 0, -1, ENC_NA); |
1084 | 0 | drbd_tree = proto_item_add_subtree(ti, ett_drbd); |
1085 | |
|
1086 | 0 | tvbuff_t *payload_tvb = decode_header(tvb, drbd_tree, &command); |
1087 | |
|
1088 | 0 | if (!payload_tvb) |
1089 | 0 | return; |
1090 | | |
1091 | | /* Indicate what kind of message this is. */ |
1092 | 0 | const char *packet_name = val_to_str(pinfo->pool, command, packet_names, "Unknown (0x%02x)"); |
1093 | 0 | drbd_ib_append_col_info(pinfo, packet_name); |
1094 | |
|
1095 | 0 | if (tree == NULL) |
1096 | 0 | return; |
1097 | | |
1098 | 0 | proto_item_set_text(ti, "DRBD [%s]", packet_name); |
1099 | |
|
1100 | 0 | const value_payload_decoder *payload_decoder = find_payload_decoder(command); |
1101 | |
|
1102 | 0 | if (payload_decoder && payload_decoder->tree_fn) |
1103 | 0 | (*payload_decoder->tree_fn) (payload_tvb, drbd_tree, NULL); |
1104 | 0 | } |
1105 | | |
1106 | | static void dissect_drbd_ib_control_message(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) |
1107 | 0 | { |
1108 | 0 | proto_tree *drbd_tree; |
1109 | 0 | proto_item *ti; |
1110 | |
|
1111 | 0 | drbd_ib_append_col_info(pinfo, "RDMA Flow Control"); |
1112 | |
|
1113 | 0 | if (tree == NULL) |
1114 | 0 | return; |
1115 | | |
1116 | 0 | ti = proto_tree_add_item(tree, proto_drbd, tvb, 0, -1, ENC_NA); |
1117 | 0 | proto_item_set_text(ti, "DRBD [RDMA Flow Control]"); |
1118 | 0 | drbd_tree = proto_item_add_subtree(ti, ett_drbd); |
1119 | |
|
1120 | 0 | proto_tree_add_item(drbd_tree, hf_drbd_new_rx_descs_data, tvb, 4, 4, ENC_BIG_ENDIAN); |
1121 | 0 | proto_tree_add_item(drbd_tree, hf_drbd_new_rx_descs_control, tvb, 8, 4, ENC_BIG_ENDIAN); |
1122 | 0 | proto_tree_add_item(drbd_tree, hf_drbd_rx_desc_stolen_from, tvb, 12, 4, ENC_BIG_ENDIAN); |
1123 | 0 | } |
1124 | | |
1125 | | static bool dissect_drbd_ib(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) |
1126 | 0 | { |
1127 | 0 | if (!test_drbd_header(tvb, 0) && !test_drbd_rdma_control_header(tvb)) |
1128 | 0 | return false; |
1129 | | |
1130 | 0 | col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRBD RDMA"); |
1131 | 0 | while (1) { |
1132 | 0 | unsigned length; |
1133 | 0 | bool is_control_packet = test_drbd_rdma_control_header(tvb); |
1134 | |
|
1135 | 0 | if (is_control_packet) |
1136 | 0 | length = DRBD_TRANSPORT_RDMA_PACKET_LEN; |
1137 | 0 | else |
1138 | 0 | length = read_drbd_packet_len(tvb, 0); |
1139 | | |
1140 | | /* Was a header recognized? */ |
1141 | 0 | if (length == 0) |
1142 | 0 | break; |
1143 | | |
1144 | 0 | tvbuff_t *packet_tvb = tvb_new_subset_length(tvb, 0, length); |
1145 | |
|
1146 | 0 | if (is_control_packet) |
1147 | 0 | dissect_drbd_ib_control_message(packet_tvb, pinfo, tree); |
1148 | 0 | else |
1149 | 0 | dissect_drbd_ib_message(packet_tvb, pinfo, tree); |
1150 | | |
1151 | | /* Is there enough data for another DRBD packet? */ |
1152 | 0 | if (tvb_reported_length(tvb) < length + DRBD_FRAME_HEADER_80_LEN) |
1153 | 0 | break; |
1154 | | |
1155 | | /* Move to the next DRBD packet. */ |
1156 | 0 | tvb = tvb_new_subset_remaining(tvb, length); |
1157 | 0 | } |
1158 | |
|
1159 | 0 | return true; |
1160 | 0 | } |
1161 | | |
1162 | | static void insert_twopc(tvbuff_t *tvb, packet_info *pinfo, drbd_conv *conv_data, enum drbd_packet command) |
1163 | 0 | { |
1164 | 0 | uint32_t flags = tvb_get_ntohl(tvb, 4); |
1165 | |
|
1166 | 0 | drbd_twopc_key *key = wmem_new0(wmem_file_scope(), drbd_twopc_key); |
1167 | 0 | key->tid = tvb_get_ntohl(tvb, 0); |
1168 | 0 | if (flags & TWOPC_HAS_FLAGS) |
1169 | 0 | key->initiator_node_id = tvb_get_int8(tvb, 10); |
1170 | 0 | else |
1171 | 0 | key->initiator_node_id = tvb_get_ntohil(tvb, 4); |
1172 | |
|
1173 | 0 | drbd_twopc_val *val = wmem_new0(wmem_file_scope(), drbd_twopc_val); |
1174 | 0 | val->prepare_frame = pinfo->num; |
1175 | 0 | val->command = command; |
1176 | |
|
1177 | 0 | wmem_map_insert(conv_data->twopc, key, val); |
1178 | 0 | } |
1179 | | |
1180 | | static void read_state_twopc_prepare(tvbuff_t *tvb, packet_info *pinfo, drbd_conv *conv_data) |
1181 | 0 | { |
1182 | 0 | insert_twopc(tvb, pinfo, conv_data, P_TWOPC_PREPARE); |
1183 | 0 | } |
1184 | | |
1185 | | static void read_state_twopc_prep_rsz(tvbuff_t *tvb, packet_info *pinfo, drbd_conv *conv_data) |
1186 | 0 | { |
1187 | 0 | insert_twopc(tvb, pinfo, conv_data, P_TWOPC_PREP_RSZ); |
1188 | 0 | } |
1189 | | |
1190 | | static void decode_payload_connection_features(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1191 | 0 | { |
1192 | 0 | proto_tree_add_item(tree, hf_drbd_protocol_min, tvb, 0, 4, ENC_BIG_ENDIAN); |
1193 | 0 | proto_tree_add_item(tree, hf_drbd_feature_flags, tvb, 4, 4, ENC_BIG_ENDIAN); |
1194 | 0 | proto_tree_add_item(tree, hf_drbd_protocol_max, tvb, 8, 4, ENC_BIG_ENDIAN); |
1195 | 0 | proto_tree_add_item(tree, hf_drbd_sender_node_id, tvb, 12, 4, ENC_BIG_ENDIAN); |
1196 | 0 | proto_tree_add_item(tree, hf_drbd_receiver_node_id, tvb, 16, 4, ENC_BIG_ENDIAN); |
1197 | 0 | } |
1198 | | |
1199 | | static void decode_payload_auth_challenge(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1200 | 0 | { |
1201 | 0 | proto_tree_add_bytes_format(tree, hf_drbd_auth_challenge_nonce, tvb, 0, CHALLENGE_LEN, NULL, "Nonce"); |
1202 | 0 | } |
1203 | | |
1204 | | static void decode_payload_auth_response(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1205 | 0 | { |
1206 | 0 | proto_tree_add_bytes_format(tree, hf_drbd_auth_response_hash, tvb, 0, -1, NULL, "Hash"); |
1207 | 0 | } |
1208 | | |
1209 | | static void decode_data_common(tvbuff_t *tvb, proto_tree *tree) |
1210 | 0 | { |
1211 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1212 | 0 | proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1213 | 0 | proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 16, 4, ENC_BIG_ENDIAN); |
1214 | 0 | proto_tree_add_bitmask(tree, tvb, 20, hf_drbd_dp_flags, ett_drbd_data_flags, data_flag_fields, ENC_BIG_ENDIAN); |
1215 | 0 | } |
1216 | | |
1217 | | static void decode_payload_data(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1218 | 0 | { |
1219 | 0 | decode_data_common(tvb, tree); |
1220 | |
|
1221 | 0 | unsigned nbytes = tvb_reported_length_remaining(tvb, 24); |
1222 | 0 | proto_tree_add_uint(tree, hf_drbd_size, tvb, 0, 0, nbytes); |
1223 | | |
1224 | | /* For infiniband the data is not in this tvb, so we do not show the data field. */ |
1225 | 0 | if (tvb_captured_length(tvb) >= 24 + nbytes) { |
1226 | 0 | proto_tree_add_bytes_format(tree, hf_drbd_data, tvb, 24, |
1227 | 0 | nbytes, NULL, "Data (%u byte%s)", nbytes, plurality(nbytes, "", "s")); |
1228 | 0 | } |
1229 | 0 | } |
1230 | | |
1231 | | static void decode_payload_barrier(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1232 | 0 | { |
1233 | 0 | proto_tree_add_item(tree, hf_drbd_barrier, tvb, 0, 4, ENC_LITTLE_ENDIAN); |
1234 | 0 | } |
1235 | | |
1236 | | static void decode_payload_data_request(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1237 | 0 | { |
1238 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1239 | 0 | proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1240 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1241 | 0 | } |
1242 | | |
1243 | | static void decode_payload_dagtag_data_request(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1244 | 0 | { |
1245 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1246 | 0 | proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1247 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1248 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag_node_id, tvb, 20, 4, ENC_BIG_ENDIAN); |
1249 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 24, 8, ENC_BIG_ENDIAN); |
1250 | 0 | } |
1251 | | |
1252 | | static void decode_payload_sync_param(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1253 | 0 | { |
1254 | 0 | unsigned length = tvb_reported_length(tvb); |
1255 | 0 | unsigned offset = 0; |
1256 | |
|
1257 | 0 | proto_tree_add_item(tree, hf_drbd_resync_rate, tvb, offset, 4, ENC_BIG_ENDIAN); |
1258 | 0 | offset += 4; |
1259 | 0 | proto_tree_add_item(tree, hf_drbd_verify_alg, tvb, offset, DRBD_STRING_MAX, ENC_ASCII); |
1260 | 0 | offset += DRBD_STRING_MAX; |
1261 | |
|
1262 | 0 | if (length >= offset + DRBD_STRING_MAX) { |
1263 | 0 | proto_tree_add_item(tree, hf_drbd_csums_alg, tvb, offset, DRBD_STRING_MAX, ENC_ASCII); |
1264 | 0 | offset += DRBD_STRING_MAX; |
1265 | 0 | } |
1266 | |
|
1267 | 0 | if (length >= offset + 16) { |
1268 | 0 | proto_tree_add_item(tree, hf_drbd_c_plan_ahead, tvb, offset, 4, ENC_BIG_ENDIAN); |
1269 | 0 | proto_tree_add_item(tree, hf_drbd_c_delay_target, tvb, offset + 4, 4, ENC_BIG_ENDIAN); |
1270 | 0 | proto_tree_add_item(tree, hf_drbd_c_fill_target, tvb, offset + 8, 4, ENC_BIG_ENDIAN); |
1271 | 0 | proto_tree_add_item(tree, hf_drbd_c_max_rate, tvb, offset + 12, 4, ENC_BIG_ENDIAN); |
1272 | 0 | } |
1273 | 0 | } |
1274 | | |
1275 | | static void decode_payload_protocol(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1276 | 0 | { |
1277 | 0 | proto_tree_add_item(tree, hf_drbd_protocol, tvb, 0, 4, ENC_BIG_ENDIAN); |
1278 | 0 | proto_tree_add_item(tree, hf_drbd_after_sb_0p, tvb, 4, 4, ENC_BIG_ENDIAN); |
1279 | 0 | proto_tree_add_item(tree, hf_drbd_after_sb_1p, tvb, 8, 4, ENC_BIG_ENDIAN); |
1280 | 0 | proto_tree_add_item(tree, hf_drbd_after_sb_2p, tvb, 12, 4, ENC_BIG_ENDIAN); |
1281 | 0 | proto_tree_add_item(tree, hf_drbd_conn_flags, tvb, 16, 4, ENC_BIG_ENDIAN); |
1282 | 0 | proto_tree_add_item(tree, hf_drbd_two_primaries, tvb, 20, 4, ENC_BIG_ENDIAN); |
1283 | 0 | proto_tree_add_item(tree, hf_drbd_integrity_alg, tvb, 24, -1, ENC_ASCII); |
1284 | 0 | } |
1285 | | |
1286 | | static void decode_payload_uuids(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1287 | 0 | { |
1288 | 0 | proto_tree_add_item(tree, hf_drbd_current_uuid, tvb, 0, 8, ENC_BIG_ENDIAN); |
1289 | 0 | proto_tree_add_item(tree, hf_drbd_bitmap_uuid, tvb, 8, 8, ENC_BIG_ENDIAN); |
1290 | 0 | proto_tree_add_item(tree, hf_drbd_history_uuid, tvb, 16, 8, ENC_BIG_ENDIAN); |
1291 | 0 | proto_tree_add_item(tree, hf_drbd_history_uuid, tvb, 24, 8, ENC_BIG_ENDIAN); |
1292 | 0 | proto_tree_add_item(tree, hf_drbd_dirty_bits, tvb, 32, 8, ENC_BIG_ENDIAN); |
1293 | 0 | proto_tree_add_bitmask(tree, tvb, 40, hf_drbd_uuid_flags, ett_drbd_uuid_flags, uuid_flag_fields, ENC_BIG_ENDIAN); |
1294 | 0 | } |
1295 | | |
1296 | | static void decode_payload_sizes(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1297 | 0 | { |
1298 | 0 | proto_tree_add_item(tree, hf_drbd_d_size, tvb, 0, 8, ENC_BIG_ENDIAN); |
1299 | 0 | proto_tree_add_item(tree, hf_drbd_u_size, tvb, 8, 8, ENC_BIG_ENDIAN); |
1300 | 0 | proto_tree_add_item(tree, hf_drbd_c_size, tvb, 16, 8, ENC_BIG_ENDIAN); |
1301 | 0 | proto_tree_add_item(tree, hf_drbd_max_bio_size, tvb, 24, 4, ENC_BIG_ENDIAN); |
1302 | 0 | proto_tree_add_item(tree, hf_drbd_queue_order_type, tvb, 28, 2, ENC_BIG_ENDIAN); |
1303 | 0 | proto_tree_add_item(tree, hf_drbd_dds_flags, tvb, 30, 2, ENC_BIG_ENDIAN); |
1304 | 0 | proto_tree_add_item(tree, hf_drbd_physical_block_size, tvb, 32, 4, ENC_BIG_ENDIAN); |
1305 | 0 | proto_tree_add_item(tree, hf_drbd_logical_block_size, tvb, 36, 4, ENC_BIG_ENDIAN); |
1306 | 0 | proto_tree_add_item(tree, hf_drbd_alignment_offset, tvb, 40, 4, ENC_BIG_ENDIAN); |
1307 | 0 | proto_tree_add_item(tree, hf_drbd_io_min, tvb, 44, 4, ENC_BIG_ENDIAN); |
1308 | 0 | proto_tree_add_item(tree, hf_drbd_io_opt, tvb, 48, 4, ENC_BIG_ENDIAN); |
1309 | 0 | proto_tree_add_item(tree, hf_drbd_discard_enabled, tvb, 52, 1, ENC_BIG_ENDIAN); |
1310 | 0 | proto_tree_add_item(tree, hf_drbd_discard_zeroes_data, tvb, 53, 1, ENC_BIG_ENDIAN); |
1311 | 0 | proto_tree_add_item(tree, hf_drbd_write_same_capable, tvb, 54, 1, ENC_BIG_ENDIAN); |
1312 | 0 | } |
1313 | | |
1314 | | static void decode_payload_state(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1315 | 0 | { |
1316 | 0 | proto_tree_add_bitmask(tree, tvb, 0, hf_drbd_state, ett_drbd_state, state_fields, ENC_BIG_ENDIAN); |
1317 | 0 | } |
1318 | | |
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[]) |
1321 | 0 | { |
1322 | 0 | int masked_i = 0; |
1323 | |
|
1324 | 0 | for (int fields_i = 0; fields[fields_i]; fields_i++) { |
1325 | 0 | header_field_info *hf = proto_registrar_get_nth(*fields[fields_i]); |
1326 | |
|
1327 | 0 | if (hf && mask & hf->bitmask) { |
1328 | 0 | masked_fields[masked_i] = fields[fields_i]; |
1329 | 0 | masked_i++; |
1330 | 0 | } |
1331 | 0 | } |
1332 | |
|
1333 | 0 | masked_fields[masked_i] = NULL; |
1334 | 0 | } |
1335 | | |
1336 | | static void decode_state_change(tvbuff_t *tvb, proto_tree *tree, int offset) |
1337 | 0 | { |
1338 | 0 | uint32_t state_mask = tvb_get_ntohl(tvb, offset); |
1339 | 0 | int * masked_state_fields[array_length(state_fields)]; |
1340 | 0 | mask_fields(state_mask, state_fields, masked_state_fields); |
1341 | |
|
1342 | 0 | if (masked_state_fields[0]) { |
1343 | 0 | proto_tree_add_bitmask(tree, tvb, offset + 4, hf_drbd_state, ett_drbd_state, masked_state_fields, ENC_BIG_ENDIAN); |
1344 | 0 | } else { |
1345 | 0 | proto_tree_add_item(tree, hf_drbd_state, tvb, offset + 4, 4, ENC_BIG_ENDIAN); |
1346 | 0 | } |
1347 | 0 | } |
1348 | | |
1349 | | static void decode_payload_req_state(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1350 | 0 | { |
1351 | 0 | decode_state_change(tvb, tree, 0); |
1352 | 0 | } |
1353 | | |
1354 | | static void decode_payload_sync_uuid(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1355 | 0 | { |
1356 | 0 | proto_tree_add_item(tree, hf_drbd_uuid, tvb, 0, 8, ENC_BIG_ENDIAN); |
1357 | 0 | } |
1358 | | |
1359 | | static void decode_payload_skip(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1360 | 0 | { |
1361 | 0 | proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 0, 4, ENC_BIG_ENDIAN); |
1362 | 0 | proto_tree_add_item(tree, hf_drbd_offset, tvb, 4, 4, ENC_BIG_ENDIAN); |
1363 | 0 | } |
1364 | | |
1365 | | static void decode_payload_out_of_sync(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1366 | 0 | { |
1367 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1368 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 8, 4, ENC_BIG_ENDIAN); |
1369 | 0 | } |
1370 | | |
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) |
1373 | 0 | { |
1374 | 0 | proto_tree_add_item_ret_uint(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN, |
1375 | 0 | key ? &key->tid : NULL); |
1376 | |
|
1377 | 0 | uint32_t flags = tvb_get_ntohl(tvb, 4); |
1378 | 0 | if (flags & TWOPC_HAS_FLAGS) { |
1379 | 0 | proto_tree_add_bitmask(tree, tvb, 4, hf_drbd_twopc_flags, ett_drbd_twopc_flags, twopc_flag_fields, ENC_BIG_ENDIAN); |
1380 | 0 | proto_tree_add_item_ret_int(tree, hf_drbd_initiator_node_id, tvb, 10, 1, ENC_BIG_ENDIAN, |
1381 | 0 | key ? &key->initiator_node_id : NULL); |
1382 | 0 | proto_tree_add_item(tree, hf_drbd_target_node_id, tvb, 11, 1, ENC_BIG_ENDIAN); |
1383 | 0 | } else { |
1384 | 0 | flags = 0; |
1385 | 0 | proto_tree_add_item_ret_int(tree, hf_drbd_initiator_node_id, tvb, 4, 4, ENC_BIG_ENDIAN, |
1386 | 0 | key ? &key->initiator_node_id : NULL); |
1387 | 0 | proto_tree_add_item(tree, hf_drbd_target_node_id, tvb, 8, 4, ENC_BIG_ENDIAN); |
1388 | 0 | } |
1389 | |
|
1390 | 0 | proto_tree_add_item(tree, hf_drbd_nodes_to_reach, tvb, 12, 8, ENC_BIG_ENDIAN); |
1391 | 0 | return flags; |
1392 | 0 | } |
1393 | | |
1394 | | static void decode_payload_twopc_prepare(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1395 | 0 | { |
1396 | 0 | uint32_t flags = decode_twopc_request_common(tvb, tree, NULL); |
1397 | |
|
1398 | 0 | if (!(flags & TWOPC_HAS_FLAGS)) |
1399 | 0 | proto_tree_add_item(tree, hf_drbd_primary_nodes, tvb, 20, 8, ENC_BIG_ENDIAN); |
1400 | |
|
1401 | 0 | decode_state_change(tvb, tree, 28); |
1402 | 0 | } |
1403 | | |
1404 | | static void decode_payload_twopc_prep_rsz(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1405 | 0 | { |
1406 | 0 | decode_twopc_request_common(tvb, tree, NULL); |
1407 | |
|
1408 | 0 | proto_tree_add_item(tree, hf_drbd_user_size, tvb, 20, 8, ENC_BIG_ENDIAN); |
1409 | 0 | proto_tree_add_item(tree, hf_drbd_dds_flags, tvb, 28, 2, ENC_BIG_ENDIAN); |
1410 | 0 | } |
1411 | | |
1412 | | static void decode_payload_twopc_commit(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data) |
1413 | 0 | { |
1414 | 0 | drbd_twopc_key key; |
1415 | 0 | uint32_t flags = decode_twopc_request_common(tvb, tree, &key); |
1416 | |
|
1417 | 0 | if (!conv_data) |
1418 | 0 | return; |
1419 | | |
1420 | 0 | drbd_twopc_val *val = wmem_map_lookup(conv_data->twopc, &key); |
1421 | 0 | if (!val) |
1422 | 0 | return; |
1423 | | |
1424 | 0 | proto_item *it = proto_tree_add_uint(tree, hf_drbd_twopc_prepare_in, |
1425 | 0 | tvb, 0, 0, val->prepare_frame); |
1426 | 0 | proto_item_set_generated(it); |
1427 | |
|
1428 | 0 | if (val->command == P_TWOPC_PREPARE) { |
1429 | 0 | proto_tree_add_item(tree, hf_drbd_primary_nodes, tvb, 20, 8, ENC_BIG_ENDIAN); |
1430 | 0 | if (!(flags & TWOPC_HAS_FLAGS)) |
1431 | 0 | decode_state_change(tvb, tree, 28); |
1432 | 0 | else if (flags & TWOPC_HAS_REACHABLE) |
1433 | 0 | proto_tree_add_item(tree, hf_drbd_reachable_nodes, tvb, 28, 8, ENC_BIG_ENDIAN); |
1434 | 0 | } else if (val->command == P_TWOPC_PREP_RSZ) { |
1435 | 0 | proto_tree_add_item(tree, hf_drbd_diskful_primary_nodes, tvb, 20, 8, ENC_BIG_ENDIAN); |
1436 | 0 | proto_tree_add_item(tree, hf_drbd_exposed_size, tvb, 28, 8, ENC_BIG_ENDIAN); |
1437 | 0 | } |
1438 | 0 | } |
1439 | | |
1440 | | static void decode_payload_dagtag(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1441 | 0 | { |
1442 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 0, 8, ENC_BIG_ENDIAN); |
1443 | 0 | } |
1444 | | |
1445 | | static void decode_payload_uuids110(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1446 | 0 | { |
1447 | 0 | proto_tree_add_item(tree, hf_drbd_current_uuid, tvb, 0, 8, ENC_BIG_ENDIAN); |
1448 | 0 | proto_tree_add_item(tree, hf_drbd_dirty_bits, tvb, 8, 8, ENC_BIG_ENDIAN); |
1449 | 0 | proto_tree_add_bitmask(tree, tvb, 16, hf_drbd_uuid_flags, ett_drbd_uuid_flags, uuid_flag_fields, ENC_BIG_ENDIAN); |
1450 | 0 | proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 24, 8, ENC_BIG_ENDIAN); |
1451 | |
|
1452 | 0 | uint64_t bitmap_uuids_mask; |
1453 | 0 | proto_tree_add_item_ret_uint64(tree, hf_drbd_bitmap_uuids_mask, tvb, 32, 8, ENC_BIG_ENDIAN, &bitmap_uuids_mask); |
1454 | |
|
1455 | 0 | unsigned offset = 40; |
1456 | 0 | for (int i = 0; i < 64; i++) { |
1457 | 0 | if (is_bit_set_64(bitmap_uuids_mask, i)) { |
1458 | 0 | uint64_t bitmap_uuid = tvb_get_ntoh64(tvb, offset); |
1459 | 0 | proto_tree_add_uint64_format(tree, hf_drbd_bitmap_uuid, tvb, offset, 8, bitmap_uuid, |
1460 | 0 | "Bitmap UUID for node %d: 0x%016" PRIx64, i, bitmap_uuid); |
1461 | 0 | offset += 8; |
1462 | 0 | } |
1463 | 0 | } |
1464 | |
|
1465 | 0 | proto_item *history_uuids = proto_tree_add_item(tree, hf_drbd_history_uuid_list, tvb, offset, -1, ENC_NA); |
1466 | 0 | proto_tree *history_tree = proto_item_add_subtree(history_uuids, ett_drbd_history_uuids); |
1467 | 0 | unsigned total_length = tvb_reported_length(tvb); |
1468 | 0 | while (offset < total_length) { |
1469 | 0 | proto_tree_add_item(history_tree, hf_drbd_history_uuid, tvb, offset, 8, ENC_BIG_ENDIAN); |
1470 | 0 | offset += 8; |
1471 | 0 | } |
1472 | 0 | } |
1473 | | |
1474 | | static void decode_payload_peer_dagtag(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1475 | 0 | { |
1476 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 0, 8, ENC_BIG_ENDIAN); |
1477 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag_node_id, tvb, 8, 4, ENC_BIG_ENDIAN); |
1478 | 0 | } |
1479 | | |
1480 | | static void decode_payload_current_uuid(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1481 | 0 | { |
1482 | 0 | proto_tree_add_item(tree, hf_drbd_uuid, tvb, 0, 8, ENC_BIG_ENDIAN); |
1483 | 0 | proto_tree_add_item(tree, hf_drbd_weak_nodes, tvb, 8, 8, ENC_BIG_ENDIAN); |
1484 | 0 | } |
1485 | | |
1486 | | static void decode_payload_data_size(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1487 | 0 | { |
1488 | 0 | decode_data_common(tvb, tree); |
1489 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 24, 4, ENC_BIG_ENDIAN); |
1490 | 0 | } |
1491 | | |
1492 | | static void decode_payload_data_wsame(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1493 | 0 | { |
1494 | 0 | decode_data_common(tvb, tree); |
1495 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 24, 4, ENC_BIG_ENDIAN); |
1496 | |
|
1497 | 0 | 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 | 0 | if (tvb_captured_length(tvb) >= 28 + nbytes) { |
1500 | 0 | proto_tree_add_bytes_format(tree, hf_drbd_data, tvb, 28, |
1501 | 0 | nbytes, NULL, "Data (%u byte%s)", nbytes, plurality(nbytes, "", "s")); |
1502 | 0 | } |
1503 | 0 | } |
1504 | | |
1505 | | static void decode_payload_rs_deallocated(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1506 | 0 | { |
1507 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1508 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 8, 4, ENC_BIG_ENDIAN); |
1509 | 0 | } |
1510 | | |
1511 | | static void decode_payload_block_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1512 | 0 | { |
1513 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1514 | 0 | proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1515 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1516 | 0 | proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 20, 4, ENC_BIG_ENDIAN); |
1517 | 0 | } |
1518 | | |
1519 | | static void decode_payload_ov_result(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1520 | 0 | { |
1521 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1522 | 0 | proto_tree_add_item(tree, hf_drbd_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1523 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1524 | 0 | proto_tree_add_item(tree, hf_drbd_seq_num, tvb, 20, 4, ENC_BIG_ENDIAN); |
1525 | 0 | proto_tree_add_item(tree, hf_drbd_ov_result, tvb, 24, 8, ENC_BIG_ENDIAN); |
1526 | 0 | } |
1527 | | |
1528 | | static void decode_payload_barrier_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1529 | 0 | { |
1530 | 0 | proto_tree_add_item(tree, hf_drbd_barrier, tvb, 0, 4, ENC_LITTLE_ENDIAN); |
1531 | 0 | proto_tree_add_item(tree, hf_drbd_set_size, tvb, 4, 4, ENC_BIG_ENDIAN); |
1532 | 0 | } |
1533 | | |
1534 | | static void decode_payload_confirm_stable(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1535 | 0 | { |
1536 | 0 | proto_tree_add_item(tree, hf_drbd_oldest_block_id, tvb, 0, 8, ENC_LITTLE_ENDIAN); |
1537 | 0 | proto_tree_add_item(tree, hf_drbd_youngest_block_id, tvb, 8, 8, ENC_LITTLE_ENDIAN); |
1538 | 0 | proto_tree_add_item(tree, hf_drbd_set_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1539 | 0 | } |
1540 | | |
1541 | | static void decode_payload_rq_s_reply(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1542 | 0 | { |
1543 | 0 | proto_tree_add_item(tree, hf_drbd_retcode, tvb, 0, 4, ENC_BIG_ENDIAN); |
1544 | 0 | } |
1545 | | |
1546 | | static void decode_payload_peer_ack(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1547 | 0 | { |
1548 | 0 | proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 0, 8, ENC_BIG_ENDIAN); |
1549 | 0 | proto_tree_add_item(tree, hf_drbd_dagtag, tvb, 8, 8, ENC_BIG_ENDIAN); |
1550 | 0 | } |
1551 | | |
1552 | | static void decode_payload_peers_in_sync(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data _U_) |
1553 | 0 | { |
1554 | 0 | proto_tree_add_item(tree, hf_drbd_sector, tvb, 0, 8, ENC_BIG_ENDIAN); |
1555 | 0 | proto_tree_add_item(tree, hf_drbd_node_mask, tvb, 8, 8, ENC_BIG_ENDIAN); |
1556 | 0 | proto_tree_add_item(tree, hf_drbd_size, tvb, 16, 4, ENC_BIG_ENDIAN); |
1557 | 0 | } |
1558 | | |
1559 | | static void decode_payload_twopc_reply(tvbuff_t *tvb, proto_tree *tree, drbd_conv *conv_data) |
1560 | 0 | { |
1561 | 0 | drbd_twopc_key key; |
1562 | |
|
1563 | 0 | proto_tree_add_item_ret_uint(tree, hf_drbd_tid, tvb, 0, 4, ENC_BIG_ENDIAN, |
1564 | 0 | &key.tid); |
1565 | 0 | proto_tree_add_item_ret_int(tree, hf_drbd_initiator_node_id, tvb, 4, 4, ENC_BIG_ENDIAN, |
1566 | 0 | &key.initiator_node_id); |
1567 | 0 | proto_tree_add_item(tree, hf_drbd_reachable_nodes, tvb, 8, 8, ENC_BIG_ENDIAN); |
1568 | |
|
1569 | 0 | if (!conv_data) |
1570 | 0 | return; |
1571 | | |
1572 | 0 | drbd_twopc_val *val = wmem_map_lookup(conv_data->twopc, &key); |
1573 | 0 | if (!val) |
1574 | 0 | return; |
1575 | | |
1576 | 0 | proto_item *it = proto_tree_add_uint(tree, hf_drbd_twopc_prepare_in, |
1577 | 0 | tvb, 0, 0, val->prepare_frame); |
1578 | 0 | proto_item_set_generated(it); |
1579 | |
|
1580 | 0 | if (val->command == P_TWOPC_PREPARE) { |
1581 | 0 | proto_tree_add_item(tree, hf_drbd_primary_nodes, tvb, 16, 8, ENC_BIG_ENDIAN); |
1582 | 0 | proto_tree_add_item(tree, hf_drbd_weak_nodes, tvb, 24, 8, ENC_BIG_ENDIAN); |
1583 | 0 | } else if (val->command == P_TWOPC_PREP_RSZ) { |
1584 | 0 | proto_tree_add_item(tree, hf_drbd_diskful_primary_nodes, tvb, 16, 8, ENC_BIG_ENDIAN); |
1585 | 0 | proto_tree_add_item(tree, hf_drbd_max_possible_size, tvb, 24, 8, ENC_BIG_ENDIAN); |
1586 | 0 | } |
1587 | 0 | } |
1588 | | |
1589 | | static void format_node_mask(char *s, uint64_t value) |
1590 | 0 | { |
1591 | 0 | if (!value) { |
1592 | 0 | (void) g_strlcpy(s, "<none>", ITEM_LABEL_LENGTH); |
1593 | 0 | return; |
1594 | 0 | } |
1595 | | |
1596 | 0 | int written = 0; |
1597 | 0 | int run_start = -1; |
1598 | 0 | for (int i = 0; i < 64 && written < ITEM_LABEL_LENGTH; i++) { |
1599 | 0 | bool is_set = is_bit_set_64(value, i); |
1600 | |
|
1601 | 0 | int run_end; |
1602 | 0 | if (!is_set) { |
1603 | 0 | run_end = i; |
1604 | 0 | } else if (i == 63) { |
1605 | 0 | if (run_start == -1) |
1606 | 0 | run_start = i; |
1607 | 0 | run_end = 64; |
1608 | 0 | } else { |
1609 | 0 | run_end = -1; |
1610 | 0 | } |
1611 | |
|
1612 | 0 | if (run_start != -1 && run_end != -1) { |
1613 | 0 | int run_length = run_end - run_start; |
1614 | 0 | const char *sep = written ? ", " : ""; |
1615 | |
|
1616 | 0 | if (run_length == 1) |
1617 | 0 | written += snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d", sep, run_start); |
1618 | 0 | else if (run_length == 2) |
1619 | 0 | written += snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d, %d", sep, run_start, run_start + 1); |
1620 | 0 | else |
1621 | 0 | written += snprintf(s + written, ITEM_LABEL_LENGTH - written, "%s%d - %d", sep, run_start, run_end - 1); |
1622 | 0 | } |
1623 | |
|
1624 | 0 | if (!is_set) |
1625 | 0 | run_start = -1; |
1626 | 0 | else if (run_start == -1) |
1627 | 0 | run_start = i; |
1628 | 0 | } |
1629 | 0 | } |
1630 | | |
1631 | | void proto_register_drbd(void) |
1632 | 14 | { |
1633 | 14 | static hf_register_info hf[] = { |
1634 | 14 | { &hf_drbd_command, { "Command", "drbd.command", FT_UINT16, BASE_HEX, VALS(packet_names), 0x0, NULL, HFILL }}, |
1635 | 14 | { &hf_drbd_length, { "Payload length", "drbd.length", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1636 | 14 | { &hf_drbd_volume, { "Volume", "drbd.volume", FT_INT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1637 | 14 | { &hf_drbd_auth_challenge_nonce, { "Nonce", "drbd.auth_nonce", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }}, |
1638 | 14 | { &hf_drbd_auth_response_hash, { "Hash", "drbd.auth_hash", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }}, |
1639 | 14 | { &hf_drbd_sector, { "Sector", "drbd.sector", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1640 | 14 | { &hf_drbd_block_id, { "Block ID", "drbd.block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1641 | 14 | { &hf_drbd_seq_num, { "Sequence number", "drbd.seq_num", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1642 | 14 | { &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 | 14 | { &hf_drbd_dp_flags, { "Data flags", "drbd.dp_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1644 | 14 | { &hf_drbd_data, { "Data", "drbd.data", FT_BYTES, BASE_NO_DISPLAY_VALUE, NULL, 0x0, NULL, HFILL }}, |
1645 | 14 | { &hf_drbd_size, { "Size", "drbd.size", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1646 | 14 | { &hf_drbd_protocol_min, { "protocol_min", "drbd.protocol_min", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1647 | 14 | { &hf_drbd_feature_flags, { "feature_flags", "drbd.feature_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1648 | 14 | { &hf_drbd_protocol_max, { "protocol_max", "drbd.protocol_max", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1649 | 14 | { &hf_drbd_sender_node_id, { "sender_node_id", "drbd.sender_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1650 | 14 | { &hf_drbd_receiver_node_id, { "receiver_node_id", "drbd.receiver_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1651 | 14 | { &hf_drbd_barrier, { "barrier", "drbd.barrier", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1652 | 14 | { &hf_drbd_set_size, { "set_size", "drbd.set_size", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1653 | 14 | { &hf_drbd_oldest_block_id, { "oldest_block_id", "drbd.oldest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1654 | 14 | { &hf_drbd_youngest_block_id, { "youngest_block_id", "drbd.youngest_block_id", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1655 | 14 | { &hf_drbd_resync_rate, { "resync_rate", "drbd.resync_rate", FT_UINT32, BASE_DEC|BASE_UNIT_STRING, UNS(&units_kibps), 0x0, NULL, HFILL }}, |
1656 | 14 | { &hf_drbd_verify_alg, { "verify_alg", "drbd.verify_alg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1657 | 14 | { &hf_drbd_csums_alg, { "csums_alg", "drbd.csums_alg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1658 | 14 | { &hf_drbd_c_plan_ahead, { "c_plan_ahead", "drbd.c_plan_ahead", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1659 | 14 | { &hf_drbd_c_delay_target, { "c_delay_target", "drbd.c_delay_target", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1660 | 14 | { &hf_drbd_c_fill_target, { "c_fill_target", "drbd.c_fill_target", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1661 | 14 | { &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 | 14 | { &hf_drbd_protocol, { "protocol", "drbd.protocol", FT_UINT32, BASE_HEX, VALS(protocol_names), 0x0, NULL, HFILL }}, |
1663 | 14 | { &hf_drbd_after_sb_0p, { "after_sb_0p", "drbd.after_sb_0p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1664 | 14 | { &hf_drbd_after_sb_1p, { "after_sb_1p", "drbd.after_sb_1p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1665 | 14 | { &hf_drbd_after_sb_2p, { "after_sb_2p", "drbd.after_sb_2p", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1666 | 14 | { &hf_drbd_conn_flags, { "conn_flags", "drbd.conn_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1667 | 14 | { &hf_drbd_two_primaries, { "two_primaries", "drbd.two_primaries", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1668 | 14 | { &hf_drbd_integrity_alg, { "integrity_alg", "drbd.integrity_alg", FT_STRINGZ, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1669 | 14 | { &hf_drbd_current_uuid, { "Current UUID", "drbd.current_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1670 | 14 | { &hf_drbd_bitmap_uuid, { "Bitmap UUID", "drbd.bitmap_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1671 | 14 | { &hf_drbd_history_uuid_list, { "History UUIDs", "drbd.history_uuids", FT_NONE, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1672 | 14 | { &hf_drbd_history_uuid, { "History UUID", "drbd.history_uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1673 | 14 | { &hf_drbd_dirty_bits, { "Dirty bits", "drbd.dirty_bits", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1674 | 14 | { &hf_drbd_uuid_flags, { "UUID flags", "drbd.uuid_flags", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1675 | 14 | { &hf_drbd_node_mask, { "Nodes", "drbd.node_mask", FT_UINT64, BASE_CUSTOM, CF_FUNC(format_node_mask), 0x0, NULL, HFILL }}, |
1676 | 14 | { &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 | 14 | { &hf_drbd_uuid, { "uuid", "drbd.uuid", FT_UINT64, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1678 | 14 | { &hf_drbd_weak_nodes, { "weak_nodes", "drbd.weak_nodes", FT_UINT64, BASE_CUSTOM, CF_FUNC(format_node_mask), 0x0, NULL, HFILL }}, |
1679 | 14 | { &hf_drbd_physical_block_size, { "physical_block_size", "drbd.physical_block_size", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1680 | 14 | { &hf_drbd_logical_block_size, { "logical_block_size", "drbd.logical_block_size", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1681 | 14 | { &hf_drbd_alignment_offset, { "alignment_offset", "drbd.alignment_offset", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1682 | 14 | { &hf_drbd_io_min, { "io_min", "drbd.io_min", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1683 | 14 | { &hf_drbd_io_opt, { "io_opt", "drbd.io_opt", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1684 | 14 | { &hf_drbd_discard_enabled, { "discard_enabled", "drbd.discard_enabled", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1685 | 14 | { &hf_drbd_discard_zeroes_data, { "discard_zeroes_data", "drbd.discard_zeroes_data", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1686 | 14 | { &hf_drbd_write_same_capable, { "write_same_capable", "drbd.write_same_capable", FT_BOOLEAN, BASE_NONE, NULL, 0x0, NULL, HFILL }}, |
1687 | 14 | { &hf_drbd_d_size, { "d_size", "drbd.d_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1688 | 14 | { &hf_drbd_u_size, { "u_size", "drbd.u_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1689 | 14 | { &hf_drbd_c_size, { "c_size", "drbd.c_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1690 | 14 | { &hf_drbd_max_bio_size, { "max_bio_size", "drbd.max_bio_size", FT_UINT32, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1691 | 14 | { &hf_drbd_queue_order_type, { "queue_order_type", "drbd.queue_order_type", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1692 | 14 | { &hf_drbd_dds_flags, { "dds_flags", "drbd.dds_flags", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1693 | 14 | { &hf_drbd_state, { "state", "drbd.state", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1694 | 14 | { &hf_drbd_retcode, { "retcode", "drbd.retcode", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1695 | 14 | { &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 | 14 | { &hf_drbd_tid, { "tid", "drbd.tid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1697 | 14 | { &hf_drbd_twopc_flags, { "twopc_flags", "drbd.twopc_flags", FT_UINT32, BASE_HEX, NULL, 0x0, NULL, HFILL }}, |
1698 | 14 | { &hf_drbd_initiator_node_id, { "initiator_node_id", "drbd.initiator_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1699 | 14 | { &hf_drbd_target_node_id, { "target_node_id", "drbd.target_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1700 | 14 | { &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 | 14 | { &hf_drbd_primary_nodes, { "primary_nodes", "drbd.primary_nodes", FT_UINT64, BASE_CUSTOM, CF_FUNC(format_node_mask), 0x0, NULL, HFILL }}, |
1702 | 14 | { &hf_drbd_user_size, { "user_size", "drbd.user_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1703 | 14 | { &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 | 14 | { &hf_drbd_exposed_size, { "exposed_size", "drbd.exposed_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1705 | 14 | { &hf_drbd_reachable_nodes, { "reachable_nodes", "drbd.reachable_nodes", FT_UINT64, BASE_CUSTOM, CF_FUNC(format_node_mask), 0x0, NULL, HFILL }}, |
1706 | 14 | { &hf_drbd_max_possible_size, { "max_possible_size", "drbd.max_possible_size", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1707 | 14 | { &hf_drbd_offset, { "offset", "drbd.offset", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1708 | 14 | { &hf_drbd_dagtag, { "dagtag", "drbd.dagtag", FT_UINT64, BASE_DEC_HEX, NULL, 0x0, NULL, HFILL }}, |
1709 | 14 | { &hf_drbd_dagtag_node_id, { "dagtag_node_id", "drbd.dagtag_node_id", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1710 | 14 | { &hf_drbd_new_rx_descs_data, { "New descriptors received (data)", "drbd.new_rx_descs_data", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1711 | 14 | { &hf_drbd_new_rx_descs_control, { "New descriptors received (control)", "drbd.new_rx_descs_control", FT_INT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1712 | 14 | { &hf_drbd_rx_desc_stolen_from, { "Descriptor stolen from", "drbd.rx_desc_stolen_from", FT_INT32, BASE_DEC, VALS(stream_names), 0x0, NULL, HFILL }}, |
1713 | | |
1714 | 14 | { &hf_drbd_state_role, { "role", "drbd.state.role", FT_UINT32, BASE_DEC, VALS(role_names), STATE_ROLE, NULL, HFILL }}, |
1715 | 14 | { &hf_drbd_state_peer, { "peer", "drbd.state.peer", FT_UINT32, BASE_DEC, VALS(role_names), STATE_PEER, NULL, HFILL }}, |
1716 | 14 | { &hf_drbd_state_conn, { "conn", "drbd.state.conn", FT_UINT32, BASE_DEC, VALS(connection_state_names), STATE_CONN, NULL, HFILL }}, |
1717 | 14 | { &hf_drbd_state_disk, { "disk", "drbd.state.disk", FT_UINT32, BASE_DEC, VALS(disk_state_names), STATE_DISK, NULL, HFILL }}, |
1718 | 14 | { &hf_drbd_state_pdsk, { "pdsk", "drbd.state.pdsk", FT_UINT32, BASE_DEC, VALS(disk_state_names), STATE_PDSK, NULL, HFILL }}, |
1719 | 14 | { &hf_drbd_state_susp, { "susp", "drbd.state.susp", FT_BOOLEAN, 32, NULL, STATE_SUSP, NULL, HFILL }}, |
1720 | 14 | { &hf_drbd_state_aftr_isp, { "aftr_isp", "drbd.state.aftr_isp", FT_BOOLEAN, 32, NULL, STATE_AFTR_ISP, NULL, HFILL }}, |
1721 | 14 | { &hf_drbd_state_peer_isp, { "peer_isp", "drbd.state.peer_isp", FT_BOOLEAN, 32, NULL, STATE_PEER_ISP, NULL, HFILL }}, |
1722 | 14 | { &hf_drbd_state_user_isp, { "user_isp", "drbd.state.user_isp", FT_BOOLEAN, 32, NULL, STATE_USER_ISP, NULL, HFILL }}, |
1723 | 14 | { &hf_drbd_state_susp_nod, { "susp_nod", "drbd.state.susp_nod", FT_BOOLEAN, 32, NULL, STATE_SUSP_NOD, NULL, HFILL }}, |
1724 | 14 | { &hf_drbd_state_susp_fen, { "susp_fen", "drbd.state.susp_fen", FT_BOOLEAN, 32, NULL, STATE_SUSP_FEN, NULL, HFILL }}, |
1725 | 14 | { &hf_drbd_state_quorum, { "quorum", "drbd.state.quorum", FT_BOOLEAN, 32, NULL, STATE_QUORUM, NULL, HFILL }}, |
1726 | | |
1727 | 14 | { &hf_drbd_twopc_flag_has_reachable, { "has_reachable", "drbd.twopc_flags.has_reachable", FT_BOOLEAN, 32, NULL, TWOPC_HAS_REACHABLE, NULL, HFILL }}, |
1728 | | |
1729 | 14 | { &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 | 14 | { &hf_drbd_uuid_flag_crashed_primary, { "crashed_primary", "drbd.uuid_flag.crashed_primary", FT_BOOLEAN, 64, NULL, UUID_FLAG_CRASHED_PRIMARY, NULL, HFILL }}, |
1731 | 14 | { &hf_drbd_uuid_flag_inconsistent, { "inconsistent", "drbd.uuid_flag.inconsistent", FT_BOOLEAN, 64, NULL, UUID_FLAG_INCONSISTENT, NULL, HFILL }}, |
1732 | 14 | { &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 | 14 | { &hf_drbd_uuid_flag_new_datagen, { "new_datagen", "drbd.uuid_flag.new_datagen", FT_BOOLEAN, 64, NULL, UUID_FLAG_NEW_DATAGEN, NULL, HFILL }}, |
1734 | 14 | { &hf_drbd_uuid_flag_stable, { "stable", "drbd.uuid_flag.stable", FT_BOOLEAN, 64, NULL, UUID_FLAG_STABLE, NULL, HFILL }}, |
1735 | 14 | { &hf_drbd_uuid_flag_got_stable, { "got_stable", "drbd.uuid_flag.got_stable", FT_BOOLEAN, 64, NULL, UUID_FLAG_GOT_STABLE, NULL, HFILL }}, |
1736 | 14 | { &hf_drbd_uuid_flag_resync, { "resync", "drbd.uuid_flag.resync", FT_BOOLEAN, 64, NULL, UUID_FLAG_RESYNC, NULL, HFILL }}, |
1737 | 14 | { &hf_drbd_uuid_flag_reconnect, { "reconnect", "drbd.uuid_flag.reconnect", FT_BOOLEAN, 64, NULL, UUID_FLAG_RECONNECT, NULL, HFILL }}, |
1738 | 14 | { &hf_drbd_uuid_flag_diskless_primary, { "diskless_primary", "drbd.uuid_flag.diskless_primary", FT_BOOLEAN, 64, NULL, UUID_FLAG_DISKLESS_PRIMARY, NULL, HFILL }}, |
1739 | 14 | { &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 }}, |
1740 | | |
1741 | 14 | { &hf_drbd_dp_hardbarrier, { "hardbarrier", "drbd.dp_flag.hardbarrier", FT_BOOLEAN, 32, NULL, DP_HARDBARRIER, NULL, HFILL }}, |
1742 | 14 | { &hf_drbd_dp_rw_sync, { "rw_sync", "drbd.dp_flag.rw_sync", FT_BOOLEAN, 32, NULL, DP_RW_SYNC, NULL, HFILL }}, |
1743 | 14 | { &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 | 14 | { &hf_drbd_dp_unplug, { "unplug", "drbd.dp_flag.unplug", FT_BOOLEAN, 32, NULL, DP_UNPLUG, NULL, HFILL }}, |
1745 | 14 | { &hf_drbd_dp_fua, { "fua", "drbd.dp_flag.fua", FT_BOOLEAN, 32, NULL, DP_FUA, NULL, HFILL }}, |
1746 | 14 | { &hf_drbd_dp_flush, { "flush", "drbd.dp_flag.flush", FT_BOOLEAN, 32, NULL, DP_FLUSH, NULL, HFILL }}, |
1747 | 14 | { &hf_drbd_dp_discard, { "discard", "drbd.dp_flag.discard", FT_BOOLEAN, 32, NULL, DP_DISCARD, NULL, HFILL }}, |
1748 | 14 | { &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 | 14 | { &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 | 14 | { &hf_drbd_dp_wsame, { "wsame", "drbd.dp_flag.wsame", FT_BOOLEAN, 32, NULL, DP_WSAME, NULL, HFILL }}, |
1751 | 14 | { &hf_drbd_dp_zeroes, { "zeroes", "drbd.dp_flag.zeroes", FT_BOOLEAN, 32, NULL, DP_ZEROES, NULL, HFILL }}, |
1752 | 14 | }; |
1753 | | |
1754 | 14 | static hf_register_info hf_lb_tcp[] = { |
1755 | 14 | { &hf_drbd_lb_tcp_seq, { "lb-tcp sequence number", "drbd_lb_tcp.seq", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, |
1756 | 14 | { &hf_drbd_lb_tcp_length, { "lb-tcp length", "drbd_lb_tcp.length", FT_UINT32, BASE_HEX_DEC, NULL, 0x0, NULL, HFILL }}, |
1757 | 14 | }; |
1758 | | |
1759 | 14 | static int *ett[] = { |
1760 | 14 | &ett_drbd, |
1761 | 14 | &ett_drbd_lb_tcp, |
1762 | 14 | &ett_drbd_state, |
1763 | 14 | &ett_drbd_twopc_flags, |
1764 | 14 | &ett_drbd_uuid_flags, |
1765 | 14 | &ett_drbd_history_uuids, |
1766 | 14 | &ett_drbd_data_flags, |
1767 | 14 | }; |
1768 | | |
1769 | 14 | proto_drbd = proto_register_protocol("DRBD Protocol", "DRBD", "drbd"); |
1770 | 14 | proto_register_field_array(proto_drbd, hf, array_length(hf)); |
1771 | | |
1772 | 14 | proto_drbd_lb_tcp = proto_register_protocol("DRBD Load-Balanced Protocol", "DRBD lb-tcp", "drbd_lb_tcp"); |
1773 | 14 | proto_register_field_array(proto_drbd_lb_tcp, hf_lb_tcp, array_length(hf_lb_tcp)); |
1774 | | |
1775 | 14 | proto_register_subtree_array(ett, array_length(ett)); |
1776 | | |
1777 | 14 | drbd_handle = register_dissector("drbd", dissect_drbd, proto_drbd); |
1778 | 14 | drbd_lb_tcp_handle = register_dissector("drbd_lb_tcp", dissect_drbd_lb_tcp, proto_drbd_lb_tcp); |
1779 | 14 | } |
1780 | | |
1781 | | void proto_reg_handoff_drbd(void) |
1782 | 14 | { |
1783 | 14 | heur_dissector_add("tcp", test_drbd_protocol, "DRBD over TCP", "drbd_tcp", proto_drbd, HEURISTIC_DISABLE); |
1784 | 14 | heur_dissector_add("infiniband.payload", dissect_drbd_ib, "DRBD over RDMA", "drbd_rdma", proto_drbd, HEURISTIC_DISABLE); |
1785 | 14 | heur_dissector_add("tcp", test_drbd_lb_tcp_protocol, "DRBD Load-Balanced over TCP", "drbd_lb_tcp", proto_drbd_lb_tcp, HEURISTIC_DISABLE); |
1786 | 14 | } |
1787 | | |
1788 | | /* |
1789 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
1790 | | * |
1791 | | * Local variables: |
1792 | | * c-basic-offset: 4 |
1793 | | * tab-width: 8 |
1794 | | * indent-tabs-mode: nil |
1795 | | * End: |
1796 | | * |
1797 | | * vi: set shiftwidth=4 tabstop=8 expandtab: |
1798 | | * :indentSize=4:tabSize=8:noTabs=true: |
1799 | | */ |