Skip to content

Commit

Permalink
Merge pull request #498 from open-traffic-generator/uhd_fixes
Browse files Browse the repository at this point in the history
UHD Fixes
  • Loading branch information
ANISH-GOTTAPU authored Mar 14, 2022
2 parents ccb8aec + 3a2b1a2 commit a7115ec
Show file tree
Hide file tree
Showing 7 changed files with 308 additions and 9 deletions.
2 changes: 1 addition & 1 deletion do.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def test():
"--ext=ixnetwork",
"--speed=speed_100_gbps",
"tests",
'-m "not e2e and not l1_manual"',
'-m "not e2e and not l1_manual and not uhd"',
"--cov=./snappi_ixnetwork --cov-report term"
" --cov-report html:cov_report",
]
Expand Down
14 changes: 14 additions & 0 deletions snappi_ixnetwork/snappi_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,20 @@ def _validate_instance(self, config):
self._initial_flows_config = self.config().flows.deserialize(
config.flows.serialize(config.flows.DICT)
)

if "UHD" in self._ixnetwork.Globals.ProductVersion:
chassis_info = "localuhd"
for port in config.ports:
if port.location is None:
continue
if ";" in port.location:
(_, card, port_info) = port.location.split(";")
port_info = "{}.{}".format(card, port_info)
elif "/" in port.location:
(_, port_info) = port.location.split("/")
else:
raise SnappiIxnException(400, "port location is not valid")
port.location = chassis_info + "/" + port_info
return config

def _apply_change(self):
Expand Down
50 changes: 42 additions & 8 deletions snappi_ixnetwork/trafficitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,14 @@ class TrafficItem(CustomField):
"gTPuOptionalFields": "gtpv1option",
"custom": "custom",
"vxlan": "vxlan",
"ethernetARP": "arp"
"ethernetARP": "arp",
}

_HEADER_TO_TYPE = {
"ethernet": "ethernet",
"pfcpause": "pfcPause",
"ethernetpause": "ethernet",
"ethernetpauseUHD": "globalPause",
"vlan": "vlan",
"ipv4": "ipv4",
"ipv6": "ipv6",
Expand All @@ -72,7 +73,17 @@ class TrafficItem(CustomField):
"gtpv1option": "gTPuOptionalFields",
"custom": "custom",
"vxlan": "vxlan",
"arp": "ethernetARP"
"arp": "ethernetARP",
}

_ETHERNETPAUSEUHD = {
"dst": "globalPause.header.header.dstAddress",
"src": "globalPause.header.header.srcAddress",
"ether_type": "globalPause.header.header.ethertype",
"control_op_code": "globalPause.header.macControl.controlOpcode",
"time": "globalPause.header.macControl.pfcQueue0",
"order": ["dst", "src", "ether_type", "control_op_code", "time"],
"convert_int_to_hex": ["ether_type", "time"],
}

