Lines Matching +full:array +full:- +full:nest
1 // SPDX-License-Identifier: GPL-2.0-or-later
28 const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain); in tcf_action_goto_chain_exec()
30 res->goto_tp = rcu_dereference_bh(chain->filter_chain); in tcf_action_goto_chain_exec()
37 kfree(cookie->data); in tcf_free_cookie_rcu()
48 call_rcu(&old->rcu, tcf_free_cookie_rcu); in tcf_set_action_cookie()
55 int opcode = TC_ACT_EXT_OPCODE(action), ret = -EINVAL; in tcf_action_check_ctrlact()
59 ret = action > TC_ACT_VALUE_MAX ? -EINVAL : 0; in tcf_action_check_ctrlact()
70 ret = -EINVAL; in tcf_action_check_ctrlact()
75 *newchain = tcf_chain_get_by_act(tp->chain->block, chain_index); in tcf_action_check_ctrlact()
77 ret = -ENOMEM; in tcf_action_check_ctrlact()
90 a->tcfa_action = action; in tcf_action_set_ctrlact()
91 goto_chain = rcu_replace_pointer(a->goto_chain, goto_chain, 1); in tcf_action_set_ctrlact()
103 struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1); in free_tcf()
105 free_percpu(p->cpu_bstats); in free_tcf()
106 free_percpu(p->cpu_bstats_hw); in free_tcf()
107 free_percpu(p->cpu_qstats); in free_tcf()
109 tcf_set_action_cookie(&p->act_cookie, NULL); in free_tcf()
118 if (p->ops->cleanup) in tcf_action_cleanup()
119 p->ops->cleanup(p); in tcf_action_cleanup()
121 gen_kill_estimator(&p->tcfa_rate_est); in tcf_action_cleanup()
127 struct tcf_idrinfo *idrinfo = p->idrinfo; in __tcf_action_put()
129 if (refcount_dec_and_mutex_lock(&p->tcfa_refcnt, &idrinfo->lock)) { in __tcf_action_put()
131 atomic_dec(&p->tcfa_bindcnt); in __tcf_action_put()
132 idr_remove(&idrinfo->action_idr, p->tcfa_index); in __tcf_action_put()
133 mutex_unlock(&idrinfo->lock); in __tcf_action_put()
140 atomic_dec(&p->tcfa_bindcnt); in __tcf_action_put()
162 if (!bind && strict && atomic_read(&p->tcfa_bindcnt) > 0) in __tcf_idr_release()
163 return -EPERM; in __tcf_idr_release()
174 const struct tc_action_ops *ops = a->ops; in tcf_idr_release()
179 module_put(ops->owner); in tcf_idr_release()
190 act_cookie = rcu_dereference(act->act_cookie); in tcf_action_shared_attrs_size()
193 cookie_len = nla_total_size(act_cookie->len); in tcf_action_shared_attrs_size()
224 if (act->ops->get_fill_size) in tcf_action_fill_size()
225 return act->ops->get_fill_size(act) + sz; in tcf_action_fill_size()
232 int err = 0, index = -1, s_i = 0, n_i = 0; in tcf_dump_walker()
233 u32 act_flags = cb->args[2]; in tcf_dump_walker()
234 unsigned long jiffy_since = cb->args[3]; in tcf_dump_walker()
235 struct nlattr *nest; in tcf_dump_walker() local
236 struct idr *idr = &idrinfo->action_idr; in tcf_dump_walker()
241 mutex_lock(&idrinfo->lock); in tcf_dump_walker()
243 s_i = cb->args[0]; in tcf_dump_walker()
254 (unsigned long)p->tcfa_tm.lastuse)) in tcf_dump_walker()
257 nest = nla_nest_start_noflag(skb, n_i); in tcf_dump_walker()
258 if (!nest) { in tcf_dump_walker()
259 index--; in tcf_dump_walker()
264 index--; in tcf_dump_walker()
265 nlmsg_trim(skb, nest); in tcf_dump_walker()
268 nla_nest_end(skb, nest); in tcf_dump_walker()
276 cb->args[0] = index + 1; in tcf_dump_walker()
278 mutex_unlock(&idrinfo->lock); in tcf_dump_walker()
281 cb->args[1] = n_i; in tcf_dump_walker()
286 nla_nest_cancel(skb, nest); in tcf_dump_walker()
292 if (atomic_read(&p->tcfa_bindcnt) > 0) in tcf_idr_release_unsafe()
293 return -EPERM; in tcf_idr_release_unsafe()
295 if (refcount_dec_and_test(&p->tcfa_refcnt)) { in tcf_idr_release_unsafe()
296 idr_remove(&p->idrinfo->action_idr, p->tcfa_index); in tcf_idr_release_unsafe()
308 struct nlattr *nest; in tcf_del_walker() local
310 int ret = -EINVAL; in tcf_del_walker()
311 struct idr *idr = &idrinfo->action_idr; in tcf_del_walker()
316 nest = nla_nest_start_noflag(skb, 0); in tcf_del_walker()
317 if (nest == NULL) in tcf_del_walker()
319 if (nla_put_string(skb, TCA_KIND, ops->kind)) in tcf_del_walker()
323 mutex_lock(&idrinfo->lock); in tcf_del_walker()
329 module_put(ops->owner); in tcf_del_walker()
334 mutex_unlock(&idrinfo->lock); in tcf_del_walker()
345 nla_nest_end(skb, nest); in tcf_del_walker()
349 nla_nest_cancel(skb, nest); in tcf_del_walker()
358 struct tcf_idrinfo *idrinfo = tn->idrinfo; in tcf_generic_walker()
367 return -EINVAL; in tcf_generic_walker()
374 struct tcf_idrinfo *idrinfo = tn->idrinfo; in tcf_idr_search()
377 mutex_lock(&idrinfo->lock); in tcf_idr_search()
378 p = idr_find(&idrinfo->action_idr, index); in tcf_idr_search()
382 refcount_inc(&p->tcfa_refcnt); in tcf_idr_search()
383 mutex_unlock(&idrinfo->lock); in tcf_idr_search()
398 mutex_lock(&idrinfo->lock); in tcf_idr_delete_index()
399 p = idr_find(&idrinfo->action_idr, index); in tcf_idr_delete_index()
401 mutex_unlock(&idrinfo->lock); in tcf_idr_delete_index()
402 return -ENOENT; in tcf_idr_delete_index()
405 if (!atomic_read(&p->tcfa_bindcnt)) { in tcf_idr_delete_index()
406 if (refcount_dec_and_test(&p->tcfa_refcnt)) { in tcf_idr_delete_index()
407 struct module *owner = p->ops->owner; in tcf_idr_delete_index()
409 WARN_ON(p != idr_remove(&idrinfo->action_idr, in tcf_idr_delete_index()
410 p->tcfa_index)); in tcf_idr_delete_index()
411 mutex_unlock(&idrinfo->lock); in tcf_idr_delete_index()
419 ret = -EPERM; in tcf_idr_delete_index()
422 mutex_unlock(&idrinfo->lock); in tcf_idr_delete_index()
430 struct tc_action *p = kzalloc(ops->size, GFP_KERNEL); in tcf_idr_create()
431 struct tcf_idrinfo *idrinfo = tn->idrinfo; in tcf_idr_create()
432 int err = -ENOMEM; in tcf_idr_create()
435 return -ENOMEM; in tcf_idr_create()
436 refcount_set(&p->tcfa_refcnt, 1); in tcf_idr_create()
438 atomic_set(&p->tcfa_bindcnt, 1); in tcf_idr_create()
441 p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); in tcf_idr_create()
442 if (!p->cpu_bstats) in tcf_idr_create()
444 p->cpu_bstats_hw = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); in tcf_idr_create()
445 if (!p->cpu_bstats_hw) in tcf_idr_create()
447 p->cpu_qstats = alloc_percpu(struct gnet_stats_queue); in tcf_idr_create()
448 if (!p->cpu_qstats) in tcf_idr_create()
451 spin_lock_init(&p->tcfa_lock); in tcf_idr_create()
452 p->tcfa_index = index; in tcf_idr_create()
453 p->tcfa_tm.install = jiffies; in tcf_idr_create()
454 p->tcfa_tm.lastuse = jiffies; in tcf_idr_create()
455 p->tcfa_tm.firstuse = 0; in tcf_idr_create()
456 p->tcfa_flags = flags; in tcf_idr_create()
458 err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, in tcf_idr_create()
459 &p->tcfa_rate_est, in tcf_idr_create()
460 &p->tcfa_lock, NULL, est); in tcf_idr_create()
465 p->idrinfo = idrinfo; in tcf_idr_create()
466 __module_get(ops->owner); in tcf_idr_create()
467 p->ops = ops; in tcf_idr_create()
471 free_percpu(p->cpu_qstats); in tcf_idr_create()
473 free_percpu(p->cpu_bstats_hw); in tcf_idr_create()
475 free_percpu(p->cpu_bstats); in tcf_idr_create()
497 struct tcf_idrinfo *idrinfo = tn->idrinfo; in tcf_idr_cleanup()
499 mutex_lock(&idrinfo->lock); in tcf_idr_cleanup()
500 /* Remove ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */ in tcf_idr_cleanup()
501 WARN_ON(!IS_ERR(idr_remove(&idrinfo->action_idr, index))); in tcf_idr_cleanup()
502 mutex_unlock(&idrinfo->lock); in tcf_idr_cleanup()
515 struct tcf_idrinfo *idrinfo = tn->idrinfo; in tcf_idr_check_alloc()
520 mutex_lock(&idrinfo->lock); in tcf_idr_check_alloc()
522 p = idr_find(&idrinfo->action_idr, *index); in tcf_idr_check_alloc()
527 mutex_unlock(&idrinfo->lock); in tcf_idr_check_alloc()
532 refcount_inc(&p->tcfa_refcnt); in tcf_idr_check_alloc()
534 atomic_inc(&p->tcfa_bindcnt); in tcf_idr_check_alloc()
539 ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index, in tcf_idr_check_alloc()
542 idr_replace(&idrinfo->action_idr, in tcf_idr_check_alloc()
543 ERR_PTR(-EBUSY), *index); in tcf_idr_check_alloc()
548 ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index, in tcf_idr_check_alloc()
551 idr_replace(&idrinfo->action_idr, ERR_PTR(-EBUSY), in tcf_idr_check_alloc()
554 mutex_unlock(&idrinfo->lock); in tcf_idr_check_alloc()
562 struct idr *idr = &idrinfo->action_idr; in tcf_idrinfo_destroy()
571 module_put(ops->owner); in tcf_idrinfo_destroy()
575 idr_destroy(&idrinfo->action_idr); in tcf_idrinfo_destroy()
588 if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup) in tcf_register_action()
589 return -EINVAL; in tcf_register_action()
601 if (act->id == a->id || (strcmp(act->kind, a->kind) == 0)) { in tcf_register_action()
604 return -EEXIST; in tcf_register_action()
607 list_add_tail(&act->head, &act_base); in tcf_register_action()
618 int err = -ENOENT; in tcf_unregister_action()
623 list_del(&act->head); in tcf_unregister_action()
643 if (strcmp(kind, a->kind) == 0) { in tc_lookup_action_n()
644 if (try_module_get(a->owner)) in tc_lookup_action_n()
662 if (nla_strcmp(kind, a->kind) == 0) { in tc_lookup_action()
663 if (try_module_get(a->owner)) in tc_lookup_action()
692 jmp_prgcnt -= 1; in tcf_action_exec()
698 ret = a->ops->act(skb, a, res); in tcf_action_exec()
701 if (--repeat_ttl != 0) in tcf_action_exec()
714 jmp_ttl -= 1; in tcf_action_exec()
721 if (unlikely(!rcu_access_pointer(a->goto_chain))) { in tcf_action_exec()
745 ops = a->ops; in tcf_action_destroy()
748 module_put(ops->owner); in tcf_action_destroy()
760 /* Put all actions in this array, skip those NULL's. */
771 ops = a->ops; in tcf_action_put_many()
773 module_put(ops->owner); in tcf_action_put_many()
780 return a->ops->dump(skb, a, bind, ref); in tcf_action_dump_old()
789 if (nla_put_string(skb, TCA_KIND, a->ops->kind)) in tcf_action_dump_terse()
795 cookie = rcu_dereference(a->act_cookie); in tcf_action_dump_terse()
797 if (nla_put(skb, TCA_ACT_COOKIE, cookie->len, cookie->data)) { in tcf_action_dump_terse()
808 return -1; in tcf_action_dump_terse()
814 int err = -EINVAL; in tcf_action_dump_1()
816 struct nlattr *nest; in tcf_action_dump_1() local
821 if (a->hw_stats != TCA_ACT_HW_STATS_ANY && in tcf_action_dump_1()
823 a->hw_stats, TCA_ACT_HW_STATS_ANY)) in tcf_action_dump_1()
826 if (a->used_hw_stats_valid && in tcf_action_dump_1()
828 a->used_hw_stats, TCA_ACT_HW_STATS_ANY)) in tcf_action_dump_1()
831 if (a->tcfa_flags && in tcf_action_dump_1()
833 a->tcfa_flags, a->tcfa_flags)) in tcf_action_dump_1()
836 nest = nla_nest_start_noflag(skb, TCA_OPTIONS); in tcf_action_dump_1()
837 if (nest == NULL) in tcf_action_dump_1()
841 nla_nest_end(skb, nest); in tcf_action_dump_1()
847 return -1; in tcf_action_dump_1()
855 int err = -EINVAL, i; in tcf_action_dump()
856 struct nlattr *nest; in tcf_action_dump() local
860 nest = nla_nest_start_noflag(skb, i + 1); in tcf_action_dump()
861 if (nest == NULL) in tcf_action_dump()
867 nla_nest_end(skb, nest); in tcf_action_dump()
873 err = -EINVAL; in tcf_action_dump()
875 nla_nest_cancel(skb, nest); in tcf_action_dump()
885 c->data = nla_memdup(tb[TCA_ACT_COOKIE], GFP_KERNEL); in nla_memdup_cookie()
886 if (!c->data) { in nla_memdup_cookie()
890 c->len = nla_len(tb[TCA_ACT_COOKIE]); in nla_memdup_cookie()
929 idrinfo = a->idrinfo; in tcf_idr_insert_many()
930 mutex_lock(&idrinfo->lock); in tcf_idr_insert_many()
931 /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc if in tcf_idr_insert_many()
934 idr_replace(&idrinfo->action_idr, a, a->tcfa_index); in tcf_idr_insert_many()
935 mutex_unlock(&idrinfo->lock); in tcf_idr_insert_many()
954 err = -EINVAL; in tc_action_load_ops()
967 return ERR_PTR(-EINVAL); in tc_action_load_ops()
986 * indicate this using -EAGAIN. in tc_action_load_ops()
989 module_put(a_o->owner); in tc_action_load_ops()
990 return ERR_PTR(-EAGAIN); in tc_action_load_ops()
994 return ERR_PTR(-ENOENT); in tc_action_load_ops()
1024 err = -ENOMEM; in tcf_action_init_1()
1032 err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind, in tcf_action_init_1()
1035 err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held, in tcf_action_init_1()
1043 tcf_set_action_cookie(&a->act_cookie, cookie); in tcf_action_init_1()
1046 a->hw_stats = hw_stats; in tcf_action_init_1()
1052 kfree(cookie->data); in tcf_action_init_1()
1085 ops[i - 1] = a_o; in tcf_action_init()
1090 ops[i - 1], &init_res[i - 1], rtnl_held, in tcf_action_init()
1098 actions[i - 1] = act; in tcf_action_init()
1107 err = i - 1; in tcf_action_init()
1115 module_put(ops[i]->owner); in tcf_action_init()
1123 if (a->cpu_bstats) { in tcf_action_update_stats()
1124 _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets); in tcf_action_update_stats()
1126 this_cpu_ptr(a->cpu_qstats)->drops += drops; in tcf_action_update_stats()
1129 _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats_hw), in tcf_action_update_stats()
1134 _bstats_update(&a->tcfa_bstats, bytes, packets); in tcf_action_update_stats()
1135 a->tcfa_qstats.drops += drops; in tcf_action_update_stats()
1137 _bstats_update(&a->tcfa_bstats_hw, bytes, packets); in tcf_action_update_stats()
1154 if (p->type == TCA_OLD_COMPAT) in tcf_action_copy_stats()
1158 &p->tcfa_lock, &d, in tcf_action_copy_stats()
1164 &p->tcfa_lock, &d, TCA_ACT_PAD); in tcf_action_copy_stats()
1169 if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 || in tcf_action_copy_stats()
1170 gnet_stats_copy_basic_hw(NULL, &d, p->cpu_bstats_hw, in tcf_action_copy_stats()
1171 &p->tcfa_bstats_hw) < 0 || in tcf_action_copy_stats()
1172 gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 || in tcf_action_copy_stats()
1173 gnet_stats_copy_queue(&d, p->cpu_qstats, in tcf_action_copy_stats()
1174 &p->tcfa_qstats, in tcf_action_copy_stats()
1175 p->tcfa_qstats.qlen) < 0) in tcf_action_copy_stats()
1184 return -1; in tcf_action_copy_stats()
1194 struct nlattr *nest; in tca_get_fill() local
1200 t->tca_family = AF_UNSPEC; in tca_get_fill()
1201 t->tca__pad1 = 0; in tca_get_fill()
1202 t->tca__pad2 = 0; in tca_get_fill()
1204 nest = nla_nest_start_noflag(skb, TCA_ACT_TAB); in tca_get_fill()
1205 if (!nest) in tca_get_fill()
1211 nla_nest_end(skb, nest); in tca_get_fill()
1213 nlh->nlmsg_len = skb_tail_pointer(skb) - b; in tca_get_fill()
1214 return skb->len; in tca_get_fill()
1218 return -1; in tca_get_fill()
1230 return -ENOBUFS; in tcf_get_notify()
1231 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, event, in tcf_get_notify()
1235 return -EINVAL; in tcf_get_notify()
1256 err = -EINVAL; in tcf_action_get_1()
1264 err = -EINVAL; in tcf_action_get_1()
1270 err = -ENOENT; in tcf_action_get_1()
1271 if (ops->lookup(net, &a, index) == 0) { in tcf_action_get_1()
1276 module_put(ops->owner); in tcf_action_get_1()
1280 module_put(ops->owner); in tcf_action_get_1()
1294 struct nlattr *nest; in tca_action_flush() local
1298 int err = -ENOMEM; in tca_action_flush()
1311 err = -EINVAL; in tca_action_flush()
1319 nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, in tca_action_flush()
1326 t->tca_family = AF_UNSPEC; in tca_action_flush()
1327 t->tca__pad1 = 0; in tca_action_flush()
1328 t->tca__pad2 = 0; in tca_action_flush()
1330 nest = nla_nest_start_noflag(skb, TCA_ACT_TAB); in tca_action_flush()
1331 if (!nest) { in tca_action_flush()
1336 err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack); in tca_action_flush()
1338 nla_nest_cancel(skb, nest); in tca_action_flush()
1342 nla_nest_end(skb, nest); in tca_action_flush()
1344 nlh->nlmsg_len = skb_tail_pointer(skb) - b; in tca_action_flush()
1345 nlh->nlmsg_flags |= NLM_F_ROOT; in tca_action_flush()
1346 module_put(ops->owner); in tca_action_flush()
1348 n->nlmsg_flags & NLM_F_ECHO); in tca_action_flush()
1357 module_put(ops->owner); in tca_action_flush()
1369 const struct tc_action_ops *ops = a->ops; in tcf_action_delete()
1373 struct tcf_idrinfo *idrinfo = a->idrinfo; in tcf_action_delete()
1374 u32 act_index = a->tcfa_index; in tcf_action_delete()
1379 module_put(ops->owner); in tcf_action_delete()
1402 return -ENOBUFS; in tcf_del_notify()
1404 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, 0, RTM_DELACTION, in tcf_del_notify()
1408 return -EINVAL; in tcf_del_notify()
1420 n->nlmsg_flags & NLM_F_ECHO); in tcf_del_notify()
1441 if (event == RTM_DELACTION && n->nlmsg_flags & NLM_F_ROOT) { in tca_action_gd()
1446 return -EINVAL; in tca_action_gd()
1456 actions[i - 1] = act; in tca_action_gd()
1484 return -ENOBUFS; in tcf_add_notify()
1486 if (tca_get_fill(skb, actions, portid, n->nlmsg_seq, n->nlmsg_flags, in tcf_add_notify()
1490 return -EINVAL; in tcf_add_notify()
1494 n->nlmsg_flags & NLM_F_ECHO); in tcf_add_notify()
1512 if (ret != -EAGAIN) in tcf_action_add()
1537 struct net *net = sock_net(skb->sk); in tc_ctl_action()
1542 if ((n->nlmsg_type != RTM_GETACTION) && in tc_ctl_action()
1544 return -EPERM; in tc_ctl_action()
1553 return -EINVAL; in tc_ctl_action()
1556 /* n->nlmsg_flags & NLM_F_CREATE */ in tc_ctl_action()
1557 switch (n->nlmsg_type) { in tc_ctl_action()
1565 if (n->nlmsg_flags & NLM_F_REPLACE) in tc_ctl_action()
1609 struct net *net = sock_net(skb->sk); in tc_dump_action()
1612 struct nlattr *nest; in tc_dump_action() local
1615 struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); in tc_dump_action()
1624 ret = nlmsg_parse_deprecated(cb->nlh, sizeof(struct tcamsg), tb, in tc_dump_action()
1625 TCA_ROOT_MAX, tcaa_policy, cb->extack); in tc_dump_action()
1639 cb->args[2] = 0; in tc_dump_action()
1642 cb->args[2] = bf.value; in tc_dump_action()
1649 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, in tc_dump_action()
1650 cb->nlh->nlmsg_type, sizeof(*t), 0); in tc_dump_action()
1655 jiffy_since = jiffies - msecs_to_jiffies(msecs_since); in tc_dump_action()
1658 t->tca_family = AF_UNSPEC; in tc_dump_action()
1659 t->tca__pad1 = 0; in tc_dump_action()
1660 t->tca__pad2 = 0; in tc_dump_action()
1661 cb->args[3] = jiffy_since; in tc_dump_action()
1666 nest = nla_nest_start_noflag(skb, TCA_ACT_TAB); in tc_dump_action()
1667 if (nest == NULL) in tc_dump_action()
1670 ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL); in tc_dump_action()
1675 nla_nest_end(skb, nest); in tc_dump_action()
1676 ret = skb->len; in tc_dump_action()
1677 act_count = cb->args[1]; in tc_dump_action()
1679 cb->args[1] = 0; in tc_dump_action()
1683 nlh->nlmsg_len = skb_tail_pointer(skb) - b; in tc_dump_action()
1684 if (NETLINK_CB(cb->skb).portid && ret) in tc_dump_action()
1685 nlh->nlmsg_flags |= NLM_F_MULTI; in tc_dump_action()
1686 module_put(a_o->owner); in tc_dump_action()
1687 return skb->len; in tc_dump_action()
1690 module_put(a_o->owner); in tc_dump_action()
1692 return skb->len; in tc_dump_action()