Merge tag 'mmc-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[cascardo/linux.git] / net / rxrpc / ar-internal.h
index ff83fb1..f60e355 100644 (file)
@@ -35,10 +35,22 @@ struct rxrpc_crypt {
 #define rxrpc_queue_delayed_work(WS,D) \
        queue_delayed_work(rxrpc_workqueue, (WS), (D))
 
-#define rxrpc_queue_call(CALL) rxrpc_queue_work(&(CALL)->processor)
-
 struct rxrpc_connection;
 
+/*
+ * Mark applied to socket buffers.
+ */
+enum rxrpc_skb_mark {
+       RXRPC_SKB_MARK_DATA,            /* data message */
+       RXRPC_SKB_MARK_FINAL_ACK,       /* final ACK received message */
+       RXRPC_SKB_MARK_BUSY,            /* server busy message */
+       RXRPC_SKB_MARK_REMOTE_ABORT,    /* remote abort message */
+       RXRPC_SKB_MARK_LOCAL_ABORT,     /* local abort message */
+       RXRPC_SKB_MARK_NET_ERROR,       /* network error message */
+       RXRPC_SKB_MARK_LOCAL_ERROR,     /* local error message */
+       RXRPC_SKB_MARK_NEW_CALL,        /* local error message */
+};
+
 /*
  * sk_state for RxRPC sockets
  */
@@ -51,20 +63,45 @@ enum {
        RXRPC_CLOSE,                    /* socket is being closed */
 };
 
+/*
+ * Service backlog preallocation.
+ *
+ * This contains circular buffers of preallocated peers, connections and calls
+ * for incoming service calls and their head and tail pointers.  This allows
+ * calls to be set up in the data_ready handler, thereby avoiding the need to
+ * shuffle packets around so much.
+ */
+struct rxrpc_backlog {
+       unsigned short          peer_backlog_head;
+       unsigned short          peer_backlog_tail;
+       unsigned short          conn_backlog_head;
+       unsigned short          conn_backlog_tail;
+       unsigned short          call_backlog_head;
+       unsigned short          call_backlog_tail;
+#define RXRPC_BACKLOG_MAX      32
+       struct rxrpc_peer       *peer_backlog[RXRPC_BACKLOG_MAX];
+       struct rxrpc_connection *conn_backlog[RXRPC_BACKLOG_MAX];
+       struct rxrpc_call       *call_backlog[RXRPC_BACKLOG_MAX];
+};
+
 /*
  * RxRPC socket definition
  */
 struct rxrpc_sock {
        /* WARNING: sk has to be the first member */
        struct sock             sk;
-       rxrpc_interceptor_t     interceptor;    /* kernel service Rx interceptor function */
+       rxrpc_notify_new_call_t notify_new_call; /* Func to notify of new call */
+       rxrpc_discard_new_call_t discard_new_call; /* Func to discard a new call */
        struct rxrpc_local      *local;         /* local endpoint */
-       struct list_head        listen_link;    /* link in the local endpoint's listen list */
-       struct list_head        secureq;        /* calls awaiting connection security clearance */
-       struct list_head        acceptq;        /* calls awaiting acceptance */
+       struct rxrpc_backlog    *backlog;       /* Preallocation for services */
+       spinlock_t              incoming_lock;  /* Incoming call vs service shutdown lock */
+       struct list_head        sock_calls;     /* List of calls owned by this socket */
+       struct list_head        to_be_accepted; /* calls awaiting acceptance */
+       struct list_head        recvmsg_q;      /* Calls awaiting recvmsg's attention  */
+       rwlock_t                recvmsg_lock;   /* Lock for recvmsg_q */
        struct key              *key;           /* security for this socket */
        struct key              *securities;    /* list of server security descriptors */
-       struct rb_root          calls;          /* outstanding calls on this socket */
+       struct rb_root          calls;          /* User ID -> call mapping */
        unsigned long           flags;
 #define RXRPC_SOCK_CONNECTED           0       /* connect_srx is set */
        rwlock_t                call_lock;      /* lock for calls */
@@ -103,13 +140,11 @@ struct rxrpc_host_header {
  * - max 48 bytes (struct sk_buff::cb)
  */
 struct rxrpc_skb_priv {
-       struct rxrpc_call       *call;          /* call with which associated */
-       unsigned long           resend_at;      /* time in jiffies at which to resend */
        union {
-               unsigned int    offset;         /* offset into buffer of next read */
+               u8              nr_jumbo;       /* Number of jumbo subpackets */
+       };
+       union {
                int             remain;         /* amount of space remaining for next write */
-               u32             error;          /* network error code */
-               bool            need_resend;    /* T if needs resending */
        };
 
        struct rxrpc_host_header hdr;           /* RxRPC packet header from this packet */
@@ -117,13 +152,6 @@ struct rxrpc_skb_priv {
 
 #define rxrpc_skb(__skb) ((struct rxrpc_skb_priv *) &(__skb)->cb)
 
-enum rxrpc_command {
-       RXRPC_CMD_SEND_DATA,            /* send data message */
-       RXRPC_CMD_SEND_ABORT,           /* request abort generation */
-       RXRPC_CMD_ACCEPT,               /* [server] accept incoming call */
-       RXRPC_CMD_REJECT_BUSY,          /* [server] reject a call as busy */
-};
-
 /*
  * RxRPC security module interface
  */
@@ -150,7 +178,12 @@ struct rxrpc_security {
                             void *);
 
        /* verify the security on a received packet */
-       int (*verify_packet)(struct rxrpc_call *, struct sk_buff *, u32 *);
+       int (*verify_packet)(struct rxrpc_call *, struct sk_buff *,
+                            unsigned int, unsigned int, rxrpc_seq_t, u16);
+
+       /* Locate the data in a received packet that has been verified. */
+       void (*locate_data)(struct rxrpc_call *, struct sk_buff *,
+                           unsigned int *, unsigned int *);
 
        /* issue a challenge */
        int (*issue_challenge)(struct rxrpc_connection *);
@@ -180,9 +213,8 @@ struct rxrpc_local {
        struct list_head        link;
        struct socket           *socket;        /* my UDP socket */
        struct work_struct      processor;
-       struct list_head        services;       /* services listening on this endpoint */
+       struct rxrpc_sock __rcu *service;       /* Service(s) listening on this endpoint */
        struct rw_semaphore     defrag_sem;     /* control re-enablement of IP DF bit */
-       struct sk_buff_head     accept_queue;   /* incoming calls awaiting acceptance */
        struct sk_buff_head     reject_queue;   /* packets awaiting rejection */
        struct sk_buff_head     event_queue;    /* endpoint event packets awaiting processing */
        struct rb_root          client_conns;   /* Client connections by socket params */
@@ -220,10 +252,12 @@ struct rxrpc_peer {
 
        /* calculated RTT cache */
 #define RXRPC_RTT_CACHE_SIZE 32
-       suseconds_t             rtt;            /* current RTT estimate (in uS) */
-       unsigned int            rtt_point;      /* next entry at which to insert */
-       unsigned int            rtt_usage;      /* amount of cache actually used */
-       suseconds_t             rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* calculated RTT cache */
+       ktime_t                 rtt_last_req;   /* Time of last RTT request */
+       u64                     rtt;            /* Current RTT estimate (in nS) */
+       u64                     rtt_sum;        /* Sum of cache contents */
+       u64                     rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* Determined RTT cache */
+       u8                      rtt_cursor;     /* next entry at which to insert */
+       u8                      rtt_usage;      /* amount of cache actually used */
 };
 
 /*
@@ -255,6 +289,9 @@ enum rxrpc_conn_flag {
        RXRPC_CONN_HAS_IDR,             /* Has a client conn ID assigned */
        RXRPC_CONN_IN_SERVICE_CONNS,    /* Conn is in peer->service_conns */
        RXRPC_CONN_IN_CLIENT_CONNS,     /* Conn is in local->client_conns */
+       RXRPC_CONN_EXPOSED,             /* Conn has extra ref for exposure */
+       RXRPC_CONN_DONT_REUSE,          /* Don't reuse this connection */
+       RXRPC_CONN_COUNTED,             /* Counted by rxrpc_nr_client_conns */
 };
 
 /*
@@ -264,18 +301,30 @@ enum rxrpc_conn_event {
        RXRPC_CONN_EV_CHALLENGE,        /* Send challenge packet */
 };
 
+/*
+ * The connection cache state.
+ */
+enum rxrpc_conn_cache_state {
+       RXRPC_CONN_CLIENT_INACTIVE,     /* Conn is not yet listed */
+       RXRPC_CONN_CLIENT_WAITING,      /* Conn is on wait list, waiting for capacity */
+       RXRPC_CONN_CLIENT_ACTIVE,       /* Conn is on active list, doing calls */
+       RXRPC_CONN_CLIENT_CULLED,       /* Conn is culled and delisted, doing calls */
+       RXRPC_CONN_CLIENT_IDLE,         /* Conn is on idle list, doing mostly nothing */
+       RXRPC_CONN__NR_CACHE_STATES
+};
+
 /*
  * The connection protocol state.
  */
 enum rxrpc_conn_proto_state {
        RXRPC_CONN_UNUSED,              /* Connection not yet attempted */
        RXRPC_CONN_CLIENT,              /* Client connection */
+       RXRPC_CONN_SERVICE_PREALLOC,    /* Service connection preallocation */
        RXRPC_CONN_SERVICE_UNSECURED,   /* Service unsecured connection */
        RXRPC_CONN_SERVICE_CHALLENGING, /* Service challenging for security */
        RXRPC_CONN_SERVICE,             /* Service secured connection */
        RXRPC_CONN_REMOTELY_ABORTED,    /* Conn aborted by peer */
        RXRPC_CONN_LOCALLY_ABORTED,     /* Conn aborted locally */
-       RXRPC_CONN_NETWORK_ERROR,       /* Conn terminated by network error */
        RXRPC_CONN__NR_STATES
 };
 
@@ -288,23 +337,33 @@ struct rxrpc_connection {
        struct rxrpc_conn_proto proto;
        struct rxrpc_conn_parameters params;
 
-       spinlock_t              channel_lock;
+       atomic_t                usage;
+       struct rcu_head         rcu;
+       struct list_head        cache_link;
 
+       spinlock_t              channel_lock;
+       unsigned char           active_chans;   /* Mask of active channels */
+#define RXRPC_ACTIVE_CHANS_MASK        ((1 << RXRPC_MAXCALLS) - 1)
+       struct list_head        waiting_calls;  /* Calls waiting for channels */
        struct rxrpc_channel {
                struct rxrpc_call __rcu *call;          /* Active call */
                u32                     call_id;        /* ID of current call */
                u32                     call_counter;   /* Call ID counter */
                u32                     last_call;      /* ID of last call */
-               u32                     last_result;    /* Result of last call (0/abort) */
+               u8                      last_type;      /* Type of last packet */
+               u16                     last_service_id;
+               union {
+                       u32             last_seq;
+                       u32             last_abort;
+               };
        } channels[RXRPC_MAXCALLS];
-       wait_queue_head_t       channel_wq;     /* queue to wait for channel to become available */
 
-       struct rcu_head         rcu;
        struct work_struct      processor;      /* connection event processor */
        union {
                struct rb_node  client_node;    /* Node in local->client_conns */
                struct rb_node  service_node;   /* Node in peer->service_conns */
        };
+       struct list_head        proc_link;      /* link in procfs list */
        struct list_head        link;           /* link in master connection list */
        struct sk_buff_head     rx_queue;       /* received conn-level packets */
        const struct rxrpc_security *security;  /* applied security module */
@@ -313,21 +372,18 @@ struct rxrpc_connection {
        struct rxrpc_crypt      csum_iv;        /* packet checksum base */
        unsigned long           flags;
        unsigned long           events;
-       unsigned long           put_time;       /* Time at which last put */
+       unsigned long           idle_timestamp; /* Time at which last became idle */
        spinlock_t              state_lock;     /* state-change lock */
-       atomic_t                usage;
-       enum rxrpc_conn_proto_state state : 8;  /* current state of connection */
+       enum rxrpc_conn_cache_state cache_state;
+       enum rxrpc_conn_proto_state state;      /* current state of connection */
        u32                     local_abort;    /* local abort code */
        u32                     remote_abort;   /* remote abort code */
-       int                     error;          /* local error incurred */
        int                     debug_id;       /* debug ID for printks */
        atomic_t                serial;         /* packet serial number counter */
-       atomic_t                hi_serial;      /* highest serial number received */
-       atomic_t                avail_chans;    /* number of channels available */
+       unsigned int            hi_serial;      /* highest serial number received */
+       u32                     security_nonce; /* response re-use preventer */
        u8                      size_align;     /* data size alignment (for security) */
-       u8                      header_size;    /* rxrpc + security header size */
        u8                      security_size;  /* security header size */
-       u32                     security_nonce; /* response re-use preventer */
        u8                      security_ix;    /* security type */
        u8                      out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
 };
@@ -337,37 +393,25 @@ struct rxrpc_connection {
  */
 enum rxrpc_call_flag {
        RXRPC_CALL_RELEASED,            /* call has been released - no more message to userspace */
-       RXRPC_CALL_TERMINAL_MSG,        /* call has given the socket its final message */
-       RXRPC_CALL_RCVD_LAST,           /* all packets received */
-       RXRPC_CALL_RUN_RTIMER,          /* Tx resend timer started */
-       RXRPC_CALL_TX_SOFT_ACK,         /* sent some soft ACKs */
-       RXRPC_CALL_PROC_BUSY,           /* the processor is busy */
-       RXRPC_CALL_INIT_ACCEPT,         /* acceptance was initiated */
        RXRPC_CALL_HAS_USERID,          /* has a user ID attached */
-       RXRPC_CALL_EXPECT_OOS,          /* expect out of sequence packets */
+       RXRPC_CALL_IS_SERVICE,          /* Call is service call */
+       RXRPC_CALL_EXPOSED,             /* The call was exposed to the world */
+       RXRPC_CALL_RX_LAST,             /* Received the last packet (at rxtx_top) */
+       RXRPC_CALL_TX_LAST,             /* Last packet in Tx buffer (at rxtx_top) */
+       RXRPC_CALL_SEND_PING,           /* A ping will need to be sent */
+       RXRPC_CALL_PINGING,             /* Ping in process */
+       RXRPC_CALL_RETRANS_TIMEOUT,     /* Retransmission due to timeout occurred */
 };
 
 /*
  * Events that can be raised on a call.
  */
 enum rxrpc_call_event {
-       RXRPC_CALL_EV_RCVD_ACKALL,      /* ACKALL or reply received */
-       RXRPC_CALL_EV_RCVD_BUSY,        /* busy packet received */
-       RXRPC_CALL_EV_RCVD_ABORT,       /* abort packet received */
-       RXRPC_CALL_EV_RCVD_ERROR,       /* network error received */
-       RXRPC_CALL_EV_ACK_FINAL,        /* need to generate final ACK (and release call) */
        RXRPC_CALL_EV_ACK,              /* need to generate ACK */
-       RXRPC_CALL_EV_REJECT_BUSY,      /* need to generate busy message */
        RXRPC_CALL_EV_ABORT,            /* need to generate abort */
-       RXRPC_CALL_EV_CONN_ABORT,       /* local connection abort generated */
-       RXRPC_CALL_EV_RESEND_TIMER,     /* Tx resend timer expired */
+       RXRPC_CALL_EV_TIMER,            /* Timer expired */
        RXRPC_CALL_EV_RESEND,           /* Tx resend required */
-       RXRPC_CALL_EV_DRAIN_RX_OOS,     /* drain the Rx out of sequence queue */
-       RXRPC_CALL_EV_LIFE_TIMER,       /* call's lifetimer ran out */
-       RXRPC_CALL_EV_ACCEPTED,         /* incoming call accepted by userspace app */
-       RXRPC_CALL_EV_SECURED,          /* incoming call's connection is now secure */
-       RXRPC_CALL_EV_POST_ACCEPT,      /* need to post an "accept?" message to the app */
-       RXRPC_CALL_EV_RELEASE,          /* need to release the call's resources */
+       RXRPC_CALL_EV_PING,             /* Ping send required */
 };
 
 /*
@@ -379,20 +423,38 @@ enum rxrpc_call_state {
        RXRPC_CALL_CLIENT_SEND_REQUEST, /* - client sending request phase */
        RXRPC_CALL_CLIENT_AWAIT_REPLY,  /* - client awaiting reply */
        RXRPC_CALL_CLIENT_RECV_REPLY,   /* - client receiving reply phase */
-       RXRPC_CALL_CLIENT_FINAL_ACK,    /* - client sending final ACK phase */
+       RXRPC_CALL_SERVER_PREALLOC,     /* - service preallocation */
        RXRPC_CALL_SERVER_SECURING,     /* - server securing request connection */
        RXRPC_CALL_SERVER_ACCEPTING,    /* - server accepting request */
        RXRPC_CALL_SERVER_RECV_REQUEST, /* - server receiving request */
        RXRPC_CALL_SERVER_ACK_REQUEST,  /* - server pending ACK of request */
        RXRPC_CALL_SERVER_SEND_REPLY,   /* - server sending reply */
        RXRPC_CALL_SERVER_AWAIT_ACK,    /* - server awaiting final ACK */
-       RXRPC_CALL_COMPLETE,            /* - call completed */
-       RXRPC_CALL_SERVER_BUSY,         /* - call rejected by busy server */
+       RXRPC_CALL_COMPLETE,            /* - call complete */
+       NR__RXRPC_CALL_STATES
+};
+
+/*
+ * Call completion condition (state == RXRPC_CALL_COMPLETE).
+ */
+enum rxrpc_call_completion {
+       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
        RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
        RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
+       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
        RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
-       RXRPC_CALL_DEAD,                /* - call is dead */
-       NR__RXRPC_CALL_STATES
+       NR__RXRPC_CALL_COMPLETIONS
+};
+
+/*
+ * Call Tx congestion management modes.
+ */
+enum rxrpc_congest_mode {
+       RXRPC_CALL_SLOW_START,
+       RXRPC_CALL_CONGEST_AVOIDANCE,
+       RXRPC_CALL_PACKET_LOSS,
+       RXRPC_CALL_FAST_RETRANSMIT,
+       NR__RXRPC_CONGEST_MODES
 };
 
 /*
@@ -402,92 +464,335 @@ enum rxrpc_call_state {
 struct rxrpc_call {
        struct rcu_head         rcu;
        struct rxrpc_connection *conn;          /* connection carrying call */
-       struct rxrpc_sock       *socket;        /* socket responsible */
-       struct timer_list       lifetimer;      /* lifetime remaining on call */
-       struct timer_list       deadspan;       /* reap timer for re-ACK'ing, etc  */
-       struct timer_list       ack_timer;      /* ACK generation timer */
-       struct timer_list       resend_timer;   /* Tx resend timer */
-       struct work_struct      destroyer;      /* call destroyer */
-       struct work_struct      processor;      /* packet processor and ACK generator */
+       struct rxrpc_peer       *peer;          /* Peer record for remote address */
+       struct rxrpc_sock __rcu *socket;        /* socket responsible */
+       ktime_t                 ack_at;         /* When deferred ACK needs to happen */
+       ktime_t                 resend_at;      /* When next resend needs to happen */
+       ktime_t                 ping_at;        /* When next to send a ping */
+       ktime_t                 expire_at;      /* When the call times out */
+       struct timer_list       timer;          /* Combined event timer */
+       struct work_struct      processor;      /* Event processor */
+       rxrpc_notify_rx_t       notify_rx;      /* kernel service Rx notification function */
        struct list_head        link;           /* link in master call list */
+       struct list_head        chan_wait_link; /* Link in conn->waiting_calls */
        struct hlist_node       error_link;     /* link in error distribution list */
-       struct list_head        accept_link;    /* calls awaiting acceptance */
-       struct rb_node          sock_node;      /* node in socket call tree */
-       struct sk_buff_head     rx_queue;       /* received packets */
-       struct sk_buff_head     rx_oos_queue;   /* packets received out of sequence */
+       struct list_head        accept_link;    /* Link in rx->acceptq */
+       struct list_head        recvmsg_link;   /* Link in rx->recvmsg_q */
+       struct list_head        sock_link;      /* Link in rx->sock_calls */
+       struct rb_node          sock_node;      /* Node in rx->calls */
        struct sk_buff          *tx_pending;    /* Tx socket buffer being filled */
-       wait_queue_head_t       tx_waitq;       /* wait for Tx window space to become available */
+       wait_queue_head_t       waitq;          /* Wait queue for channel or Tx */
        __be32                  crypto_buf[2];  /* Temporary packet crypto buffer */
        unsigned long           user_call_ID;   /* user-defined call ID */
-       unsigned long           creation_jif;   /* time of call creation */
        unsigned long           flags;
        unsigned long           events;
        spinlock_t              lock;
        rwlock_t                state_lock;     /* lock for state transition */
-       atomic_t                usage;
-       atomic_t                skb_count;      /* Outstanding packets on this call */
-       atomic_t                sequence;       /* Tx data packet sequence counter */
-       u32                     local_abort;    /* local abort code */
-       u32                     remote_abort;   /* remote abort code */
-       int                     error_report;   /* Network error (ICMP/local transport) */
+       u32                     abort_code;     /* Local/remote abort code */
        int                     error;          /* Local error incurred */
-       enum rxrpc_call_state   state : 8;      /* current state of call */
+       enum rxrpc_call_state   state;          /* current state of call */
+       enum rxrpc_call_completion completion;  /* Call completion condition */
+       atomic_t                usage;
+       u16                     service_id;     /* service ID */
+       u8                      security_ix;    /* Security type */
+       u32                     call_id;        /* call ID on connection  */
+       u32                     cid;            /* connection ID plus channel index */
        int                     debug_id;       /* debug ID for printks */
-       u8                      channel;        /* connection channel occupied by this call */
-
-       /* transmission-phase ACK management */
-       u8                      acks_head;      /* offset into window of first entry */
-       u8                      acks_tail;      /* offset into window of last entry */
-       u8                      acks_winsz;     /* size of un-ACK'd window */
-       u8                      acks_unacked;   /* lowest unacked packet in last ACK received */
-       int                     acks_latest;    /* serial number of latest ACK received */
-       rxrpc_seq_t             acks_hard;      /* highest definitively ACK'd msg seq */
-       unsigned long           *acks_window;   /* sent packet window
-                                                * - elements are pointers with LSB set if ACK'd
+       unsigned short          rx_pkt_offset;  /* Current recvmsg packet offset */
+       unsigned short          rx_pkt_len;     /* Current recvmsg packet len */
+
+       /* Rx/Tx circular buffer, depending on phase.
+        *
+        * In the Rx phase, packets are annotated with 0 or the number of the
+        * segment of a jumbo packet each buffer refers to.  There can be up to
+        * 47 segments in a maximum-size UDP packet.
+        *
+        * In the Tx phase, packets are annotated with which buffers have been
+        * acked.
+        */
+#define RXRPC_RXTX_BUFF_SIZE   64
+#define RXRPC_RXTX_BUFF_MASK   (RXRPC_RXTX_BUFF_SIZE - 1)
+#define RXRPC_INIT_RX_WINDOW_SIZE 32
+       struct sk_buff          **rxtx_buffer;
+       u8                      *rxtx_annotations;
+#define RXRPC_TX_ANNO_ACK      0
+#define RXRPC_TX_ANNO_UNACK    1
+#define RXRPC_TX_ANNO_NAK      2
+#define RXRPC_TX_ANNO_RETRANS  3
+#define RXRPC_TX_ANNO_MASK     0x03
+#define RXRPC_TX_ANNO_LAST     0x04
+#define RXRPC_TX_ANNO_RESENT   0x08
+
+#define RXRPC_RX_ANNO_JUMBO    0x3f            /* Jumbo subpacket number + 1 if not zero */
+#define RXRPC_RX_ANNO_JLAST    0x40            /* Set if last element of a jumbo packet */
+#define RXRPC_RX_ANNO_VERIFIED 0x80            /* Set if verified and decrypted */
+       rxrpc_seq_t             tx_hard_ack;    /* Dead slot in buffer; the first transmitted but
+                                                * not hard-ACK'd packet follows this.
+                                                */
+       rxrpc_seq_t             tx_top;         /* Highest Tx slot allocated. */
+
+       /* TCP-style slow-start congestion control [RFC5681].  Since the SMSS
+        * is fixed, we keep these numbers in terms of segments (ie. DATA
+        * packets) rather than bytes.
+        */
+#define RXRPC_TX_SMSS          RXRPC_JUMBO_DATALEN
+       u8                      cong_cwnd;      /* Congestion window size */
+       u8                      cong_extra;     /* Extra to send for congestion management */
+       u8                      cong_ssthresh;  /* Slow-start threshold */
+       enum rxrpc_congest_mode cong_mode:8;    /* Congestion management mode */
+       u8                      cong_dup_acks;  /* Count of ACKs showing missing packets */
+       u8                      cong_cumul_acks; /* Cumulative ACK count */
+       ktime_t                 cong_tstamp;    /* Last time cwnd was changed */
+
+       rxrpc_seq_t             rx_hard_ack;    /* Dead slot in buffer; the first received but not
+                                                * consumed packet follows this.
                                                 */
+       rxrpc_seq_t             rx_top;         /* Highest Rx slot allocated. */
+       rxrpc_seq_t             rx_expect_next; /* Expected next packet sequence number */
+       u8                      rx_winsize;     /* Size of Rx window */
+       u8                      tx_winsize;     /* Maximum size of Tx window */
+       bool                    tx_phase;       /* T if transmission phase, F if receive phase */
+       u8                      nr_jumbo_bad;   /* Number of jumbo dups/exceeds-windows */
 
        /* receive-phase ACK management */
-       rxrpc_seq_t             rx_data_expect; /* next data seq ID expected to be received */
-       rxrpc_seq_t             rx_data_post;   /* next data seq ID expected to be posted */
-       rxrpc_seq_t             rx_data_recv;   /* last data seq ID encountered by recvmsg */
-       rxrpc_seq_t             rx_data_eaten;  /* last data seq ID consumed by recvmsg */
-       rxrpc_seq_t             rx_first_oos;   /* first packet in rx_oos_queue (or 0) */
-       rxrpc_seq_t             ackr_win_top;   /* top of ACK window (rx_data_eaten is bottom) */
-       rxrpc_seq_t             ackr_prev_seq;  /* previous sequence number received */
        u8                      ackr_reason;    /* reason to ACK */
+       u16                     ackr_skew;      /* skew on packet being ACK'd */
        rxrpc_serial_t          ackr_serial;    /* serial of packet being ACK'd */
-       atomic_t                ackr_not_idle;  /* number of packets in Rx queue */
+       rxrpc_seq_t             ackr_prev_seq;  /* previous sequence number received */
+       rxrpc_seq_t             ackr_consumed;  /* Highest packet shown consumed */
+       rxrpc_seq_t             ackr_seen;      /* Highest packet shown seen */
 
-       /* received packet records, 1 bit per record */
-#define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG)
-       unsigned long           ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1];
+       /* ping management */
+       rxrpc_serial_t          ping_serial;    /* Last ping sent */
+       ktime_t                 ping_time;      /* Time last ping sent */
 
-       u8                      in_clientflag;  /* Copy of conn->in_clientflag */
-       struct rxrpc_local      *local;         /* Local endpoint. */
-       u32                     call_id;        /* call ID on connection  */
-       u32                     cid;            /* connection ID plus channel index */
-       u32                     epoch;          /* epoch of this connection */
-       u16                     service_id;     /* service ID */
+       /* transmission-phase ACK management */
+       ktime_t                 acks_latest_ts; /* Timestamp of latest ACK received */
+       rxrpc_serial_t          acks_latest;    /* serial number of latest ACK received */
+       rxrpc_seq_t             acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
 };
 
 /*
- * locally abort an RxRPC call
+ * Summary of a new ACK and the changes it made to the Tx buffer packet states.
  */
-static inline void rxrpc_abort_call(struct rxrpc_call *call, u32 abort_code)
-{
-       write_lock_bh(&call->state_lock);
-       if (call->state < RXRPC_CALL_COMPLETE) {
-               call->local_abort = abort_code;
-               call->state = RXRPC_CALL_LOCALLY_ABORTED;
-               set_bit(RXRPC_CALL_EV_ABORT, &call->events);
-       }
-       write_unlock_bh(&call->state_lock);
-}
+struct rxrpc_ack_summary {
+       u8                      ack_reason;
+       u8                      nr_acks;                /* Number of ACKs in packet */
+       u8                      nr_nacks;               /* Number of NACKs in packet */
+       u8                      nr_new_acks;            /* Number of new ACKs in packet */
+       u8                      nr_new_nacks;           /* Number of new NACKs in packet */
+       u8                      nr_rot_new_acks;        /* Number of rotated new ACKs */
+       bool                    new_low_nack;           /* T if new low NACK found */
+       bool                    retrans_timeo;          /* T if reTx due to timeout happened */
+       u8                      flight_size;            /* Number of unreceived transmissions */
+       /* Place to stash values for tracing */
+       enum rxrpc_congest_mode mode:8;
+       u8                      cwnd;
+       u8                      ssthresh;
+       u8                      dup_acks;
+       u8                      cumulative_acks;
+};
+
+enum rxrpc_skb_trace {
+       rxrpc_skb_rx_cleaned,
+       rxrpc_skb_rx_freed,
+       rxrpc_skb_rx_got,
+       rxrpc_skb_rx_lost,
+       rxrpc_skb_rx_received,
+       rxrpc_skb_rx_rotated,
+       rxrpc_skb_rx_purged,
+       rxrpc_skb_rx_seen,
+       rxrpc_skb_tx_cleaned,
+       rxrpc_skb_tx_freed,
+       rxrpc_skb_tx_got,
+       rxrpc_skb_tx_new,
+       rxrpc_skb_tx_rotated,
+       rxrpc_skb_tx_seen,
+       rxrpc_skb__nr_trace
+};
+
+extern const char rxrpc_skb_traces[rxrpc_skb__nr_trace][7];
+
+enum rxrpc_conn_trace {
+       rxrpc_conn_new_client,
+       rxrpc_conn_new_service,
+       rxrpc_conn_queued,
+       rxrpc_conn_seen,
+       rxrpc_conn_got,
+       rxrpc_conn_put_client,
+       rxrpc_conn_put_service,
+       rxrpc_conn__nr_trace
+};
+
+extern const char rxrpc_conn_traces[rxrpc_conn__nr_trace][4];
+
+enum rxrpc_client_trace {
+       rxrpc_client_activate_chans,
+       rxrpc_client_alloc,
+       rxrpc_client_chan_activate,
+       rxrpc_client_chan_disconnect,
+       rxrpc_client_chan_pass,
+       rxrpc_client_chan_unstarted,
+       rxrpc_client_cleanup,
+       rxrpc_client_count,
+       rxrpc_client_discard,
+       rxrpc_client_duplicate,
+       rxrpc_client_exposed,
+       rxrpc_client_replace,
+       rxrpc_client_to_active,
+       rxrpc_client_to_culled,
+       rxrpc_client_to_idle,
+       rxrpc_client_to_inactive,
+       rxrpc_client_to_waiting,
+       rxrpc_client_uncount,
+       rxrpc_client__nr_trace
+};
+
+extern const char rxrpc_client_traces[rxrpc_client__nr_trace][7];
+extern const char rxrpc_conn_cache_states[RXRPC_CONN__NR_CACHE_STATES][5];
+
+enum rxrpc_call_trace {
+       rxrpc_call_new_client,
+       rxrpc_call_new_service,
+       rxrpc_call_queued,
+       rxrpc_call_queued_ref,
+       rxrpc_call_seen,
+       rxrpc_call_connected,
+       rxrpc_call_release,
+       rxrpc_call_got,
+       rxrpc_call_got_userid,
+       rxrpc_call_got_kernel,
+       rxrpc_call_put,
+       rxrpc_call_put_userid,
+       rxrpc_call_put_kernel,
+       rxrpc_call_put_noqueue,
+       rxrpc_call_error,
+       rxrpc_call__nr_trace
+};
+
+extern const char rxrpc_call_traces[rxrpc_call__nr_trace][4];
+
+enum rxrpc_transmit_trace {
+       rxrpc_transmit_wait,
+       rxrpc_transmit_queue,
+       rxrpc_transmit_queue_last,
+       rxrpc_transmit_rotate,
+       rxrpc_transmit_rotate_last,
+       rxrpc_transmit_await_reply,
+       rxrpc_transmit_end,
+       rxrpc_transmit__nr_trace
+};
+
+extern const char rxrpc_transmit_traces[rxrpc_transmit__nr_trace][4];
+
+enum rxrpc_receive_trace {
+       rxrpc_receive_incoming,
+       rxrpc_receive_queue,
+       rxrpc_receive_queue_last,
+       rxrpc_receive_front,
+       rxrpc_receive_rotate,
+       rxrpc_receive_end,
+       rxrpc_receive__nr_trace
+};
+
+extern const char rxrpc_receive_traces[rxrpc_receive__nr_trace][4];
+
+enum rxrpc_recvmsg_trace {
+       rxrpc_recvmsg_enter,
+       rxrpc_recvmsg_wait,
+       rxrpc_recvmsg_dequeue,
+       rxrpc_recvmsg_hole,
+       rxrpc_recvmsg_next,
+       rxrpc_recvmsg_cont,
+       rxrpc_recvmsg_full,
+       rxrpc_recvmsg_data_return,
+       rxrpc_recvmsg_terminal,
+       rxrpc_recvmsg_to_be_accepted,
+       rxrpc_recvmsg_return,
+       rxrpc_recvmsg__nr_trace
+};
+
+extern const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
+
+enum rxrpc_rtt_tx_trace {
+       rxrpc_rtt_tx_ping,
+       rxrpc_rtt_tx_data,
+       rxrpc_rtt_tx__nr_trace
+};
+
+extern const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5];
+
+enum rxrpc_rtt_rx_trace {
+       rxrpc_rtt_rx_ping_response,
+       rxrpc_rtt_rx_requested_ack,
+       rxrpc_rtt_rx__nr_trace
+};
+
+extern const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5];
+
+enum rxrpc_timer_trace {
+       rxrpc_timer_begin,
+       rxrpc_timer_init_for_reply,
+       rxrpc_timer_init_for_send_reply,
+       rxrpc_timer_expired,
+       rxrpc_timer_set_for_ack,
+       rxrpc_timer_set_for_ping,
+       rxrpc_timer_set_for_resend,
+       rxrpc_timer_set_for_send,
+       rxrpc_timer__nr_trace
+};
+
+extern const char rxrpc_timer_traces[rxrpc_timer__nr_trace][8];
+
+enum rxrpc_propose_ack_trace {
+       rxrpc_propose_ack_client_tx_end,
+       rxrpc_propose_ack_input_data,
+       rxrpc_propose_ack_ping_for_lost_ack,
+       rxrpc_propose_ack_ping_for_lost_reply,
+       rxrpc_propose_ack_ping_for_params,
+       rxrpc_propose_ack_processing_op,
+       rxrpc_propose_ack_respond_to_ack,
+       rxrpc_propose_ack_respond_to_ping,
+       rxrpc_propose_ack_retry_tx,
+       rxrpc_propose_ack_rotate_rx,
+       rxrpc_propose_ack_terminal_ack,
+       rxrpc_propose_ack__nr_trace
+};
+
+enum rxrpc_propose_ack_outcome {
+       rxrpc_propose_ack_use,
+       rxrpc_propose_ack_update,
+       rxrpc_propose_ack_subsume,
+       rxrpc_propose_ack__nr_outcomes
+};
+
+extern const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8];
+extern const char *const rxrpc_propose_ack_outcomes[rxrpc_propose_ack__nr_outcomes];
+
+enum rxrpc_congest_change {
+       rxrpc_cong_begin_retransmission,
+       rxrpc_cong_cleared_nacks,
+       rxrpc_cong_new_low_nack,
+       rxrpc_cong_no_change,
+       rxrpc_cong_progress,
+       rxrpc_cong_retransmit_again,
+       rxrpc_cong_rtt_window_end,
+       rxrpc_cong_saw_nack,
+       rxrpc_congest__nr_change
+};
+
+extern const char rxrpc_congest_modes[NR__RXRPC_CONGEST_MODES][10];
+extern const char rxrpc_congest_changes[rxrpc_congest__nr_change][9];
+
+extern const char *const rxrpc_pkts[];
+extern const char rxrpc_ack_names[RXRPC_ACK__INVALID + 1][4];
+
+#include <trace/events/rxrpc.h>
 
 /*
  * af_rxrpc.c
  */
-extern atomic_t rxrpc_n_skbs;
+extern atomic_t rxrpc_n_tx_skbs, rxrpc_n_rx_skbs;
 extern u32 rxrpc_epoch;
 extern atomic_t rxrpc_debug_id;
 extern struct workqueue_struct *rxrpc_workqueue;
@@ -495,70 +800,179 @@ extern struct workqueue_struct *rxrpc_workqueue;
 /*
  * call_accept.c
  */
+int rxrpc_service_prealloc(struct rxrpc_sock *, gfp_t);
+void rxrpc_discard_prealloc(struct rxrpc_sock *);
+struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *,
+                                          struct rxrpc_connection *,
+                                          struct sk_buff *);
 void rxrpc_accept_incoming_calls(struct rxrpc_local *);
-struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *, unsigned long);
+struct rxrpc_call *rxrpc_accept_call(struct rxrpc_sock *, unsigned long,
+                                    rxrpc_notify_rx_t);
 int rxrpc_reject_call(struct rxrpc_sock *);
 
 /*
  * call_event.c
  */
-void __rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool);
-void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool);
+void __rxrpc_set_timer(struct rxrpc_call *, enum rxrpc_timer_trace, ktime_t);
+void rxrpc_set_timer(struct rxrpc_call *, enum rxrpc_timer_trace, ktime_t);
+void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool,
+                      enum rxrpc_propose_ack_trace);
 void rxrpc_process_call(struct work_struct *);
 
 /*
  * call_object.c
  */
