Skip to content

Commit

Permalink
Merge remote-tracking branch 'jedisct1/master'
Browse files Browse the repository at this point in the history
* jedisct1/master:
  replace timer addition with timeradd()
  Indent
  avoid calling syslog() from within signal handler
  indent
  these messages should be DEBUG
  Missing )
  Use the same type for debug as other flags
  make debug a runtime parameter
  microsecond resolution debug timestamps
  remove unused macro
  allow specification of different multicast addresses

Conflicts:
	src/carp.c
	src/globals.h
	src/ucarp.c
	src/ucarp_p.h

* miconda/master - fixed conflicts:
  - remove pid and state files in the new place of handling exit signal
  - make equivalent between the -D and -L DEBUG
  • Loading branch information
miconda committed Jul 25, 2013
2 parents 108bc65 + 9bd90e7 commit 391a407
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 90 deletions.
22 changes: 22 additions & 0 deletions README
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,28 @@ Now unplug the master. After a few seconds, the other host becomes the new
master.


------------------------ MULTICAST IP SELECTION -------------------------

The '--vhid' virtual IP identifier field only is only eight bits, providing up
to 255 different virtual IPs on the same multicast group IP. For larger
deployments, and more flexibility in allocation, ucarp can optionally use a
different multicast IP. By default, ucarp will send/listen on 224.0.0.18, which
is the assigned IP for VRRP. If you want to use a different address, use the
'--mcast' option. Consult the available multicast addresses before deciding
which to use.

http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml
http://tools.ietf.org/html/rfc5771
http://tools.ietf.org/html/rfc2365

Addresses within 239.192.0.0/14 should be most appropriate.

If ucarp isn't working on a different IP, check that your networking gear is
set up to handle it. tcpdump on each host can be handy for diagnosis:

tcpdump -n 'net 224.0.0.0/4'


------------------------ MASTER ELECTION PROCESS ------------------------


Expand Down
133 changes: 52 additions & 81 deletions src/carp.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,8 @@ static void carp_send_ad(struct carp_softc *sc)
int advskew;
int rc;

#ifdef DEBUG
logfile(LOG_DEBUG, "-> carp_send_ad()");
#endif

advbase = sc->sc_advbase;
if (carp_suppress_preempt == 0 ||
sc->sc_advskew > CARP_BULK_UPDATE_MIN_DELAY) {
Expand All @@ -220,8 +219,7 @@ static void carp_send_ad(struct carp_softc *sc)
eth_len = ip_len + sizeof eh;
if ((pkt = ALLOCA(eth_len)) == NULL) {
logfile(LOG_ERR, _("Out of memory to create packet"));
sc->sc_ad_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_ad_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_ad_tmo);
return;
}
ip.ip_v = IPVERSION;
Expand All @@ -239,7 +237,7 @@ static void carp_send_ad(struct carp_softc *sc)
ip.ip_sum = 0;

memcpy(&ip.ip_src, &srcip, sizeof ip.ip_src);
memcpy(&ip.ip_dst.s_addr, inaddr_carp_group, sizeof ip.ip_dst.s_addr);
memcpy(&ip.ip_dst.s_addr, &mcastip, sizeof ip.ip_dst.s_addr);

carp_prepare_ad(&ch, sc);

Expand All @@ -262,12 +260,13 @@ static void carp_send_ad(struct carp_softc *sc)
eh.ether_dhost[4] = 0xff;
eh.ether_dhost[5] = 0xff;
} else {
unsigned int m = ntohl(mcastip.s_addr);
eh.ether_dhost[0] = 0x01;
eh.ether_dhost[1] = 0x00;
eh.ether_dhost[2] = 0x5e;
eh.ether_dhost[3] = 0x00;
eh.ether_dhost[4] = 0x00;
eh.ether_dhost[5] = 0x12;
eh.ether_dhost[3] = m >> 16 & 0x7f;
eh.ether_dhost[4] = m >> 8 & 0xff;
eh.ether_dhost[5] = m & 0xff;
}
eh.ether_type = htons(ETHERTYPE_IP);

Expand All @@ -294,10 +293,8 @@ static void carp_send_ad(struct carp_softc *sc)
sc->sc_sendad_errors++;
}
if (sc->sc_sendad_errors == CARP_SENDAD_MAX_ERRORS) {
#ifdef DEBUG
logfile(LOG_ERR, _("write() error #%d/%d"),
carp_suppress_preempt, CARP_SENDAD_MAX_ERRORS);
#endif
carp_suppress_preempt++;
if (carp_suppress_preempt == 1) {
carp_send_ad_all(sc);
Expand All @@ -315,9 +312,7 @@ static void carp_send_ad(struct carp_softc *sc)
}
}

#ifdef DEBUG
logfile(LOG_DEBUG, _("* advertisement injected *"));
#endif

ALLOCA_FREE(pkt);

