Skip to content

Conversation

@Alphix
Copy link
Contributor

@Alphix Alphix commented Nov 9, 2025

This is just a RFC for now (and it's based on top of #8083 rather than master).

Basically, it changes luci-mod-status so that it calls odhcpd directly over ubus to get the status of DHCPv4/DHCPv6 leases (yes, I know that odhcpd isn't responsible for DHCPv4 in a default install).

Before this change, all lease status is provided via the rpcd-mod-luci plugin in rpcd, which will dig through leasefiles to get the status of leases (and it'll still do that for dnsmasq-based leases). Communicating directly with odhcpd is quicker, simpler and provides access to information which wasn't exposed in the interface before (like per-lease interface information, force reconf status, etc).

This isn't complete right now (for example, it'll render 4 tables, showing both what was returned from odhcpd and what was returned from rpcd, but that's for comparison, also needs more testing).

However, I'm posting this here now so that I can get some early feedback. Ultimately I'd like to implement a similar change to luci-mod-network/htdocs/luci-static/resources/view/network/dhcp.js, after which the odhcpd-specific code in rpcd-mod-luci won't really be necessary anymore.

It might look like a lot of duplication, but there's enough little differences between the data returned from odhcpd and rpcd (and also the resulting HTML tables carry different information), that there's not much code that can be shared between the different table generation functions.

Down the line, I guess this would also make it easier to split 40_dhcp.js into three separate files, one for dnsmasq, one for odhcpd-DHCPv4 and one for odhcpd-DHCPv6 (if that's desirable, cf. #6713).

  • This PR is not from my main or master branch 💩, but a separate branch ✅
  • Each commit has a valid ✒️ Signed-off-by: <[email protected]> row (via git commit --signoff)
  • Each commit and PR title has a valid 📝 <package name>: title first line subject for packages
  • Incremented 🆙 any PKG_VERSION in the Makefile
  • Tested on: (NanoPi R6S, Master, Chrome) ✅
  • ( Preferred ) Screenshot or mp4 of changes:
  • Description: (describe the changes proposed in this PR)

Multiple DUIDs can be defined for one static lease, and using an
"option" instead of a "list" in UCI is legacy, so store the DUID as a
list for correctness.

Signed-off-by: David Härdeman <[email protected]>
Note that "duid" from UCI can be *either* "<DUID>" or "<DUID>%<IAID>",
so update the code to handle both cases.

Also, make sure the "Reserve IP" button is disabled if the "duid" is
unknown (can only happen if dnsmasq is responsible for DHCPv6) and that
DUIDs/IAIDs are always rendered in uppercase in the UI.

Signed-off-by: David Härdeman <[email protected]>
This makes it easier to see straight away the correspondence between
render() and renderLeases().

Signed-off-by: David Härdeman <[email protected]>
Instead of lease/lease6, table/table6, etc, use a consistent
naming of the form "x4"/"x6".

Also, fix a typo (note class "lases" for "table").

Signed-off-by: David Härdeman <[email protected]>
The "macaddr" variable is actually the list of ufpd vendor hints, so
rename the variable to make this clearer.

Signed-off-by: David Härdeman <[email protected]>
This is mostly in preparation for the following patches, and makes
function signatures a bit simpler. Note also that there was an
unused "hosts" variable in renderLeases().

Signed-off-by: David Härdeman <[email protected]>
Split the creation of the DHCPv4/DHCPv6 lease tables into
separate functions in preparation for the following patches.

Signed-off-by: David Härdeman <[email protected]>
Instead of going through rpcd, which digs through statefiles to find out
which leases are active, communicate directly with odhcpd over ubus.

This allows us to expose information which isn't otherwise available,
like which interface a given lease belongs to and whether force-reconf
is supported by a given client.

It's also more efficient, and provides a small step towards a future
where the odhcpd-statefile parsing code can be removed from rpcd.

Signed-off-by: David Härdeman <[email protected]>
Similarly to the previous patch, this lets LuCI communicate directly
with odhcpd to get DHCPv4 leases, which allows us to expose information
like the interface for the lease, force-reconf status, and potentially
more in the future.

Signed-off-by: David Härdeman <[email protected]>
@Alphix
Copy link
Contributor Author

Alphix commented Nov 9, 2025

Screenshot From 2025-11-09 18-04-54

"Old" tables on top, "new" tables below

@Alphix
Copy link
Contributor Author

Alphix commented Nov 9, 2025

@systemcrash I have the feeling that your javascript-fu is much better than mine, so feel free to go through this and see if it can be made more elegant...

@systemcrash
Copy link
Contributor

test-beef haha XD

@systemcrash
Copy link
Contributor

Could you add abbr hover info for the three abbreviations in the table headers? Ideally stuffed with i18n _('blah') strings.
e.g. <abbr title=\"Domain Name System\">DNS</abbr>. So there's DUID, FR, and IAID.

Perhaps we should distinguish the table info source - somehow hint why there are two different tables (dnsmsaq, odhcpd).

Or merge the entries and use a mono table.

},

createOdhcpdTable4(iface_leases4) {
console.log("DHCPv4 leases " + JSON.stringify(iface_leases4));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not in the final product. but ok for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oversight

else if (lease.valid <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.valid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just use interpolated string.

Copy link
Contributor Author

@Alphix Alphix Nov 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I do that for %t? That's a cbi.js addition to the String class, isn't it?

else if (lease.valid <= 0)
exp = E('em', _('expired'));
else
exp = '%t'.format(lease.valid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


let host = null;
if (hint && lease.hostname && lease.hostname != hint[1] && lease.ip6addrs[0] != hint[1])
host = '%s (%s)'.format(lease.hostname, hint[1]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

let host = null;

if (hint && lease.hostname && lease.hostname != hint[1])
host = '%s (%s)'.format(lease.hostname, hint[1]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interpolated

});

function DUIDtoMAC(duid) {
if (duid == null || duid == '')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (!duid)?

@Alphix
Copy link
Contributor Author

Alphix commented Nov 9, 2025

Could you add abbr hover info for the three abbreviations in the table headers? Ideally stuffed with i18n _('blah') strings. e.g. <abbr title=\"Domain Name System\">DNS</abbr>. So there's DUID, FR, and IAID.

Yeah, that makes sense...

Perhaps we should distinguish the table info source - somehow hint why there are two different tables (dnsmsaq, odhcpd).

Or merge the entries and use a mono table.

I don't think the tables can really be merged (and they might diverge even further in the future wrt the data they expose....for example, I'm planning to add a "remove lease" button to the odhcpd table)...but we could change the table titles? As in "Active DHCPv4 Leases" -> "Active DHCPv4 Leases (dnsmasq)" or "Active DHCPv4 leases (odhcpd)"?

@Alphix
Copy link
Contributor Author

Alphix commented Nov 9, 2025

test-beef haha XD

With a DUID including a lot of 0x...BEEF

@Ansuel
Copy link
Member

Ansuel commented Nov 9, 2025

@systemcrash at least it wasn't DEAD (this time)

@Alphix
Copy link
Contributor Author

Alphix commented Nov 10, 2025

@jow- (sorry, bit of braindump here)...since you seem to have done a lot of the heavy lifting on rpcd-mod-luci, I'd like to get your feedback on this as well. The question is if it's a good idea to talk straight to odhdpd over ubus or whether that is bonkers and I should focus on getting rpcd-mod-luci to talk to odhcpd over ubus instead?

For context, I want to get rpcd-mod-luci to stop digging through the leasefile that odhcpd writes (so that we're free to change the format of the file, which is needed for some new functionality, like persisting leases across odhcpd restarts or even reboots, if the user is ok with writing leases to flash). Also, it seems a lot more "correct"/straightforward to talk directly to odhcpd over ubus to get the desired information rather than dig through its statefiles or going the LuCI -- (ubus) --> rpcd -- (ubus) --> odhcpd path.

Now, converting luci-mod-status is pretty straightforward (as can be seen in this PR), but luci-mod-network is a different beast...it'll call getHostHints, getDUIDHints and getDHCPLeases (meaning luci-mod-status digs through the leasefile four times, twice for getDHCPLeases).

getDUIDHints and getDHCPLeases are easy enough to synthesise in JavaScript from the data that odhcpd returns, but getHostHints can't really be skipped since it consults so many other sources (netlink, uci, leasefiles, /etc/ethers, getifaddrs() and RDNS)...it's also used by a lot of other modules...the more I look at it the more questionable it seems...

So...should I just throw in the towel and focus on getting rpcd-mod-luci to get more data via ubus, even if it'll add an extra intermediary?

@systemcrash
Copy link
Contributor

@Alphix did you want to bring this up to current or is this superseded?

@Alphix
Copy link
Contributor Author

Alphix commented Dec 3, 2025

@Alphix did you want to bring this up to current or is this superseded?

It needs further work, I think it might be material for after the next OpenWrt branch... Basically I think I need to get rpcd-mod-luci to talk to odhcpd first... Then I can think about more direct approaches after that...

@Self-Hosting-Group
Copy link
Contributor

@Alphix What do you think about using Hostname for IPv6 DHCP, as for IPv4?
E('th', { 'class': 'th' }, _('Hostname')),
(And the use of Host for Associated Stations could possibly be changed to Device.)

@Alphix
Copy link
Contributor Author

Alphix commented Dec 9, 2025

@Alphix What do you think about using Hostname for IPv6 DHCP, as for IPv4? E('th', { 'class': 'th' }, _('Hostname')),

Sure, see #8140

(And the use of Host for Associated Stations could possibly be changed to Device.)

I don't have any opinion on that, but feel free to create a PR and ping @systemcrash

@GoetzGoerisch
Copy link

While you are at it, a comment from my end.

Currently using dnsmasq (v4) and odhcpd-ipv6only in coexistense if there is a static lease with a DNS entry from dnsmasq the FQDN is shown in brackets next to the hostname in the v4 and v6 lease table.

If we could get consinstent this, that would be great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants