Package org.openhab.core.io.net.mac
Class MacResolver
java.lang.Object
org.openhab.core.io.net.mac.MacResolver
Utility class for resolving MAC addresses from IPv4 addresses via the operating system's ARP cache. The main method
resolveMac(String) provides an asynchronous API to get the MAC address for a given IPv4 address. If the MAC
address is cached and valid, it returns immediately. Otherwise, it starts a front end process that involves probing
the IPv4 address to trigger the OS to populate its ARP table, plus a back end process that bulk loads the OS ARP
cache into the in-memory cache and completes the pending future when the MAC address becomes available. The
implementation includes optimizations to avoid unnecessary ARP cache loads for non-local or unreachable IP addresses,
and to share pending resolution tasks for the same IP address to avoid redundant work. Resolved MAC addresses are
cached in-memory with an expiration time to avoid frequent lookups, and the back end process is scheduled to run only
when there are pending resolutions to avoid unnecessary resource usage. This class is designed to be thread-safe and
efficient for typical home network environments where devices may come and go, and ARP cache entries may expire or
change over time.- Author:
- Andrew Fiddian-Green - Initial contribution
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static classSimple wrapper class to hold a MAC address with its expiration time-stamp. -
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprotected voidPeriodic task that is run by a back end scheduler that loads the ARP cache from the operating system.protected static booleanChecks if the text begins with a standard format and valid IP address. e.g.protected @Nullable StringRetrieves a MAC address from the in-memory cache, if present and not expired.protected voidStores an IP => MAC mapping in the cache with expiration and if possible eagerly resolves any pending MAC future(s).protected voidprotected booleanisOnLocalSubnet(InetAddress address) Checks if the given IPv4 address is on the same local sub-net as any of the host's network interfaces.protected static booleanisValidMac(String mac) Checks whether the given MAC address matches typical OS-supported formats, such asAA:BB:CC:DD:EE:FF,AA-BB-CC-DD-EE-FF, oraa-bb-cc-dd-ee-ff.protected static StringnormalizeIp(String ip) Extracts IP part of a string. e.g. both192.168.1.1:8080and192.168.1.1produce the output192.168.1.1protected static StringnormalizeMac(String mac) Converts a MAC address to the standard formatXX:XX:XX:XX:XX:XX.protected voidParses a single line from ARP output, extracts the IP MAC mapping if present, and caches it.CompletableFuture<@Nullable String> resolveMac(String ipv4Address) Resolves the MAC address for a given IPv4 address.protected voidtriggerArpTableUpdate(String ipv4) Triggers the operating system to update its ARP table for the given IP address by performing probes on all valid network interfaces.
-
Field Details
-
arpCache
-
-
Constructor Details
-
MacResolver
public MacResolver()
-
-
Method Details
-
deactivate
protected void deactivate() -
resolveMac
Resolves the MAC address for a given IPv4 address. If the MAC address is cached and valid, it is returned immediately. Otherwise, an asynchronous resolution process is started that involves a front end process that probes the IPv4 target device to trigger the OS to populate its ARP table, and a back end process that bulk loads the ARP table and completes the future when the MAC address becomes available. The future completes withnullif resolution fails or takes too long. The method also includes optimizations to avoid unnecessary ARP cache loads for invalid, non-local, or unreachable IPv4 addresses by checking these conditions before scheduling the asynchronous resolution.- Parameters:
ipv4Address- the IPv4 address to resolve e.g. "192.168.1.1" or "192.168.1.1:port"- Returns:
- a future that completes with the resolved MAC address or
nullif resolution fails or times out
-
triggerArpTableUpdate
Triggers the operating system to update its ARP table for the given IP address by performing probes on all valid network interfaces. The method sends a single UDP data-gram to the discard port 9 to do the probe. However before the OS can actually try to send the data-gram, it first has to check if it has the target MAC address. And if not it must send an ARP request packet to resolve the MAC. In other words, by doing the probe we immediately trigger the ARP resolution process, and for our purposes it does not matter how or if the target device responds. Each probe is scoped to the candidate interfaces that are up, non-loopback, and on the same sub-net as the target IP.- Parameters:
ipv4- the target IPv4 address to trigger ARP resolution for
-
isOnLocalSubnet
Checks if the given IPv4 address is on the same local sub-net as any of the host's network interfaces. This avoids ARP cache loads for IPv4 addresses that are not local which therefore cannot be resolved to a MAC address via the OS ARP table. -
backEndTask
protected void backEndTask()Periodic task that is run by a back end scheduler that loads the ARP cache from the operating system. If there are no more pending futures, the back end scheduler is stopped to avoid unnecessary resource usage. -
cacheGet
Retrieves a MAC address from the in-memory cache, if present and not expired. -
cachePut
Stores an IP => MAC mapping in the cache with expiration and if possible eagerly resolves any pending MAC future(s). -
isValidMac
Checks whether the given MAC address matches typical OS-supported formats, such asAA:BB:CC:DD:EE:FF,AA-BB-CC-DD-EE-FF, oraa-bb-cc-dd-ee-ff. Mixed separators are also accepted. The method additionally rejects the all-zero MAC00:00:00:00:00:00. -
normalizeMac
Converts a MAC address to the standard formatXX:XX:XX:XX:XX:XX. -
beginsWithValidIp
Checks if the text begins with a standard format and valid IP address. e.g.192.168.1.1and192.168.1.1:1234are valid whereas999.999.999.999orfoo 192.168.1.1are not.- Parameters:
ip- the IP address to check- Returns:
- true if the text begins with a valid IP address, false otherwise
-
normalizeIp
Extracts IP part of a string. e.g. both192.168.1.1:8080and192.168.1.1produce the output192.168.1.1- Parameters:
ip- the IP address to normalize- Returns:
- the normalized IP address, or the original string if it cannot be normalized
-
parseLine
Parses a single line from ARP output, extracts the IP MAC mapping if present, and caches it.- Parameters:
line- the line to parse
-