diff options
Diffstat (limited to 'ctdb')
-rw-r--r-- | ctdb/client/ctdb_client.c | 41 | ||||
-rw-r--r-- | ctdb/include/ctdb_private.h | 17 | ||||
-rw-r--r-- | ctdb/server/ctdb_control.c | 3 | ||||
-rw-r--r-- | ctdb/server/ctdb_takeover.c | 86 | ||||
-rw-r--r-- | ctdb/tools/ctdb.c | 28 |
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>" }, |