diff --git a/src/cntlr_commands_impl.c b/src/cntlr_commands_impl.c index ad811de684f6f263645e0f1241f15d59eeac24c2..f3ca59109e30c8ffa2700ee48f746f2f908d4321 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; }