+extern const char *const rxrpc_call_states[];
+extern const char *const rxrpc_call_completions[];
 extern unsigned int rxrpc_max_call_lifetime;
-extern unsigned int rxrpc_dead_call_expiry;
 extern struct kmem_cache *rxrpc_call_jar;
 extern struct list_head rxrpc_calls;
 extern rwlock_t rxrpc_call_lock;
 
 struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rxrpc_sock *, unsigned long);
+struct rxrpc_call *rxrpc_alloc_call(gfp_t);
 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct rxrpc_conn_parameters *,
                                         struct sockaddr_rxrpc *,
                                         unsigned long, gfp_t);
-struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *,
-                                      struct rxrpc_connection *,
-                                      struct sk_buff *);
-void rxrpc_release_call(struct rxrpc_call *);
+void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
+                        struct sk_buff *);
+void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
 void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
-void __rxrpc_put_call(struct rxrpc_call *);
+bool __rxrpc_queue_call(struct rxrpc_call *);
+bool rxrpc_queue_call(struct rxrpc_call *);
+void rxrpc_see_call(struct rxrpc_call *);
+void rxrpc_get_call(struct rxrpc_call *, enum rxrpc_call_trace);
+void rxrpc_put_call(struct rxrpc_call *, enum rxrpc_call_trace);
+void rxrpc_cleanup_call(struct rxrpc_call *);
 void __exit rxrpc_destroy_all_calls(void);
 
+static inline bool rxrpc_is_service_call(const struct rxrpc_call *call)
+{
+       return test_bit(RXRPC_CALL_IS_SERVICE, &call->flags);
+}
+
+static inline bool rxrpc_is_client_call(const struct rxrpc_call *call)
+{
+       return !rxrpc_is_service_call(call);
+}
+
+/*
+ * Transition a call to the complete state.
+ */
+static inline bool __rxrpc_set_call_completion(struct rxrpc_call *call,
+                                              enum rxrpc_call_completion compl,
+                                              u32 abort_code,
+                                              int error)
+{
+       if (call->state < RXRPC_CALL_COMPLETE) {
+               call->abort_code = abort_code;
+               call->error = error;
+               call->completion = compl,
+               call->state = RXRPC_CALL_COMPLETE;
+               wake_up(&call->waitq);
+               return true;
+       }
+       return false;
+}
+
+static inline bool rxrpc_set_call_completion(struct rxrpc_call *call,
+                                            enum rxrpc_call_completion compl,
+                                            u32 abort_code,
+                                            int error)
+{
+       bool ret;
+
+       write_lock_bh(&call->state_lock);
+       ret = __rxrpc_set_call_completion(call, compl, abort_code, error);
+       write_unlock_bh(&call->state_lock);
+       return ret;
+}
+
+/*
+ * Record that a call successfully completed.
+ */
+static inline bool __rxrpc_call_completed(struct rxrpc_call *call)
+{
+       return __rxrpc_set_call_completion(call, RXRPC_CALL_SUCCEEDED, 0, 0);
+}
+
+static inline bool rxrpc_call_completed(struct rxrpc_call *call)
+{
+       bool ret;
+
+       write_lock_bh(&call->state_lock);
+       ret = __rxrpc_call_completed(call);
+       write_unlock_bh(&call->state_lock);
+       return ret;
+}
+
+/*
+ * Record that a call is locally aborted.
+ */
+static inline bool __rxrpc_abort_call(const char *why, struct rxrpc_call *call,
+                                     rxrpc_seq_t seq,
+                                     u32 abort_code, int error)
+{
+       trace_rxrpc_abort(why, call->cid, call->call_id, seq,
+                         abort_code, error);
+       return __rxrpc_set_call_completion(call, RXRPC_CALL_LOCALLY_ABORTED,
+                                          abort_code, error);
+}
+
+static inline bool rxrpc_abort_call(const char *why, struct rxrpc_call *call,
+                                   rxrpc_seq_t seq, u32 abort_code, int error)
+{
+       bool ret;
+
+       write_lock_bh(&call->state_lock);
+       ret = __rxrpc_abort_call(why, call, seq, abort_code, error);
+       write_unlock_bh(&call->state_lock);
+       return ret;
+}
+
 /*
  * conn_client.c
  */
+extern unsigned int rxrpc_max_client_connections;
+extern unsigned int rxrpc_reap_client_connections;
+extern unsigned int rxrpc_conn_idle_client_expiry;
+extern unsigned int rxrpc_conn_idle_client_fast_expiry;
 extern struct idr rxrpc_client_conn_ids;
 
 void rxrpc_destroy_client_conn_ids(void);
 int rxrpc_connect_call(struct rxrpc_call *, struct rxrpc_conn_parameters *,
                       struct sockaddr_rxrpc *, gfp_t);
-void rxrpc_unpublish_client_conn(struct rxrpc_connection *);
+void rxrpc_expose_client_call(struct rxrpc_call *);
+void rxrpc_disconnect_client_call(struct rxrpc_call *);
+void rxrpc_put_client_conn(struct rxrpc_connection *);
+void __exit rxrpc_destroy_all_client_connections(void);
 
 /*
  * conn_event.c
  */
 void rxrpc_process_connection(struct work_struct *);
-void rxrpc_reject_packet(struct rxrpc_local *, struct sk_buff *);
-void rxrpc_reject_packets(struct rxrpc_local *);
 
 /*
  * conn_object.c
  */
 extern unsigned int rxrpc_connection_expiry;
 extern struct list_head rxrpc_connections;
