Skip to content

Commit 02a1935

Browse files
committed
rxrpc: Define rxrpc_txbuf struct to carry data to be transmitted
Define a struct, rxrpc_txbuf, to carry data to be transmitted instead of a socket buffer so that it can be placed onto multiple queues at once. This also allows the data buffer to be in the same allocation as the internal data. Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent a11e6ff commit 02a1935

File tree

5 files changed

+201
-1
lines changed

5 files changed

+201
-1
lines changed

include/trace/events/rxrpc.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,18 @@
252252
E_(rxrpc_reqack_small_txwin, "SMALL-TXWN")
253253
/* ---- Must update size of stat_why_req_ack[] if more are added! */
254254

255+
#define rxrpc_txbuf_traces \
256+
EM(rxrpc_txbuf_alloc_ack, "ALLOC ACK ") \
257+
EM(rxrpc_txbuf_alloc_data, "ALLOC DATA ") \
258+
EM(rxrpc_txbuf_free, "FREE ") \
259+
EM(rxrpc_txbuf_get_trans, "GET TRANS ") \
260+
EM(rxrpc_txbuf_get_retrans, "GET RETRANS") \
261+
EM(rxrpc_txbuf_put_cleaned, "PUT CLEANED") \
262+
EM(rxrpc_txbuf_put_rotated, "PUT ROTATED") \
263+
EM(rxrpc_txbuf_put_send_aborted, "PUT SEND-X ") \
264+
EM(rxrpc_txbuf_see_send_more, "SEE SEND+ ") \
265+
E_(rxrpc_txbuf_see_unacked, "SEE UNACKED")
266+
255267
/*
256268
* Generate enums for tracing information.
257269
*/
@@ -280,6 +292,7 @@ enum rxrpc_skb_trace { rxrpc_skb_traces } __mode(byte);
280292
enum rxrpc_timer_trace { rxrpc_timer_traces } __mode(byte);
281293
enum rxrpc_transmit_trace { rxrpc_transmit_traces } __mode(byte);
282294
enum rxrpc_tx_point { rxrpc_tx_points } __mode(byte);
295+
enum rxrpc_txbuf_trace { rxrpc_txbuf_traces } __mode(byte);
283296

284297
#endif /* end __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY */
285298

@@ -308,6 +321,7 @@ rxrpc_skb_traces;
308321
rxrpc_timer_traces;
309322
rxrpc_transmit_traces;
310323
rxrpc_tx_points;
324+
rxrpc_txbuf_traces;
311325

312326
/*
313327
* Now redefine the EM() and E_() macros to map the enums to the strings that
@@ -1469,6 +1483,37 @@ TRACE_EVENT(rxrpc_req_ack,
14691483
__print_symbolic(__entry->why, rxrpc_req_ack_traces))
14701484
);
14711485

1486+
TRACE_EVENT(rxrpc_txbuf,
1487+
TP_PROTO(unsigned int debug_id,
1488+
unsigned int call_debug_id, rxrpc_seq_t seq,
1489+
int ref, enum rxrpc_txbuf_trace what),
1490+
1491+
TP_ARGS(debug_id, call_debug_id, seq, ref, what),
1492+
1493+
TP_STRUCT__entry(
1494+
__field(unsigned int, debug_id )
1495+
__field(unsigned int, call_debug_id )
1496+
__field(rxrpc_seq_t, seq )
1497+
__field(int, ref )
1498+
__field(enum rxrpc_txbuf_trace, what )
1499+
),
1500+
1501+
TP_fast_assign(
1502+
__entry->debug_id = debug_id;
1503+
__entry->call_debug_id = call_debug_id;
1504+
__entry->seq = seq;
1505+
__entry->ref = ref;
1506+
__entry->what = what;
1507+
),
1508+
1509+
TP_printk("B=%08x c=%08x q=%08x %s r=%d",
1510+
__entry->debug_id,
1511+
__entry->call_debug_id,
1512+
__entry->seq,
1513+
__print_symbolic(__entry->what, rxrpc_txbuf_traces),
1514+
__entry->ref)
1515+
);
1516+
14721517
#undef EM
14731518
#undef E_
14741519
#endif /* _TRACE_RXRPC_H */

