Fix and test heap allocation of PacketBuffers (#4632)

* Fix and test heap allocation of PacketBuffers

#### Problem

CHIP has to option to use heap-allocated packet buffers
(with `CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE == 0`) but
this configuration has been neglected, and CHIP neither builds
nor runs in this configuration.

#### Summary of Changes

Build fixes:

- Default `CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE` to 15 for heap case.
    15 is the default packet buffer pool size in SystemConfig.h.
    See also issue #4335 - Our definition of the CRMP retransmission
    table size does not really make sense

Runtime fixes:

- Ensure echo server has enough buffer space for the response (and added
  `CHECK_RETURN_VALUE` to `EnsureReservedSize()`).
- Added room for MAC in echo requester.
- Added room for MAC in `chipSendUnicast()`.
- Added parameters to `CloneData()` to request header and trailing
  space.
- Fixed CHIPMem initialization for some tests.
- Fix tests that didn't allocate enough space.

Build and code changes to assist memory troubleshooting (these should have
no cost unless enabled):

- Added a build flag `chip_config_memory_debug_checks` and corresponding
  preprocessor definition `CHIP_CONFIG_MEMORY_DEBUG_CHECKS` to enable extra
  memory checks, at a performance cost. In particular, new functions
  `Platform::MemoryDebugCheckPointer()` and `PacketBufferHandle::Check()`
  operate when this is enabled.
- Added a build flag `chip_config_memory_debug_dmalloc` and corresponding
  preprocessor definition `CHIP_CONFIG_MEMORY_DEBUG_DMALLOC` to use the
  dmalloc debugging malloc library.
- Clarified conditions for the four configurations of PacketBuffer allocation.
- Replaced some PacketBuffer #define constants with scoped constexprs.
- Renamed `CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC` to
  `CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE` to remove the ambiguity of
  what a ‘maximum allocation’ is.

Build and automated test changes:

- Made standalone builds default to heap allocation.
- Run a set of unit tests with dmalloc.

fixes #4395 - Heap packet buffer allocation is broken
fixes #4390 - ReliableMessageProtocol assumes a buffer pool

* review

* review 2

* fix messaging shutdown

* review 3

* fix tests

Co-authored-by: Justin Wood <woody@apple.com>
diff --git a/src/app/Command.cpp b/src/app/Command.cpp
index 41e4251..ef9791e 100644
--- a/src/app/Command.cpp
+++ b/src/app/Command.cpp
@@ -58,7 +58,7 @@
     if (mCommandMessageBuf.IsNull())
     {
         // TODO: Calculate the packet buffer size
-        mCommandMessageBuf = System::PacketBufferHandle::New(System::kMaxPacketBufferSize);
+        mCommandMessageBuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
         VerifyOrExit(!mCommandMessageBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
     }
 
@@ -145,7 +145,7 @@
 
 chip::TLV::TLVWriter & Command::CreateCommandDataElementTLVWriter()
 {
-    mCommandDataBuf = chip::System::PacketBufferHandle::New(System::kMaxPacketBufferSize);
+    mCommandDataBuf = chip::System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
     if (mCommandDataBuf.IsNull())
     {
         ChipLogDetail(DataManagement, "Unable to allocate packet buffer");
@@ -275,7 +275,8 @@
     err = mCommandMessageWriter.Finalize(&mCommandMessageBuf);
     SuccessOrExit(err);
 
-    mCommandMessageBuf->EnsureReservedSize(CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE);
+    VerifyOrExit(mCommandMessageBuf->EnsureReservedSize(System::PacketBuffer::kDefaultHeaderReserve),
+                 err = CHIP_ERROR_BUFFER_TOO_SMALL);
 
 exit:
     ChipLogFunctError(err);
diff --git a/src/app/tests/TestMessageDef.cpp b/src/app/tests/TestMessageDef.cpp
index 2425351..ff4a135 100644
--- a/src/app/tests/TestMessageDef.cpp
+++ b/src/app/tests/TestMessageDef.cpp
@@ -28,6 +28,7 @@
 #include <app/MessageDef/ReadRequest.h>
 #include <app/MessageDef/ReportData.h>
 #include <core/CHIPTLVDebug.hpp>
+#include <support/CHIPMem.h>
 #include <support/UnitTestRegistration.h>
 #include <system/TLVPacketBufferBackingStore.h>
 
@@ -748,7 +749,7 @@
     AttributePath::Builder attributePathBuilder;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     attributePathBuilder.Init(&writer);
     BuildAttributePath(apSuite, attributePathBuilder);
     chip::System::PacketBufferHandle buf;
@@ -771,7 +772,7 @@
     chip::System::PacketBufferTLVReader reader;
     AttributePathList::Builder attributePathListBuilder;
 
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
 
     err = attributePathListBuilder.Init(&writer);
     NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
@@ -796,7 +797,7 @@
     EventPath::Builder eventPathBuilder;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     eventPathBuilder.Init(&writer);
     BuildEventPath(apSuite, eventPathBuilder);
     chip::System::PacketBufferHandle buf;
@@ -820,7 +821,7 @@
     chip::System::PacketBufferTLVReader reader;
     EventPathList::Builder eventPathListBuilder;
 
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
 
     err = eventPathListBuilder.Init(&writer);
     NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
@@ -844,7 +845,7 @@
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
     CommandPath::Builder commandPathBuilder;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     err = commandPathBuilder.Init(&writer);
     NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
 
@@ -870,7 +871,7 @@
     EventDataElement::Parser eventDataElementParser;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     eventDataElementBuilder.Init(&writer);
     BuildEventDataElement(apSuite, eventDataElementBuilder);
     chip::System::PacketBufferHandle buf;
@@ -893,7 +894,7 @@
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
     EventList::Builder eventListBuilder;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     eventListBuilder.Init(&writer);
     BuildEventList(apSuite, eventListBuilder);
     chip::System::PacketBufferHandle buf;
@@ -915,7 +916,7 @@
     StatusElement::Parser statusElementParser;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     statusElementBuilder.Init(&writer);
     BuildStatusElement(apSuite, statusElementBuilder);
     chip::System::PacketBufferHandle buf;
@@ -939,7 +940,7 @@
     AttributeStatusElement::Parser attributeStatusElementParser;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     attributeStatusElementBuilder.Init(&writer);
     BuildAttributeStatusElement(apSuite, attributeStatusElementBuilder);
     chip::System::PacketBufferHandle buf;
@@ -961,7 +962,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     AttributeStatusList::Builder attributeStatusListBuilder;
     err = attributeStatusListBuilder.Init(&writer);
     NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR);
@@ -985,7 +986,7 @@
     AttributeDataElement::Parser attributeDataElementParser;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     attributeDataElementBuilder.Init(&writer);
     BuildAttributeDataElement(apSuite, attributeDataElementBuilder);
     chip::System::PacketBufferHandle buf;
@@ -1007,7 +1008,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     AttributeDataList::Builder attributeDataListBuilder;
     attributeDataListBuilder.Init(&writer);
     BuildAttributeDataList(apSuite, attributeDataListBuilder);
@@ -1028,7 +1029,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     AttributeDataVersionList::Builder attributeDataVersionListBuilder;
     attributeDataVersionListBuilder.Init(&writer);
     BuildAttributeDataVersionList(apSuite, attributeDataVersionListBuilder);
@@ -1051,7 +1052,7 @@
     CommandDataElement::Parser commandDataElementParser;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     commandDataElementBuilder.Init(&writer);
     BuildCommandDataElement(apSuite, commandDataElementBuilder);
     chip::System::PacketBufferHandle buf;
@@ -1074,7 +1075,7 @@
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
     CommandList::Builder commandListBuilder;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     commandListBuilder.Init(&writer);
     BuildCommandList(apSuite, commandListBuilder);
     chip::System::PacketBufferHandle buf;
@@ -1094,7 +1095,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     BuildReportData(apSuite, writer);
     chip::System::PacketBufferHandle buf;
     err = writer.Finalize(&buf);
@@ -1113,7 +1114,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     BuildInvokeCommand(apSuite, writer);
     chip::System::PacketBufferHandle buf;
     err = writer.Finalize(&buf);
@@ -1132,7 +1133,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
     chip::System::PacketBufferTLVWriter writer;
     chip::System::PacketBufferTLVReader reader;
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     BuildReadRequest(apSuite, writer);
     chip::System::PacketBufferHandle buf;
     err = writer.Finalize(&buf);
@@ -1176,6 +1177,26 @@
 // clang-format on
 } // namespace
 
+/**
+ *  Set up the test suite.
+ */
+static int TestSetup(void * inContext)
+{
+    CHIP_ERROR error = chip::Platform::MemoryInit();
+    if (error != CHIP_NO_ERROR)
+        return FAILURE;
+    return SUCCESS;
+}
+
+/**
+ *  Tear down the test suite.
+ */
+static int TestTeardown(void * inContext)
+{
+    chip::Platform::MemoryShutdown();
+    return SUCCESS;
+}
+
 int TestMessageDef()
 {
     // clang-format off
@@ -1183,8 +1204,8 @@
 	{
         "MessageDef",
         &sTests[0],
-        nullptr,
-        nullptr
+        TestSetup,
+        TestTeardown,
     };
     // clang-format on
 
diff --git a/src/app/util/chip-message-send.cpp b/src/app/util/chip-message-send.cpp
index 72d6263..43b8850 100644
--- a/src/app/util/chip-message-send.cpp
+++ b/src/app/util/chip-message-send.cpp
@@ -25,7 +25,8 @@
 #include <assert.h>
 #include <inet/InetLayer.h>
 #include <support/logging/CHIPLogging.h>
-#include <transport/SecureSessionMgr.h> // For SecureSessionMgr
+#include <transport/SecureSessionMgr.h>
+#include <transport/raw/MessageHeader.h>
 
 using namespace chip;
 
diff --git a/src/ble/BLEEndPoint.cpp b/src/ble/BLEEndPoint.cpp
index 1f1ff95..6abdb70 100644
--- a/src/ble/BLEEndPoint.cpp
+++ b/src/ble/BLEEndPoint.cpp
@@ -115,7 +115,7 @@
     mState = kState_Connecting;
 
     // Build BLE transport protocol capabilities request.
-    buf = System::PacketBufferHandle::New(System::kMaxPacketBufferSize);
+    buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
     VerifyOrExit(!buf.IsNull(), err = BLE_ERROR_NO_MEMORY);
 
     // Zero-initialize BLE transport capabilities request.
diff --git a/src/ble/BtpEngine.cpp b/src/ble/BtpEngine.cpp
index d9be4b9..ef83b90 100644
--- a/src/ble/BtpEngine.cpp
+++ b/src/ble/BtpEngine.cpp
@@ -318,7 +318,7 @@
         data->ConsumeHead(startReader.OctetsRead());
 
         // Create a new buffer for use as the Rx re-assembly area.
-        mRxBuf = System::PacketBufferHandle::New(System::kMaxPacketBufferSize);
+        mRxBuf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
 
         VerifyOrExit(!mRxBuf.IsNull(), err = BLE_ERROR_NO_MEMORY);
 
diff --git a/src/controller/CHIPDevice.cpp b/src/controller/CHIPDevice.cpp
index 49db43c..4711af7 100644
--- a/src/controller/CHIPDevice.cpp
+++ b/src/controller/CHIPDevice.cpp
@@ -254,7 +254,7 @@
     // Issue: https://github.com/project-chip/connectedhomeip/issues/4725
 
     // Construct and send "open pairing window" message to the device
-    System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::kMaxPacketBufferSize);
+    System::PacketBufferHandle buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize);
     System::PacketBufferTLVWriter writer;
 
     writer.Init(std::move(buf));
diff --git a/src/controller/java/CHIPProjectConfig.h b/src/controller/java/CHIPProjectConfig.h
index 43d4c20..c610773 100644
--- a/src/controller/java/CHIPProjectConfig.h
+++ b/src/controller/java/CHIPProjectConfig.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2016-2017 Nest Labs, Inc.
  *    Copyright (c) 2019-2020 Google LLC.
  *    All rights reserved.
@@ -43,7 +43,7 @@
 
 #define CHIP_CONFIG_LEGACY_KEY_EXPORT_DELEGATE 0
 
-#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC 300
+#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 300
 
 #define CHIP_CONFIG_ENABLE_FUNCT_ERROR_LOGGING 1
 
diff --git a/src/include/platform/internal/GenericNetworkProvisioningServerImpl.cpp b/src/include/platform/internal/GenericNetworkProvisioningServerImpl.cpp
index 9aaa0bd..9b85f79 100644
--- a/src/include/platform/internal/GenericNetworkProvisioningServerImpl.cpp
+++ b/src/include/platform/internal/GenericNetworkProvisioningServerImpl.cpp
@@ -494,7 +494,7 @@
 #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
 
     // Allocate a buffer to hold the response.
-    respBuf = PacketBufferHandle::New(kMaxPacketBufferSize);
+    respBuf = PacketBufferHandle::New(PacketBuffer::kMaxSize);
     VerifyOrExit(respBuf != NULL, err = CHIP_ERROR_NO_MEMORY);
 
     // Encode the GetNetworks response data.
diff --git a/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.cpp b/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.cpp
index 7c2c3f5..e1ce027 100644
--- a/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.cpp
+++ b/src/include/platform/internal/GenericSoftwareUpdateManagerImpl.cpp
@@ -217,7 +217,7 @@
     }
 
     // Allocate a buffer to hold the image query.
-    mImageQueryPacketBuffer = PacketBufferHandle::New(kMaxPacketBufferSize);
+    mImageQueryPacketBuffer = PacketBufferHandle::New(PacketBuffer::kMaxSize);
     VerifyOrExit(mImageQueryPacketBuffer != NULL, err = CHIP_ERROR_NO_MEMORY);
 
     err = imageQuery.pack(mImageQueryPacketBuffer);
diff --git a/src/inet/IPEndPointBasis.cpp b/src/inet/IPEndPointBasis.cpp
index 30ecb34..6a5aec6 100644
--- a/src/inet/IPEndPointBasis.cpp
+++ b/src/inet/IPEndPointBasis.cpp
@@ -1068,7 +1068,7 @@
     lPacketInfo.Clear();
     lPacketInfo.DestPort = aPort;
 
-    lBuffer = System::PacketBufferHandle::New(System::kMaxPacketBufferSizeWithoutReserve, 0);
+    lBuffer = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
 
     if (!lBuffer.IsNull())
     {
diff --git a/src/inet/TCPEndPoint.h b/src/inet/TCPEndPoint.h
index 0a9bb7b..14a4e1b 100644
--- a/src/inet/TCPEndPoint.h
+++ b/src/inet/TCPEndPoint.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2013-2017 Nest Labs, Inc.
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -562,7 +562,7 @@
     /**
      * Size of the largest TCP packet that can be received.
      */
-    constexpr static size_t kMaxReceiveMessageSize = System::kMaxPacketBufferSizeWithoutReserve;
+    constexpr static size_t kMaxReceiveMessageSize = System::PacketBuffer::kMaxSizeWithoutReserve;
 
 private:
     static chip::System::ObjectPool<TCPEndPoint, INET_CONFIG_NUM_TCP_ENDPOINTS> sPool;
diff --git a/src/inet/tests/TestInetEndPoint.cpp b/src/inet/tests/TestInetEndPoint.cpp
index cb7fd16..7ff2c09 100644
--- a/src/inet/tests/TestInetEndPoint.cpp
+++ b/src/inet/tests/TestInetEndPoint.cpp
@@ -39,6 +39,7 @@
 #include <inet/InetLayer.h>
 
 #include <support/CHIPArgParser.hpp>
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <support/UnitTestRegistration.h>
 
@@ -320,7 +321,7 @@
 #endif // INET_CONFIG_ENABLE_IPV4
     UDPEndPoint * testUDPEP  = nullptr;
     TCPEndPoint * testTCPEP1 = nullptr;
-    PacketBufferHandle buf   = PacketBufferHandle::New(kMaxPacketBufferSize);
+    PacketBufferHandle buf   = PacketBufferHandle::New(PacketBuffer::kMaxSize);
     bool didBind             = false;
     bool didListen           = false;
 
@@ -440,7 +441,7 @@
 #if INET_CONFIG_ENABLE_IPV4
     err = testUDPEP->Bind(kIPAddressType_IPv4, addr_v4, 3000, intId);
     NL_TEST_ASSERT(inSuite, err != INET_NO_ERROR);
-    buf = PacketBufferHandle::New(kMaxPacketBufferSize);
+    buf = PacketBufferHandle::New(PacketBuffer::kMaxSize);
     err = testUDPEP->SendTo(addr_v4, 3000, std::move(buf));
     testUDPEP->Free();
 #endif // INET_CONFIG_ENABLE_IPV4
@@ -448,7 +449,7 @@
     // TcpEndPoint special cases to cover the error branch
     err = testTCPEP1->GetPeerInfo(nullptr, nullptr);
     NL_TEST_ASSERT(inSuite, err == INET_ERROR_INCORRECT_STATE);
-    buf = PacketBufferHandle::New(kMaxPacketBufferSize);
+    buf = PacketBufferHandle::New(PacketBuffer::kMaxSize);
     err = testTCPEP1->Send(std::move(buf), false);
     NL_TEST_ASSERT(inSuite, err == INET_ERROR_INCORRECT_STATE);
     err = testTCPEP1->EnableKeepAlive(10, 100);
@@ -542,16 +543,19 @@
  */
 static int TestSetup(void * inContext)
 {
-    return (SUCCESS);
+    CHIP_ERROR error = chip::Platform::MemoryInit();
+    if (error != CHIP_NO_ERROR)
+        return FAILURE;
+    return SUCCESS;
 }
 
 /**
  *  Tear down the test suite.
- *  Free memory reserved at TestSetup.
  */
 static int TestTeardown(void * inContext)
 {
-    return (SUCCESS);
+    chip::Platform::MemoryShutdown();
+    return SUCCESS;
 }
 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
 
diff --git a/src/lib/core/BUILD.gn b/src/lib/core/BUILD.gn
index faa8629..b48b8a6 100644
--- a/src/lib/core/BUILD.gn
+++ b/src/lib/core/BUILD.gn
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Project CHIP Authors
+# Copyright (c) 2020-2021 Project CHIP Authors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -66,6 +66,8 @@
     "HAVE_NEW=false",
     "CHIP_CONFIG_MEMORY_MGMT_SIMPLE=${chip_config_memory_management_simple}",
     "CHIP_CONFIG_MEMORY_MGMT_PLATFORM=${chip_config_memory_management_platform}",
+    "CHIP_CONFIG_MEMORY_DEBUG_CHECKS=${chip_config_memory_debug_checks}",
+    "CHIP_CONFIG_MEMORY_DEBUG_DMALLOC=${chip_config_memory_debug_dmalloc}",
     "CHIP_CONFIG_PROVIDE_OBSOLESCENT_INTERFACES=false",
   ]
 }
diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h
index 8380825..385d95a 100644
--- a/src/lib/core/CHIPConfig.h
+++ b/src/lib/core/CHIPConfig.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2019 Google LLC.
  *    Copyright (c) 2013-2018 Nest Labs, Inc.
  *
@@ -551,6 +551,36 @@
 #endif // CHIP_CONFIG_SIMPLE_ALLOCATOR_USE_SMALL_BUFFERS
 
 /**
+ *  @def CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+ *
+ *  @brief
+ *    Enable (1) or disable (0) building with additional code
+ *    for memory-related checks.
+ */
+#ifndef CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+#define CHIP_CONFIG_MEMORY_DEBUG_CHECKS     0
+#endif // CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+
+/**
+ *  @def CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+ *
+ *  @brief
+ *    Enable (1) or disable (0) malloc memory allocator support
+ *    for dmalloc, an open-source debug malloc library. When enabled,
+ *    additional checks and logging of allocations may be performed,
+ *    with some performance cost.
+ *
+ *  @note This configuration is most relevant when
+ *        #CHIP_CONFIG_MEMORY_MGMT_MALLOC is set, but may also
+ *        affect other configurations where application or platform
+ *        code uses the malloc() family.
+ *
+ */
+#ifndef CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+#define CHIP_CONFIG_MEMORY_DEBUG_DMALLOC     0
+#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+
+/**
  *  @name chip Security Manager Time-Consuming Crypto Alerts.
  *
  *  @brief
diff --git a/src/lib/core/core.gni b/src/lib/core/core.gni
index deecc50..b7fd5ed 100644
--- a/src/lib/core/core.gni
+++ b/src/lib/core/core.gni
@@ -1,4 +1,4 @@
-# Copyright (c) 2020 Project CHIP Authors
+# Copyright (c) 2020-2021 Project CHIP Authors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -41,6 +41,12 @@
 
   # Memory management style: malloc, simple, platform.
   chip_config_memory_management = "malloc"
+
+  # Memory management debug option: enable additional checks.
+  chip_config_memory_debug_checks = false
+
+  # Memory management debug option: use dmalloc
+  chip_config_memory_debug_dmalloc = false
 }
 
 if (chip_target_style == "") {
diff --git a/src/lib/core/tests/TestCHIPTLV.cpp b/src/lib/core/tests/TestCHIPTLV.cpp
index 1994979..e3ab5f9 100644
--- a/src/lib/core/tests/TestCHIPTLV.cpp
+++ b/src/lib/core/tests/TestCHIPTLV.cpp
@@ -2471,7 +2471,7 @@
 
         ReadEncoding1(inSuite, reader);
 
-        buf = System::PacketBufferHandle::New(System::kMaxPacketBufferSizeWithoutReserve, 0);
+        buf = System::PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
     }
 }
 
diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn
index 78ef1d8..3aa67f3 100644
--- a/src/lib/support/BUILD.gn
+++ b/src/lib/support/BUILD.gn
@@ -133,4 +133,7 @@
   if (chip_logging_style == "android") {
     libs += [ "log" ]
   }
+  if (chip_config_memory_debug_dmalloc) {
+    libs += [ "dmallocthcxx" ]
+  }
 }
diff --git a/src/lib/support/CHIPMem-Malloc.cpp b/src/lib/support/CHIPMem-Malloc.cpp
index 5e520e0..2d8b6b9 100644
--- a/src/lib/support/CHIPMem-Malloc.cpp
+++ b/src/lib/support/CHIPMem-Malloc.cpp
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    All rights reserved.
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,11 @@
 #include <cstdio>
 #endif
 
+#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+#include <dmalloc.h>
+#include <support/SafeInt.h>
+#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+
 #if CHIP_CONFIG_MEMORY_MGMT_MALLOC
 
 namespace chip {
@@ -41,6 +46,7 @@
 #ifdef NDEBUG
 
 #define VERIFY_INITIALIZED()
+#define VERIFY_POINTER(p)
 
 #else
 
@@ -57,6 +63,15 @@
     }
 }
 
+#define VERIFY_POINTER(p)                                                                                                          \
+    do                                                                                                                             \
+        if (((p) != nullptr) && (MemoryDebugCheckPointer((p)) == false))                                                           \
+        {                                                                                                                          \
+            fprintf(stderr, "ABORT: chip::Platform::%s() found corruption on %p\n", __func__, (p));                                \
+            abort();                                                                                                               \
+        }                                                                                                                          \
+    while (0)
+
 #endif
 
 CHIP_ERROR MemoryAllocatorInit(void * buf, size_t bufSize)
@@ -80,6 +95,9 @@
         abort();
     }
 #endif
+#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+    dmalloc_shutdown();
+#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
 }
 
 void * MemoryAlloc(size_t size)
@@ -103,15 +121,27 @@
 void * MemoryRealloc(void * p, size_t size)
 {
     VERIFY_INITIALIZED();
+    VERIFY_POINTER(p);
     return realloc(p, size);
 }
 
 void MemoryFree(void * p)
 {
     VERIFY_INITIALIZED();
+    VERIFY_POINTER(p);
     free(p);
 }
 
+bool MemoryInternalCheckPointer(const void * p, size_t min_size)
+{
+#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+    return CanCastTo<int>(min_size) && (p != nullptr) &&
+        (dmalloc_verify_pnt(__FILE__, __LINE__, __func__, p, 1, static_cast<int>(min_size)) == MALLOC_VERIFY_NOERROR);
+#else  // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+    return (p != nullptr);
+#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
+}
+
 } // namespace Platform
 } // namespace chip
 
diff --git a/src/lib/support/CHIPMem-SimpleAlloc.cpp b/src/lib/support/CHIPMem-SimpleAlloc.cpp
index fdc887a..4099e74 100644
--- a/src/lib/support/CHIPMem-SimpleAlloc.cpp
+++ b/src/lib/support/CHIPMem-SimpleAlloc.cpp
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2019-2020 Google LLC.
  *    Copyright (c) 2018 Nest Labs, Inc.
  *    All rights reserved.
@@ -408,7 +408,7 @@
                     {
                         if (sMemBufs[blockBufferIndex] == NULL)
                         {
-                            sMemBufs[blockBufferIndex] = PacketBuffer::NewWithAvailableSize(0, kMinBufferSize).Release();
+                            sMemBufs[blockBufferIndex] = PacketBufferHandle::New(kMinBufferSize, 0).UnsafeRelease();
                             if (sMemBufs[blockBufferIndex] == NULL)
                                 return NULL;
                         }
@@ -537,6 +537,13 @@
     }
 }
 
+bool MemoryInternalCheckPointer(const void * p, size_t min_size)
+{
+    // TODO: check that \a p is actually an allocated pointer,
+    // by factoring the allocation-finding out of MemoryFree().
+    return p != nullptr;
+}
+
 } // namespace Platform
 } // namespace chip
 
diff --git a/src/lib/support/CHIPMem.h b/src/lib/support/CHIPMem.h
index d1ad2a2..af49fc0 100644
--- a/src/lib/support/CHIPMem.h
+++ b/src/lib/support/CHIPMem.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    All rights reserved.
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -182,5 +182,43 @@
     MemoryFree(p);
 }
 
+// See MemoryDebugCheckPointer().
+extern bool MemoryInternalCheckPointer(const void * p, size_t min_size);
+
+/**
+ * In debug builds, test the validity of a pointer obtained from a chip::Platform memory allocation.
+ *
+ * @param[in]  p                Pointer to a memory block previously allocated with MemoryAlloc, MemoryCalloc,
+ *                              MemoryRealloc, or New, and not freed.
+ * @param[in]  min_size         Gives a size that the allocated block is expected to be able to hold.
+ *
+ * @e Unless configured with #CHIP_CONFIG_MEMORY_DEBUG_CHECKS, this function returns `true` without performing
+ * any check, inlined with the expectation that the compiler can remove any associated failure code.
+ *
+ * With #CHIP_CONFIG_MEMORY_DEBUG_CHECKS enabled:
+ *
+ * This function is guaranteed to return `false` if \a p is `nullptr`. The function returns `true` if \a p is a valid
+ * pointer to an allocation *and* the implementation memory manager is in a fully functioning state.
+ *
+ * @note For non-null \a p, the function *may* return `true` even if the pointer is invalid. That is, a particular
+ *       implementation or configuration is not guaranteed to catch any particular faulty state.
+ * @note For non-null \a p, the function return value *may* be incorrect if the memory manager is in a faulty state
+ *       (e.g. corrupt heap), even if the faulty state does not directly involve \a p.
+ * @note For non-null \a p, the function *may* abort the program rather than return at all if the memory manager is in
+ *       a faulty state, even if \a p is valid.
+ * @note For a non-null \a p, checking *may* be slow.
+ *
+ *
+ * @return  An implementation- and configuration-defined estimate of whether \a p is a valid allocated pointer.
+ */
+inline bool MemoryDebugCheckPointer(const void * p, size_t min_size = 0)
+{
+#if CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+    return MemoryInternalCheckPointer(p, min_size);
+#else  // CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+    return true;
+#endif // CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+}
+
 } // namespace Platform
 } // namespace chip
