diff --git a/BUILD.gn b/BUILD.gn
index aa443d94e35f52..ddd893a4ca49d8 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -161,6 +161,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
         "${chip_root}/examples/shell/standalone:chip-shell",
         "${chip_root}/src/app/tests/integration:chip-im-initiator",
         "${chip_root}/src/app/tests/integration:chip-im-responder",
+        "${chip_root}/src/inet/tests:inet-layer-test-tool",
         "${chip_root}/src/lib/address_resolve:address-resolve-tool",
         "${chip_root}/src/messaging/tests/echo:chip-echo-requester",
         "${chip_root}/src/messaging/tests/echo:chip-echo-responder",
diff --git a/build/chip/tests.gni b/build/chip/tests.gni
old mode 100644
new mode 100755
index 61a2ad3e685682..8fb77932662634
--- a/build/chip/tests.gni
+++ b/build/chip/tests.gni
@@ -15,6 +15,7 @@
 import("//build_overrides/build.gni")
 import("//build_overrides/chip.gni")
 
+import("${chip_root}/build/chip/tools.gni")
 import("${chip_root}/src/platform/device.gni")
 
 declare_args() {
@@ -40,6 +41,6 @@ declare_args() {
 }
 
 declare_args() {
-  # Enable use of nlfaultinjection.
-  chip_with_nlfaultinjection = chip_build_tests
+  # Enable use of nlfaultinjection when building tests or when building tools.
+  chip_with_nlfaultinjection = chip_build_tests || chip_build_tools
 }
diff --git a/config/common/cmake/chip_gn.cmake b/config/common/cmake/chip_gn.cmake
index 618fbfccec3632..8370ec5902582e 100644
--- a/config/common/cmake/chip_gn.cmake
+++ b/config/common/cmake/chip_gn.cmake
@@ -158,6 +158,7 @@ macro(matter_build target)
         ${CHIP_ROOT}/src/include
         ${CHIP_ROOT}/third_party/nlassert/repo/include
         ${CHIP_ROOT}/third_party/nlio/repo/include
+        ${CHIP_ROOT}/third_party/nlfaultinjection/include
         ${CHIP_ROOT}/zzz_generated/app-common
         ${CMAKE_CURRENT_BINARY_DIR}/gen/include
     )
diff --git a/src/inet/tests/BUILD.gn b/src/inet/tests/BUILD.gn
old mode 100644
new mode 100755
index 3111c4e70a4805..39b707c86c8452
--- a/src/inet/tests/BUILD.gn
+++ b/src/inet/tests/BUILD.gn
@@ -14,13 +14,18 @@
 
 import("//build_overrides/build.gni")
 import("//build_overrides/chip.gni")
+import("//build_overrides/nlfaultinjection.gni")
 import("//build_overrides/pigweed.gni")
 
-import("${chip_root}/build/chip/chip_test_suite.gni")
 import("${chip_root}/build/chip/tests.gni")
+import("${chip_root}/build/chip/tools.gni")
 import("${chip_root}/src/platform/device.gni")
 import("${chip_root}/src/system/system.gni")
 
+if (chip_build_tests) {
+  import("${chip_root}/build/chip/chip_test_suite.gni")
+}
+
 config("tests_config") {
   include_dirs = [ "." ]
 }
@@ -40,9 +45,13 @@ static_library("helpers") {
     "TestSetupSignallingPosix.cpp",
   ]
 
-  if (current_os != "mbed") {
-    sources += [ "TestInetLayer.cpp" ]
-  }
+  cflags = [ "-Wconversion" ]
+
+  public_deps = [
+    "${chip_root}/src/inet",
+    "${chip_root}/src/lib/core",
+    "${chip_root}/src/platform",
+  ]
 
   if (chip_with_nlfaultinjection) {
     sources += [
@@ -50,45 +59,45 @@ static_library("helpers") {
       "TestSetupFaultInjectionPosix.cpp",
     ]
   }
+}
 
