<?xml version="1.0" encoding="us-ascii"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.1 (Ruby 3.1.2) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

<!ENTITY RFC1242 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.1242.xml">
<!ENTITY RFC2285 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2285.xml">
<!ENTITY RFC2544 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.2544.xml">
<!ENTITY RFC9004 SYSTEM "https://bib.ietf.org/public/rfc/bibxml/reference.RFC.9004.xml">
]>


<rfc ipr="trust200902" docName="draft-ietf-bmwg-mlrsearch-05" category="info" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="MLRsearch">Multiple Loss Ratio Search</title>

    <author initials="M." surname="Konstantynowicz" fullname="Maciek Konstantynowicz">
      <organization>Cisco Systems</organization>
      <address>
        <email>mkonstan@cisco.com</email>
      </address>
    </author>
    <author initials="V." surname="Polak" fullname="Vratko Polak">
      <organization>Cisco Systems</organization>
      <address>
        <email>vrpolak@cisco.com</email>
      </address>
    </author>

    <date year="2023" month="October" day="23"/>

    <area>ops</area>
    <workgroup>Benchmarking Working Group</workgroup>
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 50?>

<t>This document proposes extensions to <xref target="RFC2544"></xref> throughput search by
defining a new methodology called Multiple Loss Ratio search
(MLRsearch). The main objectives of MLRsearch are to minimize the
total search duration, to support searching for multiple loss ratios
and to improve results repeatability and comparability.</t>

<t>The main motivation behind extending <xref target="RFC2544"></xref> is the new set of challenges
and requirements posed by evaluating and testing software based networking
systems, specifically their data planes.</t>

<t>MLRsearch offers several ways to address these challenges, giving user
configuration options to select their preferred way.</t>



    </abstract>



  </front>

  <middle>


<?line 65?>


<section anchor="purpose-and-scope"><name>Purpose and Scope</name>

<t>The purpose of this document is to describe Multiple Loss Ratio search
(MLRsearch), a data plane throughput search methodology optimized for software
networking DUTs.</t>

<t>Applying vanilla <xref target="RFC2544"></xref> throughput bisection to software DUTs
results in a number of problems:</t>

<t><list style="symbols">
  <t>Binary search takes too long as most of trials are done far from the
eventually found throughput.</t>
  <t>The required final trial duration and pauses between trials
prolong the overall search duration.</t>
  <t>Software DUTs show noisy trial results,
leading to a big spread of possible discovered throughput values.</t>
  <t>Throughput requires loss of exactly zero frames, but the industry
frequently allows for small but non-zero losses.</t>
  <t>The definition of throughput is not clear when trial results are inconsistent.</t>
</list></t>

<t>MLRsearch library aims to address these problems by applying the following set
of enhancements:</t>

<t><list style="symbols">
  <t>Allow multiple shorter trials instead of one big trial per load.
  <list style="symbols">
      <t>Optionally, tolerate a percentage of trial result with higher loss.</t>
    </list></t>
  <t>Allow searching for multiple search goals, with differing loss ratios.
  <list style="symbols">
      <t>Any trial result can affect each search goal in principle.</t>
    </list></t>
  <t>Insert multiple coarse targets for each search goal, earlier ones need
to spend less time on trials.
  <list style="symbols">
      <t>Earlier targets also aim for lesser precision.</t>
      <t>Use Forwarding Rate (FR) at maximum offered load
<xref target="RFC2285"></xref> (section 3.6.2) to initialize the initial targets.</t>
    </list></t>
  <t>Take care when dealing with inconsistent trial results.
  <list style="symbols">
      <t>Reported throughput is smaller than smallest load with high loss.</t>
      <t>Smaller load candidates are measured first.</t>
    </list></t>
  <t>Apply several load selection heuristics to save even more time
by trying hard to avoid unnecessarily narrow bounds.</t>
</list></t>

<t>Some of these enhancements are formalized as MLRsearch specification,
the remaining enhancements are treated as implementation details,
thus achieving high comparability without limiting future improvements.</t>

<t>MLRsearch configuration options are flexible enough to
support both conservative settings and aggressive settings.
Where the conservative settings lead to results
unconditionally compliant with <xref target="RFC2544"></xref>,
but longer search duration and worse repeatability.
Conversely, aggressive settings lead to shorter search duration
and better repeatability, but the results are not compliant with <xref target="RFC2544"></xref>.</t>

<t>No part of <xref target="RFC2544"></xref> is intended to be obsoleted by this document.</t>

</section>
<section anchor="identified-problems"><name>Identified Problems</name>

<t>This chapter describes the problems affecting usability
of various preformance testing methodologies,
mainly a binary search for <xref target="RFC2544"></xref> unconditionally compliant throughput.</t>

<t>The last chapter will summarize how the problems are addressed,
the middle chapters provide explanations and definitions needed for that.</t>

<section anchor="long-search-duration"><name>Long Search Duration</name>

<t>Emergence of software DUTs, with frequent software updates and a
number of different frame processing modes and configurations,
has increased both the number of performance tests requred to verify DUT update
and the frequency of running those tests.
This makes the overall test execution time even more important than before.</t>

<t>In the context of characterising particular DUT&#39;s network performance,
this calls for improving the time efficiency of throughput search.
A vanilla bisection (at 60sec trial duration for unconditional <xref target="RFC2544"></xref>
compliance) is slow, because most trials spend time quite far from the
eventual throughput.</t>

<t><xref target="RFC2544"></xref> does not specify any stopping condition for throughput search,
so users can trade-off between search duration and achieved precision.
But, due to logarithmic nature of bisection, even small improvement
in search duration needs relatively big sacrifice in the precision of the
discovered throughput.</t>

</section>
<section anchor="dut-in-sut"><name>DUT in SUT</name>

<t><xref target="RFC2285"></xref> defines:
- DUT as
  - The network forwarding device to which stimulus is offered and
    response measured <xref target="RFC2285"></xref> (section 3.1.1).
- SUT as
  - The collective set of network devices to which stimulus is offered
    as a single entity and response measured <xref target="RFC2285"></xref> (section 3.1.2).</t>

<t><xref target="RFC2544"></xref> specifies a test setup with an external tester stimulating the
networking system, treating it either as a single DUT, or as a system
of devices, an SUT.</t>

<t>In case of software networking, the SUT consists nt only of the DUT
as a software program processing frames, but also of
a server hardware and operating system functions,
with server hardware resources shared across all programs
and the operating system running on the same server.</t>

<t>The DUT is effectively nested within the rest of the SUT.</t>

<t>Due to a shared multi-tenant nature of SUT, DUT is subject to
possible interference coming from the operating system and any other
software running on the same server. Some sources of such interference
can be to some degree eliminated, e.g. by pinning DUT program threads
to specific CPU cores and isolating those cores to avoid context switching.
But some level of adverse effects may remain even after
all such reasonable precautions are applied.
These effects affect DUT&#39;s network performance negatively.
As the effects are hard to predict in general, they have impact similar to
what other engineering disciplines define as a noise.
Thus, all such effects are called an SUT noise.</t>

<t>DUT can also exhibit fluctuating performance itself, for reasons
not related to the rest of SUT, for example due to pauses in execution
as needed for internal stateful processing. In many cases this
may be an expected per-design behavior, as it would be observable even
in a hypothetical scenario where all sources of SUT noise are eliminated.
Such behavior affects trial results in a way similar to SUT noise.
As the two phenomenons are hard to destinguish,
this document uses the word noise as a shorthand covering both
this internal DUT performance fluctuations and genuine SUT noise.</t>

<t>A simple model of SUT performance consists of an idealized noiseless performance,
and additional noise effects. The noiseless performance is assumed to be constant,
all observed performance variations are due to noise.
The impact of the noise can vary in time, sometimes wildly,
even within a single trial.
The noise can sometimes be negligible, but frequently
it lowers the observed SUT performance as observed in trial results.</t>

<t>In this model, SUT does not have a single performance value, it has a spectrum.
One end of the spectrum is the idealized noiseless performance value,
the other end can be called a noiseful performance. In practice, trial results
close to the noiseful end of the spectrum happen only rarely.
The worse the performance value is, the more rarely it is seen in a trial.
Therefore, the extreme noiseful end of SUT spectrum is not really observable
among trial results. Also, the extreme noiseless end of SUT spectrum
is unlikely to be observable, this time because some small noise effects
are likely to occur multiple times during a trial.</t>

<t>Unless specified otherwise, this document talks about potentially observable
ends of the SUT performance spectrum, not about the extreme ones.</t>

<t>Focusing on DUT, the benchmarking effort should aim
at eliminating only the SUT noise from SUT measurements.
In practice that is not really possible, as based on authors experience
and available literature, there are no realistic enough models
able to distinguish SUT noise from DUT fluctuations.</t>

<t>However, assuming that a well-constructed SUT has the DUT as its
performance bottleneck, the DUT ideal noiseless performance can be defined
as the noiseless end of SUT performance spectrum. At least for
throughput. For other performance quantities such as latency there may be an
additive difference.</t>

<t>Note that by this definition, DUT noiseless performance
also minimizes the impact of DUT fluctuations, as much as realistically possible
for a given trial duration.</t>

<t>In this document, we reduce the DUT in SUT problem to estimating
the noiseless end of SUT performance spectrum from a limited number of
trial results.</t>

<t>Any improvements to throughput search algorithm, aimed for better
dealing with software networking SUT and DUT setup, should employ
strategies recognizing the presence of SUT noise, and allow discovery of
(proxies for) DUT noiseless performance
at different levels of sensitivity to SUT noise.</t>

</section>
<section anchor="repeatability-and-comparability"><name>Repeatability and Comparability</name>

<t><xref target="RFC2544"></xref> does not suggest to repeat throughput search. And from just one
discovered throughput value, it cannot be determined how repeatable that value is.
In practice, poor repeatability is also the main cause of poor
comparability, that is different benchmarking teams can test the same SUT
but get throughput values differing more than expected from search precision.</t>

