]>
Commit | Line | Data |
---|---|---|
1 | #ifndef _NF_FLOW_TABLE_H | |
2 | #define _NF_FLOW_TABLE_H | |
3 | ||
4 | #include <linux/in.h> | |
5 | #include <linux/in6.h> | |
6 | #include <linux/netdevice.h> | |
7 | #include <linux/rhashtable-types.h> | |
8 | #include <linux/rcupdate.h> | |
9 | #include <linux/netfilter.h> | |
10 | #include <linux/netfilter/nf_conntrack_tuple_common.h> | |
11 | #include <net/flow_offload.h> | |
12 | #include <net/dst.h> | |
13 | ||
14 | struct nf_flowtable; | |
15 | struct nf_flow_rule; | |
16 | struct flow_offload; | |
17 | enum flow_offload_tuple_dir; | |
18 | ||
19 | struct nf_flow_key { | |
20 | struct flow_dissector_key_meta meta; | |
21 | struct flow_dissector_key_control control; | |
22 | struct flow_dissector_key_control enc_control; | |
23 | struct flow_dissector_key_basic basic; | |
24 | union { | |
25 | struct flow_dissector_key_ipv4_addrs ipv4; | |
26 | struct flow_dissector_key_ipv6_addrs ipv6; | |
27 | }; | |
28 | struct flow_dissector_key_keyid enc_key_id; | |
29 | union { | |
30 | struct flow_dissector_key_ipv4_addrs enc_ipv4; | |
31 | struct flow_dissector_key_ipv6_addrs enc_ipv6; | |
32 | }; | |
33 | struct flow_dissector_key_tcp tcp; | |
34 | struct flow_dissector_key_ports tp; | |
35 | } __aligned(BITS_PER_LONG / 8); /* Ensure that we can do comparisons as longs. */ | |
36 | ||
37 | struct nf_flow_match { | |
38 | struct flow_dissector dissector; | |
39 | struct nf_flow_key key; | |
40 | struct nf_flow_key mask; | |
41 | }; | |
42 | ||
43 | struct nf_flow_rule { | |
44 | struct nf_flow_match match; | |
45 | struct flow_rule *rule; | |
46 | }; | |
47 | ||
48 | struct nf_flowtable_type { | |
49 | struct list_head list; | |
50 | int family; | |
51 | int (*init)(struct nf_flowtable *ft); | |
52 | int (*setup)(struct nf_flowtable *ft, | |
53 | struct net_device *dev, | |
54 | enum flow_block_command cmd); | |
55 | int (*action)(struct net *net, | |
56 | const struct flow_offload *flow, | |
57 | enum flow_offload_tuple_dir dir, | |
58 | struct nf_flow_rule *flow_rule); | |
59 | void (*free)(struct nf_flowtable *ft); | |
60 | nf_hookfn *hook; | |
61 | struct module *owner; | |
62 | }; | |
63 | ||
64 | enum nf_flowtable_flags { | |
65 | NF_FLOWTABLE_HW_OFFLOAD = 0x1, /* NFT_FLOWTABLE_HW_OFFLOAD */ | |
66 | NF_FLOWTABLE_COUNTER = 0x2, /* NFT_FLOWTABLE_COUNTER */ | |
67 | }; | |
68 | ||
69 | struct nf_flowtable { | |
70 | struct list_head list; | |
71 | struct rhashtable rhashtable; | |
72 | int priority; | |
73 | const struct nf_flowtable_type *type; | |
74 | struct delayed_work gc_work; | |
75 | unsigned int flags; | |
76 | struct flow_block flow_block; | |
77 | struct rw_semaphore flow_block_lock; /* Guards flow_block */ | |
78 | possible_net_t net; | |
79 | }; | |
80 | ||
81 | static inline bool nf_flowtable_hw_offload(struct nf_flowtable *flowtable) | |
82 | { | |
83 | return flowtable->flags & NF_FLOWTABLE_HW_OFFLOAD; | |
84 | } | |
85 | ||
86 | enum flow_offload_tuple_dir { | |
87 | FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL, | |
88 | FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY, | |
89 | }; | |
90 | #define FLOW_OFFLOAD_DIR_MAX IP_CT_DIR_MAX | |
91 | ||
92 | enum flow_offload_xmit_type { | |
93 | FLOW_OFFLOAD_XMIT_NEIGH = 0, | |
94 | FLOW_OFFLOAD_XMIT_XFRM, | |
95 | FLOW_OFFLOAD_XMIT_DIRECT, | |
96 | }; | |
97 | ||
98 | #define NF_FLOW_TABLE_ENCAP_MAX 2 | |
99 | ||
100 | struct flow_offload_tuple { | |
101 | union { | |
102 | struct in_addr src_v4; | |
103 | struct in6_addr src_v6; | |
104 | }; | |
105 | union { | |
106 | struct in_addr dst_v4; | |
107 | struct in6_addr dst_v6; | |
108 | }; | |
109 | struct { | |
110 | __be16 src_port; | |
111 | __be16 dst_port; | |
112 | }; | |
113 | ||
114 | int iifidx; | |
115 | ||
116 | u8 l3proto; | |
117 | u8 l4proto; | |
118 | struct { | |
119 | u16 id; | |
120 | __be16 proto; | |
121 | } encap[NF_FLOW_TABLE_ENCAP_MAX]; | |
122 | ||
123 | /* All members above are keys for lookups, see flow_offload_hash(). */ | |
124 | struct { } __hash; | |
125 | ||
126 | u8 dir:4, | |
127 | xmit_type:2, | |
128 | encap_num:2; | |
129 | u16 mtu; | |
130 | union { | |
131 | struct dst_entry *dst_cache; | |
132 | struct { | |
133 | u32 ifidx; | |
134 | u8 h_source[ETH_ALEN]; | |
135 | u8 h_dest[ETH_ALEN]; | |
136 | } out; | |
137 | }; | |
138 | }; | |
139 | ||
140 | struct flow_offload_tuple_rhash { | |
141 | struct rhash_head node; | |
142 | struct flow_offload_tuple tuple; | |
143 | }; | |
144 | ||
145 | enum nf_flow_flags { | |
146 | NF_FLOW_SNAT, | |
147 | NF_FLOW_DNAT, | |
148 | NF_FLOW_TEARDOWN, | |
149 | NF_FLOW_HW, | |
150 | NF_FLOW_HW_DYING, | |
151 | NF_FLOW_HW_DEAD, | |
152 | NF_FLOW_HW_REFRESH, | |
153 | NF_FLOW_HW_PENDING, | |
154 | }; | |
155 | ||
156 | enum flow_offload_type { | |
157 | NF_FLOW_OFFLOAD_UNSPEC = 0, | |
158 | NF_FLOW_OFFLOAD_ROUTE, | |
159 | }; | |
160 | ||
161 | struct flow_offload { | |
162 | struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX]; | |
163 | struct nf_conn *ct; | |
164 | unsigned long flags; | |
165 | u16 type; | |
166 | u32 timeout; | |
167 | struct rcu_head rcu_head; | |
168 | }; | |
169 | ||
170 | #define NF_FLOW_TIMEOUT (30 * HZ) | |
171 | #define nf_flowtable_time_stamp (u32)jiffies | |
172 | ||
173 | static inline __s32 nf_flow_timeout_delta(unsigned int timeout) | |
174 | { | |
175 | return (__s32)(timeout - nf_flowtable_time_stamp); | |
176 | } | |
177 | ||
178 | struct nf_flow_route { | |
179 | struct { | |
180 | struct dst_entry *dst; | |
181 | struct { | |
182 | u32 ifindex; | |
183 | struct { | |
184 | u16 id; | |
185 | __be16 proto; | |
186 | } encap[NF_FLOW_TABLE_ENCAP_MAX]; | |
187 | u8 num_encaps; | |
188 | } in; | |
189 | struct { | |
190 | u32 ifindex; | |
191 | u8 h_source[ETH_ALEN]; | |
192 | u8 h_dest[ETH_ALEN]; | |
193 | } out; | |
194 | enum flow_offload_xmit_type xmit_type; | |
195 | } tuple[FLOW_OFFLOAD_DIR_MAX]; | |
196 | }; | |
197 | ||
198 | struct flow_offload *flow_offload_alloc(struct nf_conn *ct); | |
199 | void flow_offload_free(struct flow_offload *flow); | |
200 | ||
201 | static inline int | |
202 | nf_flow_table_offload_add_cb(struct nf_flowtable *flow_table, | |
203 | flow_setup_cb_t *cb, void *cb_priv) | |
204 | { | |
205 | struct flow_block *block = &flow_table->flow_block; | |
206 | struct flow_block_cb *block_cb; | |
207 | int err = 0; | |
208 | ||
209 | down_write(&flow_table->flow_block_lock); | |
210 | block_cb = flow_block_cb_lookup(block, cb, cb_priv); | |
211 | if (block_cb) { | |
212 | err = -EEXIST; | |
213 | goto unlock; | |
214 | } | |
215 | ||
216 | block_cb = flow_block_cb_alloc(cb, cb_priv, cb_priv, NULL); | |
217 | if (IS_ERR(block_cb)) { | |
218 | err = PTR_ERR(block_cb); | |
219 | goto unlock; | |
220 | } | |
221 | ||
222 | list_add_tail(&block_cb->list, &block->cb_list); | |
223 | ||
224 | unlock: | |
225 | up_write(&flow_table->flow_block_lock); | |
226 | return err; | |
227 | } | |
228 | ||
229 | static inline void | |
230 | nf_flow_table_offload_del_cb(struct nf_flowtable *flow_table, | |
231 | flow_setup_cb_t *cb, void *cb_priv) | |
232 | { | |
233 | struct flow_block *block = &flow_table->flow_block; | |
234 | struct flow_block_cb *block_cb; | |
235 | ||
236 | down_write(&flow_table->flow_block_lock); | |
237 | block_cb = flow_block_cb_lookup(block, cb, cb_priv); | |
238 | if (block_cb) { | |
239 | list_del(&block_cb->list); | |
240 | flow_block_cb_free(block_cb); | |
241 | } else { | |
242 | WARN_ON(true); | |
243 | } | |
244 | up_write(&flow_table->flow_block_lock); | |
245 | } | |
246 | ||
247 | int flow_offload_route_init(struct flow_offload *flow, | |
248 | const struct nf_flow_route *route); | |
249 | ||
250 | int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow); | |
251 | void flow_offload_refresh(struct nf_flowtable *flow_table, | |
252 | struct flow_offload *flow); | |
253 | ||
254 | struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table, | |
255 | struct flow_offload_tuple *tuple); | |
256 | void nf_flow_table_gc_cleanup(struct nf_flowtable *flowtable, | |
257 | struct net_device *dev); | |
258 | void nf_flow_table_cleanup(struct net_device *dev); | |
259 | ||
260 | int nf_flow_table_init(struct nf_flowtable *flow_table); | |
261 | void nf_flow_table_free(struct nf_flowtable *flow_table); | |
262 | ||
263 | void flow_offload_teardown(struct flow_offload *flow); | |
264 | ||
265 | void nf_flow_snat_port(const struct flow_offload *flow, | |
266 | struct sk_buff *skb, unsigned int thoff, | |
267 | u8 protocol, enum flow_offload_tuple_dir dir); | |
268 | void nf_flow_dnat_port(const struct flow_offload *flow, | |
269 | struct sk_buff *skb, unsigned int thoff, | |
270 | u8 protocol, enum flow_offload_tuple_dir dir); | |
271 | ||
272 | struct flow_ports { | |
273 | __be16 source, dest; | |
274 | }; | |
275 | ||
276 | unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, | |
277 | const struct nf_hook_state *state); | |
278 | unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, | |
279 | const struct nf_hook_state *state); | |
280 | ||
281 | #define MODULE_ALIAS_NF_FLOWTABLE(family) \ | |
282 | MODULE_ALIAS("nf-flowtable-" __stringify(family)) | |
283 | ||
284 | void nf_flow_offload_add(struct nf_flowtable *flowtable, | |
285 | struct flow_offload *flow); | |
286 | void nf_flow_offload_del(struct nf_flowtable *flowtable, | |
287 | struct flow_offload *flow); | |
288 | void nf_flow_offload_stats(struct nf_flowtable *flowtable, | |
289 | struct flow_offload *flow); | |
290 | ||
291 | void nf_flow_table_offload_flush(struct nf_flowtable *flowtable); | |
292 | int nf_flow_table_offload_setup(struct nf_flowtable *flowtable, | |
293 | struct net_device *dev, | |
294 | enum flow_block_command cmd); | |
295 | int nf_flow_rule_route_ipv4(struct net *net, const struct flow_offload *flow, | |
296 | enum flow_offload_tuple_dir dir, | |
297 | struct nf_flow_rule *flow_rule); | |
298 | int nf_flow_rule_route_ipv6(struct net *net, const struct flow_offload *flow, | |
299 | enum flow_offload_tuple_dir dir, | |
300 | struct nf_flow_rule *flow_rule); | |
301 | ||
302 | int nf_flow_table_offload_init(void); | |
303 | void nf_flow_table_offload_exit(void); | |
304 | ||
305 | #endif /* _NF_FLOW_TABLE_H */ |