.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * VMware vSockets Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2007-2013 VMware, Inc. All rights reserved. |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify it |
---|
7 | | - * under the terms of the GNU General Public License as published by the Free |
---|
8 | | - * Software Foundation version 2 and no later version. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but WITHOUT |
---|
11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
13 | | - * more details. |
---|
14 | 6 | */ |
---|
15 | 7 | |
---|
16 | 8 | #include <linux/types.h> |
---|
.. | .. |
---|
65 | 57 | static u16 vmci_transport_new_proto_supported_versions(void); |
---|
66 | 58 | static bool vmci_transport_proto_to_notify_struct(struct sock *sk, u16 *proto, |
---|
67 | 59 | bool old_pkt_proto); |
---|
| 60 | +static bool vmci_check_transport(struct vsock_sock *vsk); |
---|
68 | 61 | |
---|
69 | 62 | struct vmci_transport_recv_pkt_info { |
---|
70 | 63 | struct work_struct work; |
---|
.. | .. |
---|
81 | 74 | static u32 vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID; |
---|
82 | 75 | |
---|
83 | 76 | static int PROTOCOL_OVERRIDE = -1; |
---|
84 | | - |
---|
85 | | -#define VMCI_TRANSPORT_DEFAULT_QP_SIZE_MIN 128 |
---|
86 | | -#define VMCI_TRANSPORT_DEFAULT_QP_SIZE 262144 |
---|
87 | | -#define VMCI_TRANSPORT_DEFAULT_QP_SIZE_MAX 262144 |
---|
88 | | - |
---|
89 | | -/* The default peer timeout indicates how long we will wait for a peer response |
---|
90 | | - * to a control message. |
---|
91 | | - */ |
---|
92 | | -#define VSOCK_DEFAULT_CONNECT_TIMEOUT (2 * HZ) |
---|
93 | 77 | |
---|
94 | 78 | /* Helper function to convert from a VMCI error code to a VSock error code. */ |
---|
95 | 79 | |
---|
.. | .. |
---|
663 | 647 | static bool vmci_transport_stream_allow(u32 cid, u32 port) |
---|
664 | 648 | { |
---|
665 | 649 | static const u32 non_socket_contexts[] = { |
---|
666 | | - VMADDR_CID_RESERVED, |
---|
| 650 | + VMADDR_CID_LOCAL, |
---|
667 | 651 | }; |
---|
668 | 652 | int i; |
---|
669 | 653 | |
---|
.. | .. |
---|
1020 | 1004 | return -ECONNREFUSED; |
---|
1021 | 1005 | } |
---|
1022 | 1006 | |
---|
1023 | | - pending = __vsock_create(sock_net(sk), NULL, sk, GFP_KERNEL, |
---|
1024 | | - sk->sk_type, 0); |
---|
| 1007 | + pending = vsock_create_connected(sk); |
---|
1025 | 1008 | if (!pending) { |
---|
1026 | 1009 | vmci_transport_send_reset(sk, pkt); |
---|
1027 | 1010 | return -ENOMEM; |
---|
.. | .. |
---|
1034 | 1017 | vsock_addr_init(&vpending->remote_addr, pkt->dg.src.context, |
---|
1035 | 1018 | pkt->src_port); |
---|
1036 | 1019 | |
---|
| 1020 | + err = vsock_assign_transport(vpending, vsock_sk(sk)); |
---|
| 1021 | + /* Transport assigned (looking at remote_addr) must be the same |
---|
| 1022 | + * where we received the request. |
---|
| 1023 | + */ |
---|
| 1024 | + if (err || !vmci_check_transport(vpending)) { |
---|
| 1025 | + vmci_transport_send_reset(sk, pkt); |
---|
| 1026 | + sock_put(pending); |
---|
| 1027 | + return err; |
---|
| 1028 | + } |
---|
| 1029 | + |
---|
1037 | 1030 | /* If the proposed size fits within our min/max, accept it. Otherwise |
---|
1038 | 1031 | * propose our own size. |
---|
1039 | 1032 | */ |
---|
1040 | | - if (pkt->u.size >= vmci_trans(vpending)->queue_pair_min_size && |
---|
1041 | | - pkt->u.size <= vmci_trans(vpending)->queue_pair_max_size) { |
---|
| 1033 | + if (pkt->u.size >= vpending->buffer_min_size && |
---|
| 1034 | + pkt->u.size <= vpending->buffer_max_size) { |
---|
1042 | 1035 | qp_size = pkt->u.size; |
---|
1043 | 1036 | } else { |
---|
1044 | | - qp_size = vmci_trans(vpending)->queue_pair_size; |
---|
| 1037 | + qp_size = vpending->buffer_size; |
---|
1045 | 1038 | } |
---|
1046 | 1039 | |
---|
1047 | 1040 | /* Figure out if we are using old or new requests based on the |
---|
.. | .. |
---|
1105 | 1098 | } |
---|
1106 | 1099 | |
---|
1107 | 1100 | vsock_add_pending(sk, pending); |
---|
1108 | | - sk->sk_ack_backlog++; |
---|
| 1101 | + sk_acceptq_added(sk); |
---|
1109 | 1102 | |
---|
1110 | 1103 | pending->sk_state = TCP_SYN_SENT; |
---|
1111 | 1104 | vmci_trans(vpending)->produce_size = |
---|
1112 | 1105 | vmci_trans(vpending)->consume_size = qp_size; |
---|
1113 | | - vmci_trans(vpending)->queue_pair_size = qp_size; |
---|
| 1106 | + vpending->buffer_size = qp_size; |
---|
1114 | 1107 | |
---|
1115 | 1108 | vmci_trans(vpending)->notify_ops->process_request(pending); |
---|
1116 | 1109 | |
---|
.. | .. |
---|
1404 | 1397 | vsk->ignore_connecting_rst = false; |
---|
1405 | 1398 | |
---|
1406 | 1399 | /* Verify that we're OK with the proposed queue pair size */ |
---|
1407 | | - if (pkt->u.size < vmci_trans(vsk)->queue_pair_min_size || |
---|
1408 | | - pkt->u.size > vmci_trans(vsk)->queue_pair_max_size) { |
---|
| 1400 | + if (pkt->u.size < vsk->buffer_min_size || |
---|
| 1401 | + pkt->u.size > vsk->buffer_max_size) { |
---|
1409 | 1402 | err = -EINVAL; |
---|
1410 | 1403 | goto destroy; |
---|
1411 | 1404 | } |
---|
.. | .. |
---|
1510 | 1503 | vsk->sent_request = false; |
---|
1511 | 1504 | vsk->ignore_connecting_rst = true; |
---|
1512 | 1505 | |
---|
1513 | | - err = vmci_transport_send_conn_request( |
---|
1514 | | - sk, vmci_trans(vsk)->queue_pair_size); |
---|
| 1506 | + err = vmci_transport_send_conn_request(sk, vsk->buffer_size); |
---|
1515 | 1507 | if (err < 0) |
---|
1516 | 1508 | err = vmci_transport_error_to_vsock_error(err); |
---|
1517 | 1509 | else |
---|
.. | .. |
---|
1595 | 1587 | INIT_LIST_HEAD(&vmci_trans(vsk)->elem); |
---|
1596 | 1588 | vmci_trans(vsk)->sk = &vsk->sk; |
---|
1597 | 1589 | spin_lock_init(&vmci_trans(vsk)->lock); |
---|
1598 | | - if (psk) { |
---|
1599 | | - vmci_trans(vsk)->queue_pair_size = |
---|
1600 | | - vmci_trans(psk)->queue_pair_size; |
---|
1601 | | - vmci_trans(vsk)->queue_pair_min_size = |
---|
1602 | | - vmci_trans(psk)->queue_pair_min_size; |
---|
1603 | | - vmci_trans(vsk)->queue_pair_max_size = |
---|
1604 | | - vmci_trans(psk)->queue_pair_max_size; |
---|
1605 | | - } else { |
---|
1606 | | - vmci_trans(vsk)->queue_pair_size = |
---|
1607 | | - VMCI_TRANSPORT_DEFAULT_QP_SIZE; |
---|
1608 | | - vmci_trans(vsk)->queue_pair_min_size = |
---|
1609 | | - VMCI_TRANSPORT_DEFAULT_QP_SIZE_MIN; |
---|
1610 | | - vmci_trans(vsk)->queue_pair_max_size = |
---|
1611 | | - VMCI_TRANSPORT_DEFAULT_QP_SIZE_MAX; |
---|
1612 | | - } |
---|
1613 | 1590 | |
---|
1614 | 1591 | return 0; |
---|
1615 | 1592 | } |
---|
.. | .. |
---|
1733 | 1710 | if (!dg) |
---|
1734 | 1711 | return -ENOMEM; |
---|
1735 | 1712 | |
---|
1736 | | - memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); |
---|
| 1713 | + err = memcpy_from_msg(VMCI_DG_PAYLOAD(dg), msg, len); |
---|
| 1714 | + if (err) { |
---|
| 1715 | + kfree(dg); |
---|
| 1716 | + return err; |
---|
| 1717 | + } |
---|
1737 | 1718 | |
---|
1738 | 1719 | dg->dst = vmci_make_handle(remote_addr->svm_cid, |
---|
1739 | 1720 | remote_addr->svm_port); |
---|
.. | .. |
---|
1825 | 1806 | |
---|
1826 | 1807 | if (vmci_transport_old_proto_override(&old_pkt_proto) && |
---|
1827 | 1808 | old_pkt_proto) { |
---|
1828 | | - err = vmci_transport_send_conn_request( |
---|
1829 | | - sk, vmci_trans(vsk)->queue_pair_size); |
---|
| 1809 | + err = vmci_transport_send_conn_request(sk, vsk->buffer_size); |
---|
1830 | 1810 | if (err < 0) { |
---|
1831 | 1811 | sk->sk_state = TCP_CLOSE; |
---|
1832 | 1812 | return err; |
---|
.. | .. |
---|
1834 | 1814 | } else { |
---|
1835 | 1815 | int supported_proto_versions = |
---|
1836 | 1816 | vmci_transport_new_proto_supported_versions(); |
---|
1837 | | - err = vmci_transport_send_conn_request2( |
---|
1838 | | - sk, vmci_trans(vsk)->queue_pair_size, |
---|
| 1817 | + err = vmci_transport_send_conn_request2(sk, vsk->buffer_size, |
---|
1839 | 1818 | supported_proto_versions); |
---|
1840 | 1819 | if (err < 0) { |
---|
1841 | 1820 | sk->sk_state = TCP_CLOSE; |
---|
.. | .. |
---|
1886 | 1865 | static bool vmci_transport_stream_is_active(struct vsock_sock *vsk) |
---|
1887 | 1866 | { |
---|
1888 | 1867 | return !vmci_handle_is_invalid(vmci_trans(vsk)->qp_handle); |
---|
1889 | | -} |
---|
1890 | | - |
---|
1891 | | -static u64 vmci_transport_get_buffer_size(struct vsock_sock *vsk) |
---|
1892 | | -{ |
---|
1893 | | - return vmci_trans(vsk)->queue_pair_size; |
---|
1894 | | -} |
---|
1895 | | - |
---|
1896 | | -static u64 vmci_transport_get_min_buffer_size(struct vsock_sock *vsk) |
---|
1897 | | -{ |
---|
1898 | | - return vmci_trans(vsk)->queue_pair_min_size; |
---|
1899 | | -} |
---|
1900 | | - |
---|
1901 | | -static u64 vmci_transport_get_max_buffer_size(struct vsock_sock *vsk) |
---|
1902 | | -{ |
---|
1903 | | - return vmci_trans(vsk)->queue_pair_max_size; |
---|
1904 | | -} |
---|
1905 | | - |
---|
1906 | | -static void vmci_transport_set_buffer_size(struct vsock_sock *vsk, u64 val) |
---|
1907 | | -{ |
---|
1908 | | - if (val < vmci_trans(vsk)->queue_pair_min_size) |
---|
1909 | | - vmci_trans(vsk)->queue_pair_min_size = val; |
---|
1910 | | - if (val > vmci_trans(vsk)->queue_pair_max_size) |
---|
1911 | | - vmci_trans(vsk)->queue_pair_max_size = val; |
---|
1912 | | - vmci_trans(vsk)->queue_pair_size = val; |
---|
1913 | | -} |
---|
1914 | | - |
---|
1915 | | -static void vmci_transport_set_min_buffer_size(struct vsock_sock *vsk, |
---|
1916 | | - u64 val) |
---|
1917 | | -{ |
---|
1918 | | - if (val > vmci_trans(vsk)->queue_pair_size) |
---|
1919 | | - vmci_trans(vsk)->queue_pair_size = val; |
---|
1920 | | - vmci_trans(vsk)->queue_pair_min_size = val; |
---|
1921 | | -} |
---|
1922 | | - |
---|
1923 | | -static void vmci_transport_set_max_buffer_size(struct vsock_sock *vsk, |
---|
1924 | | - u64 val) |
---|
1925 | | -{ |
---|
1926 | | - if (val < vmci_trans(vsk)->queue_pair_size) |
---|
1927 | | - vmci_trans(vsk)->queue_pair_size = val; |
---|
1928 | | - vmci_trans(vsk)->queue_pair_max_size = val; |
---|
1929 | 1868 | } |
---|
1930 | 1869 | |
---|
1931 | 1870 | static int vmci_transport_notify_poll_in( |
---|
.. | .. |
---|
2083 | 2022 | return vmci_get_context_id(); |
---|
2084 | 2023 | } |
---|
2085 | 2024 | |
---|
2086 | | -static const struct vsock_transport vmci_transport = { |
---|
| 2025 | +static struct vsock_transport vmci_transport = { |
---|
| 2026 | + .module = THIS_MODULE, |
---|
2087 | 2027 | .init = vmci_transport_socket_init, |
---|
2088 | 2028 | .destruct = vmci_transport_destruct, |
---|
2089 | 2029 | .release = vmci_transport_release, |
---|
.. | .. |
---|
2110 | 2050 | .notify_send_pre_enqueue = vmci_transport_notify_send_pre_enqueue, |
---|
2111 | 2051 | .notify_send_post_enqueue = vmci_transport_notify_send_post_enqueue, |
---|
2112 | 2052 | .shutdown = vmci_transport_shutdown, |
---|
2113 | | - .set_buffer_size = vmci_transport_set_buffer_size, |
---|
2114 | | - .set_min_buffer_size = vmci_transport_set_min_buffer_size, |
---|
2115 | | - .set_max_buffer_size = vmci_transport_set_max_buffer_size, |
---|
2116 | | - .get_buffer_size = vmci_transport_get_buffer_size, |
---|
2117 | | - .get_min_buffer_size = vmci_transport_get_min_buffer_size, |
---|
2118 | | - .get_max_buffer_size = vmci_transport_get_max_buffer_size, |
---|
2119 | 2053 | .get_local_cid = vmci_transport_get_local_cid, |
---|
2120 | 2054 | }; |
---|
| 2055 | + |
---|
| 2056 | +static bool vmci_check_transport(struct vsock_sock *vsk) |
---|
| 2057 | +{ |
---|
| 2058 | + return vsk->transport == &vmci_transport; |
---|
| 2059 | +} |
---|
| 2060 | + |
---|
| 2061 | +static void vmci_vsock_transport_cb(bool is_host) |
---|
| 2062 | +{ |
---|
| 2063 | + int features; |
---|
| 2064 | + |
---|
| 2065 | + if (is_host) |
---|
| 2066 | + features = VSOCK_TRANSPORT_F_H2G; |
---|
| 2067 | + else |
---|
| 2068 | + features = VSOCK_TRANSPORT_F_G2H; |
---|
| 2069 | + |
---|
| 2070 | + vsock_core_register(&vmci_transport, features); |
---|
| 2071 | +} |
---|
2121 | 2072 | |
---|
2122 | 2073 | static int __init vmci_transport_init(void) |
---|
2123 | 2074 | { |
---|
.. | .. |
---|
2135 | 2086 | pr_err("Unable to create datagram handle. (%d)\n", err); |
---|
2136 | 2087 | return vmci_transport_error_to_vsock_error(err); |
---|
2137 | 2088 | } |
---|
2138 | | - |
---|
2139 | 2089 | err = vmci_event_subscribe(VMCI_EVENT_QP_RESUMED, |
---|
2140 | 2090 | vmci_transport_qp_resumed_cb, |
---|
2141 | 2091 | NULL, &vmci_transport_qp_resumed_sub_id); |
---|
.. | .. |
---|
2146 | 2096 | goto err_destroy_stream_handle; |
---|
2147 | 2097 | } |
---|
2148 | 2098 | |
---|
2149 | | - err = vsock_core_init(&vmci_transport); |
---|
| 2099 | + /* Register only with dgram feature, other features (H2G, G2H) will be |
---|
| 2100 | + * registered when the first host or guest becomes active. |
---|
| 2101 | + */ |
---|
| 2102 | + err = vsock_core_register(&vmci_transport, VSOCK_TRANSPORT_F_DGRAM); |
---|
2150 | 2103 | if (err < 0) |
---|
2151 | 2104 | goto err_unsubscribe; |
---|
2152 | 2105 | |
---|
| 2106 | + err = vmci_register_vsock_callback(vmci_vsock_transport_cb); |
---|
| 2107 | + if (err < 0) |
---|
| 2108 | + goto err_unregister; |
---|
| 2109 | + |
---|
2153 | 2110 | return 0; |
---|
2154 | 2111 | |
---|
| 2112 | +err_unregister: |
---|
| 2113 | + vsock_core_unregister(&vmci_transport); |
---|
2155 | 2114 | err_unsubscribe: |
---|
2156 | 2115 | vmci_event_unsubscribe(vmci_transport_qp_resumed_sub_id); |
---|
2157 | 2116 | err_destroy_stream_handle: |
---|
.. | .. |
---|
2177 | 2136 | vmci_transport_qp_resumed_sub_id = VMCI_INVALID_ID; |
---|
2178 | 2137 | } |
---|
2179 | 2138 | |
---|
2180 | | - vsock_core_exit(); |
---|
| 2139 | + vmci_register_vsock_callback(NULL); |
---|
| 2140 | + vsock_core_unregister(&vmci_transport); |
---|
2181 | 2141 | } |
---|
2182 | 2142 | module_exit(vmci_transport_exit); |
---|
2183 | 2143 | |
---|