<t><xref target="RFC2544"></xref> throughput requirements (60 seconds trial and
no tolerance of a single frame loss) affect the throughput results
in the following way.
The SUT behavior close to the noiseful end of its performance spectrum
consists of rare occasions of significantly low performance,
but the long trial duration makes those occasions not so rare on the trial level.
Therefore, the binary search results tend to wander away from the noiseless end
of SUT performance spectrum, more frequently and more widely than shorter
trials would, thus resulting in poor throughput repeatability.</t>

<t>The repeatability problem can be addressed by defining a search procedure
which reports more stable results,
even if they can no longer be called throughput in <xref target="RFC2544"></xref> sense.
According to the SUT performance spectrum model, better repeatability
will be at the noiseless end of the spectrum.
Therefore, solutions to the DUT in SUT problem
will help also with the repeatability problem.</t>

<t>Conversely, any alteration to <xref target="RFC2544"></xref> throughput search
that improves repeatability should be considered
as less dependent on the SUT noise.</t>

<t>An alternative option is to simply run a search multiple times, and report some
statistics (e.g. average and standard deviation). This can be used
for a subset of tests deemed more important,
but it makes the search duration problem even more pronounced.</t>

</section>
<section anchor="throughput-with-non-zero-loss"><name>Throughput with Non-Zero Loss</name>

<t><xref target="RFC1242"></xref> (section 3.17) defines throughput as:
    The maximum rate at which none of the offered frames
    are dropped by the device.</t>

<t>Then, it says:
    Since even the loss of one frame in a
    data stream can cause significant delays while
    waiting for the higher level protocols to time out,
    it is useful to know the actual maximum data
    rate that the device can support.</t>

<t>Contrary to that, many benchmarking teams settle with small, non-zero
loss ratio as the goal for a their load search.</t>

<t>Motivations are many:</t>

<t><list style="symbols">
  <t>Modern protocols tolerate frame loss better,
compared to the time when <xref target="RFC1242"></xref> and <xref target="RFC2544"></xref> were specified.</t>
  <t>Trials nowadays send way more frames within the same duration,
increasing the chance small SUT performance fluctuatios
is enough to cause frame loss.</t>
  <t>Small bursts of frame loss caused by noise have otherwise smaller impact
on the average frame loss ratio ovserved in the trial,
as during other parts of the same trial the SUT may work mroe closely
to its noiseless performance, thus perhaps lowering the trial loss ratio
below the goal loss ratio value.</t>
  <t>If an approximation of the SUT noise impact on the trial loss ratio is known,
it can be set as the goal loss ratio.</t>
</list></t>

<t>Regardless of validity of any and all similar motivations,
support for non-zero loss goals makes any search algorithm more user friendly.
<xref target="RFC2544"></xref> throughput is not user friendly in this regard.</t>

<t>Assuming users are allowed to specify the goal loss ratio value,
the usefulness is enhanced even more if users can specify multiple
loss ratio values, especially when a single search can find all relevant bounds.</t>

<t>Searching for multiple search goals also helps to describe the SUT performance
spectrum better than a single search goal result.
For example, repeated wide gap between zero and non-zero loss loads
indicates the noise has a large impact on the observed performance,
which is not evident from a single goal load search procedure result.</t>

<t>It is easy to modify the vanilla bisection to find a lower bound
for intended load that satisfies a non-zero goal loss ratio.
But it is not that obvious how to search for multiple goals at once,
hence the support for multiple search goals remains a problem.</t>

</section>
<section anchor="inconsistent-trial-results"><name>Inconsistent Trial Results</name>

<t>While performing throughput search by executing a sequence of
measurement trials, there is a risk of encountering inconsistencies
between trial results.</t>

<t>The plain bisection never encounters inconsistent trials.
But <xref target="RFC2544"></xref> hints about possibility of inconsistent trial results,
in two places in its text.
The first place is section 24, where full trial durations are required,
presumably because they can be inconsistent with results
from shorter trial durations.
The second place is section 26.3, where two successive zero-loss trials
are recommended, presumably because after one zero-loss trial
there can be subsequent inconsistent non-zero-loss trial.</t>

<t>Examples include:</t>

<t><list style="symbols">
  <t>A trial at the same load (same or different trial duration) results
in a different trial loss ratio.</t>
  <t>A trial at higher load (same or different trial duration) results
in a smaller trial loss ratio.</t>
</list></t>

<t>Any robust throughput search algorithm needs to decide how to continue
the search in presence of such inconsistencies.
Definitions of throughput in <xref target="RFC1242"></xref> and <xref target="RFC2544"></xref> are not specific enough
to imply a unique way of handling such inconsistencies.</t>

<t>Ideally, there will be a definition of a new quantity which both generalizes
throughput for non-zero-loss (and other possible repeatibility enhancements),
while being precise enough to force a specific way to resolve trial result
inconsistencies.
But until such definition is agreed upon, the correct way to handle
inconsistent trial results remains an open problem.</t>

</section>
</section>
<section anchor="mlrsearch-specification"><name>MLRsearch Specification</name>

<t>This chapter focuses on technical definitions needed for evaluating
whether a particular test procedure adheres to MLRsearch specification.</t>

<t>For motivations, explanations, and other comments see other chapters.</t>

<section anchor="mlrsearch-architecture"><name>MLRsearch Architecture</name>

<t>MLRsearch architecture consists of three main components:
the manager, the controller and the measurer.
Presence of other components (mainly the SUT) is also implied.</t>

<t>While the manager and the measurer can be seen a abstractions
present in any testing procedure, the behavior of the controller
is what distinguishes MLRsearch algorithms from other search procedures.</t>

<section anchor="measurer"><name>Measurer</name>

<t>The measurer is the component which performs one trial
as described in <xref target="RFC2544"></xref> section 23, when requested by the controller.</t>

<t>Specifically, one call to the measurer accepts a trial load value
and trial duration value, performs the trial, and returns
the measured trial loss ratio, and optionally a different duration value.</t>

<t>It is responsibility of the measurer to uphold any requirements
and assumptions present in MLRsearch specification
(e.g. trial forwarding ratio not being larger than one).
Implementers have some freedom, for example in the way they deal with
duplicated frames, or what to return if tester sent zero frames towards SUT.
Implementations are RECOMMENDED to document their behavior
related to such freedoms in as detailed way as possible</t>

<t>Implemenations MUST document any deviations from RFC documents,
for example if the wait time around traffic
is shorter than what <xref target="RFC2544"></xref> section 23 specifies.</t>

</section>
<section anchor="controller"><name>Controller</name>

<t>The controller is the component of MLRsearch architecture
that is called by the manager (just once), calls the measurer
(usually multiple times in succession),
and returns the result of the search to the manager.</t>

<t>The only required argument in the call to the controller
is a list of search goals. For the structure of the search result,
see subsection Search Result.</t>

</section>
<section anchor="manager"><name>Manager</name>

<t>The manager is the component that initializes SUT, traffic generator
(tester in <xref target="RFC2544"></xref>), the measurer and the controller
with intended configurations. It then hands over the execution
to the controller and receives its result.</t>

<t>Creation of reports of appropriate format can also be understood
as the responsibility of the manager.</t>

</section>
</section>
<section anchor="units"><name>Units</name>

<t>The specification deals with physical quantities, so it is assumed
each numeric value is accompanied by an appropriate physical unit.</t>

<t>The specification does not state which unit is appropriate,
but implementations MUST make it explicit which unit is used
for each value provided or received by the user.</t>

<t>For example, load quantities (including the conditional throughput)
returned by the controller are defined to be based on single-interface
(unidirectional) loads. For bidirectional traffic, users are likely
to expect bidirectional throughput quantities, so the manager is responsible
for making its report clear.</t>

</section>
<section anchor="sut"><name>SUT</name>

<t>As defined in <xref target="RFC2285"></xref>:
The collective set of network devices to which stimulus is offered
as a single entity and response measured.</t>

</section>
<section anchor="trial"><name>Trial</name>

<t>A trial is the part of test described in <xref target="RFC2544"></xref> section 23.</t>

<section anchor="trial-load"><name>Trial Load</name>

<t>Trial load is the intended constant load for a trial.</t>

<t>Load is the quantity implied by Constant Load of <xref target="RFC1242"></xref>,
Data Rate of <xref target="RFC2544"></xref> and Intended Load of <xref target="RFC2285"></xref>.
All three specify this value applies to one (input or output) interface.</t>

</section>
<section anchor="trial-duration"><name>Trial Duration</name>

<t>Trial duration is the intended duration of the traffic for a trial.</t>

<t>In general, this general quantity does not include any preparation nor waiting
described in section 23 of <xref target="RFC2544"></xref>.</t>

<t>However, the measurer MAY return a duration value different
from the intended duration. This may be useful for users
who want to control the overal search duration, not just the traffic part of it.
The manager MUST report how does the measurer computes the returned duration
values in that case.</t>

</section>
<section anchor="trial-forwarding-ratio"><name>Trial Forwarding Ratio</name>

<t>Trial forwarding ratio is dimensionless floating point value,
assumed to be between 0.0 and 1.0, both including.
It is computed as the number of frames forwarded by SUT, divided by
the number of frames that should have been forwarded during the trial.</t>

<t>Note that, contrary to load, frame counts used to compute
trial forwarding ratio are aggregates over all SUT ports.</t>

<t>Questions around what is the correct number of frames
that should have been forwarded it outside of the scope of this document.
E.g. what should the measurer return when it detects
that the offered load differs significantly from the intended load.</t>

<t>It is RECOMMENDED implementations return an irregular goal result
if they detect questionable (in comparability sense) trial results
affecting their goal result.</t>

</section>
<section anchor="trial-loss-ratio"><name>Trial Loss Ratio</name>

<t>Trial loss ratio is equal to one minus the trial forwarding ratio.</t>

</section>
<section anchor="trial-forwarding-rate"><name>Trial Forwarding Rate</name>

<t>The trial forwarding rate is the trial load multiplied by
the trial forwarding ratio.</t>

<t>Note that this is very similar, but not identical to Forwarding Rate
as defined in <xref target="RFC2285"></xref> section 3.6.1, as that definition
is specific to one output interface, while trial forwarding ratio
is based on frame counts aggregated over all SUT interfaces.</t>

</section>
</section>
<section anchor="traffic-profile"><name>Traffic profile</name>

<t>Any other specifics (besides trial load and trial duration)
the measurer needs to perform the trial are understood as a composite
called the traffic profile.
All its attributes are assumed to be constant during the search,
and the composite is configured on the measurer by the manager
before the search starts.</t>

<t>Traffic profile is REQUIRED by <xref target="RFC2544"></xref> to contain some specific quantities,
for example frame size.
Several more specific quantities may be RECOMMENDED.</t>

<t>Depending on SUT configuration, e.g. when testing specific protocols,
additional values need to be included in the traffic profile
and in the test report. See other IETF documents.</t>

</section>
<section anchor="search-goal"><name>Search Goal</name>

<t>A search goal is one item of the list required as an argument
when the manager calls the controller.</t>

<t>Each search goal is composite consisting of several attributes,
some of them are required.
Implementations are free to add their own attributes.</t>

<t>Subsections list all required attributes and one recommended attribute.</t>

<t>The meaning of the attributes is formally given only by their effect
on the computation of the attributes of the goal result.
The subsections do contain a short informal description,
but see other chapters for more in-depth explanations.</t>

<section anchor="goal-final-trial-duration"><name>Goal Final Trial Duration</name>

<t>A threshold value for trial durations.
REQUIRED attribute, MUST be positive.</t>

<t>Informally, the conditional throughput for this goal will be computed
only from trial results from trials as long as this.</t>

</section>
<section anchor="goal-duration-sum"><name>Goal Duration Sum</name>

<t>A threshold value for a particular sum of trial durations.
REQUIRED attribute, MUST be positive.</t>

<t>This uses the duration values returned by the measurer,
in case it returns something else than the intended durations
for the traffic part of the search.</t>

<t>Informally, even at looking only at trials done at this goal&#39;s
final trial duration, MLRsearch may spend up to this time measuring
the same load value.</t>

</section>
<section anchor="goal-loss-ratio"><name>Goal Loss Ratio</name>

<t>A threshold value for trial loss ratios.
REQUIRED attribute, MUST be non-negative and smaller than one.</t>

<t>Informally, if a load causes too many trials with trial results larger than this,
the conditional throughput for this goal will be smaller than that load.</t>

</section>
<section anchor="goal-exceed-ratio"><name>Goal Exceed Ratio</name>

<t>A threshold value for particular ratio of duration sums.
REQUIRED attribute, MUST be non-negative and smaller than one.</t>

<t>This uses the duration values returned by the measurer,
in case it returns something else than the intended durations
for the traffic part of the search.</t>

<t>Informally, this acts as the q-value for a quantile when selecting
the forwarding rate of which trial result becomes the conditional throughput.
For example, when the goal exceed ratio is 0.5 and MLRsearch
happened to use the whole goal duration sum when determining conditional
throughput, it means the conditional throughput is the median
of trial forwarding rates.
In practice, MLRsearch may stop measuring a load before the goal duration sum
is reached, and the conditional throughput in that case frequently
is the worst trial still not exceeding the goal loss ratio.
If the goal duration sum is no larger than the goal fina trial duration,
MLRsearch performs only one trial per load (unless other goals need more)
and the goal exceed ratio has no effect on the search result.</t>

</section>
<section anchor="goal-width"><name>Goal Width</name>

<t>A value used as a threshold for telling when two trial load values
are close enough.</t>

<t>RECOMMENDED attribute, positive. Implementations without this attribute
MUST give the manager other ways to control the search exit condition.</t>

<t>Absolute load difference and relative load difference are two popular choices,
but implementations may choose a different way to specify width.</t>

<t>Informally, this acts as a stopping condition, controling the precision
of the search. The search stops if every goal has reached its precision.</t>

</section>
</section>
<section anchor="search-result"><name>Search Result</name>

<t>Search result is a single composite object returned from the controller
to the manager.
It is a mapping from the search goals (see section Search Goal) into goal results
(see section Goal Result).
The mapping MUST map from all the search goals present in the controller input.</t>

<t>Each search goal instance is mapped to a goal result instance.
Multiple search goal instances may map to the same goal result instance.</t>

</section>
<section anchor="goal-result"><name>Goal Result</name>

<t>Goal result is a composite object consisting of several attributes.
All attributes are related to the same search goal, the one search goal instance
the Search Result is mapping into this instance of the Goal Result.</t>

<t>Some of the attributes are required, some are recommended,
implementations are free to add their own.</t>

<t>The subsections define attributes for regular goal result.
Implementations are free to define their own irregular goal results,
but the manager MUST report them clearly as not regular according to this section.</t>

<t>A typical irregular result is when all trials at maximum offered load
have zero loss, as the relevant upper bound does not exist in that case.</t>

<section anchor="relevant-upper-bound"><name>Relevant Upper Bound</name>

<t>Relevant upper bound is the intended load value that is classified
at the end of the search as the relevant upper bound (see Appendix A)
for this goal.
This is a REQUIRED attribute.</t>

<t>Informally, this is the smallest intended load that failed to uphold
all the requirements of this search goal, mainly the goal loss ratio
in combination with the goal exceed ratio.</t>

</section>
<section anchor="relevant-lower-bound"><name>Relevant Lower Bound</name>

<t>Relevant lower bound is the intended load value that got classified
(after all trials) as the relevant lower bound (see Appendix A) for this goal.
This is a REQUIRED attribute.</t>

<t>The distance between the relevant lower bound and the relevant upper bound
MUST NOT be larger than the goal width, for a regular goal result,
if the implementation offers width as a goal attribute.</t>

<t>Informally, this is the smallest intended load that managed to uphold
all the requirements of this search goal, mainly the goal loss ratio
in combination with the goal exceed ratio, while not being larger
than the relevant upper bound.</t>

</section>
<section anchor="conditional-throughput"><name>Conditional Throughput</name>

<t>The conditional throughput (see Appendix B) as evaluated
at the relevant lower bound.
This is a RECOMMENDED attribute.</t>

<t>Informally, a typical forwarding rate expected to be seen
at the relevant lower bound. But frequently just a conservative estimate thereof,
as MLRsearch implementations tend to stop gathering more data
as soon as they confirm this estimate cannot get worse within
the goal duration sum.</t>

</section>
</section>
</section>
<section anchor="mlrsearch-explanations"><name>MLRsearch Explanations</name>

<t>This chapter focuses on intuitions and motivations
and skips over some important details.</t>

<t>Familiarity with the MLRsearch specification is not required here,
so this chapter can act as an introduction.
For example, this chapter start talking about tightest lower bounds
before it is ready to talk about the relevant lower bound from the specification.</t>

<section anchor="mlrsearch-versions"><name>MLRsearch Versions</name>

<t>The MLRsearch algorithm has been developed in a code-first approach,
a Python library has been created, debugged and used in production
before first descriptions (even informal) were published.
In fact, multiple versions of the library were used in production
over past few years, and later code was usually not compatible
with earlier descriptions.</t>

<t>The code in (any version of) MLRsearch library fully determines
the search process (for given configuration parameters),
leaving no space for deviations.
MLRsearch as a name for a broad class of possible algorithms
leaves plenty of space for future improvements, at the cost
of poor comparability of results of different MLRsearch implementations.</t>

<t>This document aspires to prescribe a MLRsearch specification
in a way that restricts the important parts related to comparability,
while leaving other parts vague enough so implementations can improve freely.</t>

</section>
<section anchor="exit-condition"><name>Exit Condition</name>

<t><xref target="RFC2544"></xref> prescribes that after performing one trial at a specific offered load,
the next offered load should be larger or smaller, based on frame loss.</t>

<t>The usual implementation uses binary search. Here a lossy trial becomes
a new upper bound, a lossless trial becomes a new lower bound.
The span of values between the tightest lower bound and the tightest upper bound
forms an interval of possible results,
and after each trial the width of that interval halves.</t>

<t>Usually the binary search implementation tracks only the two tightest bounds,
simply calling them bounds, but the old values still remain valid bounds,
just not as tight as the new ones.</t>

<t>After some number of trials, the tightest lower bound becomes the throughput.
<xref target="RFC2544"></xref> does not specify when (if ever) should the search stop.</t>

<t>MLRsearch library introduces a concept of goal width. The search stops
when the distance between the tightest upper bound and the tightest lower bound
is smaller than a user-configured value called goal width from now on.
In other words, interval width has to be smaller than goal width
at the end of the search.</t>

<t>This goal width value therefore determines the precision of the result.
As MLRsearch specification requires a particular structure of the result,
the result itself does contain enough information to determine its precision,
thus it is not required to report the goal width value.</t>

<t>This allows MLRsearch implementations to use exit conditions
different from goal width.
The MLRsearch specification only REQUIRES the search procedure
to always finish in a finite time, regardless of possible trial results.</t>

</section>
<section anchor="load-classification"><name>Load Classification</name>

<t>MLRsearch keeps the basic logic of binary search (tracking tightest bounds,
measuring at the middle), perhaps with minor technical clarifications.
The algorithm chooses an intended load (as opposed to offered load),
the interval between bounds does not need to be split exactly in two equal halves,
and the final reported structure specifies both bounds
(optionally also the conditional throughput at the lower bound, defined later).</t>

<t>The biggest difference is that in order to classify a load
as an upper or lower bound, MLRsearch may need more than one trial
(depending on configuration options) to be performed at the same intended load.</t>

