2017-11-07 11:54:56 +03:00
/*
* Copyright ( C ) 2017 , Microsoft Corporation .
*
* Author ( s ) : Long Li < longli @ microsoft . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See
* the GNU General Public License for more details .
*/
# ifndef _SMBDIRECT_H
# define _SMBDIRECT_H
2017-11-05 04:17:24 +03:00
# ifdef CONFIG_CIFS_SMB_DIRECT
# define cifs_rdma_enabled(server) ((server)->rdma)
# include "cifsglob.h"
# include <rdma/ib_verbs.h>
# include <rdma/rdma_cm.h>
# include <linux/mempool.h>
enum keep_alive_status {
KEEP_ALIVE_NONE ,
KEEP_ALIVE_PENDING ,
KEEP_ALIVE_SENT ,
} ;
enum smbd_connection_status {
SMBD_CREATED ,
SMBD_CONNECTING ,
SMBD_CONNECTED ,
SMBD_NEGOTIATE_FAILED ,
SMBD_DISCONNECTING ,
SMBD_DISCONNECTED ,
SMBD_DESTROYED
} ;
/*
* The context for the SMBDirect transport
* Everything related to the transport is here . It has several logical parts
* 1. RDMA related structures
* 2. SMBDirect connection parameters
* 3. Memory registrations
* 4. Receive and reassembly queues for data receive path
* 5. mempools for allocating packets
*/
struct smbd_connection {
enum smbd_connection_status transport_status ;
/* RDMA related */
struct rdma_cm_id * id ;
struct ib_qp_init_attr qp_attr ;
struct ib_pd * pd ;
struct ib_cq * send_cq , * recv_cq ;
struct ib_device_attr dev_attr ;
int ri_rc ;
struct completion ri_done ;
wait_queue_head_t conn_wait ;
wait_queue_head_t wait_destroy ;
struct completion negotiate_completion ;
bool negotiate_done ;
struct work_struct destroy_work ;
struct work_struct disconnect_work ;
struct work_struct recv_done_work ;
struct work_struct post_send_credits_work ;
spinlock_t lock_new_credits_offered ;
int new_credits_offered ;
/* Connection parameters defined in [MS-SMBD] 3.1.1.1 */
int receive_credit_max ;
int send_credit_target ;
int max_send_size ;
int max_fragmented_recv_size ;
int max_fragmented_send_size ;
int max_receive_size ;
int keep_alive_interval ;
int max_readwrite_size ;
enum keep_alive_status keep_alive_requested ;
int protocol ;
atomic_t send_credits ;
atomic_t receive_credits ;
int receive_credit_target ;
int fragment_reassembly_remaining ;
/* Activity accoutning */
atomic_t send_pending ;
wait_queue_head_t wait_send_pending ;
atomic_t send_payload_pending ;
wait_queue_head_t wait_send_payload_pending ;
/* Receive queue */
struct list_head receive_queue ;
int count_receive_queue ;
spinlock_t receive_queue_lock ;
struct list_head empty_packet_queue ;
int count_empty_packet_queue ;
spinlock_t empty_packet_queue_lock ;
wait_queue_head_t wait_receive_queues ;
/* Reassembly queue */
struct list_head reassembly_queue ;
spinlock_t reassembly_queue_lock ;
wait_queue_head_t wait_reassembly_queue ;
/* total data length of reassembly queue */
int reassembly_data_length ;
int reassembly_queue_length ;
/* the offset to first buffer in reassembly queue */
int first_entry_offset ;
bool send_immediate ;
wait_queue_head_t wait_send_queue ;
/*
* Indicate if we have received a full packet on the connection
* This is used to identify the first SMBD packet of a assembled
* payload ( SMB packet ) in reassembly queue so we can return a
* RFC1002 length to upper layer to indicate the length of the SMB
* packet received
*/
bool full_packet_received ;
struct workqueue_struct * workqueue ;
struct delayed_work idle_timer_work ;
struct delayed_work send_immediate_work ;
/* Memory pool for preallocating buffers */
/* request pool for RDMA send */
struct kmem_cache * request_cache ;
mempool_t * request_mempool ;
/* response pool for RDMA receive */
struct kmem_cache * response_cache ;
mempool_t * response_mempool ;
/* for debug purposes */
unsigned int count_get_receive_buffer ;
unsigned int count_put_receive_buffer ;
unsigned int count_reassembly_queue ;
unsigned int count_enqueue_reassembly_queue ;
unsigned int count_dequeue_reassembly_queue ;
unsigned int count_send_empty ;
} ;
enum smbd_message_type {
SMBD_NEGOTIATE_RESP ,
SMBD_TRANSFER_DATA ,
} ;
# define SMB_DIRECT_RESPONSE_REQUESTED 0x0001
/* SMBD negotiation request packet [MS-SMBD] 2.2.1 */
struct smbd_negotiate_req {
__le16 min_version ;
__le16 max_version ;
__le16 reserved ;
__le16 credits_requested ;
__le32 preferred_send_size ;
__le32 max_receive_size ;
__le32 max_fragmented_size ;
} __packed ;
/* SMBD negotiation response packet [MS-SMBD] 2.2.2 */
struct smbd_negotiate_resp {
__le16 min_version ;
__le16 max_version ;
__le16 negotiated_version ;
__le16 reserved ;
__le16 credits_requested ;
__le16 credits_granted ;
__le32 status ;
__le32 max_readwrite_size ;
__le32 preferred_send_size ;
__le32 max_receive_size ;
__le32 max_fragmented_size ;
} __packed ;
/* SMBD data transfer packet with payload [MS-SMBD] 2.2.3 */
struct smbd_data_transfer {
__le16 credits_requested ;
__le16 credits_granted ;
__le16 flags ;
__le16 reserved ;
__le32 remaining_data_length ;
__le32 data_offset ;
__le32 data_length ;
__le32 padding ;
__u8 buffer [ ] ;
} __packed ;
/* The packet fields for a registered RDMA buffer */
struct smbd_buffer_descriptor_v1 {
__le64 offset ;
__le32 token ;
__le32 length ;
} __packed ;
2017-11-07 11:54:56 +03:00
/* Default maximum number of SGEs in a RDMA send/recv */
# define SMBDIRECT_MAX_SGE 16
2017-11-05 04:17:24 +03:00
/* The context for a SMBD request */
struct smbd_request {
struct smbd_connection * info ;
struct ib_cqe cqe ;
/* true if this request carries upper layer payload */
bool has_payload ;
/* the SGE entries for this packet */
struct ib_sge sge [ SMBDIRECT_MAX_SGE ] ;
int num_sge ;
/* SMBD packet header follows this structure */
u8 packet [ ] ;
} ;
/* The context for a SMBD response */
struct smbd_response {
struct smbd_connection * info ;
struct ib_cqe cqe ;
struct ib_sge sge ;
enum smbd_message_type type ;
/* Link to receive queue or reassembly queue */
struct list_head list ;
/* Indicate if this is the 1st packet of a payload */
bool first_segment ;
/* SMBD packet header and payload follows this structure */
u8 packet [ ] ;
} ;
2017-11-18 04:26:52 +03:00
/* Create a SMBDirect session */
struct smbd_connection * smbd_get_connection (
struct TCP_Server_Info * server , struct sockaddr * dstaddr ) ;
2017-11-23 03:38:35 +03:00
/* Reconnect SMBDirect session */
int smbd_reconnect ( struct TCP_Server_Info * server ) ;
2017-11-05 04:17:24 +03:00
# else
# define cifs_rdma_enabled(server) 0
struct smbd_connection { } ;
2017-11-18 04:26:52 +03:00
static inline void * smbd_get_connection (
struct TCP_Server_Info * server , struct sockaddr * dstaddr ) { return NULL ; }
2017-11-23 03:38:35 +03:00
static inline int smbd_reconnect ( struct TCP_Server_Info * server ) { return - 1 ; }
2017-11-05 04:17:24 +03:00
# endif
2017-11-07 11:54:56 +03:00
# endif