Skip to content

Commit 3136ef4

Browse files
committed
rxrpc: Delay terminal ACK transmission on a client call
Delay terminal ACK transmission on a client call by deferring it to the connection processor. This allows it to be skipped if we can send the next call instead, the first DATA packet of which will implicitly ack this call. Signed-off-by: David Howells <dhowells@redhat.com>
1 parent 9faaff5 commit 3136ef4

File tree

5 files changed

+108
-13
lines changed

5 files changed

+108
-13
lines changed

net/rxrpc/ar-internal.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,17 @@ enum rxrpc_conn_flag {
338338
RXRPC_CONN_DONT_REUSE, /* Don't reuse this connection */
339339
RXRPC_CONN_COUNTED, /* Counted by rxrpc_nr_client_conns */
340340
RXRPC_CONN_PROBING_FOR_UPGRADE, /* Probing for service upgrade */
341+
RXRPC_CONN_FINAL_ACK_0, /* Need final ACK for channel 0 */
342+
RXRPC_CONN_FINAL_ACK_1, /* Need final ACK for channel 1 */
343+
RXRPC_CONN_FINAL_ACK_2, /* Need final ACK for channel 2 */
344+
RXRPC_CONN_FINAL_ACK_3, /* Need final ACK for channel 3 */
341345
};
342346

347+
#define RXRPC_CONN_FINAL_ACK_MASK ((1UL << RXRPC_CONN_FINAL_ACK_0) | \
348+
(1UL << RXRPC_CONN_FINAL_ACK_1) | \
349+
(1UL << RXRPC_CONN_FINAL_ACK_2) | \
350+
(1UL << RXRPC_CONN_FINAL_ACK_3))
351+
343352
/*
344353
* Events that can be raised upon a connection.
345354
*/
@@ -393,6 +402,7 @@ struct rxrpc_connection {
393402
#define RXRPC_ACTIVE_CHANS_MASK ((1 << RXRPC_MAXCALLS) - 1)
394403
struct list_head waiting_calls; /* Calls waiting for channels */
395404
struct rxrpc_channel {
405+
unsigned long final_ack_at; /* Time at which to issue final ACK */
396406
struct rxrpc_call __rcu *call; /* Active call */
397407
u32 call_id; /* ID of current call */
398408
u32 call_counter; /* Call ID counter */
@@ -404,6 +414,7 @@ struct rxrpc_connection {
404414
};
405415
} channels[RXRPC_MAXCALLS];
406416

417+
struct timer_list timer; /* Conn event timer */
407418
struct work_struct processor; /* connection event processor */
408419
union {
409420
struct rb_node client_node; /* Node in local->client_conns */
@@ -861,6 +872,12 @@ static inline void rxrpc_put_connection(struct rxrpc_connection *conn)
861872
rxrpc_put_service_conn(conn);
862873
}
863874

875+
static inline void rxrpc_reduce_conn_timer(struct rxrpc_connection *conn,
876+
unsigned long expire_at)
877+
{
878+
timer_reduce(&conn->timer, expire_at);
879+
}
880+
864881
/*
865882
* conn_service.c
866883
*/

net/rxrpc/conn_client.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,11 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
554554

555555
trace_rxrpc_client(conn, channel, rxrpc_client_chan_activate);
556556

557+
/* Cancel the final ACK on the previous call if it hasn't been sent yet
558+
* as the DATA packet will implicitly ACK it.
559+
*/
560+
clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
561+
557562
write_lock_bh(&call->state_lock);
558563
if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
559564
call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
@@ -813,6 +818,19 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call)
813818
goto out_2;
814819
}
815820

