aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Hall <julian.hall@arm.com>2021-06-25 10:15:01 +0100
committerGyorgy Szing <Gyorgy.Szing@arm.com>2021-10-05 22:55:46 +0200
commita6b3e1cf8b42df109d6d73c1e9beb6a6c83cb631 (patch)
tree7cf5b0baee6b249bc942a7bd693cd12b4ef5a5e7
parentd03aced2891b8cffdba0517d3119958df0d3b46c (diff)
downloadtrusted-services-a6b3e1cf8b42df109d6d73c1e9beb6a6c83cb631.tar.gz
Add RPC demux component
To support multiple co-located service providers, the rpc_demux may be used. It presents a single input rpc_interface and demultiplexes incoming call requests to 1..* attached outputs using the interface_id parameter carried by the underlying RPC. Signed-off-by: Julian Hall <julian.hall@arm.com> Change-Id: I03d7423892cd07d8a8fcd445dbb7dc7e62497455
-rw-r--r--components/rpc/common/demux/component.cmake13
-rw-r--r--components/rpc/common/demux/rpc_demux.c57
-rw-r--r--components/rpc/common/demux/rpc_demux.h78
-rw-r--r--components/rpc/common/endpoint/rpc_interface.h10
-rw-r--r--deployments/component-test/component-test.cmake1
-rw-r--r--protocols/rpc/common/packed-c/status.h3
6 files changed, 160 insertions, 2 deletions
diff --git a/components/rpc/common/demux/component.cmake b/components/rpc/common/demux/component.cmake
new file mode 100644
index 000000000..a02eefc3e
--- /dev/null
+++ b/components/rpc/common/demux/component.cmake
@@ -0,0 +1,13 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+if (NOT DEFINED TGT)
+ message(FATAL_ERROR "mandatory parameter TGT is not defined.")
+endif()
+
+target_sources(${TGT} PRIVATE
+ "${CMAKE_CURRENT_LIST_DIR}/rpc_demux.c"
+ )
diff --git a/components/rpc/common/demux/rpc_demux.c b/components/rpc/common/demux/rpc_demux.c
new file mode 100644
index 000000000..efcc16254
--- /dev/null
+++ b/components/rpc/common/demux/rpc_demux.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+#include <protocols/rpc/common/packed-c/status.h>
+#include "rpc_demux.h"
+
+static rpc_status_t receive(struct rpc_interface *rpc_iface, struct call_req *req)
+{
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERFACE_DOES_NOT_EXIST;
+ struct rpc_demux *context = (struct rpc_demux*)rpc_iface->context;
+
+ unsigned int iface_id = call_req_get_interface_id(req);
+
+ if ((iface_id < RPC_DEMUX_MAX_OUTPUTS) && context->outputs[iface_id]) {
+
+ rpc_status = rpc_interface_receive(context->outputs[iface_id], req);
+ }
+
+ return rpc_status;
+}
+
+struct rpc_interface *rpc_demux_init(struct rpc_demux *context)
+{
+ context->input.receive = receive;
+ context->input.context = context;
+
+ for (unsigned int i = 0; i < RPC_DEMUX_MAX_OUTPUTS; ++i) {
+
+ context->outputs[i] = NULL;
+ }
+
+ return &context->input;
+}
+
+void rpc_demux_deinit(struct rpc_demux *context)
+{
+ (void)context;
+}
+
+void rpc_demux_attach(struct rpc_demux *context,
+ unsigned int iface_id, struct rpc_interface *output)
+{
+ assert(iface_id < RPC_DEMUX_MAX_OUTPUTS);
+ context->outputs[iface_id] = output;
+}
+
+void rpc_demux_dettach(struct rpc_demux *context,
+ unsigned int iface_id)
+{
+ assert(iface_id < RPC_DEMUX_MAX_OUTPUTS);
+ context->outputs[iface_id] = NULL;
+}
diff --git a/components/rpc/common/demux/rpc_demux.h b/components/rpc/common/demux/rpc_demux.h
new file mode 100644
index 000000000..46d7b0fb7
--- /dev/null
+++ b/components/rpc/common/demux/rpc_demux.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef RPC_DEMUX_H
+#define RPC_DEMUX_H
+
+#include <rpc/common/endpoint/rpc_interface.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The default maximum number of output interfaces. May be
+ * overridden to meet needs of deployment if necessary.
+ */
+#ifndef RPC_DEMUX_MAX_OUTPUTS
+#define RPC_DEMUX_MAX_OUTPUTS (8)
+#endif
+
+/** \brief RPC demux
+ *
+ * An rpc_demux is an rpc_interface that demultiplexes incoming call requests
+ * to 1..* output interfaces. Use an rpc_demux when multiple service
+ * providers are co-located and associated with a single RPC endpoint.
+ */
+struct rpc_demux
+{
+ struct rpc_interface input;
+ struct rpc_interface *outputs[RPC_DEMUX_MAX_OUTPUTS];
+};
+
+/**
+ * \brief Initialize an rpc_demux
+ *
+ * After initialization, the required number of output interfaces need
+ * to be attached,
+ *
+ * \param[in] context The instance to initialize
+ *
+ * \return The input rpc_interface
+ */
+struct rpc_interface *rpc_demux_init(struct rpc_demux *context);
+
+/**
+ * \brief Cleans up when the instance is no longer needed
+ *
+ * \param[in] context The instance to de-initialize
+ */
+void rpc_demux_deinit(struct rpc_demux *context);
+
+/**
+ * \brief Attach an output interface
+ *
+ * \param[in] context The rpc_demux instance
+ * \param[in] iface_id The interface id (small integer)
+ * \param[in] output The interface to attach
+ */
+void rpc_demux_attach(struct rpc_demux *context,
+ unsigned int iface_id, struct rpc_interface *output);
+
+/**
+ * \brief Dettach an output interface
+ *
+ * \param[in] context The rpc_demux instance
+ * \param[in] iface_id The interface id (small integer)
+ */
+void rpc_demux_dettach(struct rpc_demux *context,
+ unsigned int iface_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* RPC_DEMUX_H */
diff --git a/components/rpc/common/endpoint/rpc_interface.h b/components/rpc/common/endpoint/rpc_interface.h
index 44e578354..ba949dedc 100644
--- a/components/rpc/common/endpoint/rpc_interface.h
+++ b/components/rpc/common/endpoint/rpc_interface.h
@@ -10,6 +10,7 @@
#include <stddef.h>
#include <stdint.h>
#include <rpc_status.h>
+#include <protocols/rpc/common/packed-c/status.h>
#ifdef __cplusplus
extern "C" {
@@ -120,7 +121,14 @@ struct rpc_interface
static inline rpc_status_t rpc_interface_receive(struct rpc_interface *iface,
struct call_req *req)
{
- return iface->receive(iface, req);
+ rpc_status_t rpc_status = TS_RPC_ERROR_INTERFACE_DOES_NOT_EXIST;
+
+ if (iface) {
+
+ rpc_status = iface->receive(iface, req);
+ }
+
+ return rpc_status;
}
#ifdef __cplusplus
diff --git a/deployments/component-test/component-test.cmake b/deployments/component-test/component-test.cmake
index dfa006825..974e4e262 100644
--- a/deployments/component-test/component-test.cmake
+++ b/deployments/component-test/component-test.cmake
@@ -26,6 +26,7 @@ add_components(
"components/config/ramstore/test"
"components/rpc/common/caller"
"components/rpc/common/interface"
+ "components/rpc/common/demux"
"components/rpc/common/test/protocol"
"components/rpc/direct"
"components/rpc/dummy"
diff --git a/protocols/rpc/common/packed-c/status.h b/protocols/rpc/common/packed-c/status.h
index 3838240df..534f0dfb1 100644
--- a/protocols/rpc/common/packed-c/status.h
+++ b/protocols/rpc/common/packed-c/status.h
@@ -25,7 +25,8 @@ enum
TS_RPC_ERROR_NOT_READY = -7,
TS_RPC_ERROR_INVALID_TRANSACTION = -8,
TS_RPC_ERROR_INTERNAL = -9,
- TS_RPC_ERROR_INVALID_PARAMETER = -10
+ TS_RPC_ERROR_INVALID_PARAMETER = -10,
+ TS_RPC_ERROR_INTERFACE_DOES_NOT_EXIST = -11
};
#endif /* PROTOCOLS_RPC_COMMON_STATUS_H */