]> git.proxmox.com Git - mirror_frr.git/blob - lib/frr_zmq.h
doc: Add `show ipv6 rpf X:X::X:X` command to docs
[mirror_frr.git] / lib / frr_zmq.h
1 /*
2 * libzebra ZeroMQ bindings
3 * Copyright (C) 2015 David Lamparter
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the Free
7 * Software Foundation; either version 2 of the License, or (at your option)
8 * any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #ifndef _FRRZMQ_H
21 #define _FRRZMQ_H
22
23 #include "thread.h"
24 #include <zmq.h>
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 /* linking/packaging note: this is a separate library that needs to be
31 * linked into any daemon/library/module that wishes to use its
32 * functionality. The purpose of this is to encapsulate the libzmq
33 * dependency and not make libfrr/FRR itself depend on libzmq.
34 *
35 * libfrrzmq should be put in LDFLAGS/LIBADD *before* either libfrr or
36 * libzmq, and both of these should always be listed, e.g.
37 * foo_LDFLAGS = libfrrzmq.la libfrr.la $(ZEROMQ_LIBS)
38 */
39
40 /* callback integration */
41 struct cb_core {
42 struct thread *thread;
43 void *arg;
44
45 bool cancelled;
46
47 void (*cb_msg)(void *arg, void *zmqsock);
48 void (*cb_part)(void *arg, void *zmqsock, zmq_msg_t *msg,
49 unsigned partnum);
50 void (*cb_error)(void *arg, void *zmqsock);
51 };
52
53 struct frrzmq_cb {
54 void *zmqsock;
55 int fd;
56
57 bool in_cb; /* This context is in a read or write callback. */
58
59 struct cb_core read;
60 struct cb_core write;
61 };
62
63 /* libzmq's context
64 *
65 * this is mostly here as a convenience, it has IPv6 enabled but nothing
66 * else is tied to it; you can use a separate context without problems
67 */
68 extern void *frrzmq_context;
69
70 extern void frrzmq_init(void);
71 extern void frrzmq_finish(void);
72
73 #define _xref_zmq_a(type, f, d, call) \
74 ({ \
75 static const struct xref_threadsched _xref \
76 __attribute__((used)) = { \
77 .xref = XREF_INIT(XREFT_THREADSCHED, NULL, __func__), \
78 .funcname = #f, \
79 .dest = #d, \
80 .thread_type = THREAD_ ## type, \
81 }; \
82 XREF_LINK(_xref.xref); \
83 call; \
84 }) \
85 /* end */
86
87 /* core event registration, one of these 2 macros should be used */
88 #define frrzmq_thread_add_read_msg(m, f, e, a, z, d) \
89 _xref_zmq_a(READ, f, d, \
90 _frrzmq_thread_add_read(&_xref, m, f, NULL, e, a, z, d))
91
92 #define frrzmq_thread_add_read_part(m, f, e, a, z, d) \
93 _xref_zmq_a(READ, f, d, \
94 _frrzmq_thread_add_read(&_xref, m, NULL, f, e, a, z, d))
95
96 #define frrzmq_thread_add_write_msg(m, f, e, a, z, d) \
97 _xref_zmq_a(WRITE, f, d, \
98 _frrzmq_thread_add_write(&_xref, m, f, e, a, z, d))
99
100 struct cb_core;
101 struct frrzmq_cb;
102
103 /* Set up a POLLIN or POLLOUT notification to be called from the libfrr main
104 * loop. This has the following properties:
105 *
106 * - since ZeroMQ works with edge triggered notifications, it will loop and
107 * dispatch as many events as ZeroMQ has pending at the time libfrr calls
108 * into this code
109 * - due to this looping (which means it non-single-issue), the callback is
110 * also persistent. Do _NOT_ re-register the event inside of your
111 * callback function.
112 * - either msgfunc or partfunc will be called (only one can be specified)
113 * - msgfunc is called once for each incoming message
114 * - if partfunc is specified, the message is read and partfunc is called
115 * for each ZeroMQ multi-part subpart. Note that you can't send replies
116 * before all parts have been read because that violates the ZeroMQ FSM.
117 * - write version doesn't allow for partial callback, you must handle the
118 * whole message (all parts) in msgfunc callback
119 * - you can safely cancel the callback from within itself
120 * - installing a callback will check for pending events (ZMQ_EVENTS) and
121 * may schedule the event to run as soon as libfrr is back in its main
122 * loop.
123 */
124 extern int _frrzmq_thread_add_read(
125 const struct xref_threadsched *xref, struct thread_master *master,
126 void (*msgfunc)(void *arg, void *zmqsock),
127 void (*partfunc)(void *arg, void *zmqsock, zmq_msg_t *msg,
128 unsigned partnum),
129 void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
130 struct frrzmq_cb **cb);
131 extern int _frrzmq_thread_add_write(
132 const struct xref_threadsched *xref, struct thread_master *master,
133 void (*msgfunc)(void *arg, void *zmqsock),
134 void (*errfunc)(void *arg, void *zmqsock), void *arg, void *zmqsock,
135 struct frrzmq_cb **cb);
136
137 extern void frrzmq_thread_cancel(struct frrzmq_cb **cb, struct cb_core *core);
138
139 /*
140 * http://api.zeromq.org/4-2:zmq-getsockopt#toc10
141 *
142 * As the descriptor is edge triggered, applications must update the state of
143 * ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.To be more explicit:
144 * after calling zmq_send the socket may become readable (and vice versa)
145 * without triggering a read event on the file descriptor.
146 */
147 extern void frrzmq_check_events(struct frrzmq_cb **cbp, struct cb_core *core,
148 int event);
149
150 #ifdef __cplusplus
151 }
152 #endif
153
154 #endif /* _FRRZMQ_H */