aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-09-21 19:29:31 -0400
committerDavid Howells <dhowells@redhat.com>2016-09-21 20:23:50 -0400
commit5a924b8951f835b5ff8a3d9f434f3b230fc9905f (patch)
tree078edaea66512bc65011d3fcf1dead7ec8df405a
parent2d7a892626b5616a00d27a40fa23d70d5e618269 (diff)
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 <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h5
-rw-r--r--net/rxrpc/call_event.c11
-rw-r--r--net/rxrpc/conn_object.c1
-rw-r--r--net/rxrpc/output.c83
-rw-r--r--net/rxrpc/rxkad.c8
-rw-r--r--net/rxrpc/sendmsg.c51
6 files changed, 71 insertions, 88 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 034f525f2235..f021df4a6a22 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -385,10 +385,9 @@ struct rxrpc_connection {
385 int debug_id; /* debug ID for printks */ 385 int debug_id; /* debug ID for printks */
386 atomic_t serial; /* packet serial number counter */ 386 atomic_t serial; /* packet serial number counter */
387 unsigned int hi_serial; /* highest serial number received */ 387 unsigned int hi_serial; /* highest serial number received */
388 u32 security_nonce; /* response re-use preventer */
388 u8 size_align; /* data size alignment (for security) */ 389 u8 size_align; /* data size alignment (for security) */
389 u8 header_size; /* rxrpc + security header size */
390 u8 security_size; /* security header size */ 390 u8 security_size; /* security header size */
391 u32 security_nonce; /* response re-use preventer */
392 u8 security_ix; /* security type */ 391 u8 security_ix; /* security type */
393 u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */ 392 u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
394}; 393};
@@ -946,7 +945,7 @@ extern const s8 rxrpc_ack_priority[];
946 * output.c 945 * output.c
947 */ 946 */
948int rxrpc_send_call_packet(struct rxrpc_call *, u8); 947int rxrpc_send_call_packet(struct rxrpc_call *, u8);
949int rxrpc_send_data_packet(struct rxrpc_connection *, struct sk_buff *); 948int rxrpc_send_data_packet(struct rxrpc_call *, struct sk_buff *);
950void rxrpc_reject_packets(struct rxrpc_local *); 949void rxrpc_reject_packets(struct rxrpc_local *);
951 950
952/* 951/*
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 7d1b99824ed9..6247ce25eb21 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -139,7 +139,6 @@ void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason,
139 */ 139 */
140static void rxrpc_resend(struct rxrpc_call *call) 140static void rxrpc_resend(struct rxrpc_call *call)
141{ 141{
142 struct rxrpc_wire_header *whdr;
143 struct rxrpc_skb_priv *sp; 142 struct rxrpc_skb_priv *sp;
144 struct sk_buff *skb; 143 struct sk_buff *skb;
145 rxrpc_seq_t cursor, seq, top; 144 rxrpc_seq_t cursor, seq, top;
@@ -201,15 +200,8 @@ static void rxrpc_resend(struct rxrpc_call *call)
201 skb = call->rxtx_buffer[ix]; 200 skb = call->rxtx_buffer[ix];
202 rxrpc_get_skb(skb, rxrpc_skb_tx_got); 201 rxrpc_get_skb(skb, rxrpc_skb_tx_got);
203 spin_unlock_bh(&call->lock); 202 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);
208 203
209 whdr = (struct rxrpc_wire_header *)skb->head; 204 if (rxrpc_send_data_packet(call, skb) < 0) {
210 whdr->serial = htonl(sp->hdr.serial);
211
212 if (rxrpc_send_data_packet(call->conn, skb) < 0) {
213 call->resend_at = now + 2; 205 call->resend_at = now + 2;
214 rxrpc_free_skb(skb, rxrpc_skb_tx_freed); 206 rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
215 return; 207 return;
@@ -217,6 +209,7 @@ static void rxrpc_resend(struct rxrpc_call *call)
217 209
218 if (rxrpc_is_client_call(call)) 210 if (rxrpc_is_client_call(call))
219 rxrpc_expose_client_call(call); 211 rxrpc_expose_client_call(call);
212 sp = rxrpc_skb(skb);
220 sp->resend_at = now + rxrpc_resend_timeout; 213 sp->resend_at = now + rxrpc_resend_timeout;
221 214
222 rxrpc_free_skb(skb, rxrpc_skb_tx_freed); 215 rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 3b55aee0c436..e1e83af47866 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -53,7 +53,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
53 spin_lock_init(&conn->state_lock); 53 spin_lock_init(&conn->state_lock);
54 conn->debug_id = atomic_inc_return(&rxrpc_debug_id); 54 conn->debug_id = atomic_inc_return(&rxrpc_debug_id);
55 conn->size_align = 4; 55 conn->size_align = 4;
56 conn->header_size = sizeof(struct rxrpc_wire_header);
57 conn->idle_timestamp = jiffies; 56 conn->idle_timestamp = jiffies;
58 } 57 }
59 58
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 16e18a94ffa6..817fb0e82d6a 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -208,19 +208,42 @@ out:
208/* 208/*
209 * send a packet through the transport endpoint 209 * send a packet through the transport endpoint
210 */ 210 */
211int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb) 211int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb)
212{ 212{
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);
214 struct msghdr msg; 216 struct msghdr msg;
217 struct kvec iov[2];
218 rxrpc_serial_t serial;
219 size_t len;
215 int ret, opt; 220 int ret, opt;
216 221
217 _enter(",{%d}", skb->len); 222 _enter(",{%d}", skb->len);
218 223
219 iov[0].iov_base = skb->head; 224 /* Each transmission of a Tx packet needs a new serial number */
220 iov[0].iov_len = skb->len; 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;
221 244
222 msg.msg_name = &conn->params.peer->srx.transport; 245 msg.msg_name = &call->peer->srx.transport;
223 msg.msg_namelen = conn->params.peer->srx.transport_len; 246 msg.msg_namelen = call->peer->srx.transport_len;
224 msg.msg_control = NULL; 247 msg.msg_control = NULL;
225 msg.msg_controllen = 0; 248 msg.msg_controllen = 0;
226 msg.msg_flags = 0; 249 msg.msg_flags = 0;
@@ -234,26 +257,33 @@ int rxrpc_send_data_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
234 } 257 }
235 } 258 }
236 259
260 _proto("Tx DATA %%%u { #%u }", serial, sp->hdr.seq);
261
237 /* send the packet with the don't fragment bit set if we currently 262 /* send the packet with the don't fragment bit set if we currently
238 * think it's small enough */ 263 * think it's small enough */
239 if (skb->len - sizeof(struct rxrpc_wire_header) < conn->params.peer->maxdata) { 264 if (iov[1].iov_len >= call->peer->maxdata)
240 down_read(&conn->params.local->defrag_sem); 265 goto send_fragmentable;
241 /* send the packet by UDP 266
242 * - returns -EMSGSIZE if UDP would have to fragment the packet 267 down_read(&conn->params.local->defrag_sem);
243 * to go out of the interface 268 /* send the packet by UDP
244 * - in which case, we'll have processed the ICMP error 269 * - returns -EMSGSIZE if UDP would have to fragment the packet
245 * message and update the peer record 270 * to go out of the interface
246 */ 271 * - in which case, we'll have processed the ICMP error
247 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1, 272 * message and update the peer record
248 iov[0].iov_len); 273 */
249 274 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 2, len);
250 up_read(&conn->params.local->defrag_sem); 275
251 if (ret == -EMSGSIZE) 276 up_read(&conn->params.local->defrag_sem);
252 goto send_fragmentable; 277 if (ret == -EMSGSIZE)
253 278 goto send_fragmentable;
254 _leave(" = %d [%u]", ret, conn->params.peer->maxdata); 279
255 return ret; 280done:
281 if (ret == 0) {
282 sp->resend_at = jiffies + rxrpc_resend_timeout;
283 sp->hdr.serial = serial;
256 } 284 }
285 _leave(" = %d [%u]", ret, call->peer->maxdata);
286 return ret;
257 287
258send_fragmentable: 288send_fragmentable:
259 /* attempt to send this message with fragmentation enabled */ 289 /* attempt to send this message with fragmentation enabled */
@@ -268,8 +298,8 @@ send_fragmentable:
268 SOL_IP, IP_MTU_DISCOVER, 298 SOL_IP, IP_MTU_DISCOVER,
269 (char *)&opt, sizeof(opt)); 299 (char *)&opt, sizeof(opt));
270 if (ret == 0) { 300 if (ret == 0) {
271 ret = kernel_sendmsg(conn->params.local->socket, &msg, iov, 1, 301 ret = kernel_sendmsg(conn->params.local->socket, &msg,
272 iov[0].iov_len); 302 iov, 2, len);
273 303
274 opt = IP_PMTUDISC_DO; 304 opt = IP_PMTUDISC_DO;
275 kernel_setsockopt(conn->params.local->socket, SOL_IP, 305 kernel_setsockopt(conn->params.local->socket, SOL_IP,
@@ -298,8 +328,7 @@ send_fragmentable:
298 } 328 }
299 329
300 up_write(&conn->params.local->defrag_sem); 330 up_write(&conn->params.local->defrag_sem);
301 _leave(" = %d [frag %u]", ret, conn->params.peer->maxdata); 331 goto done;
302 return ret;
303} 332}
304 333
305/* 334/*
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index ae392558829d..88d080a1a3de 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -80,12 +80,10 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn)
80 case RXRPC_SECURITY_AUTH: 80 case RXRPC_SECURITY_AUTH:
81 conn->size_align = 8; 81 conn->size_align = 8;
82 conn->security_size = sizeof(struct rxkad_level1_hdr); 82 conn->security_size = sizeof(struct rxkad_level1_hdr);
83 conn->header_size += sizeof(struct rxkad_level1_hdr);
84 break; 83 break;
85 case RXRPC_SECURITY_ENCRYPT: 84 case RXRPC_SECURITY_ENCRYPT:
86 conn->size_align = 8; 85 conn->size_align = 8;
87 conn->security_size = sizeof(struct rxkad_level2_hdr); 86 conn->security_size = sizeof(struct rxkad_level2_hdr);
88 conn->header_size += sizeof(struct rxkad_level2_hdr);
89 break; 87 break;
90 default: 88 default:
91 ret = -EKEYREJECTED; 89 ret = -EKEYREJECTED;
@@ -161,7 +159,7 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
161 159
162 _enter(""); 160 _enter("");
163 161
164 check = sp->hdr.seq ^ sp->hdr.callNumber; 162 check = sp->hdr.seq ^ call->call_id;
165 data_size |= (u32)check << 16; 163 data_size |= (u32)check << 16;
166 164
167 hdr.data_size = htonl(data_size); 165 hdr.data_size = htonl(data_size);
@@ -205,7 +203,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
205 203
206 _enter(""); 204 _enter("");
207 205
208 check = sp->hdr.seq ^ sp->hdr.callNumber; 206 check = sp->hdr.seq ^ call->call_id;
209 207
210 rxkhdr.data_size = htonl(data_size | (u32)check << 16); 208 rxkhdr.data_size = htonl(data_size | (u32)check << 16);
211 rxkhdr.checksum = 0; 209 rxkhdr.checksum = 0;
@@ -277,7 +275,7 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
277 /* calculate the security checksum */ 275 /* calculate the security checksum */
278 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT); 276 x = (call->cid & RXRPC_CHANNELMASK) << (32 - RXRPC_CIDSHIFT);
279 x |= sp->hdr.seq & 0x3fffffff; 277 x |= sp->hdr.seq & 0x3fffffff;
280 call->crypto_buf[0] = htonl(sp->hdr.callNumber); 278 call->crypto_buf[0] = htonl(call->call_id);
281 call->crypto_buf[1] = htonl(x); 279 call->crypto_buf[1] = htonl(x);
282 280
283 sg_init_one(&sg, call->crypto_buf, 8); 281 sg_init_one(&sg, call->crypto_buf, 8);
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 6a39ee97a0b7..814b17f23971 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -134,13 +134,11 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
134 write_unlock_bh(&call->state_lock); 134 write_unlock_bh(&call->state_lock);
135 } 135 }
136 136
137 _proto("Tx DATA %%%u { #%u }", sp->hdr.serial, sp->hdr.seq);
138
139 if (seq == 1 && rxrpc_is_client_call(call)) 137 if (seq == 1 && rxrpc_is_client_call(call))
140 rxrpc_expose_client_call(call); 138 rxrpc_expose_client_call(call);
141 139
142 sp->resend_at = jiffies + rxrpc_resend_timeout; 140 sp->resend_at = jiffies + rxrpc_resend_timeout;
143 ret = rxrpc_send_data_packet(call->conn, skb); 141 ret = rxrpc_send_data_packet(call, skb);
144 if (ret < 0) { 142 if (ret < 0) {
145 _debug("need instant resend %d", ret); 143 _debug("need instant resend %d", ret);
146 rxrpc_instant_resend(call, ix); 144 rxrpc_instant_resend(call, ix);
@@ -151,29 +149,6 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb,
151} 149}
152 150
153/* 151/*
154 * Convert a host-endian header into a network-endian header.
155 */
156static 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
176/*
177 * send data through a socket 152 * send data through a socket
178 * - must be called in process context 153 * - must be called in process context
179 * - caller holds the socket locked 154 * - caller holds the socket locked
@@ -232,7 +207,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
232 space = chunk + call->conn->size_align; 207 space = chunk + call->conn->size_align;
233 space &= ~(call->conn->size_align - 1UL); 208 space &= ~(call->conn->size_align - 1UL);
234 209
235 size = space + call->conn->header_size; 210 size = space + call->conn->security_size;
236 211
237 _debug("SIZE: %zu/%zu/%zu", chunk, space, size); 212 _debug("SIZE: %zu/%zu/%zu", chunk, space, size);
238 213
@@ -248,9 +223,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
248 223
249 ASSERTCMP(skb->mark, ==, 0); 224 ASSERTCMP(skb->mark, ==, 0);
250 225
251 _debug("HS: %u", call->conn->header_size); 226 _debug("HS: %u", call->conn->security_size);
252 skb_reserve(skb, call->conn->header_size); 227 skb_reserve(skb, call->conn->security_size);
253 skb->len += call->conn->header_size; 228 skb->len += call->conn->security_size;
254 229
255 sp = rxrpc_skb(skb); 230 sp = rxrpc_skb(skb);
256 sp->remain = chunk; 231 sp->remain = chunk;
@@ -312,33 +287,23 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
312 287
313 seq = call->tx_top + 1; 288 seq = call->tx_top + 1;
314 289
315 sp->hdr.epoch = conn->proto.epoch;
316 sp->hdr.cid = call->cid;
317 sp->hdr.callNumber = call->call_id;
318 sp->hdr.seq = seq; 290 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;
323 sp->hdr._rsvd = 0; 291 sp->hdr._rsvd = 0;
324 sp->hdr.serviceId = call->service_id; 292 sp->hdr.flags = conn->out_clientflag;
325 293
326 sp->hdr.flags = conn->out_clientflag;
327 if (msg_data_left(msg) == 0 && !more) 294 if (msg_data_left(msg) == 0 && !more)
328 sp->hdr.flags |= RXRPC_LAST_PACKET; 295 sp->hdr.flags |= RXRPC_LAST_PACKET;
329 else if (call->tx_top - call->tx_hard_ack < 296 else if (call->tx_top - call->tx_hard_ack <
330 call->tx_winsize) 297 call->tx_winsize)
331 sp->hdr.flags |= RXRPC_MORE_PACKETS; 298 sp->hdr.flags |= RXRPC_MORE_PACKETS;
332 if (more && seq & 1) 299 if (seq & 1)
333 sp->hdr.flags |= RXRPC_REQUEST_ACK; 300 sp->hdr.flags |= RXRPC_REQUEST_ACK;
334 301
335 ret = conn->security->secure_packet( 302 ret = conn->security->secure_packet(
336 call, skb, skb->mark, 303 call, skb, skb->mark, skb->head);
337 skb->head + sizeof(struct rxrpc_wire_header));
338 if (ret < 0) 304 if (ret < 0)
339 goto out; 305 goto out;
340 306
341 rxrpc_insert_header(skb);
342 rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more); 307 rxrpc_queue_packet(call, skb, !msg_data_left(msg) && !more);
343 skb = NULL; 308 skb = NULL;
344 } 309 }