diff --git a/src/messaging/ExchangeMgr.cpp b/src/messaging/ExchangeMgr.cpp
index 005eeb6..76bd6dc 100644
--- a/src/messaging/ExchangeMgr.cpp
+++ b/src/messaging/ExchangeMgr.cpp
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -89,6 +89,8 @@
 
 CHIP_ERROR ExchangeManager::Shutdown()
 {
+    mReliableMessageMgr.Shutdown();
+
     if (mSessionMgr != nullptr)
     {
         mSessionMgr->SetDelegate(nullptr);
diff --git a/src/messaging/ReliableMessageMgr.cpp b/src/messaging/ReliableMessageMgr.cpp
index 65ddada..2c3854b 100644
--- a/src/messaging/ReliableMessageMgr.cpp
+++ b/src/messaging/ReliableMessageMgr.cpp
@@ -1,5 +1,5 @@
 /*
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    All rights reserved.
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -56,11 +56,11 @@
 
 void ReliableMessageMgr::Shutdown()
 {
+    StopTimer();
+
     mSystemLayer = nullptr;
     mSessionMgr  = nullptr;
 
-    StopTimer();
-
     // Clear the retransmit table
     for (RetransTableEntry & rEntry : mRetransTable)
     {
@@ -398,8 +398,9 @@
         // Clear all other fields
         rEntry = RetransTableEntry();
 
-        // Schedule next physical wakeup
-        StartTimer();
+        // Schedule next physical wakeup, unless shutting down
+        if (mSystemLayer)
+            StartTimer();
     }
 }
 
diff --git a/src/messaging/ReliableMessageProtocolConfig.h b/src/messaging/ReliableMessageProtocolConfig.h
index 16b72f0..96ba381 100644
--- a/src/messaging/ReliableMessageProtocolConfig.h
+++ b/src/messaging/ReliableMessageProtocolConfig.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2017 Nest Labs, Inc.
  *    All rights reserved.
  *
@@ -86,8 +86,10 @@
 #ifndef CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE
 #ifdef PBUF_POOL_SIZE
 #define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE (PBUF_POOL_SIZE)
+#elif CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0
+#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE (CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE)
 #else
-#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE (CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC)
+#define CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE 15
 #endif // PBUF_POOL_SIZE
 #endif // CHIP_CONFIG_RMP_RETRANS_TABLE_SIZE
 
diff --git a/src/messaging/tests/MessagingContext.cpp b/src/messaging/tests/MessagingContext.cpp
index 10eb827..a389111 100644
--- a/src/messaging/tests/MessagingContext.cpp
+++ b/src/messaging/tests/MessagingContext.cpp
@@ -48,6 +48,7 @@
 // Shutdown all layers, finalize operations
 CHIP_ERROR MessagingContext::Shutdown()
 {
+    mExchangeManager.Shutdown();
     return IOContext::Shutdown();
 }
 
diff --git a/src/messaging/tests/TestExchangeMgr.cpp b/src/messaging/tests/TestExchangeMgr.cpp
index 920e108..5cfaa78 100644
--- a/src/messaging/tests/TestExchangeMgr.cpp
+++ b/src/messaging/tests/TestExchangeMgr.cpp
@@ -29,6 +29,7 @@
 #include <messaging/Flags.h>
 #include <messaging/tests/MessagingContext.h>
 #include <protocols/Protocols.h>
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <transport/SecureSessionMgr.h>
 #include <transport/TransportMgr.h>
@@ -146,12 +147,12 @@
 
     // send a malicious packet
     // TODO: https://github.com/project-chip/connectedhomeip/issues/4635
-    // ec1->SendMessage(0x0001, 0x0002, System::PacketBufferHandle::New(System::kMaxPacketBufferSize),
+    // ec1->SendMessage(0x0001, 0x0002, System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize),
     //                 SendFlags(Messaging::SendMessageFlags::kNone));
     NL_TEST_ASSERT(inSuite, !mockUnsolicitedAppDelegate.IsOnMessageReceivedCalled);
 
     // send a good packet
-    ec1->SendMessage(0x0001, 0x0001, System::PacketBufferHandle::New(System::kMaxPacketBufferSize),
+    ec1->SendMessage(0x0001, 0x0001, System::PacketBufferHandle::New(System::PacketBuffer::kMaxSize),
                      SendFlags(Messaging::SendMessageFlags::kNone));
     NL_TEST_ASSERT(inSuite, mockUnsolicitedAppDelegate.IsOnMessageReceivedCalled);
 }
@@ -190,7 +191,11 @@
  */
 int Initialize(void * aContext)
 {
-    CHIP_ERROR err = gTransportMgr.Init("LOOPBACK");
+    CHIP_ERROR err = chip::Platform::MemoryInit();
+    if (err != CHIP_NO_ERROR)
+        return FAILURE;
+
+    err = gTransportMgr.Init("LOOPBACK");
     if (err != CHIP_NO_ERROR)
         return FAILURE;
 
@@ -204,6 +209,7 @@
 int Finalize(void * aContext)
 {
     CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
+    chip::Platform::MemoryShutdown();
     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
 }
 
diff --git a/src/messaging/tests/TestReliableMessageProtocol.cpp b/src/messaging/tests/TestReliableMessageProtocol.cpp
index aedc8f2..713aeef 100644
--- a/src/messaging/tests/TestReliableMessageProtocol.cpp
+++ b/src/messaging/tests/TestReliableMessageProtocol.cpp
@@ -247,7 +247,11 @@
  */
 int Initialize(void * aContext)
 {
-    CHIP_ERROR err = gTransportMgr.Init("LOOPBACK");
+    CHIP_ERROR err = chip::Platform::MemoryInit();
+    if (err != CHIP_NO_ERROR)
+        return FAILURE;
+
+    err = gTransportMgr.Init("LOOPBACK");
     if (err != CHIP_NO_ERROR)
         return FAILURE;
 
@@ -261,6 +265,7 @@
 int Finalize(void * aContext)
 {
     CHIP_ERROR err = reinterpret_cast<TestContext *>(aContext)->Shutdown();
+    chip::Platform::MemoryShutdown();
     return (err == CHIP_NO_ERROR) ? SUCCESS : FAILURE;
 }
 
diff --git a/src/platform/ESP32/NetworkProvisioningServerImpl.cpp b/src/platform/ESP32/NetworkProvisioningServerImpl.cpp
index 794b7b4..fefc169 100644
--- a/src/platform/ESP32/NetworkProvisioningServerImpl.cpp
+++ b/src/platform/ESP32/NetworkProvisioningServerImpl.cpp
@@ -271,7 +271,7 @@
 
         // Allocate a packet buffer to hold the encoded scan results.
         PacketBufferHandle respBuf =
-            System::PacketBufferHandle::New(kMaxPacketBufferSize - 1, CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE + 1);
+            System::PacketBufferHandle::New(PacketBuffer::kMaxSize - 1, System::PacketBuffer::kDefaultHeaderReserve + 1);
         VerifyOrExit(!respBuf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
 
         // Encode the list of scan results into the response buffer.  If the encoded size of all
diff --git a/src/platform/Linux/CHIPBluezHelper.cpp b/src/platform/Linux/CHIPBluezHelper.cpp
index 5098b9f..dd0cdcb 100644
--- a/src/platform/Linux/CHIPBluezHelper.cpp
+++ b/src/platform/Linux/CHIPBluezHelper.cpp
@@ -1279,7 +1279,7 @@
     TLVWriter innerWriter;
     chip::System::PacketBufferHandle bufferHandle;
 
-    writer.Init(chip::System::PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
 
     err = writer.OpenContainer(AnonymousTag, kTLVType_Structure, innerWriter);
     SuccessOrExit(err);
diff --git a/src/protocols/bdx/tests/TestBdxMessages.cpp b/src/protocols/bdx/tests/TestBdxMessages.cpp
index d8df11b..8f8e7d9 100644
--- a/src/protocols/bdx/tests/TestBdxMessages.cpp
+++ b/src/protocols/bdx/tests/TestBdxMessages.cpp
@@ -2,6 +2,8 @@
 
 #include <nlunit-test.h>
 
+#include <support/BufferWriter.h>
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <support/UnitTestRegistration.h>
 
@@ -138,13 +140,33 @@
 };
 // clang-format on
 
+/**
+ *  Set up the test suite.
+ */
+static int TestSetup(void * inContext)
+{
+    CHIP_ERROR error = chip::Platform::MemoryInit();
+    if (error != CHIP_NO_ERROR)
+        return FAILURE;
+    return SUCCESS;
+}
+
+/**
+ *  Tear down the test suite.
+ */
+static int TestTeardown(void * inContext)
+{
+    chip::Platform::MemoryShutdown();
+    return SUCCESS;
+}
+
 // clang-format off
 static nlTestSuite sSuite =
 {
     "Test-CHIP-BdxMessages",
     &sTests[0],
-    nullptr,
-    nullptr
+    TestSetup,
+    TestTeardown,
 };
 // clang-format on
 
diff --git a/src/protocols/bdx/tests/TestBdxTransferSession.cpp b/src/protocols/bdx/tests/TestBdxTransferSession.cpp
index 4e2c2d3..da21303 100644
--- a/src/protocols/bdx/tests/TestBdxTransferSession.cpp
+++ b/src/protocols/bdx/tests/TestBdxTransferSession.cpp
@@ -9,6 +9,7 @@
 #include <core/CHIPTLV.h>
 #include <protocols/common/Constants.h>
 #include <support/BufferReader.h>
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <support/ReturnMacros.h>
 #include <support/UnitTestRegistration.h>
@@ -749,13 +750,27 @@
 };
 // clang-format on
 
+int TestBdxTransferSession_Setup(void * inContext)
+{
+    CHIP_ERROR error = chip::Platform::MemoryInit();
+    if (error != CHIP_NO_ERROR)
+        return FAILURE;
+    return SUCCESS;
+}
+
+int TestBdxTransferSession_Teardown(void * inContext)
+{
+    chip::Platform::MemoryShutdown();
+    return SUCCESS;
+}
+
 // clang-format off
 static nlTestSuite sSuite =
 {
     "Test-CHIP-TransferSession",
     &sTests[0],
-    nullptr,
-    nullptr
+    TestBdxTransferSession_Setup,
+    TestBdxTransferSession_Teardown
 };
 // clang-format on
 
diff --git a/src/system/SystemConfig.h b/src/system/SystemConfig.h
index 5c0fa17..464e8bd 100644
--- a/src/system/SystemConfig.h
+++ b/src/system/SystemConfig.h
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *    Copyright (c) 2016-2018 Nest Labs, Inc.
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
@@ -135,9 +135,9 @@
 #define CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING INET_CONFIG_FREERTOS_LOCKING
 #endif // !defined(CHIP_SYSTEM_CONFIG_FREERTOS_LOCKING) && defined(INET_CONFIG_FREERTOS_LOCKING)
 
-#if !defined(CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC) && defined(INET_CONFIG_NUM_BUFS)
-#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC INET_CONFIG_NUM_BUFS
-#endif // !defined(CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC) && defined(INET_CONFIG_NUM_BUFS)
+#if !defined(CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE) && defined(INET_CONFIG_NUM_BUFS)
+#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE INET_CONFIG_NUM_BUFS
+#endif // !defined(CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE) && defined(INET_CONFIG_NUM_BUFS)
 
 #if !defined(CHIP_SYSTEM_CONFIG_NUM_TIMERS) && defined(INET_CONFIG_NUM_TIMERS)
 #define CHIP_SYSTEM_CONFIG_NUM_TIMERS INET_CONFIG_NUM_TIMERS
@@ -324,16 +324,16 @@
 #endif /* CHIP_SYSTEM_HEADER_RESERVE_SIZE */
 
 /**
- *  @def CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+ *  @def CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE
  *
  *  @brief
  *      This is the total number of packet buffers for the BSD sockets configuration.
  *
  *      This may be set to zero (0) to enable unbounded dynamic allocation using malloc.
  */
-#ifndef CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC 15
-#endif /* CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC */
+#ifndef CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE
+#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE 15
+#endif /* CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE */
 
 /**
  *  @def CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX
@@ -367,7 +367,7 @@
  *
  *      The size of PacketBuffer structure does not need to be included in this value.
  */
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#if CHIP_SYSTEM_CONFIG_USE_LWIP && !defined(DOXYGEN)
 #ifdef CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX
 #error "CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX cannot be defined on an LwIP-based platform."
 #endif /* CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX */
diff --git a/src/system/SystemPacketBuffer.cpp b/src/system/SystemPacketBuffer.cpp
index 1490ef7..99f6b03 100644
--- a/src/system/SystemPacketBuffer.cpp
+++ b/src/system/SystemPacketBuffer.cpp
@@ -53,22 +53,21 @@
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
 #include <lwip/mem.h>
 #include <lwip/pbuf.h>
-#else // !CHIP_SYSTEM_CONFIG_USE_LWIP
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
 #include <support/CHIPMem.h>
 #endif
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
 
 namespace chip {
 namespace System {
 
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL
 //
-// Pool allocation for PacketBuffer objects (toll-free bridged with LwIP pbuf allocator if CHIP_SYSTEM_CONFIG_USE_LWIP)
+// Pool allocation for PacketBuffer objects.
 //
-#if !CHIP_SYSTEM_CONFIG_USE_LWIP
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
 
-static BufferPoolElement sBufferPool[CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC];
+PacketBuffer::BufferPoolElement PacketBuffer::sBufferPool[CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE];
 
 PacketBuffer * PacketBuffer::sFreeList = PacketBuffer::BuildFreeList();
 
@@ -87,7 +86,96 @@
     } while (0)
 #endif // !CHIP_SYSTEM_CONFIG_NO_LOCKING
 
-#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+PacketBuffer * PacketBuffer::BuildFreeList()
+{
+    pbuf * lHead = nullptr;
+
+    for (int i = 0; i < CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE; i++)
+    {
+        pbuf * lCursor = &sBufferPool[i].Header;
+        lCursor->next  = lHead;
+        lCursor->ref   = 0;
+        lHead          = lCursor;
+    }
+
+    Mutex::Init(sBufferPoolMutex);
+
+    return static_cast<PacketBuffer *>(lHead);
+}
+
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
+//
+// Heap allocation for PacketBuffer objects.
+//
+
+#if CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+void PacketBuffer::InternalCheck(const PacketBuffer * buffer)
+{
+    if (buffer)
+    {
+        VerifyOrDieWithMsg(::chip::Platform::MemoryDebugCheckPointer(buffer, buffer->alloc_size + kStructureSize), chipSystemLayer,
+                           "invalid packet buffer pointer");
+        VerifyOrDieWithMsg(buffer->alloc_size >= buffer->ReservedSize() + buffer->len, chipSystemLayer,
+                           "packet buffer overflow %u < %u+%u", buffer->alloc_size, buffer->ReservedSize(), buffer->len);
+    }
+}
+#endif // CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+
+// Number of unused bytes below which \c RightSize() won't bother reallocating.
+constexpr uint16_t kRightSizingThreshold = 16;
+
+void PacketBufferHandle::InternalRightSize()
+{
+    // Require a single buffer with no other references.
+    if ((mBuffer == nullptr) || (mBuffer->next != nullptr) || (mBuffer->ref != 1))
+    {
+        return;
+    }
+
+    // Reallocate only if enough space will be saved.
+    uint8_t * const start   = reinterpret_cast<uint8_t *>(mBuffer) + PacketBuffer::kStructureSize;
+    uint8_t * const payload = reinterpret_cast<uint8_t *>(mBuffer->payload);
+    const uint16_t usedSize = static_cast<uint16_t>(payload - start + mBuffer->len);
+    if (usedSize + kRightSizingThreshold > mBuffer->alloc_size)
+    {
+        return;
+    }
+
+    const size_t blockSize   = usedSize + PacketBuffer::kStructureSize;
+    PacketBuffer * newBuffer = reinterpret_cast<PacketBuffer *>(chip::Platform::MemoryAlloc(blockSize));
+    if (newBuffer == nullptr)
+    {
+        ChipLogError(chipSystemLayer, "PacketBuffer: pool EMPTY.");
+        return;
+    }
+
+    uint8_t * const newStart = reinterpret_cast<uint8_t *>(newBuffer) + PacketBuffer::kStructureSize;
+    newBuffer->next          = nullptr;
+    newBuffer->payload       = newStart + (payload - start);
+    newBuffer->tot_len       = mBuffer->tot_len;
+    newBuffer->len           = mBuffer->len;
+    newBuffer->ref           = 1;
+    newBuffer->alloc_size    = static_cast<uint16_t>(usedSize);
+    memcpy(reinterpret_cast<uint8_t *>(newBuffer) + PacketBuffer::kStructureSize, start, usedSize);
+
+    PacketBuffer::Free(mBuffer);
+    mBuffer = newBuffer;
+}
+
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM
+
+void PacketBufferHandle::InternalRightSize()
+{
+    PacketBuffer * lNewPacket = static_cast<PacketBuffer *>(pbuf_rightsize((struct pbuf *) mBuffer, -1));
+    if (lNewPacket != mBuffer)
+    {
+        mBuffer = lNewPacket;
+        SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS();
+        ChipLogProgress(chipSystemLayer, "PacketBuffer: RightSize Copied");
+    }
+}
+
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE
 
 #ifndef LOCK_BUF_POOL
 #define LOCK_BUF_POOL()                                                                                                            \
@@ -103,11 +191,9 @@
     } while (0)
 #endif // !defined(UNLOCK_BUF_POOL)
 
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
-
 void PacketBuffer::SetStart(uint8_t * aNewStart)
 {
-    uint8_t * const kStart = reinterpret_cast<uint8_t *>(this) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
+    uint8_t * const kStart = reinterpret_cast<uint8_t *>(this) + kStructureSize;
     uint8_t * const kEnd   = kStart + this->AllocSize();
 
     if (aNewStart < kStart)
@@ -136,8 +222,13 @@
     this->len     = aNewLen;
     this->tot_len = static_cast<uint16_t>(this->tot_len + lDelta);
 
+    // SetDataLength is often called after a client finished writing to the buffer,
+    // so it's a good time to check for possible corruption.
+    Check(this);
+
     while (aChainHead != nullptr && aChainHead != this)
     {
+        Check(aChainHead);
         aChainHead->tot_len = static_cast<uint16_t>(aChainHead->tot_len + lDelta);
         aChainHead          = static_cast<PacketBuffer *>(aChainHead->next);
     }
@@ -145,7 +236,7 @@
 
 uint16_t PacketBuffer::MaxDataLength() const
 {
-    const uint8_t * const kStart = reinterpret_cast<const uint8_t *>(this) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
+    const uint8_t * const kStart = reinterpret_cast<const uint8_t *>(this) + kStructureSize;
     const ptrdiff_t kDelta       = static_cast<uint8_t *>(this->payload) - kStart;
     return static_cast<uint16_t>(this->AllocSize() - kDelta);
 }
@@ -160,7 +251,7 @@
     // Cast to size_t is safe because this->payload always points to "after"
     // this.
     const size_t kDelta = static_cast<size_t>(static_cast<uint8_t *>(this->payload) - reinterpret_cast<const uint8_t *>(this));
-    return static_cast<uint16_t>(kDelta - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE);
+    return static_cast<uint16_t>(kDelta - kStructureSize);
 }
 
 void PacketBuffer::AddToEnd(PacketBufferHandle && aPacketHandle)
@@ -189,7 +280,7 @@
 
 void PacketBuffer::CompactHead()
 {
-    uint8_t * const kStart = reinterpret_cast<uint8_t *>(this) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
+    uint8_t * const kStart = reinterpret_cast<uint8_t *>(this) + kStructureSize;
 
     if (this->payload != kStart)
     {
@@ -321,32 +412,33 @@
     // Adding three 16-bit-int sized numbers together will never overflow
     // assuming int is at least 32 bits.
     static_assert(INT_MAX >= INT32_MAX, "int is not big enough");
-    static_assert(CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE < UINT16_MAX, "Check for overflow more carefully");
+    static_assert(PacketBuffer::kStructureSize == sizeof(PacketBuffer), "PacketBuffer size mismatch");
+    static_assert(PacketBuffer::kStructureSize < UINT16_MAX, "Check for overflow more carefully");
     static_assert(SIZE_MAX >= INT_MAX, "Our additions might not fit in size_t");
-    static_assert(CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX <= UINT16_MAX, "PacketBuffer may have size not fitting uint16_t");
+    static_assert(PacketBuffer::kMaxSizeWithoutReserve <= UINT16_MAX, "PacketBuffer may have size not fitting uint16_t");
 
     // When `aAvailableSize` fits in uint16_t (as tested below) and size_t is at least 32 bits (as asserted above),
     // these additions will not overflow.
     const size_t lAllocSize = aReservedSize + aAvailableSize;
-    const size_t lBlockSize = CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + lAllocSize;
+    const size_t lBlockSize = PacketBuffer::kStructureSize + lAllocSize;
     PacketBuffer * lPacket;
 
     CHIP_SYSTEM_FAULT_INJECT(FaultInjection::kFault_PacketBufferNew, return PacketBufferHandle());
 
-    if (aAvailableSize > UINT16_MAX || lAllocSize > CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX || lBlockSize > UINT16_MAX)
+    if (aAvailableSize > UINT16_MAX || lAllocSize > PacketBuffer::kMaxSizeWithoutReserve || lBlockSize > UINT16_MAX)
     {
         ChipLogError(chipSystemLayer, "PacketBuffer: allocation too large.");
         return PacketBufferHandle();
     }
 
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_POOL ||                                                  \
+    CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM
 
     lPacket = static_cast<PacketBuffer *>(pbuf_alloc(PBUF_RAW, static_cast<uint16_t>(lBlockSize), PBUF_POOL));
 
     SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS();
 
-#else // !CHIP_SYSTEM_CONFIG_USE_LWIP
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL
 
     static_cast<void>(lBlockSize);
 
@@ -361,13 +453,14 @@
 
     UNLOCK_BUF_POOL();
 
-#else // !CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
 
     lPacket = reinterpret_cast<PacketBuffer *>(chip::Platform::MemoryAlloc(lBlockSize));
     SYSTEM_STATS_INCREMENT(chip::System::Stats::kSystemLayer_NumPacketBufs);
 
-#endif // !CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
+#else
+#error "Unimplemented CHIP_SYSTEM_PACKETBUFFER_STORE case"
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE
 
     if (lPacket == nullptr)
     {
@@ -375,13 +468,13 @@
         return PacketBufferHandle();
     }
 
-    lPacket->payload = reinterpret_cast<uint8_t *>(lPacket) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + aReservedSize;
+    lPacket->payload = reinterpret_cast<uint8_t *>(lPacket) + PacketBuffer::kStructureSize + aReservedSize;
     lPacket->len = lPacket->tot_len = 0;
     lPacket->next                   = nullptr;
     lPacket->ref                    = 1;
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
     lPacket->alloc_size = static_cast<uint16_t>(lAllocSize);
-#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#endif
 
     return PacketBufferHandle(lPacket);
 }
@@ -416,7 +509,8 @@
  */
 void PacketBuffer::Free(PacketBuffer * aPacket)
 {
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_POOL ||                                                  \
+    CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM
 
     if (aPacket != nullptr)
     {
@@ -425,7 +519,8 @@
         SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS();
     }
 
-#else // !CHIP_SYSTEM_CONFIG_USE_LWIP
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL ||                                                \
+    CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
 
     LOCK_BUF_POOL();
 
@@ -439,13 +534,16 @@
         if (aPacket->ref == 0)
         {
             SYSTEM_STATS_DECREMENT(chip::System::Stats::kSystemLayer_NumPacketBufs);
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
+            ::chip::Platform::MemoryDebugCheckPointer(aPacket, aPacket->alloc_size + kStructureSize);
+#endif
             aPacket->Clear();
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL
             aPacket->next = sFreeList;
             sFreeList     = aPacket;
-#else  // !CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
             chip::Platform::MemoryFree(aPacket);
-#endif // !CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE
             aPacket       = lNextPacket;
         }
         else
@@ -456,7 +554,9 @@
 
     UNLOCK_BUF_POOL();
 
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
+#else
+#error "Unimplemented CHIP_SYSTEM_PACKETBUFFER_STORE case"
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE
 }
 
 /**
@@ -468,9 +568,9 @@
 {
     tot_len = 0;
     len     = 0;
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
     alloc_size = 0;
-#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#endif
 }
 
 /**
@@ -491,27 +591,6 @@
     return lNextPacket;
 }
 
-#if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-
-PacketBuffer * PacketBuffer::BuildFreeList()
-{
-    PacketBuffer * lHead = nullptr;
-
-    for (int i = 0; i < CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC; i++)
-    {
-        PacketBuffer * lCursor = &sBufferPool[i].Header;
-        lCursor->next          = lHead;
-        lCursor->ref           = 0;
-        lHead                  = lCursor;
-    }
-
-    Mutex::Init(sBufferPoolMutex);
-
-    return lHead;
-}
-
-#endif //  !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-
 PacketBufferHandle PacketBufferHandle::PopHead()
 {
     PacketBuffer * head = mBuffer;
@@ -526,74 +605,16 @@
     return PacketBufferHandle(head);
 }
 
-PacketBufferHandle PacketBufferHandle::CloneData()
+PacketBufferHandle PacketBufferHandle::CloneData(uint16_t aAdditionalSize, uint16_t aReservedSize)
 {
     if (!mBuffer->Next().IsNull())
     {
         // We do not clone an entire chain.
         return PacketBufferHandle();
     }
-    return NewWithData(mBuffer->Start(), mBuffer->DataLength());
+    return NewWithData(mBuffer->Start(), mBuffer->DataLength(), aAdditionalSize, aReservedSize);
 }
 
-#if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS
-
-void PacketBufferHandle::RightSizeForLwIPCustomPools()
-{
-    PacketBuffer * lNewPacket = static_cast<PacketBuffer *>(pbuf_rightsize((struct pbuf *) mBuffer, -1));
-    if (lNewPacket != mBuffer)
-    {
-        mBuffer = lNewPacket;
-        SYSTEM_STATS_UPDATE_LWIP_PBUF_COUNTS();
-        ChipLogProgress(chipSystemLayer, "PacketBuffer: RightSize Copied");
-    }
-}
-
-#elif CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
-
-// Number of unused bytes below which \c RightSizeForMemoryAlloc() won't bother reallocating.
-constexpr uint16_t kRightSizingThreshold = 16;
-
-void PacketBufferHandle::RightSizeForMemoryAlloc()
-{
-    // Require a single buffer with no other references.
-    if ((mBuffer == nullptr) || (mBuffer->next != nullptr) || (mBuffer->ref != 1))
-    {
-        return;
-    }
-
-    // Reallocate only if enough space will be saved.
-    uint8_t * const start = reinterpret_cast<uint8_t *>(mBuffer) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-    uint8_t * const payload = reinterpret_cast<uint8_t *>(mBuffer->payload);
-    const size_t usedSize = static_cast<uint16_t>(payload - start + mBuffer->len);
-    if (usedSize + kRightSizingThreshold > mBuffer->alloc_size)
-    {
-        return;
-    }
-
-    const uint16_t blockSize = usedSize + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-    PacketBuffer * newBuffer = reinterpret_cast<PacketBuffer *>(chip::Platform::MemoryAlloc(blockSize));
-    if (newBuffer == nullptr)
-    {
-        ChipLogError(chipSystemLayer, "PacketBuffer: pool EMPTY.");
-        return;
-    }
-
-    uint8_t * const newStart = reinterpret_cast<uint8_t *>(newBuffer) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-    newBuffer->next = nullptr;
-    newBuffer->payload = newStart + (payload - start);
-    newBuffer->tot_len = mBuffer->tot_len;
-    newBuffer->len = mBuffer->len;
-    newBuffer->ref = 1;
-    newBuffer->alloc_size = static_cast<uint16_t>(usedSize);
-    memcpy(reinterpret_cast<uint8_t *>(newBuffer) + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE, start, usedSize);
-
-    chip::Platform::MemoryFree(mBuffer);
-    mBuffer = newBuffer;
-}
-
-#endif
-
 } // namespace System
 
 namespace Encoding {
diff --git a/src/system/SystemPacketBuffer.h b/src/system/SystemPacketBuffer.h
index f4863f9..2c07ea0 100644
--- a/src/system/SystemPacketBuffer.h
+++ b/src/system/SystemPacketBuffer.h
@@ -45,6 +45,44 @@
 
 class PacketBufferTest;
 
+/*
+ * Preprocessor definitions related to packet buffer memory configuration.
+ * These are not part of the public PacketBuffer interface; they are present
+ * here so that certain public functions can have definitions optimized for
+ * particular configurations.
+ */
+
+#undef CHIP_SYSTEM_PACKETBUFFER_STORE                // One of the following constants:
+#define CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_POOL 1   //   Default lwIP allocation
+#define CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM 2 //   Custom lwIP allocation
+#define CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL 3   //   Internal fixed pool
+#define CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP 4   //   Platform::MemoryAlloc
+
+#undef CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE // True if RightSize() has a nontrivial implementation
+#undef CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK      // True if Check() has a nontrivial implementation
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#if LWIP_PBUF_FROM_CUSTOM_POOLS
+#define CHIP_SYSTEM_PACKETBUFFER_STORE CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE 1
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK 0
+#else
+#define CHIP_SYSTEM_PACKETBUFFER_STORE CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_POOL
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE 0
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK 0
+#endif
+#else
+#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE
+#define CHIP_SYSTEM_PACKETBUFFER_STORE CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE 0
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK 0
+#else
+#define CHIP_SYSTEM_PACKETBUFFER_STORE CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE 1
+#define CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK CHIP_CONFIG_MEMORY_DEBUG_CHECKS
+#endif
+#endif
+
 namespace chip {
 namespace System {
 
@@ -58,9 +96,9 @@
     uint16_t tot_len;
     uint16_t len;
     uint16_t ref;
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
     uint16_t alloc_size;
-#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
+#endif
 };
 #endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
 
@@ -84,8 +122,7 @@
  *
  *      New objects of PacketBuffer class are initialized at the beginning of an allocation of memory obtained from the underlying
  *      environment, e.g. from LwIP pbuf target pools, from the standard C library heap, from an internal buffer pool. In the
- *      simple case, the size of the data buffer is #CHIP_SYSTEM_PACKETBUFFER_SIZE. A composer is provided that permits usage of
- *      data buffers of other sizes.
+ *      simple pool case, the size of the data buffer is PacketBuffer::kBlockSize.
  *
  *      PacketBuffer objects may be chained to accomodate larger payloads.  Chaining, however, is not transparent, and users of the
  *      class must explicitly decide to support chaining.  Examples of classes written with chaining support are as follows:
@@ -96,8 +133,36 @@
  */
 class DLL_EXPORT PacketBuffer : private pbuf
 {
+private:
+    // The effective size of the packet buffer structure.
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+    static constexpr uint16_t kStructureSize = LWIP_MEM_ALIGN_SIZE(sizeof(struct ::pbuf));
+#else  // CHIP_SYSTEM_CONFIG_USE_LWIP
+    static constexpr uint16_t kStructureSize         = CHIP_SYSTEM_ALIGN_SIZE(sizeof(::chip::System::pbuf), 4u);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
 public:
     /**
+     * The maximum size buffer an application can allocate with no protocol header reserve.
+     */
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+    static constexpr uint16_t kMaxSizeWithoutReserve = (LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - PacketBuffer::kStructureSize);
+#else
+    static constexpr uint16_t kMaxSizeWithoutReserve = CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX;
+#endif
+
+    /**
+     * The number of bytes to reserve in a network packet buffer to contain all the possible protocol encapsulation headers
+     * before the application data.
+     */
+    static constexpr uint16_t kDefaultHeaderReserve = CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE;
+
+    /**
+     * The maximum size buffer an application can allocate with the default protocol header reserve.
+     */
+    static constexpr uint16_t kMaxSize = kMaxSizeWithoutReserve - kDefaultHeaderReserve;
+
+    /**
      * Return the size of the allocation including the reserved and payload data spaces but not including space
      * allocated for the PacketBuffer structure.
      *
@@ -105,7 +170,23 @@
      *
      *  @return     size of the allocation
      */
-    uint16_t AllocSize() const;
+    uint16_t AllocSize() const
+    {
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_POOL ||                                                  \
+    CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL
+        return kMaxSizeWithoutReserve;
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_HEAP
+        return this->alloc_size;
+#elif CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_LWIP_CUSTOM
+        // Temporary workaround for custom pbufs by assuming size to be PBUF_POOL_BUFSIZE
+        if (this->flags & PBUF_FLAG_IS_CUSTOM)
+            return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - kStructureSize;
+        else
+            return LWIP_MEM_ALIGN_SIZE(memp_sizes[this->pool]) - kStructureSize;
+#else
+#error "Unimplemented CHIP_SYSTEM_PACKETBUFFER_STORE case"
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE
+    }
 
     /**
      * Get a pointer to the start of data in a buffer.
@@ -228,7 +309,7 @@
      *
      *  @return \c true if the requested reserved size is available, \c false if there's not enough room in the buffer.
      */
-    bool EnsureReservedSize(uint16_t aReservedSize);
+    CHECK_RETURN_VALUE bool EnsureReservedSize(uint16_t aReservedSize);
 
     /**
      * Align the buffer payload on the specified bytes boundary.
@@ -257,12 +338,46 @@
      */
     CHECK_RETURN_VALUE PacketBufferHandle Last();
 
-private:
-#if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-    static PacketBuffer * sFreeList;
+    /**
+     * Perform an implementation-defined check on the validity of a PacketBuffer pointer.
+     *
+     * Unless enabled by #CHIP_CONFIG_MEMORY_DEBUG_CHECKS == 1, this function does nothing.
+     *
+     * When enabled, it performs an implementation- and configuration-defined check on
+     * the validity of the packet buffer. It MAY log an error and/or abort the program
+     * if the packet buffer or the implementation-defined memory management system is in
+     * a faulty state. (Some configurations may not actually perform any check.)
+     *
+     * @note  A null pointer is not considered faulty.
+     *
+     *  @param[in] buffer - the packet buffer to check.
+     */
+    static void Check(const PacketBuffer * buffer)
+    {
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
+        InternalCheck(buffer);
+#endif
+    }
 
+private:
+    // Memory required for a maximum-size PacketBuffer.
+    static constexpr uint16_t kBlockSize = PacketBuffer::kStructureSize + PacketBuffer::kMaxSizeWithoutReserve;
+
+    // Note: this condition includes DOXYGEN to work around a Doxygen error. DOXYGEN is never defined in any actual build.
+#if CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL || defined(DOXYGEN)
+    typedef union
+    {
+        pbuf Header;
+        uint8_t Block[PacketBuffer::kBlockSize];
+    } BufferPoolElement;
+    static BufferPoolElement sBufferPool[CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE];
+    static PacketBuffer * sFreeList;
     static PacketBuffer * BuildFreeList();
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
+#endif // CHIP_SYSTEM_PACKETBUFFER_STORE == CHIP_SYSTEM_PACKETBUFFER_STORE_CHIP_POOL || defined(DOXYGEN)
+
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
+    static void InternalCheck(const PacketBuffer * buffer);
+#endif
 
     void AddRef();
     static void Free(PacketBuffer * aPacket);
@@ -277,101 +392,7 @@
     friend class ::PacketBufferTest;
 };
 
-} // namespace System
-} // namespace chip
-
-// Sizing definitions
-
-/**
- * @def CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE
- *
- *  The effective size of the packet buffer structure.
- *
- *  TODO: This is an implementation details that does not need to be public and should be moved to the source file.
- */
-
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-#define CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE LWIP_MEM_ALIGN_SIZE(sizeof(struct ::pbuf))
-#else // CHIP_SYSTEM_CONFIG_USE_LWIP
-#define CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE CHIP_SYSTEM_ALIGN_SIZE(sizeof(::chip::System::PacketBuffer), 4u)
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-/**
- * @def CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX
- *
- *  See SystemConfig.h for full description. This is defined in here specifically for LwIP platform to preserve backwards
- *  compatibility.
- *
- *  TODO: This is an implementation details that does not need to be public and should be moved to the source file.
- *
- */
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-#define CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX (LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)
-#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
-
-/**
- * @def CHIP_SYSTEM_PACKETBUFFER_SIZE
- *
- *  The memory footprint of a PacketBuffer object, computed from max capacity size and the size of the packet buffer structure.
- *
- *  TODO: This is an implementation details that does not need to be public and should be moved to the source file.
- */
-
-#define CHIP_SYSTEM_PACKETBUFFER_SIZE (CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)
-
-namespace chip {
-namespace System {
-
-/**
- * The maximum size buffer an application can allocate with the default reserve, i.e. \c PacketBufferHandle::New(size).
- */
-constexpr uint16_t kMaxPacketBufferSize = CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX - CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE;
-
-/**
- * The maximum size buffer an application can allocate with no reserve, i.e. \c PacketBufferHandle::New(size, 0).
- */
-constexpr uint16_t kMaxPacketBufferSizeWithoutReserve = CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX;
-
-//
-// Pool allocation for PacketBuffer objects (toll-free bridged with LwIP pbuf allocator if CHIP_SYSTEM_CONFIG_USE_LWIP)
-//
-#if !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-
-typedef union
-{
-    PacketBuffer Header;
-    uint8_t Block[CHIP_SYSTEM_PACKETBUFFER_SIZE];
-} BufferPoolElement;
-
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP && CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-
-inline uint16_t PacketBuffer::AllocSize() const
-{
-#if CHIP_SYSTEM_CONFIG_USE_LWIP
-#if LWIP_PBUF_FROM_CUSTOM_POOLS
-    // Temporary workaround for custom pbufs by assuming size to be PBUF_POOL_BUFSIZE
-    if (this->flags & PBUF_FLAG_IS_CUSTOM)
-        return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-    else
-        return LWIP_MEM_ALIGN_SIZE(memp_sizes[this->pool]) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-#else  // !LWIP_PBUF_FROM_CUSTOM_POOLS
-    return LWIP_MEM_ALIGN_SIZE(PBUF_POOL_BUFSIZE) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-#endif // !LWIP_PBUF_FROM_CUSTOM_POOLS
-#else  // !CHIP_SYSTEM_CONFIG_USE_LWIP
-#if CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0
-    return this->alloc_size;
-#else  // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC != 0
-    extern BufferPoolElement gDummyBufferPoolElement;
-    return sizeof(gDummyBufferPoolElement.Block) - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
-#endif // CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC != 0
-#endif // !CHIP_SYSTEM_CONFIG_USE_LWIP
-}
-
-} // namespace System
-} // namespace chip
-
-namespace chip {
-namespace System {
+static_assert(sizeof(pbuf) == sizeof(PacketBuffer), "PacketBuffer must not have additional members");
 
 /**
  * @class PacketBufferHandle
@@ -495,8 +516,8 @@
      */
     void RightSize()
     {
-#if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS
-        RightSizeForLwIPCustomPools();
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
+        InternalRightSize();
 #endif
     }
 
@@ -535,6 +556,7 @@
      */
     CHECK_RETURN_VALUE PacketBuffer * UnsafeRelease() &&
     {
+        PacketBuffer::Check(mBuffer);
         PacketBuffer * buffer = mBuffer;
         mBuffer               = nullptr;
         return buffer;
@@ -550,7 +572,7 @@
      *       provides a pointer to the start of this space.
      *
      *  Fails and returns \c nullptr if no memory is available, or if the size requested is too large.
-     *  When the sum of \a aAvailableSize and \a aReservedSize is no greater than \c kMaxPacketBufferSizeWithoutReserve,
+     *  When the sum of \a aAvailableSize and \a aReservedSize is no greater than \c PacketBuffer::kMaxSizeWithoutReserve,
      *  that is guaranteed not to be too large.
      *
      *  On success, it is guaranteed that \c AvailableDataSize() is no less than \a aAvailableSize.
@@ -560,7 +582,7 @@
      *
      *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
      */
-    static PacketBufferHandle New(size_t aAvailableSize, uint16_t aReservedSize = CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE);
+    static PacketBufferHandle New(size_t aAvailableSize, uint16_t aReservedSize = PacketBuffer::kDefaultHeaderReserve);
 
     /**
      * Allocates a packet buffer with initial contents.
@@ -573,20 +595,49 @@
      *  @return     On success, a PacketBufferHandle to the allocated buffer. On fail, \c nullptr.
      */
     static PacketBufferHandle NewWithData(const void * aData, size_t aDataSize, uint16_t aAdditionalSize = 0,
-                                          uint16_t aReservedSize = CHIP_SYSTEM_CONFIG_HEADER_RESERVE_SIZE);
+                                          uint16_t aReservedSize = PacketBuffer::kDefaultHeaderReserve);
 
     /**
      * Creates a copy of the data in this packet.
      *
      * Does NOT support chained buffers.
      *
+     *  @param[in]  aAdditionalSize Size of additional application data space after the initial contents.
+     *  @param[in]  aReservedSize   Number of octets to reserve for protocol headers.
+     *
      * @returns empty handle on allocation failure.
      */
-    PacketBufferHandle CloneData();
+    PacketBufferHandle CloneData(uint16_t aAdditionalSize = 0, uint16_t aReservedSize = PacketBuffer::kDefaultHeaderReserve);
+
+    /**
+     * Perform an implementation-defined check on the validity of a PacketBufferHandle.
+     *
+     * Unless enabled by #CHIP_CONFIG_MEMORY_DEBUG_CHECKS == 1, this function does nothing.
+     *
+     * When enabled, it performs an implementation- and configuration-defined check on
+     * the validity of the packet buffer. It MAY log an error and/or abort the program
+     * if the packet buffer or the implementation-defined memory management system is in
+     * a faulty state. (Some configurations may not actually perform any check.)
+     *
+     * @note  A null handle is not considered faulty.
+     *
+     *  @param[in] aPacket - the packet buffer handle to check.
+     */
+    void Check() const
+    {
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_CHECK
+        PacketBuffer::Check(mBuffer);
+#endif
+    }
 
 protected:
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
-    static struct pbuf * GetLwIPpbuf(const PacketBufferHandle & handle) { return static_cast<struct pbuf *>(handle.mBuffer); }
+    // For use via LwIPPacketBufferView only.
+    static struct pbuf * GetLwIPpbuf(const PacketBufferHandle & handle)
+    {
+        PacketBuffer::Check(handle.mBuffer);
+        return static_cast<struct pbuf *>(handle.mBuffer);
+    }
 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
 
 private:
@@ -609,10 +660,8 @@
 
     bool operator==(const PacketBufferHandle & aOther) { return mBuffer == aOther.mBuffer; }
 
-#if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS
-    void RightSizeForLwIPCustomPools();
-#elif !CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC
-    void RightSizeForMemoryAlloc();
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
+    void InternalRightSize();
 #endif
 
     PacketBuffer * mBuffer;
diff --git a/src/system/TLVPacketBufferBackingStore.cpp b/src/system/TLVPacketBufferBackingStore.cpp
index 80998a3..effa547 100644
--- a/src/system/TLVPacketBufferBackingStore.cpp
+++ b/src/system/TLVPacketBufferBackingStore.cpp
@@ -91,7 +91,7 @@
     mCurrentBuffer.Advance();
     if (mCurrentBuffer.IsNull())
     {
-        mCurrentBuffer = PacketBufferHandle::New(System::kMaxPacketBufferSizeWithoutReserve, 0);
+        mCurrentBuffer = PacketBufferHandle::New(System::PacketBuffer::kMaxSizeWithoutReserve, 0);
         if (mCurrentBuffer.IsNull())
         {
             return CHIP_ERROR_NO_MEMORY;
diff --git a/src/system/tests/TestSystemPacketBuffer.cpp b/src/system/tests/TestSystemPacketBuffer.cpp
index 5bdf68d..74f64a8 100644
--- a/src/system/tests/TestSystemPacketBuffer.cpp
+++ b/src/system/tests/TestSystemPacketBuffer.cpp
@@ -34,6 +34,7 @@
 #include <utility>
 #include <vector>
 
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <support/UnitTestRegistration.h>
 #include <system/SystemPacketBuffer.h>
@@ -129,6 +130,8 @@
     }
     static void PrintHandle(const char * tag, const PacketBufferHandle & handle) { PrintHandle(tag, handle.mBuffer); }
 
+    static constexpr uint16_t kBlockSize = PacketBuffer::kBlockSize;
+
 private:
     struct BufferConfiguration
     {
@@ -178,8 +181,8 @@
     std::vector<PacketBufferHandle> handles;
 };
 
-const uint16_t sTestReservedSizes[] = { 0, 10, 128, 1536, CHIP_SYSTEM_PACKETBUFFER_SIZE };
-const uint16_t sTestLengths[]       = { 0, 1, 10, 128, CHIP_SYSTEM_PACKETBUFFER_SIZE, UINT16_MAX };
+const uint16_t sTestReservedSizes[] = { 0, 10, 128, 1536, PacketBufferTest::kBlockSize };
+const uint16_t sTestLengths[]       = { 0, 1, 10, 128, PacketBufferTest::kBlockSize, UINT16_MAX };
 
 PacketBufferTest::TestContext sContext = {
     sTestReservedSizes,
@@ -200,6 +203,7 @@
 
 int PacketBufferTest::TestSetup(void * inContext)
 {
+    chip::Platform::MemoryInit();
     TestContext * const theContext = reinterpret_cast<TestContext *>(inContext);
     theContext->test               = new PacketBufferTest(theContext);
     if (theContext->test == nullptr)
@@ -262,7 +266,7 @@
 {
     if (config->handle.IsNull())
     {
-        config->handle = PacketBufferHandle::New(chip::System::kMaxPacketBufferSizeWithoutReserve, 0);
+        config->handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
         if (config->handle.IsNull())
         {
             printf("NewPacketBuffer: Failed to allocate packet buffer (%zu retained): %s\n", handles.size(), strerror(errno));
@@ -279,11 +283,11 @@
         exit(EXIT_FAILURE);
     }
 
-    const size_t lInitialSize = CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + config->reserved_size;
-    const size_t lAllocSize   = CHIP_SYSTEM_PACKETBUFFER_SIZE;
+    const size_t lInitialSize = PacketBuffer::kStructureSize + config->reserved_size;
+    const size_t lAllocSize   = kBlockSize;
 
     uint8_t * const raw = reinterpret_cast<uint8_t *>(config->handle.Get());
-    memset(raw + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE, 0, lAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE);
+    memset(raw + PacketBuffer::kStructureSize, 0, lAllocSize - PacketBuffer::kStructureSize);
 
     config->start_buffer = raw;
     config->end_buffer   = raw + lAllocSize;
@@ -342,7 +346,7 @@
  *
  *  Description: For every buffer-configuration from inContext, create a buffer's instance
  *               using the New() method. Then, verify that when the size of the reserved space
- *               passed to New() is greater than #CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX,
+ *               passed to New() is greater than PacketBuffer::kMaxSizeWithoutReserve,
  *               the method returns nullptr. Otherwise, check for correctness of initializing
  *               the new buffer's internal state.
  */
@@ -356,7 +360,7 @@
     {
         const PacketBufferHandle buffer = PacketBufferHandle::New(0, config.reserved_size);
 
-        if (config.reserved_size > CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX)
+        if (config.reserved_size > PacketBuffer::kMaxSizeWithoutReserve)
         {
             NL_TEST_ASSERT(inSuite, buffer.IsNull());
             continue;
@@ -376,6 +380,7 @@
         }
     }
 
+#if CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0
     // Use the rest of the buffer space
     std::vector<PacketBufferHandle> allocate_all_the_things;
     for (;;)
@@ -388,6 +393,7 @@
         // Hold on to the buffer, to use up all the buffer space.
         allocate_all_the_things.push_back(std::move(buffer));
     }
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP || CHIP_SYSTEM_CONFIG_PACKETBUFFER_POOL_SIZE != 0
 }
 
 /**
@@ -423,7 +429,7 @@
     PacketBufferTest * const test         = theContext->test;
     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
 
-    static constexpr ptrdiff_t sSizePacketBuffer = CHIP_SYSTEM_PACKETBUFFER_SIZE;
+    static constexpr ptrdiff_t sSizePacketBuffer = kBlockSize;
 
     for (auto & config : test->configurations)
     {
@@ -448,10 +454,10 @@
 
             config.handle->SetStart(test_start);
 
-            if (verify_start < config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE)
+            if (verify_start < config.start_buffer + PacketBuffer::kStructureSize)
             {
                 // Set start before valid payload beginning.
-                verify_start = config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE;
+                verify_start = config.start_buffer + PacketBuffer::kStructureSize;
             }
 
             if (verify_start > config.end_buffer)
@@ -835,7 +841,7 @@
 
             config.handle->CompactHead();
 
-            NL_TEST_ASSERT(inSuite, config.handle->payload == (config.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE));
+            NL_TEST_ASSERT(inSuite, config.handle->payload == (config.start_buffer + PacketBuffer::kStructureSize));
             NL_TEST_ASSERT(inSuite, config.handle->tot_len == data_length);
         }
 
@@ -885,8 +891,7 @@
 
                     config_1.handle->CompactHead();
 
-                    NL_TEST_ASSERT(inSuite,
-                                   config_1.handle->payload == (config_1.start_buffer + CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE));
+                    NL_TEST_ASSERT(inSuite, config_1.handle->payload == (config_1.start_buffer + PacketBuffer::kStructureSize));
 
                     if (config_1.handle->tot_len > config_1.handle->MaxDataLength())
                     {
@@ -1091,9 +1096,9 @@
             const uint16_t kAllocSize = config.handle->AllocSize();
             uint16_t reserved_size    = config.reserved_size;
 
-            if (CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE + config.reserved_size > kAllocSize)
+            if (PacketBuffer::kStructureSize + config.reserved_size > kAllocSize)
             {
-                reserved_size = static_cast<uint16_t>(kAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE);
+                reserved_size = static_cast<uint16_t>(kAllocSize - PacketBuffer::kStructureSize);
             }
 
             if (length <= reserved_size)
@@ -1102,7 +1107,7 @@
                 continue;
             }
 
-            if ((length + config.init_len) > (kAllocSize - CHIP_SYSTEM_PACKETBUFFER_HEADER_SIZE))
+            if ((length + config.init_len) > (kAllocSize - PacketBuffer::kStructureSize))
             {
                 NL_TEST_ASSERT(inSuite, config.handle->EnsureReservedSize(length) == false);
                 continue;
@@ -1301,8 +1306,8 @@
             // start with various buffer ref counts
             for (size_t r = 0; r < kRefs; r++)
             {
-                config_1.handle = PacketBufferHandle::New(chip::System::kMaxPacketBufferSizeWithoutReserve, 0);
-                config_2.handle = PacketBufferHandle::New(chip::System::kMaxPacketBufferSizeWithoutReserve, 0);
+                config_1.handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
+                config_2.handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
                 NL_TEST_ASSERT(inSuite, !config_1.handle.IsNull());
                 NL_TEST_ASSERT(inSuite, !config_2.handle.IsNull());
 
@@ -1453,7 +1458,7 @@
     PacketBufferHandle handle_2(nullptr);
     NL_TEST_ASSERT(inSuite, handle_2.IsNull());
 
-    PacketBufferHandle handle_3(PacketBufferHandle::New(chip::System::kMaxPacketBufferSize));
+    PacketBufferHandle handle_3(PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize));
     NL_TEST_ASSERT(inSuite, !handle_3.IsNull());
 
     // Private constructor.
@@ -1672,7 +1677,7 @@
     NL_TEST_ASSERT(inSuite, test->mContext == theContext);
 
     const char kPayload[]     = "Joy!";
-    PacketBufferHandle handle = PacketBufferHandle::New(chip::System::kMaxPacketBufferSizeWithoutReserve, 0);
+    PacketBufferHandle handle = PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0);
     PacketBuffer * buffer     = handle.mBuffer;
 
     memcpy(handle->Start(), kPayload, sizeof kPayload);
@@ -1686,20 +1691,20 @@
         NL_TEST_ASSERT(inSuite, handle.mBuffer == buffer);
     }
 
-#if (CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS) || (CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0)
+#if CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
 
     handle.RightSize();
     NL_TEST_ASSERT(inSuite, handle.mBuffer != buffer);
-    NL_TEST_ASSERT(inSuite, handle->DataSize() == sizeof kPayload);
+    NL_TEST_ASSERT(inSuite, handle->DataLength() == sizeof kPayload);
     NL_TEST_ASSERT(inSuite, memcmp(handle->Start(), kPayload, sizeof kPayload) == 0);
 
-#else // !((CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS) || (CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0))
+#else // CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
 
     // For this configuration, RightSize() does nothing.
     handle.RightSize();
     NL_TEST_ASSERT(inSuite, handle.mBuffer == buffer);
 
-#endif // !((CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_PBUF_FROM_CUSTOM_POOLS) || (CHIP_SYSTEM_CONFIG_PACKETBUFFER_MAXALLOC == 0))
+#endif // CHIP_SYSTEM_PACKETBUFFER_HAS_RIGHT_SIZE
 }
 
 void PacketBufferTest::CheckPacketBufferWriter(nlTestSuite * inSuite, void * inContext)
@@ -1716,7 +1721,9 @@
     NL_TEST_ASSERT(inSuite, !nay.IsNull());
 
     yay.Put(kPayload);
+    yay.Put('\0');
     nay.Put(kPayload);
+    nay.Put('\0');
     NL_TEST_ASSERT(inSuite, yay.Fit());
     NL_TEST_ASSERT(inSuite, !nay.Fit());
 
diff --git a/src/transport/SecureSessionMgr.h b/src/transport/SecureSessionMgr.h
index 6858d09..adeee6c 100644
--- a/src/transport/SecureSessionMgr.h
+++ b/src/transport/SecureSessionMgr.h
@@ -318,8 +318,8 @@
  */
 inline System::PacketBufferHandle New(size_t aAvailableSize)
 {
-    static_assert(CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX > kMaxFooterSize, "inadequate capacity");
-    if (aAvailableSize > CHIP_SYSTEM_CONFIG_PACKETBUFFER_CAPACITY_MAX - kMaxFooterSize)
+    static_assert(System::PacketBuffer::kMaxSize > kMaxFooterSize, "inadequate capacity");
+    if (aAvailableSize > System::PacketBuffer::kMaxSize - kMaxFooterSize)
     {
         return System::PacketBufferHandle();
     }
diff --git a/src/transport/raw/tests/NetworkTestHelpers.cpp b/src/transport/raw/tests/NetworkTestHelpers.cpp
index d3902bb..281fab2 100644
--- a/src/transport/raw/tests/NetworkTestHelpers.cpp
+++ b/src/transport/raw/tests/NetworkTestHelpers.cpp
@@ -1,6 +1,6 @@
 /*
  *
- *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2020-2021 Project CHIP Authors
  *
  *    Licensed under the Apache License, Version 2.0 (the "License");
  *    you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
 
 #include <inet/tests/TestInetCommon.h>
 
+#include <support/CHIPMem.h>
 #include <support/CodeUtils.h>
 #include <support/ErrorStr.h>
 
@@ -27,7 +28,7 @@
 
 CHIP_ERROR IOContext::Init(nlTestSuite * suite)
 {
-    CHIP_ERROR err = CHIP_NO_ERROR;
+    CHIP_ERROR err = Platform::MemoryInit();
 
     gSystemLayer.Init(nullptr);
 
@@ -46,6 +47,7 @@
     CHIP_ERROR err = CHIP_NO_ERROR;
 
     ShutdownNetwork();
+    Platform::MemoryShutdown();
 
     return err;
 }
diff --git a/src/transport/tests/TestSecureSessionMgr.cpp b/src/transport/tests/TestSecureSessionMgr.cpp
index d0e7ddd..0ea823c 100644
--- a/src/transport/tests/TestSecureSessionMgr.cpp
+++ b/src/transport/tests/TestSecureSessionMgr.cpp
@@ -190,7 +190,6 @@
     callback.ReceiveHandlerCallCount = 0;
 
     err = secureSessionMgr.SendMessage(localToRemoteSession, std::move(buffer));
-    printf("err=%d\n", err);
     NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
 
     ctx.DriveIOUntil(1000 /* ms */, []() { return callback.ReceiveHandlerCallCount != 0; });