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_ */
|