+extern struct list_head rxrpc_connection_proc_list;
 extern rwlock_t rxrpc_connection_lock;
 
 int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
 struct rxrpc_connection *rxrpc_alloc_connection(gfp_t);
 struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *,
                                                   struct sk_buff *);
-void __rxrpc_disconnect_call(struct rxrpc_call *);
+void __rxrpc_disconnect_call(struct rxrpc_connection *, struct rxrpc_call *);
 void rxrpc_disconnect_call(struct rxrpc_call *);
-void rxrpc_put_connection(struct rxrpc_connection *);
+void rxrpc_kill_connection(struct rxrpc_connection *);
+bool rxrpc_queue_conn(struct rxrpc_connection *);
+void rxrpc_see_connection(struct rxrpc_connection *);
+void rxrpc_get_connection(struct rxrpc_connection *);
+struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *);
+void rxrpc_put_service_conn(struct rxrpc_connection *);
 void __exit rxrpc_destroy_all_connections(void);
 
 static inline bool rxrpc_conn_is_client(const struct rxrpc_connection *conn)
@@ -571,24 +985,15 @@ static inline bool rxrpc_conn_is_service(const struct rxrpc_connection *conn)
        return !rxrpc_conn_is_client(conn);
 }
 
-static inline void rxrpc_get_connection(struct rxrpc_connection *conn)
+static inline void rxrpc_put_connection(struct rxrpc_connection *conn)
 {
-       atomic_inc(&conn->usage);
-}
-
-static inline
-struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *conn)
-{
-       return atomic_inc_not_zero(&conn->usage) ? conn : NULL;
-}
+       if (!conn)
+               return;
 
-static inline bool rxrpc_queue_conn(struct rxrpc_connection *conn)
-{
-       if (!rxrpc_get_connection_maybe(conn))
-               return false;
-       if (!rxrpc_queue_work(&conn->processor))
-               rxrpc_put_connection(conn);
-       return true;
+       if (rxrpc_conn_is_client(conn))
+               rxrpc_put_client_conn(conn);
+       else
+               rxrpc_put_service_conn(conn);
 }
 
 /*
@@ -596,17 +1001,14 @@ static inline bool rxrpc_queue_conn(struct rxrpc_connection *conn)
  */
 struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *,
                                                     struct sk_buff *);
-struct rxrpc_connection *rxrpc_incoming_connection(struct rxrpc_local *,
-                                                  struct sockaddr_rxrpc *,
-                                                  struct sk_buff *);
+struct rxrpc_connection *rxrpc_prealloc_service_connection(gfp_t);
+void rxrpc_new_incoming_connection(struct rxrpc_connection *, struct sk_buff *);
 void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
 
 /*
  * input.c
  */
 void rxrpc_data_ready(struct sock *);
-int rxrpc_queue_rcv_skb(struct rxrpc_call *, struct sk_buff *, bool, bool);
-void rxrpc_fast_process_packet(struct rxrpc_call *, struct sk_buff *);
 
 /*
  * insecure.c
@@ -668,25 +1070,25 @@ extern unsigned int rxrpc_idle_ack_delay;
 extern unsigned int rxrpc_rx_window_size;
 extern unsigned int rxrpc_rx_mtu;
 extern unsigned int rxrpc_rx_jumbo_max;
+extern unsigned int rxrpc_resend_timeout;
 
-extern const char *const rxrpc_pkts[];
 extern const s8 rxrpc_ack_priority[];
 
-extern const char *rxrpc_acks(u8 reason);
-
 /*
  * output.c
  */
-extern unsigned int rxrpc_resend_timeout;
-
-int rxrpc_send_data_packet(struct rxrpc_connection *, struct sk_buff *);
-int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
+int rxrpc_send_ack_packet(struct rxrpc_call *, bool);
+int rxrpc_send_abort_packet(struct rxrpc_call *);
+int rxrpc_send_data_packet(struct rxrpc_call *, struct sk_buff *, bool);
+void rxrpc_reject_packets(struct rxrpc_local *);
 
 /*
  * peer_event.c
  */
 void rxrpc_error_report(struct sock *);
 void rxrpc_peer_error_distributor(struct work_struct *);
+void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace,
+                       rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
 
 /*
  * peer_object.c
@@ -696,10 +1098,13 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu(struct rxrpc_local *,
 struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
                                     struct sockaddr_rxrpc *, gfp_t);
 struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
+struct rxrpc_peer *rxrpc_lookup_incoming_peer(struct rxrpc_local *,
+                                             struct rxrpc_peer *);
 
-static inline void rxrpc_get_peer(struct rxrpc_peer *peer)
+static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
 {
        atomic_inc(&peer->usage);
+       return peer;
 }
 
 static inline
@@ -718,14 +1123,13 @@ static inline void rxrpc_put_peer(struct rxrpc_peer *peer)
 /*
  * proc.c
  */
-extern const char *const rxrpc_call_states[];
 extern const struct file_operations rxrpc_call_seq_fops;
 extern const struct file_operations rxrpc_connection_seq_fops;
 
 /*
  * recvmsg.c
  */
-void rxrpc_remove_user_ID(struct rxrpc_sock *, struct rxrpc_call *);
+void rxrpc_notify_socket(struct rxrpc_call *);
 int rxrpc_recvmsg(struct socket *, struct msghdr *, size_t, int);
 
 /*
@@ -743,10 +1147,22 @@ void rxrpc_exit_security(void);
 int rxrpc_init_client_conn_security(struct rxrpc_connection *);
 int rxrpc_init_server_conn_security(struct rxrpc_connection *);
 
+/*
+ * sendmsg.c
+ */
+int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
+
 /*
  * skbuff.c
  */
+void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
 void rxrpc_packet_destructor(struct sk_buff *);
+void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_lose_skb(struct sk_buff *, enum rxrpc_skb_trace);
+void rxrpc_purge_queue(struct sk_buff_head *);
 
 /*
  * sysctl.c
@@ -764,6 +1180,23 @@ static inline void rxrpc_sysctl_exit(void) {}
  */
 int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
 
+static inline bool before(u32 seq1, u32 seq2)
+{
+        return (s32)(seq1 - seq2) < 0;
+}
+static inline bool before_eq(u32 seq1, u32 seq2)
+{
+        return (s32)(seq1 - seq2) <= 0;
+}
+static inline bool after(u32 seq1, u32 seq2)
+{
+        return (s32)(seq1 - seq2) > 0;
+}
+static inline bool after_eq(u32 seq1, u32 seq2)
+{
+        return (s32)(seq1 - seq2) >= 0;
+}
+
 /*
  * debug tracing
  */
@@ -846,11 +1279,12 @@ do {                                                             \
 
 #define ASSERTCMP(X, OP, Y)                                            \
 do {                                                                   \
-       unsigned long _x = (unsigned long)(X);                          \
-       unsigned long _y = (unsigned long)(Y);                          \
+       __typeof__(X) _x = (X);                                         \
+       __typeof__(Y) _y = (__typeof__(X))(Y);                          \
        if (unlikely(!(_x OP _y))) {                                    \
-               pr_err("Assertion failed - %lu(0x%lx) %s %lu(0x%lx) is false\n",                        \
-                      _x, _x, #OP, _y, _y);                            \
+               pr_err("Assertion failed - %lu(0x%lx) %s %lu(0x%lx) is false\n", \
+                      (unsigned long)_x, (unsigned long)_x, #OP,       \
+                      (unsigned long)_y, (unsigned long)_y);           \
                BUG();                                                  \
        }                                                               \
 } while (0)
@@ -865,11 +1299,12 @@ do {                                                             \
 
 #define ASSERTIFCMP(C, X, OP, Y)                                       \
 do {                                                                   \
-       unsigned long _x = (unsigned long)(X);                          \
-       unsigned long _y = (unsigned long)(Y);                          \
+       __typeof__(X) _x = (X);                                         \
+       __typeof__(Y) _y = (__typeof__(X))(Y);                          \
        if (unlikely((C) && !(_x OP _y))) {                             \
                pr_err("Assertion failed - %lu(0x%lx) %s %lu(0x%lx) is false\n", \
-                      _x, _x, #OP, _y, _y);                            \
+                      (unsigned long)_x, (unsigned long)_x, #OP,       \
+                      (unsigned long)_y, (unsigned long)_y);           \
                BUG();                                                  \
        }                                                               \
 } while (0)
@@ -893,54 +1328,3 @@ do {                                              \
 } while (0)
 
 #endif /* __KDEBUGALL */
-
-/*
- * socket buffer accounting / leak finding
- */
-static inline void __rxrpc_new_skb(struct sk_buff *skb, const char *fn)
-{
-       //_net("new skb %p %s [%d]", skb, fn, atomic_read(&rxrpc_n_skbs));
-       //atomic_inc(&rxrpc_n_skbs);
-}
-
-#define rxrpc_new_skb(skb) __rxrpc_new_skb((skb), __func__)
-
-static inline void __rxrpc_kill_skb(struct sk_buff *skb, const char *fn)
-{
-       //_net("kill skb %p %s [%d]", skb, fn, atomic_read(&rxrpc_n_skbs));
-       //atomic_dec(&rxrpc_n_skbs);
-}
-
-#define rxrpc_kill_skb(skb) __rxrpc_kill_skb((skb), __func__)
-
-static inline void __rxrpc_free_skb(struct sk_buff *skb, const char *fn)
-{
-       if (skb) {
-               CHECK_SLAB_OKAY(&skb->users);
-               //_net("free skb %p %s [%d]",
-               //     skb, fn, atomic_read(&rxrpc_n_skbs));
-               //atomic_dec(&rxrpc_n_skbs);
-               kfree_skb(skb);
-       }
-}
-
-#define rxrpc_free_skb(skb) __rxrpc_free_skb((skb), __func__)
-
-static inline void rxrpc_purge_queue(struct sk_buff_head *list)
-{
-       struct sk_buff *skb;
-       while ((skb = skb_dequeue((list))) != NULL)
-               rxrpc_free_skb(skb);
-}
-
-#define rxrpc_get_call(CALL)                           \
-do {                                                   \
-       CHECK_SLAB_OKAY(&(CALL)->usage);                \
-       if (atomic_inc_return(&(CALL)->usage) == 1)     \
-               BUG();                                  \
-} while (0)
-
-#define rxrpc_put_call(CALL)                           \
-do {                                                   \
-       __rxrpc_put_call(CALL);                         \
-} while (0)