luci-base: rpc: add call to enumerate builtin ethernet ports
authorJo-Philipp Wich <jo@mein.io>
Thu, 24 Aug 2023 14:44:40 +0000 (16:44 +0200)
committerJo-Philipp Wich <jo@mein.io>
Thu, 24 Aug 2023 14:48:01 +0000 (16:48 +0200)
Add a new luci/getBuiltinEthernetPorts RPC call which returns a consolidated
list of known ethernet ports found in `/etc/board.json`.

Add an x86/64 specific workaround which attempts to enumerate missing
ethernet devices too.

Ref: #6534, #6538
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
modules/luci-base/root/usr/share/rpcd/ucode/luci

index 35f592578b3a325b1b705644bf30bad3c592f659..3c4fea46911f66f6235821c6b149a3430f9489cf 100644 (file)
@@ -8,7 +8,7 @@ import { cursor } from 'uci';
 
 import { init_list, init_index, init_enabled, init_action, conntrack_list, process_list } from 'luci.sys';
 import { revision, branch } from 'luci.version';
-import { statvfs } from 'luci.core';
+import { statvfs, uname } from 'luci.core';
 
 import timezones from 'luci.zoneinfo';
 
@@ -538,6 +538,49 @@ const methods = {
                call: function() {
                        return { result: process_list() };
                }
+       },
+
+       getBuiltinEthernetPorts: {
+               call: function() {
+                       let fd = open('/etc/board.json', 'r');
+                       let board = fd ? json(fd) : {};
+                       let ports = [];
+
+                       for (let k in [ 'lan', 'wan' ]) {
+                               if (!board?.network?.[k])
+                                       continue;
+
+                               if (type(board.network[k].ports) == 'array') {
+                                       for (let ifname in board.network[k].ports) {
+                                               push(ports, { role: k, device: ifname });
+                                       }
+                               }
+                               else if (type(board.network[k].device) == 'string') {
+                                       push(ports, { role: k, device: board.network[k].device });
+                               }
+                       }
+
+                       /* Workaround for targets that do not enumerate  all netdevs in board.json */
+                       if (uname().machine in [ 'x86_64' ] &&
+                           match(ports[0]?.device, /^eth\d+$/)) {
+                               let bus = readlink(`/sys/class/net/${ports[0].device}/device/subsystem`);
+
+                               for (let netdev in lsdir('/sys/class/net')) {
+                                       if (!match(netdev, /^eth\d+$/))
+                                               continue;
+
+                                       if (length(filter(ports, port => port.device == netdev)))
+                                               continue;
+
+                                       if (readlink(`/sys/class/net/${netdev}/device/subsystem`) != bus)
+                                               continue;
+
+                                       push(ports, { role: 'unknown', device: netdev });
+                               }
+                       }
+
+                       return { result: ports };
+               }
        }
 };