Browse Source

1

nodeinfo-routing-update
jeka 4 weeks ago
parent
commit
0e9a91729c
  1. 2
      doc/dgram_protocol.txt
  2. 26
      doc/etcp_arch.md
  3. 1
      lib/ll_queue.h
  4. 22
      src/control_server.c
  5. 7
      src/routing.c
  6. 4
      src/utun_instance.h
  7. 117
      tools/etcpmon/etcpmon_gui.c
  8. 22
      tools/etcpmon/etcpmon_gui.h
  9. 15
      tools/etcpmon/etcpmon_protocol.h

2
doc/dgram_protocol.txt

@ -1,2 +0,0 @@
форматы кодограмм протокола dgram:
- dgram протокол отправляет сообщения в очередь input pkt_normalizer.

26
doc/etcp_arch.md

@ -1,5 +1,31 @@
Архитектура etcp: Архитектура etcp:
ETCP устанавливает только одно подключение между двумя узлами. Это подключение может добавлять-убирать каналы связи (динамически) без разрыва соединения.
Также каналы связи мониторятся и трафик распределяется между доступными каналами. Если канал определяется как недоступен - он исключается из обмена.
Все каналы периодически мониторятся на доступность (keepalive).
Роутинг.
utun поддерживает встроенный ipv4 роутинг, может через промежуточные узлы доставлять пакеты.
У каждого узла есть свои маршруты. Эти маршруты при подключении распространяются по остальным узлам.
Связь между узлами:
Каждый узел имеет настройку NAT для каждого listen сокета: public / nat / private.
public - нет nat, можно подключаться напрямую
nat - есть правильный nat с static port (т.е. можно подключаться напрямую зная присвоенный ip:port)
private - нельзя подключаться
Приоритетный способ обмена данными - прямое подключение к узлу. Если один из узлов имеет не private интерфейс то создается подключение через него.
Если не удается подключиться напрямую - выбирается переадча через промежуточный узел с наилучшим качеством канала (считается из задержки, числа хопов, bandwidth, потерь)
Для установки прямого соединения шлётся запрос удаленному узлу через существующие соединения на запрос подключения.
Запрос включает мой id, pubkey, доступные каналы связи и их [ip:port]. удаленный узел запоминает эти данные и отправляет response с такими же данными.
При получении request или response узел смотрит каких подключений (links) еще нет и пробует инициировать на подходщих линках с узлом.
Таким образом будет инициировано подключение между узлами по всем доступным линкам.
Если у каждого из узлов есть более одного канала то создаётся m * n подключений (каждый сокет с каждым). которые дальше работают как обычно - балансировщик нагрузки далее в процессе выбирает как лучше отправить очередной пакет (больше вариантов - можно найти путь лучше).
Есть статические подключения (которые прописаны в конфиге) и есть динамические - которые устанавливаются в процессе по необходимости.
Обмен маршрутами происходит только через статические подключения.
toto:
- задать ограничение bandwidth для каждого сокета (общее).
## etcp_connections: ## etcp_connections:
- обслуживает encrypt/decrypt и установку защищенного подключения. - обслуживает encrypt/decrypt и установку защищенного подключения.
- для одного etcp соединения может испольоваться несколько подключений одновременно (load balancing / filover) - для одного etcp соединения может испольоваться несколько подключений одновременно (load balancing / filover)

1
lib/ll_queue.h

@ -6,6 +6,7 @@
#include "memory_pool.h" // для struct memory_pool #include "memory_pool.h" // для struct memory_pool
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h>
#include <windows.h> #include <windows.h>
#else #else
#include <pthread.h> #include <pthread.h>

22
src/control_server.c

