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) | ||||
| 	    ); | ||||
| 
 | ||||
| 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 */ | ||||
| 
 | ||||
| /* This part must be outside protection */ | ||||
|  | ||||
| @ -258,10 +258,11 @@ 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 */ | ||||
| 	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 */ | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
| @ -657,6 +658,20 @@ enum rxrpc_recvmsg_trace { | ||||
| 
 | ||||
| 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 *rxrpc_acks(u8 reason); | ||||
| 
 | ||||
| @ -955,6 +970,8 @@ void rxrpc_reject_packets(struct rxrpc_local *); | ||||
|  */ | ||||
| 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 | ||||
|  | ||||
| @ -182,3 +182,11 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = { | ||||
| 	[rxrpc_recvmsg_to_be_accepted]	= "TBAC", | ||||
| 	[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); | ||||
| 	_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