Wireshark 4.7.3
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
packet-nvme-mi.h
1/* packet-nvme-mi.h
2 * Shared types for NVMe Management Interface (NVMe-MI) dissectors
3 * Copyright 2026, Brandon Chiu
4 *
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <[email protected]>
7 * Copyright 1998 Gerald Combs
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12#ifndef __PACKET_NVME_MI_H__
13#define __PACKET_NVME_MI_H__
14
15#include <epan/packet.h>
16
17/* NVMe-MI Message Type (NMIMT) values — NVMe-MI 2.1 Figure 20.
18 * 3h and 6h-Fh are Reserved. */
19enum nvme_mi_msg_type {
20 NVME_MI_TYPE_CONTROL = 0x0,
21 NVME_MI_TYPE_MI = 0x1,
22 NVME_MI_TYPE_ADMIN = 0x2,
23 NVME_MI_TYPE_PCIE = 0x4,
24 NVME_MI_TYPE_AEM = 0x5, /* Asynchronous Event Message (§4.1.3) */
25};
26
27/*
28 * Response Message Status values (NVMe-MI 2.1 Figure 29). The status byte is
29 * common to every response message type, so the table is shared by all the
30 * per-type body dissectors. Defined in packet-nvme-mi.c.
31 */
32extern const value_string nvme_mi_status_vals[];
33
34/*
35 * NVMe-MI Message Type (NMIMT) names (NVMe-MI 2.1 Figure 12). Defined in
36 * packet-nvme-mi.c and shared so the command-list entry decode (which carries
37 * an NMIMT in each entry) renders the same names as the message header.
38 */
39extern const value_string mi_type_vals[];
40
41/* Status values the body dissectors branch on (subset of status values). */
42#define NVME_MI_STATUS_SUCCESS 0x00
43#define NVME_MI_STATUS_MORE_PROCESSING_REQUIRED 0x01
44#define NVME_MI_STATUS_INVALID_PARAMETER 0x04
45
46/*
47 * Decode payload bytes 3:1 of a Response Message according to its Response
48 * Message Status. Those bytes are status-dependent and mutually exclusive:
49 * the Parameter Error Location on an Invalid Parameter Error Response
50 * (NVMe-MI 2.1 Figure 32), the More Processing Required Time on a More
51 * Processing Required Response (Figure 34), and Reserved on any other Error
52 * Response (Figure 30). Only a Success Response gives them a command-specific
53 * meaning, so this returns true in that case alone and the caller renders the
54 * bytes itself (the MI NVMe Management Response, the Admin reserved dwords).
55 *
56 * The error-response formats are defined at the message level and shared by
57 * every command message type, so the MI/Admin/PCIe body dissectors all call
58 * this rather than each decoding them -- and none of them mislabels an error
59 * response's bytes as command-specific. The caller must have at least 4
60 * payload bytes. Defined in packet-nvme-mi.c.
61 */
62bool nvme_mi_dissect_resp_status_bytes(tvbuff_t *tvb, proto_tree *tree,
63 uint8_t status);
64
65/*
66 * Flag a truncated/short payload via the given expert field and render any
67 * bytes remaining from `off` raw under `hf_data`. Shared by the body
68 * dissectors so the "expert + leftover bytes" rendering is defined once.
69 * Defined in packet-nvme-mi.c.
70 */
71void nvme_mi_dissect_truncated(tvbuff_t *tvb, packet_info *pinfo,
72 proto_tree *tree, proto_item *it,
73 expert_field *ei, int hf_data, int off);
74
75/*
76 * Per-transaction state shared across the request frame and every response
77 * frame (including MPR interim responses) that belongs to the same command.
78 * Allocated in wmem_file_scope().
79 *
80 * The per-type fields below are owned by the body dissector, not the framing
81 * layer: the body dissector fills them in while dissecting the request and
82 * reads them back when the matching response is dissected (the response
83 * carries no opcode of its own). 'opcode' is the per-type opcode (CP CPO /
84 * MI opcode / Admin opcode); any further per-type request state lives behind
85 * 'body_ctx'.
86 */
88 uint32_t req_frame;
89 uint32_t resp_frame; /* 0 until a non-MPR response is seen */
90 nstime_t req_time;
91 /*
92 * true once the request 'opcode' (the command byte at payload offset 0)
93 * has been recorded: by the always-run framing layer for Admin/MI Command
94 * Messages, or by the Control body once past its >= 4-byte guard. Stays
95 * false when the request was too short to record an opcode; the response
96 * side must then treat the opcode as unknown (zero-filled, not observed)
97 * rather than interpreting it. Independent of body_ctx, which the body
98 * dissector populates separately and which may be NULL even when
99 * req_parsed is true (e.g. an Admin request truncated below its 64-byte
100 * SQE, or a disabled body protocol).
101 */
102 bool req_parsed;
103 /*
104 * NMIMT of the request that owns 'opcode' and 'body_ctx'. ADMIN and MI
105 * requests share the same per-CSI command slot, so a response of one type
106 * can land on a slot opened by a request of the other type; the response
107 * side must check this matches its own NMIMT before trusting opcode or
108 * casting body_ctx. Set by the framing layer when the request is seen.
109 */
110 uint8_t nmimt;
111 unsigned opcode;
112 /*
113 * Opaque per-opcode request context, owned entirely by the body
114 * dissector that handles this transaction's NMIMT (the framing layer
115 * never looks inside). Allocated in wmem_file_scope() while dissecting
116 * the request and read back when dissecting the matching response(s),
117 * for request parameters that select the response layout or that the
118 * response must echo (e.g. the MI Read NVMe-MI Data Structure DTYP, the
119 * Configuration Set/Get CONFIGID, or the Control Primitive tag). NULL
120 * when the request did not carry those fields (truncated) or no request
121 * was seen.
122 */
123 void *body_ctx;
124};
125
126/*
127 * Passed as the 'data' void-pointer through the "nvme-mi.type" dissector
128 * table so each sub-dissector receives request/response context without
129 * needing a global. The framing layer always passes a valid pointer, but
130 * the table is globally registered and external callers (e.g. Lua scripts
131 * driving it directly) may pass NULL, so sub-dissectors must reject a NULL
132 * data pointer:
133 *
134 * if (!data) return 0;
135 *
136 * trans may be NULL when no matching request has been seen yet.
137 */
139 bool resp;
140 struct nvme_mi_transaction *trans;
141};
142
143/*
144 * Response opcode recovery, shared by the command-message body dissectors. A
145 * response carries no opcode of its own, so it must be recovered from the
146 * matching request. When 'trans' is a parsed request of NMIMT 'nmimt', adds a
147 * generated 'hf_opcode' item carrying the recovered opcode (returned via
148 * '*opcode'), and returns that proto_item so the caller can append a name.
149 * Otherwise (no request, truncated request, or a request of a different
150 * NMIMT that happens to share the slot) fires 'ei_orphan' against 'it' and
151 * returns NULL with '*opcode' set to 0. Defined in packet-nvme-mi.c.
152 */
153proto_item *nvme_mi_recover_resp_opcode(tvbuff_t *tvb, packet_info *pinfo,
154 proto_tree *tree, proto_item *it,
155 const struct nvme_mi_transaction *trans,
156 uint8_t nmimt, int hf_opcode,
157 expert_field *ei_orphan,
158 unsigned *opcode);
159
160/*
161 * Return the transaction's per-opcode request context, allocating it (zeroed,
162 * 'size' bytes, wmem_file_scope) on first use. Lets each body dissector store
163 * its own struct in trans->body_ctx without repeating the allocate-once
164 * idiom. 'trans' must be non-NULL. Defined in packet-nvme-mi.c.
165 */
166void *nvme_mi_trans_body_ctx(struct nvme_mi_transaction *trans, size_t size);
167
168#endif /* __PACKET_NVME_MI_H__ */
169
170/*
171 * Editor modelines - https://www.wireshark.org/tools/modelines.html
172 *
173 * Local variables:
174 * c-basic-offset: 4
175 * tab-width: 8
176 * indent-tabs-mode: nil
177 * End:
178 *
179 * vi: set shiftwidth=4 tabstop=8 expandtab:
180 * :indentSize=4:tabSize=8:noTabs=true:
181 */
struct _packet_info packet_info
Represents the metadata and indexing information for a single captured frame.
proto_node proto_item
Definition proto.h:927
Pairs an expert info index with its associated header field index for registration and display.
Definition expert.h:41
Definition nstime.h:26
Definition packet-nvme-mi.h:138
Definition packet-nvme-mi.h:87
struct _value_string value_string
Mapping between a 32-bit integer value and its string representation.