LCOV - code coverage report
Current view: top level - lib/iscsi - iscsi.h (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 5 10 50.0 %
Date: 2024-12-06 22:24:29 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
       3             :  *   Copyright (C) 2016 Intel Corporation.
       4             :  *   All rights reserved.
       5             :  */
       6             : 
       7             : #ifndef SPDK_ISCSI_H
       8             : #define SPDK_ISCSI_H
       9             : 
      10             : #include "spdk/stdinc.h"
      11             : #include "spdk/env.h"
      12             : #include "spdk/bdev.h"
      13             : #include "spdk/iscsi_spec.h"
      14             : #include "spdk/thread.h"
      15             : #include "spdk/sock.h"
      16             : 
      17             : #include "spdk/scsi.h"
      18             : #include "iscsi/param.h"
      19             : 
      20             : #include "spdk/assert.h"
      21             : #include "spdk/dif.h"
      22             : #include "spdk/util.h"
      23             : 
      24             : #define SPDK_ISCSI_DEFAULT_NODEBASE "iqn.2016-06.io.spdk"
      25             : 
      26             : #define DEFAULT_MAXR2T 4
      27             : #define MAX_INITIATOR_PORT_NAME 256
      28             : #define MAX_INITIATOR_NAME 223
      29             : #define MAX_TARGET_NAME 223
      30             : 
      31             : #define MAX_PORTAL 1024
      32             : #define MAX_INITIATOR 256
      33             : #define MAX_NETMASK 256
      34             : #define MAX_ISCSI_CONNECTIONS 1024
      35             : #define MAX_PORTAL_ADDR 256
      36             : #define MAX_PORTAL_PORT 32
      37             : 
      38             : #define DEFAULT_PORT 3260
      39             : #define DEFAULT_MAX_SESSIONS 128
      40             : #define DEFAULT_MAX_CONNECTIONS_PER_SESSION 2
      41             : #define DEFAULT_MAXOUTSTANDINGR2T 1
      42             : #define DEFAULT_DEFAULTTIME2WAIT 2
      43             : #define DEFAULT_DEFAULTTIME2RETAIN 20
      44             : #define DEFAULT_INITIALR2T true
      45             : #define DEFAULT_IMMEDIATEDATA true
      46             : #define DEFAULT_DATAPDUINORDER true
      47             : #define DEFAULT_DATASEQUENCEINORDER true
      48             : #define DEFAULT_ERRORRECOVERYLEVEL 0
      49             : #define DEFAULT_TIMEOUT 60
      50             : #define MAX_NOPININTERVAL 60
      51             : #define DEFAULT_NOPININTERVAL 30
      52             : 
      53             : /*
      54             :  * SPDK iSCSI target currently only supports 64KB as the maximum data segment length
      55             :  *  it can receive from initiators.  Other values may work, but no guarantees.
      56             :  */
      57             : #define SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH  65536
      58             : 
      59             : /*
      60             :  * Defines maximum number of data out buffers each connection can have in
      61             :  *  use at any given time.
      62             :  */
      63             : #define MAX_DATA_OUT_PER_CONNECTION 16
      64             : 
      65             : /*
      66             :  * Defines default maximum number of data in buffers each connection can have in
      67             :  *  use at any given time. So this limit does not affect I/O smaller than
      68             :  *  SPDK_BDEV_SMALL_BUF_MAX_SIZE.
      69             :  */
      70             : #define DEFAULT_MAX_LARGE_DATAIN_PER_CONNECTION 64
      71             : 
      72             : #define SPDK_ISCSI_MAX_BURST_LENGTH     \
      73             :                 (SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH * MAX_DATA_OUT_PER_CONNECTION)
      74             : 
      75             : /*
      76             :  * Defines default maximum amount in bytes of unsolicited data the iSCSI
      77             :  *  initiator may send to the SPDK iSCSI target during the execution of
      78             :  *  a single SCSI command. And it is smaller than the MaxBurstLength.
      79             :  */
      80             : #define SPDK_ISCSI_FIRST_BURST_LENGTH   8192
      81             : 
      82             : /*
      83             :  * Defines minimum amount in bytes of unsolicited data the iSCSI initiator
      84             :  *  may send to the SPDK iSCSI target during the execution of a single
      85             :  *  SCSI command.
      86             :  */
      87             : #define SPDK_ISCSI_MIN_FIRST_BURST_LENGTH       512
      88             : 
      89             : #define SPDK_ISCSI_MAX_FIRST_BURST_LENGTH       16777215
      90             : 
      91             : /*
      92             :  * Defines default maximum queue depth per connection and this can be
      93             :  * changed by configuration file.
      94             :  */
      95             : #define DEFAULT_MAX_QUEUE_DEPTH 64
      96             : 
      97             : /** Defines how long we should wait for a logout request when the target
      98             :  *   requests logout to the initiator asynchronously.
      99             :  */
     100             : #define ISCSI_LOGOUT_REQUEST_TIMEOUT 30 /* in seconds */
     101             : 
     102             : /** Defines how long we should wait for a TCP close after responding to a
     103             :  *   logout request, before terminating the connection ourselves.
     104             :  */
     105             : #define ISCSI_LOGOUT_TIMEOUT 5 /* in seconds */
     106             : 
     107             : /** Defines how long we should wait until login process completes. */
     108             : #define ISCSI_LOGIN_TIMEOUT 30 /* in seconds */
     109             : 
     110             : /* For spdk_iscsi_login_in related function use, we need to avoid the conflict
     111             :  * with other errors
     112             :  * */
     113             : #define SPDK_ISCSI_LOGIN_ERROR_RESPONSE -1000
     114             : #define SPDK_ISCSI_LOGIN_ERROR_PARAMETER -1001
     115             : #define SPDK_ISCSI_PARAMETER_EXCHANGE_NOT_ONCE -1002
     116             : 
     117             : #define ISCSI_AHS_LEN 60
     118             : 
     119             : struct spdk_mobj {
     120             :         struct spdk_mempool *mp;
     121             :         void *buf;
     122             :         uint32_t data_len;
     123             : };
     124             : 
     125             : /*
     126             :  * Maximum number of SGL elements, i.e.,
     127             :  * BHS, AHS, Header Digest, Data Segment and Data Digest.
     128             :  */
     129             : #define SPDK_ISCSI_MAX_SGL_DESCRIPTORS  (5)
     130             : 
     131             : #define SPDK_CRC32C_INITIAL     0xffffffffUL
     132             : #define SPDK_CRC32C_XOR         0xffffffffUL
     133             : 
     134             : typedef void (*iscsi_conn_xfer_complete_cb)(void *cb_arg);
     135             : 
     136             : struct spdk_iscsi_pdu {
     137             :         struct iscsi_bhs bhs;
     138             : 
     139             :         /* Merge multiple Data-OUT PDUs in a sequence into a subtask up to
     140             :          * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH or the final PDU comes.
     141             :          *
     142             :          * Both the size of a data buffer and MaxRecvDataSegmentLength are
     143             :          * SPDK_ISCSI_MAX_RECV_DATA_SEGMENT_LENGTH at most. Hence the data segment of
     144             :          * a Data-OUT PDU can be split into two data buffers at most.
     145             :          */
     146             :         struct spdk_mobj *mobj[2];
     147             : 
     148             :         bool is_rejected;
     149             :         uint8_t *data;
     150             :         uint8_t header_digest[ISCSI_DIGEST_LEN];
     151             :         uint8_t data_digest[ISCSI_DIGEST_LEN];
     152             :         size_t data_segment_len;
     153             :         int bhs_valid_bytes;
     154             :         int ahs_valid_bytes;
     155             :         uint32_t data_valid_bytes;
     156             :         int hdigest_valid_bytes;
     157             :         int ddigest_valid_bytes;
     158             :         int ref;
     159             :         bool data_from_mempool;  /* indicate whether the data buffer is allocated from mempool */
     160             :         struct spdk_iscsi_task *task; /* data tied to a task buffer */
     161             :         uint32_t cmd_sn;
     162             :         uint32_t writev_offset;
     163             :         uint32_t data_buf_len;
     164             :         uint32_t data_offset;
     165             :         uint32_t crc32c;
     166             :         bool dif_insert_or_strip;
     167             :         struct spdk_dif_ctx dif_ctx;
     168             :         struct spdk_iscsi_conn *conn;
     169             : 
     170             :         iscsi_conn_xfer_complete_cb             cb_fn;
     171             :         void                                    *cb_arg;
     172             : 
     173             :         /* The sock request ends with a 0 length iovec. Place the actual iovec immediately
     174             :          * after it. There is a static assert below to check if the compiler inserted
     175             :          * any unwanted padding */
     176             :         int32_t                                         mapped_length;
     177             :         struct spdk_sock_request                        sock_req;
     178             :         struct iovec                                    iov[SPDK_ISCSI_MAX_SGL_DESCRIPTORS];
     179             :         TAILQ_ENTRY(spdk_iscsi_pdu)     tailq;
     180             : 
     181             : 
     182             :         /*
     183             :          * 60 bytes of AHS should suffice for now.
     184             :          * This should always be at the end of PDU data structure.
     185             :          * we need to not zero this out when doing memory clear.
     186             :          */
     187             :         uint8_t ahs[ISCSI_AHS_LEN];
     188             : 
     189             :         struct {
     190             :                 uint16_t length; /* iSCSI SenseLength (big-endian) */
     191             :                 uint8_t data[32];
     192             :         } sense;
     193             : };
     194             : SPDK_STATIC_ASSERT(offsetof(struct spdk_iscsi_pdu,
     195             :                             sock_req) + sizeof(struct spdk_sock_request) == offsetof(struct spdk_iscsi_pdu, iov),
     196             :                    "Compiler inserted padding between iov and sock_req");
     197             : 
     198             : enum iscsi_connection_state {
     199             :         ISCSI_CONN_STATE_INVALID = 0,
     200             :         ISCSI_CONN_STATE_RUNNING = 1,
     201             :         ISCSI_CONN_STATE_EXITING = 2,
     202             :         ISCSI_CONN_STATE_EXITED = 3,
     203             : };
     204             : 
     205             : enum iscsi_chap_phase {
     206             :         ISCSI_CHAP_PHASE_NONE = 0,
     207             :         ISCSI_CHAP_PHASE_WAIT_A = 1,
     208             :         ISCSI_CHAP_PHASE_WAIT_NR = 2,
     209             :         ISCSI_CHAP_PHASE_END = 3,
     210             : };
     211             : 
     212             : enum session_type {
     213             :         SESSION_TYPE_INVALID = 0,
     214             :         SESSION_TYPE_NORMAL = 1,
     215             :         SESSION_TYPE_DISCOVERY = 2,
     216             : };
     217             : 
     218             : #define ISCSI_CHAP_CHALLENGE_LEN        1024
     219             : #define ISCSI_CHAP_MAX_USER_LEN         255
     220             : #define ISCSI_CHAP_MAX_SECRET_LEN       255
     221             : 
     222             : struct iscsi_chap_auth {
     223             :         enum iscsi_chap_phase chap_phase;
     224             : 
     225             :         char user[ISCSI_CHAP_MAX_USER_LEN + 1];
     226             :         char secret[ISCSI_CHAP_MAX_SECRET_LEN + 1];
     227             :         char muser[ISCSI_CHAP_MAX_USER_LEN + 1];
     228             :         char msecret[ISCSI_CHAP_MAX_SECRET_LEN + 1];
     229             : 
     230             :         uint8_t chap_id[1];
     231             :         uint8_t chap_mid[1];
     232             :         int chap_challenge_len;
     233             :         uint8_t chap_challenge[ISCSI_CHAP_CHALLENGE_LEN];
     234             :         int chap_mchallenge_len;
     235             :         uint8_t chap_mchallenge[ISCSI_CHAP_CHALLENGE_LEN];
     236             : };
     237             : 
     238             : struct spdk_iscsi_auth_secret {
     239             :         char user[ISCSI_CHAP_MAX_USER_LEN + 1];
     240             :         char secret[ISCSI_CHAP_MAX_SECRET_LEN + 1];
     241             :         char muser[ISCSI_CHAP_MAX_USER_LEN + 1];
     242             :         char msecret[ISCSI_CHAP_MAX_SECRET_LEN + 1];
     243             :         TAILQ_ENTRY(spdk_iscsi_auth_secret) tailq;
     244             : };
     245             : 
     246             : struct spdk_iscsi_auth_group {
     247             :         int32_t tag;
     248             :         TAILQ_HEAD(, spdk_iscsi_auth_secret) secret_head;
     249             :         TAILQ_ENTRY(spdk_iscsi_auth_group) tailq;
     250             : };
     251             : 
     252             : struct spdk_iscsi_sess {
     253             :         uint32_t connections;
     254             :         struct spdk_iscsi_conn **conns;
     255             : 
     256             :         struct spdk_scsi_port *initiator_port;
     257             :         int tag;
     258             : 
     259             :         uint64_t isid;
     260             :         uint16_t tsih;
     261             :         struct spdk_iscsi_tgt_node *target;
     262             :         int queue_depth;
     263             : 
     264             :         struct iscsi_param *params;
     265             : 
     266             :         enum session_type session_type;
     267             :         uint32_t MaxConnections;
     268             :         uint32_t MaxOutstandingR2T;
     269             :         uint32_t DefaultTime2Wait;
     270             :         uint32_t DefaultTime2Retain;
     271             :         uint32_t FirstBurstLength;
     272             :         uint32_t MaxBurstLength;
     273             :         bool InitialR2T;
     274             :         bool ImmediateData;
     275             :         bool DataPDUInOrder;
     276             :         bool DataSequenceInOrder;
     277             :         uint32_t ErrorRecoveryLevel;
     278             : 
     279             :         uint32_t ExpCmdSN;
     280             :         uint32_t MaxCmdSN;
     281             : 
     282             :         uint32_t current_text_itt;
     283             : };
     284             : 
     285             : struct spdk_iscsi_poll_group {
     286             :         struct spdk_poller                              *poller;
     287             :         struct spdk_poller                              *nop_poller;
     288             :         STAILQ_HEAD(connections, spdk_iscsi_conn)       connections;
     289             :         struct spdk_sock_group                          *sock_group;
     290             :         TAILQ_ENTRY(spdk_iscsi_poll_group)              link;
     291             :         uint32_t                                        num_active_targets;
     292             : };
     293             : 
     294             : struct spdk_iscsi_opts {
     295             :         char *authfile;
     296             :         char *nodebase;
     297             :         int32_t timeout;
     298             :         int32_t nopininterval;
     299             :         bool disable_chap;
     300             :         bool require_chap;
     301             :         bool mutual_chap;
     302             :         int32_t chap_group;
     303             :         uint32_t MaxSessions;
     304             :         uint32_t MaxConnectionsPerSession;
     305             :         uint32_t MaxConnections;
     306             :         uint32_t MaxQueueDepth;
     307             :         uint32_t DefaultTime2Wait;
     308             :         uint32_t DefaultTime2Retain;
     309             :         uint32_t FirstBurstLength;
     310             :         bool ImmediateData;
     311             :         uint32_t ErrorRecoveryLevel;
     312             :         bool AllowDuplicateIsid;
     313             :         uint32_t MaxLargeDataInPerConnection;
     314             :         uint32_t MaxR2TPerConnection;
     315             :         uint32_t pdu_pool_size;
     316             :         uint32_t immediate_data_pool_size;
     317             :         uint32_t data_out_pool_size;
     318             : };
     319             : 
     320             : struct spdk_iscsi_globals {
     321             :         char *authfile;
     322             :         char *nodebase;
     323             :         pthread_mutex_t mutex;
     324             :         uint32_t refcnt;
     325             :         TAILQ_HEAD(, spdk_iscsi_portal)         portal_head;
     326             :         TAILQ_HEAD(, spdk_iscsi_portal_grp)     pg_head;
     327             :         TAILQ_HEAD(, spdk_iscsi_init_grp)       ig_head;
     328             :         TAILQ_HEAD(, spdk_iscsi_tgt_node)       target_head;
     329             :         TAILQ_HEAD(, spdk_iscsi_auth_group)     auth_group_head;
     330             :         TAILQ_HEAD(, spdk_iscsi_poll_group)     poll_group_head;
     331             : 
     332             :         int32_t timeout;
     333             :         int32_t nopininterval;
     334             :         bool disable_chap;
     335             :         bool require_chap;
     336             :         bool mutual_chap;
     337             :         int32_t chap_group;
     338             : 
     339             :         uint32_t MaxSessions;
     340             :         uint32_t MaxConnectionsPerSession;
     341             :         uint32_t MaxConnections;
     342             :         uint32_t MaxQueueDepth;
     343             :         uint32_t DefaultTime2Wait;
     344             :         uint32_t DefaultTime2Retain;
     345             :         uint32_t FirstBurstLength;
     346             :         bool ImmediateData;
     347             :         uint32_t ErrorRecoveryLevel;
     348             :         bool AllowDuplicateIsid;
     349             :         uint32_t MaxLargeDataInPerConnection;
     350             :         uint32_t MaxR2TPerConnection;
     351             :         uint32_t pdu_pool_size;
     352             :         uint32_t immediate_data_pool_size;
     353             :         uint32_t data_out_pool_size;
     354             : 
     355             :         struct spdk_mempool *pdu_pool;
     356             :         struct spdk_mempool *pdu_immediate_data_pool;
     357             :         struct spdk_mempool *pdu_data_out_pool;
     358             :         struct spdk_mempool *session_pool;
     359             :         struct spdk_mempool *task_pool;
     360             : 
     361             :         struct spdk_iscsi_sess  **session;
     362             : };
     363             : 
     364             : #define ISCSI_SECURITY_NEGOTIATION_PHASE        0
     365             : #define ISCSI_OPERATIONAL_NEGOTIATION_PHASE     1
     366             : #define ISCSI_NSG_RESERVED_CODE                 2
     367             : #define ISCSI_FULL_FEATURE_PHASE                3
     368             : 
     369             : /* logout reason */
     370             : #define ISCSI_LOGOUT_REASON_CLOSE_SESSION               0
     371             : #define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION            1
     372             : #define ISCSI_LOGOUT_REASON_REMOVE_CONN_FOR_RECOVERY    2
     373             : 
     374             : enum spdk_error_codes {
     375             :         SPDK_ISCSI_CONNECTION_FATAL     = -1,
     376             :         SPDK_PDU_FATAL          = -2,
     377             : };
     378             : 
     379             : #define DGET24(B)                                                                                       \
     380             :         (((  (uint32_t) *((uint8_t *)(B)+0)) << 16)                               \
     381             :          | (((uint32_t) *((uint8_t *)(B)+1)) << 8)                                \
     382             :          | (((uint32_t) *((uint8_t *)(B)+2)) << 0))
     383             : 
     384             : #define DSET24(B,D)                                                                                                     \
     385             :         (((*((uint8_t *)(B)+0)) = (uint8_t)((uint32_t)(D) >> 16)),                \
     386             :          ((*((uint8_t *)(B)+1)) = (uint8_t)((uint32_t)(D) >> 8)),         \
     387             :          ((*((uint8_t *)(B)+2)) = (uint8_t)((uint32_t)(D) >> 0)))
     388             : 
     389             : #define xstrdup(s) (s ? strdup(s) : (char *)NULL)
     390             : 
     391             : extern struct spdk_iscsi_globals g_iscsi;
     392             : extern struct spdk_iscsi_opts *g_spdk_iscsi_opts;
     393             : 
     394             : struct spdk_iscsi_task;
     395             : struct spdk_json_write_ctx;
     396             : 
     397             : typedef void (*spdk_iscsi_init_cb)(void *cb_arg, int rc);
     398             : 
     399             : void spdk_iscsi_init(spdk_iscsi_init_cb cb_fn, void *cb_arg);
     400             : typedef void (*spdk_iscsi_fini_cb)(void *arg);
     401             : void spdk_iscsi_fini(spdk_iscsi_fini_cb cb_fn, void *cb_arg);
     402             : void shutdown_iscsi_conns_done(void);
     403             : void spdk_iscsi_config_json(struct spdk_json_write_ctx *w);
     404             : 
     405             : struct spdk_iscsi_opts *iscsi_opts_alloc(void);
     406             : void iscsi_opts_free(struct spdk_iscsi_opts *opts);
     407             : struct spdk_iscsi_opts *iscsi_opts_copy(struct spdk_iscsi_opts *src);
     408             : void iscsi_opts_info_json(struct spdk_json_write_ctx *w);
     409             : int iscsi_set_discovery_auth(bool disable_chap, bool require_chap,
     410             :                              bool mutual_chap, int32_t chap_group);
     411             : int iscsi_chap_get_authinfo(struct iscsi_chap_auth *auth, const char *authuser,
     412             :                             int ag_tag);
     413             : int iscsi_add_auth_group(int32_t tag, struct spdk_iscsi_auth_group **_group);
     414             : struct spdk_iscsi_auth_group *iscsi_find_auth_group_by_tag(int32_t tag);
     415             : void iscsi_delete_auth_group(struct spdk_iscsi_auth_group *group);
     416             : int iscsi_auth_group_add_secret(struct spdk_iscsi_auth_group *group,
     417             :                                 const char *user, const char *secret,
     418             :                                 const char *muser, const char *msecret);
     419             : int iscsi_auth_group_delete_secret(struct spdk_iscsi_auth_group *group,
     420             :                                    const char *user);
     421             : void iscsi_auth_groups_info_json(struct spdk_json_write_ctx *w);
     422             : 
     423             : void iscsi_task_response(struct spdk_iscsi_conn *conn,
     424             :                          struct spdk_iscsi_task *task);
     425             : int iscsi_build_iovs(struct spdk_iscsi_conn *conn, struct iovec *iovs, int iovcnt,
     426             :                      struct spdk_iscsi_pdu *pdu, uint32_t *mapped_length);
     427             : int iscsi_handle_incoming_pdus(struct spdk_iscsi_conn *conn);
     428             : void iscsi_task_mgmt_response(struct spdk_iscsi_conn *conn,
     429             :                               struct spdk_iscsi_task *task);
     430             : 
     431             : void iscsi_free_sess(struct spdk_iscsi_sess *sess);
     432             : void iscsi_clear_all_transfer_task(struct spdk_iscsi_conn *conn,
     433             :                                    struct spdk_scsi_lun *lun,
     434             :                                    struct spdk_iscsi_pdu *pdu);
     435             : bool iscsi_del_transfer_task(struct spdk_iscsi_conn *conn, uint32_t CmdSN);
     436             : 
     437             : uint32_t iscsi_pdu_calc_header_digest(struct spdk_iscsi_pdu *pdu);
     438             : uint32_t iscsi_pdu_calc_data_digest(struct spdk_iscsi_pdu *pdu);
     439             : 
     440             : /* Memory management */
     441             : void iscsi_put_pdu(struct spdk_iscsi_pdu *pdu);
     442             : struct spdk_iscsi_pdu *iscsi_get_pdu(struct spdk_iscsi_conn *conn);
     443             : void iscsi_op_abort_task_set(struct spdk_iscsi_task *task,
     444             :                              uint8_t function);
     445             : void iscsi_queue_task(struct spdk_iscsi_conn *conn, struct spdk_iscsi_task *task);
     446             : 
     447             : static inline struct spdk_mobj *
     448           7 : iscsi_datapool_get(struct spdk_mempool *pool)
     449             : {
     450           7 :         return spdk_mempool_get(pool);
     451             : }
     452             : 
     453             : static inline void
     454           0 : iscsi_datapool_put(struct spdk_mobj *mobj)
     455             : {
     456           0 :         assert(mobj != NULL);
     457             : 
     458           0 :         mobj->data_len = 0;
     459           0 :         spdk_mempool_put(mobj->mp, (void *)mobj);
     460           0 : }
     461             : 
     462             : static inline uint32_t
     463          27 : iscsi_get_max_immediate_data_size(void)
     464             : {
     465             :         /*
     466             :          * Specify enough extra space in addition to FirstBurstLength to
     467             :          *  account for a header digest, data digest and additional header
     468             :          *  segments (AHS).  These are not normally used but they do not
     469             :          *  take up much space and we need to make sure the worst-case scenario
     470             :          *  can be satisfied by the size returned here.
     471             :          */
     472          27 :         return g_iscsi.FirstBurstLength +
     473             :                ISCSI_DIGEST_LEN + /* data digest */
     474             :                ISCSI_DIGEST_LEN + /* header digest */
     475          27 :                8 +                 /* bidirectional AHS */
     476             :                52;                 /* extended CDB AHS (for a 64-byte CDB) */
     477             : }
     478             : 
     479             : #endif /* SPDK_ISCSI_H */

Generated by: LCOV version 1.15