* [PATCH 0/2] nf_tables: atomic transactional updates (v2)
@ 2013-03-28 20:22 pablo
2013-03-28 20:22 ` [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates pablo
2013-03-28 20:22 ` [PATCH 2/2] netfilter: nf_tables: set NLM_F_DUMP_INTR if dump is invalid pablo
0 siblings, 2 replies; 4+ messages in thread
From: pablo @ 2013-03-28 20:22 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, tomasz.bursztyka
From: Pablo Neira Ayuso <pablo@netfilter.org>
Hi,
This patchset comes after this patch:
http://patchwork.ozlabs.org/patch/224196/
and results from discussion with Tomasz and Patrick, the summary
of changes for the first patch are:
* Get rid of the extra struct list_head per rule as discussed with
Patrick McHardy. With this patch, a temporary object is allocated
to store the rule update information.
* A new begin operation to explicitly enter the transaction mode,
and remove the COMMIT flag per rule, as suggested by Tomasz.
* The commit and abort loops have been also simplified from ideas
extracted after discusion with Tomasz Bursztyka. Basically,
there is a single list per net namespace that contains pending
rule updates.
* The transaction list is now owned by the netlink socket portid that
adds the first rule that waits to be committed. If another process
wants to perform some rule-set update, it hits -EBUSY.
* Pending updates, if not committed, are destroyed when the process
explicit aborts or finishes its execution.
The second patch uses NLM_F_DUMP_INTR if the dump in interrupted by
an update.
Comments welcome.
Pablo Neira Ayuso (2):
netfilter: nf_tables: rework atomic transaction updates
netfilter: nf_tables: set NLM_F_DUMP_INTR if dump is invalid
include/net/netfilter/nf_tables.h | 21 ++-
include/net/netns/nftables.h | 4 +-
include/uapi/linux/netfilter/nf_tables.h | 7 +-
net/netfilter/nf_tables_api.c | 242 +++++++++++++++++++-----------
4 files changed, 179 insertions(+), 95 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates
2013-03-28 20:22 [PATCH 0/2] nf_tables: atomic transactional updates (v2) pablo
@ 2013-03-28 20:22 ` pablo
2013-04-02 9:03 ` Tomasz Bursztyka
2013-03-28 20:22 ` [PATCH 2/2] netfilter: nf_tables: set NLM_F_DUMP_INTR if dump is invalid pablo
1 sibling, 1 reply; 4+ messages in thread
From: pablo @ 2013-03-28 20:22 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, tomasz.bursztyka
From: Pablo Neira Ayuso <pablo@netfilter.org>
This patch partially reworks the commit operation (added in
1577831), main changes are:
* Get rid of the extra struct list_head per rule as discussed with
Patrick McHardy. With this patch, a temporary object is allocated
to store the rule update information.
* A new begin operation to explicitly enter the transaction mode,
and remove the COMMIT flag per rule, as suggested by Tomasz.
* The commit and abort loops have been also simplified from ideas
extracted after discusion with Tomasz Bursztyka. Basically,
there is a single list per net namespace that contains pending
rule updates.
* The transaction list is now owned by the netlink socket portid
that adds the first rule that waits to be committed. If another
process wants to perform some rule-set update, it hits -EBUSY.
* Pending updates, if not committed, are destroyed when the process
explicit aborts or finishes its execution.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_tables.h | 21 ++-
include/net/netns/nftables.h | 2 +
include/uapi/linux/netfilter/nf_tables.h | 7 +-
net/netfilter/nf_tables_api.c | 232 ++++++++++++++++++++----------
4 files changed, 174 insertions(+), 88 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 3782777..4baa84f 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -321,7 +321,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
* struct nft_rule - nf_tables rule
*
* @list: used internally
- * @dirty_list: this rule needs an update after new generation
* @rcu_head: used internally for rcu
* @handle: rule handle
* @genmask: generation mask
@@ -330,7 +329,6 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
*/
struct nft_rule {
struct list_head list;
- struct list_head dirty_list;
struct rcu_head rcu_head;
u64 handle:46,
genmask:2,
@@ -339,6 +337,23 @@ struct nft_rule {
__attribute__((aligned(__alignof__(struct nft_expr))));
};
+/**
+ * struct nft_rule_trans - nf_tables rule update in transaction
+ *
+ * @list: used internally
+ * @rule: rule that needs to be updated
+ * @chain: chain that this rule belongs to
+ * @table: table for which this chain applies
+ * @net: the net namespace that this rule updates belongs to
+ */
+struct nft_rule_trans {
+ struct list_head list;
+ struct nft_rule *rule;
+ const struct nft_chain *chain;
+ const struct nft_table *table;
+ struct net *net;
+};
+
static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
{
return (struct nft_expr *)&rule->data[0];
@@ -372,7 +387,6 @@ enum nft_chain_flags {
* struct nft_chain - nf_tables chain
*
* @rules: list of rules in the chain
- * @dirty_rules: rules that need an update after next generation
* @list: used internally
* @rcu_head: used internally
* @net: net namespace that this chain belongs to
@@ -385,7 +399,6 @@ enum nft_chain_flags {
*/
struct nft_chain {
struct list_head rules;
- struct list_head dirty_rules;
struct list_head list;
struct rcu_head rcu_head;
struct net *net;
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index cc79f82..14d9f14 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -10,6 +10,8 @@ struct netns_nftables {
struct nft_af_info *ipv4;
struct nft_af_info *ipv6;
struct nft_af_info *bridge;
+ u32 transaction_owner;
+ struct list_head transaction_rules;
u8 gencursor;
u8 genctr;
};
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 76b215f..1461a42 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -37,6 +37,7 @@ enum nf_tables_msg_types {
NFT_MSG_NEWSETELEM,
NFT_MSG_GETSETELEM,
NFT_MSG_DELSETELEM,
+ NFT_MSG_BEGIN,
NFT_MSG_COMMIT,
NFT_MSG_ABORT,
NFT_MSG_MAX,
@@ -88,18 +89,12 @@ enum nft_chain_attributes {
};
#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
-enum {
- NFT_RULE_F_COMMIT = (1 << 0),
- NFT_RULE_F_MASK = NFT_RULE_F_COMMIT,
-};
-
enum nft_rule_attributes {
NFTA_RULE_UNSPEC,
NFTA_RULE_TABLE,
NFTA_RULE_CHAIN,
NFTA_RULE_HANDLE,
NFTA_RULE_EXPRESSIONS,
- NFTA_RULE_FLAGS,
NFTA_RULE_COMPAT,
__NFTA_RULE_MAX
};
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 9ed4db1..16d1c7dc 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -970,7 +970,6 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
}
INIT_LIST_HEAD(&chain->rules);
- INIT_LIST_HEAD(&chain->dirty_rules);
chain->handle = nf_tables_alloc_handle(table);
chain->net = net;
chain->table = table;
@@ -1265,7 +1264,6 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
.len = NFT_CHAIN_MAXNAMELEN - 1 },
[NFTA_RULE_HANDLE] = { .type = NLA_U64 },
[NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED },
- [NFTA_RULE_FLAGS] = { .type = NLA_U32 },
[NFTA_RULE_COMPAT] = { .type = NLA_NESTED },
};
@@ -1520,6 +1518,23 @@ static void nf_tables_rule_destroy(struct nft_rule *rule)
static struct nft_expr_info *info;
+static int nf_tables_trans_add(struct nft_rule *rule, const struct nft_ctx *ctx)
+{
+ struct nft_rule_trans *rupd;
+
+ rupd = kmalloc(sizeof(struct nft_rule_trans), GFP_KERNEL);
+ if (rupd == NULL)
+ return -ENOMEM;
+
+ rupd->chain = ctx->chain;
+ rupd->table = ctx->table;
+ rupd->rule = rule;
+ rupd->net = ctx->net;
+ list_add(&rupd->list, &ctx->net->nft.transaction_rules);
+
+ return 0;
+}
+
static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const nla[])
@@ -1536,9 +1551,13 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
unsigned int size, i, n;
int err, rem;
bool create;
- u32 flags = 0;
u64 handle;
+ /* A transaction is happening, tell this process that it should retry */
+ if (net->nft.transaction_owner &&
+ net->nft.transaction_owner != nlh->nlmsg_pid)
+ return -EBUSY;
+
create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
@@ -1595,14 +1614,8 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
if (rule == NULL)
goto err1;
- if (nla[NFTA_RULE_FLAGS]) {
- flags = ntohl(nla_get_be32(nla[NFTA_RULE_FLAGS]));
- if (flags & ~NFT_RULE_F_MASK)
- return -EINVAL;
-
- if (flags & NFT_RULE_F_COMMIT)
- nft_rule_activate_next(net, rule);
- }
+ if (net->nft.transaction_owner)
+ nft_rule_activate_next(net, rule);
rule->handle = handle;
rule->dlen = size;
@@ -1617,7 +1630,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
}
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
- if (flags & NFT_RULE_F_COMMIT) {
+ if (net->nft.transaction_owner) {
nft_rule_disactivate_next(net, old_rule);
list_add_tail_rcu(&rule->list, &chain->rules);
} else {
@@ -1629,9 +1642,13 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb,
else
list_add_rcu(&rule->list, &chain->rules);
- if (flags & NFT_RULE_F_COMMIT)
- list_add(&rule->dirty_list, &chain->dirty_rules);
- else {
+ if (net->nft.transaction_owner) {
+ err = nf_tables_trans_add(rule, &ctx);
+ if (err < 0) {
+ list_del_rcu(&rule->list);
+ goto err2;
+ }
+ } else {
nf_tables_rule_notify(skb, nlh, table, chain, rule,
NFT_MSG_NEWRULE,
nlh->nlmsg_flags & (NLM_F_APPEND | NLM_F_REPLACE),
@@ -1649,14 +1666,19 @@ err1:
return err;
}
-static void
+static int
nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule, u32 flags)
{
- if (flags & NFT_RULE_F_COMMIT) {
- struct nft_chain *chain = (struct nft_chain *)ctx->chain;
+ int ret = 0;
- nft_rule_disactivate_next(ctx->net, rule);
- list_add(&rule->dirty_list, &chain->dirty_rules);
+ if (ctx->net->nft.transaction_owner) {
+ /* Will be deleted already in the next generation */
+ if (!nft_rule_is_active_next(ctx->net, rule))
+ return -EBUSY;
+
+ ret = nf_tables_trans_add(rule, ctx);
+ if (ret >= 0)
+ nft_rule_disactivate_next(ctx->net, rule);
} else {
list_del_rcu(&rule->list);
nf_tables_rule_notify(ctx->skb, ctx->nlh, ctx->table,
@@ -1664,6 +1686,7 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule, u32 flags)
0, ctx->afi->family);
nf_tables_rule_destroy(rule);
}
+ return ret;
}
static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
@@ -1676,10 +1699,15 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
const struct nft_table *table;
struct nft_chain *chain;
struct nft_rule *rule, *tmp;
- int family = nfmsg->nfgen_family;
+ int family = nfmsg->nfgen_family, err;
struct nft_ctx ctx;
u32 flags = 0;
+ /* A transaction is happening, tell this process that it should retry */
+ if (net->nft.transaction_owner &&
+ net->nft.transaction_owner != nlh->nlmsg_pid)
+ return -EBUSY;
+
afi = nf_tables_afinfo_lookup(net, family, false);
if (IS_ERR(afi))
return PTR_ERR(afi);
@@ -1694,19 +1722,14 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
nft_ctx_init(&ctx, skb, nlh, afi, table, chain, nla);
- if (nla[NFTA_RULE_FLAGS]) {
- flags = ntohl(nla_get_be32(nla[NFTA_RULE_FLAGS]));
-
- if (flags & ~NFT_RULE_F_MASK)
- return -EINVAL;
- }
-
if (nla[NFTA_RULE_HANDLE]) {
rule = nf_tables_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
if (IS_ERR(rule))
return PTR_ERR(rule);
- nf_tables_delrule_one(&ctx, rule, flags);
+ err = nf_tables_delrule_one(&ctx, rule, flags);
+ if (err < 0)
+ return err;
} else {
/* Remove all rules in this chain */
list_for_each_entry_safe(rule, tmp, &chain->rules, list)
@@ -1716,6 +1739,21 @@ static int nf_tables_delrule(struct sock *nlsk, struct sk_buff *skb,
return 0;
}
+static int nf_tables_begin(struct sock *nlsk, struct sk_buff *skb,
+ const struct nlmsghdr *nlh,
+ const struct nlattr * const nla[])
+{
+ struct net *net = sock_net(skb->sk);
+
+ /* Check if another process is performing a transaction */
+ if (!net->nft.transaction_owner)
+ net->nft.transaction_owner = nlh->nlmsg_pid;
+ else if (net->nft.transaction_owner != nlh->nlmsg_pid)
+ return -EBUSY;
+
+ return 0;
+}
+
static int nf_tables_commit(struct sock *nlsk, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const nla[])
@@ -1723,12 +1761,14 @@ static int nf_tables_commit(struct sock *nlsk, struct sk_buff *skb,
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
const struct nft_af_info *afi;
struct net *net = sock_net(skb->sk);
- struct nft_table *table;
- struct nft_chain *chain;
- struct nft_rule *rule, *tmp;
+ struct nft_rule_trans *rupd, *tmp;
int family = nfmsg->nfgen_family;
bool create;
+ /* Are you the owner of this transaction? */
+ if (nlh->nlmsg_pid != net->nft.transaction_owner)
+ return -EBUSY;
+
create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
@@ -1746,40 +1786,60 @@ static int nf_tables_commit(struct sock *nlsk, struct sk_buff *skb,
*/
synchronize_rcu();
- list_for_each_entry(table, &afi->tables, list) {
- list_for_each_entry(chain, &table->chains, list) {
- list_for_each_entry_safe(rule, tmp, &chain->dirty_rules, dirty_list) {
- /* Delete this rule from the dirty list */
- list_del(&rule->dirty_list);
-
- /* This rule was inactive in the past and just
- * became active. Clear the next bit of the
- * genmask since its meaning has changed, now
- * it is the future.
- */
- if (nft_rule_is_active(net, rule)) {
- nft_rule_clear(net, rule);
- nf_tables_rule_notify(skb, nlh, table,
- chain, rule,
- NFT_MSG_NEWRULE,
- 0,
- nfmsg->nfgen_family);
- continue;
- }
+ list_for_each_entry_safe(rupd, tmp, &net->nft.transaction_rules, list) {
+ /* Delete this rule from the transaction list */
+ list_del(&rupd->list);
- /* This rule is in the past, get rid of it */
- list_del_rcu(&rule->list);
- nf_tables_rule_notify(skb, nlh, table, chain,
- rule, NFT_MSG_DELRULE, 0,
- family);
- nf_tables_rule_destroy(rule);
- }
+ /* This rule was inactive in the past and just became active.
+ * Clear the next bit of the genmask since its meaning has
+ * changed, now it is the future.
+ */
+ if (nft_rule_is_active(net, rupd->rule)) {
+ nft_rule_clear(net, rupd->rule);
+ nf_tables_rule_notify(skb, nlh, rupd->table,
+ rupd->chain, rupd->rule,
+ NFT_MSG_NEWRULE, 0,
+ nfmsg->nfgen_family);
+ kfree(rupd);
+ continue;
}
+
+ /* This rule is in the past, get rid of it */
+ list_del_rcu(&rupd->rule->list);
+ nf_tables_rule_notify(skb, nlh, rupd->table, rupd->chain,
+ rupd->rule, NFT_MSG_DELRULE, 0, family);
+ nf_tables_rule_destroy(rupd->rule);
+ kfree(rupd);
}
+ /* Clear owner of this transaction list */
+ net->nft.transaction_owner = 0;
return 0;
}
+static void nf_tables_abort_all(struct net *net)
+{
+ struct nft_rule_trans *rupd, *tmp;
+
+ list_for_each_entry_safe(rupd, tmp, &net->nft.transaction_rules, list) {
+ /* Delete all rules from the transaction list */
+ list_del(&rupd->list);
+
+ if (!nft_rule_is_active_next(rupd->net, rupd->rule)) {
+ nft_rule_clear(rupd->net, rupd->rule);
+ kfree(rupd);
+ return;
+ }
+
+ /* This rule is inactive, get rid of it */
+ list_del_rcu(&rupd->rule->list);
+ nf_tables_rule_destroy(rupd->rule);
+ kfree(rupd);
+ }
+ /* Clear the owner of the transaction list */
+ net->nft.transaction_owner = 0;
+}
+
static int nf_tables_abort(struct sock *nlsk, struct sk_buff *skb,
const struct nlmsghdr *nlh,
const struct nlattr * const nla[])
@@ -1787,37 +1847,44 @@ static int nf_tables_abort(struct sock *nlsk, struct sk_buff *skb,
const struct nfgenmsg *nfmsg = nlmsg_data(nlh);
const struct nft_af_info *afi;
struct net *net = sock_net(skb->sk);
- struct nft_table *table;
- struct nft_chain *chain;
- struct nft_rule *rule, *tmp;
bool create;
+ /* Are you the owner of this transaction? */
+ if (nlh->nlmsg_pid != net->nft.transaction_owner)
+ return -EBUSY;
+
create = nlh->nlmsg_flags & NLM_F_CREATE ? true : false;
afi = nf_tables_afinfo_lookup(net, nfmsg->nfgen_family, create);
if (IS_ERR(afi))
return PTR_ERR(afi);
- list_for_each_entry(table, &afi->tables, list) {
- list_for_each_entry(chain, &table->chains, list) {
- list_for_each_entry_safe(rule, tmp, &chain->dirty_rules, dirty_list) {
- /* Delete all rules from the dirty list */
- list_del(&rule->dirty_list);
-
- if (!nft_rule_is_active_next(net, rule)) {
- nft_rule_clear(net, rule);
- continue;
- }
+ nf_tables_abort_all(net);
- /* This rule is inactive, get rid of it */
- list_del_rcu(&rule->list);
- nf_tables_rule_destroy(rule);
- }
- }
- }
return 0;
}
+static int
+nf_tables_rcv_nl_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct netlink_notify *n = ptr;
+
+ if (event != NETLINK_URELEASE || n->protocol != NETLINK_NETFILTER)
+ return NOTIFY_DONE;
+
+ if (n->portid != n->net->nft.transaction_owner)
+ return NOTIFY_DONE;
+
+ nf_tables_abort_all(n->net);
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block nf_tables_notifier = {
+ .notifier_call = nf_tables_rcv_nl_event,
+};
+
/*
* Sets
*/
@@ -2777,6 +2844,11 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
.attr_count = NFTA_SET_ELEM_LIST_MAX,
.policy = nft_set_elem_list_policy,
},
+ [NFT_MSG_BEGIN] = {
+ .call = nf_tables_begin,
+ .attr_count = NFTA_TABLE_MAX,
+ .policy = nft_rule_policy,
+ },
[NFT_MSG_COMMIT] = {
.call = nf_tables_commit,
.attr_count = NFTA_TABLE_MAX,
@@ -3165,6 +3237,7 @@ EXPORT_SYMBOL_GPL(nft_data_dump);
static int nf_tables_init_net(struct net *net)
{
INIT_LIST_HEAD(&net->nft.af_info);
+ INIT_LIST_HEAD(&net->nft.transaction_rules);
return 0;
}
@@ -3191,6 +3264,8 @@ static int __init nf_tables_module_init(void)
if (err < 0)
goto err3;
+ netlink_register_notifier(&nf_tables_notifier);
+
pr_info("nf_tables: (c) 2007-2009 Patrick McHardy <kaber@trash.net>\n");
return register_pernet_subsys(&nf_tables_net_ops);
err3:
@@ -3204,6 +3279,7 @@ err1:
static void __exit nf_tables_module_exit(void)
{
unregister_pernet_subsys(&nf_tables_net_ops);
+ netlink_unregister_notifier(&nf_tables_notifier);
nfnetlink_subsys_unregister(&nf_tables_subsys);
nf_tables_core_module_exit();
kfree(info);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] netfilter: nf_tables: set NLM_F_DUMP_INTR if dump is invalid
2013-03-28 20:22 [PATCH 0/2] nf_tables: atomic transactional updates (v2) pablo
2013-03-28 20:22 ` [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates pablo
@ 2013-03-28 20:22 ` pablo
1 sibling, 0 replies; 4+ messages in thread
From: pablo @ 2013-03-28 20:22 UTC (permalink / raw)
To: netfilter-devel; +Cc: kaber, tomasz.bursztyka
From: Pablo Neira Ayuso <pablo@netfilter.org>
Use nl_dump_check_consistent to set NLM_F_DUMP_INTR to tell user-space
that it has to retry in this dump. Just like in rtnetlink.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netns/nftables.h | 2 +-
net/netfilter/nf_tables_api.c | 11 +++++------
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index 14d9f14..dfeb8b9 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -12,8 +12,8 @@ struct netns_nftables {
struct nft_af_info *bridge;
u32 transaction_owner;
struct list_head transaction_rules;
+ unsigned int base_seq;
u8 gencursor;
- u8 genctr;
};
#endif
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 16d1c7dc..bb3bb74 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1400,8 +1400,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
unsigned int idx = 0, s_idx = cb->args[0];
struct net *net = sock_net(skb->sk);
int family = nfmsg->nfgen_family;
- u8 genctr = ACCESS_ONCE(net->nft.genctr);
- u8 gencursor = ACCESS_ONCE(net->nft.gencursor);
+
+ cb->seq = ACCESS_ONCE(net->nft.base_seq);
list_for_each_entry(afi, &net->nft.af_info, list) {
if (family != NFPROTO_UNSPEC && family != afi->family)
@@ -1430,9 +1430,7 @@ cont:
}
}
done:
- /* Invalidate this dump, a transition to the new generation happened */
- if (gencursor != net->nft.gencursor || genctr != net->nft.genctr)
- return -EBUSY;
+ nl_dump_check_consistent(cb, nlmsg_hdr(skb));
cb->args[0] = idx;
return skb->len;
@@ -1776,7 +1774,7 @@ static int nf_tables_commit(struct sock *nlsk, struct sk_buff *skb,
return PTR_ERR(afi);
/* Bump generation counter, invalidate any dump in progress */
- net->nft.genctr++;
+ while (++net->nft.base_seq == 0);
/* A new generation has just started */
net->nft.gencursor = gencursor_next(net);
@@ -3238,6 +3236,7 @@ static int nf_tables_init_net(struct net *net)
{
INIT_LIST_HEAD(&net->nft.af_info);
INIT_LIST_HEAD(&net->nft.transaction_rules);
+ net->nft.base_seq = 1;
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates
2013-03-28 20:22 ` [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates pablo
@ 2013-04-02 9:03 ` Tomasz Bursztyka
0 siblings, 0 replies; 4+ messages in thread
From: Tomasz Bursztyka @ 2013-04-02 9:03 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, kaber
Hi Pablo,
> * A new begin operation to explicitly enter the transaction mode,
> and remove the COMMIT flag per rule, as suggested by Tomasz.
Could you split your patch to 2?
- one which removes this flag and add *BEGIN* message stuff
- and a the later one which propose the rest
> +++ b/include/uapi/linux/netfilter/nf_tables.h
> @@ -37,6 +37,7 @@ enum nf_tables_msg_types {
> NFT_MSG_NEWSETELEM,
> NFT_MSG_GETSETELEM,
> NFT_MSG_DELSETELEM,
> + NFT_MSG_BEGIN,
> NFT_MSG_COMMIT,
> NFT_MSG_ABORT,
> NFT_MSG_MAX,
Still, I think it's awkward to propose a fully-explicit message name for
all but for the transaction ones.
NFT_MSG_BEGINTRANSACT or something like that, would be better.
Br,
Tomasz
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-04-02 9:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-28 20:22 [PATCH 0/2] nf_tables: atomic transactional updates (v2) pablo
2013-03-28 20:22 ` [PATCH 1/2] netfilter: nf_tables: rework atomic transaction updates pablo
2013-04-02 9:03 ` Tomasz Bursztyka
2013-03-28 20:22 ` [PATCH 2/2] netfilter: nf_tables: set NLM_F_DUMP_INTR if dump is invalid pablo
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.