Skip to content

Commit

Permalink
Add Bridging tests
Browse files Browse the repository at this point in the history
Signed-off-by: Kostiantyn Stavruk <kostiantyn.stavruk@plvision.eu>
  • Loading branch information
stavrukPLV committed Feb 9, 2023
1 parent 5d2c87a commit fd65da5
Show file tree
Hide file tree
Showing 5 changed files with 692 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import pytest
import asyncio

from dent_os_testbed.lib.bridge.bridge_fdb import BridgeFdb
from dent_os_testbed.lib.bridge.bridge_link import BridgeLink
from dent_os_testbed.lib.ip.ip_link import IpLink

from dent_os_testbed.utils.test_utils.tgen_utils import (
tgen_utils_get_dent_devices_with_tgen,
tgen_utils_get_traffic_stats,
tgen_utils_setup_streams,
tgen_utils_start_traffic,
tgen_utils_stop_traffic,
tgen_utils_dev_groups_from_config,
tgen_utils_traffic_generator_connect,
tgen_utils_get_loss
)

pytestmark = [
pytest.mark.suite_functional_bridging,
pytest.mark.asyncio,
pytest.mark.usefixtures("cleanup_bridges", "cleanup_tgen")
]

async def test_bridging_backward_forwarding(testbed):
"""
Test Name: test_bridging_backward_forwarding
Test Suite: suite_functional_bridging
Test Overview: Verify that traffic with learned source mac is not being backward forwarding
to the transmitting port which the address has been learned for.
Test Author: Kostiantyn Stavruk
Test Procedure:
1. Init bridge entity br0.
2. Set ports swp1, swp2, swp3, swp4 master br0.
3. Set bridge br0 admin state UP.
4. Set entities swp1, swp2, swp3, swp4 UP state.
5. Set ports swp1, swp2, swp3, swp4 learning ON.
6. Set ports swp1, swp2, swp3, swp4 flood OFF.
7. Traffic streamA sending to swp1 with source mac aa:bb:cc:dd:ee:11 and
destination mac ff:ff:ff:ff:ff:ff for swp1 to learn source address.
8. Traffic streamB sending to swp1 with source mac aa:bb:cc:dd:ee:12 and
destination mac aa:bb:cc:dd:ee:11.
9. Verify that there was no backward forwarding to swp1 from streamA.
10. Verify that source mac aa:bb:cc:dd:ee:11 have been learned on swp1 from streamA.
11. Verify that there was no backward forwarding back to swp1 from streamB.
"""

bridge = "br0"
tgen_dev, dent_devices = await tgen_utils_get_dent_devices_with_tgen(testbed, [], 2)
if not tgen_dev or not dent_devices:
print("The testbed does not have enough dent with tgen connections")
return
dent_dev = dent_devices[0]
device_host_name = dent_dev.host_name
tg_ports = tgen_dev.links_dict[device_host_name][0]
ports = tgen_dev.links_dict[device_host_name][1]
traffic_duration = 5

out = await IpLink.add(
input_data=[{device_host_name: [
{"device": bridge, "type": "bridge"}]}])
assert out[0][device_host_name]["rc"] == 0, f"Verify that bridge created.\n{out}"

out = await IpLink.set(
input_data=[{device_host_name: [
{"device": bridge, "operstate": "up"}]}])
assert out[0][device_host_name]["rc"] == 0, f"Verify that bridge set to 'UP' state.\n{out}"

out = await IpLink.set(
input_data=[{device_host_name: [
{"device": port, "master": bridge, "operstate": "up"} for port in ports]}])
err_msg = f"Verify that bridge entities set to 'UP' state and links enslaved to bridge.\n{out}"
assert out[0][device_host_name]["rc"] == 0, err_msg

out = await BridgeLink.set(
input_data=[{device_host_name: [
{"device": port, "learning": True, "flood": False} for port in ports]}])
err_msg = f"Verify that entities set to learning 'ON' and flooding 'OFF' state.\n{out}"
assert out[0][device_host_name]["rc"] == 0, err_msg

address_map = (
# swp port, tg port, tg ip, gw, plen
(ports[0], tg_ports[0], "1.1.1.2", "1.1.1.1", 24),
(ports[0], tg_ports[0], "1.1.1.3", "1.1.1.1", 24),
)

dev_groups = tgen_utils_dev_groups_from_config(
{"ixp": port, "ip": ip, "gw": gw, "plen": plen}
for _, port, ip, gw, plen in address_map
)

await tgen_utils_traffic_generator_connect(tgen_dev, tg_ports, ports, dev_groups)

streams = {
"streamA": {
"ip_source": dev_groups[tg_ports[0]][0]["name"],
"ip_destination": dev_groups[tg_ports[0]][1]["name"],
"srcMac": "aa:bb:cc:dd:ee:11",
"dstMac": "ff:ff:ff:ff:ff:ff",
"type": "raw",
"protocol": "802.1Q",
},
"streamB": {
"ip_source": dev_groups[tg_ports[0]][0]["name"],
"ip_destination": dev_groups[tg_ports[0]][1]["name"],
"srcMac": "aa:bb:cc:dd:ee:12",
"dstMac": "aa:bb:cc:dd:ee:11",
"type": "raw",
"protocol": "802.1Q",
},
}

await tgen_utils_setup_streams(tgen_dev, config_file_name=None, streams=streams)

await tgen_utils_start_traffic(tgen_dev)
await asyncio.sleep(traffic_duration)
await tgen_utils_stop_traffic(tgen_dev)

# check the traffic stats
stats = await tgen_utils_get_traffic_stats(tgen_dev, "Traffic Item Statistics")
for row in stats.Rows:
assert tgen_utils_get_loss(row) == 100.000, \
f"Verify that traffic from {row['Tx Port']} to {row['Rx Port']} not forwarded.\n{out}"

