Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion DentOS_Framework/DentOsTestbed/Requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ pytest
pytest-asyncio
pytest-html
pytest-repeat
ixnetwork_restpy
ixnetwork_restpy>=1.1.10
pyvis == 0.1.9
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async def test_l1_settings_(testbed, l1_settings):
await asyncio.sleep(10)

try:
await tb_get_qualified_ports(dent_devices[0], tgen_dev.links_dict[device_host_name][1], speed, duplex, required_ports=1)
await tb_get_qualified_ports(dent_devices[0], [port], speed, duplex, required_ports=1)
except ValueError as e:
pytest.skip(str(e))

Expand Down Expand Up @@ -90,7 +90,7 @@ async def test_l1_settings_(testbed, l1_settings):
await tgen_utils_update_l1_config(tgen_dev, tg_port, speed=speed, autoneg=True, duplex=duplex)
except AssertionError as e:
pytest.skip(f'TGen does not support requested mode\n{e}')
await asyncio.sleep(20) # wait needed in case port was down before
await asyncio.sleep(40) # wait needed in case port was down before

out = await Ethtool.show(input_data=[{device_host_name: [{'devname': port}]}], parse_output=True)
assert out[0][device_host_name]['rc'] == 0, 'Failed getting port duplex, speed.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ async def test_ipv6_nh_state(testbed):
'type': 'raw',
'protocol': 'ipv6',
'ip_source': dev_groups[tg_ports[0]][0]['name'],
'rate': 10, # %
'rate': 5, # %
'frame_rate_type': 'line_rate',
'srcMac': '02:00:00:00:00:01',
'dstMac': dut_mac[tg_to_swp[tg_ports[0]]],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ async def test_lacp_ecmp_distribution_over_lag(testbed):
tgen_lag_2 = ('LAG_1', [tg_ports[1]])
tgen_lag_3 = ('LAG_2', tg_ports[2:])
rate = 10000
tolerance = 0.10

# 1. Enable IPv4 forwarding
# 2. Create 3 bonds
Expand Down Expand Up @@ -142,7 +143,7 @@ async def test_lacp_ecmp_distribution_over_lag(testbed):
if row['Port Name'] not in tgen_lag_3[1]:
continue
err_msg = f'Expected packets {row["Valid Frames Rx."]}, actual packets: {tx_packets / 4}'
assert isclose(int(row['Valid Frames Rx.']), tx_packets / 4, rel_tol=0.05), err_msg
assert isclose(int(row['Valid Frames Rx.']), tx_packets / 4, rel_tol=tolerance), err_msg
total_received = sum([int(row['Valid Frames Rx.']) for row in stats.Rows])
assert isclose(total_received, tx_packets, rel_tol=0.05),\
assert isclose(total_received, tx_packets, rel_tol=tolerance),\
f'Expected packets {total_received}, actual packets: {tx_packets}'
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dent_os_testbed.lib.ip.ip_link import IpLink
from dent_os_testbed.lib.mstpctl.mstpctl import Mstpctl
from dent_os_testbed.lib.ethtool.ethtool import Ethtool