<t>As a consequence, even if a load already does have few trial results,
it still may be classified as undecided, neither a lower bound nor an upper bound.</t>

<t>Explanation of the classification logic is given in the next chatper,
as it relies heavily on other sections of this chapter.</t>

<t>For repeatability and comparability reasons, it is important that
given a set of trial results, all implementations of MLRsearch
classify the load in an equivalent way.</t>

</section>
<section anchor="loss-ratios"><name>Loss Ratios</name>

<t>Next difference is in goals of the search. <xref target="RFC2544"></xref> has a single goal,
based on classifying full-length trials as either loss-less or lossy.</t>

<t>As the name suggests, MLRsearch can seach for multiple goals, differing in their
loss ratios. Precise definition of goal loss ratio will be given later.
The <xref target="RFC2544"></xref> throughput goal then simply becomes a zero goal loss ratio.
Different goals also may have different goal width.</t>

<t>A set of trial results for one specific intended load value
can classify the load as an upper bound for some goals, but a lower bound
for some other goals, and undecided for the rest of the goals.</t>

<t>Therefore, the load classification depends not only on ttrial results,
but also on the goal. The overall search procedure becomes more complicated
(compared to binary search with a single goal),
but most of the complications do not affect the final result,
except for one phenomenon, loss inversion.</t>

</section>
<section anchor="loss-inversion"><name>Loss Inversion</name>

<t>In <xref target="RFC2544"></xref> throuhput search using bisection, any load with lossy trial
becomes a hard upper bound, meaning every subsequent trial has smaller
intended load.</t>

<t>But in MLRsearch, a load that is classified as an upper bound for one goal
may still be a lower bound for another goal, and due to that other goal
MLRsearch will probably perform trials at even higher loads.
What to do when all such higher load trials happen to have zero loss?
Does it mean the earlier upper bound was not real?
Does it mean the later lossless trials are not considered a lower bound?
Surely we do not want to have an upper bound at a load smaller than a lower bound.</t>

<t>MLRsearch is conservative in these situations.
The upper bound is considered real, and the lossless trials at higher loads
are considered to be a coincidence, at least when computing the final result.</t>

<t>This is formalized using new notions, the relevant upper bound and
the relevant lower bound.
Load classification is still based just on the set of trial results
at a given intended load (trials at other loads are ignored),
making it possible to have a lower load classified as an upper bound
and a higher load classified as a lower bound (for the same goal).
The relevant upper bound (for a goal) is the smallest load classified
as an upper bound. But the relevant lower bound is not simply
the largest among lower bounds. It is the largest load among loads
that are lower bounds while also being smaller than the relevant upper bound.</t>

<t>With these definitions, the relevant lower bound is always smaller
than the relevant upper bound (if both exist), and the two relevant bounds
are used analogously as the two tightest bounds in the binary search.
When they are less than goal width apart, the relevant bounds are used in output.</t>

<t>One consequence is that every trial result can have an impact on the search result.
That means if your SUT (or your traffic generator) needs a warmup,
be sure to warm it up before starting the search.</t>

</section>
<section anchor="exceed-ratio"><name>Exceed Ratio</name>

<t>The idea of performing multiple trials at the same load comes from
a model where some trial results (those with high loss) are affected
by infrequent effects, causing poor repeatability of <xref target="RFC2544"></xref> throughput results.
See the discussion about noiseful and noiseless ends of SUT performance spectrum.
Stable results are closer to the noiseless end of SUT preformance spectrum,
so MLRsearch may need to allow some frequency of high-loss trials
to ignore the reare but big effects near the noisefull end.</t>

<t>MLRsearch is able to do such trial result filtering, but it needs
a configuration option to tell it how much frequent can the infrequent big loss be.
This option is called exceed ratio. It tells MLRsearch what ratio of trials
(more exactly what ratio of trial seconds) can have trial loss ratio
larger than goal loss ratio and still be classified as a lower bound.
Zero exceed ratio means all trials have to have trial loss ratio
equal to or smaller than the goal loss ratio.</t>

<t>For explainability reasons, the RECOMMENDED value for exceed ratio is 0.5,
as it simplifies some later concepts by relating them to the concept of median.</t>

</section>
<section anchor="duration-sum"><name>Duration Sum</name>

<t>When more than one trial is needed to classify a load,
MLRsearch also needs something that controlls the number of trials needed.
Therefore, each goal also has an attribute called duration sum.</t>

<t>The meaning of a goal duration sum is that when a load has trials
(at full trial duration, details later)
whose trial durations when summed up give a value at least this,
the load is guaranteed to be classified as an upper bound or a lower bound
for the goal.</t>

<t>As the duration sum has a big impact on the overall search duration,
and <xref target="RFC2544"></xref> prescibes wait intervals around trial traffic,
the MLRsearch algorithm may sum durations that are different
from the actual trial traffic durations.</t>

</section>
<section anchor="short-trials"><name>Short Trials</name>

<t>Section 24 of <xref target="RFC2544"></xref> already anticipates possible time savings
when short trials (shorter than full length trials) are used.</t>

<t>MLRsearch requires each goal to specify its final trial duration.
Full-length trial is the short name for a trial whose intended trial duration
is equal to the goal final trial duration.</t>

<t>Any MLRsearch implementation may include its own configuration options
which control when and how MLRsearch chooses to use shorter trial durations.</t>

<t>For explainability reasons, when exceed ratio of 0.5 is used,
it is recommended for the goal duration sum to be an odd multiple
of the full trial durations, so conditional throughput becomes identical to
a median of a particular set of forwarding rates.</t>

<t>Presence of shorter trial results complicates the load classification logic.
Full details are given later. In short, results from short trials
may cause a load to be classified as an upper bound.
This may cause loss inversion, and thus lower the relevant lower bound
(below what would classification say when considering full-length trials only).</t>

<t>For explainability reasons, it is RECOMMENDED users use such configurations
that guarantee all trials have the same length.
Alas, such configurations are usually not compliant with <xref target="RFC2544"></xref> requirements,
or not time-saving enough.</t>

</section>
<section anchor="conditional-throughput-1"><name>Conditional Throughput</name>

<t>As testing equipment takes intended load as input parameter
for a trial measurement, any load search algorithm needs to deal
with intended load values internally.</t>

<t>But in presence of goals with non-zero loss ratio, the intended load
usually does not match the user intuition of what a throughput is.
The forwarding rate (as defined in <xref target="RFC2285"></xref> section 3.6.1) is better,
but it is not obvious how to generalize it
for loads with multiple trial results,
especially with non-zero goal exceed ratio.</t>

<t>MLRsearch defines one such generalization, called the conditional throughput.
It is the forwarding rate from one of the trials performed at the load
in question. Specification of which trial exactly is quite technical.
More detailed explanations are given in the next chapter.</t>

<t>Conditional throughput is partially related to load classification.
If a load is classified as a lower bound for a goal,
the conditional throughpt can be calculated,
and guaranteed to show effective loss ratio no larger than goal loss ratio.</t>

<t>While the conditional throughput gives more intuitive-looking values
than the relevant lower bound, especially for non-zero goal loss ratio values,
the actual definition is more complicated than the definition of the relevant
lower bound. In future, other intuitive values may become popular,
but they are unlikely to supersede the definition of the relevant lower bound
as the most fitting value for comparability purposes,
therefore the relevant lower bound remains a required attribute
of the goal result structure.</t>

<t>Note that comparing best and worst case, the same relevant lower bound value
may result in the conditional throughput differing up to the goal loss ratio.
Therefore it is rarely needed to set the goal width (if expressed
as relative difference of loads) below the goal loss ratio.
In other words, setting the goal width below the goal loss ratio
may cause the conditional throughput for a larger loss ratio to became smaller
than a conditional throughput for a goal with a smaller goal loss ratio,
which is counter-intuitive, considering they come from the same search.
Therefore it is RECOMMENDED to set the goal width to a value no smaller
than the goal loss ratio.</t>

</section>
<section anchor="search-time"><name>Search Time</name>

<t>The main motivation for MLRsearch was to have an algorithm that spends less time
finding a throughput, either the <xref target="RFC2544"></xref> compliant one,
or some generalization thereof. The art of achieving short search times
is mainly in smart selection of intended loads (and intended durations)
for the next trial to perform.</t>

<t>While there is an indirect impact of the load selection on the reported values,
in practice such impact tends to be small,
even for SUTs with quite broad performance spectrum.</t>

<t>A typical example of two approaches to load selection leading to different
relevant lower bounds is when the interval is split in a very uneven way.
An implementation chosing loads very close to the current relevant lower bound
are quite likely to eventually stumble upon a trial result
with poor performance (due to SUT noise).
For an implementation chosing load very close to the current relevant upper bound
this is unlikely, as it examines more loads that can see a performance
close to the noiseless end of the SUT performance spectrum.
The reason why it is unlikely to have two MLRsearch implementation showing
this kind of preference in load selection is precisely
in the desire to have short searches.
Even splits are the best way to achive the desired precision,
so the more optimized a search algorithm is for the overall search duration,
the better the repeatability and comparability
of its results will be, assuming the user configuration remains the same.</t>

<t>Therefore, this document remains quite vague on load selection
and other optimisation details, and configuration attributes related to them.
Assuming users prefer libreries that achieve short overall search time,
the definition of the relevant lower bound
should be strict enough to ensure result repeatability
and comparability between different implementations,
while not restricting future implementations much.</t>

<t>Sadly, different implementations may exhibit their sweet spot of
best repeatability at given search duration at different goals attribute values,
especially with respect to optional goal attributes
such as initial trial duration.
Thus, this document does not comment much on which configurations
are good for comparability between different implementations.
For comparability between different SUTs using the same implementation,
refer to configurations recommended by that particular implementation.</t>

</section>
<section anchor="rfc2544-compliance"><name><xref target="RFC2544"></xref> compliance</name>

<t>The following search goal ensures unconditional compliance with
<xref target="RFC2544"></xref> throughput search procedure:</t>

<t><list style="symbols">
  <t>Goal loss ratio: zero.</t>
  <t>Goal final trial duration: 60 seconds.</t>
  <t>Goal duration sum: 60 seconds.</t>
  <t>Goal exceed ratio: zero.</t>
</list></t>

<t>Presence of other search goals does not affect compliance of this goal result.
The relevant lower bound and the conditional throughput are in this case
equal to each other, and the value is the <xref target="RFC2544"></xref> throughput.</t>

<t>If the 60 second quantity is replaced by a smaller quantity in both attributes,
the conditional throughput is still conditionally compliant with
<xref target="RFC2544"></xref> throughput.</t>

</section>
</section>
<section anchor="selected-functional-details"><name>Selected Functional Details</name>

<t>This chapter continues with explanations,
but this time more precise definitions are needed
for readers to follow the explanations.
The definitions here are wordy, implementers can look into the next chapter
for more concise definitions.</t>

<t>The two areas of focus in this chapter are the load classification
and the conditional throughput, starting with the latter.</t>

<section anchor="performance-spectrum"><name>Performance Spectrum</name>

<t>There are several equivalent ways to define the conditional throughput computation.
One of the ways relies on an object called the performance spectrum.
First, two heavy definitions are needed.</t>

<t>Take an intended load value, and a finite set of trial results, all trials
measured at that load value. The performance spectrum is the function that maps
any non-negative real number into a sum of trial durations among all trials
in the set that have that number as their forwarding rate,
e.g. map to zero if no trial has that particular forwarding rate.</t>

<t>A related function, defined if there is at least one trial in the set,
is the performance spectrum divided by sum of durations of all trials in the set.
That function is called the performance probability function, as it satisfies
all the requirements for probability mass function function
of a discrete probability distribution,
the one-dimensional random variable being the trial forwarding rate.</t>

<t>These functions are related to the SUT performance spectrum,
as sampled by the trials in the set.</t>

<t>As for any other probability function, we can talk about percentiles,
of the performance probability function, and bout other quantiles
such as the median. The conditional throughput will be
one such quantile value for a specifically chosen set of trials.</t>

<t>Take a set of all full-length trials performed at the load in question.
The sum of durations of those trials may be less than goal duration sum, or not.
If it is less, add an imaginary trial result with zero forwarding rate
such that the new sum of durations is equal to the goal duration sum.
This is the set of trials to use. The q-value for the quantile
is the goal exceed ratio. If the quantile touches two trials,
the larger forwarding rate is used.</t>

<t>First example. For zero exceed ratio when goal duration sum
has been reached. The conditional throughput is the smallest forwarding
rate among the trials.</t>

<t>Second example. For zero exceed ratio when goal duration sum
has not been reached yet. Due to the missing duration sum,
the worst case may still happen, so the conditional througput
is zero. This is not reported to the user, as this load
cannot become the relevant lower bound yet.</t>

<t>Third example. Exceed ratio 50%, goal duration sum two seconds,
one trial present with duration one second and zero loss.
An imaginary trial is added with duration one second and zero forwarding rate.
Median would touch both trials, so the conditional throughput
is the forwarding rate of the one non-imaginary trial.
As that had zero loss, the value is equal to the offered load.</t>

<t>The classification does not need the whole performance spectrum,
only few duration sums.</t>

<t>A trial is called bad (according to a goal) if its trial loss ratio
is larger than the goal loss ratio. Trial that is not bad is called good.</t>

</section>
<section anchor="single-trial-duration"><name>Single Trial Duration</name>

<t>When goal attributes are chosen in such a way that every trial has the same
intended duration, the load classification is sipler.</t>

<t>The following description looks technical, but it follows the motivation
of goal loss ratio, goal exceed ratio and goal duration sum.
If sum of durations of all trials (at given load) is less than the goal
duration sum, imagine best case scenario (all subsequent trials having zero loss)
and worst case scenario (all subsequent trials having 100% loss).
Here we assume there is as many subsequent trials as needed
to make the sum of all trials to become equal to the goal duration sum.
As the exceed ratio is defined just using sums of durations
(number of trials does not matter), it does not matter whether
the &quot;subsequent trials&quot; can consist of integer number of full-length trials.</t>

<t>If even in the best case scenario the load exceed ratio would be larger
than the goal exceed ratio, the load is an upper bound.
If even in the worst case scenario the load exceed ratio would not be larger
than the goal exceed ratio, the load is a lower bound.</t>

<t>Even more specifically.
Take all trials measured at a given load.
Sum of durations of all bad full-length trials is called the bad sum.
Sum of durations of all good full-length trials is called the good sum.
The result of adding bad sum plus the good sum is called the measured sum.
The larger of the measured sum and the goal duration sum is called the whole sum.
The whole sum minus the measured sum is called the missing sum.
Optimistic exceed ratio is the bad sum divided by the whole sum.
Pessimistic exceed ratio is the bad sum plus the missing sum, that divided by
the whole sum.
If optimistic exceed ratio is larger than the goal exceed ratio,
the load is classified as an upper bound.
If pessimistic exceed ratio is not larger than the goal exceed ratio,
the load is classified as a lower bound.
Else, the load is classified as undecided.</t>

<t>The definition of pessimistic exceed ratio matches the logic in
the conditional throughput computation, so a load is a lower bound
if and only if the conditional throughput effective loss ratio
is not larger than the goal loss ratio.
If it is larger, the load is either an upper bound or undecided.</t>

</section>
<section anchor="short-trial-scenarios"><name>Short Trial Scenarios</name>

<t>Trials with intended duration smaller than the goal final trial duration
are called short trials.
The motivation for load classification logic in presence of short trials
is based around a counter-factual case: What would the trial result be
if a short trial has been measured as a full-length trial instead?</t>

<t>There are three main scenarios where human intuition guides
the intended behavior of load classification.</t>

<t>Scenario one. The user had their reason for not configuring shorter goal
final trial duration. Perhaps SUT has buffers that may get full at longer
trial durations. Perhaps SUT shows periodic decreases of performance
the user does not want to treat as noise. In any case, many good short trials
may became bad full-length trial in the counter-factual case.
In extreme case, there are no bad short trials.
In this scenario, we want the load classification NOT to classify the load
as a lower bound, despite the abundance of good short trials.
Effectively, we want the good short trials to be ignored, so they
do not contribute to comparisons with the goal duration sum.</t>

<t>Scenario two. When there is a frame loss in a short trial,
the counter-factual full-length trial is expected to lose at least as many
frames. And in practice, bad short trials are rarely turning into
good full-length trials. In extreme case, there are no good short trials.
In this scenario, we want the load classification
to classify the load as an upper bound just based on abundance
of short bad trials. Effectively we want the bad short trials
to contribute to comparisons with the goal duration sum,
so the load can be classified sooner.</t>

<t>Scenario three. Some SUTs are quite indifferent to trial duration.
Performance probability function constructed from short trial results
is likely to be similar to performance probability function constructed
from full-length trial results (perhaps with smaller dispersion,
but overall without big impact on the median quantiles).
For moderate goal exceed ratio values, this may mean there are both
good short trials and bad short trials.
This scenario is there just to invalidate a simple heuristic
of always ignoring good short trials and never ignoring bad short trials.
That simple heuristic would be too biased. Yes, the short bad trials
are likely to turn into full-length bad trials in the counter-factual case,
but there is no information on what would the good short trials turn into.
The only way to decide is to do more trials at full length,
the same as in scenario one.</t>

</section>
<section anchor="short-trial-logic"><name>Short Trial Logic</name>

<t>MLRsearch picks a particular logic for load classification
in presence of short trials, but it is still RECOMMENDED to use configurations
that imply no short trials, so the possible inefficiencies in that logic
do not affect the result, and the result has better explainability.</t>

<t>With thas said, the logic differs from the single trial duration case
only in different definition of bad sum.
Good sum is still the sum across all good full-length trials.</t>

<t>Few more notions are needed for definig the new bad sum.
Sum of durations of all bad full-length trials is called the bad long sum.
Sum of durations of all bad short trials is called the bad short sum.
Sum of durations of all good short trials is called the good short sum.
One minus the goal exceed ratio is called the inceed ratio.
The goal exceed ratio divided by the inceed ratio is called the exceed coefficient.
The good short sum multiplied by the exceed coefficient is called the balancing sum.
The bad short sum minus the balancing sum is called the excess sum.
If the excess sum is negative, the bad sum is equal to the bad long sum.
Else, the bad sum is equal to the bad long sum plus the excess sum.</t>

<t>Here is how the new definition of the bad sum fares in the three scenarios,
where the load is close to what would relevant bounds be
if only full-length trials were used for the search.</t>

<t>Scenario one. If duration is too short, we expect to see higher frequency
of good short trials. This could lead to negative excess sum,
which has no impact, hence the load classification is given just by
full-length trials.
Thus, MLRsearch using too short trials has no detrimental effect
on result comparability in this scenario.
But also using short trials does not help with overall search duration,
proably making it worse.</t>

<t>Scenario two. Settings with small exceed ratio have small exceed coefficient,
so the impact of good short sum is small and the bad short sum
is almost wholly converted into excess sum, thus bad short trials
have almost as big impact as full-length bad trials.
The same conclusion applies for moderate exceed ratio values
when the good short sum is small.
Thus, short trials can cause a load to get classified as an upper bound earlier
bringing time savings (while not affecting comparability).</t>

<t>Scenario three. Here excess sum is small in absolute value, as balancing sum
is expected to be be similar to the bad short sum.
Once again, full-length trials are needed for final load classification,
but usage of short trials probably means MLRsearch needed shorter search time
before selecting this load for measurement, bringing time savings
(while not affecting comparability).</t>

</section>
<section anchor="longer-trial-durations"><name>Longer Trial Durations</name>

