[networking] MAC address resolver component#5622
Conversation
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
… into mac-resolver
There was a problem hiding this comment.
Pull request overview
This PR introduces a new org.openhab.core.net.MacResolver OSGi component intended to resolve a MAC address for a given IPv4 address by leveraging the host OS ARP table, primarily to support upstream HomeKit-related work in openHAB add-ons.
Changes:
- Added
MacResolverservice with asyncresolveMac(String)API, in-memory caching, and OS-specific ARP table loading (Linux/proc/net/arp, Windows/macOSarpcommand). - Added
MacResolverTestcovering normalization/validation, parsing, caching behavior, and concurrent resolution behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| bundles/org.openhab.core/src/main/java/org/openhab/core/net/MacResolver.java | New core service for resolving IP→MAC via ARP with caching and async scheduling. |
| bundles/org.openhab.core/src/test/java/org/openhab/core/net/MacResolverTest.java | New unit tests validating parsing, caching/expiry, and concurrency behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This comment was marked as outdated.
This comment was marked as outdated.
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
This comment was marked as outdated.
This comment was marked as outdated.
|
For the record, I asked Windows 11 Copilot to tell me what GitHub Copilot could complain about. Its answers are here.. Windows 11 Copilot prediction about GitHub Copilot ReviewAndrew — yes, this version is finally correct, race‑safe, and review‑proof. I’m going to be blunt and precise, because that’s what you want at this stage. ✅ 1. The slow‑path registration is now correctThis block: pendingFutureMacs.compute(ip, (key, existingSet) -> {
String nowCached = cacheGet(ip);
if (nowCached != null) {
futureMac.complete(nowCached);
return existingSet;
}
if (existingSet == null) {
existingSet = ConcurrentHashMap.newKeySet();
}
existingSet.add(futureMac);
return existingSet;
});This is exactly the atomic pattern required:
This is the strongest possible fix. ✅ 2. The fast‑path is correctString cachedMac = cacheGet(ip);
if (cachedMac != null) {
Set<CompletableFuture<@Nullable String>> pending = pendingFutureMacs.remove(ip);
if (pending != null && !pending.isEmpty()) {
pending.forEach(f -> f.complete(cachedMac));
}
if (pendingFutureMacs.isEmpty()) {
stopBackEndTaskSchedule();
}
return CompletableFuture.completedFuture(cachedMac);
}This is now safe because:
✅ 3.
|
|
And this is what GitHub Copilot told me just now.
GitHUB Copilot Own SummaryDirect answer: I do **not** see any remaining must-fix code changes required for approval from the current PR snapshot you gave me.What I see instead is:
FULL AND TOTAL LIST of exact changes I believe are still needed before approvalNone that I can justify as a clear remaining code blocker from the current diff alone. If I were reviewing strictly and carefully, my approval gate would currently be:
But in terms of actual code edits that are still clearly required, I cannot honestly produce a non-empty list from the latest state you shared. What appears already fixed in the current codeFrom the current
What I would NOT require as approval blockersI would not block approval on these classes of comments:
Tiny remaining nits I might mention, but not block onThese are not approval blockers:
Bottom-line review verdictApproval recommendation: Why I’m saying “none”Because your request was for the full and total exact list of code changes needed for approval, and I should be careful not to invent work just to fill space. Based on the current PR state you provided, I do not have enough evidence to honestly claim any remaining exact code edits are necessary. If you want, I can do one of these next:
|
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
|
@holgerfriedrich many thanks for the review. I have adopted most of your suggestions, and it does compile and pass the Junit tests. But I do also want to run it on my actual system in order to confirm no regressions due to the NetUtils stuff. PS note that I did also ask Copilot if it could foresee any issues with Docker, and it said no. |
Signed-off-by: Andrew Fiddian-Green <software@whitebear.ch>
|
@holgerfriedrich with my commit just now, I think I have addressed all your comments. Your suggestion to use NetUtil did trigger quite a large refactoring of the Note that I have also tested it on an operative system, and I can confirm that it does indeed work just fine. |
|
@holgerfriedrich your suggestion to use ExecUtil makes 100% sense. However to avoid a circular dependency I had to move the class from |
holgerfriedrich
left a comment
There was a problem hiding this comment.
Finally :-)
Thanks for your patience, Andrew!
LGTM.
|
I triggered a CI build. It should be deployed in 20 minutes. |
Some bindings require a mechanism to determine the MAC address that corresponds to an IP address. e.g. Homekit PR openhab/openhab-addons#20801
OH Core does not currently have such a
MacResolvercomponent. So this PR adds one.This is an OSGI component that gets loaded whenever an addon requires a reference to it. It contains a cache of IP addresses and associated MAC addresses. If an addon requires the MAC address associated with a particular IP address it calls the
resolveMac(ipaddress)method which returns aCompletableFuture()for the MAC. If the MAC address is in cache then the future is completed immediately. Whereas if it is not in cache, the component prepares to send a UDP ping to the target IP on the 'discard' port 9; which means that before the ping can actually be sent, the OS has to make an ARP resolution for the MAC corresponding to the given IP. A short time after sending the ping, the component loads the OS ARP table, which now contains the new MAC entry, into the cache, and at the same time satisfies theCompletableFuture()MAC. (Note that it does not matter whether the device on the target IP responds to the ping or not; important is that the OS will have done the IP to MAC ARP resolution prior to sending that ping). The component employs quite sophisticated concurrency controls to avoid race conditions and deadlocks. It uses different code paths for loading the OS ARP table on Linux, MacOS, and Windows.The component was developed locally using Windows 11 Copilot, Google Chrome Copilot, and X Grok. And we had a lot of fun during the development because the GitHub Copilot instance did not agree with the other three AIs, which meant that it was tedious to get them all to agree. However I think that we did finally achieve consensus. Albeit that this process does highlight just how stupid some of the so called AIs really are.
Signed-off-by: Andrew Fiddian-Green software@whitebear.ch