aboutsummaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 05:05:33 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-10-14 12:01:01 -0400
commit0628b123c96d126e617beb3b4fd63b874d0e4f17 (patch)
tree78726af17d726e96d2bf9b28bf6a6d16222c2049 /include/net
parent5e94846686d027a4c8ecc5d9d52b18036d3e8f7a (diff)
netfilter: nfnetlink: add batch support and use it from nf_tables
This patch adds a batch support to nfnetlink. Basically, it adds two new control messages: * NFNL_MSG_BATCH_BEGIN, that indicates the beginning of a batch, the nfgenmsg->res_id indicates the nfnetlink subsystem ID. * NFNL_MSG_BATCH_END, that results in the invocation of the ss->commit callback function. If not specified or an error ocurred in the batch, the ss->abort function is invoked instead. The end message represents the commit operation in nftables, the lack of end message results in an abort. This patch also adds the .call_batch function that is only called from the batch receival path. This patch adds atomic rule updates and dumps based on bitmask generations. This allows to atomically commit a set of rule-set updates incrementally without altering the internal state of existing nf_tables expressions/matches/targets. The idea consists of using a generation cursor of 1 bit and a bitmask of 2 bits per rule. Assuming the gencursor is 0, then the genmask (expressed as a bitmask) can be interpreted as: 00 active in the present, will be active in the next generation. 01 inactive in the present, will be active in the next generation. 10 active in the present, will be deleted in the next generation. ^ gencursor Once you invoke the transition to the next generation, the global gencursor is updated: 00 active in the present, will be active in the next generation. 01 active in the present, needs to zero its future, it becomes 00. 10 inactive in the present, delete now. ^ gencursor If a dump is in progress and nf_tables enters a new generation, the dump will stop and return -EBUSY to let userspace know that it has to retry again. In order to invalidate dumps, a global genctr counter is increased everytime nf_tables enters a new generation. This new operation can be used from the user-space utility that controls the firewall, eg. nft -f restore The rule updates contained in `file' will be applied atomically. cat file ----- add filter INPUT ip saddr 1.1.1.1 counter accept #1 del filter INPUT ip daddr 2.2.2.2 counter drop #2 -EOF- Note that the rule 1 will be inactive until the transition to the next generation, the rule 2 will be evicted in the next generation. There is a penalty during the rule update due to the branch misprediction in the packet matching framework. But that should be quickly resolved once the iteration over the commit list that contain rules that require updates is finished. Event notification happens once the rule-set update has been committed. So we skip notifications is case the rule-set update is aborted, which can happen in case that the rule-set is tested to apply correctly. This patch squashed the following patches from Pablo: * nf_tables: atomic rule updates and dumps * nf_tables: get rid of per rule list_head for commits * nf_tables: use per netns commit list * nfnetlink: add batch support and use it from nf_tables * nf_tables: all rule updates are transactional * nf_tables: attach replacement rule after stale one * nf_tables: do not allow deletion/replacement of stale rules * nf_tables: remove unused NFTA_RULE_FLAGS Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'include/net')
-rw-r--r--include/net/netfilter/nf_tables.h25
-rw-r--r--include/net/netns/nftables.h3
2 files changed, 27 insertions, 1 deletions
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index d3272e943aac..975ad3c573c7 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -323,18 +323,39 @@ static inline void *nft_expr_priv(const struct nft_expr *expr)
323 * @list: used internally 323 * @list: used internally
324 * @rcu_head: used internally for rcu 324 * @rcu_head: used internally for rcu
325 * @handle: rule handle 325 * @handle: rule handle
326 * @genmask: generation mask
326 * @dlen: length of expression data 327 * @dlen: length of expression data
327 * @data: expression data 328 * @data: expression data
328 */ 329 */
329struct nft_rule { 330struct nft_rule {
330 struct list_head list; 331 struct list_head list;
331 struct rcu_head rcu_head; 332 struct rcu_head rcu_head;
332 u64 handle:48, 333 u64 handle:46,
334 genmask:2,
333 dlen:16; 335 dlen:16;
334 unsigned char data[] 336 unsigned char data[]
335 __attribute__((aligned(__alignof__(struct nft_expr)))); 337 __attribute__((aligned(__alignof__(struct nft_expr))));
336}; 338};
337 339
340/**
341 * struct nft_rule_trans - nf_tables rule update in transaction
342 *
343 * @list: used internally
344 * @rule: rule that needs to be updated
345 * @chain: chain that this rule belongs to
346 * @table: table for which this chain applies
347 * @nlh: netlink header of the message that contain this update
348 * @family: family expressesed as AF_*
349 */
350struct nft_rule_trans {
351 struct list_head list;
352 struct nft_rule *rule;
353 const struct nft_chain *chain;
354 const struct nft_table *table;
355 const struct nlmsghdr *nlh;
356 u8 family;
357};
358
338static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule) 359static inline struct nft_expr *nft_expr_first(const struct nft_rule *rule)
339{ 360{
340 return (struct nft_expr *)&rule->data[0]; 361 return (struct nft_expr *)&rule->data[0];
@@ -370,6 +391,7 @@ enum nft_chain_flags {
370 * @rules: list of rules in the chain 391 * @rules: list of rules in the chain
371 * @list: used internally 392 * @list: used internally
372 * @rcu_head: used internally 393 * @rcu_head: used internally
394 * @net: net namespace that this chain belongs to
373 * @handle: chain handle 395 * @handle: chain handle
374 * @flags: bitmask of enum nft_chain_flags 396 * @flags: bitmask of enum nft_chain_flags
375 * @use: number of jump references to this chain 397 * @use: number of jump references to this chain
@@ -380,6 +402,7 @@ struct nft_chain {
380 struct list_head rules; 402 struct list_head rules;
381 struct list_head list; 403 struct list_head list;
382 struct rcu_head rcu_head; 404 struct rcu_head rcu_head;
405 struct net *net;
383 u64 handle; 406 u64 handle;
384 u8 flags; 407 u8 flags;
385 u16 use; 408 u16 use;
diff --git a/include/net/netns/nftables.h b/include/net/netns/nftables.h
index a98b1c5d9913..08a4248a12b5 100644
--- a/include/net/netns/nftables.h
+++ b/include/net/netns/nftables.h
@@ -7,9 +7,12 @@ struct nft_af_info;
7 7
8struct netns_nftables { 8struct netns_nftables {
9 struct list_head af_info; 9 struct list_head af_info;
10 struct list_head commit_list;
10 struct nft_af_info *ipv4; 11 struct nft_af_info *ipv4;
11 struct nft_af_info *ipv6; 12 struct nft_af_info *ipv6;
12 struct nft_af_info *bridge; 13 struct nft_af_info *bridge;
14 u8 gencursor;
15 u8 genctr;
13}; 16};
14 17
15#endif 18#endif