Previouly, there is only one way for primary/secondary to exchange
messages, that is, primary process writes info into some predefind
file, and secondary process reads info out. That cannot address
the requirements:
a. Secondary wants to send info to primary.
b. Sending info at any time, instead of just initialization time.
c. Share FD with the other side.
This patch proposes to create a communication channel (as an unix
socket connection) for above requirements.
Three new APIs are added:
1. rte_eal_primary_secondary_add_action is used to register an action,
if the calling component wants to response the messages from the
corresponding component in its primary process or secondary processes.
2. rte_eal_primary_secondary_del_action is used to unregister the
action if the calling component does not want to response the messages.
3. rte_eal_primary_secondary_sendmsg is used to send a message.
Signed-off-by: Jianfeng Tan <jianfeng....@intel.com>
---
lib/librte_eal/bsdapp/eal/rte_eal_version.map | 8 +
lib/librte_eal/common/eal_common_proc.c | 454 ++++++++++++++++++++++++
lib/librte_eal/common/eal_filesystem.h | 18 +
lib/librte_eal/common/eal_private.h | 10 +
lib/librte_eal/common/include/rte_eal.h | 74 ++++
lib/librte_eal/linuxapp/eal/eal.c | 6 +
lib/librte_eal/linuxapp/eal/rte_eal_version.map | 8 +
7 files changed, 578 insertions(+)
diff --git a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
index aac6fd7..f4ff29f 100644
--- a/lib/librte_eal/bsdapp/eal/rte_eal_version.map
+++ b/lib/librte_eal/bsdapp/eal/rte_eal_version.map
@@ -237,3 +237,11 @@ EXPERIMENTAL {
rte_service_unregister;
} DPDK_17.08;
+
+EXPERIMENTAL {
+ global:
+
+ rte_eal_primary_secondary_add_action;
+ rte_eal_primary_secondary_del_action;
+ rte_eal_primary_secondary_sendmsg;
+} DPDK_17.11;
diff --git a/lib/librte_eal/common/eal_common_proc.c
b/lib/librte_eal/common/eal_common_proc.c
index 60526ca..fa316bf 100644
--- a/lib/librte_eal/common/eal_common_proc.c
+++ b/lib/librte_eal/common/eal_common_proc.c
@@ -33,8 +33,20 @@
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <rte_log.h>
#include <rte_eal.h>
+#include <rte_lcore.h>
+#include "eal_private.h"
#include "eal_filesystem.h"
#include "eal_internal_cfg.h"
@@ -59,3 +71,445 @@ rte_eal_primary_proc_alive(const char *config_file_path)
return !!ret;
}
+
+struct action_entry {
+ TAILQ_ENTRY(action_entry) next; /**< Next attached action entry*/
+
+#define MAX_ACTION_NAME_LEN 64
+ char action_name[MAX_ACTION_NAME_LEN];
+ rte_eal_primary_secondary_t *action;
+};
+
+/** Double linked list of actions. */
+TAILQ_HEAD(action_entry_list, action_entry);
+
+static struct action_entry_list action_entry_list =
+ TAILQ_HEAD_INITIALIZER(action_entry_list);
+
+static struct action_entry *
+find_action_entry_by_name(const char *name)
+{
+ int len = strlen(name);
+ struct action_entry *entry;
+
+ TAILQ_FOREACH(entry, &action_entry_list, next) {
+ if (strncmp(entry->action_name, name, len) == 0)
+ break;
+ }
+
+ return entry;
+}
+
+int
+rte_eal_primary_secondary_add_action(const char *action_name,
+ rte_eal_primary_secondary_t action)
+{
+ struct action_entry *entry = malloc(sizeof(struct action_entry));
+
+ if (entry == NULL)
+ return -ENOMEM;
+
+ strncpy(entry->action_name, action_name, MAX_ACTION_NAME_LEN);
+ entry->action = action;
+ TAILQ_INSERT_TAIL(&action_entry_list, entry, next);
+ return 0;
+}
+
+void
+rte_eal_primary_secondary_del_action(const char *name)
+{
+ struct action_entry *entry = find_action_entry_by_name(name);
+
+ TAILQ_REMOVE(&action_entry_list, entry, next);
+ free(entry);
+}
+
+#define MAX_SECONDARY_PROCS 8
+
+static int efd_pri_sec; /* epoll fd for primary/secondary channel thread */
+static int fd_listen; /* unix listen socket by primary */
+static int fd_to_pri; /* only used by secondary process */
+static int fds_to_sec[MAX_SECONDARY_PROCS];
+
+struct msg_hdr {
+ char action_name[MAX_ACTION_NAME_LEN];
+ int fds_num;
+ char params[0];
+} __rte_packed;
+
+static int
+add_sec_proc(int fd)
+{
+ int i;
+
+ for (i = 0; i < MAX_SECONDARY_PROCS; ++i)
+ if (fds_to_sec[i] == -1)
+ break;
+
+ if (i >= MAX_SECONDARY_PROCS)
+ return -1;
+
+ fds_to_sec[i] = fd;
+
+ return i;
+}
+
+static void
+del_sec_proc(int fd)
+{
+ int i;
+
+ for (i = 0; i < MAX_SECONDARY_PROCS; ++i) {
+ if (fds_to_sec[i] == fd) {
+ fds_to_sec[i] = -1;
+ break;
+ }
+ }
+}
+
+static int
+read_msg(int sockfd, char *buf, int buflen, int *fds, int fds_num)
+{
+ struct iovec iov;
+ struct msghdr msgh;
+ size_t fdsize = fds_num * sizeof(int);
+ char control[CMSG_SPACE(fdsize)];
+ struct cmsghdr *cmsg;
+ int ret;
+
+ memset(&msgh, 0, sizeof(msgh));
+ iov.iov_base = buf;
+ iov.iov_len = buflen;
+
+ msgh.msg_iov = &iov;
+ msgh.msg_iovlen = 1;
+ msgh.msg_control = control;
+ msgh.msg_controllen = sizeof(control);
+
+ ret = recvmsg(sockfd, &msgh, 0);
+ if (ret <= 0) {
+ RTE_LOG(ERR, EAL, "recvmsg failed\n");
+ return ret;
+ }
+
+ if (msgh.msg_flags & (MSG_TRUNC | MSG_CTRUNC)) {
+ RTE_LOG(ERR, EAL, "truncted msg\n");
+ return -1;
+ }
+
+ for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
+ if ((cmsg->cmsg_level == SOL_SOCKET) &&
+ (cmsg->cmsg_type == SCM_RIGHTS)) {
+ memcpy(fds, CMSG_DATA(cmsg), fdsize);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int
+process_msg(int fd)
+{
+ int len;
+ int params_len;
+ char buf[1024];