Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

different virutal-service may refer to the same address,when the addr… #529

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 168 additions & 1 deletion tools/keepalived/keepalived/check/ipwrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,171 @@ notify_fifo_rs(virtual_server_t* vs, real_server_t* rs)
FREE(line);
}

static int vs_addr_cmp(struct sockaddr_storage *addr_a, struct sockaddr_storage *addr_b)
{
int ret = 0;

if (addr_a->ss_family != addr_b->ss_family)
return 0;

if (addr_a->ss_family == AF_INET6) {
ret = inaddr_equal(AF_INET6, &((struct sockaddr_in6 *)addr_a)->sin6_addr,
&((struct sockaddr_in6 *)addr_b)->sin6_addr);
} else {
ret = inaddr_equal(AF_INET, &((struct sockaddr_in *)addr_a)->sin_addr,
&((struct sockaddr_in *)addr_b)->sin_addr);
}

return ret;
}

static int __vs_group_rang_addr_cmp(struct sockaddr_storage *addr,
virtual_server_group_entry_t *vsg_entry)
{
uint32_t addr_ip, ip;
struct sockaddr_storage vip_addr;
int ret = 0;

vip_addr = vsg_entry->addr;
if (vsg_entry->addr.ss_family == AF_INET6) {
//inet_sockaddrip6(&vsg_entry->addr, &addr.in6);
ip = ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3];
} else {
ip = ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr;
}

/* Parse the whole range */
for (addr_ip = ip;
((addr_ip >> 24) & 0xFF) <= vsg_entry->range;
addr_ip += 0x01000000) {
if (vsg_entry->addr.ss_family == AF_INET6) {
((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3] = addr_ip;
} else {
((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr = addr_ip;
}

ret |= vs_addr_cmp(addr, &vip_addr);
}
return ret;

}

static int __vs_group_addr_cmp(struct sockaddr_storage *addr, virtual_server_group_t *vsg)
{
virtual_server_group_entry_t *vsg_entry = NULL;
list l;
element e;
int ret = 0;

/* visit range list */
l = vsg->addr_range;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vsg_entry = ELEMENT_DATA(e);
ret |= __vs_group_rang_addr_cmp(addr, vsg_entry);
}

return ret;
}

static int __vs_group_rang_cmp(virtual_server_group_entry_t *vsg_entry,
virtual_server_group_t *vsg)
{
uint32_t addr_ip, ip;
struct sockaddr_storage vip_addr;
int ret = 0;

vip_addr = vsg_entry->addr;
if (vsg_entry->addr.ss_family == AF_INET6) {
//inet_sockaddrip6(&vsg_entry->addr, &addr.in6);
ip = ((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3];
} else {
ip = ((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr;
}

/* Parse the whole range */
for (addr_ip = ip;
((addr_ip >> 24) & 0xFF) <= vsg_entry->range;
addr_ip += 0x01000000) {
if (vsg_entry->addr.ss_family == AF_INET6) {
((struct sockaddr_in6*)&vip_addr)->sin6_addr.s6_addr32[3] = addr_ip;
} else {
((struct sockaddr_in*)&vip_addr)->sin_addr.s_addr = addr_ip;
}
ret |= __vs_group_addr_cmp(&vip_addr, vsg);
}
return ret;
}

static int vs_group_addr_cmp(virtual_server_t *vs_a, virtual_server_t *vs_b)
{
virtual_server_group_t *vsg_a = ipvs_get_group_by_name(vs_a->vsgname, check_data->vs_group);
virtual_server_group_t *vsg_b = ipvs_get_group_by_name(vs_b->vsgname, check_data->vs_group);
virtual_server_group_entry_t *vsg_entry;
list l;
element e;
int ret = 0;

if (vsg_a == NULL || vsg_b == NULL)
return 0;

if (vsg_a == vsg_b)
return 1;

/* visit range list */
l = vsg_a->addr_range;
for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
vsg_entry = ELEMENT_DATA(e);
ret |= __vs_group_rang_cmp(vsg_entry, vsg_b);
}

return ret;
}

static int all_vs_quorum_down(virtual_server_t *var_vs)
{
element e;
virtual_server_t *tmp_vs = NULL;
virtual_server_group_t *vsg = NULL;
list l;
int ret = 0;

if (NULL == check_data) {
return 1;
}

l = check_data->vs;

if (LIST_ISEMPTY(l)) {
return 1;
}

for (e = LIST_HEAD(l); e; ELEMENT_NEXT(e)) {
tmp_vs = ELEMENT_DATA(e);
if (false == tmp_vs->quorum_state_up)
continue;

if (var_vs->vsgname && tmp_vs->vsgname) {
ret = vs_group_addr_cmp(var_vs, tmp_vs);
} else if (var_vs->vsgname && NULL == tmp_vs->vsgname) {
vsg = ipvs_get_group_by_name(var_vs->vsgname, check_data->vs_group);
ret = __vs_group_addr_cmp(&tmp_vs->addr, vsg);
} else if (NULL == var_vs->vsgname && tmp_vs->vsgname) {
vsg = ipvs_get_group_by_name(tmp_vs->vsgname, check_data->vs_group);
ret = __vs_group_addr_cmp(&var_vs->addr, vsg);
} else {
ret = vs_addr_cmp(&var_vs->addr, &tmp_vs->addr);
}
weiyanhua100 marked this conversation as resolved.
Show resolved Hide resolved

if (ret) {
log_message(LOG_INFO, "VS [%s] have the same vip with VS [%s], and the quorum_state is UP",
(tmp_vs->vsgname) ? tmp_vs->vsgname : FMT_VS(tmp_vs)
,(var_vs->vsgname) ? var_vs->vsgname : FMT_VS(var_vs));
return 0;
}
}
return 1;
}

static void
do_vs_notifies(virtual_server_t* vs, bool init, long threshold, long weight_sum, bool stopping)
{
Expand All @@ -177,8 +342,10 @@ do_vs_notifies(virtual_server_t* vs, bool init, long threshold, long weight_sum,
if (notify_script) {
if (stopping)
system_call_script(master, child_killed_thread, NULL, TIMER_HZ, notify_script);
else
else if (vs->quorum_state_up || ((!vs->quorum_state_up) && all_vs_quorum_down(vs))) {
log_message(LOG_INFO, "Execute script: %s.", cmd_str(notify_script));
notify_exec(notify_script);
}
}

notify_fifo_vs(vs);
Expand Down