Matter SDK Coverage Report
Current view: top level - inet - BasicPacketFilters.h (source / functions) Coverage Total Hit
Test: SHA:4d2388ac7eed75b2fe5e05e20de377999c632502 Lines: 86.7 % 30 26
Test Date: 2025-07-26 07:12:52 Functions: 77.8 % 9 7

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2022 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : 
      18              : #pragma once
      19              : 
      20              : #include <atomic>
      21              : #include <inet/EndpointQueueFilter.h>
      22              : #include <inet/IPPacketInfo.h>
      23              : #include <lib/support/CodeUtils.h>
      24              : #include <system/SystemPacketBuffer.h>
      25              : 
      26              : namespace chip {
      27              : namespace Inet {
      28              : 
      29              : /**
      30              :  * @brief Basic filter that counts how many pending (not yet dequeued) packets
      31              :  *        are accumulated that match a predicate function, and drops those that
      32              :  *        would cause crossing of the threshold.
      33              :  */
      34              : class DropIfTooManyQueuedPacketsFilter : public chip::Inet::EndpointQueueFilter
      35              : {
      36              : public:
      37              :     typedef bool (*PacketMatchPredicateFunc)(void * context, const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
      38              :                                              const chip::System::PacketBufferHandle & pktPayload);
      39              : 
      40              :     /**
      41              :      * @brief Initialize the packet filter with a starting limit
      42              :      *
      43              :      * @param maxAllowedQueuedPackets - max number of pending-in-queue not yet processed predicate-matching packets
      44              :      */
      45            1 :     DropIfTooManyQueuedPacketsFilter(size_t maxAllowedQueuedPackets) : mMaxAllowedQueuedPackets(maxAllowedQueuedPackets) {}
      46              : 
      47              :     /**
      48              :      * @brief Set the predicate to use for filtering
      49              :      *
      50              :      * @warning DO NOT modify at runtime while the filter is being called. If you do so, the queue accounting could
      51              :      *          get out of sync, and cause the filtering to fail to properly work.
      52              :      *
      53              :      * @param predicateFunc - Predicate function to apply. If nullptr, no filtering will take place
      54              :      * @param context - Pointer to predicate-specific context that will be provided to predicate at every call. May be nullptr.
      55              :      */
      56            3 :     void SetPredicate(PacketMatchPredicateFunc predicateFunc, void * context)
      57              :     {
      58            3 :         mPredicate = predicateFunc;
      59            3 :         mContext   = context;
      60            3 :     }
      61              : 
      62              :     /**
      63              :      * @brief Set the ceiling for max allowed packets queued up that matched the predicate.
      64              :      *
      65              :      * @note Changing this at runtime while packets are coming only affects future dropping, and
      66              :      *       does not remove packets from the queue if the limit is lowered below the currently-in-queue
      67              :      *       count.
      68              :      *
      69              :      * @param maxAllowedQueuedPackets - number of packets currently pending allowed.
      70              :      */
      71            3 :     void SetMaxQueuedPacketsLimit(size_t maxAllowedQueuedPackets) { mMaxAllowedQueuedPackets.store(maxAllowedQueuedPackets); }
      72              : 
      73              :     /**
      74              :      * @return the total number of packets dropped so far by the filter
      75              :      */
      76           32 :     size_t GetNumDroppedPackets() const { return mNumDroppedPackets.load(); }
      77              : 
      78              :     /**
      79              :      * @brief Reset the counter of dropped packets.
      80              :      */
      81            1 :     void ClearNumDroppedPackets() { mNumDroppedPackets.store(0); }
      82              : 
      83              :     /**
      84              :      * @brief Method called when a packet is dropped due to high watermark getting reached, based on predicate.
      85              :      *
      86              :      * Subclasses may use this to implement additional behavior or diagnostics.
      87              :      *
      88              :      * This is called once for every dropped packet. If there is no filter predicate, this is not called.
      89              :      *
      90              :      * @param endpoint - pointer to endpoint instance (platform-dependent, which is why it's void)
      91              :      * @param pktInfo - info about source/dest of packet
      92              :      * @param pktPayload - payload content of packet
      93              :      */
      94            0 :     virtual void OnDropped(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
      95              :                            const chip::System::PacketBufferHandle & pktPayload)
      96            0 :     {}
      97              : 
      98              :     /**
      99              :      * @brief Method called whenever queue of accumulated packets is now empty, based on predicate.
     100              :      *
     101              :      * Subclasses may use this to implement additional behavior or diagnostics.
     102              :      *
     103              :      * This is possibly called repeatedly in a row, if the queue actually never gets above one.
     104              :      *
     105              :      * This is only called for packets that had matched the filtering rule, where they had
     106              :      * been explicitly allowed in the past. If there is no filter predicate, this is not called.
     107              :      *
     108              :      * @param endpoint - pointer to endpoint instance (platform-dependent, which is why it's void)
     109              :      * @param pktInfo - info about source/dest of packet
     110              :      * @param pktPayload - payload content of packet
     111              :      */
     112            0 :     virtual void OnLastMatchDequeued(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
     113              :                                      const chip::System::PacketBufferHandle & pktPayload)
     114            0 :     {}
     115              : 
     116              :     /**
     117              :      * @brief Implementation of filtering before queueing that applies the predicate.
     118              :      *
     119              :      * See base class for arguments
     120              :      */
     121           31 :     FilterOutcome FilterBeforeEnqueue(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
     122              :                                       const chip::System::PacketBufferHandle & pktPayload) override
     123              :     {
     124              :         // WARNING: This is likely called in a different context than `FilterAfterDequeue`. We use an atomic for the counter.
     125              : 
     126              :         // Non-matching is never accounted, always allowed. Lack of predicate is equivalent to non-matching.
     127           31 :         if ((mPredicate == nullptr) || !mPredicate(mContext, endpoint, pktInfo, pktPayload))
     128              :         {
     129           19 :             return FilterOutcome::kAllowPacket;
     130              :         }
     131              : 
     132           24 :         if (mNumQueuedPackets.load() >= mMaxAllowedQueuedPackets)
     133              :         {
     134            7 :             ++mNumDroppedPackets;
     135            7 :             OnDropped(endpoint, pktInfo, pktPayload);
     136            7 :             return FilterOutcome::kDropPacket;
     137              :         }
     138              : 
     139            5 :         ++mNumQueuedPackets;
     140              : 
     141            5 :         return FilterOutcome::kAllowPacket;
     142              :     }
     143              : 
     144              :     /**
     145              :      * @brief Implementation of filtering after dequeueing that applies the predicate.
     146              :      *
     147              :      * See base class for arguments
     148              :      */
     149           15 :     FilterOutcome FilterAfterDequeue(const void * endpoint, const chip::Inet::IPPacketInfo & pktInfo,
     150              :                                      const chip::System::PacketBufferHandle & pktPayload) override
     151              :     {
     152              :         // WARNING: This is likely called in a different context than `FilterBeforeEnqueue`. We use an atomic for the counter.
     153              :         // NOTE: This is always called from Matter platform event loop
     154              : 
     155              :         // Non-matching is never accounted, always allowed. Lack of predicate is equivalent to non-matching.
     156           15 :         if ((mPredicate == nullptr) || !mPredicate(mContext, endpoint, pktInfo, pktPayload))
     157              :         {
     158           10 :             return FilterOutcome::kAllowPacket;
     159              :         }
     160              : 
     161              :         // If we ever go negative, we have mismatch ingress/egress filter via predicate and
     162              :         // device may eventually starve.
     163            5 :         VerifyOrDie(mNumQueuedPackets != 0);
     164              : 
     165            5 :         --mNumQueuedPackets;
     166            5 :         size_t numQueuedPackets = mNumQueuedPackets.load();
     167            5 :         if (numQueuedPackets == 0)
     168              :         {
     169            1 :             OnLastMatchDequeued(endpoint, pktInfo, pktPayload);
     170              :         }
     171              : 
     172              :         // We always allow the packet and just do accounting, since all dropping is prior to queue entry.
     173            5 :         return FilterOutcome::kAllowPacket;
     174              :     }
     175              : 
     176              : protected:
     177              :     PacketMatchPredicateFunc mPredicate = nullptr;
     178              :     void * mContext                     = nullptr;
     179              :     std::atomic_size_t mNumQueuedPackets{ 0 };
     180              :     std::atomic_size_t mMaxAllowedQueuedPackets{ 0 };
     181              :     std::atomic_size_t mNumDroppedPackets{ 0u };
     182              : };
     183              : 
     184              : } // namespace Inet
     185              : } // namespace chip
        

Generated by: LCOV version 2.0-1