Move vrrp_net_listen() to vrrp.c:vrrp_listen() and listen control fifo fd. Add CTRL_FIFO event. Close #1715.

This commit is contained in:
Arnaud ANDRE 2016-01-18 12:13:19 +01:00
parent 2d1ea0dc75
commit 2887d74a01
8 changed files with 194 additions and 109 deletions

88
vrrp.c
View file

@ -20,10 +20,15 @@
*/ */
#include <stdio.h> #include <stdio.h>
/* pselect() */
#include <sys/select.h>
#include <signal.h>
#include "vrrp.h" #include "vrrp.h"
#include "vrrp_timer.h"
#include "vrrp_net.h" #include "vrrp_net.h"
#include "vrrp_state.h" #include "vrrp_state.h"
#include "vrrp_ctrl.h"
#include "uvrrpd.h" #include "uvrrpd.h"
#include "bits.h" #include "bits.h"
@ -110,6 +115,89 @@ int vrrp_process(struct vrrp *vrrp, struct vrrp_net *vnet)
return 0; return 0;
} }
/**
* vrrp_listen() - Wait for a event (VRRP pkt, msg on fifo ...)
*
* @return vrrp_event_t
* TIMER if current timer is expired
* another event else
*/
vrrp_event_t vrrp_listen(struct vrrp *vrrp, struct vrrp_net *vnet)
{
struct vrrp_timer *vt;
int max_fd;
/* Check which timer is running
* Advertisement timer or Masterdown timer ?
*/
if (vrrp_timer_is_running(&vrrp->adv_timer)) {
log_debug("vrid %d :: adv_timer is running", vrrp->vrid);
vt = &vrrp->adv_timer;
}
else if (vrrp_timer_is_running(&vrrp->masterdown_timer)) {
log_debug("vrid %d :: masterdown_timer is running", vrrp->vrid);
vt = &vrrp->masterdown_timer;
}
else { /* No timer ? ... exit */
log_error("vrid %d :: no timer running !", vrrp->vrid);
/* TODO die() */
exit(EXIT_FAILURE);
}
/* update timer before pselect() */
if (vrrp_timer_update(vt)) {
log_debug("vrid %d :: timer expired before pselect",
vrrp->vrid);
/* timer expired or invalid */
return TIMER;
}
/* pselect */
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(vnet->socket, &readfds);
FD_SET(vrrp->ctrl.fd, &readfds);
max_fd = max(vnet->socket, vrrp->ctrl.fd);
sigset_t emptyset;
sigemptyset(&emptyset);
/* Wait for packet or timer expiration */
if (pselect
(max_fd + 1, &readfds, NULL, NULL,
(const struct timespec *) &vt->delta, &emptyset) >= 0) {
/* Timer is expired */
if (vrrp_timer_is_expired(vt)) {
log_debug("vrid %d :: timer expired", vrrp->vrid);
return TIMER;
}
/* Else we have received a pkt */
log_debug("vrid %d :: VRRP pkt received", vrrp->vrid);
if (FD_ISSET(vnet->socket, &readfds))
/* check if received is valid or not */
return vrrp_net_recv(vnet, vrrp);
if (FD_ISSET(vrrp->ctrl.fd, &readfds)) {
return vrrp_ctrl_read(vrrp, vnet);
}
}
else { /* Signal or pselect error */
if (errno == EINTR) {
log_debug("vrid %d :: signal caught", vrrp->vrid);
return SIGNAL;
}
log_error("vrid %d :: pselect - %m", vrrp->vrid);
}
return INVALID;
}
/** /**
* vrrp_cleanup() - clean before exiting * vrrp_cleanup() - clean before exiting

15
vrrp.h
View file

@ -29,6 +29,7 @@
#include "vrrp_net.h" #include "vrrp_net.h"
#include "vrrp_timer.h" #include "vrrp_timer.h"
#include "vrrp_state.h" #include "vrrp_state.h"
#include "vrrp_ctrl.h"
/* MAX values */ /* MAX values */
#define VRID_MAX 255 #define VRID_MAX 255
@ -114,9 +115,23 @@ struct vrrp {
struct vrrp_timer masterdown_timer; struct vrrp_timer masterdown_timer;
}; };
/**
* enum vrrp_ret - Return code used in vrrp_net_listen
*/
enum _vrrp_event_type {
VRID_MISMATCH = -2, /* vrid mismatch */
INVALID = -1, /* invalid pkt */
PKT, /* valid packet */
SIGNAL, /* signal catch */
CTRL_FIFO, /* ctrl cmd event */
TIMER /* timer expired */
};
typedef enum _vrrp_event_type vrrp_event_t;
/* funcs */ /* funcs */
void vrrp_init(struct vrrp *vrrp); void vrrp_init(struct vrrp *vrrp);
void vrrp_cleanup(struct vrrp *vrrp); void vrrp_cleanup(struct vrrp *vrrp);
int vrrp_process(struct vrrp *vrrp, struct vrrp_net *vnet); int vrrp_process(struct vrrp *vrrp, struct vrrp_net *vnet);
vrrp_event_t vrrp_listen(struct vrrp *vrrp, struct vrrp_net *vnet);
#endif /* _VRRP_H_ */ #endif /* _VRRP_H_ */

