Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] [SDFAB-512] Design testing framework for ASTF-mode TRex for linerate TCP testing #368

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ba1df04
Design testing framework for ASTF-mode TRex for linerate TCP testing
Aug 26, 2021
e564ef0
Add copyright and licensing information to new files
Aug 26, 2021
90156b0
Bugfix and cleanup
Aug 26, 2021
ce508e8
Minor cleanup
Aug 27, 2021
4bebbba
Merge branch 'stratum:main' into tcp-linerate
dariusgrassi Sep 1, 2021
d27f106
Address comments
Sep 2, 2021
5376aac
Fix small mistake
Sep 2, 2021
d23ced6
Add update from debugging and forum advice
Sep 7, 2021
cb958a3
Merge branch 'stratum:main' into tcp-linerate
dariusgrassi Sep 9, 2021
e024ff5
Fix bug where ASTF servers were not receiving client requests
Sep 9, 2021
b834bcb
Merge branch 'stratum:main' into tcp-linerate
dariusgrassi Sep 13, 2021
d461149
Employ multiple methods to increase throughput and change behaviour of
Sep 16, 2021
e14cf92
Cleanup and verify test is only using one flow
Sep 18, 2021
c1ed339
Merge branch 'stratum:main' into tcp-linerate
dariusgrassi Sep 22, 2021
17e4444
Create a helper function for TRex tests which prints out readable
Sep 24, 2021
6bbce17
Normalize TRex INT tests to meet certain baseline expectations:
Sep 24, 2021
ccc3e09
Switch branch from trex-continuous-helper to main
Sep 25, 2021
95a445f
Push chassis config before INT tests and fix `int_single_flow` issues
Sep 27, 2021
dd373c9
Address Yi comments
Sep 28, 2021
d78ba82
Address comments and list all ports
Sep 28, 2021
5f554cb
Merge branch 'trex-continuous-helper' into tcp-linerate
Sep 28, 2021
c880cff
Address Carmelo comments
Sep 29, 2021
3dbbf81
Return dictionary of all results with function
Sep 29, 2021
8eb6768
Address comments
Sep 29, 2021
18925df
Merge branch 'trex-continuous-helper' into tcp-linerate
Sep 30, 2021
e2e86b6
Merge branch 'normalize-trex-test' into tcp-linerate
Sep 30, 2021
6c42081
Merge branch 'main' into tcp-linerate
Sep 30, 2021
7222d87
Remove extra monitor_port_stats function
Sep 30, 2021
cf558b7
Split sanity test, normalize and add verification
Oct 1, 2021
b86dcd3
Modify push_chassis_config and remove shaped sanity test
Oct 1, 2021
8aa46ef
Upgrade TRex to v2.92 and implement linerate unshaped sanity test
Nov 5, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ptf/tests/common/ptf_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,12 @@ def main():
action="store_true",
required=False,
)
parser.add_argument(
"--trex-astf-mode",
help="Enables TRex ASTF mode for advanced stateful TCP linerate testing",
action="store_true",
required=False,
)
args, unknown_args = parser.parse_known_args()

if not check_ptf():
Expand Down Expand Up @@ -497,6 +503,10 @@ def main():
if args.trex_address is not None:
if args.trex_sw_mode:
trex_args = "--software --no-hw-flow-stat"
if args.trex_astf_mode is not None:
trex_args += " --astf"
elif args.trex_astf_mode is not None:
trex_args = "--astf"
else:
trex_args = None
dariusgrassi marked this conversation as resolved.
Show resolved Hide resolved
trex_daemon_client = CTRexClient(args.trex_address, trex_args=trex_args)
Expand Down
26 changes: 26 additions & 0 deletions ptf/tests/common/trex_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from base_test import *
from trex.stl.api import STLClient
from trex.astf.api import ASTFClient


class TRexTest(P4RuntimeTest):
Expand All @@ -28,3 +29,28 @@ def tearDown(self):
self.trex_client.release()
self.trex_client.disconnect()
super(TRexTest, self).tearDown()


class TRexAstfTest(P4RuntimeTest):
trex_client: ASTFClient

def setUp(self):
super(TRexAstfTest, self).setUp()
trex_server_addr = ptf.testutils.test_param_get("trex_server_addr")
self.trex_client = ASTFClient(server=trex_server_addr)
self.trex_client.connect()
self.trex_client.acquire()
self.trex_client.reset() # Resets configs from all ports
self.trex_client.clear_stats() # Clear status from all ports
# Put all ports to promiscuous mode, otherwise they will drop all
# incoming packets if the destination mac is not the port mac address.
self.trex_client.set_port_attr(
self.trex_client.get_all_ports(), promiscuous=True
)

def tearDown(self):
print("Tearing down ASTFClient...")
self.trex_client.stop()
self.trex_client.release()
self.trex_client.disconnect()
super(TRexAstfTest, self).tearDown()
90 changes: 90 additions & 0 deletions ptf/tests/linerate/astf_tcp_flows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Copyright 2020-present Open Networking Foundation
# SPDX-License-Identifier: LicenseRef-ONF-Member-Only-1.0

from datetime import datetime

import os
from trex.astf.api import *

from base_test import *
from fabric_test import *
from ptf.testutils import group
from trex_test import TRexAstfTest
from trex_utils import list_port_status
from xnt import analyze_report_pcap


TRAFFIC_MULT = 1.0
TEST_DURATION = 10
CAPTURE_LIMIT = 20

SENDER_PORTS = [0]
RECEIVER_PORTS = [1]
INT_COLLECTOR_PORTS = [2]

SIZE = 1
LOOP = 10
WIN = 32
MSS = 0


class AstfTcpFlow(TRexAstfTest, SlicingTest):
@autocleanup
def runTest(self):

