Skip to content
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
06cd811
[ixia/Keysight] sample test cases and fixtures
abhijit-dhar Jun 25, 2020
b6a0963
[ixia/Keysight] adding ixia libraries
abhijit-dhar Jun 26, 2020
2a8ad2b
[ixia/Keysight] This file should be in common/ixia
abhijit-dhar Jun 26, 2020
694ae89
[ixia/Keysight] lib/ixia_fixtures.py
abhijit-dhar Jun 26, 2020
b5316e8
[ixia/Keysight] deleting ixia_helpers.py
abhijit-dhar Jun 26, 2020
663e920
[ixia/Keysight] updated test_ixia_traffic_restpy.py
abhijit-dhar Jun 26, 2020
61ff293
Update test_ixia_traffic_restpy.py
abhijit-dhar Jul 1, 2020
721b6b1
[ixia/Keysight] Changed as per review comments
abhijit-dhar Jul 1, 2020
4833513
[ixia/Keysight] added new IxiaFanoutManager class
abhijit-dhar Jul 1, 2020
b0f1bf6
[ixia/Keysight] Adding __init__().py
abhijit-dhar Jul 1, 2020
7bd3dbd
[ixia/Keysight] Adding IxiaHost class
abhijit-dhar Jul 1, 2020
cbf0235
[ixia/Keysight] corrected typo added a new class
abhijit-dhar Jul 1, 2020
84f3201
[ixia/Keysight] Deleted from the review
abhijit-dhar Jul 1, 2020
f0098d1
[ixia/Keysight] adding ixia_fixtures
abhijit-dhar Jul 1, 2020
b91dc5e
[ixia/Keysight] updated ixia_fixtures.py
abhijit-dhar Jul 1, 2020
b288123
modifying and rdma test case according to ixia proposal
abhijit-dhar Jul 6, 2020
318c287
modifying and rdma test case according to ixia proposal
abhijit-dhar Jul 6, 2020
c33e7c8
removing the low level api from test_ixia_traffic_restpy.py
abhijit-dhar Jul 14, 2020
b789490
changed test scripts and lib functions
abhijit-dhar Jul 15, 2020
0678c57
added google style comments and changed function names
abhijit-dhar Jul 15, 2020
a0182c8
Added the google doc string for the methods in ixia_fixtures.py and i…
abhijit-dhar Jul 16, 2020
cfe3cbc
Implementing PR1819 review comments
abhijit-dhar Jul 16, 2020
ed09027
Removing test_ixia_traffic_restpy.py adding test_ixia_traffic.py
abhijit-dhar Jul 16, 2020
b54f209
Changing some comment string
abhijit-dhar Jul 16, 2020
c4c5310
Added stop_protocols function in ixia_helpers.py
abhijit-dhar Jul 17, 2020
c5ca281
Removed a sleep and added a debugging statement
abhijit-dhar Jul 17, 2020
9ab2d65
[ixia/Keysight] updating the review comments PR1819
abhijit-dhar Jul 17, 2020
aba759a
adding a simple poc
abhijit-dhar Jul 20, 2020
23a687f
Changed ixia/test_ixia_poc.py a bit
abhijit-dhar Jul 20, 2020
bc27595
Implementing the comments of PR1819
abhijit-dhar Jul 21, 2020
b3970a9
Implementing the comments of PR1819
abhijit-dhar Jul 21, 2020
fc12785
Updating the files as per the comment made on PR1819
abhijit-dhar Jul 22, 2020
b7af710
Refactoring the code for Tgen POC
abhijit-dhar Jul 23, 2020
482282f
Updating common/tgen_api/keystgenapi.py
abhijit-dhar Jul 23, 2020
b5476c6
Merging with the master branch
abhijit-dhar Jul 23, 2020
6b96a73
Updating the pfc pause test cases
abhijit-dhar Jul 25, 2020
154deb0
Merge remote-tracking branch 'upstream/master'
abhijit-dhar Jul 25, 2020
398aa7e
[Ixia/Keysight] changing the import statements from common.xxx to tes…
abhijit-dhar Jul 26, 2020
8952064
Merge branch 'master' into rdma1
abhijit-dhar Jul 26, 2020
c2f8b9c
[Ixia/Keysight] Updating PFC PAUSE test case
abhijit-dhar Jul 27, 2020
2e01260
[Ixia/Keysight] Updating PFC PAUSE test case indentations + comments
abhijit-dhar Jul 27, 2020
12875ed
[Ixia/Keysight] Updating qos_fixtures.py indentations + comments
abhijit-dhar Jul 27, 2020
95e38b2
[Ixia/Keysight] Updating qos_fixtures.py indentations + comments
abhijit-dhar Jul 27, 2020
debac8c
Merge remote-tracking branch 'upstream/master'
abhijit-dhar Jul 27, 2020
1690344
deleting tgen POC
abhijit-dhar Jul 28, 2020
ffdaa54
Merge branch 'master' into rdma1
abhijit-dhar Jul 28, 2020
e23970c
[Ixia/Keysight] Updating first RDMA test cases
abhijit-dhar Jul 28, 2020
44eddb9
Implemented the review comments of PR#1979
abhijit-dhar Aug 11, 2020
4f03ba6
Implementing the comment given by Wei
abhijit-dhar Aug 14, 2020
dabddb2
correcting the function name
abhijit-dhar Aug 15, 2020
96d0ebf
Updating the first RDMA test cases as per comments
abhijit-dhar Aug 17, 2020
867394b
Changing the files as per review comments of PR1979
abhijit-dhar Aug 20, 2020
2b82d01
updating as per comments of wei --> for send_pause_frame in [True, Fa…
abhijit-dhar Aug 24, 2020
8cc251e
removed an unwanted variable assignment
abhijit-dhar Aug 24, 2020
1e5a1cd
added a Safety check 2 * RATE PERCENTAGE <= 100
abhijit-dhar Aug 25, 2020
a499c89
changed 'exp_tx_byte' to 'exp_tx_bytes'
abhijit-dhar Aug 26, 2020
08cf89c
changed 'exp_tx_byte' to 'rx_bytes'
abhijit-dhar Aug 26, 2020
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
326 changes: 326 additions & 0 deletions tests/common/ixia/ixia_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -530,3 +530,329 @@ def create_ip_traffic_item (
# Enable tracking.
traffic_item.Tracking.find().TrackBy = ['trackingenabled0']
return traffic_item


def create_ipv4_traffic(session,
name,
source,
destination,
pkt_size=64,
pkt_count=None,
duration=None,
rate_percent=100,
start_delay=0,
dscp_list=None,
lossless_prio_list=None,
ecn_capable=False):
"""
Create an IPv4 traffic item on IxNetwork.

Args:
session (obj): IxNetwork session object.
name (str): Name of traffic item
source (obj list): Source endpoints - list of IxNetwork vport objects.
destination (obj list): Destination endpoints - list of IxNetwork
vport objects.
pkt_size (int): Packet size.
pkt_count (int): Packet count.
duration (int): Traffic duration in second (positive integer only!)
rate_percent (int): Percentage of line rate.
start_delay (int): Start delay in second.
dscp_list(int list): List of DSCPs.
lossless_prio_list (int list): List of lossless priorities.
ecn_capable (bool): If packets can get ECN marked.

Returns:
The created traffic item or None in case of error.
"""
ixnetwork = session.Ixnetwork

traffic_item = ixnetwork.Traffic.TrafficItem.add(Name=name,
BiDirectional=False,
TrafficType='ipv4')

traffic_item.EndpointSet.add(Sources=source, Destinations=destination)

traffic_config = traffic_item.ConfigElement.find()[0]

# Todo: add sending rate support
traffic_config.FrameRate.update(Type='percentLineRate', Rate=rate_percent)
traffic_config.FrameRateDistribution.PortDistribution = 'splitRateEvenly'
traffic_config.FrameSize.FixedSize = pkt_size

if pkt_count is not None and duration is not None:
logger.error('You can only specify either pkt_count or duration')
return None

if pkt_count is not None:
traffic_config.TransmissionControl.update(Type='fixedFrameCount',
FrameCount=pkt_count)
elif duration is not None:
if type(duration) != int or duration <= 0:
logger.error('Invalid duration value {} (positive integer only)'.
format(duration))

return None
else:
traffic_config.TransmissionControl.update(
Type='fixedDuration',
Duration=duration)
else:
traffic_config.TransmissionControl.update(Type='continuous')

if start_delay > 0:
traffic_config.TransmissionControl.update(
StartDelayUnits='nanoseconds',
StartDelay=start_delay*(10**6))

if dscp_list is not None and len(dscp_list) > 0:
phb_field = traffic_item.ConfigElement.find().Stack.find('IPv4').Field.\
find(DisplayName='Default PHB')

phb_field.ActiveFieldChoice = True
phb_field.ValueType = 'valueList'
phb_field.ValueList = dscp_list

# Set ECN bits to 10 (ECN capable).
if ecn_capable:
phb_field = traffic_item.ConfigElement.find().Stack.find('IPv4').\
Field.find(FieldTypeId='ipv4.header.priority.ds.phb.defaultPHB.unused')

phb_field.ActiveFieldChoice = True
phb_field.ValueType = 'singleValue'
phb_field.SingleValue = 2

if lossless_prio_list is not None and len(lossless_prio_list) > 0:
eth_stack = traffic_item.ConfigElement.find()[0].Stack.find(
DisplayName='Ethernet II')

pfc_queue = eth_stack.Field.find(DisplayName='PFC Queue')
pfc_queue.ValueType = 'valueList'
pfc_queue.ValueList = lossless_prio_list

traffic_item.Tracking.find()[0].TrackBy = ['flowGroup0']

# Push ConfigElement settings down to HighLevelStream resources.
traffic_item.Generate()

return traffic_item


def create_pause_traffic(session, name, source, pkt_per_sec, pkt_count=None,
duration=None, start_delay=0, global_pause=False,
pause_prio_list=[]):
"""
Create a pause traffic item.

Args:
session (obj): IxNetwork session object.
name (str): Name of traffic item.
source (obj list): Source endpoints - list of IxNetwork vport objects.
pkt_per_sec (int): Packets per second.
pkt_count (int): Packet count.
duration (int): Traffic duration in second (positive integer only!).
start_delay (int): Start delay in second.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

float or int?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is float. Change is implemented.

global_pause (bool): If the generated packets are global pause
(IEEE 802.3X PAUSE).
pause_prio_list: list of priorities to pause. Only valid when
global_pause is False.

Returns:
The created traffic item or None if any errors happen.
"""
if pause_prio_list is not None:
for prio in pause_prio_list:
if prio < 0 or prio > 7:
logger.error('Invalid pause priorities {}'.
format(pause_prio_list))
return None

ixnetwork = session.Ixnetwork
traffic_item = ixnetwork.Traffic.TrafficItem.add(Name=name,
BiDirectional=False,
TrafficType='raw')

# Since PFC packets will not be forwarded by the switch, so
# destinations are actually not used.
traffic_item.EndpointSet.add(Sources=source.Protocols.find(),
Destinations=source.Protocols.find())

traffic_config = traffic_item.ConfigElement.find()[0]
traffic_config.FrameRate.update(Type='framesPerSecond', Rate=pkt_per_sec)
traffic_config.FrameRateDistribution.PortDistribution = 'splitRateEvenly'
traffic_config.FrameSize.FixedSize = 64

if pkt_count is not None and duration is not None:
logger.error('You can only specify either pkt_count or duration')
return None

if pkt_count is not None:
traffic_config.TransmissionControl.update(
Type='fixedFrameCount',
FrameCount=pkt_count)

elif duration is not None:
if type(duration) != int or duration <= 0:
logger.error('Invalid duration value {} (positive integer only)'.
format(duration))

return None
else:
traffic_config.TransmissionControl.update(
Type='fixedDuration',
Duration=duration)

else:
traffic_config.TransmissionControl.update(Type='continuous')

if start_delay > 0:
traffic_config.TransmissionControl.update(
StartDelayUnits='nanoseconds',
StartDelay=start_delay*(10**6))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think start_delay can be a float. But we need to ensure that start_delay * 1000000 is an int,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not changing this for the following reasons:

  1. It look quite awkward the people will give a value like start_delay 3.4623187 so the start_delay * 1000000 becomes an floating-point number (3462318.7).
  2. Even if start delay is some number like this 1.5, the start_delay * 1000000 becomes 1500000.0 the function which handles 1500000.0 should be able to handle 3462318.7
  3. The function handles "traffic_config.TransmissionControl.update" handles floating point numbers gracefully.


# Add PFC header
pfc_stack_obj = __create_pkt_hdr__(
ixnetwork=ixnetwork,
traffic_item=traffic_item,
pkt_hdr_to_add='^PFC PAUSE \(802.1Qbb\)',
append_to_stack='Ethernet II')

# Construct global pause and PFC packets.
if global_pause:
set_global_pause_fields(pfc_stack_obj)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no method defined with this name. __set_global.. is the one you meant?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function should be set_global_pause_fields

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an undiscovered error. Corrected.

else:
__set_pfc_fields__(pfc_stack_obj, pause_prio_list)

# Remove Ethernet header.
traffic_item.ConfigElement.find()[0].Stack.\
find(DisplayName="Ethernet II").Remove()

traffic_item.Tracking.find()[0].TrackBy = ['flowGroup0']

# Push ConfigElement settings down to HighLevelStream resources.
traffic_item.Generate()

return traffic_item

# This section defines helper function used in the module. These functions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use leading double underscore for all private methods

def __private_method():

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is implemented.

# should not be called from test script.
# 1. __set_global_pause_fields__
# 2. __set_eth_fields__
# 3. __set_eth_fields__
# 4. __set_pfc_fields__
# 5. __create_pkt_hdr__

def __set_global_pause_fields__(pfc_stack_obj):
code = pfc_stack_obj.find(DisplayName='Control opcode')
code.ValueType = 'singleValue'
code.SingleValue = '1'

# This field is pause duration in global pause packet.
prio_enable_vector = pfc_stack_obj.find(DisplayName='priority_enable_vector')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the newline

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is implemented.

prio_enable_vector.ValueType = 'singleValue'
prio_enable_vector.SingleValue = 'ffff'

# pad bytes
for i in range(8):
pause_duration = pfc_stack_obj.find(DisplayName='PFC Queue {}'.format(i))

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove new line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the new line.

pause_duration.ValueType = 'singleValue'
pause_duration.SingleValue = '0'


def __set_eth_fields__(eth_stack_obj, src_mac, dst_mac):
if src_mac is not None:
src_mac_field = eth_stack_obj.find(DisplayName='Source MAC Address')
src_mac_field.ValueType = 'singleValue'
src_mac_field.SingleValue = src_mac

if dst_mac is not None:
dst_mac_field = eth_stack_obj.find(DisplayName='Destination MAC Address')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove the new line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is implemented

dst_mac_field.ValueType = 'singleValue'
dst_mac_field.SingleValue = dst_mac


def __set_ip_fields__(ip_stack_obj, src_ip, dst_ip, dscp_list):
if src_ip is not None:
src_ip_field = ip_stack_obj.find(DisplayName='Source Address')
src_ip_field.ValueType = 'singleValue'
src_ip_field.SingleValue = src_ip

if dst_ip is not None:
dst_ip_field = ip_stack_obj.find(DisplayName='Destination Address')
dst_ip_field.ValueType = 'singleValue'
dst_ip_field.SingleValue = dst_ip

if dscp_list is not None and len(dscp_list) > 0:
phb_field = ip_stack_obj.find(DisplayName='Default PHB')
phb_field.ActiveFieldChoice = True
phb_field.ValueType = 'valueList'
phb_field.ValueList = dscp_list


def __set_pfc_fields__(pfc_stack_obj, pause_prio_list):
code = pfc_stack_obj.find(DisplayName='Control opcode')
code.ValueType = 'singleValue'
code.SingleValue = '101'

prio_enable_vector = pfc_stack_obj.find(DisplayName='priority_enable_vector')
prio_enable_vector.ValueType = 'singleValue'

val = 0
for prio in pause_prio_list:
val += (1 << prio)
prio_enable_vector.SingleValue = hex(val)

for i in range(8):
pause_duration = pfc_stack_obj.find(DisplayName='PFC Queue {}'.format(i))
pause_duration.ValueType = 'singleValue'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove new line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the new line

if i in pause_prio_list:
pause_duration.SingleValue = 'ffff'
else:
pause_duration.SingleValue = '0'


def __create_pkt_hdr__(ixnetwork,
traffic_item,
pkt_hdr_to_add,
append_to_stack):
#Add new packet header in traffic item
config_element = traffic_item.ConfigElement.find()[0]

# Do the followings to add packet headers on the new traffic item

# Uncomment this to show a list of all the available protocol templates
# to create (packet headers)
#for protocolHeader in ixNetwork.Traffic.ProtocolTemplate.find():
# ixNetwork.info('Protocol header: -- {} --'.
# format(protocolHeader.DisplayName))

# 1> Get the <new packet header> protocol template from the ProtocolTemplate
# list.
pkt_hdr_proto_template = \
ixnetwork.Traffic.ProtocolTemplate.find(DisplayName=pkt_hdr_to_add)
#ixNetwork.info('protocolTemplate: {}'.format(packetHeaderProtocolTemplate))

# 2> Append the <new packet header> object after the specified packet
# header stack.
append_to_stack_obj = config_element.Stack.find(
DisplayName=append_to_stack
)
#ixNetwork.info('appendToStackObj: {}'.format(appendToStackObj))
append_to_stack_obj.Append(Arg2=pkt_hdr_proto_template)

# 3> Get the new packet header stack to use it for appending an
# IPv4 stack after it. Look for the packet header object and stack ID.
pkt_hdr_stack_obj = config_element.Stack.find(DisplayName=pkt_hdr_to_add)

# 4> In order to modify the fields, get the field object
pkt_hdr_field_obj = pkt_hdr_stack_obj.Field.find()
#ixNetwork.info('packetHeaderFieldObj: {}'.format(packetHeaderFieldObj))

# 5> Save the above configuration to the base config file.
# ixNetwork.SaveConfig(Files('baseConfig.ixncfg', local_file=True))
return pkt_hdr_field_obj

53 changes: 53 additions & 0 deletions tests/common/ixia/qos_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import pytest
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the convention followed is that all features reside in their own subdirectories under the tests folder and helper files go under subdir/files

so this code should get moved to probably tests/rdma/files/

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is implemented.

"""
RDMA test cases may require variety of traffic related fixtures. This file
is repository of all different kinds of traffic related fixtures. This
file currently holds the following fixture(s):
1. lossless_prio_dscp_map
"""
@pytest.fixture(scope = "module")
def lossless_prio_dscp_map(duthost):
"""
This fixture reads the QOS parameters from SONiC DUT, and creates
lossless priority Vs. DSCP priority port map (dictionary key = lossless
priority).

Args:
duthost (pytest fixture) : duthost

Returns:
Lossless priority vs. DSCP map (dictionary, key = lossless priority).
Example: {3: [3], 4: [4]}
"""
config_facts = duthost.config_facts(host=duthost.hostname,
source="persistent")['ansible_facts']

if "PORT_QOS_MAP" not in config_facts.keys():
return None

# Read the port QOS map. If pfc_enable flag is false then return None.
port_qos_map = config_facts["PORT_QOS_MAP"]
intf = port_qos_map.keys()[0]
if 'pfc_enable' not in port_qos_map[intf]:
return None

# lossless_priorities == list of priorities values for which frame loss
# should not happen
lossless_priorities = \
[int(x) for x in port_qos_map[intf]['pfc_enable'].split(',')]

dscp_to_tc_map = config_facts["DSCP_TO_TC_MAP"]

result = dict()
for prio in lossless_priorities:
result[prio] = list()

profile = dscp_to_tc_map.keys()[0]

for dscp in dscp_to_tc_map[profile]:
tc = dscp_to_tc_map[profile][dscp]

if int(tc) in lossless_priorities:
result[int(tc)].append(int(dscp))

return result
Loading