from dent_os_testbed.utils.test_utils.tgen_utils import (tgen_utils_get_dent_devices_with_tgen,
tgen_utils_setup_streams, tgen_utils_start_traffic,
Expand Down Expand Up @@ -45,6 +46,7 @@ async def test_lacp_loopback_detection(testbed, version):
bonds[f'bond_{idx+1}'] = port
bridge = 'bridge_1'
wait_time = 40 if version == 'stp' else 20
expected_rate = 0.14 # multiplied by port speed

# 1. Create bridge entities and 6 bonds and set link up on them
out = await IpLink.add(input_data=[{dent: [{'device': bond,
Expand Down Expand Up @@ -123,6 +125,9 @@ async def test_lacp_loopback_detection(testbed, version):
await tgen_utils_stop_traffic(tgen_dev)

# 7. Verify device remain stable afterwards (during storming).
out = await Ethtool.show(input_data=[{dent: [{'devname': dut_ixia_ports[2]}]}], parse_output=True)
speed = int(out[0][dent]['parsed_output']['speed'][:-4])
expected_rate = int(expected_rate * speed)
rc, out = await device.run_cmd("echo 'Hello World'")
assert rc == 0, 'FAIL: DUT crashed due to storming'
assert out.strip() == 'Hello World', f'Expected <Hello World> got {out}'
Expand All @@ -131,8 +136,8 @@ async def test_lacp_loopback_detection(testbed, version):
# Verify there is storming
for row in stats.Rows:
if row['Port Name'] == tg_ports[0]:
err_msg = f'Expected 1400 got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > 1400, err_msg
err_msg = f'Expected {expected_rate} got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > expected_rate, err_msg

# 8. Set bridge stp_state to 1.
out = await IpLink.set(input_data=[{dent: [{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ async def test_lacp_routing_over_bridge(testbed):
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Traffic Item Statistics')
for row in stats.Rows:
err_msg = f"Expected 0.00 loss, actual {float(row['Loss %'])}"
assert tgen_utils_get_loss(row) == 0.000, err_msg
assert tgen_utils_get_loss(row) < 0.1, err_msg
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import asyncio
from math import isclose

import pytest

from dent_os_testbed.lib.ip.ip_link import IpLink
Expand Down Expand Up @@ -139,5 +141,5 @@ async def test_lacp_routing_over_lacp(testbed):
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Traffic Item Statistics')
for row in stats.Rows:
err_msg = f"Expected 0.00 loss, actual {float(row['Loss %'])}"
assert tgen_utils_get_loss(row) == 0.000, err_msg
assert isclose(tgen_utils_get_loss(row), 0.00, abs_tol=0.1), err_msg
await tgen_utils_stop_traffic(tgen_dev)
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import asyncio
from math import isclose

import pytest

from dent_os_testbed.lib.ip.ip_link import IpLink
Expand All @@ -12,9 +14,9 @@
tgen_utils_dev_groups_from_config,
tgen_utils_get_traffic_stats,
tgen_utils_setup_streams,
tgen_utils_get_loss,
tgen_utils_start_traffic,
tgen_utils_get_swp_info,
tgen_utils_get_loss,
)
pytestmark = [pytest.mark.suite_functional_lacp,
pytest.mark.asyncio,
Expand Down Expand Up @@ -167,4 +169,4 @@ async def test_lacp_routing_over_vlan_device(testbed):
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Traffic Item Statistics')
for row in stats.Rows:
err_msg = f"Expected 0.00 loss, actual {float(row['Loss %'])}"
assert tgen_utils_get_loss(row) == 0.000, err_msg
assert isclose(tgen_utils_get_loss(row), 0.00, abs_tol=0.1), err_msg
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dent_os_testbed.lib.ip.ip_link import IpLink
from dent_os_testbed.lib.mstpctl.mstpctl import Mstpctl
from dent_os_testbed.lib.ethtool.ethtool import Ethtool

from dent_os_testbed.utils.test_utils.tgen_utils import (tgen_utils_get_dent_devices_with_tgen,
tgen_utils_setup_streams, tgen_utils_start_traffic,
Expand All @@ -12,7 +13,7 @@
tgen_utils_traffic_generator_connect, )
pytestmark = [pytest.mark.suite_functional_lacp,
pytest.mark.asyncio,
pytest.mark.usefixtures('cleanup_tgen', 'cleanup_bonds', 'cleanup_bridges')]
pytest.mark.usefixtures('cleanup_tgen', 'cleanup_bonds', 'cleanup_bridges', 'enable_mstpd')]


@pytest.mark.parametrize('version', ['stp', 'rstp'])
Expand Down Expand Up @@ -60,6 +61,7 @@ async def test_lacp_traffic_during_topology_convergence(testbed, version):
bridge_names = list(bridges.keys())
tolerance = 0.15
wait_time = 40 if 'version' == 'stp' else 20
expected_rate = 0.14 # multiplied by port speed
# 1. Create 3 bridge entities and 6 bonds and set link up on them
out = await IpLink.add(input_data=[{dent: [{'device': bond,
'type': 'bond',
Expand Down Expand Up @@ -147,13 +149,17 @@ async def test_lacp_traffic_during_topology_convergence(testbed, version):
rc, out = await device.run_cmd("echo 'Hello World'")
assert rc == 0, 'FAIL: DUT crashed due to storming'
assert out.strip() == 'Hello World', f'Expected <Hello World> got {out}'
await asyncio.sleep(wait_time)

# 7. Verify there is a storming
out = await Ethtool.show(input_data=[{dent: [{'devname': dut_tgen_ports[2]}]}], parse_output=True)
speed = int(out[0][dent]['parsed_output']['speed'][:-4])
expected_rate = round(int(expected_rate * speed), 2)
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Port Statistics')
for row in stats.Rows:
if row['Port Name'] in tg_ports[:2]:
err_msg = 'Expected 1400 got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > 1400, err_msg
err_msg = f'Expected {int(expected_rate * speed)} got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > expected_rate, err_msg

# 8. Set bridge stp_state to 1.
out = await IpLink.set(input_data=[{dent: [{
Expand Down Expand Up @@ -228,8 +234,8 @@ async def test_lacp_traffic_during_topology_convergence(testbed, version):
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Port Statistics')
for row in stats.Rows:
if row['Port Name'] == tg_ports[1]:
err_msg = 'Expected 1400 got : {float(row["Rx. Rate (Mbps)"])}'
assert isclose(float(row['Rx. Rate (Mbps)']), 1400, rel_tol=tolerance), err_msg
err_msg = f'Expected 1400 got : {float(row["Rx. Rate (Mbps)"])}'
assert isclose(float(row['Rx. Rate (Mbps)']), expected_rate, rel_tol=tolerance), err_msg

# 16. Stop the traffic. Verify there is no storming
await tgen_utils_stop_traffic(tgen_dev)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from dent_os_testbed.lib.ip.ip_link import IpLink
from dent_os_testbed.lib.mstpctl.mstpctl import Mstpctl
from dent_os_testbed.lib.ethtool.ethtool import Ethtool

from dent_os_testbed.utils.test_utils.tgen_utils import (tgen_utils_get_dent_devices_with_tgen,
tgen_utils_setup_streams, tgen_utils_start_traffic,
Expand Down Expand Up @@ -45,6 +46,7 @@ async def test_stp_loopback_detection(testbed, version):
loopback_ports = {}
for idx, port in enumerate(device.links_dict[dent][0] + device.links_dict[dent][1]):
loopback_ports[f'loopback_{idx+1}'] = port
expected_rate = 0.14 # multiplied by port speed

# 1. Create bridge entity
out = await IpLink.add(input_data=[{dent: [{
Expand Down Expand Up @@ -114,12 +116,16 @@ async def test_stp_loopback_detection(testbed, version):
assert rc == 0, 'FAIL: DUT crashed due to storming'
assert out.strip() == 'Hello World', f'Expected <Hello World> got {out}'

out = await Ethtool.show(input_data=[{dent: [{'devname': dut_ixia_ports[2]}]}], parse_output=True)
speed = int(out[0][dent]['parsed_output']['speed'][:-4])
expected_rate = round(int(expected_rate * speed), 2)
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Port Statistics')

# Verify there is storming
for row in stats.Rows:
if row['Port Name'] == tg_ports[0]:
err_msg = f'Expected 1400 got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > 1400, err_msg
err_msg = f'Expected {int(expected_rate * speed)} got : {float(row["Rx. Rate (Mbps)"])}'
assert float(row['Rx. Rate (Mbps)']) > expected_rate, err_msg

# 8. Set bridge stp_state to 1.
out = await IpLink.set(input_data=[{dent: [{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ async def test_stp_switching_off_on(testbed, version):

# 7. Verify traffic is forwarded and port 2 doesn't receive any traffic
stats = await tgen_utils_get_traffic_stats(tgen_dev, 'Flow Statistics')
await asyncio.sleep(10)
for row in stats.Rows:
if row['Traffic Item'] == traffic and row['Rx Port'] == tg_ports[1]:
err_msg = f'Expected 0.0 got : {float(row["Rx Rate (Mbps)"])}'
Expand Down
1 change: 0 additions & 1 deletion DentOS_Framework/DentOsTestbedLib/Requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pyyaml
pykwalify
ixnetwork_restpy
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from dent_os_testbed.lib.traffic.ixnetwork.ixnetwork_ixia_client import IxnetworkIxiaClient
from ixnetwork_restpy.assistants.statistics.statviewassistant import StatViewAssistant as SVA
from ixnetwork_restpy import SessionAssistant, Files
from ixnetwork_restpy import SessionAssistant, Files, BatchAdd, BatchFind


class IxnetworkIxiaClientImpl(IxnetworkIxiaClient):
Expand Down Expand Up @@ -105,10 +105,20 @@ def run_connect(self, device, command, *argv, **kwarg):
swp_ports = param['swp_ports']
dev_groups = param['dev_groups']

# Batch Add all ixia ports to prevent 1 at a time restarting
with BatchAdd(IxnetworkIxiaClientImpl.ixnet):
for port in ixia_ports:
IxnetworkIxiaClientImpl.ixnet.Vport.add(Name=port, Location=port.replace(':', ';'))
# Batch Find to retrieve list of added port objects
with BatchFind(IxnetworkIxiaClientImpl.ixnet) as bf:
IxnetworkIxiaClientImpl.ixnet.Vport.find()
# Use Batch Find results to create name-addressable vport dict
vport_objects = {vport.Name: vport for vport in bf.results.vport}

vports = {}
for port, sport in zip(ixia_ports, swp_ports):
# Specify Location on Port Add to simplify assignment
vports[port] = (IxnetworkIxiaClientImpl.ixnet.Vport.add(Name=port, Location=port.replace(':', ';')), sport)
for port, swp_port in zip(ixia_ports, swp_ports):
# Vports dict uses port name to store vport object and swp port name
vports[port] = (vport_objects[port], swp_port)

device.applog.info('Assigning ports')
IxnetworkIxiaClientImpl.ixnet.AssignPorts(True)
Expand Down Expand Up @@ -762,7 +772,12 @@ def run_protocol(self, device, command, *argv, **kwarg):
if command == 'start_protocols':
device.applog.info('Starting All Protocols')
IxnetworkIxiaClientImpl.ixnet.StartAllProtocols(Arg1='sync')
time.sleep(15)
# Check that Protocols are Started and Up
protocolsSummary = SVA(IxnetworkIxiaClientImpl.ixnet, 'Protocols Summary')
device.applog.info('Waiting for Protocols for up to 20 seconds')
protocolsSummary.CheckCondition('Sessions Not Started', SVA.EQUAL, 0, Timeout=10, RaiseException=False)
protocolsSummary.CheckCondition('Sessions Down', SVA.EQUAL, 0, Timeout=10, RaiseException=False)

for ep in IxnetworkIxiaClientImpl.ip_eps:
device.applog.info('Sending ARP on ' + ep.Name)
ep.Start()
Expand Down
2 changes: 1 addition & 1 deletion DentOS_Framework/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM ubuntu:jammy
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=US/Pacific

RUN apt-get -o Acquire::Check-Valid-Until=false update
RUN apt-get update
RUN apt-get -y upgrade

# Are those packages used anywhere?
Expand Down
8 changes: 4 additions & 4 deletions DentOS_Framework/Dockerfile.dev
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ RUN pip3 install --no-cache-dir pdbpp==0.10.3
WORKDIR /DENT/DentOsTestbed

# Install each time DentOS Framework to use the latest changes from GIT
RUN printf "#!/bin/bash\nDENT_PACKAGES=(\"/DENT/DentOsTestbed\" \"/DENT/DentOsTestbedDiscovery\" \"/DENT/DentOsTestbedLib\")\n" > /entrypoint.sh
RUN printf "pip3 cache purge" >> /entrypoint.sh
RUN printf "[ -z $SKIP_INSTALL ] && for pkg in \${DENT_PACKAGES[@]}; do cd \$pkg; pip3 install --no-cache-dir --root-user-action=ignore .; done" >> /entrypoint.sh
RUN echo "#!/bin/bash\nDENT_PACKAGES=(\"/DENT/DentOsTestbed\" \"/DENT/DentOsTestbedDiscovery\" \"/DENT/DentOsTestbedLib\")\n" > /entrypoint.sh
RUN echo "pip3 cache purge" >> /entrypoint.sh
RUN echo "[ -z $SKIP_INSTALL ] && for pkg in \${DENT_PACKAGES[@]}; do cd \$pkg; pip3 install --no-cache-dir --root-user-action=ignore .; done" >> /entrypoint.sh
# `pip3 install --editable` does not work for the packages from above
RUN printf "cd /DENT/DentOsTestbed\n\$@\n" >> /entrypoint.sh
RUN echo "cd /DENT/DentOsTestbed\n\$@\n" >> /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
Expand Down
34 changes: 0 additions & 34 deletions DentOS_Framework/Dockerfile.testing

This file was deleted.

6 changes: 3 additions & 3 deletions DentOS_Framework/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ SCRIPT_DIR=$(dirname "$0")
DOCKERFILE_DIR=$SCRIPT_DIR

# Build base image
docker build -f "$DOCKERFILE_DIR"/Dockerfile -t dent-testing-base:latest .
docker build -f "$DOCKERFILE_DIR"/Dockerfile.base -t dent/test-framework-base:latest .

# Build working image
docker build -f "$DOCKERFILE_DIR"/Dockerfile.testing -t dent-testing:latest .
docker build -f "$DOCKERFILE_DIR"/Dockerfile.auto -t dent/test-framework-dev:latest .

if [ -n "$1" ]; then
COMMAND="$*"
Expand All @@ -23,5 +23,5 @@ docker run \
--mount=type=bind,target=/DENT/DentOsTestbedDiscovery,source="$PWD"/DentOsTestbedDiscovery \
--mount=type=bind,target=/DENT/DentOsTestbedLib,source="$PWD"/DentOsTestbedLib \
--name dent-testing-"$USER" \
dent-testing:latest \
dent/test-framework-dev:latest \
"$COMMAND"