18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * VMware vSockets Driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009-2013 VMware, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/socket.h> 108c2ecf20Sopenharmony_ci#include <linux/stddef.h> 118c2ecf20Sopenharmony_ci#include <net/sock.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "vmci_transport_notify.h" 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#define PKT_FIELD(vsk, field_name) (vmci_trans(vsk)->notify.pkt.field_name) 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic bool vmci_transport_notify_waiting_write(struct vsock_sock *vsk) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 208c2ecf20Sopenharmony_ci bool retval; 218c2ecf20Sopenharmony_ci u64 notify_limit; 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci if (!PKT_FIELD(vsk, peer_waiting_write)) 248c2ecf20Sopenharmony_ci return false; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL 278c2ecf20Sopenharmony_ci /* When the sender blocks, we take that as a sign that the sender is 288c2ecf20Sopenharmony_ci * faster than the receiver. To reduce the transmit rate of the sender, 298c2ecf20Sopenharmony_ci * we delay the sending of the read notification by decreasing the 308c2ecf20Sopenharmony_ci * write_notify_window. The notification is delayed until the number of 318c2ecf20Sopenharmony_ci * bytes used in the queue drops below the write_notify_window. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci if (!PKT_FIELD(vsk, peer_waiting_write_detected)) { 358c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write_detected) = true; 368c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, write_notify_window) < PAGE_SIZE) { 378c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = 388c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window); 398c2ecf20Sopenharmony_ci } else { 408c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) -= PAGE_SIZE; 418c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, write_notify_window) < 428c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window)) 438c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = 448c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci } 488c2ecf20Sopenharmony_ci notify_limit = vmci_trans(vsk)->consume_size - 498c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window); 508c2ecf20Sopenharmony_ci#else 518c2ecf20Sopenharmony_ci notify_limit = 0; 528c2ecf20Sopenharmony_ci#endif 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* For now we ignore the wait information and just see if the free 558c2ecf20Sopenharmony_ci * space exceeds the notify limit. Note that improving this function 568c2ecf20Sopenharmony_ci * to be more intelligent will not require a protocol change and will 578c2ecf20Sopenharmony_ci * retain compatibility between endpoints with mixed versions of this 588c2ecf20Sopenharmony_ci * function. 598c2ecf20Sopenharmony_ci * 608c2ecf20Sopenharmony_ci * The notify_limit is used to delay notifications in the case where 618c2ecf20Sopenharmony_ci * flow control is enabled. Below the test is expressed in terms of 628c2ecf20Sopenharmony_ci * free space in the queue: if free_space > ConsumeSize - 638c2ecf20Sopenharmony_ci * write_notify_window then notify An alternate way of expressing this 648c2ecf20Sopenharmony_ci * is to rewrite the expression to use the data ready in the receive 658c2ecf20Sopenharmony_ci * queue: if write_notify_window > bufferReady then notify as 668c2ecf20Sopenharmony_ci * free_space == ConsumeSize - bufferReady. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci retval = vmci_qpair_consume_free_space(vmci_trans(vsk)->qpair) > 698c2ecf20Sopenharmony_ci notify_limit; 708c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL 718c2ecf20Sopenharmony_ci if (retval) { 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Once we notify the peer, we reset the detected flag so the 748c2ecf20Sopenharmony_ci * next wait will again cause a decrease in the window size. 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write_detected) = false; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci#endif 808c2ecf20Sopenharmony_ci return retval; 818c2ecf20Sopenharmony_ci#else 828c2ecf20Sopenharmony_ci return true; 838c2ecf20Sopenharmony_ci#endif 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic bool vmci_transport_notify_waiting_read(struct vsock_sock *vsk) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 898c2ecf20Sopenharmony_ci if (!PKT_FIELD(vsk, peer_waiting_read)) 908c2ecf20Sopenharmony_ci return false; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* For now we ignore the wait information and just see if there is any 938c2ecf20Sopenharmony_ci * data for our peer to read. Note that improving this function to be 948c2ecf20Sopenharmony_ci * more intelligent will not require a protocol change and will retain 958c2ecf20Sopenharmony_ci * compatibility between endpoints with mixed versions of this 968c2ecf20Sopenharmony_ci * function. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci return vmci_qpair_produce_buf_ready(vmci_trans(vsk)->qpair) > 0; 998c2ecf20Sopenharmony_ci#else 1008c2ecf20Sopenharmony_ci return true; 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_cistatic void 1058c2ecf20Sopenharmony_civmci_transport_handle_waiting_read(struct sock *sk, 1068c2ecf20Sopenharmony_ci struct vmci_transport_packet *pkt, 1078c2ecf20Sopenharmony_ci bool bottom_half, 1088c2ecf20Sopenharmony_ci struct sockaddr_vm *dst, 1098c2ecf20Sopenharmony_ci struct sockaddr_vm *src) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 1128c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_read) = true; 1178c2ecf20Sopenharmony_ci memcpy(&PKT_FIELD(vsk, peer_waiting_read_info), &pkt->u.wait, 1188c2ecf20Sopenharmony_ci sizeof(PKT_FIELD(vsk, peer_waiting_read_info))); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (vmci_transport_notify_waiting_read(vsk)) { 1218c2ecf20Sopenharmony_ci bool sent; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (bottom_half) 1248c2ecf20Sopenharmony_ci sent = vmci_transport_send_wrote_bh(dst, src) > 0; 1258c2ecf20Sopenharmony_ci else 1268c2ecf20Sopenharmony_ci sent = vmci_transport_send_wrote(sk) > 0; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci if (sent) 1298c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_read) = false; 1308c2ecf20Sopenharmony_ci } 1318c2ecf20Sopenharmony_ci#endif 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic void 1358c2ecf20Sopenharmony_civmci_transport_handle_waiting_write(struct sock *sk, 1368c2ecf20Sopenharmony_ci struct vmci_transport_packet *pkt, 1378c2ecf20Sopenharmony_ci bool bottom_half, 1388c2ecf20Sopenharmony_ci struct sockaddr_vm *dst, 1398c2ecf20Sopenharmony_ci struct sockaddr_vm *src) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 1428c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write) = true; 1478c2ecf20Sopenharmony_ci memcpy(&PKT_FIELD(vsk, peer_waiting_write_info), &pkt->u.wait, 1488c2ecf20Sopenharmony_ci sizeof(PKT_FIELD(vsk, peer_waiting_write_info))); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci if (vmci_transport_notify_waiting_write(vsk)) { 1518c2ecf20Sopenharmony_ci bool sent; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (bottom_half) 1548c2ecf20Sopenharmony_ci sent = vmci_transport_send_read_bh(dst, src) > 0; 1558c2ecf20Sopenharmony_ci else 1568c2ecf20Sopenharmony_ci sent = vmci_transport_send_read(sk) > 0; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (sent) 1598c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write) = false; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci#endif 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic void 1658c2ecf20Sopenharmony_civmci_transport_handle_read(struct sock *sk, 1668c2ecf20Sopenharmony_ci struct vmci_transport_packet *pkt, 1678c2ecf20Sopenharmony_ci bool bottom_half, 1688c2ecf20Sopenharmony_ci struct sockaddr_vm *dst, struct sockaddr_vm *src) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 1718c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 1748c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_write) = false; 1758c2ecf20Sopenharmony_ci#endif 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci sk->sk_write_space(sk); 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic bool send_waiting_read(struct sock *sk, u64 room_needed) 1818c2ecf20Sopenharmony_ci{ 1828c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 1838c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 1848c2ecf20Sopenharmony_ci struct vmci_transport_waiting_info waiting_info; 1858c2ecf20Sopenharmony_ci u64 tail; 1868c2ecf20Sopenharmony_ci u64 head; 1878c2ecf20Sopenharmony_ci u64 room_left; 1888c2ecf20Sopenharmony_ci bool ret; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, sent_waiting_read)) 1938c2ecf20Sopenharmony_ci return true; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, write_notify_window) < 1968c2ecf20Sopenharmony_ci vmci_trans(vsk)->consume_size) 1978c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = 1988c2ecf20Sopenharmony_ci min(PKT_FIELD(vsk, write_notify_window) + PAGE_SIZE, 1998c2ecf20Sopenharmony_ci vmci_trans(vsk)->consume_size); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci vmci_qpair_get_consume_indexes(vmci_trans(vsk)->qpair, &tail, &head); 2028c2ecf20Sopenharmony_ci room_left = vmci_trans(vsk)->consume_size - head; 2038c2ecf20Sopenharmony_ci if (room_needed >= room_left) { 2048c2ecf20Sopenharmony_ci waiting_info.offset = room_needed - room_left; 2058c2ecf20Sopenharmony_ci waiting_info.generation = 2068c2ecf20Sopenharmony_ci PKT_FIELD(vsk, consume_q_generation) + 1; 2078c2ecf20Sopenharmony_ci } else { 2088c2ecf20Sopenharmony_ci waiting_info.offset = head + room_needed; 2098c2ecf20Sopenharmony_ci waiting_info.generation = PKT_FIELD(vsk, consume_q_generation); 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci ret = vmci_transport_send_waiting_read(sk, &waiting_info) > 0; 2138c2ecf20Sopenharmony_ci if (ret) 2148c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_read) = true; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci return ret; 2178c2ecf20Sopenharmony_ci#else 2188c2ecf20Sopenharmony_ci return true; 2198c2ecf20Sopenharmony_ci#endif 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic bool send_waiting_write(struct sock *sk, u64 room_needed) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 2258c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 2268c2ecf20Sopenharmony_ci struct vmci_transport_waiting_info waiting_info; 2278c2ecf20Sopenharmony_ci u64 tail; 2288c2ecf20Sopenharmony_ci u64 head; 2298c2ecf20Sopenharmony_ci u64 room_left; 2308c2ecf20Sopenharmony_ci bool ret; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, sent_waiting_write)) 2358c2ecf20Sopenharmony_ci return true; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci vmci_qpair_get_produce_indexes(vmci_trans(vsk)->qpair, &tail, &head); 2388c2ecf20Sopenharmony_ci room_left = vmci_trans(vsk)->produce_size - tail; 2398c2ecf20Sopenharmony_ci if (room_needed + 1 >= room_left) { 2408c2ecf20Sopenharmony_ci /* Wraps around to current generation. */ 2418c2ecf20Sopenharmony_ci waiting_info.offset = room_needed + 1 - room_left; 2428c2ecf20Sopenharmony_ci waiting_info.generation = PKT_FIELD(vsk, produce_q_generation); 2438c2ecf20Sopenharmony_ci } else { 2448c2ecf20Sopenharmony_ci waiting_info.offset = tail + room_needed + 1; 2458c2ecf20Sopenharmony_ci waiting_info.generation = 2468c2ecf20Sopenharmony_ci PKT_FIELD(vsk, produce_q_generation) - 1; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ret = vmci_transport_send_waiting_write(sk, &waiting_info) > 0; 2508c2ecf20Sopenharmony_ci if (ret) 2518c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_write) = true; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return ret; 2548c2ecf20Sopenharmony_ci#else 2558c2ecf20Sopenharmony_ci return true; 2568c2ecf20Sopenharmony_ci#endif 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic int vmci_transport_send_read_notification(struct sock *sk) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 2628c2ecf20Sopenharmony_ci bool sent_read; 2638c2ecf20Sopenharmony_ci unsigned int retries; 2648c2ecf20Sopenharmony_ci int err; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 2678c2ecf20Sopenharmony_ci sent_read = false; 2688c2ecf20Sopenharmony_ci retries = 0; 2698c2ecf20Sopenharmony_ci err = 0; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (vmci_transport_notify_waiting_write(vsk)) { 2728c2ecf20Sopenharmony_ci /* Notify the peer that we have read, retrying the send on 2738c2ecf20Sopenharmony_ci * failure up to our maximum value. XXX For now we just log 2748c2ecf20Sopenharmony_ci * the failure, but later we should schedule a work item to 2758c2ecf20Sopenharmony_ci * handle the resend until it succeeds. That would require 2768c2ecf20Sopenharmony_ci * keeping track of work items in the vsk and cleaning them up 2778c2ecf20Sopenharmony_ci * upon socket close. 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci while (!(vsk->peer_shutdown & RCV_SHUTDOWN) && 2808c2ecf20Sopenharmony_ci !sent_read && 2818c2ecf20Sopenharmony_ci retries < VMCI_TRANSPORT_MAX_DGRAM_RESENDS) { 2828c2ecf20Sopenharmony_ci err = vmci_transport_send_read(sk); 2838c2ecf20Sopenharmony_ci if (err >= 0) 2848c2ecf20Sopenharmony_ci sent_read = true; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci retries++; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (retries >= VMCI_TRANSPORT_MAX_DGRAM_RESENDS) 2908c2ecf20Sopenharmony_ci pr_err("%p unable to send read notify to peer\n", sk); 2918c2ecf20Sopenharmony_ci else 2928c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 2938c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write) = false; 2948c2ecf20Sopenharmony_ci#endif 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci return err; 2988c2ecf20Sopenharmony_ci} 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic void 3018c2ecf20Sopenharmony_civmci_transport_handle_wrote(struct sock *sk, 3028c2ecf20Sopenharmony_ci struct vmci_transport_packet *pkt, 3038c2ecf20Sopenharmony_ci bool bottom_half, 3048c2ecf20Sopenharmony_ci struct sockaddr_vm *dst, struct sockaddr_vm *src) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 3078c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 3088c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_read) = false; 3098c2ecf20Sopenharmony_ci#endif 3108c2ecf20Sopenharmony_ci sk->sk_data_ready(sk); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic void vmci_transport_notify_pkt_socket_init(struct sock *sk) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = PAGE_SIZE; 3188c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window) = PAGE_SIZE; 3198c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_read) = false; 3208c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write) = false; 3218c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_write_detected) = false; 3228c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_read) = false; 3238c2ecf20Sopenharmony_ci PKT_FIELD(vsk, sent_waiting_write) = false; 3248c2ecf20Sopenharmony_ci PKT_FIELD(vsk, produce_q_generation) = 0; 3258c2ecf20Sopenharmony_ci PKT_FIELD(vsk, consume_q_generation) = 0; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci memset(&PKT_FIELD(vsk, peer_waiting_read_info), 0, 3288c2ecf20Sopenharmony_ci sizeof(PKT_FIELD(vsk, peer_waiting_read_info))); 3298c2ecf20Sopenharmony_ci memset(&PKT_FIELD(vsk, peer_waiting_write_info), 0, 3308c2ecf20Sopenharmony_ci sizeof(PKT_FIELD(vsk, peer_waiting_write_info))); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic void vmci_transport_notify_pkt_socket_destruct(struct vsock_sock *vsk) 3348c2ecf20Sopenharmony_ci{ 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic int 3388c2ecf20Sopenharmony_civmci_transport_notify_pkt_poll_in(struct sock *sk, 3398c2ecf20Sopenharmony_ci size_t target, bool *data_ready_now) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (vsock_stream_has_data(vsk)) { 3448c2ecf20Sopenharmony_ci *data_ready_now = true; 3458c2ecf20Sopenharmony_ci } else { 3468c2ecf20Sopenharmony_ci /* We can't read right now because there is nothing in the 3478c2ecf20Sopenharmony_ci * queue. Ask for notifications when there is something to 3488c2ecf20Sopenharmony_ci * read. 3498c2ecf20Sopenharmony_ci */ 3508c2ecf20Sopenharmony_ci if (sk->sk_state == TCP_ESTABLISHED) { 3518c2ecf20Sopenharmony_ci if (!send_waiting_read(sk, 1)) 3528c2ecf20Sopenharmony_ci return -1; 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci *data_ready_now = false; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return 0; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic int 3628c2ecf20Sopenharmony_civmci_transport_notify_pkt_poll_out(struct sock *sk, 3638c2ecf20Sopenharmony_ci size_t target, bool *space_avail_now) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci s64 produce_q_free_space; 3668c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci produce_q_free_space = vsock_stream_has_space(vsk); 3698c2ecf20Sopenharmony_ci if (produce_q_free_space > 0) { 3708c2ecf20Sopenharmony_ci *space_avail_now = true; 3718c2ecf20Sopenharmony_ci return 0; 3728c2ecf20Sopenharmony_ci } else if (produce_q_free_space == 0) { 3738c2ecf20Sopenharmony_ci /* This is a connected socket but we can't currently send data. 3748c2ecf20Sopenharmony_ci * Notify the peer that we are waiting if the queue is full. We 3758c2ecf20Sopenharmony_ci * only send a waiting write if the queue is full because 3768c2ecf20Sopenharmony_ci * otherwise we end up in an infinite WAITING_WRITE, READ, 3778c2ecf20Sopenharmony_ci * WAITING_WRITE, READ, etc. loop. Treat failing to send the 3788c2ecf20Sopenharmony_ci * notification as a socket error, passing that back through 3798c2ecf20Sopenharmony_ci * the mask. 3808c2ecf20Sopenharmony_ci */ 3818c2ecf20Sopenharmony_ci if (!send_waiting_write(sk, 1)) 3828c2ecf20Sopenharmony_ci return -1; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci *space_avail_now = false; 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci return 0; 3888c2ecf20Sopenharmony_ci} 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistatic int 3918c2ecf20Sopenharmony_civmci_transport_notify_pkt_recv_init( 3928c2ecf20Sopenharmony_ci struct sock *sk, 3938c2ecf20Sopenharmony_ci size_t target, 3948c2ecf20Sopenharmony_ci struct vmci_transport_recv_notify_data *data) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_WAITING_NOTIFY 3998c2ecf20Sopenharmony_ci data->consume_head = 0; 4008c2ecf20Sopenharmony_ci data->produce_tail = 0; 4018c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL 4028c2ecf20Sopenharmony_ci data->notify_on_block = false; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, write_notify_min_window) < target + 1) { 4058c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window) = target + 1; 4068c2ecf20Sopenharmony_ci if (PKT_FIELD(vsk, write_notify_window) < 4078c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window)) { 4088c2ecf20Sopenharmony_ci /* If the current window is smaller than the new 4098c2ecf20Sopenharmony_ci * minimal window size, we need to reevaluate whether 4108c2ecf20Sopenharmony_ci * we need to notify the sender. If the number of ready 4118c2ecf20Sopenharmony_ci * bytes are smaller than the new window, we need to 4128c2ecf20Sopenharmony_ci * send a notification to the sender before we block. 4138c2ecf20Sopenharmony_ci */ 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = 4168c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window); 4178c2ecf20Sopenharmony_ci data->notify_on_block = true; 4188c2ecf20Sopenharmony_ci } 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci#endif 4218c2ecf20Sopenharmony_ci#endif 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci return 0; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int 4278c2ecf20Sopenharmony_civmci_transport_notify_pkt_recv_pre_block( 4288c2ecf20Sopenharmony_ci struct sock *sk, 4298c2ecf20Sopenharmony_ci size_t target, 4308c2ecf20Sopenharmony_ci struct vmci_transport_recv_notify_data *data) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci int err = 0; 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci /* Notify our peer that we are waiting for data to read. */ 4358c2ecf20Sopenharmony_ci if (!send_waiting_read(sk, target)) { 4368c2ecf20Sopenharmony_ci err = -EHOSTUNREACH; 4378c2ecf20Sopenharmony_ci return err; 4388c2ecf20Sopenharmony_ci } 4398c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_FLOW_CONTROL 4408c2ecf20Sopenharmony_ci if (data->notify_on_block) { 4418c2ecf20Sopenharmony_ci err = vmci_transport_send_read_notification(sk); 4428c2ecf20Sopenharmony_ci if (err < 0) 4438c2ecf20Sopenharmony_ci return err; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci data->notify_on_block = false; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci#endif 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci return err; 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_cistatic int 4538c2ecf20Sopenharmony_civmci_transport_notify_pkt_recv_pre_dequeue( 4548c2ecf20Sopenharmony_ci struct sock *sk, 4558c2ecf20Sopenharmony_ci size_t target, 4568c2ecf20Sopenharmony_ci struct vmci_transport_recv_notify_data *data) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci /* Now consume up to len bytes from the queue. Note that since we have 4618c2ecf20Sopenharmony_ci * the socket locked we should copy at least ready bytes. 4628c2ecf20Sopenharmony_ci */ 4638c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 4648c2ecf20Sopenharmony_ci vmci_qpair_get_consume_indexes(vmci_trans(vsk)->qpair, 4658c2ecf20Sopenharmony_ci &data->produce_tail, 4668c2ecf20Sopenharmony_ci &data->consume_head); 4678c2ecf20Sopenharmony_ci#endif 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return 0; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic int 4738c2ecf20Sopenharmony_civmci_transport_notify_pkt_recv_post_dequeue( 4748c2ecf20Sopenharmony_ci struct sock *sk, 4758c2ecf20Sopenharmony_ci size_t target, 4768c2ecf20Sopenharmony_ci ssize_t copied, 4778c2ecf20Sopenharmony_ci bool data_read, 4788c2ecf20Sopenharmony_ci struct vmci_transport_recv_notify_data *data) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 4818c2ecf20Sopenharmony_ci int err; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 4848c2ecf20Sopenharmony_ci err = 0; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci if (data_read) { 4878c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 4888c2ecf20Sopenharmony_ci /* Detect a wrap-around to maintain queue generation. Note 4898c2ecf20Sopenharmony_ci * that this is safe since we hold the socket lock across the 4908c2ecf20Sopenharmony_ci * two queue pair operations. 4918c2ecf20Sopenharmony_ci */ 4928c2ecf20Sopenharmony_ci if (copied >= 4938c2ecf20Sopenharmony_ci vmci_trans(vsk)->consume_size - data->consume_head) 4948c2ecf20Sopenharmony_ci PKT_FIELD(vsk, consume_q_generation)++; 4958c2ecf20Sopenharmony_ci#endif 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci err = vmci_transport_send_read_notification(sk); 4988c2ecf20Sopenharmony_ci if (err < 0) 4998c2ecf20Sopenharmony_ci return err; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci } 5028c2ecf20Sopenharmony_ci return err; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_cistatic int 5068c2ecf20Sopenharmony_civmci_transport_notify_pkt_send_init( 5078c2ecf20Sopenharmony_ci struct sock *sk, 5088c2ecf20Sopenharmony_ci struct vmci_transport_send_notify_data *data) 5098c2ecf20Sopenharmony_ci{ 5108c2ecf20Sopenharmony_ci#ifdef VSOCK_OPTIMIZATION_WAITING_NOTIFY 5118c2ecf20Sopenharmony_ci data->consume_head = 0; 5128c2ecf20Sopenharmony_ci data->produce_tail = 0; 5138c2ecf20Sopenharmony_ci#endif 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci return 0; 5168c2ecf20Sopenharmony_ci} 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_cistatic int 5198c2ecf20Sopenharmony_civmci_transport_notify_pkt_send_pre_block( 5208c2ecf20Sopenharmony_ci struct sock *sk, 5218c2ecf20Sopenharmony_ci struct vmci_transport_send_notify_data *data) 5228c2ecf20Sopenharmony_ci{ 5238c2ecf20Sopenharmony_ci /* Notify our peer that we are waiting for room to write. */ 5248c2ecf20Sopenharmony_ci if (!send_waiting_write(sk, 1)) 5258c2ecf20Sopenharmony_ci return -EHOSTUNREACH; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci return 0; 5288c2ecf20Sopenharmony_ci} 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_cistatic int 5318c2ecf20Sopenharmony_civmci_transport_notify_pkt_send_pre_enqueue( 5328c2ecf20Sopenharmony_ci struct sock *sk, 5338c2ecf20Sopenharmony_ci struct vmci_transport_send_notify_data *data) 5348c2ecf20Sopenharmony_ci{ 5358c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 5388c2ecf20Sopenharmony_ci vmci_qpair_get_produce_indexes(vmci_trans(vsk)->qpair, 5398c2ecf20Sopenharmony_ci &data->produce_tail, 5408c2ecf20Sopenharmony_ci &data->consume_head); 5418c2ecf20Sopenharmony_ci#endif 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci return 0; 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic int 5478c2ecf20Sopenharmony_civmci_transport_notify_pkt_send_post_enqueue( 5488c2ecf20Sopenharmony_ci struct sock *sk, 5498c2ecf20Sopenharmony_ci ssize_t written, 5508c2ecf20Sopenharmony_ci struct vmci_transport_send_notify_data *data) 5518c2ecf20Sopenharmony_ci{ 5528c2ecf20Sopenharmony_ci int err = 0; 5538c2ecf20Sopenharmony_ci struct vsock_sock *vsk; 5548c2ecf20Sopenharmony_ci bool sent_wrote = false; 5558c2ecf20Sopenharmony_ci int retries = 0; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci vsk = vsock_sk(sk); 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 5608c2ecf20Sopenharmony_ci /* Detect a wrap-around to maintain queue generation. Note that this 5618c2ecf20Sopenharmony_ci * is safe since we hold the socket lock across the two queue pair 5628c2ecf20Sopenharmony_ci * operations. 5638c2ecf20Sopenharmony_ci */ 5648c2ecf20Sopenharmony_ci if (written >= vmci_trans(vsk)->produce_size - data->produce_tail) 5658c2ecf20Sopenharmony_ci PKT_FIELD(vsk, produce_q_generation)++; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci#endif 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci if (vmci_transport_notify_waiting_read(vsk)) { 5708c2ecf20Sopenharmony_ci /* Notify the peer that we have written, retrying the send on 5718c2ecf20Sopenharmony_ci * failure up to our maximum value. See the XXX comment for the 5728c2ecf20Sopenharmony_ci * corresponding piece of code in StreamRecvmsg() for potential 5738c2ecf20Sopenharmony_ci * improvements. 5748c2ecf20Sopenharmony_ci */ 5758c2ecf20Sopenharmony_ci while (!(vsk->peer_shutdown & RCV_SHUTDOWN) && 5768c2ecf20Sopenharmony_ci !sent_wrote && 5778c2ecf20Sopenharmony_ci retries < VMCI_TRANSPORT_MAX_DGRAM_RESENDS) { 5788c2ecf20Sopenharmony_ci err = vmci_transport_send_wrote(sk); 5798c2ecf20Sopenharmony_ci if (err >= 0) 5808c2ecf20Sopenharmony_ci sent_wrote = true; 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci retries++; 5838c2ecf20Sopenharmony_ci } 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci if (retries >= VMCI_TRANSPORT_MAX_DGRAM_RESENDS) { 5868c2ecf20Sopenharmony_ci pr_err("%p unable to send wrote notify to peer\n", sk); 5878c2ecf20Sopenharmony_ci return err; 5888c2ecf20Sopenharmony_ci } else { 5898c2ecf20Sopenharmony_ci#if defined(VSOCK_OPTIMIZATION_WAITING_NOTIFY) 5908c2ecf20Sopenharmony_ci PKT_FIELD(vsk, peer_waiting_read) = false; 5918c2ecf20Sopenharmony_ci#endif 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci } 5948c2ecf20Sopenharmony_ci return err; 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic void 5988c2ecf20Sopenharmony_civmci_transport_notify_pkt_handle_pkt( 5998c2ecf20Sopenharmony_ci struct sock *sk, 6008c2ecf20Sopenharmony_ci struct vmci_transport_packet *pkt, 6018c2ecf20Sopenharmony_ci bool bottom_half, 6028c2ecf20Sopenharmony_ci struct sockaddr_vm *dst, 6038c2ecf20Sopenharmony_ci struct sockaddr_vm *src, bool *pkt_processed) 6048c2ecf20Sopenharmony_ci{ 6058c2ecf20Sopenharmony_ci bool processed = false; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci switch (pkt->type) { 6088c2ecf20Sopenharmony_ci case VMCI_TRANSPORT_PACKET_TYPE_WROTE: 6098c2ecf20Sopenharmony_ci vmci_transport_handle_wrote(sk, pkt, bottom_half, dst, src); 6108c2ecf20Sopenharmony_ci processed = true; 6118c2ecf20Sopenharmony_ci break; 6128c2ecf20Sopenharmony_ci case VMCI_TRANSPORT_PACKET_TYPE_READ: 6138c2ecf20Sopenharmony_ci vmci_transport_handle_read(sk, pkt, bottom_half, dst, src); 6148c2ecf20Sopenharmony_ci processed = true; 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci case VMCI_TRANSPORT_PACKET_TYPE_WAITING_WRITE: 6178c2ecf20Sopenharmony_ci vmci_transport_handle_waiting_write(sk, pkt, bottom_half, 6188c2ecf20Sopenharmony_ci dst, src); 6198c2ecf20Sopenharmony_ci processed = true; 6208c2ecf20Sopenharmony_ci break; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci case VMCI_TRANSPORT_PACKET_TYPE_WAITING_READ: 6238c2ecf20Sopenharmony_ci vmci_transport_handle_waiting_read(sk, pkt, bottom_half, 6248c2ecf20Sopenharmony_ci dst, src); 6258c2ecf20Sopenharmony_ci processed = true; 6268c2ecf20Sopenharmony_ci break; 6278c2ecf20Sopenharmony_ci } 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci if (pkt_processed) 6308c2ecf20Sopenharmony_ci *pkt_processed = processed; 6318c2ecf20Sopenharmony_ci} 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_cistatic void vmci_transport_notify_pkt_process_request(struct sock *sk) 6348c2ecf20Sopenharmony_ci{ 6358c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = vmci_trans(vsk)->consume_size; 6388c2ecf20Sopenharmony_ci if (vmci_trans(vsk)->consume_size < 6398c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window)) 6408c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window) = 6418c2ecf20Sopenharmony_ci vmci_trans(vsk)->consume_size; 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_cistatic void vmci_transport_notify_pkt_process_negotiate(struct sock *sk) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci struct vsock_sock *vsk = vsock_sk(sk); 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_window) = vmci_trans(vsk)->consume_size; 6498c2ecf20Sopenharmony_ci if (vmci_trans(vsk)->consume_size < 6508c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window)) 6518c2ecf20Sopenharmony_ci PKT_FIELD(vsk, write_notify_min_window) = 6528c2ecf20Sopenharmony_ci vmci_trans(vsk)->consume_size; 6538c2ecf20Sopenharmony_ci} 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci/* Socket control packet based operations. */ 6568c2ecf20Sopenharmony_ciconst struct vmci_transport_notify_ops vmci_transport_notify_pkt_ops = { 6578c2ecf20Sopenharmony_ci .socket_init = vmci_transport_notify_pkt_socket_init, 6588c2ecf20Sopenharmony_ci .socket_destruct = vmci_transport_notify_pkt_socket_destruct, 6598c2ecf20Sopenharmony_ci .poll_in = vmci_transport_notify_pkt_poll_in, 6608c2ecf20Sopenharmony_ci .poll_out = vmci_transport_notify_pkt_poll_out, 6618c2ecf20Sopenharmony_ci .handle_notify_pkt = vmci_transport_notify_pkt_handle_pkt, 6628c2ecf20Sopenharmony_ci .recv_init = vmci_transport_notify_pkt_recv_init, 6638c2ecf20Sopenharmony_ci .recv_pre_block = vmci_transport_notify_pkt_recv_pre_block, 6648c2ecf20Sopenharmony_ci .recv_pre_dequeue = vmci_transport_notify_pkt_recv_pre_dequeue, 6658c2ecf20Sopenharmony_ci .recv_post_dequeue = vmci_transport_notify_pkt_recv_post_dequeue, 6668c2ecf20Sopenharmony_ci .send_init = vmci_transport_notify_pkt_send_init, 6678c2ecf20Sopenharmony_ci .send_pre_block = vmci_transport_notify_pkt_send_pre_block, 6688c2ecf20Sopenharmony_ci .send_pre_enqueue = vmci_transport_notify_pkt_send_pre_enqueue, 6698c2ecf20Sopenharmony_ci .send_post_enqueue = vmci_transport_notify_pkt_send_post_enqueue, 6708c2ecf20Sopenharmony_ci .process_request = vmci_transport_notify_pkt_process_request, 6718c2ecf20Sopenharmony_ci .process_negotiate = vmci_transport_notify_pkt_process_negotiate, 6728c2ecf20Sopenharmony_ci}; 673