Lines Matching +full:key +full:- +full:release
1 // SPDX-License-Identifier: GPL-2.0-only
33 struct efx_nic *efx = zone->efx; in efx_tc_ct_zone_free()
35 netif_err(efx, drv, efx->net_dev, in efx_tc_ct_zone_free()
37 zone->zone); in efx_tc_ct_zone_free()
39 nf_flow_table_offload_del_cb(zone->nf_ft, efx_tc_flow_block, zone); in efx_tc_ct_zone_free()
48 netif_err(efx, drv, efx->net_dev, in efx_tc_ct_free()
50 conn->cookie); in efx_tc_ct_free()
52 /* We can release the counter, but we can't remove the CT itself in efx_tc_ct_free()
55 efx_tc_flower_release_counter(efx, conn->cnt); in efx_tc_ct_free()
63 rc = rhashtable_init(&efx->tc->ct_zone_ht, &efx_tc_ct_zone_ht_params); in efx_tc_init_conntrack()
66 rc = rhashtable_init(&efx->tc->ct_ht, &efx_tc_ct_ht_params); in efx_tc_init_conntrack()
71 rhashtable_destroy(&efx->tc->ct_zone_ht); in efx_tc_init_conntrack()
81 rhashtable_destroy(&efx->tc->ct_ht); in efx_tc_destroy_conntrack()
82 rhashtable_destroy(&efx->tc->ct_zone_ht); in efx_tc_destroy_conntrack()
87 rhashtable_free_and_destroy(&efx->tc->ct_zone_ht, efx_tc_ct_zone_free, NULL); in efx_tc_fini_conntrack()
88 rhashtable_free_and_destroy(&efx->tc->ct_ht, efx_tc_ct_free, efx); in efx_tc_fini_conntrack()
96 struct flow_dissector *dissector = fr->match.dissector; in efx_tc_ct_parse_match()
104 if (IS_ALL_ONES(fm.mask->addr_type)) in efx_tc_ct_parse_match()
105 switch (fm.key->addr_type) { in efx_tc_ct_parse_match()
118 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
120 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
123 if (dissector->used_keys & in efx_tc_ct_parse_match()
131 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
133 dissector->used_keys); in efx_tc_ct_parse_match()
134 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
141 if (!IS_ALL_ONES(fm.mask->n_proto)) { in efx_tc_ct_parse_match()
142 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
143 "Conntrack eth_proto is not exact-match; mask %04x\n", in efx_tc_ct_parse_match()
144 ntohs(fm.mask->n_proto)); in efx_tc_ct_parse_match()
145 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
147 conn->eth_proto = fm.key->n_proto; in efx_tc_ct_parse_match()
148 if (conn->eth_proto != (ipv == 4 ? htons(ETH_P_IP) in efx_tc_ct_parse_match()
150 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
152 ipv, ntohs(conn->eth_proto)); in efx_tc_ct_parse_match()
153 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
155 if (!IS_ALL_ONES(fm.mask->ip_proto)) { in efx_tc_ct_parse_match()
156 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
157 "Conntrack ip_proto is not exact-match; mask %02x\n", in efx_tc_ct_parse_match()
158 fm.mask->ip_proto); in efx_tc_ct_parse_match()
159 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
161 conn->ip_proto = fm.key->ip_proto; in efx_tc_ct_parse_match()
162 switch (conn->ip_proto) { in efx_tc_ct_parse_match()
169 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
171 conn->ip_proto); in efx_tc_ct_parse_match()
172 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
175 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
177 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
184 if (!IS_ALL_ONES(fm.mask->src)) { in efx_tc_ct_parse_match()
185 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
186 "Conntrack ipv4.src is not exact-match; mask %08x\n", in efx_tc_ct_parse_match()
187 ntohl(fm.mask->src)); in efx_tc_ct_parse_match()
188 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
190 conn->src_ip = fm.key->src; in efx_tc_ct_parse_match()
191 if (!IS_ALL_ONES(fm.mask->dst)) { in efx_tc_ct_parse_match()
192 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
193 "Conntrack ipv4.dst is not exact-match; mask %08x\n", in efx_tc_ct_parse_match()
194 ntohl(fm.mask->dst)); in efx_tc_ct_parse_match()
195 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
197 conn->dst_ip = fm.key->dst; in efx_tc_ct_parse_match()
202 if (!efx_ipv6_addr_all_ones(&fm.mask->src)) { in efx_tc_ct_parse_match()
203 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
204 "Conntrack ipv6.src is not exact-match; mask %pI6\n", in efx_tc_ct_parse_match()
205 &fm.mask->src); in efx_tc_ct_parse_match()
206 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
208 conn->src_ip6 = fm.key->src; in efx_tc_ct_parse_match()
209 if (!efx_ipv6_addr_all_ones(&fm.mask->dst)) { in efx_tc_ct_parse_match()
210 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
211 "Conntrack ipv6.dst is not exact-match; mask %pI6\n", in efx_tc_ct_parse_match()
212 &fm.mask->dst); in efx_tc_ct_parse_match()
213 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
215 conn->dst_ip6 = fm.key->dst; in efx_tc_ct_parse_match()
217 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
219 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
226 if (!IS_ALL_ONES(fm.mask->src)) { in efx_tc_ct_parse_match()
227 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
228 "Conntrack ports.src is not exact-match; mask %04x\n", in efx_tc_ct_parse_match()
229 ntohs(fm.mask->src)); in efx_tc_ct_parse_match()
230 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
232 conn->l4_sport = fm.key->src; in efx_tc_ct_parse_match()
233 if (!IS_ALL_ONES(fm.mask->dst)) { in efx_tc_ct_parse_match()
234 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
235 "Conntrack ports.dst is not exact-match; mask %04x\n", in efx_tc_ct_parse_match()
236 ntohs(fm.mask->dst)); in efx_tc_ct_parse_match()
237 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
239 conn->l4_dport = fm.key->dst; in efx_tc_ct_parse_match()
241 netif_dbg(efx, drv, efx->net_dev, "Conntrack missing L4 ports\n"); in efx_tc_ct_parse_match()
242 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
250 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
252 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
261 if (fm.key->flags & tcp_interesting_flags) { in efx_tc_ct_parse_match()
262 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
264 ntohs(fm.key->flags), ntohs(fm.mask->flags)); in efx_tc_ct_parse_match()
265 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
268 if (fm.mask->flags & ~tcp_interesting_flags) { in efx_tc_ct_parse_match()
269 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_parse_match()
271 ntohs(fm.key->flags), ntohs(fm.mask->flags)); in efx_tc_ct_parse_match()
272 return -EOPNOTSUPP; in efx_tc_ct_parse_match()
284 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_replace()
289 if (WARN_ON(!efx->tc)) in efx_tc_ct_replace()
290 return -ENETDOWN; in efx_tc_ct_replace()
291 if (WARN_ON(!efx->tc->up)) in efx_tc_ct_replace()
292 return -ENETDOWN; in efx_tc_ct_replace()
296 return -ENOMEM; in efx_tc_ct_replace()
297 conn->cookie = tc->cookie; in efx_tc_ct_replace()
298 old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_ht, in efx_tc_ct_replace()
299 &conn->linkage, in efx_tc_ct_replace()
303 goto release; in efx_tc_ct_replace()
305 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
306 "Already offloaded conntrack (cookie %lx)\n", tc->cookie); in efx_tc_ct_replace()
307 rc = -EEXIST; in efx_tc_ct_replace()
308 goto release; in efx_tc_ct_replace()
312 conn->zone = ct_zone; in efx_tc_ct_replace()
315 goto release; in efx_tc_ct_replace()
318 flow_action_for_each(i, fa, &fr->action) { in efx_tc_ct_replace()
319 switch (fa->id) { in efx_tc_ct_replace()
321 conn->mark = fa->ct_metadata.mark; in efx_tc_ct_replace()
322 if (memchr_inv(fa->ct_metadata.labels, 0, sizeof(fa->ct_metadata.labels))) { in efx_tc_ct_replace()
323 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
325 rc = -EOPNOTSUPP; in efx_tc_ct_replace()
326 goto release; in efx_tc_ct_replace()
330 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
331 "Unhandled action %u for conntrack\n", fa->id); in efx_tc_ct_replace()
332 rc = -EOPNOTSUPP; in efx_tc_ct_replace()
333 goto release; in efx_tc_ct_replace()
338 conn->nat_ip = conn->dnat ? conn->dst_ip : conn->src_ip; in efx_tc_ct_replace()
339 conn->l4_natport = conn->dnat ? conn->l4_dport : conn->l4_sport; in efx_tc_ct_replace()
344 goto release; in efx_tc_ct_replace()
346 conn->cnt = cnt; in efx_tc_ct_replace()
350 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
352 goto release; in efx_tc_ct_replace()
354 mutex_lock(&ct_zone->mutex); in efx_tc_ct_replace()
355 list_add_tail(&conn->list, &ct_zone->cts); in efx_tc_ct_replace()
356 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_replace()
358 release: in efx_tc_ct_replace()
359 if (conn->cnt) in efx_tc_ct_replace()
360 efx_tc_flower_release_counter(efx, conn->cnt); in efx_tc_ct_replace()
362 rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, in efx_tc_ct_replace()
376 rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, in efx_tc_ct_remove()
379 netif_err(efx, drv, efx->net_dev, in efx_tc_ct_remove()
381 conn->cookie, rc); in efx_tc_ct_remove()
383 netif_dbg(efx, drv, efx->net_dev, "Removed conntrack %lx\n", in efx_tc_ct_remove()
384 conn->cookie); in efx_tc_ct_remove()
392 * counter from being used-after-free inside efx_tc_ct_stats. in efx_tc_ct_remove_finish()
394 efx_tc_flower_release_counter(efx, conn->cnt); in efx_tc_ct_remove_finish()
401 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_destroy()
404 conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, in efx_tc_ct_destroy()
407 netif_warn(efx, drv, efx->net_dev, in efx_tc_ct_destroy()
408 "Conntrack %lx not found to remove\n", tc->cookie); in efx_tc_ct_destroy()
409 return -ENOENT; in efx_tc_ct_destroy()
412 mutex_lock(&ct_zone->mutex); in efx_tc_ct_destroy()
413 list_del(&conn->list); in efx_tc_ct_destroy()
415 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_destroy()
424 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_stats()
429 conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, in efx_tc_ct_stats()
432 netif_warn(efx, drv, efx->net_dev, in efx_tc_ct_stats()
433 "Conntrack %lx not found for stats\n", tc->cookie); in efx_tc_ct_stats()
435 return -ENOENT; in efx_tc_ct_stats()
438 cnt = conn->cnt; in efx_tc_ct_stats()
439 spin_lock_bh(&cnt->lock); in efx_tc_ct_stats()
441 flow_stats_update(&tc->stats, 0, 0, 0, cnt->touched, in efx_tc_ct_stats()
443 spin_unlock_bh(&cnt->lock); in efx_tc_ct_stats()
456 return -EOPNOTSUPP; in efx_tc_flow_block()
458 switch (tcb->command) { in efx_tc_flow_block()
469 return -EOPNOTSUPP; in efx_tc_flow_block()
480 return ERR_PTR(-ENOMEM); in efx_tc_ct_register_zone()
481 ct_zone->zone = zone; in efx_tc_ct_register_zone()
482 old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_zone_ht, in efx_tc_ct_register_zone()
483 &ct_zone->linkage, in efx_tc_ct_register_zone()
490 if (!refcount_inc_not_zero(&old->ref)) in efx_tc_ct_register_zone()
491 return ERR_PTR(-EAGAIN); in efx_tc_ct_register_zone()
493 WARN_ON_ONCE(old->nf_ft != ct_ft); in efx_tc_ct_register_zone()
494 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_register_zone()
498 ct_zone->nf_ft = ct_ft; in efx_tc_ct_register_zone()
499 ct_zone->efx = efx; in efx_tc_ct_register_zone()
500 INIT_LIST_HEAD(&ct_zone->cts); in efx_tc_ct_register_zone()
501 mutex_init(&ct_zone->mutex); in efx_tc_ct_register_zone()
503 netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", in efx_tc_ct_register_zone()
507 refcount_set(&ct_zone->ref, 1); in efx_tc_ct_register_zone()
510 rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, in efx_tc_ct_register_zone()
521 if (!refcount_dec_and_test(&ct_zone->ref)) in efx_tc_ct_unregister_zone()
523 nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); in efx_tc_ct_unregister_zone()
524 rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, in efx_tc_ct_unregister_zone()
526 mutex_lock(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
527 list_for_each_entry(conn, &ct_zone->cts, list) in efx_tc_ct_unregister_zone()
531 list_for_each_entry_safe(conn, next, &ct_zone->cts, list) in efx_tc_ct_unregister_zone()
533 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
534 mutex_destroy(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
535 netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", in efx_tc_ct_unregister_zone()
536 ct_zone->zone); in efx_tc_ct_unregister_zone()