Compare commits

...
1 Commits
Author SHA1 Message Date
Koda 911eb2577c added reporting uplink 2026-07-14 19:07:55 +00:00
2 changed files with 73 additions and 2 deletions
+1
View File
@@ -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` | | **Wired Clients** | MACs from bridge FDB | `clients.c``bridge fdb` |
| **CPU / RAM** | Real-time usage | `sysinfo.c``/proc/stat` + `/proc/meminfo` | | **CPU / RAM** | Real-time usage | `sysinfo.c``/proc/stat` + `/proc/meminfo` |
| **Interfaces** | Speed, duplex, rx/tx counters | `sysinfo.c``/proc/net/dev` | | **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` | | **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 Send** | Custom frames via AF_PACKET raw socket | `lldp.c``lldp_send_frame()` |
| **LLDP Read** | Neighbors for UniFi topology | `lldp.c``lldpctl -f json` | | **LLDP Read** | Neighbors for UniFi topology | `lldp.c``lldpctl -f json` |
+72 -2
View File
@@ -238,6 +238,73 @@ static struct json_object *build_if_table(const uf_model_t *m,
return arr; 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 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_new_boolean(false));
json_object_object_add(root, "locating", json_object_object_add(root, "locating",
json_object_new_boolean(false)); 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_object_add(root, "country_code",
json_object_new_int(0)); json_object_new_int(0));
@@ -648,6 +713,11 @@ static char *build_payload(const openuf_state_t *st,
/* ── Ethernet interfaces with real counters ──────────────── */ /* ── Ethernet interfaces with real counters ──────────────── */
json_object_object_add(root, "if_table", build_if_table(m, st)); 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) ─────────────── */ /* ── Radio capabilities (static, from the model) ─────────────── */
build_radio_table(root, m); build_radio_table(root, m);