sch_prio.c (3eb66e91a25497065c5322b1268cbc3953642227) sch_prio.c (f6bab199315b70fd83fe3ee0947bc84c7a35f3d4)
1/*
2 * net/sched/sch_prio.c Simple 3-band priority "scheduler".
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 58 unchanged lines hidden (view full) ---

67 return q->queues[q->prio2band[0]];
68
69 return q->queues[band];
70}
71
72static int
73prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
74{
1/*
2 * net/sched/sch_prio.c Simple 3-band priority "scheduler".
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *

--- 58 unchanged lines hidden (view full) ---

67 return q->queues[q->prio2band[0]];
68
69 return q->queues[band];
70}
71
72static int
73prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
74{
75 unsigned int len = qdisc_pkt_len(skb);
75 struct Qdisc *qdisc;
76 int ret;
77
78 qdisc = prio_classify(skb, sch, &ret);
79#ifdef CONFIG_NET_CLS_ACT
80 if (qdisc == NULL) {
81
82 if (ret & __NET_XMIT_BYPASS)
83 qdisc_qstats_drop(sch);
84 __qdisc_drop(skb, to_free);
85 return ret;
86 }
87#endif
88
89 ret = qdisc_enqueue(skb, qdisc, to_free);
90 if (ret == NET_XMIT_SUCCESS) {
76 struct Qdisc *qdisc;
77 int ret;
78
79 qdisc = prio_classify(skb, sch, &ret);
80#ifdef CONFIG_NET_CLS_ACT
81 if (qdisc == NULL) {
82
83 if (ret & __NET_XMIT_BYPASS)
84 qdisc_qstats_drop(sch);
85 __qdisc_drop(skb, to_free);
86 return ret;
87 }
88#endif
89
90 ret = qdisc_enqueue(skb, qdisc, to_free);
91 if (ret == NET_XMIT_SUCCESS) {
91 qdisc_qstats_backlog_inc(sch, skb);
92 sch->qstats.backlog += len;
92 sch->q.qlen++;
93 return NET_XMIT_SUCCESS;
94 }
95 if (net_xmit_drop_count(ret))
96 qdisc_qstats_drop(sch);
97 return ret;
98}
99

--- 115 unchanged lines hidden (view full) ---

215 q->bands = qopt->bands;
216 memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
217
218 for (i = q->bands; i < oldbands; i++) {
219 struct Qdisc *child = q->queues[i];
220
221 qdisc_tree_reduce_backlog(child, child->q.qlen,
222 child->qstats.backlog);
93 sch->q.qlen++;
94 return NET_XMIT_SUCCESS;
95 }
96 if (net_xmit_drop_count(ret))
97 qdisc_qstats_drop(sch);
98 return ret;
99}
100

--- 115 unchanged lines hidden (view full) ---

216 q->bands = qopt->bands;
217 memcpy(q->prio2band, qopt->priomap, TC_PRIO_MAX+1);
218
219 for (i = q->bands; i < oldbands; i++) {
220 struct Qdisc *child = q->queues[i];
221
222 qdisc_tree_reduce_backlog(child, child->q.qlen,
223 child->qstats.backlog);
223 qdisc_put(child);
224 }
225
226 for (i = oldbands; i < q->bands; i++) {
227 q->queues[i] = queues[i];
228 if (q->queues[i] != &noop_qdisc)
229 qdisc_hash_add(q->queues[i], true);
230 }
231
232 sch_tree_unlock(sch);
224 }
225
226 for (i = oldbands; i < q->bands; i++) {
227 q->queues[i] = queues[i];
228 if (q->queues[i] != &noop_qdisc)
229 qdisc_hash_add(q->queues[i], true);
230 }
231
232 sch_tree_unlock(sch);
233
234 for (i = q->bands; i < oldbands; i++)
235 qdisc_put(q->queues[i]);
233 return 0;
234}
235
236static int prio_init(struct Qdisc *sch, struct nlattr *opt,
237 struct netlink_ext_ack *extack)
238{
239 struct prio_sched_data *q = qdisc_priv(sch);
240 int err;

--- 5 unchanged lines hidden (view full) ---

246 if (err)
247 return err;
248
249 return prio_tune(sch, opt, extack);
250}
251
252static int prio_dump_offload(struct Qdisc *sch)
253{
236 return 0;
237}
238
239static int prio_init(struct Qdisc *sch, struct nlattr *opt,
240 struct netlink_ext_ack *extack)
241{
242 struct prio_sched_data *q = qdisc_priv(sch);
243 int err;

--- 5 unchanged lines hidden (view full) ---

249 if (err)
250 return err;
251
252 return prio_tune(sch, opt, extack);
253}
254
255static int prio_dump_offload(struct Qdisc *sch)
256{
254 struct net_device *dev = qdisc_dev(sch);
255 struct tc_prio_qopt_offload hw_stats = {
256 .command = TC_PRIO_STATS,
257 .handle = sch->handle,
258 .parent = sch->parent,
259 {
260 .stats = {
261 .bstats = &sch->bstats,
262 .qstats = &sch->qstats,
263 },
264 },
265 };
257 struct tc_prio_qopt_offload hw_stats = {
258 .command = TC_PRIO_STATS,
259 .handle = sch->handle,
260 .parent = sch->parent,
261 {
262 .stats = {
263 .bstats = &sch->bstats,
264 .qstats = &sch->qstats,
265 },
266 },
267 };
266 int err;
267
268
268 sch->flags &= ~TCQ_F_OFFLOADED;
269 if (!tc_can_offload(dev) || !dev->netdev_ops->ndo_setup_tc)
270 return 0;
271
272 err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO,
273 &hw_stats);
274 if (err == -EOPNOTSUPP)
275 return 0;
276
277 if (!err)
278 sch->flags |= TCQ_F_OFFLOADED;
279
280 return err;
269 return qdisc_offload_dump_helper(sch, TC_SETUP_QDISC_PRIO, &hw_stats);
281}
282
283static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
284{
285 struct prio_sched_data *q = qdisc_priv(sch);
286 unsigned char *b = skb_tail_pointer(skb);
287 struct tc_prio_qopt opt;
288 int err;

--- 15 unchanged lines hidden (view full) ---

304 return -1;
305}
306
307static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
308 struct Qdisc **old, struct netlink_ext_ack *extack)
309{
310 struct prio_sched_data *q = qdisc_priv(sch);
311 struct tc_prio_qopt_offload graft_offload;
270}
271
272static int prio_dump(struct Qdisc *sch, struct sk_buff *skb)
273{
274 struct prio_sched_data *q = qdisc_priv(sch);
275 unsigned char *b = skb_tail_pointer(skb);
276 struct tc_prio_qopt opt;
277 int err;

--- 15 unchanged lines hidden (view full) ---

293 return -1;
294}
295
296static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
297 struct Qdisc **old, struct netlink_ext_ack *extack)
298{
299 struct prio_sched_data *q = qdisc_priv(sch);
300 struct tc_prio_qopt_offload graft_offload;
312 struct net_device *dev = qdisc_dev(sch);
313 unsigned long band = arg - 1;
301 unsigned long band = arg - 1;
314 bool any_qdisc_is_offloaded;
315 int err;
316
317 if (new == NULL)
318 new = &noop_qdisc;
319
320 *old = qdisc_replace(sch, new, &q->queues[band]);
321
302
303 if (new == NULL)
304 new = &noop_qdisc;
305
306 *old = qdisc_replace(sch, new, &q->queues[band]);
307
322 if (!tc_can_offload(dev))
323 return 0;
324
325 graft_offload.handle = sch->handle;
326 graft_offload.parent = sch->parent;
327 graft_offload.graft_params.band = band;
328 graft_offload.graft_params.child_handle = new->handle;
329 graft_offload.command = TC_PRIO_GRAFT;
330
308 graft_offload.handle = sch->handle;
309 graft_offload.parent = sch->parent;
310 graft_offload.graft_params.band = band;
311 graft_offload.graft_params.child_handle = new->handle;
312 graft_offload.command = TC_PRIO_GRAFT;
313
331 err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_QDISC_PRIO,
332 &graft_offload);
333
334 /* Don't report error if the graft is part of destroy operation. */
335 if (err && new != &noop_qdisc) {
336 /* Don't report error if the parent, the old child and the new
337 * one are not offloaded.
338 */
339 any_qdisc_is_offloaded = sch->flags & TCQ_F_OFFLOADED;
340 any_qdisc_is_offloaded |= new->flags & TCQ_F_OFFLOADED;
341 if (*old)
342 any_qdisc_is_offloaded |= (*old)->flags &
343 TCQ_F_OFFLOADED;
344
345 if (any_qdisc_is_offloaded)
346 NL_SET_ERR_MSG(extack, "Offloading graft operation failed.");
347 }
348
314 qdisc_offload_graft_helper(qdisc_dev(sch), sch, new, *old,
315 TC_SETUP_QDISC_PRIO, &graft_offload,
316 extack);
349 return 0;
350}
351
352static struct Qdisc *
353prio_leaf(struct Qdisc *sch, unsigned long arg)
354{
355 struct prio_sched_data *q = qdisc_priv(sch);
356 unsigned long band = arg - 1;

--- 122 unchanged lines hidden ---
317 return 0;
318}
319
320static struct Qdisc *
321prio_leaf(struct Qdisc *sch, unsigned long arg)
322{
323 struct prio_sched_data *q = qdisc_priv(sch);
324 unsigned long band = arg - 1;

--- 122 unchanged lines hidden ---