Skip to content

Commit

Permalink
Introduce IP cache for mDNS
Browse files Browse the repository at this point in the history
  • Loading branch information
bitkis committed Jun 18, 2021
1 parent 1d9927a commit 2254264
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 3 deletions.
7 changes: 7 additions & 0 deletions src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2419,3 +2419,10 @@ extern const char CHIP_NON_PRODUCTION_MARKER[];
#define CHIP_COMMISSIONING_HINT_INDEX_PRESS_RESET_SECONDS_WITH_POWER 10
#define CHIP_COMMISSIONING_HINT_INDEX_PRESS_RESET_UNTIL_BLINK_WITH_POWER 11
#endif

#ifndef CHIP_CONFIG_IPCACHE_SIZE
#define CHIP_CONFIG_IPCACHE_SIZE 20
#endif
#ifndef CHIP_CONFIG_TTL_MS
#define CHIP_CONFIG_TTL_MS 200000
#endif
1 change: 1 addition & 0 deletions src/lib/mdns/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ static_library("mdns") {
"ServiceNaming.h",
"TxtFields.cpp",
"TxtFields.h",
"IPCache.h",
]

if (chip_mdns == "none") {
Expand Down
34 changes: 34 additions & 0 deletions src/lib/mdns/Discovery_ImplPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace chip {
namespace Mdns {

DiscoveryImplPlatform DiscoveryImplPlatform::sManager;
IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> DiscoveryImplPlatform::sIPCache;

DiscoveryImplPlatform::DiscoveryImplPlatform() = default;

Expand Down Expand Up @@ -424,6 +425,26 @@ CHIP_ERROR DiscoveryImplPlatform::ResolveNodeId(const PeerId & peerId, Inet::IPA
{
ReturnErrorOnFailure(Init());

FabricId fabricId;
Inet::IPAddress addr;
uint16_t port;
Inet::InterfaceId iface;

if (sIPCache.Lookup(peerId.GetNodeId(), fabricId, addr, port, iface) == CHIP_NO_ERROR)
{
ResolvedNodeData nodeData;

nodeData.mInterfaceId = iface;
nodeData.mPort = port;
nodeData.mAddress = addr;
nodeData.mPeerId.SetNodeId(peerId.GetNodeId());
nodeData.mPeerId.SetFabricId(fabricId);

mResolverDelegate->OnNodeIdResolved(nodeData);

return CHIP_NO_ERROR;
}

MdnsService service;

ReturnErrorOnFailure(MakeInstanceName(service.mName, sizeof(service.mName), peerId));
Expand Down Expand Up @@ -509,6 +530,19 @@ void DiscoveryImplPlatform::HandleNodeIdResolve(void * context, MdnsService * re
return;
}

error = mgr->sIPCache.Insert(
nodeData.mPeerId.GetNodeId(),
nodeData.mPeerId.GetFabricId(),
result->mAddress.Value(),
result->mPort,
result->mInterface
);

if (error != CHIP_NO_ERROR)
{
ChipLogError(Discovery, "IPCache insert failed with %s", chip::ErrorStr(error));
}

nodeData.mInterfaceId = result->mInterface;
nodeData.mAddress = result->mAddress.ValueOr({});
nodeData.mPort = result->mPort;
Expand Down
3 changes: 3 additions & 0 deletions src/lib/mdns/Discovery_ImplPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@

#pragma once

#include <core/CHIPConfig.h>
#include <core/CHIPError.h>
#include <inet/InetInterface.h>
#include <lib/mdns/Advertiser.h>
#include <lib/mdns/IPCache.h>
#include <lib/mdns/Resolver.h>
#include <lib/mdns/platform/Mdns.h>
#include <platform/CHIPDeviceConfig.h>
Expand Down Expand Up @@ -90,6 +92,7 @@ class DiscoveryImplPlatform : public ServiceAdvertiser, public Resolver
bool mMdnsInitialized = false;
ResolverDelegate * mResolverDelegate = nullptr;

static IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> sIPCache;
static DiscoveryImplPlatform sManager;
};

Expand Down
128 changes: 128 additions & 0 deletions src/lib/mdns/IPCache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#pragma once

#include <cstdint>

#include <core/PeerId.h>
#include <inet/IPAddress.h>
#include <inet/InetInterface.h>
#include <inet/InetInterface.h>
#include <inet/InetLayer.h>
#include <core/CHIPError.h>
#include <system/SystemTimer.h>
#include <system/TimeSource.h>

namespace chip {
namespace Mdns {

template<size_t IPCACHE_SIZE, uint64_t IPCACHE_TTL_MS>
class IPCache
{
public:
IPCache() : mOccupancy(0)
{
for (IPCacheEntry & e: mLookupTable)
{
e.nodeId = kUndefinedNodeId;
}
}

CHIP_ERROR Insert(NodeId nodeId, FabricId fabricId, const Inet::IPAddress & addr, uint16_t port, Inet::InterfaceId iface)
{
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

IPCacheEntry * entry = LookupEntry(nodeId, currentTime);
if (!entry) entry = LookupAvailableEntry(currentTime);
if (!entry) return CHIP_ERROR_TOO_MANY_KEYS;

if (entry->nodeId == kUndefinedNodeId)
{
mOccupancy++;
}

entry->nodeId = nodeId;
entry->fabricId = fabricId;
entry->ipAddr = addr;
entry->port = port;
entry->ifaceId = iface;

entry->expiry = currentTime + IPCACHE_TTL_MS;

return CHIP_NO_ERROR;
}

CHIP_ERROR Delete(NodeId nodeId)
{
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

IPCacheEntry * entry = LookupEntry(nodeId, currentTime);
if (!entry) return CHIP_ERROR_KEY_NOT_FOUND;

entry->nodeId = kUndefinedNodeId;
mOccupancy--;

return CHIP_NO_ERROR;
}

size_t GetOccupancy() { return mOccupancy; }

CHIP_ERROR Lookup(NodeId nodeId, FabricId & fabricId, Inet::IPAddress & addr, uint16_t & port, Inet::InterfaceId & iface)
{
const uint64_t currentTime = mTimeSource.GetCurrentMonotonicTimeMs();

IPCacheEntry * entry = LookupEntry(nodeId, currentTime);
if (!entry) return CHIP_ERROR_KEY_NOT_FOUND;

fabricId = entry->fabricId;
addr = entry->ipAddr;
port = entry->port;
iface = entry->ifaceId;

return CHIP_NO_ERROR;
}

private:
struct IPCacheEntry
{
NodeId nodeId;
FabricId fabricId;
Inet::IPAddress ipAddr;
uint16_t port;
Inet::InterfaceId ifaceId;
uint64_t expiry;
};

IPCacheEntry * LookupEntry(NodeId nodeId, uint64_t currentTime)
{
NodeId idx = nodeId % IPCACHE_SIZE;
for (auto & _: mLookupTable)
{
(void) _;

IPCacheEntry *entry = &mLookupTable[idx];

if (entry->nodeId == nodeId && entry->expiry >= currentTime)
return entry;

idx++;
idx %= IPCACHE_SIZE;
}
return nullptr;
}

IPCacheEntry * LookupAvailableEntry(uint64_t currentTime)
{
for (IPCacheEntry & entry: mLookupTable)
{
if (entry.nodeId == kUndefinedNodeId || entry.expiry < currentTime)
return &entry;
}
return nullptr;
}

IPCacheEntry mLookupTable[IPCACHE_SIZE];
size_t mOccupancy;
Time::TimeSource<Time::Source::kSystem> mTimeSource;
};

} // namespace mdns
} // namespace chip
48 changes: 45 additions & 3 deletions src/lib/mdns/Resolver_ImplMinimalMdns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
* limitations under the License.
*/

#include "IPCache.h"
#include "Resolver.h"

#include <limits>

#include "MinimalMdnsServer.h"
#include "ServiceNaming.h"

#include <core/CHIPConfig.h>

#include <mdns/TxtFields.h>
#include <mdns/minimal/Parser.h>
#include <mdns/minimal/QueryBuilder.h>
Expand Down Expand Up @@ -82,9 +85,9 @@ class PacketDataReporter : public ParserDelegate
{
public:
PacketDataReporter(ResolverDelegate * delegate, chip::Inet::InterfaceId interfaceId, DiscoveryType discoveryType,
const BytesRange & packet) :
const BytesRange & packet, Mdns::IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> & ipCache) :
mDelegate(delegate),
mDiscoveryType(discoveryType), mPacketRange(packet)
mDiscoveryType(discoveryType), mPacketRange(packet), mIPCache(ipCache)
{
mNodeData.mInterfaceId = interfaceId;
}
Expand All @@ -105,6 +108,8 @@ class PacketDataReporter : public ParserDelegate
DiscoveredNodeData mDiscoveredNodeData;
BytesRange mPacketRange;

Mdns::IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> & mIPCache;

bool mValid = false;
bool mHasNodePort = false;
bool mHasIP = false;
Expand Down Expand Up @@ -310,6 +315,19 @@ void PacketDataReporter::OnComplete()
{
mDelegate->OnNodeIdResolved(mNodeData);
}

CHIP_ERROR error = mIPCache.Insert(
mNodeData.mPeerId.GetNodeId(),
mNodeData.mPeerId.GetFabricId(),
mNodeData.mAddress,
mNodeData.mPort,
mNodeData.mInterfaceId
);

if (error != CHIP_NO_ERROR)
{
ChipLogError(Discovery, "IPCache insert failed with %s", chip::ErrorStr(error));
}
}

class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
Expand Down Expand Up @@ -345,16 +363,20 @@ class MinMdnsResolver : public Resolver, public MdnsPacketDelegate
}
static constexpr int kMaxQnameSize = 100;
char qnameStorage[kMaxQnameSize];

static Mdns::IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> sIPCache;
};

Mdns::IPCache<CHIP_CONFIG_IPCACHE_SIZE, CHIP_CONFIG_TTL_MS> MinMdnsResolver::sIPCache;

void MinMdnsResolver::OnMdnsPacketData(const BytesRange & data, const chip::Inet::IPPacketInfo * info)
{
if (mDelegate == nullptr)
{
return;
}

PacketDataReporter reporter(mDelegate, info->Interface, mDiscoveryType, data);
PacketDataReporter reporter(mDelegate, info->Interface, mDiscoveryType, data, sIPCache);

if (!ParsePacket(data, &reporter))
{
Expand Down Expand Up @@ -467,6 +489,26 @@ CHIP_ERROR MinMdnsResolver::BrowseNodes(DiscoveryType type, DiscoveryFilter filt
CHIP_ERROR MinMdnsResolver::ResolveNodeId(const PeerId & peerId, Inet::IPAddressType type)
{
mDiscoveryType = DiscoveryType::kOperational;

FabricId fabricId;
Inet::IPAddress addr;
uint16_t port;
Inet::InterfaceId iface;

if (sIPCache.Lookup(peerId.GetNodeId(), fabricId, addr, port, iface) == CHIP_NO_ERROR)
{
ResolvedNodeData mNodeData;

mNodeData.mPeerId.SetNodeId(peerId.GetNodeId());
mNodeData.mPeerId.SetFabricId(fabricId);
mNodeData.mAddress = addr;
mNodeData.mPort = port;
mNodeData.mInterfaceId = iface;

mDelegate->OnNodeIdResolved(mNodeData);
return CHIP_NO_ERROR;
}

System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
ReturnErrorCodeIf(buffer.IsNull(), CHIP_ERROR_NO_MEMORY);

Expand Down

0 comments on commit 2254264

Please sign in to comment.