fix auto_socket: handle_nl_link silently skipped on if_indextoname failure for deleted interfaces
When ip link del removes an interface, the kernel sends RTM_DELLINK after the interface is unregistered from the name table. if_indextoname fails and handle_nl_link silently returned without calling remove_iface_sockets, causing old ETCP sockets to accumulate indefinitely. Fix: fall through to remove_iface_sockets(ifindex) even when if_indextoname fails. Test: added diagnostics (diag_dump_state, per-category debug levels to file) to verify socket/links cleanup.
This commit is contained in:
1 parent
b503fa4418
commit
8583d4216f
2 files changed
+63
-2
No files matched your search
@@ -183,6 +183,51 @@ static void start_traffic(void) {
|
||||
timeout_handle = uasync_set_timeout(ctx.ua, TRAF_MON_TB, NULL, traffic_monitor_timer, "traf_mon");
|
||||
}
|
||||
|
||||
/* ── diagnostics ── */
|
||||
static void diag_dump_state(const char* label) {
|
||||
fprintf(stderr, "--- DIAG [%s] r=%d s=%d ---\n", label, ctx.round, ctx.step);
|
||||
struct ll_entry* e = ctx.client->connections->head;
|
||||
int conn_n = 0;
|
||||
while (e) { conn_n++; e = e->next; }
|
||||
fprintf(stderr, " connections=%d\n", conn_n);
|
||||
fprintf(stderr, " current_iface=%s prev_iface=%s\n", ctx.cur_iface, ctx.prev_iface[0] ? ctx.prev_iface : "(none)");
|
||||
|
||||
/* list sockets */
|
||||
fprintf(stderr, " sockets:\n");
|
||||
struct ETCP_SOCKET* s = ctx.client->etcp_sockets;
|
||||
while (s) {
|
||||
char ifname[IFNAMSIZ] = "?";
|
||||
if (s->netif_index) if_indextoname(s->netif_index, ifname);
|
||||
fprintf(stderr, " %-30s fd=%d if=%s(%u) fam=%d tcp=%d\n",
|
||||
s->name, (int)s->fd, ifname, s->netif_index,
|
||||
s->local_addr.ss_family, s->is_tcp);
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
/* list links for the server connection */
|
||||
fprintf(stderr, " links to srv 0x%016llx:\n", (unsigned long long)ctx.srv_node_id);
|
||||
e = ctx.client->connections->head;
|
||||
while (e) {
|
||||
struct conn_queue_entry* ce = (struct conn_queue_entry*)e->data;
|
||||
if (ce->conn->peer_node_id == ctx.srv_node_id) {
|
||||
int nlink = 0; for (struct ETCP_LINK* tl = ce->conn->links; tl; tl = tl->next) nlink++;
|
||||
fprintf(stderr, " conn=%s state=%d links=%d\n",
|
||||
ce->conn->log_name, ce->conn->state, nlink);
|
||||
struct ETCP_LINK* l = ce->conn->links;
|
||||
while (l) {
|
||||
char ifname[IFNAMSIZ] = "?";
|
||||
if (l->conn->netif_index) if_indextoname(l->conn->netif_index, ifname);
|
||||
fprintf(stderr, " link=%d init=%d status=%d is_tcp=%d sock=%s if=%s\n",
|
||||
l->local_link_id, l->initialized, l->link_status, l->is_tcp,
|
||||
l->conn ? l->conn->name : "?", ifname);
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
e = e->next;
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
/* ── ip addr add/del via system ── */
|
||||
static int ip_addr_add(const char* ifname, const char* cidr) {
|
||||
char cmd[256]; snprintf(cmd, sizeof(cmd), "ip addr add %s dev %s 2>/dev/null", cidr, ifname);
|
||||
@@ -229,6 +274,7 @@ static void phase_del_last(void* arg) {
|
||||
(void)arg;
|
||||
if (ctx.result) return;
|
||||
ctx.step = 11;
|
||||
diag_dump_state("before del_last");
|
||||
ip_link_del(rounds[N_ROUNDS-1].ifname);
|
||||
uasync_set_timeout(ctx.ua, STEP_TB, NULL, phase_check_del_last, "chk_del_last");
|
||||
}
|
||||
@@ -256,15 +302,19 @@ static void phase_check_del_last(void* arg) {
|
||||
static void phase_check_ip(void* arg) {
|
||||
(void)arg; if (ctx.result) return;
|
||||
static uint64_t wait_start = 0;
|
||||
static int diag_cnt = 0;
|
||||
ctx.step = 6;
|
||||
if (count_links_to_srv(ctx.cur_iface) == 0 || ctx.total_recv <= ctx.recv_at_ip_change) {
|
||||
if (++diag_cnt <= 3) diag_dump_state("wait chk_ip");
|
||||
if (!wait_start) wait_start = get_time_tb();
|
||||
if (get_time_tb() - wait_start < (uint64_t)STEP_TB * 10) {
|
||||
uasync_set_timeout(ctx.ua, STEP_TB/3, NULL, phase_check_ip, "chk_ip"); return;
|
||||
}
|
||||
diag_dump_state("timeout chk_ip");
|
||||
fail("traffic not recovered after IP change");
|
||||
return;
|
||||
}
|
||||
diag_cnt = 0;
|
||||
wait_start = 0;
|
||||
do_check(); if (ctx.result) return;
|
||||
|
||||
@@ -422,7 +472,13 @@ static void setup(void) {
|
||||
static void cleanup(void) { test_unlink(scf); test_unlink(ccf); test_rmdir(tdir); }
|
||||
|
||||
int main(void) {
|
||||
debug_config_init(); debug_set_level(DEBUG_LEVEL_WARN);
|
||||
debug_config_init();
|
||||
debug_enable_file_output("/tmp/as_dyn_diag.log", 1);
|
||||
debug_set_level(DEBUG_LEVEL_WARN);
|
||||
debug_set_category_level(DEBUG_CATEGORY_SOCKET, DEBUG_LEVEL_INFO);
|
||||
debug_set_category_level(DEBUG_CATEGORY_CONNECTION, DEBUG_LEVEL_INFO);
|
||||
debug_set_category_level(DEBUG_CATEGORY_ETCP, DEBUG_LEVEL_INFO);
|
||||
debug_set_category_level(DEBUG_CATEGORY_DEBUG, DEBUG_LEVEL_INFO);
|
||||
utun_instance_set_tun_init_enabled(0);
|
||||
setup();
|
||||
|
||||
|
||||
Reference in new issue
Block a user