-
Notifications
You must be signed in to change notification settings - Fork 740
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add PFC watchdog impact on runtime traffic test case
- Loading branch information
1 parent
ad98413
commit 700fb98
Showing
2 changed files
with
201 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import time | ||
from math import ceil | ||
|
||
from tests.common.helpers.assertions import pytest_assert | ||
from tests.common.ixia.ixia_fixtures import ixia_api_serv_ip, ixia_api_serv_port,\ | ||
ixia_api_serv_user, ixia_api_serv_passwd, ixia_api | ||
from tests.common.ixia.ixia_helpers import get_dut_port_id | ||
from tests.common.ixia.common_helpers import start_pfcwd, stop_pfcwd | ||
|
||
from abstract_open_traffic_generator.flow import DeviceTxRx, TxRx, Flow, Header,\ | ||
Size, Rate,Duration, FixedSeconds, FixedPackets, PortTxRx, PfcPause | ||
from abstract_open_traffic_generator.flow_ipv4 import Priority, Dscp | ||
from abstract_open_traffic_generator.flow import Pattern as FieldPattern | ||
from abstract_open_traffic_generator.flow import Ipv4 as Ipv4Header | ||
from abstract_open_traffic_generator.flow import Ethernet as EthernetHeader | ||
from abstract_open_traffic_generator.control import State, ConfigState,\ | ||
FlowTransmitState | ||
from abstract_open_traffic_generator.result import FlowRequest | ||
|
||
DATA_FLOW_NAME = "Data Flow" | ||
DATA_PKT_SIZE = 1024 | ||
DATA_FLOW_DURATION_SEC = 15 | ||
PFCWD_START_DELAY_SEC = 3 | ||
IXIA_POLL_DELAY_SEC = 2 | ||
TOLERANCE_THRESHOLD = 0.05 | ||
|
||
def run_pfcwd_runtime_traffic_test(api, | ||
testbed_config, | ||
conn_data, | ||
fanout_data, | ||
duthost, | ||
dut_port, | ||
prio_list, | ||
prio_dscp_map): | ||
|
||
pytest_assert(testbed_config is not None, 'Fail to get L2/3 testbed config') | ||
|
||
stop_pfcwd(duthost) | ||
|
||
""" Get the ID of the port to test """ | ||
port_id = get_dut_port_id(dut_hostname=duthost.hostname, | ||
dut_port=dut_port, | ||
conn_data=conn_data, | ||
fanout_data=fanout_data) | ||
|
||
pytest_assert(port_id is not None, | ||
'Fail to get ID for port {}'.format(dut_port)) | ||
|
||
flows = __gen_traffic(testbed_config=testbed_config, | ||
port_id=port_id, | ||
data_flow_name=DATA_FLOW_NAME, | ||
data_flow_dur_sec=DATA_FLOW_DURATION_SEC, | ||
data_pkt_size=DATA_PKT_SIZE, | ||
prio_list=prio_list, | ||
prio_dscp_map=prio_dscp_map) | ||
|
||
""" Tgen config = testbed config + flow config """ | ||
config = testbed_config | ||
config.flows = flows | ||
|
||
all_flow_names = [flow.name for flow in flows] | ||
|
||
flow_stats = __run_traffic(api=api, | ||
config=config, | ||
duthost=duthost, | ||
all_flow_names=all_flow_names, | ||
pfcwd_start_delay_sec=PFCWD_START_DELAY_SEC, | ||
exp_dur_sec=DATA_FLOW_DURATION_SEC) | ||
|
||
speed_str = config.layer1[0].speed | ||
speed_gbps = int(speed_str.split('_')[1]) | ||
|
||
__verify_results(rows=flow_stats, | ||
speed_gbps=speed_gbps, | ||
data_flow_dur_sec=DATA_FLOW_DURATION_SEC, | ||
data_pkt_size=DATA_PKT_SIZE, | ||
tolerance=TOLERANCE_THRESHOLD) | ||
|
||
def __gen_traffic(testbed_config, | ||
port_id, | ||
data_flow_name, | ||
data_flow_dur_sec, | ||
data_pkt_size, | ||
prio_list, | ||
prio_dscp_map): | ||
|
||
rx_port_id = port_id | ||
tx_port_id = (port_id + 1) % len(testbed_config.devices) | ||
|
||
data_endpoint = DeviceTxRx( | ||
tx_device_names=[testbed_config.devices[tx_port_id].name], | ||
rx_device_names=[testbed_config.devices[rx_port_id].name], | ||
) | ||
|
||
result = list() | ||
data_flow_rate_percent = int(100 / len(prio_list)) | ||
|
||
""" For each priority """ | ||
for prio in prio_list: | ||
ip_prio = Priority(Dscp(phb=FieldPattern(choice=prio_dscp_map[prio]), | ||
ecn=FieldPattern(choice=Dscp.ECN_CAPABLE_TRANSPORT_1))) | ||
pfc_queue = FieldPattern([prio]) | ||
|
||
data_flow = Flow( | ||
name='{} Prio {}'.format(data_flow_name, prio), | ||
tx_rx=TxRx(data_endpoint), | ||
packet=[ | ||
Header(choice=EthernetHeader(pfc_queue=pfc_queue)), | ||
Header(choice=Ipv4Header(priority=ip_prio)) | ||
], | ||
size=Size(data_pkt_size), | ||
rate=Rate('line', data_flow_rate_percent), | ||
duration=Duration(FixedSeconds(seconds=data_flow_dur_sec)) | ||
) | ||
|
||
result.append(data_flow) | ||
|
||
return result | ||
|
||
def __run_traffic(api, config, duthost, all_flow_names, pfcwd_start_delay_sec, exp_dur_sec): | ||
api.set_state(State(ConfigState(config=config, state='set'))) | ||
api.set_state(State(FlowTransmitState(state='start'))) | ||
|
||
time.sleep(pfcwd_start_delay_sec) | ||
start_pfcwd(duthost) | ||
time.sleep(exp_dur_sec - pfcwd_start_delay_sec) | ||
|
||
attempts = 0 | ||
max_attempts = 20 | ||
|
||
while attempts < max_attempts: | ||
rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names)) | ||
""" If all the flows have stopped """ | ||
transmit_states = [row['transmit'] for row in rows] | ||
if len(rows) == len(all_flow_names) and\ | ||
list(set(transmit_states)) == ['stopped']: | ||
time.sleep(IXIA_POLL_DELAY_SEC) | ||
break | ||
else: | ||
time.sleep(1) | ||
attempts += 1 | ||
|
||
""" Dump per-flow statistics """ | ||
rows = api.get_flow_results(FlowRequest(flow_names=all_flow_names)) | ||
api.set_state(State(FlowTransmitState(state='stop'))) | ||
|
||
return rows | ||
|
||
def __verify_results(rows, speed_gbps, data_flow_dur_sec, data_pkt_size, tolerance): | ||
data_flow_rate_percent = int(100 / len(rows)) | ||
|
||
for row in rows: | ||
flow_name = row['name'] | ||
tx_frames = row['frames_tx'] | ||
rx_frames = row['frames_rx'] | ||
|
||
pytest_assert(tx_frames == rx_frames, "{} packets of {} are dropped".\ | ||
format(tx_frames-rx_frames, flow_name)) | ||
|
||
exp_rx_pkts = data_flow_rate_percent / 100.0 * speed_gbps \ | ||
* 1e9 * data_flow_dur_sec / 8.0 / data_pkt_size | ||
|
||
deviation = (rx_frames - exp_rx_pkts) / float(exp_rx_pkts) | ||
pytest_assert(abs(deviation) < tolerance, | ||
"{} should receive {} packets (actual {})".\ | ||
format(flow_name, exp_rx_pkts, rx_frames)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import pytest | ||
|
||
from tests.common.helpers.assertions import pytest_require, pytest_assert | ||
from tests.common.fixtures.conn_graph_facts import conn_graph_facts,\ | ||
fanout_graph_facts | ||
from tests.common.ixia.ixia_fixtures import ixia_api_serv_ip, ixia_api_serv_port,\ | ||
ixia_api_serv_user, ixia_api_serv_passwd, ixia_api, ixia_testbed | ||
from tests.common.ixia.qos_fixtures import prio_dscp_map, all_prio_list | ||
|
||
from files.pfcwd_runtime_traffic_helper import run_pfcwd_runtime_traffic_test | ||
|
||
def test_pfcwd_runtime_traffic(ixia_api, | ||
ixia_testbed, | ||
conn_graph_facts, | ||
fanout_graph_facts, | ||
duthosts, | ||
rand_one_dut_hostname, | ||
rand_one_dut_portname_oper_up, | ||
all_prio_list, | ||
prio_dscp_map): | ||
|
||
dut_hostname, dut_port = rand_one_dut_portname_oper_up.split('|') | ||
pytest_require(rand_one_dut_hostname == dut_hostname, | ||
"Port is not mapped to the expected DUT") | ||
|
||
duthost = duthosts[rand_one_dut_hostname] | ||
|
||
run_pfcwd_runtime_traffic_test(api=ixia_api, | ||
testbed_config=ixia_testbed, | ||
conn_data=conn_graph_facts, | ||
fanout_data=fanout_graph_facts, | ||
duthost=duthost, | ||
dut_port=dut_port, | ||
prio_list=all_prio_list, | ||
prio_dscp_map=prio_dscp_map) |