.. | .. |
---|
130 | 130 | return 0; |
---|
131 | 131 | } |
---|
132 | 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 | + |
---|
| 221 | + return 0; |
---|
| 222 | +} |
---|
| 223 | + |
---|
133 | 224 | static int mqprio_init(struct Qdisc *sch, struct nlattr *opt, |
---|
134 | 225 | struct netlink_ext_ack *extack) |
---|
135 | 226 | { |
---|
.. | .. |
---|
139 | 230 | struct Qdisc *qdisc; |
---|
140 | 231 | int i, err = -EOPNOTSUPP; |
---|
141 | 232 | struct tc_mqprio_qopt *qopt = NULL; |
---|
142 | | - struct nlattr *tb[TCA_MQPRIO_MAX + 1]; |
---|
143 | | - struct nlattr *attr; |
---|
144 | | - int rem; |
---|
145 | 233 | int len; |
---|
146 | 234 | |
---|
147 | 235 | BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); |
---|
.. | .. |
---|
166 | 254 | |
---|
167 | 255 | len = nla_len(opt) - NLA_ALIGN(sizeof(*qopt)); |
---|
168 | 256 | if (len > 0) { |
---|
169 | | - err = parse_attr(tb, TCA_MQPRIO_MAX, opt, mqprio_policy, |
---|
170 | | - sizeof(*qopt)); |
---|
171 | | - if (err < 0) |
---|
| 257 | + err = mqprio_parse_nlattr(sch, qopt, opt, extack); |
---|
| 258 | + if (err) |
---|
172 | 259 | return err; |
---|
173 | | - |
---|
174 | | - if (!qopt->hw) |
---|
175 | | - return -EINVAL; |
---|
176 | | - |
---|
177 | | - if (tb[TCA_MQPRIO_MODE]) { |
---|
178 | | - priv->flags |= TC_MQPRIO_F_MODE; |
---|
179 | | - priv->mode = *(u16 *)nla_data(tb[TCA_MQPRIO_MODE]); |
---|
180 | | - } |
---|
181 | | - |
---|
182 | | - if (tb[TCA_MQPRIO_SHAPER]) { |
---|
183 | | - priv->flags |= TC_MQPRIO_F_SHAPER; |
---|
184 | | - priv->shaper = *(u16 *)nla_data(tb[TCA_MQPRIO_SHAPER]); |
---|
185 | | - } |
---|
186 | | - |
---|
187 | | - if (tb[TCA_MQPRIO_MIN_RATE64]) { |
---|
188 | | - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) |
---|
189 | | - return -EINVAL; |
---|
190 | | - i = 0; |
---|
191 | | - nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], |
---|
192 | | - rem) { |
---|
193 | | - if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64) |
---|
194 | | - return -EINVAL; |
---|
195 | | - if (i >= qopt->num_tc) |
---|
196 | | - break; |
---|
197 | | - priv->min_rate[i] = *(u64 *)nla_data(attr); |
---|
198 | | - i++; |
---|
199 | | - } |
---|
200 | | - priv->flags |= TC_MQPRIO_F_MIN_RATE; |
---|
201 | | - } |
---|
202 | | - |
---|
203 | | - if (tb[TCA_MQPRIO_MAX_RATE64]) { |
---|
204 | | - if (priv->shaper != TC_MQPRIO_SHAPER_BW_RATE) |
---|
205 | | - return -EINVAL; |
---|
206 | | - i = 0; |
---|
207 | | - nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], |
---|
208 | | - rem) { |
---|
209 | | - if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64) |
---|
210 | | - return -EINVAL; |
---|
211 | | - if (i >= qopt->num_tc) |
---|
212 | | - break; |
---|
213 | | - priv->max_rate[i] = *(u64 *)nla_data(attr); |
---|
214 | | - i++; |
---|
215 | | - } |
---|
216 | | - priv->flags |= TC_MQPRIO_F_MAX_RATE; |
---|
217 | | - } |
---|
218 | 260 | } |
---|
219 | 261 | |
---|
220 | 262 | /* pre-allocate qdisc, attachment can't fail */ |
---|