Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4524212
Fix TLS certificate clock skew issue in gNOI tests (#22248)
hdwhdw Feb 6, 2026
8f460cb
[Disagg T2] Add 64 port T2 topology (#21977)
vinay-nexthop Feb 6, 2026
2ff1ee9
Reduce BGP Queue test runtime with a single 'show queue counters' cmd…
PriyanshTratiya Feb 7, 2026
19e4eb7
[Scale|CRM] Optimize test runtime with adaptive polling (#22132)
AntonHryshchuk Feb 7, 2026
7a3bf3a
[Generic hash] Update the generic hash test to reduce runtime for sca…
congh-nvidia Feb 7, 2026
1850158
Adding support for restapi containers in `container_upgrade` tests (#…
mramezani95 Feb 8, 2026
4a0c5c1
Fix test_bgp_suppress_fib.py flakiness on scale topos (#21843)
dayouliu1 Feb 8, 2026
31b0386
Fix invalid method call in conftest.py (#22158)
ccroy-arista Feb 8, 2026
4b4f386
Ignore "zmq send failed" in test_bgp_suppress_fib.py loganalyzer (#22…
markx-arista Feb 8, 2026
3e8ef3e
chore: enable test_nhop_group on lt2/ft2 (#22293)
auspham Feb 9, 2026
d862683
Adding a step to test_interfaces.py to verify pmon contains all inter…
gshemesh2 Feb 9, 2026
ae012ac
Adjust tests/bgp/test_bgp_update_replication.py::test_bgp_update_repl…
gshemesh2 Feb 9, 2026
869f9db
Adjust bgp commands for v6 when v6 only. (#22167)
OriTrabelsi Feb 9, 2026
4020092
adjust buffer test to support SN6600
ytzur1 Feb 9, 2026
16823cd
Add GCU test case to test changing the source interface for NTP (#21561)
saiarcot895 Feb 9, 2026
9b47ceb
Add GCU test case for adding/removing DNS nameservers (#21588)
saiarcot895 Feb 9, 2026
0f0a911
[Disagg T2] sonic-mgmt test changes needed for single ASIC VOQ Fixed-…
lakshmi-nexthop Feb 9, 2026
75e4192
Fix MACsec test reliability and configuration issues (#21372)
rajshekhar-nexthop Feb 9, 2026
7330c49
[generic_config_updater] Fix ethernet test port availability and erro…
gupurush Feb 10, 2026
f32b754
Fix serial device prefix fallback value (#22241)
wiperi Feb 10, 2026
4af314c
Enable test_po_update with ipv6-only topo (#21910)
yanmo96 Feb 10, 2026
0048c8e
Enable test_static_route for ipv6 only topo (#21765)
yanmo96 Feb 10, 2026
4d083ff
Remove xfail conditions for test_everflow_per_interface[ipv6-erspan_i…
yanmo96 Feb 10, 2026
277a544
Fix test_ipinip teardown issue (#22276)
yyynini Feb 10, 2026
5bdd9bc
Tagging DPU steps in the ansible minigraph scenario. (#22142)
nikamirrr Feb 10, 2026
a3e981c
Add parallel manager implementation
lolyu Jan 8, 2026
689a5b4
Add HLD
lolyu Jan 8, 2026
f3311d2
Make SONiC device classes thread-safe
lolyu Jan 8, 2026
7fb68de
Fix deadlock in child process after fork
lolyu Jan 8, 2026
1477179
Hook parallel manager
lolyu Jan 8, 2026
7422a34
Fix exception interact
lolyu Jan 8, 2026
f463a46
Refine fixture reorder logic
lolyu Jan 8, 2026
b428de2
Enable docker sys_ptrace
lolyu Jan 14, 2026
98c2d57
Get thread worker count based on DUT count
lolyu Jan 15, 2026
a9e5e24
Fix ansible display deadlock
lolyu Jan 15, 2026
26a33b4
Add deadlock handling to the doc
lolyu Jan 15, 2026
b652058
Remove not-related changes
lolyu Feb 3, 2026
05daff1
Add sd to doc
lolyu Feb 3, 2026
0ca3b16
Add missing emtpy line
lolyu Feb 3, 2026
ca0ae48
Fix comments
lolyu Feb 5, 2026
b9cd1fc
Enable TCP keepalive to avoid broken pipe issue
lolyu Feb 5, 2026
63d7858
Fix config
lolyu Feb 10, 2026
9f0c4af
Fix ansible config
lolyu Feb 10, 2026
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
5 changes: 3 additions & 2 deletions ansible/ansible.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ connection_plugins = plugins/connection
lookup_plugins = plugins/lookup
# vars_plugins = /usr/share/ansible_plugins/vars_plugins
filter_plugins = plugins/filter
callback_whitelist = profile_tasks
# Disable profile tasks callback to avoid possible deadlock
# callback_whitelist = profile_tasks

# by default callbacks are not loaded for /bin/ansible, enable this if you
# want, for example, a notification or logging callback to also apply to
Expand Down Expand Up @@ -190,7 +191,7 @@ become_ask_pass=False
# ssh arguments to use
# Leaving off ControlPersist will result in poor performance, so use
# paramiko on older platforms rather than removing it
ssh_args = -o ControlMaster=auto -o ControlPersist=180s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=30 -o ServerAliveCountMax=40
ssh_args = -o ControlMaster=auto -o ControlPersist=300s -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o ServerAliveInterval=30 -o ServerAliveCountMax=40 -o TCPKeepAlive=yes


# The path to use for the ControlPath sockets. This defaults to
Expand Down
9 changes: 8 additions & 1 deletion ansible/config_sonic_basedon_testbed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@
set_fact:
testbed_file: testbed.yaml
when: testbed_file is not defined
tags: always

- name: Gathering testbed information
test_facts: testbed_name="{{ testbed_name }}" testbed_file="{{ testbed_file }}"
delegate_to: localhost
tags: always

- fail: msg="The DUT you are trying to run test does not belongs to this testbed"
when: inventory_hostname not in testbed_facts['duts']
tags: always

- name: Set default num_asic
set_fact:
Expand All @@ -60,11 +63,13 @@
- name: set testbed_type
set_fact:
topo: "{{ testbed_facts['topo'] }}"
tags: always

- name: set default light mode
set_fact:
is_light_mode: true
when: topo in ["t1-smartswitch-ha","t1-28-lag","smartswitch-t1", "t1-48-lag"] and is_light_mode is not defined
tags: always

- name: set ptf image name
set_fact:
Expand Down Expand Up @@ -756,7 +761,7 @@
macsec_profile: "{{ macsec_profile }}"
num_asics: "{{ num_asics }}"
become: true
when: "('t2' in topo) and (enable_macsec is defined)"
when: "('t2' in topo) and (macsec_profile is defined)"

- name: Use minigraph case
block:
Expand Down Expand Up @@ -915,6 +920,7 @@
become: true
# t1-28-lag is smartswitch topo only
when: topo in ["t1-smartswitch-ha","t1-28-lag","smartswitch-t1", "t1-48-lag"] and is_light_mode|bool == true
tags: [ dpu_config ]

- name: Load DPU config in smartswitch
load_extra_dpu_config:
Expand All @@ -924,6 +930,7 @@
become: true
# t1-28-lag is smartswitch topo only
when: topo in ["t1-smartswitch-ha","t1-28-lag","smartswitch-t1", "t1-48-lag"] and is_light_mode|bool == true
tags: [ dpu_config ]

- name: Configure TACACS
become: true
Expand Down
2 changes: 1 addition & 1 deletion ansible/group_vars/sonic/variables
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ broadcom_th5_hwskus: ['Arista-7060X6-64DE', 'Arista-7060X6-64DE-64x400G', 'Arist
broadcom_j2c+_hwskus: ['Nokia-IXR7250E-36x100G', 'Nokia-IXR7250E-36x400G', 'Arista-7280DR3A-36', 'Arista-7280DR3AK-36', 'Arista-7280DR3AK-36S', 'Arista-7280DR3AM-36', 'Arista-7800R3A-36DM2-C36', 'Arista-7800R3A-36DM2-D36', 'Arista-7800R3AK-36DM2-C36', 'Arista-7800R3AK-36DM2-D36', 'Nokia-IXR7250-X3B']

broadcom_jr2_hwskus: ['Arista-7800R3-48CQ2-C48', 'Arista-7800R3-48CQM2-C48']
broadcom_q3d_hwskus: ['Arista-7280R4-32QF-32DF-64O', 'Arista-7280R4K-32QF-32DF-64O']
broadcom_q3d_hwskus: ['NH-5010-F-O64', 'NH-5010-F-O32-C32', 'Arista-7280R4-32QF-32DF-64O', 'Arista-7280R4K-32QF-32DF-64O']

mellanox_spc1_hwskus: [ 'ACS-MSN2700', 'ACS-MSN2740', 'ACS-MSN2100', 'ACS-MSN2410', 'ACS-MSN2010', 'Mellanox-SN2700', 'Mellanox-SN2700-A1', 'Mellanox-SN2700-D48C8','Mellanox-SN2700-D40C8S8', 'Mellanox-SN2700-A1-D48C8', 'Mellanox-SN2700-C28D8', 'Mellanox-SN2700-A1-C28D8']
mellanox_spc2_hwskus: [ 'ACS-MSN3700', 'ACS-MSN3700C', 'ACS-MSN3800', 'Mellanox-SN3800-D112C8' , 'ACS-MSN3420']
Expand Down
4 changes: 4 additions & 0 deletions ansible/library/dut_basic_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def main():
if hasattr(device_info, 'is_chassis'):
results['is_chassis'] = device_info.is_chassis()

results['is_chassis_config_absent'] = False
if hasattr(device_info, 'is_chassis_config_absent'):
results['is_chassis_config_absent'] = device_info.is_chassis_config_absent()

if results['is_multi_asic']:
results['asic_index_list'] = []
if results['is_chassis']:
Expand Down
1 change: 1 addition & 0 deletions ansible/roles/eos/templates/t2-single-node-max-64p-core.j2
1 change: 1 addition & 0 deletions ansible/roles/eos/templates/t2-single-node-max-64p-leaf.j2
71 changes: 49 additions & 22 deletions ansible/roles/test/files/ptftests/py3/generic_hash_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class GenericHashTest(BaseTest):
# ---------------------------------------------------------------------
# Class variables
# ---------------------------------------------------------------------
DEFAULT_BALANCING_RANGE = 0.25
BALANCING_TEST_TIMES = 625
DEFAULT_BALANCING_RANGE = 0.3
BALANCING_TEST_TIMES = 480
VXLAN_PORT = 4789
VXLAN_VNI = 20001
NVGRE_TNI = 20001
Expand Down Expand Up @@ -206,12 +206,12 @@ def _get_single_layer_packet():
if self.hash_field == 'ETHERTYPE':
pkt['Ether'].type = random.choice(range(self.ethertype_range[0], self.ethertype_range[1]))
if not self.is_l2_test:
pkt_summary = f"{self.ipver} packet with src_mac:{src_mac}, dst_mac:{dst_mac}, src_ip:{src_ip}, " \
f"dst_ip:{dst_ip}, src_port:{src_port}, dst_port: {dst_port}, " \
f"ip_protocol:{_get_pkt_ip_protocol(pkt)}"
pkt_summary = f"{self.ipver} packet with src_mac: {src_mac}, dst_mac: {dst_mac}, src_ip: {src_ip}, " \
f"dst_ip: {dst_ip}, src_port: {src_port}, dst_port: {dst_port}, " \
f"ip_protocol: {_get_pkt_ip_protocol(pkt)}"
else:
pkt_summary = f"Ethernet packet with src_mac:{src_mac}, dst_mac:{dst_mac}, " \
f"ether_type:{hex(pkt['Ether'].type)}, vlan_id:{vlan_id if vlan_id != 0 else 'N/A'}"
pkt_summary = f"Ethernet packet with src_mac: {src_mac}, dst_mac: {dst_mac}, " \
f"ether_type: {hex(pkt['Ether'].type)}, vlan_id: {vlan_id if vlan_id != 0 else 'N/A'}"
if self.hash_field == 'IPV6_FLOW_LABEL':
pkt_summary += f", ipv6 flow label: {flow_label} "

Expand Down Expand Up @@ -244,10 +244,10 @@ def _get_ipinip_packet():
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "dst")
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "src")
masked_expected_pkt.set_do_not_care_packet(scapy.IPv6, "hlim")
pkt_summary = f"{self.ipver} ipinip packet with src_ip:{src_ip}, dst_ip:{dst_ip}, " \
f"ip_protocol:{_get_pkt_ip_protocol(pkt)}, inner_ipver:{self.inner_ipver}, " \
f"inner_src_ip:{inner_src_ip}, inner_dst_ip:{inner_dst_ip}, inner_src_port:{src_port}," \
f" inner_dst_port:{dst_port}, inner_ip_protocol:{_get_pkt_ip_protocol(inner_pkt)}"
pkt_summary = f"{self.ipver} ipinip packet with src_ip: {src_ip}, dst_ip: {dst_ip}, " \
f"ip_protocol: {_get_pkt_ip_protocol(pkt)}, inner_ipver: {self.inner_ipver}, " \
f"inner_src_ip: {inner_src_ip}, inner_dst_ip: {inner_dst_ip}, inner_src_port: {src_port}, " \
f" inner_dst_port: {dst_port}, inner_ip_protocol: {_get_pkt_ip_protocol(inner_pkt)}"
return pkt, masked_expected_pkt, pkt_summary

def _get_vxlan_packet():
Expand Down Expand Up @@ -286,11 +286,12 @@ def _get_vxlan_packet():
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "dst")
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "src")
masked_expected_pkt.set_do_not_care_packet(scapy.IPv6, "hlim")
pkt_summary = f"{self.ipver} vxlan packet with src_ip:{src_ip}, dst_ip:{dst_ip}, " \
f"src_port:{self.L4_SRC_PORT}, dst_port: {self.vxlan_port}, ip_protocol:{_get_pkt_ip_protocol(pkt)}, " \
f"inner_ipver:{self.inner_ipver}, inner_src_ip:{inner_src_ip}, inner_dst_ip:{inner_dst_ip}, " \
f"inner_src_port:{src_port}, inner_dst_port:{dst_port}, " \
f"inner_ip_protocol:{_get_pkt_ip_protocol(inner_pkt)}"
pkt_summary = f"{self.ipver} vxlan packet with src_ip: {src_ip}, dst_ip: {dst_ip}, " \
f"src_port: {self.L4_SRC_PORT}, dst_port: {self.vxlan_port}, " \
f"ip_protocol: {_get_pkt_ip_protocol(pkt)}, " \
f"inner_ipver: {self.inner_ipver}, inner_src_ip: {inner_src_ip}, inner_dst_ip: {inner_dst_ip}, " \
f"inner_src_port: {src_port}, inner_dst_port: {dst_port}, " \
f"inner_ip_protocol: {_get_pkt_ip_protocol(inner_pkt)}"
return pkt, masked_expected_pkt, pkt_summary

def _get_nvgre_packet():
Expand Down Expand Up @@ -325,10 +326,10 @@ def _get_nvgre_packet():
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "dst")
masked_expected_pkt.set_do_not_care_packet(scapy.Ether, "src")
masked_expected_pkt.set_do_not_care_packet(scapy.IPv6, "hlim")
pkt_summary = f"{self.ipver} nvgre packet with src_ip:{src_ip}, dst_ip:{dst_ip}, " \
f"ip_protocol:{_get_pkt_ip_protocol(pkt)}, inner_ipver:{self.inner_ipver}, " \
f"inner_src_ip:{inner_src_ip}, inner_dst_ip:{inner_dst_ip}, inner_src_port:{src_port}, " \
f"inner_dst_port:{dst_port}, inner_ip_protocol:{_get_pkt_ip_protocol(inner_pkt)}"
pkt_summary = f"{self.ipver} nvgre packet with src_ip: {src_ip}, dst_ip: {dst_ip}, " \
f"ip_protocol: {_get_pkt_ip_protocol(pkt)}, inner_ipver: {self.inner_ipver}, " \
f"inner_src_ip: {inner_src_ip}, inner_dst_ip: {inner_dst_ip}, inner_src_port: {src_port}, " \
f"inner_dst_port: {dst_port}, inner_ip_protocol: {_get_pkt_ip_protocol(inner_pkt)}"
return pkt, masked_expected_pkt, pkt_summary

src_mac = _get_src_mac()
Expand Down Expand Up @@ -396,13 +397,14 @@ def check_ip_route(self, pkt, masked_expected_pkt, sending_port):
port_index, received = testutils.verify_packet_any_port(
self, masked_expected_pkt, self.expected_port_list, timeout=0.1)
except AssertionError:
logging.error("Traffic wasn't sent successfully, trying again")
logging.warning("Packet wasn't received successfully, trying again")
logging.info(f"Expected packet: {masked_expected_pkt}")
for _ in range(5):
testutils.send_packet(self, sending_port, pkt, count=1)
time.sleep(0.1)
port_index, received = testutils.verify_packet_any_port(
self, masked_expected_pkt, self.expected_port_list, timeout=1)
logging.info("Packet was received successfully after retry.")
# The port_index is the index of expected_port_list, need to convert it to the ptf port index
return self.expected_port_list[port_index], received

Expand Down Expand Up @@ -511,6 +513,31 @@ def _check_only_lag_hash_balancing():
elif not self.ecmp_hash and self.lag_hash:
_check_only_lag_hash_balancing()

def print_result_summary(self, hit_count_map):
total_receiving_ports = len(hit_count_map)
total_received_packets = sum(hit_count_map.values())
average_packets = total_received_packets / total_receiving_ports
min_received_packets = min(hit_count_map.values())
max_received_packets = max(hit_count_map.values())
min_received_ports = [port for port, count in hit_count_map.items() if count == min_received_packets]
max_received_ports = [port for port, count in hit_count_map.items() if count == max_received_packets]
expected_total_hit_cnt = self.balancing_test_times * len(self.expected_port_list)
expected_hit_cnt_per_port = self.balancing_test_times
if self.ecmp_hash and not self.lag_hash:
expected_hit_cnt_per_port = expected_total_hit_cnt / len(self.expected_port_groups)
elif not self.ecmp_hash and self.lag_hash:
expected_hit_cnt_per_port = expected_total_hit_cnt / len(self.expected_port_groups[0])
max_deviation = max(abs(expected_hit_cnt_per_port - min_received_packets),
abs(expected_hit_cnt_per_port - max_received_packets))
max_deviation_percentage = str(max_deviation / expected_hit_cnt_per_port * 100) + "%"
logging.info(f"\nTotal number of receiving ports: {total_receiving_ports}\n"
f"Total packet count: {total_received_packets}\n"
f"Average packet count: {average_packets}\n"
f"Min packets on a port: {min_received_packets}(Ports: {min_received_ports})\n"
f"Max packets on a port: {max_received_packets}(Ports: {max_received_ports})\n"
f"Max deviation: {max_deviation}\n"
f"Max deviation percentage: {max_deviation_percentage}\n")

def runTest(self):
logging.info("=============Test Start==============")
hit_count_map = {}
Expand Down Expand Up @@ -544,9 +571,9 @@ def runTest(self):

logging.info("Received packet at index {}: {}".format(
str(matched_port), re.sub(r"(?<=\w)(?=(?:\w\w)+$)", ' ', received.hex())))
time.sleep(0.02)

hit_count_map[matched_port] = hit_count_map.get(matched_port, 0) + 1
logging.info(f"hash_field={self.hash_field}, hit count map: {hit_count_map}")
self.print_result_summary(hit_count_map)
# Check if the traffic is properly balanced
self.check_balancing(hit_count_map)
4 changes: 1 addition & 3 deletions ansible/templates/golden_config_db_t2.j2
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
{% endif %}
{%- endfor -%}
{% else %}
{
"MACSEC_PROFILE": {
"MACSEC_PROFILE": {
"{{macsec_profile}}": {
"priority": "{{priority}}",
"cipher_suite": "{{cipher_suite}}",
Expand All @@ -34,6 +33,5 @@
"send_sci": "{{send_sci}}"
}
}
},
{%- endif -%}
}
Loading