From 911eb2577c1827d59c0654ae79ada7c4b3d3a701 Mon Sep 17 00:00:00 2001 From: Koda YeenBean Date: Tue, 14 Jul 2026 19:07:55 +0000 Subject: [PATCH] added reporting uplink --- README.md | 1 + src/inform.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index edc9d7e..3156eef 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Daemon that makes an OpenWrt router appear as a UniFi AP to UniFi Network contro | **Wired Clients** | MACs from bridge FDB | `clients.c` → `bridge fdb` | | **CPU / RAM** | Real-time usage | `sysinfo.c` → `/proc/stat` + `/proc/meminfo` | | **Interfaces** | Speed, duplex, rx/tx counters | `sysinfo.c` → `/proc/net/dev` | +| **Wired Uplink** | Link state, speed, duplex, and counters for topology | `inform.c` → `uplink` | | **Channel / RF** | Channel utilization, noise, tx_power | `sysinfo.c` → `iw survey dump` | | **LLDP Send** | Custom frames via AF_PACKET raw socket | `lldp.c` → `lldp_send_frame()` | | **LLDP Read** | Neighbors for UniFi topology | `lldp.c` → `lldpctl -f json` | diff --git a/src/inform.c b/src/inform.c index 1d4c9ce..2b80564 100644 --- a/src/inform.c +++ b/src/inform.c @@ -238,6 +238,73 @@ static struct json_object *build_if_table(const uf_model_t *m, return arr; } +/* Build the wired uplink object expected by UniFi controllers. + * The model owns the interface mapping; live state and counters come from + * sysfs and /proc so third-party upstream switches still get a usable link. */ +static struct json_object *build_uplink(const uf_model_t *m, + const openuf_state_t *st) +{ + const uf_port_t *port = NULL; + for (int i = 0; i < m->port_table_len; i++) { + if (m->port_table[i].is_uplink) { + port = &m->port_table[i]; + break; + } + } + if (!port && m->port_table_len > 0) + port = &m->port_table[0]; + + struct json_object *o = json_object_new_object(); + if (!port) + return o; + + iface_stats_t stats; + sysinfo_iface(port->ifname, &stats); + int speed = stats.speed > 0 ? stats.speed : port->speed; + + json_object_object_add(o, "name", + json_object_new_string(port->ifname)); + json_object_object_add(o, "type", + json_object_new_string("wire")); + json_object_object_add(o, "media", + json_object_new_string(port->media)); + json_object_object_add(o, "mac", + json_object_new_string(stats.mac[0] ? stats.mac : st->mac)); + json_object_object_add(o, "ip", + json_object_new_string(stats.ip[0] ? stats.ip : "0.0.0.0")); + json_object_object_add(o, "num_port", + json_object_new_int(1)); + json_object_object_add(o, "port_idx", + json_object_new_int(port->port_idx)); + json_object_object_add(o, "up", + json_object_new_boolean(stats.up)); + json_object_object_add(o, "speed", + json_object_new_int(speed)); + json_object_object_add(o, "max_speed", + json_object_new_int(port->speed)); + json_object_object_add(o, "full_duplex", + json_object_new_boolean(stats.full_duplex)); + json_object_object_add(o, "rx_bytes", + json_object_new_int64(stats.rx_bytes)); + json_object_object_add(o, "tx_bytes", + json_object_new_int64(stats.tx_bytes)); + json_object_object_add(o, "rx_packets", + json_object_new_int64(stats.rx_packets)); + json_object_object_add(o, "tx_packets", + json_object_new_int64(stats.tx_packets)); + json_object_object_add(o, "rx_errors", + json_object_new_int64(stats.rx_errors)); + json_object_object_add(o, "tx_errors", + json_object_new_int64(stats.tx_errors)); + json_object_object_add(o, "rx_dropped", + json_object_new_int64(stats.rx_dropped)); + json_object_object_add(o, "tx_dropped", + json_object_new_int64(stats.tx_dropped)); + json_object_object_add(o, "rx_multicast", + json_object_new_int64(stats.rx_multicast)); + return o; +} + /* ═══════════════════════════════════════════════════════════════════ radio_table — static definition of the radio hardware ═══════════════════════════════════════════════════════════════════ @@ -637,8 +704,6 @@ static char *build_payload(const openuf_state_t *st, json_object_new_boolean(false)); json_object_object_add(root, "locating", json_object_new_boolean(false)); - json_object_object_add(root, "uplink", - json_object_new_string("eth0")); json_object_object_add(root, "country_code", json_object_new_int(0)); @@ -648,6 +713,11 @@ static char *build_payload(const openuf_state_t *st, /* ── Ethernet interfaces with real counters ──────────────── */ json_object_object_add(root, "if_table", build_if_table(m, st)); + /* ── Structured wired uplink for controller topology ─────── */ + json_object_object_add(root, "uplink", build_uplink(m, st)); + json_object_object_add(root, "uplink_table", + json_object_new_array()); + /* ── Radio capabilities (static, from the model) ─────────────── */ build_radio_table(root, m);