out = await BridgeFdb.show(input_data=[{device_host_name: [{"options": "-j"}]}],
parse_output=True)
assert out[0][device_host_name]["rc"] == 0, "Failed to get fdb entry.\n"

fdb_entries = out[0][device_host_name]["parsed_output"]
learned_macs = [en["mac"] for en in fdb_entries if "mac" in en]
list_macs = ["aa:bb:cc:dd:ee:11", "aa:bb:cc:dd:ee:12"]
for mac in list_macs:
err_msg = f"Expected MACs are not found in FDB, but found MACs:{out}\n"
assert mac in learned_macs, err_msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import pytest
import asyncio

from dent_os_testbed.lib.bridge.bridge_link import BridgeLink
from dent_os_testbed.lib.ip.ip_link import IpLink

from dent_os_testbed.utils.test_utils.tgen_utils import (
tgen_utils_get_dent_devices_with_tgen,
tgen_utils_get_traffic_stats,
tgen_utils_setup_streams,
tgen_utils_start_traffic,
tgen_utils_stop_traffic,
tgen_utils_dev_groups_from_config,
tgen_utils_traffic_generator_connect,
tgen_utils_get_loss
)

pytestmark = [
pytest.mark.suite_functional_bridging,
pytest.mark.asyncio,
pytest.mark.usefixtures("cleanup_bridges", "cleanup_tgen")
]

async def test_bridging_mac_table_size(testbed):
"""
Test Name: test_bridging_mac_table_size
Test Suite: suite_functional_bridging
Test Overview: Verify amount of extern_learn offload entities in the mac table.
Test Author: Kostiantyn Stavruk
Test Procedure:
1. Init bridge entity br0.
2. Set ports swp1, swp2, swp3, swp4 master br0.
3. Set bridge br0 admin state UP.
4. Set entities swp1, swp2, swp3, swp4 UP state.
5. Set ports swp1, swp2, swp3, swp4 learning ON.
6. Send traffic for filling bridge address table.
7. Verify amount of extern_learn offload entities.
"""

bridge = "br0"
tgen_dev, dent_devices = await tgen_utils_get_dent_devices_with_tgen(testbed, [], 2)
if not tgen_dev or not dent_devices:
print("The testbed does not have enough dent with tgen connections")
return
dent_dev = dent_devices[0]
device_host_name = dent_dev.host_name
tg_ports = tgen_dev.links_dict[device_host_name][0]
ports = tgen_dev.links_dict[device_host_name][1]
traffic_duration = 10
ixia_vhost_mac_count = 2
pps_value = 4000

out = await IpLink.add(
input_data=[{device_host_name: [
{"device": bridge, "type": "bridge"}]}])
assert out[0][device_host_name]["rc"] == 0, f"Verify that bridge created.\n{out}"

out = await IpLink.set(
input_data=[{device_host_name: [
{"device": bridge, "operstate": "up"}]}])
assert out[0][device_host_name]["rc"] == 0, f"Verify that bridge set to 'UP' state.\n{out}"

out = await IpLink.set(
input_data=[{device_host_name: [
{"device": port, "master": bridge, "operstate": "up"} for port in ports]}])
err_msg = f"Verify that bridge entities set to 'UP' state and links enslaved to bridge.\n{out}"
assert out[0][device_host_name]["rc"] == 0, err_msg

out = await BridgeLink.set(
input_data=[{device_host_name: [
{"device": port, "learning": True} for port in ports]}])
err_msg = f"Verify that entities set to learning 'ON' state.\n{out}"
assert out[0][device_host_name]["rc"] == 0, err_msg

address_map = (
# swp port, tg port, tg ip, gw, plen
(ports[0], tg_ports[0], "1.1.1.2", "1.1.1.1", 24),
(ports[1], tg_ports[1], "1.1.1.3", "1.1.1.1", 24),
)

dev_groups = tgen_utils_dev_groups_from_config(
{"ixp": port, "ip": ip, "gw": gw, "plen": plen}
for _, port, ip, gw, plen in address_map
)

await tgen_utils_traffic_generator_connect(tgen_dev, tg_ports, ports, dev_groups)

streams = {
"streamA": {
"ip_source": dev_groups[tg_ports[0]][0]["name"],
"ip_destination": dev_groups[tg_ports[1]][0]["name"],
"srcMac": {"type": "increment",
"start": "00:00:00:00:00:35",
"step": "00:00:00:00:10:00",
"count": pps_value},
"dstMac": "aa:bb:cc:dd:ee:11",
"type": "raw",
"protocol": "802.1Q",
"rate": "1000",
}
}

await tgen_utils_setup_streams(tgen_dev, config_file_name=None, streams=streams)

await tgen_utils_start_traffic(tgen_dev)
await asyncio.sleep(traffic_duration)
await tgen_utils_stop_traffic(tgen_dev)

#check the traffic stats
stats = await tgen_utils_get_traffic_stats(tgen_dev, "Traffic Item Statistics")
for row in stats.Rows:
loss = tgen_utils_get_loss(row)
assert loss == 0, f"Expected loss: 0%, actual: {loss}%"

rc, out = await dent_dev.run_cmd("bridge fdb show br br0 | grep 'extern_learn.*offload' | wc -l")
assert rc == 0, f"Failed to grep 'extern_learn.*offload'.\n"

amount = int(out) - ixia_vhost_mac_count
err_msg = f"Expected count of extern_learn offload entities: 4000, Actual count: {amount}"
assert amount == pps_value, err_msg
Loading

0 comments on commit fd65da5

Please sign in to comment.