passed = True

try:
# load ASTF profile
profile_path = '/fabric-tna/ptf/tests/linerate/http_eflow2.py'

profile_tunables = {'size': SIZE, 'loop': LOOP, 'win': WIN, 'mss': MSS}
self.trex_client.load_profile(profile = profile_path, tunables = profile_tunables)

print("Injecting with multiplier of '%s' for %s seconds" % (TRAFFIC_MULT, TEST_DURATION))
self.trex_client.start(mult = TRAFFIC_MULT, duration = TEST_DURATION)

# block until done
self.trex_client.wait_on_traffic()

# read the stats after the test
stats = self.trex_client.get_stats()

# use this for debug info on all the stats
print(stats)

if self.trex_client.get_warnings():
print('\n\n*** test had warnings ****\n\n')
for w in self.trex_client.get_warnings():
print(w)


client_stats = stats['traffic']['client']
server_stats = stats['traffic']['server']

tcp_client_sent, tcp_server_recv = client_stats.get('tcps_sndbyte', 0), server_stats.get('tcps_rcvbyte', 0)
tcp_server_sent, tcp_client_recv = server_stats.get('tcps_sndbyte', 0), client_stats.get('tcps_rcvbyte', 0)

udp_client_sent, udp_server_recv = client_stats.get('udps_sndbyte', 0), server_stats.get('udps_rcvbyte', 0)
udp_server_sent, udp_client_recv = server_stats.get('udps_sndbyte', 0), client_stats.get('udps_rcvbyte', 0)

assert (tcp_client_sent == tcp_server_recv), 'Too much TCP drops - clients sent: %s, servers received: %s' % (tcp_client_sent, tcp_server_recv)
assert (tcp_server_sent == tcp_client_recv), 'Too much TCP drops - servers sent: %s, clients received: %s' % (tcp_server_sent, tcp_client_recv)

assert (udp_client_sent == udp_server_recv), 'Too much UDP drops - clients sent: %s, servers received: %s' % (udp_client_sent, udp_server_recv)
assert (udp_server_sent == udp_client_recv), 'Too much UDP drops - servers sent: %s, clients received: %s' % (udp_server_sent, udp_client_recv)


except TRexError as e:
passed = False
print(e)

except AssertionError as e:
passed = False
print(e)

if passed:
print('\nTest has passed :-)\n')
else:
print('\nTest has failed :-(\n')
sys.exit(1)
81 changes: 81 additions & 0 deletions ptf/tests/linerate/http_eflow2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright 2020-present Open Networking Foundation
# SPDX-License-Identifier: LicenseRef-ONF-Member-Only-1.0
#
# size : is in KB for each chuck in the loop
# loops : how many chunks to download
# win : in KB, the maximum window size. make it big for BDP
# pipe : Don't block on each send, make them in the pipeline should be 1 for maximum performance
# mss : the mss of the traffic
#######

from trex.astf.api import *


# we can send either Python bytes type as below:
http_req = b'GET /3384 HTTP/1.1\r\nHost: 22.0.0.3\r\nConnection: Keep-Alive\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\nAccept: */*\r\nAccept-Language: en-us\r\nAccept-Encoding: gzip, deflate, compress\r\n\r\n'
# or we can send Python string containing ascii chars, as below:
http_response = 'HTTP/1.1 200 OK\r\nServer: Microsoft-IIS/6.0\r\nContent-Type: text/html\r\nContent-Length: 32000\r\n\r\n<html><pre>**********</pre></html>'

class Prof1():
def __init__(self):
pass # tunables

def create_profile(self,size,loop,mss,win,pipe):

bsize = len(http_response)

# client commands
prog_c = ASTFProgram()
prog_c.send(http_req)
prog_c.recv(bsize*loop)

# server commands
prog_s = ASTFProgram()
prog_s.recv(len(http_req))
if pipe:
prog_s.set_send_blocking (False) # configure the state machine to continue to the next send when there is the queue has space
prog_s.set_var("var2",loop-1); # set var to loop-1 (there is another blocking send)
prog_s.set_label("a:");
prog_s.send(http_response)
prog_s.jmp_nz("var2","a:") # dec var "var2". in case it is *not* zero jump a:
prog_s.set_send_blocking (True) # back to blocking mode
prog_s.send(http_response)


info = ASTFGlobalInfo()
if mss:
info.tcp.mss = mss
info.tcp.initwnd = 2 # start big
info.tcp.no_delay = 1 # to get fast feedback for acks
info.tcp.rxbufsize = win*1024 # 1MB window
info.tcp.txbufsize = win*1024
#info.tcp.do_rfc1323 =0


# ip generator
ip_gen_c = ASTFIPGenDist(ip_range=["16.0.0.0", "16.0.0.255"], distribution="seq")
ip_gen_s = ASTFIPGenDist(ip_range=["48.0.0.0", "48.0.255.255"], distribution="seq")
ip_gen = ASTFIPGen(glob=ASTFIPGenGlobal(ip_offset="1.0.0.0"),
dist_client=ip_gen_c,
dist_server=ip_gen_s)


# template
temp_c = ASTFTCPClientTemplate(program=prog_c, ip_gen=ip_gen, cps=1,limit=1)
temp_s = ASTFTCPServerTemplate(program=prog_s) # using default association
template = ASTFTemplate(client_template=temp_c, server_template=temp_s)

# profile
profile = ASTFProfile(default_ip_gen=ip_gen,
templates=template,
default_c_glob_info=info,
default_s_glob_info=info)

return profile

def get_profile(self, size=1, loop=10, mss=0, win=32, pipe=0, **kwargs):
return self.create_profile(size, loop, mss, win, pipe)


def register():
return Prof1()