From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: kaber@trash.net
Subject: [PATCH 10/10] netfilter: nf_tables: use new transaction infrastructure to handle elements
Date: Fri, 4 Apr 2014 15:48:14 +0200 [thread overview]
Message-ID: <1396619294-26212-11-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1396619294-26212-1-git-send-email-pablo@netfilter.org>
Leave the set content in consistent state if we fail to load the
batch. Use the new generic transaction infrastructure to achieve
this.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
include/net/netfilter/nf_tables.h | 10 ++++
net/netfilter/nf_tables_api.c | 106 ++++++++++++++++++++++++++++++++-----
2 files changed, 102 insertions(+), 14 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 15bf745..b08f2a9 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -446,6 +446,16 @@ struct nft_trans_table {
#define nft_trans_table_enable(trans) \
(((struct nft_trans_table *)trans->data)->enable)
+struct nft_trans_elem {
+ struct nft_set *set;
+ struct nft_set_elem elem;
+};
+
+#define nft_trans_elem_set(trans) \
+ (((struct nft_trans_elem *)trans->data)->set)
+#define nft_trans_elem(trans) \
+ (((struct nft_trans_elem *)trans->data)->elem)
+
static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
{
return (struct nft_expr *)&rule->data[0];
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 8305bda..5235d2c 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2983,8 +2983,26 @@ err:
return err;
}
-static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set,
- const struct nlattr *attr)
+static int nft_trans_elem_add(struct nft_ctx *ctx, int msg_type,
+ struct nft_set *set, struct nft_set_elem *elem,
+ struct list_head *trans_list)
+{
+ struct nft_trans *trans;
+
+ trans = nft_trans_alloc(ctx, msg_type, sizeof(struct nft_trans_elem));
+ if (trans == NULL)
+ return -ENOMEM;
+
+ nft_trans_elem_set(trans) = set;
+ nft_trans_elem(trans) = *elem;
+ list_add_tail(&trans->list, trans_list);
+
+ return 0;
+}
+
+static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
+ const struct nlattr *attr,
+ struct list_head *trans_list)
{
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
struct nft_data_desc d1, d2;
@@ -3061,11 +3079,17 @@ static int nft_add_set_elem(const struct nft_ctx *ctx, struct nft_set *set,
err = set->ops->insert(set, &elem);
if (err < 0)
goto err3;
- set->nelems++;
- nf_tables_setelem_notify(ctx, set, &elem, NFT_MSG_NEWSETELEM, 0);
+ err = nft_trans_elem_add(ctx, NFT_MSG_NEWSETELEM, set, &elem,
+ trans_list);
+ if (err < 0)
+ goto err4;
+
return 0;
+err4:
+ set->ops->get(set, &elem);
+ set->ops->remove(set, &elem);
err3:
if (nla[NFTA_SET_ELEM_DATA] != NULL)
nft_data_uninit(&elem.data, d2.type);
@@ -3084,6 +3108,8 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
struct nft_set *set;
struct nft_ctx ctx;
int rem, err;
+ LIST_HEAD(trans_list);
+ struct nft_trans *trans, *next;
err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true);
if (err < 0)
@@ -3103,15 +3129,27 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb,
return -EBUSY;
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
- err = nft_add_set_elem(&ctx, set, attr);
+ err = nft_add_set_elem(&ctx, set, attr, &trans_list);
if (err < 0)
- return err;
+ goto err1;
}
+ list_splice(&trans_list, &ctx.net->nft.commit_list);
+
return 0;
+
+err1:
+ list_for_each_entry_safe(trans, next, &trans_list, list) {
+ set = nft_trans_elem_set(trans);
+ set->ops->get(set, &nft_trans_elem(trans));
+ set->ops->remove(set, &nft_trans_elem(trans));
+ nft_trans_destroy(trans);
+ }
+ return err;
}
-static int nft_del_setelem(const struct nft_ctx *ctx, struct nft_set *set,
- const struct nlattr *attr)
+static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
+ const struct nlattr *attr,
+ struct list_head *trans_list)
{
struct nlattr *nla[NFTA_SET_ELEM_MAX + 1];
struct nft_data_desc desc;
@@ -3139,10 +3177,10 @@ static int nft_del_setelem(const struct nft_ctx *ctx, struct nft_set *set,
if (err < 0)
goto err2;
- set->ops->remove(set, &elem);
- set->nelems--;
-
- nf_tables_setelem_notify(ctx, set, &elem, NFT_MSG_DELSETELEM, 0);
+ err = nft_trans_elem_add(ctx, NFT_MSG_DELSETELEM, set, &elem,
+ trans_list);
+ if (err < 0)
+ goto err2;
nft_data_uninit(&elem.key, NFT_DATA_VALUE);
if (set->flags & NFT_SET_MAP)
@@ -3162,6 +3200,8 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
struct nft_set *set;
struct nft_ctx ctx;
int rem, err;
+ LIST_HEAD(trans_list);
+ struct nft_trans *trans, *next;
err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false);
if (err < 0)
@@ -3174,11 +3214,19 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
return -EBUSY;
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
- err = nft_del_setelem(&ctx, set, attr);
+ err = nft_del_setelem(&ctx, set, attr, &trans_list);
if (err < 0)
- return err;
+ goto err1;
}
+ list_splice(&trans_list, &ctx.net->nft.commit_list);
+
return 0;
+
+err1:
+ list_for_each_entry_safe(trans, next, &trans_list, list)
+ nft_trans_destroy(trans);
+
+ return err;
}
static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
@@ -3293,6 +3341,7 @@ static int nf_tables_commit(struct sk_buff *skb)
{
struct net *net = sock_net(skb->sk);
struct nft_trans *trans, *next;
+ struct nft_set *set;
/* Bump generation counter, invalidate any dump in progress */
net->nft.genctr++;
@@ -3379,6 +3428,25 @@ static int nf_tables_commit(struct sk_buff *skb)
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
NFT_MSG_DELSET);
break;
+ case NFT_MSG_NEWSETELEM:
+ nft_trans_elem_set(trans)->nelems++;
+ nf_tables_setelem_notify(&trans->ctx,
+ nft_trans_elem_set(trans),
+ &nft_trans_elem(trans),
+ NFT_MSG_NEWSETELEM, 0);
+ nft_trans_destroy(trans);
+ break;
+ case NFT_MSG_DELSETELEM:
+ nft_trans_elem_set(trans)->nelems--;
+ nf_tables_setelem_notify(&trans->ctx,
+ nft_trans_elem_set(trans),
+ &nft_trans_elem(trans),
+ NFT_MSG_DELSETELEM, 0);
+ set = nft_trans_elem_set(trans);
+ set->ops->get(set, &nft_trans_elem(trans));
+ set->ops->remove(set, &nft_trans_elem(trans));
+ nft_trans_destroy(trans);
+ break;
}
}
@@ -3412,6 +3480,7 @@ static int nf_tables_abort(struct sk_buff *skb)
{
struct net *net = sock_net(skb->sk);
struct nft_trans *trans, *next;
+ struct nft_set *set;
list_for_each_entry_safe(trans, next, &net->nft.commit_list, list) {
switch (trans->msg_type) {
@@ -3461,6 +3530,15 @@ static int nf_tables_abort(struct sk_buff *skb)
&trans->ctx.table->sets);
nft_trans_destroy(trans);
break;
+ case NFT_MSG_NEWSETELEM:
+ set = nft_trans_elem_set(trans);
+ set->ops->get(set, &nft_trans_elem(trans));
+ set->ops->remove(set, &nft_trans_elem(trans));
+ nft_trans_destroy(trans);
+ break;
+ case NFT_MSG_DELSETELEM:
+ nft_trans_destroy(trans);
+ break;
}
}
--
1.7.10.4
prev parent reply other threads:[~2014-04-04 13:48 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-04 13:48 [PATCH 00/10] new transaction infrastructure for nf_tables (v3) Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 01/10] netfilter: nf_tables: deconstify table and chain in context structure Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 02/10] netfilter: nf_tables: generalise transaction infrastructure Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 03/10] netfilter: nf_tables: relocate commit and abort routines in the source file Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 04/10] netfilter: nf_tables: add message type to transactions Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 05/10] netfilter: nf_tables: use new transaction infrastructure to handle sets Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 06/10] netfilter: nf_tables: use new transaction infrastructure to handle chain Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 07/10] netfilter: nf_tables: disabling table hooks always succeeds Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 08/10] netfilter: nf_tables: pass context to nf_tables_uptable Pablo Neira Ayuso
2014-04-04 13:48 ` [PATCH 09/10] netfilter: nf_tables: use new transaction infrastructure to handle table Pablo Neira Ayuso
2014-04-04 13:48 ` Pablo Neira Ayuso [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1396619294-26212-11-git-send-email-pablo@netfilter.org \
--to=pablo@netfilter.org \
--cc=kaber@trash.net \
--cc=netfilter-devel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).