a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER START
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The contents of this file are subject to the terms of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Common Development and Distribution License (the "License").
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You may not use this file except in compliance with the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * or http://www.opensolaris.org/os/licensing.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * See the License for the specific language governing permissions
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and limitations under the License.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * When distributing Covered Code, include this CDDL HEADER in each
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If applicable, add the following below this CDDL HEADER, with the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fields enclosed by brackets "[]" replaced with your own identifying
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * information: Portions Copyright [yyyy] [name of copyright owner]
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * CDDL HEADER END
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Use is subject to license terms.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda/*
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda * Copyright (c) 2013 by Delphix. All rights reserved.
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/conf.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/stat.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/file.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/ddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sunddi.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/modctl.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/priv.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/cpuvar.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/socket.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/strsubr.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sysmacros.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sdt.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <netinet/tcp.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <inet/tcp.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/socketvar.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/pathname.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/fs/snode.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/fs/dv_node.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/vnode.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <netinet/in.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <net/if.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/sockio.h>
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning#include <sys/ksocket.h>
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States#include <sys/filio.h> /* FIONBIO */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting#include <sys/iscsi_protocol.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_so.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap#include <sys/idm/idm_text.h>
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China#define IN_PROGRESS_DELAY 1
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in6addr_any is currently all zeroes, but use the macro in case this
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * ever changes.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlapstatic const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningstatic idm_status_t idm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_conn_destroy_common(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_conn_connect_common(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
dedec472759b1a1a25044d504201ef59ccbffb56Jack Mengstatic void idm_set_ini_preconnect_options(idm_so_conn_t *sc,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng boolean_t boot_conn);
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Bisedastatic void idm_set_postconnect_options(ksocket_t so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_i_so_tx(idm_pdu_t *pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void idm_so_send_rtt_data(idm_conn_t *ic, idm_task_t *idt,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *idb, uint32_t offset, uint32_t length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void idm_so_send_rtt_data_done(idm_task_t *idt, idm_buf_t *idb);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t idm_so_send_buf_region(idm_task_t *idt,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb, uint32_t buf_region_offset, uint32_t buf_region_length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic uint32_t idm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t ro, uint32_t dlength);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_handle_digest(idm_conn_t *it,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvpair_t *digest_choice, const idm_kv_xlate_t *ikvx);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic void idm_so_socket_set_nonblock(struct sonode *node);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic void idm_so_socket_set_block(struct sonode *node);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Transport ops prototypes
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_free_task_rsrc(idm_task_t *idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic kv_status_t idm_so_negotiate_key_values(idm_conn_t *it,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void idm_so_notice_key_values(idm_conn_t *it,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvlist_t *negotiated_nvl);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Tingstatic kv_status_t idm_so_declare_key_values(idm_conn_t *it,
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvlist_t *config_nvl, nvlist_t *outgoing_nvl);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic boolean_t idm_so_conn_is_capable(idm_conn_req_t *ic,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_transport_caps_t *caps);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_buf_free(idm_buf_t *idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_buf_setup(idm_buf_t *idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_buf_teardown(idm_buf_t *idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_tgt_svc_destroy(idm_svc_t *is);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_tgt_svc_online(idm_svc_t *is);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_tgt_svc_offline(idm_svc_t *is);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_tgt_conn_destroy(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_tgt_conn_connect(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_conn_disconnect(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void idm_so_ini_conn_destroy(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t idm_so_ini_conn_connect(idm_conn_t *ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * IDM Native Sockets transport operations
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_transport_ops_t idm_so_transport_ops = {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tx, /* it_tx_pdu */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_tx_to_ini, /* it_buf_tx_to_ini */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_rx_from_ini, /* it_buf_rx_from_ini */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_rx_datain, /* it_rx_datain */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_rx_rtt, /* it_rx_rtt */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_rx_dataout, /* it_rx_dataout */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NULL, /* it_alloc_conn_rsrc */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NULL, /* it_free_conn_rsrc */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NULL, /* it_tgt_enable_datamover */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NULL, /* it_ini_enable_datamover */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap NULL, /* it_conn_terminate */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_free_task_rsrc, /* it_free_task_rsrc */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_negotiate_key_values, /* it_negotiate_key_values */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_notice_key_values, /* it_notice_key_values */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_is_capable, /* it_conn_is_capable */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_alloc, /* it_buf_alloc */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_free, /* it_buf_free */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_setup, /* it_buf_setup */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_buf_teardown, /* it_buf_teardown */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_svc_create, /* it_tgt_svc_create */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_svc_destroy, /* it_tgt_svc_destroy */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_svc_online, /* it_tgt_svc_online */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_svc_offline, /* it_tgt_svc_offline */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_conn_destroy, /* it_tgt_conn_destroy */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_tgt_conn_connect, /* it_tgt_conn_connect */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_disconnect, /* it_tgt_conn_disconnect */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_ini_conn_create, /* it_ini_conn_create */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_ini_conn_destroy, /* it_ini_conn_destroy */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_ini_conn_connect, /* it_ini_conn_connect */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting idm_so_conn_disconnect, /* it_ini_conn_disconnect */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting idm_so_declare_key_values /* it_declare_key_values */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap};
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Stateskmutex_t idm_so_timed_socket_mutex;
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Bisedaint32_t idm_so_sndbuf = IDM_SNDBUF_SIZE;
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Bisedaint32_t idm_so_rcvbuf = IDM_RCVBUF_SIZE;
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_init()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Sockets transport initialization
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_init(idm_transport_t *it)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Cache for IDM Data and R2T Transmit PDU's */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_sotx_pdu_cache = kmem_cache_create("idm_tx_pdu_cache",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sizeof (idm_pdu_t) + sizeof (iscsi_hdr_t), 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &idm_sotx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Cache for IDM Receive PDU's */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm.idm_sorx_pdu_cache = kmem_cache_create("idm_rx_pdu_cache",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sizeof (idm_pdu_t) + IDM_SORX_CACHE_HDRLEN, 8,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &idm_sorx_pdu_constructor, NULL, NULL, NULL, NULL, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap /* 128k buffer cache */
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap idm.idm_so_128k_buf_cache = kmem_cache_create("idm_128k_buf_cache",
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap IDM_SO_BUF_CACHE_UB, 8, NULL, NULL, NULL, NULL, NULL, KM_SLEEP);
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set the sockets transport ops */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->it_ops = &idm_so_transport_ops;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_init(&idm_so_timed_socket_mutex, NULL, MUTEX_DEFAULT, NULL);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_fini()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Sockets transport teardown
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_fini(void)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap kmem_cache_destroy(idm.idm_so_128k_buf_cache);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_cache_destroy(idm.idm_sotx_pdu_cache);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_cache_destroy(idm.idm_sorx_pdu_cache);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_destroy(&idm_so_timed_socket_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningksocket_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_socreate(int domain, int type, int protocol)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t ks;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (!ksocket_socket(&ks, domain, type, protocol, KSOCKET_NOSLEEP,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED())) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (ks);
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning } else {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning return (NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_soshutdown will disconnect the socket and prevent subsequent PDU
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * reception and transmission. The sonode still exists but its state
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * gets modified to indicate it is no longer connected. Calls to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sorecv/idm_iov_sorecv will return so idm_soshutdown can be used
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * regain control of a thread stuck in idm_sorecv.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_soshutdown(ksocket_t so)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_shutdown(so, SHUT_RDWR, CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sodestroy releases all resources associated with a socket previously
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * created with idm_socreate. The socket must be shutdown using
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_soshutdown before the socket is destroyed with idm_sodestroy,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * otherwise undefined behavior will result.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_sodestroy(ksocket_t ks)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_close(ks, CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap/*
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * Function to compare two addresses in sockaddr_storage format
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap */
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlapint
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlapidm_ss_compare(const struct sockaddr_storage *cmp_ss1,
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap const struct sockaddr_storage *cmp_ss2,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States boolean_t v4_mapped_as_v4,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States boolean_t compare_ports)
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap{
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap struct sockaddr_storage mapped_v4_ss1, mapped_v4_ss2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap const struct sockaddr_storage *ss1, *ss2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap struct in_addr *in1, *in2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap struct in6_addr *in61, *in62;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap int i;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap /*
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * Normalize V4-mapped IPv6 addresses into V4 format if
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * v4_mapped_as_v4 is B_TRUE.
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap */
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ss1 = cmp_ss1;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ss2 = cmp_ss2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (v4_mapped_as_v4 && (ss1->ss_family == AF_INET6)) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in61 = &((struct sockaddr_in6 *)ss1)->sin6_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (IN6_IS_ADDR_V4MAPPED(in61)) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap bzero(&mapped_v4_ss1, sizeof (mapped_v4_ss1));
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap mapped_v4_ss1.ss_family = AF_INET;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ((struct sockaddr_in *)&mapped_v4_ss1)->sin_port =
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ((struct sockaddr_in *)ss1)->sin_port;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap IN6_V4MAPPED_TO_INADDR(in61,
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap &((struct sockaddr_in *)&mapped_v4_ss1)->sin_addr);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ss1 = &mapped_v4_ss1;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ss2 = cmp_ss2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (v4_mapped_as_v4 && (ss2->ss_family == AF_INET6)) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in62 = &((struct sockaddr_in6 *)ss2)->sin6_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (IN6_IS_ADDR_V4MAPPED(in62)) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap bzero(&mapped_v4_ss2, sizeof (mapped_v4_ss2));
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap mapped_v4_ss2.ss_family = AF_INET;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ((struct sockaddr_in *)&mapped_v4_ss2)->sin_port =
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ((struct sockaddr_in *)ss2)->sin_port;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap IN6_V4MAPPED_TO_INADDR(in62,
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap &((struct sockaddr_in *)&mapped_v4_ss2)->sin_addr);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ss2 = &mapped_v4_ss2;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap /*
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * Compare ports, then address family, then ip address
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (compare_ports &&
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (((struct sockaddr_in *)ss1)->sin_port !=
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ((struct sockaddr_in *)ss2)->sin_port)) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (((struct sockaddr_in *)ss1)->sin_port >
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap ((struct sockaddr_in *)ss2)->sin_port)
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap else
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (-1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap /*
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * ports are the same
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap */
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (ss1->ss_family != ss2->ss_family) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (ss1->ss_family == AF_INET)
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap else
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (-1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap /*
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap * address families are the same
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap */
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (ss1->ss_family == AF_INET) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in1 = &((struct sockaddr_in *)ss1)->sin_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in2 = &((struct sockaddr_in *)ss2)->sin_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (in1->s_addr > in2->s_addr)
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap else if (in1->s_addr < in2->s_addr)
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (-1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap else
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (0);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap } else if (ss1->ss_family == AF_INET6) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in61 = &((struct sockaddr_in6 *)ss1)->sin6_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap in62 = &((struct sockaddr_in6 *)ss2)->sin6_addr;
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap for (i = 0; i < 4; i++) {
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap if (in61->s6_addr32[i] > in62->s6_addr32[i])
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap else if (in61->s6_addr32[i] < in62->s6_addr32[i])
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (-1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (0);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap }
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap return (1);
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap}
e42a0851889d583925aa3bd2d9bd139189031cb0peter dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * IP address filter functions to flag addresses that should not
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * go out to initiators through discovery.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic boolean_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_v4_addr_okay(struct in_addr *in_addr)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap in_addr_t addr = ntohl(in_addr->s_addr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((INADDR_NONE == addr) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN_MULTICAST(addr)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((addr >> IN_CLASSA_NSHIFT) == 0) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_FALSE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic boolean_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_v6_addr_okay(struct in6_addr *addr6)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((IN6_IS_ADDR_UNSPECIFIED(addr6)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN6_IS_ADDR_LOOPBACK(addr6)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN6_IS_ADDR_MULTICAST(addr6)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN6_IS_ADDR_V4MAPPED(addr6)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN6_IS_ADDR_V4COMPAT(addr6)) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IN6_IS_ADDR_LINKLOCAL(addr6))) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_FALSE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_get_ipaddr will retrieve a list of IP Addresses which the host is
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * configured with by sending down a sequence of kernel ioctl to IP STREAMS.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_get_ipaddr(idm_addr_list_t **ipaddr_p)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t so4, so6;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct lifnum lifn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct lifconf lifc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct lifreq *lp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rval;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int numifs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int bufsize;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap void *buf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int i, j, n, rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr_storage ss;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr_in *sin;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr_in6 *sin6;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_addr_t *ip;
fcc214c383d20beb968b623b83d851672e174702Charles Ting idm_addr_list_t *ipaddr = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int size_ipaddr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *ipaddr_p = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_ipaddr = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap buf = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* create an ipv4 and ipv6 UDP socket */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((so6 = idm_socreate(PF_INET6, SOCK_DGRAM, 0)) == NULL)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((so4 = idm_socreate(PF_INET, SOCK_DGRAM, 0)) == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so6);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapretry_count:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* snapshot the current number of interfaces */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifn.lifn_family = PF_UNSPEC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifn.lifn_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifn.lifn_count = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning /* use vp6 for ioctls with unspecified families by default */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (ksocket_ioctl(so6, SIOCGLIFNUM, (intptr_t)&lifn, &rval, CRED())
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap numifs = lifn.lifn_count;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (numifs <= 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* allocate extra room in case more interfaces appear */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap numifs += 10;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* get the interface names and ip addresses */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bufsize = numifs * sizeof (struct lifreq);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap buf = kmem_alloc(bufsize, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifc.lifc_family = AF_UNSPEC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifc.lifc_flags = LIFC_NOXMIT | LIFC_TEMPORARY | LIFC_ALLZONES;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifc.lifc_len = bufsize;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap lifc.lifc_buf = buf;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning rc = ksocket_ioctl(so6, SIOCGLIFCONF, (intptr_t)&lifc, &rval, CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* if our extra room is used up, try again */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (bufsize <= lifc.lifc_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(buf, bufsize);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap buf = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto retry_count;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* calc actual number of ifconfs */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap n = lifc.lifc_len / sizeof (struct lifreq);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* get ip address */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (n > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_ipaddr = sizeof (idm_addr_list_t) +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (n - 1) * sizeof (idm_addr_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ipaddr = kmem_zalloc(size_ipaddr, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto cleanup;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Examine the array of interfaces and filter uninteresting ones
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (i = 0, j = 0, lp = lifc.lifc_req; i < n; i++, lp++) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Copy the address as the SIOCGLIFFLAGS ioctl is destructive
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ss = lp->lifr_addr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * fetch the flags using the socket of the correct family
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (ss.ss_family) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case AF_INET:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning rc = ksocket_ioctl(so4, SIOCGLIFFLAGS, (intptr_t)lp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &rval, CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case AF_INET6:
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning rc = ksocket_ioctl(so6, SIOCGLIFFLAGS, (intptr_t)lp,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &rval, CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If we got the flags, skip uninteresting
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * interfaces based on flags
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((lp->lifr_flags & IFF_UP) != IFF_UP)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (lp->lifr_flags &
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IFF_ANYCAST|IFF_NOLOCAL|IFF_DEPRECATED))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* save ip address */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ip = &ipaddr->al_addrs[j];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (ss.ss_family) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case AF_INET:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sin = (struct sockaddr_in *)&ss;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!idm_v4_addr_okay(&sin->sin_addr))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ip->a_addr.i_addr.in4 = sin->sin_addr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ip->a_addr.i_insize = sizeof (struct in_addr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case AF_INET6:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sin6 = (struct sockaddr_in6 *)&ss;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!idm_v6_addr_okay(&sin6->sin6_addr))
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ip->a_addr.i_addr.in6 = sin6->sin6_addr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ip->a_addr.i_insize = sizeof (struct in6_addr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap j++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (j == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* no valid ifaddr */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(ipaddr, size_ipaddr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_ipaddr = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ipaddr = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ipaddr->al_out_cnt = j;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapcleanup:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so6);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so4);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (buf != NULL)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(buf, bufsize);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *ipaddr_p = ipaddr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (size_ipaddr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_sorecv(ksocket_t so, void *msg, size_t len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovec_t iov;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(so != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(len != 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Fill in iovec and receive data
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov.iov_base = msg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov.iov_len = len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (idm_iov_sorecv(so, &iov, 1, len));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sosendto - Sends a buffered data on a non-connected socket.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function puts the data provided on the wire by calling sosendmsg.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * It will return only when all the data has been sent or if an error
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * occurs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Returns 0 for success, the socket errno value if sosendmsg fails, and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * -1 if sosendmsg returns success but uio_resid != 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_sosendto(ksocket_t so, void *buff, size_t len,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr *name, socklen_t namelen)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct msghdr msg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct iovec iov[1];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t sent = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[0].iov_base = buff;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[0].iov_len = len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Initialization of the message header. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(&msg, sizeof (msg));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iov = iov;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iovlen = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_name = name;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_namelen = namelen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED())) == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Data sent */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sent == len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* All data sent. Success. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Not all data was sent. Failure */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Send failed */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (error);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_iov_sosend - Sends an iovec on a connection.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function puts the data provided on the wire by calling sosendmsg.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * It will return only when all the data has been sent or if an error
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * occurs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Returns 0 for success, the socket errno value if sosendmsg fails, and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * -1 if sosendmsg returns success but uio_resid != 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_iov_sosend(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct msghdr msg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t sent = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(iop != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Initialization of the message header. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(&msg, sizeof (msg));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iov = iop;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iovlen = iovlen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = ksocket_sendmsg(so, &msg, 0, &sent, CRED()))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Data sent */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (sent == total_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* All data sent. Success. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Not all data was sent. Failure */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Send failed */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (error);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_iov_sorecv - Receives an iovec from a connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function gets the data asked for from the socket. It will return
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * only when all the requested data has been retrieved or if an error
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * occurs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Returns 0 for success, the socket errno value if sorecvmsg fails, and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * -1 if sorecvmsg returns success but uio_resid != 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_iov_sorecv(ksocket_t so, iovec_t *iop, int iovlen, size_t total_len)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct msghdr msg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int error;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning size_t recv;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning int flags;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(iop != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Initialization of the message header. */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(&msg, sizeof (msg));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iov = iop;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap msg.msg_iovlen = iovlen;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning flags = MSG_WAITALL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((error = ksocket_recvmsg(so, &msg, flags, &recv, CRED()))
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Received data */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (recv == total_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* All requested data received. Success */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Not all data was received. The connection has
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * probably failed.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (-1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Receive failed */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (error);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
dedec472759b1a1a25044d504201ef59ccbffb56Jack Mengidm_set_ini_preconnect_options(idm_so_conn_t *sc, boolean_t boot_conn)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int conn_abort = 10000;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int conn_notify = 2000;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int abort = 30000;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Pre-connect socket options */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning TCP_CONN_NOTIFY_THRESHOLD, (char *)&conn_notify, sizeof (int),
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning CRED());
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng if (boot_conn == B_FALSE) {
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng TCP_CONN_ABORT_THRESHOLD, (char *)&conn_abort, sizeof (int),
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng CRED());
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng (void) ksocket_setsockopt(sc->ic_so, IPPROTO_TCP,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng TCP_ABORT_THRESHOLD,
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng (char *)&abort, sizeof (int), CRED());
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Bisedaidm_set_postconnect_options(ksocket_t ks)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const int on = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set connect options */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(ks, SOL_SOCKET, SO_RCVBUF,
f99db78fa089c50b0d8fcef75f99d7a7f2e27ddaChristopher Siden (char *)&idm_so_rcvbuf, sizeof (idm_so_rcvbuf), CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(ks, SOL_SOCKET, SO_SNDBUF,
f99db78fa089c50b0d8fcef75f99d7a7f2e27ddaChristopher Siden (char *)&idm_so_sndbuf, sizeof (idm_so_sndbuf), CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(ks, IPPROTO_TCP, TCP_NODELAY,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (char *)&on, sizeof (on), CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic uint32_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapn2h24(const uchar_t *ptr)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return ((ptr[0] << 16) | (ptr[1] << 8) | ptr[2]);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorecvhdr(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_hdr_t *bhs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t hdr_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t crc_calculated;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap void *new_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int ahslen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int total_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int iovlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct iovec iov[2];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Read BHS
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs = pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = idm_sorecv(so_conn->ic_so, pdu->isp_hdr, sizeof (iscsi_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Check actual AHS length against the amount available in the buffer
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdrlen = sizeof (iscsi_hdr_t) +
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (bhs->hlength * sizeof (uint32_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_datalen = n2h24(bhs->dlength);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting if (ic->ic_conn_type == CONN_TYPE_TGT &&
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting pdu->isp_datalen > ic->ic_conn_params.max_recv_dataseglen) {
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting IDM_CONN_LOG(CE_WARN,
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting "idm_sorecvhdr: exceeded the max data segment length");
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting return (IDM_STATUS_FAIL);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (bhs->hlength > IDM_SORX_CACHE_AHSLEN) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Allocate a new header segment and change the callback */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap new_hdr = kmem_alloc(pdu->isp_hdrlen, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bcopy(pdu->isp_hdr, new_hdr, sizeof (iscsi_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdr = new_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_flags |= IDM_PDU_ADDL_HDR;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This callback will restore the expected values after
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the RX PDU has been processed.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_callback = idm_sorx_addl_pdu_cb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Setup receipt of additional header and header digest (if enabled).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (bhs->hlength > 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)(pdu->isp_hdr + 1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ahslen = pdu->isp_hdrlen - sizeof (iscsi_hdr_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = ahslen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)&hdr_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = sizeof (hdr_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((iovlen != 0) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (idm_iov_sorecv(so_conn->ic_so, &iov[0], iovlen,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len) != 0)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Validate header digest if enabled
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc_calculated = idm_crc32c(pdu->isp_hdr,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sizeof (iscsi_hdr_t) + ahslen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (crc_calculated != hdr_digest_crc) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Invalid Header Digest */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_HEADER_DIGEST);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_ini_conn_create()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Allocate the sockets transport connection resources.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_ini_conn_create(idm_conn_req_t *cr, idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t so;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t idmrc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so = idm_socreate(cr->cr_domain, cr->cr_type,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cr->cr_protocol);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (so == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Bind the socket if configured to do so */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (cr->cr_bound) {
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (ksocket_bind(so, &cr->cr_bound_addr.sin,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SIZEOF_SOCKADDR(&cr->cr_bound_addr.sin), CRED()) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idmrc = idm_so_conn_create_common(ic, so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idmrc != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set up socket options */
dedec472759b1a1a25044d504201ef59ccbffb56Jack Meng idm_set_ini_preconnect_options(so_conn, cr->cr_boot_conn);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_ini_conn_destroy()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Tear down the sockets transport connection resources.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_ini_conn_destroy(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_destroy_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_ini_conn_connect()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Establish the connection referred to by the handle previously allocated via
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_ini_conn_create().
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_ini_conn_connect(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China struct sonode *node = NULL;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China int rc;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China clock_t lbolt, conn_login_max, conn_login_interval;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China boolean_t nonblock;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China nonblock = ic->ic_conn_params.nonblock_socket;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China conn_login_max = ic->ic_conn_params.conn_login_max;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China conn_login_interval = ddi_get_lbolt() +
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(ic->ic_conn_params.conn_login_interval);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (nonblock == B_TRUE) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China node = ((struct sonode *)(so_conn->ic_so));
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* Set to none block socket mode */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China idm_so_socket_set_nonblock(node);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China do {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China rc = ksocket_connect(so_conn->ic_so,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China &ic->ic_ini_dst_addr.sin,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (SIZEOF_SOCKADDR(&ic->ic_ini_dst_addr.sin)),
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China CRED());
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (rc == 0 || rc == EISCONN) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* socket success or already success */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China rc = IDM_STATUS_SUCCESS;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China break;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if ((rc == ETIMEDOUT) || (rc == ECONNREFUSED) ||
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (rc == ECONNRESET)) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* socket connection timeout or refuse */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China break;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China lbolt = ddi_get_lbolt();
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (lbolt > conn_login_max) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /*
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China * Connection retry timeout,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China * failed connect to target.
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China break;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (lbolt < conn_login_interval) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if ((rc == EINPROGRESS) || (rc == EALREADY)) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* TCP connect still in progress */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China delay(SEC_TO_TICK(IN_PROGRESS_DELAY));
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China continue;
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China } else {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China delay(conn_login_interval - lbolt);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China conn_login_interval = ddi_get_lbolt() +
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China SEC_TO_TICK(ic->ic_conn_params.conn_login_interval);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China } while (rc != 0);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China /* resume to nonblock mode */
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (rc == IDM_STATUS_SUCCESS) {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China idm_so_socket_set_block(node);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China } else {
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China rc = ksocket_connect(so_conn->ic_so, &ic->ic_ini_dst_addr.sin,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (SIZEOF_SOCKADDR(&ic->ic_ini_dst_addr.sin)), CRED());
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China if (rc != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(so_conn->ic_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_connect_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda idm_set_postconnect_options(so_conn->ic_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_so_tgt_conn_create(idm_conn_t *ic, ksocket_t new_so)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t idmrc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda idm_set_postconnect_options(new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idmrc = idm_so_conn_create_common(ic, new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (idmrc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_conn_destroy(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_destroy_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tgt_conn_connect()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Establish the connection in ic, passed from idm_tgt_conn_finish(), which
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * is invoked from the SM as a result of an inbound connection request.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_conn_connect(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_connect_common(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangningidm_so_conn_create_common(idm_conn_t *ic, ksocket_t new_so)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = kmem_zalloc(sizeof (idm_so_conn_t), KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_so = new_so;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_private = so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_hdrlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set the scoreboarding flag on this connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_conn_flags |= IDM_CONN_USE_SCOREBOARD;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ic->ic_conn_params.max_recv_dataseglen =
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ISCSI_DEFAULT_MAX_RECV_SEG_LEN;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ic->ic_conn_params.max_xmit_dataseglen =
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ISCSI_DEFAULT_MAX_XMIT_SEG_LEN;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Initialize tx thread mutex and list
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_init(&so_conn->ic_tx_mutex, NULL, MUTEX_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_init(&so_conn->ic_tx_cv, NULL, CV_DEFAULT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_create(&so_conn->ic_tx_list, sizeof (idm_pdu_t),
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offsetof(idm_pdu_t, idm_tx_link));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_conn_destroy_common(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic->ic_transport_private = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so_conn->ic_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_destroy(&so_conn->ic_tx_list);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_destroy(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_destroy(&so_conn->ic_tx_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(so_conn, sizeof (idm_so_conn_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_conn_connect_common(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sockaddr_in6 t_addr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t t_addrlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(&t_addr, sizeof (struct sockaddr_in6));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_addrlen = sizeof (struct sockaddr_in6);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set the local and remote addresses in the idm conn handle */
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ksocket_getsockname(so_conn->ic_so, (struct sockaddr *)&t_addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &t_addrlen, CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bcopy(&t_addr, &ic->ic_laddr, t_addrlen);
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ksocket_getpeername(so_conn->ic_so, (struct sockaddr *)&t_addr,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &t_addrlen, CRED());
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bcopy(&t_addr, &ic->ic_raddr, t_addrlen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread = thread_create(NULL, 0, idm_sotx_thread, ic, 0,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &p0, TS_RUN, minclsyspri);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread = thread_create(NULL, 0, idm_sorx_thread, ic, 0,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &p0, TS_RUN, minclsyspri);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States while (so_conn->ic_rx_thread_did == 0 ||
e97fb1537da57d70dafde456e25bbd6bcc839475Peter Cudhea - Sun Microsystems - Burlington, MA United States so_conn->ic_tx_thread_did == 0)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_wait(&ic->ic_cv, &ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_conn_disconnect()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Shutdown the socket connection and stop the thread
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_conn_disconnect(idm_conn_t *ic)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* We need to wakeup the TX thread */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&so_conn->ic_tx_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* This should wakeup the RX thread if it is sleeping */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(so_conn->ic_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_join(so_conn->ic_tx_thread_did);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_join(so_conn->ic_rx_thread_did);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tgt_svc_create()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Establish a service on an IP address and port. idm_svc_req_t contains
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the service parameters.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*ARGSUSED*/
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_svc_create(idm_svc_req_t *sr, idm_svc_t *is)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_svc_t *so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc = kmem_zalloc(sizeof (idm_so_svc_t), KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set the new sockets service in svc handle */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap is->is_so_svc = (void *)so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tgt_svc_destroy()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Teardown sockets resources allocated in idm_so_tgt_svc_create()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_svc_destroy(idm_svc_t *is)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* the socket will have been torn down; free the service */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(is->is_so_svc, sizeof (idm_so_svc_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tgt_svc_online()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Launch a watch thread on the svc allocated in idm_so_tgt_svc_create()
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_svc_online(idm_svc_t *is)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_svc_t *so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_svc_req_t *sr = &is->is_svc_req;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct sockaddr_in6 sin6_ip;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const uint32_t on = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const uint32_t off = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc = (idm_so_svc_t *)is->is_so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Try creating an IPv6 socket first
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((so_svc->is_so = idm_socreate(PF_INET6, SOCK_STREAM, 0)) == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(&sin6_ip, sizeof (sin6_ip));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sin6_ip.sin6_family = AF_INET6;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sin6_ip.sin6_port = htons(sr->sr_port);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sin6_ip.sin6_addr = in6addr_any;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_REUSEADDR, (char *)&on, sizeof (on), CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Turn off SO_MAC_EXEMPT so future sobinds succeed
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(so_svc->is_so, SOL_SOCKET,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning SO_MAC_EXEMPT, (char *)&off, sizeof (off), CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (ksocket_bind(so_svc->is_so, (struct sockaddr *)&sin6_ip,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning sizeof (sin6_ip), CRED()) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f94976e74ac54bd0c370887c9aa0838c90b539eJeff Biseda idm_set_postconnect_options(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if (ksocket_listen(so_svc->is_so, 5, CRED()) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Launch a watch thread */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc->is_thread = thread_create(NULL, 0, idm_so_svc_port_watcher,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap is, 0, &p0, TS_RUN, minclsyspri);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (so_svc->is_thread == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Failure to launch; teardown the socket */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_hold(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Wait for the port watcher thread to start */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (!so_svc->is_thread_running)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_wait(&is->is_cv, &is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tgt_svc_offline
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Stop listening on the IP address and port identified by idm_svc_t.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tgt_svc_offline(idm_svc_t *is)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_svc_t *so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc = (idm_so_svc_t *)is->is_so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc->is_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&is->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning * Teardown socket
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning idm_sodestroy(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Now we expect the port watcher thread to terminate
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_join(so_svc->is_thread_did);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Watch thread for target service connection establishment.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_svc_port_watcher(void *arg)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_svc_t *svc = arg;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_t new_so;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t idmrc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_svc_t *so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const uint32_t off = 0;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning struct sockaddr_in6 t_addr;
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning socklen_t t_addrlen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning bzero(&t_addr, sizeof (struct sockaddr_in6));
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning t_addrlen = sizeof (struct sockaddr_in6);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc = svc->is_so_svc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc->is_thread_running = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc->is_thread_did = so_svc->is_thread->t_did;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&svc->is_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) online", (void *)svc,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap svc->is_svc_req.sr_port);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (so_svc->is_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning if ((rc = ksocket_accept(so_svc->is_so,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (struct sockaddr *)&t_addr, &t_addrlen,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning &new_so, CRED())) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&svc->is_mutex);
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda if (rc != ECONNABORTED && rc != EINTR) {
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda IDM_SVC_LOG(CE_NOTE, "idm_so_svc_port_watcher:"
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda " ksocket_accept failed %d", rc);
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda }
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda /*
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda * Unclean shutdown of this thread is not handled
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda * wait for !is_thread_running.
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda */
57ff5e7e2f79bd09ccd01cdeba02f38fdde17a80Jeff Biseda continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Turn off SO_MAC_EXEMPT so future sobinds succeed
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (void) ksocket_setsockopt(new_so, SOL_SOCKET, SO_MAC_EXEMPT,
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning (char *)&off, sizeof (off), CRED());
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idmrc = idm_svc_conn_create(svc, IDM_TRANSPORT_TYPE_SOCKETS,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idmrc != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Drop connection */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idmrc = idm_so_tgt_conn_create(ic, new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idmrc != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_svc_conn_destroy(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_soshutdown(new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sodestroy(new_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Kick the state machine. At CS_S3_XPT_UP the state machine
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * will notify the client (target) about the new connection.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event(ic, CE_CONNECT_ACCEPT, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
0f1702c5201310f0529cd5abb77652e5e9b241b6Yu Xiangning ksocket_rele(so_svc->is_so);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_svc->is_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&svc->is_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_SVC_LOG(CE_NOTE, "iSCSI service (%p/%d) offline", (void *)svc,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap svc->is_svc_req.sr_port);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_exit();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_free_task_rsrc() stops any ongoing processing of the task and
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * frees resources associated with the task.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * It's not clear that this should return idm_status_t. What do we do
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * if it fails?
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_free_task_rsrc(idm_task_t *idt)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States idm_buf_t *idb, *next_idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * There is nothing to cleanup on initiator connections
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (IDM_CONN_ISINI(idt->idt_ic))
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (IDM_STATUS_SUCCESS);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If this is a target connection, call idm_buf_rx_from_ini_done for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * any buffer on the "outbufv" list with idb->idb_in_transport==B_TRUE.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * In addition, remove any buffers associated with this task from
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the ic_tx_list. We'll do this by walking the idt_inbufv list, but
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * items don't actually get removed from that list (and completion
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * routines called) until idm_task_cleanup.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States for (idb = list_head(&idt->idt_outbufv); idb != NULL; idb = next_idb) {
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States next_idb = list_next(&idt->idt_outbufv, idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb->idb_in_transport) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_buf_rx_from_ini_done releases idt->idt_mutex
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_RX_FROM_INI);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States for (idb = list_head(&idt->idt_inbufv); idb != NULL; idb = next_idb) {
92adbba74606fdfb5f11be2a6497e53ff2224507Peter Cudhea - Sun Microsystems - Burlington, MA United States next_idb = list_next(&idt->idt_inbufv, idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * We want to remove these items from the tx_list as well,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * but knowing it's in the idt_inbufv list is not a guarantee
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * that it's in the tx_list. If it's on the tx list then
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * let idm_sotx_thread() clean it up.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb->idb_in_transport && !idb->idb_tx_thread) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_buf_tx_to_ini_done releases idt->idt_mutex
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_TX_TO_INI);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_negotiate_key_values() validates the key values for this connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic kv_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_negotiate_key_values(idm_conn_t *it, nvlist_t *request_nvl,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvlist_t *response_nvl, nvlist_t *negotiated_nvl)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* All parameters are negotiated at the iscsit level */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (KV_HANDLED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_notice_key_values() activates the negotiated key values for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * this connection.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_notice_key_values(idm_conn_t *it, nvlist_t *negotiated_nvl)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *nvp_name;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvpair_t *nvp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvpair_t *next_nvp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int nvrc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t idm_status;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const idm_kv_xlate_t *ikvx;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting uint64_t num_val;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap for (nvp = nvlist_next_nvpair(negotiated_nvl, NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvp != NULL; nvp = next_nvp) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap next_nvp = nvlist_next_nvpair(negotiated_nvl, nvp);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvp_name = nvpair_name(nvp);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (ikvx->ik_key_id) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_HEADER_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_DATA_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status = idm_so_handle_digest(it, nvp, ikvx);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(idm_status == 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Remove processed item from negotiated_nvl list */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvrc = nvlist_remove_all(
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap negotiated_nvl, ikvx->ik_key_name);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(nvrc == 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting case KI_MAX_RECV_DATA_SEGMENT_LENGTH:
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting /*
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting * Just pass the value down to idm layer.
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting * No need to remove it from negotiated_nvl list here.
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvrc = nvpair_value_uint64(nvp, &num_val);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ASSERT(nvrc == 0);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting it->ic_conn_params.max_xmit_dataseglen =
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting (uint32_t)num_val;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting/*
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting * idm_so_declare_key_values() declares the key values for this connection
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting/* ARGSUSED */
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Tingstatic kv_status_t
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Tingidm_so_declare_key_values(idm_conn_t *it, nvlist_t *config_nvl,
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvlist_t *outgoing_nvl)
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting{
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting char *nvp_name;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvpair_t *nvp;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvpair_t *next_nvp;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting kv_status_t kvrc;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting int nvrc = 0;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting const idm_kv_xlate_t *ikvx;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting uint64_t num_val;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting for (nvp = nvlist_next_nvpair(config_nvl, NULL);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvp != NULL && nvrc == 0; nvp = next_nvp) {
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting next_nvp = nvlist_next_nvpair(config_nvl, nvp);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvp_name = nvpair_name(nvp);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting ikvx = idm_lookup_kv_xlate(nvp_name, strlen(nvp_name));
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting switch (ikvx->ik_key_id) {
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting case KI_MAX_RECV_DATA_SEGMENT_LENGTH:
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting if ((nvrc = nvpair_value_uint64(nvp, &num_val)) != 0) {
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting break;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting }
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting if (outgoing_nvl &&
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting (nvrc = nvlist_add_uint64(outgoing_nvl,
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting nvp_name, num_val)) != 0) {
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting break;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting }
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting it->ic_conn_params.max_recv_dataseglen =
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting (uint32_t)num_val;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting break;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting default:
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting break;
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting }
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting }
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting kvrc = idm_nvstat_to_kvstat(nvrc);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting return (kvrc);
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_handle_digest(idm_conn_t *it, nvpair_t *digest_choice,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap const idm_kv_xlate_t *ikvx)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int nvrc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap char *digest_choice_string;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap nvrc = nvpair_value_string(digest_choice,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &digest_choice_string);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(nvrc == 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (strcasecmp(digest_choice_string, "crc32c") == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (ikvx->ik_key_id) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_HEADER_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->ic_conn_flags |= IDM_CONN_HEADER_DIGEST;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_DATA_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->ic_conn_flags |= IDM_CONN_DATA_DIGEST;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else if (strcasecmp(digest_choice_string, "none") == 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (ikvx->ik_key_id) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_HEADER_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->ic_conn_flags &= ~IDM_CONN_HEADER_DIGEST;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case KI_DATA_DIGEST:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap it->ic_conn_flags &= ~IDM_CONN_DATA_DIGEST;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_conn_is_capable() verifies that the passed connection is provided
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * for by the sockets interface.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic boolean_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_conn_is_capable(idm_conn_req_t *ic, idm_transport_caps_t *caps)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (B_TRUE);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_rx_datain() validates the Data Sequence number of the PDU. The
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sorecv_scsidata() function invoked earlier actually reads the data
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * off the socket into the appropriate buffers.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_rx_datain(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_hdr_t *bhs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t datasn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_t offset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_hdr_t *ihp = (iscsi_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_rsp_hdr_t *idrhp = (iscsi_data_rsp_hdr_t *)ihp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(ic != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap datasn = ntohl(bhs->datasn);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset = ntohl(bhs->offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA_RSP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Look up the task corresponding to the initiator task tag
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to get the buffers affiliated with the task.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt = idm_task_find(ic, bhs->itt, bhs->ttt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idt == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: failed to find task");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb = pdu->isp_sorx_buf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_so_rx_datain: failed to find buffer");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * DataSN values should be sequential and should not have any gaps or
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * repetitions. Check the DataSN with the one stored in the task.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (datasn == idt->idt_exp_datasn) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt->idt_exp_datasn++; /* keep track of DataSN received */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: datasn out of order");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * PDUs in a sequence should be in continuously increasing
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * address offset
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (offset != idb->idb_exp_offset) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_datain: unexpected offset");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Expected next relative buffer offset */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb->idb_exp_offset += n2h24(bhs->dlength);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idt->idt_rx_bytes += n2h24(bhs->dlength);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For now call scsi_rsp which will process the data rsp
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Revisit, need to provide an explicit client entry point for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * phase collapse completions.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (((ihp->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_SCSI_DATA_RSP) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (idrhp->flags & ISCSI_FLAG_DATA_STATUS)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*ic->ic_conn_ops.icb_rx_scsi_rsp)(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The idm_so_rx_dataout() function is used by the iSCSI target to read
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * data from the Data-Out PDU sent by the iSCSI initiator.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This function gets the Initiator Task Tag from the PDU BHS and looks up the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * task to get the buffers associated with the PDU. A PDU might span buffers.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The data is then read into the respective buffer.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_rx_dataout(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_hdr_t *bhs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_t offset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(ic != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset = ntohl(bhs->offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(bhs->opcode == ISCSI_OP_SCSI_DATA);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Look up the task corresponding to the initiator task tag
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to get the buffers affiliated with the task.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt = idm_task_find(ic, bhs->itt, bhs->ttt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idt == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_so_rx_dataout: failed to find task");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb = pdu->isp_sorx_buf;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_so_rx_dataout: failed to find buffer");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Keep track of data transferred - check data offsets */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (offset != idb->idb_exp_offset) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_NOTE, "idm_so_rx_dataout: offset out of seq: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "%ld, %d", offset, idb->idb_exp_offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Expected next relative offset */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb->idb_exp_offset += ntoh24(bhs->dlength);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idt->idt_rx_bytes += n2h24(bhs->dlength);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Call the buffer callback when the transfer is complete
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The connection state machine should only abort tasks after
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * shutting down the connection so we are assured that there
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * won't be a simultaneous attempt to abort this task at the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * same time as we are processing this PDU (due to a connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * state change).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (bhs->flags & ISCSI_FLAG_FINAL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * We only want to call idm_buf_rx_from_ini_done once
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * per transfer. It's possible that this task has
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * already been aborted in which case
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_free_task_rsrc will call idm_buf_rx_from_ini_done
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * for each buffer with idb_in_transport==B_TRUE. To
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * close this window and ensure that this doesn't happen,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we'll clear idb->idb_in_transport now while holding
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the task mutex. This is only really an issue for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * SCSI task abort -- if tasks were being aborted because
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * of a connection state change the state machine would
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * have already stopped the receive thread.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Release the task hold here (obtained in idm_task_find)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * because the task may complete synchronously during
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_buf_rx_from_ini_done. Since we still have an active
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * buffer we know there is at least one additional hold on idt.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_buf_rx_from_ini_done releases idt->idt_mutex
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf, uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_RX_FROM_INI);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_rx_from_ini_done(idt, idb, IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The idm_so_rx_rtt() function is used by the iSCSI initiator to handle
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the R2T PDU sent by the iSCSI target indicating that it is ready to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * accept data. This gets the Initiator Task Tag (itt) from the PDU BHS
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and looks up the task in the task tree using the itt to get the output
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * buffers associated the task. The R2T PDU contains the offset of the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * requested data and the data length. This function then constructs a
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * sequence of iSCSI PDUs and outputs the requested data. Each Data-Out
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * PDU is associated with the R2T by the Target Transfer Tag (ttt).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_rx_rtt(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_rtt_hdr_t *rtt_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t data_offset;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t data_length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(ic != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt_hdr = (iscsi_rtt_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap data_offset = ntohl(rtt_hdr->data_offset);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap data_length = ntohl(rtt_hdr->data_length);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt = idm_task_find(ic, rtt_hdr->itt, rtt_hdr->ttt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idt == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find task");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Find the buffer bound to the task by the iSCSI initiator */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb = idm_buf_find(&idt->idt_outbufv, data_offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: could not find buffer");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* return buffer contains this data */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (data_offset + data_length > idb->idb_buflen) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Overflow */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap IDM_CONN_LOG(CE_WARN, "idm_so_rx_rtt: read from outside "
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap "buffer");
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_rx_protocol_error(ic, pdu);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idt->idt_r2t_ttt = rtt_hdr->ttt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idt->idt_exp_datasn = 0;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_so_send_rtt_data(ic, idt, idb, data_offset,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ntohl(rtt_hdr->data_length));
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng /*
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng * the idt_mutex is released in idm_so_send_rtt_data
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorecvdata(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t pad[ISCSI_PAD_WORD_LEN];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int pad_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t data_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t crc_calculated;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int total_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pad_len = ((ISCSI_PAD_WORD_LEN -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) &
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (ISCSI_PAD_WORD_LEN - 1));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu->isp_iovlen < (PDU_MAX_IOVLEN - 2)); /* pad + data digest */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len = pdu->isp_datalen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pad_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_base = (char *)&pad;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_len = pad_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += pad_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* setup data digest */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_base =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (char *)&data_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_len =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap sizeof (data_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += sizeof (data_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap pdu->isp_data = (uint8_t *)(uintptr_t)pdu->isp_iov[0].iov_base;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idm_iov_sorecv(so_conn->ic_so, &pdu->isp_iov[0],
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen, total_len) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_IO);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc_calculated = idm_crc32c(pdu->isp_data,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_datalen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pad_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap crc_calculated = idm_crc32c_continued((char *)&pad,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pad_len, crc_calculated);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (crc_calculated != data_digest_crc) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_sorecvdata: "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "CRC error: actual 0x%x, calc 0x%x",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap data_digest_crc, crc_calculated);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Invalid Data Digest */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_DATA_DIGEST);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sorecv_scsidata() is used to receive scsi data from the socket. The
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Data-type PDU header must be read into the idm_pdu_t structure prior to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * calling this function.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorecv_scsidata(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_hdr_t *bhs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *task;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t offset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t opcode;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t dlength;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_t *buflst;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t xfer_bytes;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t status;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(ic != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs = (iscsi_data_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset = ntohl(bhs->offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap opcode = bhs->opcode;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap dlength = n2h24(bhs->dlength);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT((opcode == ISCSI_OP_SCSI_DATA_RSP) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (opcode == ISCSI_OP_SCSI_DATA));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Successful lookup implicitly gets a "hold" on the task. This
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * hold must be released before leaving this function. At one
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * point we were caching this task context and retaining the hold
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * but it turned out to be very difficult to release the hold properly.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The task can be aborted and the connection shutdown between this
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * call and the subsequent expected call to idm_so_rx_datain/
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_rx_dataout (in which case those functions are not called).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Releasing the hold in the PDU callback doesn't work well either
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * because the whole task may be completed by then at which point
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * it is too late to release the hold -- for better or worse this
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * code doesn't wait on the refcnts during normal operation.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_task_find() is very fast and it is not a huge burden if we
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * have to do it twice.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap task = idm_task_find(ic, bhs->itt, bhs->ttt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (task == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_sorecv_scsidata: could not find task");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&task->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap buflst = (opcode == ISCSI_OP_SCSI_DATA_RSP) ?
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap &task->idt_inbufv : &task->idt_outbufv;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_sorx_buf = idm_buf_find(buflst, offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&task->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_sorx_buf == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(task);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_sorecv_scsidata: could not find "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "buffer for offset %x opcode=%x",
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap offset, opcode);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap xfer_bytes = idm_fill_iov(pdu, pdu->isp_sorx_buf, offset, dlength);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(xfer_bytes != 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (xfer_bytes != dlength) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(task);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Buffer overflow, connection error. The PDU data is still
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * sitting in the socket so we can't use the connection
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * again until that data is drained.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap status = idm_sorecvdata(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_rele(task);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic uint32_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_fill_iov(idm_pdu_t *pdu, idm_buf_t *idb, uint32_t ro, uint32_t dlength)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t buf_ro = ro - idb->idb_bufoffset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t xfer_len = min(dlength, idb->idb_buflen - buf_ro);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(ro >= idb->idb_bufoffset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_base =
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (caddr_t)idb->idb_buf + buf_ro;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[pdu->isp_iovlen].iov_len = xfer_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (xfer_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorecv_nonscsidata(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_data = kmem_alloc(pdu->isp_datalen, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu->isp_data != NULL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_databuflen = pdu->isp_datalen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[0].iov_base = (caddr_t)pdu->isp_data;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iov[0].iov_len = pdu->isp_datalen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen = 1;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Since we are associating a new data buffer with this received
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * PDU we need to set a specific callback to free the data
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * after the PDU is processed.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_flags |= IDM_PDU_ADDL_DATA;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_callback = idm_sorx_addl_pdu_cb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (idm_sorecvdata(ic, pdu));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorx_thread(void *arg)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap boolean_t conn_failure = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic = (idm_conn_t *)arg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *pdu;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t rc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_hold(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread_running = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread_did = so_conn->ic_rx_thread->t_did;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&ic->ic_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (so_conn->ic_rx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Get PDU with default header size (large enough for
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * BHS plus any anticipated AHS). PDU from
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the cache will have all values set correctly
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * for sockets RX including callback.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu = kmem_cache_alloc(idm.idm_sorx_pdu_cache, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_ic = ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_flags = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_transport_hdrlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((rc = idm_sorecvhdr(ic, pdu)) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Call idm_pdu_complete so that we call the callback
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and ensure any memory allocated in idm_sorecvhdr
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * gets freed up.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If ic_rx_thread_running is still set then
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * this is some kind of connection problem
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * on the socket. In this case we want to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate an event. Otherwise some other
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * thread closed the socket due to another
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * issue in which case we don't need to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate an event.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (so_conn->ic_rx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap conn_failure = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Header has been read and validated. Now we need
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to read the PDU data payload (if present). SCSI data
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * need to be transferred from the socket directly into
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the associated transfer buffer for the SCSI task.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_datalen != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA) ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA_RSP)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = idm_sorecv_scsidata(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * All SCSI errors are fatal to the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * connection right now since we have no
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * place to put the data. What we need
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * is some kind of sink to dispose of unwanted
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * SCSI data. For example an invalid task tag
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * should not kill the connection (although
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * we may want to drop the connection).
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Not data PDUs so allocate a buffer for the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * data segment and read the remaining data.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rc = idm_sorecv_nonscsidata(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (rc != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Call idm_pdu_complete so that we call the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * callback and ensure any memory allocated
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in idm_sorecvhdr gets freed up.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If ic_rx_thread_running is still set then
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * this is some kind of connection problem
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * on the socket. In this case we want to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate an event. Otherwise some other
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * thread closed the socket due to another
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * issue in which case we don't need to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * generate an event.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (so_conn->ic_rx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap conn_failure = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_rx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap continue;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Process RX PDU
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_rx(ic, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If we dropped out of the RX processing loop because of
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * a socket problem or other connection failure (including
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * digest errors) then we need to generate a state machine
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * event to shut the connection down.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * If the state machine is already in, for example, INIT_ERROR, this
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * event will get dropped, and the TX thread will never be notified
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to shut down. To be safe, we'll just notify it here.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (conn_failure) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (so_conn->ic_tx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&so_conn->ic_tx_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event(ic, CE_TRANSPORT_FAIL, rc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rele(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_exit();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_so_tx
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This is the implementation of idm_transport_ops_t's it_tx_pdu entry
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * point. By definition, it is supposed to be fast. So, simply queue
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the entry and return. The real work is done by idm_i_so_tx() via
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sotx_thread().
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_tx(idm_conn_t *ic, idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(pdu->isp_ic == ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!so_conn->ic_tx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_insert_tail(&so_conn->ic_tx_list, (void *)pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&so_conn->ic_tx_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_i_so_tx(idm_pdu_t *pdu)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic = pdu->isp_ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t status = IDM_STATUS_SUCCESS;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint8_t pad[ISCSI_PAD_WORD_LEN];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int pad_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t hdr_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t data_digest_crc = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int total_len = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap int iovlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap struct iovec iov[6];
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Setup BHS */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = pdu->isp_hdrlen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Setup header digest */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (ic->ic_conn_flags & IDM_CONN_HEADER_DIGEST)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap hdr_digest_crc = idm_crc32c(pdu->isp_hdr, pdu->isp_hdrlen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)&hdr_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = sizeof (hdr_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Setup the data */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_datalen) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_hdr_t *ihp;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ihp = (iscsi_data_hdr_t *)pdu->isp_hdr;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Write of immediate data */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (ic->ic_ffp &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (ihp->opcode == ISCSI_OP_SCSI_CMD ||
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ihp->opcode == ISCSI_OP_SCSI_DATA)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idt = idm_task_find(ic, ihp->itt, ihp->ttt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idt) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb = idm_buf_find(&idt->idt_outbufv, 0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If the initiator call to idm_buf_alloc
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * failed then we can get to this point
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * without a bound buffer. The associated
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * connection failure will clean things up
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * later. It would be nice to come up with
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * a cleaner way to handle this. In
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * particular it seems absurd to look up
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the task and the buffer just to update
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * this counter.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (idb)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb->idb_xfer_len += pdu->isp_datalen;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)pdu->isp_data;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = pdu->isp_datalen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Setup the data pad if necessary */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pad_len = ((ISCSI_PAD_WORD_LEN -
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pdu->isp_datalen & (ISCSI_PAD_WORD_LEN - 1))) &
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (ISCSI_PAD_WORD_LEN - 1));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pad_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pad, sizeof (pad));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (void *)&pad;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = pad_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Setup the data digest if enabled. Data-digest is not sent
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * for login-phase PDUs.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if ((ic->ic_conn_flags & IDM_CONN_DATA_DIGEST) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ((pdu->isp_flags & IDM_PDU_LOGIN_TX) == 0) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (pdu->isp_datalen || pad_len)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * RFC3720/10.2.3: A zero-length Data Segment also
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * implies a zero-length data digest.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_datalen) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap data_digest_crc = idm_crc32c(pdu->isp_data,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_datalen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pad_len) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap data_digest_crc = idm_crc32c_continued(&pad,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pad_len, data_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_base = (caddr_t)&data_digest_crc;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iov[iovlen].iov_len = sizeof (data_digest_crc);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len += iov[iovlen].iov_len;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iovlen++;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Transmit the PDU */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idm_iov_sosend(so_conn->ic_so, &iov[0], iovlen,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap total_len) != 0) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Set error status */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_so_tx: failed to transmit the PDU, so: %p ic: %p "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "data: %p", (void *) so_conn->ic_so, (void *) ic,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (void *) pdu->isp_data);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap status = IDM_STATUS_IO;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Success does not mean that the PDU actually reached the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * remote node since it could get dropped along the way.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete(pdu, status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The idm_so_buf_tx_to_ini() is used by the target iSCSI layer to transmit the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Data-In PDUs using sockets. Based on the negotiated MaxRecvDataSegmentLength,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the buffer is segmented into a sequence of Data-In PDUs, ordered by DataSN.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * A target can invoke this function multiple times for a single read command
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * (identified by the same ITT) to split the input into several sequences.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * DataSN starts with 0 for the first data PDU of an input command and advances
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * by 1 for each subsequent data PDU. Each sequence will have its own F bit,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * which is set to 1 for the last data PDU of a sequence.
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * If the initiator supports phase collapse, the status bit must be set along
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * with the F bit to indicate that the status is shipped together with the last
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan * Data-In PDU.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The data PDUs within a sequence will be sent in order with the buffer offset
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in increasing order. i.e. initiator and target must have negotiated the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * "DataPDUInOrder" to "Yes". The order between sequences is not enforced.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Caller holds idt->idt_mutex
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_tx_to_ini(idm_task_t *idt, idm_buf_t *idb)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn = idb->idb_ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t tmppdu;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(mutex_owned(&idt->idt_mutex));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Put the idm_buf_t on the tx queue. It will be transmitted by
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idm_sotx_thread.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf, uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len, int, XFER_BUF_TX_TO_INI);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!so_conn->ic_tx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Don't release idt->idt_mutex since we're supposed to hold
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * in when calling idm_buf_tx_to_ini_done
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf, uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_TX_TO_INI);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_tx_to_ini_done(idt, idb, IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Build a template for the data PDU headers we will use so that
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the SN values will stay consistent with other PDU's we are
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * transmitting like R2T and SCSI status.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(&idb->idb_data_hdr_tmpl, sizeof (iscsi_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap tmppdu.isp_hdr = &idb->idb_data_hdr_tmpl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, &tmppdu,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ISCSI_OP_SCSI_DATA_RSP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb->idb_tx_thread = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_insert_tail(&so_conn->ic_tx_list, (void *)idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&so_conn->ic_tx_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Returning success here indicates the transfer was successfully
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * dispatched -- it does not mean that the transfer completed
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * successfully.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * The idm_so_buf_rx_from_ini() is used by the target iSCSI layer to specify the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * data blocks it is ready to receive from the initiator in response to a WRITE
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * SCSI command. The target iSCSI layer passes the information about the desired
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * data blocks to the initiator in one R2T PDU. The receiving buffer, the buffer
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * offset and datalen are passed via the 'idb' argument.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Scope for Prototype build:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * R2Ts are required for any Data-Out PDU, i.e. initiator and target must have
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * negotiated the "InitialR2T" to "Yes".
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap *
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Caller holds idt->idt_mutex
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_rx_from_ini(idm_task_t *idt, idm_buf_t *idb)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *pdu;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_rtt_hdr_t *rtt;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(mutex_owned(&idt->idt_mutex));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__start, idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf, uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len, int, XFER_BUF_RX_FROM_INI);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_ic = idt->idt_ic;
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan pdu->isp_flags = IDM_PDU_SET_STATSN;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pdu->isp_hdr, sizeof (iscsi_rtt_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a2383ac57dcb38468bc1c213ee2d102d1e9038b1Priya Krishnan /* iSCSI layer fills the TTT, ITT, ExpCmdSN, MaxCmdSN */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, pdu, ISCSI_OP_RTT_RSP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* set the rttsn, rtt.flags, rtt.data_offset and rtt.data_length */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt = (iscsi_rtt_hdr_t *)(pdu->isp_hdr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt->opcode = ISCSI_OP_RTT_RSP;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt->flags = ISCSI_FLAG_FINAL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt->data_offset = htonl(idb->idb_bufoffset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt->data_length = htonl(idb->idb_xfer_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap rtt->rttsn = htonl(idt->idt_exp_rttsn++);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Keep track of buffer offsets */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idb->idb_exp_offset = idb->idb_bufoffset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
63528ae45fc8c92cddd3c3b0dc846a9be84f44acJames Moore * Transmit the PDU.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
63528ae45fc8c92cddd3c3b0dc846a9be84f44acJames Moore idm_pdu_tx(pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_alloc(idm_buf_t *idb, uint64_t buflen)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap if ((buflen > IDM_SO_BUF_CACHE_LB) && (buflen <= IDM_SO_BUF_CACHE_UB)) {
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap idb->idb_buf = kmem_cache_alloc(idm.idm_so_128k_buf_cache,
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap KM_NOSLEEP);
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap idb->idb_buf_private = idm.idm_so_128k_buf_cache;
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap } else {
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap idb->idb_buf = kmem_alloc(buflen, KM_NOSLEEP);
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap idb->idb_buf_private = NULL;
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap }
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idb->idb_buf == NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_NOTE,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_so_buf_alloc: failed buffer allocation");
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_FAIL);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic idm_status_t
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_setup(idm_buf_t *idb)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /* Ensure bufalloc'd flag is unset */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb->idb_bufalloc = B_FALSE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_teardown(idm_buf_t *idb)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* nothing to do here */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_so_buf_free(idm_buf_t *idb)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap if (idb->idb_buf_private == NULL) {
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap kmem_free(idb->idb_buf, idb->idb_buflen);
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap } else {
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap kmem_cache_free(idb->idb_buf_private, idb->idb_buf);
cf8c0ebaf84c824d8f14486e47457119c138ce3cPeter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_so_send_rtt_data(idm_conn_t *ic, idm_task_t *idt, idm_buf_t *idb,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap uint32_t offset, uint32_t length)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_so_conn_t *so_conn = ic->ic_transport_private;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_pdu_t tmppdu;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_t *rtt_buf;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ASSERT(mutex_owned(&idt->idt_mutex));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Allocate a buffer to represent the RTT transfer. We could further
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * optimize this by allocating the buffers internally from an rtt
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * specific buffer cache since this is socket-specific code but for
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * now we will keep it simple.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf = idm_buf_alloc(ic, (uint8_t *)idb->idb_buf + offset, length);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (rtt_buf == NULL) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If we're in FFP then the failure was likely a resource
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * allocation issue and we should close the connection by
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * sending a CE_TRANSPORT_FAIL event.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap *
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * If we're not in FFP then idm_buf_alloc will always
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * fail and the state is transitioning to "complete" anyway
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * so we won't bother to send an event.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&ic->ic_state_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (ic->ic_ffp)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_conn_event_locked(ic, CE_TRANSPORT_FAIL,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap NULL, CT_NONE);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&ic->ic_state_mutex);
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng mutex_exit(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_buf_cb = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_cb_arg = NULL;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_bufoffset = offset;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_xfer_len = length;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_ic = idt->idt_ic;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_task_binding = idt;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng /*
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng * The new buffer (if any) represents an additional
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng * reference on the task
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng */
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng idm_task_hold(idt);
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng mutex_exit(&idt->idt_mutex);
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Put the idm_buf_t on the tx queue. It will be transmitted by
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idm_sotx_thread.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (!so_conn->ic_tx_thread_running) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_free(rtt_buf);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
c158b55c925a2d0ea2d60425a41a04a7eb90d0fcJack Meng idm_task_rele(idt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Build a template for the data PDU headers we will use so that
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * the SN values will stay consistent with other PDU's we are
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * transmitting like R2T and SCSI status.
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bzero(&rtt_buf->idb_data_hdr_tmpl, sizeof (iscsi_hdr_t));
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap tmppdu.isp_hdr = &rtt_buf->idb_data_hdr_tmpl;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap (*idt->idt_ic->ic_conn_ops.icb_build_hdr)(idt, &tmppdu,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap ISCSI_OP_SCSI_DATA);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_tx_thread = B_TRUE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap rtt_buf->idb_in_transport = B_TRUE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap list_insert_tail(&so_conn->ic_tx_list, (void *)rtt_buf);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap cv_signal(&so_conn->ic_tx_cv);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic void
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_so_send_rtt_data_done(idm_task_t *idt, idm_buf_t *idb)
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap{
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * Don't worry about status -- we assume any error handling
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * is performed by the caller (idm_sotx_thread).
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb->idb_in_transport = B_FALSE;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_task_rele(idt);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_free(idb);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap}
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapstatic idm_status_t
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlapidm_so_send_buf_region(idm_task_t *idt, idm_buf_t *idb,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t buf_region_offset, uint32_t buf_region_length)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t max_dataseglen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap size_t remainder, chunk;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap uint32_t data_offset = buf_region_offset;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap iscsi_data_hdr_t *bhs;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *pdu;
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_status_t tx_status;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(mutex_owned(&idt->idt_mutex));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ic = idt->idt_ic;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
562610838fe0b8fdbe99a91a1dc13e77da2b6546Charles Ting max_dataseglen = ic->ic_conn_params.max_xmit_dataseglen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap remainder = buf_region_length;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (remainder) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (idt->idt_state != TASK_ACTIVE) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT((idt->idt_state != TASK_IDLE) &&
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap (idt->idt_state != TASK_COMPLETE));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* check to see if we need to chunk the data */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (remainder > max_dataseglen) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap chunk = max_dataseglen;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap } else {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap chunk = remainder;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* Data PDU headers will always be sizeof (iscsi_hdr_t) */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu = kmem_cache_alloc(idm.idm_sotx_pdu_cache, KM_SLEEP);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_ic = ic;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pdu->isp_flags = 0; /* initialize isp_flags */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * We've already built a build a header template
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * to use during the transfer. Use this template so that
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the SN values stay consistent with any unrelated PDU's
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * being transmitted.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap bcopy(&idb->idb_data_hdr_tmpl, pdu->isp_hdr,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap sizeof (iscsi_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Set DataSN, data offset, and flags in BHS
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * For the prototype build, A = 0, S = 0, U = 0
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs = (iscsi_data_hdr_t *)(pdu->isp_hdr);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs->datasn = htonl(idt->idt_exp_datasn++);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap hton24(bhs->dlength, chunk);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs->offset = htonl(idb->idb_bufoffset + data_offset);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* setup data */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pdu->isp_data = (uint8_t *)idb->idb_buf + data_offset;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pdu->isp_datalen = (uint_t)chunk;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (chunk == remainder) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bhs->flags = ISCSI_FLAG_FINAL; /* F bit set to 1 */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* Piggyback the status with the last data PDU */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (idt->idt_flags & IDM_TASK_PHASECOLLAPSE_REQ) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan pdu->isp_flags |= IDM_PDU_SET_STATSN |
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan IDM_PDU_ADVANCE_STATSN;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (*idt->idt_ic->ic_conn_ops.icb_update_statsn)
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (idt, pdu);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan idt->idt_flags |=
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan IDM_TASK_PHASECOLLAPSE_SUCCESS;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan remainder -= chunk;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan data_offset += chunk;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan
a668b114487acbb725f522170849c39f8e844673Priya Krishnan /* Instrument the data-send DTrace probe. */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan if (IDM_PDU_OPCODE(pdu) == ISCSI_OP_SCSI_DATA_RSP) {
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_2(data__send,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan iscsi_data_rsp_hdr_t *,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan (iscsi_data_rsp_hdr_t *)pdu->isp_hdr);
a668b114487acbb725f522170849c39f8e844673Priya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Now that we're done working with idt_exp_datasn,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * idt->idt_state and idb->idb_bufoffset we can release
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the task lock -- don't want to hold it across the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * call to idm_i_so_tx since we could block.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Transmit the PDU. Call the internal routine directly
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * as there is already implicit ordering.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if ((tx_status = idm_i_so_tx(pdu)) != IDM_STATUS_SUCCESS) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_enter(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap return (tx_status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idt->idt_tx_bytes += chunk;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (IDM_STATUS_SUCCESS);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * TX PDU cache
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sotx_pdu_constructor(void *hdl, void *arg, int flags)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *pdu = hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pdu, sizeof (idm_pdu_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdrlen = sizeof (iscsi_hdr_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_callback = idm_sotx_cache_pdu_cb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_magic = IDM_PDU_MAGIC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pdu->isp_hdr, sizeof (iscsi_hdr_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sotx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /* reset values between use */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_datalen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_cache_free(idm.idm_sotx_pdu_cache, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * RX PDU cache
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapint
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorx_pdu_constructor(void *hdl, void *arg, int flags)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *pdu = hdl;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap bzero(pdu, sizeof (idm_pdu_t));
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_magic = IDM_PDU_MAGIC;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1); /* Ptr arithmetic */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_callback = idm_sorx_cache_pdu_cb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap return (0);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/* ARGSUSED */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorx_cache_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_iovlen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_sorx_buf = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_cache_free(idm.idm_sorx_pdu_cache, pdu);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapstatic void
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sorx_addl_pdu_cb(idm_pdu_t *pdu, idm_status_t status)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * We had to modify our cached RX PDU with a longer header buffer
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * and/or a longer data buffer. Release the new buffers and fix
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * the fields back to what we would expect for a cached RX PDU.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_flags & IDM_PDU_ADDL_HDR) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(pdu->isp_hdr, pdu->isp_hdrlen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (pdu->isp_flags & IDM_PDU_ADDL_DATA) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap kmem_free(pdu->isp_data, pdu->isp_datalen);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdr = (iscsi_hdr_t *)(pdu + 1);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_hdrlen = sizeof (iscsi_hdr_t);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_data = NULL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_datalen = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_sorx_buf = 0;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap pdu->isp_callback = idm_sorx_cache_pdu_cb;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_sorx_cache_pdu_cb(pdu, status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap/*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * This thread is only active when I/O is queued for transmit
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * because the socket is busy.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapvoid
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlapidm_sotx_thread(void *arg)
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap{
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_t *ic = arg;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_tx_obj_t *object, *next;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_so_conn_t *so_conn;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_status_t status = IDM_STATUS_SUCCESS;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_hold(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn = ic->ic_transport_private;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread_running = B_TRUE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread_did = so_conn->ic_tx_thread->t_did;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_signal(&ic->ic_cv);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&ic->ic_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (so_conn->ic_tx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (list_is_empty(&so_conn->ic_tx_list)) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DTRACE_PROBE1(soconn__tx__sleep, idm_conn_t *, ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap cv_wait(&so_conn->ic_tx_cv, &so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DTRACE_PROBE1(soconn__tx__wakeup, idm_conn_t *, ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (!so_conn->ic_tx_thread_running) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap goto tx_bail;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_remove(&so_conn->ic_tx_list, object);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (object->idm_tx_obj_magic) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan case IDM_PDU_MAGIC: {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan idm_pdu_t *pdu = (idm_pdu_t *)object;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DTRACE_PROBE2(soconn__tx__pdu, idm_conn_t *, ic,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_t *, (idm_pdu_t *)object);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan if (pdu->isp_flags & IDM_PDU_SET_STATSN) {
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan /* No IDM task */
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan (ic->ic_conn_ops.icb_update_statsn)(NULL, pdu);
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap status = idm_i_so_tx((idm_pdu_t *)object);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
60220f10412f6a7c5b45f950f6f6aa364658a179Priya Krishnan }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case IDM_BUF_MAGIC: {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb = (idm_buf_t *)object;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt = idb->idb_task_binding;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap DTRACE_PROBE2(soconn__tx__buf, idm_conn_t *, ic,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *, idb);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap status = idm_so_send_buf_region(idt,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idb, 0, idb->idb_xfer_len);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * TX thread owns the buffer so we expect it to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be "in transport"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(idb->idb_in_transport);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idm_buf_tx_to_ini_done releases
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idt->idt_mutex
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_TX_TO_INI);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_tx_to_ini_done(idt, idb, status);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_so_send_rtt_data_done(idt, idb);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN, "idm_sotx_thread: Unknown magic "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "(0x%08x)", object->idm_tx_obj_magic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap status = IDM_STATUS_FAIL;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap if (status != IDM_STATUS_SUCCESS) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap so_conn->ic_tx_thread_running = B_FALSE;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_event(ic, CE_TRANSPORT_FAIL, status);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * Before we leave, we need to abort every item remaining in the
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * TX list.
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlaptx_bail:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap object = (idm_tx_obj_t *)list_head(&so_conn->ic_tx_list);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap while (object != NULL) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap next = list_next(&so_conn->ic_tx_list, object);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap list_remove(&so_conn->ic_tx_list, object);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap switch (object->idm_tx_obj_magic) {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case IDM_PDU_MAGIC:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_pdu_complete((idm_pdu_t *)object,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_STATUS_ABORTED);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap case IDM_BUF_MAGIC: {
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_buf_t *idb = (idm_buf_t *)object;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_task_t *idt = idb->idb_task_binding;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&idt->idt_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * TX thread owns the buffer so we expect it to
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap * be "in transport"
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap */
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap ASSERT(idb->idb_in_transport);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap if (IDM_CONN_ISTGT(ic)) {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap /*
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idm_buf_tx_to_ini_done releases
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap * idt->idt_mutex
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap */
a668b114487acbb725f522170849c39f8e844673Priya Krishnan DTRACE_ISCSI_8(xfer__done,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan idm_conn_t *, idt->idt_ic,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uintptr_t, idb->idb_buf,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_bufoffset,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint64_t, 0, uint32_t, 0, uint32_t, 0,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan uint32_t, idb->idb_xfer_len,
a668b114487acbb725f522170849c39f8e844673Priya Krishnan int, XFER_BUF_TX_TO_INI);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_buf_tx_to_ini_done(idt, idb,
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap IDM_STATUS_ABORTED);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap } else {
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap idm_so_send_rtt_data_done(idt, idb);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap mutex_exit(&idt->idt_mutex);
30e7468f8f41aa30ada067b2c1d5d284046514daPeter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_enter(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap break;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap default:
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap IDM_CONN_LOG(CE_WARN,
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "idm_sotx_thread: Unexpected magic "
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap "(0x%08x)", object->idm_tx_obj_magic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap object = next;
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap }
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap mutex_exit(&so_conn->ic_tx_mutex);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap idm_conn_rele(ic);
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap thread_exit();
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap /*NOTREACHED*/
a6d42e7d71324c5193c3b94d57d96ba2925d52e1Peter Dunlap}
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic void
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinaidm_so_socket_set_nonblock(struct sonode *node)
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China{
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (void) VOP_SETFL(node->so_vnode, node->so_flag,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (node->so_state | FNONBLOCK), CRED(), NULL);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China}
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinastatic void
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing Chinaidm_so_socket_set_block(struct sonode *node)
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China{
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (void) VOP_SETFL(node->so_vnode, node->so_flag,
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China (node->so_state & (~FNONBLOCK)), CRED(), NULL);
aff4bce51ecc47df7e5a6351b7cee6bc20408c63yi zhang - Sun Microsystems - Beijing China}
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States/*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Called by kernel sockets when the connection has been accepted or
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * rejected. In early volo, a "disconnect" callback was sent instead of
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * "connectfailed", so we check for both.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States/* ARGSUSED */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesvoid
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesidm_so_timed_socket_connect_cb(ksocket_t ks,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ksocket_callback_event_t ev, void *arg, uintptr_t info)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States{
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_so_timed_socket_t *itp = arg;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(itp != NULL);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(ev == KSOCKET_EV_CONNECTED ||
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ev == KSOCKET_EV_CONNECTFAILED ||
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ev == KSOCKET_EV_DISCONNECTED);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&idm_so_timed_socket_mutex);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States itp->it_callback_called = B_TRUE;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (ev == KSOCKET_EV_CONNECTED) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States itp->it_socket_error_code = 0;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States } else {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Make sure the error code is non-zero on error */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (info == 0)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States info = ECONNRESET;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States itp->it_socket_error_code = (int)info;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States cv_signal(&itp->it_cv);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&idm_so_timed_socket_mutex);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States}
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesint
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesidm_so_timed_socket_connect(ksocket_t ks,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States struct sockaddr_storage *sa, int sa_sz, int login_max_usec)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States{
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States clock_t conn_login_max;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States int rc, nonblocking, rval;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_so_timed_socket_t it;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ksocket_callbacks_t ks_cb;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States conn_login_max = ddi_get_lbolt() + drv_usectohz(login_max_usec);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Set to non-block socket mode, with callback on connect
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Early volo used "disconnected" instead of "connectfailed",
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * so set callback to look for both.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States bzero(&it, sizeof (it));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ks_cb.ksock_cb_flags = KSOCKET_CB_CONNECTED |
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States KSOCKET_CB_CONNECTFAILED | KSOCKET_CB_DISCONNECTED;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ks_cb.ksock_cb_connected = idm_so_timed_socket_connect_cb;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ks_cb.ksock_cb_connectfailed = idm_so_timed_socket_connect_cb;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ks_cb.ksock_cb_disconnected = idm_so_timed_socket_connect_cb;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States cv_init(&it.it_cv, NULL, CV_DEFAULT, NULL);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = ksocket_setcallbacks(ks, &ks_cb, &it, CRED());
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (rc != 0)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States return (rc);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Set to non-blocking mode */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States nonblocking = 1;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = ksocket_ioctl(ks, FIONBIO, (intptr_t)&nonblocking, &rval,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States CRED());
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (rc != 0)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States goto cleanup;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States bzero(&it, sizeof (it));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States for (;;) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Warning -- in a loopback scenario, the call to
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * the connect_cb can occur inside the call to
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * ksocket_connect. Do not hold the mutex around the
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * call to ksocket_connect.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = ksocket_connect(ks, (struct sockaddr *)sa, sa_sz, CRED());
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (rc == 0 || rc == EISCONN) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* socket success or already success */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = 0;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if ((rc != EINPROGRESS) && (rc != EALREADY)) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* TCP connect still in progress. See if out of time. */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (ddi_get_lbolt() > conn_login_max) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Connection retry timeout,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * failed connect to target.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = ETIMEDOUT;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * TCP connect still in progress. Sleep until callback.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * Do NOT go to sleep if the callback already occurred!
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_enter(&idm_so_timed_socket_mutex);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (!it.it_callback_called) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) cv_timedwait(&it.it_cv,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States &idm_so_timed_socket_mutex, conn_login_max);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (it.it_callback_called) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States rc = it.it_socket_error_code;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&idm_so_timed_socket_mutex);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* If timer expires, go call ksocket_connect one last time. */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States mutex_exit(&idm_so_timed_socket_mutex);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* resume blocking mode */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States nonblocking = 0;
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ksocket_ioctl(ks, FIONBIO, (intptr_t)&nonblocking, &rval,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States CRED());
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statescleanup:
aedf2b3bb56b025fcaf87b49ec6c8aeea07f16d7srivijitha dugganapalli (void) ksocket_setcallbacks(ks, NULL, NULL, CRED());
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States cv_destroy(&it.it_cv);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (rc != 0) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States idm_soshutdown(ks);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States return (rc);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States}
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesvoid
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesidm_addr_to_sa(idm_addr_t *dportal, struct sockaddr_storage *sa)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States{
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States int dp_addr_size;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States struct sockaddr_in *sin;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States struct sockaddr_in6 *sin6;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* Build sockaddr_storage for this portal (idm_addr_t) */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States bzero(sa, sizeof (*sa));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States dp_addr_size = dportal->a_addr.i_insize;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (dp_addr_size == sizeof (struct in_addr)) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* IPv4 */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sa->ss_family = AF_INET;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sin = (struct sockaddr_in *)sa;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sin->sin_port = htons(dportal->a_port);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States bcopy(&dportal->a_addr.i_addr.in4,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States &sin->sin_addr, sizeof (struct in_addr));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States } else if (dp_addr_size == sizeof (struct in6_addr)) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* IPv6 */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sa->ss_family = AF_INET6;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sin6 = (struct sockaddr_in6 *)sa;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States sin6->sin6_port = htons(dportal->a_port);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States bcopy(&dportal->a_addr.i_addr.in6,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States &sin6->sin6_addr, sizeof (struct in6_addr));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States } else {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ASSERT(0);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States}
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States/*
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * return a human-readable form of a sockaddr_storage, in the form
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * [ip-address]:port. This is used in calls to logging functions.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * If several calls to idm_sa_ntop are made within the same invocation
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States * of a logging function, then each one needs its own buf.
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesconst char *
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Statesidm_sa_ntop(const struct sockaddr_storage *sa,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States char *buf, size_t size)
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States{
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States static const char bogus_ip[] = "[0].-1";
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States char tmp[INET6_ADDRSTRLEN];
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States switch (sa->ss_family) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States case AF_INET6:
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States const struct sockaddr_in6 *in6 =
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (const struct sockaddr_in6 *) sa;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (inet_ntop(in6->sin6_family,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States &in6->sin6_addr, tmp, sizeof (tmp)) == NULL) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States goto err;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (strlen(tmp) + sizeof ("[].65535") > size) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States goto err;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States /* struct sockaddr_storage gets port info from v4 loc */
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) snprintf(buf, size, "[%s].%u", tmp,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ntohs(in6->sin6_port));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States return (buf);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States case AF_INET:
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States const struct sockaddr_in *in =
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (const struct sockaddr_in *) sa;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (inet_ntop(in->sin_family, &in->sin_addr,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States tmp, sizeof (tmp)) == NULL) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States goto err;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States if (strlen(tmp) + sizeof ("[].65535") > size) {
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States goto err;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) snprintf(buf, size, "[%s].%u", tmp,
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States ntohs(in->sin_port));
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States return (buf);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States default:
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States break;
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States }
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United Stateserr:
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States (void) snprintf(buf, size, "%s", bogus_ip);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States return (buf);
bdbe8dc662f9700c12eafcbcceb5c724615278cfPeter Cudhea - Sun Microsystems - Burlington, MA United States}