From 0f711c8ae62beb45e03d5e129e6306717c5934d4 Mon Sep 17 00:00:00 2001 From: Janusz Dziedzic <janusz.dziedzic@iopsys.eu> Date: Thu, 5 Jun 2025 14:34:41 +0200 Subject: [PATCH] ubus: dump_topology - show short tree { { "alid": "b2:dd:74:b2:93:00", "hostname": "heimgard-9300", "2g": "11/20", "5g": "132/80", "leafs": [ { "alid": "5a:00:32:ee:a4:e0", "hostname": "Pulse-EX600-580032eea4e0", "media": "Ethernet (802_3AB_GIGABIT_ETHERNET)", "5g": "132/40", "2g": "6/20" }, { "alid": "b2:dd:74:b2:c7:50", "hostname": "heimgard-C750", "media": "Wi-Fi (802_11AC_5_GHZ)", "2g": "11/20", "5g": "132/80" } ] } } { { "alid": "b2:dd:74:b2:93:00", "hostname": "heimgard-9300" "2g": "11/20", "5g": "116/80", "leafs": [ { "alid": "5a:00:32:ee:a4:e0", "hostname": "Pulse-EX600-580032eea4e0", "media": "Ethernet (802_3AB_GIGABIT_ETHERNET)", "5g": "60/80", "2g": "11/20", "leafs": [ { "alid": "b2:dd:74:b2:c7:50", "hostname": "heimgard-C750", "media": "Wi-Fi (802_11AC_5_GHZ)", "2g": "11/20", "5g": "60/80" } ] } ] } } --- src/cntlr_commands_impl.c | 137 +++++++++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 17 deletions(-) diff --git a/src/cntlr_commands_impl.c b/src/cntlr_commands_impl.c index ad811de6..f3ca5910 100644 --- a/src/cntlr_commands_impl.c +++ b/src/cntlr_commands_impl.c @@ -3328,31 +3328,134 @@ int COMMAND(disassociate_sta)(void *priv, void *args, void *out) } #endif + +static struct bh_topology_dev *topology_get_dev(struct controller *c, uint8_t *mac) +{ + struct bh_topology_dev *dev; + + list_for_each_entry(dev, &c->topology.dev_list, list) { + if (!memcmp(dev->al_macaddr, mac, 6)) + return dev; + } + + return NULL; +} + +static bool topology_dev_any_leaf(struct controller *c, struct bh_topology_dev *dev) +{ + int i, j; + + for (i = 0; i < dev->number_of_interfaces; i++) { + if (dev->ifaces[i].number_of_neighbors == 0) + continue; + for (j = 0; j < dev->ifaces[i].number_of_neighbors; j++) { + struct bh_topology_dev *subdev; + subdev = topology_get_dev(c, dev->ifaces[i].neighbors_al_macs[j]); + if (subdev && subdev->bh.parent == dev) + return true; + } + } + + return false; +} + +static void topology_print_radio(struct controller *c, struct netif_radio *r, struct blob_buf *bb) +{ + char radio[256] = {}; + + /* Keep it short, user friendly */ + snprintf(radio, sizeof(radio), "%u/%u", + ctrl_radio_cur_opclass_ctrl_chan(r->radio_el), + ctrl_radio_cur_opclass_max_bw(r->radio_el)); + + switch(r->radio_el->band) { + case BAND_2: + blobmsg_add_string(bb, "2g", radio); + break; + case BAND_5: + blobmsg_add_string(bb, "5g", radio); + break; + case BAND_6: + blobmsg_add_string(bb, "6g", radio); + break; + default: + break; + } +} + +static void topology_print_node(struct controller *c, uint8_t *alid, struct blob_buf *bb) +{ + struct netif_radio *r = NULL; + struct node *n; + + n = cntlr_find_node(c, alid); + if (!n) + return; + + list_for_each_entry(r, &n->radiolist, list) + topology_print_radio(c, r, bb); +} + +static void topology_add_hostname(struct bh_topology_dev *dev, struct blob_buf *bb) +{ + char buf[255] = {}; + char macaddr[18] = {}; + + hwaddr_ntoa(dev->al_macaddr, macaddr); + if (dev->bh.depth == 0) + chrCmd(buf, sizeof(buf), "uci get system.@system[0].hostname"); + else + chrCmd(buf, sizeof(buf), "grep %s /tmp/dhcp.leases | awk '{print $4}'", &macaddr[3]); + + if (strlen(buf)) + blobmsg_add_string(bb, "hostname", buf); +} + +static void topology_print_dev(struct controller *c, struct bh_topology_dev *dev, + struct blob_buf *bb) +{ + void *t, *a; + int i, j; + + t = blobmsg_open_table(bb, ""); + blobmsg_add_macaddr(bb, "alid", dev->al_macaddr); + topology_add_hostname(dev, bb); + if (dev->bh.own_iface) + blobmsg_add_string(bb, "media", i1905_media_type_to_str(dev->bh.own_iface->media_type)); + topology_print_node(c, dev->al_macaddr, bb); + + if (topology_dev_any_leaf(c, dev)) { + a = blobmsg_open_array(bb, "leafs"); + for (i = 0; i < dev->number_of_interfaces; i++) { + if (dev->ifaces[i].number_of_neighbors == 0) + continue; + + for (j = 0; j < dev->ifaces[i].number_of_neighbors; j++) { + struct bh_topology_dev *subdev; + + subdev = topology_get_dev(c, dev->ifaces[i].neighbors_al_macs[j]); + if (subdev && subdev->bh.parent == dev) + topology_print_dev(c, subdev, bb); + } + } + blobmsg_close_array(bb, a); + } + + blobmsg_close_table(bb, t); +} + int COMMAND(dump_topology)(void *priv, void *args, void *out) { struct controller *c = (struct controller *)priv; struct blob_buf *bb = (struct blob_buf *)out; struct bh_topology_dev *dev = NULL; - void *t, *a; - t = blobmsg_open_table(bb, "topology"); - blobmsg_add_u32(bb, "num_nodes", c->topology.num_devs); - - a = blobmsg_open_array(bb, "node"); list_for_each_entry(dev, &c->topology.dev_list, list) { - void *tt; - - tt = blobmsg_open_table(bb, ""); - blobmsg_add_macaddr(bb, "alid", dev->al_macaddr); - blobmsg_add_u32(bb, "depth", dev->bh.depth); - blobmsg_add_u32(bb, "depth_wifi", dev->bh.wifi_hops_from_root); - if (dev->bh.parent) - blobmsg_add_macaddr(bb, "parent", dev->bh.parent->al_macaddr); - - blobmsg_close_table(bb, tt); + if (dev->bh.depth == 0) { + topology_print_dev(c, dev, bb); + break; + } } - blobmsg_close_array(bb, a); - blobmsg_close_table(bb, t); return 0; } -- GitLab