aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_hfsc.c
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-07-06 02:21:47 -0400
committerDavid S. Miller <davem@davemloft.net>2008-07-06 02:21:47 -0400
commitbe0d39d52ce35554e856de7e9ea37ac1fa4a7f91 (patch)
treebc76beba534507e921d4eafdf615d19d012437e4 /net/sched/sch_hfsc.c
parent6fe1c7a5556807e9d7154a2d2fb938d8a9e47e5f (diff)
net-sched: sch_hfsc: use dynamic class hash helpers
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_hfsc.c')
-rw-r--r--net/sched/sch_hfsc.c81
1 files changed, 40 insertions, 41 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index e817aa00441d..3a8267246a4f 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -113,7 +113,7 @@ enum hfsc_class_flags
113 113
114struct hfsc_class 114struct hfsc_class
115{ 115{
116 u32 classid; /* class id */ 116 struct Qdisc_class_common cl_common;
117 unsigned int refcnt; /* usage count */ 117 unsigned int refcnt; /* usage count */
118 118
119 struct gnet_stats_basic bstats; 119 struct gnet_stats_basic bstats;
@@ -134,7 +134,6 @@ struct hfsc_class
134 struct rb_node vt_node; /* parent's vt_tree member */ 134 struct rb_node vt_node; /* parent's vt_tree member */
135 struct rb_root cf_tree; /* active children sorted by cl_f */ 135 struct rb_root cf_tree; /* active children sorted by cl_f */
136 struct rb_node cf_node; /* parent's cf_heap member */ 136 struct rb_node cf_node; /* parent's cf_heap member */
137 struct list_head hlist; /* hash list member */
138 struct list_head dlist; /* drop list member */ 137 struct list_head dlist; /* drop list member */
139 138
140 u64 cl_total; /* total work in bytes */ 139 u64 cl_total; /* total work in bytes */
@@ -177,13 +176,11 @@ struct hfsc_class
177 unsigned long cl_nactive; /* number of active children */ 176 unsigned long cl_nactive; /* number of active children */
178}; 177};
179 178
180#define HFSC_HSIZE 16
181
182struct hfsc_sched 179struct hfsc_sched
183{ 180{
184 u16 defcls; /* default class id */ 181 u16 defcls; /* default class id */
185 struct hfsc_class root; /* root class */ 182 struct hfsc_class root; /* root class */
186 struct list_head clhash[HFSC_HSIZE]; /* class hash */ 183 struct Qdisc_class_hash clhash; /* class hash */
187 struct rb_root eligible; /* eligible tree */ 184 struct rb_root eligible; /* eligible tree */
188 struct list_head droplist; /* active leaf class list (for 185 struct list_head droplist; /* active leaf class list (for
189 dropping) */ 186 dropping) */
@@ -933,26 +930,16 @@ hfsc_adjust_levels(struct hfsc_class *cl)
933 } while ((cl = cl->cl_parent) != NULL); 930 } while ((cl = cl->cl_parent) != NULL);
934} 931}
935 932
936static inline unsigned int
937hfsc_hash(u32 h)
938{
939 h ^= h >> 8;
940 h ^= h >> 4;
941
942 return h & (HFSC_HSIZE - 1);
943}
944
945static inline struct hfsc_class * 933static inline struct hfsc_class *
946hfsc_find_class(u32 classid, struct Qdisc *sch) 934hfsc_find_class(u32 classid, struct Qdisc *sch)
947{ 935{
948 struct hfsc_sched *q = qdisc_priv(sch); 936 struct hfsc_sched *q = qdisc_priv(sch);
949 struct hfsc_class *cl; 937 struct Qdisc_class_common *clc;
950 938
951 list_for_each_entry(cl, &q->clhash[hfsc_hash(classid)], hlist) { 939 clc = qdisc_class_find(&q->clhash, classid);
952 if (cl->classid == classid) 940 if (clc == NULL)
953 return cl; 941 return NULL;
954 } 942 return container_of(clc, struct hfsc_class, cl_common);
955 return NULL;
956} 943}
957 944
958static void 945static void
@@ -1032,7 +1019,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1032 1019
1033 if (cl != NULL) { 1020 if (cl != NULL) {
1034 if (parentid) { 1021 if (parentid) {
1035 if (cl->cl_parent && cl->cl_parent->classid != parentid) 1022 if (cl->cl_parent &&
1023 cl->cl_parent->cl_common.classid != parentid)
1036 return -EINVAL; 1024 return -EINVAL;
1037 if (cl->cl_parent == NULL && parentid != TC_H_ROOT) 1025 if (cl->cl_parent == NULL && parentid != TC_H_ROOT)
1038 return -EINVAL; 1026 return -EINVAL;
@@ -1091,8 +1079,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1091 if (usc != NULL) 1079 if (usc != NULL)
1092 hfsc_change_usc(cl, usc, 0); 1080 hfsc_change_usc(cl, usc, 0);
1093 1081
1082 cl->cl_common.classid = classid;
1094 cl->refcnt = 1; 1083 cl->refcnt = 1;
1095 cl->classid = classid;
1096 cl->sched = q; 1084 cl->sched = q;
1097 cl->cl_parent = parent; 1085 cl->cl_parent = parent;
1098 cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid); 1086 cl->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, classid);
@@ -1103,7 +1091,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1103 cl->cf_tree = RB_ROOT; 1091 cl->cf_tree = RB_ROOT;
1104 1092
1105 sch_tree_lock(sch); 1093 sch_tree_lock(sch);
1106 list_add_tail(&cl->hlist, &q->clhash[hfsc_hash(classid)]); 1094 qdisc_class_hash_insert(&q->clhash, &cl->cl_common);
1107 list_add_tail(&cl->siblings, &parent->children); 1095 list_add_tail(&cl->siblings, &parent->children);
1108 if (parent->level == 0) 1096 if (parent->level == 0)
1109 hfsc_purge_queue(sch, parent); 1097 hfsc_purge_queue(sch, parent);
@@ -1111,6 +1099,8 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
1111 cl->cl_pcvtoff = parent->cl_cvtoff; 1099 cl->cl_pcvtoff = parent->cl_cvtoff;
1112 sch_tree_unlock(sch); 1100 sch_tree_unlock(sch);
1113 1101
1102 qdisc_class_hash_grow(sch, &q->clhash);
1103
1114 if (tca[TCA_RATE]) 1104 if (tca[TCA_RATE])
1115 gen_new_estimator(&cl->bstats, &cl->rate_est, 1105 gen_new_estimator(&cl->bstats, &cl->rate_est,
1116 &sch->dev->queue_lock, tca[TCA_RATE]); 1106 &sch->dev->queue_lock, tca[TCA_RATE]);
@@ -1145,7 +1135,7 @@ hfsc_delete_class(struct Qdisc *sch, unsigned long arg)
1145 hfsc_adjust_levels(cl->cl_parent); 1135 hfsc_adjust_levels(cl->cl_parent);
1146 1136
1147 hfsc_purge_queue(sch, cl); 1137 hfsc_purge_queue(sch, cl);
1148 list_del(&cl->hlist); 1138 qdisc_class_hash_remove(&q->clhash, &cl->cl_common);
1149 1139
1150 if (--cl->refcnt == 0) 1140 if (--cl->refcnt == 0)
1151 hfsc_destroy_class(sch, cl); 1141 hfsc_destroy_class(sch, cl);
@@ -1212,7 +1202,7 @@ hfsc_graft_class(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
1212 return -EINVAL; 1202 return -EINVAL;
1213 if (new == NULL) { 1203 if (new == NULL) {
1214 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, 1204 new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1215 cl->classid); 1205 cl->cl_common.classid);
1216 if (new == NULL) 1206 if (new == NULL)
1217 new = &noop_qdisc; 1207 new = &noop_qdisc;
1218 } 1208 }
@@ -1345,8 +1335,9 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb,
1345 struct hfsc_class *cl = (struct hfsc_class *)arg; 1335 struct hfsc_class *cl = (struct hfsc_class *)arg;
1346 struct nlattr *nest; 1336 struct nlattr *nest;
1347 1337
1348 tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; 1338 tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->cl_common.classid :
1349 tcm->tcm_handle = cl->classid; 1339 TC_H_ROOT;
1340 tcm->tcm_handle = cl->cl_common.classid;
1350 if (cl->level == 0) 1341 if (cl->level == 0)
1351 tcm->tcm_info = cl->qdisc->handle; 1342 tcm->tcm_info = cl->qdisc->handle;
1352 1343
@@ -1390,14 +1381,16 @@ static void
1390hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg) 1381hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg)
1391{ 1382{
1392 struct hfsc_sched *q = qdisc_priv(sch); 1383 struct hfsc_sched *q = qdisc_priv(sch);
1384 struct hlist_node *n;
1393 struct hfsc_class *cl; 1385 struct hfsc_class *cl;
1394 unsigned int i; 1386 unsigned int i;
1395 1387
1396 if (arg->stop) 1388 if (arg->stop)
1397 return; 1389 return;
1398 1390
1399 for (i = 0; i < HFSC_HSIZE; i++) { 1391 for (i = 0; i < q->clhash.hashsize; i++) {
1400 list_for_each_entry(cl, &q->clhash[i], hlist) { 1392 hlist_for_each_entry(cl, n, &q->clhash.hash[i],
1393 cl_common.hnode) {
1401 if (arg->count < arg->skip) { 1394 if (arg->count < arg->skip) {
1402 arg->count++; 1395 arg->count++;
1403 continue; 1396 continue;
@@ -1433,21 +1426,22 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
1433{ 1426{
1434 struct hfsc_sched *q = qdisc_priv(sch); 1427 struct hfsc_sched *q = qdisc_priv(sch);
1435 struct tc_hfsc_qopt *qopt; 1428 struct tc_hfsc_qopt *qopt;
1436 unsigned int i; 1429 int err;
1437 1430
1438 if (opt == NULL || nla_len(opt) < sizeof(*qopt)) 1431 if (opt == NULL || nla_len(opt) < sizeof(*qopt))
1439 return -EINVAL; 1432 return -EINVAL;
1440 qopt = nla_data(opt); 1433 qopt = nla_data(opt);
1441 1434
1442 q->defcls = qopt->defcls; 1435 q->defcls = qopt->defcls;
1443 for (i = 0; i < HFSC_HSIZE; i++) 1436 err = qdisc_class_hash_init(&q->clhash);
1444 INIT_LIST_HEAD(&q->clhash[i]); 1437 if (err < 0)
1438 return err;
1445 q->eligible = RB_ROOT; 1439 q->eligible = RB_ROOT;
1446 INIT_LIST_HEAD(&q->droplist); 1440 INIT_LIST_HEAD(&q->droplist);
1447 skb_queue_head_init(&q->requeue); 1441 skb_queue_head_init(&q->requeue);
1448 1442
1443 q->root.cl_common.classid = sch->handle;
1449 q->root.refcnt = 1; 1444 q->root.refcnt = 1;
1450 q->root.classid = sch->handle;
1451 q->root.sched = q; 1445 q->root.sched = q;
1452 q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops, 1446 q->root.qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops,
1453 sch->handle); 1447 sch->handle);
@@ -1457,7 +1451,8 @@ hfsc_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
1457 q->root.vt_tree = RB_ROOT; 1451 q->root.vt_tree = RB_ROOT;
1458 q->root.cf_tree = RB_ROOT; 1452 q->root.cf_tree = RB_ROOT;
1459 1453
1460 list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); 1454 qdisc_class_hash_insert(&q->clhash, &q->root.cl_common);
1455 qdisc_class_hash_grow(sch, &q->clhash);
1461 1456
1462 qdisc_watchdog_init(&q->watchdog, sch); 1457 qdisc_watchdog_init(&q->watchdog, sch);
1463 1458
@@ -1520,10 +1515,11 @@ hfsc_reset_qdisc(struct Qdisc *sch)
1520{ 1515{
1521 struct hfsc_sched *q = qdisc_priv(sch); 1516 struct hfsc_sched *q = qdisc_priv(sch);
1522 struct hfsc_class *cl; 1517 struct hfsc_class *cl;
1518 struct hlist_node *n;
1523 unsigned int i; 1519 unsigned int i;
1524 1520
1525 for (i = 0; i < HFSC_HSIZE; i++) { 1521 for (i = 0; i < q->clhash.hashsize; i++) {
1526 list_for_each_entry(cl, &q->clhash[i], hlist) 1522 hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode)
1527 hfsc_reset_class(cl); 1523 hfsc_reset_class(cl);
1528 } 1524 }
1529 __skb_queue_purge(&q->requeue); 1525 __skb_queue_purge(&q->requeue);
@@ -1537,17 +1533,20 @@ static void
1537hfsc_destroy_qdisc(struct Qdisc *sch) 1533hfsc_destroy_qdisc(struct Qdisc *sch)
1538{ 1534{
1539 struct hfsc_sched *q = qdisc_priv(sch); 1535 struct hfsc_sched *q = qdisc_priv(sch);
1540 struct hfsc_class *cl, *next; 1536 struct hlist_node *n, *next;
1537 struct hfsc_class *cl;
1541 unsigned int i; 1538 unsigned int i;
1542 1539
1543 for (i = 0; i < HFSC_HSIZE; i++) { 1540 for (i = 0; i < q->clhash.hashsize; i++) {
1544 list_for_each_entry(cl, &q->clhash[i], hlist) 1541 hlist_for_each_entry(cl, n, &q->clhash.hash[i], cl_common.hnode)
1545 tcf_destroy_chain(&cl->filter_list); 1542 tcf_destroy_chain(&cl->filter_list);
1546 } 1543 }
1547 for (i = 0; i < HFSC_HSIZE; i++) { 1544 for (i = 0; i < q->clhash.hashsize; i++) {
1548 list_for_each_entry_safe(cl, next, &q->clhash[i], hlist) 1545 hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i],
1546 cl_common.hnode)
1549 hfsc_destroy_class(sch, cl); 1547 hfsc_destroy_class(sch, cl);
1550 } 1548 }
1549 qdisc_class_hash_destroy(&q->clhash);
1551 __skb_queue_purge(&q->requeue); 1550 __skb_queue_purge(&q->requeue);
1552 qdisc_watchdog_cancel(&q->watchdog); 1551 qdisc_watchdog_cancel(&q->watchdog);
1553} 1552}