@ -9,6 +9,7 @@
#include "etcp.h" #include "etcp.h"
#include "etcp_connections.h" #include "etcp_connections.h"
#include "tun_if.h" #include "tun_if.h"
#include "route_lib.h"
#include "../lib/u_async.h" #include "../lib/u_async.h"
#include "../lib/debug_config.h" #include "../lib/debug_config.h"
#include "../lib/mem.h" #include "../lib/mem.h"
@ -767,6 +768,27 @@ static void send_metrics(struct control_server* server, struct control_client* c
rsp->tun.packets_written = instance->tun->packets_written; rsp->tun.packets_written = instance->tun->packets_written;
rsp->tun.read_errors = instance->tun->read_errors; rsp->tun.read_errors = instance->tun->read_errors;
rsp->tun.write_errors = instance->tun->write_errors; rsp->tun.write_errors = instance->tun->write_errors;
/* Routing statistics */
rsp->tun.routed_packets = instance->routed_packets;
rsp->tun.dropped_packets = instance->dropped_packets;
/* TUN queues */
rsp->tun.tun_in_q_packets = (uint32_t)queue_entry_count(instance->tun->input_queue);
rsp->tun.tun_in_q_bytes = (uint32_t)queue_total_bytes(instance->tun->input_queue);
rsp->tun.tun_out_q_packets = (uint32_t)queue_entry_count(instance->tun->output_queue);
rsp->tun.tun_out_q_bytes = (uint32_t)queue_total_bytes(instance->tun->output_queue);
/* Routing table */
if (instance->rt) {
rsp->tun.rt_count = (uint32_t)instance->rt->count;
rsp->tun.rt_local = (uint32_t)instance->rt->stats.local_routes;
rsp->tun.rt_learned = (uint32_t)instance->rt->stats.learned_routes;
} else {
rsp->tun.rt_count = 0;
rsp->tun.rt_local = 0;
rsp->tun.rt_learned = 0;
}
} else { } else {
memset(&rsp->tun, 0, sizeof(rsp->tun)); memset(&rsp->tun, 0, sizeof(rsp->tun));
} }

7
src/routing.c

@ -114,6 +114,7 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
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_INFO(DEBUG_CATEGORY_ROUTING, "route_pkt: no route to %s, dropping", ip_to_str(&addr, AF_INET).str); DEBUG_INFO(DEBUG_CATEGORY_ROUTING, "route_pkt: no route to %s, dropping", ip_to_str(&addr, AF_INET).str);
instance->dropped_packets++;
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
@ -124,11 +125,13 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
// Local route - send to TUN (entry has [cmd=0][IP data], TUN skips cmd byte) // Local route - send to TUN (entry has [cmd=0][IP data], TUN skips cmd byte)
if (queue_data_put(instance->tun->input_queue, entry, 0) != 0) { if (queue_data_put(instance->tun->input_queue, entry, 0) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN input_queue"); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: failed to put to TUN input_queue");
instance->dropped_packets++;
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Entry sent to TUN, don't free here // Entry sent to TUN, don't free here
instance->routed_packets++;
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sent %zu bytes to TUN", ip_len); DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sent %zu bytes to TUN", ip_len);
return; return;
} }
@ -137,6 +140,7 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
struct ETCP_CONN* conn = routes->entries[0]->next_hop; struct ETCP_CONN* conn = routes->entries[0]->next_hop;
if (!conn) { if (!conn) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: route to %s has no next_hop, dropping", ip_to_str(&addr, AF_INET).str); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: route to %s has no next_hop, dropping", ip_to_str(&addr, AF_INET).str);
instance->dropped_packets++;
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
@ -144,6 +148,7 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
if (!conn->normalizer) { if (!conn->normalizer) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: connection for %s has no normalizer, dropping", ip_to_str(&addr, AF_INET).str); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: connection for %s has no normalizer, dropping", ip_to_str(&addr, AF_INET).str);
instance->dropped_packets++;
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
@ -153,12 +158,14 @@ static void route_pkt(struct UTUN_INSTANCE* instance, struct ll_entry* entry) {
DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to ETCP %s", ip_len, conn->log_name); DEBUG_DEBUG(DEBUG_CATEGORY_ROUTING, "route_pkt: sending %zu bytes to ETCP %s", ip_len, conn->log_name);
if (etcp_send(conn, entry) != 0) { if (etcp_send(conn, entry) != 0) {
DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed for %s", ip_to_str(&addr, AF_INET).str); DEBUG_WARN(DEBUG_CATEGORY_ROUTING, "route_pkt: etcp_send failed for %s", ip_to_str(&addr, AF_INET).str);
instance->dropped_packets++;
queue_entry_free(entry); queue_entry_free(entry);
queue_dgram_free(entry); queue_dgram_free(entry);
return; return;
} }
// Entry sent successfully, don't free here // Entry sent successfully, don't free here
instance->routed_packets++;
} }
// Callback for packets from ETCP (via etcp_bind id=0) // Callback for packets from ETCP (via etcp_bind id=0)

