@@ -193,6 +193,127 @@ static void test_invalid_crc(nvme_mi_ep_t ep)
193193 assert (rc != 0 );
194194}
195195
196+ /* test: simple NVMe admin request/response */
197+ static int test_admin_id_cb (struct nvme_mi_ep * ep ,
198+ struct nvme_mi_req * req ,
199+ struct nvme_mi_resp * resp ,
200+ void * data )
201+ {
202+ __u8 ror , mt , * hdr ;
203+ __u32 dlen , cdw10 ;
204+ __u16 ctrl_id ;
205+ __u8 flags ;
206+
207+ assert (req -> hdr -> type == NVME_MI_MSGTYPE_NVME );
208+
209+ ror = req -> hdr -> nmp >> 7 ;
210+ mt = req -> hdr -> nmp >> 3 & 0x7 ;
211+ assert (ror == NVME_MI_ROR_REQ );
212+ assert (mt == NVME_MI_MT_ADMIN );
213+
214+ /* do we have enough for a mi header? */
215+ assert (req -> hdr_len == sizeof (struct nvme_mi_admin_req_hdr ));
216+
217+ /* inspect response as raw bytes */
218+ hdr = (__u8 * )req -> hdr ;
219+ assert (hdr [4 ] == nvme_admin_identify );
220+ flags = hdr [5 ];
221+
222+ ctrl_id = hdr [7 ] << 8 | hdr [6 ];
223+ assert (ctrl_id == 0x5 ); /* controller id */
224+
225+ /* we requested a full id; if we've set the length flag,
226+ * ensure the length matches */
227+ dlen = hdr [35 ] << 24 | hdr [34 ] << 16 | hdr [33 ] << 8 | hdr [32 ];
228+ if (flags & 0x1 ) {
229+ assert (dlen == sizeof (struct nvme_id_ctrl ));
230+ }
231+ assert (!(flags & 0x2 ));
232+
233+ /* CNS value of 1 in cdw10 field */
234+ cdw10 = hdr [47 ] << 24 | hdr [46 ] << 16 | hdr [45 ] << 8 | hdr [44 ];
235+ assert (cdw10 == 0x1 );
236+
237+ /* create valid (but somewhat empty) response */
238+ hdr = (__u8 * )resp -> hdr ;
239+ memset (resp -> hdr , 0 , resp -> hdr_len );
240+ memset (resp -> data , 0 , resp -> data_len );
241+ hdr [4 ] = 0x00 ; /* status: success */
242+
243+ test_transport_resp_calc_mic (resp );
244+
245+ return 0 ;
246+ }
247+
248+ static void test_admin_id (nvme_mi_ep_t ep )
249+ {
250+ struct nvme_id_ctrl id ;
251+ nvme_mi_ctrl_t ctrl ;
252+ int rc ;
253+
254+ test_set_transport_callback (ep , test_admin_id_cb , NULL );
255+
256+ ctrl = nvme_mi_init_ctrl (ep , 5 );
257+ assert (ctrl );
258+
259+ rc = nvme_mi_admin_identify_ctrl (ctrl , & id );
260+ assert (rc == 0 );
261+ }
262+
263+ /* test: simple NVMe error response */
264+ static int test_admin_err_resp_cb (struct nvme_mi_ep * ep ,
265+ struct nvme_mi_req * req ,
266+ struct nvme_mi_resp * resp ,
267+ void * data )
268+ {
269+ __u8 ror , mt , * hdr ;
270+
271+ assert (req -> hdr -> type == NVME_MI_MSGTYPE_NVME );
272+
273+ ror = req -> hdr -> nmp >> 7 ;
274+ mt = req -> hdr -> nmp >> 3 & 0x7 ;
275+ assert (ror == NVME_MI_ROR_REQ );
276+ assert (mt == NVME_MI_MT_ADMIN );
277+
278+ /* do we have enough for a mi header? */
279+ assert (req -> hdr_len == sizeof (struct nvme_mi_admin_req_hdr ));
280+
281+ /* inspect response as raw bytes */
282+ hdr = (__u8 * )req -> hdr ;
283+ assert (hdr [4 ] == nvme_admin_identify );
284+
285+ /* we need at least 8 bytes for error information */
286+ assert (resp -> hdr_len >= 8 );
287+
288+ /* create error response */
289+ hdr = (__u8 * )resp -> hdr ;
290+ hdr [4 ] = 0x02 ; /* status: internal error */
291+ hdr [5 ] = 0 ;
292+ hdr [6 ] = 0 ;
293+ hdr [7 ] = 0 ;
294+ resp -> hdr_len = 8 ;
295+ resp -> data_len = 0 ;
296+
297+ test_transport_resp_calc_mic (resp );
298+
299+ return 0 ;
300+ }
301+
302+ static void test_admin_err_resp (nvme_mi_ep_t ep )
303+ {
304+ struct nvme_id_ctrl id ;
305+ nvme_mi_ctrl_t ctrl ;
306+ int rc ;
307+
308+ test_set_transport_callback (ep , test_admin_err_resp_cb , NULL );
309+
310+ ctrl = nvme_mi_init_ctrl (ep , 1 );
311+ assert (ctrl );
312+
313+ rc = nvme_mi_admin_identify_ctrl (ctrl , & id );
314+ assert (rc != 0 );
315+ }
316+
196317#define DEFINE_TEST (name ) { #name, test_ ## name }
197318struct test {
198319 const char * name ;
@@ -201,6 +322,8 @@ struct test {
201322 DEFINE_TEST (read_mi_data ),
202323 DEFINE_TEST (transport_fail ),
203324 DEFINE_TEST (invalid_crc ),
325+ DEFINE_TEST (admin_id ),
326+ DEFINE_TEST (admin_err_resp ),
204327};
205328
206329static void print_log_buf (FILE * logfd )
0 commit comments