History

mqprio: Change handling of hw u8 to allow for multiple hardware offload modes

This patch is meant to allow for support of multiple hardware offload type for a single device. There is currently no bounds checking for the hw member of the mqprio_qopt structure. This results in us being able to pass values from 1 to 255 with all being treated the same. On retreiving the value it is returned as 1 for anything 1 or greater being set. With this change we are currently adding limited bounds checking by defining an enum and using those values to limit the reported hardware offloads.

Alexander Duyck committed 9 years ago

Commit 2026fec1 parent 5b769642 files · +24 −10Browse files

Unified · Split

2 files
  1. include/uapi/linux/pkt_sched.h +8 −0
  2. net/sched/sch_mqprio.c +16 −10
include/uapi/linux/pkt_sched.h+8−0
@@ -617,6 +617,14 @@ struct tc_drr_stats { · 616 unmodified lines
617#define TC_QOPT_BITMASK 15617#define TC_QOPT_BITMASK 15
618#define TC_QOPT_MAX_QUEUE 16618#define TC_QOPT_MAX_QUEUE 16
619 619
620enum {
621 TC_MQPRIO_HW_OFFLOAD_NONE, /* no offload requested */
622 TC_MQPRIO_HW_OFFLOAD_TCS, /* offload TCs, no queue counts */
623 __TC_MQPRIO_HW_OFFLOAD_MAX
624};
625
626#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
627
620struct tc_mqprio_qopt {628struct tc_mqprio_qopt {
621 __u8 num_tc;629 __u8 num_tc;
622 __u8 prio_tc_map[TC_QOPT_BITMASK + 1];630 __u8 prio_tc_map[TC_QOPT_BITMASK + 1];
net/sched/sch_mqprio.c+16−10
@@ -21,7 +21,7 @@ · 20 unmodified lines
21 21
22struct mqprio_sched {22struct mqprio_sched {
23 struct Qdisc **qdiscs;23 struct Qdisc **qdiscs;
24 int hw_owned;24 int hw_offload;
25};25};
26 26
27static void mqprio_destroy(struct Qdisc *sch)27static void mqprio_destroy(struct Qdisc *sch)
@@ -39,7 +39,7 @@ static void mqprio_destroy(struct Qdisc *sch) · 11 unmodified lines
39 kfree(priv->qdiscs);39 kfree(priv->qdiscs);
40 }40 }
41 41
42 if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)42 if (priv->hw_offload && dev->netdev_ops->ndo_setup_tc)
43 dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);43 dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
44 else44 else
45 netdev_set_num_tc(dev, 0);45 netdev_set_num_tc(dev, 0);
@@ -59,15 +59,20 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt) · 13 unmodified lines
59 return -EINVAL;59 return -EINVAL;
60 }60 }
61 61
62 /* net_device does not support requested operation */62 /* Limit qopt->hw to maximum supported offload value. Drivers have
63 if (qopt->hw && !dev->netdev_ops->ndo_setup_tc)63 * the option of overriding this later if they don't support the a
64 return -EINVAL;64 * given offload type.
65 */
66 if (qopt->hw > TC_MQPRIO_HW_OFFLOAD_MAX)
67 qopt->hw = TC_MQPRIO_HW_OFFLOAD_MAX;
65 68
66 /* if hw owned qcount and qoffset are taken from LLD so69 /* If hardware offload is requested we will leave it to the device
67 * no reason to verify them here70 * to either populate the queue counts itself or to validate the
71 * provided queue counts. If ndo_setup_tc is not present then
72 * hardware doesn't support offload and we should return an error.
68 */73 */
69 if (qopt->hw)74 if (qopt->hw)
70 return 0;75 return dev->netdev_ops->ndo_setup_tc ? 0 : -EINVAL;
71 76
72 for (i = 0; i < qopt->num_tc; i++) {77 for (i = 0; i < qopt->num_tc; i++) {
73 unsigned int last = qopt->offset[i] + qopt->count[i];78 unsigned int last = qopt->offset[i] + qopt->count[i];
@@ -142,10 +147,11 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) · 68 unmodified lines
142 struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,147 struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
143 { .tc = qopt->num_tc }};148 { .tc = qopt->num_tc }};
144 149
145 priv->hw_owned = 1;
146 err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);150 err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
147 if (err)151 if (err)
148 return err;152 return err;
153
154 priv->hw_offload = qopt->hw;
149 } else {155 } else {
150 netdev_set_num_tc(dev, qopt->num_tc);156 netdev_set_num_tc(dev, qopt->num_tc);
151 for (i = 0; i < qopt->num_tc; i++)157 for (i = 0; i < qopt->num_tc; i++)
@@ -243,7 +249,7 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) · 91 unmodified lines
243 249
244 opt.num_tc = netdev_get_num_tc(dev);250 opt.num_tc = netdev_get_num_tc(dev);
245 memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));251 memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
246 opt.hw = priv->hw_owned;252 opt.hw = priv->hw_offload;
247 253
248 for (i = 0; i < netdev_get_num_tc(dev); i++) {254 for (i = 0; i < netdev_get_num_tc(dev); i++) {
249 opt.count[i] = dev->tc_to_txq[i].count;255 opt.count[i] = dev->tc_to_txq[i].count;