Skip to content
Merged
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
88 changes: 85 additions & 3 deletions tests/sub_port_interfaces/Sub-ports-test-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
- [test_mtu_inherited_from_parent_port](#Test-case-test_mtu_inherited_from_parent_port)
- [test_vlan_config_impact](#Test-case-test_vlan_config_impact)
- [test_routing_between_sub_ports](#Test-case-test_routing_between_sub_ports)
- [test_routing_between_sub_ports_and_port](#Test-case-test_routing_between_sub_ports_and_port)

## Revision

Expand All @@ -23,6 +24,7 @@
| 0.1 | 11/30/2020 | Intel: Oleksandr Kozodoi | Initial version |
| 0.2 | 02/23/2021 | Intel: Oleksandr Kozodoi | New test cases |
| 0.3 | 03/18/2021 | Intel: Oleksandr Kozodoi | New test cases |
| 0.4 | 06/09/2021 | Intel: Oleksandr Kozodoi | New test cases |


## Overview
Expand Down Expand Up @@ -328,9 +330,89 @@ Example the customized testbed with applied T0 topo for test_routing_between_sub
- Setup configuration of sub-ports on the PTF.
- Add one of the sub-ports to namespace on the PTF.
- Setup static routes between sub-port and sub-port in namespace on the PTF
- Create ICMP packet.
- Send ICMP request packet from sub-port to sub-port in namespace on the PTF.
- Verify that sub-port in namespace sends ICMP reply packet to sub-port on the PTF.
- Create packet (TCP, UDP or ICMP).
- Send packet from sub-port to sub-port in namespace on the PTF.
- Verify that sub-port gets received packet on the PTF.
- Remove static routes from PTF
- Remove namespaces from PTF
- Clear configuration of sub-ports on the DUT.
- Clear configuration of sub-ports on the PTF.

### Test teardown

- reload_dut_config function: reload DUT configuration
- reload_ptf_config function: remove all sub-ports configuration

## Test case test_routing_between_sub_ports_and_port

### Test objective

Validates that packets are routed between sub-ports and ports

### Test set up
- apply_config_on_the_dut fixture(scope="function"): enable and configures sub-port interfaces on the DUT
- apply_config_on_the_ptf fixture(scope="function"): enable and configures sub-port interfaces on the PTF
- apply_route_config_for_port fixture(scope="function"): setup static routes between sub-ports and ports on the PTF

Example the customized testbed with applied T0 topo for test_routing_between_sub_ports_and_port test case:
##### Routing between sub-port and L3 RIF
```
VM VM VM VM
[] [] [] []
_______[]____[]____[]____[]______
╔═══|══════════════════════╗ |
║ | _________ DUT _║_______ |
║ | [Ethernet4] [Ethernet8] |
║ |__[_________]_______[_.10_.20_]__|
║ [ ] [ ║| | ]
║ [ ] [ ║| | ]
║ [ ] ┌────[─║|─┐ | ]
║ __[_________]__│____[_V|_│_|__]__
║ | [ ] │ [.10 │.20 ] |
╚═══|═>[__eth1___] │ [__eth2___] |
| │ │ |
| │ netns8 │ |
| └─────────┘ |
| |
| PTF |
|_________________________________|

```
##### Routing between sub-ports and SVI
```
VM VM VM VM
[] [] [] []
_______[]____[]____[]____[]______
╔═══|══════════════════════╗ |
║ |─────────────┐ DUT ║ |
║ | Vlan999 │ ║ |
║ | _________ │ _║_______ |
║ | [Ethernet4]│ [Ethernet8] |
║ |__[_________]│______[_.10_.20_]__|
║ [ ] [ ║| | ]
║ [ ] [ ║| | ]
║ [ ] ┌────[─║|─┐ | ]
║ __[_________]__│____[_V|_│_|__]__
║ | [ ] │ [.10 │.20 ] |
╚═══|═>[eth1.999_] │ [__eth2___] |
| │ │ |
| │ netns8 │ |
| └─────────┘ |
| |
| PTF |
|_________________________________|

```
### Test steps
- Setup configuration of sub-ports on the DUT.
- Setup configuration of sub-ports on the PTF.
- Setup L3 RIF or SVI on the DUT.
- Setup neighbor port for L3 RIF or SVI on the PTF.
- Add one of the sub-ports to namespace on the PTF.
- Setup static routes between port and sub-port in namespace on the PTF
- Create packet (TCP, UDP or ICMP).
- Send packet from sub-port to sub-port in namespace on the PTF.
- Verify that sub-port gets received packet on the PTF.
- Remove static routes from PTF
- Remove namespaces from PTF
- Clear configuration of sub-ports on the DUT.
Expand Down
162 changes: 145 additions & 17 deletions tests/sub_port_interfaces/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import time
import random
import jinja2

import pytest

from tests.common import config_reload
Expand All @@ -22,6 +21,16 @@
from sub_ports_helpers import remove_namespace
from sub_ports_helpers import remove_static_route
from sub_ports_helpers import get_ptf_port_list
from sub_ports_helpers import remove_ip_from_port
from sub_ports_helpers import add_ip_to_dut_port
from sub_ports_helpers import add_ip_to_ptf_port
from sub_ports_helpers import remove_ip_from_ptf_port
from sub_ports_helpers import create_sub_port_on_ptf
from sub_ports_helpers import setup_vlan
from sub_ports_helpers import remove_vlan
from sub_ports_helpers import add_member_to_vlan
from sub_ports_helpers import remove_sub_port_from_ptf
from sub_ports_helpers import remove_bond_port


def pytest_addoption(parser):
Expand Down Expand Up @@ -87,11 +96,11 @@ def define_sub_ports_configuration(request, duthost, ptfhost, ptfadapter):
interface_num = 2
ip_subnet = u'172.16.0.0/16'
prefix = 30
subnet = ipaddress.ip_network(ip_subnet)
network = ipaddress.ip_network(ip_subnet)

config_port_indices, ptf_ports = get_port(duthost, ptfhost, interface_num, request.param)

subnets = [i for i, _ in zip(subnet.subnets(new_prefix=22), config_port_indices)]
subnets = [i for i, _ in zip(network.subnets(new_prefix=22), config_port_indices)]

for port, ptf_port, subnet in zip(config_port_indices.values(), ptf_ports, subnets):
for vlan_id_dut, vlan_id_ptf, net in zip(vlan_ranges_dut, vlan_ranges_ptf, subnet.subnets(new_prefix=30)):
Expand All @@ -105,7 +114,10 @@ def define_sub_ports_configuration(request, duthost, ptfhost, ptfadapter):
yield {
'sub_ports': sub_ports_config,
'dut_ports': config_port_indices,
'ptf_ports': ptf_ports
'ptf_ports': ptf_ports,
'subnet': network,
'interface_ranges': config_port_indices.keys(),
'port_type': request.param
}


Expand Down Expand Up @@ -157,22 +169,20 @@ def apply_config_on_the_ptf(define_sub_ports_configuration, ptfhost, reload_ptf_
sub_ports = define_sub_ports_configuration['sub_ports']

for sub_port_info in sub_ports.values():
port, vlan = sub_port_info['neighbor_port'].split(".")
ptfhost.shell("ip link add link {} name {} type vlan id {}".format(port, sub_port_info['neighbor_port'], vlan))
ptfhost.shell("ip address add {} dev {}".format(sub_port_info['neighbor_ip'], sub_port_info['neighbor_port']))
ptfhost.shell("ip link set {} up".format(sub_port_info['neighbor_port']))
create_sub_port_on_ptf(ptfhost, sub_port_info['neighbor_port'], sub_port_info['neighbor_ip'])


@pytest.fixture(params=['same', 'different'])
def apply_route_config(request, define_sub_ports_configuration, apply_config_on_the_dut, apply_config_on_the_ptf, ptfhost):
def apply_route_config(request, ptfhost, define_sub_ports_configuration, apply_config_on_the_dut, apply_config_on_the_ptf):
"""
Apply route configuration on the PTF and remove after tests

Args:
request: pytest request object
ptfhost: PTF host object
define_sub_ports_configuration: Dictonary of parameters for configuration DUT
apply_config_on_the_dut: fixture for applying sub-ports configuration on the DUT
apply_config_on_the_ptf: fixture for applying sub-ports configuration on the PTF
ptfhost: PTF host object

Yields:
Dictonary of parameters for configuration DUT and PTF host
Expand Down Expand Up @@ -227,6 +237,129 @@ def apply_route_config(request, define_sub_ports_configuration, apply_config_on_
remove_namespace(ptfhost, name_of_namespace)


@pytest.fixture(params=['svi', 'l3'])
def apply_route_config_for_port(request, duthost, ptfhost, define_sub_ports_configuration, apply_config_on_the_dut, apply_config_on_the_ptf):
"""
Apply route configuration on the PTF and remove after tests

Args:
request: pytest request object
duthost: DUT host object
ptfhost: PTF host object
define_sub_ports_configuration: Dictonary of parameters for configuration DUT
apply_config_on_the_dut: fixture for applying sub-ports configuration on the DUT
apply_config_on_the_ptf: fixture for applying sub-ports configuration on the PTF

Yields:
Dictonary of parameters for configuration DUT and PTF host
"""
port_map = {}
vlan_id = 999

sub_ports = define_sub_ports_configuration['sub_ports']
dut_ports = define_sub_ports_configuration['dut_ports']
ptf_ports = define_sub_ports_configuration['ptf_ports']
port_type = define_sub_ports_configuration['port_type']
subnet = define_sub_ports_configuration['subnet']

# Get additional port for configuration of SVI port
if 'svi' in request.param:
dut_ports, ptf_ports = get_port(duthost, ptfhost, 1, port_type, dut_ports.values())

# Get additional IP addresses for configuration of RIF on the DUT and PTF
subnet = ipaddress.ip_network(str(subnet.broadcast_address + 1) + u'/24')
subnets = [i for i, _ in zip(subnet.subnets(new_prefix=30), dut_ports)]

sub_ports_keys = sub_ports.copy()

for dut_port, ptf_port, subnet in zip(dut_ports.values(), ptf_ports, subnets):
dut_port_ip, ptf_port_ip = ('{}/{}'.format(host, 30) for host in subnet.hosts())
remove_ip_from_port(duthost, dut_port)

if 'svi' in request.param:
# Configure SVI port on the DUT
ptf_port = '{}.{}'.format(ptf_port, vlan_id)
remove_member_from_vlan(duthost, vlan_id, dut_port)
setup_vlan(duthost, vlan_id)
add_member_to_vlan(duthost, vlan_id, dut_port)
add_ip_to_dut_port(duthost, 'Vlan{}'.format(vlan_id), dut_port_ip)
# Configure additional sub-port for connection between SVI port of the DUT and PTF
create_sub_port_on_ptf(ptfhost, ptf_port, ptf_port_ip)
else:
# Configure L3 RIF on the DUT
add_ip_to_dut_port(duthost, dut_port, dut_port_ip)
# Configure L3 RIF on the PTF
add_ip_to_ptf_port(ptfhost, ptf_port, ptf_port_ip)

# Get two random sub-ports which are not part of the selected DUT interface
sub_ports_on_port = random.sample([sub_port for sub_port in sub_ports_keys if dut_port + '.' not in sub_port], 2)

for sub_port in sub_ports_on_port:
sub_ports_keys.pop(sub_port)

port_map[ptf_port] = {'dut_port': dut_port,
'ip': ptf_port_ip,
'neighbor_ip': dut_port_ip,
'dst_ports': []
}

# Configure static route between selected sub-ports and selected interfaces on the PTF
for next_hop_sub_port in sub_ports_on_port:
name_of_namespace = 'vnet_for_{}'.format(next_hop_sub_port)
dst_port_network = ipaddress.ip_network(unicode(sub_ports[next_hop_sub_port]['neighbor_ip']), strict=False)

# Add selected sub-port to namespace on the PTF
add_port_to_namespace(ptfhost,
name_of_namespace,
sub_ports[next_hop_sub_port]['neighbor_port'],
sub_ports[next_hop_sub_port]['neighbor_ip'])

# Add static route from sub-port to selected interface on the PTF
add_static_route(ptfhost, subnet, sub_ports[next_hop_sub_port]['ip'], name_of_namespace)
# Add static route from selected interface to sub-port on the PTF
add_static_route(ptfhost, dst_port_network, dut_port_ip)

port_map[ptf_port]['dst_ports'].append((next_hop_sub_port, name_of_namespace))

yield {
'port_map': port_map,
'sub_ports': sub_ports
}

# Teardown
for src_port, next_hop_sub_ports in port_map.items():
src_port_network = ipaddress.ip_network(unicode(next_hop_sub_ports['ip']), strict=False)

# Remove static route between selected sub-ports and selected interfaces from the PTF
for sub_port, name_of_namespace in next_hop_sub_ports['dst_ports']:
dst_port_network = ipaddress.ip_network(unicode(sub_ports[sub_port]['ip']), strict=False)
remove_static_route(ptfhost, src_port_network, sub_ports[sub_port]['ip'], name_of_namespace)
remove_static_route(ptfhost, dst_port_network, next_hop_sub_ports['neighbor_ip'])
remove_namespace(ptfhost, name_of_namespace)


if 'svi' in request.param:
# Remove SVI port from the DUT
remove_member_from_vlan(duthost, vlan_id, next_hop_sub_ports['dut_port'])
remove_ip_from_port(duthost, 'Vlan{}'.format(vlan_id), ip=next_hop_sub_ports['neighbor_ip'])
# Remove additional sub-port from the PTF
remove_sub_port_from_ptf(ptfhost, src_port, next_hop_sub_ports['ip'])

if 'port_in_lag' in port_type:
bond_port = src_port.split('.')[0]
cfg_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts']
remove_lag_port(duthost, cfg_facts, next_hop_sub_ports['dut_port'])
remove_bond_port(ptfhost, bond_port, ptf_ports[bond_port])
else:
# Remove L3 RIF from the DUT
remove_ip_from_port(duthost, next_hop_sub_ports['dut_port'], ip=next_hop_sub_ports['neighbor_ip'])
# Remove L3 RIF from the PTF
remove_ip_from_ptf_port(ptfhost, src_port, next_hop_sub_ports['ip'])

if 'svi' in request.param:
remove_vlan(duthost, vlan_id)


@pytest.fixture
def reload_dut_config(request, duthost, define_sub_ports_configuration):
"""
Expand Down Expand Up @@ -265,23 +398,18 @@ def reload_ptf_config(request, ptfhost, define_sub_ports_configuration):
define_sub_ports_configuration: Dictonary of parameters for configuration DUT
"""
yield

sub_ports = define_sub_ports_configuration['sub_ports']
ptf_port_list = get_ptf_port_list(ptfhost)

for sub_port_info in sub_ports.values():
if sub_port_info['neighbor_port'] in ptf_port_list:
ptfhost.shell("ip address del {} dev {}".format(sub_port_info['neighbor_ip'], sub_port_info['neighbor_port']))
ptfhost.shell("ip link del {}".format(sub_port_info['neighbor_port']))
remove_sub_port_from_ptf(ptfhost, sub_port_info['neighbor_port'], sub_port_info['neighbor_ip'])

if 'port_in_lag' in request.node.name:
ptf_ports = define_sub_ports_configuration['ptf_ports']
for bond_port, port_name in ptf_ports.items():
if bond_port in ptf_port_list:
ptfhost.shell("ip link set {} nomaster".format(bond_port))
ptfhost.shell("ip link set {} nomaster".format(port_name))
ptfhost.shell("ip link set {} up".format(port_name))
ptfhost.shell("ip link del {}".format(bond_port))
remove_bond_port(ptfhost, bond_port, port_name)

ptfhost.shell("supervisorctl restart ptf_nn_agent")
time.sleep(5)
Expand Down
Loading