File: teamd.h

package info (click to toggle)
libteam 1.12-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,320 kB
  • ctags: 2,189
  • sloc: ansic: 16,808; sh: 1,190; python: 613; makefile: 110
file content (381 lines) | stat: -rw-r--r-- 12,480 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
/*
 *   teamd.h - Network team device daemon
 *   Copyright (C) 2011-2013 Jiri Pirko <jiri@resnulli.us>
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Lesser General Public
 *   License as published by the Free Software Foundation; either
 *   version 2.1 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public
 *   License along with this library; if not, write to the Free Software
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#ifndef _TEAMD_H_
#define _TEAMD_H_

#include <stdbool.h>
#include <stdint.h>
#include <errno.h>
#include <libdaemon/dlog.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <assert.h>
#include <jansson.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <team.h>
#include <private/list.h>

#include "config.h"

#ifdef ENABLE_DBUS
#include <dbus/dbus.h>
#endif

#ifdef ENABLE_ZMQ
#include <zmq.h>
#endif

#define teamd_log_err(args...) daemon_log(LOG_ERR, ##args)
#define teamd_log_warn(args...) daemon_log(LOG_WARNING, ##args)
#define teamd_log_info(args...) daemon_log(LOG_INFO, ##args)
#define teamd_log_dbg(args...) daemon_log(LOG_DEBUG, ##args)

#define teamd_log_dbgx(ctx, val, args...)	\
	if (val <= ctx->debug)			\
		daemon_log(LOG_DEBUG, ##args)

static inline void TEAMD_BUG(void)
{
	teamd_log_dbg("BUG: %s:%d\n", __FILE__, __LINE__);
	assert(0);
}

static inline void TEAMD_BUG_ON(bool condition)
{
	if (condition)
		TEAMD_BUG();
}

#define TEAMD_RUN_DIR "/var/run/teamd/"

static inline int teamd_make_rundir(void)
{
	int ret;

	ret = mkdir(TEAMD_RUN_DIR, 0755);
	if (ret && errno != EEXIST) {
		teamd_log_err("Failed to create directory \"%s\"",
			      TEAMD_RUN_DIR);
		return -errno;
	}
	return 0;
}

enum teamd_command {
	DAEMON_CMD_RUN,
	DAEMON_CMD_KILL,
	DAEMON_CMD_VERSION,
	DAEMON_CMD_HELP,
	DAEMON_CMD_CHECK
};

struct teamd_runner;
struct teamd_context;

struct teamd_context {
	enum teamd_command		cmd;
	bool				daemonize;
	unsigned int			debug;
	bool				force_recreate;
	bool				take_over;
	bool				no_quit_destroy;
	bool				init_no_ports;
	bool				pre_add_ports;
	char *				config_file;
	char *				config_text;
	json_t *			config_json;
	char *				pid_file;
	char *				team_devname;
	char *				ident;
	char *				argv0;
	struct team_handle *		th;
	const struct teamd_runner *	runner;
	void *				runner_priv;
	struct list_item		port_obj_list;
	unsigned int			port_obj_list_count;
	struct list_item                option_watch_list;
	struct list_item		event_watch_list;
	struct list_item		state_ops_list;
	struct list_item		state_val_list;
	uint32_t			ifindex;
	struct team_ifinfo *		ifinfo;
	char *				hwaddr;
	uint32_t			hwaddr_len;
	bool				hwaddr_explicit;
	struct {
		struct list_item		callback_list;
		int				ctrl_pipe_r;
		int				ctrl_pipe_w;
		int				err;
	} run_loop;
#ifdef ENABLE_DBUS
	struct {
		bool			enabled;
		DBusConnection *	con;
	} dbus;
#endif
#ifdef ENABLE_ZMQ
	struct {
		bool			enabled;
		void *			context;
		void *			sock;
		char *			addr;
	} zmq;
#endif
	struct {
		bool			enabled;
		int			sock;
		struct sockaddr_un	addr;
		struct list_item	acc_conn_list;
	} usock;
	struct {
		struct list_item	work_list;
		int			pipe_r;
		int			pipe_w;
	} workq;
};

struct teamd_port {
	uint32_t			ifindex;
	char *				ifname;
	struct team_port *		team_port;
	struct team_ifinfo *		team_ifinfo;
};

struct teamd_runner {
	const char *name;
	const char *team_mode_name;
	size_t priv_size;
	int (*init)(struct teamd_context *ctx, void *priv);
	void (*fini)(struct teamd_context *ctx, void *priv);
};

struct teamd_event_watch_ops {
	int (*hwaddr_changed)(struct teamd_context *ctx, void *priv);
	int (*ifname_changed)(struct teamd_context *ctx, void *priv);
	int (*port_added)(struct teamd_context *ctx,
			  struct teamd_port *tdport, void *priv);
	void (*port_removed)(struct teamd_context *ctx,
			     struct teamd_port *tdport, void *priv);
	int (*port_changed)(struct teamd_context *ctx,
			      struct teamd_port *tdport, void *priv);
	int (*port_link_changed)(struct teamd_context *ctx,
				 struct teamd_port *tdport, void *priv);
	int (*port_hwaddr_changed)(struct teamd_context *ctx,
				   struct teamd_port *tdport, void *priv);
	int (*port_ifname_changed)(struct teamd_context *ctx,
				   struct teamd_port *tdport, void *priv);
	int (*option_changed)(struct teamd_context *ctx,
			      struct team_option *option, void *priv);
	char *option_changed_match_name;
};

int teamd_event_port_added(struct teamd_context *ctx,
			   struct teamd_port *tdport);
void teamd_event_port_removed(struct teamd_context *ctx,
			      struct teamd_port *tdport);
int teamd_event_port_changed(struct teamd_context *ctx,
			     struct teamd_port *tdport);
int teamd_event_port_link_changed(struct teamd_context *ctx,
				  struct teamd_port *tdport);
int teamd_event_option_changed(struct teamd_context *ctx,
			       struct team_option *option);
int teamd_event_ifinfo_hwaddr_changed(struct teamd_context *ctx,
				      struct team_ifinfo *ifinfo);
int teamd_event_ifinfo_ifname_changed(struct teamd_context *ctx,
				      struct team_ifinfo *ifinfo);
int teamd_events_init(struct teamd_context *ctx);
void teamd_events_fini(struct teamd_context *ctx);
int teamd_event_watch_register(struct teamd_context *ctx,
			       const struct teamd_event_watch_ops *ops,
			       void *priv);
void teamd_event_watch_unregister(struct teamd_context *ctx,
				  const struct teamd_event_watch_ops *ops,
				  void *priv);

/* Main loop callbacks */
#define TEAMD_LOOP_FD_EVENT_READ	(1 << 0)
#define TEAMD_LOOP_FD_EVENT_WRITE	(1 << 1)
#define TEAMD_LOOP_FD_EVENT_EXCEPTION	(1 << 2)
#define TEAMD_LOOP_FD_EVENT_MASK	(TEAMD_LOOP_FD_EVENT_READ | \
					 TEAMD_LOOP_FD_EVENT_WRITE | \
					 TEAMD_LOOP_FD_EVENT_EXCEPTION)

