1 --- a/net/sched/sch_generic.c
2 +++ b/net/sched/sch_generic.c
3 @@ -382,16 +382,50 @@ static const u8 prio2band[TC_PRIO_MAX+1]
5 #define PFIFO_FAST_BANDS 3
7 +struct pfifo_fast_sched_data {
8 + struct tcf_proto *filter_list;
9 + struct sk_buff_head list[PFIFO_FAST_BANDS];
12 static inline struct sk_buff_head *prio2list(struct sk_buff *skb,
15 - struct sk_buff_head *list = qdisc_priv(qdisc);
16 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
17 + struct sk_buff_head *list = q->list;
18 return list + prio2band[skb->priority & TC_PRIO_MAX];
21 +static int pfifo_fast_filter(struct sk_buff *skb, struct Qdisc* qdisc)
23 +#ifdef CONFIG_NET_CLS_ACT
24 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
25 + int result = 0, ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
26 + struct tcf_result res;
28 + if (q->filter_list != NULL)
29 + result = tc_classify(skb, q->filter_list, &res);
34 + ret = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN;
44 static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc* qdisc)
46 struct sk_buff_head *list = prio2list(skb, qdisc);
49 + ret = pfifo_fast_filter(skb, qdisc);
53 if (skb_queue_len(list) < qdisc_dev(qdisc)->tx_queue_len) {
55 @@ -403,8 +437,9 @@ static int pfifo_fast_enqueue(struct sk_
57 static struct sk_buff *pfifo_fast_dequeue(struct Qdisc* qdisc)
59 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
60 + struct sk_buff_head *list = q->list;
62 - struct sk_buff_head *list = qdisc_priv(qdisc);
64 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++) {
65 if (!skb_queue_empty(list + prio)) {
66 @@ -424,8 +459,9 @@ static int pfifo_fast_requeue(struct sk_
68 static void pfifo_fast_reset(struct Qdisc* qdisc)
70 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
71 + struct sk_buff_head *list = q->list;
73 - struct sk_buff_head *list = qdisc_priv(qdisc);
75 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
76 __qdisc_reset_queue(qdisc, list + prio);
77 @@ -448,8 +484,9 @@ nla_put_failure:
79 static int pfifo_fast_init(struct Qdisc *qdisc, struct nlattr *opt)
81 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
82 + struct sk_buff_head *list = q->list;
84 - struct sk_buff_head *list = qdisc_priv(qdisc);
86 for (prio = 0; prio < PFIFO_FAST_BANDS; prio++)
87 skb_queue_head_init(list + prio);
88 @@ -457,9 +494,36 @@ static int pfifo_fast_init(struct Qdisc
92 +static int pfifo_fast_change_class(struct Qdisc *qdisc, u32 classid, u32 parentid,
93 + struct nlattr **tca, unsigned long *arg)
98 +static unsigned long pfifo_fast_get(struct Qdisc *qdisc, u32 classid)
103 +static struct tcf_proto **pfifo_fast_find_tcf(struct Qdisc *qdisc, unsigned long cl)
105 + struct pfifo_fast_sched_data *q = qdisc_priv(qdisc);
109 + return &q->filter_list;
112 +static const struct Qdisc_class_ops pfifo_fast_class_ops = {
113 + .get = pfifo_fast_get,
114 + .change = pfifo_fast_change_class,
115 + .tcf_chain = pfifo_fast_find_tcf,
118 static struct Qdisc_ops pfifo_fast_ops __read_mostly = {
120 - .priv_size = PFIFO_FAST_BANDS * sizeof(struct sk_buff_head),
121 + .cl_ops = &pfifo_fast_class_ops,
122 + .priv_size = sizeof(struct pfifo_fast_sched_data),
123 .enqueue = pfifo_fast_enqueue,
124 .dequeue = pfifo_fast_dequeue,
125 .requeue = pfifo_fast_requeue,
126 @@ -739,3 +803,18 @@ void dev_shutdown(struct net_device *dev
127 shutdown_scheduler_queue(dev, &dev->rx_queue, &noop_qdisc);
128 WARN_ON(timer_pending(&dev->watchdog_timer));
131 +#ifdef CONFIG_NET_SCHED
132 +static int __init sch_generic_init(void)
134 + return register_qdisc(&pfifo_fast_ops);
137 +static void __exit sch_generic_exit(void)
139 + unregister_qdisc(&pfifo_fast_ops);
142 +module_init(sch_generic_init)
143 +module_exit(sch_generic_exit)