mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 07:01:32 +00:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Flush the cleanup xtables worker to make sure destructors have completed, from Florian Westphal. 2) iifgroup is matching erroneously, also from Florian. 3) Add selftest for meta interface matching, from Florian Westphal. 4) Move nf_ct_offload_timeout() to header, from Roi Dayan. 5) Call nf_ct_offload_timeout() from flow_offload_add() to make sure garbage collection does not evict offloaded flow, from Roi Dayan. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ee895a30ef
@ -279,6 +279,18 @@ static inline bool nf_ct_should_gc(const struct nf_conn *ct)
|
||||
!nf_ct_is_dying(ct);
|
||||
}
|
||||
|
||||
#define NF_CT_DAY (86400 * HZ)
|
||||
|
||||
/* Set an arbitrary timeout large enough not to ever expire, this save
|
||||
* us a check for the IPS_OFFLOAD_BIT from the packet path via
|
||||
* nf_ct_is_expired().
|
||||
*/
|
||||
static inline void nf_ct_offload_timeout(struct nf_conn *ct)
|
||||
{
|
||||
if (nf_ct_expires(ct) < NF_CT_DAY / 2)
|
||||
ct->timeout = nfct_time_stamp + NF_CT_DAY;
|
||||
}
|
||||
|
||||
struct kernel_param;
|
||||
|
||||
int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp);
|
||||
|
@ -1507,4 +1507,6 @@ void nft_chain_filter_fini(void);
|
||||
|
||||
void __init nft_chain_route_init(void);
|
||||
void nft_chain_route_fini(void);
|
||||
|
||||
void nf_tables_trans_destroy_flush_work(void);
|
||||
#endif /* _NET_NF_TABLES_H */
|
||||
|
@ -1344,18 +1344,6 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DAY (86400 * HZ)
|
||||
|
||||
/* Set an arbitrary timeout large enough not to ever expire, this save
|
||||
* us a check for the IPS_OFFLOAD_BIT from the packet path via
|
||||
* nf_ct_is_expired().
|
||||
*/
|
||||
static void nf_ct_offload_timeout(struct nf_conn *ct)
|
||||
{
|
||||
if (nf_ct_expires(ct) < DAY / 2)
|
||||
ct->timeout = nfct_time_stamp + DAY;
|
||||
}
|
||||
|
||||
static void gc_worker(struct work_struct *work)
|
||||
{
|
||||
unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);
|
||||
|
@ -243,6 +243,8 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
|
||||
return err;
|
||||
}
|
||||
|
||||
nf_ct_offload_timeout(flow->ct);
|
||||
|
||||
if (nf_flowtable_hw_offload(flow_table)) {
|
||||
__set_bit(NF_FLOW_HW, &flow->flags);
|
||||
nf_flow_offload_add(flow_table, flow);
|
||||
|
@ -7390,6 +7390,12 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
|
||||
}
|
||||
}
|
||||
|
||||
void nf_tables_trans_destroy_flush_work(void)
|
||||
{
|
||||
flush_work(&trans_destroy_work);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_tables_trans_destroy_flush_work);
|
||||
|
||||
static int nf_tables_commit_chain_prepare(struct net *net, struct nft_chain *chain)
|
||||
{
|
||||
struct nft_rule *rule;
|
||||
@ -7572,9 +7578,9 @@ static void nf_tables_commit_release(struct net *net)
|
||||
spin_unlock(&nf_tables_destroy_list_lock);
|
||||
|
||||
nf_tables_module_autoload_cleanup(net);
|
||||
mutex_unlock(&net->nft.commit_mutex);
|
||||
|
||||
schedule_work(&trans_destroy_work);
|
||||
|
||||
mutex_unlock(&net->nft.commit_mutex);
|
||||
}
|
||||
|
||||
static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
|
@ -27,6 +27,8 @@ struct nft_xt_match_priv {
|
||||
void *info;
|
||||
};
|
||||
|
||||
static refcount_t nft_compat_pending_destroy = REFCOUNT_INIT(1);
|
||||
|
||||
static int nft_compat_chain_validate_dependency(const struct nft_ctx *ctx,
|
||||
const char *tablename)
|
||||
{
|
||||
@ -236,6 +238,15 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
|
||||
nft_target_set_tgchk_param(&par, ctx, target, info, &e, proto, inv);
|
||||
|
||||
/* xtables matches or targets can have side effects, e.g.
|
||||
* creation/destruction of /proc files.
|
||||
* The xt ->destroy functions are run asynchronously from
|
||||
* work queue. If we have pending invocations we thus
|
||||
* need to wait for those to finish.
|
||||
*/
|
||||
if (refcount_read(&nft_compat_pending_destroy) > 1)
|
||||
nf_tables_trans_destroy_flush_work();
|
||||
|
||||
ret = xt_check_target(&par, size, proto, inv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -247,6 +258,13 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __nft_mt_tg_destroy(struct module *me, const struct nft_expr *expr)
|
||||
{
|
||||
refcount_dec(&nft_compat_pending_destroy);
|
||||
module_put(me);
|
||||
kfree(expr->ops);
|
||||
}
|
||||
|
||||
static void
|
||||
nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
|
||||
{
|
||||
@ -262,8 +280,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
|
||||
if (par.target->destroy != NULL)
|
||||
par.target->destroy(&par);
|
||||
|
||||
module_put(me);
|
||||
kfree(expr->ops);
|
||||
__nft_mt_tg_destroy(me, expr);
|
||||
}
|
||||
|
||||
static int nft_extension_dump_info(struct sk_buff *skb, int attr,
|
||||
@ -494,8 +511,7 @@ __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
|
||||
if (par.match->destroy != NULL)
|
||||
par.match->destroy(&par);
|
||||
|
||||
module_put(me);
|
||||
kfree(expr->ops);
|
||||
__nft_mt_tg_destroy(me, expr);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -700,6 +716,14 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
|
||||
|
||||
static struct nft_expr_type nft_match_type;
|
||||
|
||||
static void nft_mt_tg_deactivate(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
enum nft_trans_phase phase)
|
||||
{
|
||||
if (phase == NFT_TRANS_COMMIT)
|
||||
refcount_inc(&nft_compat_pending_destroy);
|
||||
}
|
||||
|
||||
static const struct nft_expr_ops *
|
||||
nft_match_select_ops(const struct nft_ctx *ctx,
|
||||
const struct nlattr * const tb[])
|
||||
@ -738,6 +762,7 @@ nft_match_select_ops(const struct nft_ctx *ctx,
|
||||
ops->type = &nft_match_type;
|
||||
ops->eval = nft_match_eval;
|
||||
ops->init = nft_match_init;
|
||||
ops->deactivate = nft_mt_tg_deactivate,
|
||||
ops->destroy = nft_match_destroy;
|
||||
ops->dump = nft_match_dump;
|
||||
ops->validate = nft_match_validate;
|
||||
@ -828,6 +853,7 @@ nft_target_select_ops(const struct nft_ctx *ctx,
|
||||
ops->size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
|
||||
ops->init = nft_target_init;
|
||||
ops->destroy = nft_target_destroy;
|
||||
ops->deactivate = nft_mt_tg_deactivate,
|
||||
ops->dump = nft_target_dump;
|
||||
ops->validate = nft_target_validate;
|
||||
ops->data = target;
|
||||
@ -891,6 +917,8 @@ static void __exit nft_compat_module_exit(void)
|
||||
nfnetlink_subsys_unregister(&nfnl_compat_subsys);
|
||||
nft_unregister_expr(&nft_target_type);
|
||||
nft_unregister_expr(&nft_match_type);
|
||||
|
||||
WARN_ON_ONCE(refcount_read(&nft_compat_pending_destroy) != 1);
|
||||
}
|
||||
|
||||
MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
|
||||
|
@ -253,7 +253,7 @@ static bool nft_meta_get_eval_ifname(enum nft_meta_keys key, u32 *dest,
|
||||
return false;
|
||||
break;
|
||||
case NFT_META_IIFGROUP:
|
||||
if (!nft_meta_store_ifgroup(dest, nft_out(pkt)))
|
||||
if (!nft_meta_store_ifgroup(dest, nft_in(pkt)))
|
||||
return false;
|
||||
break;
|
||||
case NFT_META_OIFGROUP:
|
||||
|
@ -4,7 +4,7 @@
|
||||
TEST_PROGS := nft_trans_stress.sh nft_nat.sh bridge_brouter.sh \
|
||||
conntrack_icmp_related.sh nft_flowtable.sh ipvs.sh \
|
||||
nft_concat_range.sh nft_conntrack_helper.sh \
|
||||
nft_queue.sh
|
||||
nft_queue.sh nft_meta.sh
|
||||
|
||||
LDLIBS = -lmnl
|
||||
TEST_GEN_FILES = nf-queue
|
||||
|
124
tools/testing/selftests/netfilter/nft_meta.sh
Executable file
124
tools/testing/selftests/netfilter/nft_meta.sh
Executable file
@ -0,0 +1,124 @@
|
||||
#!/bin/bash
|
||||
|
||||
# check iif/iifname/oifgroup/iiftype match.
|
||||
|
||||
# Kselftest framework requirement - SKIP code is 4.
|
||||
ksft_skip=4
|
||||
sfx=$(mktemp -u "XXXXXXXX")
|
||||
ns0="ns0-$sfx"
|
||||
|
||||
nft --version > /dev/null 2>&1
|
||||
if [ $? -ne 0 ];then
|
||||
echo "SKIP: Could not run test without nft tool"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
cleanup()
|
||||
{
|
||||
ip netns del "$ns0"
|
||||
}
|
||||
|
||||
ip netns add "$ns0"
|
||||
ip -net "$ns0" link set lo up
|
||||
ip -net "$ns0" addr add 127.0.0.1 dev lo
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
ip netns exec "$ns0" nft -f /dev/stdin <<EOF
|
||||
table inet filter {
|
||||
counter iifcount {}
|
||||
counter iifnamecount {}
|
||||
counter iifgroupcount {}
|
||||
counter iiftypecount {}
|
||||
counter infproto4count {}
|
||||
counter il4protocounter {}
|
||||
counter imarkcounter {}
|
||||
|
||||
counter oifcount {}
|
||||
counter oifnamecount {}
|
||||
counter oifgroupcount {}
|
||||
counter oiftypecount {}
|
||||
counter onfproto4count {}
|
||||
counter ol4protocounter {}
|
||||
counter oskuidcounter {}
|
||||
counter oskgidcounter {}
|
||||
counter omarkcounter {}
|
||||
|
||||
chain input {
|
||||
type filter hook input priority 0; policy accept;
|
||||
|
||||
meta iif lo counter name "iifcount"
|
||||
meta iifname "lo" counter name "iifnamecount"
|
||||
meta iifgroup "default" counter name "iifgroupcount"
|
||||
meta iiftype "loopback" counter name "iiftypecount"
|
||||
meta nfproto ipv4 counter name "infproto4count"
|
||||
meta l4proto icmp counter name "il4protocounter"
|
||||
meta mark 42 counter name "imarkcounter"
|
||||
}
|
||||
|
||||
chain output {
|
||||
type filter hook output priority 0; policy accept;
|
||||
meta oif lo counter name "oifcount" counter
|
||||
meta oifname "lo" counter name "oifnamecount"
|
||||
meta oifgroup "default" counter name "oifgroupcount"
|
||||
meta oiftype "loopback" counter name "oiftypecount"
|
||||
meta nfproto ipv4 counter name "onfproto4count"
|
||||
meta l4proto icmp counter name "ol4protocounter"
|
||||
meta skuid 0 counter name "oskuidcounter"
|
||||
meta skgid 0 counter name "oskgidcounter"
|
||||
meta mark 42 counter name "omarkcounter"
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "SKIP: Could not add test ruleset"
|
||||
exit $ksft_skip
|
||||
fi
|
||||
|
||||
ret=0
|
||||
|
||||
check_one_counter()
|
||||
{
|
||||
local cname="$1"
|
||||
local want="packets $2"
|
||||
local verbose="$3"
|
||||
|
||||
cnt=$(ip netns exec "$ns0" nft list counter inet filter $cname | grep -q "$want")
|
||||
if [ $? -ne 0 ];then
|
||||
echo "FAIL: $cname, want \"$want\", got"
|
||||
ret=1
|
||||
ip netns exec "$ns0" nft list counter inet filter $counter
|
||||
fi
|
||||
}
|
||||
|
||||
check_lo_counters()
|
||||
{
|
||||
local want="$1"
|
||||
local verbose="$2"
|
||||
local counter
|
||||
|
||||
for counter in iifcount iifnamecount iifgroupcount iiftypecount infproto4count \
|
||||
oifcount oifnamecount oifgroupcount oiftypecount onfproto4count \
|
||||
il4protocounter \
|
||||
ol4protocounter \
|
||||
; do
|
||||
check_one_counter "$counter" "$want" "$verbose"
|
||||
done
|
||||
}
|
||||
|
||||
check_lo_counters "0" false
|
||||
ip netns exec "$ns0" ping -q -c 1 127.0.0.1 -m 42 > /dev/null
|
||||
|
||||
check_lo_counters "2" true
|
||||
|
||||
check_one_counter oskuidcounter "1" true
|
||||
check_one_counter oskgidcounter "1" true
|
||||
check_one_counter imarkcounter "1" true
|
||||
check_one_counter omarkcounter "1" true
|
||||
|
||||
if [ $ret -eq 0 ];then
|
||||
echo "OK: nftables meta iif/oif counters at expected values"
|
||||
fi
|
||||
|
||||
exit $ret
|
Loading…
Reference in New Issue
Block a user