xref: /spdk/include/spdk/nvmf_fc_spec.h (revision da6841e4509a8eec7972dfe154ea9f13d09d9be1)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2019 Intel Corporation.
3  *   Copyright (c) 2018-2019 Broadcom.  All Rights Reserved.
4  *   The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
5  */
6 
7 #ifndef __NVMF_FC_SPEC_H__
8 #define __NVMF_FC_SPEC_H__
9 
10 #include "spdk/env.h"
11 #include "spdk/nvme.h"
12 
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 
17 /*
18  * FC-NVMe Spec. Definitions
19  */
20 
21 #define FCNVME_R_CTL_CMD_REQ                   0x06
22 #define FCNVME_R_CTL_DATA_OUT                  0x01
23 #define FCNVME_R_CTL_CONFIRM                   0x03
24 #define FCNVME_R_CTL_STATUS                    0x07
25 #define FCNVME_R_CTL_ERSP_STATUS               0x08
26 #define FCNVME_R_CTL_LS_REQUEST                0x32
27 #define FCNVME_R_CTL_LS_RESPONSE               0x33
28 #define FCNVME_R_CTL_BA_ABTS                   0x81
29 
30 #define FCNVME_F_CTL_END_SEQ                   0x080000
31 #define FCNVME_F_CTL_SEQ_INIT                  0x010000
32 
33 /* END_SEQ | LAST_SEQ | Exchange Responder | SEQ init */
34 #define FCNVME_F_CTL_RSP                       0x990000
35 #define FCNVME_F_CTL_PRIORITY_ENABLE           0x020000
36 
37 #define FCNVME_D_FCTL_DEVICE_HDR_16_MASK       0x1
38 #define FCNVME_D_FCTL_NETWORK_HDR_MASK         0x20
39 #define FCNVME_D_FCTL_NETWORK_HDR_SIZE         16
40 #define FCNVME_D_FCTL_ESP_HDR_MASK             0x40
41 #define FCNVME_D_FCTL_ESP_HDR_SIZE             8
42 
43 #define FCNVME_TYPE_BLS                        0x0
44 #define FCNVME_TYPE_FC_EXCHANGE                0x08
45 #define FCNVME_TYPE_NVMF_DATA                  0x28
46 
47 #define FCNVME_CMND_IU_FC_ID                   0x28
48 #define FCNVME_CMND_IU_SCSI_ID                 0xFD
49 
50 #define FCNVME_CMND_IU_NODATA                  0x00
51 #define FCNVME_CMND_IU_READ                    0x10
52 #define FCNVME_CMND_IU_WRITE                   0x01
53 
54 /* BLS reject error codes */
55 #define FCNVME_BLS_REJECT_UNABLE_TO_PERFORM    0x09
56 #define FCNVME_BLS_REJECT_EXP_NOINFO           0x00
57 #define FCNVME_BLS_REJECT_EXP_INVALID_OXID     0x03
58 
59 /*
60  * FC NVMe Link Services (LS) constants
61  */
62 #define FCNVME_MAX_LS_REQ_SIZE                  1536
63 #define FCNVME_MAX_LS_RSP_SIZE                  64
64 
65 #define FCNVME_LS_CA_CMD_MIN_LEN                592
66 #define FCNVME_LS_CA_DESC_LIST_MIN_LEN          584
67 #define FCNVME_LS_CA_DESC_MIN_LEN               576
68 
69 /* this value needs to be in sync with low level driver buffer size */
70 #define FCNVME_MAX_LS_BUFFER_SIZE               2048
71 
72 #define FCNVME_GOOD_RSP_LEN                     12
73 #define FCNVME_ASSOC_HOSTID_LEN                 16
74 
75 
76 typedef uint64_t FCNVME_BE64;
77 typedef uint32_t FCNVME_BE32;
78 typedef uint16_t FCNVME_BE16;
79 
80 /*
81  * FC-NVME LS Commands
82  */
83 enum {
84 	FCNVME_LS_RSVD                = 0,
85 	FCNVME_LS_RJT                 = 1,
86 	FCNVME_LS_ACC                 = 2,
87 	FCNVME_LS_CREATE_ASSOCIATION  = 3,
88 	FCNVME_LS_CREATE_CONNECTION	  = 4,
89 	FCNVME_LS_DISCONNECT          = 5,
90 };
91 
92 /*
93  * FC-NVME Link Service Descriptors
94  */
95 enum {
96 	FCNVME_LSDESC_RSVD             = 0x0,
97 	FCNVME_LSDESC_RQST             = 0x1,
98 	FCNVME_LSDESC_RJT              = 0x2,
99 	FCNVME_LSDESC_CREATE_ASSOC_CMD = 0x3,
100 	FCNVME_LSDESC_CREATE_CONN_CMD  = 0x4,
101 	FCNVME_LSDESC_DISCONN_CMD      = 0x5,
102 	FCNVME_LSDESC_CONN_ID          = 0x6,
103 	FCNVME_LSDESC_ASSOC_ID         = 0x7,
104 };
105 
106 /*
107  * LS Reject reason_codes
108  */
109 enum fcnvme_ls_rjt_reason {
110 	FCNVME_RJT_RC_NONE         = 0,     /* no reason - not to be sent */
111 	FCNVME_RJT_RC_INVAL        = 0x01,  /* invalid NVMe_LS command code */
112 	FCNVME_RJT_RC_LOGIC        = 0x03,  /* logical error */
113 	FCNVME_RJT_RC_UNAB         = 0x09,  /* unable to perform request */
114 	FCNVME_RJT_RC_UNSUP        = 0x0b,  /* command not supported */
115 	FCNVME_RJT_RC_INPROG       = 0x0e,  /* command already in progress */
116 	FCNVME_RJT_RC_INV_ASSOC    = 0x40,  /* invalid Association ID */
117 	FCNVME_RJT_RC_INV_CONN     = 0x41,  /* invalid Connection ID */
118 	FCNVME_RJT_RC_INV_PARAM    = 0x42,  /* invalid parameters */
119 	FCNVME_RJT_RC_INSUFF_RES   = 0x43,  /* insufficient resources */
120 	FCNVME_RJT_RC_INV_HOST     = 0x44,  /* invalid or rejected host */
121 	FCNVME_RJT_RC_VENDOR       = 0xff,  /* vendor specific error */
122 };
123 
124 /*
125  * LS Reject reason_explanation codes
126  */
127 enum fcnvme_ls_rjt_explan {
128 	FCNVME_RJT_EXP_NONE	       = 0x00,  /* No additional explanation */
129 	FCNVME_RJT_EXP_OXID_RXID   = 0x17,  /* invalid OX_ID-RX_ID combo */
130 	FCNVME_RJT_EXP_UNAB_DATA   = 0x2a,  /* unable to supply data */
131 	FCNVME_RJT_EXP_INV_LEN     = 0x2d,  /* invalid payload length */
132 	FCNVME_RJT_EXP_INV_ESRP    = 0x40,  /* invalid ESRP ratio */
133 	FCNVME_RJT_EXP_INV_CTL_ID  = 0x41,  /* invalid controller ID */
134 	FCNVME_RJT_EXP_INV_Q_ID    = 0x42,  /* invalid queue ID */
135 	FCNVME_RJT_EXP_SQ_SIZE     = 0x43,  /* invalid submission queue size */
136 	FCNVME_RJT_EXP_INV_HOST_ID = 0x44,  /* invalid or rejected host ID */
137 	FCNVME_RJT_EXP_INV_HOSTNQN = 0x45,  /* invalid or rejected host NQN */
138 	FCNVME_RJT_EXP_INV_SUBNQN  = 0x46,  /* invalid or rejected subsys nqn */
139 };
140 
141 /*
142  * NVMe over FC CMD IU
143  */
144 struct spdk_nvmf_fc_cmnd_iu {
145 	uint32_t scsi_id: 8,
146 		 fc_id: 8,
147 		 cmnd_iu_len: 16;
148 	uint32_t rsvd0: 24,
149 		 flags: 8;
150 	uint64_t conn_id;
151 	uint32_t cmnd_seq_num;
152 	uint32_t data_len;
153 	struct spdk_nvme_cmd cmd;
154 	uint32_t rsvd1[2];
155 };
156 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_cmnd_iu) == 96, "size_mismatch");
157 
158 /*
159  * NVMe over Extended Response IU
160  */
161 struct spdk_nvmf_fc_ersp_iu {
162 	uint32_t status_code: 8,
163 		 rsvd0: 8,
164 		 ersp_len: 16;
165 	uint32_t response_seq_no;
166 	uint32_t transferred_data_len;
167 	uint32_t rsvd1;
168 	struct spdk_nvme_cpl rsp;
169 };
170 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ersp_iu) == 32, "size_mismatch");
171 
172 /*
173  * Transfer ready IU
174  */
175 struct spdk_nvmf_fc_xfer_rdy_iu {
176 	uint32_t relative_offset;
177 	uint32_t burst_len;
178 	uint32_t rsvd;
179 };
180 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_xfer_rdy_iu) == 12, "size_mismatch");
181 
182 /*
183  * FC VM header
184  */
185 struct spdk_nvmf_fc_vm_header {
186 	FCNVME_BE32 dst_vmid;
187 	FCNVME_BE32 src_vmid;
188 	FCNVME_BE32 rsvd0;
189 	FCNVME_BE32 rsvd1;
190 };
191 
192 /*
193  * FC NVME Frame Header
194  */
195 struct spdk_nvmf_fc_frame_hdr {
196 	FCNVME_BE32 r_ctl: 8,
197 		    d_id: 24;
198 	FCNVME_BE32 cs_ctl: 8,
199 		    s_id: 24;
200 	FCNVME_BE32 type: 8,
201 		    f_ctl: 24;
202 	FCNVME_BE32 seq_id: 8,
203 		    df_ctl: 8,
204 		    seq_cnt: 16;
205 	FCNVME_BE32 ox_id: 16,
206 		    rx_id: 16;
207 	FCNVME_BE32 parameter;
208 };
209 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_frame_hdr) == 24, "size_mismatch");
210 
211 /*
212  * Request payload word 0
213  */
214 struct spdk_nvmf_fc_ls_rqst_w0 {
215 	uint8_t	ls_cmd;			/* FCNVME_LS_xxx */
216 	uint8_t zeros[3];
217 };
218 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_rqst_w0) == 4, "size_mismatch");
219 
220 /*
221  * LS request information descriptor
222  */
223 struct spdk_nvmf_fc_lsdesc_rqst {
224 	FCNVME_BE32 desc_tag;		/* FCNVME_LSDESC_xxx */
225 	FCNVME_BE32 desc_len;
226 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
227 	FCNVME_BE32 rsvd12;
228 };
229 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_rqst) == 16, "size_mismatch");
230 
231 /*
232  * LS accept header
233  */
234 struct spdk_nvmf_fc_ls_acc_hdr {
235 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
236 	FCNVME_BE32 desc_list_len;
237 	struct spdk_nvmf_fc_lsdesc_rqst rqst;
238 	/* Followed by cmd-specific ACC descriptors, see next definitions */
239 };
240 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_acc_hdr) == 24, "size_mismatch");
241 
242 /*
243  * LS descriptor connection id
244  */
245 struct spdk_nvmf_fc_lsdesc_conn_id {
246 	FCNVME_BE32 desc_tag;
247 	FCNVME_BE32 desc_len;
248 	FCNVME_BE64 connection_id;
249 };
250 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_conn_id) == 16, "size_mismatch");
251 
252 /*
253  * LS descriptor association id
254  */
255 struct spdk_nvmf_fc_lsdesc_assoc_id {
256 	FCNVME_BE32 desc_tag;
257 	FCNVME_BE32 desc_len;
258 	FCNVME_BE64 association_id;
259 };
260 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) == 16, "size_mismatch");
261 
262 /*
263  * LS Create Association descriptor
264  */
265 struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd {
266 	FCNVME_BE32  desc_tag;
267 	FCNVME_BE32  desc_len;
268 	FCNVME_BE16  ersp_ratio;
269 	FCNVME_BE16  rsvd10;
270 	FCNVME_BE32  rsvd12[9];
271 	FCNVME_BE16  cntlid;
272 	FCNVME_BE16  sqsize;
273 	FCNVME_BE32  rsvd52;
274 	uint8_t hostid[FCNVME_ASSOC_HOSTID_LEN];
275 	uint8_t hostnqn[SPDK_NVME_NQN_FIELD_SIZE];
276 	uint8_t subnqn[SPDK_NVME_NQN_FIELD_SIZE];
277 	uint8_t rsvd584[432];
278 };
279 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd) == 1016, "size_mismatch");
280 
281 /*
282  * LS Create Association request payload
283  */
284 struct spdk_nvmf_fc_ls_cr_assoc_rqst {
285 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
286 	FCNVME_BE32 desc_list_len;
287 	struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd assoc_cmd;
288 };
289 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_rqst) == 1024, "size_mismatch");
290 
291 /*
292  * LS Create Association accept payload
293  */
294 struct spdk_nvmf_fc_ls_cr_assoc_acc {
295 	struct spdk_nvmf_fc_ls_acc_hdr hdr;
296 	struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id;
297 	struct spdk_nvmf_fc_lsdesc_conn_id conn_id;
298 };
299 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_acc) == 56, "size_mismatch");
300 
301 /*
302  * LS Create IO Connection descriptor
303  */
304 struct spdk_nvmf_fc_lsdesc_cr_conn_cmd {
305 	FCNVME_BE32 desc_tag;
306 	FCNVME_BE32 desc_len;
307 	FCNVME_BE16 ersp_ratio;
308 	FCNVME_BE16 rsvd10;
309 	FCNVME_BE32 rsvd12[9];
310 	FCNVME_BE16 qid;
311 	FCNVME_BE16 sqsize;
312 	FCNVME_BE32 rsvd52;
313 };
314 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_acc) == 56, "size_mismatch");
315 
316 /*
317  * LS Create IO Connection payload
318  */
319 struct spdk_nvmf_fc_ls_cr_conn_rqst {
320 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
321 	FCNVME_BE32 desc_list_len;
322 	struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id;
323 	struct spdk_nvmf_fc_lsdesc_cr_conn_cmd connect_cmd;
324 };
325 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_conn_rqst) == 80, "size_mismatch");
326 
327 /*
328  * LS Create IO Connection accept payload
329  */
330 struct spdk_nvmf_fc_ls_cr_conn_acc {
331 	struct spdk_nvmf_fc_ls_acc_hdr hdr;
332 	struct spdk_nvmf_fc_lsdesc_conn_id conn_id;
333 };
334 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_conn_acc) == 40, "size_mismatch");
335 
336 /*
337  * LS Disconnect descriptor
338  */
339 struct spdk_nvmf_fc_lsdesc_disconn_cmd {
340 	FCNVME_BE32 desc_tag;
341 	FCNVME_BE32 desc_len;
342 	FCNVME_BE32 rsvd8;
343 	FCNVME_BE32 rsvd12;
344 	FCNVME_BE32 rsvd16;
345 	FCNVME_BE32 rsvd20;
346 };
347 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_disconn_cmd) == 24, "size_mismatch");
348 
349 /*
350  * LS Disconnect payload
351  */
352 struct spdk_nvmf_fc_ls_disconnect_rqst {
353 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
354 	FCNVME_BE32 desc_list_len;
355 	struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id;
356 	struct spdk_nvmf_fc_lsdesc_disconn_cmd disconn_cmd;
357 };
358 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst) == 48, "size_mismatch");
359 
360 /*
361  * LS Disconnect accept payload
362  */
363 struct spdk_nvmf_fc_ls_disconnect_acc {
364 	struct spdk_nvmf_fc_ls_acc_hdr hdr;
365 };
366 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_disconnect_acc) == 24, "size_mismatch");
367 
368 /*
369  * LS Reject descriptor
370  */
371 struct spdk_nvmf_fc_lsdesc_rjt {
372 	FCNVME_BE32 desc_tag;
373 	FCNVME_BE32 desc_len;
374 	uint8_t rsvd8;
375 
376 	uint8_t reason_code;
377 	uint8_t reason_explanation;
378 
379 	uint8_t vendor;
380 	FCNVME_BE32 rsvd12;
381 };
382 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_rjt) == 16, "size_mismatch");
383 
384 /*
385  * LS Reject payload
386  */
387 struct spdk_nvmf_fc_ls_rjt {
388 	struct spdk_nvmf_fc_ls_rqst_w0 w0;
389 	FCNVME_BE32 desc_list_len;
390 	struct spdk_nvmf_fc_lsdesc_rqst rqst;
391 	struct spdk_nvmf_fc_lsdesc_rjt rjt;
392 };
393 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_rjt) == 40, "size_mismatch");
394 
395 /*
396  * FC World Wide Name
397  */
398 struct spdk_nvmf_fc_wwn {
399 	union {
400 		uint64_t wwn; /* World Wide Names consist of eight bytes */
401 		uint8_t octets[sizeof(uint64_t)];
402 	} u;
403 };
404 
405 #ifdef __cplusplus
406 }
407 #endif
408 
409 #endif
410