View file

@ -48,6 +48,20 @@ static inline int vrrp_adv_get_priority(const struct vrrp_net *vnet)
return vnet->__pkt.adv.priority; return vnet->__pkt.adv.priority;
} }
/**
* vrrp_adv_set_priority() - set priority in emitted adv pkt
*/
static inline void vrrp_adv_set_priority(struct vrrp_net *vnet, uint8_t prio)
{
struct vrrphdr *pkt = vnet->__adv[2].iov_base;
pkt->priority = prio;
/* recompute chksum */
pkt->chksum = vnet->adv_checksum(vnet, pkt, NULL, NULL);
log_notice("vrid %d :: new prio %d applied", vnet->vrid, pkt->priority);
}
/** /**
* vrrp_adv_addr_to_str() - return source ip from received adv pkt * vrrp_adv_addr_to_str() - return source ip from received adv pkt
* in string format * in string format

View file

@ -28,19 +28,19 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include "vrrp_ctrl.h"
#include "vrrp.h" #include "vrrp.h"
#include "common.h" #include "vrrp_ctrl.h"
#include "vrrp_adv.h"
#include "common.h"
#include "uvrrpd.h" #include "uvrrpd.h"
#include "bits.h" #include "bits.h"
#include "log.h" #include "log.h"
extern unsigned long reg; extern unsigned long reg;
static inline vrrp_event_t vrrp_ctrl_cmd(struct vrrp *vrrp,
static inline vrrp_event_t vrrp_ctrl_cmd(struct vrrp *vrrp); struct vrrp_net *vnet);
/** /**
* flush_fifo() - flush a fifo fd * flush_fifo() - flush a fifo fd
@ -93,6 +93,7 @@ static inline int split_cmd(char *str, char **words_ptr, int max_words,
break; break;
} }
return nword; return nword;
} }
@ -101,7 +102,7 @@ static inline int split_cmd(char *str, char **words_ptr, int max_words,
*/ */
int vrrp_ctrl_init(struct vrrp_ctrl *ctrl) int vrrp_ctrl_init(struct vrrp_ctrl *ctrl)
{ {
ctrl->cmd = malloc(sizeof(char *) * CTRL_CMD_TOKEN); ctrl->cmd = malloc(sizeof(char *) * CTRL_CMD_NTOKEN);
if (ctrl->cmd == NULL) { if (ctrl->cmd == NULL) {
log_error("init :: malloc - %m"); log_error("init :: malloc - %m");
@ -114,51 +115,105 @@ int vrrp_ctrl_init(struct vrrp_ctrl *ctrl)
} }
/**
* vrrp_ctrl_cmd_flush() - Flush cmd
*/
static inline void vrrp_ctrl_cmd_flush(struct vrrp_ctrl *ctrl)
{
if (ctrl == NULL)
return;
/* clean buff */
for (int i = 0; i < CTRL_CMD_NTOKEN; ctrl->cmd[i++] = NULL);
bzero(ctrl->msg, CTRL_MAXCHAR);
}
/** /**
* vrrp_ctrl_cmd() - Interprete control fifo cmd * vrrp_ctrl_cmd() - Interprete control fifo cmd
*/ */
static inline vrrp_event_t vrrp_ctrl_cmd(struct vrrp *vrrp) static inline vrrp_event_t vrrp_ctrl_cmd(struct vrrp *vrrp,
struct vrrp_net *vnet)
{ {
int nword; int nword;
nword = nword =
split_cmd(vrrp->ctrl.msg, vrrp->ctrl.cmd, CTRL_CMD_TOKEN, split_cmd(vrrp->ctrl.msg, vrrp->ctrl.cmd, CTRL_CMD_NTOKEN,
WHITESPACE); WHITESPACE);
if (nword == 0) if (nword == 0)
return INVALID; return INVALID;
/*
* control cmd stop
*/
if (matches(vrrp->ctrl.cmd[0], "stop")) { if (matches(vrrp->ctrl.cmd[0], "stop")) {
log_notice("vrid %d :: control cmd stop, exiting", vrrp->vrid); log_notice("vrid %d :: control cmd stop, exiting", vrrp->vrid);
set_bit(UVRRPD_RELOAD, &reg); set_bit(UVRRPD_RELOAD, &reg);
clear_bit(KEEP_GOING, &reg); clear_bit(KEEP_GOING, &reg);
vrrp_ctrl_cmd_flush(&vrrp->ctrl);
return CTRL_FIFO; return CTRL_FIFO;
} }
/*
* control cmd reload
*/
if (matches(vrrp->ctrl.cmd[0], "reload")) { if (matches(vrrp->ctrl.cmd[0], "reload")) {
set_bit(UVRRPD_RELOAD, &reg); set_bit(UVRRPD_RELOAD, &reg);
vrrp_ctrl_cmd_flush(&vrrp->ctrl);
return CTRL_FIFO; return CTRL_FIFO;
} }
/*
* control cmd state || status
*/
if (matches(vrrp->ctrl.cmd[0], "state") if (matches(vrrp->ctrl.cmd[0], "state")
|| matches(vrrp->ctrl.cmd[0], "status")) { || matches(vrrp->ctrl.cmd[0], "status")) {
set_bit(UVRRPD_DUMP, &reg); set_bit(UVRRPD_DUMP, &reg);
/* dump state in logs */ vrrp_ctrl_cmd_flush(&vrrp->ctrl);
} }
/*
* control cmd prio
*/
if (matches(vrrp->ctrl.cmd[0], "prio")) { if (matches(vrrp->ctrl.cmd[0], "prio")) {
if (nword != 2) { if (nword != 2) {
/* error */ log_error
("vrid %d :: invalid syntax, control cmd prio <priority>",
vrrp->vrid);
return INVALID; return INVALID;
} }
/* fetch priority */
int err;
unsigned long opt;
err = mystrtoul(&opt, vrrp->ctrl.cmd[1], VRRP_PRIO_MAX);
vrrp_ctrl_cmd_flush(&vrrp->ctrl);
if (err == -ERANGE) {
log_error
("vrid %d :: invalid control cmd prio, 0 < priority < 255",
vrrp->vrid);
return INVALID;
}
if (err == -EINVAL) {
log_error
("vrid %d :: invalid control cmd prio, error parsing \"%s\" as a number",
vrrp->vrid, vrrp->ctrl.cmd[1]);
return INVALID;
}
vrrp->priority = (uint8_t) opt;
/* change prio */ /* change prio */
// todo vrrp_adv_set_priority(vnet, vrrp->priority);
/* reload bit */ /* reload bit */
set_bit(UVRRPD_RELOAD, &reg); set_bit(UVRRPD_RELOAD, &reg);
return CTRL_FIFO; return CTRL_FIFO;
} }
@ -168,7 +223,7 @@ static inline vrrp_event_t vrrp_ctrl_cmd(struct vrrp *vrrp)
/** /**
* vrrp_ctrl_read() - Read control fifo * vrrp_ctrl_read() - Read control fifo
*/ */
vrrp_event_t vrrp_ctrl_read(struct vrrp * vrrp) vrrp_event_t vrrp_ctrl_read(struct vrrp * vrrp, struct vrrp_net * vnet)
{ {
int readbytes = 0; int readbytes = 0;
@ -177,7 +232,7 @@ vrrp_event_t vrrp_ctrl_read(struct vrrp * vrrp)
if (readbytes > 0) { if (readbytes > 0) {
flush_fifo(vrrp->ctrl.fd); flush_fifo(vrrp->ctrl.fd);
vrrp->ctrl.msg[CTRL_MAXCHAR - 1] = '\0'; vrrp->ctrl.msg[CTRL_MAXCHAR - 1] = '\0';
return vrrp_ctrl_cmd(vrrp); return vrrp_ctrl_cmd(vrrp, vnet);
} }
return INVALID; return INVALID;

View file

@ -26,10 +26,11 @@
/* from vrrp.h */ /* from vrrp.h */
struct vrrp; struct vrrp;
struct vrrp_net;
typedef enum _vrrp_event_type vrrp_event_t; typedef enum _vrrp_event_type vrrp_event_t;
#define CTRL_MAXCHAR 64 #define CTRL_MAXCHAR 64
#define CTRL_CMD_TOKENS 3 #define CTRL_CMD_NTOKEN 3
/** /**
* vrrp_ctrl - infos about control fifo * vrrp_ctrl - infos about control fifo
@ -49,7 +50,7 @@ struct vrrp_ctrl {
int vrrp_ctrl_init(struct vrrp_ctrl *ctrl); int vrrp_ctrl_init(struct vrrp_ctrl *ctrl);
void vrrp_ctrl_cleanup(struct vrrp_ctrl *ctrl); void vrrp_ctrl_cleanup(struct vrrp_ctrl *ctrl);
vrrp_event_t vrrp_ctrl_read(struct vrrp *vrrp); vrrp_event_t vrrp_ctrl_read(struct vrrp *vrrp, struct vrrp_net *vnet);
#endif /* _VRRP_CTRL_H_ */ #endif /* _VRRP_CTRL_H_ */

View file

@ -32,16 +32,13 @@
/* ifreq + ioctl */ /* ifreq + ioctl */
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <net/if.h> #include <net/if.h>
/* pselect() */
#include <sys/select.h>
#include <signal.h>
#include <sys/types.h> #include <sys/types.h>
#include <ifaddrs.h> #include <ifaddrs.h>
#include <netdb.h> /* NI_MAXHOST */ #include <netdb.h> /* NI_MAXHOST */
#include "vrrp.h" #include "vrrp.h"
#include "vrrp_net.h" #include "vrrp_net.h"
#include "vrrp_timer.h"
#include "vrrp_adv.h" #include "vrrp_adv.h"
#include "common.h" #include "common.h"
@ -249,80 +246,6 @@ int vrrp_net_vip_set(struct vrrp_net *vnet, const char *ip)
return 0; return 0;
} }
/**
* vrrp_net_listen() - Wait for a VRRP pkt on vnet->socket
*
* @return vrrp_event_t
* TIMER if current timer is expired
* another event else
*/
vrrp_event_t vrrp_net_listen(struct vrrp_net *vnet, struct vrrp *vrrp)
{
struct vrrp_timer *vt;
/* Check which timer is running
* Advertisement timer or Masterdown timer ?
*/
if (vrrp_timer_is_running(&vrrp->adv_timer)) {
log_debug("vrid %d :: adv_timer is running", vrrp->vrid);
vt = &vrrp->adv_timer;
}
else if (vrrp_timer_is_running(&vrrp->masterdown_timer)) {
log_debug("vrid %d :: masterdown_timer is running", vrrp->vrid);
vt = &vrrp->masterdown_timer;
}
else { /* No timer ? ... exit */
log_error("vrid %d :: no timer running !", vrrp->vrid);
/* TODO die() */
exit(EXIT_FAILURE);
}
/* update timer before pselect() */
if (vrrp_timer_update(vt)) {
log_debug("vrid %d :: timer expired before pselect",
vrrp->vrid);
/* timer expired or invalid */
return TIMER;
}
/* pselect */
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(vnet->socket, &readfds);
sigset_t emptyset;
sigemptyset(&emptyset);
/* Wait for packet or timer expiration */
if (pselect
(vnet->socket + 1, &readfds, NULL, NULL,
(const struct timespec *) &vt->delta, &emptyset) >= 0) {
/* Timer is expired */
if (vrrp_timer_is_expired(vt)) {
log_debug("vrid %d :: timer expired", vrrp->vrid);
return TIMER;
}
/* Else we have received a pkt */
log_debug("vrid %d :: VRRP pkt received", vrrp->vrid);
/* check if received is valid or not */
return vrrp_net_recv(vnet, vrrp);
}
else { /* Signal or pselect error */
if (errno == EINTR) {
log_debug("vrid %d :: signal caught", vrrp->vrid);
return SIGNAL;
}
log_error("vrid %d :: pselect - %m", vrrp->vrid);
}
return INVALID;
}
/** /**
* vrrp_net_invalidate_buffer() * vrrp_net_invalidate_buffer()

View file

@ -39,6 +39,7 @@
/* from vrrp.h */ /* from vrrp.h */
struct vrrp; struct vrrp;
typedef enum _vrrp_event_type vrrp_event_t;
/** /**
* constants * constants
@ -136,18 +137,6 @@ struct vrrp_net {
#define ipx_to_str ipx_helper->ipx_ntop #define ipx_to_str ipx_helper->ipx_ntop
#define str_to_ipx ipx_helper->ipx_pton #define str_to_ipx ipx_helper->ipx_pton
/**
* enum vrrp_ret - Return code used in vrrp_net_listen
*/
enum _vrrp_event_type {
VRID_MISMATCH = -2, /* vrid mismatch */
INVALID = -1, /* invalid pkt */
PKT, /* valid packet */
SIGNAL, /* signal catch */
TIMER /* timer expired */
};
typedef enum _vrrp_event_type vrrp_event_t;
/* /*
* funcs * funcs
@ -159,7 +148,6 @@ int vrrp_net_socket_xmit(struct vrrp_net *vnet);
int vrrp_net_vif_getaddr(struct vrrp_net *vnet); int vrrp_net_vif_getaddr(struct vrrp_net *vnet);
int vrrp_net_vif_mtu(struct vrrp_net *vnet); int vrrp_net_vif_mtu(struct vrrp_net *vnet);
int vrrp_net_vip_set(struct vrrp_net *vnet, const char *ip); int vrrp_net_vip_set(struct vrrp_net *vnet, const char *ip);
vrrp_event_t vrrp_net_listen(struct vrrp_net *vnet, struct vrrp *vrrp);
vrrp_event_t vrrp_net_recv(struct vrrp_net *vnet, const struct vrrp *vrrp); vrrp_event_t vrrp_net_recv(struct vrrp_net *vnet, const struct vrrp *vrrp);
int vrrp_net_send(const struct vrrp_net *vnet, struct iovec *iov, size_t len); int vrrp_net_send(const struct vrrp_net *vnet, struct iovec *iov, size_t len);

View file

@ -68,7 +68,7 @@ int vrrp_state_init(struct vrrp *vrrp, struct vrrp_net *vnet)
*/ */
int vrrp_state_backup(struct vrrp *vrrp, struct vrrp_net *vnet) int vrrp_state_backup(struct vrrp *vrrp, struct vrrp_net *vnet)
{ {
int event = vrrp_net_listen(vnet, vrrp); int event = vrrp_listen(vrrp, vnet);
char straddr[INET6_ADDRSTRLEN]; char straddr[INET6_ADDRSTRLEN];
switch (event) { switch (event) {
@ -134,7 +134,7 @@ int vrrp_state_backup(struct vrrp *vrrp, struct vrrp_net *vnet)
case SIGNAL: case SIGNAL:
log_debug("vrid %d :: signal", vrrp->vrid); log_debug("vrid %d :: signal", vrrp->vrid);
case CTRL_FIFO:
/* shutdown/reload event ? */ /* shutdown/reload event ? */
if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) { if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) {
vrrp_timer_clear(&vrrp->masterdown_timer); vrrp_timer_clear(&vrrp->masterdown_timer);
@ -168,7 +168,7 @@ int vrrp_state_backup(struct vrrp *vrrp, struct vrrp_net *vnet)
*/ */
int vrrp_state_master(struct vrrp *vrrp, struct vrrp_net *vnet) int vrrp_state_master(struct vrrp *vrrp, struct vrrp_net *vnet)
{ {
int event = vrrp_net_listen(vnet, vrrp); int event = vrrp_listen(vrrp, vnet);
switch (event) { switch (event) {
case TIMER: /* TIMER expired */ case TIMER: /* TIMER expired */
@ -245,6 +245,7 @@ int vrrp_state_master(struct vrrp *vrrp, struct vrrp_net *vnet)
case SIGNAL: case SIGNAL:
log_debug("vrid %d :: signal", vrrp->vrid); log_debug("vrid %d :: signal", vrrp->vrid);
case CTRL_FIFO:
/* shutdown/reload event ? */ /* shutdown/reload event ? */
if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) { if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) {