u8* crc)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- struct hash_desc desc;
- desc.tfm = tcp_conn->tx_tfm;
- desc.flags = 0;
- crypto_hash_digest(&desc, &buf->sg, buf->sg.length, crc);
- buf->sg.length += sizeof(uint32_t);
- crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
++ crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
+ buf->sg.length = tcp_conn->hdr_size;
}
static inline int
sg_init_one(&sg, (u8 *)hdr,
sizeof(struct iscsi_hdr) + ahslen);
- desc.tfm = tcp_conn->rx_tfm;
- desc.flags = 0;
- crypto_hash_digest(&desc, &sg, sg.length, (u8 *)&cdgst);
- crypto_digest_digest(tcp_conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
++ crypto_hash_digest(&tcp_conn->rx_hash, &sg, sg.length,
++ (u8 *)&cdgst);
rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
ahslen);
if (cdgst != rdgst) {
}
static inline void
- partial_sg_digest_update(struct iscsi_tcp_conn *tcp_conn,
- struct scatterlist *sg, int offset, int length)
-partial_sg_digest_update(struct crypto_tfm *tfm, struct scatterlist *sg,
++partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
+ int offset, int length)
{
struct scatterlist temp;
memcpy(&temp, sg, sizeof(struct scatterlist));
temp.offset = offset;
temp.length = length;
- crypto_hash_update(&tcp_conn->data_rx_hash, &temp, length);
- crypto_digest_update(tfm, &temp, 1);
++ crypto_hash_update(desc, &temp, length);
}
static void
struct scatterlist tmp;
sg_init_one(&tmp, buf, len);
- crypto_hash_update(&tcp_conn->data_rx_hash, &tmp, len);
- crypto_digest_update(tcp_conn->rx_tfm, &tmp, 1);
++ crypto_hash_update(&tcp_conn->rx_hash, &tmp, len);
}
static int iscsi_scsi_data_in(struct iscsi_conn *conn)
if (!rc) {
if (conn->datadgst_en) {
if (!offset)
- crypto_digest_update(
- tcp_conn->rx_tfm,
+ crypto_hash_update(
- &tcp_conn->data_rx_hash,
- &sg[i], sg[i].length);
++ &tcp_conn->rx_hash,
+ &sg[i], 1);
else
- partial_sg_digest_update(tcp_conn,
+ partial_sg_digest_update(
- tcp_conn->rx_tfm,
++ &tcp_conn->rx_hash,
&sg[i],
sg[i].offset + offset,
sg[i].length - offset);
/*
* data-in is complete, but buffer not...
*/
- partial_sg_digest_update(tcp_conn, &sg[i],
- partial_sg_digest_update(tcp_conn->rx_tfm,
- &sg[i],
-- sg[i].offset, sg[i].length-rc);
++ partial_sg_digest_update(&tcp_conn->rx_hash,
++ &sg[i],
++ sg[i].offset,
++ sg[i].length-rc);
rc = 0;
break;
}
*/
rc = iscsi_tcp_hdr_recv(conn);
if (!rc && tcp_conn->in.datalen) {
- if (conn->datadgst_en) {
- crypto_hash_init(&tcp_conn->data_rx_hash);
- }
+ if (conn->datadgst_en)
- crypto_digest_init(tcp_conn->rx_tfm);
++ crypto_hash_init(&tcp_conn->rx_hash);
tcp_conn->in_progress = IN_PROGRESS_DATA_RECV;
} else if (rc) {
iscsi_conn_failure(conn, rc);
tcp_conn->in.padding);
memset(pad, 0, tcp_conn->in.padding);
sg_init_one(&sg, pad, tcp_conn->in.padding);
- crypto_hash_update(&tcp_conn->data_rx_hash,
- crypto_digest_update(tcp_conn->rx_tfm,
- &sg, 1);
++ crypto_hash_update(&tcp_conn->rx_hash,
+ &sg, sg.length);
}
- crypto_hash_final(&tcp_conn->data_rx_hash,
- (u8 *)&tcp_conn->in.datadgst);
- crypto_digest_final(tcp_conn->rx_tfm,
- (u8 *) &tcp_conn->in.datadgst);
++ crypto_hash_final(&tcp_conn->rx_hash,
++ (u8 *) &tcp_conn->in.datadgst);
debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
+ tcp_conn->data_copied = 0;
} else
tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
}
static inline void
iscsi_data_digest_init(struct iscsi_tcp_conn *tcp_conn,
- struct iscsi_cmd_task *ctask)
+ struct iscsi_tcp_cmd_task *tcp_ctask)
{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
-
- crypto_hash_init(&tcp_conn->data_tx_hash);
- crypto_digest_init(tcp_conn->tx_tfm);
++ crypto_hash_init(&tcp_conn->tx_hash);
tcp_ctask->digest_count = 4;
}
iscsi_hdr_digest(conn, &tcp_ctask->headbuf,
(u8*)tcp_ctask->hdrext);
rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count);
- if (rc)
+ if (rc) {
tcp_ctask->xmstate |= XMSTATE_W_HDR;
- return rc;
+ return rc;
+ }
+
+ if (ctask->imm_count) {
+ tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
+ iscsi_set_padding(tcp_ctask, ctask->imm_count);
+
+ if (ctask->conn->datadgst_en) {
+ iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask);
+ tcp_ctask->immdigest = 0;
+ }
+ }
+
+ if (ctask->unsol_count)
+ tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT;
+ return 0;
}
- static inline int
- handle_xmstate_data_digest(struct iscsi_conn *conn,
- struct iscsi_cmd_task *ctask)
+ static int
+ iscsi_send_padding(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- int rc;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ int sent = 0, rc;
- tcp_ctask->xmstate &= ~XMSTATE_DATA_DIGEST;
- debug_tcp("resent data digest 0x%x\n", tcp_ctask->datadigest);
- rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
- &tcp_ctask->datadigest, 0);
+ if (tcp_ctask->xmstate & XMSTATE_W_PAD) {
+ iscsi_buf_init_iov(&tcp_ctask->sendbuf, (char*)&tcp_ctask->pad,
+ tcp_ctask->pad_count);
+ if (conn->datadgst_en)
- crypto_digest_update(tcp_conn->tx_tfm,
- &tcp_ctask->sendbuf.sg, 1);
++ crypto_hash_update(&tcp_conn->tx_hash,
++ &tcp_ctask->sendbuf.sg,
++ tcp_ctask->sendbuf.sg.length);
+ } else if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_PAD))
+ return 0;
+
+ tcp_ctask->xmstate &= ~XMSTATE_W_PAD;
+ tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_PAD;
+ debug_scsi("sending %d pad bytes for itt 0x%x\n",
+ tcp_ctask->pad_count, ctask->itt);
+ rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf, &tcp_ctask->pad_count,
+ &sent);
if (rc) {
- tcp_ctask->xmstate |= XMSTATE_DATA_DIGEST;
- debug_tcp("resent data digest 0x%x fail!\n",
- tcp_ctask->datadigest);
+ debug_scsi("padding send failed %d\n", rc);
+ tcp_ctask->xmstate |= XMSTATE_W_RESEND_PAD;
}
-
return rc;
}
- static inline int
- handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ static int
+ iscsi_send_digest(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
+ struct iscsi_buf *buf, uint32_t *digest)
{
- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
- struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
- int rc;
+ struct iscsi_tcp_cmd_task *tcp_ctask;
+ struct iscsi_tcp_conn *tcp_conn;
+ int rc, sent = 0;
- BUG_ON(!ctask->imm_count);
- tcp_ctask->xmstate &= ~XMSTATE_IMM_DATA;
+ if (!conn->datadgst_en)
+ return 0;
- if (conn->datadgst_en) {
- iscsi_data_digest_init(tcp_conn, ctask);
- tcp_ctask->immdigest = 0;
- }
+ tcp_ctask = ctask->dd_data;
+ tcp_conn = conn->dd_data;
- for (;;) {
- rc = iscsi_sendpage(conn, &tcp_ctask->sendbuf,
- &ctask->imm_count, &tcp_ctask->sent);
- if (rc) {
- tcp_ctask->xmstate |= XMSTATE_IMM_DATA;
- if (conn->datadgst_en) {
- crypto_hash_final(&tcp_conn->data_tx_hash,
- (u8 *)&tcp_ctask->immdigest);
- debug_tcp("tx imm sendpage fail 0x%x\n",
- tcp_ctask->datadigest);
- }
- return rc;
- }
- if (conn->datadgst_en)
- crypto_hash_update(&tcp_conn->data_tx_hash,
- &tcp_ctask->sendbuf.sg,
- tcp_ctask->sendbuf.sg.length);
+ if (!(tcp_ctask->xmstate & XMSTATE_W_RESEND_DATA_DIGEST)) {
- crypto_digest_final(tcp_conn->tx_tfm, (u8*)digest);
++ crypto_hash_final(&tcp_conn->tx_hash, (u8*)digest);
+ iscsi_buf_init_iov(buf, (char*)digest, 4);
+ }
+ tcp_ctask->xmstate &= ~XMSTATE_W_RESEND_DATA_DIGEST;
- if (!ctask->imm_count)
- break;
- iscsi_buf_init_sg(&tcp_ctask->sendbuf,
- &tcp_ctask->sg[tcp_ctask->sg_count++]);
+ rc = iscsi_sendpage(conn, buf, &tcp_ctask->digest_count, &sent);
+ if (!rc)
+ debug_scsi("sent digest 0x%x for itt 0x%x\n", *digest,
+ ctask->itt);
+ else {
+ debug_scsi("sending digest 0x%x failed for itt 0x%x!\n",
+ *digest, ctask->itt);
+ tcp_ctask->xmstate |= XMSTATE_W_RESEND_DATA_DIGEST;
}
+ return rc;
+ }
- if (conn->datadgst_en && !(tcp_ctask->xmstate & XMSTATE_W_PAD)) {
- rc = iscsi_digest_final_send(conn, ctask, &tcp_ctask->immbuf,
- &tcp_ctask->immdigest, 1);
- if (rc) {
- debug_tcp("sending imm digest 0x%x fail!\n",
- tcp_ctask->immdigest);
- return rc;
+ static int
+ iscsi_send_data(struct iscsi_cmd_task *ctask, struct iscsi_buf *sendbuf,
+ struct scatterlist **sg, int *sent, int *count,
+ struct iscsi_buf *digestbuf, uint32_t *digest)
+ {
+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
+ struct iscsi_conn *conn = ctask->conn;
+ struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+ int rc, buf_sent, offset;
+
+ while (*count) {
+ buf_sent = 0;
+ offset = sendbuf->sent;
+
+ rc = iscsi_sendpage(conn, sendbuf, count, &buf_sent);
+ *sent = *sent + buf_sent;
+ if (buf_sent && conn->datadgst_en)
- partial_sg_digest_update(tcp_conn->tx_tfm,
++ partial_sg_digest_update(&tcp_conn->tx_hash,
+ &sendbuf->sg, sendbuf->sg.offset + offset,
+ buf_sent);
+ if (!iscsi_buf_left(sendbuf) && *sg != tcp_ctask->bad_sg) {
+ iscsi_buf_init_sg(sendbuf, *sg);
+ *sg = *sg + 1;
}
- debug_tcp("sending imm digest 0x%x\n", tcp_ctask->immdigest);
+
+ if (rc)
+ return rc;
}
- return 0;
+ rc = iscsi_send_padding(conn, ctask);
+ if (rc)
+ return rc;
+
+ return iscsi_send_digest(conn, ctask, digestbuf, digest);
}
- static inline int
- handle_xmstate_uns_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
+ static int
+ iscsi_send_unsol_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
struct iscsi_data_task *dtask;
/* initial operational parameters */
tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
- tcp_conn->tx_tfm = crypto_alloc_tfm("crc32c", 0);
- if (!tcp_conn->tx_tfm)
++ tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
++ CRYPTO_ALG_ASYNC);
++ tcp_conn->tx_hash.flags = 0;
++ if (!tcp_conn->tx_hash.tfm)
+ goto free_tcp_conn;
+
- tcp_conn->rx_tfm = crypto_alloc_tfm("crc32c", 0);
- if (!tcp_conn->rx_tfm)
++ tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
++ CRYPTO_ALG_ASYNC);
++ tcp_conn->rx_hash.flags = 0;
++ if (!tcp_conn->rx_hash.tfm)
+ goto free_tx_tfm;
+
return cls_conn;
- crypto_free_tfm(tcp_conn->tx_tfm);
+ free_tx_tfm:
++ crypto_free_hash(tcp_conn->tx_hash.tfm);
+ free_tcp_conn:
+ kfree(tcp_conn);
tcp_conn_alloc_fail:
iscsi_conn_teardown(cls_conn);
return NULL;
/* now free tcp_conn */
if (digest) {
-- if (tcp_conn->tx_tfm)
- crypto_free_hash(tcp_conn->tx_tfm);
- crypto_free_tfm(tcp_conn->tx_tfm);
-- if (tcp_conn->rx_tfm)
- crypto_free_hash(tcp_conn->rx_tfm);
- if (tcp_conn->data_tx_hash.tfm)
- crypto_free_hash(tcp_conn->data_tx_hash.tfm);
- if (tcp_conn->data_rx_hash.tfm)
- crypto_free_hash(tcp_conn->data_rx_hash.tfm);
- crypto_free_tfm(tcp_conn->rx_tfm);
++ if (tcp_conn->tx_hash.tfm)
++ crypto_free_hash(tcp_conn->tx_hash.tfm);
++ if (tcp_conn->rx_hash.tfm)
++ crypto_free_hash(tcp_conn->rx_hash.tfm);
}
kfree(tcp_conn);