-  cflags = [ "-Wconversion" ]
+if (chip_build_tests) {
+  chip_test_suite("tests") {
+    output_name = "libInetLayerTests"
 
-  public_deps = [
-    "${chip_root}/src/inet",
-    "${chip_root}/src/lib/core",
-    "${chip_root}/src/platform",
-  ]
+    public_configs = [ ":tests_config" ]
+
+    public_deps = [
+      ":helpers",
+      "${chip_root}/src/inet",
+      "${chip_root}/src/lib/core",
+    ]
+    test_sources = [
+      "TestBasicPacketFilters.cpp",
+      "TestInetAddress.cpp",
+      "TestInetErrorStr.cpp",
+    ]
+    sources = []
+
+    if (chip_system_config_use_sockets && current_os != "zephyr") {
+      test_sources += [ "TestInetEndPoint.cpp" ]
+    }
+
+    cflags = [ "-Wconversion" ]
+  }
 }
 
-chip_test_suite("tests") {
-  output_name = "libInetLayerTests"
+executable("inet-layer-test-tool") {
+  sources = [ "inet-layer-test-tool.cpp" ]
 
-  public_configs = [ ":tests_config" ]
+  cflags = [ "-Wconversion" ]
 
   public_deps = [
     ":helpers",
     "${chip_root}/src/inet",
     "${chip_root}/src/lib/core",
+    "${chip_root}/src/platform",
   ]
-  test_sources = [
-    "TestBasicPacketFilters.cpp",
-    "TestInetAddress.cpp",
-    "TestInetErrorStr.cpp",
-  ]
-  sources = []
-
-  if (chip_system_config_use_sockets && current_os != "zephyr") {
-    test_sources += [ "TestInetEndPoint.cpp" ]
-  }
 
-  # This fails on Raspberry Pi (Linux arm64), so only enable on Linux
-  # x64.
-  if (current_os != "mac" && current_os != "zephyr" &&
-      chip_device_platform != "esp32" && current_cpu == "x64" &&
-      chip_device_platform != "ameba") {
-    # TODO: This test does not seem executed
-    sources += [ "TestLwIPDNS.cpp" ]
-  }
-
-  cflags = [ "-Wconversion" ]
+  output_dir = root_out_dir
 }
diff --git a/src/inet/tests/TestInetCommonOptions.cpp b/src/inet/tests/TestInetCommonOptions.cpp
index 7e4648d7466b1b..ac51573e095e6e 100644
--- a/src/inet/tests/TestInetCommonOptions.cpp
+++ b/src/inet/tests/TestInetCommonOptions.cpp
@@ -198,43 +198,36 @@ bool NetworkOptions::HandleOption(const char * progName, OptionSet * optSet, int
 
 FaultInjectionOptions::FaultInjectionOptions()
 {
-    static OptionDef optionDefs[] = {
-#if CHIP_CONFIG_TEST || CHIP_SYSTEM_CONFIG_TEST || INET_CONFIG_TEST
-        { "faults", kArgumentRequired, kToolCommonOpt_FaultInjection },
-        { "iterations", kArgumentRequired, kToolCommonOpt_FaultTestIterations },
-        { "debug-resource-usage", kNoArgument, kToolCommonOpt_DebugResourceUsage },
-        { "print-fault-counters", kNoArgument, kToolCommonOpt_PrintFaultCounters },
-        { "extra-cleanup-time", kArgumentRequired, kToolCommonOpt_ExtraCleanupTime },
-#endif
-        {}
-    };
-    OptionDefs = optionDefs;
+    static OptionDef optionDefs[] = { { "faults", kArgumentRequired, kToolCommonOpt_FaultInjection },
+                                      { "iterations", kArgumentRequired, kToolCommonOpt_FaultTestIterations },
+                                      { "debug-resource-usage", kNoArgument, kToolCommonOpt_DebugResourceUsage },
+                                      { "print-fault-counters", kNoArgument, kToolCommonOpt_PrintFaultCounters },
+                                      { "extra-cleanup-time", kArgumentRequired, kToolCommonOpt_ExtraCleanupTime },
+                                      {} };
+    OptionDefs                    = optionDefs;
 
     HelpGroupName = "FAULT INJECTION OPTIONS";
 
-    OptionHelp =
-#if CHIP_CONFIG_TEST || CHIP_SYSTEM_CONFIG_TEST || INET_CONFIG_TEST
-        "  --faults <fault-string>\n"
-        "       Inject specified fault(s) into the operation of the tool at runtime.\n"
-        "\n"
-        "  --iterations <int>\n"
-        "       Execute the program operation the given number of times\n"
-        "\n"
-        "  --debug-resource-usage\n"
-        "       Print all stats counters before exiting.\n"
-        "\n"
-        "  --print-fault-counters\n"
-        "       Print the fault-injection counters before exiting.\n"
-        "\n"
-        "  --extra-cleanup-time\n"
-        "       Allow extra time before asserting resource leaks; this is useful when\n"
-        "       running fault-injection tests to let the system free stale ExchangeContext\n"
-        "       instances after RMP has exhausted all retransmission; a failed RMP transmission\n"
-        "       should fail a normal happy-sequence test, but not necessarily a fault-injection test.\n"
-        "       The value is in milliseconds; a common value is 10000.\n"
-        "\n"
-#endif
-        "";
+    OptionHelp = "  --faults <fault-string>\n"
+                 "       Inject specified fault(s) into the operation of the tool at runtime.\n"
+                 "\n"
+                 "  --iterations <int>\n"
+                 "       Execute the program operation the given number of times\n"
+                 "\n"
+                 "  --debug-resource-usage\n"
+                 "       Print all stats counters before exiting.\n"
+                 "\n"
+                 "  --print-fault-counters\n"
+                 "       Print the fault-injection counters before exiting.\n"
+                 "\n"
+                 "  --extra-cleanup-time\n"
+                 "       Allow extra time before asserting resource leaks; this is useful when\n"
+                 "       running fault-injection tests to let the system free stale ExchangeContext\n"
+                 "       instances after RMP has exhausted all retransmission; a failed RMP transmission\n"
+                 "       should fail a normal happy-sequence test, but not necessarily a fault-injection test.\n"
+                 "       The value is in milliseconds; a common value is 10000.\n"
+                 "\n"
+                 "";
 
     // Defaults
     TestIterations       = 1;
@@ -253,7 +246,6 @@ bool FaultInjectionOptions::HandleOption(const char * progName, OptionSet * optS
 
     switch (id)
     {
-#if CHIP_CONFIG_TEST || CHIP_SYSTEM_CONFIG_TEST || INET_CONFIG_TEST
     case kToolCommonOpt_FaultInjection: {
         chip::Platform::ScopedMemoryString mutableArg(arg, strlen(arg));
         assert(mutableArg);
@@ -285,7 +277,6 @@ bool FaultInjectionOptions::HandleOption(const char * progName, OptionSet * optS
             return false;
         }
         break;
-#endif // CHIP_CONFIG_TEST || CHIP_SYSTEM_CONFIG_TEST || INET_CONFIG_TEST
     default:
         PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", progName, name);
         return false;
diff --git a/src/inet/tests/TestInetLayerCommon.hpp b/src/inet/tests/TestInetLayerCommon.hpp
index d34a7628ea3a3c..4474d56314429e 100644
--- a/src/inet/tests/TestInetLayerCommon.hpp
+++ b/src/inet/tests/TestInetLayerCommon.hpp
@@ -126,8 +126,8 @@ extern bool IsSender();
 extern bool IsTesting(const TestStatus & aTestStatus);
 extern bool WasSuccessful(const TestStatus & aTestStatus);
 
-extern chip::System::PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength, uint8_t aFirstValue);
-extern chip::System::PacketBufferHandle MakeDataBuffer(uint16_t aDesiredLength);
+extern chip::System::PacketBufferHandle MakeDataBuffer(size_t aDesiredLength, uint8_t aFirstValue);
+extern chip::System::PacketBufferHandle MakeDataBuffer(size_t aDesiredLength);
 extern chip::System::PacketBufferHandle MakeICMPv4DataBuffer(uint16_t aDesiredUserLength);
 extern chip::System::PacketBufferHandle MakeICMPv6DataBuffer(uint16_t aDesiredUserLength);
 
diff --git a/src/inet/tests/TestLwIPDNS.cpp b/src/inet/tests/TestLwIPDNS.cpp
deleted file mode 100644
index 8681f7b2e54328..00000000000000
--- a/src/inet/tests/TestLwIPDNS.cpp
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Project CHIP Authors
- *    Copyright (c) 2013-2017 Nest Labs, Inc.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-/**
- *    @file
- *      This file implements a process to effect a functional test for
- *      LwIP's Domain Name Service (DNS) interface.
- *
- */
-
-#include <inet/InetConfig.h>
-#include <lib/core/CHIPConfig.h>
-
-#include <stdint.h>
-#include <string.h>
-
-#include <sys/time.h>
-
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-#include <lwip/dns.h>
-#include <lwip/ip_addr.h>
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-#include <CHIPVersion.h>
-
-#include <inet/InetArgParser.h>
-
-#include "TestInetCommon.h"
-#include "TestInetCommonOptions.h"
-#include "TestSetupFaultInjection.h"
-#include "TestSetupSignalling.h"
-
-using namespace chip;
-using namespace chip::Inet;
-
-#define TOOL_NAME "TestLwIPDNS"
-
-static bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[]);
-
-// Globals
-
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-static uint8_t sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME;
-static ip_addr_t sIpAddrs[DNS_MAX_ADDRS_PER_NAME];
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-static const char * sHostname      = nullptr;
-static const char * sDNSServerAddr = nullptr;
-
-// clang-format off
-static ArgParser::HelpOptions gHelpOptions(TOOL_NAME,
-                                           "Usage: " TOOL_NAME " [<options...>] <hostname> <dns-server-address>\n",
-                                           CHIP_VERSION_STRING "\n" CHIP_TOOL_COPYRIGHT);
-
-static ArgParser::OptionSet * gToolOptionSets[] =
-{
-    &gNetworkOptions,
-    &gFaultInjectionOptions,
-    &gHelpOptions,
-    nullptr
-};
-// clang-format on
-
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-static void found_multi(const char * aName, ip_addr_t * aIpAddrs, uint8_t aNumIpAddrs, void * callback_arg)
-{
-    printf("\tfound_multi response\n");
-    printf("\tName: %s\n", aName);
-    printf("\tnumipaddrs: %d (DNS_MAX_ADDRS_PER_NAME: %d)\n", aNumIpAddrs, DNS_MAX_ADDRS_PER_NAME);
-
-    for (uint8_t i = 0; i < aNumIpAddrs; ++i)
-    {
-        char addrStr[INET6_ADDRSTRLEN];
-
-        IPAddress(aIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
-
-        printf("\t(%d) IPv4: %s\n", i, addrStr);
-    }
-
-    Done = true;
-}
-
-static void TestLwIPDNS(void)
-{
-    uint8_t numdns = 1;
-    ip_addr_t dnsserver[1];
-    IPAddress DNSServerIPv4Addr;
-
-    IPAddress::FromString(sDNSServerAddr, DNSServerIPv4Addr);
-
-    dnsserver[0] = DNSServerIPv4Addr.ToIPv4();
-
-    dns_setserver(numdns, dnsserver);
-
-    printf("\nStarted dns_gethostbyname_multi test...\n\n");
-
-    // Expected request / response
-    printf("Expected request / response #1\n");
-    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, sIpAddrs, sNumIpAddrs, found_multi, NULL);
-    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
-    err_t res = dns_gethostbyname_multi(hostname, sIpAddrs, &sNumIpAddrs, found_multi, NULL);
-    if (res == ERR_INPROGRESS)
-    {
-        printf("\tdns_gethostbyname_multi: %d (ERR_INPROGRESS)\n", res);
-    }
-    else
-    {
-        printf("\tdns_gethostbyname_multi: %d (expected -5: ERR_INPROGRESS)\n", res);
-    }
-
-    while (!Done)
-    {
-        constexpr uint32_t kSleepTimeMilliseconds = 10;
-        ServiceNetwork(kSleepTimeMilliseconds);
-    }
-
-    // Expected cached response
-    printf("Expected cached response #1\n");
-    sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME;
-    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
-    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
-    res = dns_gethostbyname_multi(hostname, ipaddrs, &sNumIpAddrs, found_multi, NULL);
-    if (res == ERR_OK)
-    {
-        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
-        printf("\tlocal DNS cache response\n");
-        printf("\tName: %s\n", hostname);
-        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
-        for (uint8_t i = 0; i < sNumIpAddrs; ++i)
-        {
-            char addrStr[64];
-            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
-            printf("\t(%d) IPv4: %s\n", i, addrStr);
-        }
-    }
-    else
-    {
-        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
-    }
-
-    // Expected cached response
-    printf("Expected cached response #2\n");
-    sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME - 1;
-    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
-    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
-
-    res = dns_gethostbyname_multi(hostname, sIpAddrs, &sNumIpAddrs, found_multi, NULL);
-
-    if (res == ERR_OK)
-    {
-        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
-        printf("\tlocal DNS cache response\n");
-        printf("\tName: %s\n", hostname);
-        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
-        for (i = 0; i < sNumIpAddrs; ++i)
-        {
-            char addrStr[64];
-            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
-            printf("\t(%d) IPv4: %s\n", i, addrStr);
-        }
-    }
-    else
-    {
-        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
-    }
-
-    // Expected cached response
-    printf("Expected cached response #3\n");
-    sNumIpAddrs = 0;
-    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
-    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
-
-    res = dns_gethostbyname_multi(hostname, ipaddrs, &sNumIpAddrs, found_multi, NULL);
-
-    if (res == ERR_OK)
-    {
-        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
-        printf("\tlocal DNS cache response\n");
-        printf("\tName: %s\n", hostname);
-        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
-        for (i = 0; i < sNumIpAddrs; ++i)
-        {
-            char addrStr[64];
-            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
-            printf("\t(%d) IPv4: %s\n", i, addrStr);
-        }
-    }
-    else
-    {
-        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
-    }
-}
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-int main(int argc, char * argv[])
-{
-    SetSIGUSR1Handler();
-
-    if (argc == 1)
-    {
-        gHelpOptions.PrintBriefUsage(stderr);
-        exit(EXIT_FAILURE);
-    }
-
-    if (!ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets, HandleNonOptionArgs))
-    {
-        exit(EXIT_FAILURE);
-    }
-
-    InitSystemLayer();
-
-    InitNetwork();
-
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-    TestLwIPDNS();
-#else
-    fprintf(stderr, "Please assert CHIP_SYSTEM_CONFIG_USE_LWIP to use this test.\n");
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-    ShutdownNetwork();
-
-    ShutdownSystemLayer();
-
-    return (EXIT_SUCCESS);
-}
-
-static bool HandleNonOptionArgs(const char * progName, int argc, char * const argv[])
-{
-    if (argc < 2)
-    {
-        printf("TestDNS: Missing %s argument\n", argc == 0 ? "<hostname>" : "<dns-server-address>");
-        return false;
-    }
-
-    if (argc > 2)
-    {
-        printf("Unexpected argument: %s\n", argv[1]);
-    }
-
-    sHostname      = argv[0];
-    sDNSServerAddr = argv[1];
-
-    return true;
-}
diff --git a/src/inet/tests/TestInetLayer.cpp b/src/inet/tests/inet-layer-test-tool.cpp
similarity index 99%
rename from src/inet/tests/TestInetLayer.cpp
rename to src/inet/tests/inet-layer-test-tool.cpp
index 0001e527af0464..e276600fa10108 100644
--- a/src/inet/tests/TestInetLayer.cpp
+++ b/src/inet/tests/inet-layer-test-tool.cpp
@@ -49,7 +49,7 @@ using namespace chip::System;
 
 /* Preprocessor Macros */
 
-#define kToolName "TestInetLayer"
+#define kToolName "inet-layer-test-tool"
 
 #define kToolOptTCPIP 't'