Expand All @@ -330,8 +325,7 @@ static void carp_send_ad(struct carp_softc *sc)
sc->sc_delayed_arp = -1;
}
if (advbase != 255 || advskew != 255) {
sc->sc_ad_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_ad_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_ad_tmo);
/* IPv6 ? */
}
}
Expand All @@ -344,9 +338,7 @@ static void carp_setrun(struct carp_softc *sc, sa_family_t af)
{
struct timeval tv;

#ifdef DEBUG
logfile(LOG_DEBUG, "carp_setrun()");
#endif
if (gettimeofday(&now, NULL) != 0) {
logfile(LOG_WARNING, _("initializing now to gettimeofday() failed: %s"),
strerror(errno));
Expand All @@ -362,45 +354,36 @@ static void carp_setrun(struct carp_softc *sc, sa_family_t af)
tv.tv_usec = (unsigned int) (sc->sc_advskew * 1000000ULL / 256ULL);
switch (af) {
case AF_INET:
sc->sc_md_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_md_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_md_tmo);
break;
#ifdef INET6
case AF_INET6:
sc->sc_md6_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_md6_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_md6_tmo);
break;
#endif /* INET6 */
default:
sc->sc_md_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_md_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_md_tmo);
#ifdef INET6
sc->sc_md6_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_md6_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_md6_tmo);
#endif
break;
}
break;
case MASTER:
tv.tv_sec = (unsigned int) sc->sc_advbase;
tv.tv_usec = (unsigned int) (sc->sc_advskew * 1000000ULL / 256ULL);
sc->sc_md_tmo.tv_sec = now.tv_sec + tv.tv_sec;
sc->sc_md_tmo.tv_usec = now.tv_usec + tv.tv_usec;
timeradd(&now, &tv, &sc->sc_md_tmo);
/* No IPv6 scheduling ? */
break;
}
}

