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()
280 * struct efx_tc_ct_mangler_state - tracks which fields have been pedited
295 bool first = !(mung->ipv4 || mung->tcpudp); in efx_tc_ct_mangle()
298 switch (fa->mangle.htype) { in efx_tc_ct_mangle()
300 switch (fa->mangle.offset) { in efx_tc_ct_mangle()
305 if (fa->mangle.mask) in efx_tc_ct_mangle()
306 return -EOPNOTSUPP; in efx_tc_ct_mangle()
307 conn->nat_ip = htonl(fa->mangle.val); in efx_tc_ct_mangle()
308 mung->ipv4 = 1; in efx_tc_ct_mangle()
311 return -EOPNOTSUPP; in efx_tc_ct_mangle()
321 switch (fa->mangle.offset) { in efx_tc_ct_mangle()
330 if (~fa->mangle.mask != 0xffff) in efx_tc_ct_mangle()
331 return -EOPNOTSUPP; in efx_tc_ct_mangle()
332 conn->l4_natport = htons(fa->mangle.val); in efx_tc_ct_mangle()
333 mung->tcpudp = 1; in efx_tc_ct_mangle()
336 return -EOPNOTSUPP; in efx_tc_ct_mangle()
340 return -EOPNOTSUPP; in efx_tc_ct_mangle()
346 conn->dnat = dnat; in efx_tc_ct_mangle()
347 else if (conn->dnat != dnat) in efx_tc_ct_mangle()
348 return -EOPNOTSUPP; in efx_tc_ct_mangle()
358 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_replace()
363 if (WARN_ON(!efx->tc)) in efx_tc_ct_replace()
364 return -ENETDOWN; in efx_tc_ct_replace()
365 if (WARN_ON(!efx->tc->up)) in efx_tc_ct_replace()
366 return -ENETDOWN; in efx_tc_ct_replace()
370 return -ENOMEM; in efx_tc_ct_replace()
371 conn->cookie = tc->cookie; in efx_tc_ct_replace()
372 old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_ht, in efx_tc_ct_replace()
373 &conn->linkage, in efx_tc_ct_replace()
377 goto release; in efx_tc_ct_replace()
379 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
380 "Already offloaded conntrack (cookie %lx)\n", tc->cookie); in efx_tc_ct_replace()
381 rc = -EEXIST; in efx_tc_ct_replace()
382 goto release; in efx_tc_ct_replace()
386 conn->zone = ct_zone; in efx_tc_ct_replace()
389 goto release; in efx_tc_ct_replace()
392 flow_action_for_each(i, fa, &fr->action) { in efx_tc_ct_replace()
393 switch (fa->id) { in efx_tc_ct_replace()
395 conn->mark = fa->ct_metadata.mark; in efx_tc_ct_replace()
396 if (memchr_inv(fa->ct_metadata.labels, 0, sizeof(fa->ct_metadata.labels))) { in efx_tc_ct_replace()
397 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
399 rc = -EOPNOTSUPP; in efx_tc_ct_replace()
400 goto release; in efx_tc_ct_replace()
404 if (conn->eth_proto != htons(ETH_P_IP)) { in efx_tc_ct_replace()
405 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
407 rc = -EOPNOTSUPP; in efx_tc_ct_replace()
408 goto release; in efx_tc_ct_replace()
412 goto release; in efx_tc_ct_replace()
415 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
416 "Unhandled action %u for conntrack\n", fa->id); in efx_tc_ct_replace()
417 rc = -EOPNOTSUPP; in efx_tc_ct_replace()
418 goto release; in efx_tc_ct_replace()
424 conn->nat_ip = conn->dnat ? conn->dst_ip : conn->src_ip; in efx_tc_ct_replace()
426 conn->l4_natport = conn->dnat ? conn->l4_dport : conn->l4_sport; in efx_tc_ct_replace()
431 goto release; in efx_tc_ct_replace()
433 conn->cnt = cnt; in efx_tc_ct_replace()
437 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_replace()
439 goto release; in efx_tc_ct_replace()
441 mutex_lock(&ct_zone->mutex); in efx_tc_ct_replace()
442 list_add_tail(&conn->list, &ct_zone->cts); in efx_tc_ct_replace()
443 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_replace()
445 release: in efx_tc_ct_replace()
446 if (conn->cnt) in efx_tc_ct_replace()
447 efx_tc_flower_release_counter(efx, conn->cnt); in efx_tc_ct_replace()
449 rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, in efx_tc_ct_replace()
463 rhashtable_remove_fast(&efx->tc->ct_ht, &conn->linkage, in efx_tc_ct_remove()
466 netif_err(efx, drv, efx->net_dev, in efx_tc_ct_remove()
468 conn->cookie, rc); in efx_tc_ct_remove()
470 netif_dbg(efx, drv, efx->net_dev, "Removed conntrack %lx\n", in efx_tc_ct_remove()
471 conn->cookie); in efx_tc_ct_remove()
479 * counter from being used-after-free inside efx_tc_ct_stats. in efx_tc_ct_remove_finish()
481 efx_tc_flower_release_counter(efx, conn->cnt); in efx_tc_ct_remove_finish()
488 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_destroy()
491 conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, in efx_tc_ct_destroy()
494 netif_warn(efx, drv, efx->net_dev, in efx_tc_ct_destroy()
495 "Conntrack %lx not found to remove\n", tc->cookie); in efx_tc_ct_destroy()
496 return -ENOENT; in efx_tc_ct_destroy()
499 mutex_lock(&ct_zone->mutex); in efx_tc_ct_destroy()
500 list_del(&conn->list); in efx_tc_ct_destroy()
502 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_destroy()
511 struct efx_nic *efx = ct_zone->efx; in efx_tc_ct_stats()
516 conn = rhashtable_lookup_fast(&efx->tc->ct_ht, &tc->cookie, in efx_tc_ct_stats()
519 netif_warn(efx, drv, efx->net_dev, in efx_tc_ct_stats()
520 "Conntrack %lx not found for stats\n", tc->cookie); in efx_tc_ct_stats()
522 return -ENOENT; in efx_tc_ct_stats()
525 cnt = conn->cnt; in efx_tc_ct_stats()
526 spin_lock_bh(&cnt->lock); in efx_tc_ct_stats()
528 flow_stats_update(&tc->stats, 0, 0, 0, cnt->touched, in efx_tc_ct_stats()
530 spin_unlock_bh(&cnt->lock); in efx_tc_ct_stats()
543 return -EOPNOTSUPP; in efx_tc_flow_block()
545 switch (tcb->command) { in efx_tc_flow_block()
556 return -EOPNOTSUPP; in efx_tc_flow_block()
567 return ERR_PTR(-ENOMEM); in efx_tc_ct_register_zone()
568 ct_zone->zone = zone; in efx_tc_ct_register_zone()
569 old = rhashtable_lookup_get_insert_fast(&efx->tc->ct_zone_ht, in efx_tc_ct_register_zone()
570 &ct_zone->linkage, in efx_tc_ct_register_zone()
577 if (!refcount_inc_not_zero(&old->ref)) in efx_tc_ct_register_zone()
578 return ERR_PTR(-EAGAIN); in efx_tc_ct_register_zone()
580 WARN_ON_ONCE(old->nf_ft != ct_ft); in efx_tc_ct_register_zone()
581 netif_dbg(efx, drv, efx->net_dev, in efx_tc_ct_register_zone()
585 ct_zone->nf_ft = ct_ft; in efx_tc_ct_register_zone()
586 ct_zone->efx = efx; in efx_tc_ct_register_zone()
587 INIT_LIST_HEAD(&ct_zone->cts); in efx_tc_ct_register_zone()
588 mutex_init(&ct_zone->mutex); in efx_tc_ct_register_zone()
590 netif_dbg(efx, drv, efx->net_dev, "Adding new ct_zone for %u, rc %d\n", in efx_tc_ct_register_zone()
594 refcount_set(&ct_zone->ref, 1); in efx_tc_ct_register_zone()
597 rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, in efx_tc_ct_register_zone()
608 if (!refcount_dec_and_test(&ct_zone->ref)) in efx_tc_ct_unregister_zone()
610 nf_flow_table_offload_del_cb(ct_zone->nf_ft, efx_tc_flow_block, ct_zone); in efx_tc_ct_unregister_zone()
611 rhashtable_remove_fast(&efx->tc->ct_zone_ht, &ct_zone->linkage, in efx_tc_ct_unregister_zone()
613 mutex_lock(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
614 list_for_each_entry(conn, &ct_zone->cts, list) in efx_tc_ct_unregister_zone()
618 list_for_each_entry_safe(conn, next, &ct_zone->cts, list) in efx_tc_ct_unregister_zone()
620 mutex_unlock(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
621 mutex_destroy(&ct_zone->mutex); in efx_tc_ct_unregister_zone()
622 netif_dbg(efx, drv, efx->net_dev, "Removed ct_zone for %u\n", in efx_tc_ct_unregister_zone()
623 ct_zone->zone); in efx_tc_ct_unregister_zone()