Lines Matching +full:rates +full:- +full:ru
1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
43 -------------
56 - "queues", which have no internal structure visible from outside.
57 - "schedulers", which split all the packets to "traffic classes",
75 ---dequeue
80 Queue is really empty if q->q.qlen == 0.
81 For complicated disciplines with multiple queues q->q is not
82 real packet queue, but however q->q.qlen must be valid.
84 ---enqueue
89 NET_XMIT_DROP - this packet dropped
91 NET_XMIT_CN - probably this packet enqueued, but another one dropped.
96 ---peek
100 ---reset
105 ---init
109 ---destroy
113 ---change
136 int rc = -EEXIST;
139 for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)
140 if (!strcmp(qops->id, q->id))
143 if (qops->enqueue == NULL)
144 qops->enqueue = noop_qdisc_ops.enqueue;
145 if (qops->peek == NULL) {
146 if (qops->dequeue == NULL)
147 qops->peek = noop_qdisc_ops.peek;
151 if (qops->dequeue == NULL)
152 qops->dequeue = noop_qdisc_ops.dequeue;
154 if (qops->cl_ops) {
155 const struct Qdisc_class_ops *cops = qops->cl_ops;
157 if (!(cops->find && cops->walk && cops->leaf))
160 if (cops->tcf_block && !(cops->bind_tcf && cops->unbind_tcf))
164 qops->next = NULL;
172 rc = -EINVAL;
180 int err = -ENOENT;
183 for (qp = &qdisc_base; (q = *qp) != NULL; qp = &q->next)
187 *qp = q->next;
188 q->next = NULL;
193 WARN(err, "unregister qdisc(%s) failed\n", qops->id);
201 strscpy(name, default_qdisc_ops->id, len);
209 for (q = qdisc_base; q; q = q->next) {
210 if (!strcmp(name, q->id)) {
211 if (!bpf_try_module_get(q, q->owner))
226 return -EPERM;
241 bpf_module_put(default_qdisc_ops, default_qdisc_ops->owner);
246 return ops ? 0 : -ENOENT;
268 return (root->handle == handle ? root : NULL);
270 if (!(root->flags & TCQ_F_BUILTIN) &&
271 root->handle == handle)
274 hash_for_each_possible_rcu(qdisc_dev(root)->qdisc_hash, q, hash, handle,
276 if (q->handle == handle)
284 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
286 hash_add_rcu(qdisc_dev(q)->qdisc_hash, &q->hash, q->handle);
288 q->flags |= TCQ_F_INVISIBLE;
295 if ((q->parent != TC_H_ROOT) && !(q->flags & TCQ_F_INGRESS)) {
297 hash_del_rcu(&q->hash);
308 q = qdisc_match_from_root(rtnl_dereference(dev->qdisc), handle);
314 rtnl_dereference(dev_ingress_queue(dev)->qdisc_sleeping),
327 q = qdisc_match_from_root(rcu_dereference(dev->qdisc), handle);
333 q = qdisc_match_from_root(rcu_dereference(nq->qdisc_sleeping),
343 const struct Qdisc_class_ops *cops = p->ops->cl_ops;
347 return ERR_PTR(-EOPNOTSUPP);
349 cl = cops->find(p, classid);
353 return ERR_PTR(-ENOENT);
355 return cops->leaf(p, cl);
366 for (q = qdisc_base; q; q = q->next) {
367 if (nla_strcmp(kind, q->id) == 0) {
368 if (!bpf_try_module_get(q, q->owner))
397 int low = roundup(r->mpu, 48);
399 int cell_low = low >> r->cell_log;
400 int cell_high = (high >> r->cell_log) - 1;
402 /* rtab is too inaccurate at rates > 100Mbit/s */
403 if ((r->rate > (100000000/8)) || (rtab[0] == 0)) {
425 if (tab == NULL || r->rate == 0 ||
426 r->cell_log == 0 || r->cell_log >= 32 ||
432 for (rtab = qdisc_rtab_list; rtab; rtab = rtab->next) {
433 if (!memcmp(&rtab->rate, r, sizeof(struct tc_ratespec)) &&
434 !memcmp(&rtab->data, nla_data(tab), TC_RTAB_SIZE)) {
435 rtab->refcnt++;
442 rtab->rate = *r;
443 rtab->refcnt = 1;
444 memcpy(rtab->data, nla_data(tab), TC_RTAB_SIZE);
445 if (r->linklayer == TC_LINKLAYER_UNAWARE)
446 r->linklayer = __detect_linklayer(r, rtab->data);
447 rtab->next = qdisc_rtab_list;
460 if (!tab || --tab->refcnt)
465 rtabp = &rtab->next) {
467 *rtabp = rtab->next;
498 return ERR_PTR(-EINVAL);
503 if (s->tsize > 0) {
506 return ERR_PTR(-EINVAL);
512 if (tsize != s->tsize || (!tab && tsize > 0)) {
514 return ERR_PTR(-EINVAL);
518 if (memcmp(&stab->szopts, s, sizeof(*s)))
521 memcmp(stab->data, tab, flex_array_size(stab, data, tsize)))
523 stab->refcnt++;
527 if (s->size_log > STAB_SIZE_LOG_MAX ||
528 s->cell_log > STAB_SIZE_LOG_MAX) {
530 return ERR_PTR(-EINVAL);
535 return ERR_PTR(-ENOMEM);
537 stab->refcnt = 1;
538 stab->szopts = *s;
540 memcpy(stab->data, tab, flex_array_size(stab, data, tsize));
542 list_add_tail(&stab->list, &qdisc_stab_list);
552 if (--tab->refcnt == 0) {
553 list_del(&tab->list);
566 if (nla_put(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts))
570 return skb->len;
573 return -1;
581 pkt_len = skb->len + stab->szopts.overhead;
582 if (unlikely(!stab->szopts.tsize))
585 slot = pkt_len + stab->szopts.cell_align;
589 slot >>= stab->szopts.cell_log;
590 if (likely(slot < stab->szopts.tsize))
591 pkt_len = stab->data[slot];
593 pkt_len = stab->data[stab->szopts.tsize - 1] *
594 (slot / stab->szopts.tsize) +
595 stab->data[slot % stab->szopts.tsize];
597 pkt_len <<= stab->szopts.size_log;
601 qdisc_skb_cb(skb)->pkt_len = pkt_len;
610 __netif_schedule(qdisc_root(wd->qdisc));
619 hrtimer_setup(&wd->timer, qdisc_watchdog, clockid, HRTIMER_MODE_ABS_PINNED);
620 wd->qdisc = qdisc;
637 &qdisc_root_sleeping(wd->qdisc)->state);
642 if (hrtimer_is_queued(&wd->timer)) {
645 softexpires = ktime_to_ns(hrtimer_get_softexpires(&wd->timer));
649 if (softexpires - expires <= delta_ns)
653 hrtimer_start_range_ns(&wd->timer,
662 hrtimer_cancel(&wd->timer);
689 if (clhash->hashelems * 4 <= clhash->hashsize * 3)
691 nsize = clhash->hashsize * 2;
692 nmask = nsize - 1;
697 ohash = clhash->hash;
698 osize = clhash->hashsize;
703 h = qdisc_class_hash(cl->classid, nmask);
704 hlist_add_head(&cl->hnode, &nhash[h]);
707 clhash->hash = nhash;
708 clhash->hashsize = nsize;
709 clhash->hashmask = nmask;
720 clhash->hash = qdisc_class_hash_alloc(size);
721 if (!clhash->hash)
722 return -ENOMEM;
723 clhash->hashsize = size;
724 clhash->hashmask = size - 1;
725 clhash->hashelems = 0;
732 kvfree(clhash->hash);
741 INIT_HLIST_NODE(&cl->hnode);
742 h = qdisc_class_hash(cl->classid, clhash->hashmask);
743 hlist_add_head(&cl->hnode, &clhash->hash[h]);
744 clhash->hashelems++;
751 hlist_del(&cl->hnode);
752 clhash->hashelems--;
757 * Possible range is [8000-FFFF]:0000 (0x8000 values)
771 } while (--i > 0);
786 while ((parentid = sch->parent)) {
790 if (sch->flags & TCQ_F_NOPARENT)
793 notify = !sch->q.qlen;
800 cops = sch->ops->cl_ops;
801 if (notify && cops->qlen_notify) {
805 cl = cops->find(sch, parentid);
806 cops->qlen_notify(sch, cl);
808 sch->q.qlen -= n;
809 sch->qstats.backlog -= len;
822 sch->flags &= ~TCQ_F_OFFLOADED;
823 if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
826 err = dev->netdev_ops->ndo_setup_tc(dev, type, type_data);
827 if (err == -EOPNOTSUPP)
831 sch->flags |= TCQ_F_OFFLOADED;
845 if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
848 err = dev->netdev_ops->ndo_setup_tc(dev, type, type_data);
857 any_qdisc_is_offloaded = new->flags & TCQ_F_OFFLOADED;
858 any_qdisc_is_offloaded |= sch && sch->flags & TCQ_F_OFFLOADED;
859 any_qdisc_is_offloaded |= old && old->flags & TCQ_F_OFFLOADED;
870 const struct net_device_ops *ops = dev->netdev_ops;
878 if (ops->ndo_setup_tc)
879 ops->ndo_setup_tc(dev, TC_QUERY_CAPS, &base);
889 .handle = new ? new->handle : 0,
890 .ingress = (new && new->flags & TCQ_F_INGRESS) ||
891 (old && old->flags & TCQ_F_INGRESS),
917 tcm->tcm_family = AF_UNSPEC;
918 tcm->tcm__pad1 = 0;
919 tcm->tcm__pad2 = 0;
920 tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
921 tcm->tcm_parent = clid;
922 tcm->tcm_handle = q->handle;
923 tcm->tcm_info = refcount_read(&q->refcnt);
924 if (nla_put_string(skb, TCA_KIND, q->ops->id))
926 if (q->ops->ingress_block_get) {
927 block_index = q->ops->ingress_block_get(q);
932 if (q->ops->egress_block_get) {
933 block_index = q->ops->egress_block_get(q);
938 if (q->ops->dump && q->ops->dump(q, skb) < 0)
940 if (nla_put_u8(skb, TCA_HW_OFFLOAD, !!(q->flags & TCQ_F_OFFLOADED)))
944 stab = rtnl_dereference(q->stab);
952 if (q->ops->dump_stats && q->ops->dump_stats(q, &d) < 0)
956 cpu_bstats = q->cpu_bstats;
957 cpu_qstats = q->cpu_qstats;
960 if (gnet_stats_copy_basic(&d, cpu_bstats, &q->bstats, true) < 0 ||
961 gnet_stats_copy_rate_est(&d, &q->rate_est) < 0 ||
962 gnet_stats_copy_queue(&d, cpu_qstats, &q->qstats, qlen) < 0)
968 if (extack && extack->_msg &&
969 nla_put_string(skb, TCA_EXT_WARN_MSG, extack->_msg))
972 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
974 return skb->len;
979 return -1;
984 if (q->flags & TCQ_F_BUILTIN)
986 if ((q->flags & TCQ_F_INVISIBLE) && !dump_invisible)
1001 return -ENOBUFS;
1004 if (tc_fill_qdisc(skb, q, clid, portid, n->nlmsg_seq, 0,
1009 if (skb->len)
1011 n->nlmsg_flags & NLM_F_ECHO);
1015 return -EINVAL;
1026 if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
1031 return -ENOBUFS;
1034 if (tc_fill_qdisc(skb, old, clid, portid, n->nlmsg_seq,
1039 if (tc_fill_qdisc(skb, new, clid, portid, n->nlmsg_seq,
1044 if (skb->len)
1046 n->nlmsg_flags & NLM_F_ECHO);
1050 return -EINVAL;
1067 sch->flags &= ~TCQ_F_NOLOCK;
1068 if (!(sch->flags & TCQ_F_CPUSTATS))
1071 free_percpu(sch->cpu_bstats);
1072 free_percpu(sch->cpu_qstats);
1073 sch->cpu_bstats = NULL;
1074 sch->cpu_qstats = NULL;
1075 sch->flags &= ~TCQ_F_CPUSTATS;
1100 num_q = dev->num_tx_queues;
1101 if ((q && q->flags & TCQ_F_INGRESS) ||
1102 (new && new->flags & TCQ_F_INGRESS)) {
1107 return -ENOENT;
1110 q = rtnl_dereference(dev_queue->qdisc_sleeping);
1118 return -EBUSY;
1122 if (dev->flags & IFF_UP)
1127 if (new && new->ops->attach && !ingress)
1154 old = rtnl_dereference(dev->qdisc);
1155 if (new && !new->ops->attach)
1157 rcu_assign_pointer(dev->qdisc, new ? : &noop_qdisc);
1161 if (new && new->ops->attach)
1162 new->ops->attach(new);
1165 if (dev->flags & IFF_UP)
1168 const struct Qdisc_class_ops *cops = parent->ops->cl_ops;
1173 if (new && (new->flags & TCQ_F_NOLOCK) && !(parent->flags & TCQ_F_NOLOCK))
1176 if (!cops || !cops->graft)
1177 return -EOPNOTSUPP;
1179 cl = cops->find(parent, classid);
1182 return -ENOENT;
1185 if (new && new->ops == &noqueue_qdisc_ops) {
1187 return -EINVAL;
1191 !(parent->flags & TCQ_F_MQROOT) &&
1192 rcu_access_pointer(new->stab)) {
1194 return -EINVAL;
1196 err = cops->graft(parent, cl, new, &old, extack);
1214 return -EINVAL;
1216 if (!sch->ops->ingress_block_set) {
1218 return -EOPNOTSUPP;
1220 sch->ops->ingress_block_set(sch, block_index);
1227 return -EINVAL;
1229 if (!sch->ops->egress_block_set) {
1231 return -EOPNOTSUPP;
1233 sch->ops->egress_block_set(sch, block_index);
1258 err = -ENOENT;
1269 sch->parent = parent;
1272 if (!(sch->flags & TCQ_F_INGRESS)) {
1275 err = -EINVAL;
1284 err = -ENOSPC;
1289 sch->flags |= TCQ_F_ONETXQUEUE;
1292 sch->handle = handle;
1300 if ((dev->priv_flags & IFF_NO_QUEUE) && (dev->tx_queue_len == 0)) {
1301 WRITE_ONCE(dev->tx_queue_len, DEFAULT_TX_QUEUE_LEN);
1315 rcu_assign_pointer(sch->stab, stab);
1318 if (ops->init) {
1319 err = ops->init(sch, tca[TCA_OPTIONS], extack);
1325 err = -EOPNOTSUPP;
1326 if (sch->flags & TCQ_F_MQROOT) {
1327 NL_SET_ERR_MSG(extack, "Cannot attach rate estimator to a multi-queue root qdisc");
1331 err = gen_new_estimator(&sch->bstats,
1332 sch->cpu_bstats,
1333 &sch->rate_est,
1349 /* Even if ops->init() failed, we call ops->destroy()
1352 if (ops->destroy)
1353 ops->destroy(sch);
1354 qdisc_put_stab(rtnl_dereference(sch->stab));
1356 lockdep_unregister_key(&sch->root_lock_key);
1357 netdev_put(dev, &sch->dev_tracker);
1360 bpf_module_put(ops, ops->owner);
1373 if (!sch->ops->change) {
1375 return -EINVAL;
1379 return -EOPNOTSUPP;
1381 err = sch->ops->change(sch, tca[TCA_OPTIONS], extack);
1392 ostab = rtnl_dereference(sch->stab);
1393 rcu_assign_pointer(sch->stab, stab);
1399 if (sch->flags & TCQ_F_MQROOT)
1401 gen_replace_estimator(&sch->bstats,
1402 sch->cpu_bstats,
1403 &sch->rate_est,
1425 if (q->ops->cl_ops == NULL)
1432 q->ops->cl_ops->walk(q, &arg.w);
1433 return arg.w.stop ? -ELOOP : 0;
1440 const struct Qdisc_class_ops *cops = q->ops->cl_ops;
1443 leaf = cops->leaf(q, cl);
1445 if (leaf == arg->p || arg->depth > 7)
1446 return -ELOOP;
1447 return check_loop(leaf, arg->p, arg->depth + 1);
1473 struct net *net = sock_net(skb->sk);
1479 clid = tcm->tcm_parent;
1486 return -ENOENT;
1490 q = rtnl_dereference(dev_ingress_queue(dev)->qdisc_sleeping);
1493 q = rtnl_dereference(dev->qdisc);
1497 return -ENOENT;
1502 if (tcm->tcm_handle && q->handle != tcm->tcm_handle) {
1504 return -EINVAL;
1507 q = qdisc_lookup(dev, tcm->tcm_handle);
1510 return -ENOENT;
1514 if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) {
1516 return -EINVAL;
1519 if (n->nlmsg_type == RTM_DELQDISC) {
1522 return -EINVAL;
1524 if (q->handle == 0) {
1526 return -ENOENT;
1540 struct net *net = sock_net(skb->sk);
1551 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
1553 return -ENODEV;
1564 return (n->nlmsg_flags & NLM_F_CREATE &&
1565 n->nlmsg_flags & NLM_F_REPLACE);
1570 return (n->nlmsg_flags & NLM_F_CREATE &&
1571 n->nlmsg_flags & NLM_F_EXCL);
1576 return (!(n->nlmsg_flags & NLM_F_CREATE) &&
1577 !(n->nlmsg_flags & NLM_F_REPLACE) &&
1578 !(n->nlmsg_flags & NLM_F_EXCL));
1592 clid = tcm->tcm_parent;
1600 return -ENOENT;
1606 q = rtnl_dereference(dev_ingress_queue(dev)->qdisc_sleeping);
1609 q = rtnl_dereference(dev->qdisc);
1613 if (q && q->handle == 0)
1616 if (!q || !tcm->tcm_handle || q->handle != tcm->tcm_handle) {
1617 if (tcm->tcm_handle) {
1618 if (q && !(n->nlmsg_flags & NLM_F_REPLACE)) {
1620 return -EEXIST;
1622 if (TC_H_MIN(tcm->tcm_handle)) {
1624 return -EINVAL;
1626 q = qdisc_lookup(dev, tcm->tcm_handle);
1629 if (q->parent != tcm->tcm_parent) {
1631 return -EINVAL;
1633 if (n->nlmsg_flags & NLM_F_EXCL) {
1635 return -EEXIST;
1638 nla_strcmp(tca[TCA_KIND], q->ops->id)) {
1640 return -EINVAL;
1642 if (q->flags & TCQ_F_INGRESS) {
1645 return -EINVAL;
1650 return -ELOOP;
1654 return -EINVAL;
1670 * operation - just let it fallthrough..
1688 nla_strcmp(tca[TCA_KIND], q->ops->id)) {
1698 if (!tcm->tcm_handle) {
1700 return -EINVAL;
1702 q = qdisc_lookup(dev, tcm->tcm_handle);
1708 return -ENOENT;
1710 if (n->nlmsg_flags & NLM_F_EXCL) {
1712 return -EEXIST;
1714 if (tca[TCA_KIND] && nla_strcmp(tca[TCA_KIND], q->ops->id)) {
1716 return -EINVAL;
1720 qdisc_notify(sock_net(skb->sk), skb, n, clid, NULL, q, extack);
1724 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
1726 return -ENOENT;
1732 tcm->tcm_parent, tcm->tcm_parent,
1736 err = -ENOENT;
1741 if (p && p->ops->cl_ops && p->ops->cl_ops->select_queue)
1742 dev_queue = p->ops->cl_ops->select_queue(p, tcm);
1744 dev_queue = p->dev_queue;
1749 tcm->tcm_parent, tcm->tcm_handle,
1776 bpf_module_put(ops, ops->owner);
1793 struct net *net = sock_net(skb->sk);
1807 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
1809 return -ENODEV;
1835 tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).portid,
1836 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1845 * If we've already dumped the top-level (ingress) qdisc above and the global
1851 hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
1857 tc_fill_qdisc(skb, q, q->parent, NETLINK_CB(cb->skb).portid,
1858 cb->nlh->nlmsg_seq, NLM_F_MULTI,
1868 ret = -1;
1874 struct net *net = sock_net(skb->sk);
1878 const struct nlmsghdr *nlh = cb->nlh;
1882 s_idx = cb->args[0];
1883 s_q_idx = q_idx = cb->args[1];
1889 rtm_tca_policy, cb->extack);
1903 if (tc_dump_qdisc_root(rtnl_dereference(dev->qdisc),
1912 tc_dump_qdisc_root(rtnl_dereference(dev_queue->qdisc_sleeping),
1925 cb->args[0] = idx;
1926 cb->args[1] = q_idx;
1928 return skb->len;
1945 const struct Qdisc_class_ops *cl_ops = q->ops->cl_ops;
1952 tcm->tcm_family = AF_UNSPEC;
1953 tcm->tcm__pad1 = 0;
1954 tcm->tcm__pad2 = 0;
1955 tcm->tcm_ifindex = qdisc_dev(q)->ifindex;
1956 tcm->tcm_parent = q->handle;
1957 tcm->tcm_handle = q->handle;
1958 tcm->tcm_info = 0;
1959 if (nla_put_string(skb, TCA_KIND, q->ops->id))
1961 if (cl_ops->dump && cl_ops->dump(q, cl, skb, tcm) < 0)
1968 if (cl_ops->dump_stats && cl_ops->dump_stats(q, cl, &d) < 0)
1974 if (extack && extack->_msg &&
1975 nla_put_string(skb, TCA_EXT_WARN_MSG, extack->_msg))
1978 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
1980 return skb->len;
1985 return -1;
1995 if (!rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC))
2000 return -ENOBUFS;
2002 if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0, event, extack) < 0) {
2004 return -EINVAL;
2008 n->nlmsg_flags & NLM_F_ECHO);
2020 return -ENOBUFS;
2022 if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0, RTM_NEWTCLASS,
2025 return -EINVAL;
2029 n->nlmsg_flags & NLM_F_ECHO);
2042 if (!cops->delete)
2043 return -EOPNOTSUPP;
2045 if (rtnl_notify_needed(net, n->nlmsg_flags, RTNLGRP_TC)) {
2048 return -ENOBUFS;
2050 if (tc_fill_tclass(skb, q, cl, portid, n->nlmsg_seq, 0,
2053 return -EINVAL;
2059 err = cops->delete(q, cl, extack);
2066 n->nlmsg_flags & NLM_F_ECHO);
2083 if (n && tp->ops->bind_class) {
2084 struct Qdisc *q = tcf_block_q(tp->chain->block);
2087 tp->ops->bind_class(n, a->classid, a->cl, q, a->base);
2104 const struct Qdisc_class_ops *cops = q->ops->cl_ops;
2108 block = cops->tcf_block(q, cl, NULL);
2121 arg.classid = a->clid;
2123 arg.cl = a->new_cl;
2124 tp->ops->walk(tp, &arg.w, true);
2134 const struct Qdisc_class_ops *cops = q->ops->cl_ops;
2137 if (!cops->tcf_block)
2143 q->ops->cl_ops->walk(q, &args.w);
2161 struct net *net = sock_net(skb->sk);
2172 parent == TC_H_UNSPEC - unspecified parent.
2173 parent == TC_H_ROOT - class is root, which has no parent.
2174 parent == X:0 - parent is root class.
2175 parent == X:Y - parent is a node in hierarchy.
2176 parent == 0:Y - parent is X:Y, where X:0 is qdisc.
2178 handle == 0:0 - generate handle from kernel pool.
2179 handle == 0:Y - class is X:Y, where X:0 is qdisc.
2180 handle == X:Y - clear.
2181 handle == X:0 - root class.
2186 portid = tcm->tcm_parent;
2187 clid = tcm->tcm_handle;
2196 return -EINVAL;
2200 qid = rtnl_dereference(dev->qdisc)->handle;
2211 qid = rtnl_dereference(dev->qdisc)->handle;
2217 return -ENOENT;
2220 cops = q->ops->cl_ops;
2222 return -EINVAL;
2232 cl = cops->find(q, clid);
2235 err = -ENOENT;
2236 if (n->nlmsg_type != RTM_NEWTCLASS ||
2237 !(n->nlmsg_flags & NLM_F_CREATE))
2240 switch (n->nlmsg_type) {
2242 err = -EEXIST;
2243 if (n->nlmsg_flags & NLM_F_EXCL)
2255 err = -EINVAL;
2262 return -EOPNOTSUPP;
2268 return -EINVAL;
2272 err = -EOPNOTSUPP;
2273 if (cops->change)
2274 err = cops->change(q, clid, portid, tca, &new_cl, extack);
2288 struct net *net = sock_net(skb->sk);
2299 dev = __dev_get_by_index(net, tcm->tcm_ifindex);
2301 return -ENODEV;
2321 return tc_fill_tclass(a->skb, q, cl, NETLINK_CB(a->cb->skb).portid,
2322 a->cb->nlh->nlmsg_seq, NLM_F_MULTI,
2333 *t_p < s_t || !q->ops->cl_ops ||
2334 (tcm->tcm_parent &&
2335 TC_H_MAJ(tcm->tcm_parent) != q->handle)) {
2340 memset(&cb->args[1], 0, sizeof(cb->args)-sizeof(cb->args[0]));
2345 arg.w.skip = cb->args[1];
2347 q->ops->cl_ops->walk(q, &arg.w);
2348 cb->args[1] = arg.w.count;
2350 return -1;
2366 return -1;
2371 if (tcm->tcm_parent) {
2372 q = qdisc_match_from_root(root, TC_H_MAJ(tcm->tcm_parent));
2375 return -1;
2378 hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
2380 return -1;
2392 s_t = cb->args[0];
2395 if (tc_dump_tclass_root(rtnl_dereference(dev->qdisc),
2401 tc_dump_tclass_root(rtnl_dereference(dev_queue->qdisc_sleeping),
2406 cb->args[0] = t;
2408 return skb->len;
2413 struct tcmsg *tcm = nlmsg_data(cb->nlh);
2414 struct net *net = sock_net(skb->sk);
2418 if (nlmsg_len(cb->nlh) < sizeof(*tcm))
2421 dev = dev_get_by_index(net, tcm->tcm_ifindex);
2449 e = proc_create_single("psched", 0, net->proc_net, psched_show);
2451 return -ENOMEM;
2458 remove_proc_entry("psched", net->proc_net);