There would need to be a mechanism for ordering rules instead of just the order in which they are specified, so that the order in which the rules are matched can be specified.
I think the a problem here is how to express complex yet extendable rules. RPCs need to be classified according to a logical expression to meet with different requirements. I happened to implemnt similar mechanism in another project. So I am thinking of defining rules which looks like:
JOBID=
{dd.500}@NID={192.168.1.1@tcp},JOBID={dd.0}@NID={192.168.1.*@tcp} 10000
The expression of the rule is conbined by two sub-expression, JOBID={dd.500}
@NID=
{192.168.1.1@tcp} and JOBID={dd.0}@NID={192.168.1.*@tcp}. The expression's value is the disjunction of all the sub-expressions, which mean, the expression will be true if at least one of the sub-expressions is true.
And sub-expression JOBID={dd.500}@NID={192.168.1.1@tcp}
is combined by JOBID=
{dd.500} and NID={192.168.1.1@tcp}. The value of sub-expression is the conjunction of both minimum-expressions(i.e. JOBID={dd.500}
and NID=
{192.168.1.1@tcp}
), which means the sub-expression will be trun if both of the minimum-expressions are ture.
By using this kind of expression, we can define as complex rules as we wish. And it is not necessary to change the order of matching the rules. The rules still have a decreasing priority in the list. And an coming RPC will follow the first matched rule in the list.
Ofcourse, we simply the way of defining the rules, because expression can only be written in the format of (a&&b&&...)||(c&&d&&...)||(e&&f&&...)||... There is no obvious benefit to enable complex expression like ((a&&b)||c)&&d, since it can be expressed by (a&&b&&d)||(c&&d). Otherwise, it would be too complex both for people to edit&read the rules and the computer to parse&match the rules.
The time complexity of matching the rule is N, and N is the number of minimum-expressions in the rules. Hopefully, we don't define too many rules as well as too complex expressions, so the time cost should be negligible.
Another problem is that, currently, with TBF-jobid, one bucket is allocated for RPCs belong to the same JobID. And with TBF-NID, one bucket is allocated for RPCs from the same NID. In the future, we might need to allocate one bucket for each rule instance, because otherwise, there will be too many buckets if we allocate one bucket for each kind of RPCs with different JOBID, NID and OPCODE etc.
Also, the other question I have is how RPCs within a bucket are currently ordered? Is there any sorting within the bucket (e.g. by FID) or is it FIFO?
Within a single bucket, the RPCs are queued in a FIFO way.
Not sure if it is currently possible to stack TBF on top of ORR, but that would be the logical choice to simplify implementation, but it may also be acceptable to make TBF a "super policy" that does everything instead of having separate policies.
That is a good idea. I was thinking about layered policies which means a RPC can be sorted/throttled by mutiple policies. However, with above complex rule of TBF implemented, I think ORR (or other) policy inside TBF might be enough for most (if not all) use cases. I can't think of a use case that RPCs need to be sorted for more than once. It makes sense that RPCs are first throttled for QoS purposes, and then sorted for performance improvement.
Landed for 2.8