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
13 changes: 9 additions & 4 deletions ansible/roles/test/files/ptftests/inner_hash_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def setUp(self):
self.vxlan_port = self.test_params['vxlan_port']
self.outer_encap_formats = self.test_params['outer_encap_formats']
self.symmetric_hashing = self.test_params.get('symmetric_hashing', False)
self.nvgre_tni = self.test_params.get('nvgre_tni', '')
self.outer_dst_ip = self.outer_dst_ip_interval.get_first_ip()

self.next_hop = self.fib[self.outer_dst_ip]
Expand Down Expand Up @@ -226,6 +227,7 @@ def check_ipv4_route_nvgre(self, hash_key, src_port, ip_dst, ip_src, dport, spor

outer_ip_src = self.outer_src_ip_interval.get_random_ip() if hash_key == 'outer-tuples' else self.outer_src_ip_interval.get_first_ip()
outer_ip_dst = self.outer_dst_ip_interval.get_random_ip() if hash_key == 'outer-tuples' else self.outer_dst_ip_interval.get_first_ip()
nvgre_tni = self.nvgre_tni if self.nvgre_tni else random.randint(1, 254) + 20000

pkt = self.generate_inner_pkt(sport, dport, ip_src, ip_dst, ip_proto)
nvgre_pkt = simple_nvgre_packet(
Expand All @@ -235,8 +237,9 @@ def check_ipv4_route_nvgre(self, hash_key, src_port, ip_dst, ip_src, dport, spor
ip_src=outer_ip_src,
ip_dst=outer_ip_dst,
ip_ttl=64,
nvgre_tni=random.randint(1, 254)+20000,
inner_frame=pkt)
inner_frame=pkt,
nvgre_tni=nvgre_tni,
nvgre_flowid=0)

logging.info("Sending packet from port {} outer_ip_src {} outer_ip_dst {} inner_src_ip {} inner_dst_ip {} inner_sport {} inner_dport {} inner_ipproto {}"\
.format(src_port, outer_ip_src, outer_ip_dst, ip_src, ip_dst, sport, dport, ip_proto))
Expand Down Expand Up @@ -316,15 +319,17 @@ def check_ipv6_route_nvgre(self, hash_key, src_port, ip_dst, ip_src, dport, spor

outer_ip_src = self.outer_src_ip_interval.get_random_ip() if hash_key == 'outer-tuples' else self.outer_src_ip_interval.get_first_ip()
outer_ip_dst = self.outer_dst_ip_interval.get_random_ip() if hash_key == 'outer-tuples' else self.outer_dst_ip_interval.get_first_ip()
nvgre_tni = self.nvgre_tni if self.nvgre_tni else random.randint(1, 254) + 20000

pkt = self.generate_inner_pkt(sport, dport, ip_src, ip_dst, ip_proto)
nvgre_pkt = self.simple_nvgrev6_packet(
eth_dst=self.router_mac,
eth_src=src_mac,
ipv6_src=outer_ip_src,
ipv6_dst=outer_ip_dst,
nvgre_tni=random.randint(1, 254)+20000,
inner_frame=pkt)
inner_frame=pkt,
nvgre_tni=nvgre_tni,
nvgre_flowid=0)

logging.info("Sending packet from port {} outer_ip_src {} outer_ip_dst {} inner_src_ip {} inner_dst_ip {} inner_sport {} inner_dport {} inner_ipproto {}"\
.format(src_port, outer_ip_src, outer_ip_dst, ip_src, ip_dst, sport, dport, ip_proto))
Expand Down
132 changes: 118 additions & 14 deletions tests/ecmp/inner_hashing/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import logging
import tempfile
import re
import allure

from datetime import datetime

Expand All @@ -28,6 +29,7 @@
VXLAN_PORT = 13330
DUT_VXLAN_PORT_JSON_FILE = '/tmp/vxlan.switch.json'

T0_VLAN = "1000"
IP_VERSIONS_LIST = ["ipv4", "ipv6"]
OUTER_ENCAP_FORMATS = ["vxlan", "nvgre"]
TABLE_NAME = "pbh_table"
Expand All @@ -42,10 +44,16 @@
V6_ETHER_TYPE = "0x86dd"
VXLAN_IP_PROTOCOL = "0x11"
NVGRE_IP_PROTOCOL = "0x2f"
GRE_KEY = "0x2500"
NVGRE_TNI = 0x25
GRE_MASK = "0xffffff00"
VXLAN_L4_DST_PORT = "0x3412"
VXLAN_L4_DST_PORT_OPTION = " --l4-dst-port {}".format(VXLAN_L4_DST_PORT)
NVGRE_GRE_KEY_OPTION = " --gre-key {}/{}".format(GRE_KEY, GRE_MASK)
ADD_PBH_TABLE_CMD = "sudo config pbh table add '{}' --interface-list '{}' --description '{}'"
DEL_PBH_TABLE_CMD = "sudo config pbh table delete '{}'"
ADD_PBH_RULE_BASE_CMD = "sudo config pbh rule add '{}' '{}' --priority '{}' --ether-type {}" \
" --inner-ether-type '{}' --hash '{}' --packet-action '{}' --flow-counter 'ENABLED'"
ADD_PBH_RULE_BASE_CMD = "sudo config pbh rule add '{}' '{}' --priority '{}' --ether-type {}" \
" --inner-ether-type '{}' --hash '{}' --packet-action '{}' --flow-counter 'ENABLED'"
DEL_PBH_RULE_CMD = "sudo config pbh rule delete '{}' '{}'"
Expand Down Expand Up @@ -181,6 +189,59 @@ def vlan_ptf_ports(config_facts, tbinfo, duthost):
return ports


@pytest.fixture(scope='module')
def lag_port_map(duthost, config_facts, vlan_ptf_ports, tbinfo):
'''
Create lag-port map for vlan ptf ports
'''
portchannels = config_facts.get('PORTCHANNEL', {}).keys()
mg_facts = duthost.get_extended_minigraph_facts(tbinfo)
port_list_idx = 0
lag_port_map = {}
port_key_list = list(mg_facts['minigraph_ptf_indices'].keys())
port_val_list = list(mg_facts['minigraph_ptf_indices'].values())

for portchannel_idx in range(1, 10000): # Max len of PortChannel index can be '9999'
lag_port = 'PortChannel{}'.format(portchannel_idx)

if lag_port not in portchannels:
port_idx_value = vlan_ptf_ports[port_list_idx]
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this logic assume that a port is either a part of a portchannel or a vlan? What if its part of neither, will the test break?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The test supports t0 topology, there exist the ports in VLAN.
Here, created the map, with all ports in VLAN and newly portchannels: {PortChannel10: port1, PortChannel11: port2..... }
Later, according to this map, will be removed VLAN from the port and added this port to the newly created portchannel.

Not related to already existing portchannels and on t0 topo should be the ports in VLAN.

position = port_val_list.index(port_idx_value)
port_name = port_key_list[position]
lag_port_map[lag_port] = port_name
port_list_idx += 1

if len(lag_port_map) == len(vlan_ptf_ports):
break

return lag_port_map


@pytest.fixture(scope='module')
def lag_ip_map(lag_port_map):
index = 1
base_ipv4_addr = '100.0.{}.1/31'
base_ipv6_addr = 'fc00:{}::1/126'
lag_ip_map = {}

for lag_port, _ in lag_port_map.items():
ipv4_addr = base_ipv4_addr.format(index)
ipv6_addr = base_ipv6_addr.format(index)
lag_ip_map[lag_port] = {'ipv4': ipv4_addr, 'ipv6': ipv6_addr}
index += 1

return lag_ip_map


@pytest.fixture(scope='module')
def config_lag_ports(duthost, lag_port_map, lag_ip_map):
add_lag_config(duthost, lag_port_map, lag_ip_map)

yield

remove_lag_config(duthost, lag_port_map, lag_ip_map)


@pytest.fixture(scope='module')
def router_mac(duthosts, rand_one_dut_hostname):
duthost = duthosts[rand_one_dut_hostname]
Expand Down Expand Up @@ -214,8 +275,23 @@ def inner_ipver(request):
return request.param


@pytest.fixture(scope="module")
def config_pbh_table_lag(duthost, lag_port_map):
logging.info("Create PBH table: {}".format(TABLE_NAME))
test_intfs_str = ",".join(lag_port_map.keys())

duthost.command(ADD_PBH_TABLE_CMD.format(TABLE_NAME,
test_intfs_str,
TABLE_DESCRIPTION))

yield

duthost.command(DEL_PBH_TABLE_CMD.format(TABLE_NAME))


@pytest.fixture(scope="module")
def config_pbh_table(duthost, vlan_ptf_ports, tbinfo):
logging.info("Create PBH table: {}".format(TABLE_NAME))
test_intfs_str = get_dut_test_intfs_str(duthost, vlan_ptf_ports, tbinfo)

duthost.command(ADD_PBH_TABLE_CMD.format(TABLE_NAME,
Expand All @@ -239,6 +315,7 @@ def get_dut_test_intfs_str(duthost, vlan_ptf_ports, tbinfo):

@pytest.fixture(scope="module")
def config_hash_fields(duthost):
logging.info("Create PBH hash-fields")
for hash_field, hash_field_params_dict in HASH_FIELD_CONFIG.items():
cmd = get_hash_field_add_cmd(hash_field, hash_field_params_dict)
duthost.command(cmd)
Expand All @@ -260,6 +337,7 @@ def get_hash_field_add_cmd(hash_field_name, hash_field_params_dict):

@pytest.fixture(scope="module")
def config_hash(duthost):
logging.info("Create PBH hash: {}".format(HASH_NAME))
duthost.command(ADD_PBH_HASH_CMD.format(HASH_NAME, PBH_HASH_FIELD_LIST))

yield
Expand Down Expand Up @@ -291,6 +369,7 @@ def config_ipv6_rules(duthost, inner_ipver):


def config_vxlan_rule(duthost, ip_ver_option, ether_type, outer_ipver, inner_ipver):
logging.info("Create PBH rule: {}".format(VXLAN_RULE_NAME.format(outer_ipver, inner_ipver)))
inner_ether_type = V4_ETHER_TYPE if inner_ipver == "ipv4" else V6_ETHER_TYPE
duthost.command((ADD_PBH_RULE_BASE_CMD + ip_ver_option + VXLAN_L4_DST_PORT_OPTION)
.format(TABLE_NAME,
Expand All @@ -305,8 +384,9 @@ def config_vxlan_rule(duthost, ip_ver_option, ether_type, outer_ipver, inner_ipv


def config_nvgre_rule(duthost, ip_ver_option, ether_type, outer_ipver, inner_ipver):
logging.info("Create PBH rule: {}".format(NVGRE_RULE_NAME.format(outer_ipver, inner_ipver)))
inner_ether_type = V4_ETHER_TYPE if inner_ipver == "ipv4" else V6_ETHER_TYPE
duthost.command((ADD_PBH_RULE_BASE_CMD + ip_ver_option)
duthost.command((ADD_PBH_RULE_BASE_CMD + ip_ver_option + NVGRE_GRE_KEY_OPTION)
.format(TABLE_NAME,
NVGRE_RULE_NAME.format(outer_ipver, inner_ipver),
NVGRE_RULE_PRIO,
Expand Down Expand Up @@ -341,16 +421,40 @@ def get_src_dst_ip_range(ipver):


def check_pbh_counters(duthost, outer_ipver, inner_ipver, balancing_test_times, symmetric_hashing, hash_keys):
symmetric_multiplier = 2 if symmetric_hashing else 1
exp_port_multiplier = 4 # num of POs in t0 topology
hash_keys_multiplier = len(hash_keys)
# for hash key "ip-proto", the traffic sends always in one way
exp_count = str((balancing_test_times * symmetric_multiplier * exp_port_multiplier * (hash_keys_multiplier-1))
+ (balancing_test_times * exp_port_multiplier))
pbh_statistic_output = duthost.shell("show pbh statistic")['stdout']
for outer_encap_format in OUTER_ENCAP_FORMATS:
regex = r'{}\s+{}_{}_{}\s+(\d+)\s+\d+'.format(TABLE_NAME, outer_encap_format, outer_ipver, inner_ipver)
current_count = re.search(regex, pbh_statistic_output).group(1)
assert current_count == exp_count,\
"PBH counters are different from expected for {}, outer ipver {}, inner ipver {}. Expected: {}, " \
"Current: {}".format(outer_encap_format, outer_ipver, inner_ipver, exp_count, current_count)
logging.info('Verify PBH counters')
with allure.step('Verify PBH counters'):
symmetric_multiplier = 2 if symmetric_hashing else 1
exp_port_multiplier = 4 # num of POs in t0 topology
hash_keys_multiplier = len(hash_keys)
# for hash key "ip-proto", the traffic sends always in one way
exp_count = str((balancing_test_times * symmetric_multiplier * exp_port_multiplier * (hash_keys_multiplier-1))
+ (balancing_test_times * exp_port_multiplier))
pbh_statistic_output = duthost.shell("show pbh statistic")['stdout']
for outer_encap_format in OUTER_ENCAP_FORMATS:
regex = r'{}\s+{}_{}_{}\s+(\d+)\s+\d+'.format(TABLE_NAME, outer_encap_format, outer_ipver, inner_ipver)
current_count = re.search(regex, pbh_statistic_output).group(1)
assert current_count == exp_count,\
"PBH counters are different from expected for {}, outer ipver {}, inner ipver {}. Expected: {}, " \
"Current: {}".format(outer_encap_format, outer_ipver, inner_ipver, exp_count, current_count)


def add_lag_config(duthost, lag_port_map, lag_ip_map):
logging.info('Add LAG configuration')
with allure.step('Add LAG configuration'):
for lag_port, port_name in lag_port_map.items():
duthost.shell('sudo config vlan member del {} {}'.format(T0_VLAN, port_name))
duthost.shell('sudo config portchannel add {} --fallback enable'.format(lag_port))
duthost.shell('sudo config portchannel member add {} {}'.format(lag_port, port_name))
duthost.shell('config interface ip add {} {}'.format(lag_port, lag_ip_map[lag_port]['ipv4']))
duthost.shell('config interface ip add {} {}'.format(lag_port, lag_ip_map[lag_port]['ipv6']))


def remove_lag_config(duthost, lag_port_map, lag_ip_map):
logging.info('Remove LAG configuration')
with allure.step('Remove LAG configuration'):
for lag_port, port_name in lag_port_map.items():
duthost.shell('config interface ip remove {} {}'.format(lag_port, lag_ip_map[lag_port]['ipv4']))
duthost.shell('config interface ip remove {} {}'.format(lag_port, lag_ip_map[lag_port]['ipv6']))
duthost.shell('sudo config portchannel member del {} {}'.format(lag_port, port_name))
duthost.shell('sudo config portchannel del {}'.format(lag_port))
duthost.shell('sudo config vlan member add {} {} --untagged'.format(T0_VLAN, port_name))
74 changes: 39 additions & 35 deletions tests/ecmp/inner_hashing/test_inner_hashing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@

import logging
import pytest
import allure

from datetime import datetime
from retry.api import retry_call
from tests.ptf_runner import ptf_runner
from tests.ecmp.inner_hashing.conftest import get_src_dst_ip_range, FIB_INFO_FILE_DST,\
VXLAN_PORT, PTF_QLEN, check_pbh_counters, OUTER_ENCAP_FORMATS
VXLAN_PORT, PTF_QLEN, check_pbh_counters, OUTER_ENCAP_FORMATS, NVGRE_TNI

logger = logging.getLogger(__name__)

Expand All @@ -24,44 +25,47 @@ class TestDynamicInnerHashing():

@pytest.fixture(scope="class", autouse=True)
def setup_dynamic_pbh(self, request):
request.getfixturevalue("config_pbh_table")
request.getfixturevalue("config_hash_fields")
request.getfixturevalue("config_hash")
request.getfixturevalue("config_rules")
with allure.step('Config Dynamic PBH'):
request.getfixturevalue("config_pbh_table")
request.getfixturevalue("config_hash_fields")
request.getfixturevalue("config_hash")
request.getfixturevalue("config_rules")

def test_inner_hashing(self, hash_keys, ptfhost, outer_ipver, inner_ipver, router_mac, vlan_ptf_ports, symmetric_hashing, duthost):
logging.info("Executing dynamic inner hash test for outer {} and inner {} with symmetric_hashing set to {}"
.format(outer_ipver, inner_ipver, str(symmetric_hashing)))
timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
log_file = "/tmp/inner_hash_test.DynamicInnerHashTest.{}.{}.{}.log".format(outer_ipver, inner_ipver, timestamp)
logging.info("PTF log file: %s" % log_file)

outer_src_ip_range, outer_dst_ip_range = get_src_dst_ip_range(outer_ipver)
inner_src_ip_range, inner_dst_ip_range = get_src_dst_ip_range(inner_ipver)

balancing_test_times = 150
balancing_range = 0.3

ptf_runner(ptfhost,
"ptftests",
"inner_hash_test.InnerHashTest",
platform_dir="ptftests",
params={"fib_info": FIB_INFO_FILE_DST,
"router_mac": router_mac,
"src_ports": vlan_ptf_ports,
"hash_keys": hash_keys,
"vxlan_port": VXLAN_PORT,
"inner_src_ip_range": ",".join(inner_src_ip_range),
"inner_dst_ip_range": ",".join(inner_dst_ip_range),
"outer_src_ip_range": ",".join(outer_src_ip_range),
"outer_dst_ip_range": ",".join(outer_dst_ip_range),
"balancing_test_times": balancing_test_times,
"balancing_range": balancing_range,
"outer_encap_formats": OUTER_ENCAP_FORMATS,
"symmetric_hashing": symmetric_hashing},
log_file=log_file,
qlen=PTF_QLEN,
socket_recv_size=16384)
with allure.step('Run ptf test InnerHashTest'):
timestamp = datetime.now().strftime('%Y-%m-%d-%H:%M:%S')
log_file = "/tmp/inner_hash_test.DynamicInnerHashTest.{}.{}.{}.log".format(outer_ipver, inner_ipver, timestamp)
logging.info("PTF log file: %s" % log_file)

outer_src_ip_range, outer_dst_ip_range = get_src_dst_ip_range(outer_ipver)
inner_src_ip_range, inner_dst_ip_range = get_src_dst_ip_range(inner_ipver)

balancing_test_times = 150
balancing_range = 0.3

ptf_runner(ptfhost,
"ptftests",
"inner_hash_test.InnerHashTest",
platform_dir="ptftests",
params={"fib_info": FIB_INFO_FILE_DST,
"router_mac": router_mac,
"src_ports": vlan_ptf_ports,
"hash_keys": hash_keys,
"vxlan_port": VXLAN_PORT,
"inner_src_ip_range": ",".join(inner_src_ip_range),
"inner_dst_ip_range": ",".join(inner_dst_ip_range),
"outer_src_ip_range": ",".join(outer_src_ip_range),
"outer_dst_ip_range": ",".join(outer_dst_ip_range),
"balancing_test_times": balancing_test_times,
"balancing_range": balancing_range,
"outer_encap_formats": OUTER_ENCAP_FORMATS,
"nvgre_tni": NVGRE_TNI,
"symmetric_hashing": symmetric_hashing},
log_file=log_file,
qlen=PTF_QLEN,
socket_recv_size=16384)

retry_call(check_pbh_counters,
fargs=[duthost, outer_ipver, inner_ipver, balancing_test_times, symmetric_hashing, hash_keys],
Expand Down
Loading