.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * net/sched/sch_mqprio.c |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2010 John Fastabend <john.r.fastabend@intel.com> |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or |
---|
7 | | - * modify it under the terms of the GNU General Public License |
---|
8 | | - * version 2 as published by the Free Software Foundation. |
---|
9 | 6 | */ |
---|
10 | 7 | |
---|
11 | 8 | #include <linux/types.h> |
---|
.. | .. |
---|
125 | 122 | int nested_len = nla_len(nla) - NLA_ALIGN(len); |
---|
126 | 123 | |
---|
127 | 124 | if (nested_len >= nla_attr_size(0)) |
---|
128 | | - return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len), |
---|
129 | | - nested_len, policy, NULL); |
---|
| 125 | + return nla_parse_deprecated(tb, maxtype, |
---|
| 126 | + nla_data(nla) + NLA_ALIGN(len), |
---|
| 127 | + nested_len, policy, NULL); |
---|
130 | 128 | |
---|
131 | 129 | memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); |
---|
| 130 | + return 0; |
---|
| 131 | +} |
---|
| 132 | + |
---|
| 133 | +static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt, |
---|
| 134 | + struct nlattr *opt, |
---|
| 135 | + struct netlink_ext_ack *extack) |
---|
| 136 | +{ |
---|
| 137 | + struct mqprio_sched *priv = qdisc_priv(sch); |
---|
| 138 | + struct nlattr *tb[TCA_MQPRIO_MAX + 1]; |
---|
| 139 | + struct nlattr *attr; |
---|
| 140 | + int i, rem, err; |
---|
| 141 | + |
---|
| 142 | + err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, |
---|
| 143 | + sizeof(*qopt)); |
---|
| 144 | + if (err < 0) |
---|
| 145 | + return err; |
---|
| 146 | + |
---|
| 147 | + if (!qopt->hw) { |
---|
| 148 | + NL_SET_ERR_MSG(extack, |
---|
| 149 | + "mqprio TCA_OPTIONS can only contain netlink attributes in hardware mode"); |
---|
| 150 | + return -EINVAL; |
---|
| 151 | + } |
---|
| 152 | + |
---|
| 153 | + if (tb[TCA_MQPRIO_MODE]) { |
---|
| 154 | + priv->flags |= TC_MQPRIO_F_MODE; |
---|
| 155 | + priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); |
---|
| 156 | + } |
---|
| 157 | + |
---|
| 158 | + if (tb[TCA_MQPRIO_SHAPER]) { |
---|
| 159 | + priv->flags |= TC_MQPRIO_F_SHAPER; |
---|
| 160 | + priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); |
---|
| 161 | + } |
---|
| 162 | + |
---|
| 163 | + if (tb[TCA_MQPRIO_MIN_RATE64]) { |
---|
| 164 | + if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { |
---|
| 165 | + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MIN_RATE64], |
---|
| 166 | + "min_rate accepted only when shaper is in bw_rlimit mode"); |
---|
| 167 | + return -EINVAL; |
---|
| 168 | + } |
---|
| 169 | + i = 0; |
---|
| 170 | + nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], |
---|
| 171 | + rem) { |
---|
| 172 | + if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) { |
---|
| 173 | + NL_SET_ERR_MSG_ATTR(extack, attr, |
---|
| 174 | + "Attribute type expected to be TCA_MQPRIO_MIN_RATE64"); |
---|
| 175 | + return -EINVAL; |
---|
| 176 | + } |
---|
| 177 | + |
---|
| 178 | + if (nla_len(attr) != sizeof(u64)) { |
---|
| 179 | + NL_SET_ERR_MSG_ATTR(extack, attr, |
---|
| 180 | + "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length"); |
---|
| 181 | + return -EINVAL; |
---|
| 182 | + } |
---|
| 183 | + |
---|
| 184 | + if (i >= qopt->num_tc) |
---|
| 185 | + break; |
---|
| 186 | + priv->min_rate[i] = *(u64 *)nla_data(attr); |
---|
| 187 | + i++; |
---|
| 188 | + } |
---|
| 189 | + priv->flags |= TC_MQPRIO_F_MIN_RATE; |
---|
| 190 | + } |
---|
| 191 | + |
---|
| 192 | + if (tb[TCA_MQPRIO_MAX_RATE64]) { |
---|
| 193 | + if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) { |
---|
| 194 | + NL_SET_ERR_MSG_ATTR(extack, tb[TCA_MQPRIO_MAX_RATE64], |
---|
| 195 | + "max_rate accepted only when shaper is in bw_rlimit mode"); |
---|
| 196 | + return -EINVAL; |
---|
| 197 | + } |
---|
| 198 | + i = 0; |
---|
| 199 | + nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], |
---|
| 200 | + rem) { |
---|
| 201 | + if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) { |
---|
| 202 | + NL_SET_ERR_MSG_ATTR(extack, attr, |
---|
| 203 | + "Attribute type expected to be TCA_MQPRIO_MAX_RATE64"); |
---|
| 204 | + return -EINVAL; |
---|
| 205 | + } |
---|
| 206 | + |
---|
| 207 | + if (nla_len(attr) != sizeof(u64)) { |
---|
| 208 | + NL_SET_ERR_MSG_ATTR(extack, attr, |
---|
| 209 | + "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length"); |
---|
| 210 | + return -EINVAL; |
---|
| 211 | + } |
---|
| 212 | + |
---|
| 213 | + if (i >= qopt->num_tc) |
---|
| 214 | + break; |
---|
| 215 | + priv->max_rate[i] = *(u64 *)nla_data(attr); |
---|
| 216 | + i++; |
---|
| 217 | + } |
---|
| 218 | + priv->flags |= TC_MQPRIO_F_MAX_RATE; |
---|
| 219 | + } |
---|
| 220 | + |
---|
132 | 221 | return 0; |
---|
133 | 222 | } |
---|
134 | 223 | |
---|
.. | .. |
---|
141 | 230 | struct Qdisc *qdisc; |
---|
142 | 231 | int i, err = -EOPNOTSUPP; |
---|
143 | 232 | struct tc_mqprio_qopt *qopt = NULL; |
---|
144 | | - struct nlattr *tb[TCA_MQPRIO_MAX + 1]; |
---|
145 | | - struct nlattr *attr; |
---|
146 | | - int rem; |
---|
147 | 233 | int len; |
---|
148 | 234 | |
---|
149 | 235 | BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); |
---|
.. | .. |
---|
168 | 254 | |
---|
169 | 255 | len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); |
---|
170 | 256 | if (len > 0) { |
---|
171 | | - err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, |
---|
172 | | - sizeof(*qopt)); |
---|
173 | | - if (err < 0) |
---|
| 257 | + err = mqprio_parse_nlattr(sch, qopt, opt, extack); |
---|
| 258 | + if (err) |
---|
174 | 259 | return err; |
---|
175 | | - |
---|
176 | | - if (!qopt->hw) |
---|
177 | | - return -EINVAL; |
---|
178 | | - |
---|
179 | | - if (tb[TCA_MQPRIO_MODE]) { |
---|
180 | | - priv->flags |= TC_MQPRIO_F_MODE; |
---|
181 | | - priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); |
---|
182 | | - } |
---|
183 | | - |
---|
184 | | - if (tb[TCA_MQPRIO_SHAPER]) { |
---|
185 | | - priv->flags |= TC_MQPRIO_F_SHAPER; |
---|
186 | | - priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); |
---|
187 | | - } |
---|
188 | | - |
---|
189 | | - if (tb[TCA_MQPRIO_MIN_RATE64]) { |
---|
190 | | - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) |
---|
191 | | - return -EINVAL; |
---|
192 | | - i = 0; |
---|
193 | | - nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], |
---|
194 | | - rem) { |
---|
195 | | - if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) |
---|
196 | | - return -EINVAL; |
---|
197 | | - if (i >= qopt->num_tc) |
---|
198 | | - break; |
---|
199 | | - priv->min_rate[i] = *(u64 *)nla_data(attr); |
---|
200 | | - i++; |
---|
201 | | - } |
---|
202 | | - priv->flags |= TC_MQPRIO_F_MIN_RATE; |
---|
203 | | - } |
---|
204 | | - |
---|
205 | | - if (tb[TCA_MQPRIO_MAX_RATE64]) { |
---|
206 | | - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) |
---|
207 | | - return -EINVAL; |
---|
208 | | - i = 0; |
---|
209 | | - nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], |
---|
210 | | - rem) { |
---|
211 | | - if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) |
---|
212 | | - return -EINVAL; |
---|
213 | | - if (i >= qopt->num_tc) |
---|
214 | | - break; |
---|
215 | | - priv->max_rate[i] = *(u64 *)nla_data(attr); |
---|
216 | | - i++; |
---|
217 | | - } |
---|
218 | | - priv->flags |= TC_MQPRIO_F_MAX_RATE; |
---|
219 | | - } |
---|
220 | 260 | } |
---|
221 | 261 | |
---|
222 | 262 | /* pre-allocate qdisc, attachment can't fail */ |
---|
.. | .. |
---|
349 | 389 | int i; |
---|
350 | 390 | |
---|
351 | 391 | if (priv->flags & TC_MQPRIO_F_MIN_RATE) { |
---|
352 | | - nest = nla_nest_start(skb, TCA_MQPRIO_MIN_RATE64); |
---|
| 392 | + nest = nla_nest_start_noflag(skb, TCA_MQPRIO_MIN_RATE64); |
---|
353 | 393 | if (!nest) |
---|
354 | 394 | goto nla_put_failure; |
---|
355 | 395 | |
---|
.. | .. |
---|
363 | 403 | } |
---|
364 | 404 | |
---|
365 | 405 | if (priv->flags & TC_MQPRIO_F_MAX_RATE) { |
---|
366 | | - nest = nla_nest_start(skb, TCA_MQPRIO_MAX_RATE64); |
---|
| 406 | + nest = nla_nest_start_noflag(skb, TCA_MQPRIO_MAX_RATE64); |
---|
367 | 407 | if (!nest) |
---|
368 | 408 | goto nla_put_failure; |
---|
369 | 409 | |
---|
.. | .. |
---|
568 | 608 | sch = dev_queue->qdisc_sleeping; |
---|
569 | 609 | if (gnet_stats_copy_basic(qdisc_root_sleeping_running(sch), d, |
---|
570 | 610 | sch->cpu_bstats, &sch->bstats) < 0 || |
---|
571 | | - gnet_stats_copy_queue(d, NULL, |
---|
572 | | - &sch->qstats, sch->q.qlen) < 0) |
---|
| 611 | + qdisc_qstats_copy(d, sch) < 0) |
---|
573 | 612 | return -1; |
---|
574 | 613 | } |
---|
575 | 614 | return 0; |
---|