Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 236659
b: refs/heads/master
c: 817fb15
h: refs/heads/master
i:
  236657: 48b61d0
  236655: 962b01e
v: v3
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Jan 21, 2011
1 parent db848da commit 9c204dd
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3fbd8758b027995b677046dae46f9b41ea88c88f
refs/heads/master: 817fb15dfd988d8dda916ee04fa506f0c466b9d6
42 changes: 30 additions & 12 deletions trunk/net/sched/sch_sfq.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <linux/skbuff.h>
#include <linux/jhash.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <net/ip.h>
#include <net/netlink.h>
#include <net/pkt_sched.h>
Expand Down Expand Up @@ -76,7 +77,8 @@
#define SFQ_DEPTH 128 /* max number of packets per flow */
#define SFQ_SLOTS 128 /* max number of flows */
#define SFQ_EMPTY_SLOT 255
#define SFQ_HASH_DIVISOR 1024
#define SFQ_DEFAULT_HASH_DIVISOR 1024

/* We use 16 bits to store allot, and want to handle packets up to 64K
* Scale allot by 8 (1<<3) so that no overflow occurs.
*/
Expand Down Expand Up @@ -112,15 +114,15 @@ struct sfq_sched_data {
int perturb_period;
unsigned int quantum; /* Allotment per round: MUST BE >= MTU */
int limit;

unsigned int divisor; /* number of slots in hash table */
/* Variables */
struct tcf_proto *filter_list;
struct timer_list perturb_timer;
u32 perturbation;
sfq_index cur_depth; /* depth of longest slot */
unsigned short scaled_quantum; /* SFQ_ALLOT_SIZE(quantum) */
struct sfq_slot *tail; /* current slot in round */
sfq_index ht[SFQ_HASH_DIVISOR]; /* Hash table */
sfq_index *ht; /* Hash table (divisor slots) */
struct sfq_slot slots[SFQ_SLOTS];
struct sfq_head dep[SFQ_DEPTH]; /* Linked list of slots, indexed by depth */
};
Expand All @@ -137,7 +139,7 @@ static inline struct sfq_head *sfq_dep_head(struct sfq_sched_data *q, sfq_index

static unsigned int sfq_fold_hash(struct sfq_sched_data *q, u32 h, u32 h1)
{
return jhash_2words(h, h1, q->perturbation) & (SFQ_HASH_DIVISOR - 1);
return jhash_2words(h, h1, q->perturbation) & (q->divisor - 1);
}

static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb)
Expand Down Expand Up @@ -201,7 +203,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,

if (TC_H_MAJ(skb->priority) == sch->handle &&
TC_H_MIN(skb->priority) > 0 &&
TC_H_MIN(skb->priority) <= SFQ_HASH_DIVISOR)
TC_H_MIN(skb->priority) <= q->divisor)
return TC_H_MIN(skb->priority);

if (!q->filter_list)
Expand All @@ -219,7 +221,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,
return 0;
}
#endif
if (TC_H_MIN(res.classid) <= SFQ_HASH_DIVISOR)
if (TC_H_MIN(res.classid) <= q->divisor)
return TC_H_MIN(res.classid);
}
return 0;
Expand Down Expand Up @@ -496,7 +498,11 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
q->perturb_period = ctl->perturb_period * HZ;
if (ctl->limit)
q->limit = min_t(u32, ctl->limit, SFQ_DEPTH - 1);

if (ctl->divisor) {
if (!is_power_of_2(ctl->divisor) || ctl->divisor > 65536)
return -EINVAL;
q->divisor = ctl->divisor;
}
qlen = sch->q.qlen;
while (sch->q.qlen > q->limit)
sfq_drop(sch);
Expand All @@ -514,15 +520,13 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
{
struct sfq_sched_data *q = qdisc_priv(sch);
size_t sz;
int i;

q->perturb_timer.function = sfq_perturbation;
q->perturb_timer.data = (unsigned long)sch;
init_timer_deferrable(&q->perturb_timer);

for (i = 0; i < SFQ_HASH_DIVISOR; i++)
q->ht[i] = SFQ_EMPTY_SLOT;

for (i = 0; i < SFQ_DEPTH; i++) {
q->dep[i].next = i + SFQ_SLOTS;
q->dep[i].prev = i + SFQ_SLOTS;
Expand All @@ -531,6 +535,7 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
q->limit = SFQ_DEPTH - 1;
q->cur_depth = 0;
q->tail = NULL;
q->divisor = SFQ_DEFAULT_HASH_DIVISOR;
if (opt == NULL) {
q->quantum = psched_mtu(qdisc_dev(sch));
q->scaled_quantum = SFQ_ALLOT_SIZE(q->quantum);
Expand All @@ -542,6 +547,15 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt)
return err;
}

sz = sizeof(q->ht[0]) * q->divisor;
q->ht = kmalloc(sz, GFP_KERNEL);
if (!q->ht && sz > PAGE_SIZE)
q->ht = vmalloc(sz);
if (!q->ht)
return -ENOMEM;
for (i = 0; i < q->divisor; i++)
q->ht[i] = SFQ_EMPTY_SLOT;

for (i = 0; i < SFQ_SLOTS; i++) {
slot_queue_init(&q->slots[i]);
sfq_link(q, i);
Expand All @@ -556,6 +570,10 @@ static void sfq_destroy(struct Qdisc *sch)
tcf_destroy_chain(&q->filter_list);
q->perturb_period = 0;
del_timer_sync(&q->perturb_timer);
if (is_vmalloc_addr(q->ht))
vfree(q->ht);
else
kfree(q->ht);
}

static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
Expand All @@ -568,7 +586,7 @@ static int sfq_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.perturb_period = q->perturb_period / HZ;

opt.limit = q->limit;
opt.divisor = SFQ_HASH_DIVISOR;
opt.divisor = q->divisor;
opt.flows = q->limit;

NLA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
Expand Down Expand Up @@ -646,7 +664,7 @@ static void sfq_walk(struct Qdisc *sch, struct qdisc_walker *arg)
if (arg->stop)
return;

for (i = 0; i < SFQ_HASH_DIVISOR; i++) {
for (i = 0; i < q->divisor; i++) {
if (q->ht[i] == SFQ_EMPTY_SLOT ||
arg->count < arg->skip) {
arg->count++;
Expand Down

0 comments on commit 9c204dd

Please sign in to comment.