aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-09-27 10:13:08 -0400
committerDavid Howells <dhowells@redhat.com>2018-09-28 05:32:19 -0400
commitece64fec164f523bfbe874abdef2a0e6ff376251 (patch)
tree807c8ffdc0f6d73ef93ecf5ea4ac0f1c3fa8b364
parentb604dd9883f783a94020d772e4fe03160f455372 (diff)
rxrpc: Emit BUSY packets when supposed to rather than ABORTs
In the input path, a received sk_buff can be marked for rejection by setting RXRPC_SKB_MARK_* in skb->mark and, if needed, some auxiliary data (such as an abort code) in skb->priority. The rejection is handled by queueing the sk_buff up for dealing with in process context. The output code reads the mark and priority and, theoretically, generates an appropriate response packet. However, if RXRPC_SKB_MARK_BUSY is set, this isn't noticed and an ABORT message with a random abort code is generated (since skb->priority wasn't set to anything). Fix this by outputting the appropriate sort of packet. Also, whilst we're at it, most of the marks are no longer used, so remove them and rename the remaining two to something more obvious. Fixes: 248f219cb8bc ("rxrpc: Rewrite the data and ack handling code") Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h13
-rw-r--r--net/rxrpc/call_accept.c6
-rw-r--r--net/rxrpc/input.c2
-rw-r--r--net/rxrpc/output.c23
4 files changed, 26 insertions, 18 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 9fcb3e197b14..e8861cb78070 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -40,17 +40,12 @@ struct rxrpc_crypt {
40struct rxrpc_connection; 40struct rxrpc_connection;
41 41
42/* 42/*
43 * Mark applied to socket buffers. 43 * Mark applied to socket buffers in skb->mark. skb->priority is used
44 * to pass supplementary information.
44 */ 45 */
45enum rxrpc_skb_mark { 46enum rxrpc_skb_mark {
46 RXRPC_SKB_MARK_DATA, /* data message */ 47 RXRPC_SKB_MARK_REJECT_BUSY, /* Reject with BUSY */
47 RXRPC_SKB_MARK_FINAL_ACK, /* final ACK received message */ 48 RXRPC_SKB_MARK_REJECT_ABORT, /* Reject with ABORT (code in skb->priority) */
48 RXRPC_SKB_MARK_BUSY, /* server busy message */
49 RXRPC_SKB_MARK_REMOTE_ABORT, /* remote abort message */
50 RXRPC_SKB_MARK_LOCAL_ABORT, /* local abort message */
51 RXRPC_SKB_MARK_NET_ERROR, /* network error message */
52 RXRPC_SKB_MARK_LOCAL_ERROR, /* local error message */
53 RXRPC_SKB_MARK_NEW_CALL, /* local error message */
54}; 49};
55 50
56/* 51/*
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 9d1e298b784c..e88f131c1d7f 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -353,7 +353,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
353 353
354 trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq, 354 trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
355 RX_INVALID_OPERATION, EOPNOTSUPP); 355 RX_INVALID_OPERATION, EOPNOTSUPP);
356 skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT; 356 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
357 skb->priority = RX_INVALID_OPERATION; 357 skb->priority = RX_INVALID_OPERATION;
358 _leave(" = NULL [service]"); 358 _leave(" = NULL [service]");
359 return NULL; 359 return NULL;
@@ -364,7 +364,7 @@ found_service:
364 rx->sk.sk_state == RXRPC_CLOSE) { 364 rx->sk.sk_state == RXRPC_CLOSE) {
365 trace_rxrpc_abort(0, "CLS", sp->hdr.cid, sp->hdr.callNumber, 365 trace_rxrpc_abort(0, "CLS", sp->hdr.cid, sp->hdr.callNumber,
366 sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN); 366 sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
367 skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT; 367 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
368 skb->priority = RX_INVALID_OPERATION; 368 skb->priority = RX_INVALID_OPERATION;
369 _leave(" = NULL [close]"); 369 _leave(" = NULL [close]");
370 call = NULL; 370 call = NULL;
@@ -373,7 +373,7 @@ found_service:
373 373
374 call = rxrpc_alloc_incoming_call(rx, local, conn, skb); 374 call = rxrpc_alloc_incoming_call(rx, local, conn, skb);
375 if (!call) { 375 if (!call) {
376 skb->mark = RXRPC_SKB_MARK_BUSY; 376 skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
377 _leave(" = NULL [busy]"); 377 _leave(" = NULL [busy]");
378 call = NULL; 378 call = NULL;
379 goto out; 379 goto out;
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 7f9ed3a60b9a..b0f12471f5e7 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -1354,7 +1354,7 @@ bad_message:
1354protocol_error: 1354protocol_error:
1355 skb->priority = RX_PROTOCOL_ERROR; 1355 skb->priority = RX_PROTOCOL_ERROR;
1356post_abort: 1356post_abort:
1357 skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT; 1357 skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
1358reject_packet: 1358reject_packet:
1359 trace_rxrpc_rx_done(skb->mark, skb->priority); 1359 trace_rxrpc_rx_done(skb->mark, skb->priority);
1360 rxrpc_reject_packet(local, skb); 1360 rxrpc_reject_packet(local, skb);
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 8a4da3fe96df..e8fb8922bca8 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -524,7 +524,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
524 struct kvec iov[2]; 524 struct kvec iov[2];
525 size_t size; 525 size_t size;
526 __be32 code; 526 __be32 code;
527 int ret; 527 int ret, ioc;
528 528
529 _enter("%d", local->debug_id); 529 _enter("%d", local->debug_id);
530 530
@@ -532,7 +532,6 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
532 iov[0].iov_len = sizeof(whdr); 532 iov[0].iov_len = sizeof(whdr);
533 iov[1].iov_base = &code; 533 iov[1].iov_base = &code;
534 iov[1].iov_len = sizeof(code); 534 iov[1].iov_len = sizeof(code);
535 size = sizeof(whdr) + sizeof(code);
536 535
537 msg.msg_name = &srx.transport; 536 msg.msg_name = &srx.transport;
538 msg.msg_control = NULL; 537 msg.msg_control = NULL;
@@ -540,17 +539,31 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
540 msg.msg_flags = 0; 539 msg.msg_flags = 0;
541 540
542 memset(&whdr, 0, sizeof(whdr)); 541 memset(&whdr, 0, sizeof(whdr));
543 whdr.type = RXRPC_PACKET_TYPE_ABORT;
544 542
545 while ((skb = skb_dequeue(&local->reject_queue))) { 543 while ((skb = skb_dequeue(&local->reject_queue))) {
546 rxrpc_see_skb(skb, rxrpc_skb_rx_seen); 544 rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
547 sp = rxrpc_skb(skb); 545 sp = rxrpc_skb(skb);
548 546
547 switch (skb->mark) {
548 case RXRPC_SKB_MARK_REJECT_BUSY:
549 whdr.type = RXRPC_PACKET_TYPE_BUSY;
550 size = sizeof(whdr);
551 ioc = 1;
552 break;
553 case RXRPC_SKB_MARK_REJECT_ABORT:
554 whdr.type = RXRPC_PACKET_TYPE_ABORT;
555 code = htonl(skb->priority);
556 size = sizeof(whdr) + sizeof(code);
557 ioc = 2;
558 break;
559 default:
560 rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
561 continue;
562 }
563
549 if (rxrpc_extract_addr_from_skb(local, &srx, skb) == 0) { 564 if (rxrpc_extract_addr_from_skb(local, &srx, skb) == 0) {
550 msg.msg_namelen = srx.transport_len; 565 msg.msg_namelen = srx.transport_len;
551 566
552 code = htonl(skb->priority);
553
554 whdr.epoch = htonl(sp->hdr.epoch); 567 whdr.epoch = htonl(sp->hdr.epoch);
555 whdr.cid = htonl(sp->hdr.cid); 568 whdr.cid = htonl(sp->hdr.cid);
556 whdr.callNumber = htonl(sp->hdr.callNumber); 569 whdr.callNumber = htonl(sp->hdr.callNumber);