1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
|
/*
Copyright (c) 2014-2016, Mellanox Technologies, Ltd. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __iser_private_h__
#define __iser_private_h__
#include <stdint.h>
#include <stddef.h>
#include <time.h>
#include "iscsi-private.h"
#include "scsi-lowlevel.h"
#include <strings.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#ifdef __linux
#include <infiniband/verbs.h>
#include <rdma/rdma_cma.h>
#include <rdma/rdma_verbs.h>
#define unlikely(x) __builtin_expect (!!(x), 0)
#define ISER_VER 0x10
#define ISER_WSV 0x08
#define ISER_RSV 0x04
#define DATA_BUFFER_UNIT_SHIFT SHIFT_4K
#define DATA_BUFFER_UNIT_SIZE SIZE_4K
#define DATA_BUFFER_CHUNK_SHIFT 22
#define DATA_BUFFER_CHUNK_SIZE (1ULL << DATA_BUFFER_CHUNK_SHIFT)
#define DATA_BUFFER_CHUNK_UNITS_SHIFT (DATA_BUFFER_CHUNK_SHIFT - DATA_BUFFER_UNIT_SHIFT)
#define DATA_BUFFER_CHUNK_UNITS (1 << DATA_BUFFER_CHUNK_UNITS_SHIFT)
#define ISER_HEADERS_LEN (sizeof(struct iser_hdr) + ISCSI_RAW_HEADER_SIZE)
#define ISER_RECV_DATA_SEG_LEN 128
#define ISER_RX_PAYLOAD_SIZE (ISER_HEADERS_LEN + ISER_RECV_DATA_SEG_LEN)
#define ISER_RX_LOGIN_SIZE (ISER_HEADERS_LEN + ISCSI_DEF_MAX_RECV_SEG_LEN)
#define ISCSI_DEF_MAX_RECV_SEG_LEN 8192
#define BHSSC_FLAGS_R 0x40
#define BHSSC_FLAGS_W 0x20
#define ISER_MAX_CQ_LEN 1024
#define ISER_ZBVA_NOT_SUPPORTED 0x80
#define ISER_SEND_W_INV_NOT_SUPPORTED 0x40
enum desc_type {
ISCSI_CONTROL = 0,
ISCSI_COMMAND};
enum data_dir{
DATA_WRITE = 0,
DATA_READ,
DATA_NONE};
#define SHIFT_4K 12
#define SIZE_4K (1ULL << SHIFT_4K)
#define MASK_4K (~(SIZE_4K-1))
#define ISER_DEF_XMIT_CMDS_MAX 512
#define ISER_QP_MAX_RECV_DTOS (ISER_DEF_XMIT_CMDS_MAX)
#define ISER_MIN_POSTED_RX (ISER_DEF_XMIT_CMDS_MAX >> 2)
/**
* struct iser_hdr - iSER header
*
* @flags: flags support (zbva, remote_inv)
* @rsvd: reserved
* @write_stag: write rkey
* @write_va: write virtual address
* @reaf_stag: read rkey
* @read_va: read virtual address
*/
struct iser_hdr {
uint8_t flags;
uint8_t rsvd[3];
uint32_t write_stag;
uint64_t write_va;
uint32_t read_stag;
uint64_t read_va;
} __attribute__((packed));
/**
* struct iser_rx_desc - iSER RX descriptor (for recv wr_id)
*
* @isr_hdr: iser header
* @iscsi_data: iscsi header
* @data: received data segment
* @rx_sg: ibv_sge of receive buffer
* @pad: padding
*/
struct iser_rx_desc {
struct iser_hdr iser_header;
char iscsi_header[ISCSI_RAW_HEADER_SIZE];
char data[ISER_RECV_DATA_SEG_LEN];
char pad[4];
struct ibv_mr *hdr_mr;
struct ibv_sge rx_sg;
};
static_assert(offsetof(struct iser_rx_desc, hdr_mr) % 8 == 0, "iser_rx_desc is not aligned on 8-byte boundary");
/**
* struct iser_tx_desc - iSER TX descriptor (for send wr_id)
*
* @iser_hdr: iser header
* @iscsi_header: iscsi header (bhs)
* @tx_sg: sg[0] points to iser/iscsi headers
* sg[1] optionally points to either of immediate data
* unsolicited data-out or control
* @num_sge: number sges used on this TX task
* @mr: iser/iscsi headers mr
* @data_mr: mr for case we need to allocate mr for read
* @next: next descriptor on the list
*/
struct iser_tx_desc {
struct iser_hdr iser_header;
unsigned char iscsi_header[ISCSI_RAW_HEADER_SIZE];
struct ibv_sge tx_sg[2];
int num_sge;
struct ibv_mr *hdr_mr;
char *data_buff;
struct ibv_mr *data_mr;
enum desc_type type;
enum data_dir data_dir;
struct iser_tx_desc *next;
};
struct iser_cm_hdr {
uint8_t flags;
uint8_t rsvd[3];
};
struct iser_pdu {
struct iscsi_pdu iscsi_pdu;
struct iser_tx_desc *desc;
};
struct iser_buf_chunk {
unsigned char *buf;
struct ibv_mr *mr;
struct iser_buf_chunk *next;
int8_t tree[DATA_BUFFER_CHUNK_UNITS << 1];
};
struct iser_conn {
struct rdma_cm_id *cma_id;
struct rdma_event_channel *cma_channel;
struct ibv_pd *pd;
struct ibv_cq *cq;
struct ibv_qp *qp;
struct ibv_comp_channel *comp_channel;
int rdma_connect_sent;
struct ibv_recv_wr rx_wr[ISER_MIN_POSTED_RX];
struct ibv_mr *login_resp_mr;
unsigned char *login_resp_buf;
struct iser_rx_desc *rx_descs;
uint32_t num_rx_descs;
unsigned int rx_desc_head;
unsigned int cq_nevents;
int post_recv_buf_count;
int qp_max_recv_dtos;
int min_posted_rx;
uint16_t max_cmds;
struct iser_tx_desc *tx_desc;
struct iser_buf_chunk *buf_chunk;
};
void iscsi_init_iser_transport(struct iscsi_context *iscsi);
#endif /* __linux */
#endif /* __iser_private_h__ */
|