static void carp_master_down(struct carp_softc *sc)
{
#ifdef DEBUG
logfile(LOG_DEBUG, "carp_master_down()");
#endif
switch (sc->sc_state) {
case INIT:
#ifdef DEBUG
logfile(LOG_DEBUG, _("master_down event in INIT state"));
#endif
break;
case MASTER:
break;
Expand Down Expand Up @@ -434,7 +417,6 @@ static void packethandler(unsigned char *dummy,
return;
}
memcpy(&etherhead, sp, sizeof etherhead);
#ifdef DEBUG
logfile(LOG_DEBUG, "Ethernet "
"[%02x:%02x:%02x:%02x:%02x:%02x]->[%02x:%02x:%02x:%02x:%02x:%02x] "
"type [%04x]",
Expand All @@ -451,7 +433,6 @@ static void packethandler(unsigned char *dummy,
(unsigned int) etherhead.ether_dhost[4],
(unsigned int) etherhead.ether_dhost[5],
(unsigned int) ntohs(etherhead.ether_type));
#endif
sp += sizeof etherhead;
caplen = header->caplen - sizeof etherhead;
memcpy(&iphead, sp, sizeof iphead);
Expand All @@ -469,22 +450,18 @@ static void packethandler(unsigned char *dummy,
struct timeval sc_tv;
struct timeval ch_tv;

#ifdef DEBUG
logfile(LOG_DEBUG,
"\n---------------------------\n\n"
"carp [%d.%d.%d.%d] -> [%d.%d.%d.%d]",
source >> 24 & 0xff, source >> 16 & 0xff,
source >> 8 & 0xff, source & 0xff,
dest >> 24 & 0xff, dest >> 16 & 0xff,
dest >> 8 & 0xff, dest & 0xff);
#endif
if (caplen < ip_len + sizeof ch) {
#ifdef DEBUG
logfile(LOG_DEBUG,
"Bogus size: caplen=[%u], ip_len=[%u] ch_len=[%u]",
(unsigned int) caplen, (unsigned int) ip_len,
(unsigned int) sizeof ch);
#endif
return;
}
memcpy(&ch, sp + ip_len, sizeof ch);
Expand Down Expand Up @@ -514,12 +491,15 @@ static void packethandler(unsigned char *dummy,
return;
}
if (ch.carp_vhid != vhid) {
#ifdef DEBUG
logfile(LOG_NOTICE, _("Ignoring vhid: [%u]"),
logfile(LOG_DEBUG, _("Ignoring vhid: [%u]"),
(unsigned int) ch.carp_vhid);
#endif
return;
}
if (iphead.ip_dst.s_addr != mcastip.s_addr) {
logfile(LOG_DEBUG, _("Ignoring different multicast ip: [%s]"),
inet_ntoa(iphead.ip_dst));
return;
}
if (cksum(sp, ip_len + sizeof ch) != 0) {
logfile(LOG_WARNING, _("Bad IP checksum"));
return;
Expand Down Expand Up @@ -575,11 +555,9 @@ static void packethandler(unsigned char *dummy,
ch_tv.tv_usec = (unsigned int)
(ch.carp_advskew * 1000000ULL / 256ULL);

#ifdef DEBUG
logfile(LOG_DEBUG, "sc_tv(local) = [%lu] ch_tv(remote) = [%lu]",
(unsigned long) sc_tv.tv_sec,
(unsigned long) ch_tv.tv_sec);
#endif

switch (sc.sc_state) {
case INIT:
Expand Down Expand Up @@ -698,33 +676,18 @@ static void udpu_dispatch(void)

static RETSIGTYPE sighandler_exit(const int sig)
{
(void) sig;
#ifdef DEBUG
logfile(LOG_DEBUG, "sighandler_exit(): Calling [%s] and exiting",
downscript);
#endif
if (sc.sc_state != BACKUP) {
(void) spawn_handler(dev_desc_fd, downscript);
}

if (pid_file != NULL)
unlink(pid_file);

if (state_file != NULL)
unlink(state_file);

_exit(EXIT_SUCCESS);
received_signal=15;
}

static RETSIGTYPE sighandler_usr(const int sig)
{
switch (sig) {
case SIGUSR1:
received_signal=1;
break;
received_signal=1;
break;
case SIGUSR2:
received_signal=2;
break;
received_signal=2;
break;
}
}

Expand All @@ -748,9 +711,7 @@ static char *build_bpf_rule(void)

snprintf(rule, sizeof rule, "proto %u and src host not %s",
(unsigned int) IPPROTO_CARP, srcip_s);
#ifdef DEBUG
logfile(LOG_DEBUG, "BPF rule: [%s]", rule);
#endif

return rule;
}
Expand Down Expand Up @@ -845,7 +806,7 @@ int docarp(void)
}
if (!no_mcast) {
memset(&req_add, 0, sizeof req_add);
req_add.imr_multiaddr.s_addr = inet_addr("224.0.0.18");
req_add.imr_multiaddr.s_addr = mcastip.s_addr;
req_add.imr_interface.s_addr = srcip.s_addr;
if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&req_add, sizeof req_add) < 0) {
Expand Down Expand Up @@ -921,25 +882,35 @@ int docarp(void)
#endif
if (received_signal != 0) {
int flag = received_signal;

received_signal = 0;
switch (flag) {
case 1:
logfile(LOG_INFO, "%s on %s id %d",
(sc.sc_state == BACKUP ? "BACKUP" : "MASTER"),
interface, sc.sc_vhid);
break;
case 2:
#ifdef DEBUG
logfile(LOG_DEBUG, "Caught signal (USR2) considering going down");
#endif
if (sc.sc_state != BACKUP) {
carp_set_state(&sc, BACKUP);
sleep(3); /* hold up a sec... */
carp_setrun(&sc, 0); /* now listen for 3 heartbeats, as usual */
continue;
}
break;
case 1:
logfile(LOG_INFO, "%s on %s id %d",
(sc.sc_state == BACKUP ? "BACKUP" : "MASTER"),
interface, sc.sc_vhid);
break;
case 2:
logfile(LOG_DEBUG, "Caught signal (USR2) considering going down");
if (sc.sc_state != BACKUP) {
carp_set_state(&sc, BACKUP);
sleep(3); /* hold up a sec... */
carp_setrun(&sc, 0); /* now listen for 3 heartbeats, as usual */
continue;
}
break;
case 15:
logfile(LOG_DEBUG, "sighandler_exit(): Calling [%s] and exiting",
downscript);
if (sc.sc_state != BACKUP) {
(void) spawn_handler(dev_desc_fd, downscript);
}
if (pid_file != NULL)
unlink(pid_file);
if (state_file != NULL)
unlink(state_file);
_exit(EXIT_SUCCESS);
break;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
GLOBAL0(char *interface);
GLOBAL0(struct in_addr srcip);
GLOBAL0(char *srcip_arg);
GLOBAL0(struct in_addr mcastip);
GLOBAL0(unsigned char vhid);
GLOBAL0(char *pass);
GLOBAL0(struct in_addr vaddr);
Expand All @@ -20,6 +21,7 @@ GLOBAL(unsigned int dead_ratio, DEFAULT_DEAD_RATIO);
GLOBAL0(unsigned char advskew);
GLOBAL(char *upscript, NULL);
GLOBAL(char *downscript, NULL);
GLOBAL0(signed char debug);
GLOBAL0(signed char preempt);
GLOBAL0(signed char neutral);
GLOBAL0(signed char shutdown_at_exit);
Expand All @@ -32,7 +34,6 @@ GLOBAL(int syslog_facility, DEFAULT_FACILITY);
GLOBAL(int syslog_level, LOG_INFO);
GLOBAL0(char *vaddr_arg);
GLOBAL0(char *xparam);
GLOBAL(unsigned char inaddr_carp_group[4], { 224 _COMA_ 0 _COMA_ 0 _COMA_ 18 });
GLOBAL0(sig_atomic_t received_signal);
GLOBAL(char *udpu_addr, NULL);
GLOBAL(unsigned int udpu_port, 112);
Expand Down
Loading

0 comments on commit 391a407

Please sign in to comment.