Add a header with data structures and constants defining the protocol for communication between the guest and the hypervisor implementing the Hyper-V/VMBus network adapter.
Mostly taken from the corresponding definitions in the Linux kernel. TODO: move RNDIS stuff to rndis.h Signed-off-by: Roman Kagan <rka...@virtuozzo.com> --- hw/net/hvnet-proto.h | 1161 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1161 insertions(+) create mode 100644 hw/net/hvnet-proto.h diff --git a/hw/net/hvnet-proto.h b/hw/net/hvnet-proto.h new file mode 100644 index 0000000000..1582c7e5a2 --- /dev/null +++ b/hw/net/hvnet-proto.h @@ -0,0 +1,1161 @@ +/* + * Hyper-V network device protocol definitions + * + * Copyright (c) 2011, Microsoft Corporation. + * Copyright (c) 2018 Virtuozzo International GmbH. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#ifndef _HVNET_PROTO_H_ +#define _HVNET_PROTO_H_ + +/**** + * c&p from linux drivers/net/hyperv/hyperv_net.h + ****/ + +/* RSS related */ +#define OID_GEN_RECEIVE_SCALE_CAPABILITIES 0x00010203 /* query only */ +#define OID_GEN_RECEIVE_SCALE_PARAMETERS 0x00010204 /* query and set */ + +#define NDIS_OBJECT_TYPE_RSS_CAPABILITIES 0x88 +#define NDIS_OBJECT_TYPE_RSS_PARAMETERS 0x89 +#define NDIS_OBJECT_TYPE_OFFLOAD 0xa7 + +#define NDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2 2 +#define NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2 2 + +struct ndis_obj_header { + uint8_t type; + uint8_t rev; + uint16_t size; +} QEMU_PACKED; + +/* ndis_recv_scale_cap/cap_flag */ +#define NDIS_RSS_CAPS_MESSAGE_SIGNALED_INTERRUPTS 0x01000000 +#define NDIS_RSS_CAPS_CLASSIFICATION_AT_ISR 0x02000000 +#define NDIS_RSS_CAPS_CLASSIFICATION_AT_DPC 0x04000000 +#define NDIS_RSS_CAPS_USING_MSI_X 0x08000000 +#define NDIS_RSS_CAPS_RSS_AVAILABLE_ON_PORTS 0x10000000 +#define NDIS_RSS_CAPS_SUPPORTS_MSI_X 0x20000000 +#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV4 0x00000100 +#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6 0x00000200 +#define NDIS_RSS_CAPS_HASH_TYPE_TCP_IPV6_EX 0x00000400 + +struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */ + struct ndis_obj_header hdr; + uint32_t cap_flag; + uint32_t num_int_msg; + uint32_t num_recv_que; + uint16_t num_indirect_tabent; +} QEMU_PACKED; + + +/* ndis_recv_scale_param flags */ +#define NDIS_RSS_PARAM_FLAG_BASE_CPU_UNCHANGED 0x0001 +#define NDIS_RSS_PARAM_FLAG_HASH_INFO_UNCHANGED 0x0002 +#define NDIS_RSS_PARAM_FLAG_ITABLE_UNCHANGED 0x0004 +#define NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED 0x0008 +#define NDIS_RSS_PARAM_FLAG_DISABLE_RSS 0x0010 + +/* Hash info bits */ +#define NDIS_HASH_FUNC_TOEPLITZ 0x00000001 +#define NDIS_HASH_IPV4 0x00000100 +#define NDIS_HASH_TCP_IPV4 0x00000200 +#define NDIS_HASH_IPV6 0x00000400 +#define NDIS_HASH_IPV6_EX 0x00000800 +#define NDIS_HASH_TCP_IPV6 0x00001000 +#define NDIS_HASH_TCP_IPV6_EX 0x00002000 + +#define NDIS_RSS_INDIRECTION_TABLE_MAX_SIZE_REVISION_2 (128 * 4) +#define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40 + +#define ITAB_NUM 128 + +struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */ + struct ndis_obj_header hdr; + + /* Qualifies the rest of the information */ + uint16_t flag; + + /* The base CPU number to do receive processing. not used */ + uint16_t base_cpu_number; + + /* This describes the hash function and type being enabled */ + uint32_t hashinfo; + + /* The size of indirection table array */ + uint16_t indirect_tabsize; + + /* The offset of the indirection table from the beginning of this + * structure + */ + uint32_t indirect_taboffset; + + /* The size of the hash secret key */ + uint16_t hashkey_size; + + /* The offset of the secret key from the beginning of this structure */ + uint32_t kashkey_offset; + + uint32_t processor_masks_offset; + uint32_t num_processor_masks; + uint32_t processor_masks_entry_size; +}; + +/* Fwd declaration */ +struct ndis_tcp_ip_checksum_info; +struct ndis_pkt_8021q_info; + +/* + * Represent netvsc packet which contains 1 RNDIS and 1 ethernet frame + * within the RNDIS + * + * The size of this structure is less than 48 bytes and we can now + * place this structure in the skb->cb field. + */ +struct hv_netvsc_packet { + /* Bookkeeping stuff */ + uint8_t cp_partial; /* partial copy into send buffer */ + + uint8_t rmsg_size; /* RNDIS header and PPI size */ + uint8_t rmsg_pgcnt; /* page count of RNDIS header and PPI */ + uint8_t page_buf_cnt; + + uint16_t q_idx; + uint16_t total_packets; + + uint32_t total_bytes; + uint32_t send_buf_index; + uint32_t total_data_buflen; +}; + +enum rndis_device_state { + RNDIS_DEV_UNINITIALIZED = 0, + RNDIS_DEV_INITIALIZING, + RNDIS_DEV_INITIALIZED, + RNDIS_DEV_DATAINITIALIZED, +}; + +#define NETVSC_HASH_KEYLEN 40 + +#define NVSP_INVALID_PROTOCOL_VERSION ((uint32_t)0xFFFFFFFF) + +#define NVSP_PROTOCOL_VERSION_1 2 +#define NVSP_PROTOCOL_VERSION_2 0x30002 +#define NVSP_PROTOCOL_VERSION_4 0x40000 +#define NVSP_PROTOCOL_VERSION_5 0x50000 + +enum { + NVSP_MSG_TYPE_NONE = 0, + + /* Init Messages */ + NVSP_MSG_TYPE_INIT = 1, + NVSP_MSG_TYPE_INIT_COMPLETE = 2, + + NVSP_VERSION_MSG_START = 100, + + /* Version 1 Messages */ + NVSP_MSG1_TYPE_SEND_NDIS_VER = NVSP_VERSION_MSG_START, + + NVSP_MSG1_TYPE_SEND_RECV_BUF, + NVSP_MSG1_TYPE_SEND_RECV_BUF_COMPLETE, + NVSP_MSG1_TYPE_REVOKE_RECV_BUF, + + NVSP_MSG1_TYPE_SEND_SEND_BUF, + NVSP_MSG1_TYPE_SEND_SEND_BUF_COMPLETE, + NVSP_MSG1_TYPE_REVOKE_SEND_BUF, + + NVSP_MSG1_TYPE_SEND_RNDIS_PKT, + NVSP_MSG1_TYPE_SEND_RNDIS_PKT_COMPLETE, + + /* Version 2 messages */ + NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF, + NVSP_MSG2_TYPE_SEND_CHIMNEY_DELEGATED_BUF_COMP, + NVSP_MSG2_TYPE_REVOKE_CHIMNEY_DELEGATED_BUF, + + NVSP_MSG2_TYPE_RESUME_CHIMNEY_RX_INDICATION, + + NVSP_MSG2_TYPE_TERMINATE_CHIMNEY, + NVSP_MSG2_TYPE_TERMINATE_CHIMNEY_COMP, + + NVSP_MSG2_TYPE_INDICATE_CHIMNEY_EVENT, + + NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT, + NVSP_MSG2_TYPE_SEND_CHIMNEY_PKT_COMP, + + NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ, + NVSP_MSG2_TYPE_POST_CHIMNEY_RECV_REQ_COMP, + + NVSP_MSG2_TYPE_ALLOC_RXBUF, + NVSP_MSG2_TYPE_ALLOC_RXBUF_COMP, + + NVSP_MSG2_TYPE_FREE_RXBUF, + + NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT, + NVSP_MSG2_TYPE_SEND_VMQ_RNDIS_PKT_COMP, + + NVSP_MSG2_TYPE_SEND_NDIS_CONFIG, + + NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE, + NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP, + + NVSP_MSG2_MAX = NVSP_MSG2_TYPE_ALLOC_CHIMNEY_HANDLE_COMP, + + /* Version 4 messages */ + NVSP_MSG4_TYPE_SEND_VF_ASSOCIATION, + NVSP_MSG4_TYPE_SWITCH_DATA_PATH, + NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED, + + NVSP_MSG4_MAX = NVSP_MSG4_TYPE_UPLINK_CONNECT_STATE_DEPRECATED, + + /* Version 5 messages */ + NVSP_MSG5_TYPE_OID_QUERY_EX, + NVSP_MSG5_TYPE_OID_QUERY_EX_COMP, + NVSP_MSG5_TYPE_SUBCHANNEL, + NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE, + + NVSP_MSG5_MAX = NVSP_MSG5_TYPE_SEND_INDIRECTION_TABLE, +}; + +enum { + NVSP_STAT_NONE = 0, + NVSP_STAT_SUCCESS, + NVSP_STAT_FAIL, + NVSP_STAT_PROTOCOL_TOO_NEW, + NVSP_STAT_PROTOCOL_TOO_OLD, + NVSP_STAT_INVALID_RNDIS_PKT, + NVSP_STAT_BUSY, + NVSP_STAT_PROTOCOL_UNSUPPORTED, + NVSP_STAT_MAX, +}; + +struct nvsp_msg_header { + uint32_t msg_type; +}; + +/* Init Messages */ + +/* + * This message is used by the VSC to initialize the channel after the channels + * has been opened. This message should never include anything other then + * versioning (i.e. this message will be the same for ever). + */ +struct nvsp_msg_init { + uint32_t min_protocol_ver; + uint32_t max_protocol_ver; +} QEMU_PACKED; + +/* + * This message is used by the VSP to complete the initialization of the + * channel. This message should never include anything other then versioning + * (i.e. this message will be the same for ever). + */ +struct nvsp_msg_init_complete { + uint32_t negotiated_protocol_ver; + uint32_t max_mdl_chain_len; + uint32_t status; +}; + +/* Version 1 Messages */ + +/* + * This message is used by the VSC to send the NDIS version to the VSP. The VSP + * can use this information when handling OIDs sent by the VSC. + */ +struct nvsp1_msg_ndis_ver { + uint32_t ndis_major_ver; + uint32_t ndis_minor_ver; +} QEMU_PACKED; + +/* + * This message is used by the VSC to send a receive buffer to the VSP. The VSP + * can then use the receive buffer to send data to the VSC. + */ +struct nvsp1_msg_rcvbuf { + uint32_t gpadl_handle; + uint16_t id; +} QEMU_PACKED; + +struct nvsp1_rcvbuf_section { + uint32_t offset; + uint32_t sub_alloc_size; + uint32_t num_sub_allocs; + uint32_t end_offset; +} QEMU_PACKED; + +/* + * This message is used by the VSP to acknowledge a receive buffer send by the + * VSC. This message must be sent by the VSP before the VSP uses the receive + * buffer. + */ +struct nvsp1_msg_rcvbuf_complete { + uint32_t status; + uint32_t num_sections; + + /* + * The receive buffer is split into two parts, a large suballocation + * section and a small suballocation section. These sections are then + * suballocated by a certain size. + */ + + /* + * For example, the following break up of the receive buffer has 6 + * large suballocations and 10 small suballocations. + */ + + /* + * | Large Section | | Small Section | + * ------------------------------------------------------------ + * | | | | | | | | | | | | | | | | | | + * | | + * LargeOffset SmallOffset + */ + + struct nvsp1_rcvbuf_section sections[1]; +} QEMU_PACKED; + +/* + * This message is sent by the VSC to revoke the receive buffer. After the VSP + * completes this transaction, the vsp should never use the receive buffer + * again. + */ +struct nvsp1_msg_revoke_rcvbuf { + uint16_t id; +}; + +/* + * This message is used by the VSC to send a send buffer to the VSP. The VSC + * can then use the send buffer to send data to the VSP. + */ +struct nvsp1_msg_sndbuf { + uint32_t gpadl_handle; + uint16_t id; +} QEMU_PACKED; + +/* + * This message is used by the VSP to acknowledge a send buffer sent by the + * VSC. This message must be sent by the VSP before the VSP uses the sent + * buffer. + */ +struct nvsp1_msg_sndbuf_complete { + uint32_t status; + + /* + * The VSC gets to choose the size of the send buffer and the VSP gets + * to choose the sections size of the buffer. This was done to enable + * dynamic reconfigurations when the cost of GPA-direct buffers + * decreases. + */ + uint32_t section_size; +} QEMU_PACKED; + +/* + * This message is sent by the VSC to revoke the send buffer. After the VSP + * completes this transaction, the vsp should never use the send buffer again. + */ +struct nvsp1_msg_revoke_sndbuf { + uint16_t id; +}; + +/* + * This message is used by both the VSP and the VSC to send a RNDIS message to + * the opposite channel endpoint. + */ +struct nvsp1_msg_rndis_pkt { + /* + * This field is specified by RNDIS. They assume there's two different + * channels of communication. However, the Network VSP only has one. + * Therefore, the channel travels with the RNDIS packet. + */ + uint32_t channel_type; + + /* + * This field is used to send part or all of the data through a send + * buffer. This values specifies an index into the send buffer. If the + * index is 0xFFFFFFFF, then the send buffer is not being used and all + * of the data was sent through other VMBus mechanisms. + */ + uint32_t send_buf_section_index; + uint32_t send_buf_section_size; +} QEMU_PACKED; + +/* + * This message is used by both the VSP and the VSC to complete a RNDIS message + * to the opposite channel endpoint. At this point, the initiator of this + * message cannot use any resources associated with the original RNDIS packet. + */ +struct nvsp1_msg_rndis_pkt_complete { + uint32_t status; +}; + +/* + * Network VSP protocol version 2 messages: + */ +struct nvsp2_vsc_capability { + union { + uint64_t data; + struct { + uint64_t vmq:1; + uint64_t chimney:1; + uint64_t sriov:1; + uint64_t ieee8021q:1; + uint64_t correlation_id:1; + uint64_t teaming:1; + }; + }; +} QEMU_PACKED; + +struct nvsp2_send_ndis_config { + uint32_t mtu; + uint32_t reserved; + struct nvsp2_vsc_capability capability; +} QEMU_PACKED; + +/* Allocate receive buffer */ +struct nvsp2_alloc_rxbuf { + /* Allocation ID to match the allocation request and response */ + uint32_t alloc_id; + + /* Length of the VM shared memory receive buffer that needs to + * be allocated + */ + uint32_t len; +} QEMU_PACKED; + +/* Allocate receive buffer complete */ +struct nvsp2_alloc_rxbuf_comp { + /* The NDIS_STATUS code for buffer allocation */ + uint32_t status; + + uint32_t alloc_id; + + /* GPADL handle for the allocated receive buffer */ + uint32_t gpadl_handle; + + /* Receive buffer ID */ + uint64_t recv_buf_id; +} QEMU_PACKED; + +struct nvsp2_free_rxbuf { + uint64_t recv_buf_id; +} QEMU_PACKED; + +struct nvsp4_send_vf_association { + /* 1: allocated, serial number is valid. 0: not allocated */ + uint32_t allocated; + + /* Serial number of the VF to team with */ + uint32_t serial; +} QEMU_PACKED; + +enum nvsp_vm_datapath { + NVSP_DATAPATH_SYNTHETIC = 0, + NVSP_DATAPATH_VF, + NVSP_DATAPATH_MAX +}; + +struct nvsp4_sw_datapath { + uint32_t active_datapath; /* active data path in VM */ +} QEMU_PACKED; + +enum nvsp_subchannel_operation { + NVSP_SUBCHANNEL_NONE = 0, + NVSP_SUBCHANNEL_ALLOCATE, + NVSP_SUBCHANNEL_MAX +}; + +struct nvsp5_subchannel_request { + uint32_t op; + uint32_t num_subchannels; +} QEMU_PACKED; + +struct nvsp5_subchannel_complete { + uint32_t status; + uint32_t num_subchannels; /* Actual number of subchannels allocated */ +} QEMU_PACKED; + +struct nvsp5_send_indirect_table { + /* The number of entries in the send indirection table */ + uint32_t count; + + /* The offset of the send indirection table from top of this struct. + * The send indirection table tells which channel to put the send + * traffic on. Each entry is a channel number. + */ + uint32_t offset; +} QEMU_PACKED; + +union nvsp_all_messages { + struct nvsp_msg_init init; + struct nvsp_msg_init_complete init_complete; + + struct nvsp1_msg_ndis_ver send_ndis_ver; + struct nvsp1_msg_rcvbuf send_recv_buf; + struct nvsp1_msg_rcvbuf_complete send_recv_buf_complete; + struct nvsp1_msg_revoke_rcvbuf revoke_recv_buf; + struct nvsp1_msg_sndbuf send_send_buf; + struct nvsp1_msg_sndbuf_complete send_send_buf_complete; + struct nvsp1_msg_revoke_sndbuf revoke_send_buf; + struct nvsp1_msg_rndis_pkt send_rndis_pkt; + struct nvsp1_msg_rndis_pkt_complete send_rndis_pkt_complete; + + struct nvsp2_send_ndis_config send_ndis_config; + struct nvsp2_alloc_rxbuf alloc_rxbuf; + struct nvsp2_alloc_rxbuf_comp alloc_rxbuf_comp; + struct nvsp2_free_rxbuf free_rxbuf; + + struct nvsp4_send_vf_association vf_assoc; + struct nvsp4_sw_datapath active_dp; + + struct nvsp5_subchannel_request subchn_req; + struct nvsp5_subchannel_complete subchn_comp; + struct nvsp5_send_indirect_table send_table; +} QEMU_PACKED; + +/* ALL Messages */ +struct nvsp_msg { + struct nvsp_msg_header hdr; + union nvsp_all_messages msg; +} QEMU_PACKED; + + +#define NETVSC_MTU 65535 +#define NETVSC_MTU_MIN ETH_MIN_MTU + +#define NETVSC_RECEIVE_BUFFER_SIZE (1024*1024*16) /* 16MB */ +#define NETVSC_RECEIVE_BUFFER_SIZE_LEGACY (1024*1024*15) /* 15MB */ +#define NETVSC_SEND_BUFFER_SIZE (1024 * 1024 * 15) /* 15MB */ +#define NETVSC_INVALID_INDEX -1 + + +#define NETVSC_RECEIVE_BUFFER_ID 0xcafe +#define NETVSC_SEND_BUFFER_ID 0 + +#define NETVSC_PACKET_SIZE 4096 + +#define VRSS_SEND_TAB_SIZE 16 /* must be power of 2 */ +#define VRSS_CHANNEL_MAX 64 +#define VRSS_CHANNEL_DEFAULT 8 + +#define RNDIS_MAX_PKT_DEFAULT 8 +#define RNDIS_PKT_ALIGN_DEFAULT 8 + +/* Netvsc Receive Slots Max */ +#define NETVSC_RECVSLOT_MAX (NETVSC_RECEIVE_BUFFER_SIZE / ETH_DATA_LEN + 1) + +/* NdisInitialize message */ +struct rndis_initialize_request { + uint32_t req_id; + uint32_t major_ver; + uint32_t minor_ver; + uint32_t max_xfer_size; +}; + +/* Response to NdisInitialize */ +struct rndis_initialize_complete { + uint32_t req_id; + uint32_t status; + uint32_t major_ver; + uint32_t minor_ver; + uint32_t dev_flags; + uint32_t medium; + uint32_t max_pkt_per_msg; + uint32_t max_xfer_size; + uint32_t pkt_alignment_factor; + uint32_t af_list_offset; + uint32_t af_list_size; +}; + +/* Call manager devices only: Information about an address family */ +/* supported by the device is appended to the response to NdisInitialize. */ +struct rndis_co_address_family { + uint32_t address_family; + uint32_t major_ver; + uint32_t minor_ver; +}; + +/* NdisHalt message */ +struct rndis_halt_request { + uint32_t req_id; +}; + +/* NdisQueryRequest message */ +struct rndis_query_request { + uint32_t req_id; + uint32_t oid; + uint32_t info_buflen; + uint32_t info_buf_offset; + uint32_t dev_vc_handle; +}; + +/* Response to NdisQueryRequest */ +struct rndis_query_complete { + uint32_t req_id; + uint32_t status; + uint32_t info_buflen; + uint32_t info_buf_offset; +}; + +/* NdisSetRequest message */ +struct rndis_set_request { + uint32_t req_id; + uint32_t oid; + uint32_t info_buflen; + uint32_t info_buf_offset; + uint32_t dev_vc_handle; +}; + +/* Response to NdisSetRequest */ +struct rndis_set_complete { + uint32_t req_id; + uint32_t status; +}; + +/* NdisReset message */ +struct rndis_reset_request { + uint32_t reserved; +}; + +/* Response to NdisReset */ +struct rndis_reset_complete { + uint32_t status; + uint32_t addressing_reset; +}; + +/* NdisMIndicateStatus message */ +struct rndis_indicate_status { + uint32_t status; + uint32_t status_buflen; + uint32_t status_buf_offset; +}; + +/* Diagnostic information passed as the status buffer in */ +/* struct rndis_indicate_status messages signifying error conditions. */ +struct rndis_diagnostic_info { + uint32_t diag_status; + uint32_t error_offset; +}; + +/* NdisKeepAlive message */ +struct rndis_keepalive_request { + uint32_t req_id; +}; + +/* Response to NdisKeepAlive */ +struct rndis_keepalive_complete { + uint32_t req_id; + uint32_t status; +}; + +/* + * Data message. All Offset fields contain byte offsets from the beginning of + * struct rndis_packet. All Length fields are in bytes. VcHandle is set + * to 0 for connectionless data, otherwise it contains the VC handle. + */ +struct rndis_packet { + uint32_t data_offset; + uint32_t data_len; + uint32_t oob_data_offset; + uint32_t oob_data_len; + uint32_t num_oob_data_elements; + uint32_t per_pkt_info_offset; + uint32_t per_pkt_info_len; + uint32_t vc_handle; + uint32_t reserved; +}; + +/* Optional Out of Band data associated with a Data message. */ +struct rndis_oobd { + uint32_t size; + uint32_t type; + uint32_t class_info_offset; +}; + +/* Packet extension field contents associated with a Data message. */ +struct rndis_per_packet_info { + uint32_t size; + uint32_t type; + uint32_t ppi_offset; +}; + +enum ndis_per_pkt_info_type { + TCPIP_CHKSUM_PKTINFO, + IPSEC_PKTINFO, + TCP_LARGESEND_PKTINFO, + CLASSIFICATION_HANDLE_PKTINFO, + NDIS_RESERVED, + SG_LIST_PKTINFO, + IEEE_8021Q_INFO, + ORIGINAL_PKTINFO, + PACKET_CANCEL_ID, + NBL_HASH_VALUE = PACKET_CANCEL_ID, + ORIGINAL_NET_BUFLIST, + CACHED_NET_BUFLIST, + SHORT_PKT_PADINFO, + MAX_PER_PKT_INFO +}; + +struct ndis_pkt_8021q_info { + union { + struct { + uint32_t pri:3; /* User Priority */ + uint32_t cfi:1; /* Canonical Format ID */ + uint32_t vlanid:12; /* VLAN ID */ + uint32_t reserved:16; + }; + uint32_t value; + }; +}; + +struct ndis_object_header { + uint8_t type; + uint8_t revision; + uint16_t size; +}; + +#define NDIS_OBJECT_TYPE_DEFAULT 0x80 +#define NDIS_OFFLOAD_PARAMETERS_REVISION_3 3 +#define NDIS_OFFLOAD_PARAMETERS_REVISION_2 2 +#define NDIS_OFFLOAD_PARAMETERS_REVISION_1 1 + +#define NDIS_OFFLOAD_PARAMETERS_NO_CHANGE 0 +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED 1 +#define NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED 2 +#define NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED 2 +#define NDIS_OFFLOAD_PARAMETERS_RSC_DISABLED 1 +#define NDIS_OFFLOAD_PARAMETERS_RSC_ENABLED 2 +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED 1 +#define NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED 2 +#define NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED 3 +#define NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED 4 + +#define NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE 1 +#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV4 0 +#define NDIS_TCP_LARGE_SEND_OFFLOAD_IPV6 1 + +#define VERSION_4_OFFLOAD_SIZE 22 +/* + * New offload OIDs for NDIS 6 + */ +#define OID_TCP_OFFLOAD_CURRENT_CONFIG 0xFC01020B /* query only */ +#define OID_TCP_OFFLOAD_PARAMETERS 0xFC01020C /* set only */ +#define OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020D/* query only */ +#define OID_TCP_CONNECTION_OFFLOAD_CURRENT_CONFIG 0xFC01020E /* query only */ +#define OID_TCP_CONNECTION_OFFLOAD_HARDWARE_CAPABILITIES 0xFC01020F /* query */ +#define OID_OFFLOAD_ENCAPSULATION 0x0101010A /* set/query */ + +/* + * OID_TCP_OFFLOAD_HARDWARE_CAPABILITIES + * ndis_type: NDIS_OBJTYPE_OFFLOAD + */ + +#define NDIS_OFFLOAD_ENCAP_NONE 0x0000 +#define NDIS_OFFLOAD_ENCAP_NULL 0x0001 +#define NDIS_OFFLOAD_ENCAP_8023 0x0002 +#define NDIS_OFFLOAD_ENCAP_8023PQ 0x0004 +#define NDIS_OFFLOAD_ENCAP_8023PQ_OOB 0x0008 +#define NDIS_OFFLOAD_ENCAP_RFC1483 0x0010 + +struct ndis_csum_offload { + uint32_t ip4_txenc; + uint32_t ip4_txcsum; +#define NDIS_TXCSUM_CAP_IP4OPT 0x001 +#define NDIS_TXCSUM_CAP_TCP4OPT 0x004 +#define NDIS_TXCSUM_CAP_TCP4 0x010 +#define NDIS_TXCSUM_CAP_UDP4 0x040 +#define NDIS_TXCSUM_CAP_IP4 0x100 + +#define NDIS_TXCSUM_ALL_TCP4 (NDIS_TXCSUM_CAP_TCP4 | NDIS_TXCSUM_CAP_TCP4OPT) + + uint32_t ip4_rxenc; + uint32_t ip4_rxcsum; +#define NDIS_RXCSUM_CAP_IP4OPT 0x001 +#define NDIS_RXCSUM_CAP_TCP4OPT 0x004 +#define NDIS_RXCSUM_CAP_TCP4 0x010 +#define NDIS_RXCSUM_CAP_UDP4 0x040 +#define NDIS_RXCSUM_CAP_IP4 0x100 + uint32_t ip6_txenc; + uint32_t ip6_txcsum; +#define NDIS_TXCSUM_CAP_IP6EXT 0x001 +#define NDIS_TXCSUM_CAP_TCP6OPT 0x004 +#define NDIS_TXCSUM_CAP_TCP6 0x010 +#define NDIS_TXCSUM_CAP_UDP6 0x040 + uint32_t ip6_rxenc; + uint32_t ip6_rxcsum; +#define NDIS_RXCSUM_CAP_IP6EXT 0x001 +#define NDIS_RXCSUM_CAP_TCP6OPT 0x004 +#define NDIS_RXCSUM_CAP_TCP6 0x010 +#define NDIS_RXCSUM_CAP_UDP6 0x040 + +#define NDIS_TXCSUM_ALL_TCP6 (NDIS_TXCSUM_CAP_TCP6 | \ + NDIS_TXCSUM_CAP_TCP6OPT | \ + NDIS_TXCSUM_CAP_IP6EXT) +}; + +struct ndis_lsov1_offload { + uint32_t encap; + uint32_t maxsize; + uint32_t minsegs; + uint32_t opts; +}; + +struct ndis_ipsecv1_offload { + uint32_t encap; + uint32_t ah_esp; + uint32_t xport_tun; + uint32_t ip4_opts; + uint32_t flags; + uint32_t ip4_ah; + uint32_t ip4_esp; +}; + +struct ndis_lsov2_offload { + uint32_t ip4_encap; + uint32_t ip4_maxsz; + uint32_t ip4_minsg; + uint32_t ip6_encap; + uint32_t ip6_maxsz; + uint32_t ip6_minsg; + uint32_t ip6_opts; +#define NDIS_LSOV2_CAP_IP6EXT 0x001 +#define NDIS_LSOV2_CAP_TCP6OPT 0x004 + +#define NDIS_LSOV2_CAP_IP6 (NDIS_LSOV2_CAP_IP6EXT | \ + NDIS_LSOV2_CAP_TCP6OPT) +}; + +struct ndis_ipsecv2_offload { + uint32_t encap; + uint16_t ip6; + uint16_t ip4opt; + uint16_t ip6ext; + uint16_t ah; + uint16_t esp; + uint16_t ah_esp; + uint16_t xport; + uint16_t tun; + uint16_t xport_tun; + uint16_t lso; + uint16_t extseq; + uint32_t udp_esp; + uint32_t auth; + uint32_t crypto; + uint32_t sa_caps; +}; + +struct ndis_rsc_offload { + uint16_t ip4; + uint16_t ip6; +}; + +struct ndis_encap_offload { + uint32_t flags; + uint32_t maxhdr; +}; + +struct ndis_offload { + struct ndis_object_header header; + struct ndis_csum_offload csum; + struct ndis_lsov1_offload lsov1; + struct ndis_ipsecv1_offload ipsecv1; + struct ndis_lsov2_offload lsov2; + uint32_t flags; + /* NDIS >= 6.1 */ + struct ndis_ipsecv2_offload ipsecv2; + /* NDIS >= 6.30 */ + struct ndis_rsc_offload rsc; + struct ndis_encap_offload encap_gre; +}; + +#define NDIS_OFFLOAD_SIZE sizeof(struct ndis_offload) +#define NDIS_OFFLOAD_SIZE_6_0 offsetof(struct ndis_offload, ipsecv2) +#define NDIS_OFFLOAD_SIZE_6_1 offsetof(struct ndis_offload, rsc) + +struct ndis_offload_params { + struct ndis_object_header header; + uint8_t ip_v4_csum; + uint8_t tcp_ip_v4_csum; + uint8_t udp_ip_v4_csum; + uint8_t tcp_ip_v6_csum; + uint8_t udp_ip_v6_csum; + uint8_t lso_v1; + uint8_t ip_sec_v1; + uint8_t lso_v2_ipv4; + uint8_t lso_v2_ipv6; + uint8_t tcp_connection_ip_v4; + uint8_t tcp_connection_ip_v6; + uint32_t flags; + uint8_t ip_sec_v2; + uint8_t ip_sec_v2_ip_v4; + struct { + uint8_t rsc_ip_v4; + uint8_t rsc_ip_v6; + }; + struct { + uint8_t encapsulated_packet_task_offload; + uint8_t encapsulation_types; + }; +}; + +struct ndis_tcp_ip_checksum_info { + union { + struct { + uint32_t is_ipv4:1; + uint32_t is_ipv6:1; + uint32_t tcp_checksum:1; + uint32_t udp_checksum:1; + uint32_t ip_header_checksum:1; + uint32_t reserved:11; + uint32_t tcp_header_offset:10; + } transmit; + struct { + uint32_t tcp_checksum_failed:1; + uint32_t udp_checksum_failed:1; + uint32_t ip_checksum_failed:1; + uint32_t tcp_checksum_succeeded:1; + uint32_t udp_checksum_succeeded:1; + uint32_t ip_checksum_succeeded:1; + uint32_t loopback:1; + uint32_t tcp_checksum_value_invalid:1; + uint32_t ip_checksum_value_invalid:1; + } receive; + uint32_t value; + }; +}; + +struct ndis_tcp_lso_info { + union { + struct { + uint32_t unused:30; + uint32_t type:1; + uint32_t reserved2:1; + } transmit; + struct { + uint32_t mss:20; + uint32_t tcp_header_offset:10; + uint32_t type:1; + uint32_t reserved2:1; + } lso_v1_transmit; + struct { + uint32_t tcp_payload:30; + uint32_t type:1; + uint32_t reserved2:1; + } lso_v1_transmit_complete; + struct { + uint32_t mss:20; + uint32_t tcp_header_offset:10; + uint32_t type:1; + uint32_t ip_version:1; + } lso_v2_transmit; + struct { + uint32_t reserved:30; + uint32_t type:1; + uint32_t reserved2:1; + } lso_v2_transmit_complete; + uint32_t value; + }; +}; + +#define NDIS_VLAN_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ + sizeof(struct ndis_pkt_8021q_info)) + +#define NDIS_CSUM_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ + sizeof(struct ndis_tcp_ip_checksum_info)) + +#define NDIS_LSO_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ + sizeof(struct ndis_tcp_lso_info)) + +#define NDIS_HASH_PPI_SIZE (sizeof(struct rndis_per_packet_info) + \ + sizeof(uint32_t)) + +/* Total size of all PPI data */ +#define NDIS_ALL_PPI_SIZE (NDIS_VLAN_PPI_SIZE + NDIS_CSUM_PPI_SIZE + \ + NDIS_LSO_PPI_SIZE + NDIS_HASH_PPI_SIZE) + +/* Format of Information buffer passed in a SetRequest for the OID */ +/* OID_GEN_RNDIS_CONFIG_PARAMETER. */ +struct rndis_config_parameter_info { + uint32_t parameter_name_offset; + uint32_t parameter_name_length; + uint32_t parameter_type; + uint32_t parameter_value_offset; + uint32_t parameter_value_length; +}; + +/* Values for ParameterType in struct rndis_config_parameter_info */ +#define RNDIS_CONFIG_PARAM_TYPE_INTEGER 0 +#define RNDIS_CONFIG_PARAM_TYPE_STRING 2 + +/* CONDIS Miniport messages for connection oriented devices */ +/* that do not implement a call manager. */ + +/* CoNdisMiniportCreateVc message */ +struct rcondis_mp_create_vc { + uint32_t req_id; + uint32_t ndis_vc_handle; +}; + +/* Response to CoNdisMiniportCreateVc */ +struct rcondis_mp_create_vc_complete { + uint32_t req_id; + uint32_t dev_vc_handle; + uint32_t status; +}; + +/* CoNdisMiniportDeleteVc message */ +struct rcondis_mp_delete_vc { + uint32_t req_id; + uint32_t dev_vc_handle; +}; + +/* Response to CoNdisMiniportDeleteVc */ +struct rcondis_mp_delete_vc_complete { + uint32_t req_id; + uint32_t status; +}; + +/* CoNdisMiniportQueryRequest message */ +struct rcondis_mp_query_request { + uint32_t req_id; + uint32_t request_type; + uint32_t oid; + uint32_t dev_vc_handle; + uint32_t info_buflen; + uint32_t info_buf_offset; +}; + +/* CoNdisMiniportSetRequest message */ +struct rcondis_mp_set_request { + uint32_t req_id; + uint32_t request_type; + uint32_t oid; + uint32_t dev_vc_handle; + uint32_t info_buflen; + uint32_t info_buf_offset; +}; + +/* CoNdisIndicateStatus message */ +struct rcondis_indicate_status { + uint32_t ndis_vc_handle; + uint32_t status; + uint32_t status_buflen; + uint32_t status_buf_offset; +}; + +/* CONDIS Call/VC parameters */ +struct rcondis_specific_parameters { + uint32_t parameter_type; + uint32_t parameter_length; + uint32_t parameter_lffset; +}; + +struct rcondis_media_parameters { + uint32_t flags; + uint32_t reserved1; + uint32_t reserved2; + struct rcondis_specific_parameters media_specific; +}; + +struct rndis_flowspec { + uint32_t token_rate; + uint32_t token_bucket_size; + uint32_t peak_bandwidth; + uint32_t latency; + uint32_t delay_variation; + uint32_t service_type; + uint32_t max_sdu_size; + uint32_t minimum_policed_size; +}; + +struct rcondis_call_manager_parameters { + struct rndis_flowspec transmit; + struct rndis_flowspec receive; + struct rcondis_specific_parameters call_mgr_specific; +}; + +/* CoNdisMiniportActivateVc message */ +struct rcondis_mp_activate_vc_request { + uint32_t req_id; + uint32_t flags; + uint32_t dev_vc_handle; + uint32_t media_params_offset; + uint32_t media_params_length; + uint32_t call_mgr_params_offset; + uint32_t call_mgr_params_length; +}; + +/* Response to CoNdisMiniportActivateVc */ +struct rcondis_mp_activate_vc_complete { + uint32_t req_id; + uint32_t status; +}; + +/* CoNdisMiniportDeactivateVc message */ +struct rcondis_mp_deactivate_vc_request { + uint32_t req_id; + uint32_t flags; + uint32_t dev_vc_handle; +}; + +/* Response to CoNdisMiniportDeactivateVc */ +struct rcondis_mp_deactivate_vc_complete { + uint32_t req_id; + uint32_t status; +}; + + +/* union with all of the RNDIS messages */ +union rndis_message_container { + struct rndis_packet pkt; + struct rndis_initialize_request init_req; + struct rndis_halt_request halt_req; + struct rndis_query_request query_req; + struct rndis_set_request set_req; + struct rndis_reset_request reset_req; + struct rndis_keepalive_request keep_alive_req; + struct rndis_indicate_status indicate_status; + struct rndis_initialize_complete init_complete; + struct rndis_query_complete query_complete; + struct rndis_set_complete set_complete; + struct rndis_reset_complete reset_complete; + struct rndis_keepalive_complete keep_alive_complete; + struct rcondis_mp_create_vc co_miniport_create_vc; + struct rcondis_mp_delete_vc co_miniport_delete_vc; + struct rcondis_indicate_status co_indicate_status; + struct rcondis_mp_activate_vc_request co_miniport_activate_vc; + struct rcondis_mp_deactivate_vc_request co_miniport_deactivate_vc; + struct rcondis_mp_create_vc_complete co_miniport_create_vc_complete; + struct rcondis_mp_delete_vc_complete co_miniport_delete_vc_complete; + struct rcondis_mp_activate_vc_complete co_miniport_activate_vc_complete; + struct rcondis_mp_deactivate_vc_complete + co_miniport_deactivate_vc_complete; +}; + +/* Remote NDIS message format */ +struct rndis_msg_hdr { + uint32_t msg_type; + uint32_t msg_len; +}; + +#define NDIS_PACKET_TYPE_DIRECTED 0x00000001 +#define NDIS_PACKET_TYPE_MULTICAST 0x00000002 +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 +#define NDIS_PACKET_TYPE_BROADCAST 0x00000008 +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 +#define NDIS_PACKET_TYPE_SMT 0x00000040 +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 +#define NDIS_PACKET_TYPE_GROUP 0x00000100 +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00000200 +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x00000400 +#define NDIS_PACKET_TYPE_MAC_FRAME 0x00000800 + +#define TRANSPORT_INFO_NOT_IP 0 +#define TRANSPORT_INFO_IPV4_TCP 0x01 +#define TRANSPORT_INFO_IPV4_UDP 0x02 +#define TRANSPORT_INFO_IPV6_TCP 0x10 +#define TRANSPORT_INFO_IPV6_UDP 0x20 + +#endif -- 2.14.3