summaryrefslogtreecommitdiffstats
path: root/ctdb
diff options
context:
space:
mode:
authorRonnie Sahlberg <sahlberg@ronnie>2007-10-09 11:56:09 +1000
committerRonnie Sahlberg <sahlberg@ronnie>2007-10-09 11:56:09 +1000
commit80cd82f8e42dead148b141ee9b0521f10529c4fe (patch)
tree1c13a424488791fdf4505caba4b2f88f1fe26315 /ctdb
parent292e9d91095e74a68349089575641fca835d6a3e (diff)
downloadsamba-80cd82f8e42dead148b141ee9b0521f10529c4fe.tar.gz
samba-80cd82f8e42dead148b141ee9b0521f10529c4fe.tar.xz
samba-80cd82f8e42dead148b141ee9b0521f10529c4fe.zip
add a control to send gratious arps from the ctdb daemon
(This used to be ctdb commit 563819dd1acb344f95aabb4bad990b36f7ea4520)
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/client/ctdb_client.c41
-rw-r--r--ctdb/include/ctdb_private.h17
-rw-r--r--ctdb/server/ctdb_control.c3
-rw-r--r--ctdb/server/ctdb_takeover.c86
-rw-r--r--ctdb/tools/ctdb.c28
5 files changed, 174 insertions, 1 deletions
diff --git a/ctdb/client/ctdb_client.c b/ctdb/client/ctdb_client.c
index b816d2d720..8957ad3145 100644
--- a/ctdb/client/ctdb_client.c
+++ b/ctdb/client/ctdb_client.c
@@ -2340,6 +2340,47 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
}
/*
+ send a gratious arp
+ */
+int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
+ struct timeval timeout,
+ uint32_t destnode,
+ struct sockaddr_in *sin,
+ const char *ifname)
+{
+ TDB_DATA data;
+ int32_t res;
+ int ret, len;
+ struct ctdb_control_gratious_arp *gratious_arp;
+ TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
+
+
+ len = strlen(ifname)+1;
+ gratious_arp = talloc_size(tmp_ctx,
+ offsetof(struct ctdb_control_gratious_arp, iface) + len);
+ CTDB_NO_MEMORY(ctdb, gratious_arp);
+
+ gratious_arp->sin = *sin;
+ gratious_arp->len = len;
+ memcpy(&gratious_arp->iface[0], ifname, len);
+
+
+ data.dsize = offsetof(struct ctdb_control_gratious_arp, iface) + len;
+ data.dptr = (unsigned char *)gratious_arp;
+
+ ret = ctdb_control(ctdb, destnode, 0, CTDB_CONTROL_SEND_GRATIOUS_ARP, 0, data, NULL,
+ NULL, &res, &timeout, NULL);
+ if (ret != 0 || res != 0) {
+ DEBUG(0,(__location__ " ctdb_control for gratious_arp failed\n"));
+ talloc_free(tmp_ctx);
+ return -1;
+ }
+
+ talloc_free(tmp_ctx);
+ return 0;
+}
+
+/*
get a list of all tcp tickles that a node knows about for a particular vnn
*/
int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index ea5efabbcd..983871006a 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -471,6 +471,7 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0,
CTDB_CONTROL_DB_ATTACH_PERSISTENT = 61,
CTDB_CONTROL_PERSISTENT_STORE = 62,
CTDB_CONTROL_UPDATE_RECORD = 63,
+ CTDB_CONTROL_SEND_GRATIOUS_ARP = 64,
};
/*
@@ -515,6 +516,15 @@ struct ctdb_control_killtcp {
};
/*
+ struct for send_gratious_arp
+ */
+struct ctdb_control_gratious_arp {
+ struct sockaddr_in sin;
+ uint32_t len;
+ char iface[1];
+};
+
+/*
struct for tcp_add and tcp_remove controls
*/
struct ctdb_control_tcp_vnn {
@@ -1095,6 +1105,7 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata);
int32_t ctdb_control_tcp_remove(struct ctdb_context *ctdb, TDB_DATA indata);
int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn);
int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata);
+int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata);
int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata);
int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata);
@@ -1144,6 +1155,12 @@ int ctdb_ctrl_killtcp(struct ctdb_context *ctdb,
uint32_t destnode,
struct ctdb_control_killtcp *killtcp);
+int ctdb_ctrl_gratious_arp(struct ctdb_context *ctdb,
+ struct timeval timeout,
+ uint32_t destnode,
+ struct sockaddr_in *sin,
+ const char *ifname);
+
int ctdb_ctrl_get_tcp_tickles(struct ctdb_context *ctdb,
struct timeval timeout,
uint32_t destnode,
diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c
index cd6c9c6e52..959705de6e 100644
--- a/ctdb/server/ctdb_control.c
+++ b/ctdb/server/ctdb_control.c
@@ -321,6 +321,9 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
case CTDB_CONTROL_UPDATE_RECORD:
return ctdb_control_update_record(ctdb, c, indata, async_reply);
+ case CTDB_CONTROL_SEND_GRATIOUS_ARP:
+ return ctdb_control_send_gratious_arp(ctdb, indata);
+
default:
DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode));
return -1;
diff --git a/ctdb/server/ctdb_takeover.c b/ctdb/server/ctdb_takeover.c
index a5baa86692..49d8e8741a 100644
--- a/ctdb/server/ctdb_takeover.c
+++ b/ctdb/server/ctdb_takeover.c
@@ -980,7 +980,7 @@ int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
if (vnn == NULL) {
DEBUG(0,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n",
inet_ntoa(p->dest.sin_addr)));
- return-1;
+ return -1;
}
@@ -1651,3 +1651,87 @@ void ctdb_start_tcp_tickle_update(struct ctdb_context *ctdb)
timeval_current_ofs(ctdb->tunable.tickle_update_interval, 0),
ctdb_update_tcp_tickles, ctdb);
}
+
+
+
+
+struct control_gratious_arp {
+ struct ctdb_context *ctdb;
+ struct sockaddr_in sin;
+ const char *iface;
+ int count;
+};
+
+/*
+ send a control_gratuitous arp
+ */
+static void send_gratious_arp(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private_data)
+{
+ int ret;
+ struct control_gratious_arp *arp = talloc_get_type(private_data,
+ struct control_gratious_arp);
+
+DEBUG(0,("SENDING GRATIOUS ARP ip:%s iface:%s\n",inet_ntoa(arp->sin.sin_addr),arp->iface));
+
+ ret = ctdb_sys_send_arp(&arp->sin, arp->iface);
+ if (ret != 0) {
+ DEBUG(0,(__location__ " sending of gratious arp failed (%s)\n", strerror(errno)));
+ }
+
+
+ arp->count++;
+ if (arp->count == CTDB_ARP_REPEAT) {
+ talloc_free(arp);
+ return;
+ }
+
+ event_add_timed(arp->ctdb->ev, arp,
+ timeval_current_ofs(CTDB_ARP_INTERVAL, 0),
+ send_gratious_arp, arp);
+}
+
+
+/*
+ send a gratious arp
+ */
+int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata)
+{
+ struct ctdb_control_gratious_arp *gratious_arp = (struct ctdb_control_gratious_arp *)indata.dptr;
+ struct control_gratious_arp *arp;
+
+
+ /* verify the size of indata */
+ if (indata.dsize < offsetof(struct ctdb_control_gratious_arp, iface)) {
+ DEBUG(0,(__location__ " Too small indata to hold a ctdb_control_gratious_arp structure\n"));
+ return -1;
+ }
+ if (indata.dsize !=
+ ( offsetof(struct ctdb_control_gratious_arp, iface)
+ + gratious_arp->len ) ){
+
+ DEBUG(0,(__location__ " Wrong size of indata. Was %d bytes "
+ "but should be %d bytes\n",
+ indata.dsize,
+ offsetof(struct ctdb_control_gratious_arp, iface)+gratious_arp->len));
+ return -1;
+ }
+
+
+ arp = talloc(ctdb, struct control_gratious_arp);
+ CTDB_NO_MEMORY(ctdb, arp);
+
+ arp->ctdb = ctdb;
+ arp->sin = gratious_arp->sin;
+ arp->iface = talloc_strdup(arp, gratious_arp->iface);
+ CTDB_NO_MEMORY(ctdb, arp->iface);
+ arp->count = 0;
+
+ DEBUG(0,("GRATIOUS ARP for interface [%s] and ip:%s\n",arp->iface,inet_ntoa(arp->sin.sin_addr)));
+
+ event_add_timed(arp->ctdb->ev, arp,
+ timeval_zero(), send_gratious_arp, arp);
+
+ return 0;
+}
+
diff --git a/ctdb/tools/ctdb.c b/ctdb/tools/ctdb.c
index dbefaf946a..d896495cf3 100644
--- a/ctdb/tools/ctdb.c
+++ b/ctdb/tools/ctdb.c
@@ -380,6 +380,33 @@ static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
/*
+ send a gratious arp
+ */
+static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
+{
+ int ret;
+ struct sockaddr_in sin;
+
+ if (argc < 2) {
+ usage();
+ }
+
+ sin.sin_family = AF_INET;
+ if (inet_aton(argv[0], &sin.sin_addr) == 0) {
+ DEBUG(0,("Wrongly formed ip address '%s'\n", argv[0]));
+ return -1;
+ }
+
+ ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &sin, argv[1]);
+ if (ret != 0) {
+ DEBUG(0, ("Unable to send gratious_arp from node %u\n", options.pnn));
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
register a server id
*/
static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
@@ -1071,6 +1098,7 @@ static const struct {
{ "thaw", control_thaw, true, "thaw all databases" },
{ "isnotrecmaster", control_isnotrecmaster, false, "check if the local node is recmaster or not" },
{ "killtcp", kill_tcp, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
+ { "gratiousarp", control_gratious_arp, false, "send a gratious arp", "<ip> <interface>" },
{ "tickle", tickle_tcp, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
{ "gettickles", control_get_tickles, false, "get the list of tickles registered for this ip", "<ip>" },