diff options
author | David Howells <dhowells@redhat.com> | 2016-09-21 19:29:31 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-09-21 20:23:50 -0400 |
commit | 5a924b8951f835b5ff8a3d9f434f3b230fc9905f (patch) | |
tree | 078edaea66512bc65011d3fcf1dead7ec8df405a | |
parent | 2d7a892626b5616a00d27a40fa23d70d5e618269 (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.h | 5 | ||||
-rw-r--r-- | net/rxrpc/call_event.c | 11 | ||||
-rw-r--r-- | net/rxrpc/conn_object.c | 1 | ||||
-rw-r--r-- | net/rxrpc/output.c | 83 | ||||
-rw-r--r-- | net/rxrpc/rxkad.c | 8 | ||||
-rw-r--r-- | net/rxrpc/sendmsg.c | 51 |
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 | */ |
948 | int rxrpc_send_call_packet(struct rxrpc_call *, u8); | 947 | 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 *); |
950 | void rxrpc_reject_packets(struct rxrpc_local *); | 949 | void 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 | */ |
140 | static void rxrpc_resend(struct rxrpc_call *call) | 140 | static 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 | */ |
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) |
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; | 280 | done: |
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 | ||
258 | send_fragmentable: | 288 | send_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 | */ | ||
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 | |||
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 | } |