Software Design Document: MAC Address Mapping for All Hardcoded Events

This document describes the enhancement that broadens model-based MAC address mapping (hardcodedEventMacAddressMapping) from events "1116 - cpe comes with bootstrap" / "1011 - new device arrive" only, to every hardcoded event — meaning any event that is otherwise enabled for the domain (see Domain Changes); this flag only changes what MAC value such an event carries, it never causes an event to be sent that would otherwise be disabled, nor suppresses one that would otherwise be sent. This is achieved through two complementary mechanisms: (1) the existing session-level deferral (previously scoped to 1116/1011 only) is broadened to cover every hardcoded event raised while a TR-069/TR-181 device is new or in a bootstrap session, and (2) for everything else, MAC resolution is centralized in a single chokepoint that resolves from the device’s persisted parameter tree and caches positive results in Hazelcast. Resolved values are used as-is, with no format validation or case normalization.

For the SOAP templates, placeholders, REST API and database schema of the Hardcoded Events module, see Hardcoded Events. For the pre-existing 1116/1011 deferred-until-tree-retrieval flow, now broadened to all events for new/bootstrap sessions, see MAC Resolution Flows (Events 1116 / 1011).

1. Description

Before this enhancement, hardcodedEventMacAddressMapping only gated MAC resolution for events 1116 and 1011: when enabled and the device had a mac_model mapping, the ACS deferred sending those two events until a GetParameterValuesResponse containing the mapped paths arrived, then extracted the MAC from that response. Every other hardcoded event always used the MAC address already cached for the device from its connection-time parameters (the last Inform, for TR-069/TR-181 devices), regardless of the flag.

This enhancement reuses the existing flag — no new configuration key is introduced — and broadens its meaning so that model-based MAC mapping applies to all hardcoded events, via two paths:

  • Session-level deferral: for a TR-069/TR-181 device that is new (checked on both the freshly-loaded device record and the active session’s device instance) or whose current session is a bootstrap session — and only while hardcodedEventMacAddressMapping=1 — every hardcoded event raised during that session — not only 1116/1011 — is queued and deferred until either the GetParameterValuesResponse containing the mapped paths arrives, or the session ends, in which case it is resolved from the parameters accumulated during the session (or sent without a MAC if that also yields nothing).

  • Synchronous chokepoint resolution (this document, sections below): for every other case — a regular (non-new, non-bootstrap) session, or a non-TR protocol, which has no such session concept — the MAC is resolved synchronously from the device’s already-persisted parameter tree, at the moment the event is sent, with no deferral.

2. Flag Reuse and Broadened Meaning

hardcodedEventMacAddressMapping (see Event Monitoring & Routing):

State Effect

0 (default)

No model-based mapping for any event. Every hardcoded event uses the MAC address already cached for the device (from its last Inform, for TR-069/TR-181 devices).

1

Model-based mapping is attempted for every hardcoded event. For a TR-069/TR-181 device that is new or in a bootstrap session, every event of that session (not only 1116/1011) defers sending until the mapped paths are retrieved via GetParameterValuesResponse, or — if the session ends first — resolves the MAC from the parameters accumulated during the session (sent without a MAC only if that also fails). For every other case (regular session, or non-TR protocol), the event resolves the MAC from the persisted parameter tree at send time, with no deferral.

No new flag was introduced because the existing flag already expresses the intent ("use model-based MAC mapping instead of the device’s raw cached MAC") — only the set of events it applies to changed.

3. Resolution Chokepoint and Algorithm

Resolution is centralized in FTMonitorCreatorService.createFTMonitorObject(…​), the single method that builds the FTMonitorBase instance used to send any hardcoded event (SOAP/HTTP/SNMP/SYSLOG). This is the same method already called by every hardcoded-event sender (HardcodedEventBootstrapProcessor, periodic/other event senders, session-end flush).

The chokepoint only resolves a MAC address when the caller did not already pass one in explicitly. This has two sources of bypass:

  • The deferred-events dispatch (onRetrieveParametersResponse / sendEventsOnMacReceive, covering 1116/1011 and every other event deferred for a new/bootstrap session) resolves its own MAC from the GetParameterValuesResponse and passes it in directly.

  • FTEventProcessor.shouldDeferForTreeRetrieval(cpe) returning true short-circuits the caller before it ever reaches the chokepoint — the event is queued instead of sent, so this document’s branch logic below does not run for it at all until it is dispatched (with a MAC already resolved, or none).

The device’s product-class group is required to look up its MAC mapping — without it, the ACS cannot even tell whether the device’s model has a mapping configured, let alone use one. If the group isn’t already known when the event is sent, the chokepoint attempts one cheap, targeted lookup for it in DB — deliberately not the same blocking retry used elsewhere for a just-created device, which must not run per event — before falling back to the device’s raw cached MAC. If that lookup also comes up empty, the event is treated exactly as if no mapping existed for it at all — the ACS simply has no way to know otherwise.

When no MAC address is passed in, the algorithm is:

Branch Flag Condition Result

1

OFF

n/a

The MAC address already cached for the device (legacy behavior, unchanged).

2

ON

The device’s group is unknown even after the cheap lookup, OR its group is known but its model has no MAC mapping configured

Same fallback as branch 1.

3

ON

The device’s group is known (directly, or via the cheap lookup) AND its model has a MAC mapping configured

MAC address resolved from the device’s persisted parameter tree via the mapped paths (first checking the Hazelcast cache, which may already hold a value warmed by the deferred-event flow — see Hazelcast Cache). Never falls back to the cached MAC from branch 1/2 — if resolution yields nothing, the event is sent with an empty MAC address.

Branch 3 is the new behavior. It deliberately does not fall back to the device’s raw cached MAC: once a device is known to have a MAC mapping, that cached value is considered unreliable/irrelevant for it (it may reference the wrong interface), so an empty result is preferred over a possibly-wrong value.

3.1. Sequence

hardcoded-events-mac-all-resolution

4. Hazelcast Cache

Resolved MAC addresses are cached in a Hazelcast IMap (com.friendly.dm.monitoring.mac.MacMappingResolver.macAddressCache) keyed by cpeId.

Cache contract:

  • Positive results only. An empty/unresolved result (branch 3 with no value found) is never written to the cache — only a successfully resolved MAC address is cached.

  • TTL-only expiry (currently 10 minutes per entry — see MAC_CACHE_TTL_MINUTES). This is an accepted trade-off: the mapped MAC parameters (e.g. a WiFi/Ethernet interface MAC) rarely change on a running device, so a bounded staleness window is preferred over adding write-path invalidation logic to every path that can update a mapped parameter.

  • No negative caching — a device with no mapping, or a device for which resolution currently fails, is re-attempted on every subsequent event rather than being cached as "no MAC."

  • Multiple writers. Besides resolveMappedMacAddress’s own read-through write (above), the cache is also warmed directly with values already known to be correct, via `MacMappingResolver.cacheResolvedMac(cpe, macAddress):

    • From HardcodedEventBootstrapProcessor.onRetrieveParametersResponse, right after extracting the MAC from a live GetParameterValuesResponse mid-session — so that other, non-deferred events for the same device (which go through the chokepoint, not the deferred queue) don’t have to race the resulting parameter tree’s persistence to the database, which can be asynchronous/batched (BulkSQLProcessorCpeParameter).

    • From MacMappingResolver.resolveMacFromSessionParameters, called by HardcodedEventBootstrapProcessor.onSessionEnd when a device’s session ends with events still deferred, resolving from the parameters accumulated during that session rather than the (possibly not-yet-persisted) database tree.

      Both writers deduplicate candidate values the same way resolveMappedMacAddress does before joining and caching.

  • Cleared together with other device data. MacMappingResolver.evictCachedMac(cpeId) removes a single device’s cache entry, and runs whenever a device’s other cached data is cleared: when the device is deleted, and when the cleanCacheForCPE web service (ACSWebService#cleanCacheForCPE) is called for it. Both go through the same per-protocol ICpeDataCache.removeCpeDataFromCache(Integer cpeId) implementation (AbstractTRCpeDataCache, shared by TR-069/TR-181; MqttCpeDataCache; UspCpeDataCache), which is where this eviction is wired in.

5. Multi-MAC Devices

Some devices legitimately expose several MAC addresses through the mapping (e.g. one mapped path per interface), which are comma-joined into a single value for the outgoing event (see ${macAddress} placeholder in Supported Placeholders). Duplicate values (the same value resolved under more than one mapped path) are removed before joining; there is otherwise no per-candidate filtering.

6. Out of Scope / Not Duplicated Here

The following are unchanged by this enhancement and documented in Hardcoded Events instead of being repeated here:

  • SOAP/Windstream templates and the ${macAddress} placeholder.

  • The MAC model mapping REST API (/rest/mac-mappings/*).

  • The event_hardcoded* / event_receiver_url* database schema.