typedef int (*teamd_loop_callback_func_t)(struct teamd_context *ctx,
					  int events, void *priv);

int teamd_loop_callback_fd_add(struct teamd_context *ctx,
			       const char *cb_name, void *priv,
			       teamd_loop_callback_func_t func,
			       int fd, int fd_event);
int teamd_loop_callback_fd_add_tail(struct teamd_context *ctx,
				    const char *cb_name, void *priv,
				    teamd_loop_callback_func_t func,
				    int fd, int fd_event);
int teamd_loop_callback_timer_add_set(struct teamd_context *ctx,
				      const char *cb_name, void *priv,
				      teamd_loop_callback_func_t func,
				      struct timespec *interval,
				      struct timespec *initial);
int teamd_loop_callback_timer_add(struct teamd_context *ctx,
				  const char *cb_name, void *priv,
				  teamd_loop_callback_func_t func);
int teamd_loop_callback_timer_set(struct teamd_context *ctx,
				  const char *cb_name, void *priv,
				  struct timespec *interval,
				  struct timespec *initial);
void teamd_loop_callback_del(struct teamd_context *ctx, const char *cb_name,
			     void *priv);
int teamd_loop_callback_enable(struct teamd_context *ctx, const char *cb_name,
			       void *priv);
int teamd_loop_callback_disable(struct teamd_context *ctx, const char *cb_name,
				void *priv);
void teamd_run_loop_quit(struct teamd_context *ctx, int err);
void teamd_run_loop_restart(struct teamd_context *ctx);

int teamd_change_debug_level(struct teamd_context *ctx, unsigned int new_debug);

/* Runner structures */
extern const struct teamd_runner teamd_runner_broadcast;
extern const struct teamd_runner teamd_runner_roundrobin;
extern const struct teamd_runner teamd_runner_random;
extern const struct teamd_runner teamd_runner_activebackup;
extern const struct teamd_runner teamd_runner_loadbalance;
extern const struct teamd_runner teamd_runner_lacp;

struct teamd_port_priv {
	int (*init)(struct teamd_context *ctx, struct teamd_port *tdport,
		    void *this_priv, void *creator_priv);
	void (*fini)(struct teamd_context *ctx, struct teamd_port *tdport,
		     void *this_priv, void *creator_priv);
	size_t priv_size;
};

