Skip to content

Commit 5a924b8

Browse files
committed
rxrpc: Don't store the rxrpc header in the Tx queue sk_buffs
Don't store the rxrpc protocol header in sk_buffs on the transmit queue, but rather generate it on the fly and pass it to kernel_sendmsg() as a separate iov. This reduces the amount of storage required. Note that the security header is still stored in the sk_buff as it may get encrypted along with the data (and doesn't change with each transmission). Signed-off-by: David Howells <[email protected]>
1 parent 2d7a892 commit 5a924b8

File tree

6 files changed

+71
-88
lines changed

6 files changed

+71
-88
lines changed

net/rxrpc/ar-internal.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,9 @@ struct rxrpc_connection {
385385
int debug_id; /* debug ID for printks */
386386
atomic_t serial; /* packet serial number counter */
387387
unsigned int hi_serial; /* highest serial number received */
388+
u32 security_nonce; /* response re-use preventer */
388389
u8 size_align; /* data size alignment (for security) */
389-
u8 header_size; /* rxrpc + security header size */
390390
u8 security_size; /* security header size */
391-
u32 security_nonce; /* response re-use preventer */
392391
u8 security_ix; /* security type */
393392
u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
394393
};
@@ -946,7 +945,7 @@ extern const s8 rxrpc_ack_priority[];
946945
* output.c
947946
*/
948947
int rxrpc_send_call_packet(struct rxrpc_call *, u8);
949-
int rxrpc_send_data_packet(struct rxrpc_connection *, struct sk_buff *);
948+
int rxrpc_send_data_packet(struct rxrpc_call *, struct sk_buff *);
950949
void rxrpc_reject_packets(struct rxrpc_local *);
951950

952951
/*

net/rxrpc/call_event.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,6 @@ void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
139139
*/
140140
static void rxrpc_resend(struct rxrpc_call *call)
141141
{
142-
struct rxrpc_wire_header *whdr;
143142
struct rxrpc_skb_priv *sp;
144143
struct sk_buff *skb;
145144
rxrpc_seq_t cursor, seq, top;
@@ -201,22 +200,16 @@ static void rxrpc_resend(struct rxrpc_call *call)
201200
skb = call->rxtx_buffer[ix];
202201
rxrpc_get_skb(skb, rxrpc_skb_tx_got);
203202
spin_unlock_bh(&call->lock);
204-
sp = rxrpc_skb(skb);
205-
206-
/* Each Tx packet needs a new serial number */
207-
sp->hdr.serial = atomic_inc_return(&call->conn->serial);
208203

209-
whdr = (struct rxrpc_wire_header *)skb->head;
210-
whdr->serial = htonl(sp->hdr.serial);
211-
212-
if (rxrpc_send_data_packet(call->conn, skb) < 0) {
204+
if (rxrpc_send_data_packet(call, skb) < 0) {
213205
call->resend_at = now + 2;
214206
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
215207
return;
216208
}
217209

218210
if (rxrpc_is_client_call(call))
219211
rxrpc_expose_client_call(call);
212+
sp = rxrpc_skb(skb);
220213
sp->resend_at = now + rxrpc_resend_timeout;
221214

222215
rxrpc_free_skb(skb, rxrpc_skb_tx_freed);

net/rxrpc/conn_object.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
5353
spin_lock_init(&conn->state_lock);
5454
conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
5555
conn->size_align = 4;
56-
conn->header_size = sizeof(struct rxrpc_wire_header);
5756
conn->idle_timestamp = jiffies;
5857
}
5958

net/rxrpc/output.c

Lines changed: 56 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -208,19 +208,42 @@ int rxrpc_send_call_packet(struct rxrpc_call *call, u8 type)
208208
/*
209209
* send a packet through the transport endpoint
210210
*/
211-
int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
211+
int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb)
212212
{
213-
struct kvec iov[1];
213+
struct rxrpc_connection *conn = call->conn;
214+
struct rxrpc_wire_header whdr;
215+
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
214216
struct msghdr msg;
217+
struct kvec iov[2];
218+
rxrpc_serial_t serial;
219+
size_t len;
215220
int ret, opt;
216221

217222
_enter(",{%d}", skb->len);
218223

219-
iov[0].iov_base = skb->head;
220-
iov[0].iov_len = skb->len;
224+
/* Each transmission of a Tx packet needs a new serial number */
225+
serial = atomic_inc_return(&conn->serial);
226+
227+
whdr.epoch = htonl(conn->proto.epoch);
228+
whdr.cid = htonl(call->cid);
229+
whdr.callNumber = htonl(call->call_id);
230+
whdr.seq = htonl(sp->hdr.seq);
231+
whdr.serial = htonl(serial);
232+
whdr.type = RXRPC_PACKET_TYPE_DATA;
233+
whdr.flags = sp->hdr.flags;
234+
whdr.userStatus = 0;
235+
whdr.securityIndex = call->security_ix;
236+
whdr._rsvd = htons(sp->hdr._rsvd);
237+
whdr.serviceId = htons(call->service_id);
238+
239+
iov[0].iov_base = &whdr;
240+
iov[0].iov_len = sizeof(whdr);
241+
iov[1].iov_base = skb->head;
242+
iov[1].iov_len = skb->len;
243+
len = iov[0].iov_len + iov[1].iov_len;
221244

222-
msg.msg_name = &conn->params.peer->srx.transport;
223-
msg.msg_namelen = conn->params.peer->srx.transport_len;
245+
msg.msg_name = &call->peer->srx.transport;
246+
msg.msg_namelen = call->peer->srx.transport_len;
224247
msg.msg_control = NULL;
225248
msg.msg_controllen = 0;
226249
msg.msg_flags = 0;
@@ -234,26 +257,33 @@ int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
234257
}
235258
}
236259