4
src/utun_instance.h

@ -56,6 +56,10 @@ struct UTUN_INSTANCE {
// Active sockets // Active sockets
struct ETCP_SOCKET* etcp_sockets;// linked-list struct ETCP_SOCKET* etcp_sockets;// linked-list
// Routing statistics
uint64_t routed_packets;
uint64_t dropped_packets;
// ETCP API bindings (per-instance) // ETCP API bindings (per-instance)
struct ETCP_BINDINGS api_bindings; struct ETCP_BINDINGS api_bindings;

117
tools/etcpmon/etcpmon_gui.c

@ -19,7 +19,7 @@
//#pragma comment(lib, "user32.lib") //#pragma comment(lib, "user32.lib")
//#pragma comment(lib, "gdi32.lib") //#pragma comment(lib, "gdi32.lib")
#define WINDOW_WIDTH 900 #define WINDOW_WIDTH 900
#define WINDOW_HEIGHT 1080 #define WINDOW_HEIGHT 1150
#define UPDATE_INTERVAL 10 /* 50ms → 20 samples per second */ #define UPDATE_INTERVAL 10 /* 50ms → 20 samples per second */
/* Global app pointer for callbacks */ /* Global app pointer for callbacks */
static struct etcpmon_app* g_app = NULL; static struct etcpmon_app* g_app = NULL;
@ -255,7 +255,7 @@ static void CreateControls(struct etcpmon_app* app) {
y = 485; y = 485;
CreateWindowExA(0, "BUTTON", "ETCP Metrics", CreateWindowExA(0, "BUTTON", "ETCP Metrics",
WS_CHILD | WS_VISIBLE | BS_GROUPBOX, WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
x, y, 430, 220, hWnd, (HMENU)IDC_STATIC, hInst, NULL); x, y, 430, 180, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
int mx = x + 10, my = y + 20; int mx = x + 10, my = y + 20;
@ -263,7 +263,7 @@ static void CreateControls(struct etcpmon_app* app) {
WS_CHILD | WS_VISIBLE, mx, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); WS_CHILD | WS_VISIBLE, mx, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditEtcpName = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", app->hEditEtcpName = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_AUTOHSCROLL, WS_CHILD | WS_VISIBLE | ES_READONLY | ES_AUTOHSCROLL,
mx + 85, my, 330, 20, hWnd, (HMENU)IDC_EDIT_ETCP_NAME, hInst, NULL); mx + 85, my, 310, 20, hWnd, (HMENU)IDC_EDIT_ETCP_NAME, hInst, NULL);
my += 25; my += 25;
CreateWindowExA(0, "STATIC", "RTT Last:", CreateWindowExA(0, "STATIC", "RTT Last:",
@ -279,7 +279,7 @@ static void CreateControls(struct etcpmon_app* app) {
mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_ETCP_RTT_AVG10, hInst, NULL); mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_ETCP_RTT_AVG10, hInst, NULL);
my += 25; my += 25;
CreateWindowExA(0, "STATIC", "RTT Avg 100:", CreateWindowExA(0, "STATIC", "RTTAvg100:",
WS_CHILD | WS_VISIBLE, mx, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); WS_CHILD | WS_VISIBLE, mx, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditEtcpRttAvg100 = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", app->hEditEtcpRttAvg100 = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY, WS_CHILD | WS_VISIBLE | ES_READONLY,
@ -324,11 +324,11 @@ static void CreateControls(struct etcpmon_app* app) {
WS_CHILD | WS_VISIBLE | ES_READONLY, WS_CHILD | WS_VISIBLE | ES_READONLY,
mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_ETCP_LINKS, hInst, NULL); mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_ETCP_LINKS, hInst, NULL);
/* TUN Metrics group - right of ETCP Metrics */ /* TUN/Routing Metrics group - right of ETCP Metrics */
x = 460; y = 485; x = 460; y = 485;
CreateWindowExA(0, "BUTTON", "TUN Metrics", CreateWindowExA(0, "BUTTON", "TUN/Routing Metrics",
WS_CHILD | WS_VISIBLE | BS_GROUPBOX, WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
x, y, 430, 140, hWnd, (HMENU)IDC_STATIC, hInst, NULL); x, y, 430, 180, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
mx = x + 10; my = y + 20; mx = x + 10; my = y + 20;
@ -339,7 +339,7 @@ static void CreateControls(struct etcpmon_app* app) {
mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_BYTES, hInst, NULL); mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_BYTES, hInst, NULL);
CreateWindowExA(0, "STATIC", "Write Bytes:", CreateWindowExA(0, "STATIC", "Write Bytes:",
WS_CHILD | WS_VISIBLE, mx + 200, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); WS_CHILD | WS_VISIBLE, mx + 200, my, 90, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditTunWriteBytes = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", app->hEditTunWriteBytes = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY, WS_CHILD | WS_VISIBLE | ES_READONLY,
mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_BYTES, hInst, NULL); mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_BYTES, hInst, NULL);
@ -352,7 +352,7 @@ static void CreateControls(struct etcpmon_app* app) {
mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_PKTS, hInst, NULL); mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_PKTS, hInst, NULL);
CreateWindowExA(0, "STATIC", "Write Pkts:", CreateWindowExA(0, "STATIC", "Write Pkts:",
WS_CHILD | WS_VISIBLE, mx + 200, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); WS_CHILD | WS_VISIBLE, mx + 200, my, 90, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditTunWritePkts = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", app->hEditTunWritePkts = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY, WS_CHILD | WS_VISIBLE | ES_READONLY,
mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_PKTS, hInst, NULL); mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_PKTS, hInst, NULL);
@ -365,11 +365,63 @@ static void CreateControls(struct etcpmon_app* app) {
mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_ERRS, hInst, NULL); mx + 85, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_READ_ERRS, hInst, NULL);
CreateWindowExA(0, "STATIC", "Write Errs:", CreateWindowExA(0, "STATIC", "Write Errs:",
WS_CHILD | WS_VISIBLE, mx + 200, my, 80, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL); WS_CHILD | WS_VISIBLE, mx + 200, my, 90, 20, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditTunWriteErrs = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", app->hEditTunWriteErrs = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY, WS_CHILD | WS_VISIBLE | ES_READONLY,
mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_ERRS, hInst, NULL); mx + 285, my, 100, 20, hWnd, (HMENU)IDC_EDIT_TUN_WRITE_ERRS, hInst, NULL);
/* Routing section */
my += 30;
CreateWindowExA(0, "STATIC", "Routed:",
WS_CHILD | WS_VISIBLE, mx, my, 60, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtRouted = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 65, my - 2, 80, 18, hWnd, (HMENU)IDC_EDIT_RT_ROUTED, hInst, NULL);
CreateWindowExA(0, "STATIC", "Dropped:",
WS_CHILD | WS_VISIBLE, mx + 155, my, 60, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtDropped = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 220, my - 2, 80, 18, hWnd, (HMENU)IDC_EDIT_RT_DROPPED, hInst, NULL);
my += 25;
CreateWindowExA(0, "STATIC", "TunInQ:",
WS_CHILD | WS_VISIBLE, mx, my, 60, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtTunInQPkts = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 65, my - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_RT_TUN_IN_Q_PKTS, hInst, NULL);
app->hEditRtTunInQBytes = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 120, my - 2, 60, 18, hWnd, (HMENU)IDC_EDIT_RT_TUN_IN_Q_BYTES, hInst, NULL);
CreateWindowExA(0, "STATIC", "TunOutQ:",
WS_CHILD | WS_VISIBLE, mx + 190, my, 60, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtTunOutQPkts = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 255, my - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_RT_TUN_OUT_Q_PKTS, hInst, NULL);
app->hEditRtTunOutQBytes = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 310, my - 2, 60, 18, hWnd, (HMENU)IDC_EDIT_RT_TUN_OUT_Q_BYTES, hInst, NULL);
my += 25;
CreateWindowExA(0, "STATIC", "RT:",
WS_CHILD | WS_VISIBLE, mx, my, 30, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtCount = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 35, my - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_RT_COUNT, hInst, NULL);
CreateWindowExA(0, "STATIC", "Local:",
WS_CHILD | WS_VISIBLE, mx + 95, my, 40, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtLocal = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 140, my - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_RT_LOCAL, hInst, NULL);
CreateWindowExA(0, "STATIC", "Learned:",
WS_CHILD | WS_VISIBLE, mx + 200, my, 55, 18, hWnd, (HMENU)IDC_STATIC, hInst, NULL);
app->hEditRtLearned = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "",
WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER,
mx + 260, my - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_RT_LEARNED, hInst, NULL);
/* Links list */ /* Links list */
y = 715; y = 715;
CreateWindowExA(0, "STATIC", "Links:", CreateWindowExA(0, "STATIC", "Links:",
@ -378,10 +430,10 @@ static void CreateControls(struct etcpmon_app* app) {
app->hListLinks = CreateWindowExA(WS_EX_CLIENTEDGE, "LISTBOX", "", app->hListLinks = CreateWindowExA(WS_EX_CLIENTEDGE, "LISTBOX", "",
WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT, WS_CHILD | WS_VISIBLE | LBS_NOTIFY | WS_VSCROLL | LBS_NOINTEGRALHEIGHT,
10, y + 20, 880, 100, hWnd, (HMENU)IDC_LIST_LINKS, hInst, NULL); 10, y + 20, 880, 160, hWnd, (HMENU)IDC_LIST_LINKS, hInst, NULL);
/* Queues & Errors group - below Links */ /* Queues & Errors group - below Links */
y = 845; y = 905;
CreateWindowExA(0, "BUTTON", "Queues & Errors", CreateWindowExA(0, "BUTTON", "Queues & Errors",
WS_CHILD | WS_VISIBLE | BS_GROUPBOX, WS_CHILD | WS_VISIBLE | BS_GROUPBOX,
10, y, 880, 165, hWnd, (HMENU)IDC_STATIC_QUEUES, hInst, NULL); 10, y, 880, 165, hWnd, (HMENU)IDC_STATIC_QUEUES, hInst, NULL);
@ -765,6 +817,17 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
UpdateEditIfChanged(hMain, IDC_EDIT_TUN_READ_ERRS, "%u", metrics->tun.read_errors); UpdateEditIfChanged(hMain, IDC_EDIT_TUN_READ_ERRS, "%u", metrics->tun.read_errors);
UpdateEditIfChanged(hMain, IDC_EDIT_TUN_WRITE_ERRS, "%u", metrics->tun.write_errors); UpdateEditIfChanged(hMain, IDC_EDIT_TUN_WRITE_ERRS, "%u", metrics->tun.write_errors);
/* Routing Metrics */
UpdateEditIfChanged(hMain, IDC_EDIT_RT_ROUTED, "%llu", (unsigned long long)metrics->tun.routed_packets);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_DROPPED, "%llu", (unsigned long long)metrics->tun.dropped_packets);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_TUN_IN_Q_PKTS, "%u", metrics->tun.tun_in_q_packets);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_TUN_IN_Q_BYTES, "%u", metrics->tun.tun_in_q_bytes);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_TUN_OUT_Q_PKTS, "%u", metrics->tun.tun_out_q_packets);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_TUN_OUT_Q_BYTES, "%u", metrics->tun.tun_out_q_bytes);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_COUNT, "%u", metrics->tun.rt_count);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_LOCAL, "%u", metrics->tun.rt_local);
UpdateEditIfChanged(hMain, IDC_EDIT_RT_LEARNED, "%u", metrics->tun.rt_learned);
/* Queue Metrics */ /* Queue Metrics */
UpdateEditIfChanged(hMain, IDC_EDIT_Q_IN_Q_BYTES, "%u", metrics->etcp.input_queue_bytes); UpdateEditIfChanged(hMain, IDC_EDIT_Q_IN_Q_BYTES, "%u", metrics->etcp.input_queue_bytes);
UpdateEditIfChanged(hMain, IDC_EDIT_Q_IN_Q_PKTS, "%u", metrics->etcp.input_queue_packets); UpdateEditIfChanged(hMain, IDC_EDIT_Q_IN_Q_PKTS, "%u", metrics->etcp.input_queue_packets);
@ -798,13 +861,13 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
if (app->hListLinks) { if (app->hListLinks) {
SendMessage(app->hListLinks, LB_RESETCONTENT, 0, 0); SendMessage(app->hListLinks, LB_RESETCONTENT, 0, 0);
for (uint8_t i = 0; i < links_count; i++) { for (uint8_t i = 0; i < links_count; i++) {
char display[380]; char line1[320];
snprintf(display, sizeof(display), char line2[256];
snprintf(line1, sizeof(line1),
"Link %u: Status=%s, EncErr=%u, DecErr=%u, " "Link %u: Status=%s, EncErr=%u, DecErr=%u, "
"SndErr=%u, RcvErr=%u, Enc=%llu, Dec=%llu, " "SndErr=%u, RcvErr=%u, Enc=%llu, Dec=%llu, "
"BW=%u Kbps, NAT=%u, RTT=%u us, TT=%u us, " "BW=%u Kbps, NAT=%u, RTT=%u us, TT=%u us",
"Timers: Init=%s, KA=%s, Shaper=%s, "
"KAsent=%u, KArecv=%u",
links[i].local_link_id, links[i].local_link_id,
links[i].status ? "UP" : "DOWN", links[i].status ? "UP" : "DOWN",
links[i].encrypt_errors, links[i].encrypt_errors,
@ -816,13 +879,19 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app,
links[i].bandwidth, links[i].bandwidth,
links[i].nat_changes_count, links[i].nat_changes_count,
links[i].rtt_last * 100, links[i].rtt_last * 100,
links[i].tt_last * 100, links[i].tt_last * 100);
snprintf(line2, sizeof(line2),
" Timers: Init=%s, KA=%s, Shaper=%s | "
"KAsent=%u, KArecv=%u",
links[i].init_timer_active ? "ON" : "OFF", links[i].init_timer_active ? "ON" : "OFF",
links[i].keepalive_timer_active ? "ON" : "OFF", links[i].keepalive_timer_active ? "ON" : "OFF",
links[i].shaper_timer_active ? "ON" : "OFF", links[i].shaper_timer_active ? "ON" : "OFF",
links[i].keepalive_sent, links[i].keepalive_sent,
links[i].keepalive_recv); links[i].keepalive_recv);
SendMessageA(app->hListLinks, LB_ADDSTRING, 0, (LPARAM)display);
SendMessageA(app->hListLinks, LB_ADDSTRING, 0, (LPARAM)line1);
SendMessageA(app->hListLinks, LB_ADDSTRING, 0, (LPARAM)line2);
} }
InvalidateRect(app->hListLinks, NULL, FALSE); InvalidateRect(app->hListLinks, NULL, FALSE);
} }
@ -851,6 +920,16 @@ void etcpmon_gui_clear_metrics(struct etcpmon_app* app) {
SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_READ_ERRS, ""); SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_READ_ERRS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_WRITE_ERRS, ""); SetDlgItemTextA(app->hWndMain, IDC_EDIT_TUN_WRITE_ERRS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_ROUTED, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_DROPPED, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_TUN_IN_Q_PKTS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_TUN_IN_Q_BYTES, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_TUN_OUT_Q_PKTS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_TUN_OUT_Q_BYTES, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_COUNT, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_LOCAL, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_RT_LEARNED, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_Q_BYTES, ""); SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_Q_BYTES, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_Q_PKTS, ""); SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_Q_PKTS, "");
SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_SEND_BYTES, ""); SetDlgItemTextA(app->hWndMain, IDC_EDIT_Q_IN_SEND_BYTES, "");

22
tools/etcpmon/etcpmon_gui.h

@ -59,6 +59,17 @@ extern "C" {
#define IDC_EDIT_TUN_READ_ERRS 304 #define IDC_EDIT_TUN_READ_ERRS 304
#define IDC_EDIT_TUN_WRITE_ERRS 305 #define IDC_EDIT_TUN_WRITE_ERRS 305
/* Routing Metrics control IDs */
#define IDC_EDIT_RT_ROUTED 306
#define IDC_EDIT_RT_DROPPED 307
#define IDC_EDIT_RT_TUN_IN_Q_PKTS 308
#define IDC_EDIT_RT_TUN_IN_Q_BYTES 309
#define IDC_EDIT_RT_TUN_OUT_Q_PKTS 310
#define IDC_EDIT_RT_TUN_OUT_Q_BYTES 311
#define IDC_EDIT_RT_COUNT 312
#define IDC_EDIT_RT_LOCAL 313
#define IDC_EDIT_RT_LEARNED 314
/* Link list control ID */ /* Link list control ID */
#define IDC_LIST_LINKS 400 #define IDC_LIST_LINKS 400
@ -157,6 +168,17 @@ struct etcpmon_app {
HWND hEditTunReadErrs; HWND hEditTunReadErrs;
HWND hEditTunWriteErrs; HWND hEditTunWriteErrs;
/* Routing metrics controls */
HWND hEditRtRouted;
HWND hEditRtDropped;
HWND hEditRtTunInQPkts;
HWND hEditRtTunInQBytes;
HWND hEditRtTunOutQPkts;
HWND hEditRtTunOutQBytes;
HWND hEditRtCount;
HWND hEditRtLocal;
HWND hEditRtLearned;
/* Links list */ /* Links list */
HWND hListLinks; HWND hListLinks;

15
tools/etcpmon/etcpmon_protocol.h

@ -170,6 +170,21 @@ struct etcpmon_tun_metrics {
uint32_t packets_written; /* Packets written to TUN */ uint32_t packets_written; /* Packets written to TUN */
uint32_t read_errors; /* Read error count */ uint32_t read_errors; /* Read error count */
uint32_t write_errors; /* Write error count */ uint32_t write_errors; /* Write error count */
/* Routing statistics */
uint64_t routed_packets; /* Successfully routed packets */
uint64_t dropped_packets; /* Dropped packets */
/* TUN queues */
uint32_t tun_in_q_packets; /* Packets in TUN input queue */
uint32_t tun_in_q_bytes; /* Bytes in TUN input queue */
uint32_t tun_out_q_packets; /* Packets in TUN output queue */
uint32_t tun_out_q_bytes; /* Bytes in TUN output queue */
/* Routing table */
uint32_t rt_count; /* Total routes in table */
uint32_t rt_local; /* Local routes */
uint32_t rt_learned; /* Learned routes (BGP) */
}; };
struct etcpmon_rsp_metrics { struct etcpmon_rsp_metrics {

Loading…
Cancel
Save