2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "ha_kernel.h"
18 typedef u_int32_t u32
;
21 #include <linux/jhash.h>
25 #include <sys/types.h>
29 #define CLUSTERIP_DIR "/proc/net/ipt_CLUSTERIP"
31 typedef struct private_ha_kernel_t private_ha_kernel_t
;
34 * Private data of an ha_kernel_t object.
36 struct private_ha_kernel_t
{
39 * Public ha_kernel_t interface.
44 * Init value for jhash
49 * Total number of ClusterIP segments
55 * Implementation of ha_kernel_t.in_segment
57 static bool in_segment(private_ha_kernel_t
*this, host_t
*host
, u_int segment
)
59 if (host
->get_family(host
) == AF_INET
)
64 addr
= *(u_int32_t
*)host
->get_address(host
).ptr
;
65 hash
= jhash_1word(ntohl(addr
), this->initval
);
67 if ((((u_int64_t
)hash
* this->count
) >> 32) + 1 == segment
)
76 * Activate/Deactivate a segment for a given clusterip file
78 static void enable_disable(private_ha_kernel_t
*this, u_int segment
,
79 char *file
, bool enable
)
84 snprintf(cmd
, sizeof(cmd
), "%c%d\n", enable ?
'+' : '-', segment
);
86 fd
= open(file
, O_WRONLY
);
89 DBG1(DBG_CFG
, "opening CLUSTERIP file '%s' failed: %s",
90 file
, strerror(errno
));
93 if (write(fd
, cmd
, strlen(cmd
) == -1))
95 DBG1(DBG_CFG
, "writing to CLUSTERIP file '%s' failed: %s",
96 file
, strerror(errno
));
102 * Get the currenlty active segments in the kernel for a clusterip file
104 static segment_mask_t
get_active(private_ha_kernel_t
*this, char *file
)
107 segment_mask_t mask
= 0;
111 fd
= open(file
, O_RDONLY
);
114 DBG1(DBG_CFG
, "opening CLUSTERIP file '%s' failed: %s",
115 file
, strerror(errno
));
118 len
= read(fd
, buf
, sizeof(buf
)-1);
121 DBG1(DBG_CFG
, "reading from CLUSTERIP file '%s' failed: %s",
122 file
, strerror(errno
));
126 enumerator_t
*enumerator
;
131 enumerator
= enumerator_create_token(buf
, ",", " ");
132 while (enumerator
->enumerate(enumerator
, &token
))
134 segment
= atoi(token
);
137 mask
|= SEGMENTS_BIT(segment
);
140 enumerator
->destroy(enumerator
);
146 * Implementation of ha_kernel_t.activate
148 static void activate(private_ha_kernel_t
*this, u_int segment
)
150 enumerator_t
*enumerator
;
153 enumerator
= enumerator_create_directory(CLUSTERIP_DIR
);
154 while (enumerator
->enumerate(enumerator
, NULL
, &file
, NULL
))
156 enable_disable(this, segment
, file
, TRUE
);
158 enumerator
->destroy(enumerator
);
162 * Implementation of ha_kernel_t.deactivate
164 static void deactivate(private_ha_kernel_t
*this, u_int segment
)
166 enumerator_t
*enumerator
;
169 enumerator
= enumerator_create_directory(CLUSTERIP_DIR
);
170 while (enumerator
->enumerate(enumerator
, NULL
, &file
, NULL
))
172 enable_disable(this, segment
, file
, FALSE
);
174 enumerator
->destroy(enumerator
);
178 * Enable all not-yet enabled segments on all clusterip addresses
180 static void activate_all(private_ha_kernel_t
*this)
182 enumerator_t
*enumerator
;
183 segment_mask_t active
;
187 enumerator
= enumerator_create_directory(CLUSTERIP_DIR
);
188 while (enumerator
->enumerate(enumerator
, NULL
, &file
, NULL
))
190 active
= get_active(this, file
);
191 for (i
= 1; i
<= this->count
; i
++)
193 if (!(active
& SEGMENTS_BIT(i
)))
195 enable_disable(this, i
, file
, TRUE
);
199 enumerator
->destroy(enumerator
);
203 * Implementation of ha_kernel_t.destroy.
205 static void destroy(private_ha_kernel_t
*this)
213 ha_kernel_t
*ha_kernel_create(u_int count
)
215 private_ha_kernel_t
*this = malloc_thing(private_ha_kernel_t
);
217 this->public.in_segment
= (bool(*)(ha_kernel_t
*, host_t
*host
, u_int segment
))in_segment
;
218 this->public.activate
= (void(*)(ha_kernel_t
*, u_int segment
))activate
;
219 this->public.deactivate
= (void(*)(ha_kernel_t
*, u_int segment
))deactivate
;
220 this->public.destroy
= (void(*)(ha_kernel_t
*))destroy
;
227 return &this->public;