@@ -559,13 +559,21 @@ rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u64 x, u64 y)
u32 dsm;
if (isc->sm1 <= isc->sm2) {
- /* service curve is convex */
- y1 = rtsc_x2y(rtsc, x);
- if (y1 < y)
- /* the current rtsc is smaller */
- return;
- rtsc->x = x;
- rtsc->y = y;
+ /* service curve is convex or linear */
+ y1 = rtsc_x2y(rtsc, x + isc->dx);
+ if (y1 > y + isc->dy) {
+ /*
+ * sm1/sm2 junction point is below the old curve, so
+ * update the curve with ours; note that for strictly
+ * convex curves a brief part of the first segment
+ * might be above, but it's important that 2nd infinite
+ * segment wins (which is below the old curve in this
+ * case)
+ */
+ rtsc->x = x;
+ rtsc->y = y;
+ }
+ /* else: the current rtsc is smaller */
return;
}
The condition, which chooses smaller curve in convex/convex case is a bit too simple. If we actually have intersecting curves, and base the test on initial (x,y), instead of (x+dx,y+dy), the we can choose wrong curve: + * + *++++ x,y ++*+ new ++++ * * **** old **** From the above art, (x,y) will win the comparison and old curve will be chosen, but it's new that should be selected (as its infinite 2nd segment is below the old one). Another possibility is to flatten the 1st segment (see hfsc paper), which has an effect for *y2x() functions to return max x such that f(x) = y. In this way the old curve would take precedence on the initial part. Worth considering for another patch. Signed-off-by: Michal Soltys <soltys@ziu.info> --- net/sched/sch_hfsc.c | 22 +++++++++++++++------- 1 files changed, 15 insertions(+), 7 deletions(-)