root/net/vmw_vsock/vmci_transport.h
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * VMware vSockets Driver
 *
 * Copyright (C) 2013 VMware, Inc. All rights reserved.
 */

#ifndef _VMCI_TRANSPORT_H_
#define _VMCI_TRANSPORT_H_

#include <linux/vmw_vmci_defs.h>
#include <linux/vmw_vmci_api.h>

#include <net/vsock_addr.h>
#include <net/af_vsock.h>

/* If the packet format changes in a release then this should change too. */
#define VMCI_TRANSPORT_PACKET_VERSION 1

/* The resource ID on which control packets are sent. */
#define VMCI_TRANSPORT_PACKET_RID 1

/* The resource ID on which control packets are sent to the hypervisor. */
#define VMCI_TRANSPORT_HYPERVISOR_PACKET_RID 15

#define VSOCK_PROTO_INVALID        0
#define VSOCK_PROTO_PKT_ON_NOTIFY (1 << 0)
#define VSOCK_PROTO_ALL_SUPPORTED (VSOCK_PROTO_PKT_ON_NOTIFY)

#define vmci_trans(_vsk) ((struct vmci_transport *)((_vsk)->trans))

enum vmci_transport_packet_type {
        VMCI_TRANSPORT_PACKET_TYPE_INVALID = 0,
        VMCI_TRANSPORT_PACKET_TYPE_REQUEST,
        VMCI_TRANSPORT_PACKET_TYPE_NEGOTIATE,
        VMCI_TRANSPORT_PACKET_TYPE_OFFER,
        VMCI_TRANSPORT_PACKET_TYPE_ATTACH,
        VMCI_TRANSPORT_PACKET_TYPE_WROTE,
        VMCI_TRANSPORT_PACKET_TYPE_READ,
        VMCI_TRANSPORT_PACKET_TYPE_RST,
        VMCI_TRANSPORT_PACKET_TYPE_SHUTDOWN,
        VMCI_TRANSPORT_PACKET_TYPE_WAITING_WRITE,
        VMCI_TRANSPORT_PACKET_TYPE_WAITING_READ,
        VMCI_TRANSPORT_PACKET_TYPE_REQUEST2,
        VMCI_TRANSPORT_PACKET_TYPE_NEGOTIATE2,
        VMCI_TRANSPORT_PACKET_TYPE_MAX
};

struct vmci_transport_waiting_info {
        u64 generation;
        u64 offset;
};

/* Control packet type for STREAM sockets.  DGRAMs have no control packets nor
 * special packet header for data packets, they are just raw VMCI DGRAM
 * messages.  For STREAMs, control packets are sent over the control channel
 * while data is written and read directly from queue pairs with no packet
 * format.
 */
struct vmci_transport_packet {
        struct vmci_datagram dg;
        u8 version;
        u8 type;
        u16 proto;
        u32 src_port;
        u32 dst_port;
        u32 _reserved2;
        union {
                u64 size;
                u64 mode;
                struct vmci_handle handle;
                struct vmci_transport_waiting_info wait;
        } u;
};

struct vmci_transport_notify_pkt {
        u64 write_notify_window;
        u64 write_notify_min_window;
        bool peer_waiting_read;
        bool peer_waiting_write;
        bool peer_waiting_write_detected;
        bool sent_waiting_read;
        bool sent_waiting_write;
        struct vmci_transport_waiting_info peer_waiting_read_info;
        struct vmci_transport_waiting_info peer_waiting_write_info;
        u64 produce_q_generation;
        u64 consume_q_generation;
};

struct vmci_transport_notify_pkt_q_state {
        u64 write_notify_window;
        u64 write_notify_min_window;
        bool peer_waiting_write;
        bool peer_waiting_write_detected;
};

union vmci_transport_notify {
        struct vmci_transport_notify_pkt pkt;
        struct vmci_transport_notify_pkt_q_state pkt_q_state;
};

/* Our transport-specific data. */
struct vmci_transport {
        /* For DGRAMs. */
        struct vmci_handle dg_handle;
        /* For STREAMs. */
        struct vmci_handle qp_handle;
        struct vmci_qp *qpair;
        u64 produce_size;
        u64 consume_size;
        u32 detach_sub_id;
        union vmci_transport_notify notify;
        const struct vmci_transport_notify_ops *notify_ops;
        struct list_head elem;
        struct sock *sk;
        spinlock_t lock; /* protects sk. */
};

int vmci_transport_send_wrote_bh(struct sockaddr_vm *dst,
                                 struct sockaddr_vm *src);
int vmci_transport_send_read_bh(struct sockaddr_vm *dst,
                                struct sockaddr_vm *src);
int vmci_transport_send_wrote(struct sock *sk);
int vmci_transport_send_read(struct sock *sk);
int vmci_transport_send_waiting_write(struct sock *sk,
                                      struct vmci_transport_waiting_info *wait);
int vmci_transport_send_waiting_read(struct sock *sk,
                                     struct vmci_transport_waiting_info *wait);

#endif