c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * This file contains code imported from the OFED rds source file af_rds.c
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * Oracle elects to have and use the contents of af_rds.c under and governed
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * by the OpenIB.org BSD license (see below for full license text). However,
16e76cdd6e3cfaac7d91c3b0644ee1bc6cf52347agiri * the following notice accompanied the original version of this file:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Copyright (c) 2006 Oracle. All rights reserved.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * This software is available to you under a choice of one of two
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * licenses. You may choose to be licensed under the terms of the GNU
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * General Public License (GPL) Version 2, available from the file
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * COPYING in the main directory of this source tree, or the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * OpenIB.org BSD license below:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Redistribution and use in source and binary forms, with or
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * without modification, are permitted provided that the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * conditions are met:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - Redistributions of source code must retain the above
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * copyright notice, this list of conditions and the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * disclaimer.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - Redistributions in binary form must reproduce the above
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * copyright notice, this list of conditions and the following
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * disclaimer in the documentation and/or other materials
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * provided with the distribution.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * SOFTWARE.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/stat.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/conf.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sunddi.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/modctl.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/rds.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/stropts.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/socket.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/socketvar.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sockio.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/sysmacros.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <inet/ip.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <net/if_types.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdma.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdma_transport.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#include <sys/ib/clients/rdsv3/rdsv3_debug.h>
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern void rdsv3_remove_bound(struct rdsv3_sock *rds);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern int rdsv3_verify_bind_address(ipaddr_t addr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern ddi_taskq_t *rdsv3_taskq;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern struct rdma_cm_id *rdsv3_rdma_listen_id;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* this is just used for stats gathering :/ */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otakmutex_t rdsv3_sock_lock;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic unsigned long rdsv3_sock_count;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otalist_t rdsv3_sock_list;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * This is called as the final descriptor referencing this socket is closed.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * We have to unbind the socket so that another socket can be bound to the
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * address it was using.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * We have to be careful about racing with the incoming path. sock_orphan()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * sets SOCK_DEAD and we use that as an indicator to the rx path that new
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * messages shouldn't be queued.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_release(sock_lower_handle_t proto_handle, int flgs, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota if (!sk)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_release", "Enter(rs: %p, sk: %p)", rs, sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_sock_orphan(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_remove_socket(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_remove_bound(rs);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Note - rdsv3_clear_recv_queue grabs rs_recv_lock, so
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * that ensures the recv path has completed messing
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * with the socket.
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota *
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota * Note2 - rdsv3_clear_recv_queue(rs) should be called first
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota * to prevent some race conditions, which is different from
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota * the Linux code.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_clear_recv_queue(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_send_drop_to(rs, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_drop_keys(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) rdsv3_notify_queue_get(rs, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_remove_node(&rs->rs_item);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sock_count--;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
6e18d381c642549b8bb1774a803d3510aec6baafagiri while (sk->sk_refcount > 1) {
6e18d381c642549b8bb1774a803d3510aec6baafagiri /* wait for 1 sec and try again */
6e18d381c642549b8bb1774a803d3510aec6baafagiri delay(drv_usectohz(1000000));
6e18d381c642549b8bb1774a803d3510aec6baafagiri }
6e18d381c642549b8bb1774a803d3510aec6baafagiri
6e18d381c642549b8bb1774a803d3510aec6baafagiri /* this will free the rs and sk */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_sock_put(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_release", "Return (rds: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota__rdsv3_wake_sk_sleep(struct rsock *sk)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* wakup anyone waiting in recvmsg */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rdsv3_sk_sock_flag(sk, SOCK_DEAD) && sk->sk_sleep)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_wake_up(sk->sk_sleep);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * Careful not to race with rdsv3_release -> sock_orphan which clears sk_sleep.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * _bh() isn't OK here, we're called from interrupt handlers. It's probably OK
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * to wake the waitqueue after sk_sleep is clear as we hold a sock ref, but
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * this seems more conservative.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * NB - normally, one would use sk_callback_lock for this, but we can
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * get here from interrupts, whereas the network code grabs sk_callback_lock
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * with _lock_bh only - so relying on sk_callback_lock introduces livelocks.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_wake_sk_sleep(struct rdsv3_sock *rs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_wake_sk_sleep", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&rs->rs_recv_lock, RW_READER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __rdsv3_wake_sk_sleep(rdsv3_rs_to_sk(rs));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&rs->rs_recv_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_getname(sock_lower_handle_t proto_handle, struct sockaddr *addr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota socklen_t *addr_len, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct sockaddr_in *sin = (struct sockaddr_in *)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getname", "Enter(rs: %p, port: %d)", rs,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_bound_port);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_port = rs->rs_bound_port;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_addr.s_addr = rs->rs_bound_addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_family = AF_INET_OFFLOAD;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *addr_len = sizeof (*sin);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * RDS' poll is without a doubt the least intuitive part of the interface,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * as POLLIN and POLLOUT do not behave entirely as you would expect from
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * a network protocol.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * POLLIN is asserted if
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - there is data on the receive queue.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - to signal that a previously congested destination may have become
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * uncongested
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * - A notification has been queued to the socket (this can be a congestion
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * update, or a RDMA completion).
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * POLLOUT is asserted if there is room on the send queue. This does not mean
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * however, that the next sendmsg() call will succeed. If the application tries
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * to send to a congested destination, the system call may still fail (and
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * return ENOBUFS).
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic short
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_poll(sock_lower_handle_t proto_handle, short events, int anyyet,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota unsigned short mask = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#if 0
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_poll", "enter(%p %x %d)", rs, events, anyyet);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota /*
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * If rs_seen_congestion is on, wait until it's off.
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * This is implemented for the following OFED code.
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * if (rs->rs_seen_congestion)
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota * poll_wait(file, &rds_poll_waitq, wait);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota */
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_enter(&rs->rs_congested_lock);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota while (rs->rs_seen_congestion) {
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cv_wait(&rs->rs_congested_cv,
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota &rs->rs_congested_lock);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota }
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_exit(&rs->rs_congested_lock);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&rs->rs_recv_lock, RW_READER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rs->rs_cong_monitor) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /*
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * When a congestion map was updated, we signal POLLIN for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * "historical" reasons. Applications can also poll for
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota * WRBAND instead.
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_cong_updated_since(&rs->rs_cong_track))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mask |= (POLLIN | POLLRDNORM | POLLWRBAND);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&rs->rs_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rs->rs_cong_notify)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mask |= (POLLIN | POLLRDNORM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&rs->rs_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!list_is_empty(&rs->rs_recv_queue) ||
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota !list_is_empty(&rs->rs_notify_queue))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mask |= (POLLIN | POLLRDNORM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rs->rs_snd_bytes < rdsv3_sk_sndbuf(rs))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mask |= (POLLOUT | POLLWRNORM);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota /* clear state any time we wake a seen-congested socket */
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota if (mask) {
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_enter(&rs->rs_congested_lock);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota rs->rs_seen_congestion = 0;
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_exit(&rs->rs_congested_lock);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota }
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota rw_exit(&rs->rs_recv_lock);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#if 0
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_poll", "return(%p %x)", rs, mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (mask);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_ioctl(sock_lower_handle_t proto_handle, int cmd, intptr_t arg,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int mode, int32_t *rvalp, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ksocket_t so4;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct lifconf lifc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct lifreq lifr, *lifrp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ifconf ifc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct ifreq ifr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int rval = 0, rc, len;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int bufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota void *buf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ioctl", "enter: cmd: %d", cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Only ipv4 for now */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = ksocket_socket(&so4, PF_INET, SOCK_DGRAM, 0, KSOCKET_NOSLEEP,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "ksocket_socket returned %d",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (cmd) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFNUM :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFNUM :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = rdsv3_do_ip_ioctl(so4, &buf, &bufsize, &numifs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (cmd == SIOCGLIFNUM) {
b27516f55237249607f754e6e42e865f12456675agiri struct lifnum lifn;
b27516f55237249607f754e6e42e865f12456675agiri lifn.lifn_family = AF_INET_OFFLOAD;
b27516f55237249607f754e6e42e865f12456675agiri lifn.lifn_flags = 0;
b27516f55237249607f754e6e42e865f12456675agiri lifn.lifn_count = numifs;
b27516f55237249607f754e6e42e865f12456675agiri (void) ddi_copyout(&lifn, (void *)arg,
b27516f55237249607f754e6e42e865f12456675agiri sizeof (struct lifnum), 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota len = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota for (lifrp = (struct lifreq *)buf, rc = 0; rc < numifs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc++, lifrp++) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (strlen(lifrp->lifr_name) <= IFNAMSIZ) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota len++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ddi_copyout(&len, (void *)arg,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (int), 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFCONF :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyin((void *)arg, &lifc, sizeof (struct lifconf), 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "ddi_copyin failed lifc");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = rdsv3_do_ip_ioctl(so4, &buf, &bufsize, &numifs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdsv3_do_ip_ioctl failed: %d", rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((lifc.lifc_len > 0) && (numifs > 0)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyout(buf, (void *)lifc.lifc_req,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (lifc.lifc_len < bufsize) ? lifc.lifc_len :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bufsize, 0) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "copyout of records failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lifc.lifc_len = bufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyout(&lifc, (void *)arg, sizeof (struct lifconf),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota 0) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "copyout of lifconf failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFCONF :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case O_SIOCGIFCONF :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyin((void *)arg, &ifc, sizeof (struct ifconf), 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "ddi_copyin failed ifc");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "O_SIOCGIFCONF: ifc_len: %d, req: %p",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ifc.ifc_len, ifc.ifc_req);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = rdsv3_do_ip_ioctl_old(so4, &buf, &bufsize, &numifs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rval != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "rdsv3_do_ip_ioctl_old failed: %d", rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((ifc.ifc_len > 0) && (numifs > 0)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyout(buf, (void *)ifc.ifc_req,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (ifc.ifc_len < bufsize) ? ifc.ifc_len :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota bufsize, 0) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "copyout of records failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ifc.ifc_len = bufsize;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyout(&ifc, (void *)arg, sizeof (struct ifconf),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota 0) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "copyout of ifconf failed");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(buf, bufsize);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFFLAGS :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCSLIFFLAGS :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFMTU :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFNETMASK :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGLIFINDEX :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyin((void *)arg, &lifr, sizeof (struct lifreq), 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "ddi_copyin failed lifr");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, cmd, (intptr_t)&lifr, &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl failed: %d, name: %s cmd: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc, lifr.lifr_name, cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ddi_copyout(&lifr, (void *)arg,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct lifreq), 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFFLAGS :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCSIFFLAGS :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFMTU :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFNETMASK :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SIOCGIFINDEX :
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyin((void *)arg, &ifr, sizeof (struct ifreq), 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "ddi_copyin failed ifr");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EFAULT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "1. name: %s", ifr.ifr_name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc = ksocket_ioctl(so4, cmd, (intptr_t)&ifr, &rval, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rc != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "ksocket_ioctl failed: %d, name: %s cmd: 0x%x",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rc, ifr.ifr_name, cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_ioctl", "2. name: %s", ifr.ifr_name);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ddi_copyout(&ifr, (void *)arg,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct ifreq), 0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota if ((cmd >= RDS_INFO_FIRST) &&
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota (cmd <= RDS_INFO_LAST)) {
b27516f55237249607f754e6e42e865f12456675agiri return (rdsv3_info_ioctl((struct rsock *)proto_handle,
b27516f55237249607f754e6e42e865f12456675agiri cmd, (char *)arg, rvalp));
b27516f55237249607f754e6e42e865f12456675agiri }
b27516f55237249607f754e6e42e865f12456675agiri RDSV3_DPRINTF2("rdsv3_ioctl", "Unknown ioctl cmd: %d", cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cmn_err(CE_CONT, "unsupported IOCTL cmd: %d \n", cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rval = EOPNOTSUPP;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ksocket_close(so4, CRED());
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_ioctl", "return: %d cmd: %d", rval, cmd);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *rvalp = rval;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (rval);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_cancel_sent_to(struct rdsv3_sock *rs, char *optval, int len)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct sockaddr_in sin;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* racing with another thread binding seems ok here */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rs->rs_bound_addr == 0)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENOTCONN); /* XXX not a great errno */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (len < sizeof (struct sockaddr_in))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ddi_copyin((void *)optval, &sin, sizeof (struct sockaddr_in),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota 0) != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_cancel_sent_to", "ddi_copyin failed sin");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EFAULT);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_send_drop_to(rs, &sin);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_set_bool_option(unsigned char *optvar, char *optval, int optlen)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int value = *optval;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (optlen < sizeof (int))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *optvar = !!value;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_cong_monitor(struct rdsv3_sock *rs, char *optval, int optlen)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_set_bool_option(&rs->rs_cong_monitor, optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret == 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rs->rs_cong_monitor) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_add_socket(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota } else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_remove_socket(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_cong_mask = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_cong_notify = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_setsockopt(sock_lower_handle_t proto_handle, int level,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int optname, const void *optval, socklen_t optlen, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_setsockopt", "enter(%p %d %d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs, level, optname);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (optname) {
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_CANCEL_SENT_TO:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_cancel_sent_to(rs, (char *)optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_GET_MR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_get_mr(rs, optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_GET_MR_FOR_DEST:
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota ret = rdsv3_get_mr_for_dest(rs, optval, optlen);
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota break;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_FREE_MR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_free_mr(rs, optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_RECVERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_set_bool_option(&rs->rs_recverr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (char *)optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_CONG_MONITOR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_cong_monitor(rs, (char *)optval, optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SO_SNDBUF:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_sndbuf = *(uint_t *)optval;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SO_RCVBUF:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_rcvbuf = *(uint_t *)optval;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#if 1
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota break;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#else
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = -ENOPROTOOPT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* XXX */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_getsockopt(sock_lower_handle_t proto_handle, int level,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int optname, void *optval, socklen_t *optlen, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getsockopt", "enter(%p %d %d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs, optname, *optlen);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota switch (optname) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SO_SNDBUF:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getsockopt", "SO_SNDBUF(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_sndbuf);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (*optlen != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *((int *)optval) = sk->sk_sndbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *optlen = sizeof (uint_t);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota case SO_RCVBUF:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getsockopt", "SO_RCVBUF(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_rcvbuf);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (*optlen != 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *((int *)optval) = sk->sk_rcvbuf;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *optlen = sizeof (uint_t);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota case RDS_RECVERR:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getsockopt", "RDSV3_RECVERR(%d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_recverr);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (*optlen < sizeof (int))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-EINVAL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota else {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *(int *)optval = rs->rs_recverr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *optlen = sizeof (int);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota default:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_getsockopt",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "Unknown: level: %d optname: %d", level, optname);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = -ENOPROTOOPT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_getsockopt", "return(%p %d %d)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs, optname, ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int rdsv3_connect(sock_lower_handle_t proto_handle,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota const struct sockaddr *addr, socklen_t addr_len, sock_connid_t *conn,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct sockaddr_in *sin = (struct sockaddr_in *)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_connect", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&sk->sk_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (addr_len != sizeof (struct sockaddr_in)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = -EINVAL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (sin->sin_family != AF_INET_OFFLOAD) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = -EAFNOSUPPORT;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (sin->sin_addr.s_addr == htonl(INADDR_ANY)) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = -EDESTADDRREQ;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_conn_addr = sin->sin_addr.s_addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_conn_port = sin->sin_port;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_upcalls->su_connected(sk->sk_upper_handle, 0, NULL, -1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_connect", "Return(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&sk->sk_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic int
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_shutdown(sock_lower_handle_t proto_handle, int how, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_shutdown", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_activate(sock_lower_handle_t proto_handle,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sock_upper_handle_t sock_handle, sock_upcalls_t *sock_upcalls,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int flags, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_activate", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_upcalls = sock_upcalls;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk->sk_upper_handle = sock_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_activate", "Return (rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_send_uio(sock_lower_handle_t proto_handle, uio_t *uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct nmsghdr *msg, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_send_uio", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_sendmsg(rs, uio, msg, uio->uio_resid);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_send_uio", "Return(rs: %p ret %d)", rs, ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret < 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/* ARGSUSED */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_recv_uio(sock_lower_handle_t proto_handle, uio_t *uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct nmsghdr *msg, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_recv_uio", "Enter (rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_recvmsg(rs, uio, msg, uio->uio_resid, msg->msg_flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_recv_uio", "Return(rs: %p ret %d)", rs, ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret < 0) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_getpeername(sock_lower_handle_t proto_handle, struct sockaddr *addr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota socklen_t *addr_len, cred_t *cr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct sockaddr_in *sin = (struct sockaddr_in *)addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_getpeername", "enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) memset(sin->sin_zero, 0, sizeof (sin->sin_zero));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* racey, don't care */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (!rs->rs_conn_addr)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (-ENOTCONN);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_port = rs->rs_conn_port;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_addr.s_addr = rs->rs_conn_addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sin->sin_family = AF_INET_OFFLOAD;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *addr_len = sizeof (*sin);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (0);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_clrflowctrl(sock_lower_handle_t proto_handle)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk = (struct rsock *)proto_handle;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF2("rdsv3_clrflowctrl", "enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifndef __lock_lint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic struct sock_downcalls_s rdsv3_sock_downcalls = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_close = rdsv3_release,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_bind = rdsv3_bind,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_connect = rdsv3_connect,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_accept = NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_getsockname = rdsv3_getname,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_poll = rdsv3_poll,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_ioctl = rdsv3_ioctl,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_listen = NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_shutdown = rdsv3_shutdown,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_setsockopt = rdsv3_setsockopt,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_getsockopt = rdsv3_getsockopt,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_send_uio = rdsv3_send_uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_recv_uio = rdsv3_recv_uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_activate = rdsv3_activate,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_getpeername = rdsv3_getpeername,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_send = NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota .sd_clr_flowctrl = NULL
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota};
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#else
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic struct sock_downcalls_s rdsv3_sock_downcalls = {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_activate,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_bind,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_connect,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_getpeername,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_getname,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_getsockopt,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_setsockopt,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_send_uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_recv_uio,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_poll,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_shutdown,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_ioctl,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_release
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota};
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otasock_lower_handle_t
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_create(int family, int type, int proto, sock_downcalls_t **sock_downcalls,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota uint_t *smodep, int *errorp, int flags, cred_t *credp)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rsock *sk;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_create", "Enter (family: %d type: %d, proto: %d "
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota "flags: %d", family, type, proto, flags);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sk = rdsv3_sk_alloc();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (sk == NULL)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sock_init_data(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs = rdsv3_sk_to_rs(sk);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_sk = sk;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&rs->rs_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_init(&rs->rs_recv_lock, NULL, RW_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&rs->rs_send_queue, sizeof (struct rdsv3_message),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_message, m_sock_item));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&rs->rs_recv_queue, sizeof (struct rdsv3_incoming),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_incoming, i_item));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_create(&rs->rs_notify_queue, sizeof (struct rdsv3_notifier),
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota offsetof(struct rdsv3_notifier, n_list));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&rs->rs_rdma_lock, NULL, MUTEX_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota avl_create(&rs->rs_rdma_keys, rdsv3_mr_compare,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sizeof (struct rdsv3_mr), offsetof(struct rdsv3_mr, r_rb_node));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_init(&rs->rs_conn_lock, NULL, MUTEX_DRIVER, NULL);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota mutex_init(&rs->rs_congested_lock, NULL, MUTEX_DRIVER, NULL);
5d5562f583b2b6affe19bdce0b3c8b1840d667a4Eiji Ota cv_init(&rs->rs_congested_cv, NULL, CV_DRIVER, NULL);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_cred = credp;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_zoneid = getzoneid();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota crhold(credp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota list_insert_tail(&rdsv3_sock_list, rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sock_count++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* Initialize RDMA/IB on the 1st socket if not done at attach */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_sock_count == 1) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *errorp = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *smodep = SM_ATOMIC;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota *sock_downcalls = &rdsv3_sock_downcalls;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_create", "Return: %p", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return ((sock_lower_handle_t)rdsv3_rs_to_sk(rs));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_addref(struct rdsv3_sock *rs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_addref", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_sock_hold(rdsv3_rs_to_sk(rs));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_put(struct rdsv3_sock *rs)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_put", "Enter(rs: %p)", rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_sock_put(rdsv3_rs_to_sk(rs));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_inc_info(struct rsock *sock, unsigned int len,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_info_iterator *iter, struct rdsv3_info_lengths *lens)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_incoming *inc;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota unsigned int total = 0;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_inc_info", "Enter(rs: %p)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_to_rs(sock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota len /= sizeof (struct rds_info_message);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_FOR_EACH_LIST_NODE(rs, &rdsv3_sock_list, rs_item) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_enter(&rs->rs_recv_lock, RW_READER);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* XXX too lazy to maintain counts.. */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_FOR_EACH_LIST_NODE(inc, &rs->rs_recv_queue, i_item) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota total++;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (total <= len)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_inc_info_copy(inc, iter, inc->i_saddr,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rs->rs_bound_addr, 1);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rw_exit(&rs->rs_recv_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lens->nr = total;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota lens->each = sizeof (struct rds_info_message);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_inc_info", "return(rs: %p)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_to_rs(sock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otastatic void
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_sock_info(struct rsock *sock, unsigned int len,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_info_iterator *iter, struct rdsv3_info_lengths *lens)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota struct rds_info_socket sinfo;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota struct rdsv3_sock *rs;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota unsigned long bytes;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_info", "Enter(rs: %p)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_to_rs(sock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota len /= sizeof (struct rds_info_socket);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_enter(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if ((len < rdsv3_sock_count) || (iter->addr == NULL))
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota bytes = sizeof (struct rds_info_socket);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_FOR_EACH_LIST_NODE(rs, &rdsv3_sock_list, rs_item) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.sndbuf = rdsv3_sk_sndbuf(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.rcvbuf = rdsv3_sk_rcvbuf(rs);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.bound_addr = rs->rs_bound_addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.connected_addr = rs->rs_conn_addr;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.bound_port = rs->rs_bound_port;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota sinfo.connected_port = rs->rs_conn_port;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_info_copy(iter, &sinfo, bytes);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_sock_info", "Return(rs: %p)",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sk_to_rs(sock));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota lens->nr = rdsv3_sock_count;
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota lens->each = sizeof (struct rds_info_socket);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota mutex_exit(&rdsv3_sock_lock);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_delayed_work_t *rdsv3_rdma_dwp = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otauint_t rdsv3_rdma_init_delay = 5; /* secs */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaextern void rdsv3_rdma_init_worker(struct rdsv3_work_s *work);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otavoid
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_exit(void)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_exit", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_rdma_dwp) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cancel_delayed_work(rdsv3_rdma_dwp);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota (void) ddi_taskq_dispatch(rdsv3_taskq, rdsv3_rdma_exit,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota NULL, DDI_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota while (rdsv3_rdma_listen_id != NULL) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#ifndef __lock_lint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF5("rdsv3", "%s-%d Waiting for rdsv3_rdma_exit",
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota __func__, __LINE__);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota#endif
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota delay(drv_usectohz(1000));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_conn_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sysctl_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_threads_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_exit();
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota rdsv3_info_deregister_func(RDS_INFO_SOCKETS, rdsv3_sock_info);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota rdsv3_info_deregister_func(RDS_INFO_RECV_MESSAGES,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sock_inc_info);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (rdsv3_rdma_dwp) {
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota kmem_free(rdsv3_rdma_dwp, sizeof (rdsv3_delayed_work_t));
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_dwp = NULL;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota }
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_exit", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota/*ARGSUSED*/
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaint
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otardsv3_init()
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota{
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota int ret;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_init", "Enter");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_init();
cadbfdc3bdb156e92d7a88978bc98ea87f6e037fEiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_conn_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_threads_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out_conn;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_sysctl_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out_threads;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota ret = rdsv3_stats_init();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota if (ret)
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out_sysctl;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota rdsv3_info_register_func(RDS_INFO_SOCKETS, rdsv3_sock_info);
fe817b6022080da0a98b5d2d8cd179f594d6ca5eEiji Ota rdsv3_info_register_func(RDS_INFO_RECV_MESSAGES, rdsv3_sock_inc_info);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota /* rdsv3_rdma_init need to be called with a little delay */
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_dwp = kmem_zalloc(sizeof (rdsv3_delayed_work_t), KM_SLEEP);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_INIT_DELAYED_WORK(rdsv3_rdma_dwp, rdsv3_rdma_init_worker);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_queue_delayed_work(rdsv3_wq, rdsv3_rdma_dwp,
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_rdma_init_delay);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota RDSV3_DPRINTF4("rdsv3_init", "Return");
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota goto out;
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout_stats:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_stats_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout_sysctl:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_sysctl_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout_threads:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_threads_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout_conn:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_conn_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota rdsv3_cong_exit();
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Otaout:
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota return (ret);
c0dd49bdd68c0d758a67d56f07826f3b45cfc664Eiji Ota}