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>
/* pselect() */
#include <sys/select.h>
#include <signal.h>
#include "vrrp.h"
#include "vrrp_timer.h"
#include "vrrp_net.h"
#include "vrrp_state.h"
#include "vrrp_ctrl.h"
#include "uvrrpd.h"
#include "bits.h"
@ -110,6 +115,89 @@ int vrrp_process(struct vrrp *vrrp, struct vrrp_net *vnet)
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

15
vrrp.h
View File

@ -29,6 +29,7 @@
#include "vrrp_net.h"
#include "vrrp_timer.h"
#include "vrrp_state.h"
#include "vrrp_ctrl.h"
/* MAX values */
#define VRID_MAX 255
@ -114,9 +115,23 @@ struct vrrp {
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 */
void vrrp_init(struct vrrp *vrrp);
void vrrp_cleanup(struct vrrp *vrrp);
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_ */

View File

@ -48,6 +48,20 @@ static inline int vrrp_adv_get_priority(const struct vrrp_net *vnet)
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
* in string format

View File

@ -28,19 +28,19 @@
#include <string.h>
#include <ctype.h>
#include "vrrp_ctrl.h"
#include "vrrp.h"
#include "common.h"
#include "vrrp_ctrl.h"
#include "vrrp_adv.h"
#include "common.h"
#include "uvrrpd.h"
#include "bits.h"
#include "log.h"
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
@ -93,6 +93,7 @@ static inline int split_cmd(char *str, char **words_ptr, int max_words,
break;
}
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)
{
ctrl->cmd = malloc(sizeof(char *) * CTRL_CMD_TOKEN);
ctrl->cmd = malloc(sizeof(char *) * CTRL_CMD_NTOKEN);
if (ctrl->cmd == NULL) {
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
*/
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;
nword =
split_cmd(vrrp->ctrl.msg, vrrp->ctrl.cmd, CTRL_CMD_TOKEN,
split_cmd(vrrp->ctrl.msg, vrrp->ctrl.cmd, CTRL_CMD_NTOKEN,
WHITESPACE);
if (nword == 0)
return INVALID;
/*
* control cmd stop
*/
if (matches(vrrp->ctrl.cmd[0], "stop")) {
log_notice("vrid %d :: control cmd stop, exiting", vrrp->vrid);
set_bit(UVRRPD_RELOAD, &reg);
clear_bit(KEEP_GOING, &reg);
vrrp_ctrl_cmd_flush(&vrrp->ctrl);
return CTRL_FIFO;
}
/*
* control cmd reload
*/
if (matches(vrrp->ctrl.cmd[0], "reload")) {
set_bit(UVRRPD_RELOAD, &reg);
vrrp_ctrl_cmd_flush(&vrrp->ctrl);
return CTRL_FIFO;
}
/*
* control cmd state || status
*/
if (matches(vrrp->ctrl.cmd[0], "state")
|| matches(vrrp->ctrl.cmd[0], "status")) {
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 (nword != 2) {
/* error */
log_error
("vrid %d :: invalid syntax, control cmd prio <priority>",
vrrp->vrid);
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 */
// todo
vrrp_adv_set_priority(vnet, vrrp->priority);
/* reload bit */
set_bit(UVRRPD_RELOAD, &reg);
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_event_t vrrp_ctrl_read(struct vrrp * vrrp)
vrrp_event_t vrrp_ctrl_read(struct vrrp * vrrp, struct vrrp_net * vnet)
{
int readbytes = 0;
@ -177,7 +232,7 @@ vrrp_event_t vrrp_ctrl_read(struct vrrp * vrrp)
if (readbytes > 0) {
flush_fifo(vrrp->ctrl.fd);
vrrp->ctrl.msg[CTRL_MAXCHAR - 1] = '\0';
return vrrp_ctrl_cmd(vrrp);
return vrrp_ctrl_cmd(vrrp, vnet);
}
return INVALID;

View File

@ -26,10 +26,11 @@
/* from vrrp.h */
struct vrrp;
struct vrrp_net;
typedef enum _vrrp_event_type vrrp_event_t;
#define CTRL_MAXCHAR 64
#define CTRL_CMD_TOKENS 3
#define CTRL_CMD_NTOKEN 3
/**
* vrrp_ctrl - infos about control fifo
@ -49,7 +50,7 @@ struct vrrp_ctrl {
int vrrp_ctrl_init(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_ */

View File

@ -32,16 +32,13 @@
/* ifreq + ioctl */
#include <sys/ioctl.h>
#include <net/if.h>
/* pselect() */
#include <sys/select.h>
#include <signal.h>
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h> /* NI_MAXHOST */
#include "vrrp.h"
#include "vrrp_net.h"
#include "vrrp_timer.h"
#include "vrrp_adv.h"
#include "common.h"
@ -249,80 +246,6 @@ int vrrp_net_vip_set(struct vrrp_net *vnet, const char *ip)
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()

View File

@ -39,6 +39,7 @@
/* from vrrp.h */
struct vrrp;
typedef enum _vrrp_event_type vrrp_event_t;
/**
* constants
@ -136,18 +137,6 @@ struct vrrp_net {
#define ipx_to_str ipx_helper->ipx_ntop
#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
@ -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_mtu(struct vrrp_net *vnet);
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);
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 event = vrrp_net_listen(vnet, vrrp);
int event = vrrp_listen(vrrp, vnet);
char straddr[INET6_ADDRSTRLEN];
switch (event) {
@ -134,7 +134,7 @@ int vrrp_state_backup(struct vrrp *vrrp, struct vrrp_net *vnet)
case SIGNAL:
log_debug("vrid %d :: signal", vrrp->vrid);
case CTRL_FIFO:
/* shutdown/reload event ? */
if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) {
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 event = vrrp_net_listen(vnet, vrrp);
int event = vrrp_listen(vrrp, vnet);
switch (event) {
case TIMER: /* TIMER expired */
@ -245,6 +245,7 @@ int vrrp_state_master(struct vrrp *vrrp, struct vrrp_net *vnet)
case SIGNAL:
log_debug("vrid %d :: signal", vrrp->vrid);
case CTRL_FIFO:
/* shutdown/reload event ? */
if (test_and_clear_bit(UVRRPD_RELOAD, &reg)) {