Commit c3874bbe authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'rxrpc-iothread-20240305' of...

Merge tag 'rxrpc-iothread-20240305' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

David Howells says:

====================
Here are some changes to AF_RXRPC:

 (1) Cache the transmission serial number of ACK and DATA packets in the
     rxrpc_txbuf struct and log this in the retransmit tracepoint.

 (2) Don't use atomics on rxrpc_txbuf::flags[*] and cache the intended wire
     header flags there too to avoid duplication.

 (3) Cache the wire checksum in rxrpc_txbuf to make it easier to create
     jumbo packets in future (which will require altering the wire header
     to a jumbo header and restoring it back again for retransmission).

 (4) Fix the protocol names in the wire ACK trailer struct.

 (5) Strip all the barriers and atomics out of the call timer tracking[*].

 (6) Remove atomic handling from call->tx_transmitted and
     call->acks_prev_seq[*].

 (7) Don't bother resetting the DF flag after UDP packet transmission.  To
     change it, we now call directly into UDP code, so it's quick just to
     set it every time.

 (8) Merge together the DF/non-DF branches of the DATA transmission to
     reduce duplication in the code.

 (9) Add a kvec array into rxrpc_txbuf and start moving things over to it.
     This paves the way for using page frags.

(10) Split (sub)packet preparation and timestamping out of the DATA
     transmission function.  This helps pave the way for future jumbo
     packet generation.

(11) In rxkad, don't pick values out of the wire header stored in
     rxrpc_txbuf, buf rather find them elsewhere so we can remove the wire
     header from there.

(12) Move rxrpc_send_ACK() to output.c so that it can be merged with
     rxrpc_send_ack_packet().

(13) Use rxrpc_txbuf::kvec[0] to access the wire header for the packet
     rather than directly accessing the copy in rxrpc_txbuf.  This will
     allow that to be removed to a page frag.

(14) Switch from keeping the transmission buffers in rxrpc_txbuf allocated
     in the slab to allocating them using page fragment allocators.  There
     are separate allocators for DATA packets (which persist for a while)
     and control packets (which are discarded immediately).

     We can then turn on MSG_SPLICE_PAGES when transmitting DATA and ACK
     packets.

     We can also get rid of the RCU cleanup on rxrpc_txbufs, preferring
     instead to release the page frags as soon as possible.

(15) Parse received packets before handling timeouts as the former may
     reset the latter.

(16) Make sure we don't retransmit DATA packets after all the packets have
     been ACK'd.

(17) Differentiate traces for PING ACK transmission.

(18) Switch to keeping timeouts as ktime_t rather than a number of jiffies
     as the latter is too coarse a granularity.  Only set the call timer at
     the end of the call event function from the aggregate of all the
     timeouts, thereby reducing the number of timer calls made.  In future,
     it might be possible to reduce the number of timers from one per call
     to one per I/O thread and to use a high-precision timer.

(19) Record RTT probes after successful transmission rather than recording
     it before and then cancelling it after if unsuccessful[*].  This
     allows a number of calls to get the current time to be removed.

(20) Clean up the resend algorithm as there's now no need to walk the
     transmission buffer under lock[*].  DATA packets can be retransmitted
     as soon as they're found rather than being queued up and transmitted
     when the locked is dropped.

(21) When initially parsing a received ACK packet, extract some of the
     fields from the ack info to the skbuff private data.  This makes it
     easier to do path MTU discovery in the future when the call to which a
     PING RESPONSE ACK refers has been deallocated.

[*] Possible with the move of almost all code from softirq context to the
    I/O thread.

Link: https://lore.kernel.org/r/20240301163807.385573-1-dhowells@redhat.com/ # v1
Link: https://lore.kernel.org/r/20240304084322.705539-1-dhowells@redhat.com/ # v2

