Optimize device matching in Network Server
For Redis I/O, memory usage and overall compute performance when we increasing DevAddr reuse and increasing DevAddr size.
Currently, NS ranges over devices by DevAddr, and decodes the proto. The protos are big, containing the mac state and recent uplink and downlink messages, plus there can be many protos (hundreds) of duplicate DevAddr.
We need a materialized view in Redis for matching uplinks to devices by UID, before loading the matched device.
Store relevant information for matching in dedicated keys, so basically DevAddr, FCnt, NwkSIntKeys and UID.
A sorted set and/or hash map would be useful as this enables Redis sorting and from-querying by FCnt, getting the integrity keys and UID.
Update this materialized view on each uplink and join-accept.
We can have a rolling migration with fallback to the existing matching scheme.
Unit tests, potentially with asserting the Redis keys and their values in the test.
Can review
I think a better approach would be to tackle this in another way, which also increases performance in general case - split out the space-consuming data out of the protos and store those separately - i.e. recent_uplinks
, recent_downlinks
etc., it also makes way more sense to store these in lists instead of marshaled protos - that means we wouldn't actually need to query the existing messages, but would just append a new one, which is way more efficient, but let's start with just the proto and go from there.
Given that we have fieldmasks, splitting the proto would be quite straightforward and completely handled by Redis registry implementations.
So the suggestion is to have:
ns:devices:uid:foo:bar:recent_uplinks
ns:devices:uid:foo:bar:recent_downlinks
ns:devices:uid:foo:bar:mac_state:recent_uplinks
ns:devices:uid:foo:bar:mac_state:recent_downlinks
ns:devices:uid:foo:bar:pending_mac_state:recent_uplinks
ns:devices:uid:foo:bar:pending_mac_state:recent_downlinks
ns:devices:uid:foo:bar
- rest of the protoMigration would happen automatically, similarly how deprecated fields are handled in registries already.
What is the status here?
I expect this to be ready for merge by the end of next week.
The implementation is done for weeks, working on refactoring and then adapting tests ever since
Please consider making the returned error more clear if the device can't be matched. See for example https://github.com/TheThingsNetwork/lorawan-stack/issues/2394.
We can't provide a whole lot of information, but device_not_found
implies that the device can't be found, while it could be that the DevAddr is not found at all, that the MIC mismatches with found entries and/or that the FCnt reset while that is not allowed with found entries.
Good suggestion, but I think it's best to do it as a next step, because it will be a huge PR to review with a lot of relatively complex functionality