hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/sched/sch_api.c
....@@ -1044,12 +1044,12 @@
10441044
10451045 if (parent == NULL) {
10461046 unsigned int i, num_q, ingress;
1047
+ struct netdev_queue *dev_queue;
10471048
10481049 ingress = 0;
10491050 num_q = dev->num_tx_queues;
10501051 if ((q && q->flags & TCQ_F_INGRESS) ||
10511052 (new && new->flags & TCQ_F_INGRESS)) {
1052
- num_q = 1;
10531053 ingress = 1;
10541054 if (!dev_ingress_queue(dev)) {
10551055 NL_SET_ERR_MSG(extack, "Device does not have an ingress queue");
....@@ -1065,18 +1065,18 @@
10651065 if (new && new->ops->attach)
10661066 goto skip;
10671067
1068
- for (i = 0; i < num_q; i++) {
1069
- struct netdev_queue *dev_queue = dev_ingress_queue(dev);
1070
-
1071
- if (!ingress)
1068
+ if (!ingress) {
1069
+ for (i = 0; i < num_q; i++) {
10721070 dev_queue = netdev_get_tx_queue(dev, i);
1071
+ old = dev_graft_qdisc(dev_queue, new);
10731072
1074
- old = dev_graft_qdisc(dev_queue, new);
1075
- if (new && i > 0)
1076
- qdisc_refcount_inc(new);
1077
-
1078
- if (!ingress)
1073
+ if (new && i > 0)
1074
+ qdisc_refcount_inc(new);
10791075 qdisc_put(old);
1076
+ }
1077
+ } else {
1078
+ dev_queue = dev_ingress_queue(dev);
1079
+ old = dev_graft_qdisc(dev_queue, new);
10801080 }
10811081
10821082 skip:
....@@ -1112,6 +1112,11 @@
11121112 if (!cl) {
11131113 NL_SET_ERR_MSG(extack, "Specified class not found");
11141114 return -ENOENT;
1115
+ }
1116
+
1117
+ if (new && new->ops == &noqueue_qdisc_ops) {
1118
+ NL_SET_ERR_MSG(extack, "Cannot assign noqueue to a class");
1119
+ return -EINVAL;
11151120 }
11161121
11171122 err = cops->graft(parent, cl, new, &old, extack);
....@@ -1218,7 +1223,12 @@
12181223 sch->parent = parent;
12191224
12201225 if (handle == TC_H_INGRESS) {
1221
- sch->flags |= TCQ_F_INGRESS;
1226
+ if (!(sch->flags & TCQ_F_INGRESS)) {
1227
+ NL_SET_ERR_MSG(extack,
1228
+ "Specified parent ID is reserved for ingress and clsact Qdiscs");
1229
+ err = -EINVAL;
1230
+ goto err_out3;
1231
+ }
12221232 handle = TC_H_MAKE(TC_H_INGRESS, 0);
12231233 } else {
12241234 if (handle == 0) {
....@@ -1503,10 +1513,28 @@
15031513 return 0;
15041514 }
15051515
1516
+static bool req_create_or_replace(struct nlmsghdr *n)
1517
+{
1518
+ return (n->nlmsg_flags & NLM_F_CREATE &&
1519
+ n->nlmsg_flags & NLM_F_REPLACE);
1520
+}
1521
+
1522
+static bool req_create_exclusive(struct nlmsghdr *n)
1523
+{
1524
+ return (n->nlmsg_flags & NLM_F_CREATE &&
1525
+ n->nlmsg_flags & NLM_F_EXCL);
1526
+}
1527
+
1528
+static bool req_change(struct nlmsghdr *n)
1529
+{
1530
+ return (!(n->nlmsg_flags & NLM_F_CREATE) &&
1531
+ !(n->nlmsg_flags & NLM_F_REPLACE) &&
1532
+ !(n->nlmsg_flags & NLM_F_EXCL));
1533
+}
1534
+
15061535 /*
15071536 * Create/change qdisc.
15081537 */
1509
-
15101538 static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
15111539 struct netlink_ext_ack *extack)
15121540 {
....@@ -1579,10 +1607,19 @@
15791607 NL_SET_ERR_MSG(extack, "Invalid qdisc name");
15801608 return -EINVAL;
15811609 }
1610
+ if (q->flags & TCQ_F_INGRESS) {
1611
+ NL_SET_ERR_MSG(extack,
1612
+ "Cannot regraft ingress or clsact Qdiscs");
1613
+ return -EINVAL;
1614
+ }
15821615 if (q == p ||
15831616 (p && check_loop(q, p, 0))) {
15841617 NL_SET_ERR_MSG(extack, "Qdisc parent/child loop detected");
15851618 return -ELOOP;
1619
+ }
1620
+ if (clid == TC_H_INGRESS) {
1621
+ NL_SET_ERR_MSG(extack, "Ingress cannot graft directly");
1622
+ return -EINVAL;
15861623 }
15871624 qdisc_refcount_inc(q);
15881625 goto graft;
....@@ -1594,27 +1631,35 @@
15941631 *
15951632 * We know, that some child q is already
15961633 * attached to this parent and have choice:
1597
- * either to change it or to create/graft new one.
1634
+ * 1) change it or 2) create/graft new one.
1635
+ * If the requested qdisc kind is different
1636
+ * than the existing one, then we choose graft.
1637
+ * If they are the same then this is "change"
1638
+ * operation - just let it fallthrough..
15981639 *
15991640 * 1. We are allowed to create/graft only
1600
- * if CREATE and REPLACE flags are set.
1641
+ * if the request is explicitly stating
1642
+ * "please create if it doesn't exist".
16011643 *
1602
- * 2. If EXCL is set, requestor wanted to say,
1603
- * that qdisc tcm_handle is not expected
1644
+ * 2. If the request is to exclusive create
1645
+ * then the qdisc tcm_handle is not expected
16041646 * to exist, so that we choose create/graft too.
16051647 *
16061648 * 3. The last case is when no flags are set.
1649
+ * This will happen when for example tc
1650
+ * utility issues a "change" command.
16071651 * Alas, it is sort of hole in API, we
16081652 * cannot decide what to do unambiguously.
1609
- * For now we select create/graft, if
1610
- * user gave KIND, which does not match existing.
1653
+ * For now we select create/graft.
16111654 */
1612
- if ((n->nlmsg_flags & NLM_F_CREATE) &&
1613
- (n->nlmsg_flags & NLM_F_REPLACE) &&
1614
- ((n->nlmsg_flags & NLM_F_EXCL) ||
1615
- (tca[TCA_KIND] &&
1616
- nla_strcmp(tca[TCA_KIND], q->ops->id))))
1617
- goto create_n_graft;
1655
+ if (tca[TCA_KIND] &&
1656
+ nla_strcmp(tca[TCA_KIND], q->ops->id)) {
1657
+ if (req_create_or_replace(n) ||
1658
+ req_create_exclusive(n))
1659
+ goto create_n_graft;
1660
+ else if (req_change(n))
1661
+ goto create_n_graft2;
1662
+ }
16181663 }
16191664 }
16201665 } else {
....@@ -1648,6 +1693,7 @@
16481693 NL_SET_ERR_MSG(extack, "Qdisc not found. To create specify NLM_F_CREATE flag");
16491694 return -ENOENT;
16501695 }
1696
+create_n_graft2:
16511697 if (clid == TC_H_INGRESS) {
16521698 if (dev_ingress_queue(dev)) {
16531699 q = qdisc_create(dev, dev_ingress_queue(dev), p,