summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-06-05 09:30:49 -0400
committerDavid Howells <dhowells@redhat.com>2017-06-05 09:30:49 -0400
commit4722974d90e06d0164ca1b73a6b34cec6bdb64ad (patch)
treef8f839ed9e2b63691c8122c6e94dc0d4fea9d98f
parent28036f44851e2515aa91b547b45cefddcac52ff6 (diff)
rxrpc: Implement service upgrade
Implement AuriStor's service upgrade facility. There are three problems that this is meant to deal with: (1) Various of the standard AFS RPC calls have IPv4 addresses in their requests and/or replies - but there's no room for including IPv6 addresses. (2) Definition of IPv6-specific RPC operations in the standard operation sets has not yet been achieved. (3) One could envision the creation a new service on the same port that as the original service. The new service could implement improved operations - and the client could try this first, falling back to the original service if it's not there. Unfortunately, certain servers ignore packets addressed to a service they don't implement and don't respond in any way - not even with an ABORT. This means that the client must then wait for the call timeout to occur. What service upgrade does is to see if the connection is marked as being 'upgradeable' and if so, change the service ID in the server and thus the request and reply formats. Note that the upgrade isn't mandatory - a server that supports only the original call set will ignore the upgrade request. In the protocol, the procedure is then as follows: (1) To request an upgrade, the first DATA packet in a new connection must have the userStatus set to 1 (this is normally 0). The userStatus value is normally ignored by the server. (2) If the server doesn't support upgrading, the reply packets will contain the same service ID as for the first request packet. (3) If the server does support upgrading, all future reply packets on that connection will contain the new service ID and the new service ID will be applied to *all* further calls on that connection as well. (4) The RPC op used to probe the upgrade must take the same request data as the shadow call in the upgrade set (but may return a different reply). GetCapability RPC ops were added to all standard sets for just this purpose. Ops where the request formats differ cannot be used for probing. (5) The client must wait for completion of the probe before sending any further RPC ops to the same destination. It should then use the service ID that recvmsg() reported back in all future calls. (6) The shadow service must have call definitions for all the operation IDs defined by the original service. To support service upgrading, a server should: (1) Call bind() twice on its AF_RXRPC socket before calling listen(). Each bind() should supply a different service ID, but the transport addresses must be the same. This allows the server to receive requests with either service ID. (2) Enable automatic upgrading by calling setsockopt(), specifying RXRPC_UPGRADEABLE_SERVICE and passing in a two-member array of unsigned shorts as the argument: unsigned short optval[2]; This specifies a pair of service IDs. They must be different and must match the service IDs bound to the socket. Member 0 is the service ID to upgrade from and member 1 is the service ID to upgrade to. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--Documentation/networking/rxrpc.txt34
-rw-r--r--include/linux/rxrpc.h1
-rw-r--r--include/rxrpc/packet.h2
-rw-r--r--net/rxrpc/af_rxrpc.c23
-rw-r--r--net/rxrpc/ar-internal.h10
-rw-r--r--net/rxrpc/call_accept.c2
-rw-r--r--net/rxrpc/conn_service.c11
7 files changed, 71 insertions, 12 deletions
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index b7115ec55e04..2a1662760450 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -433,6 +433,13 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
433 Encrypted checksum plus entire packet padded and encrypted, including 433 Encrypted checksum plus entire packet padded and encrypted, including
434 actual packet length. 434 actual packet length.
435 435
436 (*) RXRPC_UPGRADEABLE_SERVICE
437
438 This is used to indicate that a service socket with two bindings may
439 upgrade one bound service to the other if requested by the client. optval
440 must point to an array of two unsigned short ints. The first is the
441 service ID to upgrade from and the second the service ID to upgrade to.
442
436 443
437======== 444========
438SECURITY 445SECURITY
@@ -588,7 +595,7 @@ A server would be set up to accept operations in the following manner:
588 The keyring can be manipulated after it has been given to the socket. This 595 The keyring can be manipulated after it has been given to the socket. This
589 permits the server to add more keys, replace keys, etc. whilst it is live. 596 permits the server to add more keys, replace keys, etc. whilst it is live.
590 597
591 (2) A local address must then be bound: 598 (3) A local address must then be bound:
592 599
593 struct sockaddr_rxrpc srx = { 600 struct sockaddr_rxrpc srx = {
594 .srx_family = AF_RXRPC, 601 .srx_family = AF_RXRPC,
@@ -604,11 +611,22 @@ A server would be set up to accept operations in the following manner:
604 parameters are the same. The limit is currently two. To do this, bind() 611 parameters are the same. The limit is currently two. To do this, bind()
605 should be called twice. 612 should be called twice.
606 613
607 (3) The server is then set to listen out for incoming calls: 614 (4) If service upgrading is required, first two service IDs must have been
615 bound and then the following option must be set:
616
617 unsigned short service_ids[2] = { from_ID, to_ID };
618 setsockopt(server, SOL_RXRPC, RXRPC_UPGRADEABLE_SERVICE,
619 service_ids, sizeof(service_ids));
620
621 This will automatically upgrade connections on service from_ID to service
622 to_ID if they request it. This will be reflected in msg_name obtained
623 through recvmsg() when the request data is delivered to userspace.
624
625 (5) The server is then set to listen out for incoming calls:
608 626
609 listen(server, 100); 627 listen(server, 100);
610 628
611 (4) The kernel notifies the server of pending incoming connections by sending 629 (6) The kernel notifies the server of pending incoming connections by sending
612 it a message for each. This is received with recvmsg() on the server 630 it a message for each. This is received with recvmsg() on the server
613 socket. It has no data, and has a single dataless control message 631 socket. It has no data, and has a single dataless control message
614 attached: 632 attached:
@@ -620,13 +638,13 @@ A server would be set up to accept operations in the following manner:
620 the time it is accepted - in which case the first call still on the queue 638 the time it is accepted - in which case the first call still on the queue
621 will be accepted. 639 will be accepted.
622 640
623 (5) The server then accepts the new call by issuing a sendmsg() with two 641 (7) The server then accepts the new call by issuing a sendmsg() with two
624 pieces of control data and no actual data: 642 pieces of control data and no actual data:
625 643
626 RXRPC_ACCEPT - indicate connection acceptance 644 RXRPC_ACCEPT - indicate connection acceptance
627 RXRPC_USER_CALL_ID - specify user ID for this call 645 RXRPC_USER_CALL_ID - specify user ID for this call
628 646
629 (6) The first request data packet will then be posted to the server socket for 647 (8) The first request data packet will then be posted to the server socket for
630 recvmsg() to pick up. At that point, the RxRPC address for the call can 648 recvmsg() to pick up. At that point, the RxRPC address for the call can
631 be read from the address fields in the msghdr struct. 649 be read from the address fields in the msghdr struct.
632 650
@@ -638,7 +656,7 @@ A server would be set up to accept operations in the following manner:
638 656
639 RXRPC_USER_CALL_ID - specifies the user ID for this call 657 RXRPC_USER_CALL_ID - specifies the user ID for this call
640 658
641 (8) The reply data should then be posted to the server socket using a series 659 (9) The reply data should then be posted to the server socket using a series
642 of sendmsg() calls, each with the following control messages attached: 660 of sendmsg() calls, each with the following control messages attached:
643 661
644 RXRPC_USER_CALL_ID - specifies the user ID for this call 662 RXRPC_USER_CALL_ID - specifies the user ID for this call
@@ -646,7 +664,7 @@ A server would be set up to accept operations in the following manner:
646 MSG_MORE should be set in msghdr::msg_flags on all but the last message 664 MSG_MORE should be set in msghdr::msg_flags on all but the last message
647 for a particular call. 665 for a particular call.
648 666
649 (9) The final ACK from the client will be posted for retrieval by recvmsg() 667(10) The final ACK from the client will be posted for retrieval by recvmsg()
650 when it is received. It will take the form of a dataless message with two 668 when it is received. It will take the form of a dataless message with two
651 control messages attached: 669 control messages attached:
652 670
@@ -656,7 +674,7 @@ A server would be set up to accept operations in the following manner:
656 MSG_EOR will be flagged to indicate that this is the final message for 674 MSG_EOR will be flagged to indicate that this is the final message for
657 this call. 675 this call.
658 676
659(10) Up to the point the final packet of reply data is sent, the call can be 677(11) Up to the point the final packet of reply data is sent, the call can be
660 aborted by calling sendmsg() with a dataless message with the following 678 aborted by calling sendmsg() with a dataless message with the following
661 control messages attached: 679 control messages attached:
662 680
diff --git a/include/linux/rxrpc.h b/include/linux/rxrpc.h
index c68307bc306f..634116561a6a 100644
--- a/include/linux/rxrpc.h
+++ b/include/linux/rxrpc.h
@@ -37,6 +37,7 @@ struct sockaddr_rxrpc {
37#define RXRPC_SECURITY_KEYRING 2 /* [srvr] set ring of server security keys */ 37#define RXRPC_SECURITY_KEYRING 2 /* [srvr] set ring of server security keys */
38#define RXRPC_EXCLUSIVE_CONNECTION 3 /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */ 38#define RXRPC_EXCLUSIVE_CONNECTION 3 /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */
39#define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */ 39#define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */
40#define RXRPC_UPGRADEABLE_SERVICE 5 /* Upgrade service[0] -> service[1] */
40 41
41/* 42/*
42 * RxRPC control messages 43 * RxRPC control messages
diff --git a/include/rxrpc/packet.h b/include/rxrpc/packet.h
index 703a64b4681a..a2dcfb850b9f 100644
--- a/include/rxrpc/packet.h
+++ b/include/rxrpc/packet.h
@@ -58,6 +58,8 @@ struct rxrpc_wire_header {
58#define RXRPC_SLOW_START_OK 0x20 /* [ACK] slow start supported */ 58#define RXRPC_SLOW_START_OK 0x20 /* [ACK] slow start supported */
59 59
60 uint8_t userStatus; /* app-layer defined status */ 60 uint8_t userStatus; /* app-layer defined status */
61#define RXRPC_USERSTATUS_SERVICE_UPGRADE 0x01 /* AuriStor service upgrade request */
62
61 uint8_t securityIndex; /* security protocol ID */ 63 uint8_t securityIndex; /* security protocol ID */
62 union { 64 union {
63 __be16 _rsvd; /* reserved */ 65 __be16 _rsvd; /* reserved */
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 3b982bca7d22..0c4dc4a7832c 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -490,6 +490,7 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
490{ 490{
491 struct rxrpc_sock *rx = rxrpc_sk(sock->sk); 491 struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
492 unsigned int min_sec_level; 492 unsigned int min_sec_level;
493 u16 service_upgrade[2];
493 int ret; 494 int ret;
494 495
495 _enter(",%d,%d,,%d", level, optname, optlen); 496 _enter(",%d,%d,,%d", level, optname, optlen);
@@ -546,6 +547,28 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
546 rx->min_sec_level = min_sec_level; 547 rx->min_sec_level = min_sec_level;
547 goto success; 548 goto success;
548 549
550 case RXRPC_UPGRADEABLE_SERVICE:
551 ret = -EINVAL;
552 if (optlen != sizeof(service_upgrade) ||
553 rx->service_upgrade.from != 0)
554 goto error;
555 ret = -EISCONN;
556 if (rx->sk.sk_state != RXRPC_SERVER_BOUND2)
557 goto error;
558 ret = -EFAULT;
559 if (copy_from_user(service_upgrade, optval,
560 sizeof(service_upgrade)) != 0)
561 goto error;
562 ret = -EINVAL;
563 if ((service_upgrade[0] != rx->srx.srx_service ||
564 service_upgrade[1] != rx->second_service) &&
565 (service_upgrade[0] != rx->second_service ||
566 service_upgrade[1] != rx->srx.srx_service))
567 goto error;
568 rx->service_upgrade.from = service_upgrade[0];
569 rx->service_upgrade.to = service_upgrade[1];
570 goto success;
571
549 default: 572 default:
550 break; 573 break;
551 } 574 }
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 781fbc253b5a..c1ebd886a53f 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -144,8 +144,13 @@ struct rxrpc_sock {
144#define RXRPC_SECURITY_MAX RXRPC_SECURITY_ENCRYPT 144#define RXRPC_SECURITY_MAX RXRPC_SECURITY_ENCRYPT
145 bool exclusive; /* Exclusive connection for a client socket */ 145 bool exclusive; /* Exclusive connection for a client socket */
146 u16 second_service; /* Additional service bound to the endpoint */ 146 u16 second_service; /* Additional service bound to the endpoint */
147 struct {
148 /* Service upgrade information */
149 u16 from; /* Service ID to upgrade (if not 0) */
150 u16 to; /* service ID to upgrade to */
151 } service_upgrade;
147 sa_family_t family; /* Protocol family created with */ 152 sa_family_t family; /* Protocol family created with */
148 struct sockaddr_rxrpc srx; /* local address */ 153 struct sockaddr_rxrpc srx; /* Primary Service/local addresses */
149 struct sockaddr_rxrpc connect_srx; /* Default client address from connect() */ 154 struct sockaddr_rxrpc connect_srx; /* Default client address from connect() */
150}; 155};
151 156
@@ -861,7 +866,8 @@ static inline void rxrpc_put_connection(struct rxrpc_connection *conn)
861struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *, 866struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *,
862 struct sk_buff *); 867 struct sk_buff *);
863struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t); 868struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t);
864void rxrpc_new_incoming_connection(struct rxrpc_connection *, struct sk_buff *); 869void rxrpc_new_incoming_connection(struct rxrpc_sock *,
870 struct rxrpc_connection *, struct sk_buff *);
865void rxrpc_unpublish_service_conn(struct rxrpc_connection *); 871void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
866 872
867/* 873/*
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 544df53ccf79..0d4d84e8c074 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -296,7 +296,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
296 conn->params.local = local; 296 conn->params.local = local;
297 conn->params.peer = peer; 297 conn->params.peer = peer;
298 rxrpc_see_connection(conn); 298 rxrpc_see_connection(conn);
299 rxrpc_new_incoming_connection(conn, skb); 299 rxrpc_new_incoming_connection(rx, conn, skb);
300 } else { 300 } else {
301 rxrpc_get_connection(conn); 301 rxrpc_get_connection(conn);
302 } 302 }
diff --git a/net/rxrpc/conn_service.c b/net/rxrpc/conn_service.c
index c7f8682a55b2..e60fcd2a4a02 100644
--- a/net/rxrpc/conn_service.c
+++ b/net/rxrpc/conn_service.c
@@ -150,7 +150,8 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
150 * Set up an incoming connection. This is called in BH context with the RCU 150 * Set up an incoming connection. This is called in BH context with the RCU
151 * read lock held. 151 * read lock held.
152 */ 152 */
153void rxrpc_new_incoming_connection(struct rxrpc_connection *conn, 153void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
154 struct rxrpc_connection *conn,
154 struct sk_buff *skb) 155 struct sk_buff *skb)
155{ 156{
156 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 157 struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -168,6 +169,14 @@ void rxrpc_new_incoming_connection(struct rxrpc_connection *conn,
168 else 169 else
169 conn->state = RXRPC_CONN_SERVICE; 170 conn->state = RXRPC_CONN_SERVICE;
170 171
172 /* See if we should upgrade the service. This can only happen on the
173 * first packet on a new connection. Once done, it applies to all
174 * subsequent calls on that connection.
175 */
176 if (sp->hdr.userStatus == RXRPC_USERSTATUS_SERVICE_UPGRADE &&
177 conn->service_id == rx->service_upgrade.from)
178 conn->service_id = rx->service_upgrade.to;
179
171 /* Make the connection a target for incoming packets. */ 180 /* Make the connection a target for incoming packets. */
172 rxrpc_publish_service_conn(conn->params.peer, conn); 181 rxrpc_publish_service_conn(conn->params.peer, conn);
173 182