Commit 939f72b8 authored by Leigh B. Stoller's avatar Leigh B. Stoller

Add back the cache to avoid generating spurious events when bootinfo

packets are lost; do not send the events if a node has requested
bootinfo within the last 10 seconds; this implies that the bootinfo
reply packet was lost and the node is retrying. This should quiet
things a bit from stated, although eventually this should be dealt
with in stated instead of with this hack.

Mac originally added the cache to proxydhcp. I've added a cache to
bootinfo to solve the same problem (proxydhcp is no longer used),
although I have changed to implementation to use the DBM backend
rather then a one-off hash table. dbopen() with a NULL file argument
creates an in-memory database (no backing store), and I have used the
DB_HASH db type. So, the hash table is done with a couple of calls to
DBM routines.
parent 1bc0444e
......@@ -13,14 +13,26 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <db.h>
#include <fcntl.h>
#include "log.h"
#include "tbdefs.h"
#include "bootwhat.h"
#include "bootinfo.h"
/*
* Minimum number of seconds that must pass before we send another
* event for a node. This is to decrease the number of spurious events
* we get from nodes when bootinfo packets are lost.
*/
#define MINEVENTTIME 10
static void log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo);
static void onhup(int sig);
static char *progname;
static int bicache_init(void);
static int bicache_shutdown(void);
static int bicache_needevent(struct in_addr ipaddr);
int debug = 0;
void
......@@ -86,6 +98,11 @@ main(int argc, char **argv)
error("could not open database");
exit(1);
}
err = bicache_init();
if (err) {
error("could not initialize cache");
exit(1);
}
#ifdef EVENTSYS
err = bievent_init();
if (err) {
......@@ -118,6 +135,8 @@ main(int argc, char **argv)
signal(SIGHUP, onhup);
while (1) {
int needevent = 1;
if ((mlen = recvfrom(sock, &boot_info, sizeof(boot_info),
0, (struct sockaddr *)&client, &length))
< 0) {
......@@ -131,8 +150,10 @@ main(int argc, char **argv)
info("%s: REQUEST (vers %d)\n",
inet_ntoa(client.sin_addr), boot_info.version);
#ifdef EVENTSYS
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEBOOTING);
needevent = bicache_needevent(client.sin_addr);
if (needevent)
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEBOOTING);
#endif
err = query_bootinfo_db(client.sin_addr,
boot_info.version,
......@@ -151,24 +172,26 @@ main(int argc, char **argv)
boot_info.status = BISTAT_SUCCESS;
log_bootwhat(client.sin_addr, boot_whatp);
#ifdef EVENTSYS
switch (boot_whatp->type) {
case BIBOOTWHAT_TYPE_PART:
case BIBOOTWHAT_TYPE_SYSID:
case BIBOOTWHAT_TYPE_MB:
case BIBOOTWHAT_TYPE_MFS:
bievent_send(client.sin_addr,
TBDB_NODESTATE_BOOTING);
break;
case BIBOOTWHAT_TYPE_WAIT:
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEWAIT);
break;
default:
error("%s: invalid boot directive: %d\n",
inet_ntoa(client.sin_addr),
boot_whatp->type);
break;
if (needevent) {
switch (boot_whatp->type) {
case BIBOOTWHAT_TYPE_PART:
case BIBOOTWHAT_TYPE_SYSID:
case BIBOOTWHAT_TYPE_MB:
case BIBOOTWHAT_TYPE_MFS:
bievent_send(client.sin_addr,
TBDB_NODESTATE_BOOTING);
break;
case BIBOOTWHAT_TYPE_WAIT:
bievent_send(client.sin_addr,
TBDB_NODESTATE_PXEWAIT);
break;
default:
error("%s: invalid boot directive: %d\n",
inet_ntoa(client.sin_addr),
boot_whatp->type);
break;
}
}
#endif
}
......@@ -185,6 +208,7 @@ main(int argc, char **argv)
#ifdef EVENTSYS
bievent_shutdown();
#endif
bicache_shutdown();
info("daemon terminating\n");
exit(0);
}
......@@ -203,6 +227,88 @@ onhup(int sig)
}
}
/*
* Simple cache to prevent dups when bootinfo packets get lost.
*/
static DB *dbp;
/*
* Initialize an in-memory DB
*/
static int
bicache_init(void)
{
if ((dbp =
dbopen(NULL, O_CREAT|O_TRUNC|O_RDWR, 664, DB_HASH, NULL)) == NULL) {
errorc("failed to initialize the bootinfo DBM");
return 1;
}
return 0;
}
static int
bicache_shutdown(void)
{
if (dbp) {
if (dbp->close(dbp) < 0) {
errorc("failed to sutdown the bootinfo DBM");
return 1;
}
}
return 0;
}
/*
* This does both a check and an insert. The idea is that we store the
* current time of the request, returning yes/no to the caller if the
* current request is is within a small delta of the previous request.
* This should keep the number of repeats to a minimum, since a requests
* coming within a few seconds of each other indicate lost bootinfo packets.
*/
static int
bicache_needevent(struct in_addr ipaddr)
{
DBT key, item;
time_t tt = time(NULL);
int rval = 1, r;
key.data = (void *) &ipaddr;
key.size = sizeof(ipaddr);
/*
* First find current value.
*/
if ((r = (dbp->get)(dbp, &key, &item, NULL)) != NULL) {
if (r == -1) {
errorc("Could not retrieve entry from DBM for %s\n",
inet_ntoa(ipaddr));
}
}
if (r == NULL) {
time_t oldtt = *((time_t *)item.data);
if (debug) {
info("Timestamps: old:%ld new:%ld\n", oldtt, tt);
}
if (tt - oldtt <= MINEVENTTIME) {
rval = 0;
info("%s: no event will be sent: last:%ld cur:%ld\n",
inet_ntoa(ipaddr), oldtt, tt);
}
}
if (rval) {
item.data = (void *) &tt;
item.size = sizeof(tt);
if ((dbp->put)(dbp, &key, &item, NULL) != NULL) {
errorc("Could not insert DBM entry for %s\n",
inet_ntoa(ipaddr));
}
}
return rval;
}
static void
log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo)
{
......@@ -234,3 +340,4 @@ log_bootwhat(struct in_addr ipaddr, boot_what_t *bootinfo)
info("%s: REPLY: command line: %s\n", ipstr, bootinfo->cmdline);
}
}
......@@ -8,7 +8,7 @@
#ifndef _OSKIT_BOOT_BOOTWHAT_H_
#define _OSKIT_BOOT_BOOTWHAT_H_
#define BOOTWHAT_DSTPORT 6968
#define BOOTWHAT_DSTPORT 6969
#define BOOTWHAT_SRCPORT 9696
#define BOOTWHAT_SENDPORT 6970
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment