summaryrefslogtreecommitdiffstats
path: root/ldpd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2017-02-01 12:51:54 +0100
committerRenato Westphal <renato@opensourcerouting.org>2017-02-02 00:55:47 +0100
commit28e8294caa010c246bccbff308cb2118b7d52bdb (patch)
tree420b6245cc9d0d869b94d8b183d267e9b6241819 /ldpd
parentldpd: fix a bug in the explicit-null command (diff)
downloadfrr-28e8294caa010c246bccbff308cb2118b7d52bdb.tar.xz
frr-28e8294caa010c246bccbff308cb2118b7d52bdb.zip
ldpd: add synchronous IPC channels
By default all ldpd interprocess communication is asynchronous (non-blocking socketpairs). Under some circumstances, however, we'll need synchronous IPC as well. Examples: * the lde child process requesting labels to zebra (through the parent process); * apply an access-list on a given IP prefix (ACLs are only available in the parent process). This patch only adds the necessary infrastructure to allow the child processes to make synchronous requests to the parent process. Later patches will make use of this new infrastructure. Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
Diffstat (limited to 'ldpd')
-rw-r--r--ldpd/lde.c16
-rw-r--r--ldpd/ldpd.c66
-rw-r--r--ldpd/ldpd.h3
-rw-r--r--ldpd/ldpe.c16
4 files changed, 72 insertions, 29 deletions
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 91b2b1727..a28862881 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -58,7 +58,7 @@ struct ldpd_conf *ldeconf;
struct nbr_tree lde_nbrs = RB_INITIALIZER(&lde_nbrs);
static struct imsgev *iev_ldpe;
-static struct imsgev *iev_main;
+static struct imsgev *iev_main, *iev_main_sync;
/* Master of threads. */
struct thread_master *master;
@@ -133,15 +133,18 @@ lde(const char *user, const char *group)
/* setup signal handler */
signal_init(master, array_size(lde_signals), lde_signals);
- /* setup pipe and event handler to the parent process */
- if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
+ /* setup pipes and event handlers to the parent process */
+ if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
fatal(NULL);
- imsg_init(&iev_main->ibuf, 3);
+ imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
iev_main->handler_read = lde_dispatch_parent;
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
iev_main, iev_main->ibuf.fd);
iev_main->handler_write = ldp_write_handler;
- iev_main->ev_write = NULL;
+
+ if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
+ fatal(NULL);
+ imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
/* start the LIB garbage collector */
lde_gc_start_timer();
@@ -162,6 +165,8 @@ lde_shutdown(void)
close(iev_ldpe->ibuf.fd);
msgbuf_clear(&iev_main->ibuf.w);
close(iev_main->ibuf.fd);
+ msgbuf_clear(&iev_main_sync->ibuf.w);
+ close(iev_main_sync->ibuf.fd);
lde_gc_stop_timer();
lde_nbr_clear();
@@ -171,6 +176,7 @@ lde_shutdown(void)
free(iev_ldpe);
free(iev_main);
+ free(iev_main_sync);
log_info("label decision engine exiting");
exit(0);
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index c9f4e37ee..6fd4251ed 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -42,7 +42,7 @@
#include "qobj.h"
static void ldpd_shutdown(void);
-static pid_t start_child(enum ldpd_process, char *, int,
+static pid_t start_child(enum ldpd_process, char *, int, int,
const char *, const char *);
static int main_dispatch_ldpe(struct thread *);
static int main_dispatch_lde(struct thread *);
@@ -77,8 +77,8 @@ DEFINE_QOBJ_TYPE(ldpd_conf)
struct ldpd_global global;
struct ldpd_conf *ldpd_conf;
-static struct imsgev *iev_ldpe;
-static struct imsgev *iev_lde;
+static struct imsgev *iev_ldpe, *iev_ldpe_sync;
+static struct imsgev *iev_lde, *iev_lde_sync;
static pid_t ldpe_pid;
static pid_t lde_pid;
@@ -207,8 +207,8 @@ main(int argc, char *argv[])
{
char *saved_argv0;
int lflag = 0, eflag = 0;
- int pipe_parent2ldpe[2];
- int pipe_parent2lde[2];
+ int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
+ int pipe_parent2lde[2], pipe_parent2lde_sync[2];
char *p;
char *vty_addr = NULL;
int vty_port = LDP_VTY_PORT;
@@ -347,22 +347,34 @@ main(int argc, char *argv[])
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2ldpe) == -1)
fatal("socketpair");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
+ pipe_parent2ldpe_sync) == -1)
+ fatal("socketpair");
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
fatal("socketpair");
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
+ pipe_parent2lde_sync) == -1)
+ fatal("socketpair");
sock_set_nonblock(pipe_parent2ldpe[0]);
sock_set_cloexec(pipe_parent2ldpe[0]);
sock_set_nonblock(pipe_parent2ldpe[1]);
sock_set_cloexec(pipe_parent2ldpe[1]);
+ sock_set_nonblock(pipe_parent2ldpe_sync[0]);
+ sock_set_cloexec(pipe_parent2ldpe_sync[0]);
+ sock_set_cloexec(pipe_parent2ldpe_sync[1]);
sock_set_nonblock(pipe_parent2lde[0]);
sock_set_cloexec(pipe_parent2lde[0]);
sock_set_nonblock(pipe_parent2lde[1]);
sock_set_cloexec(pipe_parent2lde[1]);
+ sock_set_nonblock(pipe_parent2lde_sync[0]);
+ sock_set_cloexec(pipe_parent2lde_sync[0]);
+ sock_set_cloexec(pipe_parent2lde_sync[1]);
/* start children */
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
- pipe_parent2lde[1], user, group);
+ pipe_parent2lde[1], pipe_parent2lde_sync[1], user, group);
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
- pipe_parent2ldpe[1], user, group);
+ pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], user, group);
/* drop privileges */
if (user)
@@ -378,22 +390,34 @@ main(int argc, char *argv[])
ldp_zebra_init(master);
/* setup pipes to children */
- if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL ||
- (iev_lde = malloc(sizeof(struct imsgev))) == NULL)
+ if ((iev_ldpe = calloc(1, sizeof(struct imsgev))) == NULL ||
+ (iev_ldpe_sync = calloc(1, sizeof(struct imsgev))) == NULL ||
+ (iev_lde = calloc(1, sizeof(struct imsgev))) == NULL ||
+ (iev_lde_sync = calloc(1, sizeof(struct imsgev))) == NULL)
fatal(NULL);
imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
iev_ldpe->handler_read = main_dispatch_ldpe;
iev_ldpe->ev_read = thread_add_read(master, iev_ldpe->handler_read,
iev_ldpe, iev_ldpe->ibuf.fd);
iev_ldpe->handler_write = ldp_write_handler;
- iev_ldpe->ev_write = NULL;
+
+ imsg_init(&iev_ldpe_sync->ibuf, pipe_parent2ldpe_sync[0]);
+ iev_ldpe_sync->handler_read = main_dispatch_ldpe;
+ iev_ldpe_sync->ev_read = thread_add_read(master,
+ iev_ldpe_sync->handler_read, iev_ldpe_sync, iev_ldpe_sync->ibuf.fd);
+ iev_ldpe_sync->handler_write = ldp_write_handler;
imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
iev_lde->handler_read = main_dispatch_lde;
iev_lde->ev_read = thread_add_read(master, iev_lde->handler_read,
iev_lde, iev_lde->ibuf.fd);
iev_lde->handler_write = ldp_write_handler;
- iev_lde->ev_write = NULL;
+
+ imsg_init(&iev_lde_sync->ibuf, pipe_parent2lde_sync[0]);
+ iev_lde_sync->handler_read = main_dispatch_lde;
+ iev_lde_sync->ev_read = thread_add_read(master,
+ iev_lde_sync->handler_read, iev_lde_sync, iev_lde_sync->ibuf.fd);
+ iev_lde_sync->handler_write = ldp_write_handler;
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf))
fatal("could not establish imsg links");
@@ -466,8 +490,8 @@ ldpd_shutdown(void)
}
static pid_t
-start_child(enum ldpd_process p, char *argv0, int fd, const char *user,
- const char *group)
+start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
+ const char *user, const char *group)
{
char *argv[7];
int argc = 0;
@@ -479,12 +503,15 @@ start_child(enum ldpd_process p, char *argv0, int fd, const char *user,
case 0:
break;
default:
- close(fd);
+ close(fd_async);
+ close(fd_sync);
return (pid);
}
- if (dup2(fd, 3) == -1)
- fatal("cannot setup imsg fd");
+ if (dup2(fd_async, LDPD_FD_ASYNC) == -1)
+ fatal("cannot setup imsg async fd");
+ if (dup2(fd_sync, LDPD_FD_SYNC) == -1)
+ fatal("cannot setup imsg sync fd");
argv[argc++] = argv0;
switch (p) {
@@ -702,10 +729,11 @@ main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len)
void
imsg_event_add(struct imsgev *iev)
{
- THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev,
- iev->ibuf.fd);
+ if (iev->handler_read)
+ THREAD_READ_ON(master, iev->ev_read, iev->handler_read, iev,
+ iev->ibuf.fd);
- if (iev->ibuf.w.queued)
+ if (iev->handler_write && iev->ibuf.w.queued)
THREAD_WRITE_ON(master, iev->ev_write, iev->handler_write, iev,
iev->ibuf.fd);
}
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index 3f6d7ac56..2c9706cf4 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -33,6 +33,9 @@
#define CONF_FILE "/etc/ldpd.conf"
#define LDPD_USER "_ldpd"
+#define LDPD_FD_ASYNC 3
+#define LDPD_FD_SYNC 4
+
#define LDPD_OPT_VERBOSE 0x00000001
#define LDPD_OPT_VERBOSE2 0x00000002
#define LDPD_OPT_NOACTION 0x00000004
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index 1a60af8f4..236e71f32 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -48,7 +48,7 @@ struct ldpd_conf *leconf;
struct ldpd_sysdep sysdep;
#endif
-static struct imsgev *iev_main;
+static struct imsgev *iev_main, *iev_main_sync;
static struct imsgev *iev_lde;
#ifdef __OpenBSD__
static struct thread *pfkey_ev;
@@ -142,15 +142,18 @@ ldpe(const char *user, const char *group)
/* setup signal handler */
signal_init(master, array_size(ldpe_signals), ldpe_signals);
- /* setup pipe and event handler to the parent process */
- if ((iev_main = malloc(sizeof(struct imsgev))) == NULL)
+ /* setup pipes and event handlers to the parent process */
+ if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL)
fatal(NULL);
- imsg_init(&iev_main->ibuf, 3);
+ imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC);
iev_main->handler_read = ldpe_dispatch_main;
iev_main->ev_read = thread_add_read(master, iev_main->handler_read,
iev_main, iev_main->ibuf.fd);
iev_main->handler_write = ldp_write_handler;
- iev_main->ev_write = NULL;
+
+ if ((iev_main_sync = calloc(1, sizeof(struct imsgev))) == NULL)
+ fatal(NULL);
+ imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC);
#ifdef __OpenBSD__
if (sysdep.no_pfkey == 0)
@@ -191,6 +194,8 @@ ldpe_shutdown(void)
msgbuf_write(&iev_main->ibuf.w);
msgbuf_clear(&iev_main->ibuf.w);
close(iev_main->ibuf.fd);
+ msgbuf_clear(&iev_main_sync->ibuf.w);
+ close(iev_main_sync->ibuf.fd);
control_cleanup();
config_clear(leconf);
@@ -215,6 +220,7 @@ ldpe_shutdown(void)
/* clean up */
free(iev_lde);
free(iev_main);
+ free(iev_main_sync);
free(pkt_ptr);
log_info("ldp engine exiting");