mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net_sched: Add size table for qdiscs
Add size table functions for qdiscs and calculate packet size in qdisc_enqueue(). Based on patch by Patrick McHardy http://marc.info/?l=linux-netdev&m=115201979221729&w=2 Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									0abf77e55a
								
							
						
					
					
						commit
						175f9c1bba
					
				
					 7 changed files with 199 additions and 5 deletions
				
			
		| 
						 | 
					@ -85,6 +85,26 @@ struct tc_ratespec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TC_RTAB_SIZE	1024
 | 
					#define TC_RTAB_SIZE	1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct tc_sizespec {
 | 
				
			||||||
 | 
						unsigned char	cell_log;
 | 
				
			||||||
 | 
						unsigned char	size_log;
 | 
				
			||||||
 | 
						short		cell_align;
 | 
				
			||||||
 | 
						int		overhead;
 | 
				
			||||||
 | 
						unsigned int	linklayer;
 | 
				
			||||||
 | 
						unsigned int	mpu;
 | 
				
			||||||
 | 
						unsigned int	mtu;
 | 
				
			||||||
 | 
						unsigned int	tsize;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum {
 | 
				
			||||||
 | 
						TCA_STAB_UNSPEC,
 | 
				
			||||||
 | 
						TCA_STAB_BASE,
 | 
				
			||||||
 | 
						TCA_STAB_DATA,
 | 
				
			||||||
 | 
						__TCA_STAB_MAX
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define TCA_STAB_MAX (__TCA_STAB_MAX - 1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* FIFO section */
 | 
					/* FIFO section */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct tc_fifo_qopt
 | 
					struct tc_fifo_qopt
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -482,6 +482,7 @@ enum
 | 
				
			||||||
	TCA_RATE,
 | 
						TCA_RATE,
 | 
				
			||||||
	TCA_FCNT,
 | 
						TCA_FCNT,
 | 
				
			||||||
	TCA_STATS2,
 | 
						TCA_STATS2,
 | 
				
			||||||
 | 
						TCA_STAB,
 | 
				
			||||||
	__TCA_MAX
 | 
						__TCA_MAX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,7 @@ extern struct Qdisc *qdisc_lookup_class(struct net_device *dev, u32 handle);
 | 
				
			||||||
extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
 | 
					extern struct qdisc_rate_table *qdisc_get_rtab(struct tc_ratespec *r,
 | 
				
			||||||
		struct nlattr *tab);
 | 
							struct nlattr *tab);
 | 
				
			||||||
extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 | 
					extern void qdisc_put_rtab(struct qdisc_rate_table *tab);
 | 
				
			||||||
 | 
					extern void qdisc_put_stab(struct qdisc_size_table *tab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern void __qdisc_run(struct Qdisc *q);
 | 
					extern void __qdisc_run(struct Qdisc *q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,13 @@ enum qdisc_state_t
 | 
				
			||||||
	__QDISC_STATE_SCHED,
 | 
						__QDISC_STATE_SCHED,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct qdisc_size_table {
 | 
				
			||||||
 | 
						struct list_head	list;
 | 
				
			||||||
 | 
						struct tc_sizespec	szopts;
 | 
				
			||||||
 | 
						int			refcnt;
 | 
				
			||||||
 | 
						u16			data[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Qdisc
 | 
					struct Qdisc
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
 | 
						int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
 | 
				
			||||||
| 
						 | 
					@ -39,6 +46,7 @@ struct Qdisc
 | 
				
			||||||
#define TCQ_F_INGRESS	4
 | 
					#define TCQ_F_INGRESS	4
 | 
				
			||||||
	int			padded;
 | 
						int			padded;
 | 
				
			||||||
	struct Qdisc_ops	*ops;
 | 
						struct Qdisc_ops	*ops;
 | 
				
			||||||
 | 
						struct qdisc_size_table	*stab;
 | 
				
			||||||
	u32			handle;
 | 
						u32			handle;
 | 
				
			||||||
	u32			parent;
 | 
						u32			parent;
 | 
				
			||||||
	atomic_t		refcnt;
 | 
						atomic_t		refcnt;
 | 
				
			||||||
| 
						 | 
					@ -165,6 +173,16 @@ struct tcf_proto
 | 
				
			||||||
	struct tcf_proto_ops	*ops;
 | 
						struct tcf_proto_ops	*ops;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct qdisc_skb_cb {
 | 
				
			||||||
 | 
						unsigned int		pkt_len;
 | 
				
			||||||
 | 
						char			data[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct qdisc_skb_cb *qdisc_skb_cb(struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return (struct qdisc_skb_cb *)skb->cb;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
 | 
					static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return &qdisc->q.lock;
 | 
						return &qdisc->q.lock;
 | 
				
			||||||
| 
						 | 
					@ -257,6 +275,8 @@ extern struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
 | 
				
			||||||
extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
 | 
					extern struct Qdisc *qdisc_create_dflt(struct net_device *dev,
 | 
				
			||||||
				       struct netdev_queue *dev_queue,
 | 
									       struct netdev_queue *dev_queue,
 | 
				
			||||||
				       struct Qdisc_ops *ops, u32 parentid);
 | 
									       struct Qdisc_ops *ops, u32 parentid);
 | 
				
			||||||
 | 
					extern void qdisc_calculate_pkt_len(struct sk_buff *skb,
 | 
				
			||||||
 | 
									   struct qdisc_size_table *stab);
 | 
				
			||||||
extern void tcf_destroy(struct tcf_proto *tp);
 | 
					extern void tcf_destroy(struct tcf_proto *tp);
 | 
				
			||||||
extern void tcf_destroy_chain(struct tcf_proto **fl);
 | 
					extern void tcf_destroy_chain(struct tcf_proto **fl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -308,16 +328,19 @@ static inline bool qdisc_tx_is_noop(const struct net_device *dev)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline unsigned int qdisc_pkt_len(struct sk_buff *skb)
 | 
					static inline unsigned int qdisc_pkt_len(struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return skb->len;
 | 
						return qdisc_skb_cb(skb)->pkt_len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 | 
					static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						if (sch->stab)
 | 
				
			||||||
 | 
							qdisc_calculate_pkt_len(skb, sch->stab);
 | 
				
			||||||
	return sch->enqueue(skb, sch);
 | 
						return sch->enqueue(skb, sch);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
 | 
					static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						qdisc_skb_cb(skb)->pkt_len = skb->len;
 | 
				
			||||||
	return qdisc_enqueue(skb, sch);
 | 
						return qdisc_enqueue(skb, sch);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -286,6 +286,129 @@ void qdisc_put_rtab(struct qdisc_rate_table *tab)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(qdisc_put_rtab);
 | 
					EXPORT_SYMBOL(qdisc_put_rtab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static LIST_HEAD(qdisc_stab_list);
 | 
				
			||||||
 | 
					static DEFINE_SPINLOCK(qdisc_stab_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct nla_policy stab_policy[TCA_STAB_MAX + 1] = {
 | 
				
			||||||
 | 
						[TCA_STAB_BASE]	= { .len = sizeof(struct tc_sizespec) },
 | 
				
			||||||
 | 
						[TCA_STAB_DATA] = { .type = NLA_BINARY },
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct qdisc_size_table *qdisc_get_stab(struct nlattr *opt)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *tb[TCA_STAB_MAX + 1];
 | 
				
			||||||
 | 
						struct qdisc_size_table *stab;
 | 
				
			||||||
 | 
						struct tc_sizespec *s;
 | 
				
			||||||
 | 
						unsigned int tsize = 0;
 | 
				
			||||||
 | 
						u16 *tab = NULL;
 | 
				
			||||||
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = nla_parse_nested(tb, TCA_STAB_MAX, opt, stab_policy);
 | 
				
			||||||
 | 
						if (err < 0)
 | 
				
			||||||
 | 
							return ERR_PTR(err);
 | 
				
			||||||
 | 
						if (!tb[TCA_STAB_BASE])
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s = nla_data(tb[TCA_STAB_BASE]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (s->tsize > 0) {
 | 
				
			||||||
 | 
							if (!tb[TCA_STAB_DATA])
 | 
				
			||||||
 | 
								return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
							tab = nla_data(tb[TCA_STAB_DATA]);
 | 
				
			||||||
 | 
							tsize = nla_len(tb[TCA_STAB_DATA]) / sizeof(u16);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!s || tsize != s->tsize || (!tab && tsize > 0))
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_for_each_entry(stab, &qdisc_stab_list, list) {
 | 
				
			||||||
 | 
							if (memcmp(&stab->szopts, s, sizeof(*s)))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							if (tsize > 0 && memcmp(stab->data, tab, tsize * sizeof(u16)))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
							stab->refcnt++;
 | 
				
			||||||
 | 
							spin_unlock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
							return stab;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stab = kmalloc(sizeof(*stab) + tsize * sizeof(u16), GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!stab)
 | 
				
			||||||
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stab->refcnt = 1;
 | 
				
			||||||
 | 
						stab->szopts = *s;
 | 
				
			||||||
 | 
						if (tsize > 0)
 | 
				
			||||||
 | 
							memcpy(stab->data, tab, tsize * sizeof(u16));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
						list_add_tail(&stab->list, &qdisc_stab_list);
 | 
				
			||||||
 | 
						spin_unlock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stab;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qdisc_put_stab(struct qdisc_size_table *tab)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!tab)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_lock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (--tab->refcnt == 0) {
 | 
				
			||||||
 | 
							list_del(&tab->list);
 | 
				
			||||||
 | 
							kfree(tab);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spin_unlock(&qdisc_stab_lock);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(qdisc_put_stab);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int qdisc_dump_stab(struct sk_buff *skb, struct qdisc_size_table *stab)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct nlattr *nest;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						nest = nla_nest_start(skb, TCA_STAB);
 | 
				
			||||||
 | 
						NLA_PUT(skb, TCA_STAB_BASE, sizeof(stab->szopts), &stab->szopts);
 | 
				
			||||||
 | 
						nla_nest_end(skb, nest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return skb->len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					nla_put_failure:
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void qdisc_calculate_pkt_len(struct sk_buff *skb, struct qdisc_size_table *stab)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int pkt_len, slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pkt_len = skb->len + stab->szopts.overhead;
 | 
				
			||||||
 | 
						if (unlikely(!stab->szopts.tsize))
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						slot = pkt_len + stab->szopts.cell_align;
 | 
				
			||||||
 | 
						if (unlikely(slot < 0))
 | 
				
			||||||
 | 
							slot = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						slot >>= stab->szopts.cell_log;
 | 
				
			||||||
 | 
						if (likely(slot < stab->szopts.tsize))
 | 
				
			||||||
 | 
							pkt_len = stab->data[slot];
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							pkt_len = stab->data[stab->szopts.tsize - 1] *
 | 
				
			||||||
 | 
									(slot / stab->szopts.tsize) +
 | 
				
			||||||
 | 
									stab->data[slot % stab->szopts.tsize];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pkt_len <<= stab->szopts.size_log;
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
 | 
						if (unlikely(pkt_len < 1))
 | 
				
			||||||
 | 
							pkt_len = 1;
 | 
				
			||||||
 | 
						qdisc_skb_cb(skb)->pkt_len = pkt_len;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL(qdisc_calculate_pkt_len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
 | 
					static enum hrtimer_restart qdisc_watchdog(struct hrtimer *timer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
 | 
						struct qdisc_watchdog *wd = container_of(timer, struct qdisc_watchdog,
 | 
				
			||||||
| 
						 | 
					@ -613,6 +736,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
 | 
				
			||||||
	struct nlattr *kind = tca[TCA_KIND];
 | 
						struct nlattr *kind = tca[TCA_KIND];
 | 
				
			||||||
	struct Qdisc *sch;
 | 
						struct Qdisc *sch;
 | 
				
			||||||
	struct Qdisc_ops *ops;
 | 
						struct Qdisc_ops *ops;
 | 
				
			||||||
 | 
						struct qdisc_size_table *stab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ops = qdisc_lookup_ops(kind);
 | 
						ops = qdisc_lookup_ops(kind);
 | 
				
			||||||
#ifdef CONFIG_KMOD
 | 
					#ifdef CONFIG_KMOD
 | 
				
			||||||
| 
						 | 
					@ -670,6 +794,14 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
 | 
				
			||||||
	sch->handle = handle;
 | 
						sch->handle = handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
 | 
						if (!ops->init || (err = ops->init(sch, tca[TCA_OPTIONS])) == 0) {
 | 
				
			||||||
 | 
							if (tca[TCA_STAB]) {
 | 
				
			||||||
 | 
								stab = qdisc_get_stab(tca[TCA_STAB]);
 | 
				
			||||||
 | 
								if (IS_ERR(stab)) {
 | 
				
			||||||
 | 
									err = PTR_ERR(stab);
 | 
				
			||||||
 | 
									goto err_out3;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								sch->stab = stab;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if (tca[TCA_RATE]) {
 | 
							if (tca[TCA_RATE]) {
 | 
				
			||||||
			err = gen_new_estimator(&sch->bstats, &sch->rate_est,
 | 
								err = gen_new_estimator(&sch->bstats, &sch->rate_est,
 | 
				
			||||||
						qdisc_root_lock(sch),
 | 
											qdisc_root_lock(sch),
 | 
				
			||||||
| 
						 | 
					@ -691,6 +823,7 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
 | 
				
			||||||
		return sch;
 | 
							return sch;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
err_out3:
 | 
					err_out3:
 | 
				
			||||||
 | 
						qdisc_put_stab(sch->stab);
 | 
				
			||||||
	dev_put(dev);
 | 
						dev_put(dev);
 | 
				
			||||||
	kfree((char *) sch - sch->padded);
 | 
						kfree((char *) sch - sch->padded);
 | 
				
			||||||
err_out2:
 | 
					err_out2:
 | 
				
			||||||
| 
						 | 
					@ -702,15 +835,26 @@ qdisc_create(struct net_device *dev, struct netdev_queue *dev_queue,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
 | 
					static int qdisc_change(struct Qdisc *sch, struct nlattr **tca)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (tca[TCA_OPTIONS]) {
 | 
						struct qdisc_size_table *stab = NULL;
 | 
				
			||||||
		int err;
 | 
						int err = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tca[TCA_OPTIONS]) {
 | 
				
			||||||
		if (sch->ops->change == NULL)
 | 
							if (sch->ops->change == NULL)
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		err = sch->ops->change(sch, tca[TCA_OPTIONS]);
 | 
							err = sch->ops->change(sch, tca[TCA_OPTIONS]);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			return err;
 | 
								return err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (tca[TCA_STAB]) {
 | 
				
			||||||
 | 
							stab = qdisc_get_stab(tca[TCA_STAB]);
 | 
				
			||||||
 | 
							if (IS_ERR(stab))
 | 
				
			||||||
 | 
								return PTR_ERR(stab);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qdisc_put_stab(sch->stab);
 | 
				
			||||||
 | 
						sch->stab = stab;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (tca[TCA_RATE])
 | 
						if (tca[TCA_RATE])
 | 
				
			||||||
		gen_replace_estimator(&sch->bstats, &sch->rate_est,
 | 
							gen_replace_estimator(&sch->bstats, &sch->rate_est,
 | 
				
			||||||
				      qdisc_root_lock(sch), tca[TCA_RATE]);
 | 
									      qdisc_root_lock(sch), tca[TCA_RATE]);
 | 
				
			||||||
| 
						 | 
					@ -994,6 +1138,9 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid,
 | 
				
			||||||
		goto nla_put_failure;
 | 
							goto nla_put_failure;
 | 
				
			||||||
	q->qstats.qlen = q->q.qlen;
 | 
						q->qstats.qlen = q->q.qlen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (q->stab && qdisc_dump_stab(skb, q->stab) < 0)
 | 
				
			||||||
 | 
							goto nla_put_failure;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
 | 
						if (gnet_stats_start_copy_compat(skb, TCA_STATS2, TCA_STATS,
 | 
				
			||||||
					 TCA_XSTATS, qdisc_root_lock(q), &d) < 0)
 | 
										 TCA_XSTATS, qdisc_root_lock(q), &d) < 0)
 | 
				
			||||||
		goto nla_put_failure;
 | 
							goto nla_put_failure;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -469,6 +469,7 @@ static void __qdisc_destroy(struct rcu_head *head)
 | 
				
			||||||
	struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
 | 
						struct Qdisc *qdisc = container_of(head, struct Qdisc, q_rcu);
 | 
				
			||||||
	const struct Qdisc_ops  *ops = qdisc->ops;
 | 
						const struct Qdisc_ops  *ops = qdisc->ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qdisc_put_stab(qdisc->stab);
 | 
				
			||||||
	gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
 | 
						gen_kill_estimator(&qdisc->bstats, &qdisc->rate_est);
 | 
				
			||||||
	if (ops->reset)
 | 
						if (ops->reset)
 | 
				
			||||||
		ops->reset(qdisc);
 | 
							ops->reset(qdisc);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -84,8 +84,9 @@ struct netem_skb_cb {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
 | 
					static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct netem_skb_cb));
 | 
						BUILD_BUG_ON(sizeof(skb->cb) <
 | 
				
			||||||
	return (struct netem_skb_cb *)skb->cb;
 | 
							sizeof(struct qdisc_skb_cb) + sizeof(struct netem_skb_cb));
 | 
				
			||||||
 | 
						return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* init_crandom - initialize correlated random number generator
 | 
					/* init_crandom - initialize correlated random number generator
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue