From 2887d74a01aa175525f16ddf0d2f934265e49677 Mon Sep 17 00:00:00 2001 From: Arnaud ANDRE Date: Mon, 18 Jan 2016 12:13:19 +0100 Subject: [PATCH] Move vrrp_net_listen() to vrrp.c:vrrp_listen() and listen control fifo fd. Add CTRL_FIFO event. Close #1715. --- vrrp.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++ vrrp.h | 15 +++++++++ vrrp_adv.h | 14 +++++++++ vrrp_ctrl.c | 81 +++++++++++++++++++++++++++++++++++++++-------- vrrp_ctrl.h | 5 +-- vrrp_net.c | 79 +--------------------------------------------- vrrp_net.h | 14 +-------- vrrp_state.c | 7 +++-- 8 files changed, 194 insertions(+), 109 deletions(-) diff --git a/vrrp.c b/vrrp.c index 8589b7f..d12427e 100644 --- a/vrrp.c +++ b/vrrp.c @@ -20,10 +20,15 @@ */ #include +/* pselect() */ +#include +#include #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 diff --git a/vrrp.h b/vrrp.h index 064c79e..3b7bea1 100644 --- a/vrrp.h +++ b/vrrp.h @@ -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_ */ diff --git a/vrrp_adv.h b/vrrp_adv.h index 9920060..8d24e22 100644 --- a/vrrp_adv.h +++ b/vrrp_adv.h @@ -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 diff --git a/vrrp_ctrl.c b/vrrp_ctrl.c index be69a5c..8769b56 100644 --- a/vrrp_ctrl.c +++ b/vrrp_ctrl.c @@ -28,19 +28,19 @@ #include #include -#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, ®); clear_bit(KEEP_GOING, ®); + vrrp_ctrl_cmd_flush(&vrrp->ctrl); return CTRL_FIFO; } + /* + * control cmd reload + */ if (matches(vrrp->ctrl.cmd[0], "reload")) { set_bit(UVRRPD_RELOAD, ®); + 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, ®); - /* 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 ", + 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, ®); + 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; diff --git a/vrrp_ctrl.h b/vrrp_ctrl.h index d02ccf5..b35e267 100644 --- a/vrrp_ctrl.h +++ b/vrrp_ctrl.h @@ -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_ */ diff --git a/vrrp_net.c b/vrrp_net.c index 6e8714c..7893983 100644 --- a/vrrp_net.c +++ b/vrrp_net.c @@ -32,16 +32,13 @@ /* ifreq + ioctl */ #include #include -/* pselect() */ -#include -#include + #include #include #include /* 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() diff --git a/vrrp_net.h b/vrrp_net.h index 2cc04cf..146e36c 100644 --- a/vrrp_net.h +++ b/vrrp_net.h @@ -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); diff --git a/vrrp_state.c b/vrrp_state.c index 6193461..7bc5bf4 100644 --- a/vrrp_state.c +++ b/vrrp_state.c @@ -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, ®)) { 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, ®)) {