<t>If there are trial results with intended duration larger
than the goal trial duration, the classification logic is intentionally undefined.</t>

<t>The implementations MAY treat such longer trials as if they were full-length.
In any case, presence of such longer trials in either the relevant lower bound
or the relevant upper bound SHOULD be mentioned, as for sume SUTs
it is likely to affect comparability.</t>

<t>TODO: Here will be a chapter summarizing how MLRsearch library
adresses the problems from the Identified Problems chapter.</t>


</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<t>No requests of IANA.</t>

</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<t>Benchmarking activities as described in this memo are limited to
technology characterization of a DUT/SUT using controlled stimuli in a
laboratory environment, with dedicated address space and the constraints
specified in the sections above.</t>

<t>The benchmarking network topology will be an independent test setup and
MUST NOT be connected to devices that may forward the test traffic into
a production network or misroute traffic to the test management network.</t>

<t>Further, benchmarking is performed on a &quot;black-box&quot; basis, relying
solely on measurements observable external to the DUT/SUT.</t>

<t>Special capabilities SHOULD NOT exist in the DUT/SUT specifically for
benchmarking purposes. Any implications for network security arising
from the DUT/SUT SHOULD be identical in the lab and in production
networks.</t>

</section>
<section anchor="acknowledgements"><name>Acknowledgements</name>

<t>Many thanks to Alec Hothan of OPNFV NFVbench project for thorough
review and numerous useful comments and suggestions.</t>

<t>Special wholehearted gratitude and thanks to late Al Morton for his
thorough reviews filled with very specific feedback and constructive
guidelines. Thank you Al for the close collaboration over the years,
for your continuous unwavering encouragements full of empathy and
positive attitude.
Al, you are dearly missed.</t>

</section>
<section anchor="appendix-a"><name>Appendix A</name>

<t>This is a specification of load classification.</t>

<t>The block at the end of this appendix holds pseudocode
which computes two values, stored in variables named optimistic and pessimistic.
The pseudocode happens to be a valid Python code.</t>

<t>If both values are computed to be true, the load in question
is classified as a lower bound according to the goal in question.
If both values are false, the load is classified as an upper bound.
Otherwise, the load is classifies as undecided.</t>

<t>The pseudocole expects the following variables hold values as follows:</t>

<t><list style="symbols">
  <t>goal_duration_sum: The goal duration sum value.</t>
  <t>goal_exceed_ratio: The goal exceed ratio value.</t>
  <t>good_long_sum: Sum of durations across trials with trial duration
at least equal to the goal final trial duration and with trial loss ratio
not higher than the goal loss ratio.</t>
  <t>bad_long_sum: Sum of durations across trials with trial duration
at least equal to the goal final trial duration and with trial loss ratio
higher than the goal loss ratio.</t>
  <t>good_short_sum: Sum of durations across trials with trial duration
shorter than the goal final trial duration and with trial loss ratio
not higher than the goal loss ratio.</t>
  <t>bad_short_sum: Sum of durations across trials with trial duration
shorter than the goal final trial duration and with trial loss ratio
higher than the goal loss ratio.</t>
</list></t>

<t>Here the implicit set of available trial results consists of all trials
measured at given intended load at the end of search.</t>

<t>The code works correctly also when there are no trial results at given load.</t>

<t><spanx style="verb">
balancing_sum = good_short_sum * goal_exceed_ratio / (1.0 - goal_exceed_ratio)
effective_bad_sum = bad_long_sum + max(0.0, bad_short_sum - balancing_sum)
effective_whole_sum = max(good_long_sum + effective_bad_sum, goal_duration_sum)
quantile_duration_sum = effective_whole_sum * goal_exceed_ratio
optimistic = effective_bad_sum &lt;= quantile_duration_sum
pessimistic = (effective_whole_sum - good_long_sum) &lt;= quantile_duration_sum
</spanx></t>

</section>
<section anchor="appendix-b"><name>Appendix B</name>

<t>This is a specification of conditional throughput.</t>

<t>The block at the end of this appendix holds pseudocode
which computes a value stored as variable conditional_throughput.
The pseudocode happens to be a valid Python code.</t>

<t>The pseudocole expects the following variables hold values as follows:</t>

<t><list style="symbols">
  <t>goal_duration_sum: The goal duration sum value.</t>
  <t>goal_exceed_ratio: The goal exceed ratio value.</t>
  <t>good_long_sum: Sum of durations across trials with trial duration
at least equal to the goal final trial duration and with trial loss ratio
not higher than the goal loss ratio.</t>
  <t>bad_long_sum: Sum of durations across trials with trial duration
at least equal to the goal final trial duration and with trial loss ratio
higher than the goal loss ratio.</t>
  <t>long_trials: An iterable of all trial results from trials with trial duration
at least equal to the goal final trial duration,
sorted by increasing trial loss ratio.
A trial result is a composite with the following two attributes available:  <list style="symbols">
      <t>trial.loss_ratio: The trial loss ratio as measured for this trial.</t>
      <t>trial.duration: The trial duration of this trial.</t>
    </list></t>
</list></t>

<t>Here the implicit set of available trial results consists of all trials
measured at given intended load at the end of search.</t>

<t>The code works correctly only when there if there is at leas one
trial result measured at given load.</t>

<t>```
all_long_sum = max(goal_duration_sum, good_long_sum + bad_long_sum)
remaining = all_long_sum * (1.0 - goal_exceed_ratio)
quantile_loss_ratio = None
for trial in long_trials:
    if quantile_loss_ratio is None or remaining &gt; 0.0:
        quantile_loss_ratio = trial.loss_ratio
        remaining -= trial.duration
    else:
        break
else:
    if remaining &gt; 0.0:
        quantile_loss_ratio = 1.0</t>

<t>conditional_throughput = intended_load * (1.0 - quantile_loss_ratio)
```</t>

</section>


  </middle>

  <back>


    <references title='Normative References' anchor="sec-normative-references">

&RFC1242;
&RFC2285;
&RFC2544;
&RFC9004;


    </references>

    <references title='Informative References' anchor="sec-informative-references">

<reference anchor="TST009" target="https://www.etsi.org/deliver/etsi_gs/NFV-TST/001_099/009/03.04.01_60/gs_NFV-TST009v030401p.pdf">
  <front>
    <title>TST 009</title>
    <author >
      <organization></organization>
    </author>
    <date year="n.d."/>
  </front>
</reference>
<reference anchor="FDio-CSIT-MLRsearch" target="https://csit.fd.io/cdocs/methodology/measurements/data_plane_throughput/mlr_search/">
  <front>
    <title>FD.io CSIT Test Methodology - MLRsearch</title>
    <author >
      <organization></organization>
    </author>
    <date year="2023" month="October"/>
  </front>
</reference>
<reference anchor="PyPI-MLRsearch" target="https://pypi.org/project/MLRsearch/0.4.1/">
  <front>
    <title>MLRsearch 0.4.1, Python Package Index</title>
    <author >
      <organization></organization>
    </author>
    <date year="2021" month="July"/>
  </front>
</reference>


    </references>



  </back>

