rxrpc: Add per-peer RTT tracker
authorDavid Howells <dhowells@redhat.com>
Wed, 21 Sep 2016 23:41:53 +0000 (00:41 +0100)
committerDavid Howells <dhowells@redhat.com>
Thu, 22 Sep 2016 00:26:25 +0000 (01:26 +0100)
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>
include/trace/events/rxrpc.h
net/rxrpc/ar-internal.h
net/rxrpc/misc.c
net/rxrpc/peer_event.c

index 75a5d8bf50e16c3914772d852d03d3c8ba0e931c..e8f2afbbe0bfaf407c8097615a59035d18720359 100644 (file)
@@ -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 */
index dcf54e3fb478c491b459bc35ecf737bfc47cee83..79c671e552c3016ddd413cd0c69b9d5c89b114fa 100644 (file)
@@ -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
index 026e1f2e83ffc51ab8303161d52152dd208f568c..6321c23f9a6e6b8aea33737befbdf9a439241c05 100644 (file)
@@ -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",
+};
index 18276e7cb9e050ae2f176fe0c388378c7a997076..bf13b8470c9ad51783325d7f47c32414b07f0c40 100644 (file)
@@ -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);
+}