1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/kernel.h>
3 #include <linux/slab.h>
4 #include <net/flow_offload.h>
6 struct flow_rule *flow_rule_alloc(unsigned int num_actions)
8 struct flow_rule *rule;
10 rule = kzalloc(struct_size(rule, action.entries, num_actions),
15 rule->action.num_entries = num_actions;
19 EXPORT_SYMBOL(flow_rule_alloc);
21 #define FLOW_DISSECTOR_MATCH(__rule, __type, __out) \
22 const struct flow_match *__m = &(__rule)->match; \
23 struct flow_dissector *__d = (__m)->dissector; \
25 (__out)->key = skb_flow_dissector_target(__d, __type, (__m)->key); \
26 (__out)->mask = skb_flow_dissector_target(__d, __type, (__m)->mask); \
28 void flow_rule_match_meta(const struct flow_rule *rule,
29 struct flow_match_meta *out)
31 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_META, out);
33 EXPORT_SYMBOL(flow_rule_match_meta);
35 void flow_rule_match_basic(const struct flow_rule *rule,
36 struct flow_match_basic *out)
38 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_BASIC, out);
40 EXPORT_SYMBOL(flow_rule_match_basic);
42 void flow_rule_match_control(const struct flow_rule *rule,
43 struct flow_match_control *out)
45 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_CONTROL, out);
47 EXPORT_SYMBOL(flow_rule_match_control);
49 void flow_rule_match_eth_addrs(const struct flow_rule *rule,
50 struct flow_match_eth_addrs *out)
52 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS, out);
54 EXPORT_SYMBOL(flow_rule_match_eth_addrs);
56 void flow_rule_match_vlan(const struct flow_rule *rule,
57 struct flow_match_vlan *out)
59 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_VLAN, out);
61 EXPORT_SYMBOL(flow_rule_match_vlan);
63 void flow_rule_match_cvlan(const struct flow_rule *rule,
64 struct flow_match_vlan *out)
66 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_CVLAN, out);
68 EXPORT_SYMBOL(flow_rule_match_cvlan);
70 void flow_rule_match_ipv4_addrs(const struct flow_rule *rule,
71 struct flow_match_ipv4_addrs *out)
73 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS, out);
75 EXPORT_SYMBOL(flow_rule_match_ipv4_addrs);
77 void flow_rule_match_ipv6_addrs(const struct flow_rule *rule,
78 struct flow_match_ipv6_addrs *out)
80 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS, out);
82 EXPORT_SYMBOL(flow_rule_match_ipv6_addrs);
84 void flow_rule_match_ip(const struct flow_rule *rule,
85 struct flow_match_ip *out)
87 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_IP, out);
89 EXPORT_SYMBOL(flow_rule_match_ip);
91 void flow_rule_match_ports(const struct flow_rule *rule,
92 struct flow_match_ports *out)
94 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_PORTS, out);
96 EXPORT_SYMBOL(flow_rule_match_ports);
98 void flow_rule_match_tcp(const struct flow_rule *rule,
99 struct flow_match_tcp *out)
101 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_TCP, out);
103 EXPORT_SYMBOL(flow_rule_match_tcp);
105 void flow_rule_match_icmp(const struct flow_rule *rule,
106 struct flow_match_icmp *out)
108 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ICMP, out);
110 EXPORT_SYMBOL(flow_rule_match_icmp);
112 void flow_rule_match_mpls(const struct flow_rule *rule,
113 struct flow_match_mpls *out)
115 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_MPLS, out);
117 EXPORT_SYMBOL(flow_rule_match_mpls);
119 void flow_rule_match_enc_control(const struct flow_rule *rule,
120 struct flow_match_control *out)
122 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_CONTROL, out);
124 EXPORT_SYMBOL(flow_rule_match_enc_control);
126 void flow_rule_match_enc_ipv4_addrs(const struct flow_rule *rule,
127 struct flow_match_ipv4_addrs *out)
129 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV4_ADDRS, out);
131 EXPORT_SYMBOL(flow_rule_match_enc_ipv4_addrs);
133 void flow_rule_match_enc_ipv6_addrs(const struct flow_rule *rule,
134 struct flow_match_ipv6_addrs *out)
136 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS, out);
138 EXPORT_SYMBOL(flow_rule_match_enc_ipv6_addrs);
140 void flow_rule_match_enc_ip(const struct flow_rule *rule,
141 struct flow_match_ip *out)
143 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_IP, out);
145 EXPORT_SYMBOL(flow_rule_match_enc_ip);
147 void flow_rule_match_enc_ports(const struct flow_rule *rule,
148 struct flow_match_ports *out)
150 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_PORTS, out);
152 EXPORT_SYMBOL(flow_rule_match_enc_ports);
154 void flow_rule_match_enc_keyid(const struct flow_rule *rule,
155 struct flow_match_enc_keyid *out)
157 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_KEYID, out);
159 EXPORT_SYMBOL(flow_rule_match_enc_keyid);
161 void flow_rule_match_enc_opts(const struct flow_rule *rule,
162 struct flow_match_enc_opts *out)
164 FLOW_DISSECTOR_MATCH(rule, FLOW_DISSECTOR_KEY_ENC_OPTS, out);
166 EXPORT_SYMBOL(flow_rule_match_enc_opts);
168 struct flow_block_cb *flow_block_cb_alloc(flow_setup_cb_t *cb,
169 void *cb_ident, void *cb_priv,
170 void (*release)(void *cb_priv))
172 struct flow_block_cb *block_cb;
174 block_cb = kzalloc(sizeof(*block_cb), GFP_KERNEL);
176 return ERR_PTR(-ENOMEM);
179 block_cb->cb_ident = cb_ident;
180 block_cb->cb_priv = cb_priv;
181 block_cb->release = release;
185 EXPORT_SYMBOL(flow_block_cb_alloc);
187 void flow_block_cb_free(struct flow_block_cb *block_cb)
189 if (block_cb->release)
190 block_cb->release(block_cb->cb_priv);
194 EXPORT_SYMBOL(flow_block_cb_free);
196 struct flow_block_cb *flow_block_cb_lookup(struct flow_block *block,
197 flow_setup_cb_t *cb, void *cb_ident)
199 struct flow_block_cb *block_cb;
201 list_for_each_entry(block_cb, &block->cb_list, list) {
202 if (block_cb->cb == cb &&
203 block_cb->cb_ident == cb_ident)
209 EXPORT_SYMBOL(flow_block_cb_lookup);
211 void *flow_block_cb_priv(struct flow_block_cb *block_cb)
213 return block_cb->cb_priv;
215 EXPORT_SYMBOL(flow_block_cb_priv);
217 void flow_block_cb_incref(struct flow_block_cb *block_cb)
221 EXPORT_SYMBOL(flow_block_cb_incref);
223 unsigned int flow_block_cb_decref(struct flow_block_cb *block_cb)
225 return --block_cb->refcnt;
227 EXPORT_SYMBOL(flow_block_cb_decref);
229 bool flow_block_cb_is_busy(flow_setup_cb_t *cb, void *cb_ident,
230 struct list_head *driver_block_list)
232 struct flow_block_cb *block_cb;
234 list_for_each_entry(block_cb, driver_block_list, driver_list) {
235 if (block_cb->cb == cb &&
236 block_cb->cb_ident == cb_ident)
242 EXPORT_SYMBOL(flow_block_cb_is_busy);
244 int flow_block_cb_setup_simple(struct flow_block_offload *f,
245 struct list_head *driver_block_list,
247 void *cb_ident, void *cb_priv,
250 struct flow_block_cb *block_cb;
253 f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
256 f->driver_block_list = driver_block_list;
258 switch (f->command) {
259 case FLOW_BLOCK_BIND:
260 if (flow_block_cb_is_busy(cb, cb_ident, driver_block_list))
263 block_cb = flow_block_cb_alloc(cb, cb_ident, cb_priv, NULL);
264 if (IS_ERR(block_cb))
265 return PTR_ERR(block_cb);
267 flow_block_cb_add(block_cb, f);
268 list_add_tail(&block_cb->driver_list, driver_block_list);
270 case FLOW_BLOCK_UNBIND:
271 block_cb = flow_block_cb_lookup(f->block, cb, cb_ident);
275 flow_block_cb_remove(block_cb, f);
276 list_del(&block_cb->driver_list);
282 EXPORT_SYMBOL(flow_block_cb_setup_simple);