diff mbox

[06/11] sch_hfsc.c: seg_y2x(), rtsc_y2x(), hfsc_change_class() minor changes

Message ID 1320460377-8682-7-git-send-email-soltys@ziu.info
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Michal Soltys Nov. 5, 2011, 2:32 a.m. UTC
hfsc_change_class():

Make sure that invalid input (flat 2nd segment, USC without FSC) is not
allowed. Even though userspace (tc) does the respective checks as well - we
want to verify if everything is in order before the following seg_y2x() change
(and some other userspace tools not doing such checks might exist):

seg_y2x():

All callers (actually there's only one - rtsc_y2x()) guarantee that the
slope argument actually makese sense (otherwise the results would be
unusable) - so we don't heave to check for +inf case.

rtsc_y2x():

In case of flat 1st segment of a service curve, the function always
returns maximum a, such that f(a) = y (for our curves then, a = x + dx).
To keep things consistent (and continuous), we also return x+dx for
values < y.
---
 net/sched/sch_hfsc.c |   39 +++++++++++++++++++++++++++++----------
 1 files changed, 29 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
index e0cf11b..8da2d88 100644
--- a/net/sched/sch_hfsc.c
+++ b/net/sched/sch_hfsc.c
@@ -400,6 +400,8 @@  seg_y2x(u64 y, u64 ism)
 {
 	u64 x;
 
+	/* callers guarantee that ism is not infinity */
+#if 0
 	if (y == 0)
 		x = 0;
 	else if (ism == HT_INFINITY)
@@ -408,6 +410,8 @@  seg_y2x(u64 y, u64 ism)
 		x = (y >> ISM_SHIFT) * ism
 		    + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
 	}
+#endif
+	x = (y >> ISM_SHIFT) * ism + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
 	return x;
 }
 
@@ -509,7 +513,7 @@  rtsc_y2x(struct runtime_sc *rtsc, u64 y)
 {
 	u64 x;
 
-	if (y < rtsc->y)
+	if (y < rtsc->y && rtsc->dy != 0)
 		x = rtsc->x;
 	else if (y <= rtsc->y + rtsc->dy) {
 		/* x belongs to the 1st segment */
@@ -985,22 +989,40 @@  hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
 	if (tb[TCA_HFSC_RSC]) {
 		rsc = nla_data(tb[TCA_HFSC_RSC]);
-		if (rsc->m1 == 0 && rsc->m2 == 0)
-			rsc = NULL;
+		if (rsc->m2 == 0) {
+			if (rsc->m1 != 0)
+				return -EINVAL;
+			else
+				rsc = NULL;
+		}
 	}
 
 	if (tb[TCA_HFSC_FSC]) {
 		fsc = nla_data(tb[TCA_HFSC_FSC]);
-		if (fsc->m1 == 0 && fsc->m2 == 0)
-			fsc = NULL;
+		if (fsc->m2 == 0) {
+			if (fsc->m1 != 0)
+				return -EINVAL;
+			else
+				fsc = NULL;
+		}
 	}
 
 	if (tb[TCA_HFSC_USC]) {
 		usc = nla_data(tb[TCA_HFSC_USC]);
-		if (usc->m1 == 0 && usc->m2 == 0)
-			usc = NULL;
+		if (usc->m2 == 0) {
+			if (usc->m1 != 0)
+				return -EINVAL;
+			else
+				usc = NULL;
+		}
 	}
 
+	if (rsc == NULL && fsc == NULL)
+		return -EINVAL;
+
+	if (fsc == NULL && usc != NULL)
+		return -EINVAL;
+
 	if (cl != NULL) {
 		if (parentid) {
 			if (cl->cl_parent &&
@@ -1053,9 +1075,6 @@  hfsc_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 	if (hfsc_find_class(classid, sch))
 		return -EEXIST;
 
-	if (rsc == NULL && fsc == NULL)
-		return -EINVAL;
-
 	cl = kzalloc(sizeof(struct hfsc_class), GFP_KERNEL);
 	if (cl == NULL)
 		return -ENOBUFS;