<!-- ##markdown-source:
H4sIAAAAAAAAA+19a48cV3Ll9/srEhoY7vZWF1uUZjxD7KyXEqkZYkVJZjdn
4DUMOasqqyuHWZnlfHSzx/B/34gTEfeVWU3JY+x6AQ9gmOrKvHkfceN5IuLq
6sqN9dhUL4q3UzPWp6Yqvu2GoXhXjnVX3FRlvz24crPpq3t65Nt3g/xl123b
8khv7fpyP17V1bi/2hwf7q6OTS+PXF3/0u3KkR55fv38i6vPr6+ef+Fcfepf
FGM/DePz6+vfXD93ZV+VL4ruNLiHuxfFV1W7PRzL/kPd3hV/7OT//67vppP7
8PCieNOOVd9W49Ur/qrbluOLom73nXPbbkePviim4aoctnXtTvWLgv73i2Jb
tvTXqij7vnwsLup9UTZN8VgNl0XXF4dyOBSHqq9cUYzd9gX/QP8cun7sq/3w
AkPsqn1JmzPQE/b741F+5v905TQeuv6FK/C/K/3/BU2Nnni7Lv5X1w5j2Y6P
bfdQb//sf5cdfFtu6+rD2Ye6npb1dT1s6TQeh7E6Dv6n6ljWzYvi+EFe/Z9b
fmq97Y7LM/nDuviha8oP2ff/0Jfjhy776dNfve9P/Eb0Udd2/ZHI5r7irXj3
zdefP//yuf7z+fNf/9L++csvv9R//ub6mv7p+AijN29vbok2ZDvHsr+r6JQP
43gaXjx79vDwsK7GoV7TBJ/tqoZe6Z/xH368G559980frujlZ9fXn/94/Zvf
0P+n//tiff3lmv7wq+tnd8OP+gj9cn/9xfWX15+f1qfdXj4l1+Az+rmg3z+j
P37zqu6uvr55c3vlKX95WtuhHtf73brunm3pagzPjhWRxK5rurtH+nc5TH11
rNpxeEZXovzx1JRt9eN4IMK+O5ym8Rndmh9l/GfJXL55RUMWPIPithrG4m0Y
trgK1/EzvJTcNvrLD48/vPnUxE+PJ9nLU9/9qdqOz/zzz67XX64/T6fjfyzw
44o+QfNpix/K7YfyrqL7uas+ZpP5/Or6b527uroqys0w9uV2dO72UA8F7dPE
e1LQp0/dUA1F9XGs2qEmauab9o9KK/9UhI0q9PObR0eXsm6ZPZRFWz0U0YbT
lW+aarfI0JR9XfiVXK6L20NVEE23RbfhLSCSGopuH3aXWEfFEzrS9471n+nf
h8qN3Vg2Np3d1PPo7YofG6bTidiH/sYzJOoujjaZhieDxwdXtjt+oz7SFtxX
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
QIa6Dx7j+IazCf+aSQcUJVoo4mQsXrVQAPOG+yoaaRfjYq0aL28nO1iOCEuX
c8tK4tZPu/Tk09oXK+/bOYOoOW1ka94ABUIl/cvVeEodQaaMmLzIoT5xHog9
K3dA0jC6fNtdaIQhezAYOgiujJXOPZ5DlMOd5rMf13kjNTlwINK5P7y5JMGy
7TizLQWA1/0MxS8kbEjmStRipWqH0MArPRM3hw0aIDYAwzIgoGW5CHpEviZ+
EMv0SYtYTAhG3pQ7vsRnR4VuXH081JvaWgQMNA+Wp2zD7t1G69bFBDWqxZW3
KU36dFvvL3Prm3TJbdoefwBYxWC5WUrt4KzTvFaKn3k4bw/TkBOg9wdoixUJ
k4Gp1HM3D8xIrss419c/eTLChz/1EiTk5BtXCvA2GWjlhGClEkrsOor9nBvN
lYq8jOkwolzNtZutalmhAXZc50GolRltrIaGd6V7xRO9fQMKDz2ufpdqfC+A
lFr7X5Y81S+K0Po7PBm7cpefiP0g/jvzvjVJdRBPHYrhixZqsN9ZHb8ns9DP
wcf7yjd8ZGMrhBkRPcDMAmLDl+BP9dPYL2OFjPxGRPXGUbad26RJ3X5vJ4Qn
WkGKxKUbn5i8hzFFvzePmeNykSaQZHwDNk+T+YaISkd/JZw9yzS2LmCqQibN
ktRS95XmpPtxDvBVkBzsRyfFPUqutSq9rhoz5NJiibeHdAho0DwO24VcKy7u
+MKKDvtIrNZJ6mlyvjAjB2SzuWn4EhouazYSEthOQyAN3QjTIxbcUO5pSlsF
NIrPribxOFrTiB8iXevGutaL+MZXrYZMiiQf0rIn5wglqou5BpKns8Yuj4Ph
7DsA1a1+TXBALiuB33AG8gpbxgD9xzNHzTvLrSJmqSjaykhQbZqdcx5zb0EQ
a2pUameSqIYhrL7Ftu3mJlUiL7Sew4lT4x/TmnuMgrQYOcioPFOMUgFp0dzq
AB/EBzT6UPqa4OKCqvvcX0sSlwvdaikiOOnqPRvpAeeby5NsBFhspmzZMkMW
jNTJUNvTIuERxMBPfGUF3Ba3MdRxtz0Ju8GWdgi8hBEV4uW3PuBZ8s8IIFhk
c1iCIi9K7YC6XHMDhRej14+cke0/af9wCP0xDqqvxvR7nMwIdut1ddqdK19H
n4mR6LQ7EqXRAje+a593ri8cyC0AhfbxxfpO5ywsAE4G2N2+juPCznIESSDY
Vht7eQ8fpDNmVBWBPrqtUH6Rw1f7n3oWLXJgDehqFRyD8gdzSSAuuIxneJFa
M84HP3wtyLhApM/7g0DjSHub8IfBcxb7M9PGQsxxMexRxGEPrUY1J+kxAE18
CesMSxkrP2gURioL4hFiFfPTK1S/ghegvBOYZoItgzSQDmIpFcnG+gr+jIWe
zXIRZZAic27jCjfxDioEQA4rLs/JT9qhGEuYB7QKVXT88Y3dJJ4hK11oUBvx
sC7UyFfoBmSJuZqkxc6fZ2gx+IvmVSt9CQ0ttvck6eXQ5jAlhykJUw/3bQ1c
C+tw//7JScGeMMHikS5v8Wry3hcyqmF0JKSEjQshgCKkYUh+g+8WNF8pR5dp
oVCzCzt8MUrVj6gfZiN8ZQWbJRqohWo0FnM26PFYKWq/j3bmdbwhv7z+q9US
0oPbAIt5sHJRQU4tBYirEFrXtL63MPMeH2pWV2B6mVi27Vg8fXqMGbN+K9gQ
gTaAikULt4T9JxNQ7YIsVK1VSQIVI5vvWqBi0BN2cb23xMpIrnacrWslU7Kc
rTRJ92D1apeFjFT1JqaSFSiOWzZZXz3kDse173yygHiqZmDNOi/KPA8xaOlz
S0kC3WkE17L9O+0ldSOpX3mt9D/6W5eVKlR5IX38DnEBkxitfiiDp8zN/Prn
U+PY6mIwgDX5C/Z6VNUGpsgQYuQeOCxPWzjSQilunv+4Wqg7izD0nMW/2X9K
JbvwPiEke5tsSk/HpdJMSFZ9puBCA6kNpAJ1NBwysNKUNCBueBs8OUsJ3YiN
/cQBPr++/isZYO1QEeXBumlEmuwgVcHng5SGamV0OBrVjUHAR3sicT5mdJ8S
oQrrzMHBpmAjfUg8R3yFknNwFzPIbQyEYUArME/ZHwvtdAw58NlsjZ9BpdMi
oxaq4tsW9R+aqULim6giKMbCyXqiT+VbWvUmixumdeqCjjUHpGXfX6KMpyYg
sulnTyLLm0NcIGlVInAnUScDfcTWZhndnrW7OXPZmH8tqKCp1cMPgarOjSJu
zk8Ng6eGEI+xlqTcD4VxBPKV4tRMQ/J8NoxfpB/KChvtZ797N9gitDsaVMSO
H9H/Z9RvKRk3m5IqRHj/ewk7jNwLPrt+0WbGxmk2gR+4jetPGMFvVPT5lQiN
rINZNDjRc3d+gosSMKHTBIr+NJbzDecmnV8KX42/7HvpLXndDFV6jc6Uh7Cy
oEk45uxMgf3zeFlUgmif8nBGjivoYeXyreZaoNJnhoP5vsn40ohLkC331AZm
RerVsMOT6QZZlYxZykC8VylwvrhRtjdoszJ1sM77OC5nvCx56SU5V65TDCHW
At0peuMsZjnHfSZg5NoafGkOQunxLHvFkDFPf1H8MSCGg6/E92/AocUDh3qI
gfXyQc94IYpYV+Xu72IHqfTaBETFhMmg+XiH6VhGNTKLu4kbh/mCNxK2iXrU
L4IMnZ0VGnHAzEQI9lBabWsNiu8VEWwxIo8+sVz4xSwAdgCj4A+7hbARk1Sy
VXflI8qHAg0Px2cLEZih9pNBOMgO/0fd7Th9o+Iqk4P0QYqxAGYLBh3EktNH
LkspNbBrdhS8aeFtElAatC+RKjlQXeFTi+IwoNPmFAPkV/VxZM9egL7p+bad
8OqEpN+of95OHO4umf4Z7Z1rDse5VPacy3kgO1CHUy21YotyQ38qPQi6yyfy
2tgKR3PjOcyetdZkkh5u1uWj08IASN+QiKyvo1gP1rjhnIYaiJNM7HVh+b+q
KkcFCYuosRXmYwGm9DQWjm1ICvICP+K9yaqMO2l6uS5etlo81LqT5Ccn/lAB
FXI/A6tR784oP6C9Jyhj4UR+Nmm4JbJYSAKDuu/r7HjCcJ5Lbnw1inUR0UXy
/XxDnLXX+JlH74Eq2jKpzbJCuDoxLNVAIMwn1wUq/SPmHZBQDEuzcPjY5RzK
/fAJH7H0OGR8a7WbpbD4WgosPT1UiHEZ0tcygsz9pA9IstqcTn3CdVJAzcTn
rh5Omv6CuKXBS6wpyjxNTxOHvLtbUV2c7g0/z9xIVyCFUB+6TGj1ECVX9i25
OVuAf33G4G5jEladlcaQ1sQdZ/NwcUo4LyVDlaRdRTKHVS+EPKRSAbgNX7Ll
7zLMrg8PLU2jHGfjB7OQe3Rtar4S6+IfKnVj5ZfBhdbooC7uGIsgW3yI4fGn
BIWHhwuDa7uk3CEwJInmscCE7euiFkFxVFyYKGvYa6SDS16urwEQ5SGuQjc1
gF/CQUmvrkzZ+5YVqzgP5FRz4dIkIU2UrzOqmXtCKfMOJg8KyEDBjIZeyp2S
alltl42mbMXnatZtxVmgNX27jlpVY75uXm9JKy1FTQCg9YmGBw9HmgAWCnEg
+FXvTLfm7bB+xQEMLQ7BlEEJfqNTPG/gZKlp4s3v30UGsWyYuYnKbc+S8glb
nIMW1YNQhtaniYLeWkSav3rnQzefNPt/svMAfRY/OVRC7QseCAFLftIP8cQw
0e9iqicNlRe7rEVv122cHHW7+EZm1cevZKPpa9vOiHS0MeM5pl2Yz7w426yG
5JH3R9zm+xctOXl0YYJEU+Y1SP8kaf6CQVglXok8CJCefzDSf8rzwcURT0Yc
rLXmwSmxzsGV9oF92VeeNYvJ5a0tRkBWMUAGXgMFGkccOa83I6agxCPmFyCU
o/c1jaySS2qRvYl6LdbSN1LTah+smYQkR1RWRsnXFnGLSr1Ez7aYM4Pb+W0P
FQl7aGkd2hRO1IcViUnm0k8EEcSjKNokqc4LTEZgk0FeKDqxS3m1fXhX0X8D
ZdhEbXGtJk+Cfqwz3XiNVE+Ue1A/djy+twsPVXMSfeos0pnzA7iuW6h5hY4X
MwvlRlJ6YvUsb7F3X6V/j+6o13pD/kR202utzuQFUHJpHWo4IRuMvXnAzHFe
9Ihk0rGLT7dAivRMX5c0FxmDhVpQHMvhjEajSANpiM4Z/VKP53QC/mofa5UL
CqWLGlguLtXoJTk7xAmyvHF2JDxZ5kIL47kNa4NStzgUaiguAs5ZBL500Ivo
63LB3gCbSVmeHBAbpNYz0FBhQ8pLXWZ8bqrMcFiQat+jreAdaRirxfqnqbQW
l8zCRRVNcxrKu5nGFYoYSiWbcE91YHP6RNh1a+DhO54WPvguBBBncy9uv/tp
24+qlewjyqKmgwFUzWuWGE1nnI+LAZe8Sss4D0j7Wr8Y0uNT2R+KyJn6jnPI
+9uX/6CuJ4RvxdcVRffEwauNSqKzhc0fHFSJpjwfiEulh2SzxeSBLvstviM3
v//+/bevmA6PsjT0TZVrjEgl29ZaBiMYPRGa2R8X7YK7/f7V9y/kjjz4Ypu+
Ic50PNJV+jMfdFrMQ4v5u3KHrEsrQd+Rwn6M1OU3qIWBy/6D/RgysP/1xQuF
4P+bcwX97xfhKencEOob4/fvUAyiigqMiqSXlnlW0lsQF6rlcw41vyr7EZdB
tMVVWBpEzbnq70H82BLXMiHet1XxWVaw7TNtpMm38FBq9rdGmJ/2oPOYA1nD
+DR6SS2731MfHL8FjcFuU1yC9ecUlpOtEqUCVdEk7IkLVloROe07nxh0uh16
94tbDu8GuAT/9HJQrtTaLpyR5L4LcZryiUHiite+n4Q2QBLOBa3HGk3Y7R7w
sl983PpGnC01SBacD8XgSaT6JtiyvW+14m+WThZXVuHNirtTnyEm2eNBC9We
y9Ghzeca//me5XtVWURZD0Bus8ZlpUUokJNx/088+I3dUJ88nsFZVsvEhpfj
bK84r43FO2aUyh//0fcmzHI6RLsu1gEHYJeRasUvJOXrUYUK+bOLFahsBxgX
Q6dg7HXRGgR/4qpBY8fQKR9B4zRo+TLoiDUG4uW7eiulBwPVzg7CF/8Jvmed
EHowhxIqUfYR3ei7+ZEiGSkaBoMkRao1NUQziM+lRl2GO/nq/S2PSHJB/vSD
z+FFoEY1yHAnwGKzM8KL0uFtQVMMpTvXxVuZFwZB742jJO1qDqsQUJQ1BuGF
2nE421AnhTQScYtJP9upHg542+e5yjnK6oYxCDV+6Ex1jwPcZVYFwsrGaRd1
6d60w/shH2sRxFZYxzlNqw7bJ/QT57JZFWI7vzwralCOy7qylcvAIHnJjM1k
XZhDz6GsZM84A52Aey3cN3/V5OZ5HZ939lHzcf1VWKqiGSr7bCrLAub6H5xT
wAKPs39+c3395T/Z7W+50QXy57d1v52O2g955csReVnER8q0hmAiLViFb0ju
5vH4oSwbjteF+nv4yqFWBv9gWQzMe4RypiGQkSft8Byd6qsMJL9vuHyGiTt+
5U0SZwJu8/EkUU75iDVxVD91XMtEPAp8XESgj0OtQ0aVeoxNAH0JcI1Rc9c1
IT9IWsoI0ZW2RtqDkOxqpnegPJ+RJPX78e6hOynCkrm4VoAZpMtUaA4nMWoo
swv5sYHjvJvlGX+d5BkvUqV1W8u4QyIEsspGs2P4fDivXVkKWSQLSAaIdjiI
bas5ut4ibiVQdSFO/3L0Zbqs1J8Ic9XRFiQUwAdSxTDWDTQACp2GufkDyIVo
BNw/2lIULCgHJhkenXbB+Pobzyeh/xpuL2PL6m+C9sgCD2EguMExyD4v7Lv2
QpSf9nhgcVNL2nRf+Vr7WSk14ZlWbDToIzdjD+NbfOd+0FlC7UoZIUOXGeU4
VXNffVh60OUPnkIXeb7W+rlICmUtMdjLaHvmWxNUcF9tiMeYFcQZZjWQMu0u
UrI5DqM2ONrVq2dCsyV8zpCMa6vPdEXkC+r1eFrFhh8AjIJt8GnsOGy1tWlu
RTqV912dp6DXwzAprevJp9n61i38keiXmISm11dRGQT4Z9HGU09N6OMry+CM
3FIQbdzoOCrV4YvJR4oGBvhWgFPlLtQtVh+I+jvYKt9Pog9uiZSOg7RCirkR
D2Rp2ecbimmI+1juIkZ3G6cXEXl9R+SFgsPcuUOeupk0+2Gz2Ik57k+sx8tc
cMhT64MjKnz9TatIXI4eiLvlnQa7M3FSZ40aZudhaq+oNJupRjkn9XClXvkz
aaZejPrX4EpBhn3qwEq61yxDnrxJqxPXNWb1EEMRwLEjBgw5HUxGuy/CcoG/
h7Vy4cuOXCZM+VxanEkIRTuzZQXkdKjwEEo78M2VO+yzmrwSdVYwSbDSYANQ
x7Q8lJbYMla9aNCcYQtsQoruIAa7b212ebZuhpgagDMmRoV68iPbQtbkYeyw
lGL6kpiw1pNpHiOlHsJKOWDpyxBZwNzSVxE+SMSS+9cXz4KziEj/5XcvWclH
5SpzMH7XQTBzzyg+LX5G881pKnyL8he+qtrt4Vj20vCZ4TJE2BV8fd4c8KrW
sTp20tagPtbiEHZIs+ia7o5zBUtWQ6reykIh75PUyGdMWMKirSZ2heLlZGLV
8EK7hsz0nvsMsOZ9X/ddK+4MUXvZAoXWSFqgSFJ0843SvgdSMljbdcEH5jM2
LQ90Q1zFOtLFy26J83X9B1rNSRbi/YAoFwXtC7gcvjuijXPfk7fvb26Badtg
Bq33kXMT420VwQc1QUlYAg9iGhFwV2XU6dnPhfWveiDWMgb9yZgKj0AXtLwD
tdsrHBgXNr9Kl1fHmZgoqfTZpim3H6423cfP0D5x4PK3DfcrcwOxEWk5FfnD
iZY2oGxWNqqPUqbUpqPny3EHkfkkJ05CtUxI6qzlfUITDjsWI4sk25SZRTJ3
KwjIuDbxZ/lGU8B66m4NRt6M2uJleP+rfSb4jEN14toaC22Ua8ctt3VoVNwu
Xm4/tN0DEe2dutPcWxarrA99gAH4kvSA4vedlJDfF9//8N03fyjo/7AYHhap
/cLBOggMR9Knrh4EAzQdiY9PyMrkxhB6zQUgpD3g1Mloewwk/IE4CdPcHV/n
katUy42wWXHOM02teEuCR9GxdI2dTaGQKXBRblxI3DVpeWXN1PbEZDdEK1Zt
SCBgxN8cgLwN173iYC19kfuG8MeMTUv4eUt3Xa42GMK9OqWkhTkqQ6DdiFa5
wB60D8QAeynmu6Uflc4ltMe7W3Fj8wOsKkfUIZ4M4s3YAi4zvMJcUGBdHOOc
WCAY8OLlCcbUx+JlaH5U5r1Oz+GQwTqajvcja1vLo9jIorqdhmraddxa3VcH
Z0C9ZumaojyMDEUt0OpYMtwHlDvfxdkNIhw9rl+CmWF8TUw1T0SpXZO14z0/
IflHsNDVFii1tOgU4np0tEneQcjTdk+nLBRJfqIX0Umi98Ln9+UnEh3yPIzv
zVA889KwlB1h29QYEMFyRi1zMOz7IepCjXAS0gVRsocX9KNpKz+i3I7HzSTZ
ONaiV18RNeVHrb+zDLWJX+l2P7J3Qb4wQwcpOsrQGbVHXkbhEw8M/mkl8MXt
E0aKMjMKAR5E9vOC8o55b8r/VNP+KVPGVkMj/wsmnTRJ+L+zzf9Jpvzp6f7e
4EgitOvRF4u4L+umnHV9NiMnS59NCs8stYFLGXHUO7wC5ysgxOmfPRf9tKbG
DwGkryj2dC5Jyi6N9s///M/OwyJ494vfZhRU/M38whfPiovP19fFAi+4dD4Z
6kccK4aM71Hx30jH+3hxvb5epQdfXBXJVOKhoBXoYPx2wlBoxNlHV3POdukM
cJ38mUZc+s7Csl0kuX47/2Tx339bLH7Bxalrvy0ulj6X8cjL84PxkcXi/qsn
xf25Uu//QRLf6v+qtCfh4uvZRF/+Mf7yv0PE/5e4+y9xd2bKmK7M6EXBNTxI
BoD8Ymab9kD5j5w/u8YG7wOsW6TDQV/MlsMewJfJbOTC8k1iTb8K+TiBpFE8
LipDYQLmBfuFrrTqB38jJsz8y0ikMlkjNkw9WMWQaJxQkTGMEmqe7NPX/rMK
wc7Hp0UILtQp4xiESw5iPolIOtJkg6Ax4ZMxkVWRy6P4Jl06QVXwif62SMb7
myfkqOf+4YDp9e949jhFS3yMb4D4M/fF0ru0A9+hg0dfhPn8j4LksLzG/1v+
Zk5n/vEwztVvMyqSUDnZQWHwDd2NDy78jeb5MydCe+XcslyhX41yfgTl+K1d
GOpShOjVFbO87Qf3fwAL0P3iivoAAA==

-->

</rfc>

