Re: [PATCH nf-next] netfilter: fib: avoid lookup if socket is available

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
> ---
>  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
> 
> 




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux