+| | ${pdr_sum}= | Set Variable | ${result.pdr_interval.measured_low.target_tr}
+| | ${pdr_per_stream}= | Evaluate | ${pdr_sum} / float(${traffic_directions})
+| | ${ndr_sum}= | Set Variable | ${result.ndr_interval.measured_low.target_tr}
+| | ${ndr_per_stream}= | Evaluate | ${ndr_sum} / float(${traffic_directions})
+| | ${rate}= | Evaluate | 0.9 * ${pdr_per_stream}
+| | Run Keyword If | ${latency}
+| | ... | Measure and show latency at specified rate | Latency at 90% PDR:
+| | ... | ${latency_duration} | ${rate} | ${framesize}
+| | ... | ${traffic_profile} | ${traffic_directions}
+| | ${rate}= | Evaluate | 0.5 * ${pdr_per_stream}
+| | Run Keyword If | ${latency}
+| | ... | Measure and show latency at specified rate | Latency at 50% PDR:
+| | ... | ${latency_duration} | ${rate} | ${framesize}
+| | ... | ${traffic_profile} | ${traffic_directions}
+| | ${rate}= | Evaluate | 0.1 * ${pdr_per_stream}
+| | Run Keyword If | ${latency}
+| | ... | Measure and show latency at specified rate | Latency at 10% PDR:
+| | ... | ${latency_duration} | ${rate} | ${framesize}
+| | ... | ${traffic_profile} | ${traffic_directions}
+| | Run Keyword If | ${latency}
+| | ... | Measure and show latency at specified rate | Latency at 0% PDR:
+| | ... | ${latency_duration} | ${0} | ${framesize}
+| | ... | ${traffic_profile} | ${traffic_directions}
+| | # Finally, trials with runtime and other stats.
+| | # We expect NDR and PDR to have different-looking stats.
+| | Send traffic at specified rate
+| | ... | ${1.0} | ${pdr_per_stream} | ${framesize} | ${traffic_profile}
+| | ... | traffic_directions=${traffic_directions}
+| | Send traffic at specified rate
+| | ... | ${1.0} | ${ndr_per_stream} | ${framesize} | ${traffic_profile}
+| | ... | traffic_directions=${traffic_directions}
+
+| Find Throughput Using MLRsearch
+| | [Documentation]
+| | ... | Find and return lower bound PDR (zero PLR by default)
+| | ... | aggregate throughput using MLRsearch algorithm.
+| | ... | Input rates are understood as uni-directional.
+| | ... | Currently, the min_rate value is hardcoded to match test teardowns.
+| |
+| | ... | *Test (or broader scope) variables read:*
+| | ... | - traffic_profile - Name of module defining traffc for measurements.
+| | ... | Type: string
+| | ... | - frame_size - L2 Frame Size [B] or IMIX string. Type: integer or
+| | ... | string
+| | ... | - max_rate - Calculated unidirectional maximal transmit rate [pps].
+| | ... | Type: float
+| |
+| | ... | *Arguments:*
+| | ... | - packet_loss_ratio - Accepted loss during search. Type: float
+| | ... | - final_relative_width - Maximal width multiple of upper. Type: float
+| | ... | - final_trial_duration - Duration of final trials [s]. Type: float
+| | ... | - initial_trial_duration - Duration of initial trials [s]. Type: float
+| | ... | - intermediate phases - Number of intermediate phases [1].
+| | ... | Type: integer
+| | ... | - timeout - Fail if search duration is longer [s]. Type: float
+| | ... | - doublings - How many doublings to do when expanding [1].
+| | ... | Type: integer
+| | ... | - traffic_directions - Bi- (2) or uni- (1) directional traffic.
+| | ... | Type: integer
+| | ... | - latency - True to enable latency measurement; default value: False.
+| | ... | Type: boolean
+| |
+| | ... | *Returns:*
+| | ... | - Lower bound for bi-directional throughput at given PLR. Type: float
+| |
+| | ... | *Example:*
+| |
+| | ... | \| \${throughpt}= \| Find Throughput Using MLRsearch \| \${0} \
+| | ... | \| \${0.001} \| \${10.0}\| \${1.0} \| \${1} \| \${720.0} \| \${2} \
+| | ... | \| \${2} \|
+| |
+| | [Arguments] | ${packet_loss_ratio}=${0.0}
+| | ... | ${final_relative_width}=${0.001} | ${final_trial_duration}=${10.0}
+| | ... | ${initial_trial_duration}=${1.0}
+| | ... | ${number_of_intermediate_phases}=${1} | ${timeout}=${720.0}
+| | ... | ${doublings}=${2} | ${traffic_directions}=${2} | ${latency}=${False}
+| |
+| | ${result} = | Perform optimized ndrpdr search | ${frame_size}
+| | ... | ${traffic_profile} | ${10000} | ${max_rate}
+| | ... | ${packet_loss_ratio} | ${final_relative_width}
+| | ... | ${final_trial_duration} | ${initial_trial_duration}
+| | ... | ${number_of_intermediate_phases} | timeout=${timeout}
+| | ... | doublings=${doublings} | traffic_directions=${traffic_directions}
+| | ... | latency=${latency}
+| | Check NDRPDR interval validity | ${result.pdr_interval}
+| | ... | ${packet_loss_ratio}
+| | Return From Keyword | ${result.pdr_interval.measured_low.target_tr}