On 7/25/2019 2:54 PM, Pablo Neira Ayuso wrote: > On Wed, Jul 24, 2019 at 05:32:09PM +0800, wenxu@xxxxxxxxx wrote: >> From: wenxu <wenxu@xxxxxxxxx> >> >> In the action store tun_id to reg in a host endian. But the >> nft_cmp action get the user data in a net endian which lead >> match failed. >> >> nft --debug=netlink add rule netdev firewall aclin ip daddr 10.0.0.7 >> tunnel key 1000 fwd to eth0 >> >> [ meta load protocol => reg 1 ] >> [ cmp eq reg 1 0x00000008 ] >> [ payload load 4b @ network header + 16 => reg 1 ] >> [ cmp eq reg 1 0x0700000a ] >> [ tunnel load id => reg 1 ] >> [ cmp eq reg 1 0xe8030000 ] >> [ immediate reg 1 0x0000000f ] >> [ fwd sreg_dev 1 ] >> >> Fixes: aaecfdb5c5dd ("netfilter: nf_tables: match on tunnel metadata") >> Signed-off-by: wenxu <wenxu@xxxxxxxxx> >> --- >> net/netfilter/nft_tunnel.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/net/netfilter/nft_tunnel.c b/net/netfilter/nft_tunnel.c >> index 3d4c2ae..c9f4585 100644 >> --- a/net/netfilter/nft_tunnel.c >> +++ b/net/netfilter/nft_tunnel.c >> @@ -53,7 +53,7 @@ static void nft_tunnel_get_eval(const struct nft_expr *expr, >> !(tun_info->mode & IP_TUNNEL_INFO_TX)) || >> (priv->mode == NFT_TUNNEL_MODE_TX && >> (tun_info->mode & IP_TUNNEL_INFO_TX))) >> - *dest = ntohl(tunnel_id_to_key32(tun_info->key.tun_id)); >> + *dest = tunnel_id_to_key32(tun_info->key.tun_id); > Something is wrong here: > > __be32 tunnel_id_to_key32(...) > > This function returns __be32 and you are now storing this in big > endian, while description refers to "host endian". The vlaue should store as the network endian in the reg(which is same as nft_paylaod). "tunnel key 1000" convert to [cmp eq reg 1 0xe8030000] which in network-endian But original it is store as host endian so fix it. Maybe the description so bad and confuse you