821+
/* Schedule the final ACK to be transmitted in a short while so that it
822+
* can be skipped if we find a follow-on call. The first DATA packet
823+
* of the follow on call will implicitly ACK this call.
824+
*/
825+
if (test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
826+
unsigned long final_ack_at = jiffies + 2;
827+
828+
WRITE_ONCE(chan->final_ack_at, final_ack_at);
829+
smp_wmb(); /* vs rxrpc_process_delayed_final_acks() */
830+
set_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
831+
rxrpc_reduce_conn_timer(conn, final_ack_at);
832+
}
833+
816834
/* Things are more complex and we need the cache lock. We might be
817835
* able to simply idle the conn or it might now be lurking on the wait
818836
* list. It might even get moved back to the active list whilst we're

net/rxrpc/conn_event.c

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@
2424
* Retransmit terminal ACK or ABORT of the previous call.
2525
*/
2626
static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
27-
struct sk_buff *skb)
27+
struct sk_buff *skb,
28+
unsigned int channel)
2829
{
29-
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
30+
struct rxrpc_skb_priv *sp = skb ? rxrpc_skb(skb) : NULL;
3031
struct rxrpc_channel *chan;
3132
struct msghdr msg;
3233
struct kvec iov;
@@ -48,15 +49,15 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
4849

4950
_enter("%d", conn->debug_id);
5051

51-
chan = &conn->channels[sp->hdr.cid & RXRPC_CHANNELMASK];
52+
chan = &conn->channels[channel];
5253

5354
/* If the last call got moved on whilst we were waiting to run, just
5455
* ignore this packet.
5556
*/
5657
call_id = READ_ONCE(chan->last_call);
5758
/* Sync with __rxrpc_disconnect_call() */
5859
smp_rmb();
59-
if (call_id != sp->hdr.callNumber)
60+
if (skb && call_id != sp->hdr.callNumber)
6061
return;
6162

6263
msg.msg_name = &conn->params.peer->srx.transport;
@@ -65,9 +66,9 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
6566
msg.msg_controllen = 0;
6667
msg.msg_flags = 0;
6768

68-
pkt.whdr.epoch = htonl(sp->hdr.epoch);
69-
pkt.whdr.cid = htonl(sp->hdr.cid);
70-
pkt.whdr.callNumber = htonl(sp->hdr.callNumber);
69+
pkt.whdr.epoch = htonl(conn->proto.epoch);
70+
pkt.whdr.cid = htonl(conn->proto.cid);
71+
pkt.whdr.callNumber = htonl(call_id);
7172
pkt.whdr.seq = 0;
7273
pkt.whdr.type = chan->last_type;
7374
pkt.whdr.flags = conn->out_clientflag;
@@ -87,11 +88,11 @@ static void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
8788
mtu = conn->params.peer->if_mtu;
8889
mtu -= conn->params.peer->hdrsize;
8990
pkt.ack.bufferSpace = 0;
90-
pkt.ack.maxSkew = htons(skb->priority);
91-
pkt.ack.firstPacket = htonl(chan->last_seq);
92-
pkt.ack.previousPacket = htonl(chan->last_seq - 1);
93-
pkt.ack.serial = htonl(sp->hdr.serial);
94-
pkt.ack.reason = RXRPC_ACK_DUPLICATE;
91+
pkt.ack.maxSkew = htons(skb ? skb->priority : 0);
92+
pkt.ack.firstPacket = htonl(chan->last_seq + 1);
93+
pkt.ack.previousPacket = htonl(chan->last_seq);
94+
pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0);
95+
pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
9596
pkt.ack.nAcks = 0;
9697
pkt.info.rxMTU = htonl(rxrpc_rx_mtu);
9798
pkt.info.maxMTU = htonl(mtu);
@@ -272,7 +273,8 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
272273
switch (sp->hdr.type) {
273274
case RXRPC_PACKET_TYPE_DATA:
274275
case RXRPC_PACKET_TYPE_ACK:
275-
rxrpc_conn_retransmit_call(conn, skb);
276+
rxrpc_conn_retransmit_call(conn, skb,
277+
sp->hdr.cid & RXRPC_CHANNELMASK);
276278
return 0;
277279

278280
case RXRPC_PACKET_TYPE_BUSY:
@@ -378,6 +380,48 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn)
378380
_leave(" [aborted]");
379381
}
380382

