Skip to content

Commit

Permalink
Add PFC watchdog impact on runtime traffic test case
Browse files Browse the repository at this point in the history
  • Loading branch information
baiwei0427 committed Feb 11, 2021
1 parent ad98413 commit 700fb98
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 0 deletions.
166 changes: 166 additions & 0 deletions tests/ixia/pfcwd/files/pfcwd_runtime_traffic_helper.py
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))
35 changes: 35 additions & 0 deletions tests/ixia/pfcwd/test_pfcwd_runtime_traffic.py
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)

0 comments on commit 700fb98

Please sign in to comment.