diff options
Diffstat (limited to 'net/sched/sch_cbq.c')
-rw-r--r-- | net/sched/sch_cbq.c | 76 |
1 files changed, 29 insertions, 47 deletions
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 03e389e8d945..9e43ed949167 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -405,40 +405,6 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
405 | return ret; | 405 | return ret; |
406 | } | 406 | } |
407 | 407 | ||
408 | static int | ||
409 | cbq_requeue(struct sk_buff *skb, struct Qdisc *sch) | ||
410 | { | ||
411 | struct cbq_sched_data *q = qdisc_priv(sch); | ||
412 | struct cbq_class *cl; | ||
413 | int ret; | ||
414 | |||
415 | if ((cl = q->tx_class) == NULL) { | ||
416 | kfree_skb(skb); | ||
417 | sch->qstats.drops++; | ||
418 | return NET_XMIT_CN; | ||
419 | } | ||
420 | q->tx_class = NULL; | ||
421 | |||
422 | cbq_mark_toplevel(q, cl); | ||
423 | |||
424 | #ifdef CONFIG_NET_CLS_ACT | ||
425 | q->rx_class = cl; | ||
426 | cl->q->__parent = sch; | ||
427 | #endif | ||
428 | if ((ret = cl->q->ops->requeue(skb, cl->q)) == 0) { | ||
429 | sch->q.qlen++; | ||
430 | sch->qstats.requeues++; | ||
431 | if (!cl->next_alive) | ||
432 | cbq_activate_class(cl); | ||
433 | return 0; | ||
434 | } | ||
435 | if (net_xmit_drop_count(ret)) { | ||
436 | sch->qstats.drops++; | ||
437 | cl->qstats.drops++; | ||
438 | } | ||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | /* Overlimit actions */ | 408 | /* Overlimit actions */ |
443 | 409 | ||
444 | /* TC_CBQ_OVL_CLASSIC: (default) penalize leaf class by adding offtime */ | 410 | /* TC_CBQ_OVL_CLASSIC: (default) penalize leaf class by adding offtime */ |
@@ -1669,7 +1635,8 @@ static int cbq_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new, | |||
1669 | #endif | 1635 | #endif |
1670 | } | 1636 | } |
1671 | sch_tree_lock(sch); | 1637 | sch_tree_lock(sch); |
1672 | *old = xchg(&cl->q, new); | 1638 | *old = cl->q; |
1639 | cl->q = new; | ||
1673 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); | 1640 | qdisc_tree_decrease_qlen(*old, (*old)->q.qlen); |
1674 | qdisc_reset(*old); | 1641 | qdisc_reset(*old); |
1675 | sch_tree_unlock(sch); | 1642 | sch_tree_unlock(sch); |
@@ -1798,11 +1765,23 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1798 | } | 1765 | } |
1799 | 1766 | ||
1800 | if (tb[TCA_CBQ_RATE]) { | 1767 | if (tb[TCA_CBQ_RATE]) { |
1801 | rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), tb[TCA_CBQ_RTAB]); | 1768 | rtab = qdisc_get_rtab(nla_data(tb[TCA_CBQ_RATE]), |
1769 | tb[TCA_CBQ_RTAB]); | ||
1802 | if (rtab == NULL) | 1770 | if (rtab == NULL) |
1803 | return -EINVAL; | 1771 | return -EINVAL; |
1804 | } | 1772 | } |
1805 | 1773 | ||
1774 | if (tca[TCA_RATE]) { | ||
1775 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1776 | qdisc_root_sleeping_lock(sch), | ||
1777 | tca[TCA_RATE]); | ||
1778 | if (err) { | ||
1779 | if (rtab) | ||
1780 | qdisc_put_rtab(rtab); | ||
1781 | return err; | ||
1782 | } | ||
1783 | } | ||
1784 | |||
1806 | /* Change class parameters */ | 1785 | /* Change class parameters */ |
1807 | sch_tree_lock(sch); | 1786 | sch_tree_lock(sch); |
1808 | 1787 | ||
@@ -1810,8 +1789,8 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1810 | cbq_deactivate_class(cl); | 1789 | cbq_deactivate_class(cl); |
1811 | 1790 | ||
1812 | if (rtab) { | 1791 | if (rtab) { |
1813 | rtab = xchg(&cl->R_tab, rtab); | 1792 | qdisc_put_rtab(cl->R_tab); |
1814 | qdisc_put_rtab(rtab); | 1793 | cl->R_tab = rtab; |
1815 | } | 1794 | } |
1816 | 1795 | ||
1817 | if (tb[TCA_CBQ_LSSOPT]) | 1796 | if (tb[TCA_CBQ_LSSOPT]) |
@@ -1838,10 +1817,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1838 | 1817 | ||
1839 | sch_tree_unlock(sch); | 1818 | sch_tree_unlock(sch); |
1840 | 1819 | ||
1841 | if (tca[TCA_RATE]) | ||
1842 | gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
1843 | qdisc_root_sleeping_lock(sch), | ||
1844 | tca[TCA_RATE]); | ||
1845 | return 0; | 1820 | return 0; |
1846 | } | 1821 | } |
1847 | 1822 | ||
@@ -1888,6 +1863,17 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1888 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); | 1863 | cl = kzalloc(sizeof(*cl), GFP_KERNEL); |
1889 | if (cl == NULL) | 1864 | if (cl == NULL) |
1890 | goto failure; | 1865 | goto failure; |
1866 | |||
1867 | if (tca[TCA_RATE]) { | ||
1868 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1869 | qdisc_root_sleeping_lock(sch), | ||
1870 | tca[TCA_RATE]); | ||
1871 | if (err) { | ||
1872 | kfree(cl); | ||
1873 | goto failure; | ||
1874 | } | ||
1875 | } | ||
1876 | |||
1891 | cl->R_tab = rtab; | 1877 | cl->R_tab = rtab; |
1892 | rtab = NULL; | 1878 | rtab = NULL; |
1893 | cl->refcnt = 1; | 1879 | cl->refcnt = 1; |
@@ -1929,10 +1915,6 @@ cbq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, struct nlattr **t | |||
1929 | 1915 | ||
1930 | qdisc_class_hash_grow(sch, &q->clhash); | 1916 | qdisc_class_hash_grow(sch, &q->clhash); |
1931 | 1917 | ||
1932 | if (tca[TCA_RATE]) | ||
1933 | gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
1934 | qdisc_root_sleeping_lock(sch), tca[TCA_RATE]); | ||
1935 | |||
1936 | *arg = (unsigned long)cl; | 1918 | *arg = (unsigned long)cl; |
1937 | return 0; | 1919 | return 0; |
1938 | 1920 | ||
@@ -2066,7 +2048,7 @@ static struct Qdisc_ops cbq_qdisc_ops __read_mostly = { | |||
2066 | .priv_size = sizeof(struct cbq_sched_data), | 2048 | .priv_size = sizeof(struct cbq_sched_data), |
2067 | .enqueue = cbq_enqueue, | 2049 | .enqueue = cbq_enqueue, |
2068 | .dequeue = cbq_dequeue, | 2050 | .dequeue = cbq_dequeue, |
2069 | .requeue = cbq_requeue, | 2051 | .peek = qdisc_peek_dequeued, |
2070 | .drop = cbq_drop, | 2052 | .drop = cbq_drop, |
2071 | .init = cbq_init, | 2053 | .init = cbq_init, |
2072 | .reset = cbq_reset, | 2054 | .reset = cbq_reset, |