aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-09-24 13:05:26 -0400
committerDavid Howells <dhowells@redhat.com>2016-09-24 13:05:26 -0400
commit805b21b929e29192fb5de16154f616bfc1116e3e (patch)
treeb48e21a8c4d7b824fe0e9289fe51a9e739a5c46e
parentc6a77ff82fb849534748719f37f3f9086d78ed39 (diff)
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: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h3
-rw-r--r--net/rxrpc/misc.c1
-rw-r--r--net/rxrpc/output.c25
-rw-r--r--net/rxrpc/recvmsg.c13
4 files changed, 33 insertions, 9 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 042dbcc52654..e3bf9c0e3ad1 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -533,6 +533,8 @@ struct rxrpc_call {
533 u16 ackr_skew; /* skew on packet being ACK'd */ 533 u16 ackr_skew; /* skew on packet being ACK'd */
534 rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ 534 rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */
535 rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */ 535 rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */
536 rxrpc_seq_t ackr_consumed; /* Highest packet shown consumed */
537 rxrpc_seq_t ackr_seen; /* Highest packet shown seen */
536 rxrpc_serial_t ackr_ping; /* Last ping sent */ 538 rxrpc_serial_t ackr_ping; /* Last ping sent */
537 ktime_t ackr_ping_time; /* Time last ping sent */ 539 ktime_t ackr_ping_time; /* Time last ping sent */
538 540
@@ -695,6 +697,7 @@ enum rxrpc_propose_ack_trace {
695 rxrpc_propose_ack_respond_to_ack, 697 rxrpc_propose_ack_respond_to_ack,
696 rxrpc_propose_ack_respond_to_ping, 698 rxrpc_propose_ack_respond_to_ping,
697 rxrpc_propose_ack_retry_tx, 699 rxrpc_propose_ack_retry_tx,
700 rxrpc_propose_ack_rotate_rx,
698 rxrpc_propose_ack_terminal_ack, 701 rxrpc_propose_ack_terminal_ack,
699 rxrpc_propose_ack__nr_trace 702 rxrpc_propose_ack__nr_trace
700}; 703};
diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c
index 1ca14835d87f..a473fd7dabaa 100644
--- a/net/rxrpc/misc.c
+++ b/net/rxrpc/misc.c
@@ -202,6 +202,7 @@ const char rxrpc_propose_ack_traces[rxrpc_propose_ack__nr_trace][8] = {
202 [rxrpc_propose_ack_respond_to_ack] = "Rsp2Ack", 202 [rxrpc_propose_ack_respond_to_ack] = "Rsp2Ack",
203 [rxrpc_propose_ack_respond_to_ping] = "Rsp2Png", 203 [rxrpc_propose_ack_respond_to_ping] = "Rsp2Png",
204 [rxrpc_propose_ack_retry_tx] = "RetryTx", 204 [rxrpc_propose_ack_retry_tx] = "RetryTx",
205 [rxrpc_propose_ack_rotate_rx] = "RxAck ",
205 [rxrpc_propose_ack_terminal_ack] = "ClTerm ", 206 [rxrpc_propose_ack_terminal_ack] = "ClTerm ",
206}; 207};
207 208
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 0c563e325c9d..3eb01445e814 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -36,7 +36,9 @@ struct rxrpc_pkt_buffer {
36 * Fill out an ACK packet. 36 * Fill out an ACK packet.
37 */ 37 */
38static size_t rxrpc_fill_out_ack(struct rxrpc_call *call, 38static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
39 struct rxrpc_pkt_buffer *pkt) 39 struct rxrpc_pkt_buffer *pkt,
40 rxrpc_seq_t *_hard_ack,
41 rxrpc_seq_t *_top)
40{ 42{
41 rxrpc_serial_t serial; 43 rxrpc_serial_t serial;
42 rxrpc_seq_t hard_ack, top, seq; 44 rxrpc_seq_t hard_ack, top, seq;
@@ -48,6 +50,8 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
48 serial = call->ackr_serial; 50 serial = call->ackr_serial;
49 hard_ack = READ_ONCE(call->rx_hard_ack); 51 hard_ack = READ_ONCE(call->rx_hard_ack);
50 top = smp_load_acquire(&call->rx_top); 52 top = smp_load_acquire(&call->rx_top);
53 *_hard_ack = hard_ack;
54 *_top = top;
51 55
52 pkt->ack.bufferSpace = htons(8); 56 pkt->ack.bufferSpace = htons(8);
53 pkt->ack.maxSkew = htons(call->ackr_skew); 57 pkt->ack.maxSkew = htons(call->ackr_skew);
@@ -96,6 +100,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
96 struct msghdr msg; 100 struct msghdr msg;
97 struct kvec iov[2]; 101 struct kvec iov[2];
98 rxrpc_serial_t serial; 102 rxrpc_serial_t serial;
103 rxrpc_seq_t hard_ack, top;
99 size_t len, n; 104 size_t len, n;
100 bool ping = false; 105 bool ping = false;
101 int ioc, ret; 106 int ioc, ret;
@@ -146,7 +151,7 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
146 goto out; 151 goto out;
147 } 152 }
148 ping = (call->ackr_reason == RXRPC_ACK_PING); 153 ping = (call->ackr_reason == RXRPC_ACK_PING);
149 n = rxrpc_fill_out_ack(call, pkt); 154 n = rxrpc_fill_out_ack(call, pkt, &hard_ack, &top);
150 call->ackr_reason = 0; 155 call->ackr_reason = 0;
151 156
152 spin_unlock_bh(&call->lock); 157 spin_unlock_bh(&call->lock);
@@ -203,18 +208,22 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
203 if (ping) 208 if (ping)
204 call->ackr_ping_time = ktime_get_real(); 209 call->ackr_ping_time = ktime_get_real();
205 210
206 if (ret < 0 && call->state < RXRPC_CALL_COMPLETE) { 211 if (type == RXRPC_PACKET_TYPE_ACK &&
207 switch (type) { 212 call->state < RXRPC_CALL_COMPLETE) {
208 case RXRPC_PACKET_TYPE_ACK: 213 if (ret < 0) {
209 clear_bit(RXRPC_CALL_PINGING, &call->flags); 214 clear_bit(RXRPC_CALL_PINGING, &call->flags);
210 rxrpc_propose_ACK(call, pkt->ack.reason, 215 rxrpc_propose_ACK(call, pkt->ack.reason,
211 ntohs(pkt->ack.maxSkew), 216 ntohs(pkt->ack.maxSkew),
212 ntohl(pkt->ack.serial), 217 ntohl(pkt->ack.serial),
213 true, true, 218 true, true,
214 rxrpc_propose_ack_retry_tx); 219 rxrpc_propose_ack_retry_tx);
215 break; 220 } else {
216 case RXRPC_PACKET_TYPE_ABORT: 221 spin_lock_bh(&call->lock);
217 break; 222 if (after(hard_ack, call->ackr_consumed))
223 call->ackr_consumed = hard_ack;
224 if (after(top, call->ackr_seen))
225 call->ackr_seen = top;
226 spin_unlock_bh(&call->lock);
218 } 227 }
219 } 228 }
220 229
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index 8c7f3de45bac..a7458c398b9e 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -201,8 +201,19 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
201 201
202 _debug("%u,%u,%02x", hard_ack, top, flags); 202 _debug("%u,%u,%02x", hard_ack, top, flags);
203 trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); 203 trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
204 if (flags & RXRPC_LAST_PACKET) 204 if (flags & RXRPC_LAST_PACKET) {
205 rxrpc_end_rx_phase(call); 205 rxrpc_end_rx_phase(call);
206 } else {
207 /* Check to see if there's an ACK that needs sending. */
208 if (after_eq(hard_ack, call->ackr_consumed + 2) ||
209 after_eq(top, call->ackr_seen + 2) ||
210 (hard_ack == top && after(hard_ack, call->ackr_consumed)))
211 rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
212 true, false,
213 rxrpc_propose_ack_rotate_rx);
214 if (call->ackr_reason)
215 rxrpc_send_call_packet(call, RXRPC_PACKET_TYPE_ACK);
216 }
206} 217}
207 218
208/* 219/*