41#include <sys/capsicum.h>
42#include <sys/condvar.h>
43#include <sys/endian.h>
45#include <sys/kernel.h>
46#include <sys/kthread.h>
48#include <sys/malloc.h>
49#include <sys/module.h>
53#include <sys/socket.h>
54#include <sys/sysctl.h>
57#include <sys/unistd.h>
74#include <dev/iscsi/icl.h>
75#include <dev/iscsi/icl_wrappers.h>
76#include <dev/iscsi/iscsi_proto.h>
79#ifdef ICL_KERNEL_PROXY
80#include <sys/socketvar.h>
83#ifdef ICL_KERNEL_PROXY
84FEATURE(cfiscsi_kernel_proxy,
"iSCSI target built with ICL_KERNEL_PROXY");
88#define ISCSI_BHS_OPCODE_INTERNAL 0x3e
90static MALLOC_DEFINE(M_CFISCSI,
"cfiscsi",
"Memory used for CTL iSCSI frontend");
93SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
94 "CAM Target Layer iSCSI Frontend");
97 &
debug, 1,
"Enable debug messages");
100 &
ping_timeout, 5,
"Interval between ping (NOP-Out) requests, in seconds");
103 &
login_timeout, 60,
"Time to wait for ctld(8) to finish Login Phase, in seconds");
106 &
maxtags, 0,
"Max number of requests queued by initiator");
108#define CFISCSI_DEBUG(X, ...) \
111 printf("%s: " X "\n", \
112 __func__, ## __VA_ARGS__); \
116#define CFISCSI_WARN(X, ...) \
119 printf("WARNING: %s: " X "\n", \
120 __func__, ## __VA_ARGS__); \
124#define CFISCSI_SESSION_DEBUG(S, X, ...) \
127 printf("%s: %s (%s): " X "\n", \
128 __func__, S->cs_initiator_addr, \
129 S->cs_initiator_name, ## __VA_ARGS__); \
133#define CFISCSI_SESSION_WARN(S, X, ...) \
136 printf("WARNING: %s (%s): " X "\n", \
137 S->cs_initiator_addr, \
138 S->cs_initiator_name, ## __VA_ARGS__); \
142#define CFISCSI_SESSION_LOCK(X) mtx_lock(&X->cs_lock)
143#define CFISCSI_SESSION_UNLOCK(X) mtx_unlock(&X->cs_lock)
144#define CFISCSI_SESSION_LOCK_ASSERT(X) mtx_assert(&X->cs_lock, MA_OWNED)
146#define CONN_SESSION(X) ((struct cfiscsi_session *)(X)->ic_prv0)
147#define PDU_SESSION(X) CONN_SESSION((X)->ip_conn)
155 ((struct cfiscsi_priv *)&(io)->io_hdr.ctl_private[CTL_PRIV_FRONTEND])
156#define PRIV_REQUEST(io) PRIV(io)->request
157#define PRIV_EXPDATASN(io) PRIV(io)->expdatasn
158#define PRIV_R2TSN(io) PRIV(io)->r2tsn
166 u_long cmd, caddr_t addr,
int flag,
struct thread *td);
180 uint32_t initiator_task_tag,
181 uint32_t *target_transfer_tagp);
185 *softc,
const char *name, uint16_t tag);
187 struct cfiscsi_softc *softc,
const char *name,
const char *alias,
204static struct icl_pdu *
208 return (icl_pdu_new(request->ip_conn, flags));
214 const struct iscsi_bhs_scsi_command *bhssc;
216 uint32_t cmdsn, curcmdsn;
232 if (request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE)
238 if (request->ip_bhs->bhs_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_OUT)
245 bhssc = (
const struct iscsi_bhs_scsi_command *)request->ip_bhs;
246 curcmdsn = cmdsn = ntohl(bhssc->bhssc_cmdsn);
252 if (atomic_fcmpset_32(&cs->
cs_cmdsn, &curcmdsn, cmdsn + 1))
254 }
while (curcmdsn == cmdsn);
260 if (ISCSI_SNLT(cmdsn, curcmdsn) ||
261 ISCSI_SNGT(cmdsn, curcmdsn - 1 +
maxtags)) {
263 "while expected %u", cmdsn, curcmdsn);
273 "while expected %u; dropping connection",
289 icl_pdu_free(request);
299 switch (request->ip_bhs->bhs_opcode &
300 ~ISCSI_BHS_OPCODE_IMMEDIATE) {
301 case ISCSI_BHS_OPCODE_NOP_OUT:
304 case ISCSI_BHS_OPCODE_SCSI_COMMAND:
307 case ISCSI_BHS_OPCODE_TASK_REQUEST:
310 case ISCSI_BHS_OPCODE_SCSI_DATA_OUT:
313 case ISCSI_BHS_OPCODE_LOGOUT_REQUEST:
318 "opcode 0x%x; dropping connection",
319 request->ip_bhs->bhs_opcode);
320 icl_pdu_free(request);
329#ifdef ICL_KERNEL_PROXY
333 if (cs->cs_waiting_for_ctld || cs->cs_login_phase) {
334 if (cs->cs_login_pdu == NULL)
335 cs->cs_login_pdu = request;
337 icl_pdu_free(request);
338 cv_signal(&cs->cs_login_cv);
361 struct iscsi_bhs_scsi_response *bhssr;
362 bool advance_statsn =
true;
373 bhssr = (
struct iscsi_bhs_scsi_response *)response->ip_bhs;
379 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_R2T)
380 advance_statsn =
false;
386 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_NOP_IN &&
387 bhssr->bhssr_initiator_task_tag == 0xffffffff)
388 advance_statsn =
false;
394 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN &&
395 (bhssr->bhssr_flags & BHSDI_FLAGS_S) == 0)
396 advance_statsn =
false;
402 if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN ||
403 (bhssr->bhssr_flags & BHSDI_FLAGS_S))
404 bhssr->bhssr_statsn = htonl(cs->
cs_statsn);
406 bhssr->bhssr_expcmdsn = htonl(cmdsn);
407 bhssr->bhssr_maxcmdsn = htonl(cmdsn - 1 +
425 icl_pdu_queue(response);
436 icl_pdu_queue_cb(response, cb);
444 struct iscsi_bhs_nop_out *bhsno;
445 struct iscsi_bhs_nop_in *bhsni;
446 struct icl_pdu *response;
452 bhsno = (
struct iscsi_bhs_nop_out *)request->ip_bhs;
454 if (bhsno->bhsno_initiator_task_tag == 0xffffffff) {
459 icl_pdu_free(request);
463 datasize = icl_pdu_data_segment_length(request);
465 data = malloc(datasize, M_CFISCSI, M_NOWAIT | M_ZERO);
468 "dropping connection");
469 icl_pdu_free(request);
473 icl_pdu_get_data(request, 0, data, datasize);
477 if (response == NULL) {
479 "droppping connection");
480 free(data, M_CFISCSI);
481 icl_pdu_free(request);
485 bhsni = (
struct iscsi_bhs_nop_in *)response->ip_bhs;
486 bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN;
487 bhsni->bhsni_flags = 0x80;
488 bhsni->bhsni_initiator_task_tag = bhsno->bhsno_initiator_task_tag;
489 bhsni->bhsni_target_transfer_tag = 0xffffffff;
491 error = icl_pdu_append_data(response, data, datasize, M_NOWAIT);
494 "dropping connection");
495 free(data, M_CFISCSI);
496 icl_pdu_free(request);
497 icl_pdu_free(response);
501 free(data, M_CFISCSI);
504 icl_pdu_free(request);
511 struct iscsi_bhs_scsi_command *bhssc;
517 bhssc = (
struct iscsi_bhs_scsi_command *)request->ip_bhs;
523 "ImmediateData=No; dropping connection");
524 icl_pdu_free(request);
538 switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) {
539 case BHSSC_FLAGS_ATTR_UNTAGGED:
542 case BHSSC_FLAGS_ATTR_SIMPLE:
545 case BHSSC_FLAGS_ATTR_ORDERED:
548 case BHSSC_FLAGS_ATTR_HOQ:
551 case BHSSC_FLAGS_ATTR_ACA:
557 bhssc->bhssc_flags & BHSSC_FLAGS_ATTR);
561 memcpy(io->
scsiio.
cdb, bhssc->bhssc_cdb,
sizeof(bhssc->bhssc_cdb));
566 "dropping connection", error);
569 icl_pdu_free(request);
577 struct iscsi_bhs_task_management_request *bhstmr;
578 struct iscsi_bhs_task_management_response *bhstmr2;
579 struct icl_pdu *response;
585 bhstmr = (
struct iscsi_bhs_task_management_request *)request->ip_bhs;
595 switch (bhstmr->bhstmr_function & ~0x80) {
596 case BHSTMR_FUNCTION_ABORT_TASK:
603 case BHSTMR_FUNCTION_ABORT_TASK_SET:
609 case BHSTMR_FUNCTION_CLEAR_TASK_SET:
615 case BHSTMR_FUNCTION_LOGICAL_UNIT_RESET:
621 case BHSTMR_FUNCTION_TARGET_WARM_RESET:
627 case BHSTMR_FUNCTION_TARGET_COLD_RESET:
633 case BHSTMR_FUNCTION_QUERY_TASK:
640 case BHSTMR_FUNCTION_QUERY_TASK_SET:
646 case BHSTMR_FUNCTION_I_T_NEXUS_RESET:
652 case BHSTMR_FUNCTION_QUERY_ASYNC_EVENT:
660 bhstmr->bhstmr_function & ~0x80);
664 if (response == NULL) {
666 "dropping connection");
667 icl_pdu_free(request);
671 bhstmr2 = (
struct iscsi_bhs_task_management_response *)
673 bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE;
674 bhstmr2->bhstmr_flags = 0x80;
675 bhstmr2->bhstmr_response =
676 BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
677 bhstmr2->bhstmr_initiator_task_tag =
678 bhstmr->bhstmr_initiator_task_tag;
679 icl_pdu_free(request);
688 "dropping connection", error);
691 icl_pdu_free(request);
699 struct iscsi_bhs_data_out *bhsdo;
702 size_t copy_len,
len, off, buffer_offset;
708 KASSERT((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
709 ISCSI_BHS_OPCODE_SCSI_DATA_OUT ||
710 (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
711 ISCSI_BHS_OPCODE_SCSI_COMMAND,
712 (
"bad opcode 0x%x", request->ip_bhs->bhs_opcode));
717 bhsdo = (
struct iscsi_bhs_data_out *)request->ip_bhs;
721 (
"CTL_FLAG_DATA_IN"));
738 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
739 ISCSI_BHS_OPCODE_SCSI_DATA_OUT)
740 buffer_offset = ntohl(bhsdo->bhsdo_buffer_offset);
743 len = icl_pdu_data_segment_length(request);
751 buffer_offset +
len <=
754 "expected %zd; dropping connection", buffer_offset,
778 (
"cdw->cdw_sg_index >= ctl_sg_count"));
783 KASSERT(off <=
len, (
"len > off"));
784 copy_len =
len - off;
788 icl_pdu_get_data(request, off, cdw->
cdw_sg_addr, copy_len);
825 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
826 ISCSI_BHS_OPCODE_SCSI_COMMAND)
830 "expected %zd; dropping connection",
831 icl_pdu_data_segment_length(request), off);
838 (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) == 0) {
840 "the F flag; flags = 0x%x; dropping connection",
848 (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) != 0) {
849 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
850 ISCSI_BHS_OPCODE_SCSI_DATA_OUT) {
852 "transmitted size was %zd bytes instead of %d; "
853 "dropping connection",
883 struct iscsi_bhs_data_out *bhsdo;
890 bhsdo = (
struct iscsi_bhs_data_out *)request->ip_bhs;
893 TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next) {
896 "ttt 0x%x, itt 0x%x",
897 bhsdo->bhsdo_target_transfer_tag,
898 bhsdo->bhsdo_initiator_task_tag,
901 if (bhsdo->bhsdo_target_transfer_tag ==
908 "0x%x, not found; dropping connection",
909 bhsdo->bhsdo_target_transfer_tag, bhsdo->bhsdo_initiator_task_tag);
910 icl_pdu_free(request);
915 if (cdw->
cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) {
917 "DataSN %u, while expected %u; dropping connection",
919 icl_pdu_free(request);
923 cdw->
cdw_datasn += request->ip_additional_pdus + 1;
927 (
"CTL_FLAG_DATA_IN"));
932 TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
944 icl_pdu_free(request);
950 struct iscsi_bhs_logout_request *bhslr;
951 struct iscsi_bhs_logout_response *bhslr2;
952 struct icl_pdu *response;
956 bhslr = (
struct iscsi_bhs_logout_request *)request->ip_bhs;
957 switch (bhslr->bhslr_reason & 0x7f) {
958 case BHSLR_REASON_CLOSE_SESSION:
959 case BHSLR_REASON_CLOSE_CONNECTION:
961 if (response == NULL) {
963 icl_pdu_free(request);
967 bhslr2 = (
struct iscsi_bhs_logout_response *)response->ip_bhs;
968 bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE;
969 bhslr2->bhslr_flags = 0x80;
970 bhslr2->bhslr_response = BHSLR_RESPONSE_CLOSED_SUCCESSFULLY;
971 bhslr2->bhslr_initiator_task_tag =
972 bhslr->bhslr_initiator_task_tag;
973 icl_pdu_free(request);
977 case BHSLR_REASON_REMOVE_FOR_RECOVERY:
979 if (response == NULL) {
981 "failed to allocate memory; dropping connection");
982 icl_pdu_free(request);
986 bhslr2 = (
struct iscsi_bhs_logout_response *)response->ip_bhs;
987 bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE;
988 bhslr2->bhslr_flags = 0x80;
989 bhslr2->bhslr_response = BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED;
990 bhslr2->bhslr_initiator_task_tag =
991 bhslr->bhslr_initiator_task_tag;
992 icl_pdu_free(request);
997 bhslr->bhslr_reason);
998 icl_pdu_free(request);
1008 struct iscsi_bhs_nop_in *bhsni;
1020#ifdef ICL_KERNEL_PROXY
1021 if (cs->cs_waiting_for_ctld || cs->cs_login_phase) {
1024 "%d seconds; dropping connection", cs->
cs_timeout);
1062 cp = icl_pdu_new(cs->
cs_conn, M_NOWAIT);
1067 bhsni = (
struct iscsi_bhs_nop_in *)cp->ip_bhs;
1068 bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN;
1069 bhsni->bhsni_flags = 0x80;
1070 bhsni->bhsni_initiator_task_tag = 0xffffffff;
1077 uint32_t initiator_task_tag, uint32_t *target_transfer_tagp)
1085 "failed to allocate %zd bytes",
sizeof(*cdw));
1093 "icl_conn_transfer_setup() failed with error %d", error);
1139 int error, last, wait;
1143 ip = icl_pdu_new(cs->
cs_conn, M_WAITOK);
1166 while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) {
1167 TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next);
1179 "waiting for CTL to terminate %d tasks", wait);
1186 0,
"cfiscsi_terminate", hz / 100);
1234#ifdef ICL_KERNEL_PROXY
1235 cv_signal(&cs->cs_login_cv);
1287 cs = malloc(
sizeof(*cs), M_CFISCSI, M_NOWAIT | M_ZERO);
1295 TAILQ_INIT(&cs->cs_waiting_for_data_out);
1296 mtx_init(&cs->
cs_lock,
"cfiscsi_lock", NULL, MTX_DEF);
1298#ifdef ICL_KERNEL_PROXY
1299 cv_init(&cs->cs_login_cv,
"cfiscsi_login");
1309 cs->
cs_conn = icl_new_conn(offload,
false,
"cfiscsi", &cs->
cs_lock);
1311 free(cs, M_CFISCSI);
1321 free(cs, M_CFISCSI);
1325 mtx_lock(&softc->
lock);
1327 TAILQ_INSERT_TAIL(&softc->sessions, cs, cs_next);
1328 mtx_unlock(&softc->
lock);
1347 (
"destroying session with outstanding CTL pdus"));
1348 KASSERT(TAILQ_EMPTY(&cs->cs_waiting_for_data_out),
1349 (
"destroying session with non-empty queue"));
1351 mtx_lock(&softc->
lock);
1352 TAILQ_REMOVE(&softc->sessions, cs, cs_next);
1353 mtx_unlock(&softc->
lock);
1360 free(cs, M_CFISCSI);
1370 bzero(softc,
sizeof(*softc));
1371 mtx_init(&softc->
lock,
"cfiscsi", NULL, MTX_DEF);
1374#ifdef ICL_KERNEL_PROXY
1375 cv_init(&softc->accept_cv,
"cfiscsi_accept");
1377 TAILQ_INIT(&softc->sessions);
1378 TAILQ_INIT(&softc->targets);
1392 if (!TAILQ_EMPTY(&softc->sessions) || !TAILQ_EMPTY(&softc->targets))
1396#ifdef ICL_KERNEL_PROXY
1397 cv_destroy(&softc->accept_cv);
1400 mtx_destroy(&softc->
lock);
1404#ifdef ICL_KERNEL_PROXY
1406cfiscsi_accept(
struct socket *so,
struct sockaddr *sa,
int portal_id)
1416 icl_conn_handoff_sock(cs->
cs_conn, so);
1417 cs->cs_initiator_sa = sa;
1418 cs->cs_portal_id = portal_id;
1420 cs->cs_waiting_for_ctld =
true;
1444 mtx_lock(&softc->
lock);
1446 mtx_unlock(&softc->
lock);
1450 online = softc->
online++;
1451 mtx_unlock(&softc->
lock);
1455#ifdef ICL_KERNEL_PROXY
1456 if (softc->listener != NULL)
1457 icl_listen_free(softc->listener);
1458 softc->listener = icl_listen_new(cfiscsi_accept);
1473 mtx_lock(&softc->
lock);
1475 mtx_unlock(&softc->
lock);
1479 online = --softc->
online;
1482 TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1486 TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1494 "cv_wait failed with error %d\n", error);
1498 }
while (cs != NULL && ct->
ct_online == 0);
1499 mtx_unlock(&softc->
lock);
1503#ifdef ICL_KERNEL_PROXY
1504 icl_listen_free(softc->listener);
1505 softc->listener = NULL;
1515 retval = sbuf_printf(sb,
"\t<cfiscsi_state>%d</cfiscsi_state>\n",
1541 "%s: target not found", __func__);
1545#ifdef ICL_KERNEL_PROXY
1546 if (cihp->
socket > 0 && cihp->connection_id > 0) {
1548 "both socket and connection_id set");
1556 if (cs->
cs_id == cihp->connection_id)
1562 "connection not found");
1574 "%s: cfiscsi_session_new failed", __func__);
1578#ifdef ICL_KERNEL_PROXY
1589 cs->
cs_conn->ic_max_recv_data_segment_length =
1591 cs->
cs_conn->ic_max_send_data_segment_length =
1597 cs->
cs_conn->ic_header_crc32c =
true;
1599 cs->
cs_conn->ic_data_crc32c =
true;
1615 mtx_lock(&softc->
lock);
1617 mtx_unlock(&softc->
lock);
1625 "%s: port offline", __func__);
1629 mtx_unlock(&softc->
lock);
1633 mtx_lock(&softc->
lock);
1634 TAILQ_FOREACH(cs2, &softc->sessions, cs_next) {
1641 "session reinstatement from "
1642 "different address %s",
1646 "session reinstatement");
1649 mtx_unlock(&softc->
lock);
1650 pause(
"cfiscsi_reinstate", 1);
1654 mtx_unlock(&softc->
lock);
1662#ifdef ICL_KERNEL_PROXY
1673 "%s: icl_conn_handoff failed with error %d",
1677#ifdef ICL_KERNEL_PROXY
1681#ifdef ICL_KERNEL_PROXY
1682 cs->cs_login_phase =
false;
1688 if (cs->cs_login_pdu != NULL) {
1691 cs->cs_login_pdu = NULL;
1720 sb = sbuf_new(NULL, NULL, cilp->
alloc_len, SBUF_FIXEDLEN);
1724 "Unable to allocate %d bytes for iSCSI session list",
1729 sbuf_printf(sb,
"<ctlislist>\n");
1730 mtx_lock(&softc->
lock);
1731 TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1734 error = sbuf_printf(sb,
"<connection id=\"%d\">"
1735 "<initiator>%s</initiator>"
1736 "<initiator_addr>%s</initiator_addr>"
1737 "<initiator_alias>%s</initiator_alias>"
1738 "<target>%s</target>"
1739 "<target_alias>%s</target_alias>"
1740 "<target_portal_group_tag>%u</target_portal_group_tag>"
1741 "<header_digest>%s</header_digest>"
1742 "<data_digest>%s</data_digest>"
1743 "<max_recv_data_segment_length>%d</max_recv_data_segment_length>"
1744 "<max_send_data_segment_length>%d</max_send_data_segment_length>"
1745 "<max_burst_length>%d</max_burst_length>"
1746 "<first_burst_length>%d</first_burst_length>"
1747 "<immediate_data>%d</immediate_data>"
1749 "<offload>%s</offload>"
1755 cs->
cs_conn->ic_header_crc32c ?
"CRC32C" :
"None",
1756 cs->
cs_conn->ic_data_crc32c ?
"CRC32C" :
"None",
1757 cs->
cs_conn->ic_max_recv_data_segment_length,
1758 cs->
cs_conn->ic_max_send_data_segment_length,
1767 mtx_unlock(&softc->
lock);
1768 error = sbuf_printf(sb,
"</ctlislist>\n");
1773 "Out of space, %d bytes is too small", cilp->
alloc_len);
1778 error = copyout(sbuf_data(sb), cilp->
conn_xml, sbuf_len(sb) + 1);
1782 "copyout failed with error %d", error);
1794 struct icl_pdu *response;
1795 struct iscsi_bhs_asynchronous_message *bhsam;
1804 mtx_lock(&softc->
lock);
1805 TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1811 response = icl_pdu_new(cs->
cs_conn, M_NOWAIT);
1812 if (response == NULL) {
1815 "Unable to allocate memory");
1816 mtx_unlock(&softc->
lock);
1820 (
struct iscsi_bhs_asynchronous_message *)response->ip_bhs;
1821 bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE;
1822 bhsam->bhsam_flags = 0x80;
1823 bhsam->bhsam_async_event = BHSAM_EVENT_TARGET_REQUESTS_LOGOUT;
1824 bhsam->bhsam_parameter3 = htons(10);
1828 mtx_unlock(&softc->
lock);
1833 "No matching connections found");
1843 struct icl_pdu *response;
1844 struct iscsi_bhs_asynchronous_message *bhsam;
1853 mtx_lock(&softc->
lock);
1854 TAILQ_FOREACH(cs, &softc->sessions, cs_next) {
1860 response = icl_pdu_new(cs->
cs_conn, M_NOWAIT);
1861 if (response == NULL) {
1866 bhsam = (
struct iscsi_bhs_asynchronous_message *)
1868 bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE;
1869 bhsam->bhsam_flags = 0x80;
1870 bhsam->bhsam_0xffffffff = 0xffffffff;
1871 bhsam->bhsam_async_event =
1872 BHSAM_EVENT_TARGET_TERMINATES_SESSION;
1878 mtx_unlock(&softc->
lock);
1883 "No matching connections found");
1894 struct icl_drv_limits idl;
1899 error = icl_limits(cilp->
offload,
false, &idl);
1903 "%s: icl_limits failed with error %d",
1909 idl.idl_max_recv_data_segment_length;
1911 idl.idl_max_send_data_segment_length;
1918#ifdef ICL_KERNEL_PROXY
1920cfiscsi_ioctl_listen(
struct ctl_iscsi *ci)
1922 struct ctl_iscsi_listen_params *cilp;
1923 struct sockaddr *sa;
1926 cilp = (
struct ctl_iscsi_listen_params *)&(ci->
data);
1935 error = getsockaddr(&sa, (
void *)cilp->addr, cilp->addrlen);
1943 error = icl_listen_add(
cfiscsi_softc.listener, cilp->iser, cilp->domain,
1944 cilp->socktype, cilp->protocol, sa, cilp->portal_id);
1949 "icl_listen_add failed, error %d", error);
1958cfiscsi_ioctl_accept(
struct ctl_iscsi *ci)
1960 struct ctl_iscsi_accept_params *ciap;
1964 ciap = (
struct ctl_iscsi_accept_params *)&(ci->
data);
1969 if (cs->cs_waiting_for_ctld)
1984 cs->cs_waiting_for_ctld =
false;
1985 cs->cs_login_phase =
true;
1987 ciap->connection_id = cs->
cs_id;
1988 ciap->portal_id = cs->cs_portal_id;
1989 ciap->initiator_addrlen = cs->cs_initiator_sa->sa_len;
1990 error = copyout(cs->cs_initiator_sa, ciap->initiator_addr,
1991 cs->cs_initiator_sa->sa_len);
1994 "copyout failed with error %d", error);
2005 struct ctl_iscsi_send_params *cisp;
2012 cisp = (
struct ctl_iscsi_send_params *)&(ci->
data);
2016 if (cs->
cs_id == cisp->connection_id)
2028 if (cs->cs_login_phase ==
false)
2038 datalen = cisp->data_segment_len;
2043 if (datalen > 65535) {
2049 data = malloc(datalen, M_CFISCSI, M_WAITOK);
2050 error = copyin(cisp->data_segment, data, datalen);
2052 free(data, M_CFISCSI);
2059 ip = icl_pdu_new(cs->
cs_conn, M_WAITOK);
2060 memcpy(ip->ip_bhs, cisp->bhs,
sizeof(*ip->ip_bhs));
2062 icl_pdu_append_data(ip, data, datalen, M_WAITOK);
2063 free(data, M_CFISCSI);
2072cfiscsi_ioctl_receive(
struct ctl_iscsi *ci)
2074 struct ctl_iscsi_receive_params *cirp;
2080 cirp = (
struct ctl_iscsi_receive_params *)&(ci->
data);
2084 if (cs->
cs_id == cirp->connection_id)
2090 "connection not found");
2097 if (is->is_login_phase ==
false)
2102 while (cs->cs_login_pdu == NULL && cs->
cs_terminating ==
false) {
2103 error = cv_wait_sig(&cs->cs_login_cv, &cs->
cs_lock);
2107 "interrupted by signal");
2116 "connection terminating");
2120 ip = cs->cs_login_pdu;
2121 cs->cs_login_pdu = NULL;
2124 if (ip->ip_data_len > cirp->data_segment_len) {
2127 "data segment too big");
2132 copyout(ip->ip_bhs, cirp->bhs,
sizeof(*ip->ip_bhs));
2133 if (ip->ip_data_len > 0) {
2134 data = malloc(ip->ip_data_len, M_CFISCSI, M_WAITOK);
2135 icl_pdu_get_data(ip, 0, data, ip->ip_data_len);
2136 copyout(data, cirp->data_segment, ip->ip_data_len);
2137 free(data, M_CFISCSI);
2151 const char *target, *alias, *val;
2153 int retval, len, idlen;
2156 target = dnvlist_get_string(req->
args_nvl,
"cfiscsi_target", NULL);
2157 alias = dnvlist_get_string(req->
args_nvl,
"cfiscsi_target_alias", NULL);
2158 val = dnvlist_get_string(req->
args_nvl,
"cfiscsi_portal_group_tag",
2161 if (target == NULL || val == NULL) {
2164 "Missing required argument");
2168 tag = strtoul(val, NULL, 0);
2173 "failed to create target \"%s\"", target);
2179 "target \"%s\" for portal group tag %u already exists",
2206 idlen = strlen(target) + strlen(
",t,0x0001") + 1;
2207 idlen = roundup2(idlen, 4);
2210 M_CTL, M_WAITOK | M_ZERO);
2217 snprintf(desc->
identifier, idlen,
"%s,t,0x%4.4x", target, tag);
2220 idlen = strlen(target) + 1;
2221 idlen = roundup2(idlen, 4);
2224 M_CTL, M_WAITOK | M_ZERO);
2240 "ctl_port_register() failed with error %d", retval);
2254 const char *target, *val;
2257 target = dnvlist_get_string(req->
args_nvl,
"cfiscsi_target", NULL);
2258 val = dnvlist_get_string(req->
args_nvl,
"cfiscsi_portal_group_tag",
2261 if (target == NULL || val == NULL) {
2264 "Missing required argument");
2268 tag = strtoul(val, NULL, 0);
2273 "can't find target \"%s\"", target);
2286 u_long cmd, caddr_t addr,
int flag,
struct thread *td)
2303 "Unsupported request type %d", req->
reqtype);
2328#ifdef ICL_KERNEL_PROXY
2330 cfiscsi_ioctl_listen(ci);
2333 cfiscsi_ioctl_accept(ci);
2336 cfiscsi_ioctl_send(ci);
2339 cfiscsi_ioctl_receive(ci);
2348 "%s: CTL compiled without ICL_KERNEL_PROXY",
2355 "%s: invalid iSCSI request type %d", __func__, ci->
type);
2375 mtx_lock(&softc->
lock);
2377 TAILQ_REMOVE(&softc->targets, ct, ct_next);
2378 mtx_unlock(&softc->
lock);
2382 printf(
"%s: ctl_port_deregister() failed\n",
2385 free(ct, M_CFISCSI);
2389 mtx_unlock(&softc->
lock);
2397 mtx_lock(&softc->
lock);
2398 TAILQ_FOREACH(ct, &softc->targets, ct_next) {
2400 strcmp(name, ct->
ct_name) != 0 ||
2404 mtx_unlock(&softc->
lock);
2407 mtx_unlock(&softc->
lock);
2414 const char *alias, uint16_t tag)
2421 newct = malloc(
sizeof(*newct), M_CFISCSI, M_WAITOK | M_ZERO);
2423 mtx_lock(&softc->
lock);
2424 TAILQ_FOREACH(ct, &softc->targets, ct_next) {
2426 strcmp(name, ct->
ct_name) != 0 ||
2430 mtx_unlock(&softc->
lock);
2431 free(newct, M_CFISCSI);
2441 if (TAILQ_EMPTY(&softc->targets))
2444 TAILQ_INSERT_TAIL(&softc->targets, newct, ct_next);
2445 mtx_unlock(&softc->
lock);
2456 ((
ctl_ref)ip->ip_prv0)(ip->ip_prv1, -1);
2463 struct icl_pdu *request, *response;
2464 const struct iscsi_bhs_scsi_command *bhssc;
2465 struct iscsi_bhs_data_in *bhsdi;
2467 size_t len, expected_len, sg_len, buffer_offset;
2468 size_t max_send_data_segment_length;
2469 const char *sg_addr;
2471 int ctl_sg_count, error, i;
2476 bhssc = (
const struct iscsi_bhs_scsi_command *)request->ip_bhs;
2477 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2478 ISCSI_BHS_OPCODE_SCSI_COMMAND,
2479 (
"bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND"));
2502 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
2507 if (buffer_offset >= expected_len) {
2510 "already sent the expected len", buffer_offset);
2526 if (cs->
cs_conn->ic_hw_isomax != 0)
2527 max_send_data_segment_length = cs->
cs_conn->ic_hw_isomax;
2529 max_send_data_segment_length =
2530 cs->
cs_conn->ic_max_send_data_segment_length;
2532 if (response == NULL) {
2534 if (response == NULL) {
2536 "allocate memory; dropping connection");
2542 bhsdi = (
struct iscsi_bhs_data_in *)response->ip_bhs;
2543 bhsdi->bhsdi_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_IN;
2544 bhsdi->bhsdi_initiator_task_tag =
2545 bhssc->bhssc_initiator_task_tag;
2546 bhsdi->bhsdi_target_transfer_tag = 0xffffffff;
2548 bhsdi->bhsdi_buffer_offset = htonl(buffer_offset);
2551 KASSERT(i < ctl_sg_count, (
"i >= ctl_sg_count"));
2553 sg_addr = ctl_sglist[i].
addr;
2554 sg_len = ctl_sglist[i].
len;
2555 KASSERT(sg_len > 0, (
"sg_len <= 0"));
2563 KASSERT(response->ip_data_len < max_send_data_segment_length,
2564 (
"ip_data_len %zd >= max_send_data_segment_length %zd",
2565 response->ip_data_len, max_send_data_segment_length));
2566 if (response->ip_data_len + len > max_send_data_segment_length) {
2567 len = max_send_data_segment_length - response->ip_data_len;
2568 KASSERT(len <= sg_len, (
"len %zd > sg_len %zd",
2575 KASSERT(buffer_offset + response->ip_data_len < expected_len,
2576 (
"buffer_offset %zd + ip_data_len %zd >= expected_len %zd",
2577 buffer_offset, response->ip_data_len, expected_len));
2578 if (buffer_offset + response->ip_data_len + len > expected_len) {
2580 "to expected data transfer length %zd",
2581 buffer_offset + response->ip_data_len + len, expected_len);
2582 len = expected_len - (buffer_offset + response->ip_data_len);
2583 KASSERT(len <= sg_len, (
"len %zd > sg_len %zd",
2587 error = icl_pdu_append_data(response, sg_addr, len,
2588 M_NOWAIT | (cb ? ICL_NOCOPY : 0));
2591 "allocate memory; dropping connection");
2592 icl_pdu_free(response);
2602 KASSERT(buffer_offset + response->ip_data_len <= expected_len,
2603 (
"buffer_offset %zd + ip_data_len %zd > expected_len %zd",
2604 buffer_offset, response->ip_data_len, expected_len));
2605 if (buffer_offset + response->ip_data_len == expected_len) {
2617 if (i == ctl_sg_count - 1) {
2626 if (response->ip_data_len == max_send_data_segment_length) {
2635 buffer_offset += response->ip_data_len;
2637 buffer_offset == expected_len) {
2638 buffer_offset -= response->ip_data_len;
2642 cs->
cs_conn->ic_max_send_data_segment_length);
2653 if (response != NULL) {
2654 buffer_offset += response->ip_data_len;
2656 buffer_offset == expected_len) {
2657 bhsdi->bhsdi_flags |= BHSDI_FLAGS_F;
2659 bhsdi->bhsdi_flags |= BHSDI_FLAGS_S;
2661 ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2662 bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW;
2663 bhsdi->bhsdi_residual_count =
2664 htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) -
2667 ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2668 bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW;
2669 bhsdi->bhsdi_residual_count =
2671 ntohl(bhssc->bhssc_expected_data_transfer_length));
2677 KASSERT(response->ip_data_len > 0, (
"sending empty Data-In"));
2679 cs->
cs_conn->ic_max_send_data_segment_length);
2695 struct icl_pdu *request, *response;
2696 const struct iscsi_bhs_scsi_command *bhssc;
2697 struct iscsi_bhs_r2t *bhsr2t;
2700 uint32_t expected_len, datamove_len, r2t_off, r2t_len;
2701 uint32_t target_transfer_tag;
2707 bhssc = (
const struct iscsi_bhs_scsi_command *)request->ip_bhs;
2708 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2709 ISCSI_BHS_OPCODE_SCSI_COMMAND,
2710 (
"bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND"));
2715 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length);
2724 target_transfer_tag =
2726 if (target_transfer_tag == 0xffffffff) {
2727 target_transfer_tag =
2731 &target_transfer_tag);
2734 "allocate memory; dropping connection");
2742 "task tag 0x%x, target transfer tag 0x%x",
2743 bhssc->bhssc_initiator_task_tag, target_transfer_tag);
2758 ctl_sglist->
len = datamove_len;
2764 while (r2t_off > 0) {
2779 icl_pdu_data_segment_length(request)) {
2797 (
"%s: I/O request %p on termating session %p not aborted",
2803 TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next);
2811 if (response == NULL) {
2813 "allocate memory; dropping connection");
2820 bhsr2t = (
struct iscsi_bhs_r2t *)response->ip_bhs;
2821 bhsr2t->bhsr2t_opcode = ISCSI_BHS_OPCODE_R2T;
2822 bhsr2t->bhsr2t_flags = 0x80;
2823 bhsr2t->bhsr2t_lun = bhssc->bhssc_lun;
2824 bhsr2t->bhsr2t_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
2825 bhsr2t->bhsr2t_target_transfer_tag = target_transfer_tag;
2831 bhsr2t->bhsr2t_r2tsn = htonl(
PRIV_R2TSN(io)++);
2841 bhsr2t->bhsr2t_buffer_offset = htonl(r2t_off);
2847 bhsr2t->bhsr2t_desired_data_transfer_length = htonl(r2t_len);
2867 struct icl_pdu *request, *response;
2868 struct iscsi_bhs_scsi_command *bhssc;
2869 struct iscsi_bhs_scsi_response *bhssr;
2874 uint16_t sense_length;
2877 bhssc = (
struct iscsi_bhs_scsi_command *)request->ip_bhs;
2878 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2879 ISCSI_BHS_OPCODE_SCSI_COMMAND,
2880 (
"replying to wrong opcode 0x%x", bhssc->bhssc_opcode));
2888 TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next)
2889 KASSERT(bhssc->bhssc_initiator_task_tag !=
2902 icl_pdu_free(request);
2907 bhssr = (
struct iscsi_bhs_scsi_response *)response->ip_bhs;
2908 bhssr->bhssr_opcode = ISCSI_BHS_OPCODE_SCSI_RESPONSE;
2909 bhssr->bhssr_flags = 0x80;
2915 ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2916 bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW;
2917 bhssr->bhssr_residual_count =
2918 htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) -
2923 ntohl(bhssc->bhssc_expected_data_transfer_length)) {
2924 bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW;
2926 ntohl(bhssc->bhssc_expected_data_transfer_length));
2930 bhssr->bhssr_response = BHSSR_RESPONSE_COMMAND_COMPLETED;
2932 bhssr->bhssr_initiator_task_tag = bhssc->bhssc_initiator_task_tag;
2941 icl_pdu_append_data(response,
2942 &sense_length,
sizeof(sense_length), M_WAITOK);
2943 icl_pdu_append_data(response,
2948 icl_pdu_free(request);
2955 struct icl_pdu *request, *response;
2956 struct iscsi_bhs_task_management_request *bhstmr;
2957 struct iscsi_bhs_task_management_response *bhstmr2;
2965 bhstmr = (
struct iscsi_bhs_task_management_request *)request->ip_bhs;
2966 KASSERT((bhstmr->bhstmr_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) ==
2967 ISCSI_BHS_OPCODE_TASK_REQUEST,
2968 (
"replying to wrong opcode 0x%x", bhstmr->bhstmr_opcode));
2972 bhstmr->bhstmr_initiator_task_tag,
2973 bhstmr->bhstmr_referenced_task_tag);
2976 if ((bhstmr->bhstmr_function & ~0x80) ==
2977 BHSTMR_FUNCTION_ABORT_TASK) {
2982 TAILQ_FOREACH_SAFE(cdw,
2983 &cs->cs_waiting_for_data_out, cdw_next, tmpcdw) {
2984 if (bhstmr->bhstmr_referenced_task_tag !=
2990 "tag 0x%x", bhstmr->bhstmr_initiator_task_tag);
2992 TAILQ_REMOVE(&cs->cs_waiting_for_data_out,
2998 if ((bhstmr->bhstmr_function & ~0x80) ==
2999 BHSTMR_FUNCTION_TARGET_COLD_RESET &&
3004 bhstmr2 = (
struct iscsi_bhs_task_management_response *)
3006 bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE;
3007 bhstmr2->bhstmr_flags = 0x80;
3010 bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_COMPLETE;
3013 bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_SUCCEEDED;
3016 bhstmr2->bhstmr_response = BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST;
3020 bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED;
3023 memcpy(bhstmr2->bhstmr_additional_reponse_information,
3025 bhstmr2->bhstmr_initiator_task_tag = bhstmr->bhstmr_initiator_task_tag;
3028 icl_pdu_free(request);
3033 mtx_lock(&softc->
lock);
3034 TAILQ_FOREACH(tcs, &softc->sessions, cs_next) {
3038 mtx_unlock(&softc->
lock);
3045 struct icl_pdu *request;
3054 switch (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) {
3055 case ISCSI_BHS_OPCODE_SCSI_COMMAND:
3058 case ISCSI_BHS_OPCODE_TASK_REQUEST:
3065 icl_pdu_free(request);
3072 panic(
"cfiscsi_done called with wrong opcode 0x%x",
3073 request->ip_bhs->bhs_opcode);
FEATURE(scbus, "SCSI devices support")
uint32_t ctl_decode_lun(uint64_t encoded)
void ctl_free_io(union ctl_io *io)
int ctl_remove_initiator(struct ctl_port *port, int iid)
int ctl_add_initiator(struct ctl_port *port, int iid, uint64_t wwpn, char *name)
void ctl_datamove_done(union ctl_io *io, bool samethr)
int ctl_run(union ctl_io *io)
void ctl_zero_io(union ctl_io *io)
union ctl_io * ctl_alloc_io(void *pool_ref)
#define CTL_RETVAL_COMPLETE
void ctl_set_data_phase_error(struct ctl_scsiio *ctsio)
void ctl_set_busy(struct ctl_scsiio *ctsio)
int ctl_port_deregister(struct ctl_port *port)
void ctl_port_offline(struct ctl_port *port)
int ctl_port_register(struct ctl_port *port)
static void cfiscsi_pdu_handle_data_out(struct icl_pdu *request)
#define CFISCSI_SESSION_WARN(S, X,...)
static void cfiscsi_session_unregister_initiator(struct cfiscsi_session *cs)
static void cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request)
static void cfiscsi_pdu_handle_task_request(struct icl_pdu *request)
#define CFISCSI_SESSION_DEBUG(S, X,...)
static struct cfiscsi_softc cfiscsi_softc
static void cfiscsi_receive_callback(struct icl_pdu *request)
CTL_FRONTEND_DECLARE(cfiscsi, cfiscsi_frontend)
static struct ctl_frontend cfiscsi_frontend
static void cfiscsi_ioctl_logout(struct ctl_iscsi *ci)
static void cfiscsi_pdu_done(struct icl_pdu *ip, int error)
static int cfiscsi_session_register_initiator(struct cfiscsi_session *cs)
static void cfiscsi_maintenance_thread(void *arg)
#define CFISCSI_SESSION_LOCK_ASSERT(X)
static void cfiscsi_target_release(struct cfiscsi_target *ct)
#define ISCSI_BHS_OPCODE_INTERNAL
static void cfiscsi_pdu_queue(struct icl_pdu *response)
static struct cfiscsi_target * cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name, uint16_t tag)
SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Target Layer iSCSI Frontend")
static void cfiscsi_target_hold(struct cfiscsi_target *ct)
static void cfiscsi_pdu_queue_cb(struct icl_pdu *response, icl_pdu_cb cb)
static void cfiscsi_ioctl_port_create(struct ctl_req *req)
#define CFISCSI_WARN(X,...)
static bool cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request)
static struct cfiscsi_target * cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name, const char *alias, uint16_t tag)
static uma_zone_t cfiscsi_data_wait_zone
#define PRIV_EXPDATASN(io)
static void cfiscsi_datamove_in(union ctl_io *io)
static void cfiscsi_data_wait_free(struct cfiscsi_session *cs, struct cfiscsi_data_wait *cdw)
static void cfiscsi_done(union ctl_io *io)
static void cfiscsi_datamove(union ctl_io *io)
#define CFISCSI_DEBUG(X,...)
#define CFISCSI_SESSION_UNLOCK(X)
#define CFISCSI_SESSION_LOCK(X)
static void cfiscsi_ioctl_handoff(struct ctl_iscsi *ci)
static void cfiscsi_ioctl_list(struct ctl_iscsi *ci)
static void cfiscsi_ioctl_limits(struct ctl_iscsi *ci)
static int cfiscsi_shutdown(void)
static void cfiscsi_pdu_handle_logout_request(struct icl_pdu *request)
static int cfiscsi_pdu_prepare(struct icl_pdu *response)
static void cfiscsi_ioctl_port_remove(struct ctl_req *req)
static struct cfiscsi_data_wait * cfiscsi_data_wait_new(struct cfiscsi_session *cs, union ctl_io *io, uint32_t initiator_task_tag, uint32_t *target_transfer_tagp)
SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN, &debug, 1, "Enable debug messages")
static void cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs)
static void cfiscsi_datamove_out(union ctl_io *io)
static MALLOC_DEFINE(M_CFISCSI, "cfiscsi", "Memory used for CTL iSCSI frontend")
static void cfiscsi_pdu_handle(struct icl_pdu *request)
static void cfiscsi_scsi_command_done(union ctl_io *io)
static void cfiscsi_offline(void *arg)
static void cfiscsi_session_terminate(struct cfiscsi_session *cs)
static void cfiscsi_pdu_handle_nop_out(struct icl_pdu *request)
static void cfiscsi_online(void *arg)
static void cfiscsi_task_management_done(union ctl_io *io)
static void cfiscsi_data_wait_abort(struct cfiscsi_session *cs, struct cfiscsi_data_wait *cdw, int status)
static struct icl_pdu * cfiscsi_pdu_new_response(struct icl_pdu *request, int flags)
static void cfiscsi_session_delete(struct cfiscsi_session *cs)
static int cfiscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
static int cfiscsi_info(void *arg, struct sbuf *sb)
static void cfiscsi_callout(void *context)
static bool cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *cdw)
static void cfiscsi_ioctl_terminate(struct ctl_iscsi *ci)
static int cfiscsi_init(void)
MODULE_DEPEND(cfiscsi, icl, 1, 1, 1)
static void cfiscsi_error_callback(struct icl_conn *ic)
static struct cfiscsi_session * cfiscsi_session_new(struct cfiscsi_softc *softc, const char *offload)
#define CFISCSI_TARGET_STATE_ACTIVE
#define CFISCSI_TARGET_STATE_DYING
#define CFISCSI_TARGET_STATE_INVALID
@ CTL_TASK_QUERY_ASYNC_EVENT
@ CTL_TASK_QUERY_TASK_SET
@ CTL_TASK_CLEAR_TASK_SET
@ CTL_TASK_ABORT_TASK_SET
@ CTL_TASK_I_T_NEXUS_RESET
void(* ctl_ref)(void *arg, int diff)
@ CTL_TASK_LUN_DOES_NOT_EXIST
@ CTL_TASK_FUNCTION_SUCCEEDED
@ CTL_TASK_FUNCTION_NOT_SUPPORTED
@ CTL_TASK_FUNCTION_COMPLETE
@ CTL_ISCSI_DIGEST_CRC32C
#define CTL_ISCSI_NAME_LEN
@ CTL_ISCSI_SESSION_NOT_FOUND
@ CTL_ISCSI_LIST_NEED_MORE_SPACE
#define SVPD_ID_ASSOC_TARGET
#define SVPD_ID_TYPE_SCSI_NAME
#define SVPD_ID_CODESET_UTF8
#define SVPD_ID_ASSOC_PORT
union ctl_io * cdw_ctl_io
uint32_t cdw_initiator_task_tag
uint32_t cdw_target_transfer_tag
struct cv cs_maintenance_cv
char cs_initiator_name[CTL_ISCSI_NAME_LEN]
struct callout cs_callout
char cs_initiator_id[CTL_ISCSI_NAME_LEN+5+6+1]
struct cfiscsi_target * cs_target
char cs_initiator_alias[CTL_ISCSI_ALIAS_LEN]
uint32_t cs_target_transfer_tag
char cs_initiator_addr[CTL_ISCSI_ADDR_LEN]
struct icl_conn * cs_conn
char cs_initiator_isid[6]
bool cs_terminating_tasks
volatile u_int cs_outstanding_ctl_pdus
bool cs_handoff_in_progress
int cs_first_burst_length
unsigned int last_session_id
char ct_name[CTL_ISCSI_NAME_LEN]
char ct_alias[CTL_ISCSI_ALIAS_LEN]
struct cfiscsi_softc * ct_softc
volatile u_int ct_refcount
char name[CTL_DRIVER_NAME_LEN]
char initiator_alias[CTL_ISCSI_ALIAS_LEN]
int max_recv_data_segment_length
int max_send_data_segment_length
ctl_iscsi_digest data_digest
char target_name[CTL_ISCSI_NAME_LEN]
char initiator_addr[CTL_ISCSI_ADDR_LEN]
ctl_iscsi_digest header_digest
uint8_t initiator_isid[6]
char initiator_name[CTL_ISCSI_NAME_LEN]
char offload[CTL_ISCSI_OFFLOAD_LEN]
int max_send_data_segment_length
char offload[CTL_ISCSI_OFFLOAD_LEN]
int max_recv_data_segment_length
char initiator_name[CTL_ISCSI_NAME_LEN]
char initiator_addr[CTL_ISCSI_ADDR_LEN]
char initiator_name[CTL_ISCSI_NAME_LEN]
char initiator_addr[CTL_ISCSI_NAME_LEN]
char error_str[CTL_ERROR_STR_LEN]
union ctl_iscsi_data data
struct ctl_frontend * frontend
port_info_func_t port_info
void(* fe_datamove)(union ctl_io *io)
struct ctl_devid * port_devid
struct ctl_devid * target_devid
void(* fe_done)(union ctl_io *io)
char error_str[CTL_ERROR_STR_LEN]
struct scsi_sense_data sense_data
uint8_t cdb[CTL_MAX_CDBLEN]
ctl_task_type task_action