260+
_proto("Tx DATA %%%u { #%u }", serial, sp->hdr.seq);
261+
237262
/* send the packet with the don't fragment bit set if we currently
238263
* think it's small enough */
239-
if (skb->len - sizeof(struct rxrpc_wire_header) < conn->params.peer->maxdata) {
240-
down_read(&conn->params.local->defrag_sem);
241-
/* send the packet by UDP
242-
* - returns -EMSGSIZE if UDP would have to fragment the packet
243-
* to go out of the interface
244-
* - in which case, we'll have processed the ICMP error
245-
* message and update the peer record
246-
*/
247-
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1,
248-
iov[0].iov_len);
249-
250-
up_read(&conn->params.local->defrag_sem);
251-
if (ret == -EMSGSIZE)
252-
goto send_fragmentable;
253-
254-
_leave(" = %d [%u]", ret, conn->params.peer->maxdata);
255-
return ret;
264+
if (iov[1].iov_len >= call->peer->maxdata)
265+
goto send_fragmentable;
266+
267+
down_read(&conn->params.local->defrag_sem);
268+
/* send the packet by UDP
269+
* - returns -EMSGSIZE if UDP would have to fragment the packet
270+
* to go out of the interface
271+
* - in which case, we'll have processed the ICMP error
272+
* message and update the peer record
273+
*/
274+
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
275+
276+
up_read(&conn->params.local->defrag_sem);
277+
if (ret == -EMSGSIZE)
278+
goto send_fragmentable;
279+
280+
done:
281+
if (ret == 0) {
282+
sp->resend_at = jiffies + rxrpc_resend_timeout;
283+
sp->hdr.serial = serial;
256284
}
285+
_leave(" = %d [%u]", ret, call->peer->maxdata);
286+
return ret;
257287

258288
send_fragmentable:
259289
/* attempt to send this message with fragmentation enabled */
@@ -268,8 +298,8 @@ int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
268298
SOL_IP, IP_MTU_DISCOVER,
269299
(char *)&opt, sizeof(opt));
270300
if (ret == 0) {
271-
ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1,
272-
iov[0].iov_len);
301+
ret = kernel_sendmsg(conn->params.local->socket, &msg,
302+
iov, 2, len);
273303

274304
opt = IP_PMTUDISC_DO;
275305
kernel_setsockopt(conn->params.local->socket, SOL_IP,
@@ -298,8 +328,7 @@ int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
298328
}
299329

300330
up_write(&conn->params.local->defrag_sem);
301-
_leave(" = %d [frag %u]", ret, conn->params.peer->maxdata);
302-
return ret;
331+
goto done;
303332
}
304333

305334
/*

net/rxrpc/rxkad.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,10 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn)
8080
case RXRPC_SECURITY_AUTH:
8181
conn->size_align = 8;
8282
conn->security_size = sizeof(struct rxkad_level1_hdr);
83-
conn->header_size += sizeof(struct rxkad_level1_hdr);
8483
break;
8584
case RXRPC_SECURITY_ENCRYPT:
8685
conn->size_align = 8;
8786
conn->security_size = sizeof(struct rxkad_level2_hdr);
88-
conn->header_size += sizeof(struct rxkad_level2_hdr);
8987
break;
9088
default:
9189
ret = -EKEYREJECTED;
@@ -161,7 +159,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
161159

162160
_enter("");
163161

164-
check = sp->hdr.seq ^ sp->hdr.callNumber;
162+
check = sp->hdr.seq ^ call->call_id;
165163
data_size |= (u32)check << 16;
166164

167165
hdr.data_size = htonl(data_size);
@@ -205,7 +203,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
205203

206204
_enter("");
207205

208-
check = sp->hdr.seq ^ sp->hdr.callNumber;
206+
check = sp->hdr.seq ^ call->call_id;
209207

210208
rxkhdr.data_size = htonl(data_size | (u32)check << 16);
211209
rxkhdr.checksum = 0;
@@ -277,7 +275,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
277275
/* calculate the security checksum */
278276
x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
279277
x |= sp->hdr.seq & 0x3fffffff;
280-
call->crypto_buf[0] = htonl(sp->hdr.callNumber);
278+
call->crypto_buf[0] = htonl(call->call_id);
281279
call->crypto_buf[1] = htonl(x);
282280

283281
sg_init_one(&sg, call->crypto_buf, 8);

net/rxrpc/sendmsg.c

Lines changed: 8 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,11 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
134134
write_unlock_bh(&call->state_lock);
135135
}
136136

137-
_proto("Tx DATA %%%u { #%u }", sp->hdr.serial, sp->hdr.seq);
138-
139137
if (seq == 1 && rxrpc_is_client_call(call))
140138
rxrpc_expose_client_call(call);
141139

142140
sp->resend_at = jiffies + rxrpc_resend_timeout;
143-
ret = rxrpc_send_data_packet(call->conn, skb);
141+
ret = rxrpc_send_data_packet(call, skb);
144142
if (ret < 0) {
145143
_debug("need instant resend %d", ret);
146144
rxrpc_instant_resend(call, ix);
@@ -150,29 +148,6 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
150148
_leave("");
151149
}
152150

153-
/*
154-
* Convert a host-endian header into a network-endian header.
155-
*/
156-
static void rxrpc_insert_header(struct sk_buff *skb)
157-
{
158-
struct rxrpc_wire_header whdr;
159-
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
160-
161-
whdr.epoch = htonl(sp->hdr.epoch);
162-
whdr.cid = htonl(sp->hdr.cid);
163-
whdr.callNumber = htonl(sp->hdr.callNumber);
164-
whdr.seq = htonl(sp->hdr.seq);
165-
whdr.serial = htonl(sp->hdr.serial);
166-
whdr.type = sp->hdr.type;
167-
whdr.flags = sp->hdr.flags;
168-
whdr.userStatus = sp->hdr.userStatus;
169-
whdr.securityIndex = sp->hdr.securityIndex;
170-
whdr._rsvd = htons(sp->hdr._rsvd);
171-
whdr.serviceId = htons(sp->hdr.serviceId);
172-
173-
memcpy(skb->head, &whdr, sizeof(whdr));
174-
}
175-
176151
/*
177152
* send data through a socket
178153
* - must be called in process context
@@ -232,7 +207,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
232207
space = chunk + call->conn->size_align;
233208
space &= ~(call->conn->size_align - 1UL);
234209

235-
size = space + call->conn->header_size;
210+
size = space + call->conn->security_size;
236211

237212
_debug("SIZE: %zu/%zu/%zu", chunk, space, size);
238213

@@ -248,9 +223,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
248223

249224
ASSERTCMP(skb->mark, ==, 0);
250225

251-
_debug("HS: %u", call->conn->header_size);
252-
skb_reserve(skb, call->conn->header_size);
253-
skb->len += call->conn->header_size;
226+
_debug("HS: %u", call->conn->security_size);
227+
skb_reserve(skb, call->conn->security_size);
228+
skb->len += call->conn->security_size;
254229

255230
sp = rxrpc_skb(skb);
256231
sp->remain = chunk;
@@ -312,33 +287,23 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
312287

313288
seq = call->tx_top + 1;
314289

315-
sp->hdr.epoch = conn->proto.epoch;
316-
sp->hdr.cid = call->cid;
317-
sp->hdr.callNumber = call->call_id;
318290
sp->hdr.seq = seq;
319-
sp->hdr.serial = atomic_inc_return(&conn->serial);
320-
sp->hdr.type = RXRPC_PACKET_TYPE_DATA;
321-
sp->hdr.userStatus = 0;
322-
sp->hdr.securityIndex = call->security_ix;
323291
sp->hdr._rsvd = 0;
324-
sp->hdr.serviceId = call->service_id;
292+
sp->hdr.flags = conn->out_clientflag;
325293

326-
sp->hdr.flags = conn->out_clientflag;
327294
if (msg_data_left(msg) == 0 && !more)
328295
sp->hdr.flags |= RXRPC_LAST_PACKET;
329296
else if (call->tx_top - call->tx_hard_ack <
330297
call->tx_winsize)
331298
sp->hdr.flags |= RXRPC_MORE_PACKETS;
332-
if (more && seq & 1)
299+
if (seq & 1)
333300
sp->hdr.flags |= RXRPC_REQUEST_ACK;
334301

335302
ret = conn->security->secure_packet(
336-
call, skb, skb->mark,
337-
skb->head + sizeof(struct rxrpc_wire_header));
303+
call, skb, skb->mark, skb->head);
338304
if (ret < 0)
339305
goto out;
340306

341-
rxrpc_insert_header(skb);
342307
rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more);
343308
skb = NULL;
344309
}

0 commit comments

Comments
 (0)