_BIT_RATE_UNITS_TYPE = {
Expand Down Expand Up @@ -167,7 +178,7 @@ class TrafficItem(CustomField):
"sender_hardware_addr",
"sender_protocol_addr",
"target_hardware_addr",
"target_protocol_addr"
"target_protocol_addr",
],
"convert_int_to_hex": [
"hardware_type",
Expand Down Expand Up @@ -622,7 +633,9 @@ def config_raw_stack(self, xpath, packet):
ce_path = "%s/configElement[1]" % xpath
config_elem = {"xpath": ce_path, "stack": []}
for i, header in enumerate(packet):
stack_name = self._HEADER_TO_TYPE.get(header.parent.choice)
stack_name = self._HEADER_TO_TYPE.get(
self._getUhdHeader(header.parent.choice)
)
header_xpath = "%s/stack[@alias = '%s-%d']" % (
ce_path,
stack_name,
Expand Down Expand Up @@ -800,6 +813,8 @@ def _configure_tracking(self, tr_item_json):
return {"tracking": tracking}

def _configure_options(self):
if self.isUhd is True:
return
enable_min_frame_size = False
for flow in self._config.flows:
if (
Expand Down Expand Up @@ -835,7 +850,9 @@ def _configure_packet(self, ixn_stack, snappi_packet):
else:
stack_names.append(choice)
for index, stack in enumerate(stack_names):
ixn_header_name = self._HEADER_TO_TYPE.get(stack)
ixn_header_name = self._HEADER_TO_TYPE.get(
self._getUhdHeader(stack)
)
if ixn_header_name is None:
msg = "%s ixia header is not mapped" % ixn_header_name
raise SnappiIxnException("400", msg)
Expand All @@ -859,8 +876,13 @@ def _append_header(
header_index=None,
is_raw_traffic=False,
):
field_map = getattr(self, "_%s" % snappi_header.parent.choice.upper())
stack_name = self._HEADER_TO_TYPE.get(snappi_header.parent.choice)
field_map = getattr(
self,
"_%s" % (self._getUhdHeader(snappi_header.parent.choice).upper()),
)
stack_name = self._HEADER_TO_TYPE.get(
self._getUhdHeader(snappi_header.parent.choice)
)
if stack_name is None:
raise NotImplementedError(
"%s stack is not implemented" % snappi_header.parent.choice
Expand Down Expand Up @@ -889,6 +911,15 @@ def _generate_fields(self, field_map, xpath):
fields.append({"xpath": "%s/field[@alias = '%s']" % (xpath, fmap)})
return fields

@property
def isUhd(self):
return "UHD" in self._api._ixnetwork.Globals.ProductVersion

def _getUhdHeader(self, header=None):
if self.isUhd is True and header == "ethernetpause":
return header + "UHD"
return header

def _configure_stack_fields(
self, ixn_fields, snappi_header, stacks, is_raw_traffic=False
):
Expand All @@ -897,7 +928,10 @@ def _configure_stack_fields(
f["xpath"].split(" = ")[-1].strip("']").split("-")[0]
for f in ixn_fields
]
field_map = getattr(self, "_%s" % snappi_header.parent.choice.upper())
field_map = getattr(
self,
"_%s" % (self._getUhdHeader(snappi_header.parent.choice).upper()),
)
for field in snappi_header._TYPES:
format_type = None
try:
Expand Down
1 change: 1 addition & 0 deletions tests/pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ addopts = -s -v
markers =
e2e: marks tests as e2e since they're slower (deselect with '-m "not e2e"')
l1_manual: marks test as layer1 manual which needs to be run separately for specific Novus card
uhd: runs only uhd tests
serial
filterwarnings =
ignore::urllib3.exceptions.InsecureRequestWarning
Expand Down
48 changes: 48 additions & 0 deletions tests/uhd/test_uhd_global_pause.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import pytest


@pytest.mark.uhd
def test_uhd_global_pause(api, b2b_raw_config_vports, utils):
"""
Configure Ethernet Pause flow and validate the snappi
config is applied in UHD
"""
# fixed
flow1 = b2b_raw_config_vports.flows[0]
eth = flow1.packet.ethernetpause()[-1]
eth.dst.value = "01:80:c2:00:00:01"
eth.src.value = "00:AB:BC:AB:BC:AB"
eth.control_op_code.value = 1
eth.time.value = 65535
api.set_config(b2b_raw_config_vports)

attrs = {
"Destination address": "01:80:c2:00:00:01",
"Source address": "00:ab:bc:ab:bc:ab",
"Ethertype": "8808",
"Control opcode": "1",
"PAUSE Quanta": "ffff",
}
utils.validate_config(api, "f1", 0, **attrs)

eth.dst.increment.start = "01:80:c2:00:00:01"
eth.dst.increment.step = "00:00:00:01:00:00"
eth.dst.increment.count = 10
eth.src.increment.start = "00:AB:BC:AB:BC:AB"
eth.src.increment.step = "00:00:00:01:00:00"
eth.src.increment.count = 10

api.set_config(b2b_raw_config_vports)

attrs = {
"Destination address": (
"01:80:c2:00:00:01",
"00:00:00:01:00:00",
"10",
),
"Source address": ("00:ab:bc:ab:bc:ab", "00:00:00:01:00:00", "10"),
"Ethertype": "8808",
"Control opcode": "1",
"PAUSE Quanta": "ffff",
}
utils.validate_config(api, "f1", 0, **attrs)
146 changes: 146 additions & 0 deletions tests/uhd/test_uhd_mock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import snappi
from mock import MagicMock
from snappi_ixnetwork.snappi_api import Api as ixn_api
from snappi_ixnetwork.trafficitem import TrafficItem


def test_uhd_port_locations():
api = ixn_api()
api._ixnetwork = lambda x: None
api._ixnetwork.Globals = lambda y: None
api._ixnetwork.Globals.ProductVersion = "UHD"
api._traffic = lambda z: None
api._traffic.State = "Stopped"
config = snappi.Api().config()
api._config = config
port = config.ports.port(location="a;b;c", name="p1").port(
location="localuhd/a", name="p2"
)
api._validate_instance(config)
assert port[0].location == "localuhd/b.c"
assert port[1].location == "localuhd/a"


expected_global = {
"xpath": "/traffic",
"trafficItem": [
{
"xpath": "/traffic/trafficItem[1]",
"name": "f1",
"srcDestMesh": "oneToOne",
"endpointSet": [
{
"xpath": "/traffic/trafficItem[1]/endpointSet[1]",
"sources": ["/vport[1]/protocols"],
"destinations": ["/vport[2]/protocols"],
}
],
"trafficType": "raw",
"configElement": [
{
"xpath": "/traffic/trafficItem[1]/configElement[1]",
"stack": [
{
"xpath": "/traffic/trafficItem[1]/configElement[1]"
"/stack[@alias = 'globalPause-1']",
"field": [
{
"xpath": "/traffic/trafficItem[1]/config"
"Element[1]/stack[@alias = 'globalPause-1'"
"]/field[@alias = 'globalPause.header."
"header.dstAddress-1']",
"valueType": "singleValue",
"singleValue": "01:80:c2:00:00:01",
"activeFieldChoice": False,
"auto": False,
},
{
"xpath": "/traffic/trafficItem[1]/config"
"Element[1]/stack[@alias = 'globalPause-1']"
"/field[@alias = 'globalPause.header."
"header.srcAddress-2']",
"valueType": "singleValue",
"singleValue": "00:00:00:00:00:00",
"activeFieldChoice": False,
"auto": False,
},
{
"xpath": "/traffic/trafficItem[1]/config"
"Element[1]/stack[@alias = 'globalPause-1'"
"]/field[@alias = 'globalPause.header."
"header.ethertype-3']",
"valueType": "singleValue",
"singleValue": "8808",
"activeFieldChoice": False,
"auto": False,
},
{
"xpath": "/traffic/trafficItem[1]/config"
"Element[1]/stack[@alias = 'globalPause-1"
"']/field[@alias = 'globalPause.header."
"macControl.controlOpcode-4']",
"valueType": "singleValue",
"singleValue": 1,
"activeFieldChoice": False,
"auto": False,
},
{
"xpath": "/traffic/trafficItem[1]/config"
"Element[1]/stack[@alias = 'globalPause-1'"
"]/field[@alias = 'globalPause.header."
"macControl.pfcQueue0-5']",
"valueType": "singleValue",
"singleValue": "0",
"activeFieldChoice": False,
"auto": False,
},
],
}
],
}
],
}
],
}


def test_global_pause_header():
config = snappi.Api().config()
api = ixn_api()
api._ixnetwork = lambda x: None
api._ixnetwork.Globals = lambda y: None
api._ixnetwork.Globals.ProductVersion = "UHD"
tr_obj = TrafficItem(api)
ports = {"p1": "/vport[1]", "p2": "/vport[2]"}
tr_obj.get_ports_encap = MagicMock(return_value=ports)
tr_obj.get_device_encap = MagicMock(return_value={})
f1 = config.flows.flow(name="f1")[-1]
f1.tx_rx.port.tx_name = "p1"
f1.tx_rx.port.rx_name = "p2"
f1.packet.ethernetpause()
tr_obj.copy_flow_packet(config)
tr_raw = tr_obj.create_traffic(config)
assert tr_raw == expected_global


def test_enable_min_frame_size():
config = snappi.Api().config()
api = ixn_api()
tr_obj = TrafficItem(api)
api._ixnetwork = lambda x: None
api._ixnetwork.Globals = lambda y: None
api._ixnetwork.Globals.ProductVersion = "ABC"
api._traffic = lambda x: None
api._traffic.EnableMinFrameSize = False
f1 = config.flows.flow()[-1]
f1.name = "flow1"
f1.packet.pfcpause()
tr_obj._config = config

tr_obj._configure_options()
assert api._traffic.EnableMinFrameSize is True
api._ixnetwork.Globals.ProductVersion = "UHD"

api._traffic.EnableMinFrameSize = False
tr_obj._configure_options()
assert api._traffic.EnableMinFrameSize is False
Loading

0 comments on commit a7115ec

Please sign in to comment.