You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
65 lines
3.0 KiB
65 lines
3.0 KiB
#ifndef TEST_CONNECTION_LOSS_H |
|
#define TEST_CONNECTION_LOSS_H |
|
|
|
#include "etcp_api.h" |
|
#include "etcp_connections.h" |
|
#include "utun_instance.h" |
|
#include "../lib/debug_config.h" |
|
|
|
/* Разрыв пары узлов охватывает и новые линки из свежего NODEINFO. |
|
* only/spared позволяют отдельно проверить потерю одного линка и работу |
|
* единственного оставшегося линка. Контекст живёт до loss_destroy(). */ |
|
struct test_connection_loss { |
|
struct UTUN_INSTANCE* instance; |
|
uint64_t peer_id; |
|
struct ETCP_LINK* only; |
|
struct ETCP_LINK* spared; |
|
int blocked; |
|
unsigned links; |
|
unsigned long long dropped; |
|
}; |
|
|
|
static ssize_t test_loss_send(socket_t fd, const void* buf, size_t len, const struct sockaddr* addr, |
|
socklen_t addr_len, struct ETCP_LINK* link, void* arg) { |
|
struct test_connection_loss* loss = arg; |
|
if (loss->blocked && (!loss->only || loss->only == link) && loss->spared != link) { |
|
loss->dropped++; |
|
return (ssize_t)len; |
|
} |
|
return socket_sendto(fd, buf, len, addr, addr_len); |
|
} |
|
|
|
static void test_loss_link(struct ETCP_CONN* conn, struct ETCP_LINK* link, int old_state, int old_status, void* arg) { |
|
(void)old_state; (void)old_status; |
|
struct test_connection_loss* loss = arg; |
|
if (conn->peer_node_id != loss->peer_id || link->send_hook == test_loss_send) return; |
|
link->send_hook = test_loss_send; link->send_hook_ctx = loss; loss->links++; |
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "test partition: peer=%016llx attached link=%p total=%u blocked=%d", |
|
(unsigned long long)loss->peer_id, (void*)link, loss->links, loss->blocked); |
|
} |
|
|
|
static void test_loss_init(struct test_connection_loss* loss, struct UTUN_INSTANCE* instance, uint64_t peer_id) { |
|
loss->instance = instance; loss->peer_id = peer_id; |
|
etcp_add_link_status_cbk(instance, test_loss_link, loss); |
|
struct ETCP_CONN* conn = instance_find_conn(instance, peer_id); |
|
for (struct ETCP_LINK* link = conn ? conn->links : NULL; link; link = link->next) |
|
test_loss_link(conn, link, 0, 0, loss); |
|
} |
|
|
|
static void test_loss_set(struct test_connection_loss* loss, int blocked, struct ETCP_LINK* only, struct ETCP_LINK* spared) { |
|
loss->blocked = blocked; loss->only = only; loss->spared = spared; |
|
DEBUG_INFO(DEBUG_CATEGORY_BGP, "test partition: peer=%016llx blocked=%d only=%p spared=%p links=%u dropped=%llu", |
|
(unsigned long long)loss->peer_id, blocked, (void*)only, (void*)spared, loss->links, loss->dropped); |
|
} |
|
|
|
static void test_loss_destroy(struct test_connection_loss* loss) { |
|
if (!loss->instance) return; |
|
etcp_remove_link_status_cbk(loss->instance, test_loss_link, loss); |
|
struct ETCP_CONN* conn = instance_find_conn(loss->instance, loss->peer_id); |
|
for (struct ETCP_LINK* link = conn ? conn->links : NULL; link; link = link->next) { |
|
if (link->send_hook_ctx != loss) continue; |
|
link->send_hook = NULL; link->send_hook_ctx = NULL; |
|
} |
|
loss->instance = NULL; |
|
} |
|
#endif
|
|
|