sch_mqprio.c (c54876cd5961ce0f8e74807f79a6739cd6b35ddf) | sch_mqprio.c (f62af20bed2d9e824f51cfc97ff01bc261f40e58) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * net/sched/sch_mqprio.c 4 * 5 * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> 6 */ 7 | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * net/sched/sch_mqprio.c 4 * 5 * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> 6 */ 7 |
8#include <linux/ethtool_netlink.h> |
|
8#include <linux/types.h> 9#include <linux/slab.h> 10#include <linux/kernel.h> 11#include <linux/string.h> 12#include <linux/errno.h> 13#include <linux/skbuff.h> 14#include <linux/module.h> 15#include <net/netlink.h> --- 6 unchanged lines hidden (view full) --- 22struct mqprio_sched { 23 struct Qdisc **qdiscs; 24 u16 mode; 25 u16 shaper; 26 int hw_offload; 27 u32 flags; 28 u64 min_rate[TC_QOPT_MAX_QUEUE]; 29 u64 max_rate[TC_QOPT_MAX_QUEUE]; | 9#include <linux/types.h> 10#include <linux/slab.h> 11#include <linux/kernel.h> 12#include <linux/string.h> 13#include <linux/errno.h> 14#include <linux/skbuff.h> 15#include <linux/module.h> 16#include <net/netlink.h> --- 6 unchanged lines hidden (view full) --- 23struct mqprio_sched { 24 struct Qdisc **qdiscs; 25 u16 mode; 26 u16 shaper; 27 int hw_offload; 28 u32 flags; 29 u64 min_rate[TC_QOPT_MAX_QUEUE]; 30 u64 max_rate[TC_QOPT_MAX_QUEUE]; |
31 u32 fp[TC_QOPT_MAX_QUEUE]; |
|
30}; 31 32static int mqprio_enable_offload(struct Qdisc *sch, 33 const struct tc_mqprio_qopt *qopt, 34 struct netlink_ext_ack *extack) 35{ 36 struct mqprio_sched *priv = qdisc_priv(sch); 37 struct net_device *dev = qdisc_dev(sch); --- 20 unchanged lines hidden (view full) --- 58 if (priv->flags & TC_MQPRIO_F_MAX_RATE) 59 for (i = 0; i < mqprio.qopt.num_tc; i++) 60 mqprio.max_rate[i] = priv->max_rate[i]; 61 break; 62 default: 63 return -EINVAL; 64 } 65 | 32}; 33 34static int mqprio_enable_offload(struct Qdisc *sch, 35 const struct tc_mqprio_qopt *qopt, 36 struct netlink_ext_ack *extack) 37{ 38 struct mqprio_sched *priv = qdisc_priv(sch); 39 struct net_device *dev = qdisc_dev(sch); --- 20 unchanged lines hidden (view full) --- 60 if (priv->flags & TC_MQPRIO_F_MAX_RATE) 61 for (i = 0; i < mqprio.qopt.num_tc; i++) 62 mqprio.max_rate[i] = priv->max_rate[i]; 63 break; 64 default: 65 return -EINVAL; 66 } 67 |
68 mqprio_fp_to_offload(priv->fp, &mqprio); 69 |
|
66 err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_MQPRIO, 67 &mqprio); 68 if (err) 69 return err; 70 71 priv->hw_offload = mqprio.qopt.hw; 72 73 return 0; --- 66 unchanged lines hidden (view full) --- 140 NL_SET_ERR_MSG(extack, 141 "Device does not support hardware offload"); 142 return -EINVAL; 143 } 144 145 return 0; 146} 147 | 70 err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_MQPRIO, 71 &mqprio); 72 if (err) 73 return err; 74 75 priv->hw_offload = mqprio.qopt.hw; 76 77 return 0; --- 66 unchanged lines hidden (view full) --- 144 NL_SET_ERR_MSG(extack, 145 "Device does not support hardware offload"); 146 return -EINVAL; 147 } 148 149 return 0; 150} 151 |
152static const struct 153nla_policy mqprio_tc_entry_policy[TCA_MQPRIO_TC_ENTRY_MAX + 1] = { 154 [TCA_MQPRIO_TC_ENTRY_INDEX] = NLA_POLICY_MAX(NLA_U32, 155 TC_QOPT_MAX_QUEUE), 156 [TCA_MQPRIO_TC_ENTRY_FP] = NLA_POLICY_RANGE(NLA_U32, 157 TC_FP_EXPRESS, 158 TC_FP_PREEMPTIBLE), 159}; 160 |
|
148static const struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = { 149 [TCA_MQPRIO_MODE] = { .len = sizeof(u16) }, 150 [TCA_MQPRIO_SHAPER] = { .len = sizeof(u16) }, 151 [TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED }, 152 [TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED }, | 161static const struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = { 162 [TCA_MQPRIO_MODE] = { .len = sizeof(u16) }, 163 [TCA_MQPRIO_SHAPER] = { .len = sizeof(u16) }, 164 [TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED }, 165 [TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED }, |
166 [TCA_MQPRIO_TC_ENTRY] = { .type = NLA_NESTED }, |
|
153}; 154 | 167}; 168 |
169static int mqprio_parse_tc_entry(u32 fp[TC_QOPT_MAX_QUEUE], 170 struct nlattr *opt, 171 unsigned long *seen_tcs, 172 struct netlink_ext_ack *extack) 173{ 174 struct nlattr *tb[TCA_MQPRIO_TC_ENTRY_MAX + 1]; 175 int err, tc; 176 177 err = nla_parse_nested(tb, TCA_MQPRIO_TC_ENTRY_MAX, opt, 178 mqprio_tc_entry_policy, extack); 179 if (err < 0) 180 return err; 181 182 if (NL_REQ_ATTR_CHECK(extack, opt, tb, TCA_MQPRIO_TC_ENTRY_INDEX)) { 183 NL_SET_ERR_MSG(extack, "TC entry index missing"); 184 return -EINVAL; 185 } 186 187 tc = nla_get_u32(tb[TCA_MQPRIO_TC_ENTRY_INDEX]); 188 if (*seen_tcs & BIT(tc)) { 189 NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_TC_ENTRY_INDEX], 190 "Duplicate tc entry"); 191 return -EINVAL; 192 } 193 194 *seen_tcs |= BIT(tc); 195 196 if (tb[TCA_MQPRIO_TC_ENTRY_FP]) 197 fp[tc] = nla_get_u32(tb[TCA_MQPRIO_TC_ENTRY_FP]); 198 199 return 0; 200} 201 202static int mqprio_parse_tc_entries(struct Qdisc *sch, struct nlattr *nlattr_opt, 203 int nlattr_opt_len, 204 struct netlink_ext_ack *extack) 205{ 206 struct mqprio_sched *priv = qdisc_priv(sch); 207 struct net_device *dev = qdisc_dev(sch); 208 bool have_preemption = false; 209 unsigned long seen_tcs = 0; 210 u32 fp[TC_QOPT_MAX_QUEUE]; 211 struct nlattr *n; 212 int tc, rem; 213 int err = 0; 214 215 for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++) 216 fp[tc] = priv->fp[tc]; 217 218 nla_for_each_attr(n, nlattr_opt, nlattr_opt_len, rem) { 219 if (nla_type(n) != TCA_MQPRIO_TC_ENTRY) 220 continue; 221 222 err = mqprio_parse_tc_entry(fp, n, &seen_tcs, extack); 223 if (err) 224 goto out; 225 } 226 227 for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++) { 228 priv->fp[tc] = fp[tc]; 229 if (fp[tc] == TC_FP_PREEMPTIBLE) 230 have_preemption = true; 231 } 232 233 if (have_preemption && !ethtool_dev_mm_supported(dev)) { 234 NL_SET_ERR_MSG(extack, "Device does not support preemption"); 235 return -EOPNOTSUPP; 236 } 237out: 238 return err; 239} 240 |
|
155/* Parse the other netlink attributes that represent the payload of 156 * TCA_OPTIONS, which are appended right after struct tc_mqprio_qopt. 157 */ 158static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, 159 struct nlattr *opt, 160 struct netlink_ext_ack *extack) 161{ 162 struct nlattr *nlattr_opt = nla_data(opt) + NLA_ALIGN(sizeof(*qopt)); --- 66 unchanged lines hidden (view full) --- 229 if (i >= qopt->num_tc) 230 break; 231 priv->max_rate[i] = nla_get_u64(attr); 232 i++; 233 } 234 priv->flags |= TC_MQPRIO_F_MAX_RATE; 235 } 236 | 241/* Parse the other netlink attributes that represent the payload of 242 * TCA_OPTIONS, which are appended right after struct tc_mqprio_qopt. 243 */ 244static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, 245 struct nlattr *opt, 246 struct netlink_ext_ack *extack) 247{ 248 struct nlattr *nlattr_opt = nla_data(opt) + NLA_ALIGN(sizeof(*qopt)); --- 66 unchanged lines hidden (view full) --- 315 if (i >= qopt->num_tc) 316 break; 317 priv->max_rate[i] = nla_get_u64(attr); 318 i++; 319 } 320 priv->flags |= TC_MQPRIO_F_MAX_RATE; 321 } 322 |
323 if (tb[TCA_MQPRIO_TC_ENTRY]) { 324 err = mqprio_parse_tc_entries(sch, nlattr_opt, nlattr_opt_len, 325 extack); 326 if (err) 327 return err; 328 } 329 |
|
237 return 0; 238} 239 240static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, 241 struct netlink_ext_ack *extack) 242{ 243 struct net_device *dev = qdisc_dev(sch); 244 struct mqprio_sched *priv = qdisc_priv(sch); 245 struct netdev_queue *dev_queue; 246 struct Qdisc *qdisc; 247 int i, err = -EOPNOTSUPP; 248 struct tc_mqprio_qopt *qopt = NULL; 249 struct tc_mqprio_caps caps; | 330 return 0; 331} 332 333static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, 334 struct netlink_ext_ack *extack) 335{ 336 struct net_device *dev = qdisc_dev(sch); 337 struct mqprio_sched *priv = qdisc_priv(sch); 338 struct netdev_queue *dev_queue; 339 struct Qdisc *qdisc; 340 int i, err = -EOPNOTSUPP; 341 struct tc_mqprio_qopt *qopt = NULL; 342 struct tc_mqprio_caps caps; |
250 int len; | 343 int len, tc; |
251 252 BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); 253 BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); 254 255 if (sch->parent != TC_H_ROOT) 256 return -EOPNOTSUPP; 257 258 if (!netif_is_multiqueue(dev)) 259 return -EOPNOTSUPP; 260 261 /* make certain can allocate enough classids to handle queues */ 262 if (dev->num_tx_queues >= TC_H_MIN_PRIORITY) 263 return -ENOMEM; 264 265 if (!opt || nla_len(opt) < sizeof(*qopt)) 266 return -EINVAL; 267 | 344 345 BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); 346 BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); 347 348 if (sch->parent != TC_H_ROOT) 349 return -EOPNOTSUPP; 350 351 if (!netif_is_multiqueue(dev)) 352 return -EOPNOTSUPP; 353 354 /* make certain can allocate enough classids to handle queues */ 355 if (dev->num_tx_queues >= TC_H_MIN_PRIORITY) 356 return -ENOMEM; 357 358 if (!opt || nla_len(opt) < sizeof(*qopt)) 359 return -EINVAL; 360 |
361 for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++) 362 priv->fp[tc] = TC_FP_EXPRESS; 363 |
|
268 qdisc_offload_query_caps(dev, TC_SETUP_QDISC_MQPRIO, 269 &caps, sizeof(caps)); 270 271 qopt = nla_data(opt); 272 if (mqprio_parse_opt(dev, qopt, &caps, extack)) 273 return -EINVAL; 274 275 len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); --- 134 unchanged lines hidden (view full) --- 410 } 411 return 0; 412 413nla_put_failure: 414 nla_nest_cancel(skb, nest); 415 return -1; 416} 417 | 364 qdisc_offload_query_caps(dev, TC_SETUP_QDISC_MQPRIO, 365 &caps, sizeof(caps)); 366 367 qopt = nla_data(opt); 368 if (mqprio_parse_opt(dev, qopt, &caps, extack)) 369 return -EINVAL; 370 371 len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); --- 134 unchanged lines hidden (view full) --- 506 } 507 return 0; 508 509nla_put_failure: 510 nla_nest_cancel(skb, nest); 511 return -1; 512} 513 |
514static int mqprio_dump_tc_entries(struct mqprio_sched *priv, 515 struct sk_buff *skb) 516{ 517 struct nlattr *n; 518 int tc; 519 520 for (tc = 0; tc < TC_QOPT_MAX_QUEUE; tc++) { 521 n = nla_nest_start(skb, TCA_MQPRIO_TC_ENTRY); 522 if (!n) 523 return -EMSGSIZE; 524 525 if (nla_put_u32(skb, TCA_MQPRIO_TC_ENTRY_INDEX, tc)) 526 goto nla_put_failure; 527 528 if (nla_put_u32(skb, TCA_MQPRIO_TC_ENTRY_FP, priv->fp[tc])) 529 goto nla_put_failure; 530 531 nla_nest_end(skb, n); 532 } 533 534 return 0; 535 536nla_put_failure: 537 nla_nest_cancel(skb, n); 538 return -EMSGSIZE; 539} 540 |
|
418static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) 419{ 420 struct net_device *dev = qdisc_dev(sch); 421 struct mqprio_sched *priv = qdisc_priv(sch); 422 struct nlattr *nla = (struct nlattr *)skb_tail_pointer(skb); 423 struct tc_mqprio_qopt opt = { 0 }; 424 struct Qdisc *qdisc; 425 unsigned int ntx; --- 34 unchanged lines hidden (view full) --- 460 nla_put_u16(skb, TCA_MQPRIO_SHAPER, priv->shaper)) 461 goto nla_put_failure; 462 463 if ((priv->flags & TC_MQPRIO_F_MIN_RATE || 464 priv->flags & TC_MQPRIO_F_MAX_RATE) && 465 (dump_rates(priv, &opt, skb) != 0)) 466 goto nla_put_failure; 467 | 541static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) 542{ 543 struct net_device *dev = qdisc_dev(sch); 544 struct mqprio_sched *priv = qdisc_priv(sch); 545 struct nlattr *nla = (struct nlattr *)skb_tail_pointer(skb); 546 struct tc_mqprio_qopt opt = { 0 }; 547 struct Qdisc *qdisc; 548 unsigned int ntx; --- 34 unchanged lines hidden (view full) --- 583 nla_put_u16(skb, TCA_MQPRIO_SHAPER, priv->shaper)) 584 goto nla_put_failure; 585 586 if ((priv->flags & TC_MQPRIO_F_MIN_RATE || 587 priv->flags & TC_MQPRIO_F_MAX_RATE) && 588 (dump_rates(priv, &opt, skb) != 0)) 589 goto nla_put_failure; 590 |
591 if (mqprio_dump_tc_entries(priv, skb)) 592 goto nla_put_failure; 593 |
|
468 return nla_nest_end(skb, nla); 469nla_put_failure: 470 nlmsg_trim(skb, nla); 471 return -1; 472} 473 474static struct Qdisc *mqprio_leaf(struct Qdisc *sch, unsigned long cl) 475{ --- 176 unchanged lines hidden --- | 594 return nla_nest_end(skb, nla); 595nla_put_failure: 596 nlmsg_trim(skb, nla); 597 return -1; 598} 599 600static struct Qdisc *mqprio_leaf(struct Qdisc *sch, unsigned long cl) 601{ --- 176 unchanged lines hidden --- |