Skip to content

Commit 2a625d0

Browse files
maggiemsftlguohan
authored andcommitted
[TestLAG] add additional/alternative lag_2 test (#199)
* add additional/alternative lag test for using lab graph file to identify fanout switch ports; modify the lacp_time playbook be able to validate both fast and slow rate; leave traffic balancing part of lag test to FIB test * modify it run for T0 lag too * add todo and fix typo * Pretty much sure lacp timing issue is covered by lag_2.yml, all other existing lab tests, not very sure if they are still working or not since cannot test in my environment. Will leave it here until I can confirm no one is running it * minor typo fix * fix comment
1 parent a9d0e80 commit 2a625d0

File tree

10 files changed

+359
-14
lines changed

10 files changed

+359
-14
lines changed

ansible/group_vars/lab/labinfo.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"Arista-7050-Q4S48": "Arista",
44
"Arista-7508-Q288": "Arista",
55
"Arista-7260QX-64": "Arista",
6+
"Arista-VM": "Arista",
67
"Nexus-3064-NX": "Nexus",
78
"Force10-S6100": "Force10",
89
"Force10-S6000": "Force10"
@@ -16,7 +17,7 @@
1617
"Arista": {
1718
"user": "admin",
1819
"passwd": ["password", "123456"],
19-
"enable": null
20+
"enable": ['', null]
2021
},
2122
"Force10": {
2223
"user": "admin",

ansible/library/lag_facts.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#!/usr/bin/python
2+
3+
import json
4+
from ansible.module_utils.basic import *
5+
6+
DOCUMENTATION = '''
7+
---
8+
module: lag_facts
9+
Ansible_version_added: "2.0.0.2"
10+
Sonic_version: "2.0"
11+
short_description: Retrieve lag(LACP) information from a device
12+
description:
13+
- Retrieved facts will be inserted to:
14+
lag_facts:
15+
- 'names': [list all portchannel names]
16+
- 'lags': {portchannel: detailed portchannel information }
17+
'''
18+
19+
EXAMPLES = '''
20+
# Gather lab facts
21+
- name: Gather lag info
22+
lag_facts: host=10.255.0.200
23+
- name: display lag information
24+
debug: var=lag_facts
25+
'''
26+
27+
class LagModule(object):
28+
def __init__(self):
29+
self.module = AnsibleModule(
30+
argument_spec=dict(
31+
host=dict(required=True),
32+
),
33+
supports_check_mode=False,
34+
)
35+
self.lag_names = []
36+
self.lags = {}
37+
return
38+
39+
def run(self):
40+
'''
41+
Main method of the class
42+
'''
43+
self.get_po_names()
44+
for po in self.lag_names:
45+
self.lags[po] = {}
46+
self.lags[po]['po_stats'] = self.get_po_status(po)
47+
self.lags[po]['po_config'] = self.get_po_config(po)
48+
self.lags[po]['po_intf_stat'] = self.get_po_intf_stat(po)
49+
self.module.exit_json(ansible_facts={'lag_facts': {'names': self.lag_names, 'lags': self.lags}})
50+
return
51+
52+
def get_po_names(self):
53+
'''
54+
Collect configured lag interface names
55+
'''
56+
rt, out, err = self.module.run_command("sonic-cfggen -m /etc/sonic/minigraph.xml -v \"minigraph_portchannels.keys() | join(' ')\"")
57+
if rt != 0:
58+
fail_msg="Command to retrieve portchannel names failed return=%d, out=%s, err=%s" %(rt, out, err)
59+
self.module.fail_json(msg=fail_msg)
60+
else:
61+
self.lag_names = out.split()
62+
return
63+
64+
def get_po_status(self, po_name):
65+
'''
66+
Collect lag information by command docker teamdctl
67+
'''
68+
rt, out, err = self.module.run_command("docker exec -i teamd teamdctl "+po_name+" state dump")
69+
if rt != 0:
70+
fail_msg="failed dump port channel %s status return=%d, out=%s, err=%s" %(po_name, rt, out, err)
71+
self.module.fail_json(msg=fail_msg)
72+
json_info = json.loads(out)
73+
return json_info
74+
75+
def get_po_config(self, po_name):
76+
'''
77+
Collect lag information by command docker teamdctl
78+
'''
79+
rt, out, err = self.module.run_command("docker exec -i teamd teamdctl "+po_name+" config dump")
80+
if rt != 0:
81+
fail_msg="failed dump port channel %s config return=%d, out=%s, err=%s" %(po_name, rt, out, err)
82+
self.module.fail_json(msg=fail_msg)
83+
json_info = json.loads(out)
84+
return json_info
85+
86+
def get_po_intf_stat(self, po_name):
87+
'''
88+
Collect lag information by command docker teamdctl
89+
'''
90+
rt, out, err = self.module.run_command("ip link show " + po_name)
91+
if rt != 0:
92+
fail_msg="failed show interface status of %s return=%d, out=%s, err=%s" %(po_name, rt, out, err)
93+
self.module.fail_json(msg=fail_msg)
94+
if 'NO-CARRIER' in out:
95+
return 'Down'
96+
else:
97+
return 'Up'
98+
99+
def main():
100+
lags = LagModule()
101+
lags.run()
102+
103+
if __name__ == '__main__':
104+
main()

ansible/roles/test/tasks/lag_2.yml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
### this is the Lag_2 lag test that tests each Lag interface minimum link and rate of sending LACP DU packets
2+
### this test could be consider as an additional/alternative lag test from existing lagall.yml.
3+
### Due to some labs are using two layer fanout switches, and one DUT might connects to multiple fanoutleaf switches
4+
### so for minimum link test of lag member flaps, it requires to use lab connection facts to determine the fanout neighbor ports,
5+
### Also, most of the traffic load balancing tests of LAG interface are covered in new FIB tests. so we are ignoring traffic test
6+
### for lag member flaps for now, will consider add traffic back if required
7+
8+
- fail: msg="Please define ptf_host"
9+
when: ptf_host is not defined
10+
11+
- fail: msg="Please define testbed_type"
12+
when: testbed_type is not defined
13+
14+
15+
- fail: msg="this test only support t1-lag and t0 testbed_type"
16+
when: testbed_type not in ['t1-lag', 't0']
17+
18+
- name: gathering lag facts from device
19+
lag_facts: host={{ inventory_hostname }}
20+
21+
- fail: msg="No lag configuration found in {{ inventory_hostname }}"
22+
when: lag_facts.names == []
23+
24+
- name: Gathering peer VM information from lldp
25+
lldp:
26+
vars:
27+
ansible_shell_type: docker
28+
ansible_python_interpreter: docker exec -i lldp python
29+
30+
- name: gathering minigraph of the device configuration
31+
minigraph_facts: host={{ inventory_hostname }}
32+
connection: local
33+
34+
- name: Gathering lab graph facts about the device
35+
conn_graph_facts: host={{ inventory_hostname }}
36+
connection: local
37+
38+
- set_fact:
39+
fanout_neighbors: "{{device_conn}}"
40+
41+
- set_fact:
42+
vm_neighbors: "{{ minigraph_neighbors }}"
43+
44+
- name: Copy PTF test into PTF-docker for test LACP DU.
45+
copy: src=roles/test/files/acstests/{{ item }} dest=/tmp/{{ item }}
46+
with_items:
47+
- lag_test.py
48+
- acs_base_test.py
49+
- router_utils.py
50+
delegate_to: "{{ ptf_host }}"
51+
52+
- name: Include testbed topology configuration (to get LAG IP and PTF docker interfaces, that are behind LAG VMs).
53+
include_vars: vars/topo_t1-lag.yml
54+
when: testbed_type == 't1-lag'
55+
56+
- name: Include testbed topology configuration (to get LAG IP and PTF docker interfaces, that are behind LAG VMs).
57+
include_vars: vars/topo_t0.yml
58+
when: testbed_type == 't0'
59+
60+
- set_fact:
61+
dut_mac: "{{ ansible_Ethernet0['macaddress'] }}"
62+
63+
- name: test each lag interface minimum links and rate
64+
include: single_lag_test.yml
65+
with_items: lag_facts.names

ansible/roles/test/tasks/lag_lacp_timing_test.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
#-----------------------------------
2-
# --- Part of lagall.yml test ---
3-
#-----------------------------------
1+
#--------------------------------------------------
2+
# --- lag_2.yml test---
3+
#-------------------------------------------------
44
# Using PTF test framework, check the LACP packets timing
55
# for each VM that has LAG configured.
66
#
77
# @ params: iface_behind_lag_member_0 - PTF docker iface, that receives all the packets that VM LAG member does.
88
# @ params: iface_behind_lag_member_1 - PTF docker iface, that receives all the packets that VM LAG member does.
99
# @ params: vm_name - VM hostname that will be printed before running test.
10-
#-----------------------------------
10+
#
11+
# Originally in lagall.yml, and lag_2.yml should cover it
12+
#--------------------------------------------------------
1113

1214
- set_fact:
1315
lacp_ether_type: '0x8809'
14-
packet_timing: 30
16+
packet_timing: "{{ lacp_timer }}"
1517
packet_timeout: 35
1618

1719
- name: Check LACP timing on eth{{ iface_behind_lag_member_0 }} (interface behind {{ vm_name }}).
@@ -27,3 +29,4 @@
2729
lag_ptf_test_name: LacpTimingTest
2830
params: "exp_iface={{ iface_behind_lag_member_1 }}; timeout={{ packet_timeout }}; packet_timing={{ packet_timing }}; ether_type={{ lacp_ether_type }}"
2931
change_dir: /tmp
32+
when: iface_behind_lab_member_1 is defined
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
### This playbook is part of lag_2.yml test
2+
### It is to test LACP LAG functionality behave correctly when link flaps.
3+
### In this playbook the neighbor of the selected flap_intf interface is shutdown and playbook validate Portchannel interface status and member
4+
### selection status are correct based on port channel min link configuration. Then bring up the remote interface to make sure
5+
### Port channel interface is up after peer port is back
6+
7+
- block:
8+
- name: Shut down neighbor interface {{ neighbor_interface }} on {{ peer_device }}
9+
action: apswitch template=neighbor_interface_shut_single.j2
10+
args:
11+
host: "{{peer_host}}"
12+
login: "{{switch_login[hwsku_map[peer_hwsku]]}}"
13+
connection: switch
14+
15+
- pause:
16+
seconds: "{{ wait_down_time }}"
17+
18+
- lag_facts: host={{ inventory_hostname }}
19+
20+
- name: Verify all other lag member interfaces are marked selected
21+
assert: { that: "'{{ lag_facts.lags[po]['po_stats']['ports'][item]['runner']['selected'] }}' == 'True'" }
22+
with_items: "{{ po_interfaces.keys() }}"
23+
when: item != "{{ flap_intf }}"
24+
25+
- name: Verify {{ flap_intf}} lag member interfaces are marked as deselected for the shutdown port
26+
assert: { that: "'{{ lag_facts.lags[po]['po_stats']['ports'][item]['runner']['selected'] }}' == 'False'" }
27+
with_items: "{{ po_interfaces.keys() }}"
28+
when: item == "{{ flap_intf }}"
29+
30+
- name: verify port-channel {{ po }} interface are marked down correctly if portchannel should down
31+
assert: { that: "'{{ lag_facts.lags[po]['po_intf_stat'] }}' == 'Down' "}
32+
when: po_flap == True
33+
34+
- name: verify port-channel {{ po }} interface are marked Up correctly if portchannel should keepup
35+
assert: { that: "'{{ lag_facts.lags[po]['po_intf_stat'] }}' == 'Up' "}
36+
when: po_flap != True
37+
38+
### always bring back port in case test error and left testbed in unknow stage
39+
always:
40+
- name: Bring up neighbor interface {{ neighbor_interface }} on {{ peer_host }}
41+
action: apswitch template=neighbor_interface_no_shut_single.j2
42+
args:
43+
host: "{{peer_host}}"
44+
login: "{{switch_login[hwsku_map[peer_hwsku]]}}"
45+
connection: switch
46+
47+
- pause:
48+
seconds: 20
49+
50+
- lag_facts: host={{ inventory_hostname }}
51+
52+
- name: Verify all interfaces in port_channel are marked up
53+
assert: { that: "'{{ lag_facts.lags[po]['po_stats']['ports'][item]['link']['up'] }}' == 'True'" }
54+
with_items: "{{ po_interfaces.keys() }}"
55+
56+
- name: verify port-channel {{ po }} interface are marked up correctly
57+
assert: { that: "'{{ lag_facts.lags[po]['po_intf_stat'] }}' == 'Up' "}

ansible/roles/test/tasks/lagall.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,3 @@
135135
dut_lag_member: "{{ dut_lag_members[1] }}"
136136
num_of_pkts: 100
137137
when: dut_lag_members is defined
138-
139-
- name: --TEST-- LACP timing test.
140-
include: lag_lacp_timing_test.yml
141-
vars:
142-
iface_behind_lag_member_0: "{{ topology['VMs'][item]['vlans'][0] }}"
143-
iface_behind_lag_member_1: "{{ topology['VMs'][item]['vlans'][1] }}"
144-
vm_name: "{{ item }}"
145-
with_items: lag_vms.keys()
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
### Part of lag test palybook lag_2.yml (--tag lag_2)
2+
### This playbook test one single port channel minimum link feature of one member interface shutdown
3+
### and portchannel member interfaces sending ACP DU rate
4+
5+
# Gather information of port channel ports, minimum links and total interface member numbers
6+
- set_fact:
7+
po: "{{ item }}"
8+
po_interfaces: "{{ lag_facts.lags[item]['po_config']['ports'] }}"
9+
po_intf_num: "{{ lag_facts.lags[item]['po_config']['ports']|length }}"
10+
po_min_links: "{{lag_facts.lags[item]['po_config']['runner']['min_ports']}}"
11+
12+
# pick flap interface name and calculate when it flaps, should portchannel interface flap or not
13+
# Current it is using a static capacity < 75%, Portchannel will flap which match Sonic configuration
14+
# if need to be random, then will make it a var
15+
- set_fact:
16+
po_flap: "{{ (po_intf_num|float - 1)/(po_min_links|float)*100 < 75 }}"
17+
flap_intf: "{{ lag_facts.lags[item]['po_config']['ports'].keys()[0] }}"
18+
19+
### figure out fanout switches info for the flapping lag member and run minlink test
20+
- set_fact:
21+
peer_device: "{{ fanout_neighbors[flap_intf]['peerdevice'] }}"
22+
neighbor_interface: "{{ fanout_neighbors[flap_intf]['peerport'] }}"
23+
24+
- conn_graph_facts: host={{ peer_device }}
25+
connection: local
26+
27+
- set_fact:
28+
peer_host: "{{ device_info['mgmtip'] }}"
29+
peer_hwsku: "{{ device_info['HwSku'] }}"
30+
31+
- name: test fanout interface (physical) flap and lacp keep correct po status follow minimum links requirement
32+
include: lag_minlink.yml
33+
vars:
34+
wait_down_time: 20
35+
36+
### Now figure out remote VM and interface info for the falpping lag member and run minlink test
37+
- set_fact:
38+
peer_device: "{{vm_neighbors[flap_intf]['name']}}"
39+
neighbor_interface: "{{vm_neighbors[flap_intf]['port']}}"
40+
peer_hwsku: 'Arista-VM'
41+
42+
##############################################################################################
43+
##### TODO: use minigraph/and VM configuration to figure out neighbor host access info #####
44+
##### try not using lldp dynamic info to find neighbor access
45+
##############################################################################################
46+
- set_fact:
47+
peer_host: "{{ lldp[flap_intf]['chassis']['mgmt-ip'] }}"
48+
49+
- name: test vm interface flap (no physical port down, more like remote port lock) that lag interface can change to correct po status follow minimum links requirement
50+
include: lag_minlink.yml
51+
vars:
52+
wait_down_time: 120
53+
54+
### Now prepare for the remote VM interfaces that using PTF docker to check teh LACP DU packet rate is correct
55+
- set_fact:
56+
iface_behind_lag_member_0: "{{ topology['VMs'][peer_device]['vlans'][0] }}"
57+
58+
- set_fact:
59+
iface_behind_lag_member_1: "{{ topology['VMs'][peer_device]['vlans'][1] }}"
60+
when: testbed_type == 't1-lag'
61+
62+
- set_fact:
63+
neighbor_lag_intfs: []
64+
65+
- set_fact:
66+
neighbor_lag_intfs: "{{ neighbor_lag_intfs }} + [ '{{ vm_neighbors[item]['port'] }}' ]"
67+
with_items: "{{ po_interfaces }}"
68+
69+
# make sure portchannel peer rate is set to fast
70+
- name: make sure all lag members on VM are set to fast
71+
action: apswitch template=neighbor_lag_rate_fast.j2
72+
args:
73+
host: "{{peer_host}}"
74+
login: "{{switch_login[hwsku_map[peer_hwsku]]}}"
75+
connection: switch
76+
77+
- pause:
78+
seconds: 5
79+
80+
- name: test lacp packet sending rate is 1 seconds
81+
include: lag_lacp_timing_test.yml
82+
vars:
83+
vm_name: "{{ peer_device }}"
84+
lacp_timer: 1
85+
86+
# make sure portchannel peer rate is set to slow
87+
- name: make sure all lag members on VM are set to slow
88+
action: apswitch template=neighbor_lag_rate_slow.j2
89+
args:
90+
host: "{{peer_host}}"
91+
login: "{{switch_login[hwsku_map[peer_hwsku]]}}"
92+
connection: switch
93+
94+
- pause:
95+
seconds: 5
96+
97+
- name: test lacp packet sending rate is 30 seconds
98+
include: lag_lacp_timing_test.yml
99+
vars:
100+
vm_name: "{{ peer_device }}"
101+
lacp_timer: 30

0 commit comments

Comments
 (0)