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

#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