netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Florian Westphal <fw@strlen.de>
Cc: netfilter-devel@vger.kernel.org
Subject: Re: [PATCH nf-next] netfilter: fib: avoid lookup if socket is available
Date: Wed, 12 Mar 2025 20:15:07 +0100	[thread overview]
Message-ID: <Z9HdO_7XgQBbxcg1@calendula> (raw)
In-Reply-To: <20250220130703.2043-1-fw@strlen.de>

On Thu, Feb 20, 2025 at 02:07:01PM +0100, Florian Westphal wrote:
> In case the fib match is used from the input hook we can avoid the fib
> lookup if early demux assigned a socket for us: check that the input
> interface matches sk-cached one.
> 
> Rework the existing 'lo bypass' logic to first check sk, then
> for loopback interface type to elide the fib lookup.
> 
> This speeds up fib matching a little, before:
> 93.08 GBit/s (no rules at all)
> 75.1  GBit/s ("fib saddr . iif oif missing drop" in prerouting)
> 75.62 GBit/s ("fib saddr . iif oif missing drop" in input)
> 
> After:
> 92.48 GBit/s (no rules at all)
> 75.62 GBit/s (fib rule in prerouting)
> 90.37 GBit/s (fib rule in input).
> 
> Numbers for the 'no rules' and 'prerouting' are expected to
> closely match in-between runs, the 3rd/input test case exercises the
> the 'avoid lookup if cached ifindex in sk matches' case.
> 
> Test used iperf3 via veth interface, lo can't be used due to existing
> loopback test.

A few questions below.

> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
>  include/net/netfilter/nft_fib.h   | 21 +++++++++++++++++++++
>  net/ipv4/netfilter/nft_fib_ipv4.c | 11 +++++------
>  net/ipv6/netfilter/nft_fib_ipv6.c | 19 ++++++++++---------
>  3 files changed, 36 insertions(+), 15 deletions(-)
> 
> diff --git a/include/net/netfilter/nft_fib.h b/include/net/netfilter/nft_fib.h
> index 38cae7113de4..6e202ed5e63f 100644
> --- a/include/net/netfilter/nft_fib.h
> +++ b/include/net/netfilter/nft_fib.h
> @@ -18,6 +18,27 @@ nft_fib_is_loopback(const struct sk_buff *skb, const struct net_device *in)
>  	return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
>  }
>  
> +static inline bool nft_fib_can_skip(const struct nft_pktinfo *pkt)
> +{
> +	const struct net_device *indev = nft_in(pkt);
> +	const struct sock *sk;
> +
> +	switch (nft_hook(pkt)) {
> +	case NF_INET_PRE_ROUTING:
> +	case NF_INET_INGRESS:

Not an issue in your patch itself, it seems nft_fib_validate() was
never updated to support NF_INET_INGRESS.

> +	case NF_INET_LOCAL_IN:
> +		break;
> +	default:
> +		return false;
> +	}
> +
> +	sk = pkt->skb->sk;
> +	if (sk && sk_fullsock(sk))
> +	       return sk->sk_rx_dst_ifindex == indev->ifindex;
> +
> +	return nft_fib_is_loopback(pkt->skb, indev);
> +}
> +
>  int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr, bool reset);
>  int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
>  		 const struct nlattr * const tb[]);
> diff --git a/net/ipv4/netfilter/nft_fib_ipv4.c b/net/ipv4/netfilter/nft_fib_ipv4.c
> index 625adbc42037..9082ca17e845 100644
> --- a/net/ipv4/netfilter/nft_fib_ipv4.c
> +++ b/net/ipv4/netfilter/nft_fib_ipv4.c
> @@ -71,6 +71,11 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
>  	const struct net_device *oif;
>  	const struct net_device *found;
>  
> +	if (nft_fib_can_skip(pkt)) {
> +		nft_fib_store_result(dest, priv, nft_in(pkt));
> +		return;
> +	}

Silly question: Does this optimization work for all cases?
NFTA_FIB_F_MARK and NFTA_FIB_F_DADDR.

>  	/*
>  	 * Do not set flowi4_oif, it restricts results (for example, asking
>  	 * for oif 3 will get RTN_UNICAST result even if the daddr exits
> @@ -85,12 +90,6 @@ void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
>  	else
>  		oif = NULL;
>  
> -	if (nft_hook(pkt) == NF_INET_PRE_ROUTING &&
> -	    nft_fib_is_loopback(pkt->skb, nft_in(pkt))) {
> -		nft_fib_store_result(dest, priv, nft_in(pkt));
> -		return;
> -	}
> -
>  	iph = skb_header_pointer(pkt->skb, noff, sizeof(_iph), &_iph);
>  	if (!iph) {
>  		regs->verdict.code = NFT_BREAK;
> diff --git a/net/ipv6/netfilter/nft_fib_ipv6.c b/net/ipv6/netfilter/nft_fib_ipv6.c
> index c9f1634b3838..7fd9d7b21cd4 100644
> --- a/net/ipv6/netfilter/nft_fib_ipv6.c
> +++ b/net/ipv6/netfilter/nft_fib_ipv6.c
> @@ -170,6 +170,11 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
>  	struct rt6_info *rt;
>  	int lookup_flags;
>  
> +	if (nft_fib_can_skip(pkt)) {
> +		nft_fib_store_result(dest, priv, nft_in(pkt));
> +		return;
> +	}
> +
>  	if (priv->flags & NFTA_FIB_F_IIF)
>  		oif = nft_in(pkt);
>  	else if (priv->flags & NFTA_FIB_F_OIF)
> @@ -181,17 +186,13 @@ void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
>  		return;
>  	}
>  
> -	lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
> -
> -	if (nft_hook(pkt) == NF_INET_PRE_ROUTING ||
> -	    nft_hook(pkt) == NF_INET_INGRESS) {
> -		if (nft_fib_is_loopback(pkt->skb, nft_in(pkt)) ||
> -		    nft_fib_v6_skip_icmpv6(pkt->skb, pkt->tprot, iph)) {
> -			nft_fib_store_result(dest, priv, nft_in(pkt));
> -			return;
> -		}
> +	if (nft_fib_v6_skip_icmpv6(pkt->skb, pkt->tprot, iph)) {
> +		nft_fib_store_result(dest, priv, nft_in(pkt));
> +		return;
>  	}
>  
> +	lookup_flags = nft_fib6_flowi_init(&fl6, priv, pkt, oif, iph);
> +
>  	*dest = 0;
>  	rt = (void *)ip6_route_lookup(nft_net(pkt), &fl6, pkt->skb,
>  				      lookup_flags);
> -- 
> 2.45.3
> 
> 

  reply	other threads:[~2025-03-12 19:15 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-20 13:07 [PATCH nf-next] netfilter: fib: avoid lookup if socket is available Florian Westphal
2025-03-12 19:15 ` Pablo Neira Ayuso [this message]
2025-03-12 21:38   ` Florian Westphal
2025-03-12 23:19     ` Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Z9HdO_7XgQBbxcg1@calendula \
    --to=pablo@netfilter.org \
    --cc=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).