text: /* 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_register(void);
  void vmci_transport_unregister(void);
  
  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
  