* tag 'rxrpc-iothread-20240305' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: (21 commits)
  rxrpc: Extract useful fields from a received ACK to skb priv data
  rxrpc: Clean up the resend algorithm
  rxrpc: Record probes after transmission and reduce number of time-gets
  rxrpc: Use ktimes for call timeout tracking and set the timer lazily
  rxrpc: Differentiate PING ACK transmission traces.
  rxrpc: Don't permit resending after all Tx packets acked
  rxrpc: Parse received packets before dealing with timeouts
  rxrpc: Do zerocopy using MSG_SPLICE_PAGES and page frags
  rxrpc: Use rxrpc_txbuf::kvec[0] instead of rxrpc_txbuf::wire
  rxrpc: Move rxrpc_send_ACK() to output.c with rxrpc_send_ack_packet()
  rxrpc: Don't pick values out of the wire header when setting up security
  rxrpc: Split up the DATA packet transmission function
  rxrpc: Add a kvec[] to the rxrpc_txbuf struct
  rxrpc: Merge together DF/non-DF branches of data Tx function
  rxrpc: Do lazy DF flag resetting
  rxrpc: Remove atomic handling on some fields only used in I/O thread
  rxrpc: Strip barriers and atomics off of timer tracking
  rxrpc: Fix the names of the fields in the ACK trailer struct
  rxrpc: Note cksum in txbuf
  rxrpc: Convert rxrpc_txbuf::flags into a mask and don't use atomics
  ...
====================

Link: https://lore.kernel.org/r/


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 9cb3d523 4b68137a
Loading
Loading
Loading
Loading
+107 −91
Original line number Diff line number Diff line
@@ -83,7 +83,7 @@
	EM(rxrpc_badmsg_bad_abort,		"bad-abort")		\
	EM(rxrpc_badmsg_bad_jumbo,		"bad-jumbo")		\
	EM(rxrpc_badmsg_short_ack,		"short-ack")		\
	EM(rxrpc_badmsg_short_ack_info,		"short-ack-info")	\
	EM(rxrpc_badmsg_short_ack_trailer,	"short-ack-trailer")	\
	EM(rxrpc_badmsg_short_hdr,		"short-hdr")		\
	EM(rxrpc_badmsg_unsupported_packet,	"unsup-pkt")		\
	EM(rxrpc_badmsg_zero_call,		"zero-call")		\
@@ -119,6 +119,7 @@
	EM(rxrpc_call_poke_complete,		"Compl")	\
	EM(rxrpc_call_poke_error,		"Error")	\
	EM(rxrpc_call_poke_idle,		"Idle")		\
	EM(rxrpc_call_poke_set_timeout,		"Set-timo")	\
	EM(rxrpc_call_poke_start,		"Start")	\
	EM(rxrpc_call_poke_timer,		"Timer")	\
	E_(rxrpc_call_poke_timer_now,		"Timer-now")
@@ -340,35 +341,26 @@
	E_(rxrpc_rtt_rx_requested_ack,		"RACK")

#define rxrpc_timer_traces \
	EM(rxrpc_timer_begin,			"Begin ") \
	EM(rxrpc_timer_exp_ack,			"ExpAck") \
	EM(rxrpc_timer_exp_hard,		"ExpHrd") \
	EM(rxrpc_timer_exp_idle,		"ExpIdl") \
	EM(rxrpc_timer_exp_keepalive,		"ExpKA ") \
	EM(rxrpc_timer_exp_lost_ack,		"ExpLoA") \
	EM(rxrpc_timer_exp_normal,		"ExpNml") \
	EM(rxrpc_timer_exp_ping,		"ExpPng") \
	EM(rxrpc_timer_exp_resend,		"ExpRsn") \
	EM(rxrpc_timer_init_for_reply,		"IniRpl") \
	EM(rxrpc_timer_init_for_send_reply,	"SndRpl") \
	EM(rxrpc_timer_restart,			"Restrt") \
	EM(rxrpc_timer_set_for_ack,		"SetAck") \
	EM(rxrpc_timer_set_for_hard,		"SetHrd") \
	EM(rxrpc_timer_set_for_idle,		"SetIdl") \
	EM(rxrpc_timer_set_for_keepalive,	"KeepAl") \
	EM(rxrpc_timer_set_for_lost_ack,	"SetLoA") \
	EM(rxrpc_timer_set_for_normal,		"SetNml") \
	EM(rxrpc_timer_set_for_ping,		"SetPng") \
	EM(rxrpc_timer_set_for_resend,		"SetRTx") \
	E_(rxrpc_timer_set_for_send,		"SetSnd")
	EM(rxrpc_timer_trace_delayed_ack,	"DelayAck ") \
	EM(rxrpc_timer_trace_expect_rx,		"ExpectRx ") \
	EM(rxrpc_timer_trace_hard,		"HardLimit") \
	EM(rxrpc_timer_trace_idle,		"IdleLimit") \
	EM(rxrpc_timer_trace_keepalive,		"KeepAlive") \
	EM(rxrpc_timer_trace_lost_ack,		"LostAck  ") \
	EM(rxrpc_timer_trace_ping,		"DelayPing") \
	EM(rxrpc_timer_trace_resend,		"Resend   ") \
	EM(rxrpc_timer_trace_resend_reset,	"ResendRst") \
	E_(rxrpc_timer_trace_resend_tx,		"ResendTx ")

#define rxrpc_propose_ack_traces \
	EM(rxrpc_propose_ack_client_tx_end,	"ClTxEnd") \
	EM(rxrpc_propose_ack_delayed_ack,	"DlydAck") \
	EM(rxrpc_propose_ack_input_data,	"DataIn ") \
	EM(rxrpc_propose_ack_input_data_hole,	"DataInH") \
	EM(rxrpc_propose_ack_ping_for_keepalive, "KeepAlv") \
	EM(rxrpc_propose_ack_ping_for_lost_ack,	"LostAck") \
	EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
	EM(rxrpc_propose_ack_ping_for_0_retrans, "0-Retrn") \
	EM(rxrpc_propose_ack_ping_for_old_rtt,	"OldRtt ") \
	EM(rxrpc_propose_ack_ping_for_params,	"Params ") \
	EM(rxrpc_propose_ack_ping_for_rtt,	"Rtt    ") \
@@ -1084,9 +1076,9 @@ TRACE_EVENT(rxrpc_tx_packet,

TRACE_EVENT(rxrpc_tx_data,
	    TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
		     rxrpc_serial_t serial, u8 flags, bool retrans, bool lose),
		     rxrpc_serial_t serial, unsigned int flags, bool lose),

	    TP_ARGS(call, seq, serial, flags, retrans, lose),
	    TP_ARGS(call, seq, serial, flags, lose),

	    TP_STRUCT__entry(
		    __field(unsigned int,	call)
@@ -1094,8 +1086,7 @@ TRACE_EVENT(rxrpc_tx_data,
		    __field(rxrpc_serial_t,	serial)
		    __field(u32,		cid)
		    __field(u32,		call_id)
		    __field(u8,			flags)
		    __field(bool,		retrans)
		    __field(u16,		flags)
		    __field(bool,		lose)
			     ),

@@ -1106,7 +1097,6 @@ TRACE_EVENT(rxrpc_tx_data,
		    __entry->seq = seq;
		    __entry->serial = serial;
		    __entry->flags = flags;
		    __entry->retrans = retrans;
		    __entry->lose = lose;
			   ),

@@ -1116,8 +1106,8 @@ TRACE_EVENT(rxrpc_tx_data,
		      __entry->call_id,
		      __entry->serial,
		      __entry->seq,
		      __entry->flags,
		      __entry->retrans ? " *RETRANS*" : "",
		      __entry->flags & RXRPC_TXBUF_WIRE_FLAGS,
		      __entry->flags & RXRPC_TXBUF_RESENT ? " *RETRANS*" : "",
		      __entry->lose ? " *LOSE*" : "")
	    );

@@ -1314,90 +1304,112 @@ TRACE_EVENT(rxrpc_rtt_rx,
		      __entry->rto)
	    );

TRACE_EVENT(rxrpc_timer,
	    TP_PROTO(struct rxrpc_call *call, enum rxrpc_timer_trace why,
		     unsigned long now),
TRACE_EVENT(rxrpc_timer_set,
	    TP_PROTO(struct rxrpc_call *call, ktime_t delay,
		     enum rxrpc_timer_trace why),

	    TP_ARGS(call, why, now),
	    TP_ARGS(call, delay, why),

	    TP_STRUCT__entry(
		    __field(unsigned int,		call)
		    __field(enum rxrpc_timer_trace,	why)
		    __field(long,			now)
		    __field(long,			ack_at)
		    __field(long,			ack_lost_at)
		    __field(long,			resend_at)
		    __field(long,			ping_at)
		    __field(long,			expect_rx_by)
		    __field(long,			expect_req_by)
		    __field(long,			expect_term_by)
		    __field(long,			timer)
		    __field(ktime_t,			delay)
			     ),

	    TP_fast_assign(
		    __entry->call		= call->debug_id;
		    __entry->why		= why;
		    __entry->now		= now;
		    __entry->ack_at		= call->delay_ack_at;
		    __entry->ack_lost_at	= call->ack_lost_at;
		    __entry->resend_at		= call->resend_at;
		    __entry->expect_rx_by	= call->expect_rx_by;
		    __entry->expect_req_by	= call->expect_req_by;
		    __entry->expect_term_by	= call->expect_term_by;
		    __entry->timer		= call->timer.expires;
		    __entry->delay		= delay;
			   ),

	    TP_printk("c=%08x %s a=%ld la=%ld r=%ld xr=%ld xq=%ld xt=%ld t=%ld",
	    TP_printk("c=%08x %s to=%lld",
		      __entry->call,
		      __print_symbolic(__entry->why, rxrpc_timer_traces),
		      __entry->ack_at - __entry->now,
		      __entry->ack_lost_at - __entry->now,
		      __entry->resend_at - __entry->now,
		      __entry->expect_rx_by - __entry->now,
		      __entry->expect_req_by - __entry->now,
		      __entry->expect_term_by - __entry->now,
		      __entry->timer - __entry->now)
		      ktime_to_us(__entry->delay))
	    );

TRACE_EVENT(rxrpc_timer_expired,
	    TP_PROTO(struct rxrpc_call *call, unsigned long now),
TRACE_EVENT(rxrpc_timer_exp,
	    TP_PROTO(struct rxrpc_call *call, ktime_t delay,
		     enum rxrpc_timer_trace why),

	    TP_ARGS(call, now),
	    TP_ARGS(call, delay, why),

	    TP_STRUCT__entry(
		    __field(unsigned int,		call)
		    __field(enum rxrpc_timer_trace,	why)
		    __field(ktime_t,			delay)
			     ),

	    TP_fast_assign(
		    __entry->call		= call->debug_id;
		    __entry->why		= why;
		    __entry->delay		= delay;
			   ),

	    TP_printk("c=%08x %s to=%lld",
		      __entry->call,
		      __print_symbolic(__entry->why, rxrpc_timer_traces),
		      ktime_to_us(__entry->delay))
	    );

TRACE_EVENT(rxrpc_timer_can,
	    TP_PROTO(struct rxrpc_call *call, enum rxrpc_timer_trace why),

	    TP_ARGS(call, why),

	    TP_STRUCT__entry(
		    __field(unsigned int,		call)
		    __field(enum rxrpc_timer_trace,	why)
			     ),

	    TP_fast_assign(
		    __entry->call		= call->debug_id;
		    __entry->why		= why;
			   ),

	    TP_printk("c=%08x %s",
		      __entry->call,
		      __print_symbolic(__entry->why, rxrpc_timer_traces))
	    );

TRACE_EVENT(rxrpc_timer_restart,
	    TP_PROTO(struct rxrpc_call *call, ktime_t delay, unsigned long delayj),

	    TP_ARGS(call, delay, delayj),

	    TP_STRUCT__entry(
		    __field(unsigned int,		call)
		    __field(long,		now)
		    __field(long,		ack_at)
		    __field(long,		ack_lost_at)
		    __field(long,		resend_at)
		    __field(long,		ping_at)
		    __field(long,		expect_rx_by)
		    __field(long,		expect_req_by)
		    __field(long,		expect_term_by)
		    __field(long,		timer)
		    __field(unsigned long,		delayj)
		    __field(ktime_t,			delay)
			     ),

	    TP_fast_assign(
		    __entry->call		= call->debug_id;
		    __entry->now		= now;
		    __entry->ack_at		= call->delay_ack_at;
		    __entry->ack_lost_at	= call->ack_lost_at;
		    __entry->resend_at		= call->resend_at;
		    __entry->expect_rx_by	= call->expect_rx_by;
		    __entry->expect_req_by	= call->expect_req_by;
		    __entry->expect_term_by	= call->expect_term_by;
		    __entry->timer		= call->timer.expires;
		    __entry->delayj		= delayj;
		    __entry->delay		= delay;
			   ),

	    TP_printk("c=%08x EXPIRED a=%ld la=%ld r=%ld xr=%ld xq=%ld xt=%ld t=%ld",
	    TP_printk("c=%08x to=%lld j=%ld",
		      __entry->call,
		      __entry->ack_at - __entry->now,
		      __entry->ack_lost_at - __entry->now,
		      __entry->resend_at - __entry->now,
		      __entry->expect_rx_by - __entry->now,
		      __entry->expect_req_by - __entry->now,
		      __entry->expect_term_by - __entry->now,
		      __entry->timer - __entry->now)
		      ktime_to_us(__entry->delay),
		      __entry->delayj)
	    );

TRACE_EVENT(rxrpc_timer_expired,
	    TP_PROTO(struct rxrpc_call *call),

	    TP_ARGS(call),

	    TP_STRUCT__entry(
		    __field(unsigned int,	call)
			     ),

	    TP_fast_assign(
		    __entry->call		= call->debug_id;
			   ),

	    TP_printk("c=%08x EXPIRED",
		      __entry->call)
	    );

TRACE_EVENT(rxrpc_rx_lose,
@@ -1506,26 +1518,30 @@ TRACE_EVENT(rxrpc_drop_ack,
	    );

TRACE_EVENT(rxrpc_retransmit,
	    TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq, s64 expiry),
	    TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
		     rxrpc_serial_t serial, ktime_t expiry),

	    TP_ARGS(call, seq, expiry),
	    TP_ARGS(call, seq, serial, expiry),

	    TP_STRUCT__entry(
		    __field(unsigned int,	call)
		    __field(rxrpc_seq_t,	seq)
		    __field(s64,		expiry)
		    __field(rxrpc_serial_t,	serial)
		    __field(ktime_t,		expiry)
			     ),

	    TP_fast_assign(
		    __entry->call = call->debug_id;
		    __entry->seq = seq;
		    __entry->serial = serial;
		    __entry->expiry = expiry;
			   ),

	    TP_printk("c=%08x q=%x xp=%lld",
	    TP_printk("c=%08x q=%x r=%x xp=%lld",
		      __entry->call,
		      __entry->seq,
		      __entry->expiry)
		      __entry->serial,
		      ktime_to_us(__entry->expiry))
	    );

TRACE_EVENT(rxrpc_congest,
+6 −6
Original line number Diff line number Diff line
@@ -487,7 +487,7 @@ EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
 * rxrpc_kernel_set_max_life - Set maximum lifespan on a call
 * @sock: The socket the call is on
 * @call: The call to configure
 * @hard_timeout: The maximum lifespan of the call in jiffies
 * @hard_timeout: The maximum lifespan of the call in ms
 *
 * Set the maximum lifespan of a call.  The call will end with ETIME or
 * ETIMEDOUT if it takes longer than this.
@@ -495,14 +495,14 @@ EXPORT_SYMBOL(rxrpc_kernel_new_call_notification);
void rxrpc_kernel_set_max_life(struct socket *sock, struct rxrpc_call *call,
			       unsigned long hard_timeout)
{
	unsigned long now;
	ktime_t delay = ms_to_ktime(hard_timeout), expect_term_by;

	mutex_lock(&call->user_mutex);

	now = jiffies;
	hard_timeout += now;
	WRITE_ONCE(call->expect_term_by, hard_timeout);
	rxrpc_reduce_call_timer(call, hard_timeout, now, rxrpc_timer_set_for_hard);
	expect_term_by = ktime_add(ktime_get_real(), delay);
	WRITE_ONCE(call->expect_term_by, expect_term_by);
	trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_hard);
	rxrpc_poke_call(call, rxrpc_call_poke_set_timeout);

	mutex_unlock(&call->user_mutex);
}
+39 −49
Original line number Diff line number Diff line
@@ -198,8 +198,8 @@ struct rxrpc_host_header {
 * - max 48 bytes (struct sk_buff::cb)
 */
struct rxrpc_skb_priv {
	struct rxrpc_connection *conn;	/* Connection referred to (poke packet) */
	union {
		struct rxrpc_connection *conn;	/* Connection referred to (poke packet) */
		struct {
			u16		offset;		/* Offset of data */
			u16		len;		/* Length of data */
@@ -208,9 +208,12 @@ struct rxrpc_skb_priv {
		};
		struct {
			rxrpc_seq_t	first_ack;	/* First packet in acks table */
			rxrpc_seq_t	prev_ack;	/* Highest seq seen */
			rxrpc_serial_t	acked_serial;	/* Packet in response to (or 0) */
			u8		reason;		/* Reason for ack */
			u8		nr_acks;	/* Number of acks+nacks */
			u8		nr_nacks;	/* Number of nacks */
		};
		} ack;
	};
	struct rxrpc_host_header hdr;	/* RxRPC packet header from this packet */
};
@@ -248,10 +251,9 @@ struct rxrpc_security {
					struct rxrpc_key_token *);

	/* Work out how much data we can store in a packet, given an estimate
	 * of the amount of data remaining.
	 * of the amount of data remaining and allocate a data buffer.
	 */
	int (*how_much_data)(struct rxrpc_call *, size_t,
			     size_t *, size_t *, size_t *);
	struct rxrpc_txbuf *(*alloc_txbuf)(struct rxrpc_call *call, size_t remaining, gfp_t gfp);

	/* impose security on a packet */
	int (*secure_packet)(struct rxrpc_call *, struct rxrpc_txbuf *);
@@ -292,6 +294,7 @@ struct rxrpc_local {
	struct socket		*socket;	/* my UDP socket */
	struct task_struct	*io_thread;
	struct completion	io_thread_ready; /* Indication that the I/O thread started */
	struct page_frag_cache	tx_alloc;	/* Tx control packet allocation (I/O thread only) */
	struct rxrpc_sock	*service;	/* Service(s) listening on this endpoint */
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
	struct sk_buff_head	rx_delay_queue;	/* Delay injection queue */
@@ -352,8 +355,8 @@ struct rxrpc_peer {
	u32			mdev_us;	/* medium deviation			*/
	u32			mdev_max_us;	/* maximal mdev for the last rtt period	*/
	u32			rttvar_us;	/* smoothed mdev_max			*/
	u32			rto_j;		/* Retransmission timeout in jiffies */
	u8			backoff;	/* Backoff timeout */
	u32			rto_us;		/* Retransmission timeout in usec */
	u8			backoff;	/* Backoff timeout (as shift) */

	u8			cong_ssthresh;	/* Congestion slow-start threshold */
};
@@ -500,6 +503,8 @@ struct rxrpc_connection {
	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 */
	struct page_frag_cache	tx_data_alloc;	/* Tx DATA packet allocation */
	struct mutex		tx_data_alloc_lock;

	struct mutex		security_lock;	/* Lock for security management */
	const struct rxrpc_security *security;	/* applied security module */
@@ -618,17 +623,17 @@ struct rxrpc_call {
	const struct rxrpc_security *security;	/* applied security module */
	struct mutex		user_mutex;	/* User access mutex */
	struct sockaddr_rxrpc	dest_srx;	/* Destination address */
	unsigned long		delay_ack_at;	/* When DELAY ACK needs to happen */
	unsigned long		ack_lost_at;	/* When ACK is figured as lost */
	unsigned long		resend_at;	/* When next resend needs to happen */
	unsigned long		ping_at;	/* When next to send a ping */
	unsigned long		keepalive_at;	/* When next to send a keepalive ping */
	unsigned long		expect_rx_by;	/* When we expect to get a packet by */
	unsigned long		expect_req_by;	/* When we expect to get a request DATA packet by */
	unsigned long		expect_term_by;	/* When we expect call termination by */
	u32			next_rx_timo;	/* Timeout for next Rx packet (jif) */
	u32			next_req_timo;	/* Timeout for next Rx request packet (jif) */
	u32			hard_timo;	/* Maximum lifetime or 0 (jif) */
	ktime_t			delay_ack_at;	/* When DELAY ACK needs to happen */
	ktime_t			ack_lost_at;	/* When ACK is figured as lost */
	ktime_t			resend_at;	/* When next resend needs to happen */
	ktime_t			ping_at;	/* When next to send a ping */
	ktime_t			keepalive_at;	/* When next to send a keepalive ping */
	ktime_t			expect_rx_by;	/* When we expect to get a packet by */
	ktime_t			expect_req_by;	/* When we expect to get a request DATA packet by */
	ktime_t			expect_term_by;	/* When we expect call termination by */
	u32			next_rx_timo;	/* Timeout for next Rx packet (ms) */
	u32			next_req_timo;	/* Timeout for next Rx request packet (ms) */
	u32			hard_timo;	/* Maximum lifetime or 0 (s) */
	struct timer_list	timer;		/* Combined event timer */
	struct work_struct	destroyer;	/* In-process-context destroyer */
	rxrpc_notify_rx_t	notify_rx;	/* kernel service Rx notification function */
@@ -673,7 +678,7 @@ struct rxrpc_call {
	rxrpc_seq_t		tx_transmitted;	/* Highest packet transmitted */
	rxrpc_seq_t		tx_prepared;	/* Highest Tx slot prepared. */
	rxrpc_seq_t		tx_top;		/* Highest Tx slot allocated. */
	u16			tx_backoff;	/* Delay to insert due to Tx failure */
	u16			tx_backoff;	/* Delay to insert due to Tx failure (ms) */
	u8			tx_winsize;	/* Maximum size of Tx window */
#define RXRPC_TX_MAX_WINDOW	128
	ktime_t			tx_last_sent;	/* Last time a transmission occurred */
@@ -788,40 +793,30 @@ struct rxrpc_send_params {
 * Buffer of data to be output as a packet.
 */
struct rxrpc_txbuf {
	struct rcu_head		rcu;
	struct list_head	call_link;	/* Link in call->tx_sendmsg/tx_buffer */
	struct list_head	tx_link;	/* Link in live Enc queue or Tx queue */
	ktime_t			last_sent;	/* Time at which last transmitted */
	refcount_t		ref;
	rxrpc_seq_t		seq;		/* Sequence number of this packet */
	rxrpc_serial_t		serial;		/* Last serial number transmitted with */
	unsigned int		call_debug_id;
	unsigned int		debug_id;
	unsigned int		len;		/* Amount of data in buffer */
	unsigned int		space;		/* Remaining data space */
	unsigned int		offset;		/* Offset of fill point */
	unsigned long		flags;
#define RXRPC_TXBUF_LAST	0		/* Set if last packet in Tx phase */
#define RXRPC_TXBUF_RESENT	1		/* Set if has been resent */
	unsigned int		flags;
#define RXRPC_TXBUF_WIRE_FLAGS	0xff		/* The wire protocol flags */
#define RXRPC_TXBUF_RESENT	0x100		/* Set if has been resent */
	__be16			cksum;		/* Checksum to go in header */
	unsigned short		ack_rwind;	/* ACK receive window */
	u8 /*enum rxrpc_propose_ack_trace*/ ack_why;	/* If ack, why */
	struct {
		/* The packet for encrypting and DMA'ing.  We align it such
		 * that data[] aligns correctly for any crypto blocksize.
		 */
		u8		pad[64 - sizeof(struct rxrpc_wire_header)];
		struct rxrpc_wire_header wire;	/* Network-ready header */
		union {
			u8	data[RXRPC_JUMBO_DATALEN]; /* Data packet */
			struct {
				struct rxrpc_ackpacket ack;
				DECLARE_FLEX_ARRAY(u8, acks);
			};
		};
	} __aligned(64);
	u8			nr_kvec;	/* Amount of kvec[] used */
	struct kvec		kvec[3];
};

static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb)
{
	return txb->wire.flags & RXRPC_CLIENT_INITIATED;
	return txb->flags & RXRPC_CLIENT_INITIATED;
}

static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb)
@@ -869,17 +864,11 @@ int rxrpc_user_charge_accept(struct rxrpc_sock *, unsigned long);
 */
void rxrpc_propose_ping(struct rxrpc_call *call, u32 serial,
			enum rxrpc_propose_ack_trace why);
void rxrpc_send_ACK(struct rxrpc_call *, u8, rxrpc_serial_t, enum rxrpc_propose_ack_trace);
void rxrpc_propose_delay_ACK(struct rxrpc_call *, rxrpc_serial_t,
			     enum rxrpc_propose_ack_trace);
void rxrpc_shrink_call_tx_buffer(struct rxrpc_call *);
void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb);

void rxrpc_reduce_call_timer(struct rxrpc_call *call,
			     unsigned long expire_at,
			     unsigned long now,
			     enum rxrpc_timer_trace why);

bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb);

/*
@@ -1160,9 +1149,9 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
/*
 * output.c
 */
int rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb);
void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
		    rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why);
int rxrpc_send_abort_packet(struct rxrpc_call *);
int rxrpc_send_data_packet(struct rxrpc_call *, struct rxrpc_txbuf *);
void rxrpc_send_conn_abort(struct rxrpc_connection *conn);
void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb);
void rxrpc_send_keepalive(struct rxrpc_peer *);
@@ -1223,7 +1212,7 @@ static inline int rxrpc_abort_eproto(struct rxrpc_call *call,
 */
void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace, int,
			rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
unsigned long rxrpc_get_rto_backoff(struct rxrpc_peer *, bool);
ktime_t rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans);
void rxrpc_peer_init_rtt(struct rxrpc_peer *);

