diff options
Diffstat (limited to 'net/sched/sch_hfsc.c')
-rw-r--r-- | net/sched/sch_hfsc.c | 109 |
1 files changed, 27 insertions, 82 deletions
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 407c6fb1ba14..9d124c4ee3a7 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
@@ -59,13 +59,13 @@ | |||
59 | #include <linux/skbuff.h> | 59 | #include <linux/skbuff.h> |
60 | #include <linux/string.h> | 60 | #include <linux/string.h> |
61 | #include <linux/slab.h> | 61 | #include <linux/slab.h> |
62 | #include <linux/timer.h> | ||
63 | #include <linux/list.h> | 62 | #include <linux/list.h> |
64 | #include <linux/rbtree.h> | 63 | #include <linux/rbtree.h> |
65 | #include <linux/init.h> | 64 | #include <linux/init.h> |
66 | #include <linux/netdevice.h> | 65 | #include <linux/netdevice.h> |
67 | #include <linux/rtnetlink.h> | 66 | #include <linux/rtnetlink.h> |
68 | #include <linux/pkt_sched.h> | 67 | #include <linux/pkt_sched.h> |
68 | #include <net/netlink.h> | ||
69 | #include <net/pkt_sched.h> | 69 | #include <net/pkt_sched.h> |
70 | #include <net/pkt_cls.h> | 70 | #include <net/pkt_cls.h> |
71 | #include <asm/system.h> | 71 | #include <asm/system.h> |
@@ -192,23 +192,9 @@ struct hfsc_sched | |||
192 | struct list_head droplist; /* active leaf class list (for | 192 | struct list_head droplist; /* active leaf class list (for |
193 | dropping) */ | 193 | dropping) */ |
194 | struct sk_buff_head requeue; /* requeued packet */ | 194 | struct sk_buff_head requeue; /* requeued packet */ |
195 | struct timer_list wd_timer; /* watchdog timer */ | 195 | struct qdisc_watchdog watchdog; /* watchdog timer */ |
196 | }; | 196 | }; |
197 | 197 | ||
198 | /* | ||
199 | * macros | ||
200 | */ | ||
201 | #ifdef CONFIG_NET_SCH_CLK_GETTIMEOFDAY | ||
202 | #include <linux/time.h> | ||
203 | #undef PSCHED_GET_TIME | ||
204 | #define PSCHED_GET_TIME(stamp) \ | ||
205 | do { \ | ||
206 | struct timeval tv; \ | ||
207 | do_gettimeofday(&tv); \ | ||
208 | (stamp) = 1ULL * USEC_PER_SEC * tv.tv_sec + tv.tv_usec; \ | ||
209 | } while (0) | ||
210 | #endif | ||
211 | |||
212 | #define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */ | 198 | #define HT_INFINITY 0xffffffffffffffffULL /* infinite time value */ |
213 | 199 | ||
214 | 200 | ||
@@ -394,28 +380,17 @@ cftree_update(struct hfsc_class *cl) | |||
394 | * ism: (psched_us/byte) << ISM_SHIFT | 380 | * ism: (psched_us/byte) << ISM_SHIFT |
395 | * dx: psched_us | 381 | * dx: psched_us |
396 | * | 382 | * |
397 | * Clock source resolution (CONFIG_NET_SCH_CLK_*) | 383 | * The clock source resolution with ktime is 1.024us. |
398 | * JIFFIES: for 48<=HZ<=1534 resolution is between 0.63us and 1.27us. | ||
399 | * CPU: resolution is between 0.5us and 1us. | ||
400 | * GETTIMEOFDAY: resolution is exactly 1us. | ||
401 | * | 384 | * |
402 | * sm and ism are scaled in order to keep effective digits. | 385 | * sm and ism are scaled in order to keep effective digits. |
403 | * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective | 386 | * SM_SHIFT and ISM_SHIFT are selected to keep at least 4 effective |
404 | * digits in decimal using the following table. | 387 | * digits in decimal using the following table. |
405 | * | 388 | * |
406 | * Note: We can afford the additional accuracy (altq hfsc keeps at most | ||
407 | * 3 effective digits) thanks to the fact that linux clock is bounded | ||
408 | * much more tightly. | ||
409 | * | ||
410 | * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps | 389 | * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps |
411 | * ------------+------------------------------------------------------- | 390 | * ------------+------------------------------------------------------- |
412 | * bytes/0.5us 6.25e-3 62.5e-3 625e-3 6250e-e 62500e-3 | 391 | * bytes/1.024us 12.8e-3 128e-3 1280e-3 12800e-3 128000e-3 |
413 | * bytes/us 12.5e-3 125e-3 1250e-3 12500e-3 125000e-3 | ||
414 | * bytes/1.27us 15.875e-3 158.75e-3 1587.5e-3 15875e-3 158750e-3 | ||
415 | * | 392 | * |
416 | * 0.5us/byte 160 16 1.6 0.16 0.016 | 393 | * 1.024us/byte 78.125 7.8125 0.78125 0.078125 0.0078125 |
417 | * us/byte 80 8 0.8 0.08 0.008 | ||
418 | * 1.27us/byte 63 6.3 0.63 0.063 0.0063 | ||
419 | */ | 394 | */ |
420 | #define SM_SHIFT 20 | 395 | #define SM_SHIFT 20 |
421 | #define ISM_SHIFT 18 | 396 | #define ISM_SHIFT 18 |
@@ -460,8 +435,8 @@ m2sm(u32 m) | |||
460 | u64 sm; | 435 | u64 sm; |
461 | 436 | ||
462 | sm = ((u64)m << SM_SHIFT); | 437 | sm = ((u64)m << SM_SHIFT); |
463 | sm += PSCHED_JIFFIE2US(HZ) - 1; | 438 | sm += PSCHED_TICKS_PER_SEC - 1; |
464 | do_div(sm, PSCHED_JIFFIE2US(HZ)); | 439 | do_div(sm, PSCHED_TICKS_PER_SEC); |
465 | return sm; | 440 | return sm; |
466 | } | 441 | } |
467 | 442 | ||
@@ -474,7 +449,7 @@ m2ism(u32 m) | |||
474 | if (m == 0) | 449 | if (m == 0) |
475 | ism = HT_INFINITY; | 450 | ism = HT_INFINITY; |
476 | else { | 451 | else { |
477 | ism = ((u64)PSCHED_JIFFIE2US(HZ) << ISM_SHIFT); | 452 | ism = ((u64)PSCHED_TICKS_PER_SEC << ISM_SHIFT); |
478 | ism += m - 1; | 453 | ism += m - 1; |
479 | do_div(ism, m); | 454 | do_div(ism, m); |
480 | } | 455 | } |
@@ -487,7 +462,7 @@ d2dx(u32 d) | |||
487 | { | 462 | { |
488 | u64 dx; | 463 | u64 dx; |
489 | 464 | ||
490 | dx = ((u64)d * PSCHED_JIFFIE2US(HZ)); | 465 | dx = ((u64)d * PSCHED_TICKS_PER_SEC); |
491 | dx += USEC_PER_SEC - 1; | 466 | dx += USEC_PER_SEC - 1; |
492 | do_div(dx, USEC_PER_SEC); | 467 | do_div(dx, USEC_PER_SEC); |
493 | return dx; | 468 | return dx; |
@@ -499,7 +474,7 @@ sm2m(u64 sm) | |||
499 | { | 474 | { |
500 | u64 m; | 475 | u64 m; |
501 | 476 | ||
502 | m = (sm * PSCHED_JIFFIE2US(HZ)) >> SM_SHIFT; | 477 | m = (sm * PSCHED_TICKS_PER_SEC) >> SM_SHIFT; |
503 | return (u32)m; | 478 | return (u32)m; |
504 | } | 479 | } |
505 | 480 | ||
@@ -510,7 +485,7 @@ dx2d(u64 dx) | |||
510 | u64 d; | 485 | u64 d; |
511 | 486 | ||
512 | d = dx * USEC_PER_SEC; | 487 | d = dx * USEC_PER_SEC; |
513 | do_div(d, PSCHED_JIFFIE2US(HZ)); | 488 | do_div(d, PSCHED_TICKS_PER_SEC); |
514 | return (u32)d; | 489 | return (u32)d; |
515 | } | 490 | } |
516 | 491 | ||
@@ -654,9 +629,7 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y) | |||
654 | static void | 629 | static void |
655 | init_ed(struct hfsc_class *cl, unsigned int next_len) | 630 | init_ed(struct hfsc_class *cl, unsigned int next_len) |
656 | { | 631 | { |
657 | u64 cur_time; | 632 | u64 cur_time = psched_get_time(); |
658 | |||
659 | PSCHED_GET_TIME(cur_time); | ||
660 | 633 | ||
661 | /* update the deadline curve */ | 634 | /* update the deadline curve */ |
662 | rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); | 635 | rtsc_min(&cl->cl_deadline, &cl->cl_rsc, cur_time, cl->cl_cumul); |
@@ -779,7 +752,7 @@ init_vf(struct hfsc_class *cl, unsigned int len) | |||
779 | if (cl->cl_flags & HFSC_USC) { | 752 | if (cl->cl_flags & HFSC_USC) { |
780 | /* class has upper limit curve */ | 753 | /* class has upper limit curve */ |
781 | if (cur_time == 0) | 754 | if (cur_time == 0) |
782 | PSCHED_GET_TIME(cur_time); | 755 | cur_time = psched_get_time(); |
783 | 756 | ||
784 | /* update the ulimit curve */ | 757 | /* update the ulimit curve */ |
785 | rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time, | 758 | rtsc_min(&cl->cl_ulimit, &cl->cl_usc, cur_time, |
@@ -1063,7 +1036,7 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1063 | if (cl->cl_parent == NULL && parentid != TC_H_ROOT) | 1036 | if (cl->cl_parent == NULL && parentid != TC_H_ROOT) |
1064 | return -EINVAL; | 1037 | return -EINVAL; |
1065 | } | 1038 | } |
1066 | PSCHED_GET_TIME(cur_time); | 1039 | cur_time = psched_get_time(); |
1067 | 1040 | ||
1068 | sch_tree_lock(sch); | 1041 | sch_tree_lock(sch); |
1069 | if (rsc != NULL) | 1042 | if (rsc != NULL) |
@@ -1149,22 +1122,11 @@ hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
1149 | } | 1122 | } |
1150 | 1123 | ||
1151 | static void | 1124 | static void |
1152 | hfsc_destroy_filters(struct tcf_proto **fl) | ||
1153 | { | ||
1154 | struct tcf_proto *tp; | ||
1155 | |||
1156 | while ((tp = *fl) != NULL) { | ||
1157 | *fl = tp->next; | ||
1158 | tcf_destroy(tp); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | static void | ||
1163 | hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) | 1125 | hfsc_destroy_class(struct Qdisc *sch, struct hfsc_class *cl) |
1164 | { | 1126 | { |
1165 | struct hfsc_sched *q = qdisc_priv(sch); | 1127 | struct hfsc_sched *q = qdisc_priv(sch); |
1166 | 1128 | ||
1167 | hfsc_destroy_filters(&cl->filter_list); | 1129 | tcf_destroy_chain(cl->filter_list); |
1168 | qdisc_destroy(cl->qdisc); | 1130 | qdisc_destroy(cl->qdisc); |
1169 | #ifdef CONFIG_NET_ESTIMATOR | 1131 | #ifdef CONFIG_NET_ESTIMATOR |
1170 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | 1132 | gen_kill_estimator(&cl->bstats, &cl->rate_est); |
@@ -1389,7 +1351,7 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, | |||
1389 | struct tcmsg *tcm) | 1351 | struct tcmsg *tcm) |
1390 | { | 1352 | { |
1391 | struct hfsc_class *cl = (struct hfsc_class *)arg; | 1353 | struct hfsc_class *cl = (struct hfsc_class *)arg; |
1392 | unsigned char *b = skb->tail; | 1354 | unsigned char *b = skb_tail_pointer(skb); |
1393 | struct rtattr *rta = (struct rtattr *)b; | 1355 | struct rtattr *rta = (struct rtattr *)b; |
1394 | 1356 | ||
1395 | tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; | 1357 | tcm->tcm_parent = cl->cl_parent ? cl->cl_parent->classid : TC_H_ROOT; |
@@ -1400,11 +1362,11 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, | |||
1400 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); | 1362 | RTA_PUT(skb, TCA_OPTIONS, 0, NULL); |
1401 | if (hfsc_dump_curves(skb, cl) < 0) | 1363 | if (hfsc_dump_curves(skb, cl) < 0) |
1402 | goto rtattr_failure; | 1364 | goto rtattr_failure; |
1403 | rta->rta_len = skb->tail - b; | 1365 | rta->rta_len = skb_tail_pointer(skb) - b; |
1404 | return skb->len; | 1366 | return skb->len; |
1405 | 1367 | ||
1406 | rtattr_failure: | 1368 | rtattr_failure: |
1407 | skb_trim(skb, b - skb->data); | 1369 | nlmsg_trim(skb, b); |
1408 | return -1; | 1370 | return -1; |
1409 | } | 1371 | } |
1410 | 1372 | ||
@@ -1459,21 +1421,11 @@ hfsc_walk(struct Qdisc *sch, struct qdisc_walker *arg) | |||
1459 | } | 1421 | } |
1460 | 1422 | ||
1461 | static void | 1423 | static void |
1462 | hfsc_watchdog(unsigned long arg) | 1424 | hfsc_schedule_watchdog(struct Qdisc *sch) |
1463 | { | ||
1464 | struct Qdisc *sch = (struct Qdisc *)arg; | ||
1465 | |||
1466 | sch->flags &= ~TCQ_F_THROTTLED; | ||
1467 | netif_schedule(sch->dev); | ||
1468 | } | ||
1469 | |||
1470 | static void | ||
1471 | hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) | ||
1472 | { | 1425 | { |
1473 | struct hfsc_sched *q = qdisc_priv(sch); | 1426 | struct hfsc_sched *q = qdisc_priv(sch); |
1474 | struct hfsc_class *cl; | 1427 | struct hfsc_class *cl; |
1475 | u64 next_time = 0; | 1428 | u64 next_time = 0; |
1476 | long delay; | ||
1477 | 1429 | ||
1478 | if ((cl = eltree_get_minel(q)) != NULL) | 1430 | if ((cl = eltree_get_minel(q)) != NULL) |
1479 | next_time = cl->cl_e; | 1431 | next_time = cl->cl_e; |
@@ -1482,11 +1434,7 @@ hfsc_schedule_watchdog(struct Qdisc *sch, u64 cur_time) | |||
1482 | next_time = q->root.cl_cfmin; | 1434 | next_time = q->root.cl_cfmin; |
1483 | } | 1435 | } |
1484 | WARN_ON(next_time == 0); | 1436 | WARN_ON(next_time == 0); |
1485 | delay = next_time - cur_time; | 1437 | qdisc_watchdog_schedule(&q->watchdog, next_time); |
1486 | delay = PSCHED_US2JIFFIE(delay); | ||
1487 | |||
1488 | sch->flags |= TCQ_F_THROTTLED; | ||
1489 | mod_timer(&q->wd_timer, jiffies + delay); | ||
1490 | } | 1438 | } |
1491 | 1439 | ||
1492 | static int | 1440 | static int |
@@ -1523,9 +1471,7 @@ hfsc_init_qdisc(struct Qdisc *sch, struct rtattr *opt) | |||
1523 | 1471 | ||
1524 | list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); | 1472 | list_add(&q->root.hlist, &q->clhash[hfsc_hash(q->root.classid)]); |
1525 | 1473 | ||
1526 | init_timer(&q->wd_timer); | 1474 | qdisc_watchdog_init(&q->watchdog, sch); |
1527 | q->wd_timer.function = hfsc_watchdog; | ||
1528 | q->wd_timer.data = (unsigned long)sch; | ||
1529 | 1475 | ||
1530 | return 0; | 1476 | return 0; |
1531 | } | 1477 | } |
@@ -1595,8 +1541,7 @@ hfsc_reset_qdisc(struct Qdisc *sch) | |||
1595 | __skb_queue_purge(&q->requeue); | 1541 | __skb_queue_purge(&q->requeue); |
1596 | q->eligible = RB_ROOT; | 1542 | q->eligible = RB_ROOT; |
1597 | INIT_LIST_HEAD(&q->droplist); | 1543 | INIT_LIST_HEAD(&q->droplist); |
1598 | del_timer(&q->wd_timer); | 1544 | qdisc_watchdog_cancel(&q->watchdog); |
1599 | sch->flags &= ~TCQ_F_THROTTLED; | ||
1600 | sch->q.qlen = 0; | 1545 | sch->q.qlen = 0; |
1601 | } | 1546 | } |
1602 | 1547 | ||
@@ -1612,14 +1557,14 @@ hfsc_destroy_qdisc(struct Qdisc *sch) | |||
1612 | hfsc_destroy_class(sch, cl); | 1557 | hfsc_destroy_class(sch, cl); |
1613 | } | 1558 | } |
1614 | __skb_queue_purge(&q->requeue); | 1559 | __skb_queue_purge(&q->requeue); |
1615 | del_timer(&q->wd_timer); | 1560 | qdisc_watchdog_cancel(&q->watchdog); |
1616 | } | 1561 | } |
1617 | 1562 | ||
1618 | static int | 1563 | static int |
1619 | hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) | 1564 | hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) |
1620 | { | 1565 | { |
1621 | struct hfsc_sched *q = qdisc_priv(sch); | 1566 | struct hfsc_sched *q = qdisc_priv(sch); |
1622 | unsigned char *b = skb->tail; | 1567 | unsigned char *b = skb_tail_pointer(skb); |
1623 | struct tc_hfsc_qopt qopt; | 1568 | struct tc_hfsc_qopt qopt; |
1624 | 1569 | ||
1625 | qopt.defcls = q->defcls; | 1570 | qopt.defcls = q->defcls; |
@@ -1627,7 +1572,7 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb) | |||
1627 | return skb->len; | 1572 | return skb->len; |
1628 | 1573 | ||
1629 | rtattr_failure: | 1574 | rtattr_failure: |
1630 | skb_trim(skb, b - skb->data); | 1575 | nlmsg_trim(skb, b); |
1631 | return -1; | 1576 | return -1; |
1632 | } | 1577 | } |
1633 | 1578 | ||
@@ -1681,7 +1626,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1681 | if ((skb = __skb_dequeue(&q->requeue))) | 1626 | if ((skb = __skb_dequeue(&q->requeue))) |
1682 | goto out; | 1627 | goto out; |
1683 | 1628 | ||
1684 | PSCHED_GET_TIME(cur_time); | 1629 | cur_time = psched_get_time(); |
1685 | 1630 | ||
1686 | /* | 1631 | /* |
1687 | * if there are eligible classes, use real-time criteria. | 1632 | * if there are eligible classes, use real-time criteria. |
@@ -1698,7 +1643,7 @@ hfsc_dequeue(struct Qdisc *sch) | |||
1698 | cl = vttree_get_minvt(&q->root, cur_time); | 1643 | cl = vttree_get_minvt(&q->root, cur_time); |
1699 | if (cl == NULL) { | 1644 | if (cl == NULL) { |
1700 | sch->qstats.overlimits++; | 1645 | sch->qstats.overlimits++; |
1701 | hfsc_schedule_watchdog(sch, cur_time); | 1646 | hfsc_schedule_watchdog(sch); |
1702 | return NULL; | 1647 | return NULL; |
1703 | } | 1648 | } |
1704 | } | 1649 | } |