Lines Matching refs:chain
53 return jhash_3words(tp->chain->index, tp->prio, in destroy_obj_hashfn()
57 static void tcf_proto_signal_destroying(struct tcf_chain *chain, in tcf_proto_signal_destroying() argument
60 struct tcf_block *block = chain->block; in tcf_proto_signal_destroying()
71 return tp1->chain->index == tp2->chain->index && in tcf_proto_cmp()
76 static bool tcf_proto_exists_destroying(struct tcf_chain *chain, in tcf_proto_exists_destroying() argument
84 hash_for_each_possible_rcu(chain->block->proto_destroy_ht, iter, in tcf_proto_exists_destroying()
97 tcf_proto_signal_destroyed(struct tcf_chain *chain, struct tcf_proto *tp) in tcf_proto_signal_destroyed() argument
99 struct tcf_block *block = chain->block; in tcf_proto_signal_destroyed()
251 u32 prio, struct tcf_chain *chain, in tcf_proto_create() argument
270 tp->chain = chain; in tcf_proto_create()
291 static void tcf_chain_put(struct tcf_chain *chain);
298 tcf_proto_signal_destroyed(tp->chain, tp); in tcf_proto_destroy()
299 tcf_chain_put(tp->chain); in tcf_proto_destroy()
371 struct tcf_chain *chain; in tcf_chain_create() local
375 chain = kzalloc(sizeof(*chain), GFP_KERNEL); in tcf_chain_create()
376 if (!chain) in tcf_chain_create()
378 list_add_tail(&chain->list, &block->chain_list); in tcf_chain_create()
379 mutex_init(&chain->filter_chain_lock); in tcf_chain_create()
380 chain->block = block; in tcf_chain_create()
381 chain->index = chain_index; in tcf_chain_create()
382 chain->refcnt = 1; in tcf_chain_create()
383 if (!chain->index) in tcf_chain_create()
384 block->chain0.chain = chain; in tcf_chain_create()
385 return chain; in tcf_chain_create()
395 static void tcf_chain0_head_change(struct tcf_chain *chain, in tcf_chain0_head_change() argument
399 struct tcf_block *block = chain->block; in tcf_chain0_head_change()
401 if (chain->index) in tcf_chain0_head_change()
412 static bool tcf_chain_detach(struct tcf_chain *chain) in tcf_chain_detach() argument
414 struct tcf_block *block = chain->block; in tcf_chain_detach()
418 list_del(&chain->list); in tcf_chain_detach()
419 if (!chain->index) in tcf_chain_detach()
420 block->chain0.chain = NULL; in tcf_chain_detach()
436 static void tcf_chain_destroy(struct tcf_chain *chain, bool free_block) in tcf_chain_destroy() argument
438 struct tcf_block *block = chain->block; in tcf_chain_destroy()
440 mutex_destroy(&chain->filter_chain_lock); in tcf_chain_destroy()
441 kfree_rcu(chain, rcu); in tcf_chain_destroy()
446 static void tcf_chain_hold(struct tcf_chain *chain) in tcf_chain_hold() argument
448 ASSERT_BLOCK_LOCKED(chain->block); in tcf_chain_hold()
450 ++chain->refcnt; in tcf_chain_hold()
453 static bool tcf_chain_held_by_acts_only(struct tcf_chain *chain) in tcf_chain_held_by_acts_only() argument
455 ASSERT_BLOCK_LOCKED(chain->block); in tcf_chain_held_by_acts_only()
460 return chain->refcnt == chain->action_refcnt; in tcf_chain_held_by_acts_only()
466 struct tcf_chain *chain; in tcf_chain_lookup() local
470 list_for_each_entry(chain, &block->chain_list, list) { in tcf_chain_lookup()
471 if (chain->index == chain_index) in tcf_chain_lookup()
472 return chain; in tcf_chain_lookup()
477 static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb,
484 struct tcf_chain *chain = NULL; in __tcf_chain_get() local
488 chain = tcf_chain_lookup(block, chain_index); in __tcf_chain_get()
489 if (chain) { in __tcf_chain_get()
490 tcf_chain_hold(chain); in __tcf_chain_get()
494 chain = tcf_chain_create(block, chain_index); in __tcf_chain_get()
495 if (!chain) in __tcf_chain_get()
500 ++chain->action_refcnt; in __tcf_chain_get()
501 is_first_reference = chain->refcnt - chain->action_refcnt == 1; in __tcf_chain_get()
510 tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL, in __tcf_chain_get()
513 return chain; in __tcf_chain_get()
517 return chain; in __tcf_chain_get()
539 static void __tcf_chain_put(struct tcf_chain *chain, bool by_act, in __tcf_chain_put() argument
542 struct tcf_block *block = chain->block; in __tcf_chain_put()
550 if (!chain->explicitly_created) { in __tcf_chain_put()
554 chain->explicitly_created = false; in __tcf_chain_put()
558 chain->action_refcnt--; in __tcf_chain_put()
564 refcnt = --chain->refcnt; in __tcf_chain_put()
565 tmplt_ops = chain->tmplt_ops; in __tcf_chain_put()
566 tmplt_priv = chain->tmplt_priv; in __tcf_chain_put()
569 if (refcnt - chain->action_refcnt == 0 && !by_act) { in __tcf_chain_put()
570 tc_chain_notify_delete(tmplt_ops, tmplt_priv, chain->index, in __tcf_chain_put()
573 chain->flushing = false; in __tcf_chain_put()
577 free_block = tcf_chain_detach(chain); in __tcf_chain_put()
582 tcf_chain_destroy(chain, free_block); in __tcf_chain_put()
586 static void tcf_chain_put(struct tcf_chain *chain) in tcf_chain_put() argument
588 __tcf_chain_put(chain, false, false); in tcf_chain_put()
591 void tcf_chain_put_by_act(struct tcf_chain *chain) in tcf_chain_put_by_act() argument
593 __tcf_chain_put(chain, true, false); in tcf_chain_put_by_act()
597 static void tcf_chain_put_explicitly_created(struct tcf_chain *chain) in tcf_chain_put_explicitly_created() argument
599 __tcf_chain_put(chain, false, true); in tcf_chain_put_explicitly_created()
602 static void tcf_chain_flush(struct tcf_chain *chain, bool rtnl_held) in tcf_chain_flush() argument
606 mutex_lock(&chain->filter_chain_lock); in tcf_chain_flush()
607 tp = tcf_chain_dereference(chain->filter_chain, chain); in tcf_chain_flush()
610 tcf_proto_signal_destroying(chain, tp); in tcf_chain_flush()
613 tp = tcf_chain_dereference(chain->filter_chain, chain); in tcf_chain_flush()
614 RCU_INIT_POINTER(chain->filter_chain, NULL); in tcf_chain_flush()
615 tcf_chain0_head_change(chain, NULL); in tcf_chain_flush()
616 chain->flushing = true; in tcf_chain_flush()
617 mutex_unlock(&chain->filter_chain_lock); in tcf_chain_flush()
818 chain0 = block->chain0.chain; in tcf_chain0_head_change_cb_add()
856 if (block->chain0.chain) in tcf_chain0_head_change_cb_del()
951 __tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain) in __tcf_get_next_chain() argument
954 if (chain) in __tcf_get_next_chain()
955 chain = list_is_last(&chain->list, &block->chain_list) ? in __tcf_get_next_chain()
956 NULL : list_next_entry(chain, list); in __tcf_get_next_chain()
958 chain = list_first_entry_or_null(&block->chain_list, in __tcf_get_next_chain()
962 while (chain && tcf_chain_held_by_acts_only(chain)) in __tcf_get_next_chain()
963 chain = list_is_last(&chain->list, &block->chain_list) ? in __tcf_get_next_chain()
964 NULL : list_next_entry(chain, list); in __tcf_get_next_chain()
966 if (chain) in __tcf_get_next_chain()
967 tcf_chain_hold(chain); in __tcf_get_next_chain()
970 return chain; in __tcf_get_next_chain()
983 tcf_get_next_chain(struct tcf_block *block, struct tcf_chain *chain) in tcf_get_next_chain() argument
985 struct tcf_chain *chain_next = __tcf_get_next_chain(block, chain); in tcf_get_next_chain()
987 if (chain) in tcf_get_next_chain()
988 tcf_chain_put(chain); in tcf_get_next_chain()
995 __tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp) in __tcf_get_next_proto() argument
1000 mutex_lock(&chain->filter_chain_lock); in __tcf_get_next_proto()
1003 tp = tcf_chain_dereference(chain->filter_chain, chain); in __tcf_get_next_proto()
1010 tp = tcf_chain_dereference(chain->filter_chain, chain); in __tcf_get_next_proto()
1012 for (; tp; tp = tcf_chain_dereference(tp->next, chain)) in __tcf_get_next_proto()
1016 tp = tcf_chain_dereference(tp->next, chain); in __tcf_get_next_proto()
1022 mutex_unlock(&chain->filter_chain_lock); in __tcf_get_next_proto()
1036 tcf_get_next_proto(struct tcf_chain *chain, struct tcf_proto *tp, in tcf_get_next_proto() argument
1039 struct tcf_proto *tp_next = __tcf_get_next_proto(chain, tp); in tcf_get_next_proto()
1050 struct tcf_chain *chain; in tcf_block_flush_all_chains() local
1055 for (chain = tcf_get_next_chain(block, NULL); in tcf_block_flush_all_chains()
1056 chain; in tcf_block_flush_all_chains()
1057 chain = tcf_get_next_chain(block, chain)) { in tcf_block_flush_all_chains()
1058 tcf_chain_put_explicitly_created(chain); in tcf_block_flush_all_chains()
1059 tcf_chain_flush(chain, rtnl_held); in tcf_block_flush_all_chains()
1446 struct tcf_chain *chain, *chain_prev; in tcf_block_playback_offloads() local
1452 for (chain = __tcf_get_next_chain(block, NULL); in tcf_block_playback_offloads()
1453 chain; in tcf_block_playback_offloads()
1454 chain_prev = chain, in tcf_block_playback_offloads()
1455 chain = __tcf_get_next_chain(block, chain), in tcf_block_playback_offloads()
1457 for (tp = __tcf_get_next_proto(chain, NULL); tp; in tcf_block_playback_offloads()
1459 tp = __tcf_get_next_proto(chain, tp), in tcf_block_playback_offloads()
1478 tcf_chain_put(chain); in tcf_block_playback_offloads()
1604 ext->chain = err & TC_ACT_EXT_VAL_MASK; in tcf_classify()
1619 tp->chain->block->index, in tcf_classify()
1636 static struct tcf_proto *tcf_chain_tp_prev(struct tcf_chain *chain, in tcf_chain_tp_prev() argument
1639 return tcf_chain_dereference(*chain_info->pprev, chain); in tcf_chain_tp_prev()
1642 static int tcf_chain_tp_insert(struct tcf_chain *chain, in tcf_chain_tp_insert() argument
1646 if (chain->flushing) in tcf_chain_tp_insert()
1649 if (*chain_info->pprev == chain->filter_chain) in tcf_chain_tp_insert()
1650 tcf_chain0_head_change(chain, tp); in tcf_chain_tp_insert()
1652 RCU_INIT_POINTER(tp->next, tcf_chain_tp_prev(chain, chain_info)); in tcf_chain_tp_insert()
1658 static void tcf_chain_tp_remove(struct tcf_chain *chain, in tcf_chain_tp_remove() argument
1662 struct tcf_proto *next = tcf_chain_dereference(chain_info->next, chain); in tcf_chain_tp_remove()
1665 if (tp == chain->filter_chain) in tcf_chain_tp_remove()
1666 tcf_chain0_head_change(chain, next); in tcf_chain_tp_remove()
1670 static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain,
1680 static struct tcf_proto *tcf_chain_tp_insert_unique(struct tcf_chain *chain, in tcf_chain_tp_insert_unique() argument
1689 mutex_lock(&chain->filter_chain_lock); in tcf_chain_tp_insert_unique()
1691 if (tcf_proto_exists_destroying(chain, tp_new)) { in tcf_chain_tp_insert_unique()
1692 mutex_unlock(&chain->filter_chain_lock); in tcf_chain_tp_insert_unique()
1697 tp = tcf_chain_tp_find(chain, &chain_info, in tcf_chain_tp_insert_unique()
1700 err = tcf_chain_tp_insert(chain, &chain_info, tp_new); in tcf_chain_tp_insert_unique()
1701 mutex_unlock(&chain->filter_chain_lock); in tcf_chain_tp_insert_unique()
1714 static void tcf_chain_tp_delete_empty(struct tcf_chain *chain, in tcf_chain_tp_delete_empty() argument
1723 mutex_lock(&chain->filter_chain_lock); in tcf_chain_tp_delete_empty()
1726 for (pprev = &chain->filter_chain; in tcf_chain_tp_delete_empty()
1727 (tp_iter = tcf_chain_dereference(*pprev, chain)); in tcf_chain_tp_delete_empty()
1741 mutex_unlock(&chain->filter_chain_lock); in tcf_chain_tp_delete_empty()
1745 tcf_proto_signal_destroying(chain, tp); in tcf_chain_tp_delete_empty()
1746 next = tcf_chain_dereference(chain_info.next, chain); in tcf_chain_tp_delete_empty()
1747 if (tp == chain->filter_chain) in tcf_chain_tp_delete_empty()
1748 tcf_chain0_head_change(chain, next); in tcf_chain_tp_delete_empty()
1750 mutex_unlock(&chain->filter_chain_lock); in tcf_chain_tp_delete_empty()
1755 static struct tcf_proto *tcf_chain_tp_find(struct tcf_chain *chain, in tcf_chain_tp_find() argument
1764 for (pprev = &chain->filter_chain; in tcf_chain_tp_find()
1765 (tp = tcf_chain_dereference(*pprev, chain)); in tcf_chain_tp_find()
1815 if (nla_put_u32(skb, TCA_CHAIN, tp->chain->index)) in tcf_fill_node()
1909 struct tcf_chain *chain, int event, in tfilter_notify_chain() argument
1914 for (tp = tcf_get_next_proto(chain, NULL, rtnl_held); in tfilter_notify_chain()
1915 tp; tp = tcf_get_next_proto(chain, tp, rtnl_held)) in tfilter_notify_chain()
1940 struct tcf_chain *chain = NULL; in tc_new_tfilter() local
2022 chain = tcf_chain_get(block, chain_index, true); in tc_new_tfilter()
2023 if (!chain) { in tc_new_tfilter()
2029 mutex_lock(&chain->filter_chain_lock); in tc_new_tfilter()
2030 tp = tcf_chain_tp_find(chain, &chain_info, protocol, in tc_new_tfilter()
2041 if (chain->flushing) { in tc_new_tfilter()
2061 prio = tcf_auto_prio(tcf_chain_tp_prev(chain, in tc_new_tfilter()
2064 mutex_unlock(&chain->filter_chain_lock); in tc_new_tfilter()
2066 protocol, prio, chain, rtnl_held, in tc_new_tfilter()
2074 tp = tcf_chain_tp_insert_unique(chain, tp_new, protocol, prio, in tc_new_tfilter()
2081 mutex_unlock(&chain->filter_chain_lock); in tc_new_tfilter()
2105 if (chain->tmplt_ops && chain->tmplt_ops != tp->ops) { in tc_new_tfilter()
2125 tcf_chain_tp_delete_empty(chain, tp, rtnl_held, NULL); in tc_new_tfilter()
2127 if (chain) { in tc_new_tfilter()
2131 tcf_chain_put(chain); in tc_new_tfilter()
2149 mutex_unlock(&chain->filter_chain_lock); in tc_new_tfilter()
2166 struct tcf_chain *chain = NULL; in tc_del_tfilter() local
2231 chain = tcf_chain_get(block, chain_index, false); in tc_del_tfilter()
2232 if (!chain) { in tc_del_tfilter()
2247 chain, RTM_DELTFILTER, rtnl_held); in tc_del_tfilter()
2248 tcf_chain_flush(chain, rtnl_held); in tc_del_tfilter()
2253 mutex_lock(&chain->filter_chain_lock); in tc_del_tfilter()
2254 tp = tcf_chain_tp_find(chain, &chain_info, protocol, in tc_del_tfilter()
2265 tcf_proto_signal_destroying(chain, tp); in tc_del_tfilter()
2266 tcf_chain_tp_remove(chain, &chain_info, tp); in tc_del_tfilter()
2267 mutex_unlock(&chain->filter_chain_lock); in tc_del_tfilter()
2275 mutex_unlock(&chain->filter_chain_lock); in tc_del_tfilter()
2292 tcf_chain_tp_delete_empty(chain, tp, rtnl_held, extack); in tc_del_tfilter()
2296 if (chain) { in tc_del_tfilter()
2299 tcf_chain_put(chain); in tc_del_tfilter()
2309 mutex_unlock(&chain->filter_chain_lock); in tc_del_tfilter()
2326 struct tcf_chain *chain = NULL; in tc_get_tfilter() local
2387 chain = tcf_chain_get(block, chain_index, false); in tc_get_tfilter()
2388 if (!chain) { in tc_get_tfilter()
2394 mutex_lock(&chain->filter_chain_lock); in tc_get_tfilter()
2395 tp = tcf_chain_tp_find(chain, &chain_info, protocol, in tc_get_tfilter()
2397 mutex_unlock(&chain->filter_chain_lock); in tc_get_tfilter()
2422 if (chain) { in tc_get_tfilter()
2425 tcf_chain_put(chain); in tc_get_tfilter()
2455 static bool tcf_chain_dump(struct tcf_chain *chain, struct Qdisc *q, u32 parent, in tcf_chain_dump() argument
2460 struct tcf_block *block = chain->block; in tcf_chain_dump()
2465 for (tp = __tcf_get_next_proto(chain, NULL); in tcf_chain_dump()
2468 tp = __tcf_get_next_proto(chain, tp), in tcf_chain_dump()
2518 struct tcf_chain *chain, *chain_prev; in tc_dump_tfilter() local
2586 for (chain = __tcf_get_next_chain(block, NULL); in tc_dump_tfilter()
2587 chain; in tc_dump_tfilter()
2588 chain_prev = chain, in tc_dump_tfilter()
2589 chain = __tcf_get_next_chain(block, chain), in tc_dump_tfilter()
2592 nla_get_u32(tca[TCA_CHAIN]) != chain->index) in tc_dump_tfilter()
2594 if (!tcf_chain_dump(chain, q, parent, skb, cb, in tc_dump_tfilter()
2596 tcf_chain_put(chain); in tc_dump_tfilter()
2663 static int tc_chain_notify(struct tcf_chain *chain, struct sk_buff *oskb, in tc_chain_notify() argument
2667 struct tcf_block *block = chain->block; in tc_chain_notify()
2676 if (tc_chain_fill_node(chain->tmplt_ops, chain->tmplt_priv, in tc_chain_notify()
2677 chain->index, net, skb, block, portid, in tc_chain_notify()
2719 static int tc_chain_tmplt_add(struct tcf_chain *chain, struct net *net, in tc_chain_tmplt_add() argument
2738 tmplt_priv = ops->tmplt_create(net, chain, tca, extack); in tc_chain_tmplt_add()
2743 chain->tmplt_ops = ops; in tc_chain_tmplt_add()
2744 chain->tmplt_priv = tmplt_priv; in tc_chain_tmplt_add()
2770 struct tcf_chain *chain = NULL; in tc_ctl_chain() local
2802 chain = tcf_chain_lookup(block, chain_index); in tc_ctl_chain()
2804 if (chain) { in tc_ctl_chain()
2805 if (tcf_chain_held_by_acts_only(chain)) { in tc_ctl_chain()
2809 tcf_chain_hold(chain); in tc_ctl_chain()
2821 chain = tcf_chain_create(block, chain_index); in tc_ctl_chain()
2822 if (!chain) { in tc_ctl_chain()
2829 if (!chain || tcf_chain_held_by_acts_only(chain)) { in tc_ctl_chain()
2834 tcf_chain_hold(chain); in tc_ctl_chain()
2843 tcf_chain_hold(chain); in tc_ctl_chain()
2844 chain->explicitly_created = true; in tc_ctl_chain()
2850 err = tc_chain_tmplt_add(chain, net, tca, extack); in tc_ctl_chain()
2852 tcf_chain_put_explicitly_created(chain); in tc_ctl_chain()
2856 tc_chain_notify(chain, NULL, 0, NLM_F_CREATE | NLM_F_EXCL, in tc_ctl_chain()
2861 chain, RTM_DELTFILTER, true); in tc_ctl_chain()
2863 tcf_chain_flush(chain, true); in tc_ctl_chain()
2867 tcf_chain_put_explicitly_created(chain); in tc_ctl_chain()
2870 err = tc_chain_notify(chain, skb, n->nlmsg_seq, in tc_ctl_chain()
2882 tcf_chain_put(chain); in tc_ctl_chain()
2903 struct tcf_chain *chain; in tc_dump_chain() local
2967 list_for_each_entry(chain, &block->chain_list, list) { in tc_dump_chain()
2969 nla_get_u32(tca[TCA_CHAIN]) != chain->index)) in tc_dump_chain()
2975 if (tcf_chain_held_by_acts_only(chain)) in tc_dump_chain()
2977 err = tc_chain_fill_node(chain->tmplt_ops, chain->tmplt_priv, in tc_dump_chain()
2978 chain->index, net, skb, block, in tc_dump_chain()