Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: nft_fib: add reduce support

The fib expression stores to a register, so we can't add empty stub.
Check that the register that is being written is in fact redundant.

In most cases, this is expected to cancel tracking as re-use is
unlikely.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
3c1eb413 611580d2

+51
+3
include/net/netfilter/nft_fib.h
··· 37 37 38 38 void nft_fib_store_result(void *reg, const struct nft_fib *priv, 39 39 const struct net_device *dev); 40 + 41 + bool nft_fib_reduce(struct nft_regs_track *track, 42 + const struct nft_expr *expr); 40 43 #endif
+2
net/ipv4/netfilter/nft_fib_ipv4.c
··· 152 152 .init = nft_fib_init, 153 153 .dump = nft_fib_dump, 154 154 .validate = nft_fib_validate, 155 + .reduce = nft_fib_reduce, 155 156 }; 156 157 157 158 static const struct nft_expr_ops nft_fib4_ops = { ··· 162 161 .init = nft_fib_init, 163 162 .dump = nft_fib_dump, 164 163 .validate = nft_fib_validate, 164 + .reduce = nft_fib_reduce, 165 165 }; 166 166 167 167 static const struct nft_expr_ops *
+2
net/ipv6/netfilter/nft_fib_ipv6.c
··· 211 211 .init = nft_fib_init, 212 212 .dump = nft_fib_dump, 213 213 .validate = nft_fib_validate, 214 + .reduce = nft_fib_reduce, 214 215 }; 215 216 216 217 static const struct nft_expr_ops nft_fib6_ops = { ··· 221 220 .init = nft_fib_init, 222 221 .dump = nft_fib_dump, 223 222 .validate = nft_fib_validate, 223 + .reduce = nft_fib_reduce, 224 224 }; 225 225 226 226 static const struct nft_expr_ops *
+42
net/netfilter/nft_fib.c
··· 156 156 } 157 157 EXPORT_SYMBOL_GPL(nft_fib_store_result); 158 158 159 + bool nft_fib_reduce(struct nft_regs_track *track, 160 + const struct nft_expr *expr) 161 + { 162 + const struct nft_fib *priv = nft_expr_priv(expr); 163 + unsigned int len = NFT_REG32_SIZE; 164 + const struct nft_fib *fib; 165 + 166 + switch (priv->result) { 167 + case NFT_FIB_RESULT_OIF: 168 + break; 169 + case NFT_FIB_RESULT_OIFNAME: 170 + if (priv->flags & NFTA_FIB_F_PRESENT) 171 + len = NFT_REG32_SIZE; 172 + else 173 + len = IFNAMSIZ; 174 + break; 175 + case NFT_FIB_RESULT_ADDRTYPE: 176 + break; 177 + default: 178 + WARN_ON_ONCE(1); 179 + break; 180 + } 181 + 182 + if (!nft_reg_track_cmp(track, expr, priv->dreg)) { 183 + nft_reg_track_update(track, expr, priv->dreg, len); 184 + return false; 185 + } 186 + 187 + fib = nft_expr_priv(track->regs[priv->dreg].selector); 188 + if (priv->result != fib->result || 189 + priv->flags != fib->flags) { 190 + nft_reg_track_update(track, expr, priv->dreg, len); 191 + return false; 192 + } 193 + 194 + if (!track->regs[priv->dreg].bitwise) 195 + return true; 196 + 197 + return false; 198 + } 199 + EXPORT_SYMBOL_GPL(nft_fib_reduce); 200 + 159 201 MODULE_LICENSE("GPL"); 160 202 MODULE_AUTHOR("Florian Westphal <fw@strlen.de>");
+1
net/netfilter/nft_fib_inet.c
··· 49 49 .init = nft_fib_init, 50 50 .dump = nft_fib_dump, 51 51 .validate = nft_fib_validate, 52 + .reduce = nft_fib_reduce, 52 53 }; 53 54 54 55 static struct nft_expr_type nft_fib_inet_type __read_mostly = {
+1
net/netfilter/nft_fib_netdev.c
··· 58 58 .init = nft_fib_init, 59 59 .dump = nft_fib_dump, 60 60 .validate = nft_fib_validate, 61 + .reduce = nft_fib_reduce, 61 62 }; 62 63 63 64 static struct nft_expr_type nft_fib_netdev_type __read_mostly = {