Browse Source

linux routing + debug output

nodeinfo-routing-update
Evgeny 1 month ago
parent
commit
1aec884c2d
  1. 4
      lib/debug_config.c
  2. 12
      src/config_parser.c
  3. 2
      src/routing.c
  4. 119
      src/tun_route.c
  5. 9
      src/tun_route.h
  6. 39
      src/utun_instance.c
  7. BIN
      tests/bench_timeout_heap
  8. BIN
      tests/bench_uasync_timeouts

4
lib/debug_config.c

@ -75,6 +75,10 @@ static debug_category_t get_category_by_name(const char* name) {
{"tun", DEBUG_CATEGORY_TUN}, {"tun", DEBUG_CATEGORY_TUN},
{"routing", DEBUG_CATEGORY_ROUTING}, {"routing", DEBUG_CATEGORY_ROUTING},
{"timers", DEBUG_CATEGORY_TIMERS}, {"timers", DEBUG_CATEGORY_TIMERS},
{"normalizer", DEBUG_CATEGORY_NORMALIZER},
{"bgp", DEBUG_CATEGORY_BGP},
{"socket", DEBUG_CATEGORY_SOCKET},
{"control", DEBUG_CATEGORY_CONTROL},
{"dump", DEBUG_CATEGORY_DUMP}, {"dump", DEBUG_CATEGORY_DUMP},
{"all", DEBUG_CATEGORY_ALL}, {"all", DEBUG_CATEGORY_ALL},
{NULL, 0} {NULL, 0}

12
src/config_parser.c

@ -532,6 +532,18 @@ static struct utun_config* parse_config_internal(FILE *fp, const char *filename)
add_route_entry(&cfg->my_subnets, value); add_route_entry(&cfg->my_subnets, value);
} }
break; break;
case SECTION_DEBUG:
// Format: category=level (e.g., etcp=debug, crypto=info)
if (cfg->global.debug_levels.count < 16) {
strncpy(cfg->global.debug_levels.category[cfg->global.debug_levels.count],
key, 15);
cfg->global.debug_levels.category[cfg->global.debug_levels.count][15] = '\0';
strncpy(cfg->global.debug_levels.level[cfg->global.debug_levels.count],
value, 15);
cfg->global.debug_levels.level[cfg->global.debug_levels.count][15] = '\0';
cfg->global.debug_levels.count++;
}
break;
default: default:
DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "%s:%d: Key outside section: %s", filename, line_num, key); DEBUG_WARN(DEBUG_CATEGORY_CONFIG, "%s:%d: Key outside section: %s", filename, line_num, key);
break; break;

2
src/routing.c

