66 lines
3.0 KiB
C
66 lines
3.0 KiB
C
#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
|