~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/sched/sch_mqprio_lib.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 
  3 #include <linux/net.h>
  4 #include <linux/netdevice.h>
  5 #include <linux/netlink.h>
  6 #include <linux/types.h>
  7 #include <net/pkt_sched.h>
  8 
  9 #include "sch_mqprio_lib.h"
 10 
 11 /* Returns true if the intervals [a, b) and [c, d) overlap. */
 12 static bool intervals_overlap(int a, int b, int c, int d)
 13 {
 14         int left = max(a, c), right = min(b, d);
 15 
 16         return left < right;
 17 }
 18 
 19 static int mqprio_validate_queue_counts(struct net_device *dev,
 20                                         const struct tc_mqprio_qopt *qopt,
 21                                         bool allow_overlapping_txqs,
 22                                         struct netlink_ext_ack *extack)
 23 {
 24         int i, j;
 25 
 26         for (i = 0; i < qopt->num_tc; i++) {
 27                 unsigned int last = qopt->offset[i] + qopt->count[i];
 28 
 29                 if (!qopt->count[i]) {
 30                         NL_SET_ERR_MSG_FMT_MOD(extack, "No queues for TC %d",
 31                                                i);
 32                         return -EINVAL;
 33                 }
 34 
 35                 /* Verify the queue count is in tx range being equal to the
 36                  * real_num_tx_queues indicates the last queue is in use.
 37                  */
 38                 if (qopt->offset[i] >= dev->real_num_tx_queues ||
 39                     last > dev->real_num_tx_queues) {
 40                         NL_SET_ERR_MSG_FMT_MOD(extack,
 41                                                "Queues %d:%d for TC %d exceed the %d TX queues available",
 42                                                qopt->count[i], qopt->offset[i],
 43                                                i, dev->real_num_tx_queues);
 44                         return -EINVAL;
 45                 }
 46 
 47                 if (allow_overlapping_txqs)
 48                         continue;
 49 
 50                 /* Verify that the offset and counts do not overlap */
 51                 for (j = i + 1; j < qopt->num_tc; j++) {
 52                         if (intervals_overlap(qopt->offset[i], last,
 53                                               qopt->offset[j],
 54                                               qopt->offset[j] +
 55                                               qopt->count[j])) {
 56                                 NL_SET_ERR_MSG_FMT_MOD(extack,
 57                                                        "TC %d queues %d@%d overlap with TC %d queues %d@%d",
 58                                                        i, qopt->count[i], qopt->offset[i],
 59                                                        j, qopt->count[j], qopt->offset[j]);
 60                                 return -EINVAL;
 61                         }
 62                 }
 63         }
 64 
 65         return 0;
 66 }
 67 
 68 int mqprio_validate_qopt(struct net_device *dev, struct tc_mqprio_qopt *qopt,
 69                          bool validate_queue_counts,
 70                          bool allow_overlapping_txqs,
 71                          struct netlink_ext_ack *extack)
 72 {
 73         int i, err;
 74 
 75         /* Verify num_tc is not out of max range */
 76         if (qopt->num_tc > TC_MAX_QUEUE) {
 77                 NL_SET_ERR_MSG(extack,
 78                                "Number of traffic classes is outside valid range");
 79                 return -EINVAL;
 80         }
 81 
 82         /* Verify priority mapping uses valid tcs */
 83         for (i = 0; i <= TC_BITMASK; i++) {
 84                 if (qopt->prio_tc_map[i] >= qopt->num_tc) {
 85                         NL_SET_ERR_MSG(extack,
 86                                        "Invalid traffic class in priority to traffic class mapping");
 87                         return -EINVAL;
 88                 }
 89         }
 90 
 91         if (validate_queue_counts) {
 92                 err = mqprio_validate_queue_counts(dev, qopt,
 93                                                    allow_overlapping_txqs,
 94                                                    extack);
 95                 if (err)
 96                         return err;
 97         }
 98 
 99         return 0;
100 }
101 EXPORT_SYMBOL_GPL(mqprio_validate_qopt);
102 
103 void mqprio_qopt_reconstruct(struct net_device *dev, struct tc_mqprio_qopt *qopt)
104 {
105         int tc, num_tc = netdev_get_num_tc(dev);
106 
107         qopt->num_tc = num_tc;
108         memcpy(qopt->prio_tc_map, dev->prio_tc_map, sizeof(qopt->prio_tc_map));
109 
110         for (tc = 0; tc < num_tc; tc++) {
111                 qopt->count[tc] = dev->tc_to_txq[tc].count;
112                 qopt->offset[tc] = dev->tc_to_txq[tc].offset;
113         }
114 }
115 EXPORT_SYMBOL_GPL(mqprio_qopt_reconstruct);
116 
117 void mqprio_fp_to_offload(u32 fp[TC_QOPT_MAX_QUEUE],
118                           struct tc_mqprio_qopt_offload *mqprio)
119 {
120         unsigned long preemptible_tcs = 0;
121         int tc;
122 
123         for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++)
124                 if (fp[tc] == TC_FP_PREEMPTIBLE)
125                         preemptible_tcs |= BIT(tc);
126 
127         mqprio->preemptible_tcs = preemptible_tcs;
128 }
129 EXPORT_SYMBOL_GPL(mqprio_fp_to_offload);
130 
131 MODULE_LICENSE("GPL");
132 MODULE_DESCRIPTION("Shared mqprio qdisc code currently between taprio and mqprio");
133 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php