4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "lib/events/events.h"
22 #include "lib/tdb/include/tdb.h"
23 #include "lib/util/dlinklist.h"
24 #include "system/network.h"
25 #include "system/filesys.h"
26 #include "system/wait.h"
27 #include "../include/ctdb_private.h"
28 #include "../common/rb_tree.h"
31 #define TAKEOVER_TIMEOUT() timeval_current_ofs(ctdb->tunable.takeover_timeout,0)
33 #define CTDB_ARP_INTERVAL 1
34 #define CTDB_ARP_REPEAT 3
36 struct ctdb_takeover_arp {
37 struct ctdb_context *ctdb;
39 struct sockaddr_in sin;
40 struct ctdb_tcp_array *tcparray;
46 lists of tcp endpoints
48 struct ctdb_tcp_list {
49 struct ctdb_tcp_list *prev, *next;
50 struct ctdb_tcp_connection connection;
54 list of clients to kill on IP release
56 struct ctdb_client_ip {
57 struct ctdb_client_ip *prev, *next;
58 struct ctdb_context *ctdb;
59 struct sockaddr_in ip;
67 static void ctdb_control_send_arp(struct event_context *ev, struct timed_event *te,
68 struct timeval t, void *private_data)
70 struct ctdb_takeover_arp *arp = talloc_get_type(private_data,
71 struct ctdb_takeover_arp);
73 struct ctdb_tcp_array *tcparray;
76 ret = ctdb_sys_send_arp(&arp->sin, arp->vnn->iface);
78 DEBUG(DEBUG_CRIT,(__location__ " sending of arp failed (%s)\n", strerror(errno)));
81 s = ctdb_sys_open_sending_socket();
83 DEBUG(DEBUG_CRIT,(__location__ " failed to open raw socket for sending tickles\n"));
87 tcparray = arp->tcparray;
89 for (i=0;i<tcparray->num;i++) {
90 DEBUG(DEBUG_INFO,("sending tcp tickle ack for %u->%s:%u\n",
91 (unsigned)ntohs(tcparray->connections[i].daddr.sin_port),
92 inet_ntoa(tcparray->connections[i].saddr.sin_addr),
93 (unsigned)ntohs(tcparray->connections[i].saddr.sin_port)));
94 ret = ctdb_sys_send_tcp(s, &tcparray->connections[i].saddr,
95 &tcparray->connections[i].daddr, 0, 0, 0);
97 DEBUG(DEBUG_CRIT,(__location__ " Failed to send tcp tickle ack for %s\n",
98 inet_ntoa(tcparray->connections[i].saddr.sin_addr)));
106 if (arp->count == CTDB_ARP_REPEAT) {
111 event_add_timed(arp->ctdb->ev, arp->vnn->takeover_ctx,
112 timeval_current_ofs(CTDB_ARP_INTERVAL, 0),
113 ctdb_control_send_arp, arp);
116 struct takeover_callback_state {
117 struct ctdb_req_control *c;
118 struct sockaddr_in *sin;
119 struct ctdb_vnn *vnn;
123 called when takeip event finishes
125 static void takeover_ip_callback(struct ctdb_context *ctdb, int status,
128 struct takeover_callback_state *state =
129 talloc_get_type(private_data, struct takeover_callback_state);
130 struct ctdb_takeover_arp *arp;
131 char *ip = inet_ntoa(state->sin->sin_addr);
132 struct ctdb_tcp_array *tcparray;
134 ctdb_enable_monitoring(ctdb);
137 DEBUG(DEBUG_ERR,(__location__ " Failed to takeover IP %s on interface %s\n",
138 ip, state->vnn->iface));
139 ctdb_request_control_reply(ctdb, state->c, NULL, status, NULL);
144 if (!state->vnn->takeover_ctx) {
145 state->vnn->takeover_ctx = talloc_new(ctdb);
146 if (!state->vnn->takeover_ctx) {
151 arp = talloc_zero(state->vnn->takeover_ctx, struct ctdb_takeover_arp);
152 if (!arp) goto failed;
155 arp->sin = *state->sin;
156 arp->vnn = state->vnn;
158 tcparray = state->vnn->tcp_array;
160 /* add all of the known tcp connections for this IP to the
161 list of tcp connections to send tickle acks for */
162 arp->tcparray = talloc_steal(arp, tcparray);
164 state->vnn->tcp_array = NULL;
165 state->vnn->tcp_update_needed = true;
168 event_add_timed(arp->ctdb->ev, state->vnn->takeover_ctx,
169 timeval_zero(), ctdb_control_send_arp, arp);
171 /* the control succeeded */
172 ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL);
177 ctdb_request_control_reply(ctdb, state->c, NULL, -1, NULL);
183 Find the vnn of the node that has a public ip address
184 returns -1 if the address is not known as a public address
186 static struct ctdb_vnn *find_public_ip_vnn(struct ctdb_context *ctdb, struct sockaddr_in ip)
188 struct ctdb_vnn *vnn;
190 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
191 if (ctdb_same_ip(&vnn->public_address, &ip)) {
201 take over an ip address
203 int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
204 struct ctdb_req_control *c,
209 struct takeover_callback_state *state;
210 struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
211 struct ctdb_vnn *vnn;
213 /* update out vnn list */
214 vnn = find_public_ip_vnn(ctdb, pip->sin);
216 DEBUG(DEBUG_ERR,("takeoverip called for an ip '%s' that is not a public address\n",
217 inet_ntoa(pip->sin.sin_addr)));
222 /* if our kernel already has this IP, do nothing */
223 if (ctdb_sys_have_ip(pip->sin)) {
227 state = talloc(ctdb, struct takeover_callback_state);
228 CTDB_NO_MEMORY(ctdb, state);
230 state->c = talloc_steal(ctdb, c);
231 state->sin = talloc(ctdb, struct sockaddr_in);
232 CTDB_NO_MEMORY(ctdb, state->sin);
233 *state->sin = pip->sin;
237 DEBUG(DEBUG_NOTICE,("Takeover of IP %s/%u on interface %s\n",
238 inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
241 ctdb_disable_monitoring(ctdb);
243 ret = ctdb_event_script_callback(ctdb,
244 timeval_current_ofs(ctdb->tunable.script_timeout, 0),
245 state, takeover_ip_callback, state,
248 inet_ntoa(pip->sin.sin_addr),
249 vnn->public_netmask_bits);
252 ctdb_enable_monitoring(ctdb);
253 DEBUG(DEBUG_ERR,(__location__ " Failed to takeover IP %s on interface %s\n",
254 inet_ntoa(pip->sin.sin_addr), vnn->iface));
259 /* tell ctdb_control.c that we will be replying asynchronously */
266 kill any clients that are registered with a IP that is being released
268 static void release_kill_clients(struct ctdb_context *ctdb, struct sockaddr_in in)
270 struct ctdb_client_ip *ip;
272 DEBUG(DEBUG_INFO,("release_kill_clients for ip %s\n", inet_ntoa(in.sin_addr)));
274 for (ip=ctdb->client_ip_list; ip; ip=ip->next) {
275 DEBUG(DEBUG_INFO,("checking for client %u with IP %s\n",
276 ip->client_id, inet_ntoa(ip->ip.sin_addr)));
277 if (ctdb_same_ip(&ip->ip, &in)) {
278 struct ctdb_client *client = ctdb_reqid_find(ctdb,
281 DEBUG(DEBUG_INFO,("matched client %u with IP %s and pid %u\n",
282 ip->client_id, inet_ntoa(ip->ip.sin_addr), client->pid));
283 if (client->pid != 0) {
284 DEBUG(DEBUG_INFO,(__location__ " Killing client pid %u for IP %s on client_id %u\n",
285 (unsigned)client->pid, inet_ntoa(in.sin_addr),
287 kill(client->pid, SIGKILL);
294 called when releaseip event finishes
296 static void release_ip_callback(struct ctdb_context *ctdb, int status,
299 struct takeover_callback_state *state =
300 talloc_get_type(private_data, struct takeover_callback_state);
301 char *ip = inet_ntoa(state->sin->sin_addr);
304 ctdb_enable_monitoring(ctdb);
306 /* send a message to all clients of this node telling them
307 that the cluster has been reconfigured and they should
308 release any sockets on this IP */
309 data.dptr = (uint8_t *)ip;
310 data.dsize = strlen(ip)+1;
312 ctdb_daemon_send_message(ctdb, ctdb->pnn, CTDB_SRVID_RELEASE_IP, data);
314 /* kill clients that have registered with this IP */
315 release_kill_clients(ctdb, *state->sin);
317 /* the control succeeded */
318 ctdb_request_control_reply(ctdb, state->c, NULL, 0, NULL);
323 release an ip address
325 int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
326 struct ctdb_req_control *c,
331 struct takeover_callback_state *state;
332 struct ctdb_public_ip *pip = (struct ctdb_public_ip *)indata.dptr;
333 struct ctdb_vnn *vnn;
335 /* update our vnn list */
336 vnn = find_public_ip_vnn(ctdb, pip->sin);
338 DEBUG(DEBUG_ERR,("releaseip called for an ip '%s' that is not a public address\n",
339 inet_ntoa(pip->sin.sin_addr)));
344 /* stop any previous arps */
345 talloc_free(vnn->takeover_ctx);
346 vnn->takeover_ctx = NULL;
348 if (!ctdb_sys_have_ip(pip->sin)) {
349 DEBUG(DEBUG_INFO,("Redundant release of IP %s/%u on interface %s (ip not held)\n",
350 inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
355 DEBUG(DEBUG_NOTICE,("Release of IP %s/%u on interface %s\n",
356 inet_ntoa(pip->sin.sin_addr), vnn->public_netmask_bits,
359 state = talloc(ctdb, struct takeover_callback_state);
360 CTDB_NO_MEMORY(ctdb, state);
362 state->c = talloc_steal(state, c);
363 state->sin = talloc(state, struct sockaddr_in);
364 CTDB_NO_MEMORY(ctdb, state->sin);
365 *state->sin = pip->sin;
369 ctdb_disable_monitoring(ctdb);
371 ret = ctdb_event_script_callback(ctdb,
372 timeval_current_ofs(ctdb->tunable.script_timeout, 0),
373 state, release_ip_callback, state,
374 "releaseip %s %s %u",
376 inet_ntoa(pip->sin.sin_addr),
377 vnn->public_netmask_bits);
379 ctdb_enable_monitoring(ctdb);
381 DEBUG(DEBUG_ERR,(__location__ " Failed to release IP %s on interface %s\n",
382 inet_ntoa(pip->sin.sin_addr), vnn->iface));
387 /* tell the control that we will be reply asynchronously */
394 static int add_public_address(struct ctdb_context *ctdb, struct sockaddr_in addr, unsigned mask, const char *iface)
396 struct ctdb_vnn *vnn;
398 /* Verify that we dont have an entry for this ip yet */
399 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
400 if (ctdb_same_sockaddr(&addr, &vnn->public_address)) {
401 DEBUG(DEBUG_CRIT,("Same ip '%s' specified multiple times in the public address list \n",
402 inet_ntoa(addr.sin_addr)));
407 /* create a new vnn structure for this ip address */
408 vnn = talloc_zero(ctdb, struct ctdb_vnn);
409 CTDB_NO_MEMORY_FATAL(ctdb, vnn);
410 vnn->iface = talloc_strdup(vnn, iface);
411 vnn->public_address = addr;
412 vnn->public_netmask_bits = mask;
415 DLIST_ADD(ctdb->vnn, vnn);
422 setup the event script directory
424 int ctdb_set_event_script_dir(struct ctdb_context *ctdb, const char *script_dir)
426 ctdb->event_script_dir = talloc_strdup(ctdb, script_dir);
427 CTDB_NO_MEMORY(ctdb, ctdb->event_script_dir);
432 setup the public address lists from a file
434 int ctdb_set_public_addresses(struct ctdb_context *ctdb, const char *alist)
440 lines = file_lines_load(alist, &nlines, ctdb);
442 ctdb_set_error(ctdb, "Failed to load public address list '%s'\n", alist);
445 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
449 for (i=0;i<nlines;i++) {
451 struct sockaddr_in addr;
455 tok = strtok(lines[i], " \t");
456 if (!tok || !parse_ip_mask(tok, &addr, &mask)) {
457 DEBUG(DEBUG_CRIT,("Badly formed line %u in public address list\n", i+1));
461 tok = strtok(NULL, " \t");
463 if (NULL == ctdb->default_public_interface) {
464 DEBUG(DEBUG_CRIT,("No default public interface and no interface specified at line %u of public address list\n",
469 iface = ctdb->default_public_interface;
474 if (add_public_address(ctdb, addr, mask, iface)) {
475 DEBUG(DEBUG_CRIT,("Failed to add line %u to the public address list\n", i+1));
488 struct ctdb_public_ip_list {
489 struct ctdb_public_ip_list *next;
491 struct sockaddr_in sin;
495 /* Given a physical node, return the number of
496 public addresses that is currently assigned to this node.
498 static int node_ip_coverage(struct ctdb_context *ctdb,
500 struct ctdb_public_ip_list *ips)
504 for (;ips;ips=ips->next) {
505 if (ips->pnn == pnn) {
513 /* Check if this is a public ip known to the node, i.e. can that
514 node takeover this ip ?
516 static int can_node_serve_ip(struct ctdb_context *ctdb, int32_t pnn,
517 struct ctdb_public_ip_list *ip)
519 struct ctdb_all_public_ips *public_ips;
522 public_ips = ctdb->nodes[pnn]->public_ips;
524 if (public_ips == NULL) {
528 for (i=0;i<public_ips->num;i++) {
529 if (ip->sin.sin_addr.s_addr == public_ips->ips[i].sin.sin_addr.s_addr) {
530 /* yes, this node can serve this public ip */
539 /* search the node lists list for a node to takeover this ip.
540 pick the node that currently are serving the least number of ips
541 so that the ips get spread out evenly.
543 static int find_takeover_node(struct ctdb_context *ctdb,
544 struct ctdb_node_map *nodemap, uint32_t mask,
545 struct ctdb_public_ip_list *ip,
546 struct ctdb_public_ip_list *all_ips)
552 for (i=0;i<nodemap->num;i++) {
553 if (nodemap->nodes[i].flags & mask) {
554 /* This node is not healty and can not be used to serve
560 /* verify that this node can serve this ip */
561 if (can_node_serve_ip(ctdb, i, ip)) {
562 /* no it couldnt so skip to the next node */
566 num = node_ip_coverage(ctdb, i, all_ips);
567 /* was this the first node we checked ? */
579 DEBUG(DEBUG_WARNING,(__location__ " Could not find node to take over public address '%s'\n", inet_ntoa(ip->sin.sin_addr)));
587 struct ctdb_public_ip_list *
588 add_ip_to_merged_list(struct ctdb_context *ctdb,
590 struct ctdb_public_ip_list *ip_list,
591 struct ctdb_public_ip *ip)
593 struct ctdb_public_ip_list *tmp_ip;
595 /* do we already have this ip in our merged list ?*/
596 for (tmp_ip=ip_list;tmp_ip;tmp_ip=tmp_ip->next) {
598 /* we already have this public ip in the list */
599 if (tmp_ip->sin.sin_addr.s_addr == ip->sin.sin_addr.s_addr) {
604 /* this is a new public ip, we must add it to the list */
605 tmp_ip = talloc_zero(tmp_ctx, struct ctdb_public_ip_list);
606 CTDB_NO_MEMORY_NULL(ctdb, tmp_ip);
607 tmp_ip->pnn = ip->pnn;
608 tmp_ip->sin = ip->sin;
609 tmp_ip->next = ip_list;
614 struct ctdb_public_ip_list *
615 create_merged_ip_list(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx)
618 struct ctdb_public_ip_list *ip_list = NULL;
619 struct ctdb_all_public_ips *public_ips;
621 for (i=0;i<ctdb->num_nodes;i++) {
622 public_ips = ctdb->nodes[i]->public_ips;
624 /* there were no public ips for this node */
625 if (public_ips == NULL) {
629 for (j=0;j<public_ips->num;j++) {
630 ip_list = add_ip_to_merged_list(ctdb, tmp_ctx,
631 ip_list, &public_ips->ips[j]);
639 make any IP alias changes for public addresses that are necessary
641 int ctdb_takeover_run(struct ctdb_context *ctdb, struct ctdb_node_map *nodemap)
643 int i, num_healthy, retries;
644 struct ctdb_public_ip ip;
646 struct ctdb_public_ip_list *all_ips, *tmp_ip;
647 int maxnode, maxnum=0, minnode, minnum=0, num;
649 struct timeval timeout;
650 struct client_async_data *async_data;
651 struct ctdb_client_control_state *state;
652 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
657 /* Count how many completely healthy nodes we have */
659 for (i=0;i<nodemap->num;i++) {
660 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED))) {
665 if (num_healthy > 0) {
666 /* We have healthy nodes, so only consider them for
667 serving public addresses
669 mask = NODE_FLAGS_INACTIVE|NODE_FLAGS_DISABLED;
671 /* We didnt have any completely healthy nodes so
672 use "disabled" nodes as a fallback
674 mask = NODE_FLAGS_INACTIVE;
677 /* since nodes only know about those public addresses that
678 can be served by that particular node, no single node has
679 a full list of all public addresses that exist in the cluster.
680 Walk over all node structures and create a merged list of
681 all public addresses that exist in the cluster.
683 all_ips = create_merged_ip_list(ctdb, tmp_ctx);
685 /* If we want deterministic ip allocations, i.e. that the ip addresses
686 will always be allocated the same way for a specific set of
687 available/unavailable nodes.
689 if (1 == ctdb->tunable.deterministic_public_ips) {
690 DEBUG(DEBUG_NOTICE,("Deterministic IPs enabled. Resetting all ip allocations\n"));
691 for (i=0,tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next,i++) {
692 tmp_ip->pnn = i%nodemap->num;
697 /* mark all public addresses with a masked node as being served by
700 for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
701 if (tmp_ip->pnn == -1) {
704 if (nodemap->nodes[tmp_ip->pnn].flags & mask) {
710 /* now we must redistribute all public addresses with takeover node
711 -1 among the nodes available
715 /* loop over all ip's and find a physical node to cover for
718 for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
719 if (tmp_ip->pnn == -1) {
720 if (find_takeover_node(ctdb, nodemap, mask, tmp_ip, all_ips)) {
721 DEBUG(DEBUG_WARNING,("Failed to find node to cover ip %s\n", inet_ntoa(tmp_ip->sin.sin_addr)));
727 /* now, try to make sure the ip adresses are evenly distributed
729 for each ip address, loop over all nodes that can serve this
730 ip and make sure that the difference between the node
731 serving the most and the node serving the least ip's are not greater
734 for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
735 if (tmp_ip->pnn == -1) {
739 /* Get the highest and lowest number of ips's served by any
740 valid node which can serve this ip.
744 for (i=0;i<nodemap->num;i++) {
745 if (nodemap->nodes[i].flags & mask) {
749 /* only check nodes that can actually serve this ip */
750 if (can_node_serve_ip(ctdb, i, tmp_ip)) {
751 /* no it couldnt so skip to the next node */
755 num = node_ip_coverage(ctdb, i, all_ips);
776 DEBUG(DEBUG_WARNING,(__location__ " Could not find maxnode. May not be able to serve ip '%s'\n", inet_ntoa(tmp_ip->sin.sin_addr)));
780 /* If we want deterministic IPs then dont try to reallocate
781 them to spread out the load.
783 if (1 == ctdb->tunable.deterministic_public_ips) {
787 /* if the spread between the smallest and largest coverage by
788 a node is >=2 we steal one of the ips from the node with
789 most coverage to even things out a bit.
790 try to do this at most 5 times since we dont want to spend
791 too much time balancing the ip coverage.
793 if ( (maxnum > minnum+1)
795 struct ctdb_public_ip_list *tmp;
797 /* mark one of maxnode's vnn's as unassigned and try
800 for (tmp=all_ips;tmp;tmp=tmp->next) {
801 if (tmp->pnn == maxnode) {
812 /* at this point ->pnn is the node which will own each IP
813 or -1 if there is no node that can cover this ip
816 /* now tell all nodes to delete any alias that they should not
817 have. This will be a NOOP on nodes that don't currently
818 hold the given alias */
819 async_data = talloc_zero(tmp_ctx, struct client_async_data);
820 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
822 for (i=0;i<nodemap->num;i++) {
823 /* don't talk to unconnected nodes, but do talk to banned nodes */
824 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
828 for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
829 if (tmp_ip->pnn == nodemap->nodes[i].pnn) {
830 /* This node should be serving this
831 vnn so dont tell it to release the ip
835 ip.pnn = tmp_ip->pnn;
836 ip.sin.sin_family = AF_INET;
837 ip.sin.sin_addr = tmp_ip->sin.sin_addr;
839 timeout = TAKEOVER_TIMEOUT();
840 data.dsize = sizeof(ip);
841 data.dptr = (uint8_t *)&ip;
842 state = ctdb_control_send(ctdb, nodemap->nodes[i].pnn,
843 0, CTDB_CONTROL_RELEASE_IP, 0,
847 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control CTDB_CONTROL_RELEASE_IP to node %u\n", nodemap->nodes[i].pnn));
848 talloc_free(tmp_ctx);
852 ctdb_client_async_add(async_data, state);
855 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
856 DEBUG(DEBUG_ERR,(__location__ " Async control CTDB_CONTROL_RELEASE_IP failed\n"));
857 talloc_free(tmp_ctx);
860 talloc_free(async_data);
863 /* tell all nodes to get their own IPs */
864 async_data = talloc_zero(tmp_ctx, struct client_async_data);
865 CTDB_NO_MEMORY_FATAL(ctdb, async_data);
866 for (tmp_ip=all_ips;tmp_ip;tmp_ip=tmp_ip->next) {
867 if (tmp_ip->pnn == -1) {
868 /* this IP won't be taken over */
871 ip.pnn = tmp_ip->pnn;
872 ip.sin.sin_family = AF_INET;
873 ip.sin.sin_addr = tmp_ip->sin.sin_addr;
875 timeout = TAKEOVER_TIMEOUT();
876 data.dsize = sizeof(ip);
877 data.dptr = (uint8_t *)&ip;
878 state = ctdb_control_send(ctdb, tmp_ip->pnn,
879 0, CTDB_CONTROL_TAKEOVER_IP, 0,
883 DEBUG(DEBUG_ERR,(__location__ " Failed to call async control CTDB_CONTROL_TAKEOVER_IP to node %u\n", tmp_ip->pnn));
884 talloc_free(tmp_ctx);
888 ctdb_client_async_add(async_data, state);
890 if (ctdb_client_async_wait(ctdb, async_data) != 0) {
891 DEBUG(DEBUG_ERR,(__location__ " Async control CTDB_CONTROL_TAKEOVER_IP failed\n"));
892 talloc_free(tmp_ctx);
896 talloc_free(tmp_ctx);
902 destroy a ctdb_client_ip structure
904 static int ctdb_client_ip_destructor(struct ctdb_client_ip *ip)
906 DEBUG(DEBUG_DEBUG,("destroying client tcp for %s:%u (client_id %u)\n",
907 inet_ntoa(ip->ip.sin_addr), ntohs(ip->ip.sin_port), ip->client_id));
908 DLIST_REMOVE(ip->ctdb->client_ip_list, ip);
913 called by a client to inform us of a TCP connection that it is managing
914 that should tickled with an ACK when IP takeover is done
916 int32_t ctdb_control_tcp_client(struct ctdb_context *ctdb, uint32_t client_id,
919 struct ctdb_client *client = ctdb_reqid_find(ctdb, client_id, struct ctdb_client);
920 struct ctdb_control_tcp *p = (struct ctdb_control_tcp *)indata.dptr;
921 struct ctdb_tcp_list *tcp;
922 struct ctdb_control_tcp_vnn t;
925 struct ctdb_client_ip *ip;
926 struct ctdb_vnn *vnn;
928 vnn = find_public_ip_vnn(ctdb, p->dest);
930 if (ntohl(p->dest.sin_addr.s_addr) != INADDR_LOOPBACK) {
931 DEBUG(DEBUG_ERR,("Could not add client IP %s. This is not a public address.\n",
932 inet_ntoa(p->dest.sin_addr)));
937 if (vnn->pnn != ctdb->pnn) {
938 DEBUG(DEBUG_ERR,("Attempt to register tcp client for IP %s we don't hold - failing (client_id %u pid %u)\n",
939 inet_ntoa(p->dest.sin_addr),
940 client_id, client->pid));
941 /* failing this call will tell smbd to die */
945 ip = talloc(client, struct ctdb_client_ip);
946 CTDB_NO_MEMORY(ctdb, ip);
950 ip->client_id = client_id;
951 talloc_set_destructor(ip, ctdb_client_ip_destructor);
952 DLIST_ADD(ctdb->client_ip_list, ip);
954 tcp = talloc(client, struct ctdb_tcp_list);
955 CTDB_NO_MEMORY(ctdb, tcp);
957 tcp->connection.saddr = p->src;
958 tcp->connection.daddr = p->dest;
960 DLIST_ADD(client->tcp_list, tcp);
965 data.dptr = (uint8_t *)&t;
966 data.dsize = sizeof(t);
968 DEBUG(DEBUG_INFO,("registered tcp client for %u->%s:%u (client_id %u pid %u)\n",
969 (unsigned)ntohs(p->dest.sin_port),
970 inet_ntoa(p->src.sin_addr),
971 (unsigned)ntohs(p->src.sin_port), client_id, client->pid));
973 /* tell all nodes about this tcp connection */
974 ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0,
975 CTDB_CONTROL_TCP_ADD,
976 0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
978 DEBUG(DEBUG_ERR,(__location__ " Failed to send CTDB_CONTROL_TCP_ADD\n"));
986 see if two sockaddr_in are the same
988 static bool same_sockaddr_in(struct sockaddr_in *in1, struct sockaddr_in *in2)
990 return in1->sin_family == in2->sin_family &&
991 in1->sin_port == in2->sin_port &&
992 in1->sin_addr.s_addr == in2->sin_addr.s_addr;
996 find a tcp address on a list
998 static struct ctdb_tcp_connection *ctdb_tcp_find(struct ctdb_tcp_array *array,
999 struct ctdb_tcp_connection *tcp)
1003 if (array == NULL) {
1007 for (i=0;i<array->num;i++) {
1008 if (same_sockaddr_in(&array->connections[i].saddr, &tcp->saddr) &&
1009 same_sockaddr_in(&array->connections[i].daddr, &tcp->daddr)) {
1010 return &array->connections[i];
1017 called by a daemon to inform us of a TCP connection that one of its
1018 clients managing that should tickled with an ACK when IP takeover is
1021 int32_t ctdb_control_tcp_add(struct ctdb_context *ctdb, TDB_DATA indata)
1023 struct ctdb_control_tcp_vnn *p = (struct ctdb_control_tcp_vnn *)indata.dptr;
1024 struct ctdb_tcp_array *tcparray;
1025 struct ctdb_tcp_connection tcp;
1026 struct ctdb_vnn *vnn;
1028 vnn = find_public_ip_vnn(ctdb, p->dest);
1030 DEBUG(DEBUG_ERR,(__location__ " got TCP_ADD control for an address which is not a public address '%s'\n",
1031 inet_ntoa(p->dest.sin_addr)));
1036 tcparray = vnn->tcp_array;
1038 /* If this is the first tickle */
1039 if (tcparray == NULL) {
1040 tcparray = talloc_size(ctdb->nodes,
1041 offsetof(struct ctdb_tcp_array, connections) +
1042 sizeof(struct ctdb_tcp_connection) * 1);
1043 CTDB_NO_MEMORY(ctdb, tcparray);
1044 vnn->tcp_array = tcparray;
1047 tcparray->connections = talloc_size(tcparray, sizeof(struct ctdb_tcp_connection));
1048 CTDB_NO_MEMORY(ctdb, tcparray->connections);
1050 tcparray->connections[tcparray->num].saddr = p->src;
1051 tcparray->connections[tcparray->num].daddr = p->dest;
1057 /* Do we already have this tickle ?*/
1059 tcp.daddr = p->dest;
1060 if (ctdb_tcp_find(vnn->tcp_array, &tcp) != NULL) {
1061 DEBUG(DEBUG_DEBUG,("Already had tickle info for %s:%u for vnn:%u\n",
1062 inet_ntoa(tcp.daddr.sin_addr),
1063 ntohs(tcp.daddr.sin_port),
1068 /* A new tickle, we must add it to the array */
1069 tcparray->connections = talloc_realloc(tcparray, tcparray->connections,
1070 struct ctdb_tcp_connection,
1072 CTDB_NO_MEMORY(ctdb, tcparray->connections);
1074 vnn->tcp_array = tcparray;
1075 tcparray->connections[tcparray->num].saddr = p->src;
1076 tcparray->connections[tcparray->num].daddr = p->dest;
1079 DEBUG(DEBUG_INFO,("Added tickle info for %s:%u from vnn %u\n",
1080 inet_ntoa(tcp.daddr.sin_addr),
1081 ntohs(tcp.daddr.sin_port),
1089 called by a daemon to inform us of a TCP connection that one of its
1090 clients managing that should tickled with an ACK when IP takeover is
1093 static void ctdb_remove_tcp_connection(struct ctdb_context *ctdb, struct ctdb_tcp_connection *conn)
1095 struct ctdb_tcp_connection *tcpp;
1096 struct ctdb_vnn *vnn = find_public_ip_vnn(ctdb, conn->daddr);
1099 DEBUG(DEBUG_ERR,(__location__ " unable to find public address %s\n", inet_ntoa(conn->daddr.sin_addr)));
1103 /* if the array is empty we cant remove it
1104 and we dont need to do anything
1106 if (vnn->tcp_array == NULL) {
1107 DEBUG(DEBUG_INFO,("Trying to remove tickle that doesnt exist (array is empty) %s:%u\n",
1108 inet_ntoa(conn->daddr.sin_addr),
1109 ntohs(conn->daddr.sin_port)));
1114 /* See if we know this connection
1115 if we dont know this connection then we dont need to do anything
1117 tcpp = ctdb_tcp_find(vnn->tcp_array, conn);
1119 DEBUG(DEBUG_INFO,("Trying to remove tickle that doesnt exist %s:%u\n",
1120 inet_ntoa(conn->daddr.sin_addr),
1121 ntohs(conn->daddr.sin_port)));
1126 /* We need to remove this entry from the array.
1127 Instead of allocating a new array and copying data to it
1128 we cheat and just copy the last entry in the existing array
1129 to the entry that is to be removed and just shring the
1132 *tcpp = vnn->tcp_array->connections[vnn->tcp_array->num - 1];
1133 vnn->tcp_array->num--;
1135 /* If we deleted the last entry we also need to remove the entire array
1137 if (vnn->tcp_array->num == 0) {
1138 talloc_free(vnn->tcp_array);
1139 vnn->tcp_array = NULL;
1142 vnn->tcp_update_needed = true;
1144 DEBUG(DEBUG_INFO,("Removed tickle info for %s:%u\n",
1145 inet_ntoa(conn->saddr.sin_addr),
1146 ntohs(conn->saddr.sin_port)));
1151 called when a daemon restarts - send all tickes for all public addresses
1152 we are serving immediately to the new node.
1154 int32_t ctdb_control_startup(struct ctdb_context *ctdb, uint32_t vnn)
1156 /*XXX here we should send all tickes we are serving to the new node */
1162 called when a client structure goes away - hook to remove
1163 elements from the tcp_list in all daemons
1165 void ctdb_takeover_client_destructor_hook(struct ctdb_client *client)
1167 while (client->tcp_list) {
1168 struct ctdb_tcp_list *tcp = client->tcp_list;
1169 DLIST_REMOVE(client->tcp_list, tcp);
1170 ctdb_remove_tcp_connection(client->ctdb, &tcp->connection);
1176 release all IPs on shutdown
1178 void ctdb_release_all_ips(struct ctdb_context *ctdb)
1180 struct ctdb_vnn *vnn;
1182 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
1183 if (!ctdb_sys_have_ip(vnn->public_address)) {
1186 ctdb_event_script(ctdb, "releaseip %s %s %u",
1188 inet_ntoa(vnn->public_address.sin_addr),
1189 vnn->public_netmask_bits);
1190 release_kill_clients(ctdb, vnn->public_address);
1196 get list of public IPs
1198 int32_t ctdb_control_get_public_ips(struct ctdb_context *ctdb,
1199 struct ctdb_req_control *c, TDB_DATA *outdata)
1202 struct ctdb_all_public_ips *ips;
1203 struct ctdb_vnn *vnn;
1205 /* count how many public ip structures we have */
1207 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
1211 len = offsetof(struct ctdb_all_public_ips, ips) +
1212 num*sizeof(struct ctdb_public_ip);
1213 ips = talloc_zero_size(outdata, len);
1214 CTDB_NO_MEMORY(ctdb, ips);
1216 outdata->dsize = len;
1217 outdata->dptr = (uint8_t *)ips;
1221 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
1222 ips->ips[i].pnn = vnn->pnn;
1223 ips->ips[i].sin = vnn->public_address;
1233 structure containing the listening socket and the list of tcp connections
1234 that the ctdb daemon is to kill
1236 struct ctdb_kill_tcp {
1237 struct ctdb_vnn *vnn;
1238 struct ctdb_context *ctdb;
1241 struct fd_event *fde;
1242 trbt_tree_t *connections;
1247 a tcp connection that is to be killed
1249 struct ctdb_killtcp_con {
1250 struct sockaddr_in src;
1251 struct sockaddr_in dst;
1253 struct ctdb_kill_tcp *killtcp;
1256 /* this function is used to create a key to represent this socketpair
1257 in the killtcp tree.
1258 this key is used to insert and lookup matching socketpairs that are
1259 to be tickled and RST
1261 #define KILLTCP_KEYLEN 4
1262 static uint32_t *killtcp_key(struct sockaddr_in *src, struct sockaddr_in *dst)
1264 static uint32_t key[KILLTCP_KEYLEN];
1266 key[0] = dst->sin_addr.s_addr;
1267 key[1] = src->sin_addr.s_addr;
1268 key[2] = dst->sin_port;
1269 key[3] = src->sin_port;
1275 called when we get a read event on the raw socket
1277 static void capture_tcp_handler(struct event_context *ev, struct fd_event *fde,
1278 uint16_t flags, void *private_data)
1280 struct ctdb_kill_tcp *killtcp = talloc_get_type(private_data, struct ctdb_kill_tcp);
1281 struct ctdb_killtcp_con *con;
1282 struct sockaddr_in src, dst;
1283 uint32_t ack_seq, seq;
1285 if (!(flags & EVENT_FD_READ)) {
1289 if (ctdb_sys_read_tcp_packet(killtcp->capture_fd,
1290 killtcp->private_data,
1292 &ack_seq, &seq) != 0) {
1293 /* probably a non-tcp ACK packet */
1297 /* check if we have this guy in our list of connections
1300 con = trbt_lookuparray32(killtcp->connections,
1301 KILLTCP_KEYLEN, killtcp_key(&src, &dst));
1303 /* no this was some other packet we can just ignore */
1307 /* This one has been tickled !
1308 now reset him and remove him from the list.
1310 DEBUG(DEBUG_INFO, ("sending a tcp reset to kill connection :%d -> %s:%d\n", ntohs(con->dst.sin_port), inet_ntoa(con->src.sin_addr), ntohs(con->src.sin_port)));
1312 ctdb_sys_send_tcp(killtcp->sending_fd, &con->dst,
1313 &con->src, ack_seq, seq, 1);
1318 /* when traversing the list of all tcp connections to send tickle acks to
1319 (so that we can capture the ack coming back and kill the connection
1321 this callback is called for each connection we are currently trying to kill
1323 static void tickle_connection_traverse(void *param, void *data)
1325 struct ctdb_killtcp_con *con = talloc_get_type(data, struct ctdb_killtcp_con);
1326 struct ctdb_kill_tcp *killtcp = talloc_get_type(param, struct ctdb_kill_tcp);
1328 /* have tried too many times, just give up */
1329 if (con->count >= 5) {
1334 /* othervise, try tickling it again */
1336 ctdb_sys_send_tcp(killtcp->sending_fd, &con->dst, &con->src, 0, 0, 0);
1341 called every second until all sentenced connections have been reset
1343 static void ctdb_tickle_sentenced_connections(struct event_context *ev, struct timed_event *te,
1344 struct timeval t, void *private_data)
1346 struct ctdb_kill_tcp *killtcp = talloc_get_type(private_data, struct ctdb_kill_tcp);
1349 /* loop over all connections sending tickle ACKs */
1350 trbt_traversearray32(killtcp->connections, KILLTCP_KEYLEN, tickle_connection_traverse, killtcp);
1353 /* If there are no more connections to kill we can remove the
1354 entire killtcp structure
1356 if ( (killtcp->connections == NULL) ||
1357 (killtcp->connections->root == NULL) ) {
1358 talloc_free(killtcp);
1362 /* try tickling them again in a seconds time
1364 event_add_timed(killtcp->ctdb->ev, killtcp, timeval_current_ofs(1, 0),
1365 ctdb_tickle_sentenced_connections, killtcp);
1369 destroy the killtcp structure
1371 static int ctdb_killtcp_destructor(struct ctdb_kill_tcp *killtcp)
1373 if (killtcp->sending_fd != -1) {
1374 close(killtcp->sending_fd);
1375 killtcp->sending_fd = -1;
1377 killtcp->vnn->killtcp = NULL;
1382 /* nothing fancy here, just unconditionally replace any existing
1383 connection structure with the new one.
1385 dont even free the old one if it did exist, that one is talloc_stolen
1386 by the same node in the tree anyway and will be deleted when the new data
1389 static void *add_killtcp_callback(void *parm, void *data)
1395 add a tcp socket to the list of connections we want to RST
1397 static int ctdb_killtcp_add_connection(struct ctdb_context *ctdb,
1398 struct sockaddr_in *src, struct sockaddr_in *dst)
1400 struct ctdb_kill_tcp *killtcp;
1401 struct ctdb_killtcp_con *con;
1402 struct ctdb_vnn *vnn;
1404 vnn = find_public_ip_vnn(ctdb, *dst);
1406 vnn = find_public_ip_vnn(ctdb, *src);
1409 /* if it is not a public ip it could be our 'single ip' */
1410 if (ctdb->single_ip_vnn) {
1411 if (ctdb_same_ip(&ctdb->single_ip_vnn->public_address, dst)) {
1412 vnn = ctdb->single_ip_vnn;
1417 DEBUG(DEBUG_ERR,(__location__ " Could not killtcp, not a public address\n"));
1421 killtcp = vnn->killtcp;
1423 /* If this is the first connection to kill we must allocate
1426 if (killtcp == NULL) {
1427 killtcp = talloc_zero(ctdb, struct ctdb_kill_tcp);
1428 CTDB_NO_MEMORY(ctdb, killtcp);
1431 killtcp->ctdb = ctdb;
1432 killtcp->capture_fd = -1;
1433 killtcp->sending_fd = -1;
1434 killtcp->connections = trbt_create(killtcp, 0);
1436 vnn->killtcp = killtcp;
1437 talloc_set_destructor(killtcp, ctdb_killtcp_destructor);
1442 /* create a structure that describes this connection we want to
1443 RST and store it in killtcp->connections
1445 con = talloc(killtcp, struct ctdb_killtcp_con);
1446 CTDB_NO_MEMORY(ctdb, con);
1450 con->killtcp = killtcp;
1453 trbt_insertarray32_callback(killtcp->connections,
1454 KILLTCP_KEYLEN, killtcp_key(&con->dst, &con->src),
1455 add_killtcp_callback, con);
1458 If we dont have a socket to send from yet we must create it
1460 if (killtcp->sending_fd == -1) {
1461 killtcp->sending_fd = ctdb_sys_open_sending_socket();
1462 if (killtcp->sending_fd == -1) {
1463 DEBUG(DEBUG_CRIT,(__location__ " Failed to open sending socket for killtcp\n"));
1469 If we dont have a socket to listen on yet we must create it
1471 if (killtcp->capture_fd == -1) {
1472 killtcp->capture_fd = ctdb_sys_open_capture_socket(vnn->iface, &killtcp->private_data);
1473 if (killtcp->capture_fd == -1) {
1474 DEBUG(DEBUG_CRIT,(__location__ " Failed to open capturing socket for killtcp\n"));
1480 if (killtcp->fde == NULL) {
1481 killtcp->fde = event_add_fd(ctdb->ev, killtcp, killtcp->capture_fd,
1482 EVENT_FD_READ | EVENT_FD_AUTOCLOSE,
1483 capture_tcp_handler, killtcp);
1485 /* We also need to set up some events to tickle all these connections
1486 until they are all reset
1488 event_add_timed(ctdb->ev, killtcp, timeval_current_ofs(1, 0),
1489 ctdb_tickle_sentenced_connections, killtcp);
1492 /* tickle him once now */
1493 ctdb_sys_send_tcp(killtcp->sending_fd, &con->dst, &con->src, 0, 0, 0);
1498 talloc_free(vnn->killtcp);
1499 vnn->killtcp = NULL;
1504 kill a TCP connection.
1506 int32_t ctdb_control_kill_tcp(struct ctdb_context *ctdb, TDB_DATA indata)
1508 struct ctdb_control_killtcp *killtcp = (struct ctdb_control_killtcp *)indata.dptr;
1510 return ctdb_killtcp_add_connection(ctdb, &killtcp->src, &killtcp->dst);
1514 called by a daemon to inform us of the entire list of TCP tickles for
1515 a particular public address.
1516 this control should only be sent by the node that is currently serving
1517 that public address.
1519 int32_t ctdb_control_set_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata)
1521 struct ctdb_control_tcp_tickle_list *list = (struct ctdb_control_tcp_tickle_list *)indata.dptr;
1522 struct ctdb_tcp_array *tcparray;
1523 struct ctdb_vnn *vnn;
1525 /* We must at least have tickles.num or else we cant verify the size
1526 of the received data blob
1528 if (indata.dsize < offsetof(struct ctdb_control_tcp_tickle_list,
1529 tickles.connections)) {
1530 DEBUG(DEBUG_ERR,("Bad indata in ctdb_control_set_tcp_tickle_list. Not enough data for the tickle.num field\n"));
1534 /* verify that the size of data matches what we expect */
1535 if (indata.dsize < offsetof(struct ctdb_control_tcp_tickle_list,
1536 tickles.connections)
1537 + sizeof(struct ctdb_tcp_connection)
1538 * list->tickles.num) {
1539 DEBUG(DEBUG_ERR,("Bad indata in ctdb_control_set_tcp_tickle_list\n"));
1543 vnn = find_public_ip_vnn(ctdb, list->ip);
1545 DEBUG(DEBUG_ERR,(__location__ " Could not set tcp tickle list, '%s' is not a public address\n",
1546 inet_ntoa(list->ip.sin_addr)));
1550 /* remove any old ticklelist we might have */
1551 talloc_free(vnn->tcp_array);
1552 vnn->tcp_array = NULL;
1554 tcparray = talloc(ctdb->nodes, struct ctdb_tcp_array);
1555 CTDB_NO_MEMORY(ctdb, tcparray);
1557 tcparray->num = list->tickles.num;
1559 tcparray->connections = talloc_array(tcparray, struct ctdb_tcp_connection, tcparray->num);
1560 CTDB_NO_MEMORY(ctdb, tcparray->connections);
1562 memcpy(tcparray->connections, &list->tickles.connections[0],
1563 sizeof(struct ctdb_tcp_connection)*tcparray->num);
1565 /* We now have a new fresh tickle list array for this vnn */
1566 vnn->tcp_array = talloc_steal(vnn, tcparray);
1572 called to return the full list of tickles for the puclic address associated
1573 with the provided vnn
1575 int32_t ctdb_control_get_tcp_tickle_list(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata)
1577 struct sockaddr_in *ip = (struct sockaddr_in *)indata.dptr;
1578 struct ctdb_control_tcp_tickle_list *list;
1579 struct ctdb_tcp_array *tcparray;
1581 struct ctdb_vnn *vnn;
1583 vnn = find_public_ip_vnn(ctdb, *ip);
1585 DEBUG(DEBUG_ERR,(__location__ " Could not get tcp tickle list, '%s' is not a public address\n",
1586 inet_ntoa(ip->sin_addr)));
1590 tcparray = vnn->tcp_array;
1592 num = tcparray->num;
1597 outdata->dsize = offsetof(struct ctdb_control_tcp_tickle_list,
1598 tickles.connections)
1599 + sizeof(struct ctdb_tcp_connection) * num;
1601 outdata->dptr = talloc_size(outdata, outdata->dsize);
1602 CTDB_NO_MEMORY(ctdb, outdata->dptr);
1603 list = (struct ctdb_control_tcp_tickle_list *)outdata->dptr;
1606 list->tickles.num = num;
1608 memcpy(&list->tickles.connections[0], tcparray->connections,
1609 sizeof(struct ctdb_tcp_connection) * num);
1617 set the list of all tcp tickles for a public address
1619 static int ctdb_ctrl_set_tcp_tickles(struct ctdb_context *ctdb,
1620 struct timeval timeout, uint32_t destnode,
1621 struct sockaddr_in *ip,
1622 struct ctdb_tcp_array *tcparray)
1626 struct ctdb_control_tcp_tickle_list *list;
1629 num = tcparray->num;
1634 data.dsize = offsetof(struct ctdb_control_tcp_tickle_list,
1635 tickles.connections) +
1636 sizeof(struct ctdb_tcp_connection) * num;
1637 data.dptr = talloc_size(ctdb, data.dsize);
1638 CTDB_NO_MEMORY(ctdb, data.dptr);
1640 list = (struct ctdb_control_tcp_tickle_list *)data.dptr;
1642 list->tickles.num = num;
1644 memcpy(&list->tickles.connections[0], tcparray->connections, sizeof(struct ctdb_tcp_connection) * num);
1647 ret = ctdb_daemon_send_control(ctdb, CTDB_BROADCAST_CONNECTED, 0,
1648 CTDB_CONTROL_SET_TCP_TICKLE_LIST,
1649 0, CTDB_CTRL_FLAG_NOREPLY, data, NULL, NULL);
1651 DEBUG(DEBUG_ERR,(__location__ " ctdb_control for set tcp tickles failed\n"));
1655 talloc_free(data.dptr);
1662 perform tickle updates if required
1664 static void ctdb_update_tcp_tickles(struct event_context *ev,
1665 struct timed_event *te,
1666 struct timeval t, void *private_data)
1668 struct ctdb_context *ctdb = talloc_get_type(private_data, struct ctdb_context);
1670 struct ctdb_vnn *vnn;
1672 for (vnn=ctdb->vnn;vnn;vnn=vnn->next) {
1673 /* we only send out updates for public addresses that
1676 if (ctdb->pnn != vnn->pnn) {
1679 /* We only send out the updates if we need to */
1680 if (!vnn->tcp_update_needed) {
1683 ret = ctdb_ctrl_set_tcp_tickles(ctdb,
1685 CTDB_BROADCAST_CONNECTED,
1686 &vnn->public_address,
1689 DEBUG(DEBUG_ERR,("Failed to send the tickle update for public address %s\n",
1690 inet_ntoa(vnn->public_address.sin_addr)));
1694 event_add_timed(ctdb->ev, ctdb->tickle_update_context,
1695 timeval_current_ofs(ctdb->tunable.tickle_update_interval, 0),
1696 ctdb_update_tcp_tickles, ctdb);
1701 start periodic update of tcp tickles
1703 void ctdb_start_tcp_tickle_update(struct ctdb_context *ctdb)
1705 ctdb->tickle_update_context = talloc_new(ctdb);
1707 event_add_timed(ctdb->ev, ctdb->tickle_update_context,
1708 timeval_current_ofs(ctdb->tunable.tickle_update_interval, 0),
1709 ctdb_update_tcp_tickles, ctdb);
1715 struct control_gratious_arp {
1716 struct ctdb_context *ctdb;
1717 struct sockaddr_in sin;
1723 send a control_gratuitous arp
1725 static void send_gratious_arp(struct event_context *ev, struct timed_event *te,
1726 struct timeval t, void *private_data)
1729 struct control_gratious_arp *arp = talloc_get_type(private_data,
1730 struct control_gratious_arp);
1732 ret = ctdb_sys_send_arp(&arp->sin, arp->iface);
1734 DEBUG(DEBUG_ERR,(__location__ " sending of gratious arp failed (%s)\n", strerror(errno)));
1739 if (arp->count == CTDB_ARP_REPEAT) {
1744 event_add_timed(arp->ctdb->ev, arp,
1745 timeval_current_ofs(CTDB_ARP_INTERVAL, 0),
1746 send_gratious_arp, arp);
1753 int32_t ctdb_control_send_gratious_arp(struct ctdb_context *ctdb, TDB_DATA indata)
1755 struct ctdb_control_gratious_arp *gratious_arp = (struct ctdb_control_gratious_arp *)indata.dptr;
1756 struct control_gratious_arp *arp;
1759 /* verify the size of indata */
1760 if (indata.dsize < offsetof(struct ctdb_control_gratious_arp, iface)) {
1761 DEBUG(DEBUG_ERR,(__location__ " Too small indata to hold a ctdb_control_gratious_arp structure\n"));
1765 ( offsetof(struct ctdb_control_gratious_arp, iface)
1766 + gratious_arp->len ) ){
1768 DEBUG(DEBUG_ERR,(__location__ " Wrong size of indata. Was %u bytes "
1769 "but should be %u bytes\n",
1770 (unsigned)indata.dsize,
1771 (unsigned)(offsetof(struct ctdb_control_gratious_arp, iface)+gratious_arp->len)));
1776 arp = talloc(ctdb, struct control_gratious_arp);
1777 CTDB_NO_MEMORY(ctdb, arp);
1780 arp->sin = gratious_arp->sin;
1781 arp->iface = talloc_strdup(arp, gratious_arp->iface);
1782 CTDB_NO_MEMORY(ctdb, arp->iface);
1785 event_add_timed(arp->ctdb->ev, arp,
1786 timeval_zero(), send_gratious_arp, arp);