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
					
				| @ -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 New Issue
	
	Block a user