net/rxrpc/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ rxrpc-y := \
3030
sendmsg.o \
3131
server_key.o \
3232
skbuff.o \
33+
txbuf.o \
3334
utils.o
3435

3536
rxrpc-$(CONFIG_PROC_FS) += proc.o

net/rxrpc/ar-internal.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct rxrpc_crypt {
2929

3030
struct key_preparsed_payload;
3131
struct rxrpc_connection;
32+
struct rxrpc_txbuf;
3233

3334
/*
3435
* Mark applied to socket buffers in skb->mark. skb->priority is used
@@ -759,6 +760,48 @@ struct rxrpc_send_params {
759760
bool upgrade; /* If the connection is upgradeable */
760761
};
761762

763+
/*
764+
* Buffer of data to be output as a packet.
765+
*/
766+
struct rxrpc_txbuf {
767+
struct rcu_head rcu;
768+
struct list_head call_link; /* Link in call->tx_queue */
769+
struct list_head tx_link; /* Link in live Enc queue or Tx queue */
770+
struct rxrpc_call *call; /* Call to which belongs */
771+
ktime_t last_sent; /* Time at which last transmitted */
772+
refcount_t ref;
773+
rxrpc_seq_t seq; /* Sequence number of this packet */
774+
unsigned int call_debug_id;
775+
unsigned int debug_id;
776+
unsigned int len; /* Amount of data in buffer */
777+
unsigned int space; /* Remaining data space */
778+
unsigned int offset; /* Offset of fill point */
779+
unsigned long flags;
780+
#define RXRPC_TXBUF_ACKED 0 /* Set if ACK'd */
781+
#define RXRPC_TXBUF_NACKED 1 /* Set if NAK'd */
782+
#define RXRPC_TXBUF_LAST 2 /* Set if last packet in Tx phase */
783+
#define RXRPC_TXBUF_RESENT 3 /* Set if has been resent */
784+
#define RXRPC_TXBUF_RETRANS 4 /* Set if should be retransmitted */
785+
struct {
786+
/* The packet for encrypting and DMA'ing. We align it such
787+
* that data[] aligns correctly for any crypto blocksize.
788+
*/
789+
u8 pad[64 - sizeof(struct rxrpc_wire_header)];
790+
struct rxrpc_wire_header wire; /* Network-ready header */
791+
u8 data[RXRPC_JUMBO_DATALEN]; /* Data packet */
792+
} __aligned(64);
793+
};
794+
795+
static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb)
796+
{
797+
return txb->wire.flags & RXRPC_CLIENT_INITIATED;
798+
}
799+
800+
static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb)
801+
{
802+
return !rxrpc_sending_to_server(txb);
803+
}
804+
762805
#include <trace/events/rxrpc.h>
763806

764807
/*
@@ -1125,6 +1168,16 @@ static inline int __init rxrpc_sysctl_init(void) { return 0; }
11251168
static inline void rxrpc_sysctl_exit(void) {}
11261169
#endif
11271170

1171+
/*
1172+
* txbuf.c
1173+
*/
1174+
extern atomic_t rxrpc_nr_txbuf;
1175+
struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type,
1176+
gfp_t gfp);
1177+
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
1178+
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
1179+
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
1180+
11281181
/*
11291182
* utils.c
11301183
*/

net/rxrpc/proc.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,8 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
458458
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_slow_start]),
459459
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_small_txwin]));
460460
seq_printf(seq,
461-
"Buffers : txb=%u rxb=%u\n",
461+
"Buffers : txb=%u,%u rxb=%u\n",
462+
atomic_read(&rxrpc_nr_txbuf),
462463
atomic_read(&rxrpc_n_tx_skbs),
463464
atomic_read(&rxrpc_n_rx_skbs));
464465
return 0;

net/rxrpc/txbuf.c

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/* RxRPC Tx data buffering.
3+
*
4+
* Copyright (C) 2022 Red Hat, Inc. All Rights Reserved.
5+
* Written by David Howells ([email protected])
6+
*/
7+
8+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9+
10+
#include <linux/slab.h>
11+
#include "ar-internal.h"
12+
13+
static atomic_t rxrpc_txbuf_debug_ids;
14+
atomic_t rxrpc_nr_txbuf;
15+
16+
/*
17+
* Allocate and partially initialise an I/O request structure.
18+
*/
19+
struct rxrpc_txbuf *rxrpc_alloc_txbuf(struct rxrpc_call *call, u8 packet_type,
20+
gfp_t gfp)
21+
{
22+
struct rxrpc_txbuf *txb;
23+
24+
txb = kmalloc(sizeof(*txb), gfp);
25+
if (txb) {
26+
INIT_LIST_HEAD(&txb->call_link);
27+
INIT_LIST_HEAD(&txb->tx_link);
28+
refcount_set(&txb->ref, 1);
29+
txb->call = call;
30+
txb->call_debug_id = call->debug_id;
31+
txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids);
32+
txb->space = sizeof(txb->data);
33+
txb->len = 0;
34+
txb->offset = 0;
35+
txb->flags = 0;
36+
txb->seq = call->tx_top + 1;
37+
txb->wire.epoch = htonl(call->conn->proto.epoch);
38+
txb->wire.cid = htonl(call->cid);
39+
txb->wire.callNumber = htonl(call->call_id);
40+
txb->wire.seq = htonl(txb->seq);
41+
txb->wire.type = packet_type;
42+
txb->wire.flags = call->conn->out_clientflag;
43+
txb->wire.userStatus = 0;
44+
txb->wire.securityIndex = call->security_ix;
45+
txb->wire._rsvd = 0;
46+
txb->wire.serviceId = htons(call->service_id);
47+
48+
trace_rxrpc_txbuf(txb->debug_id,
49+
txb->call_debug_id, txb->seq, 1,
50+
packet_type == RXRPC_PACKET_TYPE_DATA ?
51+
rxrpc_txbuf_alloc_data :
52+
rxrpc_txbuf_alloc_ack);
53+
atomic_inc(&rxrpc_nr_txbuf);
54+
}
55+
56+
return txb;
57+
}
58+
59+
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
60+
{
61+
int r;
62+
63+
__refcount_inc(&txb->ref, &r);
64+
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r + 1, what);
65+
}
66+
67+
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
68+
{
69+
int r = refcount_read(&txb->ref);
70+
71+
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, r, what);
72+
}
73+
74+
static void rxrpc_free_txbuf(struct rcu_head *rcu)
75+
{
76+
struct rxrpc_txbuf *txb = container_of(rcu, struct rxrpc_txbuf, rcu);
77+
78+
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0,
79+
rxrpc_txbuf_free);
80+
kfree(txb);
81+
atomic_dec(&rxrpc_nr_txbuf);
82+
}
83+
84+
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
85+
{
86+
unsigned int debug_id, call_debug_id;
87+
rxrpc_seq_t seq;
88+
bool dead;
89+
int r;
90+
91+
if (txb) {
92+
debug_id = txb->debug_id;
93+
call_debug_id = txb->call_debug_id;
94+
seq = txb->seq;
95+
dead = __refcount_dec_and_test(&txb->ref, &r);
96+
trace_rxrpc_txbuf(debug_id, call_debug_id, seq, r - 1, what);
97+
if (dead)
98+
call_rcu(&txb->rcu, rxrpc_free_txbuf);
99+
}
100+
}

0 commit comments

Comments
 (0)