[VOL-2052] Bandwidth Profile Validation
Change-Id: Icdf6ab05435d5359158dabb704e5cecb7f7d4b37
diff --git a/libraries/onos.robot b/libraries/onos.robot
index 4d10af5..69ee7e2 100644
--- a/libraries/onos.robot
+++ b/libraries/onos.robot
@@ -361,3 +361,30 @@
${targetFlows}= Calculate flows by workflow ${workflow} ${uni_count} ${olt_count} ${provisioned}
Wait Until Keyword Succeeds 10m 5s Count ADDED flows
... ${onos_ip} ${onos_port} ${targetFlows}
+
+Get Bandwidth Details
+ [Arguments] ${bandwidth_profile_name}
+ [Documentation] Collects the bandwidth profile details for the given bandwidth profile and
+ ... returns the limiting bandwidth
+ ${bandwidth_profile_values}= Execute ONOS CLI Command ${ONOS_SSH_IP} ${ONOS_SSH_PORT}
+ ... bandwidthprofile ${bandwidth_profile_name}
+ @{bandwidth_profile_array}= Split String ${bandwidth_profile_values} ,
+ @{parameter_value_pair}= Split String ${bandwidth_profile_array[1]} =
+ ${bandwidthparameter}= Set Variable ${parameter_value_pair[0]}
+ ${value}= Set Variable ${parameter_value_pair[1]}
+ ${cir_value} Run Keyword If '${bandwidthparameter}' == ' committedInformationRate'
+ ... Set Variable ${value}
+ @{parameter_value_pair}= Split String ${bandwidth_profile_array[2]} =
+ ${bandwidthparameter}= Set Variable ${parameter_value_pair[0]}
+ ${value}= Set Variable ${parameter_value_pair[1]}
+ ${cbs_value} Run Keyword If '${bandwidthparameter}' == ' committedBurstSize' Set Variable ${value}
+ @{parameter_value_pair}= Split String ${bandwidth_profile_array[3]} =
+ ${bandwidthparameter}= Set Variable ${parameter_value_pair[0]}
+ ${value}= Set Variable ${parameter_value_pair[1]}
+ ${eir_value} Run Keyword If '${bandwidthparameter}' == ' exceededInformationRate' Set Variable ${value}
+ @{parameter_value_pair}= Split String ${bandwidth_profile_array[4]} =
+ ${bandwidthparameter}= Set Variable ${parameter_value_pair[0]}
+ ${value}= Set Variable ${parameter_value_pair[1]}
+ ${ebs_value} Run Keyword If '${bandwidthparameter}' == ' exceededBurstSize' Set Variable ${value}
+ ${limiting_BW}= Evaluate ${cir_value}+${eir_value}
+ [Return] ${limiting_BW}
diff --git a/libraries/utils.robot b/libraries/utils.robot
index 258b465..8c9f655 100644
--- a/libraries/utils.robot
+++ b/libraries/utils.robot
@@ -529,4 +529,52 @@
... Evaluate (${olt_count} * 2)
... ELSE
... Evaluate (${uni_count} * 6) + (${olt_count} * 1)
- Return From Keyword ${flow_count}
\ No newline at end of file
+ Return From Keyword ${flow_count}
+
+Get Bandwidth Profile Name For Given Subscriber
+ [Arguments] ${subscriber_id} ${stream_type}=upstreamBandwidthProfile
+ [Documentation] Keyword to get the bandwidth details of the given subscriber
+ ${bandwidth_profile_output}= Execute ONOS CLI Command ${ONOS_SSH_IP} ${ONOS_SSH_PORT}
+ ... volt-programmed-subscribers | grep ${subscriber_id}
+ @{bandwidth_profile_array}= Split String ${bandwidth_profile_output} ,
+ Log ${bandwidth_profile_array}
+ FOR ${value} IN @{bandwidth_profile_array}
+ @{row_value}= Split String ${value} =
+ ${bandwidth_profile_name}= Set Variable If '${row_value[0]}' == ' ${stream_type}'
+ ... ${row_value[1]}
+ ${bandwidth_profile_name}= Convert To String ${bandwidth_profile_name}
+ Run Keyword If "${bandwidth_profile_name}" != "None" Exit For Loop
+ END
+ Log ${bandwidth_profile_name}
+ [Return] ${bandwidth_profile_name}
+
+Execute Remote Command
+ [Documentation] SSH into a remote host and execute a command on the bare host or in a container.
+ ... This replaces and simplifies the Login And Run Command On Remote System keyword in CORDRobot.
+ [Arguments] ${cmd} ${ip} ${user} ${pass}=${None}
+ ... ${container_type}=${None} ${container_name}=${None}
+ ${conn_id}= SSHLibrary.Open Connection ${ip}
+ Run Keyword If '${pass}' != '${None}'
+ ... SSHLibrary.Login ${user} ${pass}
+ ... ELSE
+ ... SSHLibrary.Login With Public Key ${user} %{HOME}/.ssh/id_rsa
+ ${namespace}= Run Keyword If '${container_type}' == 'K8S' SSHLibrary.Execute Command
+ ... kubectl get pods --all-namespaces | grep ${container_name} | awk '{print $1}'
+ ${output}= Run Keyword If '${container_type}' == 'LXC'
+ ... SSHLibrary.Execute Command lxc exec ${container_name} -- ${cmd}
+ ... ELSE IF '${container_type}' == 'K8S'
+ ... SSHLibrary.Execute Command kubectl -n ${namespace} exec ${container_name} -- ${cmd}
+ ... ELSE
+ ... SSHLibrary.Execute Command ${cmd}
+ Log ${output}
+ SSHLibrary.Close Connection
+ [Return] ${output}
+
+Run Iperf3 Test Client
+ [Arguments] ${src} ${server} ${args}
+ [Documentation] Login to ${src} and run the iperf3 client against ${server} using ${args}.
+ ... Return a Dictionary containing the results of the test.
+ ${output}= Execute Remote Command iperf3 -J -c ${server} ${args} | jq -M -c '.'
+ ... ${src['ip']} ${src['user']} ${src['pass']} ${src['container_type']} ${src['container_name']}
+ ${object}= Evaluate json.loads(r'''${output}''') json
+ [Return] ${object}
diff --git a/tests/data/tucson-pod-sadis.json b/tests/data/tucson-pod-sadis.json
index 9f4fcc1..1ee05da 100644
--- a/tests/data/tucson-pod-sadis.json
+++ b/tests/data/tucson-pod-sadis.json
@@ -25,8 +25,8 @@
"ponCTag": 11,
"ponSTag": 11,
"technologyProfileId": 64,
- "upstreamBandwidthProfile": "User_Bandwidth1",
- "downstreamBandwidthProfile": "User_Bandwidth1",
+ "upstreamBandwidthProfile": "Default",
+ "downstreamBandwidthProfile": "Default",
"isDhcpRequired": true
}]
},
@@ -39,7 +39,7 @@
"ponCTag": 12,
"ponSTag": 11,
"technologyProfileId": 64,
- "upstreamBandwidthProfile": "User_Bandwidth2",
+ "upstreamBandwidthProfile": "User_Bandwidth1",
"downstreamBandwidthProfile": "User_Bandwidth2",
"isDhcpRequired": true
}]
@@ -80,7 +80,7 @@
{
"id": "User_Bandwidth1",
"air": 100000,
- "cbs": 10000,
+ "cbs": 1000,
"cir": 30000,
"ebs": 1000,
"eir": 20000
@@ -97,9 +97,9 @@
"id": "User_Bandwidth3",
"air": 100000,
"cbs": 5000,
- "cir": 1000000,
+ "cir": 500000,
"ebs": 5000,
- "eir": 1000000
+ "eir": 500000
}
]
diff --git a/tests/functional/Voltha_PODTests.robot b/tests/functional/Voltha_PODTests.robot
index 7671f1a..993b489 100644
--- a/tests/functional/Voltha_PODTests.robot
+++ b/tests/functional/Voltha_PODTests.robot
@@ -51,6 +51,12 @@
${teardown_device} False
${scripts} ../../scripts
+# For dataplane bandwidth testing
+${upper_margin_pct} 105 # Allow 5% over the limit
+${lower_margin_pct} 93 # Allow 7% under the limit
+${udp_rate_multiplier} 1.10 # Send UDP at bw profile limit * rate_multiplier
+${udp_packet_bytes} 1400 # UDP payload in bytes
+
# Per-test logging on failure is turned off by default; set this variable to enable
${container_log_dir} ${None}
@@ -445,6 +451,103 @@
END
Run Keyword and Ignore Error Collect Logs
+Data plane verification using TCP
+ [Documentation] Test bandwidth profile is met and not exceeded for each subscriber.
+ ... Assumes iperf3 and jq installed on client and iperf -s running on DHCP server
+ [Tags] dataplane BW-profile-TCP VOL-2052
+ [Setup] None
+ [Teardown] None
+ Pass Execution If '${has_dataplane}'=='False' Bandwidth profile validation can be done only in
+ ... physical pod. Skipping this test in BBSIM.
+ FOR ${I} IN RANGE 0 ${num_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in ONOS ${src['onu']}
+ ... ${of_id}
+ ${subscriber_id}= Set Variable ${of_id}/${onu_port}
+ ${bandwidth_profile_name} Get Bandwidth Profile Name For Given Subscriber ${subscriber_id}
+ ... upstreamBandwidthProfile
+ ${limiting_bw_value_upstream} Get Bandwidth Details ${bandwidth_profile_name}
+ ${bandwidth_profile_name} Get Bandwidth Profile Name For Given Subscriber ${subscriber_id}
+ ... downstreamBandwidthProfile
+ ${limiting_bw_value_dnstream} Get Bandwidth Details ${bandwidth_profile_name}
+
+ # Stream TCP packets from RG to server
+ ${updict}= Run Iperf3 Test Client ${src} server=${dst['dp_iface_ip_qinq']}
+ ... args=-t 30
+ ${actual_upstream_bw_used}= Evaluate ${updict['end']['sum_received']['bits_per_second']}/1000
+
+ # Stream TCP packets from server to RG
+ ${dndict}= Run Iperf3 Test Client ${src} server=${dst['dp_iface_ip_qinq']}
+ ... args=-R -t 30
+ ${actual_dnstream_bw_used}= Evaluate ${dndict['end']['sum_received']['bits_per_second']}/1000
+
+ ${pct_limit_up}= Evaluate 100*${actual_upstream_bw_used}/${limiting_bw_value_upstream}
+ ${pct_limit_dn}= Evaluate 100*${actual_dnstream_bw_used}/${limiting_bw_value_dnstream}
+ Log Up: bwprof ${limiting_bw_value_upstream}Kbps, got ${actual_upstream_bw_used}Kbps (${pct_limit_up}%)
+ Log Down: bwprof ${limiting_bw_value_dnstream}Kbps, got ${actual_dnstream_bw_used}Kbps (${pct_limit_dn}%)
+
+ Should Be True ${pct_limit_up} <= ${upper_margin_pct}
+ ... The upstream bandwidth exceeded the limit (${pct_limit_up}% of limit)
+ Should Be True ${pct_limit_dn} <= ${upper_margin_pct}
+ ... The downstream bandwidth exceeded the limit (${pct_limit_dn}% of limit)
+ Should Be True ${pct_limit_up} >= ${lower_margin_pct}
+ ... The upstream bandwidth guarantee was not met (${pct_limit_up}% of resv)
+ Should Be True ${pct_limit_dn} >= ${lower_margin_pct}
+ ... The downstream bandwidth guarantee was not met (${pct_limit_dn}% of resv)
+ END
+
+Data plane verification using UDP
+ [Documentation] Test bandwidth profile is met and not exceeded for each subscriber.
+ ... Assumes iperf3 and jq installed on client and iperf -s running on DHCP server
+ [Tags] dataplane BW-profile-UDP VOL-2052
+ [Setup] None
+ [Teardown] None
+ Pass Execution If '${has_dataplane}'=='False' Bandwidth profile validation can be done only in
+ ... physical pod. Skipping this test in BBSIM.
+ FOR ${I} IN RANGE 0 ${num_onus}
+ ${src}= Set Variable ${hosts.src[${I}]}
+ ${dst}= Set Variable ${hosts.dst[${I}]}
+ ${onu_port}= Wait Until Keyword Succeeds ${timeout} 2s Get ONU Port in ONOS ${src['onu']}
+ ... ${of_id}
+ ${subscriber_id}= Set Variable ${of_id}/${onu_port}
+ ${bandwidth_profile_name} Get Bandwidth Profile Name For Given Subscriber ${subscriber_id}
+ ... upstreamBandwidthProfile
+ ${limiting_bw_value_upstream} Get Bandwidth Details ${bandwidth_profile_name}
+ ${bandwidth_profile_name} Get Bandwidth Profile Name For Given Subscriber ${subscriber_id}
+ ... downstreamBandwidthProfile
+ ${limiting_bw_value_dnstream} Get Bandwidth Details ${bandwidth_profile_name}
+
+ # Stream UDP packets from RG to server
+ ${uprate}= Evaluate ${limiting_bw_value_upstream}*${udp_rate_multiplier}
+ ${updict}= Run Iperf3 Test Client ${src} server=${dst['dp_iface_ip_qinq']}
+ ... args=-u -b ${uprate}K -t 30 -l ${udp_packet_bytes}
+ # With UDP test, bits per second is the sending rate. Multiply by the loss rate to get the throughput.
+ ${actual_upstream_bw_used}= Evaluate
+ ... (100 - ${updict['end']['sum']['lost_percent']})*${updict['end']['sum']['bits_per_second']}/100000
+
+ # Stream UDP packets from server to RG
+ ${dnrate}= Evaluate ${limiting_bw_value_dnstream}*${udp_rate_multiplier}
+ ${dndict}= Run Iperf3 Test Client ${src} server=${dst['dp_iface_ip_qinq']}
+ ... args=-u -b ${dnrate}K -R -t 30 -l ${udp_packet_bytes}
+ # With UDP test, bits per second is the sending rate. Multiply by the loss rate to get the throughput.
+ ${actual_dnstream_bw_used}= Evaluate
+ ... (100 - ${dndict['end']['sum']['lost_percent']})*${dndict['end']['sum']['bits_per_second']}/100000
+
+ ${pct_limit_up}= Evaluate 100*${actual_upstream_bw_used}/${limiting_bw_value_upstream}
+ ${pct_limit_dn}= Evaluate 100*${actual_dnstream_bw_used}/${limiting_bw_value_dnstream}
+ Log Up: bwprof ${limiting_bw_value_upstream}Kbps, got ${actual_upstream_bw_used}Kbps (${pct_limit_up}%)
+ Log Down: bwprof ${limiting_bw_value_dnstream}Kbps, got ${actual_dnstream_bw_used}Kbps (${pct_limit_dn}%)
+
+ Should Be True ${pct_limit_up} <= ${upper_margin_pct}
+ ... The upstream bandwidth exceeded the limit (${pct_limit_up}% of limit)
+ Should Be True ${pct_limit_dn} <= ${upper_margin_pct}
+ ... The downstream bandwidth exceeded the limit (${pct_limit_dn}% of limit)
+ Should Be True ${pct_limit_up} >= ${lower_margin_pct}
+ ... The upstream bandwidth guarantee was not met (${pct_limit_up}% of resv)
+ Should Be True ${pct_limit_dn} >= ${lower_margin_pct}
+ ... The downstream bandwidth guarantee was not met (${pct_limit_dn}% of resv)
+ END
*** Keywords ***
Setup Suite