4 Copyright (C) Ronnie Sahlberg 2007
5 Copyright (C) Andrew Tridgell 2007
6 Copyright (C) Martin Schwenke 2011
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, see <http://www.gnu.org/licenses/>.
23 #include "system/network.h"
25 #include "ctdb_private.h"
27 #include "lib/util/time.h"
29 #include "lib/util/debug.h"
30 #include "common/logging.h"
32 #include "common/common.h"
33 #include "common/rb_tree.h"
35 #include "protocol/protocol_util.h"
37 #include "server/ipalloc_private.h"
39 #define TAKEOVER_TIMEOUT() timeval_current_ofs(ctdb->tunable.takeover_timeout,0)
41 /* Given a physical node, return the number of
42 public addresses that is currently assigned to this node.
44 int node_ip_coverage(uint32_t pnn
, struct public_ip_list
*ips
)
48 for (;ips
;ips
=ips
->next
) {
49 if (ips
->pnn
== pnn
) {
57 /* Can the given node host the given IP: is the public IP known to the
58 * node and is NOIPHOST unset?
60 static bool can_node_host_ip(struct ipalloc_state
*ipalloc_state
,
62 struct public_ip_list
*ip
)
64 return bitmap_query(ip
->available_on
, pnn
);
67 bool can_node_takeover_ip(struct ipalloc_state
*ipalloc_state
,
69 struct public_ip_list
*ip
)
71 if (ipalloc_state
->no_ip_takeover
) {
75 return can_node_host_ip(ipalloc_state
, pnn
, ip
);
78 /* search the node lists list for a node to takeover this ip.
79 pick the node that currently are serving the least number of ips
80 so that the ips get spread out evenly.
82 int find_takeover_node(struct ipalloc_state
*ipalloc_state
,
83 struct public_ip_list
*ip
)
87 unsigned int i
, numnodes
;
89 numnodes
= ipalloc_state
->num
;
90 pnn
= CTDB_UNKNOWN_PNN
;
91 for (i
=0; i
<numnodes
; i
++) {
92 /* verify that this node can serve this ip */
93 if (!can_node_takeover_ip(ipalloc_state
, i
, ip
)) {
94 /* no it couldnt so skip to the next node */
98 num
= node_ip_coverage(i
, ipalloc_state
->all_ips
);
99 /* was this the first node we checked ? */
100 if (pnn
== CTDB_UNKNOWN_PNN
) {
110 if (pnn
== CTDB_UNKNOWN_PNN
) {
111 DEBUG(DEBUG_WARNING
,(__location__
" Could not find node to take over public address '%s'\n",
112 ctdb_sock_addr_to_string(ipalloc_state
,
123 uint32_t *ip_key(ctdb_sock_addr
*ip
)
125 static uint32_t key
[IP_KEYLEN
];
127 bzero(key
, sizeof(key
));
129 switch (ip
->sa
.sa_family
) {
131 key
[3] = htonl(ip
->ip
.sin_addr
.s_addr
);
134 uint32_t *s6_a32
= (uint32_t *)&(ip
->ip6
.sin6_addr
.s6_addr
);
135 key
[0] = htonl(s6_a32
[0]);
136 key
[1] = htonl(s6_a32
[1]);
137 key
[2] = htonl(s6_a32
[2]);
138 key
[3] = htonl(s6_a32
[3]);
142 DEBUG(DEBUG_ERR
, (__location__
" ERROR, unknown family passed :%u\n", ip
->sa
.sa_family
));
149 /* Allocate any unassigned IPs just by looping through the IPs and
150 * finding the best node for each.
152 void basic_allocate_unassigned(struct ipalloc_state
*ipalloc_state
)
154 struct public_ip_list
*t
;
156 /* loop over all ip's and find a physical node to cover for
159 for (t
= ipalloc_state
->all_ips
; t
!= NULL
; t
= t
->next
) {
160 if (t
->pnn
== CTDB_UNKNOWN_PNN
) {
161 if (find_takeover_node(ipalloc_state
, t
)) {
163 ("Failed to find node to cover ip %s\n",
164 ctdb_sock_addr_to_string(ipalloc_state
,
172 void unassign_unsuitable_ips(struct ipalloc_state
*ipalloc_state
)
174 struct public_ip_list
*t
;
176 /* verify that the assigned nodes can serve that public ip
177 and set it to CTDB_UNKNOWN_PNN if not
179 for (t
= ipalloc_state
->all_ips
; t
!= NULL
; t
= t
->next
) {
180 if (t
->pnn
== CTDB_UNKNOWN_PNN
) {
183 if (!can_node_host_ip(ipalloc_state
, t
->pnn
, t
) != 0) {
184 /* this node can not serve this ip. */
185 DEBUG(DEBUG_DEBUG
,("Unassign IP: %s from %d\n",
186 ctdb_sock_addr_to_string(
190 t
->pnn
= CTDB_UNKNOWN_PNN
;