rxrpc: Emit BUSY packets when supposed to rather than ABORTs
authorDavid Howells <dhowells@redhat.com>
Thu, 27 Sep 2018 14:13:08 +0000 (15:13 +0100)
committerDavid Howells <dhowells@redhat.com>
Fri, 28 Sep 2018 09:32:19 +0000 (10:32 +0100)
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>
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/input.c
net/rxrpc/output.c

index 9fcb3e1..e8861cb 100644 (file)
@@ -40,17 +40,12 @@ struct rxrpc_crypt {
 struct rxrpc_connection;
 
 /*
- * Mark applied to socket buffers.
+ * Mark applied to socket buffers in skb->mark.  skb->priority is used
+ * to pass supplementary information.
  */
 enum rxrpc_skb_mark {
-       RXRPC_SKB_MARK_DATA,            /* data message */
-       RXRPC_SKB_MARK_FINAL_ACK,       /* final ACK received message */
-       RXRPC_SKB_MARK_BUSY,            /* server busy message */
-       RXRPC_SKB_MARK_REMOTE_ABORT,    /* remote abort message */
-       RXRPC_SKB_MARK_LOCAL_ABORT,     /* local abort message */
-       RXRPC_SKB_MARK_NET_ERROR,       /* network error message */
-       RXRPC_SKB_MARK_LOCAL_ERROR,     /* local error message */
-       RXRPC_SKB_MARK_NEW_CALL,        /* local error message */
+       RXRPC_SKB_MARK_REJECT_BUSY,     /* Reject with BUSY */
+       RXRPC_SKB_MARK_REJECT_ABORT,    /* Reject with ABORT (code in skb->priority) */
 };
 
 /*
index 9d1e298..e88f131 100644 (file)
@@ -353,7 +353,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
 
        trace_rxrpc_abort(0, "INV", sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
                          RX_INVALID_OPERATION, EOPNOTSUPP);
-       skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
+       skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
        skb->priority = RX_INVALID_OPERATION;
        _leave(" = NULL [service]");
        return NULL;
@@ -364,7 +364,7 @@ found_service:
            rx->sk.sk_state == RXRPC_CLOSE) {
                trace_rxrpc_abort(0, "CLS", sp->hdr.cid, sp->hdr.callNumber,
                                  sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
-               skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
+               skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
                skb->priority = RX_INVALID_OPERATION;
                _leave(" = NULL [close]");
                call = NULL;
@@ -373,7 +373,7 @@ found_service:
 
        call = rxrpc_alloc_incoming_call(rx, local, conn, skb);
        if (!call) {
-               skb->mark = RXRPC_SKB_MARK_BUSY;
+               skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
                _leave(" = NULL [busy]");
                call = NULL;
                goto out;
index 7f9ed3a..b0f1247 100644 (file)
@@ -1354,7 +1354,7 @@ bad_message:
 protocol_error:
        skb->priority = RX_PROTOCOL_ERROR;
 post_abort:
-       skb->mark = RXRPC_SKB_MARK_LOCAL_ABORT;
+       skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
 reject_packet:
        trace_rxrpc_rx_done(skb->mark, skb->priority);
        rxrpc_reject_packet(local, skb);
index 8a4da3f..e8fb892 100644 (file)
@@ -524,7 +524,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
        struct kvec iov[2];
        size_t size;
        __be32 code;
-       int ret;
+       int ret, ioc;
 
        _enter("%d", local->debug_id);
 
@@ -532,7 +532,6 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
        iov[0].iov_len = sizeof(whdr);
        iov[1].iov_base = &code;
        iov[1].iov_len = sizeof(code);
-       size = sizeof(whdr) + sizeof(code);
 
        msg.msg_name = &srx.transport;
        msg.msg_control = NULL;
@@ -540,17 +539,31 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
        msg.msg_flags = 0;
 
        memset(&whdr, 0, sizeof(whdr));
-       whdr.type = RXRPC_PACKET_TYPE_ABORT;
 
        while ((skb = skb_dequeue(&local->reject_queue))) {
                rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
                sp = rxrpc_skb(skb);
 
+               switch (skb->mark) {
+               case RXRPC_SKB_MARK_REJECT_BUSY:
+                       whdr.type = RXRPC_PACKET_TYPE_BUSY;
+                       size = sizeof(whdr);
+                       ioc = 1;
+                       break;
+               case RXRPC_SKB_MARK_REJECT_ABORT:
+                       whdr.type = RXRPC_PACKET_TYPE_ABORT;
+                       code = htonl(skb->priority);
+                       size = sizeof(whdr) + sizeof(code);
+                       ioc = 2;
+                       break;
+               default:
+                       rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
+                       continue;
+               }
+
                if (rxrpc_extract_addr_from_skb(local, &srx, skb) == 0) {
                        msg.msg_namelen = srx.transport_len;
 
-                       code = htonl(skb->priority);
-
                        whdr.epoch      = htonl(sp->hdr.epoch);
                        whdr.cid        = htonl(sp->hdr.cid);
                        whdr.callNumber = htonl(sp->hdr.callNumber);