@ -177,7 +177,7 @@ static void routing_pkt_from_tun_cb(struct ll_queue* q, void* arg) {
struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip); struct ROUTE_ARRAY* routes = route_table_lookup(instance->rt, dst_ip);
if (!routes || routes->routes == 0) { if (!routes || routes->routes == 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str); DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "No route to %s, dropping packet", ip_to_str(&addr, AF_INET).str);
free(pkt->ll.dgram); free(pkt->ll.dgram);
memory_pool_free(instance->tun->pool, pkt); memory_pool_free(instance->tun->pool, pkt);
} else { } else {

119
src/tun_route.c

@ -46,18 +46,37 @@ struct nl_req {
}; };
static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int cmd, int flags) { static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int cmd, int flags) {
int fd = socket(AF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, NETLINK_ROUTE); int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if (fd < 0) { if (fd < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create netlink socket: %s", strerror(errno)); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to create netlink socket: %s", strerror(errno));
return -1; return -1;
} }
// Bind to receive responses
struct sockaddr_nl addr;
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_pid = getpid();
addr.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to bind netlink socket: %s", strerror(errno));
close(fd);
return -1;
}
// Prepare destination address (kernel)
struct sockaddr_nl dest;
memset(&dest, 0, sizeof(dest));
dest.nl_family = AF_NETLINK;
dest.nl_pid = 0; // kernel
dest.nl_groups = 0;
struct nl_req req; struct nl_req req;
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.nl.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
req.nl.nlmsg_type = cmd; // RTM_NEWROUTE or RTM_DELROUTE req.nl.nlmsg_type = cmd; // RTM_NEWROUTE or RTM_DELROUTE
req.nl.nlmsg_flags = flags | NLM_F_REQUEST; req.nl.nlmsg_flags = flags | NLM_F_REQUEST | NLM_F_ACK; // Request ACK from kernel
req.nl.nlmsg_seq = 1; req.nl.nlmsg_seq = 1;
req.nl.nlmsg_pid = getpid(); req.nl.nlmsg_pid = getpid();
@ -82,12 +101,15 @@ static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int
memcpy(RTA_DATA(rta), &ifindex, 4); memcpy(RTA_DATA(rta), &ifindex, 4);
req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rta->rta_len); req.nl.nlmsg_len = NLMSG_ALIGN(req.nl.nlmsg_len) + RTA_ALIGN(rta->rta_len);
if (send(fd, &req, req.nl.nlmsg_len, 0) < 0) { if (sendto(fd, &req, req.nl.nlmsg_len, 0, (struct sockaddr *)&dest, sizeof(dest)) < 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to send netlink message: %s", strerror(errno)); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Failed to send netlink message: %s", strerror(errno));
close(fd); close(fd);
return -1; return -1;
} }
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Netlink message sent: seq=%u pid=%u len=%d",
req.nl.nlmsg_seq, req.nl.nlmsg_pid, req.nl.nlmsg_len);
// Wait for response with timeout using poll // Wait for response with timeout using poll
struct pollfd pfd = { .fd = fd, .events = POLLIN }; struct pollfd pfd = { .fd = fd, .events = POLLIN };
int poll_ret = poll(&pfd, 1, 1000); // 1 second timeout int poll_ret = poll(&pfd, 1, 1000); // 1 second timeout
@ -96,11 +118,13 @@ static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int
close(fd); close(fd);
return -1; return -1;
} else if (poll_ret == 0) { } else if (poll_ret == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Timeout waiting for netlink response"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Timeout waiting for netlink response (sent %d bytes)", req.nl.nlmsg_len);
close(fd); close(fd);
return -1; return -1;
} }
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Poll returned: revents=%d", pfd.revents);
// Receive response // Receive response
char reply[4096]; char reply[4096];
ssize_t len = recv(fd, reply, sizeof(reply), 0); ssize_t len = recv(fd, reply, sizeof(reply), 0);
@ -110,7 +134,12 @@ static int netlink_route(int ifindex, uint32_t network, uint8_t prefix_len, int
return -1; return -1;
} }
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Received netlink response: len=%d", (int)len);
struct nlmsghdr *nl_hdr = (struct nlmsghdr *)reply; struct nlmsghdr *nl_hdr = (struct nlmsghdr *)reply;
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Netlink msg: type=%d seq=%d pid=%d",
nl_hdr->nlmsg_type, nl_hdr->nlmsg_seq, nl_hdr->nlmsg_pid);
if (nl_hdr->nlmsg_type == NLMSG_ERROR) { if (nl_hdr->nlmsg_type == NLMSG_ERROR) {
struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nl_hdr); struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nl_hdr);
if (err->error < 0) { if (err->error < 0) {
@ -138,44 +167,42 @@ static int ip_route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len
return (ret == 0) ? 0 : -1; return (ret == 0) ? 0 : -1;
} }
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_add(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
if (ifindex == 0) { if (ifindex == 0 && (!ifname || !ifname[0])) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index and name are both invalid");
return -1; return -1;
} }
network = htonl(network); network = htonl(network);
// Try netlink first // Try netlink first
if (netlink_route(ifindex, network, prefix_len, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL) == 0) { if (ifindex != 0 && netlink_route(ifindex, network, prefix_len, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL) == 0) {
return 0; return 0;
} }
// Fallback to ip route command // Fallback to ip route command
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex); DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex);
char ifname[16]; const char *dev = ifname ? ifname : "";
snprintf(ifname, sizeof(ifname), "%u", ifindex); return ip_route_cmd(dev, ntohl(network), prefix_len, "add");
return ip_route_cmd(ifname, ntohl(network), prefix_len, "add");
} }
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_del(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
if (ifindex == 0) { if (ifindex == 0 && (!ifname || !ifname[0])) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex and ifname are both invalid");
return -1; return -1;
} }
network = htonl(network); network = htonl(network);
// Try netlink first // Try netlink first
if (netlink_route(ifindex, network, prefix_len, RTM_DELROUTE, 0) == 0) { if (ifindex != 0 && netlink_route(ifindex, network, prefix_len, RTM_DELROUTE, 0) == 0) {
return 0; return 0;
} }
// Fallback to ip route command // Fallback to ip route command
char ifname[16];
snprintf(ifname, sizeof(ifname), "%u", ifindex);
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex); DEBUG_WARN(DEBUG_CATEGORY_TUN, "Netlink failed, trying ip route command for ifindex %u", ifindex);
return ip_route_cmd(ifname, ntohl(network), prefix_len, "del"); const char *dev = ifname ? ifname : "";
return ip_route_cmd(dev, ntohl(network), prefix_len, "del");
} }
int tun_route_flush(const char *ifname) { int tun_route_flush(const char *ifname) {
@ -196,11 +223,30 @@ int tun_route_flush(const char *ifname) {
return (ret == 0) ? 0 : -1; return (ret == 0) ? 0 : -1;
} }
int tun_route_del_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENTRY *routes) {
int count = 0;
struct CFG_ROUTE_ENTRY *entry = routes;
while (entry) {
uint32_t network = ntohl(entry->ip.addr.v4.s_addr);
if (entry->ip.family == AF_INET) {
if (tun_route_del(ifindex, ifname, network, entry->netmask) == 0) {
count++;
}
}
entry = entry->next;
}
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted %d routes via ifindex=%lu", count, (unsigned long)ifindex);
return count;
}
#elif defined(_WIN32) #elif defined(_WIN32)
// Windows IP Helper API implementation // Windows IP Helper API implementation
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_add(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
(void)ifname; // Not used on Windows
if (ifindex == 0) { if (ifindex == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_add: ifindex is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_add: ifindex is 0");
return -1; return -1;
@ -248,7 +294,8 @@ int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) {
return 0; return 0;
} }
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_del(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
(void)ifname; // Not used on Windows
if (ifindex == 0) { if (ifindex == 0) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0");
return -1; return -1;
@ -318,14 +365,14 @@ int tun_route_flush(const char *ifname) {
return 0; return 0;
} }
int tun_route_del_all(uint32_t ifindex, struct CFG_ROUTE_ENTRY *routes) { int tun_route_del_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENTRY *routes) {
int count = 0; int count = 0;
struct CFG_ROUTE_ENTRY *entry = routes; struct CFG_ROUTE_ENTRY *entry = routes;
while (entry) { while (entry) {
uint32_t network = ntohl(entry->ip.addr.v4.s_addr); uint32_t network = ntohl(entry->ip.addr.v4.s_addr);
if (entry->ip.family == AF_INET) { if (entry->ip.family == AF_INET) {
if (tun_route_del(ifindex, network, entry->netmask) == 0) { if (tun_route_del(ifindex, ifname, network, entry->netmask) == 0) {
count++; count++;
} }
} }
@ -415,40 +462,38 @@ static int route_cmd(const char *ifname, uint32_t network, uint8_t prefix_len, c
return (ret == 0) ? 0 : -1; return (ret == 0) ? 0 : -1;
} }
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_add(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
if (ifindex == 0) { if (ifindex == 0 && (!ifname || !ifname[0])) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "Interface index and name are both invalid");
return -1; return -1;
} }
// Try routing socket first // Try routing socket first
if (routing_socket_cmd(ifindex, network, prefix_len, RTM_ADD) == 0) { if (ifindex != 0 && routing_socket_cmd(ifindex, network, prefix_len, RTM_ADD) == 0) {
return 0; return 0;
} }
// Fallback to route command // Fallback to route command
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex); DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex);
char ifname[16]; const char *dev = ifname ? ifname : "";
snprintf(ifname, sizeof(ifname), "%u", ifindex); return route_cmd(dev, network, prefix_len, "add");
return route_cmd(ifname, network, prefix_len, "add");
} }
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len) { int tun_route_del(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len) {
if (ifindex == 0) { if (ifindex == 0 && (!ifname || !ifname[0])) {
DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex is 0"); DEBUG_ERROR(DEBUG_CATEGORY_TUN, "tun_route_del: ifindex and ifname are both invalid");
return -1; return -1;
} }
// Try routing socket first // Try routing socket first
if (routing_socket_cmd(ifindex, network, prefix_len, RTM_DELETE) == 0) { if (ifindex != 0 && routing_socket_cmd(ifindex, network, prefix_len, RTM_DELETE) == 0) {
return 0; return 0;
} }
// Fallback to route command // Fallback to route command
char ifname[16];
snprintf(ifname, sizeof(ifname), "%u", ifindex);
DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex); DEBUG_WARN(DEBUG_CATEGORY_TUN, "Routing socket failed, trying route command for ifindex %u", ifindex);
return route_cmd(ifname, network, prefix_len, "delete"); const char *dev = ifname ? ifname : "";
return route_cmd(dev, network, prefix_len, "delete");
} }
int tun_route_flush(const char *ifname) { int tun_route_flush(const char *ifname) {
@ -474,7 +519,7 @@ int tun_route_add_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENT
while (entry) { while (entry) {
uint32_t network = ntohl(entry->ip.addr.v4.s_addr); uint32_t network = ntohl(entry->ip.addr.v4.s_addr);
if (entry->ip.family == AF_INET) { if (entry->ip.family == AF_INET) {
if (tun_route_add(ifindex, network, entry->netmask) == 0) { if (tun_route_add(ifindex, ifname, network, entry->netmask) == 0) {
struct in_addr addr; struct in_addr addr;
addr.s_addr = entry->ip.addr.v4.s_addr; addr.s_addr = entry->ip.addr.v4.s_addr;
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added route %s/%d via %s", ip_to_str(&addr, AF_INET).str, entry->netmask, ifname); DEBUG_INFO(DEBUG_CATEGORY_TUN, "Added route %s/%d via %s", ip_to_str(&addr, AF_INET).str, entry->netmask, ifname);

9
src/tun_route.h

@ -14,28 +14,31 @@ struct CFG_ROUTE_ENTRY;
/** /**
* @brief Add system route for a subnet via TUN interface * @brief Add system route for a subnet via TUN interface
* @param ifindex Interface index * @param ifindex Interface index
* @param ifname Interface name (e.g., "tun0")
* @param network Network address in host byte order * @param network Network address in host byte order
* @param prefix_len Prefix length (1-32) * @param prefix_len Prefix length (1-32)
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
int tun_route_add(uint32_t ifindex, uint32_t network, uint8_t prefix_len); int tun_route_add(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len);
/** /**
* @brief Delete system route for a subnet via TUN interface * @brief Delete system route for a subnet via TUN interface
* @param ifindex Interface index * @param ifindex Interface index
* @param ifname Interface name (e.g., "tun0")
* @param network Network address in host byte order * @param network Network address in host byte order
* @param prefix_len Prefix length (1-32) * @param prefix_len Prefix length (1-32)
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
int tun_route_del(uint32_t ifindex, uint32_t network, uint8_t prefix_len); int tun_route_del(uint32_t ifindex, const char *ifname, uint32_t network, uint8_t prefix_len);
/** /**
* @brief Delete all system routes from config entries * @brief Delete all system routes from config entries
* @param ifindex Interface index * @param ifindex Interface index
* @param ifname Interface name (e.g., "tun0")
* @param routes Linked list of route entries to delete * @param routes Linked list of route entries to delete
* @return Number of routes deleted * @return Number of routes deleted
*/ */
int tun_route_del_all(uint32_t ifindex, struct CFG_ROUTE_ENTRY *routes); int tun_route_del_all(uint32_t ifindex, const char *ifname, struct CFG_ROUTE_ENTRY *routes);
/** /**
* @brief Delete all system routes via specified interface * @brief Delete all system routes via specified interface

39
src/utun_instance.c

@ -159,6 +159,43 @@ struct UTUN_INSTANCE* utun_instance_create(struct UASYNC* ua, const char *config
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Applied debug_level from config: %s", config->global.debug_level); DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Applied debug_level from config: %s", config->global.debug_level);
} }
// Apply per-category debug levels from [debug] section
for (int i = 0; i < config->global.debug_levels.count; i++) {
const char* cat_name = config->global.debug_levels.category[i];
const char* lvl_str = config->global.debug_levels.level[i];
debug_category_t cat = 0;
// Map category name to bitmask
if (strcmp(cat_name, "uasync") == 0) cat = DEBUG_CATEGORY_UASYNC;
else if (strcmp(cat_name, "ll_queue") == 0) cat = DEBUG_CATEGORY_LL_QUEUE;
else if (strcmp(cat_name, "connection") == 0) cat = DEBUG_CATEGORY_CONNECTION;
else if (strcmp(cat_name, "etcp") == 0) cat = DEBUG_CATEGORY_ETCP;
else if (strcmp(cat_name, "crypto") == 0) cat = DEBUG_CATEGORY_CRYPTO;
else if (strcmp(cat_name, "memory") == 0) cat = DEBUG_CATEGORY_MEMORY;
else if (strcmp(cat_name, "timing") == 0) cat = DEBUG_CATEGORY_TIMING;
else if (strcmp(cat_name, "config") == 0) cat = DEBUG_CATEGORY_CONFIG;
else if (strcmp(cat_name, "tun") == 0) cat = DEBUG_CATEGORY_TUN;
else if (strcmp(cat_name, "routing") == 0) cat = DEBUG_CATEGORY_ROUTING;
else if (strcmp(cat_name, "timers") == 0) cat = DEBUG_CATEGORY_TIMERS;
else if (strcmp(cat_name, "normalizer") == 0) cat = DEBUG_CATEGORY_NORMALIZER;
else if (strcmp(cat_name, "bgp") == 0) cat = DEBUG_CATEGORY_BGP;
else if (strcmp(cat_name, "socket") == 0) cat = DEBUG_CATEGORY_SOCKET;
else if (strcmp(cat_name, "control") == 0) cat = DEBUG_CATEGORY_CONTROL;
else if (strcmp(cat_name, "dump") == 0) cat = DEBUG_CATEGORY_DUMP;
if (cat) {
debug_level_t lvl = DEBUG_LEVEL_NONE;
if (strcmp(lvl_str, "error") == 0) lvl = DEBUG_LEVEL_ERROR;
else if (strcmp(lvl_str, "warn") == 0) lvl = DEBUG_LEVEL_WARN;
else if (strcmp(lvl_str, "info") == 0) lvl = DEBUG_LEVEL_INFO;
else if (strcmp(lvl_str, "debug") == 0) lvl = DEBUG_LEVEL_DEBUG;
else if (strcmp(lvl_str, "trace") == 0) lvl = DEBUG_LEVEL_TRACE;
debug_set_category_level(cat, lvl);
DEBUG_INFO(DEBUG_CATEGORY_CONFIG, "Applied per-category debug: %s=%s", cat_name, lvl_str);
}
}
// Allocate instance // Allocate instance
struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE)); struct UTUN_INSTANCE *instance = calloc(1, sizeof(struct UTUN_INSTANCE));
if (!instance) { if (!instance) {
@ -252,7 +289,7 @@ void utun_instance_destroy(struct UTUN_INSTANCE *instance) {
// Delete system routes added at startup // Delete system routes added at startup
if (instance->tun->ifindex && instance->route_subnets) { if (instance->tun->ifindex && instance->route_subnets) {
int deleted = tun_route_del_all(instance->tun->ifindex, instance->route_subnets); int deleted = tun_route_del_all(instance->tun->ifindex, instance->tun->ifname, instance->route_subnets);
DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted %d system routes for TUN interface", deleted); DEBUG_INFO(DEBUG_CATEGORY_TUN, "Deleted %d system routes for TUN interface", deleted);
} }

BIN
tests/bench_timeout_heap

Binary file not shown.

BIN
tests/bench_uasync_timeouts

Binary file not shown.
Loading…
Cancel
Save