]> git.puffer.fish Git - matthieu/frr.git/commitdiff
ldpd: add synchronous IPC channels
authorRenato Westphal <renato@opensourcerouting.org>
Wed, 1 Feb 2017 11:51:54 +0000 (09:51 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Wed, 1 Feb 2017 23:55:47 +0000 (21:55 -0200)
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>
ldpd/lde.c
ldpd/ldpd.c
ldpd/ldpd.h
ldpd/ldpe.c

index 91b2b1727f170addca0544455f2fea9b26c9901c..a28862881d7c8e177b6bbbb0063fae1697d62948 100644 (file)
@@ -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);
index c9f4e37eeef4320eae2f11659de3a85cfba068a5..6fd4251edcd416474f1d21e882d6260b014e5f96 100644 (file)
@@ -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);
 }
index 3f6d7ac569429247f66b474029c514280bd4a7f3..2c9706cf477f230bb670cfa2412a45ef510b9951 100644 (file)
@@ -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
index 1a60af8f411f6b0c4691cbd2056807f6d4d62f9b..236e71f3220f857ed79b7d6b9d395cf6de818993 100644 (file)
@@ -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");