mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-25 13:14:07 +08:00
rxrpc: Obtain RTT data by requesting ACKs on DATA packets
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 <dhowells@redhat.com>
This commit is contained in:
parent
77f2efcbdd
commit
50235c4b5a
@ -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 int offset; /* 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
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -355,6 +355,38 @@ ack:
|
||||
_leave(" [queued]");
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a requested ACK.
|
||||
*/
|
||||
static void rxrpc_input_requested_ack(struct rxrpc_call *call,
|
||||
ktime_t resp_time,
|
||||
rxrpc_serial_t orig_serial,
|
||||
rxrpc_serial_t ack_serial)
|
||||
{
|
||||
struct rxrpc_skb_priv *sp;
|
||||
struct sk_buff *skb;
|
||||
ktime_t sent_at;
|
||||
int ix;
|
||||
|
||||
for (ix = 0; ix < RXRPC_RXTX_BUFF_SIZE; ix++) {
|
||||
skb = call->rxtx_buffer[ix];
|
||||
if (!skb)
|
||||
continue;
|
||||
|
||||
sp = rxrpc_skb(skb);
|
||||
if (sp->hdr.serial != orig_serial)
|
||||
continue;
|
||||
smp_rmb();
|
||||
sent_at = skb->tstamp;
|
||||
goto found;
|
||||
}
|
||||
return;
|
||||
|
||||
found:
|
||||
rxrpc_peer_add_rtt(call, rxrpc_rtt_rx_requested_ack,
|
||||
orig_serial, ack_serial, sent_at, resp_time);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a ping response.
|
||||
*/
|
||||
@ -508,6 +540,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb,
|
||||
if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
|
||||
rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
|
||||
sp->hdr.serial);
|
||||
if (buf.ack.reason == RXRPC_ACK_REQUESTED)
|
||||
rxrpc_input_requested_ack(call, skb->tstamp, acked_serial,
|
||||
sp->hdr.serial);
|
||||
|
||||
if (buf.ack.reason == RXRPC_ACK_PING) {
|
||||
_proto("Rx ACK %%%u PING Request", sp->hdr.serial);
|
||||
|
@ -68,9 +68,9 @@ unsigned int rxrpc_rx_mtu = 5692;
|
||||
unsigned int rxrpc_rx_jumbo_max = 4;
|
||||
|
||||
/*
|
||||
* Time till packet resend (in jiffies).
|
||||
* Time till packet resend (in milliseconds).
|
||||
*/
|
||||
unsigned int rxrpc_resend_timeout = 4 * HZ;
|
||||
unsigned int rxrpc_resend_timeout = 4 * 1000;
|
||||
|
||||
const char *const rxrpc_pkts[] = {
|
||||
"?00",
|
||||
@ -186,8 +186,10 @@ const char rxrpc_recvmsg_traces[rxrpc_recvmsg__nr_trace][5] = {
|
||||
|
||||
const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = {
|
||||
[rxrpc_rtt_tx_ping] = "PING",
|
||||
[rxrpc_rtt_tx_data] = "DATA",
|
||||
};
|
||||
|
||||
const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = {
|
||||
[rxrpc_rtt_rx_ping_response] = "PONG",
|
||||
[rxrpc_rtt_rx_requested_ack] = "RACK",
|
||||
};
|
||||
|
@ -300,9 +300,12 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb)
|
||||
goto send_fragmentable;
|
||||
|
||||
done:
|
||||
if (ret == 0) {
|
||||
sp->resend_at = jiffies + rxrpc_resend_timeout;
|
||||
if (ret >= 0) {
|
||||
skb->tstamp = ktime_get_real();
|
||||
smp_wmb();
|
||||
sp->hdr.serial = serial;
|
||||
if (whdr.flags & RXRPC_REQUEST_ACK)
|
||||
trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, serial);
|
||||
}
|
||||
_leave(" = %d [%u]", ret, call->peer->maxdata);
|
||||
return ret;
|
||||
|
@ -137,7 +137,6 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
|
||||
if (seq == 1 && rxrpc_is_client_call(call))
|
||||
rxrpc_expose_client_call(call);
|
||||
|
||||
sp->resend_at = jiffies + rxrpc_resend_timeout;
|
||||
ret = rxrpc_send_data_packet(call, skb);
|
||||
if (ret < 0) {
|
||||
_debug("need instant resend %d", ret);
|
||||
|
@ -59,7 +59,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
||||
.data = &rxrpc_resend_timeout,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_ms_jiffies,
|
||||
.proc_handler = proc_dointvec,
|
||||
.extra1 = (void *)&one,
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user