On 2025-07-31 14:55, Vadim Goncharov wrote:
> On Thu, 31 Jul 2025 13:03:22 +0200
> Kajetan Staszkiewicz <veg...@tuxpowered.net> wrote:
> 
>> Hello group,
>>
>> I'm researching loop prevention in pfil. There are cases where packets
>> are reinjected into the network stack and would be handled by the same
>> hooks again, i.e. pf + dummynet where currently pf itself handles loop
>> prevention on its own. My current experiment's approach to making loop
>> prevention a general, non-pf-specific thing is to create a new mtag with
>> pointer to the last hook and update it in pfil.c/pfil_mbuf_common().
>> That works good so far, but it means memory allocation when pfil hooks
>> are involved. I'm unsure what the impact on performance would be.
>> Another approach would be to extend struct mbuf, or probably rather
>> struct m_pkthdr, to contain the aforementioned pointer. But is changing
>> that struct something that can be easily done and approved and merged?
> 
> First, you certainly don't need it in every mbuf - just first in chain with
> struct pkthdr (where mtags also start).

True.

> Second.
> The "last hook ptr" does not look like general solution for all cases and
> occupies 8 bytes. What about idea from network itself - TTL ? It occupies less
> bytes, the main problem is to decide where to decrement (e.g. each netgraph
> hook, etc.)

The loop prevention I'm talking about is not as much about the packet
looping through the network stack, but rather packet looping through
pfil hooks. Consider those 2 scenarios:

1. Dummynet reinjection, this is how it works in the current pf:
a) A packet enters via ip6_input()
b) pfil_mbuf_in() sends it to pf_check6_in() which then sends it to
pf_test()
c) pf sends it to dummynet configured for a delay pipe
d) dummynet consumes the packet, pfil_mbuf_in()'s loop is interrupted
e) later dummynet re-injects the packet using netisr_dispatch()
f) the packet goes through ip6_input() and pfil_mbuf_in() again
g) pf_check6_in()/pf_test() perform their own logic to determine that
the packet has already went through pf_test()
h) the packet continues through pfil_mbuf_in() and finally goes through
ip6_(try)?forward and so on

In this case we could benefit from marking the packet/mbuf that it has
already went through pf_check6_in() in pfil_mbuf_in()'s loop. When the
loop is run again, all pfil hooks before and including pf_check_in6()
can be skipped.

2. af-to Address Family translation, the algorithm below is for the
experimental pf code I've mentioned:
a) A packet enters via ip6_input()
b) pfil_mbuf_in() sends it to pf_check6_in() which then sends it to
pf_test()
c) pf_test() translates the packet from IPv6 to IPv4
d) pf marks the packet as if it has went through pf_check_in() even
though it has really went through pf_check6_in()
e) the translated packet is sent through dummynet, as in the previous
scenario
f) dummynet reinjects the packet using netisr_dispatch()
g) the packet goes through pfil_mbuf_in() and pf_check_in() is skipped

> Third.
> What about redoing mtag allocator so that it reuses m_pktdat[] when M_EXT is
> set? This could optimize performance for many tags, not just yours.

I'm not sure I understand this idea. Storing mtags directly in m_pktdat?

-- 
| pozdrawiam / regards | Powered by Debian and FreeBSD  |
| Kajetan Staszkiewicz |   www: http://tuxpowered.net   |
|                      | matrix: @vegeta:tuxpowered.net |
`----------------------^--------------------------------'

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to