mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	rxrpc: Add per-peer RTT tracker
Add a function to track the average RTT for a peer. Sources of RTT data will be added in subsequent patches. The RTT data will be useful in the future for determining resend timeouts and for handling the slow-start part of the Rx protocol. Also add a pair of tracepoints, one to log transmissions to elicit a response for RTT purposes and one to log responses that contribute RTT data. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
		
							parent
							
								
									f07373ead4
								
							
						
					
					
						commit
						cf1a6474f8
					
				
					 4 changed files with 131 additions and 4 deletions
				
			
		| 
						 | 
					@ -353,6 +353,67 @@ TRACE_EVENT(rxrpc_recvmsg,
 | 
				
			||||||
		      __entry->ret)
 | 
							      __entry->ret)
 | 
				
			||||||
	    );
 | 
						    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRACE_EVENT(rxrpc_rtt_tx,
 | 
				
			||||||
 | 
						    TP_PROTO(struct rxrpc_call *call, enum rxrpc_rtt_tx_trace why,
 | 
				
			||||||
 | 
							     rxrpc_serial_t send_serial),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_ARGS(call, why, send_serial),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_STRUCT__entry(
 | 
				
			||||||
 | 
							    __field(struct rxrpc_call *,	call		)
 | 
				
			||||||
 | 
							    __field(enum rxrpc_rtt_tx_trace,	why		)
 | 
				
			||||||
 | 
							    __field(rxrpc_serial_t,		send_serial	)
 | 
				
			||||||
 | 
								     ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_fast_assign(
 | 
				
			||||||
 | 
							    __entry->call = call;
 | 
				
			||||||
 | 
							    __entry->why = why;
 | 
				
			||||||
 | 
							    __entry->send_serial = send_serial;
 | 
				
			||||||
 | 
								   ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_printk("c=%p %s sr=%08x",
 | 
				
			||||||
 | 
							      __entry->call,
 | 
				
			||||||
 | 
							      rxrpc_rtt_tx_traces[__entry->why],
 | 
				
			||||||
 | 
							      __entry->send_serial)
 | 
				
			||||||
 | 
						    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRACE_EVENT(rxrpc_rtt_rx,
 | 
				
			||||||
 | 
						    TP_PROTO(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
 | 
				
			||||||
 | 
							     rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
 | 
				
			||||||
 | 
							     s64 rtt, u8 nr, s64 avg),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_ARGS(call, why, send_serial, resp_serial, rtt, nr, avg),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_STRUCT__entry(
 | 
				
			||||||
 | 
							    __field(struct rxrpc_call *,	call		)
 | 
				
			||||||
 | 
							    __field(enum rxrpc_rtt_rx_trace,	why		)
 | 
				
			||||||
 | 
							    __field(u8,				nr		)
 | 
				
			||||||
 | 
							    __field(rxrpc_serial_t,		send_serial	)
 | 
				
			||||||
 | 
							    __field(rxrpc_serial_t,		resp_serial	)
 | 
				
			||||||
 | 
							    __field(s64,			rtt		)
 | 
				
			||||||
 | 
							    __field(u64,			avg		)
 | 
				
			||||||
 | 
								     ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_fast_assign(
 | 
				
			||||||
 | 
							    __entry->call = call;
 | 
				
			||||||
 | 
							    __entry->why = why;
 | 
				
			||||||
 | 
							    __entry->send_serial = send_serial;
 | 
				
			||||||
 | 
							    __entry->resp_serial = resp_serial;
 | 
				
			||||||
 | 
							    __entry->rtt = rtt;
 | 
				
			||||||
 | 
							    __entry->nr = nr;
 | 
				
			||||||
 | 
							    __entry->avg = avg;
 | 
				
			||||||
 | 
								   ),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    TP_printk("c=%p %s sr=%08x rr=%08x rtt=%lld nr=%u avg=%lld",
 | 
				
			||||||
 | 
							      __entry->call,
 | 
				
			||||||
 | 
							      rxrpc_rtt_rx_traces[__entry->why],
 | 
				
			||||||
 | 
							      __entry->send_serial,
 | 
				
			||||||
 | 
							      __entry->resp_serial,
 | 
				
			||||||
 | 
							      __entry->rtt,
 | 
				
			||||||
 | 
							      __entry->nr,
 | 
				
			||||||
 | 
							      __entry->avg)
 | 
				
			||||||
 | 
						    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* _TRACE_RXRPC_H */
 | 
					#endif /* _TRACE_RXRPC_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This part must be outside protection */
 | 
					/* This part must be outside protection */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,10 +258,11 @@ struct rxrpc_peer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* calculated RTT cache */
 | 
						/* calculated RTT cache */
 | 
				
			||||||
#define RXRPC_RTT_CACHE_SIZE 32
 | 
					#define RXRPC_RTT_CACHE_SIZE 32
 | 
				
			||||||
	suseconds_t		rtt;		/* current RTT estimate (in uS) */
 | 
						u64			rtt;		/* Current RTT estimate (in nS) */
 | 
				
			||||||
	unsigned int		rtt_point;	/* next entry at which to insert */
 | 
						u64			rtt_sum;	/* Sum of cache contents */
 | 
				
			||||||
	unsigned int		rtt_usage;	/* amount of cache actually used */
 | 
						u64			rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* Determined RTT cache */
 | 
				
			||||||
	suseconds_t		rtt_cache[RXRPC_RTT_CACHE_SIZE]; /* calculated RTT cache */
 | 
						u8			rtt_cursor;	/* next entry at which to insert */
 | 
				
			||||||
 | 
						u8			rtt_usage;	/* amount of cache actually used */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					@ -657,6 +658,20 @@ enum rxrpc_recvmsg_trace {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
 | 
					extern const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum rxrpc_rtt_tx_trace {
 | 
				
			||||||
 | 
						rxrpc_rtt_tx_ping,
 | 
				
			||||||
 | 
						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__nr_trace
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern const char *const rxrpc_pkts[];
 | 
					extern const char *const rxrpc_pkts[];
 | 
				
			||||||
extern const char *rxrpc_acks(u8 reason);
 | 
					extern const char *rxrpc_acks(u8 reason);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -955,6 +970,8 @@ void rxrpc_reject_packets(struct rxrpc_local *);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void rxrpc_error_report(struct sock *);
 | 
					void rxrpc_error_report(struct sock *);
 | 
				
			||||||
void rxrpc_peer_error_distributor(struct work_struct *);
 | 
					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
 | 
					 * peer_object.c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -182,3 +182,11 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = {
 | 
				
			||||||
	[rxrpc_recvmsg_to_be_accepted]	= "TBAC",
 | 
						[rxrpc_recvmsg_to_be_accepted]	= "TBAC",
 | 
				
			||||||
	[rxrpc_recvmsg_return]		= "RETN",
 | 
						[rxrpc_recvmsg_return]		= "RETN",
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = {
 | 
				
			||||||
 | 
						[rxrpc_rtt_tx_ping]		= "PING",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = {
 | 
				
			||||||
 | 
						[rxrpc_rtt_rx_ping_response]	= "PONG",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,3 +305,44 @@ void rxrpc_peer_error_distributor(struct work_struct *work)
 | 
				
			||||||
	rxrpc_put_peer(peer);
 | 
						rxrpc_put_peer(peer);
 | 
				
			||||||
	_leave("");
 | 
						_leave("");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Add RTT information to cache.  This is called in softirq mode and has
 | 
				
			||||||
 | 
					 * exclusive access to the peer RTT data.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
 | 
				
			||||||
 | 
								rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
 | 
				
			||||||
 | 
								ktime_t send_time, ktime_t resp_time)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct rxrpc_peer *peer = call->peer;
 | 
				
			||||||
 | 
						s64 rtt;
 | 
				
			||||||
 | 
						u64 sum = peer->rtt_sum, avg;
 | 
				
			||||||
 | 
						u8 cursor = peer->rtt_cursor, usage = peer->rtt_usage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rtt = ktime_to_ns(ktime_sub(resp_time, send_time));
 | 
				
			||||||
 | 
						if (rtt < 0)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Replace the oldest datum in the RTT buffer */
 | 
				
			||||||
 | 
						sum -= peer->rtt_cache[cursor];
 | 
				
			||||||
 | 
						sum += rtt;
 | 
				
			||||||
 | 
						peer->rtt_cache[cursor] = rtt;
 | 
				
			||||||
 | 
						peer->rtt_cursor = (cursor + 1) & (RXRPC_RTT_CACHE_SIZE - 1);
 | 
				
			||||||
 | 
						peer->rtt_sum = sum;
 | 
				
			||||||
 | 
						if (usage < RXRPC_RTT_CACHE_SIZE) {
 | 
				
			||||||
 | 
							usage++;
 | 
				
			||||||
 | 
							peer->rtt_usage = usage;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Now recalculate the average */
 | 
				
			||||||
 | 
						if (usage == RXRPC_RTT_CACHE_SIZE) {
 | 
				
			||||||
 | 
							avg = sum / RXRPC_RTT_CACHE_SIZE;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							avg = sum;
 | 
				
			||||||
 | 
							do_div(avg, usage);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						peer->rtt = avg;
 | 
				
			||||||
 | 
						trace_rxrpc_rtt_rx(call, why, send_serial, resp_serial, rtt,
 | 
				
			||||||
 | 
								   usage, avg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue