2 * Routines for NVMe Management Interface (NVMe-MI), over MCTP
3 * Copyright 2022, Jeremy Kerr <jk@codeconstruct.com.au>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
12 /* NVMe is defined by the NVM Express Management Interface standard,
13 * athttps://nvmexpress.org/developers/nvme-mi-specification/
18 #include <epan/conversation.h>
19 #include <epan/crc32-tvb.h>
20 #include <epan/packet.h>
22 #include <wsutil/array.h>
23 #include "packet-mctp.h"
25 void proto_register_nvme_mi(void);
26 void proto_reg_handoff_nvme_mi(void);
28 static int proto_nvme_mi
;
30 static int hf_nvme_mi_mctp_mt
;
31 static int hf_nvme_mi_mctp_ic
;
32 static int hf_nvme_mi_csi
;
33 static int hf_nvme_mi_type
;
34 static int hf_nvme_mi_ror
;
35 static int hf_nvme_mi_meb
;
36 static int hf_nvme_mi_mic
;
38 static int hf_nvme_mi_mi_opcode
;
39 static int hf_nvme_mi_mi_cdw0
;
40 static int hf_nvme_mi_mi_cdw1
;
41 static int hf_nvme_mi_mi_status
;
42 static int hf_nvme_mi_mi_nmresp
;
43 static int hf_nvme_mi_mi_data
;
45 static int hf_nvme_mi_admin_opcode
;
46 static int hf_nvme_mi_admin_status
;
47 static int hf_nvme_mi_admin_flags
;
48 static int hf_nvme_mi_admin_flags_doff
;
49 static int hf_nvme_mi_admin_flags_dlen
;
50 static int hf_nvme_mi_admin_ctrl_id
;
51 static int hf_nvme_mi_admin_sqe1
;
52 static int hf_nvme_mi_admin_sqe2
;
53 static int hf_nvme_mi_admin_sqe3
;
54 static int hf_nvme_mi_admin_sqe4
;
55 static int hf_nvme_mi_admin_sqe5
;
56 static int hf_nvme_mi_admin_doff
;
57 static int hf_nvme_mi_admin_dlen
;
58 static int hf_nvme_mi_admin_resv0
;
59 static int hf_nvme_mi_admin_resv1
;
60 static int hf_nvme_mi_admin_sqe10
;
61 static int hf_nvme_mi_admin_sqe11
;
62 static int hf_nvme_mi_admin_sqe12
;
63 static int hf_nvme_mi_admin_sqe13
;
64 static int hf_nvme_mi_admin_sqe14
;
65 static int hf_nvme_mi_admin_sqe15
;
66 static int hf_nvme_mi_admin_data
;
67 static int hf_nvme_mi_admin_cqe1
;
68 static int hf_nvme_mi_admin_cqe2
;
69 static int hf_nvme_mi_admin_cqe3
;
71 static int hf_nvme_mi_response_in
;
72 static int hf_nvme_mi_response_to
;
73 static int hf_nvme_mi_response_time
;
76 static int ett_nvme_mi
;
77 static int ett_nvme_mi_hdr
;
78 static int ett_nvme_mi_mi
;
79 static int ett_nvme_mi_admin
;
80 static int ett_nvme_mi_admin_flags
;
83 NVME_MI_TYPE_CONTROL
= 0x0,
84 NVME_MI_TYPE_MI
= 0x1,
85 NVME_MI_TYPE_ADMIN
= 0x2,
86 NVME_MI_TYPE_PCIE
= 0x4,
89 struct nvme_mi_command
{
91 enum nvme_mi_type type
;
98 struct nvme_mi_conv_info
{
99 struct nvme_mi_command command_slots
[2];
102 static const value_string mi_mctp_type_vals
[] = {
107 static const value_string mi_type_vals
[] = {
108 { NVME_MI_TYPE_CONTROL
, "Control primitive" },
109 { NVME_MI_TYPE_MI
, "MI command" },
110 { NVME_MI_TYPE_ADMIN
, "NVMe Admin command" },
111 { NVME_MI_TYPE_PCIE
, "PCIe command" },
115 static const value_string mi_opcode_vals
[] = {
116 { 0x00, "Read NVMe-MI Data Structure" },
117 { 0x01, "NVM Subsystem Health Status Poll" },
118 { 0x02, "Controller Health Status Poll" },
119 { 0x03, "Configuration Set" },
120 { 0x04, "Configuration Get" },
124 static const value_string admin_opcode_vals
[] = {
125 { 0x00, "Delete I/O Submission Queue" },
126 { 0x01, "Create I/O Submission Queue" },
127 { 0x02, "Get Log Page" },
128 { 0x04, "Delete I/O Completion Queue" },
129 { 0x05, "Create I/O Completion Queue" },
130 { 0x06, "Identify" },
131 { 0x09, "Set Features" },
132 { 0x0a, "Get Features" },
133 { 0x0d, "Namespace Management" },
134 { 0x10, "Firmware Commit" },
135 { 0x11, "Firmware Image Download" },
136 { 0x80, "Format NVM" },
137 { 0x81, "Security Send" },
138 { 0x82, "Security Receive" },
142 static const true_false_string tfs_meb
= { "data in MEB", "data in message" };
145 dissect_nvme_mi_mi(tvbuff_t
*tvb
, bool resp
, struct nvme_mi_command
*cmd
,
148 proto_item
*it
, *it2
;
151 it
= proto_tree_add_item(tree
, proto_nvme_mi
, tvb
, 0, -1, ENC_NA
);
152 mi_tree
= proto_item_add_subtree(it
, ett_nvme_mi_mi
);
155 proto_tree_add_item_ret_uint(mi_tree
, hf_nvme_mi_mi_opcode
,
156 tvb
, 0, 1, ENC_NA
, &cmd
->opcode
);
158 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_cdw0
,
159 tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
160 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_cdw1
,
161 tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
163 if (tvb_reported_length(tvb
) > 12)
164 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_data
,
165 tvb
, 12, -1, ENC_NA
);
167 it2
= proto_tree_add_uint(mi_tree
, hf_nvme_mi_mi_opcode
,
168 tvb
, 0, 0, cmd
->opcode
);
169 proto_item_set_generated(it2
);
171 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_status
,
173 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_nmresp
,
174 tvb
, 1, 3, ENC_LITTLE_ENDIAN
);
176 if (tvb_reported_length(tvb
) > 4)
177 proto_tree_add_item(mi_tree
, hf_nvme_mi_mi_data
,
185 dissect_nvme_mi_admin(tvbuff_t
*tvb
, bool resp
, struct nvme_mi_command
*cmd
,
188 proto_tree
*admin_tree
;
189 proto_item
*it
, *it2
;
191 it
= proto_tree_add_item(tree
, proto_nvme_mi
, tvb
, 0, -1, ENC_NA
);
192 admin_tree
= proto_item_add_subtree(it
, ett_nvme_mi_admin
);
194 proto_item_set_text(it
, "NVMe Admin %s",
195 resp
? "response" : "request");
198 it2
= proto_tree_add_uint(admin_tree
, hf_nvme_mi_admin_opcode
,
199 tvb
, 0, 0, cmd
->opcode
);
200 proto_item_set_generated(it2
);
202 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_status
,
205 if (tvb_reported_length(tvb
) >= 16) {
206 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_cqe1
,
207 tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
208 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_cqe2
,
209 tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
210 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_cqe3
,
211 tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
214 if (tvb_reported_length(tvb
) > 16)
215 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_data
,
216 tvb
, 16, -1, ENC_NA
);
218 static int * const nvme_mi_admin_flags
[] = {
219 &hf_nvme_mi_admin_flags_doff
,
220 &hf_nvme_mi_admin_flags_dlen
,
224 proto_tree_add_item_ret_uint(admin_tree
, hf_nvme_mi_admin_opcode
,
225 tvb
, 0, 1, ENC_NA
, &cmd
->opcode
);
227 proto_tree_add_bitmask(admin_tree
, tvb
, 1, hf_nvme_mi_admin_flags
,
228 ett_nvme_mi_admin_flags
, nvme_mi_admin_flags
,
231 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_ctrl_id
,
232 tvb
, 2, 2, ENC_LITTLE_ENDIAN
);
233 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe1
,
234 tvb
, 4, 4, ENC_LITTLE_ENDIAN
);
235 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe2
,
236 tvb
, 8, 4, ENC_LITTLE_ENDIAN
);
237 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe3
,
238 tvb
, 12, 4, ENC_LITTLE_ENDIAN
);
239 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe4
,
240 tvb
, 16, 4, ENC_LITTLE_ENDIAN
);
241 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe5
,
242 tvb
, 20, 4, ENC_LITTLE_ENDIAN
);
243 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_doff
,
244 tvb
, 24, 4, ENC_LITTLE_ENDIAN
);
245 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_dlen
,
246 tvb
, 28, 4, ENC_LITTLE_ENDIAN
);
247 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_resv0
,
248 tvb
, 32, 4, ENC_LITTLE_ENDIAN
);
249 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_resv1
,
250 tvb
, 36, 4, ENC_LITTLE_ENDIAN
);
251 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe10
,
252 tvb
, 40, 4, ENC_LITTLE_ENDIAN
);
253 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe11
,
254 tvb
, 44, 4, ENC_LITTLE_ENDIAN
);
255 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe12
,
256 tvb
, 48, 4, ENC_LITTLE_ENDIAN
);
257 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe13
,
258 tvb
, 52, 4, ENC_LITTLE_ENDIAN
);
259 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe14
,
260 tvb
, 56, 4, ENC_LITTLE_ENDIAN
);
261 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_sqe15
,
262 tvb
, 60, 4, ENC_LITTLE_ENDIAN
);
264 if (tvb_reported_length(tvb
) > 64)
265 proto_tree_add_item(admin_tree
, hf_nvme_mi_admin_data
,
266 tvb
, 64, -1, ENC_NA
);
273 dissect_nvme_mi(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
276 proto_tree
*nvme_mi_tree
, *nvme_mi_hdr_tree
;
277 struct nvme_mi_conv_info
*mi_conv
;
278 unsigned len
, payload_len
, type
;
279 bool resp
, mic_enabled
;
280 proto_item
*ti
, *it2
;
281 conversation_t
*conv
;
286 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "NVMe-MI");
287 col_clear(pinfo
->cinfo
, COL_INFO
);
289 /* Check that the packet is long enough for it to belong to us. */
290 len
= tvb_reported_length(tvb
);
293 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Bogus length %u, minimum %u",
295 return tvb_captured_length(tvb
);
298 ti
= proto_tree_add_item(tree
, proto_nvme_mi
, tvb
, 0, -1, ENC_NA
);
299 nvme_mi_tree
= proto_item_add_subtree(ti
, ett_nvme_mi
);
301 ti
= proto_tree_add_item(nvme_mi_tree
, proto_nvme_mi
, tvb
, 0, 4, ENC_NA
);
302 proto_item_set_text(ti
, "NVMe-MI header");
303 nvme_mi_hdr_tree
= proto_item_add_subtree(ti
, ett_nvme_mi_hdr
);
305 proto_tree_add_item(nvme_mi_hdr_tree
, hf_nvme_mi_mctp_mt
,
306 tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
308 proto_tree_add_item_ret_boolean(nvme_mi_hdr_tree
, hf_nvme_mi_mctp_ic
,
309 tvb
, 0, 4, ENC_LITTLE_ENDIAN
, &mic_enabled
);
311 proto_tree_add_item_ret_uint(nvme_mi_hdr_tree
, hf_nvme_mi_csi
,
312 tvb
, 0, 4, ENC_LITTLE_ENDIAN
, &csi
);
314 proto_tree_add_item_ret_uint(nvme_mi_hdr_tree
, hf_nvme_mi_type
,
315 tvb
, 0, 4, ENC_LITTLE_ENDIAN
, &type
);
317 proto_tree_add_item_ret_boolean(nvme_mi_hdr_tree
, hf_nvme_mi_ror
,
318 tvb
, 0, 4, ENC_LITTLE_ENDIAN
, &resp
);
320 proto_tree_add_item(nvme_mi_hdr_tree
, hf_nvme_mi_meb
,
321 tvb
, 0, 4, ENC_LITTLE_ENDIAN
);
323 payload_len
= tvb_reported_length(tvb
) - 4;
325 mic
= ~crc32c_tvb_offset_calculate(tvb
, 0, payload_len
, 0xffffffff);
329 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "NVMe-MI %s %s",
330 val_to_str_const(type
, mi_type_vals
, "command"),
331 tfs_get_string(resp
, &tfs_response_request
));
333 conv
= find_or_create_conversation(pinfo
);
334 mi_conv
= conversation_get_proto_data(conv
, proto_nvme_mi
);
336 mi_conv
= wmem_new0(wmem_file_scope(), struct nvme_mi_conv_info
);
337 conversation_add_proto_data(conv
, proto_nvme_mi
, mi_conv
);
340 struct nvme_mi_command
*cmd
= &mi_conv
->command_slots
[csi
];
343 if (cmd
->req_frame
) {
346 nstime_delta(&ns
, &pinfo
->fd
->abs_ts
, &cmd
->req_time
);
348 it2
= proto_tree_add_uint(nvme_mi_tree
, hf_nvme_mi_response_to
,
349 tvb
, 0, 0, cmd
->req_frame
);
350 proto_item_set_generated(it2
);
351 it2
= proto_tree_add_time(nvme_mi_tree
, hf_nvme_mi_response_time
,
353 proto_item_set_generated(it2
);
355 /* TODO: no request frame available? */
357 cmd
->resp_frame
= pinfo
->num
;
360 if (cmd
->resp_frame
) {
361 it2
= proto_tree_add_uint(nvme_mi_tree
, hf_nvme_mi_response_in
,
362 tvb
, 0, 0, cmd
->resp_frame
);
363 proto_item_set_generated(it2
);
368 cmd
->req_frame
= pinfo
->num
;
369 cmd
->req_time
= pinfo
->fd
->abs_ts
;
372 sub_tvb
= tvb_new_subset_length(tvb
, 4, payload_len
);
375 case NVME_MI_TYPE_MI
:
376 dissect_nvme_mi_mi(sub_tvb
, resp
, cmd
, nvme_mi_tree
);
378 case NVME_MI_TYPE_ADMIN
:
379 dissect_nvme_mi_admin(sub_tvb
, resp
, cmd
, nvme_mi_tree
);
386 proto_tree_add_checksum(nvme_mi_tree
, tvb
, payload_len
+ 4,
387 hf_nvme_mi_mic
, -1, NULL
, pinfo
, mic
,
388 ENC_BIG_ENDIAN
, PROTO_CHECKSUM_VERIFY
);
390 return tvb_captured_length(tvb
);
394 proto_register_nvme_mi(void)
397 /* Field definitions */
398 static hf_register_info hf
[] = {
400 { &hf_nvme_mi_mctp_mt
,
401 { "MCTP message type", "nvme-mi.mctp-mt",
402 FT_UINT32
, BASE_HEX
, VALS(mi_mctp_type_vals
), 0x7f,
405 { &hf_nvme_mi_mctp_ic
,
406 { "MCTP IC", "nvme-mi.mctp-ic",
407 FT_BOOLEAN
, 32, NULL
, 0x00000080,
411 { "CSI", "nvme-mi.csi",
412 FT_UINT32
, BASE_DEC
, NULL
, 0x00000100,
416 { "Type", "nvme-mi.type",
417 FT_UINT32
, BASE_HEX
, VALS(mi_type_vals
), 0x00007800,
421 { "ROR", "nvme-mi.ror",
422 FT_BOOLEAN
, 32, TFS(&tfs_response_request
), 0x00008000,
426 { "MEB", "nvme-mi.meb",
427 FT_BOOLEAN
, 32, TFS(&tfs_meb
), 0x00010000,
431 { "Message Integrity Check", "nvme-mi.mic",
432 FT_UINT32
, BASE_HEX
, NULL
, 0,
437 { &hf_nvme_mi_response_in
,
438 { "Response In", "nvme-mi.response_in",
439 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE
), 0x0,
440 "The response to this NVMe-MI request is in this frame", HFILL
}
442 { &hf_nvme_mi_response_to
,
443 { "Request In", "nvme-mi.response_to",
444 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST
), 0x0,
445 "This is a response to the NVMe-MI request in this frame", HFILL
}
447 { &hf_nvme_mi_response_time
,
448 { "Response Time", "nvme-mi.response_time",
449 FT_RELATIVE_TIME
, BASE_NONE
, NULL
, 0x0,
450 "The time between the request and the response", HFILL
}
454 { &hf_nvme_mi_mi_opcode
,
455 { "Opcode", "nvme-mi.mi.opcode",
456 FT_UINT8
, BASE_HEX
, VALS(mi_opcode_vals
), 0,
459 { &hf_nvme_mi_mi_cdw0
,
460 { "Command dword 0", "nvme-mi.mi.cdw0",
461 FT_UINT32
, BASE_HEX
, NULL
, 0,
464 { &hf_nvme_mi_mi_cdw1
,
465 { "Command dword 1", "nvme-mi.mi.cdw1",
466 FT_UINT32
, BASE_HEX
, NULL
, 0,
469 { &hf_nvme_mi_mi_status
,
470 { "Status", "nvme-mi.mi.status",
471 FT_UINT8
, BASE_HEX
, NULL
, 0,
474 { &hf_nvme_mi_mi_nmresp
,
475 { "Management Response", "nvme-mi.mi.nmresp",
476 FT_UINT24
, BASE_HEX
, NULL
, 0,
479 { &hf_nvme_mi_mi_data
,
480 { "Data", "nvme-mi.mi.data",
481 FT_BYTES
, SEP_SPACE
, NULL
, 0,
486 { &hf_nvme_mi_admin_opcode
,
487 { "Opcode", "nvme-mi.admin.opcode",
488 FT_UINT8
, BASE_HEX
, VALS(admin_opcode_vals
), 0,
491 { &hf_nvme_mi_admin_status
,
492 { "Status", "nvme-mi.admin.status",
493 FT_UINT8
, BASE_HEX
, NULL
, 0,
496 { &hf_nvme_mi_admin_flags
,
497 { "Command Flags", "nvme-mi.admin.flags",
498 FT_UINT8
, BASE_HEX
, NULL
, 0,
501 { &hf_nvme_mi_admin_flags_dlen
,
502 { "Use Data Length", "nvme-mi.admin.flags.dlen",
503 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x1,
506 { &hf_nvme_mi_admin_flags_doff
,
507 { "Use Data Offset", "nvme-mi.admin.flags.doff",
508 FT_BOOLEAN
, 8, TFS(&tfs_set_notset
), 0x2,
511 { &hf_nvme_mi_admin_ctrl_id
,
512 { "Controller ID", "nvme-mi.admin.ctrl-id",
513 FT_UINT16
, BASE_HEX
, NULL
, 0,
516 { &hf_nvme_mi_admin_sqe1
,
517 { "Submission Queue Entry dword 1", "nvme-mi.admin.sqe1",
518 FT_UINT32
, BASE_HEX
, NULL
, 0,
521 { &hf_nvme_mi_admin_sqe2
,
522 { "Submission Queue Entry dword 2", "nvme-mi.admin.sqe2",
523 FT_UINT32
, BASE_HEX
, NULL
, 0,
526 { &hf_nvme_mi_admin_sqe3
,
527 { "Submission Queue Entry dword 3", "nvme-mi.admin.sqe3",
528 FT_UINT32
, BASE_HEX
, NULL
, 0,
531 { &hf_nvme_mi_admin_sqe4
,
532 { "Submission Queue Entry dword 4", "nvme-mi.admin.sqe4",
533 FT_UINT32
, BASE_HEX
, NULL
, 0,
536 { &hf_nvme_mi_admin_sqe5
,
537 { "Submission Queue Entry dword 5", "nvme-mi.admin.sqe5",
538 FT_UINT32
, BASE_HEX
, NULL
, 0,
541 { &hf_nvme_mi_admin_doff
,
542 { "Data Offset", "nvme-mi.admin.doff",
543 FT_UINT32
, BASE_HEX
, NULL
, 0,
546 { &hf_nvme_mi_admin_dlen
,
547 { "Data Length", "nvme-mi.admin.dlen",
548 FT_UINT32
, BASE_HEX
, NULL
, 0,
551 { &hf_nvme_mi_admin_resv0
,
552 { "Reserved", "nvme-mi.admin.reserved",
553 FT_UINT32
, BASE_HEX
, NULL
, 0,
556 { &hf_nvme_mi_admin_resv1
,
557 { "Reserved", "nvme-mi.admin.reserved",
558 FT_UINT32
, BASE_HEX
, NULL
, 0,
561 { &hf_nvme_mi_admin_sqe10
,
562 { "Submission Queue Entry dword 10", "nvme-mi.admin.sqe10",
563 FT_UINT32
, BASE_HEX
, NULL
, 0,
566 { &hf_nvme_mi_admin_sqe11
,
567 { "Submission Queue Entry dword 11", "nvme-mi.admin.sqe11",
568 FT_UINT32
, BASE_HEX
, NULL
, 0,
571 { &hf_nvme_mi_admin_sqe12
,
572 { "Submission Queue Entry dword 12", "nvme-mi.admin.sqe12",
573 FT_UINT32
, BASE_HEX
, NULL
, 0,
576 { &hf_nvme_mi_admin_sqe13
,
577 { "Submission Queue Entry dword 13", "nvme-mi.admin.sqe13",
578 FT_UINT32
, BASE_HEX
, NULL
, 0,
581 { &hf_nvme_mi_admin_sqe14
,
582 { "Submission Queue Entry dword 14", "nvme-mi.admin.sqe14",
583 FT_UINT32
, BASE_HEX
, NULL
, 0,
586 { &hf_nvme_mi_admin_sqe15
,
587 { "Submission Queue Entry dword 15", "nvme-mi.admin.sqe15",
588 FT_UINT32
, BASE_HEX
, NULL
, 0,
591 { &hf_nvme_mi_admin_cqe1
,
592 { "Completion Queue Entry dword 1", "nvme-mi.admin.cqe1",
593 FT_UINT32
, BASE_HEX
, NULL
, 0,
596 { &hf_nvme_mi_admin_cqe2
,
597 { "Completion Queue Entry dword 2", "nvme-mi.admin.cqe2",
598 FT_UINT32
, BASE_HEX
, NULL
, 0,
601 { &hf_nvme_mi_admin_cqe3
,
602 { "Completion Queue Entry dword 3", "nvme-mi.admin.cqe3",
603 FT_UINT32
, BASE_HEX
, NULL
, 0,
606 { &hf_nvme_mi_admin_data
,
607 { "Data", "nvme-mi.admin.data",
608 FT_BYTES
, SEP_SPACE
, NULL
, 0,
613 /* protocol subtree */
614 static int *ett
[] = {
619 &ett_nvme_mi_admin_flags
,
622 proto_nvme_mi
= proto_register_protocol("NVMe-MI", "NVMe-MI", "nvme-mi");
624 proto_register_field_array(proto_nvme_mi
, hf
, array_length(hf
));
625 proto_register_subtree_array(ett
, array_length(ett
));
629 proto_reg_handoff_nvme_mi(void)
631 dissector_handle_t nvme_mi_handle
;
632 nvme_mi_handle
= create_dissector_handle(dissect_nvme_mi
, proto_nvme_mi
);
633 dissector_add_uint("mctp.type", MCTP_TYPE_NVME
, nvme_mi_handle
);
637 * Editor modelines - https://www.wireshark.org/tools/modelines.html
642 * indent-tabs-mode: nil
645 * vi: set shiftwidth=4 tabstop=8 expandtab:
646 * :indentSize=4:tabSize=8:noTabs=true: