Commit 805b21b9 authored by David Howells's avatar David Howells

rxrpc: Send an ACK after every few DATA packets we receive

Send an ACK if we haven't sent one for the last two packets we've received.
This keeps the other end apprised of where we've got to - which is
important if they're doing slow-start.

We do this in recvmsg so that we can dispatch a packet directly without the
need to wake up the background thread.

This should possibly be made configurable in future.
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent c6a77ff8
...@@ -533,6 +533,8 @@ struct rxrpc_call { ...@@ -533,6 +533,8 @@ struct rxrpc_call {
u16 ackr_skew; /* skew on packet being ACK'd */ u16 ackr_skew; /* skew on packet being ACK'd */
rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */ rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */
rxrpc_seq_t ackr_consumed; /* Highest packet shown consumed */
rxrpc_seq_t ackr_seen; /* Highest packet shown seen */
rxrpc_serial_t ackr_ping; /* Last ping sent */ rxrpc_serial_t ackr_ping; /* Last ping sent */
ktime_t ackr_ping_time; /* Time last ping sent */ ktime_t ackr_ping_time; /* Time last ping sent */
...@@ -695,6 +697,7 @@ enum rxrpc_propose_ack_trace { ...@@ -695,6 +697,7 @@ enum rxrpc_propose_ack_trace {
rxrpc_propose_ack_respond_to_ack, rxrpc_propose_ack_respond_to_ack,
rxrpc_propose_ack_respond_to_ping, rxrpc_propose_ack_respond_to_ping,
rxrpc_propose_ack_retry_tx, rxrpc_propose_ack_retry_tx,
rxrpc_propose_ack_rotate_rx,
rxrpc_propose_ack_terminal_ack, rxrpc_propose_ack_terminal_ack,
rxrpc_propose_ack__nr_trace rxrpc_propose_ack__nr_trace
}; };
......
...@@ -202,6 +202,7 @@ const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8] = { ...@@ -202,6 +202,7 @@ const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8] = {
[rxrpc_propose_ack_respond_to_ack] = "Rsp2Ack", [rxrpc_propose_ack_respond_to_ack] = "Rsp2Ack",
[rxrpc_propose_ack_respond_to_ping] = "Rsp2Png", [rxrpc_propose_ack_respond_to_ping] = "Rsp2Png",
[rxrpc_propose_ack_retry_tx] = "RetryTx", [rxrpc_propose_ack_retry_tx] = "RetryTx",
[rxrpc_propose_ack_rotate_rx] = "RxAck ",
[rxrpc_propose_ack_terminal_ack] = "ClTerm ", [rxrpc_propose_ack_terminal_ack] = "ClTerm ",
}; };
......
...@@ -36,7 +36,9 @@ struct rxrpc_pkt_buffer { ...@@ -36,7 +36,9 @@ struct rxrpc_pkt_buffer {
* Fill out an ACK packet. * Fill out an ACK packet.
*/ */
static size_t rxrpc_fill_out_ack(struct rxrpc_call *call, static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
struct rxrpc_pkt_buffer *pkt) struct rxrpc_pkt_buffer *pkt,
rxrpc_seq_t *_hard_ack,
rxrpc_seq_t *_top)
{ {
rxrpc_serial_t serial; rxrpc_serial_t serial;
rxrpc_seq_t hard_ack, top, seq; rxrpc_seq_t hard_ack, top, seq;
...@@ -48,6 +50,8 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call, ...@@ -48,6 +50,8 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
serial = call->ackr_serial; serial = call->ackr_serial;
hard_ack = READ_ONCE(call->rx_hard_ack); hard_ack = READ_ONCE(call->rx_hard_ack);
top = smp_load_acquire(&call->rx_top); top = smp_load_acquire(&call->rx_top);
*_hard_ack = hard_ack;
*_top = top;
pkt->ack.bufferSpace = htons(8); pkt->ack.bufferSpace = htons(8);
pkt->ack.maxSkew = htons(call->ackr_skew); pkt->ack.maxSkew = htons(call->ackr_skew);
...@@ -96,6 +100,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type) ...@@ -96,6 +100,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
struct msghdr msg; struct msghdr msg;
struct kvec iov[2]; struct kvec iov[2];
rxrpc_serial_t serial; rxrpc_serial_t serial;
rxrpc_seq_t hard_ack, top;
size_t len, n; size_t len, n;
bool ping = false; bool ping = false;
int ioc, ret; int ioc, ret;
...@@ -146,7 +151,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type) ...@@ -146,7 +151,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
goto out; goto out;
} }
ping = (call->ackr_reason == RXRPC_ACK_PING); ping = (call->ackr_reason == RXRPC_ACK_PING);
n = rxrpc_fill_out_ack(call, pkt); n = rxrpc_fill_out_ack(call, pkt, &hard_ack, &top);
call->ackr_reason = 0; call->ackr_reason = 0;
spin_unlock_bh(&call->lock); spin_unlock_bh(&call->lock);
...@@ -203,18 +208,22 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type) ...@@ -203,18 +208,22 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
if (ping) if (ping)
call->ackr_ping_time = ktime_get_real(); call->ackr_ping_time = ktime_get_real();
if (ret < 0 && call->state < RXRPC_CALL_COMPLETE) { if (type == RXRPC_PACKET_TYPE_ACK &&
switch (type) { call->state < RXRPC_CALL_COMPLETE) {
case RXRPC_PACKET_TYPE_ACK: if (ret < 0) {
clear_bit(RXRPC_CALL_PINGING, &call->flags); clear_bit(RXRPC_CALL_PINGING, &call->flags);
rxrpc_propose_ACK(call, pkt->ack.reason, rxrpc_propose_ACK(call, pkt->ack.reason,
ntohs(pkt->ack.maxSkew), ntohs(pkt->ack.maxSkew),
ntohl(pkt->ack.serial), ntohl(pkt->ack.serial),
true, true, true, true,
rxrpc_propose_ack_retry_tx); rxrpc_propose_ack_retry_tx);
break; } else {
case RXRPC_PACKET_TYPE_ABORT: spin_lock_bh(&call->lock);
break; if (after(hard_ack, call->ackr_consumed))
call->ackr_consumed = hard_ack;
if (after(top, call->ackr_seen))
call->ackr_seen = top;
spin_unlock_bh(&call->lock);
} }
} }
......
...@@ -201,8 +201,19 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call) ...@@ -201,8 +201,19 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
_debug("%u,%u,%02x", hard_ack, top, flags); _debug("%u,%u,%02x", hard_ack, top, flags);
trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
if (flags & RXRPC_LAST_PACKET) if (flags & RXRPC_LAST_PACKET) {
rxrpc_end_rx_phase(call); rxrpc_end_rx_phase(call);
} else {
/* Check to see if there's an ACK that needs sending. */
if (after_eq(hard_ack, call->ackr_consumed + 2) ||
after_eq(top, call->ackr_seen + 2) ||
(hard_ack == top && after(hard_ack, call->ackr_consumed)))
rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
true, false,
rxrpc_propose_ack_rotate_rx);
if (call->ackr_reason)
rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK);
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment