Skip to content

Commit 20a6934

Browse files
kaberummakynes
authored andcommitted
netfilter: nf_tables: add netlink set API
This patch adds the new netlink API for maintaining nf_tables sets independently of the ruleset. The API supports the following operations: - creation of sets - deletion of sets - querying of specific sets - dumping of all sets - addition of set elements - removal of set elements - dumping of all set elements Sets are identified by name, each table defines an individual namespace. The name of a set may be allocated automatically, this is mostly useful in combination with the NFT_SET_ANONYMOUS flag, which destroys a set automatically once the last reference has been released. Sets can be marked constant, meaning they're not allowed to change while linked to a rule. This allows to perform lockless operation for set types that would otherwise require locking. Additionally, if the implementation supports it, sets can (as before) be used as maps, associating a data value with each key (or range), by specifying the NFT_SET_MAP flag and can be used for interval queries by specifying the NFT_SET_INTERVAL flag. Set elements are added and removed incrementally. All element operations support batching, reducing netlink message and set lookup overhead. The old "set" and "hash" expressions are replaced by a generic "lookup" expression, which binds to the specified set. Userspace is not aware of the actual set implementation used by the kernel anymore, all configuration options are generic. Currently the implementation selection logic is largely missing and the kernel will simply use the first registered implementation supporting the requested operation. Eventually, the plan is to have userspace supply a description of the data characteristics and select the implementation based on expected performance and memory use. This patch includes the new 'lookup' expression to look up for element matching in the set. This patch includes kernel-doc descriptions for this set API and it also includes the following fixes. From Patrick McHardy: * netfilter: nf_tables: fix set element data type in dumps * netfilter: nf_tables: fix indentation of struct nft_set_elem comments * netfilter: nf_tables: fix oops in nft_validate_data_load() * netfilter: nf_tables: fix oops while listing sets of built-in tables * netfilter: nf_tables: destroy anonymous sets immediately if binding fails * netfilter: nf_tables: propagate context to set iter callback * netfilter: nf_tables: add loop detection From Pablo Neira Ayuso: * netfilter: nf_tables: allow to dump all existing sets * netfilter: nf_tables: fix wrong type for flags variable in newelem Signed-off-by: Patrick McHardy <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 9651851 commit 20a6934

File tree

11 files changed

+1854
-677
lines changed

11 files changed

+1854
-677
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 142 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <linux/netfilter/nf_tables.h>
77
#include <net/netlink.h>
88

9+
#define NFT_JUMP_STACK_SIZE 16
10+
911
struct nft_pktinfo {
1012
struct sk_buff *skb;
1113
const struct net_device *in;
@@ -48,23 +50,22 @@ static inline void nft_data_debug(const struct nft_data *data)
4850
}
4951

5052
/**
51-
* struct nft_ctx - nf_tables rule context
53+
* struct nft_ctx - nf_tables rule/set context
5254
*
55+
* @skb: netlink skb
56+
* @nlh: netlink message header
5357
* @afi: address family info
5458
* @table: the table the chain is contained in
5559
* @chain: the chain the rule is contained in
5660
*/
5761
struct nft_ctx {
62+
const struct sk_buff *skb;
63+
const struct nlmsghdr *nlh;
5864
const struct nft_af_info *afi;
5965
const struct nft_table *table;
6066
const struct nft_chain *chain;
6167
};
6268

63-
enum nft_data_types {
64-
NFT_DATA_VALUE,
65-
NFT_DATA_VERDICT,
66-
};
67-
6869
struct nft_data_desc {
6970
enum nft_data_types type;
7071
unsigned int len;
@@ -83,13 +84,144 @@ static inline enum nft_data_types nft_dreg_to_type(enum nft_registers reg)
8384
return reg == NFT_REG_VERDICT ? NFT_DATA_VERDICT : NFT_DATA_VALUE;
8485
}
8586

87+
static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
88+
{
89+
return type == NFT_DATA_VERDICT ? NFT_REG_VERDICT : NFT_REG_1;
90+
}
91+
8692
extern int nft_validate_input_register(enum nft_registers reg);
8793
extern int nft_validate_output_register(enum nft_registers reg);
8894
extern int nft_validate_data_load(const struct nft_ctx *ctx,
8995
enum nft_registers reg,
9096
const struct nft_data *data,
9197
enum nft_data_types type);
9298

99+
/**
100+
* struct nft_set_elem - generic representation of set elements
101+
*
102+
* @cookie: implementation specific element cookie
103+
* @key: element key
104+
* @data: element data (maps only)
105+
* @flags: element flags (end of interval)
106+
*
107+
* The cookie can be used to store a handle to the element for subsequent
108+
* removal.
109+
*/
110+
struct nft_set_elem {
111+
void *cookie;
112+
struct nft_data key;
113+
struct nft_data data;
114+
u32 flags;
115+
};
116+
117+
struct nft_set;
118+
struct nft_set_iter {
119+
unsigned int count;
120+
unsigned int skip;
121+
int err;
122+
int (*fn)(const struct nft_ctx *ctx,
123+
const struct nft_set *set,
124+
const struct nft_set_iter *iter,
125+
const struct nft_set_elem *elem);
126+
};
127+
128+
/**
129+
* struct nft_set_ops - nf_tables set operations
130+
*
131+
* @lookup: look up an element within the set
132+
* @insert: insert new element into set
133+
* @remove: remove element from set
134+
* @walk: iterate over all set elemeennts
135+
* @privsize: function to return size of set private data
136+
* @init: initialize private data of new set instance
137+
* @destroy: destroy private data of set instance
138+
* @list: nf_tables_set_ops list node
139+
* @owner: module reference
140+
* @features: features supported by the implementation
141+
*/
142+
struct nft_set_ops {
143+
bool (*lookup)(const struct nft_set *set,
144+
const struct nft_data *key,
145+
struct nft_data *data);
146+
int (*get)(const struct nft_set *set,
147+
struct nft_set_elem *elem);
148+
int (*insert)(const struct nft_set *set,
149+
const struct nft_set_elem *elem);
150+
void (*remove)(const struct nft_set *set,
151+
const struct nft_set_elem *elem);
152+
void (*walk)(const struct nft_ctx *ctx,
153+
const struct nft_set *set,
154+
struct nft_set_iter *iter);
155+
156+
unsigned int (*privsize)(const struct nlattr * const nla[]);
157+
int (*init)(const struct nft_set *set,
158+
const struct nlattr * const nla[]);
159+
void (*destroy)(const struct nft_set *set);
160+
161+
struct list_head list;
162+
struct module *owner;
163+
u32 features;
164+
};
165+
166+
extern int nft_register_set(struct nft_set_ops *ops);
167+
extern void nft_unregister_set(struct nft_set_ops *ops);
168+
169+
/**
170+
* struct nft_set - nf_tables set instance
171+
*
172+
* @list: table set list node
173+
* @bindings: list of set bindings
174+
* @name: name of the set
175+
* @ktype: key type (numeric type defined by userspace, not used in the kernel)
176+
* @dtype: data type (verdict or numeric type defined by userspace)
177+
* @ops: set ops
178+
* @flags: set flags
179+
* @klen: key length
180+
* @dlen: data length
181+
* @data: private set data
182+
*/
183+
struct nft_set {
184+
struct list_head list;
185+
struct list_head bindings;
186+
char name[IFNAMSIZ];
187+
u32 ktype;
188+
u32 dtype;
189+
/* runtime data below here */
190+
const struct nft_set_ops *ops ____cacheline_aligned;
191+
u16 flags;
192+
u8 klen;
193+
u8 dlen;
194+
unsigned char data[]
195+
__attribute__((aligned(__alignof__(u64))));
196+
};
197+
198+
static inline void *nft_set_priv(const struct nft_set *set)
199+
{
200+
return (void *)set->data;
201+
}
202+
203+
extern struct nft_set *nf_tables_set_lookup(const struct nft_table *table,
204+
const struct nlattr *nla);
205+
206+
/**
207+
* struct nft_set_binding - nf_tables set binding
208+
*
209+
* @list: set bindings list node
210+
* @chain: chain containing the rule bound to the set
211+
*
212+
* A set binding contains all information necessary for validation
213+
* of new elements added to a bound set.
214+
*/
215+
struct nft_set_binding {
216+
struct list_head list;
217+
const struct nft_chain *chain;
218+
};
219+
220+
extern int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
221+
struct nft_set_binding *binding);
222+
extern void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
223+
struct nft_set_binding *binding);
224+
93225
/**
94226
* struct nft_expr_ops - nf_tables expression operations
95227
*
@@ -115,7 +247,7 @@ struct nft_expr_ops {
115247
void (*destroy)(const struct nft_expr *expr);
116248
int (*dump)(struct sk_buff *skb,
117249
const struct nft_expr *expr);
118-
250+
const struct nft_data * (*get_verdict)(const struct nft_expr *expr);
119251
struct list_head list;
120252
const char *name;
121253
struct module *owner;
@@ -298,4 +430,7 @@ extern void nft_unregister_expr(struct nft_expr_ops *);
298430
#define MODULE_ALIAS_NFT_EXPR(name) \
299431
MODULE_ALIAS("nft-expr-" name)
300432

433+
#define MODULE_ALIAS_NFT_SET() \
434+
MODULE_ALIAS("nft-set")
435+
301436
#endif /* _NET_NF_TABLES_H */

0 commit comments

Comments
 (0)