/*
@@ -1295,8 +1284,9 @@ static inline void rxrpc_sysctl_exit(void) {}
 * txbuf.c
 */
extern atomic_t rxrpc_nr_txbuf;
struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type,
				      gfp_t gfp);
struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size,
					   size_t data_align, gfp_t gfp);
struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t sack_size);
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
+143 −184

File changed.

Preview size limit exceeded, changes collapsed.

+25 −31
Original line number Diff line number Diff line
@@ -70,20 +70,11 @@ static void rxrpc_call_timer_expired(struct timer_list *t)
	_enter("%d", call->debug_id);

	if (!__rxrpc_call_is_complete(call)) {
		trace_rxrpc_timer_expired(call, jiffies);
		trace_rxrpc_timer_expired(call);
		rxrpc_poke_call(call, rxrpc_call_poke_timer);
	}
}

void rxrpc_reduce_call_timer(struct rxrpc_call *call,
			     unsigned long expire_at,
			     unsigned long now,
			     enum rxrpc_timer_trace why)
{
	trace_rxrpc_timer(call, why, now);
	timer_reduce(&call->timer, expire_at);
}

static struct lock_class_key rxrpc_call_user_mutex_lock_class_key;

static void rxrpc_destroy_call(struct work_struct *);
@@ -169,6 +160,14 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
	call->next_req_timo	= 1 * HZ;
	call->ackr_window	= 1;
	call->ackr_wtop		= 1;
	call->delay_ack_at	= KTIME_MAX;
	call->ack_lost_at	= KTIME_MAX;
	call->resend_at		= KTIME_MAX;
	call->ping_at		= KTIME_MAX;
	call->keepalive_at	= KTIME_MAX;
	call->expect_rx_by	= KTIME_MAX;
	call->expect_req_by	= KTIME_MAX;
	call->expect_term_by	= KTIME_MAX;

	memset(&call->sock_node, 0xed, sizeof(call->sock_node));

@@ -226,11 +225,11 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
		__set_bit(RXRPC_CALL_EXCLUSIVE, &call->flags);

	if (p->timeouts.normal)
		call->next_rx_timo = min(msecs_to_jiffies(p->timeouts.normal), 1UL);
		call->next_rx_timo = min(p->timeouts.normal, 1);
	if (p->timeouts.idle)
		call->next_req_timo = min(msecs_to_jiffies(p->timeouts.idle), 1UL);
		call->next_req_timo = min(p->timeouts.idle, 1);
	if (p->timeouts.hard)
		call->hard_timo = p->timeouts.hard * HZ;
		call->hard_timo = p->timeouts.hard;

	ret = rxrpc_init_client_call_security(call);
	if (ret < 0) {
@@ -253,18 +252,13 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
 */
void rxrpc_start_call_timer(struct rxrpc_call *call)
{
	unsigned long now = jiffies;
	unsigned long j = now + MAX_JIFFY_OFFSET;

	call->delay_ack_at = j;
	call->ack_lost_at = j;
	call->resend_at = j;
	call->ping_at = j;
	call->keepalive_at = j;
	call->expect_rx_by = j;
	call->expect_req_by = j;
	call->expect_term_by = j + call->hard_timo;
	call->timer.expires = now;
	if (call->hard_timo) {
		ktime_t delay = ms_to_ktime(call->hard_timo * 1000);

		call->expect_term_by = ktime_add(ktime_get_real(), delay);
		trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_hard);
	}
	call->timer.expires = jiffies;
}

/*
Loading