383+
/*
384+
* Process delayed final ACKs that we haven't subsumed into a subsequent call.
385+
*/
386+
static void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn)
387+
{
388+
unsigned long j = jiffies, next_j;
389+
unsigned int channel;
390+
bool set;
391+
392+
again:
393+
next_j = j + LONG_MAX;
394+
set = false;
395+
for (channel = 0; channel < RXRPC_MAXCALLS; channel++) {
396+
struct rxrpc_channel *chan = &conn->channels[channel];
397+
unsigned long ack_at;
398+
399+
if (!test_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags))
400+
continue;
401+
402+
smp_rmb(); /* vs rxrpc_disconnect_client_call */
403+
ack_at = READ_ONCE(chan->final_ack_at);
404+
405+
if (time_before(j, ack_at)) {
406+
if (time_before(ack_at, next_j)) {
407+
next_j = ack_at;
408+
set = true;
409+
}
410+
continue;
411+
}
412+
413+
if (test_and_clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel,
414+
&conn->flags))
415+
rxrpc_conn_retransmit_call(conn, NULL, channel);
416+
}
417+
418+
j = jiffies;
419+
if (time_before_eq(next_j, j))
420+
goto again;
421+
if (set)
422+
rxrpc_reduce_conn_timer(conn, next_j);
423+
}
424+
381425
/*
382426
* connection-level event processor
383427
*/
@@ -394,6 +438,10 @@ void rxrpc_process_connection(struct work_struct *work)
394438
if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
395439
rxrpc_secure_connection(conn);
396440

441+
/* Process delayed ACKs whose time has come. */
442+
if (conn->flags & RXRPC_CONN_FINAL_ACK_MASK)
443+
rxrpc_process_delayed_final_acks(conn);
444+
397445
/* go through the conn-level event packets, releasing the ref on this
398446
* connection that each one has when we've finished with it */
399447
while ((skb = skb_dequeue(&conn->rx_queue))) {

net/rxrpc/conn_object.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ unsigned int rxrpc_connection_expiry = 10 * 60;
2424

2525
static void rxrpc_destroy_connection(struct rcu_head *);
2626

27+
static void rxrpc_connection_timer(struct timer_list *timer)
28+
{
29+
struct rxrpc_connection *conn =
30+
container_of(timer, struct rxrpc_connection, timer);
31+
32+
rxrpc_queue_conn(conn);
33+
}
34+
2735
/*
2836
* allocate a new connection
2937
*/
@@ -38,6 +46,7 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
3846
INIT_LIST_HEAD(&conn->cache_link);
3947
spin_lock_init(&conn->channel_lock);
4048
INIT_LIST_HEAD(&conn->waiting_calls);
49+
timer_setup(&conn->timer, &rxrpc_connection_timer, 0);
4150
INIT_WORK(&conn->processor, &rxrpc_process_connection);
4251
INIT_LIST_HEAD(&conn->proc_link);
4352
INIT_LIST_HEAD(&conn->link);
@@ -332,6 +341,7 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
332341

333342
_net("DESTROY CONN %d", conn->debug_id);
334343

344+
del_timer_sync(&conn->timer);
335345
rxrpc_purge_queue(&conn->rx_queue);
336346

337347
conn->security->clear(conn);

net/rxrpc/recvmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,13 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
144144
trace_rxrpc_receive(call, rxrpc_receive_end, 0, call->rx_top);
145145
ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
146146

147+
#if 0 // TODO: May want to transmit final ACK under some circumstances anyway
147148
if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
148149
rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, true, false,
149150
rxrpc_propose_ack_terminal_ack);
150151
rxrpc_send_ack_packet(call, false);
151152
}
153+
#endif
152154

153155
write_lock_bh(&call->state_lock);
154156

0 commit comments

Comments
 (0)