int teamd_port_priv_create_and_get(void **ppriv, struct teamd_port *tdport,
				   const struct teamd_port_priv *pp,
				   void *creator_priv);
int teamd_port_priv_create(struct teamd_port *tdport,
			   const struct teamd_port_priv *pp, void *creator_priv);
void *teamd_get_next_port_priv_by_creator(struct teamd_port *tdport,
					  void *creator_priv, void *priv);
void *teamd_get_first_port_priv_by_creator(struct teamd_port *tdport,
					   void *creator_priv);
#define teamd_for_each_port_priv_by_creator(priv, tdport, creator_priv)		\
	for (priv = teamd_get_next_port_priv_by_creator(tdport, creator_priv,	\
							NULL);			\
	     priv;								\
	     priv = teamd_get_next_port_priv_by_creator(tdport,	creator_priv,	\
							priv))

int teamd_per_port_init(struct teamd_context *ctx);
void teamd_per_port_fini(struct teamd_context *ctx);
struct teamd_port *teamd_get_port(struct teamd_context *ctx, uint32_t ifindex);
struct teamd_port *teamd_get_port_by_ifname(struct teamd_context *ctx,
					    const char *ifname);
struct teamd_port *teamd_get_next_tdport(struct teamd_context *ctx,
					 struct teamd_port *tdport);
#define teamd_for_each_tdport(tdport, ctx)				\
	for (tdport = teamd_get_next_tdport(ctx, NULL); tdport;		\
	     tdport = teamd_get_next_tdport(ctx, tdport))
static inline bool teamd_has_ports(struct teamd_context *ctx)
{
	return !list_empty(&ctx->port_obj_list);
}

static inline unsigned int teamd_port_count(struct teamd_context *ctx)
{
	return ctx->port_obj_list_count;
}

int teamd_port_add_ifname(struct teamd_context *ctx, const char *port_name);
int teamd_port_remove_ifname(struct teamd_context *ctx, const char *port_name);
int teamd_port_remove_all(struct teamd_context *ctx);
void teamd_port_obj_remove_all(struct teamd_context *ctx);
int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport,
		       bool *enabled);
int teamd_port_prio(struct teamd_context *ctx, struct teamd_port *tdport);
int teamd_port_check_enable(struct teamd_context *ctx,
			    struct teamd_port *tdport,
			    bool should_enable, bool should_disable);

static inline bool teamd_port_present(struct teamd_context *ctx,
				      struct teamd_port *tdport)
{
	return team_is_port_present(ctx->th, tdport->team_port);
}

bool teamd_link_watch_port_up(struct teamd_context *ctx,
			      struct teamd_port *tdport);
void teamd_link_watches_set_forced_active(struct teamd_context *ctx,
					  bool forced_active);
int teamd_link_watch_init(struct teamd_context *ctx);
void teamd_link_watch_fini(struct teamd_context *ctx);

int teamd_option_watch_init(struct teamd_context *ctx);
void teamd_option_watch_fini(struct teamd_context *ctx);

int teamd_ifinfo_watch_init(struct teamd_context *ctx);
void teamd_ifinfo_watch_fini(struct teamd_context *ctx);

struct teamd_balancer;
int teamd_balancer_init(struct teamd_context *ctx, struct teamd_balancer **ptb);
void teamd_balancer_fini(struct teamd_balancer *tb);
int teamd_balancer_port_added(struct teamd_balancer *tb,
			      struct teamd_port *tdport);
void teamd_balancer_port_removed(struct teamd_balancer *tb,
				 struct teamd_port *tdport);

int teamd_hash_func_set(struct teamd_context *ctx);

int teamd_packet_sock_open(int *sock_p, const uint32_t ifindex,
			   const unsigned short family,
			   const struct sock_fprog *fprog,
			   const struct sock_fprog *alt_fprog);
int teamd_getsockname_hwaddr(int sock, struct sockaddr_ll *addr,
			     size_t expected_len);
int teamd_sendto(int sockfd, const void *buf, size_t len, int flags,
		 const struct sockaddr *dest_addr, socklen_t addrlen);
int teamd_recvfrom(int sockfd, void *buf, size_t len, int flags,
		   struct sockaddr *src_addr, socklen_t addrlen);

/* Various helpers */
static inline void ms_to_timespec(struct timespec *ts, int ms)
{
	ts->tv_sec = ms / 1000;
	ts->tv_nsec = (ms % 1000) * 1000000;
}

static inline int timespec_to_ms(struct timespec *ts)
{
	return ts->tv_sec * 1000 + ts->tv_nsec / 1000000;
}

static inline bool timespec_is_zero(struct timespec *ts)
{
	return !ts->tv_sec && !ts->tv_nsec;
}

#define TEAMD_ENOENT(err) (err == -ENOENT || err == -ENODEV)

#endif /* _TEAMD_H_ */