mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-26 14:14:01 +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 {
|
struct rxrpc_skb_priv {
|
||||||
union {
|
union {
|
||||||
unsigned long resend_at; /* time in jiffies at which to resend */
|
u8 nr_jumbo; /* Number of jumbo subpackets */
|
||||||
struct {
|
|
||||||
u8 nr_jumbo; /* Number of jumbo subpackets */
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
union {
|
union {
|
||||||
unsigned int offset; /* offset into buffer of next read */
|
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 {
|
enum rxrpc_rtt_tx_trace {
|
||||||
rxrpc_rtt_tx_ping,
|
rxrpc_rtt_tx_ping,
|
||||||
|
rxrpc_rtt_tx_data,
|
||||||
rxrpc_rtt_tx__nr_trace
|
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 {
|
enum rxrpc_rtt_rx_trace {
|
||||||
rxrpc_rtt_rx_ping_response,
|
rxrpc_rtt_rx_ping_response,
|
||||||
|
rxrpc_rtt_rx_requested_ack,
|
||||||
rxrpc_rtt_rx__nr_trace
|
rxrpc_rtt_rx__nr_trace
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,12 +142,14 @@ static void rxrpc_resend(struct rxrpc_call *call)
|
|||||||
struct rxrpc_skb_priv *sp;
|
struct rxrpc_skb_priv *sp;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
rxrpc_seq_t cursor, seq, top;
|
rxrpc_seq_t cursor, seq, top;
|
||||||
unsigned long resend_at, now;
|
ktime_t now = ktime_get_real(), max_age, oldest, resend_at;
|
||||||
int ix;
|
int ix;
|
||||||
u8 annotation, anno_type;
|
u8 annotation, anno_type;
|
||||||
|
|
||||||
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
|
_enter("{%d,%d}", call->tx_hard_ack, call->tx_top);
|
||||||
|
|
||||||
|
max_age = ktime_sub_ms(now, rxrpc_resend_timeout);
|
||||||
|
|
||||||
spin_lock_bh(&call->lock);
|
spin_lock_bh(&call->lock);
|
||||||
|
|
||||||
cursor = call->tx_hard_ack;
|
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
|
* the packets in the Tx buffer we're going to resend and what the new
|
||||||
* resend timeout will be.
|
* resend timeout will be.
|
||||||
*/
|
*/
|
||||||
now = jiffies;
|
oldest = now;
|
||||||
resend_at = now + rxrpc_resend_timeout;
|
|
||||||
for (seq = cursor + 1; before_eq(seq, top); seq++) {
|
for (seq = cursor + 1; before_eq(seq, top); seq++) {
|
||||||
ix = seq & RXRPC_RXTX_BUFF_MASK;
|
ix = seq & RXRPC_RXTX_BUFF_MASK;
|
||||||
annotation = call->rxtx_annotations[ix];
|
annotation = call->rxtx_annotations[ix];
|
||||||
@ -175,9 +176,9 @@ static void rxrpc_resend(struct rxrpc_call *call)
|
|||||||
sp = rxrpc_skb(skb);
|
sp = rxrpc_skb(skb);
|
||||||
|
|
||||||
if (anno_type == RXRPC_TX_ANNO_UNACK) {
|
if (anno_type == RXRPC_TX_ANNO_UNACK) {
|
||||||
if (time_after(sp->resend_at, now)) {
|
if (ktime_after(skb->tstamp, max_age)) {
|
||||||
if (time_before(sp->resend_at, resend_at))
|
if (ktime_before(skb->tstamp, oldest))
|
||||||
resend_at = sp->resend_at;
|
oldest = skb->tstamp;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -186,7 +187,8 @@ static void rxrpc_resend(struct rxrpc_call *call)
|
|||||||
call->rxtx_annotations[ix] = RXRPC_TX_ANNO_RETRANS | annotation;
|
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
|
/* 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
|
* 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);
|
spin_unlock_bh(&call->lock);
|
||||||
|
|
||||||
if (rxrpc_send_data_packet(call, skb) < 0) {
|
if (rxrpc_send_data_packet(call, skb) < 0) {
|
||||||
call->resend_at = now + 2;
|
|
||||||
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rxrpc_is_client_call(call))
|
if (rxrpc_is_client_call(call))
|
||||||
rxrpc_expose_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);
|
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
|
||||||
spin_lock_bh(&call->lock);
|
spin_lock_bh(&call->lock);
|
||||||
|
@ -355,6 +355,38 @@ ack:
|
|||||||
_leave(" [queued]");
|
_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.
|
* 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)
|
if (buf.ack.reason == RXRPC_ACK_PING_RESPONSE)
|
||||||
rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
|
rxrpc_input_ping_response(call, skb->tstamp, acked_serial,
|
||||||
sp->hdr.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) {
|
if (buf.ack.reason == RXRPC_ACK_PING) {
|
||||||
_proto("Rx ACK %%%u PING Request", sp->hdr.serial);
|
_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;
|
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[] = {
|
const char *const rxrpc_pkts[] = {
|
||||||
"?00",
|
"?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] = {
|
const char rxrpc_rtt_tx_traces[rxrpc_rtt_tx__nr_trace][5] = {
|
||||||
[rxrpc_rtt_tx_ping] = "PING",
|
[rxrpc_rtt_tx_ping] = "PING",
|
||||||
|
[rxrpc_rtt_tx_data] = "DATA",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = {
|
const char rxrpc_rtt_rx_traces[rxrpc_rtt_rx__nr_trace][5] = {
|
||||||
[rxrpc_rtt_rx_ping_response] = "PONG",
|
[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;
|
goto send_fragmentable;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (ret == 0) {
|
if (ret >= 0) {
|
||||||
sp->resend_at = jiffies + rxrpc_resend_timeout;
|
skb->tstamp = ktime_get_real();
|
||||||
|
smp_wmb();
|
||||||
sp->hdr.serial = serial;
|
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);
|
_leave(" = %d [%u]", ret, call->peer->maxdata);
|
||||||
return ret;
|
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))
|
if (seq == 1 && rxrpc_is_client_call(call))
|
||||||
rxrpc_expose_client_call(call);
|
rxrpc_expose_client_call(call);
|
||||||
|
|
||||||
sp->resend_at = jiffies + rxrpc_resend_timeout;
|
|
||||||
ret = rxrpc_send_data_packet(call, skb);
|
ret = rxrpc_send_data_packet(call, skb);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
_debug("need instant resend %d", ret);
|
_debug("need instant resend %d", ret);
|
||||||
|
@ -59,7 +59,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
|||||||
.data = &rxrpc_resend_timeout,
|
.data = &rxrpc_resend_timeout,
|
||||||
.maxlen = sizeof(unsigned int),
|
.maxlen = sizeof(unsigned int),
|
||||||
.mode = 0644,
|
.mode = 0644,
|
||||||
.proc_handler = proc_dointvec_ms_jiffies,
|
.proc_handler = proc_dointvec,
|
||||||
.extra1 = (void *)&one,
|
.extra1 = (void *)&one,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user