[PATCH net-next 7/9] rxrpc: Obtain RTT data by requesting ACKs on DATA packets [ver #2]

2016-09-22 Thread David Howells
In addition to sending a PING ACK to gain RTT data, we can set the
RXRPC_REQUEST_ACK flag on a DATA packet and get a REQUESTED-ACK ACK.  The
ACK packet contains the serial number of the packet it is in response to,
so we can look through the Tx buffer for a matching DATA packet.

This requires that the data packets be stamped with the time of
transmission as a ktime rather than having the resend_at time in jiffies.

This further requires the resend code to do the resend determination in
ktimes and convert to jiffies to set the timer.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +++
 net/rxrpc/call_event.c  |   19 +--
 net/rxrpc/input.c   |   35 +++
 net/rxrpc/misc.c|6 --
 net/rxrpc/output.c  |7 +--
 net/rxrpc/sendmsg.c |1 -
 net/rxrpc/sysctl.c  |2 +-
 7 files changed, 57 insertions(+), 20 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 8b47f468eb9d..1c4597b2c6cd 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -142,10 +142,7 @@ struct rxrpc_host_header {
  */
 struct rxrpc_skb_priv {
union {
-   unsigned long   resend_at;  /* time in jiffies at which to 
resend */
-   struct {
-   u8  nr_jumbo;   /* Number of jumbo subpackets */
-   };
+   u8  nr_jumbo;   /* Number of jumbo subpackets */
};
union {
unsigned intoffset; /* offset into buffer of next 
read */
@@ -663,6 +660,7 @@ extern const char 
rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
 
 enum rxrpc_rtt_tx_trace {
rxrpc_rtt_tx_ping,
+   rxrpc_rtt_tx_data,
rxrpc_rtt_tx__nr_trace
 };
 
@@ -670,6 +668,7 @@ 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_requested_ack,
rxrpc_rtt_rx__nr_trace
 };
 
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 34ad967f2d81..adb2ec61e21f 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -142,12 +142,14 @@ static void rxrpc_resend(struct rxrpc_call *call)
struct rxrpc_skb_priv *sp;
struct sk_buff *skb;
rxrpc_seq_t cursor, seq, top;
-   unsigned long resend_at, now;
+   ktime_t now = ktime_get_real(), max_age, oldest, resend_at;
int ix;
u8 annotation, anno_type;
 
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
 
+   max_age = ktime_sub_ms(now, rxrpc_resend_timeout);
+
spin_lock_bh(&call->lock);
 
cursor = call->tx_hard_ack;
@@ -160,8 +162,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
 * the packets in the Tx buffer we're going to resend and what the new
 * resend timeout will be.
 */
-   now = jiffies;
-   resend_at = now + rxrpc_resend_timeout;
+   oldest = now;
for (seq = cursor + 1; before_eq(seq, top); seq++) {
ix = seq & RXRPC_RXTX_BUFF_MASK;
annotation = call->rxtx_annotations[ix];
@@ -175,9 +176,9 @@ static void rxrpc_resend(struct rxrpc_call *call)
sp = rxrpc_skb(skb);
 
if (anno_type == RXRPC_TX_ANNO_UNACK) {
-   if (time_after(sp->resend_at, now)) {
-   if (time_before(sp->resend_at, resend_at))
-   resend_at = sp->resend_at;
+   if (ktime_after(skb->tstamp, max_age)) {
+   if (ktime_before(skb->tstamp, oldest))
+   oldest = skb->tstamp;
continue;
}
}
@@ -186,7 +187,8 @@ static void rxrpc_resend(struct rxrpc_call *call)
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
}
 
-   call->resend_at = resend_at;
+   resend_at = ktime_sub(ktime_add_ns(oldest, rxrpc_resend_timeout), now);
+   call->resend_at = jiffies + nsecs_to_jiffies(ktime_to_ns(resend_at));
 
/* Now go through the Tx window and perform the retransmissions.  We
 * have to drop the lock for each send.  If an ACK comes in whilst the
@@ -205,15 +207,12 @@ static void rxrpc_resend(struct rxrpc_call *call)
spin_unlock_bh(&call->lock);
 
if (rxrpc_send_data_packet(call, skb) < 0) {
-   call->resend_at = now + 2;
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
return;
}
 
if (rxrpc_is_client_call(call))
rxrpc_expose_client_call(call);
-   sp = rxrpc_skb(skb);
-   sp->resend_at = now + rxrpc_resend_timeout;
 
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
spin_lock_bh(&call->lock)

[PATCH net-next 7/9] rxrpc: Obtain RTT data by requesting ACKs on DATA packets

2016-09-21 Thread David Howells
In addition to sending a PING ACK to gain RTT data, we can set the
RXRPC_REQUEST_ACK flag on a DATA packet and get a REQUESTED-ACK ACK.  The
ACK packet contains the serial number of the packet it is in response to,
so we can look through the Tx buffer for a matching DATA packet.

This requires that the data packets be stamped with the time of
transmission as a ktime rather than having the resend_at time in jiffies.

This further requires the resend code to do the resend determination in
ktimes and convert to jiffies to set the timer.

Signed-off-by: David Howells 
---

 net/rxrpc/ar-internal.h |7 +++
 net/rxrpc/call_event.c  |   20 ++--
 net/rxrpc/input.c   |   35 +++
 net/rxrpc/misc.c|6 --
 net/rxrpc/output.c  |7 +--
 net/rxrpc/sendmsg.c |1 -
 net/rxrpc/sysctl.c  |2 +-
 7 files changed, 58 insertions(+), 20 deletions(-)

diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 8b47f468eb9d..1c4597b2c6cd 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -142,10 +142,7 @@ struct rxrpc_host_header {
  */
 struct rxrpc_skb_priv {
union {
-   unsigned long   resend_at;  /* time in jiffies at which to 
resend */
-   struct {
-   u8  nr_jumbo;   /* Number of jumbo subpackets */
-   };
+   u8  nr_jumbo;   /* Number of jumbo subpackets */
};
union {
unsigned intoffset; /* offset into buffer of next 
read */
@@ -663,6 +660,7 @@ extern const char 
rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5];
 
 enum rxrpc_rtt_tx_trace {
rxrpc_rtt_tx_ping,
+   rxrpc_rtt_tx_data,
rxrpc_rtt_tx__nr_trace
 };
 
@@ -670,6 +668,7 @@ 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_requested_ack,
rxrpc_rtt_rx__nr_trace
 };
 
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 34ad967f2d81..77802da14456 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -142,12 +142,14 @@ static void rxrpc_resend(struct rxrpc_call *call)
struct rxrpc_skb_priv *sp;
struct sk_buff *skb;
rxrpc_seq_t cursor, seq, top;
-   unsigned long resend_at, now;
+   ktime_t now = ktime_get_real(), max_age, oldest, resend_at;
int ix;
u8 annotation, anno_type;
 
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
 
+   max_age = ktime_sub_ms(now, rxrpc_resend_timeout);
+
spin_lock_bh(&call->lock);
 
cursor = call->tx_hard_ack;
@@ -160,8 +162,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
 * the packets in the Tx buffer we're going to resend and what the new
 * resend timeout will be.
 */
-   now = jiffies;
-   resend_at = now + rxrpc_resend_timeout;
+   oldest = now;
for (seq = cursor + 1; before_eq(seq, top); seq++) {
ix = seq & RXRPC_RXTX_BUFF_MASK;
annotation = call->rxtx_annotations[ix];
@@ -175,9 +176,9 @@ static void rxrpc_resend(struct rxrpc_call *call)
sp = rxrpc_skb(skb);
 
if (anno_type == RXRPC_TX_ANNO_UNACK) {
-   if (time_after(sp->resend_at, now)) {
-   if (time_before(sp->resend_at, resend_at))
-   resend_at = sp->resend_at;
+   if (ktime_after(skb->tstamp, max_age)) {
+   if (ktime_before(skb->tstamp, oldest))
+   oldest = skb->tstamp;
continue;
}
}
@@ -186,7 +187,9 @@ static void rxrpc_resend(struct rxrpc_call *call)
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
}
 
-   call->resend_at = resend_at;
+   resend_at = ktime_sub(ktime_add_ns(oldest, rxrpc_resend_timeout), now);
+   call->resend_at = jiffies +
+   usecs_to_jiffies(ktime_to_ns(resend_at) / NSEC_PER_USEC);
 
/* Now go through the Tx window and perform the retransmissions.  We
 * have to drop the lock for each send.  If an ACK comes in whilst the
@@ -205,15 +208,12 @@ static void rxrpc_resend(struct rxrpc_call *call)
spin_unlock_bh(&call->lock);
 
if (rxrpc_send_data_packet(call, skb) < 0) {
-   call->resend_at = now + 2;
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
return;
}
 
if (rxrpc_is_client_call(call))
rxrpc_expose_client_call(call);
-   sp = rxrpc_skb(skb);
-   sp->resend_at = now + rxrpc_resend_timeout;
 
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);